Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

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(&currentLeftFootFall, 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(&currentRightFootFall, 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 &current_position, Stuff::YawPitchRoll &current_rotation)
{
current_position = GetLocalToWorld();
current_rotation = GetLocalToWorld();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void Mech::GetDeadReckonedNetworkPosition(Stuff::Point3D &current_position, Stuff::YawPitchRoll &current_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());
}
}