//===========================================================================//
// File:	ai.hpp																	     //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
//	07/13/99  AHF	Created File                  //
//---------------------------------------------------------------------------//
// Copyright (C) 1999, Microsoft										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "adept\Adept.hpp"
#include "adept\Driver.hpp"
#include "AI_Graveyard.hpp"


namespace ElementRenderer
{
	class GroupElement;
};

namespace MechWarrior4
{
	class AI;
	class LancematePlug;
};
#include "mwobject.hpp"

#include "abl.h"

class CCommandLineServer;

namespace MW4AI
{
	extern HGOSHEAP g_AIHeap,g_MoverAIHeap,g_CombatAIHeap,g_RailHeap;

	typedef void (* AIExecuteFunction) (AI *curunit,Stuff::Time till,NameTable *table);

	const int AIExecutionDelta = 4;						// means once every fourth frame
	const int	NUM_MEMORY_CELLS=60;
	const Stuff::Scalar MOODMIN = 1;					// change the enums in MW4::AI_MOODS.HPP if you change this
	const Stuff::Scalar MOODMAX = 10;					// change the enums in MW4::AI_MOODS.HPP if you change this
	const Stuff::Scalar SKILL_MULT = 100.0f;			// mult for a normalized number to skill range
	enum { MAX_GLOBAL_TRIGGERS = 100 };					// maximum number of global triggers

	void ResetGlobalTriggers();

	extern int g_AIExecutionNumber;

	void SetupAIStagger (void);

	const int SORT_DEPTH=4;
#ifdef _ARMOR
	class CommandEntry : public Signature
#else
	class CommandEntry
#endif
	{
		friend class MechWarrior4::AI;

	protected:
		static Stuff::MemoryBlockOf<CommandEntry> *m_EmptyCommand;

		bool highlevel;
		int commandType;
		Stuff::Time startTime;
		int from;
		union
		{
			Stuff::Scalar		dataScalar;
			int							dataInt;
			void						*dataPtr;
		};
		Stuff::Point3D		dataPoint;
		bool							dataBoolean;		

	public:
		CommandEntry (int type,bool high)
		{
			commandType = type;
			highlevel = high;	
		}

		~CommandEntry (void)
		{}

		bool HighLevel (void) const
		{ return highlevel; }
		Stuff::Time StartTime (void) const
		{	return startTime;	}
		
		void StartTime (Stuff::Time time)
		{ startTime = time; }

		int Type (void) const
		{ return commandType; }

		void DataScalar (Stuff::Scalar value)
		{ dataScalar = value;	}
		Stuff::Scalar DataScalar (void)
		{	return dataScalar; }
		
		void DataInt (int value)
		{ dataInt = value;	}
		int DataInt (void) const
		{	return dataInt; }

		void DataBoolean (bool value)
		{ dataBoolean = value;	}
		bool DataBoolean (void) const
		{	return dataBoolean; }
		
		void DataPtr (void *value)
		{ dataPtr = value;	}
		void *DataPtr (void)
		{	return dataPtr; }

		void DataPoint3D (Stuff::Point3D value)
		{ dataPoint = value;	}
		Stuff::Point3D DataPoint3D (void)
		{	return dataPoint; }
		
		void TestInstance()
		{}

		static CommandEntry *GetBlankCommand (void) { return (CommandEntry *) m_EmptyCommand->New (); }
		static void DoneCommand (CommandEntry *oldknow)  { m_EmptyCommand->Delete (oldknow); }
	
		void *operator new (size_t size) {return GetBlankCommand (); }
		void operator delete (void *value,size_t size) { DoneCommand ((CommandEntry *) value); }
	};

#if 0
	enum KNOWLEDGE_LEVEL {KNOW_LOCATION,KNOW_AFFILIATION,KNOW_CHASSIS,KNOW_TRUE};
	enum THREAT_LEVEL {IMMEDIATE_THREAT,POTENTIAL_THREAT,WARNING_THREAT,OPPORTUNITY_THREAT,NON_THREAT};

#ifdef _ARMOR	
	class AIKnowledge : public Signature
#else
	class AIKnowledge
#endif
	{
		friend class MechWarrior4::AI;
	private:
		static Stuff::MemoryBlockOf<AIKnowledge> *m_EmptyKnowledge;
	
	protected:
		AI *unit;
		KNOWLEDGE_LEVEL knowledge;
		THREAT_LEVEL threat;
		unsigned int subthreat;
	
		float validCount;							// decays over time
		AIKnowledge *next,*prev;
		AIKnowledge *sort_next,*sort_prev;
	
	public:
		AIKnowledge (void);
		~AIKnowledge (void);
	
		static AIKnowledge *GetBlankKnowledge (void) { return (AIKnowledge *) m_EmptyKnowledge->New (); }
		static void DoneKnowledge (AIKnowledge *oldknow)  { m_EmptyKnowledge->Delete (oldknow); }
	
		void *operator new (size_t size) {return GetBlankKnowledge (); }
		void operator delete (void *value,size_t size) { DoneKnowledge ((AIKnowledge *) value); }
		
		void TestInstance()
		{}
	};
#endif

};



