//===========================================================================//
// File:	Mech.hpp												
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 09/09/98  JSE  Inital base class based off of Shadowrun/Adept             //
// 09/22/98  BDD  Inital base Mech class based off Vehicle					 //
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "MW4.hpp"
#include "Vehicle.hpp"
#include "MechAnimationState.hpp"
#include "Blanderizer.hpp"
#include "DeceleratorOf.hpp"
#include "SpringOf.hpp"
#include "MechLabHeaders.h"
#include <Stuff\Spline.hpp>

// MSL 5.02 headshot
#define MECH_HEAD_SHOT_RCVD        0x00000001 //used to increase the chance of a fall down just for this one hit
#define MECH_BAP_DESTROYED         0x00000002
#define MECH_ECM_DESTROYED         0x00000004
#define MECH_PERMANENT_OVERHEAT_FX 0x00000008
#define MECH_RETICULE_WASH         0x00000010
#define MECH_HEAD_SHOT_FX          0x0000001F //add flags to HUD too for overheat/reticule distortion //**^ 
// MSL 5.03 Gyro Hit
#define MECH_GYRO_HIT_RCVD         0x00000001

namespace Adept
{
	class Effect;
	class Site;
}

namespace MidLevelRenderer
{
	class MLRTexture;
	class MLRTexturePool;
};

namespace MechWarrior4
{

	class Mech;
	class Subsystem;
	class JumpJet;
	class ECM;
	class Gyro;
	class EyePointManager;
	class Armor;
	class MechTablePlug;


	void MechSecurityCheckStart();
	void MechSecurityCheckStop();	



	//##########################################################################
	//#####################    Foot Step Plug  #################################
	//##########################################################################

	class FootStepPlug:
		public Stuff::Plug
	{
	public:
		FootStepPlug(int material, MidLevelRenderer::MLRTexture *foot_texture, bool is_default = false) : Plug(Plug::DefaultData)
		{
			m_material = material;
			m_footTexture = foot_texture;
			m_isDefault = is_default;
		}
		~FootStepPlug() {}

		void
			SaveToStream(Stuff::MemoryStream *stream);

		MidLevelRenderer::MLRTexture*
			GetFootTexture()
				{Check_Object(this); return m_footTexture;}
	private:
		MidLevelRenderer::MLRTexture
			*m_footTexture;
		int
			m_material;
		bool
			m_isDefault;

	};

	//##########################################################################
	//#####################    Mech::ModelResource   ###########################
	//##########################################################################

