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

438 lines
12 KiB
C++

#include "MW4Headers.hpp"
#include "Field_Base.hpp"
#include "moverai.hpp"
#include "mech.hpp"
#include <Adept\EntityManager.hpp>
const Scalar DOOR_MOVE_AMOUNT = 6.5f; //m
const Scalar LIFT_MOVE_AMOUNT = 10.0f; //m
const Scalar LIFT_OPEN_SPEED = 1.0f; // mps
const Scalar DOOR_OPEN_SPEED = (DOOR_MOVE_AMOUNT/(LIFT_MOVE_AMOUNT/LIFT_OPEN_SPEED)); // mps
//#############################################################################
//############################# FieldBase ################################
//#############################################################################
const StateEngine::StateEntry
FieldBase::ExecutionStateEngine::StateEntries[]=
{
STATE_ENTRY(FieldBase__ExecutionStateEngine, OpenDoor),
STATE_ENTRY(FieldBase__ExecutionStateEngine, CloseDoor)
};
FieldBase::ExecutionStateEngine::ClassData* FieldBase::ExecutionStateEngine::DefaultData = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::ExecutionStateEngine::InitializeClass()
{
Check_Object(BaseClass::DefaultData);
Verify(!DefaultData);
DefaultData =
new ClassData(
FieldBase__ExecutionStateEngineClassID,
"FieldBase::ExecutionStateEngine",
BaseClass::DefaultData,
ELEMENTS(StateEntries), StateEntries,
(Entity::ExecutionStateEngine::Factory)Make,
(Entity::ExecutionStateEngine::FactoryRequest::Factory)
&FactoryRequest::ConstructFactoryRequest
);
Register_Object(DefaultData);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::ExecutionStateEngine::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
FieldBase::ExecutionStateEngine* FieldBase::ExecutionStateEngine::Make(FieldBase *vehicle,FactoryRequest *request)
{
Check_Object(vehicle);
Check_Object(request);
gos_PushCurrentHeap(Heap);
FieldBase::ExecutionStateEngine *engine = new FieldBase::ExecutionStateEngine(DefaultData, vehicle, request);
gos_PopCurrentHeap();
return engine;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int FieldBase::ExecutionStateEngine::RequestState(int new_state,void* data)
{
Check_Object(this);
Check_Object(owningEntity);
//
//-------------------------------------------
// If there is no change of state just return
//-------------------------------------------
//
// FieldBase *base = Cast_Object (FieldBase *,owningEntity);
if (new_state == currentState)
return currentState;
switch (new_state)
{
case RepairState:
if (currentState != CloseDoorState)
{
new_state = CloseDoorState;
}
break;
case NeverExecuteState:
if ((currentState == RepairState) || (currentState == CloseDoorState))
{
new_state = OpenDoorState;
}
break;
break;
}
BaseClass::RequestState(new_state, data);
return currentState;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::ExecutionStateEngine::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
FieldBase::ClassData* FieldBase::DefaultData = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::InitializeClass()
{
Check_Object(MWMover::ExecutionStateEngine::DefaultData);
Verify(!DefaultData);
DefaultData =
new ClassData(
FieldBaseClassID,
"MechWarrior4::FieldBase",
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 FieldBase::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
FieldBase* FieldBase::Make(
CreateMessage *message,
ReplicatorID *base_id
)
{
Check_Object(message);
gos_PushCurrentHeap(Heap);
FieldBase *new_entity = new FieldBase(DefaultData, message, base_id, NULL);
gos_PopCurrentHeap();
Check_Object(new_entity);
Check_Object(EntityManager::GetInstance());
EntityManager::GetInstance()->AddMover(new_entity);
return new_entity;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
FieldBase::FieldBase(
ClassData *class_data,
CreateMessage *message,
ReplicatorID *base_id,
ElementRenderer::Element *element
):
MFB(class_data, message, base_id, element)
{
Check_Pointer(this);
Check_Object(message);
CommonCreation(message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
FieldBase::~FieldBase()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::Reuse(const CreateMessage *message,ReplicatorID *base_id)
{
Check_Object(this);
Check_Object(message);
STOP(("Not implemented"));
BaseClass::Reuse(message, base_id);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::CommonCreation(CreateMessage *message)
{
Check_Object(this);
Check_Object(message);
m_FirstFrame = true;
//m_RepairDistance = 9.0f;
m_DoorAR = FindChildMover ("joint_DoorAR");
m_DoorFR = FindChildMover ("joint_DoorAL");
m_DoorAL = FindChildMover ("joint_DoorFR");
m_DoorFL = FindChildMover ("joint_DoorFL");
m_Lift = FindChildMover ("joint_Lift");
m_HasDoors = false;
if ((m_DoorAR) && (m_DoorFR) && (m_DoorAL) && (m_DoorFL) && (m_Lift))
m_HasDoors = true;
m_BaseYDoorAR = 0;
m_BaseYDoorFR = 0;
m_BaseYDoorAL = 0;
m_BaseYDoorFL = 0;
m_BaseYLift = 0;
m_LiftAmount =0;
m_DoorAmount =0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::Respawn(Entity::CreateMessage *message)
{
Check_Object(this);
Check_Object(message);
BaseClass::Respawn(message);
CreateMessage *vehicle_message = Cast_Pointer(CreateMessage *, message);
CommonCreation(vehicle_message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::TurnOn (void)
{
lastParameterization = gos_GetElapsedTime ();
executionState->RequestState(ExecutionStateEngine::DrivingMotionState);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::PreCollisionExecute(Time till)
{
Check_Object(this);
PRECOLLISION_LOGIC("MFB");
//
//-------------------------------------------------------------
// Let the base class deal with setting up the motion variables
//-------------------------------------------------------------
//
if ((m_FirstFrame) && (m_HasDoors))
{
Point3D loc;
loc = (Point3D) m_DoorAR->GetLocalToParent ();
m_BaseYDoorAR = loc.x;
loc = (Point3D) m_DoorFR->GetLocalToParent ();
m_BaseYDoorFR = loc.x;
loc = (Point3D) m_DoorAL->GetLocalToParent ();
m_BaseYDoorAL = loc.x;
loc = (Point3D) m_DoorFL->GetLocalToParent ();
m_BaseYDoorFL = loc.x;
loc = (Point3D) m_Lift->GetLocalToParent ();
m_BaseYLift = loc.y;
}
m_FirstFrame = false;
BaseClass::PreCollisionExecute(till);
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::OpenDoorState:
DoorOpenAnim (time_slice);
if ((m_DoorAmount == 0) || (!m_HasDoors))
{
executionState->RequestState (ExecutionStateEngine::NeverExecuteState);
if (m_repairingMech.GetCurrent ())
{
AI *ai;
ai = m_repairingMech.GetCurrent ()->GetAI ();
if (ai && ai->IsDerivedFrom (MoverAI::DefaultData))
{
MoverAI *move;
move = Cast_Object (MoverAI *,ai);
move->NextFieldBase ();
}
}
}
break;
//
//-----------------------------------------------------------
//We need to repair now...some mech powered down inside of us
//-----------------------------------------------------------
//
case ExecutionStateEngine::CloseDoorState:
DoorCloseAnim (time_slice);
if ((m_DoorAmount == DOOR_MOVE_AMOUNT) || (!m_HasDoors))
executionState->RequestState (ExecutionStateEngine::RepairState);
break;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::DoorOpenAnim (Stuff::Time slice)
{
if (!m_HasDoors)
return;
m_DoorAmount -= (Scalar) (slice / DOOR_OPEN_SPEED);
Clamp (m_DoorAmount,0,DOOR_MOVE_AMOUNT);
m_LiftAmount -= (Scalar) (slice / LIFT_OPEN_SPEED);
Clamp (m_LiftAmount,0,LIFT_MOVE_AMOUNT);
LinearMatrix4D mat = m_DoorAR->GetLocalToParent ();
mat(W_Axis, X_Axis) = m_BaseYDoorAR + m_DoorAmount;
m_DoorAR->SetNewLocalToParent (mat);
mat = m_DoorFR->GetLocalToParent ();
mat(W_Axis, X_Axis) = m_BaseYDoorFR - m_DoorAmount;
m_DoorFR->SetNewLocalToParent (mat);
mat = m_DoorAL->GetLocalToParent ();
mat(W_Axis, X_Axis) = m_BaseYDoorAL + m_DoorAmount;
m_DoorAL->SetNewLocalToParent (mat);
mat = m_DoorFL->GetLocalToParent ();
mat(W_Axis, X_Axis) = m_BaseYDoorFL - m_DoorAmount;
m_DoorFL->SetNewLocalToParent (mat);
mat = m_Lift->GetLocalToParent ();
mat(W_Axis, Y_Axis) = m_BaseYLift - m_LiftAmount;
m_Lift->SetNewLocalToParent (mat);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::DoorCloseAnim (Stuff::Time slice)
{
if (!m_HasDoors)
return;
m_DoorAmount += (Scalar) (slice / DOOR_OPEN_SPEED);
Clamp (m_DoorAmount,0,DOOR_MOVE_AMOUNT);
m_LiftAmount += (Scalar) (slice / LIFT_OPEN_SPEED);
Clamp (m_LiftAmount,0,LIFT_MOVE_AMOUNT);
LinearMatrix4D mat = m_DoorAR->GetLocalToParent ();
mat(W_Axis, X_Axis) = m_BaseYDoorAR + m_DoorAmount;
m_DoorAR->SetNewLocalToParent (mat);
mat = m_DoorFR->GetLocalToParent ();
mat(W_Axis, X_Axis) = m_BaseYDoorFR - m_DoorAmount;
m_DoorFR->SetNewLocalToParent (mat);
mat = m_DoorAL->GetLocalToParent ();
mat(W_Axis, X_Axis) = m_BaseYDoorAL + m_DoorAmount;
m_DoorAL->SetNewLocalToParent (mat);
mat = m_DoorFL->GetLocalToParent ();
mat(W_Axis, X_Axis) = m_BaseYDoorFL - m_DoorAmount;
m_DoorFL->SetNewLocalToParent (mat);
mat = m_Lift->GetLocalToParent ();
mat(W_Axis, Y_Axis) = m_BaseYLift - m_LiftAmount;
m_Lift->SetNewLocalToParent (mat);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool FieldBase::CollisionHandler(Stuff::LinearMatrix4D *new_position,Stuff::DynamicArrayOf<CollisionData> *collisions)
{
Check_Object(this);
Verify(GetInterestLevel() != DormantInterestLevel);
Verify(!newCollisions);
delete collisions;
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::ReactToDestruction(int damage_mode, int damage_type)
{
if (m_repairingMech.GetCurrent ())
{
AI *ai;
m_repairingMech.GetCurrent ()->ShutDownRequest(false);
ai = m_repairingMech.GetCurrent ()->GetAI ();
if (ai && ai->IsDerivedFrom (MoverAI::DefaultData))
{
MoverAI *move;
move = Cast_Object (MoverAI *,ai);
move->FieldBaseDead ();
}
}
MFB::ReactToDestruction (damage_mode,damage_type);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void FieldBase::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}