namespace MechWarrior4
{
	const int DEFAULT_MEMORYCELL_VALUES = 10;
	extern DWORD Executed_AI_Count;
	extern DWORD Path_Calcs_Count;
	extern DWORD GridPath_Calcs_Count;
	extern DWORD QuickPath_Calcs_Count;
	extern DWORD QuickRail_Calcs_Count;
	extern DWORD FailedPath_Calcs_Count;

	//##########################################################################
	//##################    AIDriver::CreateMessage    #########################
	//##########################################################################

	class AI__CreateMessage:public Driver__CreateMessage
	{
	public:
		int entityID;
		char scriptName[128];
		Stuff::Scalar cellValues[DEFAULT_MEMORYCELL_VALUES];
		int gunnerySkill;
		int pilotSkill;
		int eliteSkill;
		int minHeatSkill;
		int maxHeatSkill;

		int sensorSkill;
		int blindFightingSkill;
		int longRangeGunnerySkill;
		int shortRangeGunnerySkill;

		int towardsGunnerySkill;
		int towardsPilotSkill;
		int towardsEliteSkill;

//		char scriptParams[2000];

		AI__CreateMessage(
			 size_t length,
			 int priority,
			 int message_flags,
			 Stuff::RegisteredClass::ClassID class_id,
			 int replicator_flags,
			 const ResourceID& data_list_id,
			 const Stuff::LinearMatrix4D &creation_matrix,
			 Stuff::Scalar age,
			 int execution_state,
			 int name_id,
			 int entity_alignment,
			 int drop_zone,
			 int entity_name_id,
			 const char *script_name,
			 Stuff::Scalar cell_values[DEFAULT_MEMORYCELL_VALUES],
			 int gun,
			 int pilot,
			 int elite,
			 int minheat,
			 int maxheat,
			 int sensor,
			 int blind,
			 int longrange,
			 int shortrange,
			 int tgun,
			 int tpilot,
			 int telite
//			 / char* script_params
			 ):
		Driver__CreateMessage(
			 length,
			 priority,
			 message_flags,
			 class_id,
			 replicator_flags,
			 data_list_id,
			 creation_matrix,
			 age,
			 execution_state,
			 name_id,
			 entity_alignment,
			 drop_zone
			 ),
		entityID(entity_name_id)
		{
				Check_Pointer(script_name);
				Str_Copy(scriptName, script_name, sizeof(scriptName));
				memcpy (cellValues,cell_values,sizeof (Stuff::Scalar)*DEFAULT_MEMORYCELL_VALUES);
				gunnerySkill = gun;
				pilotSkill = pilot;
				eliteSkill = elite;
				minHeatSkill = minheat;
				maxHeatSkill = maxheat;
				sensorSkill = sensor;
				blindFightingSkill = blind;
				longRangeGunnerySkill = longrange;
				shortRangeGunnerySkill = shortrange;
				towardsGunnerySkill = tgun;
				towardsPilotSkill = tpilot;
				towardsEliteSkill = telite;

//				strncpy(scriptParams,script_params,2000);
		}

