Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
10234 lines
279 KiB
C++
10234 lines
279 KiB
C++
//===========================================================================//
|
|
// 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 <Adept\Map.hpp>
|
|
#include <Adept\CollisionGrid.hpp>
|
|
#include <Adept\GUITextManager.hpp>
|
|
#include <Adept\GUITextObject.hpp>
|
|
#include <Adept\EntityManager.hpp>
|
|
#include <Adept\DamageObject.hpp>
|
|
#include <Adept\Effect.hpp>
|
|
#include <Adept\NameTable.hpp>
|
|
#include <Adept\Mission.hpp>
|
|
#include <Adept\CollisionVolume.hpp>
|
|
#include <Adept\Site.hpp>
|
|
#include <Adept\LightManager.hpp>
|
|
#include <Adept\AudioCommand.hpp>
|
|
#include <Adept\AudioRenderer.hpp>
|
|
#include "mwguimanager.hpp"
|
|
#include "hudmap.hpp"
|
|
// MSL 5.02
|
|
#include "guilightamp.hpp"
|
|
#include "guiradarmanager.hpp"
|
|
#include "hudtarg.hpp"
|
|
|
|
#include "ai_userconstants.hpp"
|
|
|
|
#include <ElementRenderer\Element.hpp>
|
|
|
|
#include <MLR\MLRTexturePool.hpp>
|
|
#include <MLR\MLRTexture.hpp>
|
|
#include <MLR\MLRShadowLight.hpp>
|
|
|
|
#include <Compost\CompostHeaders.hpp>
|
|
|
|
// 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<MWMover*> 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<Subsystem*> 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<CollisionData> *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; i<collisions->GetLength(); ++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<Mech*, Time> 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; j<oldCollisions->GetLength(); ++j)
|
|
{
|
|
if ((*oldCollisions)[j].m_otherVolume == data->m_otherVolume)
|
|
break;
|
|
}
|
|
if (j<oldCollisions->GetLength())
|
|
{
|
|
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<DamageObject *> 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<DamageObject *> 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<Subsystem*> 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<Subsystem*> 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<Subsystem*> 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<Subsystem*> 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<Weapon*> weaponIterator(&weaponChain);
|
|
|
|
Weapon *weapon;
|
|
while((weapon = weaponIterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(weapon);
|
|
if(weapon->IsDestroyed())
|
|
{
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void Mech::ReloadAmmoAll()
|
|
{
|
|
ChainIteratorOf<Weapon*> 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());
|
|
}
|
|
}
|
|
|