#include "MW4Headers.hpp" #include "Field_Base.hpp" #include "moverai.hpp" #include "mech.hpp" #include 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 *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)); }