Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
350 lines
10 KiB
C++
350 lines
10 KiB
C++
//===========================================================================//
|
|
// File: Mech.cpp
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 09/09/98 JSE Inital base class based off of Shadowrun/Adept //
|
|
// 09/22/98 BDB Inital base Mech class based off Vehicle //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1998, Fasa Interactive //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "MW4Headers.hpp"
|
|
|
|
#include "Hovercraft.hpp"
|
|
|
|
#include <Adept\EntityManager.hpp>
|
|
#include <Adept\DamageObject.hpp>
|
|
#include <Adept\Effect.hpp>
|
|
#include <Adept\NameTable.hpp>
|
|
#include <Adept\CollisionGrid.hpp>
|
|
|
|
#include <ElementRenderer\Element.hpp>
|
|
#include <Adept\Map.hpp>
|
|
|
|
//#############################################################################
|
|
//############################### Hovercraft ##############################
|
|
//#############################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Hovercraft::ClassData*
|
|
Hovercraft::DefaultData = NULL;
|
|
|
|
DWORD MechWarrior4::Executed_Hovercraft_Count = 0;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Hovercraft::InitializeClass()
|
|
{
|
|
Check_Object(ExecutionStateEngine::DefaultData);
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
HovercraftClassID,
|
|
"MechWarrior4::Hovercraft",
|
|
BaseClass::DefaultData,
|
|
NULL, NULL,
|
|
(Entity::Factory)Make,
|
|
(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
|
|
ExecutionStateEngine::DefaultData,
|
|
(Entity::GameModel::Factory)GameModel::ConstructGameModel,
|
|
(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
|
|
(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
|
|
(Entity::GameModel::ModelWrite)GameModel::WriteToText,
|
|
(Entity::GameModel::ModelSave)GameModel::SaveGameModel,
|
|
(AnimationStateEngine::Factory)AnimationStateEngine::Make
|
|
);
|
|
Register_Object(DefaultData);
|
|
|
|
//Dave Need to add attribute entries
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Hovercraft__GameModel,
|
|
HoverVehicleHeight,
|
|
hoverVehicleHeight,
|
|
Scalar
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Hovercraft__GameModel,
|
|
MaxHoverVehicleHeight,
|
|
maxHoverVehicleHeight,
|
|
Scalar
|
|
);
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Hovercraft::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Hovercraft*
|
|
Hovercraft::Make(
|
|
CreateMessage *message,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
Check_Object(message);
|
|
gos_PushCurrentHeap(Heap);
|
|
Hovercraft *new_entity = new
|
|
Hovercraft(DefaultData, message, base_id, NULL);
|
|
gos_PopCurrentHeap();
|
|
Check_Object(new_entity);
|
|
|
|
Check_Object(EntityManager::GetInstance());
|
|
EntityManager::GetInstance()->AddMover(new_entity);
|
|
|
|
return new_entity;
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Hovercraft::Hovercraft(
|
|
ClassData *class_data,
|
|
CreateMessage *message,
|
|
ReplicatorID *base_id,
|
|
ElementRenderer::Element *element
|
|
):
|
|
Vehicle(class_data, message, base_id, element)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(message);
|
|
|
|
HookUpSubsystems();
|
|
CommonCreation(message);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Hovercraft::CommonCreation(CreateMessage *message)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message);
|
|
|
|
#if defined(_ARMOR)
|
|
const GameModel *model = GetGameModel();
|
|
Check_Object(model);
|
|
Verify(model->moveTypeFlag == GameModel::HOVER_MOVETYPE);
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Hovercraft::Respawn(Entity__CreateMessage *message)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message);
|
|
|
|
BaseClass::Respawn(message);
|
|
CreateMessage *airplane_message = Cast_Pointer(CreateMessage *, message);
|
|
CommonCreation(airplane_message);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Hovercraft::~Hovercraft()
|
|
{
|
|
Check_Pointer(this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Hovercraft::Reuse(
|
|
const CreateMessage *message,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message);
|
|
|
|
STOP(("Not implemented"));
|
|
BaseClass::Reuse(message, base_id);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Hovercraft::TurnOn (void)
|
|
{
|
|
lastParameterization = gos_GetElapsedTime ();
|
|
executionState->RequestState(ExecutionStateEngine::FlyingMotionState);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Hovercraft::PreCollisionExecute(Time till)
|
|
{
|
|
Check_Object(this);
|
|
PRECOLLISION_LOGIC("Hovercraft");
|
|
|
|
BaseClass::PreCollisionExecute(till);
|
|
|
|
//
|
|
//---------------------------------
|
|
// If we aren't executing, stop now
|
|
//---------------------------------
|
|
//
|
|
Set_Statistic(Executed_Hovercraft_Count, Executed_Hovercraft_Count+1);
|
|
Check_Object(executionState);
|
|
int pre_state = executionState->GetState();
|
|
Verify(pre_state != ExecutionStateEngine::NeverExecuteState);
|
|
|
|
Scalar time_slice = GetTimeSlice(till);
|
|
if (pre_state == ExecutionStateEngine::FlyingMotionState)
|
|
{
|
|
ComputeForwardSpeed(time_slice);
|
|
UpdateHoverVehiclePosition(time_slice);
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Hovercraft::UpdateHoverVehiclePosition(Scalar time_slice )
|
|
{
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Apply velocity/acceleration to position and acceleration to velocity
|
|
//---------------------------------------------------------------------
|
|
//
|
|
const LinearMatrix4D &vehicle_to_world = GetLocalToWorld();
|
|
Point3D world_translation(vehicle_to_world);
|
|
Vector3D delta;
|
|
delta.AddScaled(
|
|
localSpaceVelocity.linearMotion,
|
|
localSpaceAcceleration.linearMotion,
|
|
0.5f * time_slice
|
|
);
|
|
Vector3D world_delta;
|
|
world_delta.Multiply(delta, vehicle_to_world);
|
|
world_translation.AddScaled(world_translation, world_delta, time_slice);
|
|
localSpaceVelocity.linearMotion.y += localSpaceAcceleration.linearMotion.y*time_slice;
|
|
|
|
//
|
|
//--------------------------------------
|
|
// Update our turn rates and orientation
|
|
//--------------------------------------
|
|
//
|
|
const GameModel *model = GetGameModel();
|
|
Check_Object(model);
|
|
Scalar temp = Lerp(model->fullStopTurnRate, model->topSpeedTurnRate, currentSpeedMPS/GetMaxSpeed());
|
|
YawPitchRoll new_rotation(vehicle_to_world);
|
|
temp *= time_slice;
|
|
new_rotation.yaw += yawDemand * temp;
|
|
new_rotation.pitch += pitchDemand * temp;
|
|
new_rotation.roll += rollDemand * temp;
|
|
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Adjust position from network
|
|
//----------------------------------------------
|
|
//
|
|
|
|
YawPitchRoll correction_angle;
|
|
Point3D correction_position;
|
|
|
|
GetNetworkAdjustment(time_slice, correction_position, correction_angle);
|
|
|
|
new_rotation.yaw.angle += correction_angle.yaw.angle;
|
|
new_rotation.pitch.angle += correction_angle.pitch.angle;
|
|
new_rotation.roll.angle += correction_angle.roll.angle;
|
|
world_translation += correction_position;
|
|
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Cast a ray down to see what we are driving on
|
|
//----------------------------------------------
|
|
//
|
|
Stuff::Line3D line;
|
|
line.m_length = 20.001f + model->hoverVehicleHeight + m_WaterDelta;
|
|
line.m_direction = Vector3D::Down;
|
|
line.m_origin = world_translation;
|
|
line.m_origin.y += 20.0f;
|
|
Stuff::Normal3D normal;
|
|
CollisionQuery query(&line, &normal, CanBeWalkedOnFlag, this);
|
|
Check_Object(CollisionGrid::Instance);
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// If we miss the ground, go to where gravity said
|
|
//------------------------------------------------
|
|
//
|
|
LinearMatrix4D new_local_to_world;
|
|
new_local_to_world.BuildRotation(new_rotation);
|
|
if (!CollisionGrid::Instance->ProjectLine(&query))
|
|
{
|
|
materialHit = MaterialCount;
|
|
worldSpaceVelocity.linearMotion.Multiply(
|
|
localSpaceVelocity.linearMotion,
|
|
vehicle_to_world
|
|
);
|
|
if (worldSpaceVelocity.linearMotion.y > 10.0f)
|
|
{
|
|
worldSpaceVelocity.linearMotion.y = 10.0f;
|
|
localSpaceVelocity.linearMotion.MultiplyByInverse(
|
|
worldSpaceVelocity.linearMotion,
|
|
vehicle_to_world
|
|
);
|
|
}
|
|
new_local_to_world.BuildTranslation(world_translation);
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------
|
|
// Otherwise, adapt the vehicle to the ground normal
|
|
//--------------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
materialHit = query.m_material;
|
|
line.m_length -= model->hoverVehicleHeight;
|
|
line.FindEnd(&world_translation);
|
|
world_translation.y += m_WaterDelta;
|
|
new_local_to_world.BuildTranslation(world_translation);
|
|
if (m_WaterDelta > 0)
|
|
new_local_to_world.AlignLocalAxisToWorldVector(Vector3D::Up, Y_Axis, X_Axis, Z_Axis);
|
|
else
|
|
new_local_to_world.AlignLocalAxisToWorldVector(normal, Y_Axis, X_Axis, Z_Axis);
|
|
|
|
//
|
|
//--------------------------------------------------
|
|
// Update the velocities to conform to the landscape
|
|
//--------------------------------------------------
|
|
//
|
|
localSpaceVelocity.linearMotion.x = 0.0f;
|
|
localSpaceVelocity.linearMotion.y = 0.0f;
|
|
localSpaceVelocity.linearMotion.z = currentSpeedMPS;
|
|
worldSpaceVelocity.linearMotion.Multiply(
|
|
localSpaceVelocity.linearMotion,
|
|
new_local_to_world
|
|
);
|
|
}
|
|
SetNewLocalToParent(new_local_to_world);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Hovercraft::TestInstance() const
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|