		static void ConstructCreateMessage(Script *script);
	};

	typedef Driver__ReceiveDropZoneMessage    AI__ReceiveDropZoneMessage;

	//##########################################################################
	//###########################   AI    ######################################
	//##########################################################################

	class AI: public Driver
	{
		friend class LancematePlug;
		friend void MW4AI::SetupAIStagger (void);
	public:
		static void InitializeClass();
		static void TerminateClass();

		static ClassData *DefaultData;
		static ElementRenderer::GroupElement *m_GroupElement;
		static int m_BoardGameMechAI,m_LastBoardGameMechAI;
		static int m_BoardGameVehicleAI,m_LastBoardGameVehicleAI;
		static int m_ActiveMechAI,m_LastActiveMechAI;
		static int m_ActiveVehicleAI,m_LastActiveVehicleAI;

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Inheritance Support
		//
	public:
		typedef AI__CreateMessage       CreateMessage;
		typedef AI__ReceiveDropZoneMessage    DropZoneMessage;

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Run-time Construction and Destruction Support
		//
	public:

		static AI* Make(CreateMessage *message,ReplicatorID *base_id);
		Replicator::CreateMessage* SaveMakeMessage(Stuff::MemoryStream *stream, Adept::ResourceFile *res_file);

		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);

		void Respawn(Entity::CreateMessage *message);

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

		~AI();

	public:
		bool LoadScript (char *filename);
		void UnloadScript (void);
		bool ReloadScript (ABL::ABLError *err);


		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Command Support
		//

	protected:
		virtual void ExecuteHighCommand (MW4AI::CommandEntry *command);
		virtual void ExecuteLowCommand (MW4AI::CommandEntry *command);

		MW4AI::CommandEntry *CreateAdjustRatioCommand (Stuff::Time start=gos_GetElapsedTime ())
		{ return CreateBaseCommand (ADJUSTRATIO_LOWID,false,start); }

	public:
		enum
		{
			ENDMISSION_HIGHID,
			EJECT_HIGHID,
			SETPROP_HIGHID,
			NextHighCommandID
		};

		enum
		{
			ADJUSTRATIO_LOWID,
			NextLowCommandID
		};


		virtual void PostCollisionExecute(Time till);
		MW4AI::CommandEntry *CreateBaseCommand (int type,bool high,Stuff::Time start=gos_GetElapsedTime ())
		{
			MW4AI::CommandEntry *toret;

			toret = new MW4AI::CommandEntry (type,high);
			Check_Object (toret);
			toret->StartTime (start);
			return toret;
		}

		MW4AI::CommandEntry *CreateEndMissionCommand (Stuff::Time start=gos_GetElapsedTime ())
		{ return CreateBaseCommand (ENDMISSION_HIGHID,true,start); }
		MW4AI::CommandEntry *CreateEjectCommand (Stuff::Time start=gos_GetElapsedTime ())
		{ return CreateBaseCommand (EJECT_HIGHID,true,start); }
		MW4AI::CommandEntry *CreateSetPropCommand (Stuff::Time start=gos_GetElapsedTime ())
		{ return CreateBaseCommand (SETPROP_HIGHID,true,start); }

		void ExecuteCommand (MW4AI::CommandEntry *command);

		Entity *getEntity (void) const
		{ return vehicle;	}

		virtual void EnsureNotTargeting(Adept::ObjectID object) {};

		void SelfDestruct (void);
		bool m_SelfDestructing;

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Skill Support
		//

	protected:
		int m_GunnerySkill;
		int m_PilotSkill;
		int m_EliteSkill;
		int m_MinHeatSkill;
		int m_MaxHeatSkill;
		int m_SensorSkill;
		int m_BlindFightingSkill;
		int m_LongRangeGunnerySkill;
		int m_ShortRangeGunnerySkill;

		int m_TowardsPilotSkill;
		int m_TowardsGunnerySkill;
		int m_TowardsEliteSkill;
		int m_StartGunnerySkill;
		int m_StartPilotSkill;
		int m_StartEliteSkill;

