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

#pragma once

#include "MW4.hpp"
#pragma warning (push)
#include <stlport\string>
#include <stlport\vector>
#include <stlport\algorithm>
#pragma warning (pop)

#include "MWMover.hpp"
#include "AnimationState.hpp"
#include "AnimationTrigger.hpp"
#include "Group.hpp"
#include "AI_FindObjectCache.hpp"

namespace Adept
{
	class DamageObject;
	class Effect;
	class Site;
}

namespace MechWarrior4
{	
	class Weapon;
	class MoverAI;
	class CombatAI;
	class HeatManager;
	class MWObject;
	class Weapon;
	class Torso;
	class MWInternalDamageObject;
	class Sensor;
	class Beagle;
	class AMS;
	class SearchLight;
	class Subsystem;
	class ECM;
	class VehicleInterface;
// MSL 5.02 SubSystems
	class IFF_Jammer;
//	class EnhancedOptics;
	class AdvancedGyro;


	class IdleEffectObject : public Stuff::Plug
	{
	public:
		IdleEffectObject();

		Adept::ResourceID effectResourceID;
		Stuff::SlotOf<Adept::Effect *> idleEffect;
		Stuff::SlotOf<Adept::Site *> siteSlot;
	};

	//##########################################################################
	//#####################    MWObject::ClassData    ##########################
	//##########################################################################

	class MWObject__ClassData:
		public MWMover__ClassData
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	public:
		typedef MWMover__ClassData BaseClass;

		MWObject__ClassData(
			Stuff::RegisteredClass::ClassID class_id,
			const char* class_name,
			Adept::Replicator::ClassData *parent_class,
			int message_count,
			const Adept::Receiver::MessageEntry *message_handlers,
			Adept::Entity::Factory entity_factory,
			Adept::Entity::CreateMessage::Factory message_factory,
			Adept::Entity::ExecutionStateEngine::ClassData *execution_state,
			Adept::Entity::GameModel::Factory model_factory,
			Adept::Entity::GameModel::Factory obb_factory,
			Adept::Entity::GameModel::ReadAndVerifier verifier,
			Adept::Entity::GameModel::ModelWrite model_write_to_text,
			Adept::Entity::GameModel::ModelSave model_save_to_text,
			AnimationStateEngine::Factory animation_state_factory
		):
			MWMover__ClassData(
				class_id,
				class_name,
				parent_class,
				message_count,
				message_handlers,
				entity_factory,
				message_factory,
				execution_state,
				model_factory,
				obb_factory,
				verifier,
				model_write_to_text,
				model_save_to_text
			)
		{
			//This line is commented out due to Internal Compile Error in
			//and Armor Build

#if 0
			Check_Pointer(animation_state_factory);
#endif
			animationStateFactory = animation_state_factory;
		}
		