	class Mech__GameModel:
		public Vehicle::GameModel
	{
	public:
		typedef Vehicle::GameModel BaseClass;
		
		Stuff::Radian
			tiltSpeed;

		Stuff::Radian
			tiltDegree;

		Stuff::Scalar
			footReturnSeconds;

		Stuff::Scalar
			percentageOfTurnToStartTilt;
		
		Stuff::Scalar
			percentageOfSpeedToStartTilt;

		Stuff::Scalar
			fallAdjustmentSeconds;

		Stuff::Scalar
			getUpAdjustmentSeconds;

		Stuff::Scalar
			fallAdjustmentDelaySeconds;

		Stuff::Scalar
			getUpAdjustmentDelaySeconds;

		Stuff::Scalar
			dampenWorldJoint,
			dampenRootJoint,
			dampenTorsoJoint,
			dampenHipJoint,
			dampenTranslationJoint;
		
		Stuff::Scalar
			undampenWorldJoint,
			undampenRootJoint,
			undampenTorsoJoint,
			undampenHipJoint,
			undampenTranslationJoint;


		Stuff::Scalar
			scaleInternalTiltDegree,
			
			torsoScaleTakeHit,
			hipScaleTakeHit,
			rootScaleTakeHit,

			minimumDamageForHitAnimation,
			minimumDamageForInternalHitAnimation,
			
			torsoHitSpringMotionLimit,
			torsoHitSpringDeceleration,
			torsoHitSpringReturnSpeed,
			torsoHitSpringSpeed,

			hipHitSpringMotionLimit,
			hipHitSpringDeceleration,
			hipHitSpringReturnSpeed,
			hipHitSpringSpeed,

			rootHitSpringMotionLimit,
			rootHitSpringDeceleration,
			rootHitSpringReturnSpeed,
			rootHitSpringSpeed,


			externalHitScaleBeamDamage,
			externalHitScaleMissileDamage,
			externalHitScaleProjectileDamage,
			externalHitScaleSplashDamage,
			externalHitScaleHeatDamage,

			internalHitScaleBeamDamage,
			internalHitScaleMissileDamage,
			internalHitScaleProjectileDamage,
			internalHitScaleSplashDamage,
			internalHitScaleHeatDamage,
			
			internalSpinHitScaleBeamDamage,
			internalSpinHitScaleMissileDamage,
			internalSpinHitScaleProjectileDamage,
			internalSpinHitScaleSplashDamage,
			internalSpinHitScaleHeatDamage,
			

			spinForceBeamDamage,
			spinForceMissileDamage,
			spinForceProjectileDamage,
			spinForceSplashDamage,
			spinForceHeatDamage;


		Stuff::Point3D
			eyeSpringMotionLimit,
			eyeSpringConstant,
			eyeSpringDrag,
			eyeSpringStopThreshold;



		Adept::ResourceID
			jumpJetEffect;
		Adept::ResourceID dropJumpEffect;

		Adept::ResourceID
			initialJumpJetEffect;
		Adept::ResourceID
			searchLightResource;

		Adept::ResourceID cradle;
		Adept::ResourceID cradleDeathEffect;

		char
			leftJumpJetSiteName[MaxStringLength],
			rightJumpJetSiteName[MaxStringLength];

		Adept::ResourceID
			footFallEffectsTable;

		Stuff::Scalar
			maxHeat;
		Adept::ResourceID
			heatManagerResource;
		Adept::ResourceID
			footStepsResource;
		int
			mechID;
		int
			techType;
		int
			m_craterID;

		bool
			m_canLoadJumpJets,
			m_canLoadECM,
			m_canLoadBeagle,
			m_canLoadLightAmp,
			m_canLoadAMS,
			m_canLoadLAMS;
		Stuff::Scalar
			m_jumpJetTonnage;

		Adept::ResourceID
			m_cageDamageEffect;
		Stuff::Scalar
			damageNeededForCageEffect;

		Adept::ResourceID
			m_mechRamEffect;
// MSL 5.03 Glass
		Adept::ResourceID
			m_mechGlassRamEffect;

		Adept::ResourceID
			m_wakeEffectResource;

// MSL 5.02 SubSystems
		Stuff::Scalar
			m_advancedGyroTonnage;

		static bool
			ReadAndVerify(
				Mech__GameModel *model,
				ModelAttributeEntry *attribute_entry,
				const char *data,
				char **error,
				int error_buffer = 128
			);

		static void
			ConstructGameModel(Script *script);

		enum {
			TiltSpeedAttributeID = Vehicle__GameModel::NextAttributeID,
			TiltDegreeAttributeID,
	
			ScaleInternalTiltDegreeAttributeID,

			FootReturnSecondsAttributeID,
			FallAdjustmentSecondsAttributeID,
			GetUpAdjustmentSecondsAttributeID,
			FallAdjustmentDelaySecondsAttributeID,
			GetUpAdjustmentDelaySecondsAttributeID,
			PercentageOfTurnToStartTiltAttributeID,
			PercentageOfSpeedToStartTiltAttributeID,
			
			DampenWorldJointAttributeID,
			DampenRootJointAttributeID,
			DampenTorsoJointAttributeID,
			DampenHipJointAttributeID,
			DampenTranslationJointAttributeID,

			UndampenWorldJointAttributeID,
			UndampenRootJointAttributeID,
			UndampenTorsoJointAttributeID,
			UndampenHipJointAttributeID,
			UndampenTranslationJointAttributeID,
						
			TorsoScaleTakeHitAttributeID,
			HipScaleTakeHitAttributeID,
			RootScaleTakeHitAttributeID,
			
			MinimumDamageForHitAnimationAttributeID,
			MinimumDamageForInternalHitAnimationAttributeID,
			
			TorsoHitSpringMotionLimitAttributeID,
			TorsoHitSpringDecelerationAttributeID,
			TorsoHitSpringReturnSpeedAttributeID,
			TorsoHitSpringSpeedAttributeID,

			HipHitSpringMotionLimitAttributeID,
			HipHitSpringDecelerationAttributeID,
			HipHitSpringReturnSpeedAttributeID,
			HipHitSpringSpeedAttributeID,

			RootHitSpringMotionLimitAttributeID,
			RootHitSpringDecelerationAttributeID,
			RootHitSpringReturnSpeedAttributeID,
			RootHitSpringSpeedAttributeID,
			
			ExternalHitScaleBeamDamageAttributeID,
			ExternalHitScaleMissileDamageAttributeID,
			ExternalHitScaleProjectileDamageAttributeID,
			ExternalHitScaleSplashDamageAttributeID,
			ExternalHitScaleHeatDamageAttributeID,

			InternalHitScaleBeamDamageAttributeID,
			InternalHitScaleMissileDamageAttributeID,
			InternalHitScaleProjectileDamageAttributeID,
			InternalHitScaleSplashDamageAttributeID,
			InternalHitScaleHeatDamageAttributeID,
			
			InternalSpinHitScaleBeamDamageAttributeID,
			InternalSpinHitScaleMissileDamageAttributeID,
			InternalSpinHitScaleProjectileDamageAttributeID,
			InternalSpinHitScaleSplashDamageAttributeID,
			InternalSpinHitScaleHeatDamageAttributeID,

			SpinForceBeamDamageAttributeID,
			SpinForceMissileDamageAttributeID,
			SpinForceProjectileDamageAttributeID,
			SpinForceSplashDamageAttributeID,
			SpinForceHeatDamageAttributeID,


			EyeSpringMotionLimitAttributeID,
			EyeSpringConstantAttributeID,
			EyeSpringDragAttributeID,
			EyeSpringStopThresholdAttributeID,

			JumpJetEffectAttributeID,
			LeftJumpJetSiteNameAttributeID,
			RightJumpJetSiteNameAttributeID,
			SearchLightResourceAttributeID,
			InitialJumpJetEffectAttributeID,

			MaxHeatAttributeID,
			MechIDAttributeID,

			CanLoadJumpJetsAttributeID,
			CanLoadECMAttributeID,
			CanLoadBeagleAttributeID,
			CanLoadLightAmpAttributeID,
			CanLoadAMSAttributeID,
			CanLoadLAMSAttributeID,

			JumpJetTonnageAttributeID,
			TechTypeAttributeID,

			CageDamageEffectAttributeID,
			DamageNeededForCageEffectAttributeID,
			MechRamEffectAttributeID,
// MSL 5.03 Glass
			MechGlassRamEffectAttributeID,
			WakeEffectResourceAttributeID,

			CradleAttributeID,
			CradleDeathEffectAttributeID,
			DropJumpEffectAttributeID,
// MSL 5.02 SubSystems
//			CanLoadEnhancedOpticsAttributeID,
			CanLoadIFF_JammerAttributeID,
			CanLoadAdvancedGyroAttributeID,
			AdvancedGyroTonnageAttributeID,

			NextAttributeID
		};

// MSL 5.02 SubSystems
//		bool
//			m_canLoadEnhancedOptics;
		bool
			m_canLoadIFF_Jammer;
		bool
			m_canLoadAdvancedGyro;

	};