	public:
		int RootGunnerySkill (void) const
		{ return m_GunnerySkill; }
		int RootPilotSkill (void) const
		{ return m_PilotSkill; }
		int RootSensorSkill (void) const
		{ return m_SensorSkill; }
		int RootBlindFightingSkill (void) const
		{ return m_BlindFightingSkill; }
		int RootLongRangeGunnerySkill (void) const
		{ return m_LongRangeGunnerySkill; }
		int RootShortRangeGunnerySkill (void) const
		{ return m_ShortRangeGunnerySkill; }
		int RootEliteSkill (void) const
		{ return m_EliteSkill; }
		int RootMinHeatSkill (void) const
		{ return m_MinHeatSkill; }
		int RootMaxHeatSkill (void) const
		{ return m_MaxHeatSkill; }

		int GunnerySkill (void) const;
		int PilotSkill (void) const;
		int SensorSkill (void) const;
		int BlindFightingSkill (void) const;
		int LongRangeGunnerySkill (void) const;
		int ShortRangeGunnerySkill (void) const;
		int EliteSkill (void) const;
		int MinHeatSkill (void) const;
		int MaxHeatSkill (void) const;
		void GunnerySkill (int newvalue)
		{
			m_GunnerySkill = newvalue;
			m_StartGunnerySkill = newvalue;
		}
		virtual void AddTowardGunnery (int value=-1);			// -1 means default add value

		void PilotSkill (int newvalue)
		{
			m_PilotSkill = newvalue;
			m_StartPilotSkill = newvalue;
		}

		virtual bool PilotSkillCheck (Stuff::Scalar damage_amount,bool jump);			// negative damage_amount means ignore damage for possible check

		virtual void AddTowardPilot (int value = -1);			// -1 means default add value

		void SensorSkill (int newvalue)
		{ m_SensorSkill = newvalue; }
		
		void BlindFightingSkill (int newvalue)
		{ m_BlindFightingSkill = newvalue; }
		
		void LongRangeGunnerySkill (int newvalue)
		{ m_LongRangeGunnerySkill = newvalue; }
		
		void ShortRangeGunnerySkill (int newvalue)
		{ m_ShortRangeGunnerySkill = newvalue; }

		void EliteSkill (int newvalue)
		{
			m_EliteSkill = newvalue;
			m_StartEliteSkill = newvalue;
		}
		virtual void AddTowardElite (int value=-1);				// -1 means default add value
																									
		void MinHeatSkill (int newvalue)
		{ m_MinHeatSkill = newvalue; }

		void MaxHeatSkill (int newvalue)
		{ m_MaxHeatSkill = newvalue; }

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Mood Support
		//

	protected:

		Stuff::Scalar m_EntropyMood;
		Stuff::Scalar m_CurrentMood;
		Stuff::Scalar m_LastMoodChange;
		bool m_UsingCoolant;

	public:

		Stuff::Scalar EntropyMood () const
		{ return m_EntropyMood; }
		Stuff::Scalar CurrentMood () const
		{ return m_CurrentMood; }
		void EntropyMood (Stuff::Scalar newvalue)
		{
			Verify (newvalue>=MW4AI::MOODMIN);
			Verify (newvalue<=MW4AI::MOODMAX);
			m_EntropyMood = newvalue;
		}
		void CurrentMood (Stuff::Scalar newvalue)
		{
			Verify (newvalue>=MW4AI::MOODMIN);
			Verify (newvalue<=MW4AI::MOODMAX);
			m_CurrentMood = newvalue;
			m_LastMoodChange = (Stuff::Scalar)gos_GetElapsedTime ();
		}
		void UpdateMood();
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Combat Support
		//
	protected:
		Stuff::SlotOf<Entity *>	m_CurrentTarget;

		bool m_IgnoringFriendlyFire;

		ObjectID m_ShotBy;
		Stuff::Scalar m_LastTimeShot;

		ObjectID m_RammedBy;
		Stuff::Scalar m_LastTimeRammed;

	public:
		Entity *Target (void)
		{ return m_CurrentTarget.GetCurrent(); }
		void Target (Entity *newtarget);

