Files
firestorm/Gameleap/code/mw4/Code/MW4/Truck.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

331 lines
9.3 KiB
C++

//===========================================================================//
// File: Truck.cpp
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 09/09/98 JSE Inital base class based off of Shadowrun/Adept //
// 09/23/98 BDB State engine update //
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include "MW4Headers.hpp"
#include "Truck.hpp"
#include "gameinfo.hpp"
#include "MWDamageObject.hpp"
#include "obstacle.hpp"
#include "ai.hpp"
#include <adept\effect.hpp>
#include <Adept\EntityManager.hpp>
//#############################################################################
//############################### Truck ##############################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Truck::ClassData*
Truck::DefaultData = NULL;
DWORD MechWarrior4::Executed_Truck_Count = 0;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Truck::InitializeClass()
{
Check_Object(MWMover::ExecutionStateEngine::DefaultData);
Verify(!DefaultData);
DefaultData =
new ClassData(
TruckClassID,
"MechWarrior4::Truck",
BaseClass::DefaultData,
0, 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::Make
);
Register_Object(DefaultData);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Truck::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Truck*
Truck::Make(
CreateMessage *message,
ReplicatorID *base_id
)
{
Check_Object(message);
gos_PushCurrentHeap(Heap);
Truck *new_entity = new
Truck(DefaultData, message, base_id, NULL);
gos_PopCurrentHeap();
Check_Object(new_entity);
Check_Object(EntityManager::GetInstance());
EntityManager::GetInstance()->AddMover(new_entity);
return new_entity;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Truck::Truck(
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);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Truck::~Truck()
{
Check_Object(EntityManager::GetInstance());
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Truck::Reuse(
const CreateMessage *message,
ReplicatorID *base_id
)
{
Check_Object(this);
Check_Object(message);
STOP(("Not implemented"));
BaseClass::Reuse(message, base_id);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Truck::CommonCreation(CreateMessage *message)
{
Check_Object(this);
Check_Object(message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Truck::Respawn(Entity::CreateMessage *message)
{
Check_Object(this);
Check_Object(message);
BaseClass::Respawn(message);
CreateMessage *vehicle_message = Cast_Pointer(CreateMessage *, message);
CommonCreation(vehicle_message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void Truck::TurnOn (void)
{
lastParameterization = gos_GetElapsedTime ();
executionState->RequestState(ExecutionStateEngine::DrivingMotionState);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Truck::PreCollisionExecute(Time till)
{
Check_Object(this);
PRECOLLISION_LOGIC("Truck");
#if defined(LAB_ONLY)
if (!instanceName)
MWGameInfo::g_LastVehicle[0] = '\0';
else
{
strncpy(MWGameInfo::g_LastVehicle, instanceName, sizeof(MWGameInfo::g_LastVehicle)-1);
MWGameInfo::g_LastVehicle[sizeof(MWGameInfo::g_LastVehicle)-1] = '\0';
}
MWGameInfo::g_LastVehiclePos = GetLocalToWorld ();
#endif
//
//-------------------------------------------------------------
// Let the base class deal with setting up the motion variables
//-------------------------------------------------------------
//
BaseClass::PreCollisionExecute(till);
Set_Statistic(Executed_Truck_Count, Executed_Truck_Count+1);
//
//----------------------------------------------------------------------
// Any executing vehicle should not be in never execute state and should
// always use post collision
//----------------------------------------------------------------------
//
Check_Object(executionState);
int pre_state = executionState->GetState();
Verify(pre_state != ExecutionStateEngine::NeverExecuteState);
//
//-------------------------------------------------------------------------
// Do the appropriate type of simulation. Animated motion state is for BRB
//-------------------------------------------------------------------------
//
Scalar time_slice = GetTimeSlice(till);
switch (pre_state)
{
//
//----------------------------------------------------
// Always execute state is for the normal driving code
//----------------------------------------------------
//
case ExecutionStateEngine::DyingState:
ComputeFrictionSpeed (time_slice);
UpdateVehiclePosition (time_slice);
break;
case ExecutionStateEngine::DrivingMotionState:
ComputeForwardSpeed(time_slice);
UpdateVehiclePosition(time_slice);
break;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void Truck::PostCollisionExecute (Stuff::Time time)
{
Check_Object(this);
POSTCOLLISION_LOGIC("Truck");
int pre_state = executionState->GetState();
Verify(pre_state != ExecutionStateEngine::NeverExecuteState);
switch (pre_state)
{
case ExecutionStateEngine::DyingState:
// check for unit stopped falling and moving
if ((localSpaceVelocity.linearMotion.z == 0.0f) && ((localSpaceVelocity.linearMotion.y == 0.0f)))
{
Verify (m_DeathDamageMode != -1);
Verify (m_DeathDamageType != -1);
const GameModel *model = GetGameModel();
Check_Object(model);
DealSplashDamage();
SetDead ();
Entity::ReactToDestruction(m_DeathDamageMode,m_DeathDamageType);
// CreateEffect(model->secondaryDestroyedEffectResource, this);
if(!m_deathEntity.GetCurrent())
{
Entity *death_entity = CreateStaticHermitEntity(model->deathEntityResource);
if(death_entity)
{
m_deathEntity.Remove();
m_deathEntity.Add(death_entity);
}
}
executionState->RequestState(ExecutionStateEngine::NeverExecuteState);
entityElement->SetAlwaysCullMode();
RemoveCollision();
lastParameterization = GetTimeSlice (time);
initialLocalToParent = GetLocalToParent();
SyncMatrices(true);
}
break;
}
BaseClass::PostCollisionExecute (time);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Truck::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void Truck::ReactToDestruction(int damage_mode, int damage_type)
{
if (damage_mode != InternalDamageObject::DestructionDamageMode)
{
SPEW(("jerryeds", "DYING WITHOUT DEATH!!!"));
SPEW(("daberger", "DYING WITHOUT DEATH!!!"));
damage_mode = InternalDamageObject::DestructionDamageMode;
}
if ((localSpaceVelocity.linearMotion.z == 0.0f) && ((localSpaceVelocity.linearMotion.y == 0.0f)))
{
BaseClass::ReactToDestruction (damage_mode,damage_type);
return;
}
switch(damage_mode)
{
case InternalDamageObject::DestructionDamageMode:
{
if(m_AI)
{
Check_Object(m_AI);
m_AI->Die();
}
else
{
MW4AI::g_Rect4DHash->RemovePermRect (this);
}
if((!IsDestroyed()) && (!m_SecondaryExplosion.GetCurrent ()))
{
m_DeathDamageMode = damage_mode;
m_DeathDamageType = damage_type;
const GameModel *model = GetGameModel();
SetDying ();
Check_Object(model);
Effect *eff;
eff = CreateEffect(model->secondaryDestroyedEffectResource, this,true);
Check_Object (eff);
m_SecondaryExplosion.Add (eff);
executionState->RequestState(ExecutionStateEngine::DyingState);
}
}
}
}