	//##########################################################################
	//###############    Mech::ExecutionStateEngine    ######################
	//##########################################################################

	class Mech__ExecutionStateEngine:
		public Vehicle::ExecutionStateEngine
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		typedef Vehicle::ExecutionStateEngine BaseClass;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		typedef Mech__ExecutionStateEngine*
			(*Factory)(
				Mech *entity,
				FactoryRequest *request
			);

		static Mech__ExecutionStateEngine*
			Make(
				Mech *mover,
				FactoryRequest *request
			);

	protected:
		Mech__ExecutionStateEngine(
			ClassData *class_data,
			Mech *mover,
			FactoryRequest *request
		);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data support
	//
	public:
		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// State stuff
	//
	public:
		int
			RequestState(
				int new_state,
				void* data = NULL
			);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Support
	//
	public:
		void
		  	TestInstance() const;
	};

	//##########################################################################
	//##################    Mech::CreateMessage    #############################
	//##########################################################################

	class Mech__CreateMessage:
		public Vehicle::CreateMessage
	{
	public:
		typedef Vehicle::CreateMessage BaseClass;

		//These numbers are for nothing more than the shell
		int
			m_powerBar,
			m_speedBar,
			m_heatBar,
			m_armorBar;
		int
			m_mechID;

		Stuff::Scalar
			currentHeat;
		Stuff::Scalar
			currentCoolant;
		Stuff::Scalar
			maxCoolant;

		bool
			m_doesHaveLightAmp;

		Mech__CreateMessage(
			size_t length,
			int priority,
			int message_flags,
			Stuff::RegisteredClass::ClassID class_id,
			int replicator_flags,
			const ResourceID& instance_id,
			const Stuff::LinearMatrix4D &creation_matrix,
			Stuff::Scalar age,
			int execution_state,
			int name_id,
			int entity_alignment,
			const Stuff::Motion3D &initial_velocity,
			const Stuff::Motion3D &initial_acceleration,
			const char *entity_name,
			const ResourceID& armature_id,
			const Adept::ResourceID& site_id,
			const ResourceID& subsystem_id,
			const ResourceID& damage_id,
			char skin_prefix,
			int team_prefix,
			int pilot_prefix,
			int name_index,
			bool has_instance_name,
			Stuff::Scalar current_heat,
			Stuff::Scalar current_coolant,
			Stuff::Scalar max_coolant,
			bool light_amp
		):
			Vehicle__CreateMessage(
				length,
				priority,
				message_flags,
				class_id,
				replicator_flags,
				instance_id,
				creation_matrix,
				age,
				execution_state,
				name_id,
				entity_alignment,
				initial_velocity,
				initial_acceleration,
				entity_name,
				armature_id,
				site_id,
				subsystem_id,
				damage_id,
				skin_prefix,
				team_prefix,
				pilot_prefix,
				name_index,
				has_instance_name
			),
			currentHeat(current_heat),
			currentCoolant(current_coolant),
			maxCoolant(max_coolant),
			m_doesHaveLightAmp(light_amp),
			m_powerBar(0),
			m_heatBar(0),
			m_armorBar(0),
			m_speedBar(0),
			m_mechID(0)
			{};

		static void
			ConstructCreateMessage(Script *script);
	};
	
	//##########################################################################
	//############    Entity::TakeDamageMessage     ############################
	//##########################################################################

	class Mech__UpdateMessage:
		public Vehicle::UpdateMessage
	{
	public:
		typedef Vehicle::UpdateMessage BaseClass;

		Stuff::Scalar
			currentSpeedMPS;

	protected:
		Mech__UpdateMessage();
	};

	//##########################################################################
	//############################    Mech
	//##########################################################################

	//-------------------------------------------------------------------------
	// The following helper classes must always be typedef'd or overriden by an
	// inheritor
	//
	typedef Vehicle__ClassData							Mech__ClassData;
	typedef Vehicle__Message							Mech__Message;

	extern DWORD Executed_Mech_Count;
	
	//-----------------------  End of inheritance stuff ------------------------

	class Mech:
		public Vehicle
	{
		friend class MovementClass;

	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		typedef Vehicle BaseClass;

	//##########################################################################
	// Inheritance support
	//
	public:
		typedef Mech__ClassData				ClassData;
		typedef Mech__GameModel				GameModel;
		typedef Mech__Message				Message;
		typedef Mech__ExecutionStateEngine	ExecutionStateEngine;
		typedef Mech__CreateMessage			CreateMessage;
		typedef Mech__UpdateMessage			UpdateMessage;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		static Mech*
			Make(
				CreateMessage *message,
				ReplicatorID *base_id
			);
		Adept::Replicator::CreateMessage*
			SaveMakeMessage(MemoryStream *stream, Adept::ResourceFile *res_file);

		void
			Respawn(Adept::Entity::CreateMessage *message);
		void
			CommonCreation(CreateMessage *message);

		void
			LoadAnimationScripts();

	protected:
		Mech(
			ClassData *class_data,
			CreateMessage *message,
			ReplicatorID *base_id,
			ElementRenderer::Element *element
		);
		
		~Mech();

		void
			Reuse(
				const CreateMessage *message,
				ReplicatorID *base_id
			);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Message Support
	//
	public:
		void
			UpdateMessageHandler(const UpdateMessage *message);

		Entity::UpdateMessage*
			ConstructUpdate(Stuff::MemoryStream *stream);

	protected:
		static const MessageEntry
			MessageEntries[];

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data support
	//
	public:
		static ClassData
			*DefaultData;

 	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Renderer Support
	//
 	virtual void
  		BecomeInteresting(bool render_me);


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Game Model Support
	//
	public:
		const GameModel*
			GetGameModel()
				{
					Check_Object(this);
					return Cast_Pointer(const GameModel*,gameModelResource.GetPointer());
				}
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Skill Checks
	//
	public:
		bool PilotSkillCheck (Stuff::Scalar damage_amount,bool jump);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Execution Support
	//
	protected:
		Stuff::Scalar m_DroppingFinalY,m_DroppingStartY;
		SlotOf <Entity *> m_DropCradle;
		bool m_NeedKillDropCradleEffect;
		bool m_CanStartDropJetEffect;
		Stuff::Scalar m_LastSoundSpeedMPS;
		bool m_CanStartGettingUp;
		bool m_NeedStartDrop;
		Site *m_DropSite;
		Site *m_JumpSite1;
		Site *m_JumpSite2;
		Site *m_JumpSite3;
		Site *m_JumpSite4;
		SlotOf <Effect *> m_JumpEffect1;
		SlotOf <Effect *> m_JumpEffect2;
		SlotOf <Effect *> m_JumpEffect3;
		SlotOf <Effect *> m_JumpEffect4;
		Stuff::Time m_SlideTimer;

	public:
		void DroppingMovementSimulation(Stuff::Time till);
		void StartDropping (void);
		void RealStartDropping (void);
		void HandleSalvage (void);
		virtual void TurnOn (void);
		virtual void TurnOff (void);
		virtual void GetTransSpeedKPH (Stuff::Scalar& forward,Stuff::Scalar& reverse);
		virtual void GetMaxSpeedKPH (Stuff::Scalar& forward,Stuff::Scalar& reverse);
		virtual void GetTransSpeedNormalized (Stuff::Scalar& forward,Stuff::Scalar& reverse);
		int GetHeatEffic();

		int
			GetExecutionSlot();

		void
			PreCollisionExecute(Stuff::Time till);
		#if defined(LAB_ONLY)
			void
				SyncMatrices(bool update_matrix);
		#endif
		void
			PostCollisionExecute(Stuff::Time till);

		void
			ComputeForwardSpeed(Stuff::Scalar time_slice);


		void
			SetCooling(int new_int);

		void Eject (void);
		void ProcessSelfDestruct();

		Stuff::Time
			m_selfDestructTimer;

		void
			SetMechTablePlug(MechTablePlug *mech_plug)
				{Check_Object(this); m_mechTablePlug = mech_plug;}

		MechTablePlug *
			m_mechTablePlug;

		void
			NotifyFired(const Adept::Entity::CollisionQuery& query);

		void
			NullArms();

	protected:
		static int s_mechSlots[NoMechID];
		int m_mechSlot;
		int m_NeedEject;

		Stuff::SlotOf<Adept::Effect *> ejectEffect;

		Stuff::SlotOf<Adept::Effect *> m_wakeEffect;
		int
			m_needWakeEffect;
		Stuff::SortedChainOf<Mech*, Stuff::Time>
			m_lastHits;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Collision Support
	//
	public:
		bool
			CollisionHandler(
				Stuff::LinearMatrix4D *new_position,
				Stuff::DynamicArrayOf<CollisionData> *collisions
			);

		bool allowedToAnimateVelocity;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Animation Support
	//
	public:
		enum FallMode {
			NoFallMode = 0,
			FallForwardMode,
			FallLeftMode,
			FallRightMode,
			FallBackMode
		};

		int queFallState;
		int fallDirection;


		enum {
			NoDeathTrigger,
			PowerDownDeathTrigger,
			FallDownDeathTrigger,
			DoneDeathTrigger
		};

		int triggerDeath;

		enum {
			NotGimpedMode = 0,
			LeftGimpMode,
			RightGimpMode
		};

		int gimpState;

		Origin3D *initialPositions;

		void AnimDiagTest1(void)
			{
				Test_Reset();
			};

		void AnimDiagTest2(void)
			{	
				Test_LeftGimp();
			};
		void AnimDiagTest3(void)
			{
				Test_RightGimp();
			};
		void AnimDiagTest4(void)
			{	
				//Test_Hit1();
				Test_FallForward();
			};
		void AnimDiagTest5(void)
			{
				//Test_Hit2();
				Test_FallLeft();
			};
		void AnimDiagTest6(void)
			{
				//Test_Hit3();
				Test_FallRight();
			};
		void AnimDiagTest7(void)
			{
				//Test_Hit4();
				Test_FallBackward();
			};
		
		void AnimDiagTest8(void){};

		static bool
			NoBlend;
		static bool
			DontLoadBlends;
	

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// AI force stuff, for jumping
	//
		bool m_ForceYaw;
		Stuff::Scalar m_ForceYawValue;
		bool m_ForceSpeed;
		Stuff::Scalar m_ForceSpeedValue;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//	if this mech is a lancemate
	//  if not this is -1;

		int lancemateIndex;

		bool IsLanceMate()
		{
			return (lancemateIndex != -1)?true:false;
		}
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Fall adjust stuff
	//
		Stuff::Scalar m_FallDamage;				// accumulator for falling damage
// MSL 5.02 headshot
		Stuff::Scalar m_HeadShotFallDamageMod;
		Stuff::Scalar m_HeadShotTorsoRockDamageMod;
		Stuff::Scalar m_HeadShotTorsoSpinDamageMod;
// MSL 5.02 SubSystems
		Stuff::Scalar m_AdvancedGyroFallDamageMod;
		Stuff::Scalar m_AdvancedGyroTorsoRockDamageMod;
		Stuff::Scalar m_AdvancedGyroTorsoSpinDamageMod;
		void StartFall(void);

		UnitQuaternion
			initialPosition;
		
		Stuff::Scalar
			fallTimer,
			getUpTimer;

		Stuff::Scalar
			blockFallTimer;

		Stuff::UnitQuaternion
			fallGround;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Arm nulification
	//

		bool armsNulled;
		Stuff::Scalar armReNullTime;

		BlanderizerOf<UnitQuaternion>
			armBlanderizer;
		
		BlanderizerOf<UnitQuaternion>
			torsoBlanderizer;


		int leftGunJointIndex;
		int leftArmJointIndex;
		int rightGunJointIndex;
		int rightArmJointIndex;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Hit & Recoil
	//


		SpringOf<Point3D>
			eyeSpringRotation;



		DeceleratorOf<YawPitchRoll>
			rootHit;

		DeceleratorOf<YawPitchRoll>
			torsoHit;

		DeceleratorOf<YawPitchRoll>
			hipHit;
#if 0
		DeceleratorOf<YawPitchRoll>
			leftGunRecoil;

		DeceleratorOf<YawPitchRoll>
			leftArmRecoil;

		DeceleratorOf<Point3D>
			rightGunRecoil;
#endif


		int torsoAboveJointIndex;
		int hipAboveJointIndex;
		
		int leftGunAboveJointIndex;
		int leftArmAboveJointIndex;
		
		int rightGunAboveJointIndex;
		
		void RunSprings(Stuff::Scalar time_slice);



	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Internal Dampening..
	//
		

		int worldJointIndex;
		int rootJointIndex;
		int hipJointIndex;
		int torsoJointIndex;

		void DampenMech(Stuff::Scalar time_slice);

		BlanderizerOf<Stuff::UnitQuaternion>	worldRotDampener;
		BlanderizerOf<Stuff::UnitQuaternion>	rootRotDampener;
		BlanderizerOf<Stuff::Point3D>			rootTransDampener;
		BlanderizerOf<Stuff::UnitQuaternion>	torsoRotDampener;
		BlanderizerOf<Stuff::UnitQuaternion>	hipRotDampener;
		

		void FadeDampened();
		void FadeUndampened();

		void SetDampened();
		void SetUndampened();


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Tilt Stuff for falls and running tilt
	//

		MWMover *jointWorld;

		Stuff::Scalar tiltAngle;
		Stuff::Scalar tiltRequest;

		void TiltMech(Stuff::Scalar time_slice);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Foot Stuff
	//

		Adept::Site *siteLeftFoot;
		Adept::Site *siteRightFoot;
		
		MWMover *jointLeftAnkle;
		MWMover *jointRightAnkle;

		enum {
			LeftFootType = 0,
			RightFootType
		};


		Scalar lastSpeedMPS;

		void FindGroundAngles(void);
		void FindGroundAngle(const Stuff::LinearMatrix4D &local_to_world);

		Stuff::Scalar FindMechFootPenetration(void);

		void LockLeftFoot(void);
		void LockRightFoot(void);
		void ReleaseLeftFoot(void);
		void ReleaseRightFoot(void);


		void FootLockSimulation(Stuff::Scalar time_slice);

		

		Stuff::Scalar leftFootTurnAccumulation;
		Stuff::Scalar rightFootTurnAccumulation;

		Stuff::Scalar leftFootLerpBackValue;
		Stuff::Scalar rightFootLerpBackValue;

		Stuff::Scalar leftFootReturnTimer;
		Stuff::Scalar rightFootReturnTimer;

		int leftFootState;
		int rightFootState;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Ground smoothing
	//

		AverageOf<Stuff::Scalar>
			pitchSmoother,
			rollSmoother;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Last Chance Push Up Support
	//

		bool debugPushupOff;
		Scalar lastFramePushUp;
		Scalar leftFootGround;
		Scalar rightFootGround;



		bool fastTransition;
		bool GetFastTransition() {Check_Object(this); return fastTransition;};
		void FastTransition() {Check_Object(this); fastTransition = !fastTransition;};


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Animation Support
	//
		Stuff::YawPitchRoll
			groundAngleDbg;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Simulation Animation Requests
	//
	public:
		void GetUpRequestRequest(void);
		bool ShutDownRequest(bool shutdown);			// true to shutdown and false to startup
		void CrouchRequest(void);
		bool JumpRequest(void);
		void StopJumpRequest(void);

		bool IsShutdown();
		bool IsCrouched();

		void MaintainWalkingAnimStates(bool run_minimal = false);


		static void
			LeftFootTriggerHandler(int trigger_value, void *pass_data);
		
		static void
			RightFootTriggerHandler(int trigger_value, void *pass_data);



	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Network
	//
	public:
	
		CubicCurve *deadReckonCurve;
		Scalar deadReckonScale;
		Scalar deadReckonCurveTime;

		YawPitchRoll startRotation;
		YawPitchRoll endRotation;


		void GetNetworkPosition(Stuff::Point3D &current_position, Stuff::YawPitchRoll &current_rotation);
		void GetDeadReckonedNetworkPosition(Stuff::Point3D &current_position, Stuff::YawPitchRoll &current_rotation);

		void ClearNetworkPosition();
		void SetNetworkCorretionPosition(Stuff::Point3D new_position, Stuff::YawPitchRoll new_rotation, Point3D velocity, Scalar vel_request, Scalar latency, Scalar update_rate);
		bool GetNetworkAdjustment(Stuff::Scalar time_slice, Stuff::Point3D &current_position, Stuff::YawPitchRoll &current_rotation);
			

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Damage/Destruction Support
	//
	public:

		bool
			FriendlyFire(const TakeDamageMessage *message);

		void
			ReactToHit(const Adept::Entity__TakeDamageMessage *message,Adept::DamageObject *part_hit);
		void
			ReactToDestruction(int damage_mode, int damage_type);
		void
			ReactToInternalDamage(int damage_mode);
		void
			ReactToDamageTaken(Stuff::Scalar damage_taken, const Adept::ReplicatorID& inflicting_entity, int wepaonID, int damageType);
// MSL 5.02 headshot
		void HeadShotInternal( );
// MSL 5.03 Gyro Hit
		void GyroHitInternal( );
		void
			TakeDamageMessageHandler(const TakeDamageMessage *message);
// MSL 5.05 Torso
		void
			DestroyLeftArmSpecialZones();
		void
			DestroyRightArmSpecialZones();
		void
			DestroyLeftTorsoSpecialZones();
		void
			DestroyRightTorsoSpecialZones();
		void
			DestroyLeftLegSpecialZones();
		void
			DestroyRightLegSpecialZones();
		void
			DestroyLeftArm();
		void
			DestroyRightArm();
		void
			SetLeftGimp();
		void
			SetRightGimp();
		void
			SetNoGimp()
				{Check_Object(this); gimpState = NotGimpedMode;}
		bool
			IsGimped()
				{Check_Object(this); return gimpState != NotGimpedMode;}
		void
			CreateJumpJetEffect();
		void
			CreateFootEffect(const Adept::ResourceID& effect_id, Adept::Site *foot, const Stuff::Normal3D& normal);
		void
			SetSearchLightIntensity(Stuff::Scalar intensity);
		void
			InitializeDamageArray();

		Stuff::Scalar
			FriendlyFireDamageMultiplier() const;

		Adept::Effect
			*leftJumpJetEffect;
		Adept::Effect
			*rightJumpJetEffect;
		Adept::Site
			*leftJumpJetSite;
		Adept::Site
			*rightJumpJetSite;

// MSL 5.02 headshot
		int dwDamageFlags;
// MSL 5.03 headshot
		int dwGyroDamageFlags;

		//Cage Effect Support
		Adept::Effect*
			CreateCageDamageEffect(Adept::Site *site);
		Stuff::SlotOf<Adept::Effect *>
			m_leftCageEffect;
		Stuff::SlotOf<Adept::Effect *>
			m_rightCageEffect;
		bool
			m_playLeftCageEffect;
		bool
			m_playRightCageEffect;
		Adept::Site
			*m_leftCageSite;
		Adept::Site
			*m_rightCageSite;

		void
			DestroySearchLight();
		MWMover
			*jointSearchLight;
		bool
			diedBySplash;

		Adept::Site *searchLightSite;

		MWMover *centerTorso;

		Adept::Effect *searchLightEffect;

		Stuff::Normal3D
			leftFootNormal,
			rightFootNormal,
			groundNormal;
		bool
			isLeftFootDown,
			isRightFootDown;

		Adept::ResourceID
			currentLeftFootFall;
		Adept::ResourceID
			currentRightFootFall;
		
		enum
		{
			NoHitDirection = 0,
			ForwardHitDirection,
			RearHitDirection,
			LeftHitDirection,
			RightHitDirection	
		};

		bool
			takenDamageThisFrame;
		Scalar
			lastDamageTaken;

		int
			lastHitDirection;
		int
			damageArray[11];

		Scalar AverageDamage (void) const;			// 0-1 for average damage of mech  center torso has a higher weight

		void
			CreateFootTextureChain(Adept::ResourceID resource_id);
		MidLevelRenderer::MLRTexture*
			GetFootTexture(int material);

		FootStepPlug *
			m_defaultFootStep;

		Stuff::SortedChainOf<FootStepPlug *, int>
			m_footSteps;

		Adept::Entity *
			m_footHitEntity;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Support
	//
	public:
		void
      		TestInstance() const;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	public:
		void
			HookUpSubsystems(void);
		void
			AddSubsystem(Subsystem *subsystem);
		void
			RemoveSubsystem(Subsystem *subsystem);
		void
			SeedHeatManager();
		void
			ReactToShutDown();
		void
			MovementSimulation(Scalar time_slice, Stuff::Vector3D &new_velocity, Stuff::Vector3D &instantanious_angular_velocity);
		void
			BallisticMovementSimulation(Stuff::Time till);
		void
			FallingMovementSimulation(Scalar time_slice, Stuff::Vector3D &new_velocity, Stuff::Vector3D &instantanious_angular_velocity);
		void
			Test_ArmActivation();
		bool
			Test_GetArmActivation() const;
		void
			Test_PushupOff();
		bool
			Test_GetPushupOff() const;
		void
			Test_LeftArmRecoil();
		void
			Test_RightGunRecoil();
		void
			Test_Hit1();
		void
			Test_Hit2();
		void
			Test_Hit3();
		void
			Test_Hit4();
		void
			Test_Reset();
		void
			Test_LeftGimp();
		bool
			Test_GetLeftGimp() const;
		void
			Test_RightGimp();
		bool
			Test_GetRightGimp() const;
		void
			Test_FallForward();
		void
			Test_FallBackward();
		void
			Test_FallRight();
		void
			Test_FallLeft();

		JumpJet*
			GetJumpJet()
				{return jumpJet;}
		Armor*
			GetArmor()
				{return armor;}
		int
			m_numHeatSinks;

		EyePointManager*
			GetEyePointManager()
				{return m_eyePointManager;}

		void
			EnableFallDamping(const Point3D& point);

		void
			DisableFallDamping();

		void
			FallDampingSimulation();

		Stuff::Scalar
			m_heatMaterialMultiplier;
		Stuff::Scalar
			m_sensorDinstanceMultiplier;

		bool
			m_alreadyShutDown;

		Stuff::Scalar
			GetLastFootFallTime() const;

		virtual void
			GetLineOfSight(Stuff::LinearMatrix4D& line_of_sight);

		void
			SetMaxFlagsCarried(int max_flags)
				{	m_MaxFlagsCarried = max_flags;	}

		int
			GetMaxFlagsCarried() const;

		void
			ToggleLightAmpLoad();
		
//
// [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
//
//		void
//			SetSearchLightMode(bool fOn)
//				{m_previousSearchLightState = fOn;}

	protected:
		JumpJet
			*jumpJet;
		Gyro
			*m_gyro;
		Armor
			*armor;
		Stuff::Scalar
			m_startTons;
//		bool
//			m_previousSearchLightState;

	
		EyePointManager
			*m_eyePointManager;

		bool
			m_FallDampingEnabled;

		Point3D
			m_FallDampingLocus;

		Stuff::Scalar
			m_LastFootFallTime;

		int
			m_MaxFlagsCarried;

		Stuff::Scalar
			m_LastMissionWarning;

		Stuff::Scalar
			m_SavedFractionalDamage;

// MSL 5.05 Advance Mode
		Stuff::Scalar
			m_SavedFractionalModDamage;

// MSL 5.03 Lava
		Stuff::Time
			m_lastLavaTime;

		Stuff::Scalar
			m_lastFall;

	public:
		int
			GetAlignment() const;			

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	public: // jcem
        int GetJumpJetState() const;
// MSL 5.05 Advance Mode
		int m_AdvanceMode;
// MSL 5.06 Armor Mode
		int m_ArmorMode;

	public: // jcem - for cameraship
        class CMechOther : public SlotOf<Mech*>
        {
        private:
            // SlotOf<Mech*>: Currently, I'm Attacking... // Actually SlotOf<Mech*> should be SlotOf<Adept::Entity*>
            Stuff::Scalar m_fTimeStart; // in mission time, attack - start time
            Stuff::Scalar m_fTimeLast; // in mission time, last attack time
        public:
            CMechOther();
            void Clear();
            static Stuff::Scalar GetMissionTime();
            Mech* Get(Stuff::Scalar& fTime = *(Stuff::Scalar*)NULL);
            void Set(Entity* pMech);
            Stuff::Scalar GetStartTime() const { return m_fTimeStart; }
            Stuff::Scalar GetTimeDuration() const { return m_fTimeLast - m_fTimeStart; }
        };
        CMechOther m_Others[2]; // 0: Attacking, 1: Who Killed Me
        void ClearInterestings();
    public: // for delayed lancemate respawn
        Stuff::Scalar m_fTimeRespawnRequestEnd;
        Stuff::Scalar m_fTimeMsgSentEnd; // jcem - gos_GetElapsedTime() + duration
        int m_nMsgKind; // 0-6(team message), 7-13(taunt, FFA), 14/15 yes/no
    public:
        void RepairForCOOP();
        void RepairGimp();
        void RepairWeapons();
        void ReloadAmmoAll();
        void ReloadCoolant();
	};

	inline
		Mech__ExecutionStateEngine::Mech__ExecutionStateEngine(
			ClassData *class_data,
			Mech *mech,
			FactoryRequest *request
		):
			BaseClass(class_data, mech, request)
	{
	}
}

void Mech_CheckDamage(Replicator* pVictim, Replicator* pInflictor, bool bDeath = false);