		void SetIgnoringFriendlyFire(bool fIgnoreFriendlyFire);

	protected:
		virtual bool GetIgnoringFriendlyFire() const;

	public:
		Entity* ShotBy(Stuff::Time lastvalid) const
		{
			if (lastvalid < m_LastTimeShot)
			{
				if ((NameTable::GetInstance() == 0) ||
					(m_ShotBy == 0xFFFFFFFF))
				{
					return (0);
				}

				Entity* rv = NameTable::GetInstance()->FindData(m_ShotBy);

				if ((rv == 0) ||
					(rv->IsDestroyed() == true) ||
					(rv == getEntity()))
				{
					return (0);
				}

				if ((getEntity() != 0) &&
					(rv->GetAlignment() == getEntity()->GetAlignment()) &&
					(GetIgnoringFriendlyFire() == true))
				{
					return (0);
				}

				return (rv);
			}
			return (0);
		}

		virtual bool GetLeaderAlignment(int& alignment);

		Entity* RammedBy(Stuff::Time lastvalid) const;

		virtual void NotifyShot(ObjectID who, bool fCanBeRecursive = true);
		virtual void NotifyShotFired(const Adept::Entity::CollisionQuery& query, MWObject& shooter);
		virtual void NotifyProjectileApproaching(const Stuff::Point3D& origin) {};
		virtual void NotifyLastShotWasFriendlyFire(Adept::Entity& who_i_hit) {};
		virtual void NotifyInternalHit() {};
		virtual void NotifyComponentDestroyed(int zone)	{};
		virtual void NotifyShutdown() {};
		virtual void NotifyAlignmentChanged() {};
		virtual void NotifyInTargetingReticule(MWObject& who) {};
		virtual void NotifyHeatShutdownImminent();
		virtual void NotifyFailedPilotingRoll() {};
		virtual void NotifyFriendlyFire(Adept::Entity& who_shot_me) {};
		virtual void NotifyRespawned();

		virtual bool Attacking() const	{ return (false); }

		virtual bool ReactToCollision(Stuff::DynamicArrayOf<CollisionData> *collisions,bool& shoulddamage);

		Stuff::Scalar GetIsShotRadius() const;
		void SetIsShotRadius(Stuff::Scalar radius);

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Execution Support
		//
	protected:

		int
			GetTableArray()
				{Check_Object(this); return NameTable::AIArray;}
		enum
		{
			Sensor_Area,
			Knowledge_Area,
			Communication_Area,
			NextAIAreaID
		};

		Stuff::Scalar				memory[MW4AI::NUM_MEMORY_CELLS];
		std::string scriptName;
		long									aiScriptHandle;
		ABL::ABLModulePtr			aiBrain;
		void *aiDLLBrain;
		MW4AI::AIExecuteFunction			aiDLLExecute;

		bool m_FirstFrame;
    bool m_SecondFrame;
		bool m_Active;					// from shutdown and startup commands
		void (*m_DebugPrintCallback)(char* s);
		bool m_Debugging;
		bool m_Dead;
		bool m_ScriptRunning;
		int m_ExecutionNumber;
		bool m_AlwaysActive;		// true if the this ai should always be active
		static int m_AlwaysActiveCount;

		Stuff::Scalar m_IsShotRadius;

		static MW4AI::Graveyard* m_Graveyard;
		bool	m_StartupRequest;
		bool	m_ShutdownRequest;

		static bool m_GlobalTriggers[MW4AI::MAX_GLOBAL_TRIGGERS];

	public:
		bool m_Deactive;				// from distance to player
		bool m_TurningOn;				// true when the vehicle is being told to activate
		virtual void TurnOn (void);
		virtual void TurnOff (void);
		bool TurningOn (void)
		{ return m_TurningOn;  }

		static MW4AI::Graveyard* GetGraveyard();

		static void CreateGraveyard();
		static void DestroyGraveyard();

		virtual bool ShouldRunScript()
		{	return (true);	}

		virtual void Shutdown (void);
		virtual void Startup (void);
		bool ShouldRun (bool execnumonly=false) const;
		void ExecutionNumber (int num)
		{ m_ExecutionNumber = num; }
		void AlwayActive (bool p1);

