Files
firestorm/Gameleap/code/mw4/Code/MW4/HoverCraft.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

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));
}