//===========================================================================// // 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 // // 12/26/01 MSL Added Eject Code to ReactToDestruction and changed site to // // "site_eject2" // //---------------------------------------------------------------------------// // Copyright (C) 1998, Fasa Interactive // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "MW4Headers.hpp" #include "Mech.hpp" #include "Torso.hpp" #include "HeatManager.hpp" #include "JumpJet.hpp" #include "SearchLight.hpp" #include "Engine.hpp" #include "ECM.hpp" // MSL 5.02 SubSystems #include "IFF_Jammer.hpp" #include "MoverAI.hpp" #include "HeatSink.hpp" #include "MechAnimationState.hpp" #include "Blanderizer.hpp" #include "SpringOf.hpp" #include "VehicleInterface.hpp" #include "MWDamageObject.hpp" #include "EyePointManager.hpp" #include "AI_Statistics.hpp" #include "MFB.hpp" #include "Armor.hpp" #include "MWApplication.hpp" #include "Gyro.hpp" #include "SubsystemClassData.hpp" #include "mwmission.hpp" #include "bucket.hpp" #include "Sensor.hpp" #include "mwgame.hpp" #include "salvage.hpp" #include "flag.hpp" #include "playerai.hpp" #include "mwmap.hpp" #include "Team.hpp" #include "Weapon.hpp" #include "ProjectileWeapon.hpp" #include "mw4shell.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mwguimanager.hpp" #include "hudmap.hpp" // MSL 5.02 #include "guilightamp.hpp" #include "guiradarmanager.hpp" #include "hudtarg.hpp" #include "ai_userconstants.hpp" #include #include #include #include #include // ngLog addition // JKK #if !defined(NO_LOG) #include "nglog_MW4.hpp" #endif // !defined(NO_LOG) #include "mechlabheaders.h" // jcem - start #include "windows.h" #include "ctcls.h" #include "ctcl.h" #include "recscore.h" // jcem extern int g_nMR; // jcem - end // MSL 5.02 headshot namespace MechWarrior4 { extern Scalar g_HUDHeatLevel; extern Scalar g_HUDPPCLevel; extern int g_HUDHeatAlpha; } // MSL 5.02 SubSystems #include "AdvancedGyro.hpp" #include "MechLab.hpp" const Stuff::Scalar mission_area_warning_frequency = 10.0f; const Stuff::Scalar WALK_SPEED_SOUND = 10.0f; // mps // MSL 5.02 headshot const Scalar MECH_HEAD_SHOT_FALL_MOD = 1.3f; //the percentage to lower the damage threshold of what it takes to fall down when a mech takes a head-shot const Scalar MECH_HEAD_SHOT_TORSO_ROCK_MOD = 1.3f; const Scalar MECH_HEAD_SHOT_TORSO_SPIN_MOD = 1.3f; // MSL 5.02 SubSystems const Scalar ADVANCED_GYRO_FALL_MOD = 0.15f; const Scalar ADVANCED_GYRO_TORSO_ROCK_MOD = 0.15f; const Scalar ADVANCED_GYRO_TORSO_SPIN_MOD = 0.15f; // MSL 5.04 Friendly Fire Betty Stuff::Scalar m_FriendlyFireHit; //############################################################################# //################## Mech::ExecutionStateEngine ###################### //############################################################################# static int Ground_Mode=2; static bool __stdcall CheckSnapToGround() {return Ground_Mode==0;} static void __stdcall EnableSnapToGround() {Ground_Mode = (Ground_Mode==0) ? 1 : 0;} static bool __stdcall CheckFlying() {return Ground_Mode==2;} static void __stdcall EnableFlying() {Ground_Mode = (Ground_Mode==2) ? 1 : 2;} static Scalar Special_Mech_Gravity=4.0f; static bool __stdcall Checkg1_0() {return Special_Mech_Gravity==1.0f;} static bool __stdcall Checkg1_2() {return Special_Mech_Gravity==1.2f;} static bool __stdcall Checkg1_4() {return Special_Mech_Gravity==1.4f;} static bool __stdcall Checkg1_6() {return Special_Mech_Gravity==1.6f;} static bool __stdcall Checkg1_8() {return Special_Mech_Gravity==1.8f;} static bool __stdcall Checkg2_0() {return Special_Mech_Gravity==2.0f;} static bool __stdcall Checkg2_5() {return Special_Mech_Gravity==2.5f;} static bool __stdcall Checkg3_0() {return Special_Mech_Gravity==3.0f;} static bool __stdcall Checkg4_0() {return Special_Mech_Gravity==4.0f;} static bool __stdcall Checkg5_0() {return Special_Mech_Gravity==5.0f;} static void __stdcall Enableg1_0() {Special_Mech_Gravity = 1.0f;} static void __stdcall Enableg1_2() {Special_Mech_Gravity = (Special_Mech_Gravity!=1.2f) ? 1.2f : 1.0f;} static void __stdcall Enableg1_4() {Special_Mech_Gravity = (Special_Mech_Gravity!=1.4f) ? 1.4f : 1.0f;} static void __stdcall Enableg1_6() {Special_Mech_Gravity = (Special_Mech_Gravity!=1.6f) ? 1.6f : 1.0f;} static void __stdcall Enableg1_8() {Special_Mech_Gravity = (Special_Mech_Gravity!=1.8f) ? 1.8f : 1.0f;} static void __stdcall Enableg2_0() {Special_Mech_Gravity = (Special_Mech_Gravity!=2.0f) ? 2.0f : 1.0f;} static void __stdcall Enableg2_5() {Special_Mech_Gravity = (Special_Mech_Gravity!=2.5f) ? 2.5f : 1.0f;} static void __stdcall Enableg3_0() {Special_Mech_Gravity = (Special_Mech_Gravity!=3.0f) ? 3.0f : 1.0f;} static void __stdcall Enableg4_0() {Special_Mech_Gravity = (Special_Mech_Gravity!=4.0f) ? 4.0f : 1.0f;} static void __stdcall Enableg5_0() {Special_Mech_Gravity = (Special_Mech_Gravity!=5.0f) ? 5.0f : 1.0f;} void FootStepPlug::SaveToStream(MemoryStream *stream) { Check_Object(this); Check_Pointer(stream); *stream << m_material; MString texture_name = m_footTexture->GetTextureName(); *stream << texture_name; *stream << m_isDefault; } Mech::ExecutionStateEngine::ClassData* Mech::ExecutionStateEngine::DefaultData = NULL; bool Mech::DontLoadBlends = false; bool Mech::NoBlend = false; const Stuff::Scalar arm_re_null_time = 10.0f; void MechWarrior4::MechSecurityCheckStart() { _asm { nop } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ExecutionStateEngine::InitializeClass() { Check_Object(BaseClass::DefaultData); Verify(!DefaultData); DefaultData = new ClassData( Mech__ExecutionStateEngineClassID, "Mech::ExecutionStateEngine", BaseClass::DefaultData, 0, NULL, (Entity::ExecutionStateEngine::Factory)Make, (Entity::ExecutionStateEngine::FactoryRequest::Factory) &FactoryRequest::ConstructFactoryRequest ); Register_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ExecutionStateEngine::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Mech::ExecutionStateEngine* Mech::ExecutionStateEngine::Make( Mech *vehicle, FactoryRequest *request ) { Check_Object(vehicle); Check_Object(request); gos_PushCurrentHeap(Heap); Mech::ExecutionStateEngine *engine = new Mech::ExecutionStateEngine(DefaultData, vehicle, request); gos_PopCurrentHeap(); return engine; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Mech::ExecutionStateEngine::RequestState( int new_state, void* data ) { Check_Object(this); Check_Object(owningEntity); // //------------------------------------------- // If there is no change of state just return //------------------------------------------- // if (new_state == currentState) return currentState; // //---------------------------------------------------------------------- // If we are entering flying mode, take the animation velocities and jam // them into the mover variables //---------------------------------------------------------------------- // Mech *mech = Cast_Object(Mech*, owningEntity); Check_Object(mech); switch (BaseClass::RequestState(new_state, data)) { case DroppingState: case FlyingMotionState: mech->GetEyePointManager()->Follow(1.0f); mech->animStateEngine->RequestState(MechAnimationStateEngine::FlyState, Mech::NoBlend); break; // //----------------------------------------------------------------------- // If we are entering driving state, set the animation engine accordingly //----------------------------------------------------------------------- // case DrivingMotionState: if (mech->queFallState != Mech::NoFallMode) { switch(mech->queFallState) { case Mech::FallBackMode: mech->animStateEngine->RequestState(MechAnimationStateEngine::FallBackwardState, Mech::NoBlend); break; case Mech::FallRightMode: mech->animStateEngine->RequestState(MechAnimationStateEngine::FallRightState, Mech::NoBlend); break; case Mech::FallLeftMode: mech->animStateEngine->RequestState(MechAnimationStateEngine::FallLeftState, Mech::NoBlend); break; case Mech::FallForwardMode: mech->animStateEngine->RequestState(MechAnimationStateEngine::FallForwardState, Mech::NoBlend); break; } mech->StartFall(); mech->fallDirection = mech->queFallState; // mech->queFallState = Mech::NoFallMode; } else if (mech->currentSpeedMPS <= 0.0f) mech->animStateEngine->RequestState(MechAnimationStateEngine::StandState, Mech::NoBlend); else mech->animStateEngine->RequestState(MechAnimationStateEngine::ForwardState, Mech::NoBlend); break; } return currentState; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ExecutionStateEngine::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //############################################################################# //############################### Mech ############################## //############################################################################# DWORD MechWarrior4::Executed_Mech_Count = 0; // MSL ADD MECH int Mech::s_mechSlots[NoMechID]={ MechExecutionSlot+7, // Annihilator(shares with Atlas) MechExecutionSlot+6, // Archer (shares with Sunder) MechExecutionSlot+13, // Arctic Wolf(shares with Uziel) MechExecutionSlot+1, // Ares (shares with Chimera-Bushwacker) MechExecutionSlot+2, // Argus (shares with catapult) MechExecutionSlot+15, // Assassin2 (shares with crab) MechExecutionSlot+7, // Atlas MechExecutionSlot+3, // Avatar (shares with Vulture) MechExecutionSlot+0, // Awesome (shares with Mauler) MechExecutionSlot+0, // Battlemaster (Awesome) MechExecutionSlot+0, // BattlemasterIIc (Awesome) MechExecutionSlot+15, // Behemoth (shares with Daishi) MechExecutionSlot+15, // Behemoth II(shares with Daishi) MechExecutionSlot+1, // Black Hawk (shares with bushwacker MechExecutionSlot+0, // Black Knight (shares with Mauler) MechExecutionSlot+3, // Black Lanner (shares with Madcat) MechExecutionSlot+14, // Brigand (shares with Commando) MechExecutionSlot+1, // Bushwacker (shares with Chimera) MechExecutionSlot+2, // Catapult (shares with Argus) MechExecutionSlot+3, // CauldronBorn (shares with Madcat) MechExecutionSlot+1, // Chimera (shares with Bushwacker) MechExecutionSlot+14, // Commando MechExecutionSlot+8, // Cougar MechExecutionSlot+7, // Cyclops (shares with Atlas) MechExecutionSlot+9, // Daishi // MechExecutionSlot+14, // Dasher (shares with Commando) MechExecutionSlot+3, // Deimos (shares with Madcat) MechExecutionSlot+6, // Dragon (shares with Thor) MechExecutionSlot+0, // Fafnir ( Mauler ) MechExecutionSlot+5, // Flea (shares with Raven) MechExecutionSlot+0, // Gladiator (shares with Mauler) MechExecutionSlot+0, // Grizzly (shares with Awesome) MechExecutionSlot+9, // Hauptmann (shares with Daishi) MechExecutionSlot+1, // Hellhound (Chimera) MechExecutionSlot+10, // Hellspawn, MechExecutionSlot+0, // Highlander (shares with Awesome) MechExecutionSlot+15, // Hollander (shares with Crab) MechExecutionSlot+10, // Hunchback (shares with Hellspawn) MechExecutionSlot+0, // Kodiak (shares with Awesome) MechExecutionSlot+6, // Loki (shares with Thor) MechExecutionSlot+0, // Longbow (shares with Mauler) MechExecutionSlot+3, // Madcat (shares with Vulture) MechExecutionSlot+11, // Madcat2 MechExecutionSlot+9, // Masakari (shares with Daishi) MechExecutionSlot+0, // Mauler (shares with Awesome) MechExecutionSlot+4, // Novacat (shares with Thanatos) MechExecutionSlot+5, // Osiris (shares with Raven) MechExecutionSlot+5, // Owens (shares with Raven) MechExecutionSlot+8, // Puma (shares with Cougar) MechExecutionSlot+5, // Raven (shares with Osiris) MechExecutionSlot+6, // Rifleman (shares with Sunder-Thor) MechExecutionSlot+1, // Ryoken (shares with bushwacker MechExecutionSlot+12, // Shadowcat MechExecutionSlot+8, // Solitaire (Shares with Cougar) MechExecutionSlot+6, // Sunder (shares with Thor) MechExecutionSlot+0, // Templar (Awesome) MechExecutionSlot+4, // Thanatos (shares with novacat) MechExecutionSlot+6, // Thor (shares with Loki) MechExecutionSlot+8, // Uller (shares with Cougar) MechExecutionSlot+10, // Urbanmech (shares with Hellspawn) MechExecutionSlot+13, // Uziel MechExecutionSlot+0, // Victor (shares with Mauler) MechExecutionSlot+3, // Vulture (shares with Madcat) MechExecutionSlot+6, // Warhammer (shares with Thor, Sunder) MechExecutionSlot+10, // Wolfhound (shares with HellSpawn MechExecutionSlot+0 // Zeus(shares with Awesome) }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Mech::ClassData* Mech::DefaultData = NULL; const Receiver::MessageEntry Mech::MessageEntries[]= { MESSAGE_ENTRY(Mech, Update), MESSAGE_ENTRY(Mech, TakeDamage) }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::InitializeClass() { Check_Object(ExecutionStateEngine::DefaultData); Verify(!DefaultData); DefaultData = new ClassData( MechClassID, "MechWarrior4::Mech", BaseClass::DefaultData, ELEMENTS(MessageEntries), MessageEntries, (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)MechAnimationStateEngine::Make ); Register_Object(DefaultData); //Dave Need to add attribute entries DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, TiltSpeed, tiltSpeed, Radian ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, TiltDegree, tiltDegree, Radian ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, ScaleInternalTiltDegree, scaleInternalTiltDegree, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, FootReturnSeconds, footReturnSeconds, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, FallAdjustmentSeconds, fallAdjustmentSeconds, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, GetUpAdjustmentSeconds, getUpAdjustmentSeconds, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, FallAdjustmentDelaySeconds, fallAdjustmentDelaySeconds, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, GetUpAdjustmentDelaySeconds, getUpAdjustmentDelaySeconds, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, PercentageOfTurnToStartTilt, percentageOfTurnToStartTilt, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, PercentageOfSpeedToStartTilt, percentageOfSpeedToStartTilt, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, DampenWorldJoint, dampenWorldJoint, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, DampenRootJoint, dampenRootJoint, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, DampenTorsoJoint, dampenTorsoJoint, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, DampenHipJoint, dampenHipJoint, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, DampenTranslationJoint, dampenTranslationJoint, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, UndampenWorldJoint, undampenWorldJoint, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, UndampenRootJoint, undampenRootJoint, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, UndampenTorsoJoint, undampenTorsoJoint, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, UndampenHipJoint, undampenHipJoint, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, UndampenTranslationJoint, undampenTranslationJoint, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, TorsoScaleTakeHit, torsoScaleTakeHit, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, HipScaleTakeHit, hipScaleTakeHit, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, RootScaleTakeHit, rootScaleTakeHit, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, MinimumDamageForHitAnimation, minimumDamageForHitAnimation, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, MinimumDamageForInternalHitAnimation, minimumDamageForInternalHitAnimation, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, TorsoHitSpringMotionLimit, torsoHitSpringMotionLimit, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, TorsoHitSpringDeceleration, torsoHitSpringDeceleration, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, TorsoHitSpringReturnSpeed, torsoHitSpringReturnSpeed, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, TorsoHitSpringSpeed, torsoHitSpringSpeed, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, HipHitSpringMotionLimit, hipHitSpringMotionLimit, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, HipHitSpringDeceleration, hipHitSpringDeceleration, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, HipHitSpringReturnSpeed, hipHitSpringReturnSpeed, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, HipHitSpringSpeed, hipHitSpringSpeed, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, RootHitSpringMotionLimit, rootHitSpringMotionLimit, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, RootHitSpringDeceleration, rootHitSpringDeceleration, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, RootHitSpringReturnSpeed, rootHitSpringReturnSpeed, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, RootHitSpringSpeed, rootHitSpringSpeed, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, ExternalHitScaleBeamDamage, externalHitScaleBeamDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, ExternalHitScaleMissileDamage, externalHitScaleMissileDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, ExternalHitScaleProjectileDamage, externalHitScaleProjectileDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, ExternalHitScaleSplashDamage, externalHitScaleSplashDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, ExternalHitScaleHeatDamage, externalHitScaleHeatDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InternalHitScaleBeamDamage, internalHitScaleBeamDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InternalHitScaleMissileDamage, internalHitScaleMissileDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InternalHitScaleProjectileDamage, internalHitScaleProjectileDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InternalHitScaleSplashDamage, internalHitScaleSplashDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InternalHitScaleHeatDamage, internalHitScaleHeatDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InternalSpinHitScaleBeamDamage, internalSpinHitScaleBeamDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InternalSpinHitScaleMissileDamage, internalSpinHitScaleMissileDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InternalSpinHitScaleProjectileDamage, internalSpinHitScaleProjectileDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InternalSpinHitScaleSplashDamage, internalSpinHitScaleSplashDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InternalSpinHitScaleHeatDamage, internalSpinHitScaleHeatDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, SpinForceBeamDamage, spinForceBeamDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, SpinForceMissileDamage, spinForceMissileDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, SpinForceProjectileDamage, spinForceProjectileDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, SpinForceSplashDamage, spinForceSplashDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, SpinForceHeatDamage, spinForceHeatDamage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, EyeSpringMotionLimit, eyeSpringMotionLimit, Point3D ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, EyeSpringConstant, eyeSpringConstant, Point3D ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, EyeSpringDrag, eyeSpringDrag, Point3D ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, EyeSpringStopThreshold, eyeSpringStopThreshold, Point3D ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, JumpJetEffect, jumpJetEffect, ResourceID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, LeftJumpJetSiteName, leftJumpJetSiteName, const char *, CharClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, RightJumpJetSiteName, rightJumpJetSiteName, const char *, CharClassID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, SearchLightResource, searchLightResource, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, InitialJumpJetEffect, initialJumpJetEffect, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, MaxHeat, maxHeat, Scalar ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, MechID, mechID, int, IntClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, CanLoadJumpJets, m_canLoadJumpJets, bool, BoolClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, CanLoadECM, m_canLoadECM, bool, BoolClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, CanLoadBeagle, m_canLoadBeagle, bool, BoolClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, CanLoadLightAmp, m_canLoadLightAmp, bool, BoolClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, CanLoadAMS, m_canLoadAMS, bool, BoolClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, CanLoadLAMS, m_canLoadLAMS, bool, BoolClassID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, JumpJetTonnage, m_jumpJetTonnage, Scalar ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, TechType, techType, int, IntClassID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, CageDamageEffect, m_cageDamageEffect, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, DamageNeededForCageEffect, damageNeededForCageEffect, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, MechRamEffect, m_mechRamEffect, ResourceID ); // MSL 5.03 Glass DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, MechGlassRamEffect, m_mechGlassRamEffect, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, WakeEffectResource, m_wakeEffectResource, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, Cradle, cradle, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, CradleDeathEffect, cradleDeathEffect, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, DropJumpEffect, dropJumpEffect, ResourceID ); // MSL 5.02 SubSystems // CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( // Mech__GameModel, // CanLoadEnhancedOptics, // m_canLoadEnhancedOptics, // bool, // BoolClassID // ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, CanLoadIFF_Jammer, m_canLoadIFF_Jammer, bool, BoolClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, CanLoadAdvancedGyro, m_canLoadAdvancedGyro, bool, BoolClassID ); DIRECT_GAME_MODEL_ATTRIBUTE( Mech__GameModel, AdvancedGyroTonnage, m_advancedGyroTonnage, Scalar ); AddDebuggerMenuItem("Libraries\\Mech\\Snap To Ground", CheckSnapToGround, EnableSnapToGround, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\Enable Jump Animation", CheckFlying, EnableFlying, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\ ",0,0,0); AddDebuggerMenuItem("Libraries\\Mech\\1.0 g", Checkg1_0, Enableg1_0, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\1.2 g", Checkg1_2, Enableg1_2, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\1.4 g", Checkg1_4, Enableg1_4, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\1.6 g", Checkg1_6, Enableg1_6, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\1.8 g", Checkg1_8, Enableg1_8, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\2.0 g", Checkg2_0, Enableg2_0, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\2.5 g", Checkg2_5, Enableg2_5, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\3.0 g", Checkg3_0, Enableg3_0, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\4.0 g", Checkg4_0, Enableg4_0, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\5.0 g", Checkg5_0, Enableg5_0, 0 ); AddDebuggerMenuItem("Libraries\\Mech\\ ",0,0,0); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Mech* Mech::Make( CreateMessage *message, ReplicatorID *base_id ) { Check_Object(message); gos_PushCurrentHeap(Heap); Mech *new_mech = new Mech(DefaultData, message, base_id, NULL); gos_PopCurrentHeap(); Check_Object(new_mech); Check_Object(EntityManager::GetInstance()); EntityManager::GetInstance()->AddMover(new_mech); return new_mech; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Replicator::CreateMessage* Mech::SaveMakeMessage(MemoryStream *stream, ResourceFile *res_file) { Check_Object(this); Check_Object(stream); stream->AllocateBytes(sizeof(CreateMessage)); BaseClass::SaveMakeMessage(stream, res_file); CreateMessage *message = Cast_Pointer(CreateMessage*, stream->GetPointer()); message->messageLength = sizeof(*message); Check_Object(m_heatManager); message->currentHeat = m_heatManager->GetHeat(); message->currentCoolant = m_heatManager->GetCoolant(); message->maxCoolant = m_heatManager->GetMaxCoolant(); message->m_doesHaveLightAmp = m_doesHaveLightAmp; //Used for Mech lab and are not read in except by the shell // MSL 5.04 Modified Firepower bar // message->m_powerBar = (int)(GetBattleValue()); // message->m_powerBar = (int)(GetBattleValue() / 4); message->m_powerBar = (int)((GetBattleValue() / 80.0) * 100.0); Clamp(message->m_powerBar, 0, 100); // MSL 5.04 Modified Speed bar Engine *engine = GetEngine(); Check_Object(engine); const GameModel *mech_model = GetGameModel(); Verify(mech_model->maxSpeed > mech_model->minMaxSpeed); // Scalar speed_ratio = (engine->GetMaxSpeed()- mech_model->minMaxSpeed) / (mech_model->maxSpeed - mech_model->minMaxSpeed); Scalar speed_ratio = (engine->GetMaxSpeed() / mech_model->maxSpeed); message->m_speedBar = (int)(speed_ratio * 100); Clamp(message->m_speedBar, 0, 100); // MSL 5.04 Modified Armor bar Armor *armor = GetArmor(); Check_Object(armor); // message->m_armorBar = (int)armor->GetTotalTonage() * 5; // Clamp(message->m_armorBar, 0, 100); // message->m_armorBar = (int)((armor->GetTotalArmor() / 307.0) * 100.0); // MSL 5.05 Modified Armor bar message->m_armorBar = (int)((armor->GetTotalArmor() / 535.0) * 100.0); Clamp(message->m_armorBar, 0, 100); message->m_heatBar = GetHeatEffic(); Clamp(message->m_heatBar, 0, 100); message->m_mechID = mech_model->mechID; return message; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Mech::Mech( ClassData *class_data, CreateMessage *message, ReplicatorID *base_id, ElementRenderer::Element *element ): ejectEffect (NULL), BaseClass(class_data, message, base_id, element), m_FallDampingEnabled(false), m_LastFootFallTime(0), m_footSteps(NULL, true), m_LastMissionWarning(0), m_leftCageEffect(NULL), m_rightCageEffect(NULL), m_DropCradle (NULL), m_JumpEffect1 (NULL), m_JumpEffect2 (NULL), m_JumpEffect3 (NULL), m_JumpEffect4 (NULL), m_wakeEffect(NULL), // MSL 5.02 headshot dwDamageFlags(0), m_HeadShotFallDamageMod(1.0), m_HeadShotTorsoRockDamageMod(1.0), m_HeadShotTorsoSpinDamageMod(1.0), // MSL 5.02 SubSystems dwGyroDamageFlags(0), m_AdvancedGyroFallDamageMod(1.0), m_AdvancedGyroTorsoRockDamageMod(1.0), m_AdvancedGyroTorsoSpinDamageMod(1.0), m_lastHits(NULL, true) { Check_Pointer(this); Check_Object(message); Verify(animStateEngine != NULL); initialPositions = new Origin3D[animationArrayCount]; Register_Pointer(initialPositions); lancemateIndex = -1; m_FallDamage = 0; m_numHeatSinks = 0; m_LastSoundSpeedMPS = 0; m_mechTablePlug = NULL; m_MaxFlagsCarried = -1; Verify(!CanBeWalkedOn()); for (int i = 0; i < animationArrayCount; ++i) { ElementRenderer::Element *element; Verify(!animationArray[i]->CanBeWalkedOn()); element = animationArray[i]->GetElement(); Check_Object(element); initialPositions[i] = element->GetNewLocalToParent(); } //find the feet... jumpJet = NULL; HookUpSubsystems(); jointWorld = NULL; jointWorld = FindChildMover("joint_WORLD"); siteLeftFoot = NULL; siteRightFoot = NULL; leftFootNormal = Normal3D (0,1,0); rightFootNormal = Normal3D (0,1,0); jointSearchLight = NULL; jointSearchLight = FindChildMover("joint_searchlight"); m_leftCageSite = NULL; m_rightCageSite = NULL; m_playLeftCageEffect = false; m_playRightCageEffect = false; m_leftCageSite = FindSite("site_cageleft"); m_rightCageSite = FindSite("site_cageright"); /* has to be redone in BecomeInteresting anyway if(Mission::GetInstance()) { Check_Pointer(Mission::GetInstance()); const Mission::GameModel *mission_model = Mission::GetInstance()->GetGameModel(); Check_Object(mission_model); if(!mission_model->m_allowRunningLights) { DestroyRunningLight(); } if(!mission_model->m_allowSearchLights) { DestroySearchLight(); if(GetSearchLight()) GetSearchLight()->HideBeam(); } } */ siteLeftFoot = FindSite("site_lfoot"); siteRightFoot = FindSite("site_rfoot"); Check_Object(siteLeftFoot); Check_Object(siteRightFoot); jointLeftAnkle = NULL; jointRightAnkle = NULL; jointLeftAnkle = FindChildMover("joint_lbelowankle"); jointRightAnkle = FindChildMover("joint_rbelowankle"); Check_Object(jointLeftAnkle); Check_Object(jointRightAnkle); worldJointIndex = FindChildMoverIndex("joint_WORLD"); rootJointIndex = FindChildMoverIndex("joint_ROOT"); hipJointIndex = FindChildMoverIndex("joint_hip"); torsoJointIndex = FindChildMoverIndex("joint_torso"); centerTorso = FindChildMover("joint_torso"); searchLightSite = FindSite("site_light"); Check_Object(searchLightSite); const GameModel *model = GetGameModel(); Check_Object(model); m_mechSlot = s_mechSlots[model->mechID]; // MSL Add Mech Verify(m_mechSlot >= MechExecutionSlot && m_mechSlot < MechExecutionSlot+16); // //--------------------------------------------------- //If we have a search light then we have to create it //--------------------------------------------------- // searchLightEffect = NULL; if(model->searchLightResource != ResourceID::Null) { searchLightEffect = CreateEffect(model->searchLightResource, searchLightSite, true); Check_Object(searchLightEffect); } Verify(worldJointIndex != -1); Verify(rootJointIndex != -1); Verify(hipJointIndex != -1); Verify(torsoJointIndex != -1); torsoAboveJointIndex = FindChildMoverIndex("joint_torsoabove"); hipAboveJointIndex = FindChildMoverIndex("joint_hipabove"); //leftGunAboveJointIndex = FindChildMoverIndex("joint_lgunabove"); //leftArmAboveJointIndex = FindChildMoverIndex("joint_luarmabove"); //rightGunAboveJointIndex = FindChildMoverIndex("joint_rgunabove"); Verify(torsoAboveJointIndex != -1); Verify(hipAboveJointIndex != -1); //Verify(leftGunAboveJointIndex != -1); //Verify(leftArmAboveJointIndex != -1); //Verify(rightGunAboveJointIndex != -1); leftGunJointIndex = FindChildMoverIndex("joint_lgun"); leftArmJointIndex = FindChildMoverIndex("joint_luarm"); rightGunJointIndex = FindChildMoverIndex("joint_rgun"); rightArmJointIndex = FindChildMoverIndex("joint_ruarm"); Verify(leftGunJointIndex != -1); Verify(leftArmJointIndex != -1); Verify(rightGunJointIndex != -1); Verify(rightArmJointIndex != -1); int joint_number = FindChildMoverIndexUserData("site_lfoot", this); animationTriggerManager.RegisterTriggerCallback(joint_number, 0, (TriggerMessageHandler)LeftFootTriggerHandler); joint_number = FindChildMoverIndexUserData("site_rfoot", this); animationTriggerManager.RegisterTriggerCallback(joint_number, 0, (TriggerMessageHandler)RightFootTriggerHandler); leftJumpJetSite = NULL; rightJumpJetSite = NULL; leftJumpJetSite = FindSite(model->leftJumpJetSiteName); rightJumpJetSite = FindSite(model->rightJumpJetSiteName); if(GetJumpJet()) GetJumpJet()->SetJumpJetData( model->jumpJetEffect, model->initialJumpJetEffect, leftJumpJetSite, rightJumpJetSite ); m_heatManager = new HeatManager( model->maxHeat, message->currentHeat, message->maxCoolant, message->currentCoolant, this, model->heatManagerResource ); m_doesHaveLightAmp = message->m_doesHaveLightAmp; if(m_doesHaveLightAmp) { if(DoesHaveAvailableTonage(1.0f)) { AddTonage(1.0f); } else { //no Tonnage for this! m_doesHaveLightAmp = false; } } SeedHeatManager(); m_eyePointManager = new EyePointManager(this); m_gyro = new Gyro(this); deadReckonCurve = NULL; CommonCreation(message); // // [johnyo] 08/27/00 PreviousSearchLight code is experimental code that I have checked in to keep a backup // of only. It may be ripped out shortly if the effect that it was intended to have isn't // put into the game // // if (GetSearchLight()) // { // m_previousSearchLightState = GetSearchLight()->isLightOn; // } // else // { // m_previousSearchLightState = false; // } if(model->footStepsResource != ResourceID::Null) { CreateFootTextureChain(model->footStepsResource); } m_startTons = GetTonage(); // MSL 5.02 SubSystems if (GetAdvancedGyro()) { // MSL 5.03 Gyro Hit m_AdvancedGyroFallDamageMod = 1.0; m_AdvancedGyroTorsoRockDamageMod = 1.0; m_AdvancedGyroTorsoSpinDamageMod = 1.0; // m_AdvancedGyroFallDamageMod = ADVANCED_GYRO_FALL_MOD; // m_AdvancedGyroTorsoRockDamageMod = ADVANCED_GYRO_TORSO_ROCK_MOD; // m_AdvancedGyroTorsoSpinDamageMod = ADVANCED_GYRO_TORSO_SPIN_MOD; } else { m_AdvancedGyroFallDamageMod = 1.0; m_AdvancedGyroTorsoRockDamageMod = 1.0; m_AdvancedGyroTorsoSpinDamageMod = 1.0; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::CommonCreation(CreateMessage *message) { Check_Object(this); Check_Object(message); const GameModel *model = GetGameModel(); Check_Object(model); ClearInterestings(); // jcem m_fTimeRespawnRequestEnd = 0.0f; // jcem - for delayed lancemate respawn m_fTimeMsgSentEnd = 0.0f; // jcem - gos_GetElapsedTime() + duration m_nMsgKind = 0; // 0-6(team message), 7-13(taunt, FFA), 14/15 yes/no m_CanStartGettingUp = false; m_NeedStartDrop = false; m_CanStartDropJetEffect = false; m_DropSite = NULL; m_JumpSite1 = NULL; m_JumpSite2 = NULL; m_JumpSite3 = NULL; m_JumpSite4 = NULL; m_NeedKillDropCradleEffect = false; m_gyro->AbortFall(); if (deadReckonCurve != NULL) { delete deadReckonCurve; deadReckonCurve = NULL; } deadReckonScale = 0.0f; deadReckonCurveTime = 0.0f; allowedToAnimateVelocity = true; m_footHitEntity = NULL; m_lastFall = (Scalar)gos_GetElapsedTime(); m_ForceYaw = false; m_ForceYawValue = 0; m_ForceSpeed = false; m_ForceSpeedValue = 0; m_FallDamage = 0.0f; m_heatMaterialMultiplier = 1.0f; m_sensorDinstanceMultiplier = 1.0f; diedBySplash = false; lastFramePushUp = 0.0f; leftFootGround = 0.0f; rightFootGround = 0.0f; leftFootReturnTimer = 0.0f; rightFootReturnTimer = 0.0f; tiltAngle = 0.0f; m_SavedFractionalDamage = 0.0f; m_SavedFractionalModDamage = 0.0f; // MSL 5.03 Lava m_lastLavaTime = gos_GetElapsedTime(); m_NeedEject = 0; // MSL 5.03 PPC Hud Effect Reset g_HUDPPCLevel = 0; fallTimer = 0.0f; getUpTimer = 0.0f; blockFallTimer = 0.0f; m_needWakeEffect = 0; groundAngleDbg = Stuff::YawPitchRoll::Identity; leftFootDown = false; rightFootDown = false; isLeftFootDown = false; isRightFootDown = false; m_selfDestructTimer = gos_GetElapsedTime(); pitchSmoother.SetSize(4); rollSmoother.SetSize(4); lastSpeedMPS = 0.0f; leftJumpJetEffect = NULL; rightJumpJetEffect = NULL; queFallState = NoFallMode; fallDirection = NoFallMode; gimpState = NotGimpedMode; triggerDeath = NoDeathTrigger; vehicleRunsInterface = false; lastHitDirection = NoHitDirection; takenDamageThisFrame = false; lastDamageTaken = 0.0f; currentRightFootFall = ResourceID::Null; currentLeftFootFall = ResourceID::Null; armsNulled = false; armBlanderizer.SetNewDampen(0.0f); armReNullTime = 0; torsoBlanderizer.SetNewDampen(0.0f); m_alreadyShutDown = false; leftFootTurnAccumulation = 0.0f; rightFootTurnAccumulation = 0.0f; leftFootState = FootNormal; rightFootState = FootNormal; YawPitchRoll motion_limit; YawPitchRoll motion_acceleration; YawPitchRoll return_speed; YawPitchRoll home_position; YawPitchRoll outward_force; Point3D p_motion_limit; Point3D p_motion_acceleration; Point3D p_return_speed; Point3D p_outward_force; motion_limit = YawPitchRoll(0.0f, model->rootHitSpringMotionLimit, 0.0f); motion_acceleration = YawPitchRoll(0.0f,model->rootHitSpringDeceleration, 0.0f); return_speed = YawPitchRoll(0.0f,model->rootHitSpringReturnSpeed,0.0f); outward_force = YawPitchRoll(0.0f,model->rootHitSpringSpeed,0.0f); home_position = initialPositions[rootJointIndex].angularPosition; rootHit.Initialize(motion_limit, motion_acceleration, return_speed, home_position, outward_force); motion_limit = YawPitchRoll(model->torsoHitSpringMotionLimit, 0.0f, 0.0f); motion_acceleration = YawPitchRoll(model->torsoHitSpringDeceleration, 0.0f, 0.0f); return_speed = YawPitchRoll(model->torsoHitSpringReturnSpeed,0.0f, 0.0f); outward_force = YawPitchRoll(model->torsoHitSpringSpeed,0.0f,0.0f); home_position = initialPositions[torsoAboveJointIndex].angularPosition; torsoHit.Initialize(motion_limit, motion_acceleration, return_speed, home_position, outward_force); motion_limit = YawPitchRoll(0.0f, model->hipHitSpringMotionLimit, 0.0f); motion_acceleration = YawPitchRoll(0.0f,model->hipHitSpringDeceleration, 0.0f); return_speed = YawPitchRoll(0.0f,model->hipHitSpringReturnSpeed,0.0f); outward_force = YawPitchRoll(0.0f,model->hipHitSpringSpeed,0.0f); home_position = initialPositions[hipAboveJointIndex].angularPosition; hipHit.Initialize(motion_limit, motion_acceleration, return_speed, home_position, outward_force); #if 0 motion_limit = YawPitchRoll(40.0f*Stuff::Radians_Per_Degree,50.0f*Stuff::Radians_Per_Degree,40.0f*Stuff::Radians_Per_Degree); motion_acceleration = YawPitchRoll(1.0f*Stuff::Radians_Per_Degree,1.0f*Stuff::Radians_Per_Degree,1.0f*Stuff::Radians_Per_Degree); return_speed = YawPitchRoll(50.0f*Stuff::Radians_Per_Degree,70.0f*Stuff::Radians_Per_Degree,50.0f*Stuff::Radians_Per_Degree); outward_force = YawPitchRoll(40.0f*Stuff::Radians_Per_Degree,50.0f*Stuff::Radians_Per_Degree,40.0f*Stuff::Radians_Per_Degree); home_position = initialPositions[leftGunAboveJointIndex].angularPosition; leftGunRecoil.Initialize(motion_limit, motion_acceleration, return_speed, home_position, outward_force); motion_limit = YawPitchRoll(40.0f*Stuff::Radians_Per_Degree,50.0f*Stuff::Radians_Per_Degree,40.0f*Stuff::Radians_Per_Degree); motion_acceleration = YawPitchRoll(1.0f*Stuff::Radians_Per_Degree,1.0f*Stuff::Radians_Per_Degree,1.0f*Stuff::Radians_Per_Degree); return_speed = YawPitchRoll(50.0f*Stuff::Radians_Per_Degree,70.0f*Stuff::Radians_Per_Degree,50.0f*Stuff::Radians_Per_Degree); outward_force = YawPitchRoll(40.0f*Stuff::Radians_Per_Degree,50.0f*Stuff::Radians_Per_Degree,40.0f*Stuff::Radians_Per_Degree); home_position = initialPositions[leftArmAboveJointIndex].angularPosition; leftArmRecoil.Initialize(motion_limit, motion_acceleration, return_speed, home_position, outward_force); p_motion_limit = Point3D(10.0f,10.0f,1.0f); p_motion_acceleration = Point3D(0.0f,0.0f,0.05f); p_return_speed = Point3D(0.0f,0.0f,2.0f); p_outward_force = Point3D(10.0f,10.0f,1.0f); rightGunRecoil.Initialize(p_motion_limit, p_motion_acceleration, p_return_speed, initialPositions[rightGunAboveJointIndex].linearPosition, p_outward_force); #endif worldRotDampener.SetNewDampen(model->dampenWorldJoint); rootRotDampener.SetNewDampen(model->dampenRootJoint); rootTransDampener.SetNewDampen(model->dampenTranslationJoint); torsoRotDampener.SetNewDampen(model->dampenTorsoJoint); hipRotDampener.SetNewDampen(model->dampenHipJoint); eyeSpringRotation.Initialize(model->eyeSpringMotionLimit, model->eyeSpringConstant, model->eyeSpringDrag, model->eyeSpringStopThreshold); if (GetReplicatorMode() == ReplicantMode) { debugPushupOff = true; } else { debugPushupOff = true; } fastTransition = true; InitializeDamageArray(); m_defaultFootStep = NULL; m_whoShotMeLast = Adept::ReplicatorID::Null; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::CreateFootTextureChain(ResourceID resource_id) { Check_Object(this); Resource stream(resource_id); Verify(stream.DoesResourceExist()); while(stream.GetBytesRemaining() > 0) { int material; stream >> material; MString texture_name; stream >> texture_name; bool is_default; stream >> is_default; MidLevelRenderer::MLRTexture *foot_texture; foot_texture = MidLevelRenderer::MLRTexturePool::Instance->Add(texture_name); FootStepPlug *foot_plug = new FootStepPlug(material, foot_texture, is_default); if(is_default) { m_defaultFootStep = foot_plug; } else { m_footSteps.AddValue(foot_plug, material); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // extern int temporaryQuickIDLookup[COMPRESS_JOINT_COUNT]; void Mech::LoadAnimationScripts() { for (int i = 0; i < COMPRESS_JOINT_COUNT; ++i) { temporaryQuickIDLookup[i] = -1; } Stuff::ChainIteratorOf iterator(&armatureChain); MWMover *mover; i = 0; while ((mover = iterator.ReadAndNext()) != NULL) { MString temp; int index = MW4Animation::CompressName(mover->instanceName, temp); if (index != -1) { Verify(index < COMPRESS_JOINT_COUNT); Verify(index >= 0); temporaryQuickIDLookup[index] = i; } ++i; } const GameModel *model = GetGameModel(); Check_Object(model); if (model->animScriptName[0] != NULL && !animStateEngine->alreadyLoaded) { animStateEngine->LoadScript(model->animScriptName, DontLoadBlends); NoBlend = DontLoadBlends; } animStateEngine->Reset(); animStateEngine->RequestState(MechAnimationStateEngine::StandState, Mech::NoBlend); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Respawn(Entity::CreateMessage *message) { Check_Object(this); Check_Object(message); // MSL 5.02 headshot //fix head-shot damage, if present if ((dwDamageFlags & MECH_HEAD_SHOT_RCVD) == MECH_HEAD_SHOT_RCVD) { if (vehicleInterface) { vehicleInterface->hudZoomDestroyed = false; //reinstate the zoom } dwDamageFlags = 0; //unset all the damage flags } // MSL 5.03 Gyro Hit //fix gyro hit damage, if present if ((dwGyroDamageFlags & MECH_GYRO_HIT_RCVD) == MECH_GYRO_HIT_RCVD) { dwGyroDamageFlags = 0; //unset all the damage flags } //SPEW(("jerryeds", "RESPAWN")); BaseClass::Respawn(message); CreateMessage *mech_message = Cast_Pointer(CreateMessage *, message); CommonCreation(mech_message); m_heatManager->Reuse(); m_eyePointManager->Reuse(); // // [johnyo] 08/27/00 PreviousSearchLight code is experimental code that I have checked in to keep a backup // of only. It may be ripped out shortly if the effect that it was intended to have isn't // put into the game // // if (m_previousSearchLightState && GetSearchLight()) // { // if (IsPlayerVehicle()) // { // Mission::GetInstance()->SetSearchLightMissionLights(); // } // GetSearchLight()->ShowBeam(); // } SetTonnage(m_startTons); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Mech::~Mech() { DESTRUCTOR("Mech"); Check_Pointer(this); if (deadReckonCurve != NULL) { delete deadReckonCurve; deadReckonCurve = NULL; } delete m_eyePointManager; delete m_gyro; Unregister_Pointer(initialPositions); delete[] initialPositions; if (m_defaultFootStep) { Check_Object(m_defaultFootStep); delete m_defaultFootStep; } m_footSteps.DeletePlugs(); if(m_leftCageEffect.GetCurrent()) delete m_leftCageEffect.GetCurrent(); if(m_rightCageEffect.GetCurrent()) delete m_rightCageEffect.GetCurrent(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::PilotSkillCheck (Stuff::Scalar damage_amount,bool jump) { if (m_AI) return m_AI->PilotSkillCheck (damage_amount,jump); return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::GetTransSpeedKPH (Stuff::Scalar& forward,Stuff::Scalar& reverse) { const GameModel *model = GetGameModel(); Check_Object(model); forward = model->minSpeed* 3.6f; reverse = model->minReverseSpeed* 3.6f; } void Mech::GetMaxSpeedKPH (Stuff::Scalar& forward,Stuff::Scalar& reverse) { const GameModel *model = GetGameModel(); Check_Object(model); forward = GetMaxSpeed () * 3.6f; reverse = model->maxReverseSpeed * 3.6f; } void Mech::GetTransSpeedNormalized (Stuff::Scalar& forward,Stuff::Scalar& reverse) { const GameModel *model = GetGameModel(); Check_Object(model); forward = model->minSpeed / GetMaxSpeed(); reverse = model->minReverseSpeed / -model->maxReverseSpeed; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::TurnOn (void) { lastParameterization = gos_GetElapsedTime (); animStateEngine->Reset(); animStateEngine->RequestState(MechAnimationStateEngine::StandState, Mech::NoBlend); executionState->RequestState(m_LastState); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::TurnOff (void) { m_LastState = executionState->GetState (); if (!IsPlayerVehicle() && !IsLanceMate()) { executionState->RequestState(ExecutionStateEngine::AIMotionState); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Reuse( const CreateMessage *message, ReplicatorID *base_id ) { Check_Object(this); Check_Object(message); STOP(("Not Implemented")); // m_previousSearchLightState = false; BaseClass::Reuse(message, base_id); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::UpdateMessageHandler(const UpdateMessage *message) { Check_Object(this); Check_Object(message); Verify(GetReplicatorMode() == ReplicantMode); BaseClass::UpdateMessageHandler(message); currentSpeedMPS = message->currentSpeedMPS; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Entity::UpdateMessage* Mech::ConstructUpdate(Stuff::MemoryStream *stream) { Check_Object(this); Check_Object(stream); Verify(updateFlags); Verify(GetReplicatorMode() == MasterMode); Verify(owningConnection == Connection::Local); // //------------------------------------------------------------ // Make sure there is enough room for the update on the stream //------------------------------------------------------------ // stream->AllocateBytes(sizeof(UpdateMessage)); UpdateMessage *message = Cast_Pointer( UpdateMessage*, BaseClass::ConstructUpdate(stream) ); Check_Object(message); message->messageLength = sizeof(*message); message->currentSpeedMPS = currentSpeedMPS; return message; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::HookUpSubsystems() { Stuff::ChainIteratorOf iterator(&subsystemsInVehicle); Subsystem *subsystem; while ((subsystem = iterator.ReadAndNext()) != NULL) { if (subsystem->IsDerivedFrom(Engine::DefaultData)) { engine = Cast_Object(Engine *, subsystem); } else if (subsystem->IsDerivedFrom(Torso::DefaultData)) { Torso* torso = Cast_Object(Torso*, subsystem); if (std::find(m_Torsos.begin(),m_Torsos.end(),torso) == m_Torsos.end()) { m_Torsos.push_back(torso); } } else if (subsystem->IsDerivedFrom(ECM::DefaultData)) { ecm = Cast_Object(ECM *, subsystem); } else if (subsystem->IsDerivedFrom(JumpJet::DefaultData)) { jumpJet = Cast_Object(JumpJet *, subsystem); } // MSL 5.02 SubSystems else if (subsystem->IsDerivedFrom(IFF_Jammer::DefaultData)) { iff_jammer = Cast_Object(IFF_Jammer *, subsystem); } else if (subsystem->IsDerivedFrom(Armor::DefaultData)) { armor = Cast_Object(Armor *, subsystem); } AddSubsystem(subsystem); //Tell the Damage Zone that holds the subsystem that it is there!!! } if(engine) engine->ConnectEngine(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::AddSubsystem(Subsystem *subsystem) { Check_Object(this); BaseClass::AddSubsystem(subsystem); if (subsystem->IsDerivedFrom(JumpJet::DefaultData)) { jumpJet = Cast_Object(JumpJet *, subsystem); } else if(subsystem->IsDerivedFrom(HeatSink::DefaultData)) { m_numHeatSinks++; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::RemoveSubsystem(Subsystem *subsystem) { Check_Object(this); BaseClass::RemoveSubsystem(subsystem); if (subsystem->IsDerivedFrom(JumpJet::DefaultData)) { jumpJet = NULL; } else if(subsystem->IsDerivedFrom(HeatSink::DefaultData)) { m_numHeatSinks--; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Mech::GetExecutionSlot() { Check_Object(this); return m_mechSlot; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::StartDropping (void) { if (executionState->GetState() != ExecutionStateEngine::DroppingState) m_NeedStartDrop = true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::RealStartDropping (void) { m_NeedStartDrop = false; const GameModel *model = GetGameModel(); m_DropSite = FindSite ("site_jcattach"); m_JumpSite1 = FindSite ("site_jcjetport01"); m_JumpSite2 = FindSite ("site_jcjetport02"); m_JumpSite3 = FindSite ("site_jcjetport03"); m_JumpSite4 = FindSite ("site_jcjetport04"); if ((model->cradle != ResourceID::Null) && (!GetJumpJet ()) && (m_DropSite)) { Entity::ClassID class_ID; class_ID = Entity::GetClassIDFromDataListID(model->cradle); Verify(class_ID != NullClassID); NameTable *table = NameTable::GetInstance(); Check_Object (table); int aiid; aiid = table->AddEntry ("",NameTable::BuildingArray); Building::CreateMessage Building_Create_Message(sizeof(Building::CreateMessage), DefaultEventPriority, Building::CreateMessage::DefaultFlags, class_ID, Building::CreateMessage::DefaultFlags, model->cradle, GetLocalToWorld(), 0.0f, Entity__ExecutionStateEngine::AlwaysExecuteState, aiid, GetAlignment(), Motion3D::Identity, Motion3D::Identity, "", ResourceID::Null, ResourceID::Null, ResourceID::Null, ResourceID::Null, DefaultSkinPrefix, 0, 0, 0, false ); MemoryStream stream(&Building_Create_Message, Building_Create_Message.messageLength); ReplicatorID cradle_id = Connection::Local->GetNextReplicatorID(); Entity *cradle = Entity::CreateEntity(&stream, &cradle_id, false); m_DropCradle.Add (cradle); MWMap::GetInstance ()->AddChild (cradle); } executionState->RequestState(Vehicle__ExecutionStateEngine::DroppingState); m_LastState = Vehicle__ExecutionStateEngine::DroppingState; // Find the ground // // make a line... // Point3D curlocation (GetLocalToWorld ()); Point3D new_translation (-1,-1,-1); Stuff::Line3D line; line.m_length = 1020.0f; line.m_direction = Vector3D::Down; line.m_origin = curlocation; // // Prepare query // Stuff::Normal3D normal; Entity::CollisionQuery query(&line, &normal, Entity::CanBeWalkedOnFlag, this); // // Cast ray // Adept::Entity *entity_hit; Check_Object(CollisionGrid::Instance); entity_hit = CollisionGrid::Instance->ProjectLine(&query); if (entity_hit != NULL) { // if we hit ground, great! line.FindEnd(&new_translation); } #ifdef LAB_ONLY else { PAUSE (("tried to start a mech drop when not above the ground")); } #endif m_DroppingFinalY = new_translation.y; m_DroppingStartY = curlocation.y; if (m_AI) m_AI->AlwayActive (true); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::DroppingMovementSimulation(Stuff::Time till) { Check_Object(this); // //---------------------------------------------------------- // Put gravity into local space and compute our new position //---------------------------------------------------------- // currentSpeedMPS = localSpaceVelocity.linearMotion.z; Scalar time_slice = GetTimeSlice(till); Check_Object(this); // //--------------------------------------------------------------------- // 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); Max_Clamp(world_delta.y, -5.0f*time_slice); Min_Clamp(world_delta.y, -40.0f); if (localSpaceVelocity.linearMotion.y < -40.0f) { m_CanStartDropJetEffect = true; } world_translation.AddScaled(world_translation, world_delta, time_slice); localSpaceVelocity.linearMotion.y += localSpaceAcceleration.linearMotion.y*time_slice; localSpaceVelocity.linearMotion.x = 0; localSpaceVelocity.linearMotion.z = 0; // Max_Clamp(localSpaceVelocity.linearMotion.y, -5.0f); // Min_Clamp(localSpaceVelocity.linearMotion.y, -40.0f); // //-------------------------------------- // 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; new_rotation.yaw = 0; new_rotation.pitch = 0; new_rotation.roll = 0; // //---------------------------------------------- // 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; if (GetNetworkAdjustment(time_slice, correction_position, correction_angle)) { new_rotation = correction_angle; world_translation = correction_position; } // //---------------------------------------------- // Cast a ray down to see what we are driving on //---------------------------------------------- // Stuff::Line3D line; line.m_length = 10.001f; line.m_direction = Vector3D::Down; line.m_origin = world_translation; line.m_origin.y += 10.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 ); Max_Clamp(worldSpaceVelocity.linearMotion.y, 0.0f); new_local_to_world.BuildTranslation(world_translation); } // //-------------------------------------------------- // Otherwise, adapt the vehicle to the ground normal //-------------------------------------------------- // else { materialHit = query.m_material; line.FindEnd(&world_translation); new_local_to_world.BuildTranslation(world_translation); // //-------------------------------------------------- // 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 ); { new_local_to_world(3,1) = line.m_origin.y - line.m_length; SetNewLocalToParent(new_local_to_world); localSpaceVelocity.linearMotion.y = 0.0f; worldSpaceVelocity.linearMotion.y = 0.0f; executionState->RequestState(ExecutionStateEngine::DrivingMotionState); } } SetNewLocalToParent(new_local_to_world); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::PreCollisionExecute(Time till) { Check_Object(this); PRECOLLISION_LOGIC("Mech"); // //---------------------------------------------------------------------- // If the we have an interface, let it adjust the time slice for network //---------------------------------------------------------------------- // Set_Statistic(Executed_Mech_Count, Executed_Mech_Count+1); Scalar time_slice = GetTimeSlice(till); if (m_FallDamage) { m_FallDamage -= (MW4AI::UserConstants::Instance ()->Get(MW4AI::UserConstants::fall_damage_minus) * time_slice); Min_Clamp (m_FallDamage,0); // MSL 5.02 headshot m_HeadShotFallDamageMod = 1.0; m_HeadShotTorsoRockDamageMod = 1.0; m_HeadShotTorsoSpinDamageMod = 1.0; // MSL 5.02 SubSystems if (GetAdvancedGyro()) { // MSL 5.03 Gyro Hit m_AdvancedGyroFallDamageMod = 1.0; // m_AdvancedGyroFallDamageMod = ADVANCED_GYRO_FALL_MOD; } else { m_AdvancedGyroFallDamageMod = 1.0; } } if (vehicleInterface) { Verify(!vehicleRunsInterface); Check_Object(vehicleInterface); vehicleInterface->PreCollisionExecute(till); Verify(!vehicleInterface->IsUsingPostCollision() || EntityManager::GetInstance()->IsInPostCollisionExecution(vehicleInterface)); } Verify(time_slice > 0.0f); blockFallTimer += time_slice; // //--------------------------------- // Let vehicle set up the variables //--------------------------------- // BaseClass::PreCollisionExecute(till); // //--------------------------------------- // Figure out what motion state we are in //--------------------------------------- // Check_Object(executionState); int pre_state = executionState->GetState(); Verify(pre_state != ExecutionStateEngine::NeverExecuteState); switch (pre_state) { // //------------------------------------------------------------------------ // If we are in the walking state, first evaluate the ground to figure out // our mech's speed and orientation //------------------------------------------------------------------------ // case ExecutionStateEngine::DroppingState: { PRECOLLISION_LOGIC("Mech::DroppingState"); // //----------------------------- // Put gravity into local space //----------------------------- // UnitVector3D world_down_in_local; GetLocalToWorld().GetWorldDownInLocal(&world_down_in_local); Point3D loc(GetLocalToWorld ()); if (loc.y < (((m_DroppingStartY - m_DroppingFinalY)/2.0f)+m_DroppingFinalY)) { localSpaceAcceleration.linearMotion.AddScaled( localSpaceAcceleration.linearMotion, world_down_in_local, -g_Gravity ); } else { localSpaceAcceleration.linearMotion.AddScaled( localSpaceAcceleration.linearMotion, world_down_in_local, g_Gravity ); } animationVelocity = Stuff::Point3D::Identity; instantaniousAngularVelocity = Stuff::Vector3D::Identity; animStateEngine->RunStates(time_slice, Mech::NoBlend); DroppingMovementSimulation(till); FootLockSimulation(time_slice); DampenMech(time_slice); RunSprings(time_slice); if (executionState->GetState() != ExecutionStateEngine::DroppingState) { // if (GetJumpJet ()) // { // GetJumpJet ()->StopJumpJetEffectOnly (); // } // else { if (m_DropCradle.GetCurrent ()) { m_NeedKillDropCradleEffect = true; m_DropCradle.GetCurrent ()->SentenceToDeathRow (); } if (m_JumpEffect1.GetCurrent ()) { m_JumpEffect1.GetCurrent()->executionState->RequestState(Effect::ExecutionStateEngine::StoppingState); m_JumpEffect1.Remove(); } if (m_JumpEffect2.GetCurrent ()) { m_JumpEffect2.GetCurrent()->executionState->RequestState(Effect::ExecutionStateEngine::StoppingState); m_JumpEffect2.Remove(); } if (m_JumpEffect3.GetCurrent ()) { m_JumpEffect3.GetCurrent()->executionState->RequestState(Effect::ExecutionStateEngine::StoppingState); m_JumpEffect3.Remove(); } if (m_JumpEffect4.GetCurrent ()) { m_JumpEffect4.GetCurrent()->executionState->RequestState(Effect::ExecutionStateEngine::StoppingState); m_JumpEffect4.Remove(); } } } } break; case ExecutionStateEngine::DrivingMotionState: { PRECOLLISION_LOGIC("Mech::DrivingState"); // //----------------------------- // Put gravity into local space //----------------------------- // FindGroundAngles(); ComputeForwardSpeed(time_slice); TiltMech(time_slice); // //------------------------------ // Run the animation on the mech //------------------------------ // MaintainWalkingAnimStates(Mech::NoBlend); Check_Object(m_gyro); m_gyro->Execute(); instantaniousAngularVelocity = Stuff::Vector3D::Identity; animationVelocity = Stuff::Point3D::Identity; // if we are landing we need to have a specific speed if (animStateEngine->GetState() == MechAnimationStateEngine::FlyState && animStateEngine->GetTransitionState() == MechAnimationStateEngine::ForwardState) { currentSpeedMPS = GetMaxSpeed() * 0.5f; } animStateEngine->RunStates(time_slice, Mech::NoBlend); if (animStateEngine->IsTransitioning() && animStateEngine->GetTransitionState() == MechAnimationStateEngine::FlyState) { animationVelocity.z = currentSpeedMPS; } else if (animStateEngine->GetState() == MechAnimationStateEngine::FlyState) { animationVelocity.z = currentSpeedMPS; } if (!allowedToAnimateVelocity) { animationVelocity.x = 0.0f; animationVelocity.z = 0.0f; } MovementSimulation(time_slice, animationVelocity, instantaniousAngularVelocity); FootLockSimulation(time_slice); DampenMech(time_slice); RunSprings(time_slice); } break; // //------------------------------------ // Handle being in the ballistic state //------------------------------------ // case ExecutionStateEngine::FlyingMotionState: { PRECOLLISION_LOGIC("Mech::FlyingState"); // //----------------------------- // Put gravity into local space //----------------------------- // m_gyro->Execute(); FindGroundAngles(); animationVelocity = Stuff::Point3D::Identity; instantaniousAngularVelocity = Stuff::Vector3D::Identity; animStateEngine->RunStates(time_slice, Mech::NoBlend); BallisticMovementSimulation(till); FootLockSimulation(time_slice); DampenMech(time_slice); RunSprings(time_slice); if (m_FallDampingEnabled == true) { FallDampingSimulation(); } } break; // //---------------------------------- // Handle being in the fallinging state //---------------------------------- // case ExecutionStateEngine::FallingMotionState: { PRECOLLISION_LOGIC("Mech::FallingState"); blockFallTimer = 0.0f; // //----------------------------- // Put gravity into local space //----------------------------- // UnitVector3D world_down_in_local; GetLocalToWorld().GetWorldDownInLocal(&world_down_in_local); localSpaceAcceleration.linearMotion.AddScaled( localSpaceAcceleration.linearMotion, world_down_in_local, g_Gravity ); instantaniousAngularVelocity = Stuff::Vector3D::Identity; if (!animStateEngine->IsTransitioning()) { switch (animStateEngine->GetState()) { case MechAnimationStateEngine::FallForwardState: case MechAnimationStateEngine::FallBackwardState: case MechAnimationStateEngine::FallLeftState: case MechAnimationStateEngine::FallRightState: { m_CanStartGettingUp = true; } break; default: if (!IsDestroyed()) { executionState->RequestState(ExecutionStateEngine::DrivingMotionState); tiltAngle = 0.0f; tiltRequest = 0.0f; currentSpeedMPS = 0.0f; } break; } } FindGroundAngles(); //TiltMech(time_slice); ComputeFrictionSpeed (time_slice); if ((m_SlideTimer < gos_GetElapsedTime ()) || (Small_Enough (localSpaceVelocity.linearMotion.z) && m_CanStartGettingUp)) { localSpaceVelocity.linearMotion = Vector3D::Identity; worldSpaceVelocity.linearMotion = Vector3D::Identity; if (!IsDestroyed()) { queFallState = NoFallMode; animStateEngine->RequestState(MechAnimationStateEngine::StandState, Mech::NoBlend); } else { if (triggerDeath == NoDeathTrigger) { triggerDeath = FallDownDeathTrigger; } } } animStateEngine->RunStates(time_slice, Mech::NoBlend); Stuff::Vector3D temp = animationVelocity; animationVelocity = localSpaceVelocity.linearMotion; Min_Clamp (animationVelocity.x,temp.x); Min_Clamp (animationVelocity.y,temp.y); Min_Clamp (animationVelocity.z,temp.z); FallingMovementSimulation(time_slice, animationVelocity, instantaniousAngularVelocity); FootLockSimulation(time_slice); DampenMech(time_slice); RunSprings(time_slice); worldSpaceVelocity.linearMotion.Multiply( localSpaceVelocity.linearMotion, GetLocalToWorld () ); } break; } groundAngleDbg.yaw = 0.0f; groundAngleDbg.roll = localGroundRoll; groundAngleDbg.pitch = localGroundPitch; // //-------------------------------------------------------------------------- // If this is the player vehicle, check to see if we are in the mission area //-------------------------------------------------------------------------- // if (IsPlayerVehicle()) { PRECOLLISION_LOGIC("Mech::MapBounds"); Check_Object(Mission::GetInstance()); ElementRenderer::Element *element = GetElement(); Check_Object(element); Point3D where(element->GetNewLocalToParent()); Mission::MissionArea area = Mission::GetInstance()->GetMissionArea(where); // //------------------------------------------------------------------------ // If we aren't in the mission area, set up a fake collision if we haven't // already collided //------------------------------------------------------------------------ // switch (area) { case Mission::InMissionArea: { break; } case Mission::OutOfMissionArea: { if ((vehicleInterface) && (vehicleInterface->executionState) && (vehicleInterface->executionState->GetState() == VehicleInterface::ExecutionStateEngine::AIRunningState)) { break; } // //---------------------------------------------------------------- // Now move the player back to where he was, except for the height //---------------------------------------------------------------- // Check_Object(entityElement); LinearMatrix4D new_local_to_parent = element->GetNewLocalToParent(); Point3D new_translation; new_translation = new_local_to_parent; Point3D old_translation; MWMission* mission = Cast_Object(MWMission*,Mission::GetInstance()); if (mission->m_ConstraintTopLeft != Point3D::Identity) { old_translation = new_translation; Stuff::Scalar min_x = mission->m_ConstraintTopLeft.x; Stuff::Scalar max_x = mission->m_ConstraintBottomRight.x; if (min_x > max_x) { Scalar temp = min_x; min_x = max_x; max_x = temp; } Clamp(old_translation.x,min_x,max_x); Stuff::Scalar min_z = mission->m_ConstraintTopLeft.z; Stuff::Scalar max_z = mission->m_ConstraintBottomRight.z; if (min_z > max_z) { Scalar temp = min_z; min_z = max_z; max_z = temp; } Clamp(old_translation.z,min_z,max_z); Point3D delta; delta.Subtract(old_translation,new_translation); if (delta.GetLengthSquared() > 5.0f * 5.0f) { break; } } else { old_translation = (element->GetLocalToParent()); } old_translation.y = new_translation.y; new_local_to_parent.BuildTranslation(old_translation); SetNewLocalToParent(new_local_to_parent); SyncMatrices(true); if (m_LastMissionWarning + mission_area_warning_frequency < (Stuff::Scalar)gos_GetElapsedTime()) { if ((vehicleInterface) && (vehicleInterface->GetBoundsWarningsEnabled() == true)) { if ((g_nMR != 2) && MW4Shell::Instance->m_optionsObject->m_bettyOn) { AudioCommand *command = AudioCommand::Create( AudioRenderer::BettyType, "cmp_exit_mission_area.wav{handle}", 1.0f, 1.0f ); Check_Object(command); command->Play(); } } m_LastMissionWarning = (Stuff::Scalar)gos_GetElapsedTime(); } break; } case Mission::InWarningArea: { if (m_LastMissionWarning + mission_area_warning_frequency < (Stuff::Scalar)gos_GetElapsedTime()) { if ((vehicleInterface) && (vehicleInterface->GetBoundsWarningsEnabled() == true)) { if ((g_nMR != 2) && MW4Shell::Instance->m_optionsObject->m_bettyOn) { AudioCommand *command = AudioCommand::Create( AudioRenderer::BettyType, "cmp_approach_boundary.wav{handle}", 1.0f, 1.0f ); Check_Object(command); command->Play(); } } m_LastMissionWarning = (Stuff::Scalar)gos_GetElapsedTime(); } break; } } } //WE are not a player Mech else { //Make sure to keep them atleast 15 meters from the edge of the map since then can //pass the warning and mission bounds Scalar min_x, min_z, max_x, max_z; Check_Object(Map::GetInstance()); Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x); ElementRenderer::Element *element = GetElement(); Check_Object(element); Point3D where(element->GetNewLocalToParent()); Clamp(where.x, min_x + 15.0f, max_x - 15.0f); Clamp(where.z, min_z + 15.0f, max_z - 15.0f); LinearMatrix4D clamped_position = element->GetNewLocalToParent(); clamped_position.BuildTranslation(where); SetNewLocalToParent(clamped_position); SyncMatrices(true); } { PRECOLLISION_LOGIC("Mech::LastBits"); Check_Object(m_heatManager); //This should be set to the material heat, but for not it stays 1 m_sensorDinstanceMultiplier = 1.0f; //WE then can add to it the effect stuff too MWMission *mw_mission = Cast_Object(MWMission *, MWMission::GetInstance()); mw_mission->ProcessReactionSpheres(this); GetSensor()->m_maxRange *= m_sensorDinstanceMultiplier; m_heatManager->ApplyMovementHeat(currentSpeedMPS, GetMaxSpeed()); m_heatManager->Execute(); if ((armReNullTime != 0) && ((Stuff::Scalar)gos_GetElapsedTime() > armReNullTime)) { if (armsNulled == true) { armsNulled = false; armBlanderizer.FadeToNewDampen(0.0f, 1.0f); } armReNullTime = 0; } if(GetTorso()) GetTorso()->SetHeatMultiplier(m_heatManager->GetTorsoTwistMultiplier()); if((vehicleShutDown) && (!m_alreadyShutDown)) { //Check to see if we are shut down if(!animStateEngine->IsTransitioning() && animStateEngine->GetState() == MechAnimationStateEngine::PowerDownState) { ReactToShutDown(); } //Else check to see if we are gimped in which case we can't shutdown in the anim system else if(gimpState != NotGimpedMode) { ReactToShutDown(); } } allowedToAnimateVelocity = true; } // SPECIAL CASE WORK AROUND FOR NETWORK BUG :JSE // Sometimes, for god knows what reason mechs spawn REALLY low under ground. // this detects and correct the problem. if (IsPlayerVehicle() && MWApplication::GetInstance()->networkingFlag) { Point3D position; position = GetElement()->GetNewLocalToParent(); if (position.y < -2000.0f) { //damn mech is below ground... const LinearMatrix4D& local_to_world = GetElement()->GetNewLocalToParent(); Stuff::Line3D line; line.m_length = 2000.0f; line.m_direction = Vector3D::Down; line.m_origin = local_to_world; line.m_origin.y = 1000.0f; Stuff::Normal3D normal; CollisionQuery query(&line, &normal, CanBeWalkedOnFlag, this); Check_Object(CollisionGrid::Instance); CollisionGrid::Instance->ProjectLine(&query); Point3D tr; line.FindEnd(&tr); LinearMatrix4D new_local_to_world = local_to_world; new_local_to_world.BuildTranslation(tr); SetNewLocalToParent(new_local_to_world); } } #if 0 if (Connection::Local->GetID() == GetReplicatorID().connectionID && !MWApplication::GetInstance()->serverFlag) { Point3D position; position = GetElement()->GetNewLocalToParent(); //SPEW(("jerryeds","PRE-MOVEMENT : %f %f %f", position.x, position.y, position.z)); } #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::FallDampingSimulation() { PRECOLLISION_LOGIC("Mech::FallDampingSim"); localSpaceVelocity.linearMotion.MultiplyByInverse(worldSpaceVelocity.linearMotion,GetLocalToWorld()); Stuff::Scalar length(Fabs(localSpaceVelocity.linearMotion.z)); Stuff::Point3D world_velocity; world_velocity.Subtract(m_FallDampingLocus,(Point3D)GetLocalToWorld()); Stuff::Vector3D local_velocity(localSpaceVelocity.linearMotion); local_velocity.MultiplyByInverse(world_velocity,GetLocalToWorld()); localSpaceVelocity.linearMotion.z = local_velocity.z; Clamp(localSpaceVelocity.linearMotion.z,-length,length); worldSpaceVelocity.linearMotion.Multiply(localSpaceVelocity.linearMotion,GetLocalToWorld()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::CollisionHandler( Stuff::LinearMatrix4D *new_position, Stuff::DynamicArrayOf *collisions ) { Check_Object(this); Check_Object(collisions); Verify(GetInterestLevel() != DormantInterestLevel); Verify(EntityManager::GetInstance()->IsInPostCollisionExecution(this)); bool shoulddamage=true; // //---------------------------------------------------------- // If we are destroyed, delete the collision list and return //---------------------------------------------------------- // if (IsDestroyed()) { Verify(!newCollisions); delete collisions; SetNewLocalToParent(GetLocalToParent()); // reset this since collision handler won't now return false; } // //-------------------------------- // Ask the AI about the collision //-------------------------------- // if (m_AI) { if (!m_AI->ReactToCollision(collisions,shoulddamage)) // ai will return false if collision should not occur { Verify(!newCollisions); delete collisions; return false; } } // //---------------------------------------- // Turn off collision if we are going fast //---------------------------------------- // #ifdef LAB_ONLY if (m_DebugFast) { Verify(!newCollisions); delete collisions; return false; } #endif // //------------------------- // Figure out our mech data //------------------------- // int step_class; Scalar mech_speed; Scalar building_speed; Scalar damage_given; Scalar slowdown; if (GetTonage() >= MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_heavy_tonage)) { step_class = HeavyCanWalkThruType; mech_speed = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_heavy_mech_speed); building_speed = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_heavy_building_speed); damage_given = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_heavy_damage); slowdown = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_heavy_slowdown); } else if (GetTonage() >= MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_medium_tonage)) { step_class = MediumCanWalkThruType; mech_speed = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_medium_mech_speed); building_speed = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_medium_building_speed); damage_given = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_medium_damage); slowdown = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_medium_slowdown); } else { step_class = AnythingCanWalkThruType; mech_speed = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_light_mech_speed); building_speed = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_light_building_speed); damage_given = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_light_damage); slowdown = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_light_slowdown); } // //----------------------- // Iterate the collisions //----------------------- // Vector3D delta = Vector3D::Identity; bool just_bump = true; bool ignore_collision = true; for (int i=0; iGetLength(); ++i) { CollisionData *data = &(*collisions)[i]; Check_Pointer(data); // //--------------------------------------------------------------------- // Look to see if we have run into a collider, and if so, calculate the // relative velocity //--------------------------------------------------------------------- // Entity *other = data->m_otherEntity; if (other->IsACollider()) { MWObject *mover = Cast_Object(MWObject*, other); Vector3D rel_vel; rel_vel.Subtract(mover->worldSpaceVelocity.linearMotion, worldSpaceVelocity.linearMotion); Scalar speed = rel_vel.GetLengthSquared(); // //------------------------------------------------ // If its a mech, figure out the tonnage constants //------------------------------------------------ // if (other->GetClassID() == MechClassID) { if (other->IsDestroyed()) { continue; } ignore_collision = false; just_bump = false; Mech *mech = Cast_Object(Mech*, mover); Scalar damage_received; if (mech->GetTonage() >= MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_heavy_tonage)) damage_received = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_heavy_damage); else if (mech->GetTonage() >= MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_medium_tonage)) damage_received = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_medium_damage); else damage_received = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_mech_light_damage); // //-------------------------- // See if the hit will count //-------------------------- // Time too_old = gos_GetElapsedTime() - 5.0; SortedChainIteratorOf oldies(&m_lastHits); Mech *maybe_mech; while ((maybe_mech = oldies.GetCurrent()) != NULL) { if (oldies.GetValue() <= too_old) oldies.Remove(); else if (maybe_mech == mech) break; else oldies.Next(); } if (maybe_mech) shoulddamage = false; // //------------------------------------------------------------------------------------ // See if we are going fast enough to get damaged, add ourselves to the last hit chain // to avoid further unpleasantness //------------------------------------------------------------------------------------ // if (speed >= mech_speed) { if (shoulddamage) { m_lastHits.AddValue(mech, gos_GetElapsedTime()); // //------------------------ // Play the ramming effect //------------------------ // Point3D target_local_to_world; target_local_to_world = data->m_otherVolume->m_worldSpaceBounds.localToParent; Point3D local_to_world; local_to_world = data->m_volume->m_worldSpaceBounds.localToParent; Point3D effect_offset; effect_offset.Subtract(target_local_to_world, local_to_world); effect_offset *= 0.5f; Point3D effect_translation; effect_translation.Add(local_to_world, effect_offset); const GameModel *model = GetGameModel(); Check_Object(model); CreateEffect(model->m_mechRamEffect, effect_translation); } // //------------------------ // Evaluate the DFA states //------------------------ // speed = Sqrt(speed)*mover->GetTonage(); Scalar min_dfa_vel = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_dfa_speed); Entity::ExecutionStateEngine *engine = executionState; bool our_dfa = worldSpaceVelocity.linearMotion.y <= -min_dfa_vel && engine->GetState() == ExecutionStateEngine::FlyingMotionState; engine = mech->executionState; bool their_dfa = mech->worldSpaceVelocity.linearMotion.y <= -min_dfa_vel && engine->GetState() == ExecutionStateEngine::FlyingMotionState; // //--------------------------------------- // Use the appropriate collision modifier //--------------------------------------- // if (our_dfa ^ their_dfa) { if (our_dfa) speed *= MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_dfa_damage_taken); else speed *= MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_dfa_damage_given); // //------------------------------------------------------------- // Figure out the direction that the mech needs to fall down in //------------------------------------------------------------- // Check_Object(m_gyro); Vector3D local_vel; local_vel.MultiplyByInverse( rel_vel, GetElement()->GetNewLocalToParent() ); if (Fabs(local_vel.z) > Fabs(local_vel.x)) { if (local_vel.z > 0) m_gyro->FallDown(FallForwardMode, 0.0f); else m_gyro->FallDown(FallBackMode, 0.0f); } else { if (local_vel.x > 0) m_gyro->FallDown(FallRightMode, 0.0f); else m_gyro->FallDown(FallLeftMode, 0.0f); } } else { speed *= damage_received; our_dfa = their_dfa = false; } // //------------------------------------ // Figure out the direction of the hit //------------------------------------ // char damage_type; if (our_dfa) damage_type = RammingDamageFromBelowType; else if (their_dfa) damage_type = RammingDamageFromAboveType; else { Vector3D local_vel; local_vel.MultiplyByInverse( rel_vel, GetElement()->GetNewLocalToParent() ); if (Fabs(local_vel.z) > Fabs(local_vel.x)) { if (local_vel.z > 0) damage_type = RammingDamageFromBehindType; else damage_type = RammingDamageFromAheadType; } else { if (local_vel.x > 0) damage_type = RammingDamageFromLeftType; else damage_type = RammingDamageFromRightType; } } if (vehicleInterface) { switch (damage_type) { case RammingDamageFromBelowType: vehicleInterface->PlayHitForce (Point3D (1.0f,0.0f,1.0f),2.0f); break; case RammingDamageFromAboveType: vehicleInterface->PlayHitForce (Point3D (1.0f,0.0f,1.0f),2.0f); break; case RammingDamageFromBehindType: vehicleInterface->PlayHitForce (Point3D (0.0f,0.0f,-1.0f),2.0f); break; case RammingDamageFromAheadType: vehicleInterface->PlayHitForce (Point3D (0.0f,0.0f,1.0f),2.0f); break; case RammingDamageFromLeftType: vehicleInterface->PlayHitForce (Point3D (-1.0f,0.0f,0.0f),2.0f); break; case RammingDamageFromRightType: vehicleInterface->PlayHitForce (Point3D (1.0f,0.0f,0.0f),2.0f); break; } } // //---------------------------------- // Set the damage message to ourself //---------------------------------- // if (shoulddamage) { // MSL 5.02 Collision Smoke Point3D myloc; myloc = animationArray[torsoAboveJointIndex]->GetLocalToWorld(); // Stuff::Point3D myloc(GetLocalToWorld()); // myloc.y += 6.0f; // MSL 5.06 Advance Mode MWApplication *m_App; m_App = MWApplication::GetInstance (); m_ArmorMode = m_App->GetLocalNetParams()->m_armormodeOn; TakeDamageMessage damage_message( GetReplicatorID(), other->GetReplicatorID(), speed, m_ArmorMode, damage_type, data->m_normal, myloc, // data->m_worldIntersectionPoint, 0.0f, false, TakeDamageMessage::DefaultWeaponType ); Receive(&damage_message); } } } // //----------------------------------------------------- // We didn't hit a mech, so see if we need to slow down //----------------------------------------------------- // else if ((step_class > other->GetWalkThruType()) || ((GetAlignment () == Player) && (other->GetAlignment () == Player))) { ignore_collision = false; just_bump = false; } else continue; } // //-------------------------------------------------------------- // If we've run into a static object, see if we can just kill it //-------------------------------------------------------------- // else { ignore_collision = false; // MSL 5.03 Hit Glass Effect // // Currently the shield does not display a reasonable effect when a mech runs into it, so we'll special // case glass to play an effect. // if ((data->m_otherVolume->m_material & 0x1f) == GlassMaterial) { // //------------------------ // Play the ramming effect //------------------------ // Point3D local_to_world; local_to_world = data->m_volume->m_worldSpaceBounds.localToParent; // // In order to make this look at all right, I'll need to do two additional steps: // Identify the closest point on the target volumes closest plane as the place to create the effect // Send the normal along with the effect to have it played correctly. // // // Find the correct plane to use: // // Point3D effect_offset; const GameModel *model = GetGameModel(); Check_Object(model); OBB::SeparatingAxis axis; Vector3D adj; axis = data->m_volume->m_worldSpaceBounds.CalculateSeparationVector( &adj, data->m_otherVolume->m_worldSpaceBounds); // Need to compensate for the size of the collision volume. Vector3D adjDirection; Stuff::Scalar adjDirection_length = adj.GetLengthSquared(); if (!Small_Enough(adjDirection_length)) { // // Normalize // adjDirection_length = 1.0f / Sqrt(adjDirection_length); adjDirection.x = adj.x * adjDirection_length; adjDirection.y = adj.y * adjDirection_length; adjDirection.z = adj.z * adjDirection_length; adjDirection *= data->m_volume->m_worldSpaceBounds.axisExtents.z; effect_offset.Subtract(local_to_world, adjDirection); CreateEffect(model->m_mechGlassRamEffect, effect_offset, adj); } } // if we hit glass if (step_class <= other->GetWalkThruType()) { // if (shoulddamage) { TakeDamageMessage damage_message( other->GetReplicatorID(), GetReplicatorID(), 100000.0f, // MSL 5.05 Armor Mode 0, RammingDamageFromAboveType, data->m_otherNormal, data->m_worldIntersectionPoint, 0.0f, false, TakeDamageMessage::DefaultWeaponType ); other->Receive(&damage_message); continue; } } // //------------------------------------------------------------- // Otherwise, check to see if we are going fast enough to apply // damage //------------------------------------------------------------- // Scalar min_dfa_vel = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_dfa_speed); Entity::ExecutionStateEngine *engine = executionState; // //--------------------------------------- // Use the appropriate collision modifier //--------------------------------------- // char damage_type; Scalar speed = worldSpaceVelocity.linearMotion.GetLengthSquared(); Scalar damage; if (worldSpaceVelocity.linearMotion.y <= -min_dfa_vel && engine->GetState() == ExecutionStateEngine::FlyingMotionState) { damage_type = RammingDamageFromAboveType; damage = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::collision_dfa_damage_given); } else { damage_type = RammingDamageFromAheadType; damage = damage_given; } // //----------------------------------- // If we can crush the thing, kill it //----------------------------------- // // MSL 5.06 Building Collision Damage Applied // Collision damage modifed based on armor mode MWApplication *m_App; m_App = MWApplication::GetInstance (); m_ArmorMode = m_App->GetLocalNetParams()->m_armormodeOn; just_bump = false; if (speed >= building_speed) { if (shoulddamage) { if (m_ArmorMode) { TakeDamageMessage damage_message( other->GetReplicatorID(), GetReplicatorID(), 0.1f, m_ArmorMode, damage_type, data->m_otherNormal, data->m_worldIntersectionPoint, 0.0f, false, TakeDamageMessage::DefaultWeaponType ); other->Receive(&damage_message); } else { TakeDamageMessage damage_message( other->GetReplicatorID(), GetReplicatorID(), damage * Sqrt(speed) * GetTonage(), m_ArmorMode, damage_type, data->m_otherNormal, data->m_worldIntersectionPoint, 0.0f, false, TakeDamageMessage::DefaultWeaponType ); other->Receive(&damage_message); } } } } // //------------------------------------------------------- // Calculate how our mech needs to adapt to the collision //------------------------------------------------------- // OBB::SeparatingAxis axis; Vector3D adj; axis = data->m_volume->m_worldSpaceBounds.CalculateSeparationVector( &adj, data->m_otherVolume->m_worldSpaceBounds ); // //------------------------------------------------------------------------- // If we are being pushed up, and this object is in our old collision list, // we could very well be stuck on top of the thing //------------------------------------------------------------------------- // if (oldCollisions) { for (unsigned j=0; jGetLength(); ++j) { if ((*oldCollisions)[j].m_otherVolume == data->m_otherVolume) break; } if (jGetLength()) { UnitVector3D nudge(adj); if (nudge.y > 0.85f) { data->m_volume->m_worldSpaceBounds.CalculateSecondarySeparationVector( &adj, data->m_otherVolume->m_worldSpaceBounds, nudge ); } } } delta += adj; } if (ignore_collision) { delete collisions; return false; } // //------------------------------------------------------------------------ // If the mech is flying, make sure it isn't a bump before zeroing out the // mech's velocity against the normal it bounced on //------------------------------------------------------------------------ // Entity::ExecutionStateEngine *engine = executionState; if (engine->GetState() == ExecutionStateEngine::FlyingMotionState) { Scalar dot = delta*worldSpaceVelocity.linearMotion; if (!just_bump && dot < -SMALL) { UnitVector3D direction(delta); dot = direction*worldSpaceVelocity.linearMotion; worldSpaceVelocity.linearMotion.AddScaled( worldSpaceVelocity.linearMotion, direction, -1.05f*dot ); localSpaceVelocity.linearMotion.MultiplyByInverse( worldSpaceVelocity.linearMotion, GetLocalToWorld() ); currentSpeedMPS = currentSpeedKPH = localSpaceVelocity.linearMotion.z * 3.6f; } } // //-------------------------------------------- // If we are just bumping something, slow down //-------------------------------------------- // else { const GameModel *model = GetGameModel(); if (just_bump) { if (currentSpeedMPS-slowdown > model->minStandTransitionSpeed) { currentSpeedMPS -= slowdown; currentSpeedKPH = currentSpeedMPS * 3.6f; Verify(engine->GetState() != ExecutionStateEngine::NeverExecuteState); Verify(!newCollisions); delete collisions; return false; } if (currentSpeedMPS+slowdown < -model->minStandTransitionSpeed) { currentSpeedMPS += slowdown; currentSpeedKPH = currentSpeedMPS * 3.6f; Verify(engine->GetState() != ExecutionStateEngine::NeverExecuteState); Verify(!newCollisions); delete collisions; return false; } } // //------------------------------------------------------------------ // We have come to a stop, so let the animation system handle things //------------------------------------------------------------------ // allowedToAnimateVelocity = false; Max_Clamp(currentSpeedMPS, model->minStandTransitionSpeed); currentSpeedKPH = currentSpeedMPS * 3.6f; switch (animStateEngine->GetState()) { case MechAnimationStateEngine::ForwardState: case MechAnimationStateEngine::BackwardState: animStateEngine->RequestState(MechAnimationStateEngine::StandState, Mech::NoBlend); break; case MechAnimationStateEngine::GimpForwardLeftState: animStateEngine->RequestState(MechAnimationStateEngine::GimpStandLeftState, Mech::NoBlend); break; case MechAnimationStateEngine::GimpForwardRightState: animStateEngine->RequestState(MechAnimationStateEngine::GimpStandRightState, Mech::NoBlend); break; } } // //-------------------------------------------------------------------- // If the mech isn't executing, it can't move or retain its collisions //-------------------------------------------------------------------- // if (engine->GetState() == ExecutionStateEngine::NeverExecuteState) { Verify(!newCollisions); delete collisions; return false; } // //---------------------------------------------------------------------- // Adjust the physical position by evaluating the other OBB position and // moving away from it //---------------------------------------------------------------------- // *new_position = GetElement()->GetNewLocalToParent(); (*new_position)(3,0) += delta.x; (*new_position)(3,1) += delta.y; (*new_position)(3,2) += delta.z; engine = executionState; if (engine->GetState() == ExecutionStateEngine::NeverExecuteState) { Verify(!newCollisions); delete collisions; return false; } else newCollisions = collisions; return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Eject (void) { if (m_NeedEject == 0) m_NeedEject = 1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ProcessSelfDestruct() { Check_Object(this); m_whoShotMeLast = GetReplicatorID(); if(m_NeedEject == 0) { Eject(); m_selfDestructTimer = gos_GetElapsedTime() + 0.3; // 2.0f; } if(gos_GetElapsedTime() >= m_selfDestructTimer) BaseClass::ProcessSelfDestruct(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #if defined(LAB_ONLY) void Mech::SyncMatrices(bool update_matrix) { SYNC_LOGIC("Mech"); BaseClass::SyncMatrices(update_matrix); } #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::PostCollisionExecute(Time till) { Check_Object(this); POSTCOLLISION_LOGIC("Mech"); // MSL 5.03 Lava if (executionState->GetState() == ExecutionStateEngine::DrivingMotionState) { if (materialHit == OpenLavaMaterial) { NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); extern bool HeatOn(NetMissionParameters::MWNetMissionParameters& net_params); // found in HeatManager.cpp if (HeatOn(*params) == true) { if (gos_GetElapsedTime() - m_lastLavaTime > 0.3f) { // MSL 5.06 Armor Mode MWApplication *m_App; m_App = MWApplication::GetInstance (); m_ArmorMode = m_App->GetLocalNetParams()->m_armormodeOn; TakeDamageMessage damage_message( GetReplicatorID(), GetReplicatorID(), 1.0f, //damage m_ArmorMode, LavaDamageType, Normal3D::Up, Point3D::Identity, 0.0f, //heat false, TakeDamageMessage::DefaultWeaponType); Receive (&damage_message); // MSL 5.04 Lava Modified heat modifier from 1.0 to 0.5 m_heatManager->AddHeat (0.85f); m_lastLavaTime = gos_GetElapsedTime(); } } } else if (materialHit == CrackedLavaMaterial) { if (gos_GetElapsedTime() - m_lastLavaTime > 0.3f) { // MSL 5.04 Lava Modified heat modifier from 1.0 to 0.5 m_heatManager->AddHeat (0.85f); m_lastLavaTime = gos_GetElapsedTime(); } } } m_eyePointManager->PostCollisionExecute(GetTimeSlice(till)); if (m_NeedKillDropCradleEffect) { Verify (m_DropSite); m_NeedKillDropCradleEffect = false; const GameModel *model = GetGameModel(); Effect *cradle_dead_effect; cradle_dead_effect = CreateEffect(model->cradleDeathEffect,m_DropSite,false); Check_Object(cradle_dead_effect); cradle_dead_effect->BecomeInteresting (true); cradle_dead_effect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState); } if (executionState->GetState() == ExecutionStateEngine::DroppingState) { if (m_DropCradle.GetCurrent () && m_DropSite) { LinearMatrix4D new_position; Verify (m_DropSite); new_position = m_DropSite->GetLocalToWorld(); m_DropCradle.GetCurrent ()->SetNewLocalToParent(new_position); m_DropCradle.GetCurrent ()->SyncMatrices(true); } Point3D loc(GetLocalToWorld ()); if ((m_CanStartDropJetEffect) && (leftJumpJetSite) && (!m_JumpEffect1.GetCurrent ())) { const GameModel *model = GetGameModel(); Effect *jump_jet_effect; jump_jet_effect = CreateLoopingEffect(model->dropJumpEffect,leftJumpJetSite,true); Check_Object(jump_jet_effect); jump_jet_effect->BecomeInteresting (true); jump_jet_effect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState); m_JumpEffect1.Add(jump_jet_effect); jump_jet_effect = CreateLoopingEffect(model->dropJumpEffect,rightJumpJetSite,true); Check_Object(jump_jet_effect); jump_jet_effect->BecomeInteresting (true); jump_jet_effect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState); m_JumpEffect2.Add(jump_jet_effect); } else if ((m_CanStartDropJetEffect) && (!m_JumpEffect1.GetCurrent ())) { const GameModel *model = GetGameModel(); Effect *jump_jet_effect; jump_jet_effect = CreateLoopingEffect(model->dropJumpEffect,m_JumpSite1,true); Check_Object(jump_jet_effect); jump_jet_effect->BecomeInteresting (true); jump_jet_effect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState); m_JumpEffect1.Add(jump_jet_effect); jump_jet_effect = CreateLoopingEffect(model->dropJumpEffect,m_JumpSite2,true); Check_Object(jump_jet_effect); jump_jet_effect->BecomeInteresting (true); jump_jet_effect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState); m_JumpEffect2.Add(jump_jet_effect); jump_jet_effect = CreateLoopingEffect(model->dropJumpEffect,m_JumpSite3,true); Check_Object(jump_jet_effect); jump_jet_effect->BecomeInteresting (true); jump_jet_effect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState); m_JumpEffect3.Add(jump_jet_effect); jump_jet_effect = CreateLoopingEffect(model->dropJumpEffect,m_JumpSite4,true); Check_Object(jump_jet_effect); jump_jet_effect->BecomeInteresting (true); jump_jet_effect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState); m_JumpEffect4.Add(jump_jet_effect); } } if (m_NeedStartDrop) RealStartDropping (); if ((m_needSelfDestruct) )//&& (m_AI) && (m_AI->IsDerivedFrom (PlayerAI::DefaultData))) ProcessSelfDestruct(); //SPEW(("jerryeds", "TEST--MECH ---------------------------")); //Play Steps if(isLeftFootDown) { isLeftFootDown = false; CreateFootEffect(currentLeftFootFall, siteLeftFoot, leftFootNormal); if (vehicleInterface) { vehicleInterface->PlayForce (VehicleInterface::LeftFootForce); } } if(isRightFootDown) { isRightFootDown = false; CreateFootEffect(currentRightFootFall, siteRightFoot, rightFootNormal); if (vehicleInterface) { vehicleInterface->PlayForce (VehicleInterface::RightFootForce); } } const GameModel *model = GetGameModel(); Check_Object(model); //Play Cage Effects if needed if(m_playLeftCageEffect) { if(!m_leftCageEffect.GetCurrent()) { Effect *effect; effect = CreateCageDamageEffect(m_leftCageSite); if(effect) m_leftCageEffect.Add(effect); } m_playLeftCageEffect = false; } if(m_playRightCageEffect) { if(!m_rightCageEffect.GetCurrent()) { Effect *effect; effect = CreateCageDamageEffect(m_rightCageSite); if(effect) m_rightCageEffect.Add(effect); } m_playRightCageEffect = false; } //Are we cooling if(m_heatManager->IsCooling()) { if(!m_heatManager->coolantEffect.GetCurrent()) { Check_Object(centerTorso); Effect *effect; effect = CreateEffect(model->coolantEffectResource, centerTorso, true); if(effect) { if (m_heatManager->coolantEffect.GetCurrent ()) m_heatManager->coolantEffect.Remove (); m_heatManager->coolantEffect.Add(effect); } } } //Check if we are overheating // MSL 5.02 Heat // Changed from .75 to .66 if (m_heatManager->GetHeatPercentage() > 0.66) { if(!m_heatManager->overHeatEffect.GetCurrent()) { Check_Object(centerTorso); Effect *effect; effect = CreateEffect(model->overHeatEffectResource, centerTorso, true); if(effect) { m_heatManager->overHeatEffect.Add(effect); } } } // MSL 5.02 headshot //This adds an overheat-like effect when a player takes a head-shot... //It cycles over 20 hard-coded values modified by a slight amount //g_HUDHeatAlpha is applied in hudcomp.cpp if (((Mech::dwDamageFlags & MECH_PERMANENT_OVERHEAT_FX) == MECH_PERMANENT_OVERHEAT_FX) && (vehicleInterface) ) // e.g. this 'Mech is the local 'Mech { static unsigned int HudDistortionCounter = 0; static int HudDistortionValues[20] = { 20, 56, 92, 125, 165, 180, 160, 138, 165, 120, 150, 160, 140, 120, 115, 120, 100, 60, 80, 50 }; g_HUDHeatAlpha = (int) (HudDistortionValues[HudDistortionCounter++] + (Stuff::Random::GetFraction () * 100)); if (HudDistortionCounter == 19) HudDistortionCounter = 0; //reset the counter Clamp (g_HUDHeatAlpha,0,180); if (!g_HUDHeatLevel) //The alpha is not applied if HUDHeatLevel is 0, and if its not 0 (meaning there is real heat) we do not want to set it to this small non-zero value g_HUDHeatLevel = (Scalar)0.01; } if (((Mech::dwDamageFlags & MECH_RETICULE_WASH) == MECH_RETICULE_WASH) && (vehicleInterface) ) // e.g. this 'Mech is the local 'Mech { if (!g_HUDPPCLevel) g_HUDPPCLevel = 10; } //»óÈÆ //extern bool sh_isdeathmode; //Are we ejecting? if (m_NeedEject) { Verify ((m_NeedEject == 1) || (m_NeedEject == 2) || (m_NeedEject == 3)); if (m_NeedEject == 1) { if (!ejectEffect.GetCurrent ()) { if (vehicleInterface != NULL) vehicleInterface->SetEjectMode(); // Changed Site location from site_eject to site_eject2 // MSL 5.00 Adept::Site *ejectSite = FindSite("site_eject2"); Check_Object(ejectSite); Effect *effect; effect = CreateEffect(model->ejectEffectResource, ejectSite, true); if(effect) ejectEffect.Add(effect); } m_NeedEject = 2; //sh_isdeathmode=true; } else if (m_NeedEject == 2) // eject is done { if (!ejectEffect.GetCurrent ()) { ReactToDestruction (InternalDamageObject::DestructionDamageMode,0); m_NeedEject = 3; } } } else { //sh_isdeathmode=false; } //We are moving in the water if(m_needWakeEffect && currentSpeedMPS) { if(!m_wakeEffect.GetCurrent()) { Point3D effect_translation; effect_translation = GetLocalToWorld(); Check_Object (Map::GetInstance()); Check_Object (Map::GetInstance()->GetGameModel ()); effect_translation.y = Map::GetInstance()->GetGameModel ()->m_waterLevel; Effect *effect = CreateEffect(model->m_wakeEffectResource, effect_translation); if(effect) { effect->BecomeInteresting (true); effect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState); m_wakeEffect.Add(effect); } } else { LinearMatrix4D new_position = GetLocalToWorld(); Check_Object (Map::GetInstance()); Check_Object (Map::GetInstance()->GetGameModel ()); new_position.entries[7] = Map::GetInstance()->GetGameModel ()->m_waterLevel; m_wakeEffect.GetCurrent()->SetNewLocalToParent(new_position); m_wakeEffect.GetCurrent()->SyncMatrices(true); } } else { if(m_wakeEffect.GetCurrent()) { m_wakeEffect.GetCurrent()->executionState->RequestState(Effect::ExecutionStateEngine::StoppingState); } } if (triggerDeath == PowerDownDeathTrigger) { const GameModel *model = GetGameModel(); Check_Object(model); Point3D location; location = animationArray[torsoAboveJointIndex]->GetLocalToWorld(); CreateEffect(model->secondaryDestroyedEffectResource, location); SetDestroyedFlag(InternalDamageObject::DestructionDamageMode); if (diedBySplash) DealSplashDamage(); entityElement->SetAlwaysCullMode(); // // Moved this to here so that we couldn't fall right through objects like // buildings during the death animation // SetDestroyedFlag(InternalDamageObject::DestructionDamageMode); Entity *effect = CreateStaticHermitEntity(model->deathEntityResource); HandleSalvage(); if(Compost::TerrainTextureLogistic::Instance) { const GameModel *model = GetGameModel(); Check_Object(model); if(model->m_craterID >= 0) { Point3D local_to_world; local_to_world = GetLocalToWorld(); Compost::TerrainTextureLogistic::Instance->AddFeature( model->m_craterID, local_to_world.x, local_to_world.z); } } if(GetSearchLight()) { // // [johnyo] 08/27/00 PreviousSearchLight code is experimental code that I have checked in to keep a backup // of only. It may be ripped out shortly if the effect that it was intended to have isn't // put into the game // // m_previousSearchLightState = GetSearchLight()->isLightOn; // if (IsPlayerVehicle()) // { // Mission::GetInstance()->ResetMissionLights(); // } GetSearchLight()->HideBeam(); GetSearchLight()->DestroySubsystem(); } if (effect != NULL) MWApplication::GetInstance()->AddReplicatedHermit(effect); // if the player isn't the local player //if (!IsPlayerVehicle() || GetReplicatorID().connectionID != Connection::Local->GetID()) if (!IsPlayerVehicle() && !IsLanceMate()) { executionState->RequestState(ExecutionStateEngine::NeverExecuteState); RemoveCollision(); } // if it is not a player if (!IsPlayerVehicle() && !IsLanceMate()) { AbstractEvent *event = m_pendingInterestMessage.GetCurrent(); if (event) { Check_Object(event); delete event; } SetInterestLevel(DormantInterestLevel); } triggerDeath = DoneDeathTrigger; SyncMatrices(true); lastParameterization = till; initialLocalToParent = GetLocalToParent(); if (lancemateIndex != -1 && MWApplication::GetInstance()->serverFlag) { MWApplication::GetInstance()->QueRespawnLancemate(lancemateIndex); } } else if (triggerDeath == FallDownDeathTrigger) { const GameModel *model = GetGameModel(); Check_Object(model); Point3D location; location = animationArray[torsoAboveJointIndex]->GetLocalToWorld(); // CreateEffect(model->secondaryDestroyedEffectResource, centerTorso,true); SetDestroyedFlag(InternalDamageObject::DestructionDamageMode); if (diedBySplash) DealSplashDamage(); entityElement->SetAlwaysCullMode(); HandleSalvage (); Entity *effect = CreateStaticHermitEntity(model->secondaryDeathEntityResource); Point3D secondary_location; secondary_location = GetLocalToWorld(); CreateEffect(model->secondaryDestroyedEffectResource, secondary_location); if(Compost::TerrainTextureLogistic::Instance) { const GameModel *model = GetGameModel(); Check_Object(model); if(model->m_craterID >= 0) { Point3D local_to_world; local_to_world = GetLocalToWorld(); Compost::TerrainTextureLogistic::Instance->AddFeature( model->m_craterID, local_to_world.x, local_to_world.z); } } if(GetSearchLight()) { // if (IsPlayerVehicle()) // { // Mission::GetInstance()->ResetMissionLights(); // } GetSearchLight()->HideBeam(); GetSearchLight()->DestroySubsystem(); } if (effect != NULL) MWApplication::GetInstance()->AddReplicatedHermit(effect); //if (!IsPlayerVehicle() || GetReplicatorID().connectionID != Connection::Local->GetID()) if (!IsPlayerVehicle() && !IsLanceMate()) { executionState->RequestState(ExecutionStateEngine::NeverExecuteState); RemoveCollision(); //remove from execution will crash } // if it is not a player if (!IsPlayerVehicle() && !IsLanceMate()) { AbstractEvent *event = m_pendingInterestMessage.GetCurrent(); if (event) { Check_Object(event); delete event; } SetInterestLevel(DormantInterestLevel); } triggerDeath = DoneDeathTrigger; SyncMatrices(true); lastParameterization = till; initialLocalToParent = GetLocalToParent(); if (lancemateIndex != -1 && MWApplication::GetInstance()->serverFlag) { MWApplication::GetInstance()->QueRespawnLancemate(lancemateIndex); } } else { lastParameterization = till; initialLocalToParent = GetLocalToParent(); BaseClass::PostCollisionExecute(till); } #if 0 if (Connection::Local->GetID() == GetReplicatorID().connectionID && !MWApplication::GetInstance()->serverFlag) { Point3D position; position = GetElement()->GetNewLocalToParent(); //SPEW(("jerryeds","POST-MOVEMENT : %f %f %f", position.x, position.y, position.z)); } #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::FindGroundAngles(void) { Check_Object(this); PRECOLLISION_LOGIC("Mech::FindGroundAngles-1"); // //--------------------------------------------------- // Look for the centerpoint of where our feet are now //--------------------------------------------------- // const LinearMatrix4D& local_to_world = GetLocalToWorld(); Stuff::Line3D line; line.m_length = 2000.0f; line.m_direction = Vector3D::Down; line.m_origin = local_to_world; line.m_origin.y += 1000.0f; Stuff::Normal3D normal; CollisionQuery query(&line, &normal, CanBeWalkedOnFlag, this); Check_Object(CollisionGrid::Instance); Entity *entity_hit = CollisionGrid::Instance->ProjectLine(&query); m_footHitEntity = entity_hit; //if (!entity_hit) // STOP(("Mech is off edge")); //else //{ // Verify(entity_hit->CanBeWalkedOn()); //} materialHit = query.m_material; m_needWakeEffect = 0; Point3D tr; line.FindEnd(&tr); Check_Object (Map::GetInstance()); Check_Object (Map::GetInstance()->GetGameModel ()); m_WaterDelta = Map::GetInstance()->GetGameModel ()->m_waterLevel - tr.y; m_heatMaterialMultiplier = 1.0f; if ((m_WaterDelta >= ShallowWaterDepth) && (m_WaterDelta < MidWaterDepth)) { materialHit = FakeShallowWaterMaterial; m_heatMaterialMultiplier = 1.50f; m_needWakeEffect = 1; } else if ((m_WaterDelta >= MidWaterDepth) && (m_WaterDelta < DeepWaterDepth)) { materialHit = FakeMidWaterMaterial; m_heatMaterialMultiplier = 2.0f; m_needWakeEffect = 1; } else if (m_WaterDelta >= DeepWaterDepth) { materialHit = FakeOceanicWaterMaterial; m_heatMaterialMultiplier = 3.0f; m_needWakeEffect = 1; } if(m_needWakeEffect) { if(local_to_world.entries[7] > Map::GetInstance()->GetGameModel ()->m_waterLevel) m_needWakeEffect = 0; } // //---------------------------------------------------------------- // Figure out the slope of the ground under the center of the mech //---------------------------------------------------------------- // Stuff::Vector3D world_avg_normal(*query.m_normal); groundNormal = world_avg_normal; LinearMatrix4D world_to_local; world_to_local.Invert(local_to_world); m_LocalNormal.MultiplyByInverse(world_avg_normal, world_to_local); Stuff::Vector3D local_normal (m_LocalNormal); rawLocalGroundRoll = -Arctan(local_normal.x, local_normal.y); rawLocalGroundPitch = -Arctan(local_normal.z, local_normal.y); // //----------------------------------------- // Get the ground angle under the left foot //----------------------------------------- // Verify(siteLeftFoot != NULL); line.m_length = 2000.0f; line.m_direction = Vector3D::Down; line.m_origin = siteLeftFoot->GetLocalToWorld(); line.m_origin.y += 1000.0f; CollisionGrid::Instance->ProjectLine(&query); //if (!CollisionGrid::Instance->ProjectLine(&query)) // STOP(("Mech foot is off edge")); // //-------------------------------------------------------- // Store the left foot normal, height, and effect resource //-------------------------------------------------------- // world_avg_normal += *query.m_normal; leftFootNormal = *query.m_normal; Stuff::Point3D end_point; line.FindEnd(&end_point); leftFootGround = end_point.y; const GameModel *model = GetGameModel(); Check_Object(model); if (model->footFallEffectsTable != ResourceID::Null) Entity__GameModel::GetEffectResourceID(¤tLeftFootFall, model->footFallEffectsTable, materialHit); // //------------------------------------------ // Get the ground angle under the right foot //------------------------------------------ // Verify(siteRightFoot != NULL); line.m_length = 2000.0f; line.m_direction = Vector3D::Down; line.m_origin = siteRightFoot->GetLocalToWorld(); line.m_origin.y += 1000.0f; CollisionGrid::Instance->ProjectLine(&query); //if (!CollisionGrid::Instance->ProjectLine(&query)) // STOP(("Mech foot is off edge")); // //-------------------------------------------------------- // Store the right foot normal, height, and effect resource //-------------------------------------------------------- // world_avg_normal += *query.m_normal; leftFootNormal = *query.m_normal; line.FindEnd(&end_point); leftFootGround = end_point.y; if (model->footFallEffectsTable != ResourceID::Null) Entity__GameModel::GetEffectResourceID(¤tRightFootFall, model->footFallEffectsTable, materialHit); // //-------------------------------------------------------------- // take our normal sum and figure out the local pitch/roll angle //-------------------------------------------------------------- // UnitVector3D temp_vec (world_avg_normal); m_RawGroundPitch = Arccos (temp_vec.y); // world pitch m_WorldAvgNormal = temp_vec; local_normal.Multiply(world_avg_normal, world_to_local); float local_ground_roll = -Arctan(local_normal.x, local_normal.y); float local_ground_pitch = -Arctan(local_normal.z, local_normal.y); // //---------------------------------------------------------------------- // clamp the values to something usable by the animation system, then // stick the numbers into the smoothers and set our resultant pitch/roll // variables from the frame smoothed averages //---------------------------------------------------------------------- // Scalar max_value = Pi_Over_4 - Radians_Per_Degree; Clamp(local_ground_roll, -max_value, max_value); Clamp(local_ground_pitch, -max_value, max_value); pitchSmoother.Add(local_ground_pitch); rollSmoother.Add(local_ground_roll); localGroundPitch = pitchSmoother.CalculateAverage(); localGroundRoll = rollSmoother.CalculateAverage(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ComputeForwardSpeed(Stuff::Scalar time_slice) { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); Stuff::Scalar maxSpeedMod; Stuff::Scalar tonnage; bool slopecollide = false; PRECOLLISION_LOGIC("Mech::ComputeForwardSpeed"); // //---------------------------------------------------- // Set the demands to zero if the vehicle is shut down //---------------------------------------------------- // if (vehicleShutDown) { speedDemand = 0.0f; speedDemandKPH = 0.0f; } maxSpeedMod = 1.0f; tonnage = GetTonage (); switch (materialHit) { case WaterMaterial: { maxSpeedMod = 0.75f; break; } // PAUSE (("mech walked on water or swamp material")); case SnowMaterial: maxSpeedMod = 0.95f; break; case FakeShallowWaterMaterial: maxSpeedMod = 0.75f; break; case FakeMidWaterMaterial: maxSpeedMod = 0.5f; break; // MSL 5.03 Deep Water Fix case FakeOceanicWaterMaterial: maxSpeedMod = 0.25f; break; } switch (materialHit) { case FakeShallowWaterMaterial: case FakeMidWaterMaterial: case FakeOceanicWaterMaterial: if (vehicleInterface) { vehicleInterface->PlayForce (VehicleInterface::WaterMoveForce); vehicleInterface->ReactToEvent (VehicleInterface::STEP_WATER_START); } break; default: if (vehicleInterface) { vehicleInterface->StopForce (VehicleInterface::WaterMoveForce); vehicleInterface->ReactToEvent (VehicleInterface::STEP_WATER_STOP); } break; } #ifdef LAB_ONLY if (m_DebugFast) { maxSpeedMod = 10.0f; } #endif if (maxSpeedMod == 0.0f) // tell the ai we had a collision based on material type { if (vehicleInterface) vehicleInterface->ReactToEvent (VehicleInterface::TERRAIN_BAD); if ((m_AI) && (m_AI->IsDerivedFrom (MoverAI::DefaultData))) { MoverAI *ai = Cast_Object(MoverAI*, m_AI); ai->SlopeCollide(); } } // //------------------------------------------------------------------------ // Figure out our desired speed. If we are stopped, set the KPH variables // to zero and quit //------------------------------------------------------------------------ // if (speedDemand >= 0.0f) speedDemandMPS = (speedDemand * GetMaxSpeed()*maxSpeedMod); else speedDemandMPS = -(speedDemand * model->maxReverseSpeed*maxSpeedMod); speedDemandMPS *= m_heatManager->GetSpeedMultiplier(); if (speedDemandMPS == 0.0f && currentSpeedMPS == 0.0f) { localSpaceVelocity.linearMotion.z = 0.0f; speedDemandKPH = 0.0f; currentSpeedKPH = 0.0f; if ((m_LastSoundSpeedMPS != 0) && (vehicleInterface)) { vehicleInterface->ReactToEvent (VehicleInterface::ENGINE_STOP); } m_LastSoundSpeedMPS = 0; return; } // //---------------------------------------------------------------------- // Figure out the grade we are on. If it is less than what the mech can // normally walk on, slow or speed up based on pitch if we are moving // forward. Reverse is always at a constant speed. //---------------------------------------------------------------------- // Scalar grade; Scalar cosang; UnitVector3D forward; if (speedDemandMPS < 0) GetLocalToWorld().GetLocalBackwardInWorld(&forward); else GetLocalToWorld().GetLocalForwardInWorld(&forward); cosang = (forward.x*m_WorldAvgNormal.x)+(forward.y*m_WorldAvgNormal.y)+(forward.z*m_WorldAvgNormal.z); // if (m_LocalNormal.z < 0) if (cosang < 0) // going up the slope, { grade = Abs (m_RawGroundPitch); m_RawGroundPitch = m_RawGroundPitch < 0 ? m_RawGroundPitch * -1.0f : m_RawGroundPitch; } else { grade = 0; m_RawGroundPitch = m_RawGroundPitch > 0 ? m_RawGroundPitch * -1.0f : m_RawGroundPitch; } Scalar decceleration = model->decceleration; if (m_WaterDelta > 0) { if (currentSpeedMPS > 0.0f) { Stuff::Scalar speed_effect = -0.4f; speed_effect *= m_WaterDelta/DeepWaterDepth; speedDemandMPS += speedDemandMPS * speed_effect; } } #ifdef LAB_ONLY if (m_DebugFast) { } else #endif if (grade <= startSlopeDeceleration) { if (currentSpeedMPS > 0.0f) { Stuff::Scalar speed_effect = (m_RawGroundPitch >= 0.0f) ? -0.4f : -0.3f; speed_effect *= m_RawGroundPitch/startSlopeDeceleration; speedDemandMPS += speedDemandMPS * speed_effect; } } // //----------------------------------------------------------------------- // The slope is higher than we can tolerate, so we will have to slow down // very quickly to zero //------------------------------------------------------------------------ // else if (m_RawGroundPitch > 0.0f) { slopecollide = true; speedDemandMPS = 0.0f; // //------------------------------------------------ // If the grade is high enough, treat it as a wall //------------------------------------------------ // if (grade >= maxSlope) { if (vehicleInterface) vehicleInterface->ReactToEvent (VehicleInterface::HILL_TOO_STEEP); decceleration = model->slopeDecel3; if ((m_AI) && (m_AI->IsDerivedFrom (MoverAI::DefaultData))) { MoverAI *ai = Cast_Object(MoverAI*, m_AI); ai->SlopeCollide(); } } // //---------------------------------------------------------- // Pick the amount of deceleration to use based on the slope //---------------------------------------------------------- // else { if ((m_AI) && (m_AI->IsDerivedFrom (MoverAI::DefaultData))) // the models will quickly slow to zero. mech should not be going up this slope { MoverAI *ai = Cast_Object(MoverAI*, m_AI); ai->SlopeCollide(); } Verify(startSlopeDeceleration <= (Pi_Over_4+Pi_Over_8)); Scalar band_size = (maxSlope - startSlopeDeceleration)/3.0f; Scalar grade_band_one = startSlopeDeceleration + band_size; if (grade < grade_band_one) decceleration = model->slopeDecel1; else { Scalar grade_band_two = grade_band_one + band_size; decceleration = (grade < grade_band_two) ? model->slopeDecel2 : model->slopeDecel3; } } } // //-------------------------------------------- // Anything can go down - ain't gravity great? //-------------------------------------------- // else { Stuff::Scalar adjust_pitch = -localGroundPitch; Max_Clamp(adjust_pitch, Pi_Over_4); Stuff::Scalar speed_effect = 0.3f * adjust_pitch / Pi_Over_4; speedDemandMPS += speedDemandMPS * speed_effect; } // //---------------------------- // If we are gimped, slow down //---------------------------- // if (gimpState != NotGimpedMode) { Max_Clamp(speedDemandMPS, model->maxGimpSpeed); Min_Clamp(speedDemandMPS,0); } // //-------------------------------------------------------------------- // If we are not going backwards, find out what speed we want after we // consider braking //-------------------------------------------------------------------- // if (currentSpeedMPS >= 0.0f) { Stuff::Scalar decel_speed = currentSpeedMPS - (decceleration * time_slice); // //----------------------------------------------------------------- // If we want to move slower than our minimum speed and we want to // decelerate to a stand, set our current speed to be between those // two bounds //----------------------------------------------------------------- // if (m_ForceSpeed) { currentSpeedMPS = m_ForceSpeedValue; m_ForceSpeed = false; } else if ((currentSpeedMPS == 0) && (speedDemandMPS < 0)) { currentSpeedMPS = model->minReverseSpeed; } else if ((currentSpeedMPS == 0) && (speedDemandMPS > 0)) { currentSpeedMPS = model->minSpeed; } else if (speedDemandMPS <= model->minSpeed && decel_speed <= model->minStandTransitionSpeed) Clamp(currentSpeedMPS, model->minSpeed, model->minStandTransitionSpeed); // //-------------------------------------- // Otherwise, adjust our speed as needed //-------------------------------------- // else if (speedDemandMPS > currentSpeedMPS) { #ifdef LAB_ONLY if (m_DebugFast) currentSpeedMPS = speedDemandMPS; else #endif currentSpeedMPS += (model->acceleration * time_slice); Max_Clamp(currentSpeedMPS, speedDemandMPS); } else if (speedDemandMPS < currentSpeedMPS) { #ifdef LAB_ONLY if (m_DebugFast) currentSpeedMPS = speedDemandMPS; else #endif currentSpeedMPS -= (decceleration * time_slice); Min_Clamp(currentSpeedMPS, speedDemandMPS); } } // //-------------------------------------------------------------- // We are backing up, so tell the AI if we had a grade collision //-------------------------------------------------------------- // else { Stuff::Scalar decel_spped = currentSpeedMPS + (model->reverseDeccelerationMultiplier * time_slice); // //------------------------------------------------------------- // Deal with the stand transition if that is the case we are in //------------------------------------------------------------- // if (speedDemandMPS >= model->minReverseSpeed && decel_spped >= -model->minStandTransitionSpeed) Clamp(currentSpeedMPS, -model->minStandTransitionSpeed, model->minReverseSpeed); // //------------------------------------- // Otherwise adjust our speed as needed //------------------------------------- // else if (speedDemandMPS < currentSpeedMPS) { currentSpeedMPS -= (model->acceleration * model->reverseAccelerationMultiplier * time_slice); Min_Clamp(currentSpeedMPS, speedDemandMPS); } else if (speedDemandMPS > currentSpeedMPS) { currentSpeedMPS += (decceleration * model->reverseDeccelerationMultiplier * time_slice); Max_Clamp(currentSpeedMPS, speedDemandMPS); } } // //---------------------------------------------------- // Now adjust all this to the limits in the model file //---------------------------------------------------- // Clamp(currentSpeedMPS, model->maxReverseSpeed*maxSpeedMod, GetMaxSpeed()*maxSpeedMod); localSpaceVelocity.linearMotion.z = currentSpeedMPS; // //---------------------- // Set the KPH variables //---------------------- // currentSpeedKPH = currentSpeedMPS * 3.6f; speedDemandKPH = speedDemandMPS * 3.6f; if ((m_LastSoundSpeedMPS == 0) && (currentSpeedMPS != 0) && (vehicleInterface)) { if (currentSpeedMPS < 0) vehicleInterface->ReactToEvent (VehicleInterface::ENGINE_REVERSE); else vehicleInterface->ReactToEvent (VehicleInterface::ENGINE_WALK); } else if ((m_LastSoundSpeedMPS > 0) && (currentSpeedMPS < 0) && (vehicleInterface)) { vehicleInterface->ReactToEvent (VehicleInterface::ENGINE_REVERSE); } else if ((m_LastSoundSpeedMPS < WALK_SPEED_SOUND) && (currentSpeedMPS >= WALK_SPEED_SOUND) && (vehicleInterface)) { vehicleInterface->ReactToEvent (VehicleInterface::ENGINE_RUN); } else if ((m_LastSoundSpeedMPS != 0) && (currentSpeedMPS == 0) && (vehicleInterface)) { vehicleInterface->ReactToEvent (VehicleInterface::ENGINE_STOP); } m_LastSoundSpeedMPS = currentSpeedMPS; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::TiltMech(Stuff::Scalar time_slice) { Check_Object(this); PRECOLLISION_LOGIC("Mech::TiltMech"); // //---------------------------------------------- // Figure out the area of mech motion we tilt in //---------------------------------------------- // const GameModel *model = GetGameModel(); tiltRequest = 0.0f; Scalar temp = GetTurnSpeed(); Scalar tilt_tan = currentSpeedMPS * yawDemand * temp; tiltRequest = Arctan(tilt_tan, g_Gravity) * model->tiltDegree / Pi_Over_2; // //---------------------------------------- // Smooth the motion of the tilt angle out //---------------------------------------- // if (tiltAngle < tiltRequest) { tiltAngle += (model->tiltSpeed*time_slice); Max_Clamp(tiltAngle, tiltRequest); } else if (tiltAngle > tiltRequest) { tiltAngle -= (model->tiltSpeed*time_slice); Min_Clamp(tiltAngle, tiltRequest); } if (internalViewPoint) tiltAngle *= model->scaleInternalTiltDegree; // //------------------------------------------------------------------------ // Apply the extra tilt to the ground to make the mech appear to lean over //------------------------------------------------------------------------ // localGroundRoll += tiltAngle; // //----------------------------------- // Add any damage rotation from a hit //----------------------------------- // localGroundPitch += rootHit.GetCurrentPosition().pitch; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::MaintainWalkingAnimStates(bool run_minimal) { PRECOLLISION_LOGIC("Mech::MaintainAnimStates"); const GameModel *model = GetGameModel(); if (!animStateEngine->IsTransitioning()) { if (queFallState != NoFallMode) { switch(queFallState) { case FallBackMode: animStateEngine->RequestState(MechAnimationStateEngine::FallBackwardState, run_minimal); break; case FallRightMode: animStateEngine->RequestState(MechAnimationStateEngine::FallRightState, run_minimal); break; case FallLeftMode: animStateEngine->RequestState(MechAnimationStateEngine::FallLeftState, run_minimal); break; case FallForwardMode: animStateEngine->RequestState(MechAnimationStateEngine::FallForwardState, run_minimal); break; } StartFall(); fallDirection = queFallState; // queFallState = NoFallMode; return; } else if (gimpState == LeftGimpMode) { if (animStateEngine->GetState() == MechAnimationStateEngine::ForwardState) { animStateEngine->RequestState(MechAnimationStateEngine::GimpForwardLeftState, run_minimal); } } else if (gimpState == RightGimpMode) { if (animStateEngine->GetState() == MechAnimationStateEngine::ForwardState) { animStateEngine->RequestState(MechAnimationStateEngine::GimpForwardRightState, run_minimal); } } else if (animStateEngine->GetState() == MechAnimationStateEngine::FallForwardState) { localSpaceVelocity.linearMotion = Vector3D::Identity; worldSpaceVelocity.linearMotion = Vector3D::Identity; if (!IsDestroyed()) { animStateEngine->RequestState(MechAnimationStateEngine::StandState, run_minimal); } } else if (animStateEngine->GetState() == MechAnimationStateEngine::FallBackwardState) { localSpaceVelocity.linearMotion = Vector3D::Identity; worldSpaceVelocity.linearMotion = Vector3D::Identity; if (!IsDestroyed()) { animStateEngine->RequestState(MechAnimationStateEngine::StandState, run_minimal); } } else if (animStateEngine->GetState() == MechAnimationStateEngine::FallLeftState) { localSpaceVelocity.linearMotion = Vector3D::Identity; worldSpaceVelocity.linearMotion = Vector3D::Identity; if (!IsDestroyed()) { animStateEngine->RequestState(MechAnimationStateEngine::StandState, run_minimal); } } else if (animStateEngine->GetState() == MechAnimationStateEngine::FallRightState) { localSpaceVelocity.linearMotion = Vector3D::Identity; worldSpaceVelocity.linearMotion = Vector3D::Identity; if (!IsDestroyed()) { animStateEngine->RequestState(MechAnimationStateEngine::StandState, run_minimal); } } if (animStateEngine->GetState() == MechAnimationStateEngine::FlyState) { if (executionState->GetState() == ExecutionStateEngine::DrivingMotionState) { if (currentSpeedMPS <= 0.0f) animStateEngine->RequestState(MechAnimationStateEngine::StandState, run_minimal); else animStateEngine->RequestState(MechAnimationStateEngine::ForwardState, run_minimal); } } else if (animStateEngine->GetState() == MechAnimationStateEngine::ForwardState) { m_eyePointManager->Stabalize(1.0f); if (currentSpeedMPS <= model->minStandTransitionSpeed && speedDemandMPS <= model->minSpeed) { animStateEngine->RequestState(MechAnimationStateEngine::StandState, run_minimal); lastSpeedMPS = currentSpeedMPS; } } else if (animStateEngine->GetState() == MechAnimationStateEngine::BackwardState) { m_eyePointManager->Stabalize(1.0f); if (currentSpeedMPS >= -model->minStandTransitionSpeed && speedDemandMPS >= model->minReverseSpeed) { animStateEngine->RequestState(MechAnimationStateEngine::StandState, run_minimal); lastSpeedMPS = currentSpeedMPS; } } else if (animStateEngine->GetState() == MechAnimationStateEngine::StandState) { m_eyePointManager->Stabalize(1.0f); if (vehicleShutDown) { // MSL 5.03 Cockpit Follow m_eyePointManager->Follow(0.0f); animStateEngine->RequestState(MechAnimationStateEngine::PowerDownState,run_minimal); if (vehicleInterface) vehicleInterface->EndEngineIdle (); } else if (speedDemandMPS < model->minReverseSpeed) { currentSpeedMPS = 0.0f; animStateEngine->RequestState(MechAnimationStateEngine::BackwardState,run_minimal); } else if (speedDemandMPS > model->minSpeed) { animStateEngine->RequestState(MechAnimationStateEngine::ForwardState,run_minimal); } else if (yawDemand < 0.0f && speedDemandMPS == 0.0f) { currentSpeedMPS = 0.0f; animStateEngine->RequestState(MechAnimationStateEngine::TurnLeftState,run_minimal); } else if (yawDemand > 0.0f && speedDemandMPS == 0.0f) { currentSpeedMPS = 0.0f; animStateEngine->RequestState(MechAnimationStateEngine::TurnRightState,run_minimal); } else { currentSpeedMPS = 0.0f; } } else if (animStateEngine->GetState() == MechAnimationStateEngine::GimpStandLeftState) { m_eyePointManager->Stabalize(1.0f); if (speedDemandMPS > model->minSpeed) { animStateEngine->RequestState(MechAnimationStateEngine::GimpForwardLeftState,run_minimal); } else if (yawDemand < 0.0f && speedDemandMPS == 0.0f) { currentSpeedMPS = 0.0f; animStateEngine->RequestState(MechAnimationStateEngine::LGimpTurnLeftState,run_minimal); } else if (yawDemand > 0.0f && speedDemandMPS == 0.0f) { currentSpeedMPS = 0.0f; animStateEngine->RequestState(MechAnimationStateEngine::LGimpTurnRightState,run_minimal); } else { currentSpeedMPS = 0.0f; } } else if (animStateEngine->GetState() == MechAnimationStateEngine::GimpStandRightState) { m_eyePointManager->Stabalize(1.0f); if (speedDemandMPS > model->minSpeed) { animStateEngine->RequestState(MechAnimationStateEngine::GimpForwardRightState,run_minimal); } else if (yawDemand < 0.0 && speedDemandMPS == 0.0f) { currentSpeedMPS = 0.0f; animStateEngine->RequestState(MechAnimationStateEngine::RGimpTurnLeftState,run_minimal); } else if (yawDemand > 0.0f && speedDemandMPS == 0.0f) { currentSpeedMPS = 0.0f; animStateEngine->RequestState(MechAnimationStateEngine::RGimpTurnRightState,run_minimal); } else { currentSpeedMPS = 0.0f; } } else if (animStateEngine->GetState() == MechAnimationStateEngine::GimpForwardLeftState) { m_eyePointManager->Stabalize(1.0f); if (currentSpeedMPS <= model->minStandTransitionSpeed && speedDemandMPS <= model->minSpeed) { animStateEngine->RequestState(MechAnimationStateEngine::GimpStandLeftState,run_minimal); lastSpeedMPS = currentSpeedMPS; } } else if (animStateEngine->GetState() == MechAnimationStateEngine::GimpForwardRightState) { m_eyePointManager->Stabalize(1.0f); if (currentSpeedMPS <= model->minStandTransitionSpeed && speedDemandMPS <= model->minSpeed) { animStateEngine->RequestState(MechAnimationStateEngine::GimpStandRightState,run_minimal); lastSpeedMPS = currentSpeedMPS; } } else if (animStateEngine->GetState() == MechAnimationStateEngine::TurnRightState) { m_eyePointManager->Stabalize(1.0f); if (animStateEngine->CurrentStateLoopedThisFrame()) { if (yawDemand == 0.0f || speedDemand != 0.0f) { animStateEngine->RequestState(MechAnimationStateEngine::StandState,run_minimal); } else { animStateEngine->RequestState(MechAnimationStateEngine::TurnLeftState,run_minimal); } } } else if (animStateEngine->GetState() == MechAnimationStateEngine::TurnLeftState) { m_eyePointManager->Stabalize(1.0f); if (animStateEngine->CurrentStateLoopedThisFrame()) { if (yawDemand == 0.0f || speedDemand != 0.0f) { animStateEngine->RequestState(MechAnimationStateEngine::StandState,run_minimal); } else { animStateEngine->RequestState(MechAnimationStateEngine::TurnRightState,run_minimal); } } } else if (animStateEngine->GetState() == MechAnimationStateEngine::LGimpTurnRightState) { m_eyePointManager->Stabalize(1.0f); if (animStateEngine->CurrentStateLoopedThisFrame()) { if (yawDemand == 0.0f || speedDemand != 0.0f) { animStateEngine->RequestState(MechAnimationStateEngine::GimpStandLeftState,run_minimal); } else { animStateEngine->RequestState(MechAnimationStateEngine::LGimpTurnLeftState,run_minimal); } } } else if (animStateEngine->GetState() == MechAnimationStateEngine::LGimpTurnLeftState) { m_eyePointManager->Stabalize(1.0f); if (animStateEngine->CurrentStateLoopedThisFrame()) { if (yawDemand == 0.0f || speedDemand != 0.0f) { animStateEngine->RequestState(MechAnimationStateEngine::GimpStandLeftState,run_minimal); } else { animStateEngine->RequestState(MechAnimationStateEngine::LGimpTurnRightState,run_minimal); } } } else if (animStateEngine->GetState() == MechAnimationStateEngine::RGimpTurnRightState) { m_eyePointManager->Stabalize(1.0f); if (animStateEngine->CurrentStateLoopedThisFrame()) { if (yawDemand == 0.0f || speedDemand != 0.0f) { animStateEngine->RequestState(MechAnimationStateEngine::GimpStandRightState,run_minimal); } else { animStateEngine->RequestState(MechAnimationStateEngine::RGimpTurnLeftState,run_minimal); } } } else if (animStateEngine->GetState() == MechAnimationStateEngine::RGimpTurnLeftState) { m_eyePointManager->Stabalize(1.0f); if (animStateEngine->CurrentStateLoopedThisFrame()) { if (yawDemand == 0.0f || speedDemand != 0.0f) { animStateEngine->RequestState(MechAnimationStateEngine::GimpStandRightState,run_minimal); } else { animStateEngine->RequestState(MechAnimationStateEngine::RGimpTurnRightState,run_minimal); } } } else if (animStateEngine->GetState() == MechAnimationStateEngine::PowerDownState) { if (currentSpeedMPS != speedDemandMPS) { m_LastSoundSpeedMPS = speedDemandMPS; currentSpeedMPS = speedDemandMPS; } if (triggerDeath == NoDeathTrigger && IsDestroyed()) { triggerDeath = PowerDownDeathTrigger; } else { if (!vehicleShutDown) { if (vehicleInterface) vehicleInterface->StartEngineIdle (); animStateEngine->RequestState(MechAnimationStateEngine::StandState, run_minimal); } } } } else { //we are in a transition... if (animStateEngine->GetTransitionState() == MechAnimationStateEngine::ForwardState) { Min_Clamp(currentSpeedMPS, model->minSpeed); } else if (animStateEngine->GetTransitionState() == MechAnimationStateEngine::BackwardState) { Max_Clamp(currentSpeedMPS, model->minReverseSpeed); } else if (animStateEngine->GetTransitionState() == MechAnimationStateEngine::GimpForwardRightState) { Min_Clamp(currentSpeedMPS, model->minSpeed); } else if (animStateEngine->GetTransitionState() == MechAnimationStateEngine::GimpForwardLeftState) { Min_Clamp(currentSpeedMPS, model->minSpeed); } else if (animStateEngine->GetTransitionState() == MechAnimationStateEngine::FlyState) { //Min_Clamp(currentSpeedMPS, model->minSpeed); } else if (animStateEngine->GetTransitionState() == MechAnimationStateEngine::StandState) { //Min_Clamp(currentSpeedMPS, lastSpeedMPS); } else if (animStateEngine->GetTransitionState() == MechAnimationStateEngine::StandHalfState) { //Min_Clamp(currentSpeedMPS, lastSpeedMPS); } else if (animStateEngine->GetTransitionState() == MechAnimationStateEngine::GimpStandRightState) { //Min_Clamp(currentSpeedMPS, lastSpeedMPS); } else if (animStateEngine->GetTransitionState() == MechAnimationStateEngine::GimpStandLeftState) { //Min_Clamp(currentSpeedMPS, lastSpeedMPS); } // if we are falling add some slide // etc etc.. } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::MovementSimulation( Scalar time_slice, Stuff::Vector3D &new_velocity, Stuff::Vector3D &instantanious_angular_velocity ) { Check_Object(this); Verify(time_slice > 0.0f); PRECOLLISION_LOGIC("Mech::MovementSim"); bool networking = MWApplication::GetInstance()->networkingFlag; // //------------------------------------- // Find the position we are standing on //------------------------------------- // const Stuff::LinearMatrix4D &mech_to_world = GetLocalToWorld(); Stuff::LinearMatrix4D axis_to_world(Stuff::LinearMatrix4D::Identity); if (leftFootDown && !rightFootDown && !networking) { const LinearMatrix4D &matrix = siteLeftFoot->GetLocalToWorld(); axis_to_world(3,0) = matrix(3,0); axis_to_world(3,1) = matrix(3,1); axis_to_world(3,2) = matrix(3,2); } else if (!leftFootDown && rightFootDown && !networking) { const LinearMatrix4D &matrix = siteRightFoot->GetLocalToWorld(); axis_to_world(3,0) = matrix(3,0); axis_to_world(3,1) = matrix(3,1); axis_to_world(3,2) = matrix(3,2); } else { axis_to_world(3,0) = mech_to_world(3,0); axis_to_world(3,1) = mech_to_world(3,1); axis_to_world(3,2) = mech_to_world(3,2); } // //----------------------------------------------------------------------- // add in the yaw, pitch, and roll demands from the interface & animation //----------------------------------------------------------------------- // YawPitchRoll mech_rotation_local_to_world(mech_to_world); Scalar temp = GetTurnSpeed(); temp *= time_slice; YawPitchRoll rotation_step; rotation_step.yaw = yawDemand * temp; rotation_step.pitch = pitchDemand * temp; rotation_step.roll = rollDemand * temp; // //----------------------------------------------------------------------- // if either foot is locked, accumulate the rotation for counter steering //----------------------------------------------------------------------- // if (rightFootState == FootLocked) rightFootTurnAccumulation += rotation_step.yaw; if (leftFootState == FootLocked) leftFootTurnAccumulation += rotation_step.yaw; // //------------------------------------------------------------- // Compute the acceleration on the mech and move it accordingly //------------------------------------------------------------- // Point3D mech_in_world(mech_to_world); JumpJet *jump_jet = GetJumpJet(); if (!jump_jet || jump_jet->executionState->GetState() != JumpJet::ExecutionStateEngine::JumpingState) Max_Clamp(localSpaceVelocity.linearMotion.y, 0.0f); else Max_Clamp(localSpaceVelocity.linearMotion.y, 30.0f); new_velocity.y = localSpaceVelocity.linearMotion.y + 0.5f*localSpaceAcceleration.linearMotion.y*time_slice*Special_Mech_Gravity; Vector3D adj; adj.Multiply(new_velocity, mech_to_world); adj *= time_slice; mech_in_world += adj; localSpaceVelocity.linearMotion.y += localSpaceAcceleration.linearMotion.y*time_slice*Special_Mech_Gravity; // //------------------------------------------------ // Find the correct axis to rotate the mech around //------------------------------------------------ // Point3D mech_in_axis; mech_in_axis.MultiplyByInverse(mech_in_world, axis_to_world); LinearMatrix4D rotation_matrix(true); rotation_matrix.BuildRotation(rotation_step); Point3D mech_in_axle; mech_in_axle.Multiply(mech_in_axis, rotation_matrix); mech_in_world.Multiply(mech_in_axle, axis_to_world); if (m_ForceYaw) { mech_rotation_local_to_world.yaw = m_ForceYawValue; m_ForceYaw = false; } else { mech_rotation_local_to_world.yaw += rotation_step.yaw; } mech_rotation_local_to_world.pitch += rotation_step.pitch; mech_rotation_local_to_world.roll += rotation_step.roll; //------------------------------------ // add in the network dead reckon adjustments... //------------------------------------ YawPitchRoll correction_angle; Point3D correction_position; //GetNetworkAdjustment(time_slice, correction_position, correction_angle); //mech_rotation_local_to_world.yaw += correction_angle.yaw; //mech_in_world.Add(mech_in_world, correction_position); if (GetNetworkAdjustment(time_slice, correction_position, correction_angle)) { mech_rotation_local_to_world = correction_angle; mech_in_world = correction_position; } // //---------------------- // Test our new location //---------------------- // Stuff::Line3D line; //regular... if ((GetReplicatorMode () == ClientMasterMode) || (GetReplicatorMode () == MasterMode)) { line.m_length = (Ground_Mode==0) ? 40.0f : (m_groundRaycastHeight + 0.0001f); } else { line.m_length = 40.0f; } line.m_direction = Vector3D::Down; line.m_origin = mech_in_world; line.m_origin.y += m_groundRaycastHeight; Stuff::Normal3D normal; CollisionQuery query(&line, &normal, CanBeWalkedOnFlag, this); Check_Object(CollisionGrid::Instance); // //---------------------------------------------------------------------- // If we don't hit the ground, and neither foot is marked to hit the // ground, we will need to see where we will be after the jump transition // occurs //---------------------------------------------------------------------- // LinearMatrix4D new_local_to_world; new_local_to_world.BuildRotation(mech_rotation_local_to_world); if (!CollisionGrid::Instance->ProjectLine(&query)) { if ((GetReplicatorMode () == ClientMasterMode) || (GetReplicatorMode () == MasterMode)) { if (Ground_Mode==2 && !(isLeftFootDown || isRightFootDown)) { Point3D mech_in_world(mech_to_world); Scalar t = time_slice + 0.8f; Vector3D v(Vector3D::Identity); v.y = localSpaceVelocity.linearMotion.y + 0.5f*localSpaceAcceleration.linearMotion.y*t*Special_Mech_Gravity; Vector3D adj; adj.Multiply(v, mech_to_world); adj *= t; mech_in_world += adj; line.m_origin = mech_in_world; line.m_origin.y += m_groundRaycastHeight; line.m_length = m_groundRaycastHeight + 0.001f; // //----------------------------------------------- // If we still haven't hit anything, start flying //----------------------------------------------- // if (!CollisionGrid::Instance->ProjectLine(&query)) executionState->RequestState(ExecutionStateEngine::FlyingMotionState); } } new_local_to_world.BuildTranslation(mech_in_world); worldSpaceVelocity.linearMotion.Multiply( localSpaceVelocity.linearMotion, new_local_to_world ); // //----------------------------------------------- // Make sure we can't leave footprints in the air //----------------------------------------------- // isLeftFootDown = false; isRightFootDown = false; } // //-------------------------------------- // Otherwise, just snap to that position //-------------------------------------- // else { line.FindEnd(&mech_in_world); Vector3D linear_motion; Point3D old_position; old_position = mech_to_world; linear_motion.Subtract(mech_in_world, old_position); linear_motion.Divide(linear_motion, time_slice); if (!jump_jet || jump_jet->executionState->GetState() != JumpJet::ExecutionStateEngine::JumpingState) Max_Clamp(linear_motion.y, 0.0f); new_local_to_world.BuildTranslation(mech_in_world); worldSpaceVelocity.linearMotion = linear_motion; localSpaceVelocity.linearMotion.MultiplyByInverse( worldSpaceVelocity.linearMotion, new_local_to_world ); } // //----------------------------------------- // Place the mech at the specified location //----------------------------------------- // SetNewLocalToParent(new_local_to_world); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::FallingMovementSimulation(Scalar time_slice, Stuff::Vector3D &new_velocity, Stuff::Vector3D &instantanious_angular_velocity) { Check_Object(this); Verify(time_slice > 0.0f); PRECOLLISION_LOGIC("Mech::FallingMovementSim"); //instantanious_angular_velocity.Divide(instantanious_angular_velocity, time_slice); // // get the local to world matrix from the locator // const Stuff::LinearMatrix4D &local_to_world = GetLocalToWorld(); // // make a vector of where we want to go // Vector3D point = Point3D::Identity; point.Multiply( new_velocity, time_slice ); // // put it in local space // Vector3D adj; adj.Multiply(point, local_to_world); // // add the local adjustment to the current position // Point3D new_translation; new_translation = local_to_world; new_translation += adj; // // get the current yawpitchroll from the local to world matrix // YawPitchRoll new_rotation(YawPitchRoll::Identity); new_rotation = local_to_world; // // then add in the yaw, pitch, and roll demands from the animation // new_rotation.yaw += instantanious_angular_velocity.y * time_slice; new_rotation.pitch += instantanious_angular_velocity.x * time_slice; new_rotation.roll += instantanious_angular_velocity.z * time_slice; YawPitchRoll correction_angle; Point3D correction_position; //GetNetworkAdjustment(time_slice, correction_position, correction_angle); //new_rotation.yaw += correction_angle.yaw; //new_translation.Add(new_translation, correction_position); if (GetNetworkAdjustment(time_slice, correction_position, correction_angle)) { new_rotation = correction_angle; new_translation = correction_position; } // Find the ground // // make a line... // Stuff::Line3D line; line.m_length = m_groundRaycastHeight; line.m_direction = Vector3D::Down; line.m_origin = new_translation; line.m_origin.y += 5.0f; // pretty harsh hill! =) // // Prepare query // Stuff::Normal3D normal; CollisionQuery query(&line, &normal, CanBeWalkedOnFlag, this); // // Cast ray // Adept::Entity *entity_hit; Check_Object(CollisionGrid::Instance); entity_hit = CollisionGrid::Instance->ProjectLine(&query); Stuff::Vector3D world_avg_normal(Stuff::Vector3D::Identity); if(entity_hit != NULL) { // if we hit ground, great! line.FindEnd(&new_translation); world_avg_normal = *query.m_normal; } else { // Damnit...then find the ground aggresivly!!!! line.m_length = 10000.0f; entity_hit = CollisionGrid::Instance->ProjectLine(&query); if (entity_hit != NULL) { line.FindEnd(&new_translation); world_avg_normal = *query.m_normal; } else // now try up! { line.m_direction = Vector3D(0.0f, 1.0f, 0.0f); entity_hit = CollisionGrid::Instance->ProjectLine(&query); if (entity_hit != NULL) { line.FindEnd(&new_translation); world_avg_normal = *query.m_normal; } } // ok stop we are way off the map } // figure out the ground angle... Stuff::Vector3D local_normal; local_normal.MultiplyByInverse(world_avg_normal, local_to_world); Stuff::Scalar local_ground_roll = 0.0f; Stuff::Scalar local_ground_pitch = 0.0f; if (local_normal.y != 0) { local_ground_roll = Arctan(local_normal.x, local_normal.y); local_ground_pitch = Arctan(local_normal.z, local_normal.y); } // // create a new matrix and build the translation and rotation // LinearMatrix4D new_local_to_world; new_local_to_world.BuildTranslation(new_translation); new_local_to_world.BuildRotation(new_rotation); // // set the local to parent to the new matrix created above // SetNewLocalToParent(new_local_to_world); if (animStateEngine->IsTransitioning()) { switch (animStateEngine->GetState()) { case MechAnimationStateEngine::FallForwardState: case MechAnimationStateEngine::FallBackwardState: case MechAnimationStateEngine::FallLeftState: case MechAnimationStateEngine::FallRightState: { if (fallTimer <= 0.0f) { // tilt the mech to adjust back.. const GameModel *model = GetGameModel(); YawPitchRoll rotation(YawPitchRoll::Identity); rotation.roll = -local_ground_roll; rotation.pitch = local_ground_pitch; UnitQuaternion ground_quaternion; ground_quaternion = rotation; if (getUpTimer > 0.0f) { // tilt the mech to adjust on the ground Stuff::Scalar slerp_value; // if the delay is gone... if (getUpTimer < model->getUpAdjustmentDelaySeconds) { slerp_value = getUpTimer / model->getUpAdjustmentSeconds; } else { slerp_value = 1.0f; } fallGround.Lerp(UnitQuaternion::Identity, ground_quaternion, slerp_value); getUpTimer -= time_slice; } else { fallGround = UnitQuaternion::Identity; } Point3D translation(Point3D::Identity); LinearMatrix4D new_local_to_parent; new_local_to_parent.BuildRotation(fallGround); new_local_to_parent.BuildTranslation(translation); jointWorld->SetNewLocalToParent(new_local_to_parent); } } break; default: { const GameModel *model = GetGameModel(); YawPitchRoll rotation(YawPitchRoll::Identity); rotation.roll = -local_ground_roll; rotation.pitch = local_ground_pitch; UnitQuaternion ground_quaternion; ground_quaternion = rotation; if (fallTimer > 0.0f) { // tilt the mech to adjust on the ground Stuff::Scalar slerp_value; // if the delay is gone... if (fallTimer < model->fallAdjustmentSeconds) { slerp_value = fallTimer / model->fallAdjustmentSeconds; } else { slerp_value = 1.0f; } fallGround.Lerp(ground_quaternion, initialPosition, slerp_value); fallGround.Normalize(); fallTimer -= time_slice; } else { fallGround = rotation; } Point3D translation(Point3D::Identity); LinearMatrix4D new_local_to_parent; new_local_to_parent.BuildRotation(fallGround); new_local_to_parent.BuildTranslation(translation); jointWorld->SetNewLocalToParent(new_local_to_parent); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::StartFall(void) { m_CanStartGettingUp = false; armsNulled = false; armReNullTime = 0; if (vehicleInterface) { vehicleInterface->PlayForce (VehicleInterface::FallDownForce); } GetTorso()->LookForward(); // MSL 5.03 Cockpit follow m_eyePointManager->Follow(0.0f); executionState->RequestState(ExecutionStateEngine::FallingMotionState); initialPosition = jointWorld->GetLocalToParent(); initialPosition.Normalize(); const GameModel *model = GetGameModel(); fallTimer = model->fallAdjustmentSeconds + model->fallAdjustmentDelaySeconds; getUpTimer = model->getUpAdjustmentSeconds + model->getUpAdjustmentDelaySeconds; m_SlideTimer = gos_GetElapsedTime () + 3.0f; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::BallisticMovementSimulation(Stuff::Time till) { Check_Object(this); PRECOLLISION_LOGIC("Mech::BallisticSim"); // //---------------------------------------------------------- // Put gravity into local space and compute our new position //---------------------------------------------------------- // LinearDragMotionSimulation(till); currentSpeedMPS = localSpaceVelocity.linearMotion.z; Scalar time_slice = GetTimeSlice(till); YawPitchRoll mech_rotation(entityElement->GetNewLocalToParent()); Scalar turn_rate = MW4AI::UserConstants::m_Instance->Get(MW4AI::UserConstants::flying_turn_rate); if (turn_rate != 0.0f) { Scalar deflection = turn_rate * time_slice * yawDemand; SinCosPair rot(deflection); Scalar new_x = rot.cosine*worldSpaceVelocity.linearMotion.x + rot.sine*worldSpaceVelocity.linearMotion.z; Scalar new_z = rot.cosine*worldSpaceVelocity.linearMotion.z - rot.sine*worldSpaceVelocity.linearMotion.x; worldSpaceVelocity.linearMotion.x = new_x; worldSpaceVelocity.linearMotion.z = new_z; mech_rotation.yaw += deflection; } Point3D mech_position(entityElement->GetNewLocalToParent()); //------------------------------------ // add in the network dead reckon adjustments... //------------------------------------ YawPitchRoll correction_angle; Point3D correction_position; //GetNetworkAdjustment(time_slice, correction_position, correction_angle); //mech_rotation.yaw += correction_angle.yaw; //mech_position.Add(mech_position, correction_position); if (GetNetworkAdjustment(time_slice, correction_position, correction_angle)) { mech_rotation = correction_angle; mech_position = correction_position; } LinearMatrix4D lin_mat; lin_mat.BuildRotation(mech_rotation); lin_mat.BuildTranslation(mech_position); SetNewLocalToParent(lin_mat); //worldSpaceVelocity.linearMotion.Multiply(localSpaceVelocity.linearMotion, lin_mat); // //------------------------------------- // Grab the new position and cast a ray //------------------------------------- // LinearMatrix4D new_local_to_world = GetElement()->GetNewLocalToParent(); Stuff::Line3D line; line.m_length = m_groundRaycastHeight + 0.001f; line.m_direction = Vector3D::Down; line.m_origin = new_local_to_world; line.m_origin.y += m_groundRaycastHeight; Stuff::Normal3D normal; CollisionQuery query(&line, &normal, CanBeWalkedOnFlag, this); Adept::Entity *entity_hit; Check_Object(CollisionGrid::Instance); entity_hit = CollisionGrid::Instance->ProjectLine(&query); // //------------------------------------------------------------------------ // If we have hit the ground, time to drive again, so put ourself where we // hit and zero out the vertical velocity //------------------------------------------------------------------------ // if (entity_hit) { new_local_to_world(3,1) = line.m_origin.y - line.m_length; SetNewLocalToParent(new_local_to_world); localSpaceVelocity.linearMotion.y = 0.0f; worldSpaceVelocity.linearMotion.y = 0.0f; // //------------------------------------- // If we have jumpjets, tell it to stop //------------------------------------- // JumpJet *jump_jet = GetJumpJet(); if (jump_jet) { Check_Object(jump_jet); jump_jet->RequestJumpJetsOff(); } executionState->RequestState(ExecutionStateEngine::DrivingMotionState); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::FindGroundAngle(const Stuff::LinearMatrix4D &local_to_world) { PRECOLLISION_LOGIC("Mech::FingGroundAngle-2"); // Get where we are... local_to_world.TestInstance(); // put four lines into the world to collide with the ground Stuff::Point3D forward_point(Stuff::Point3D::Identity); // one would think I can just get the forward_point = local_to_world; Stuff::Vector3D world_avg_normal(Stuff::Vector3D::Identity); Stuff::Normal3D normal; Stuff::Line3D line; CollisionQuery query(&line, &normal, CanBeWalkedOnFlag, this); // // Cast ray // Adept::Entity *entity_hit; Check_Object(CollisionGrid::Instance); line.m_length = 2000.0f; line.m_direction = Vector3D::Down; line.m_origin = forward_point; line.m_origin.y = 1000.0f; entity_hit = CollisionGrid::Instance->ProjectLine(&query); if(entity_hit != NULL) { // if we hit ground, great! world_avg_normal = *query.m_normal; } else { return; } Stuff::Vector3D local_normal; local_normal.MultiplyByInverse(world_avg_normal, local_to_world); float local_ground_roll = -Arctan(local_normal.x, local_normal.y); float local_ground_pitch = -Arctan(local_normal.z, local_normal.y); rawLocalGroundRoll = local_ground_roll; rawLocalGroundPitch = local_ground_pitch; Scalar max_value = Pi_Over_4 - 0.02f; Clamp(local_ground_roll, -max_value, max_value); Clamp(local_ground_pitch, -max_value, max_value); pitchSmoother.Add(local_ground_pitch); rollSmoother.Add(local_ground_roll); localGroundPitch = pitchSmoother.CalculateAverage(); localGroundRoll = rollSmoother.CalculateAverage(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar Mech::FindMechFootPenetration(void) { PRECOLLISION_LOGIC("Mech::FootPenetration"); Verify(siteLeftFoot != NULL); Verify(siteRightFoot != NULL); Stuff::Point3D left_foot_point(Stuff::Point3D::Identity); Stuff::Point3D right_foot_point(Stuff::Point3D::Identity); left_foot_point = siteLeftFoot->GetLocalToWorld(); right_foot_point = siteRightFoot->GetLocalToWorld(); right_foot_point.y -= lastFramePushUp; left_foot_point.y -= lastFramePushUp; Stuff::Scalar push_up = 0.0f; if (leftFootGround > left_foot_point.y) { push_up = leftFootGround - left_foot_point.y; } if (rightFootGround > right_foot_point.y) { if (rightFootGround - right_foot_point.y > push_up) { push_up = rightFootGround - right_foot_point.y; } } lastFramePushUp = push_up * 1.3f; if (debugPushupOff) { push_up = 0.0f; } return push_up; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::GetUpRequestRequest(void) { if (animStateEngine->IsTransitioning()) { return; } switch (animStateEngine->GetState()) { case MechAnimationStateEngine::FallForwardState: case MechAnimationStateEngine::FallBackwardState: case MechAnimationStateEngine::FallLeftState: case MechAnimationStateEngine::FallRightState: animStateEngine->RequestState(MechAnimationStateEngine::StandState); break; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::ShutDownRequest(bool shutdown) { if (shutdown) { if (GetAI() != 0) { GetAI()->NotifyShutdown(); } vehicleShutDown = true; if(!animStateEngine->IsTransitioning() && animStateEngine->GetState() == MechAnimationStateEngine::StandState) { vehicleShutDown = true; return true; } else if (animStateEngine->GetState() == MechAnimationStateEngine::PowerDownState) { return true; } return true; } else { bool can_start = true; if (m_heatManager) { can_start = !m_heatManager->shutdown; } if(can_start) { // if(m_previousSearchLightState) // { // if (IsPlayerVehicle()) // { // Mission::GetInstance()->SetSearchLightMissionLights(); // } // searchLight->ShowBeam(); // } if (!animStateEngine->IsTransitioning()) { switch (animStateEngine->GetState()) { case MechAnimationStateEngine::GimpStandRightState: case MechAnimationStateEngine::GimpStandLeftState: case MechAnimationStateEngine::PowerDownState: case MechAnimationStateEngine::CrouchState: vehicleShutDown = false; m_alreadyShutDown = false; return true; } } else if (animStateEngine->GetState() != MechAnimationStateEngine::PowerDownState) { return true; } } } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::CrouchRequest(void) { if(!animStateEngine->IsTransitioning() && animStateEngine->GetState() == MechAnimationStateEngine::StandState) { animStateEngine->RequestState(MechAnimationStateEngine::CrouchState, Mech::NoBlend); // MSL 5.03 Cockpit Follow m_eyePointManager->Follow(0.0f); } else if (!animStateEngine->IsTransitioning() && animStateEngine->GetState() == MechAnimationStateEngine::CrouchState) { animStateEngine->RequestState(MechAnimationStateEngine::StandState, Mech::NoBlend); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::IsShutdown() { return vehicleShutDown; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::IsCrouched() { if (!animStateEngine->IsTransitioning() && animStateEngine->GetState() == MechAnimationStateEngine::CrouchState) return true; if (animStateEngine->IsTransitioning() && animStateEngine->GetTransitionState() == MechAnimationStateEngine::CrouchState) return true; return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::JumpRequest(void) { // //-------------------------- // No jumpjets == no jumping //-------------------------- // JumpJet *jump_jet = GetJumpJet(); if (!jump_jet) return false; // //----------------------------------------------- // Make sure the animation states are OK for this //----------------------------------------------- // switch (animStateEngine->GetState()) { // case MechAnimationStateEngine::BackwardState: case MechAnimationStateEngine::FallForwardState: case MechAnimationStateEngine::FallBackwardState: case MechAnimationStateEngine::FallLeftState: case MechAnimationStateEngine::FallRightState: case MechAnimationStateEngine::FallCataclysmicState: case MechAnimationStateEngine::PowerDownState: case MechAnimationStateEngine::PowerDownCataclysmicState: // case MechAnimationStateEngine::CrouchState: return false; } if (executionState->GetState () == Vehicle__ExecutionStateEngine::DroppingState) { return false; } if (animStateEngine->IsTransitioning() && animStateEngine->GetTransitionState() != MechAnimationStateEngine::FlyState) return false; jump_jet->RequestJumpJetsOn(); return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::EnableFallDamping(const Point3D& point) { m_FallDampingLocus = point; m_FallDampingEnabled = true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::DisableFallDamping() { m_FallDampingEnabled = false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::StopJumpRequest(void) { JumpJet *jump_jet = GetJumpJet(); if (jump_jet) { Check_Object(jump_jet); jump_jet->RequestJumpJetsOff(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::CreateJumpJetEffect() { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); if(model->dropJumpEffect != ResourceID::Null) { Resource jet_resource(model->jumpJetEffect); if(jet_resource.DoesResourceExist()) { ClassID class_ID; class_ID = GetClassIDFromDataListID(model->jumpJetEffect); Verify(class_ID != NullClassID); if(leftJumpJetSite) { Check_Object(leftJumpJetSite); Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags, model->jumpJetEffect, LinearMatrix4D::Identity, 0.0f, ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Entity *entity; ReplicatorID trail_id = Connection::Hermit->GetNextReplicatorID(); entity = CreateEntity(&stream, &trail_id, false); Check_Object(entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); leftJumpJetEffect = Cast_Object(Effect *, entity); leftJumpJetEffect->SetFollowEntity(leftJumpJetSite); leftJumpJetEffect->PlaceOnEntity(); leftJumpJetEffect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState); entity->SyncMatrices(true); } if(rightJumpJetSite) { Check_Object(rightJumpJetSite); Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags, model->jumpJetEffect, LinearMatrix4D::Identity, 0.0f, ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Entity *entity; ReplicatorID trail_id = Connection::Hermit->GetNextReplicatorID(); entity = CreateEntity(&stream, &trail_id, false); Check_Object(entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); rightJumpJetEffect = Cast_Object(Effect *, entity); rightJumpJetEffect->SetFollowEntity(rightJumpJetSite); leftJumpJetEffect->PlaceOnEntity(); rightJumpJetEffect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState); entity->SyncMatrices(true); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::LeftFootTriggerHandler(int trigger_value, void *pass_data) { Mech *mech = Cast_Object(Mech *, pass_data); PRECOLLISION_LOGIC("Mech::LeftFootDown"); if (trigger_value) { //SPEW(("jerryeds", "LEFT-DOWN")); mech->LockLeftFoot(); mech->leftFootDown = true; // //--------------------------------------------- //This is where we know that the foot came down //--------------------------------------------- // mech->isLeftFootDown = true; } else { //SPEW(("jerryeds", "LEFT-UP")); mech->ReleaseLeftFoot(); mech->leftFootDown = false; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::RightFootTriggerHandler(int trigger_value, void *pass_data) { Mech *mech = Cast_Object(Mech *, pass_data); PRECOLLISION_LOGIC("Mech::RightFootDown"); if (trigger_value) { //SPEW(("jerryeds", "RIGHT-DOWN")); mech->LockRightFoot(); mech->rightFootDown = true; // //--------------------------------------------- //This is where we know that the foot came down //--------------------------------------------- // mech->isRightFootDown = true; } else { //SPEW(("jerryeds", "RIGHT-UP")); mech->ReleaseRightFoot(); mech->rightFootDown = false; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::CreateFootEffect(const ResourceID& effect_id, Site *foot, const Normal3D& normal) { Check_Object(this); Check_Object(foot); m_LastFootFallTime = (Stuff::Scalar)gos_GetElapsedTime(); if(effect_id != ResourceID::Null) { Resource foot_resource(effect_id); if(foot_resource.DoesResourceExist()) { ClassID class_ID; class_ID = GetClassIDFromDataListID(effect_id); Verify(class_ID != NullClassID); LinearMatrix4D effect_position = LinearMatrix4D::Identity; effect_position.AlignLocalAxisToWorldVector(normal, Y_Axis, X_Axis, Z_Axis); Point3D effect_translation; effect_translation = foot->GetLocalToWorld(); effect_position.BuildTranslation(effect_translation); Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags, effect_id, effect_position, 0.0f, ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Entity *entity; ReplicatorID fall_id = Connection::Hermit->GetNextReplicatorID(); entity = CreateEntity(&stream, &fall_id, false); Check_Object(entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); entity->SyncMatrices(true); UnitVector3D mech_forward; GetLocalToWorld().GetLocalForwardInWorld(&mech_forward); effect_position.AlignLocalAxisToWorldVector(mech_forward, Z_Axis, Y_Axis, -1); MidLevelRenderer::MLRTexture *foot_texture = GetFootTexture(materialHit); if(foot_texture) { if((m_footHitEntity) && (m_footHitEntity->GetClassID() == MWMapClassID)) { Check_Object(CollisionGrid::Instance); CollisionGrid::Instance->MakeFootStep(effect_position, 2.0f, foot_texture); } } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MidLevelRenderer::MLRTexture* Mech::GetFootTexture(int material) { FootStepPlug *foot_plug = m_footSteps.Find(material); if(!foot_plug) foot_plug = m_defaultFootStep; if(foot_plug) return foot_plug->GetFootTexture(); return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::LockLeftFoot(void) { //SPEW(("jerryeds", "LOCK LEFT")); Verify(jointLeftAnkle != NULL); Verify(jointRightAnkle != NULL); if (gimpState == LeftGimpMode) { const GameModel *model = GetGameModel(); leftFootReturnTimer = model->footReturnSeconds; leftFootLerpBackValue = leftFootTurnAccumulation; leftFootState = FootReturn; return; } leftFootState = FootLocked; leftFootTurnAccumulation = 0.0f; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::LockRightFoot(void) { //SPEW(("jerryeds", "LOCK RIGHT")); Verify(jointLeftAnkle != NULL); Verify(jointRightAnkle != NULL); if (gimpState == RightGimpMode) { const GameModel *model = GetGameModel(); rightFootReturnTimer = model->footReturnSeconds; rightFootLerpBackValue = rightFootTurnAccumulation; rightFootState = FootReturn; return; } rightFootState = FootLocked; rightFootTurnAccumulation = 0.0f; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ReleaseLeftFoot(void) { //SPEW(("jerryeds", "REL LEFT")); Verify(jointLeftAnkle != NULL); Verify(jointRightAnkle != NULL); leftFootState = FootReturn; const GameModel *model = GetGameModel(); leftFootReturnTimer = model->footReturnSeconds; leftFootLerpBackValue = leftFootTurnAccumulation; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ReleaseRightFoot(void) { //SPEW(("jerryeds", "REL RIGHT")); Verify(jointLeftAnkle != NULL); Verify(jointRightAnkle != NULL); rightFootState = FootReturn; const GameModel *model = GetGameModel(); rightFootReturnTimer = model->footReturnSeconds; rightFootLerpBackValue = rightFootTurnAccumulation; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::FootLockSimulation(Stuff::Scalar time_slice) { Verify(jointLeftAnkle != NULL); Verify(jointRightAnkle != NULL); PRECOLLISION_LOGIC("Mech::FootLockSim"); const GameModel *model = GetGameModel(); if (rightFootState == FootLocked) { Point3D translation(Point3D::Identity); YawPitchRoll rotation(YawPitchRoll::Identity); rotation.yaw = -rightFootTurnAccumulation; //SPEW(("jerryeds", "TURN RIGHT %f ", -siteRightFootTurnAccumulation)); LinearMatrix4D new_local_to_parent; new_local_to_parent.BuildRotation(rotation); new_local_to_parent.BuildTranslation(translation); jointRightAnkle->SetNewLocalToParent(new_local_to_parent); } else if (rightFootState == FootReturn) { Point3D translation(Point3D::Identity); YawPitchRoll rotation(YawPitchRoll::Identity); rotation.yaw.Lerp(0.0f, -rightFootLerpBackValue, rightFootReturnTimer/model->footReturnSeconds); //SPEW(("jerryeds", "RIGHT %f %f %f %f", 0.0f, -siteRightFootLerpBackValue, siteRightFootReturnTimer/footReturnTime, rotation.yaw.angle)); LinearMatrix4D new_local_to_parent; new_local_to_parent.BuildRotation(rotation); new_local_to_parent.BuildTranslation(translation); jointRightAnkle->SetNewLocalToParent(new_local_to_parent); rightFootReturnTimer -= (time_slice); if (rightFootReturnTimer <= 0.0f) { rightFootState = FootNormal; } } else { //SPEW(("jerryeds", "NORM RIGHT ")); LinearMatrix4D new_local_to_parent(LinearMatrix4D::Identity); jointRightAnkle->SetNewLocalToParent(new_local_to_parent); } if (leftFootState == FootLocked) { Point3D translation(Point3D::Identity); YawPitchRoll rotation(YawPitchRoll::Identity); rotation.yaw = -leftFootTurnAccumulation; //SPEW(("jerryeds", "TURN LEFT %f ", -siteLeftFootTurnAccumulation)); LinearMatrix4D new_local_to_parent; new_local_to_parent.BuildRotation(rotation); new_local_to_parent.BuildTranslation(translation); jointLeftAnkle->SetNewLocalToParent(new_local_to_parent); } else if (leftFootState == FootReturn) { Point3D translation(Point3D::Identity); YawPitchRoll rotation(YawPitchRoll::Identity); rotation.yaw.Lerp(0.0f, -leftFootLerpBackValue, leftFootReturnTimer/model->footReturnSeconds); //SPEW(("jerryeds", "LEFT %f %f %f %f", 0.0f, -siteLeftFootLerpBackValue, siteLeftFootReturnTimer/footReturnTime, rotation.yaw.angle)); LinearMatrix4D new_local_to_parent; new_local_to_parent.BuildRotation(rotation); new_local_to_parent.BuildTranslation(translation); jointLeftAnkle->SetNewLocalToParent(new_local_to_parent); leftFootReturnTimer -= (time_slice); if (leftFootReturnTimer <= 0.0f) { leftFootState = FootNormal; } } else { //SPEW(("jerryeds", "NORM LEFT ")); LinearMatrix4D new_local_to_parent(LinearMatrix4D::Identity); jointLeftAnkle->SetNewLocalToParent(new_local_to_parent); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::FadeDampened() { const GameModel *model = GetGameModel(); Check_Object(model); worldRotDampener.FadeToNewDampen(model->dampenWorldJoint, 1.0f); rootRotDampener.FadeToNewDampen(model->dampenRootJoint, 1.0f); rootTransDampener.FadeToNewDampen(model->dampenTranslationJoint, 1.0f); torsoRotDampener.FadeToNewDampen(model->dampenTorsoJoint, 1.0f); hipRotDampener.FadeToNewDampen(model->dampenHipJoint, 1.0f); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::FadeUndampened() { const GameModel *model = GetGameModel(); Check_Object(model); worldRotDampener.FadeToNewDampen(model->undampenWorldJoint, 1.0f); rootRotDampener.FadeToNewDampen(model->undampenRootJoint, 1.0f); rootTransDampener.FadeToNewDampen(model->undampenTranslationJoint, 1.0f); torsoRotDampener.FadeToNewDampen(model->undampenTorsoJoint, 1.0f); hipRotDampener.FadeToNewDampen(model->undampenHipJoint, 1.0f); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::SetDampened() { const GameModel *model = GetGameModel(); Check_Object(model); worldRotDampener.SetNewDampen(model->dampenWorldJoint); rootRotDampener.SetNewDampen(model->dampenRootJoint); rootTransDampener.SetNewDampen(model->dampenTranslationJoint); torsoRotDampener.SetNewDampen(model->dampenTorsoJoint); hipRotDampener.SetNewDampen(model->dampenHipJoint); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::SetUndampened() { const GameModel *model = GetGameModel(); Check_Object(model); worldRotDampener.SetNewDampen(model->undampenWorldJoint); rootRotDampener.SetNewDampen(model->undampenRootJoint); rootTransDampener.SetNewDampen(model->undampenTranslationJoint); torsoRotDampener.SetNewDampen(model->undampenTorsoJoint); hipRotDampener.SetNewDampen(model->undampenHipJoint); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::DampenMech(Stuff::Scalar time_slice) { PRECOLLISION_LOGIC("Mech::DampenMech"); worldRotDampener.AdvanceTime(time_slice); rootRotDampener.AdvanceTime(time_slice); rootTransDampener.AdvanceTime(time_slice); torsoRotDampener.AdvanceTime(time_slice); hipRotDampener.AdvanceTime(time_slice); if (internalViewPoint) { ElementRenderer::Element *element; Point3D old_position; Point3D new_position; UnitQuaternion joint_old_rot; UnitQuaternion joint_new_rot; LinearMatrix4D new_matrix; element = animationArray[worldJointIndex]->GetElement(); Check_Object(element); joint_old_rot = element->GetNewLocalToParent(); old_position = element->GetNewLocalToParent(); joint_new_rot = worldRotDampener.DampenValue(initialPositions[worldJointIndex].angularPosition, joint_old_rot); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(old_position); new_matrix.BuildRotation(joint_new_rot); animationArray[worldJointIndex]->SetNewLocalToParent(new_matrix); element = animationArray[rootJointIndex]->GetElement(); Check_Object(element); joint_old_rot = element->GetNewLocalToParent(); old_position = element->GetNewLocalToParent(); joint_new_rot = rootRotDampener.DampenValue(initialPositions[rootJointIndex].angularPosition, joint_old_rot); new_position = rootTransDampener.DampenValue(initialPositions[rootJointIndex].linearPosition, old_position); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(new_position); new_matrix.BuildRotation(joint_new_rot); animationArray[rootJointIndex]->SetNewLocalToParent(new_matrix); element = animationArray[hipJointIndex]->GetElement(); Check_Object(element); joint_old_rot = element->GetNewLocalToParent(); old_position = element->GetNewLocalToParent(); joint_new_rot = hipRotDampener.DampenValue(initialPositions[hipJointIndex].angularPosition, joint_old_rot); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(old_position); new_matrix.BuildRotation(joint_new_rot); animationArray[hipJointIndex]->SetNewLocalToParent(new_matrix); element = animationArray[torsoJointIndex]->GetElement(); Check_Object(element); joint_old_rot = element->GetNewLocalToParent(); old_position = element->GetNewLocalToParent(); joint_new_rot = torsoRotDampener.DampenValue(initialPositions[torsoJointIndex].angularPosition, joint_old_rot); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(old_position); new_matrix.BuildRotation(joint_new_rot); animationArray[torsoJointIndex]->SetNewLocalToParent(new_matrix); } ElementRenderer::Element *element; Point3D old_position; UnitQuaternion joint_old_rot; UnitQuaternion joint_new_rot; LinearMatrix4D new_matrix; if (!internalViewPoint) { Torso *torso = GetTorso(); const Torso::GameModel *model = torso->GetGameModel(); Scalar ratio; Verify(model->armRatioAngle > 0); ratio = Abs(torso->yawValue) / model->armRatioAngle; Max_Clamp(ratio, 1.0f); bool torso_stable = true; switch(animStateEngine->GetState()) { case MechAnimationStateEngine::FallForwardState: case MechAnimationStateEngine::FallBackwardState: case MechAnimationStateEngine::FallLeftState: case MechAnimationStateEngine::FallRightState: case MechAnimationStateEngine::CrouchState: case MechAnimationStateEngine::PowerDownState: torso_stable = false; break; } if (animStateEngine->IsTransitioning()) { switch(animStateEngine->GetTransitionState()) { case MechAnimationStateEngine::FallForwardState: case MechAnimationStateEngine::FallBackwardState: case MechAnimationStateEngine::FallLeftState: case MechAnimationStateEngine::FallRightState: case MechAnimationStateEngine::CrouchState: case MechAnimationStateEngine::PowerDownState: torso_stable = false; break; } } if (torso_stable) { torsoBlanderizer.FadeToNewDampen(ratio, 0.1f); } else { torsoBlanderizer.FadeToNewDampen(0.0f, 0.2f); } if (!armsNulled) { armBlanderizer.FadeToNewDampen(ratio, 0.2f); } UnitQuaternion old_rotation; old_position = centerTorso->GetElement()->GetNewLocalToParent(); old_rotation = centerTorso->GetElement()->GetNewLocalToParent(); LinearMatrix4D joint_to_world = centerTorso->GetElement()->GetLocalToWorld(); joint_to_world.AlignLocalAxisToWorldVector(Vector3D::Up,Y_Axis, Z_Axis, -1); LinearMatrix4D world_to_parent; world_to_parent.Invert(centerTorso->GetParentEntity()->GetElement()->GetLocalToWorld()); LinearMatrix4D local_twist; local_twist.Multiply(joint_to_world, world_to_parent); UnitQuaternion stabalized_rotation; stabalized_rotation = local_twist; joint_new_rot = torsoBlanderizer.DampenValue(stabalized_rotation, old_rotation); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(old_position); new_matrix.BuildRotation(joint_new_rot); centerTorso->SetNewLocalToParent(new_matrix); } // nullify the arms armBlanderizer.AdvanceTime(time_slice); torsoBlanderizer.AdvanceTime(time_slice); element = animationArray[leftGunJointIndex]->GetElement(); Check_Object(element); joint_old_rot = element->GetNewLocalToParent(); old_position = element->GetNewLocalToParent(); joint_new_rot = armBlanderizer.DampenValue(initialPositions[leftGunJointIndex].angularPosition, joint_old_rot); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(old_position); new_matrix.BuildRotation(joint_new_rot); animationArray[leftGunJointIndex]->SetNewLocalToParent(new_matrix); element = animationArray[leftArmJointIndex]->GetElement(); Check_Object(element); joint_old_rot = element->GetNewLocalToParent(); old_position = element->GetNewLocalToParent(); joint_new_rot = armBlanderizer.DampenValue(initialPositions[leftArmJointIndex].angularPosition, joint_old_rot); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(old_position); new_matrix.BuildRotation(joint_new_rot); animationArray[leftArmJointIndex]->SetNewLocalToParent(new_matrix); element = animationArray[rightGunJointIndex]->GetElement(); Check_Object(element); joint_old_rot = element->GetNewLocalToParent(); old_position = element->GetNewLocalToParent(); joint_new_rot = armBlanderizer.DampenValue(initialPositions[rightGunJointIndex].angularPosition, joint_old_rot); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(old_position); new_matrix.BuildRotation(joint_new_rot); animationArray[rightGunJointIndex]->SetNewLocalToParent(new_matrix); element = animationArray[rightArmJointIndex]->GetElement(); Check_Object(element); joint_old_rot = element->GetNewLocalToParent(); old_position = element->GetNewLocalToParent(); joint_new_rot = armBlanderizer.DampenValue(initialPositions[rightArmJointIndex].angularPosition, joint_old_rot); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(old_position); new_matrix.BuildRotation(joint_new_rot); animationArray[rightArmJointIndex]->SetNewLocalToParent(new_matrix); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::RunSprings(Stuff::Scalar time_slice) { PRECOLLISION_LOGIC("Mech::RunSprings"); eyeSpringRotation.AdvanceTime(time_slice); LinearMatrix4D new_matrix; new_matrix = LinearMatrix4D::Identity; Point3D position = eyeSpringRotation.GetCurrentPosition(); new_matrix.BuildRotation(YawPitchRoll(position.x*Stuff::Radians_Per_Degree, position.y*Stuff::Radians_Per_Degree, position.z*Stuff::Radians_Per_Degree)); m_eyePointManager->SetSpringOffset(new_matrix); ElementRenderer::Element *element; UnitQuaternion rotation; new_matrix = LinearMatrix4D::Identity; YawPitchRoll ypr_rotation; if (executionState->GetState() != ExecutionStateEngine::FallingMotionState) { element = animationArray[worldJointIndex]->GetElement(); Check_Object(element); position = element->GetNewLocalToParent(); rootHit.AdvanceTime(time_slice); ypr_rotation = rootHit.GetCurrentPosition(); ypr_rotation.roll = -tiltAngle; rotation = ypr_rotation; new_matrix.BuildIdentity(); new_matrix.BuildTranslation(position); new_matrix.BuildRotation(rotation); animationArray[worldJointIndex]->SetNewLocalToParent(new_matrix); } else { rootHit.Reset(); } element = animationArray[torsoAboveJointIndex]->GetElement(); Check_Object(element); position = element->GetNewLocalToParent(); torsoHit.AdvanceTime(time_slice); rotation = torsoHit.GetCurrentPosition(); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(position); new_matrix.BuildRotation(rotation); animationArray[torsoAboveJointIndex]->SetNewLocalToParent(new_matrix); element = animationArray[hipAboveJointIndex]->GetElement(); Check_Object(element); position = element->GetNewLocalToParent(); hipHit.AdvanceTime(time_slice); rotation = hipHit.GetCurrentPosition(); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(position); new_matrix.BuildRotation(rotation); animationArray[hipAboveJointIndex]->SetNewLocalToParent(new_matrix); #if 0 element = animationArray[leftGunAboveJointIndex]->GetElement(); Check_Object(element); position = element->GetNewLocalToParent(); leftGunRecoil.AdvanceTime(time_slice); rotation = leftGunRecoil.GetCurrentPosition(); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(position); new_matrix.BuildRotation(rotation); animationArray[leftGunAboveJointIndex]->SetNewLocalToParent(new_matrix); element = animationArray[leftArmAboveJointIndex]->GetElement(); Check_Object(element); position = element->GetNewLocalToParent(); leftArmRecoil.AdvanceTime(time_slice); rotation = leftArmRecoil.GetCurrentPosition(); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(position); new_matrix.BuildRotation(rotation); animationArray[leftArmAboveJointIndex]->SetNewLocalToParent(new_matrix); element = animationArray[rightGunAboveJointIndex]->GetElement(); Check_Object(element); UnitQuaternion quat; quat = element->GetNewLocalToParent(); rightGunRecoil.AdvanceTime(time_slice); position = rightGunRecoil.GetCurrentPosition(); new_matrix.BuildIdentity(); new_matrix.BuildTranslation(position); new_matrix.BuildRotation(quat); animationArray[rightGunAboveJointIndex]->SetNewLocalToParent(new_matrix); #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::FriendlyFire(const TakeDamageMessage *message) { MWApplication *app = MWApplication::GetInstance(); if (app->serverFlag) { if (app->GetLocalNetParams()->m_friendlyFirePercentage != 100) { Connection *connection = Network::GetInstance()->GetConnection(message->inflictingEntityID.connectionID); if (connection != 0) { Check_Object(connection); Replicator* r = connection->FindReplicator(message->inflictingEntityID); if (r != NULL) { Entity *entity = Cast_Object(Entity*, r); if (entity->GetClassID() == MechClassID) { Mech *inflictor = Cast_Object(Mech*, entity); if (inflictor->teamNumber == teamNumber && teamNumber != MWApplication::No_Team) { //if high explosive then only damage ourselves not our friends. if(message->typeOfDamage == HighExplosiveDamageType) { if(inflictor == this) return false; else return true; } else { return true; } } } } } } } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::TakeDamageMessageHandler(const TakeDamageMessage *message) { Check_Object(this); Check_Object(message); Verify(message->messageID == TakeDamageMessageID); ChainOf effected_parts(NULL); PRECOLLISION_LOGIC("Mech::TakeDamage"); switch(message->typeOfDamage) { case RammingDamageFromAboveType: { if (g_nMR != 2) { if (MWApplication::GetInstance()->networkingFlag == true) { MWMission *mission; Check_Object (MWMission::GetInstance()); mission = Cast_Object (MWMission *,MWMission::GetInstance()); mission->m_BucketManager->NotifyAction (CBucketManager::DFA,message->inflictingEntityID,1); } } DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::HeadArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); damage_object = damageObjects.Find(DamageObject::LeftTorsoArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); damage_object = damageObjects.Find(DamageObject::RightTorsoArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); damage_object = damageObjects.Find(DamageObject::CenterTorsoArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); break; } case RammingDamageFromBelowType: { DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::RightLegArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); damage_object = damageObjects.Find(DamageObject::LeftLegArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); break; } case RammingDamageFromLeftType: { DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::LeftArmArmorZone); if(damage_object) effected_parts.Add(damage_object); else { damage_object = damageObjects.Find(DamageObject::LeftTorsoArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); } damage_object = damageObjects.Find(DamageObject::LeftLegArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); break; } case RammingDamageFromRightType: { DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::RightArmArmorZone); if(damage_object) effected_parts.Add(damage_object); else { damage_object = damageObjects.Find(DamageObject::RightTorsoArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); } damage_object = damageObjects.Find(DamageObject::RightLegArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); break; } case RammingDamageFromAheadType: { DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::CenterTorsoArmorZone); if(damage_object) effected_parts.Add(damage_object); damage_object = damageObjects.Find(DamageObject::RightTorsoArmorZone); if(damage_object) effected_parts.Add(damage_object); damage_object = damageObjects.Find(DamageObject::LeftTorsoArmorZone); if(damage_object) effected_parts.Add(damage_object); break; } case RammingDamageFromBehindType: { DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::CenterRearTorsoArmorZone); if(damage_object) effected_parts.Add(damage_object); break; } // MSL 5.03 Lava case LavaDamageType : { DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::RightLegArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); damage_object = damageObjects.Find(DamageObject::LeftLegArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); break; } // MSL 5.03 Ammo Bay Fire case AmmoFireDamageType : { DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::CenterTorsoArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); damage_object = damageObjects.Find(DamageObject::RightTorsoArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); damage_object = damageObjects.Find(DamageObject::LeftTorsoArmorZone); Check_Object(damage_object); effected_parts.Add(damage_object); break; } } DamageObject *special_zone_1 = damageObjects.Find(DamageObject::SpecialArmorZone1); DamageObject *special_zone_2 = damageObjects.Find(DamageObject::SpecialArmorZone2); DamageObject *rammed_part = NULL; ChainIteratorOf iterator(&effected_parts); if(effected_parts.GetSize() > 0) { Scalar damage_ammount = message->amountOfDamage / effected_parts.GetSize(); TakeDamageMessage *damage_message = (TakeDamageMessage *)message; damage_message->amountOfDamage = damage_ammount; while((rammed_part = iterator.ReadAndNext()) != NULL) { Check_Object(rammed_part); rammed_part->TakeDamage(damage_message, NULL); if(special_zone_1) { Check_Object(special_zone_1); if(special_zone_1->m_specialConnectedToZone == rammed_part->armorZone) { special_zone_1->TakeDamage(damage_message, NULL); } } if(special_zone_2) { Check_Object(special_zone_2); if(special_zone_2->m_specialConnectedToZone == rammed_part->armorZone) { special_zone_2->TakeDamage(damage_message, NULL); } } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ReactToHit(const Entity__TakeDamageMessage *message,Adept::DamageObject *part_hit) { Check_Object(this); Check_Object(message); PRECOLLISION_LOGIC("Mech::ReactToHit"); if (IsDestroyed()) return; if (g_nMR == 2) { BaseClass::ReactToHit(message,part_hit); return; } Replicator* r = NULL; Connection *connection = NULL; if (IsPlayerVehicle ()) { Connection *mechconn = Network::GetInstance ()->GetConnection (GetReplicatorID ().connectionID); if (mechconn == Connection::Local) { connection = Network::GetInstance()->GetConnection(message->inflictingEntityID.connectionID); if (connection != NULL) { r = connection->FindReplicator(message->inflictingEntityID); if (r != 0) { Verify(r->IsDerivedFrom(Entity::DefaultData)); Entity* e = Cast_Object(Entity*,r); MWGUIManager *gui = MWGUIManager::GetInstance (); GUIRadarManager *radar; radar = Cast_Object (GUIRadarManager *,gui->Component (MWGUIManager::HUD_RADAR)); Verify (radar); radar->AddShot (e->objectID); HUDMap *map; map = Cast_Object (HUDMap *,gui->Component (MWGUIManager::HUD_MAP)); map->AddShot (e->objectID); } } } } takenDamageThisFrame = true; lastDamageTaken = (Scalar)gos_GetElapsedTime(); #if !defined(NO_MR) if(MWApplication::GetInstance()->serverFlag && IsPlayerVehicle()) { MWApplication *app = MWApplication::GetInstance(); app->SetMissionReviewTakeDamage(GetReplicatorID().connectionID); } #endif // !defined(NO_MR) BaseClass::ReactToHit(message,part_hit); if (vehicleInterface) { switch (message->weaponID) { case W_ClanERPPC: case W_ERPPC: case W_PPC: vehicleInterface->ReactToEvent (VehicleInterface::INTERNAL_PPC_WASH, message->weaponID); break; } } if(message->amountOfHeat > 0.0f) { Check_Object(m_heatManager); m_heatManager->AddHeat(message->amountOfHeat); } //------------ always play - only on local ---------------- // spin the mech // spin the torso //------------ external play - everyone ---------------- // hit the root joint // hit the torso joint // hit the hip joint //------------ internal play - only on local ---------------- // hit the eye joint const GameModel *model = GetGameModel(); Check_Object(model); Scalar internal_damage_scale = 1.0f; Scalar external_damage_scale = 1.0f; Scalar internal_spin_damage_scale = 1.0f; Scalar spin_force = 0.0f; switch(message->typeOfDamage) { case BeamDamageType: internal_damage_scale = model->internalHitScaleBeamDamage; external_damage_scale = model->externalHitScaleBeamDamage; internal_spin_damage_scale = model->internalSpinHitScaleBeamDamage; spin_force = model->spinForceBeamDamage; break; case MissileDamageType: internal_damage_scale = model->internalHitScaleMissileDamage; external_damage_scale = model->externalHitScaleMissileDamage; internal_spin_damage_scale = model->internalSpinHitScaleMissileDamage; spin_force = model->spinForceMissileDamage; break; case ProjectileDamageType: internal_damage_scale = model->internalHitScaleProjectileDamage; external_damage_scale = model->externalHitScaleProjectileDamage; internal_spin_damage_scale = model->internalSpinHitScaleProjectileDamage; spin_force = model->spinForceProjectileDamage; break; case SplashDamageType: internal_damage_scale = model->internalHitScaleSplashDamage; external_damage_scale = model->externalHitScaleSplashDamage; internal_spin_damage_scale = model->internalSpinHitScaleSplashDamage; spin_force = model->spinForceSplashDamage; break; case HeatDamageType: internal_damage_scale = model->internalHitScaleHeatDamage; external_damage_scale = model->externalHitScaleHeatDamage; internal_spin_damage_scale = model->internalSpinHitScaleHeatDamage; spin_force = model->spinForceHeatDamage; break; case AmmoFireDamageType: internal_damage_scale = model->internalHitScaleProjectileDamage; external_damage_scale = model->externalHitScaleProjectileDamage; internal_spin_damage_scale = model->internalSpinHitScaleProjectileDamage; spin_force = model->spinForceProjectileDamage; break; default: int i = 0; i = 0; break; } MWMission *mission; Check_Object (MWMission::GetInstance()); mission = Cast_Object (MWMission *,MWMission::GetInstance()); if ((MWApplication::GetInstance()->networkingFlag == true) && (IsDestroyed() == false)) { if (part_hit) { switch (part_hit->armorZone) { case Adept::DamageObject::LeftLegArmorZone: case Adept::DamageObject::RightLegArmorZone: mission->m_BucketManager->NotifyAction (CBucketManager::LEG_SHOTS,message->inflictingEntityID,1); break; case Adept::DamageObject::LeftArmArmorZone: case Adept::DamageObject::RightArmArmorZone: mission->m_BucketManager->NotifyAction (CBucketManager::ARM_SHOTS,message->inflictingEntityID,1); break; case Adept::DamageObject::RightTorsoArmorZone: case Adept::DamageObject::LeftTorsoArmorZone: case Adept::DamageObject::CenterTorsoArmorZone: case Adept::DamageObject::CenterRearTorsoArmorZone: mission->m_BucketManager->NotifyAction (CBucketManager::TORSO_SHOTS,message->inflictingEntityID,1); break; case Adept::DamageObject::HeadArmorZone: mission->m_BucketManager->NotifyAction (CBucketManager::HEAD_SHOTS,message->inflictingEntityID,1); break; } } } if (part_hit) { g_RSF.RecScore(CBucketManager::SHOTS_HIT, message->inflictingEntityID, GetReplicatorID(), message->weaponID, part_hit->armorZone, message->typeOfDamage); // jcem switch (part_hit->armorZone) { case Adept::DamageObject::CenterTorsoArmorZone: if (part_hit->GetCurrentDamageLevel() == Adept::DamageObject::Destroyed) { if(vehicleInterface) vehicleInterface->ReactToEvent (VehicleInterface::DAMAGE_CRITICAL); } break; } } Torso *torso = GetTorso(); if(torso) { Check_Object(torso); Point3D hit_location; Connection *connection = Network::GetInstance()->GetConnection(message->inflictingEntityID.connectionID); if (connection == NULL) return; Check_Object(connection); Replicator* rep = connection->FindReplicator(message->inflictingEntityID); if (rep == NULL) return; Entity *inflictor = Cast_Object(Entity *, rep); Point3D inflictor_location; inflictor_location = inflictor->GetLocalToWorld(); hit_location.MultiplyByInverse(inflictor_location, torso->twistJoint->GetLocalToWorld()); UnitVector3D normalized_location; if (Small_Enough(hit_location)) { hit_location.z = 1.0f; hit_location.x = 1.0f; hit_location.y = 1.0f; } normalized_location.Normalize(hit_location); LinearMatrix4D torso_matrix = torso->GetTwistJointMatrix(); Point3D torso_location; torso_location = torso_matrix; //figure out the quadrent if (Abs(normalized_location.z) > Abs(normalized_location.x)) { if (normalized_location.z > 0.0f) { lastHitDirection = ForwardHitDirection; } else { lastHitDirection = RearHitDirection; } } else { if (normalized_location.x > 0.0f) { lastHitDirection = LeftHitDirection; } else { lastHitDirection = RightHitDirection; } } if (IsPlayerVehicle () && vehicleInterface) { MWGUIManager *gui = MWGUIManager::GetInstance (); HUDReticle *ret; ret = Cast_Object (HUDReticle *,gui->Component (MWGUIManager::HUD_RETICLE)); Verify (ret); switch (lastHitDirection) { case ForwardHitDirection: ret->ForwardHit (); break; case RearHitDirection: ret->RearHit (); break; case LeftHitDirection: ret->LeftHit (); break; case RightHitDirection: ret->RightHit (); break; } } //Check to see if we want to play cage damage! if(IsPlayerVehicle() && internalViewPoint) { if(message->amountOfDamage >= model->damageNeededForCageEffect) { switch(lastHitDirection) { case LeftHitDirection: m_playLeftCageEffect = true; break; case RightHitDirection: m_playRightCageEffect = true; break; case ForwardHitDirection: m_playLeftCageEffect = true; m_playRightCageEffect = true; break; } } } if (message->amountOfDamage > model->minimumDamageForInternalHitAnimation) { Scalar scaled_damage = message->amountOfDamage - model->minimumDamageForInternalHitAnimation; // MSL 5.02 headshot // MSL 5.03 Gyro Hit // spin_force = scaled_damage * internal_spin_damage_scale * spin_force; // spin_force = scaled_damage * (internal_spin_damage_scale * ((m_HeadShotTorsoSpinDamageMod + m_AdvancedGyroTorsoSpinDamageMod)/2)) * spin_force; spin_force = scaled_damage * (internal_spin_damage_scale * m_HeadShotTorsoSpinDamageMod) * spin_force; if (vehicleInterface) { vehicleInterface->PlayHitForce (Point3D (normalized_location), spin_force); } Max_Clamp(spin_force, 1.5f); Min_Clamp(spin_force, 0.0f); if(message->hitOffset.y >= torso_location.y) { //spin the torso if (vehicleInterface) { // MSL 5.02 Torso Spin / Mech Spin switch (part_hit->armorZone) { case Adept::DamageObject::LeftArmArmorZone: if (normalized_location.z >= 0.0f) { vehicleInterface->SpinTorsoYaw(spin_force*2); } else { vehicleInterface->SpinTorsoYaw(-spin_force*2); } break; case Adept::DamageObject::LeftTorsoArmorZone: if (normalized_location.z >= 0.0f) { vehicleInterface->SpinTorsoYaw(spin_force); } else { vehicleInterface->SpinTorsoYaw(-spin_force); } break; case Adept::DamageObject::RightArmArmorZone: if (normalized_location.z >= 0.0f) { vehicleInterface->SpinTorsoYaw(-spin_force*2); } else { vehicleInterface->SpinTorsoYaw(spin_force*2); } break; case Adept::DamageObject::RightTorsoArmorZone: if (normalized_location.z >= 0.0f) { vehicleInterface->SpinTorsoYaw(-spin_force); } else { vehicleInterface->SpinTorsoYaw(spin_force); } break; case Adept::DamageObject::CenterRearTorsoArmorZone: vehicleInterface->SpinTorsoPitch(spin_force*0.6f); break; case Adept::DamageObject::CenterTorsoArmorZone: case Adept::DamageObject::HeadArmorZone: if (normalized_location.z >= 0.0f) { vehicleInterface->SpinTorsoPitch(-spin_force*0.6f); } else { vehicleInterface->SpinTorsoPitch(spin_force*0.6f); } break; } } } else { //spin the legs if (vehicleInterface) { switch (part_hit->armorZone) { case Adept::DamageObject::LeftLegArmorZone: if (normalized_location.z >= 0.0f) { vehicleInterface->SpinMechYaw(spin_force); } else { vehicleInterface->SpinMechYaw(-spin_force); } break; case Adept::DamageObject::RightLegArmorZone: if (normalized_location.z >= 0.0f) { vehicleInterface->SpinMechYaw(-spin_force); } else { vehicleInterface->SpinMechYaw(spin_force); } break; } } } } // if (normalized_location.x >= 0.0f) // { // vehicleInterface->SpinTorsoYaw(-spin_force); // } // else // { // vehicleInterface->SpinTorsoYaw(spin_force); // } // if (normalized_location.z >= 0.0f) // { // vehicleInterface->SpinTorsoPitch(-spin_force*0.6f); // } // else // { // vehicleInterface->SpinTorsoPitch(spin_force*0.6f); // } // } // } // if (normalized_location.x >= 0.0f) // { // vehicleInterface->SpinMechYaw(-spin_force); // } // else // { // vehicleInterface->SpinMechYaw(spin_force); // } // } // } // } if (!usingEyeSpring) { // hit the root // hit the torso // hit the hip // MSL 5.05 Armor Mode affect damage fall check float damage_hit_check = message->amountOfDamage; if (message->amountOfModifier) { damage_hit_check *= 2.0f; } // MSL 5.05 // if (message->amountOfDamage > model->minimumDamageForHitAnimation) if (damage_hit_check > model->minimumDamageForHitAnimation) { // //This should be the position local to us where we were hit. //i.e. if y is lower that some value then it hit our lower section //if z is > 0 then it hit us in the back. // // MSL 5.05 // Scalar pitch = (message->amountOfDamage - model->minimumDamageForHitAnimation) / model->rootScaleTakeHit; Scalar pitch = (damage_hit_check - model->minimumDamageForHitAnimation) / model->rootScaleTakeHit; if(normalized_location.z > 0) pitch = -pitch; // MSL 5.05 // Scalar yaw = (message->amountOfDamage - model->minimumDamageForHitAnimation) / model->torsoScaleTakeHit; Scalar yaw = (damage_hit_check - model->minimumDamageForHitAnimation) / model->torsoScaleTakeHit; if(normalized_location.x > 0) yaw = -yaw; if(normalized_location.z > 0) yaw = -yaw; // MSL 5.02 headshot // MSL 5.03 Gyro Hit // pitch *= external_damage_scale; // yaw *= external_damage_scale; // pitch *= (external_damage_scale * ((m_HeadShotTorsoRockDamageMod + m_AdvancedGyroTorsoRockDamageMod)/2)); // yaw *= (external_damage_scale * ((m_HeadShotTorsoRockDamageMod + m_AdvancedGyroTorsoRockDamageMod)/2)); pitch *= (external_damage_scale * m_HeadShotTorsoRockDamageMod); yaw *= (external_damage_scale * m_HeadShotTorsoRockDamageMod); rootHit.SetInitialSpeed(YawPitchRoll(0.0f, pitch, 0.0f)); torsoHit.SetInitialSpeed(YawPitchRoll(yaw, 0.0f, 0.0f)); // MSL 5.05 // pitch = (message->amountOfDamage - model->minimumDamageForHitAnimation) / model->hipScaleTakeHit; pitch = (damage_hit_check - model->minimumDamageForHitAnimation) / model->hipScaleTakeHit; // MSL 5.02 headshot // MSL 5.03 Gyro Hit // pitch *= external_damage_scale; // pitch *= (external_damage_scale * ((m_HeadShotTorsoRockDamageMod + m_AdvancedGyroTorsoRockDamageMod)/2)); pitch *= (external_damage_scale * m_HeadShotTorsoRockDamageMod); hipHit.SetInitialSpeed(YawPitchRoll(0.0f, pitch, 0.0f)); } } else { float damage_hit_check = message->amountOfDamage; if (message->amountOfModifier) { damage_hit_check *= 2.0f; } // MSL 5.05 // if (message->amountOfDamage > model->minimumDamageForInternalHitAnimation) if (damage_hit_check > model->minimumDamageForInternalHitAnimation) { // MSL 5.05 // Scalar scaled_damage = message->amountOfDamage - model->minimumDamageForInternalHitAnimation; Scalar scaled_damage = damage_hit_check - model->minimumDamageForInternalHitAnimation; scaled_damage *= internal_damage_scale; // SPEW(("johnyo", "Time = %2.3f, HitSpring(%2.3f, %2.3f, %2.3f)",(Stuff::Scalar)gos_GetElapsedTime(), // normalized_location.x * scaled_damage, normalized_location.z * scaled_damage, normalized_location.x * scaled_damage)); eyeSpringRotation.HitSpring(Point3D( normalized_location.x * scaled_damage, normalized_location.z * scaled_damage, normalized_location.x * scaled_damage)); } } } if ((m_AI) || (GetReplicatorMode () == ClientMasterMode) || (GetReplicatorMode () == MasterMode)) { if (((Scalar)gos_GetElapsedTime() - m_lastFall) > (MW4AI::UserConstants::Instance ()->Get(MW4AI::UserConstants::min_fall_timer))) { if (message->typeOfDamage == SplashDamageType) { m_FallDamage += (MW4AI::UserConstants::Instance ()->Get(MW4AI::UserConstants::fall_splash_multiplier))*message->typeOfDamage; } else { // MSL 5.05 Armor Mode affect damage fall check if(message->amountOfModifier) { m_FallDamage += ((message->amountOfDamage) * 2); } else { m_FallDamage += (message->amountOfDamage); } } // Fall Factor callculated here (no changes) // falldamage >= (AIConstant * tonnage) to cause a pilot check // MSL 5.02 headshot // MSL 5.03 Gyro Hit // if (m_FallDamage >= (MW4AI::UserConstants::Instance ()->Get(MW4AI::UserConstants::damage_amount)) * GetTonage ()) if ( (m_FallDamage * ((m_HeadShotFallDamageMod + m_AdvancedGyroFallDamageMod)/2)) >= (MW4AI::UserConstants::Instance ()->Get(MW4AI::UserConstants::damage_amount)) * GetTonage ()) // if ( (m_FallDamage * m_HeadShotFallDamageMod) >= (MW4AI::UserConstants::Instance ()->Get(MW4AI::UserConstants::damage_amount)) * GetTonage ()) { bool fall=false; if (!m_AI) // MSL 5.05 Pilot Checking fall = (Stuff::Random::GetFraction () > 0.66f); // 33% chance of failing pilot check else fall = !PilotSkillCheck (m_FallDamage,false); if (fall) { m_lastFall = (Scalar)gos_GetElapsedTime(); m_FallDamage = 0; Check_Object(m_gyro); switch(lastHitDirection) { case ForwardHitDirection: m_gyro->FallDown(FallBackMode, 0.0f); break; case LeftHitDirection: m_gyro->FallDown(FallRightMode, 0.0f); break; case RightHitDirection: m_gyro->FallDown(FallLeftMode, 0.0f); break; case NoHitDirection: case RearHitDirection: m_gyro->FallDown(FallForwardMode, 0.0f); break; } } } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ReactToDamageTaken(Stuff::Scalar damage_taken, const Adept::ReplicatorID& inflicting_entity, int weaponID, int damageType) { if (IsDestroyed() == true) return; MWApplication* app = MWApplication::GetInstance(); if (app->networkingFlag == false) { if (!app->IsCampCOOP()) return; } /* if (g_nMR != 2) { MWApplication* mwapplication = Cast_Object(MWApplication*,MWApplication::GetInstance()); MWMission *mission = Cast_Object (MWMission *,MWMission::GetInstance()); int damage((int)damage_taken); float mod_damage = damage_taken; Stuff::Scalar integer_damage((Stuff::Scalar)damage); m_SavedFractionalDamage += damage_taken - integer_damage; if (m_SavedFractionalDamage > 1) { int added_damage = (int)m_SavedFractionalDamage; m_SavedFractionalDamage -= (Stuff::Scalar)added_damage; damage += added_damage; } */ if (g_nMR != 2) { MWApplication* mwapplication = Cast_Object(MWApplication*,MWApplication::GetInstance()); MWMission *mission = Cast_Object (MWMission *,MWMission::GetInstance()); // int damage((int)damage_taken); float mod_damage_taken = damage_taken; int mod_damage((int)damage_taken); // Stuff::Scalar integer_damage((Stuff::Scalar)damage); // m_SavedFractionalDamage += damage_taken - integer_damage; // if (m_SavedFractionalDamage > 1) // { // int added_damage = (int)m_SavedFractionalDamage; // m_SavedFractionalDamage -= (Stuff::Scalar)added_damage; // damage += added_damage; // } // MSL 5.06 Armor Mode MWApplication *m_App; m_App = MWApplication::GetInstance (); m_ArmorMode = m_App->GetLocalNetParams()->m_armormodeOn; // MSL 5.06 Armor damage mode is bumped up x2 for scoring if (m_ArmorMode) { mod_damage_taken *= 2; mod_damage = (int)mod_damage_taken; } Stuff::Scalar integer_mod_damage((Stuff::Scalar)mod_damage); m_SavedFractionalModDamage += mod_damage_taken - integer_mod_damage; if (m_SavedFractionalModDamage > 1) { int added_mod_damage = (int)m_SavedFractionalModDamage; m_SavedFractionalModDamage -= (Stuff::Scalar)added_mod_damage; // mod_damage += added_mod_damage; mod_damage_taken += added_mod_damage; } mod_damage_taken = (int)mod_damage_taken; ReplicatorID inflicting = inflicting_entity; Connection *connection = Network::GetInstance()->GetConnection(inflicting.connectionID); if (connection != 0) { Check_Object(connection); Replicator* rep = connection->FindReplicator(inflicting); if (rep != 0) { Entity* ent = Cast_Object(Entity*,rep); if (ent->IsDerivedFrom(Mech::DefaultData) == true) { Mech* inflicting_mech = Cast_Object(Mech*,ent); if ((inflicting_mech->IsDestroyed() == true) && (inflicting_mech->m_whoShotMeLast != ReplicatorID::Null)) { inflicting = inflicting_mech->m_whoShotMeLast; } } } } #if 0 // This doesnt allow for hurting self if((inflicting == GetReplicatorID()) || (inflicting == ReplicatorID::Null)) #else // Skip only if the Mech doesnt exist if(inflicting == ReplicatorID::Null) #endif { return; } // mission->m_BucketManager->NotifyAction (CBucketManager::DAMAGE_RECEIVE,GetReplicatorID (),damage_taken); // mission->m_BucketManager->NotifyAction (CBucketManager::DAMAGE_INFLICT,inflicting,damage_taken); mission->m_BucketManager->NotifyAction (CBucketManager::DAMAGE_RECEIVE,GetReplicatorID (),mod_damage_taken); mission->m_BucketManager->NotifyAction (CBucketManager::DAMAGE_INFLICT,inflicting,mod_damage_taken); mission->m_BucketManager->NotifyAction (CBucketManager::SHOTS_HIT,inflicting,1); CBucketManager::Bucket_Type receive_type; CBucketManager::Bucket_Type inflict_type; if (mwapplication->TeamsAreFriendly(inflicting,GetReplicatorID()) == false) { receive_type = CBucketManager::ENEMY_DAMAGE_RECEIVE; inflict_type = CBucketManager::ENEMY_DAMAGE_INFLICT; } else { receive_type = CBucketManager::FRIENDLY_DAMAGE_RECEIVE; inflict_type = CBucketManager::FRIENDLY_DAMAGE_INFLICT; // MSL 5.04 Friendly Fire Betty // If is on team and is not you, then sound betty if((inflicting == GetReplicatorID()) || (inflicting == ReplicatorID::Null)) { // do not sound the betty because we are hurting ourselves } else { if (m_FriendlyFireHit + 1.0f < gos_GetElapsedTime()) { MWApplication* app = Cast_Object(MWApplication*,MWApplication::GetInstance()); app->SendSound(inflicting, VehicleInterface::FRIENDLYFIREPENALTY); } m_FriendlyFireHit = (Stuff::Scalar)gos_GetElapsedTime(); } } // mission->m_BucketManager->NotifyAction(receive_type,GetReplicatorID (),damage_taken); // mission->m_BucketManager->NotifyAction(inflict_type,inflicting,damage_taken,GetReplicatorID()); mission->m_BucketManager->NotifyAction(receive_type,GetReplicatorID (),mod_damage_taken); mission->m_BucketManager->NotifyAction(inflict_type,inflicting,mod_damage_taken,GetReplicatorID()); if (g_nMR == 1) { // extern void g_MRF_MechDamageTaken(ReplicatorID id1, ReplicatorID id2, Stuff::Scalar damage_taken, int weaponID, int damageType); // g_MRF_MechDamageTaken(GetReplicatorID(), inflicting_entity, damage_taken, weaponID, damageType); extern void g_MRF_MechDamageTaken(ReplicatorID id1, ReplicatorID id2, Stuff::Scalar mod_damage_taken, int weaponID, int damageType); g_MRF_MechDamageTaken(GetReplicatorID(), inflicting_entity, mod_damage_taken, weaponID, damageType); } } ReplicatorID inflicting = inflicting_entity; Connection *inflConn = Network::GetInstance()->GetConnection(inflicting.connectionID); if (inflConn != 0) { Check_Object(inflConn); Replicator* repInfl = inflConn->FindReplicator(inflicting); if (repInfl) Mech_CheckDamage(this, repInfl); } // ngLog addition #if !defined(NO_LOG) MWApplication *app = MWApplication::GetInstance(); if(app->serverFlag) {// && (IsPlayerVehicle() || IsLanceMate()) Replicator *r = NULL; int i = inflicting.connectionID; int j = weaponID; int self; if(IsLanceMate()) { self = Maximum_Players + lancemateIndex; } else { self = GetReplicatorID().connectionID; } if(damageType >= RammingDamageFromAboveType || j < 0) { j = 200 + damageType; } // Check if inflictor is a lancemate if(i == Connection::Server->GetID()) { connection = Network::GetInstance()->GetConnection(inflicting.connectionID); if(connection != NULL) { r = connection->FindReplicator(inflicting); if(r && r->GetClassID() == MechClassID) { Mech *inflictor = Cast_Object(Mech *, r); if(inflictor->IsLanceMate()) { i = inflictor->lancemateIndex + Maximum_Players; } } } } // Keep track of only player-to-player damage if(i >= 0) { if(damageType < SplashDamageType || (j >= 200 && j != 200+SplashDamageType)) { if(i >= Maximum_Players) { app->lancemateConnectionData[i-Maximum_Players].wep_hits[j]++; // Just for sanity's sake if(j >= 200) { app->lancemateConnectionData[i-Maximum_Players].wep_atts[j]++; } } else { app->servedConnectionData[i].wep_hits[j]++; // Just for sanity's sake if(j >= 200) { app->servedConnectionData[i].wep_atts[j]++; } } } /* if(i >= Maximum_Players) { app->lancemateConnectionData[i-Maximum_Players].dmg_given[j] += damage; app->lancemateConnectionData[i-Maximum_Players].pdmg_given[self] += damage; app->lancemateConnectionData[i-Maximum_Players].stats_update = 1; } else { app->servedConnectionData[i].dmg_given[j] += damage; app->servedConnectionData[i].pdmg_given[self] += damage; app->servedConnectionData[i].stats_update = 1; } if(self >= Maximum_Players) { app->lancemateConnectionData[self-Maximum_Players].pdmg_rcvd[i] += damage; app->lancemateConnectionData[self-Maximum_Players].stats_update = 1; } else { app->servedConnectionData[self].pdmg_rcvd[i] += damage; app->servedConnectionData[self].stats_update = 1; } // Move this out if we want ALL received damage collected if(self >= Maximum_Players) { app->lancemateConnectionData[self-Maximum_Players].dmg_rcvd[j] += damage; app->lancemateConnectionData[self-Maximum_Players].stats_update = 1; } else { app->servedConnectionData[self].dmg_rcvd[j] += damage; app->servedConnectionData[self].stats_update = 1; } */ if(i >= Maximum_Players) { app->lancemateConnectionData[i-Maximum_Players].dmg_given[j] += mod_damage; app->lancemateConnectionData[i-Maximum_Players].pdmg_given[self] += mod_damage; app->lancemateConnectionData[i-Maximum_Players].stats_update = 1; } else { app->servedConnectionData[i].dmg_given[j] += mod_damage; app->servedConnectionData[i].pdmg_given[self] += mod_damage; app->servedConnectionData[i].stats_update = 1; } if(self >= Maximum_Players) { app->lancemateConnectionData[self-Maximum_Players].pdmg_rcvd[i] += mod_damage; app->lancemateConnectionData[self-Maximum_Players].stats_update = 1; } else { app->servedConnectionData[self].pdmg_rcvd[i] += mod_damage; app->servedConnectionData[self].stats_update = 1; } // Move this out if we want ALL received damage collected if(self >= Maximum_Players) { app->lancemateConnectionData[self-Maximum_Players].dmg_rcvd[j] += mod_damage; app->lancemateConnectionData[self-Maximum_Players].stats_update = 1; } else { app->servedConnectionData[self].dmg_rcvd[j] += mod_damage; app->servedConnectionData[self].stats_update = 1; } } } #endif // !defined(NO_LOG) } // MSL 5.02 headshot //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::HeadShotInternal( ) //**^ { if ((dwDamageFlags & MECH_HEAD_SHOT_RCVD) == MECH_HEAD_SHOT_RCVD) { return; } //set all flags for internal head damage dwDamageFlags |= MECH_HEAD_SHOT_FX; m_HeadShotFallDamageMod = MECH_HEAD_SHOT_FALL_MOD; //*= ? //fall-down chance increased... (see modifier at top of file : MECH_HEAD_SHOT_FALL_MOD) -- handled by setting the flags m_HeadShotTorsoRockDamageMod = MECH_HEAD_SHOT_TORSO_ROCK_MOD; m_HeadShotTorsoSpinDamageMod = MECH_HEAD_SHOT_TORSO_SPIN_MOD; if (vehicleInterface) //if we are the player getting hit --possibly need to add IsPlayerVehicle() check if needed { vehicleInterface->hudZoomDestroyed = true; //Zoom is destroyed vehicleInterface->HideZoom(); //zoom -- if in zoom, take out of zoom //play sound "component destroyed" vehicleInterface->ReactToEvent (VehicleInterface::COMPONENT_DESTROYED); } //BAP/ECM destroyed -- iterate over the mech's subsystems and remove BAP/ECM if they exist if ((DoesHaveECM()) /*|| (DoesHaveBeagle())*/) { for (int j=0;(j<10); j++) { MWInternalDamageObject* damage_obj = internalDamageObjects.Find (j); if (damage_obj != NULL) { ChainIteratorOf subsys_iter(&damage_obj->subsystemChain); Subsystem* subsys; while ((subsys = subsys_iter.ReadAndNext()) != NULL) { if(subsys->IsDerivedFrom(ECM::DefaultData) /*|| subsys->IsDerivedFrom(Beagle::DefaultData)*/) { subsys->TakeCriticalHit(); damage_obj->destroyedSubsystemChain.Add(subsys); // So we can later completely remove the subsystem //** damage_obj->subsystemChain.Remove(subsys); subsys_iter.First(); } } } } } } // MSL 5.03 Gyro Hit //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::GyroHitInternal( ) //**^ { // MSL 5.05 Advance Mode MWApplication *m_App; m_App = MWApplication::GetInstance (); m_AdvanceMode = m_App->GetLocalNetParams()->m_advancemodeOn; if (!m_AdvanceMode) { return; } if ((dwGyroDamageFlags & MECH_GYRO_HIT_RCVD) == MECH_GYRO_HIT_RCVD) { return; } if (Stuff::Random::GetFraction () > 0.0625f) // 1 in 16 chance of gyro hit { return; } //set all flags for internal damage dwGyroDamageFlags |= MECH_GYRO_HIT_RCVD; m_AdvancedGyroFallDamageMod = ADVANCED_GYRO_FALL_MOD; //*= ? //fall-down chance increased... (see modifier at top of file : MECH_HEAD_SHOT_FALL_MOD) -- handled by setting the flags //Advanced Gyro destroyed -- iterate over the mech's subsystems and remove if exist if (DoesHaveAdvancedGyro()) { for (int j=0;(j<10); j++) { MWInternalDamageObject* damage_obj = internalDamageObjects.Find (j); if (damage_obj != NULL) { ChainIteratorOf subsys_iter(&damage_obj->subsystemChain); Subsystem* subsys; while ((subsys = subsys_iter.ReadAndNext()) != NULL) { if(subsys->IsDerivedFrom(AdvancedGyro::DefaultData)) { subsys->TakeCriticalHit(); damage_obj->destroyedSubsystemChain.Add(subsys); // So we can later completely remove the subsystem //** damage_obj->subsystemChain.Remove(subsys); subsys_iter.First(); } } } } } if (vehicleInterface) //if we are the player getting hit --possibly need to add IsPlayerVehicle() check if needed { //play sound "component destroyed" vehicleInterface->ReactToEvent (VehicleInterface::COMPDESTROYED); //reset cameramode vehicleInterface->SetCameraMode(0); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::HandleSalvage (void) { MWGame *game; if (GetAlignment() != Entity::Enemy) return; game = MWGame::GetInstance (); if (!game) return; Scalar value = MW4AI::UserConstants::Instance ()->Get(MW4AI::UserConstants::chance_salvage); Scalar chance = Stuff::Random::GetFraction (); if (chance > (value*0.01f)) return; m_markedForSalvage = true; game->AddMechInstance(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // pick a random sound for the crowd noises in a coliseum game static void ColiseumDeathNoise() { if (VehicleInterface::GetInstance()) { // if a coliseum game MWMission *mission = Cast_Object (MWMission *,MWMission::GetInstance()); Check_Object (mission); int theType = mission->GetMissionType(); if (theType == MWMission::MISSIONTYPE_COLISEUM) { // VehicleInterface::GetInstance()->ReactToEvent(VehicleInterface::COLISEUM_HORN); // 80% of the time if (Stuff::Random::GetLessThan(100) < 80) { // play a random crowd noise const numSounds = 9; VehicleInterface::SOUND_TRIGGER soundList[numSounds] = { VehicleInterface::COLISEUM_CHEER1, VehicleInterface::COLISEUM_CHEER2, VehicleInterface::COLISEUM_AHH, VehicleInterface::COLISEUM_BOO2, VehicleInterface::COLISEUM_CHEER9, VehicleInterface::COLISEUM_CHEER8, VehicleInterface::COLISEUM_CHEER5, VehicleInterface::COLISEUM_AWW, VehicleInterface::COLISEUM_ROAR, }; VehicleInterface::GetInstance()->ReactToEvent( soundList[Stuff::Random::GetLessThan(numSounds)] ); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ReactToDestruction(int damage_mode, int damage_type) { PRECOLLISION_LOGIC("Mech::ReactToDestruction"); if (damage_mode != InternalDamageObject::HeadShotDamageMode) damage_mode = InternalDamageObject::DestructionDamageMode; switch(damage_mode) { case InternalDamageObject::HeadShotDamageMode: { if(!IsDestroyed()) { // coliseum games have a reaction to 'Mech death ColiseumDeathNoise(); if (vehicleInterface) { vehicleInterface->ReactToEvent (VehicleInterface::NO_HEAT); vehicleInterface->ReactToEvent (VehicleInterface::COOLANT_FLUSH_STOP); vehicleInterface->ReactToEvent (VehicleInterface::NARC_SIGNAL_STOP); vehicleInterface->ReactToEvent (VehicleInterface::STEP_WATER_STOP); } // ngLog addition #if !defined(NO_LOG) if(MWApplication::GetInstance()->serverFlag && MWApplication::GetInstance()->networkingFlag) { int self = 0; int enemy = 0; int t_delta = 0; Replicator *r = NULL; Connection *conn = Network::GetInstance()->GetConnection(m_whoShotMeLast.connectionID); if(IsLanceMate()) { self = lancemateIndex + Maximum_Players; } else { self = GetReplicatorID().connectionID; } enemy = m_whoShotMeLast.connectionID; if(conn) { r = conn->FindReplicator(m_whoShotMeLast); if(r && r->GetClassID() == MechClassID) { Mech *inflictor = Cast_Object(Mech *, r); if(inflictor->IsLanceMate()) { enemy = inflictor->lancemateIndex + Maximum_Players; } if(enemy > 0) { t_delta = (int)GetTonage() - (int)inflictor->GetTonage(); if(t_delta < 0) { t_delta = 0; } } } } if(m_weaponShotMeLast == -50) { MW4log_generic(MW4P_KILL, va("Player_Suicide\t%d", self)); } else { int i = m_weaponShotMeLast; if(i < 0) { i = 200 + damage_type; } MW4log_generic(MW4P_KILL, va("Player_Kill\t%d\t%d\t%d\t%d", enemy, self, i, t_delta)); } } #endif // !defined(NO_LOG) Check_Object(Mission::GetInstance()); // MSL 5.02 headshot Mission::GetInstance()->ScoringReactToMechDeath(m_whoShotMeLast, GetReplicatorID(), damage_mode); //need to somehow learn if the death was caused by a headshot, cuz right now its in destructiondamagemode and that will just not do Flag::RemoveAllFlagsFrom(*this); // MSL 5.02 headshot // also remove our head-shot flags dwDamageFlags = 0; //reset the flags -- heal the mech after destruction //** reset the flags -- still need to do this if (vehicleInterface) { vehicleInterface->hudZoomDestroyed = false; } if (vehicleInterface != NULL) { vehicleInterface->SetDeathMode(); } // MSL 5.03 Gyro Hit dwGyroDamageFlags = 0; // MSL 5.05 Server/Client issues with ejeect effect for headshot if (!ejectEffect.GetCurrent ()) { const GameModel *model = GetGameModel(); Check_Object(model); Adept::Site *ejectSite = FindSite("site_eject2"); Check_Object(ejectSite); Effect *effect; effect = CreateEffect(model->ejectEffectResource, ejectSite, true); if(effect) ejectEffect.Add(effect); } // if we are standing #if 0 if(!animStateEngine->IsTransitioning() && animStateEngine->GetState() == MechAnimationStateEngine::StandState) { vehicleShutDown = true; } // if we are powering down else if (animStateEngine->IsTransitioning() && animStateEngine->GetTransitionState() == MechAnimationStateEngine::PowerDownState) { vehicleShutDown = true; } // if we are powered down else if (!animStateEngine->IsTransitioning() && animStateEngine->GetState() == MechAnimationStateEngine::PowerDownState) { vehicleShutDown = true; } else #endif { // fall the opposite way you got hit Check_Object(m_gyro); switch(lastHitDirection) { case ForwardHitDirection: m_gyro->FallDown(FallBackMode, 0.0f); break; case LeftHitDirection: m_gyro->FallDown(FallRightMode, 0.0f); break; case RightHitDirection: m_gyro->FallDown(FallLeftMode, 0.0f); break; case NoHitDirection: case RearHitDirection: m_gyro->FallDown(FallForwardMode, 0.0f); break; } } Check_Object(executionState); if(m_AI) { Check_Object(m_AI); m_AI->Die(); } const GameModel *model = GetGameModel(); Check_Object(model); CreateEffect(model->destroyedEffectResource, FindChildMover("joint_centertorsofront"), true); // SetDestroyedFlag(damage_mode); DestroyChildren(damage_mode); if (damage_type == SplashDamageType) diedBySplash = true; else // MSL 5.04 Disable Splash for Ejecting (Disabled) // if (!m_needSelfDestruct) DealSplashDamage(); break; } } case InternalDamageObject::DestructionDamageMode: { if(!IsDestroyed()) { // coliseum games have a reaction to 'Mech death ColiseumDeathNoise(); if (vehicleInterface) { vehicleInterface->ReactToEvent (VehicleInterface::NO_HEAT); vehicleInterface->ReactToEvent (VehicleInterface::COOLANT_FLUSH_STOP); vehicleInterface->ReactToEvent (VehicleInterface::NARC_SIGNAL_STOP); vehicleInterface->ReactToEvent (VehicleInterface::STEP_WATER_STOP); } // ngLog addition #if !defined(NO_LOG) if(MWApplication::GetInstance()->serverFlag && MWApplication::GetInstance()->networkingFlag) { int self = 0; int enemy = 0; int t_delta = 0; Replicator *r = NULL; Connection *conn = Network::GetInstance()->GetConnection(m_whoShotMeLast.connectionID); if(IsLanceMate()) { self = lancemateIndex + Maximum_Players; } else { self = GetReplicatorID().connectionID; } enemy = m_whoShotMeLast.connectionID; if(conn) { r = conn->FindReplicator(m_whoShotMeLast); if(r && r->GetClassID() == MechClassID) { Mech *inflictor = Cast_Object(Mech *, r); if(inflictor->IsLanceMate()) { enemy = inflictor->lancemateIndex + Maximum_Players; } if(enemy > 0) { t_delta = (int)GetTonage() - (int)inflictor->GetTonage(); if(t_delta < 0) { t_delta = 0; } } } } if(m_weaponShotMeLast == -50) { MW4log_generic(MW4P_KILL, va("Player_Suicide\t%d", self)); } else { int i = m_weaponShotMeLast; if(i < 0) { i = 200 + damage_type; } MW4log_generic(MW4P_KILL, va("Player_Kill\t%d\t%d\t%d\t%d", enemy, self, i, t_delta)); } } #endif // !defined(NO_LOG) Check_Object(Mission::GetInstance()); // MSL 5.02 headshot Mission::GetInstance()->ScoringReactToMechDeath(m_whoShotMeLast, GetReplicatorID(), damage_mode); //need to somehow learn if the death was caused by a headshot, cuz right now its in destructiondamagemode and that will just not do Flag::RemoveAllFlagsFrom(*this); // MSL 5.02 headshot // also remove our head-shot flags dwDamageFlags = 0; //reset the flags -- heal the mech after destruction //** reset the flags -- still need to do this if (vehicleInterface) { vehicleInterface->hudZoomDestroyed = false; } if (vehicleInterface != NULL) { vehicleInterface->SetDeathMode(); } // MSL 5.03 Gyro Hit dwGyroDamageFlags = 0; //MSL 5.00 // - Added eject Effect Code here if (!ejectEffect.GetCurrent ()) { const GameModel *model = GetGameModel(); Check_Object(model); Adept::Site *ejectSite = FindSite("site_eject2"); Check_Object(ejectSite); Effect *effect; effect = CreateEffect(model->ejectEffectResource, ejectSite, true); if(effect) ejectEffect.Add(effect); } // if we are standing #if 0 if(!animStateEngine->IsTransitioning() && animStateEngine->GetState() == MechAnimationStateEngine::StandState) { vehicleShutDown = true; } // if we are powering down else if (animStateEngine->IsTransitioning() && animStateEngine->GetTransitionState() == MechAnimationStateEngine::PowerDownState) { vehicleShutDown = true; } // if we are powered down else if (!animStateEngine->IsTransitioning() && animStateEngine->GetState() == MechAnimationStateEngine::PowerDownState) { vehicleShutDown = true; } else #endif { // fall the opposite way you got hit Check_Object(m_gyro); switch(lastHitDirection) { case ForwardHitDirection: m_gyro->FallDown(FallBackMode, 0.0f); break; case LeftHitDirection: m_gyro->FallDown(FallRightMode, 0.0f); break; case RightHitDirection: m_gyro->FallDown(FallLeftMode, 0.0f); break; case NoHitDirection: case RearHitDirection: m_gyro->FallDown(FallForwardMode, 0.0f); break; } } Check_Object(executionState); if(m_AI) { Check_Object(m_AI); m_AI->Die(); } const GameModel *model = GetGameModel(); Check_Object(model); CreateEffect(model->destroyedEffectResource, FindChildMover("joint_centertorsofront"), true); // SetDestroyedFlag(damage_mode); DestroyChildren(damage_mode); if (damage_type == SplashDamageType) diedBySplash = true; else // MSL 5.04 Disable Splash for Ejecting (Disabled) // if (!m_needSelfDestruct) DealSplashDamage(); break; } } } SetDead (); if (vehicleInterface) { vehicleInterface->EndEngineIdle (); } // m_previousSearchLightState = GetSearchLight()->isLightOn; // if (IsPlayerVehicle()) // { // Mission::GetInstance()->ResetMissionLights(); // } // GetSearchLight()->HideBeam(); Entity::ReactToDestruction(damage_mode, damage_type); #ifdef LAB_ONLY if (MW4AI::Statistics::Enabled() == true) { MW4AI::Statistics::NotifyDestroyed(objectID); } #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Fix Bug #3100 // Damage Object are now refreshed when a mech sustains internal damage void Mech::ReactToInternalDamage(int damage_mode) { Check_Object(this); for (int i = 0; i < 11; i++) { DamageObject *damage_object = damageObjects.Find(i); if(damage_object) { damage_object->RefreshCurrentDamageLevel(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // MSL 5.05 Torso void Mech::DestroyLeftArmSpecialZones() { Check_Object(this); if(IsDestroyed()) return; MWInternalDamageObject *special = internalDamageObjects.Find(InternalDamageObject::SpecialZone1); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::LeftArmZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone1); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } special = internalDamageObjects.Find(InternalDamageObject::SpecialZone2); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::LeftArmZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone2); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // MSL 5.05 Torso void Mech::DestroyRightArmSpecialZones() { Check_Object(this); if(IsDestroyed()) return; MWInternalDamageObject *special = internalDamageObjects.Find(InternalDamageObject::SpecialZone1); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::RightArmZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone1); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } special = internalDamageObjects.Find(InternalDamageObject::SpecialZone2); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::RightArmZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone2); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // MSL 5.05 Torso void Mech::DestroyLeftTorsoSpecialZones() { Check_Object(this); if(IsDestroyed()) return; MWInternalDamageObject *special = internalDamageObjects.Find(InternalDamageObject::SpecialZone1); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::LeftTorsoZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone1); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } special = internalDamageObjects.Find(InternalDamageObject::SpecialZone2); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::LeftTorsoZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone2); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // MSL 5.05 Torso void Mech::DestroyRightTorsoSpecialZones() { Check_Object(this); if(IsDestroyed()) return; MWInternalDamageObject *special = internalDamageObjects.Find(InternalDamageObject::SpecialZone1); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::RightTorsoZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone1); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } special = internalDamageObjects.Find(InternalDamageObject::SpecialZone2); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::RightTorsoZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone2); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // MSL 5.05 Torso void Mech::DestroyLeftLegSpecialZones() { Check_Object(this); if(IsDestroyed()) return; MWInternalDamageObject *special = internalDamageObjects.Find(InternalDamageObject::SpecialZone1); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::LeftLegZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone1); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } special = internalDamageObjects.Find(InternalDamageObject::SpecialZone2); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::LeftLegZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone2); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // MSL 5.05 Torso void Mech::DestroyRightLegSpecialZones() { Check_Object(this); if(IsDestroyed()) return; MWInternalDamageObject *special = internalDamageObjects.Find(InternalDamageObject::SpecialZone1); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::RightLegZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone1); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } special = internalDamageObjects.Find(InternalDamageObject::SpecialZone2); if (special) { Check_Object(special); if(special->m_specialConnectedTo == InternalDamageObject::RightLegZone) { special->SetCurrentDamageLevel(2); special->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::SpecialArmorZone2); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // MSL 5.05 Torso void Mech::DestroyLeftArm() { Check_Object(this); if(IsDestroyed()) return; MWInternalDamageObject *arm = internalDamageObjects.Find(InternalDamageObject::LeftArmZone); if (arm) { Check_Object(arm); arm->SetCurrentDamageLevel(2); arm->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::LeftArmArmorZone); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // MSL 5.05 Torso void Mech::DestroyRightArm() { Check_Object(this); if(IsDestroyed()) return; MWInternalDamageObject *arm = internalDamageObjects.Find(InternalDamageObject::RightArmZone); if (arm) { Check_Object(arm); arm->SetCurrentDamageLevel(2); arm->KillAllContainedSubsystems(); DamageObject *damage_object; damage_object = damageObjects.Find(DamageObject::RightArmArmorZone); Check_Object(damage_object); damage_object->SetCurrentDamageLevel(2); } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::SetRightGimp() { Check_Object(this); if(IsDestroyed()) return; if (gimpState == LeftGimpMode) { ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); return; } if (gimpState == NotGimpedMode) { gimpState = RightGimpMode; if(vehicleInterface) { MWEntityManager::GetInstance()->m_uPostDeathFlags |= 1; //vehicleInterface->ReactToEvent(VehicleInterface::CRITICAL_HIT_GIMP); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::SetLeftGimp() { Check_Object(this); if(IsDestroyed()) return; if (gimpState == RightGimpMode) { ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0); return; } if (gimpState == NotGimpedMode) { gimpState = LeftGimpMode; if(vehicleInterface) { MWEntityManager::GetInstance()->m_uPostDeathFlags |= 1; //vehicleInterface->ReactToEvent(VehicleInterface::CRITICAL_HIT_GIMP); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::SetSearchLightIntensity(Scalar intensity) { Check_Object(this); if(searchLightEffect) { Check_Object(searchLightEffect); searchLightEffect->lightIntensity = intensity; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::SetCooling(int new_int) { Check_Object(this); Check_Object(m_heatManager); m_heatManager->SetCooling(new_int); } Scalar Mech::AverageDamage (void) const // 0-1 for average damage of mech center torso has a higher weight { int i; Scalar toret; Scalar count; count = 0; toret = 0; for (i=0;i<11;i++) { if (damageArray[i] != -1) { if (i==6) { toret += (damageArray[i]*5.0f); count+=5.0f; } else { toret += damageArray[i]; count++; } } } if (count) { toret /= count; } return toret; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::InitializeDamageArray() { Check_Object(this); memset(damageArray, -1, sizeof(int) * 11); for(int i=0; i<11; i++) { DamageObject *damage_object = damageObjects.Find(i); if(damage_object) { damageArray[i] = damage_object->damageLevel; damage_object->SetDamageArrayEntry(&damageArray[i]); } else { damageArray[i] = -1; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar Mech::FriendlyFireDamageMultiplier() const { NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); return (Scalar)params->m_friendlyFirePercentage * 0.01f; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::DestroySearchLight() { Check_Object(this); if(jointSearchLight) { Check_Object(jointSearchLight); jointSearchLight->GetElement()->SetAlwaysCullMode(); if(jointSearchLight->GetSolidVolume() && !jointSearchLight->GetSolidVolume()->IsDestroyed()) jointSearchLight->GetSolidVolume()->Destroy(); if(jointSearchLight->GetHierarchicalVolume() && !jointSearchLight->GetHierarchicalVolume()->IsDestroyed()) jointSearchLight->GetHierarchicalVolume()->Destroy(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_ArmActivation() { //arms activate - deactive if (!armsNulled) { armsNulled = true; armBlanderizer.FadeToNewDampen(1.0f, 0.2f); } else { armsNulled = false; armBlanderizer.FadeToNewDampen(0.0f, 1.0f); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::Test_GetArmActivation() const { return (armsNulled); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_PushupOff() { debugPushupOff = !debugPushupOff; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::Test_GetPushupOff() const { return (!debugPushupOff); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_LeftArmRecoil() { // leftArmRecoil.SetInitialSpeed(YawPitchRoll(0.0f, 8.0f, 0.0f)); // leftGunRecoil.SetInitialSpeed(YawPitchRoll(0.0f, -8.0f, 0.0f)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_RightGunRecoil() { // rightGunRecoil.SetInitialSpeed(Point3D(0.0f, 0.0f, -8.0f)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_Hit1() { //eyeSpringPosition.HitSpring(Point3D(10.0f,20.0f,0.0f)); vehicleInterface->SpinTorsoYaw(0.5f); vehicleInterface->SpinTorsoPitch(0.5f); if (usingEyeSpring) { eyeSpringRotation.HitSpring( Point3D(30.0f, 0.0f, -20.0f) ); } else { rootHit.SetInitialSpeed(YawPitchRoll(0.0f, 0.5f, 0.0f)); torsoHit.SetInitialSpeed(YawPitchRoll(0.5f, 0.0f, 0.0f)); hipHit.SetInitialSpeed(YawPitchRoll(0.0f, 0.5f, 0.0f)); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_Hit2() { vehicleInterface->SpinTorsoYaw(-0.5f); vehicleInterface->SpinTorsoPitch(-0.5f); //eyeSpringPosition.HitSpring(Point3D(-10.0f,10.0f,0.0f)); if (usingEyeSpring) { eyeSpringRotation.HitSpring( Point3D(-30.0f, 0.0f, 20.0f) ); } else { rootHit.SetInitialSpeed(YawPitchRoll(0.0f, 1.0f, 0.0f)); torsoHit.SetInitialSpeed(YawPitchRoll(1.0f, 0.0f, 0.0f)); hipHit.SetInitialSpeed(YawPitchRoll(0.0f, 1.0f, 0.0f)); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_Hit3() { vehicleInterface->SpinMechYaw(-0.5f); if (usingEyeSpring) { eyeSpringRotation.HitSpring( Point3D( 0.0f, 30.0f,10.0f) ); } else { rootHit.SetInitialSpeed(YawPitchRoll(0.0f, -0.5f, 0.0f)); torsoHit.SetInitialSpeed(YawPitchRoll(-0.5f, 0.0f, 0.0f)); hipHit.SetInitialSpeed(YawPitchRoll(0.0f, -0.5f, 0.0f)); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_Hit4() { vehicleInterface->SpinMechYaw(0.5f); if (usingEyeSpring) { eyeSpringRotation.HitSpring( Point3D( 0.0f, -30.0f,-10.0f) ); } else { rootHit.SetInitialSpeed(YawPitchRoll(0.0f, -1.0f, 0.0f)); torsoHit.SetInitialSpeed(YawPitchRoll(-1.0f, 0.0f, 0.0f)); hipHit.SetInitialSpeed(YawPitchRoll(0.0f, -1.0f, 0.0f)); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_Reset() { lastSpeedMPS = 0.0f; speedDemand = 0.0f; speedDemandMPS = 0.0f; currentSpeedMPS = 0.0f; currentSpeedKPH = 0.0; speedDemandKPH = 0.0; gimpState = NotGimpedMode; queFallState = NoFallMode; fallDirection = NoFallMode; animStateEngine->Reset(); animStateEngine->RequestState(MechAnimationStateEngine::StandState, Mech::NoBlend); executionState->RequestState(ExecutionStateEngine::DrivingMotionState); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_LeftGimp() { if (gimpState == LeftGimpMode) { gimpState = NotGimpedMode; } else { gimpState = LeftGimpMode; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::Test_GetLeftGimp() const { return (gimpState == LeftGimpMode); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_RightGimp() { if (gimpState == RightGimpMode) { gimpState = NotGimpedMode; } else { gimpState = RightGimpMode; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::Test_GetRightGimp() const { return (gimpState == RightGimpMode); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_FallForward() { Check_Object(m_gyro); m_gyro->FallDown(FallForwardMode, 0.0f); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_FallBackward() { Check_Object(m_gyro); m_gyro->FallDown(FallBackMode, 0.0f); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_FallRight() { Check_Object(m_gyro); m_gyro->FallDown(FallRightMode, 0.0f); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::Test_FallLeft() { Check_Object(m_gyro); m_gyro->FallDown(FallLeftMode, 0.0f); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::BecomeInteresting(bool render_me) { Check_Object(this); LOAD_LOGIC("Become Interesting::Mech"); BaseClass::BecomeInteresting(render_me); // // Need to destroy these each time we cross a zone // Check_Pointer(Mission::GetInstance()); // if(!Mission::GetInstance()->DoesAllowRunningLights()) // { // DestroyRunningLight(); // } if(!Mission::GetInstance()->DoesAllowSearchLights()) { DestroySearchLight(); if(GetSearchLight()) { // if (IsPlayerVehicle()) // { // Mission::GetInstance()->ResetMissionLights(); // } GetSearchLight()->HideBeam(); GetSearchLight()->DestroySubsystem(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::SeedHeatManager() { Check_Object(this); Subsystem *subsystem; Stuff::ChainIteratorOf iterator(&subsystemsInVehicle); while((subsystem = iterator.ReadAndNext()) != NULL) { Check_Object(subsystem); subsystem->ConnectHeatManager(m_heatManager); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ReactToShutDown() { Check_Object(this); // //-------------------------------- //Check to see if we are in an MFB //-------------------------------- // MFB::IsWithinMFB(this); #if 0 Check_Object(MFB::Instance); if(IsWithin(MFB::Instance, 2.0f)) { MFB::Instance->StartNewMech(this); } } #endif m_alreadyShutDown = true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar Mech::GetLastFootFallTime() const { return (m_LastFootFallTime); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::GetLineOfSight(Stuff::LinearMatrix4D& line_of_sight) { if ((eyeSitePointer.GetCurrent() != 0) && (GetTorso() != 0) && (GetTorso()->twistJoint != 0)) { line_of_sight = GetTorso()->twistJoint->GetLocalToWorld(); Stuff::Point3D middle(line_of_sight); middle += (Stuff::Point3D)eyeSitePointer.GetCurrent()->GetLocalToWorld(); middle *= 0.5f; line_of_sight.BuildTranslation(middle); } else { Vehicle::GetLineOfSight(line_of_sight); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Mech::GetMaxFlagsCarried() const { if (m_MaxFlagsCarried == -1) { MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance()); return (mwmission->GetMaxFlagsCarried()); } return (m_MaxFlagsCarried); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ToggleLightAmpLoad() { Check_Object(this); if(DoesHaveLightAmp()) { m_doesHaveLightAmp = false; SubtractTonage(1.0f); } else { if(DoesHaveAvailableTonage(1.0f)) { m_doesHaveLightAmp = true; AddTonage(1.0f); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect* Mech::CreateCageDamageEffect(Site *site) { Check_Object(this); Effect *effect = NULL; const GameModel *model = GetGameModel(); Check_Object(model); if((site) && (model->m_cageDamageEffect != ResourceID::Null)) { effect = CreateEffect(model->m_cageDamageEffect, site, true); } return effect; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::GetNetworkPosition(Stuff::Point3D ¤t_position, Stuff::YawPitchRoll ¤t_rotation) { current_position = GetLocalToWorld(); current_rotation = GetLocalToWorld(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::GetDeadReckonedNetworkPosition(Stuff::Point3D ¤t_position, Stuff::YawPitchRoll ¤t_rotation) { current_position = correctionPosition; current_rotation = correctionAngle; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::ClearNetworkPosition() { if (deadReckonCurve != NULL) { delete deadReckonCurve; deadReckonCurve = NULL; } deadReckonScale = 0.0f; deadReckonCurveTime = 0.0f; correctingPosition = false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::SetNetworkCorretionPosition(Stuff::Point3D new_position, Stuff::YawPitchRoll new_rotation, Point3D velocity, Scalar vel_request, Scalar latency, Scalar rate) { // p1 is our position // p2 is our position over the latency // p3 is the network position plus the latency // p4 is the network position plus the latency and the lerp time correctionAngle = new_rotation; correctionPosition = new_position; if (deadReckonCurve != NULL) { delete deadReckonCurve; deadReckonCurve = NULL; } deadReckonScale = 0.0f; deadReckonCurveTime = 0.0f; correctingPosition = false; Point3D p1,p2,p3,p4; p1 = GetLocalToWorld(); Point3D distance_point; distance_point.Subtract(new_position,p1); Scalar distance = 0.0f; if (!Small_Enough(distance_point)) { distance = distance_point.GetLengthSquared(); } if (distance < 1600.0f) { startRotation = GetLocalToWorld(); endRotation = new_rotation; startRotation.pitch = 0.0f; startRotation.roll = 0.0f; endRotation.pitch = 0.0f; endRotation.roll = 0.0f; //if (Close_Enough(p1, p2)) //{ // SPEWALWAYS(("jerryeds", "NO MOVE-------------")); // // we are in the same place, no correction needed. // return; //} //Point3D local_vel(0.0f, 0.0f, currentSpeedMPS * (latency+rate)); //p2.Multiply(local_vel, GetLocalToWorld()); LinearMatrix4D network_update_position; network_update_position.BuildTranslation(new_position); network_update_position.BuildRotation(new_rotation); //Point3D net_update_vel(0.0f, 0.0f, speed * latency); //Point3D net_update_vel(0.0f, 0.0f, speed); //p3.Multiply(net_update_vel, network_update_position); //SPEWALWAYS(("jerryeds", "LATENCY : %f", latency)); const GameModel *model = GetGameModel(); Check_Object(model); if (velocity.z >= 0.0f) { if (vel_request > currentSpeedMPS) { velocity.z += (model->acceleration * (latency+rate)); Max_Clamp(velocity.z, vel_request); } else if (vel_request < currentSpeedMPS) { velocity.z -= (model->decceleration * (latency+rate)); Min_Clamp(velocity.z, vel_request); } } else { if (vel_request < currentSpeedMPS) { velocity.z -= (model->acceleration * model->reverseAccelerationMultiplier * (latency+rate)); Min_Clamp(velocity.z, vel_request); } else if (vel_request > currentSpeedMPS) { velocity.z += (model->decceleration * model->reverseDeccelerationMultiplier * (latency+rate)); Max_Clamp(velocity.z, vel_request); } } Point3D net_update_vel; net_update_vel.Multiply(velocity, (latency+rate)); p4.Multiply(net_update_vel, network_update_position); //p4 = new_position; p2.Lerp(p1,p4, 0.33f); p3.Lerp(p1,p4, 0.66f); deadReckonCurve = new CubicCurve(p1, p2, p3, p4); deadReckonCurveTime = 0.0f; deadReckonScale = (latency+rate); Min_Clamp(deadReckonScale,0.001f); //SPEWALWAYS(("jerryeds", "SET CURVE-------------")); //SPEWALWAYS(("jerryeds", "length : %f", deadReckonScale)); //SPEWALWAYS(("jerryeds", "p1 : < %f : %f : %f > ", p1.x, p1.y, p1.z)); //SPEWALWAYS(("jerryeds", "p2 : < %f : %f : %f > ", p2.x, p2.y, p2.z)); //SPEWALWAYS(("jerryeds", "p3 : < %f : %f : %f > ", p3.x, p3.y, p3.z)); //SPEWALWAYS(("jerryeds", "p4 : < %f : %f : %f > ", p4.x, p4.y, p4.z)); //SPEWALWAYS(("jerryeds", "nt : < %f : %f : %f > \n", new_position.x, new_position.y, new_position.z)); } else { //SPEWALWAYS(("jerryeds", "SET SNAP-------------")); correctingPosition = true; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Mech::GetNetworkAdjustment(Stuff::Scalar time_slice, Point3D &adjustment_position, Stuff::YawPitchRoll &adjustment_rotation) { adjustment_position = Point3D::Identity; adjustment_rotation = YawPitchRoll::Identity; if (correctingPosition) { correctingPosition = false; adjustment_position = correctionPosition; adjustment_rotation = correctionAngle; //SPEWALWAYS(("jerryeds", "SNAP : %f : < %f : %f : %f > \n", deadReckonCurveTime, adjustment_position.x, adjustment_position.y, adjustment_position.z)); return true; } if (deadReckonCurve == NULL) { //SPEWALWAYS(("jerryeds", "NO RECKON")); return false; } //SPEWALWAYS(("jerryeds", "CURVE RECKON")); deadReckonCurveTime += (time_slice / deadReckonScale); Max_Clamp(deadReckonCurveTime, 1.0f); Vector3D velocity; deadReckonCurve->Evaluate(deadReckonCurveTime, &adjustment_position, &velocity); //if (Close_Enough(second_position, adjustment_position)) //{ //twice as fast... Scalar rot_time = deadReckonCurveTime * 2.0f; Max_Clamp(rot_time, 1.0f); adjustment_rotation.yaw.Lerp(startRotation.yaw, endRotation.yaw, rot_time); //} //else //{ // YawPitchRange ypr; // ypr = velocity; // adjustment_rotation.yaw = ypr.yaw; //} //SPEWALWAYS(("jerryeds", "v : < %f : %f : %f >", velocity.x, velocity.y, velocity.z)); //SPEWALWAYS(("jerryeds", "r : < %f : %f : %f >", ypr.yaw.angle*Degrees_Per_Radian, ypr.pitch.angle*Degrees_Per_Radian, ypr.range)); //SPEWALWAYS(("jerryeds", "r : < %f : %f : %f >", adjustment_rotation.yaw.angle*Degrees_Per_Radian, adjustment_rotation.pitch.angle*Degrees_Per_Radian, adjustment_rotation.roll*Degrees_Per_Radian)); if (deadReckonCurveTime == 1.0f) { ClearNetworkPosition(); } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Mech::GetHeatEffic() { Check_Object(this); Check_Object(m_heatManager); // MSL 5.04 0.08 changed to 0.04 due to Head Sink Eff change // Scalar heat_dissapation = (m_numHeatSinks + 10) * 0.08f; // Scalar heat_dissapation = (m_numHeatSinks + 10) * 0.04f; Scalar heat_dissapation = ((m_numHeatSinks + 10) * 2) * 0.04f; Scalar heat_add = 0.0f; Subsystem *subsystem; ChainIteratorOf iterator(&subsystemsInVehicle); while((subsystem = iterator.ReadAndNext()) != NULL) { if(subsystem->IsDerivedFrom(Weapon::DefaultData)) { Weapon *weapon = Cast_Object(Weapon *, subsystem); Check_Object(weapon); const Weapon::GameModel *weapon_model = weapon->GetGameModel(); Check_Object(weapon_model); // heat_add += (weapon_model->heat * 2) * (10 / (weapon_model->reloadTime + 1.0f)); heat_add += (weapon_model->heat * 2); } } heat_dissapation *= 20; // MSL 5.04 Modified Heat Effic bar int value = 100; if(!Small_Enough(heat_add)) value = (int)(((100.0 + (((heat_dissapation - heat_add)/heat_add) * 100.0)) / 240.0) * 100.0); // int value = 100; // if(!Small_Enough(heat_add)) // value = (int)(100 + (((heat_dissapation - heat_add)/heat_add) * 100)); // int value = (int)(heat_dissapation - heat_add); // value *= 10; Clamp(value, 0, 100); return value; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Mech::GetAlignment() const { if ((m_AI != 0) && (isPlayerVehicle == false)) { int align(0); if (m_AI->GetLeaderAlignment(align) == true) { return (align); } } if (teamNumber < MWApplication::No_Team) { if (MWApplication::GetInstance()->teams[teamNumber] != 0) { Team* team = MWApplication::GetInstance()->teams[teamNumber]->GetCurrent(); if (team != 0) { return (team->GetTeamAlignment() + Team1); } } return (teamNumber + Team1); } if (MWApplication::GetAlignmentSchema() == MWApplication::MP_NON_TEAMPLAY) { if ((m_AI != 0) && (isPlayerVehicle == false)) { return (objectID + 100); } return (teamNumber + MWApplication::No_Team + replicatorID.connectionID); } return (MWObject::GetAlignment()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Mech::NullArms() { if (armsNulled == false) { armsNulled = true; armBlanderizer.FadeToNewDampen(1.0f, 0.2f); armReNullTime = (Stuff::Scalar)gos_GetElapsedTime() + arm_re_null_time; } else { if (armReNullTime != 0) { armReNullTime = (Stuff::Scalar)gos_GetElapsedTime() + arm_re_null_time; } } } void Mech::NotifyFired(const Adept::Entity::CollisionQuery& query) { NullArms(); Vehicle::NotifyFired(query); } void MechWarrior4::MechSecurityCheckStop() { _asm { nop } } int Mech::GetJumpJetState() const { JumpJet *jump_jet = ((Mech*)this)->GetJumpJet(); if (jump_jet) { if (jump_jet->IsDestroyed()) return 0; // destroyed else return +1; // not destroyed & attached } else { return -1; // no jump jet } } void Mech::ClearInterestings() { for(int i = 0; i < sizeof(m_Others) / sizeof(m_Others[0]); i++) { m_Others[i].Clear(); } } Mech::CMechOther::CMechOther() : m_fTimeStart(0.0f), m_fTimeLast(0.0f) { } void Mech::CMechOther::Clear() { while (GetCurrent() != NULL) { Remove(); } m_fTimeStart = m_fTimeLast = GetMissionTime(); } Stuff::Scalar Mech::CMechOther::GetMissionTime() { if (MWMission::GetInstance()) { // to check the case of MechLab...Mech::CommonCreation...Clear MWMission* mission = Cast_Object(MWMission*, MWMission::GetInstance()); if (mission) { return mission->GetMissionTime(); } } return 0.0f; } Mech* Mech::CMechOther::Get(Stuff::Scalar& fTime/* = *(Stuff::Scalar*)NULL*/) { if (&fTime) { fTime = GetMissionTime() - m_fTimeLast; } return GetCurrent(); } void Mech::CMechOther::Set(Entity* pMech) { Check_Object(pMech); if (pMech->IsDerivedFrom(Mech::DefaultData)) { m_fTimeLast = GetMissionTime(); Mech* pOld = GetCurrent(); if (pOld != pMech) { while (GetCurrent() != NULL) { Remove(); } Add(Cast_Pointer(Mech*, pMech)); m_fTimeStart = m_fTimeLast; } } else { //Clear(); } } void Mech_CheckDamage(Replicator* pVictim, Replicator* pInflictor, bool bDeath/* = false*/) { if (pVictim && pInflictor) { if (pVictim->IsDerivedFrom(Mech::DefaultData) && pInflictor->IsDerivedFrom(Mech::DefaultData)) { Mech* pMechVictim = Cast_Pointer(Mech*, pVictim); Mech* pMechInflictor = Cast_Pointer(Mech*, pInflictor); if (bDeath) { pMechVictim->m_Others[1].Set(pMechInflictor); } else if (pMechVictim != pMechInflictor) { if (!pMechVictim->IsDestroyed() && !pMechInflictor->IsDestroyed()) { pMechInflictor->m_Others[0].Set(pMechVictim); } } } } } void Mech::RepairForCOOP() { RepairGimp(); RepairWeapons(); ReloadAmmoAll(); ReloadCoolant(); } void Mech::RepairGimp() { if (IsGimped()) { SetNoGimp(); animStateEngine->Reset(); animStateEngine->RequestState(MechAnimationStateEngine::PowerDownState, Mech::NoBlend); //We also must make the legs have atleast one internal structure point MWInternalDamageObject *leg = internalDamageObjects.Find(InternalDamageObject::LeftLegZone); Check_Object(leg); Min_Clamp(leg->currentInternalDamage, 1.0f); leg = internalDamageObjects.Find(InternalDamageObject::RightLegZone); Check_Object(leg); Min_Clamp(leg->currentInternalDamage, 1.0f); } } void Mech::RepairWeapons() { #if 0 ChainIteratorOf weaponIterator(&weaponChain); Weapon *weapon; while((weapon = weaponIterator.ReadAndNext()) != NULL) { Check_Object(weapon); if(weapon->IsDestroyed()) { } } #endif } void Mech::ReloadAmmoAll() { ChainIteratorOf weaponIterator(&weaponChain); Weapon *weapon; while((weapon = weaponIterator.ReadAndNext()) != NULL) { Check_Object(weapon); if(weapon->HasFiredAmmo()) { weapon->Reload(); } } } void Mech::ReloadCoolant() { if(m_heatManager->GetCoolant() < m_heatManager->GetMaxCoolant()) { m_heatManager->AddCoolant(m_heatManager->GetMaxCoolant()); } }