		const char* GetScriptName()
		{ return (scriptName.c_str()); }

		ABL::ABLModulePtr	Brain (void)
		{ return aiBrain; }
		void StopScript (void)
		{ m_ScriptRunning = false; }
		void StartScript (void)
		{ m_ScriptRunning = true; }

		void Debug (bool flag,void (*printCallback)(char* s))
		{
			m_Debugging = flag;
			m_DebugPrintCallback = printCallback;
		}
#ifdef LAB_ONLY
		void DebugMessage (char *s)
		{
			if (m_DebugPrintCallback)
				m_DebugPrintCallback (s);
		}
#else
		void DebugMessage (char *s)
		{	}
#endif

		virtual void Info (void (*printCallback)(char* s));

		void PreCollisionExecute(Stuff::Time till);
		void DetermineExecution(Stuff::Time till);

		virtual void StartExecute (void);
		virtual void StopExecute (void);
		virtual void Die (void);
		virtual void Eject (void);
		bool Dead (void) const
		{ return m_Dead; }

		bool CanAct() const
		{
			if ((m_Active == true) &&
				(m_Dead == false))
			{
				return (true);
			}

			return (false);
		}

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Memory Support
		//
	public:

		void IntegerMemory (long index, long val)
		{
			Verify (index >=0);
			Verify (index <MW4AI::NUM_MEMORY_CELLS);
			memory[index] = (float) val;
		}

		void RealMemory (long index, Stuff::Scalar val)
		{
			Verify (index >=0);
			Verify (index <MW4AI::NUM_MEMORY_CELLS);
			memory[index] = val;
		}

		long IntegerMemory (long index) const
		{
			Verify (index >=0);
			Verify (index <MW4AI::NUM_MEMORY_CELLS);
			return((long) memory[index]);
		}

		Stuff::Scalar RealMemory (long index) const
		{
			Verify (index >=0);
			Verify (index <MW4AI::NUM_MEMORY_CELLS);
			return(memory[index]);
		}

		static bool GetGlobalTrigger(int index)
		{
			Verify(index >= 0);
			Verify(index < MW4AI::MAX_GLOBAL_TRIGGERS);

			return (m_GlobalTriggers[index]);
		}

		static void SetGlobalTrigger(int index, bool value)
		{
			Verify(index >= 0);
			Verify(index < MW4AI::MAX_GLOBAL_TRIGGERS);

			m_GlobalTriggers[index] = value;
		}

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

		virtual bool GetExtendedSensorData(std::vector<MWObject*>& sensor_data_list)
		{
			return (false);
		}

		virtual Stuff::Scalar GetLeastSquaredSensorDistance(const Stuff::Point3D& point) const;

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Lancemate Support
		//
	protected:
		LancematePlug *m_Lancemate;

	public:
		void ConnectLancemate(LancematePlug *lancemate);
		void DisconnectLancemate(void);
		LancematePlug *GetLancemate (void) const
		{ return m_Lancemate; }

		Stuff::MString GetTalkerSuffix() const;
		
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Misc Support
		//

	public:
		void ConnectEntity(MWObject *entity);

		ResourceID interfaceResourceID;

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// File Support
		//
		void SaveInstanceText(Stuff::Page *page);

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

#if 1
#define AI_LOGIC(string) PRECOLLISION_LOGIC("AI::" string)
#else
#define AI_LOGIC(string)
#endif

#if 1
#define MOVER_LOGIC(string) AI_LOGIC("Mover::" string)
#else
#define MOVER_LOGIC(string)
#endif

#if 1
#define COMBAT_LOGIC(string) AI_LOGIC("Combat::" string)
#else
#define COMBAT_LOGIC(string)
#endif

#if 1
#define ABL_LOGIC(string) AI_LOGIC("ABL::" string)
#else
#define ABL_LOGIC(string)
#endif

#if 1
#define PATH_LOGIC(string) AI_LOGIC("Path::" string)
#else
#define PATH_LOGIC(string)
#endif
