//===========================================================================// // 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 #include #include #include #include #include #include //############################################################################# //############################### 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)); }