		AnimationStateEngine::Factory
			animationStateFactory;
	};

	//##########################################################################
	//#####################    MWObject::ModelResource   #######################
	//##########################################################################

	class MWObject__GameModel:
		public MWMover__GameModel
	{
	public:
		typedef MWMover__GameModel BaseClass;

		enum
		{
			LEG_MOVETYPE,
			LEGJUMP_MOVETYPE,
			TRACK_MOVETYPE,
			WHEEL_MOVETYPE,
			FLYER_MOVETYPE,
			HOVER_MOVETYPE,
			HELI_MOVETYPE,
			NONE_MOVETYPE,
			DROPSHIP_MOVETYPE,
			WATER_MOVETYPE,
			LAST_MOVETYPE
		};

		int moveTypeFlag;

#if NSWIZZLE
		
		Adept::ResourceID
			deathEntityResource;
		Adept::ResourceID
			destroyedEffectResource;

		// these can be used for special derived classes
		// mech uses it for alternate deaths and a two
		// part explosion
		Adept::ResourceID
			secondaryDeathEntityResource;
		Adept::ResourceID
			secondaryDestroyedEffectResource;

		Adept::ResourceID
			idleEffectResourceID;
		Adept::ResourceID
			partDestructionEffectResource;
#else
		// these can be used for special derived classes
		// mech uses it for alternate deaths and a two
		// part explosion
		Adept::ResourceID
			secondaryDeathEntityResource;
		Adept::ResourceID
			secondaryDestroyedEffectResource;

		Adept::ResourceID
			idleEffectResourceID;
		Adept::ResourceID
			partDestructionEffectResource;

		Adept::ResourceID
			deathEntityResource;
		Adept::ResourceID
			destroyedEffectResource;
#endif

		Stuff::Scalar
			vehicleTonnage;
		Stuff::Scalar
			maxVehicleTonnage;

		int
			vehicleBattleValue;

		Stuff::Scalar
			splashDamageRadius;
		Stuff::Scalar
			splashDamageAmount;
		Stuff::Scalar
			splashHeatAmount;

		char animScriptName[256];
		char eyeSiteName [MaxStringLength];

		Adept::ResourceID
			coolantEffectResource;
		Adept::ResourceID
			overHeatEffectResource;
		Adept::ResourceID	
			ejectEffectResource;

		Adept::ResourceID
			hierarchicalOBBStreamResourceID;
		int
			m_nameIndex;

		enum {
			DeathEntityResourceAttributeID = MWMover__GameModel::NextAttributeID,
			DestroyedEffectResourceAttributeID,
			SecondaryDeathEntityResourceAttributeID,
			SecondaryDestroyedEffectResourceAttributeID,
			VehicleTonnageAttributeID,
			MaxVehicleTonnageAttributeID,
			EyeSiteNameAttributeID,
			PartDestructionEffectResourceAttributeID,
			SplashDamageRadiusAttributeID,
			SplashDamageAmountAttributeID,
			VehicleBattleValueAttributeID,
			CoolantEffectResourceAttributeID,
			SplashHeatAmountAttributeID,
			EjectEffectResourceAttributeID,
			NameIndexAttributeID,
			OverHeatEffectResourceAttributeID,
			NextAttributeID
		};

		static bool
			ReadAndVerify(
				MWObject__GameModel *model,
				Adept::ModelAttributeEntry *attribute_entry,
				const char *data,
				char **error,
				int error_buffer = 128
			);
		static int ConvertStringToMoveType (const char *str);

		static void
			ConstructGameModel(Script *script);
		static void
			ConstructOBBStream(Script *script);
		static Adept::ResourceID
			CreateEffectTableResource(Stuff::NotationFile *effect_file, BYTE length);
	};

	//##########################################################################
	//##################    MWObject::CreateMessage    #########################
	//##########################################################################

	class MWObject__CreateMessage:
		public MWMover__CreateMessage
	{
	public:
		typedef MWMover__CreateMessage BaseClass;

#if NSWIZZLE
		Adept::ResourceID
			subsystemStreamResourceID;
		Adept::ResourceID
			damageStreamResourceID;
#else
		Adept::ResourceID
			damageStreamResourceID;
		Adept::ResourceID
			subsystemStreamResourceID;
#endif

		char
			skinPrefix;
		int
			teamDecal;
		int
			pilotDecal;
		int
			nameIndex;
		bool
			doesHaveInstanceName;
			

		MWObject__CreateMessage(
			size_t length,
			int priority,
			int message_flags,
			Stuff::RegisteredClass::ClassID class_id,
			int replicator_flags,
			const Adept::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 Adept::ResourceID& armature_id,
			const Adept::ResourceID& site_id,
			const Adept::ResourceID& subsystem_id,
			const Adept::ResourceID& damage_id,
			char skin_prefix,
			int team_decal,
			int pilot_decal,
			int name_index,
			bool has_instance_name
		):
			MWMover__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
			),
			subsystemStreamResourceID(subsystem_id),
			damageStreamResourceID(damage_id),
			skinPrefix(skin_prefix),
			teamDecal(team_decal),
			pilotDecal(pilot_decal),
			nameIndex(name_index),
			doesHaveInstanceName(has_instance_name)
				{}

		static void
			ConstructCreateMessage(Script *script);
	};

	//##########################################################################
	//############################    MWObject    ##############################
	//##########################################################################

	//-------------------------------------------------------------------------
	// The following helper classes must always be typedef'd or overriden by an
	// inheritor
	//
	typedef MWMover__Message					MWObject__Message;
	typedef MWMover__UpdateMessage				MWObject__UpdateMessage;
	typedef MWMover__ExecutionStateEngine		MWObject__ExecutionStateEngine;

	//-----------------------  End of inheritance stuff ------------------------

	class MWObject:
		public MWMover
	{
		friend class MovementClass;

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

		typedef MWMover BaseClass;

	//##########################################################################
	// Inheritance support
	//
	public:
		typedef MWObject__ClassData							ClassData;
		typedef MWObject__GameModel							GameModel;
		typedef MWObject__Message							Message;
		typedef MWObject__ExecutionStateEngine				ExecutionStateEngine;
		typedef MWObject__CreateMessage						CreateMessage;
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		static MWObject*
			Make(
				CreateMessage *message,
				Adept::ReplicatorID *base_id
			);
		Adept::Replicator::CreateMessage*
			SaveMakeMessage(Stuff::MemoryStream *stream, Adept::ResourceFile *res_file);

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

		void
			SaveInstanceText(Stuff::Page *page);

		void
			LoadSubsystemsFromResource(
				const Adept::ResourceID &subsystem_stream_id,
				Adept::ReplicatorID *base_id
			);
		void
			LoadIdleEffectsFromResource(const Adept::ResourceID &effects_stream_id);
		Adept::Effect*
			CreateIdleEffect(IdleEffectObject *effect_object);

		static void
			CreateArmatureStream(Stuff::MemoryStream *stream, Stuff::NotationFile *notation_file);
		static void
			CreateDamageStream(Stuff::MemoryStream *stream, Stuff::NotationFile *notation_file);
		static void
			CreateSubsystemStream(Stuff::MemoryStream *stream, Stuff::NotationFile *notation_file);

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

		void
			LoadDamageObjectsFromResource(
				const Adept::ResourceID &damage_stream_id
			);
		
		~MWObject();

		void SentenceToDeathRow();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Message support
	//
	public:
		void
			TakeDamageMessageHandler(const TakeDamageMessage *message);

	protected:
		static const MessageEntry
			MessageEntries[];

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Child Support
	//
	public:
		void
			AddChild(Adept::Entity *entity);
		void
			RemoveChild(Adept::Entity *entity);

	protected:
		void
			ChildPreCollisionChanged(Adept::Entity *entity);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Game Model Support
	//
	public:
		const GameModel*
			GetGameModel()
				{
					Check_Object(this);
					return Cast_Pointer(const GameModel*,gameModelResource.GetPointer());
				}
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Animation Support
	//
	public:

		Stuff::Vector3D animationVelocity;
		Stuff::Vector3D	instantaniousAngularVelocity;

		int	animationArrayCount;
		MWMover **animationArray;
		int *lastTriggerArray;

		MW4AI::FindObjectCache* m_FindObjectCache;
		MW4AI::FindObjectList* m_FindObjectList;

		AnimationTriggerManager animationTriggerManager;

		static void
			ApplyChannel
			(
				MW4Animation::ChannelApplication &channel_data,
				int joint_index,
				void *user_data
			);

		void
			MakeAnimationArray();

		
		AnimationStateEngine *animStateEngine;
		


		
		virtual void
			LoadAnimationScripts();
	
		
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Simulation Animation Requests
	//
	public:
		virtual void GetUpRequestRequest(void){};
		virtual bool ShutDownRequest(bool shutdown){return false;}
		virtual void CrouchRequest(void){};
		virtual bool JumpRequest(void){return false;};
		virtual void StopJumpRequest(void){};
		virtual bool IsCrouched() {return false;}

		bool vehicleShutDown;
		bool vehicleJustPoweredUp;			// used in sensors to send vehicleinterface messages

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Execution Support
	//
	public:
		AI *m_AI;
		void AttachAI (AI *ai);
		AI* GetAI() { return m_AI; }

		bool m_bHasAI;
		void HasAI(bool hasAI) { m_bHasAI = hasAI; }
		bool HasAI() { return m_bHasAI; }

// MSL 5.06 Armor Mode
		int
			m_ArmorMode;
		
		virtual void TurnOn (void) {}
		virtual void TurnOff (void) {}

		Stuff::Scalar m_HitPoints,m_MaxHitPoints;				// for hud tracking
		Stuff::Scalar armorArray[12];
		virtual void InitializeArmorArray();

		void
			PreCollisionExecute(Stuff::Time till);
		void
			SyncMatrices(bool update_matrix);
		void PostCollisionExecute(Stuff::Time till);
		void
			ReactToDestruction(int damage_mode, int damage_type);
		void
			ReactToHit(const Adept::Entity::TakeDamageMessage *message,Adept::DamageObject *part_hit);
		
		virtual void EngineDead (void);

		bool
			CollisionHandler(
				Stuff::LinearMatrix4D *new_position,
				Stuff::DynamicArrayOf<CollisionData> *collisions
			);

		void DestroyDamageObjects();
		void DestroyRunningLight();

		bool
			m_hasExecuted;
		MWMover
			*jointRunningLight;

#if 0
		void
			CreateDestructionEffect();
		void
			CreateSecondaryDeathEntity();
		void
			CreateSecondaryDestructionEffect();
		void
			CreateDeathEntity();
#endif


		Adept::Effect*
			CreateEffect(const Adept::ResourceID& effect_id, MWMover *parent_part, bool follow_joint = false);
		Adept::Effect*
			CreateLoopingEffect(const Adept::ResourceID& effect_id, MWMover *parent_part, bool follow_joint = false);
		Adept::Effect*
			CreateEffect(const Adept::ResourceID& effect_id, const Stuff::Point3D &location);
// MSL 5.03 Glass
		Adept::Effect*
			CreateEffect(const Adept::ResourceID& effect_id, const Stuff::Point3D &location, const Stuff::Vector3D &normal);
		Adept::Effect*
			CreateLoopingEffect(const Adept::ResourceID& effect_id, const Stuff::Point3D &location);

		//Effect support to accept sites
		Adept::Effect*
			CreateEffect(const Adept::ResourceID& effect_id, Adept::Site *parent_part, bool follow_joint = false);
		Adept::Effect*
			CreateLoopingEffect(const Adept::ResourceID& effect_id, Adept::Site *parent_part, bool follow_joint = false);

		Adept::Entity*
			CreateStaticHermitEntity(Adept::ResourceID entity_id);

		Adept::Entity::CollisionMask
			originalCollisionMask;

		unsigned
			originalCullMode;

		virtual void
			RemoveFromExecution();

		static int
			FindChildMoverIndexUserData(
				const char *joint_name,
				void *user_data
			);

		int
			FindChildMoverIndex(
				const char *joint_name
			);


		MWMover*
			FindChildMover(
				const char *joint_name
			);

		Adept::Site*
			FindSite(const char *site_name)
#ifdef _DEBUG
            ;
#else // !_DEBUG
				{Check_Object(this); Check_Pointer(site_name); return m_sites.Find(site_name);}
#endif // _DEBUG

		void
			ConnectDamageObjects();
		void
			ReuseDamageObjects();
		void
			MakeArmatureChain();
		void
			ConnectMWMover(MWMover *mover);
		void
			ToggleSearchLight();
		void
			TurnOnSearchLight();
		void
			TurnOffSearchLight();
		bool
			IsSearchLightOn();

		//Entity__CollisionQuery
		//	*targetQuery;
		
		Stuff::ChainOf<Subsystem*>
			subsystemsInVehicle;
		Stuff::ChainOf<Subsystem*>
			executingSubsystems;
		Stuff::ChainOf<MWMover*>
			entitiesToSync;
		//Damage

		virtual void DealSplashDamage();
		void TakeSplashDamage(Adept::Entity::TakeDamageMessage *message);
		static void SplashCallBack(Adept::Entity *entity, Adept::Entity *original_enitiy, const Stuff::Sphere &sphere);
		static void SubSplashCallBack(Adept::CollisionVolume *solid, Adept::Entity *original_enitiy, const Stuff::Sphere &sphere);

		Stuff::ChainOf<Adept::Entity *>
			splashedEntities;

		int
			splashSize;



		Stuff::SortedChainOf<Adept::DamageObject*, int>
			damageObjects;

		Stuff::SortedChainOf<MWInternalDamageObject *, int>
			internalDamageObjects;

		Stuff::ChainOf<MWMover*>
			armatureChain;

		Stuff::ChainOf<IdleEffectObject *>
			idleEffects;

		Adept::ResourceID
			damageStreamResourceID;
		Adept::ResourceID
			subsystemStreamResourceID;

		typedef std::vector<Group::identifier> GroupList;
		const GroupList&
			GetGroups() const;
		GroupList&
			GetGroups();

		void
			BecomeInteresting(bool render_me);
		void
			CheckVideoStates(bool render_me);

// MSL 5.05 Torso
		virtual void
			DestroyLeftArmSpecialZones()
				{};
		virtual void
			DestroyRightArmSpecialZones()
				{};
		virtual void
			DestroyLeftTorsoSpecialZones()
				{};
		virtual void
			DestroyRightTorsoSpecialZones()
				{};
		virtual void
			DestroyLeftLegSpecialZones()
				{};
		virtual void
			DestroyRightLegSpecialZones()
				{};
		virtual void
			DestroyLeftArm()
				{};
		virtual void
			DestroyRightArm()
				{};
		virtual void
			SetLeftGimp()
				{};
		virtual void
			SetRightGimp()
				{};
// MSL 5.02 headshot
		virtual void
			HeadShotInternal()
				{};
// MSL 5.03 Gyro Hit
		virtual void
			GyroHitInternal()
				{};

		Stuff::Scalar
			GetTonage()
			{
				Check_Object(this); 
				return tonage;
			}
		void
			AddTonage(Stuff::Scalar add_tonage)
			{
				Check_Object(this); 
				tonage += add_tonage;
			}
		void
			SubtractTonage(Stuff::Scalar subtract_tonage)
			{
				Check_Object(this); 
				tonage -= subtract_tonage;
			}
		void
			SetTonnage(Stuff::Scalar new_tonnage)
			{
				Check_Object(this); 
				tonage = new_tonnage;
			}
		bool
			DoesHaveAvailableTonage(Stuff::Scalar tons);

		int
			GetBattleValue()
			{
				Check_Object(this); 
				return battleValue;
			}
		void
			AddBattleValue(int add_value)
			{
				Check_Object(this); 
				battleValue += add_value;
			}
		void
			SubtractBattleValue(int subtract_value)
			{
				Check_Object(this); 
				battleValue -= subtract_value;
			}


		VehicleInterface
			*vehicleInterface;

//		int
//			m_RadarMode;

		int
			GetSensorMode();
		Sensor*
			GetSensor()
				{return sensor;}

		AMS*
			GetAMS()
				{Check_Object(this); return ams;}

		Beagle
			*GetBeagle()
				{Check_Object(this); return beagle;}
		bool
			DoesHaveBeagle();
		void
			DestroyBeagle()
				{Check_Object(this); beagle = NULL;}
		ECM
			*GetECM()
				{Check_Object(this); return ecm;}
		bool
			DoesHaveECM()
				{return ecm != NULL;}
		void
			DestroyECM()
				{Check_Object(this); ecm = NULL;}

// MSL 5.02 SubSystems
//		EnhancedOptics
//			*GetEnhancedOptics()
//				{Check_Object(this); return enhancedOptics;}

//		bool
//			DoesHaveEnhancedOptics()
//				{return enhancedOptics != NULL;}
//		void
//			DestroyEnhancedOptics()
//				{Check_Object(this); enhancedOptics = NULL;}

		IFF_Jammer
			*GetIFF_Jammer()
				{Check_Object(this); return iff_jammer;}

		bool
			DoesHaveIFF_Jammer()
				{return iff_jammer != NULL;}
		void
			DestroyIFF_Jammer()
				{Check_Object(this); iff_jammer = NULL;}

		AdvancedGyro
			*GetAdvancedGyro()
				{Check_Object(this); return advancedGyro;}

		bool
			DoesHaveAdvancedGyro()
				{return advancedGyro != NULL;}
		void
			DestroyAdvancedGyro()
				{Check_Object(this); advancedGyro = NULL;}

		virtual void
			AddStatsToString(std::string& s);

		void
			AddDamageInfoToString(std::string& s);

		void
			SetTargetDesirability(Stuff::Scalar desirability);
		Stuff::Scalar
			GetTargetDesirability() const;

		virtual void
			NotifyFired(const Adept::Entity::CollisionQuery& query);
		void
			NotifyInTargetingReticule(MWObject& mwobject);

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

		Stuff::Point3D
			GetLineOfSight();

		virtual Stuff::Scalar
			FriendlyFireDamageMultiplier() const;

		enum
		{
			desirability_invalid = -2,
			desirability_never = -1
		};

		void
			NotifyProjectileApproaching(const Stuff::Point3D& origin);
		Adept::ResourceID
			ReactToMissileApproach(Stuff::Scalar distance, const Stuff::Point3D& current_position);
		void
			NotifyOfMissileLock();

		virtual Stuff::Point3D&
			EstimateFuturePosition(
				Stuff::Point3D *new_position,
				Stuff::Scalar seconds,
				bool consider_terrain = true
			);

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

		bool
			m_markedForSalvage;

	private:
		Stuff::Scalar
			tonage;
		int
			battleValue;

		std::vector<Group::identifier>
			m_groups;

		Stuff::Scalar
			m_TargetDesirability;

	protected:
		Sensor
			*sensor;
		Beagle
			*beagle;
		AMS
			*ams;
		ECM
			*ecm;
// MSL 5.02 SubSystems
//		EnhancedOptics
//			*enhancedOptics;
		IFF_Jammer	
			*iff_jammer;
		AdvancedGyro
			*advancedGyro;

		bool
			m_VisibleOnSensors;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Localization Support
	//
	public:
		char*
			GetObjectName();
        char*
			GetModelName();

		bool
			m_doesHaveInstanceName;
		int
			m_localizeIndex;
		
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Support
	//
	public:
		void
      		TestInstance() const;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	public:

		virtual void
			HookUpSubsystems(void);
		void
			ReuseSubsystems(Stuff::MemoryStream *stream);
		virtual void
			AddSubsystem(Subsystem *subsystem);
		virtual void
			RemoveSubsystem(Subsystem *subsystem);

		Torso*
			GetTorso(int index = 0)
		{
			Check_Object(this);
			if ((index < 0) ||
				(index >= m_Torsos.size()))
			{
				return (0);
			}

			return m_Torsos[index];
		}

		int
			NumTorsos() const
		{
			return (m_Torsos.size());
		}

		bool
			GetVisibleOnSensors() const;

		void
			SetVisibleOnSensors(bool visible);

		SearchLight*
			GetSearchLight()
				{Check_Object(this); return searchLight;}

		Stuff::ChainOf<Weapon *>
			weaponChain;

		Stuff::SlotOf<MWMover*>	
			eyeSitePointer;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Heat support
	//
	public:
		virtual void
			ReactToOverHeat()
				{}
		virtual void
			SetCooling(int new_int)
				{}

		HeatManager
			*m_heatManager;

		const std::vector<Torso*>&
			GetTorsos()
		{
			return (m_Torsos);
		}

//		virtual void
//			SetSearchLightMode(bool fOn)
//				{}
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Subsystem vars
	protected:

		std::vector<Torso*>
			m_Torsos;

		SearchLight
			*searchLight;
//		bool
//			m_previousSearchLightState;
	public:
		void SetDmgModifier (int nIdx, int nDmgFactor); // jcem
        void RepairDamage (Stuff::Scalar fRepair); // jcem
	};
}
