//***************************************************************************
//
//								ABLXSTD.CPP
//
//***************************************************************************
#include "MW4Headers.hpp"
#include <abl.h>
#include <ablheap.h>
#include <ablfile.h>
#include "ablfuncs.hpp"
#include "ablprofiler.hpp"
#include <ai.hpp>
#include <Adept\player.hpp>
#include "vehicle.hpp"
#include "moverai.hpp"
#include "combatai.hpp"
#include "mwmission.hpp"
#include "bucket.hpp"
#include "mwdamageobject.hpp"
#include "AI_FindObject.hpp"
#include "AI_DebugRenderer.hpp"
#include "AI_Groups.hpp"
#include "AI_Squad.hpp"
#include "AI_Graveyard.hpp"
#include "AI_LancemateCommands.hpp"
#include "aiutils.hpp"
#include "objective.hpp"
#include "NavPoint.hpp"
#include "planeai.hpp"
#include "Building.hpp"
#include "mwplayer.hpp"
#include "vehicleinterface.hpp"
#include "CameraShip.hpp"
#include "EffectGenerator.hpp"
#include <Adept\AudioRenderer.hpp>
#include <adept\map.hpp>
#include <Adept\CollisionGrid.hpp>
#include <Adept\CollisionVolume.hpp>
#include <ElementRenderer\StateChange.hpp>
#include "move_formation.hpp"
#include "MWCampaign.hpp"
#include "AI_Specials.hpp"
#include <Adept\Controls.hpp>
#include "Salvage.hpp"
#include "mwapplication.hpp"
#include <ElementRenderer\CameraElement.hpp>
#include "flag.hpp"
#include "MWGame.hpp"
#include "sensor.hpp"
#include "Team.hpp"
#include <GameOS\ToolOS.hpp>
#include <Compost\TerrainTextureLogistic.hpp>
#include "lancemate.hpp"
#include "MechLabHeaders.h"
#include "mwguimanager.hpp"
#include "hudtimer.hpp"
#include "hudhelparrow.hpp"
#include "hudcomm.hpp"
#include "DamageDispatch.hpp"
#include "AI_Action.hpp"
#include "AI_Damage.hpp"
#include "weapon.hpp"
#include "ABLAudio.hpp"
#include <Adept\Zone.hpp>
#include <Adept\DropZone.hpp>
#include <Adept\AudioCommand.hpp>
#include "mw4shell.hpp"

#include "nglog_mw4.hpp"

#pragma warning (disable : 4189)

using namespace Stuff;
using namespace MW4AI;

namespace MW4AI
{
	bool BoardDropShip (stlport::vector<MoverAI *>& GroupList,Dropship *drop);
}

namespace ABL
{
	bool g_MissionMusic = true;
	inline signed int double2long(double _in)
	{
		_in+=6755399441055744.0;
		return(*(signed int*)&_in);
	}

	ObjectID most_recent_no_team_nav = -1;

	const Stuff::Scalar who_shot_duration = 5.0f;
	const Stuff::Scalar who_rammed_duration = 5.0f;

	const char* talker_suffixes[]={
		"_IAN.wav{handle}",
		"_RAT.wav{handle}",
		"_CAS.wav{handle}",
		"_GON.wav{handle}",
		"_JEN.wav{handle}",
		"_TER.wav{handle}",
		"_DAM.wav{handle}",
		"_RES.wav{handle}",
		"_65C.wav{handle}",
		"_EV1.wav{handle}",
		"_EV2.wav{handle}",
		"_SAL.wav{handle}",
		"_REC.wav{handle}",
		"_SUP.wav{handle}",
		"_FO1.wav{handle}",
		"_FO2.wav{handle}",
		"_FO3.wav{handle}",
		"_FO4.wav{handle}",
		"_FO5.wav{handle}",
		"_FO6.wav{handle}",
		"_PI1.wav{handle}",
		"_PI2.wav{handle}",
		"_PI3.wav{handle}",
		"_PI4.wav{handle}",
		"_ART.wav{handle}",
		"_SHE.wav{handle}",
		"_BD1.wav{handle}",
		"_BD2.wav{handle}",
		"_FOX.wav{handle}",
		"_KIL.wav{handle}",
		"_SGT.wav{handle}",
		"_ROM.wav{handle}",
		"_XRY.wav{handle}",
		"_CCG.wav{handle}",
		"_ERL.wav{handle}",
		"_PA1.wav{handle}",
		"_PA2.wav{handle}",
		"_PA3.wav{handle}",
		"_PA4.wav{handle}",
		"_BRV.wav{handle}",
		"_CHL.wav{handle}",
		"_DEN.wav{handle}",
		"_RCG.wav{handle}",
		"_VRD.wav{handle}",
		"_VOR.wav{handle}",
		"_HQ1.wav{handle}",
		"_HQ2.wav{handle}",
		"_HQ3.wav{handle}",
		"_MED.wav{handle}",
		"_SFQ.wav{handle}",
		"_CJK.wav{handle}",
		"_ABC.wav{handle}",
		"_BRK.wav{handle}",
		"_CST.wav{handle}",
		"_ROL.wav{handle}",
		"_WIL.wav{handle}",
		"_EPS.wav{handle}",
		"_PET.wav{handle}",
		"_EP2.wav{handle}",
		"_BET.wav{handle}"					// the last one should always be betty
	};
	
	int FindTalkerID (const char *suf)
	{
		int i;
		for (i=0;i<(sizeof (talker_suffixes) / sizeof (const char *));i++)
		{
			if (!strnicmp (suf,talker_suffixes[i],4))
			{
				return i;
			}
		}
		return -1;
	}

//***************************************************************************

//----------
// EXTERNALS

	extern StackItem       returnValue;
	extern bool          eofFlag;
	extern bool          ExitWithReturn;
	extern bool          ExitFromTacOrder;

	extern long       level;
	extern long       execLineNumber;
	extern long       FileNumber;

	extern char*      codeSegmentPtr;
	extern TokenCodeType  codeToken;

	extern StackItem*   stack;
	extern StackItemPtr   tos;
	extern StackItemPtr   stackFrameBasePtr;
	extern SymTableNodePtr  CurRoutineIdPtr;
	extern long       CurModuleHandle;

	extern TypePtr      IntegerTypePtr;
	extern TypePtr      RealTypePtr;
	extern TypePtr      BooleanTypePtr;
	extern TypePtr      CharTypePtr;

	extern ABLModulePtr   CurModule;

//--------
// GLOBALS

	extern TokenCodeType     ExitRoutineCodeSegment[];
	extern TokenCodeType     ExitOrderCodeSegment[];

	extern UserHeapPtr    AblStackHeap;

	extern long MaxLoopIterations;

	extern DebuggerPtr    debugger;

#define ABL_NO_UNIT (-2)


	const int ABL_ERROR_STRING_SIZE = 2048;
	char ablErrorString[ABL_ERROR_STRING_SIZE];

	char *ablERROR(char *str)
	{
		ablErrorString[0] = 0;
		ABL_runtimeErrorString (ablErrorString,ABL_ERROR_STRING_SIZE);
		Str_Cat (ablErrorString," ",ABL_ERROR_STRING_SIZE);
		Str_Cat (ablErrorString,str,ABL_ERROR_STRING_SIZE);
		return ablErrorString;
	}

//---------------------
// MW SPECIFIC STUFF...
	MechWarrior4::Vehicle *CurVehicle = NULL;
	extern MechWarrior4::AI             *CurWarrior;
	MechWarrior4::MoverAI *CurMoverAI = NULL;

	char*      ExceptionGameMsg;
	char       ChunkDebugMsg[5120];

#define DEBUG_MISSION_SCRIPT
#define	MAX_MISSION_MSGS	1000
	long NumMissionScriptMessages = 0;
	short MissionScriptMessageLog[MAX_MISSION_MSGS][3];

#ifdef USE_OBJECTS
//extern TerrainPtr		land;

//extern CreatedPartRoster createdPartRoster[];
//extern long currentCreatorPart;
//extern long languageOffset;

#endif

//***************************************************************************
// DEBUG ROUTINES
//***************************************************************************

	void DebugMissionScriptMessages (void)
	{
#if 0
		ChunkDebugMsg[0] = NULL;

		char outString[512];

		sprintf(outString, "\n%d Mission Script Messages\n\n", NumMissionScriptMessages);
		strcat(ChunkDebugMsg, outString);

		for (long i = 0; i < NumMissionScriptMessages; i++)
		{
			sprintf(outString, "line %5d: %5d, %5d\n",
							MissionScriptMessageLog[i][0],
							MissionScriptMessageLog[i][1],
							MissionScriptMessageLog[i][2]);
			strcat(ChunkDebugMsg, outString);
		}

		File* debugFile = new File;
		debugFile->create("scriptmsg.dbg");
		debugFile->writeString(ChunkDebugMsg);
		debugFile->close();
		delete debugFile;
		debugFile = NULL;

		ExceptionGameMsg = ChunkDebugMsg;
#endif
	}

//***************************************************************************
// USEFUL ABL HELP ROUTINES
//***************************************************************************

	inline void startFunction (void)
	{

		//---------------------------
		// Grab the opening LPAREN...
		getCodeToken();
	}

//---------------------------------------------------------------------------

	inline void endFunction (void)
	{

		//-----------------------
		// Grab closing RPAREN...
		getCodeToken();
	}

//---------------------------------------------------------------------------
// ABLContext: a  helper class that will call startFunction() and endFunction()
// for you automatically.  To use, create an ABLContext object at the start of
// your function.  Instantiating the object will call startFunction(), and when it
// goes out of scope, endFunction() will be called.

	class ABLContext
	{
	public:
		ABLContext()
		{
			startFunction();
		}
		~ABLContext()
		{
			endFunction();
		}
	};

//---------------------------------------------------------------------------
// DECLARE_ABL_CONTEXT: a macro that automatically gives you an ABLContext object

#define DECLARE_ABL_CONTEXT ABLContext abl_context;


	Stuff::Point3D popPoint()
	{
		Stuff::Point3D loc;

		getCodeToken();
		SymTableNodePtr idPtr = getCodeSymTableNodePtr();
		baseType(execVariable(idPtr, USE_REFPARAM));
		long* waypoint = (long*)(&((StackItemPtr)tos->address)->integer);
		Check_Pointer (waypoint);
		pop();

		loc.x = (float) waypoint[0];
		loc.y = (float) waypoint[1];
		loc.z = (float) waypoint[2];

		return (loc);
	}


//---------------------------------------------------------------------------

	template <class T>
	T* GetObjectForID(long object_id)
	{
		if (object_id == -1)
		{
			return(CurWarrior);
		}

		int array_index = NameTableEntry::GetArrayIndex(object_id);
		ablREPORT(array_index >= 0,ablERROR ("invalid object id from abl"));
		ablREPORT(array_index < NameTable::GetInstance()->TableSize,ablERROR ("invalid object id from abl"));
		Entity* ent = NameTable::GetInstance()->FindData(object_id);
		ablREPORT (ent,ablERROR ("invalid object id from abl"));
		ablREPORT (ent->IsDerivedFrom (T::DefaultData),ablERROR ("tried to convert an objectid to the wrong type of object, probably from calling a function with the wrong type of objectid"));

		if (!ent)
			return NULL;
		if (((int) ent) == -1)
			return NULL;
		return(Cast_Object(T*,ent));
	}
	
	Flag* GetFlagForID(long object_id)
	{
		int array_index = NameTableEntry::GetArrayIndex(object_id);
		ablREPORT(array_index >= 0,ablERROR ("invalid flag id from abl"));
		ablREPORT(array_index < NameTable::GetInstance()->TableSize,ablERROR ("invalid flag id from abl"));
		Entity* ent = NameTable::GetInstance()->FindData(object_id);
		ablREPORT (ent,ablERROR ("invalid flag id from abl"));
		ablREPORT (ent->IsDerivedFrom (Flag::DefaultData),ablERROR ("tried to convert an objectid to the wrong type of object, probably from calling a function with the wrong type of objectid"));

		if (!ent)
			return NULL;
		if (((int) ent) == -1)
			return NULL;
		return(Cast_Object(Flag*,ent));
	}

	MechWarrior4::MWObject* GetMWObjectForID(long object_id)
	{
		if (object_id == -1)
		{
			if (CurWarrior == 0)
			{
				return (0);
			}

			Adept::Entity* entity = CurWarrior->getEntity();

			if ((entity != 0) &&
				(entity->IsDerivedFrom(MWObject::DefaultData) == true))
			{
				return (Cast_Object(MWObject*,entity));
			}

			return (0);
		}

		int array_index = NameTableEntry::GetArrayIndex(object_id);
		ablREPORT(array_index >= 0,ablERROR ("invalid object id from abl"));
		ablREPORT(array_index < NameTable::GetInstance()->TableSize,ablERROR ("invalid object id from abl"));
		Entity* ent = NameTable::GetInstance()->FindData(object_id);

		if (!ent)
			return NULL;
		if (((int) ent) == -1)
			return NULL;

		if (ent->IsDerivedFrom(AI::DefaultData) == true)
		{
			AI* ai = Cast_Object(AI*,ent);
			Check_Object(ai);

			Adept::Entity* entity = ai->getEntity();

			if ((entity != 0) &&
				(entity->IsDerivedFrom(MWObject::DefaultData) == true))
			{
				return (Cast_Object(MWObject*,entity));
			}

			return (0);
		}
		ablREPORT (ent->IsDerivedFrom(MWObject::DefaultData),ablERROR ("tried to convert an objectid to the wrong type of object, probably from calling a function with the wrong type of objectid"));

		return(Cast_Object(MWObject*,ent));
	}

	MechWarrior4::AI* GetAIForID(long object_id)
	{
		if (object_id == -1)
		{
			return (CurWarrior);
		}

		int array_index = NameTableEntry::GetArrayIndex(object_id);
		ablREPORT(array_index >= 0,ablERROR ("invalid object id from abl"));
		ablREPORT(array_index < NameTable::GetInstance()->TableSize,ablERROR ("invalid object id from abl"));
		Entity* ent = NameTable::GetInstance()->FindData(object_id);
		ablREPORT(ent,ablERROR ("invalid object id from abl"));

		if (!ent)
			return NULL;
		if (((int) ent) == -1)
			return NULL;

		if ((ent->IsDerivedFrom(AI::DefaultData) == false) &&
			(ent->IsDerivedFrom(MWObject::DefaultData) == true))
		{
			MWObject* mwobject = Cast_Object(MWObject*,ent);
			return (mwobject->GetAI());
		}

		ablREPORT(ent->IsDerivedFrom(AI::DefaultData),ablERROR("tried to convert an objectid to the wrong type of object, probably from calling a function with the wrong type of objectid"));

		return(Cast_Object(AI*,ent));
	}

	MechWarrior4::MoverAI* GetMoverAIForID(long object_id)
	{
		AI* ai = GetAIForID(object_id);

		if ((ai != 0) &&
			(ai->IsDerivedFrom(MoverAI::DefaultData) == true))
		{
			return (Cast_Object(MoverAI*,ai));
		}
		
		ablREPORT(false,ablERROR("tried to convert an objectid to the wrong type of object, probably from calling a function with the wrong type of objectid"));

		return (0);
	}

	MechWarrior4::CombatAI* GetCombatAIForID(long object_id)
	{
		AI* ai = GetAIForID(object_id);

		if ((ai != 0) &&
			(ai->IsDerivedFrom(CombatAI::DefaultData) == true))
		{
			return (Cast_Object(CombatAI*,ai));
		}

//		ablREPORT(false,ablERROR("tried to convert an objectid to the wrong type of object, probably from calling a function with the wrong type of objectid"));
		return (0);
	}

	Adept::Entity* ConvertAIToEntity(Entity *who)			// if who is not an ai then just return it
	{
		if (who == 0)
		{
			ablREPORT(false,ablERROR("convert ai to entity called for a non object"));
			return (0);
		}

		if (who->IsDerivedFrom (AI::DefaultData) == true)
		{
			AI* temp = Cast_Object(AI *,who);
			return (temp->getEntity());
		}
		return who;
	}

	bool ObjectIDisGroup(long object_id)
	{
		return((object_id >> 24) == Adept::NameTable::Groups_Reserved);
	}

	bool ObjectIDisTeam(long object_id)
	{
		if ((object_id & 0x00F00000) > 0)
		{
			return ((object_id >> 24) == Adept::NameTable::Groups_Reserved);
		}

		return (false);
	}

	Group::identifier ObjectIDtoGroupID(long object_id)
	{
		ablREPORT(ObjectIDisGroup(object_id),ablERROR ("Bad group ID: must use GroupObjectID() to convert raw group ID to group object ID"));
		return(object_id & 0x00FFFFFF);
	}

	int ObjectIDtoTeamNumber(long object_id)
	{
		return((object_id & 0x000FFFFF) - 0x00F00000);
	}

	GroupContainer& GetGroupContainer()
	{
		Verify(Adept::Mission::GetInstance() != 0);
		Verify(Adept::Mission::GetInstance()->IsDerivedFrom(MechWarrior4::MWMission::DefaultData) == true);

		MechWarrior4::MWMission* mission = Cast_Object(MechWarrior4::MWMission*,Adept::Mission::GetInstance());
		Check_Object(mission);

		return(mission->GetGroupContainer());
	}

	typedef std::vector<MWObject*> mwobject_list;

	void GetVehiclesFromTeam(int team_number, mwobject_list& objects)
	{
		if ((team_number < 0) ||
			(team_number > 8))
		{
			return;
		}

		NameTable *table = NameTable::GetInstance();

		{
			int size(table->nameTableArray[NameTable::VehicleArray].GetLength());

			{for (int i = 0;
				  i < size;
				  ++i)
			{
				NameTableEntry *data;

				data = &table->nameTableArray [NameTable::VehicleArray][i];
				Adept::Entity* entity = data->dataPointer->GetCurrent ();

				if ((entity != 0) &&
					(entity->IsDestroyed() == false) &&
					(entity->IsDerivedFrom(Vehicle::DefaultData) == true))
				{
					Vehicle* vehicle = Cast_Object(Vehicle*,entity);

					if (vehicle->GetTeam() != MWApplication::No_Team)
					{
						if ((team_number == 0) ||
							(vehicle->GetTeam() == team_number - 1))
						{
							objects.push_back(vehicle);
						}
					}
				}
			}}
		}

		{
			int size(table->nameTableArray[NameTable::PlayerArray].GetLength());

			{for (int i = 0;
				  i < size;
				  ++i)
			{
				NameTableEntry *data;

				data = &table->nameTableArray [NameTable::PlayerArray][i];
				Adept::Entity* entity = data->dataPointer->GetCurrent ();

				if ((entity != 0) &&
					(entity->IsDerivedFrom(MWPlayer::DefaultData) == true))
				{
					MWPlayer* player = Cast_Object(MWPlayer*,entity);

					if ((player->vehicle != 0) &&
						(player->vehicle->IsDestroyed() == false) &&
						(player->vehicle->IsDerivedFrom(Vehicle::DefaultData) == true))
					{
						Vehicle* v = Cast_Object(Vehicle*,player->vehicle);

						if (v->GetTeam() != MWApplication::No_Team)
						{
							if ((team_number == 0) ||
								(v->GetTeam() == team_number - 1))
							{
								objects.push_back(v);
							}
						}
					}
				}
			}}
		}
	}

	void GetVehiclesFromGroup(Group::identifier group_id,
							  mwobject_list& objects,
							  bool can_be_dead = false)
	{
		Verify(Adept::NameTable::GetInstance() != 0);

		if (group_id & 0x00F00000)
		{
			GetVehiclesFromTeam(group_id - 0x00F00000,objects);
			return;
		}

		const GroupContainer& vgc = GetGroupContainer();
		if (vgc.GroupExists(group_id) == false)
		{
			return;
		}

		const Group& group = vgc.GetGroup(group_id);

		{for (Group::element_list::const_iterator i = group.GetElements().begin();
				 i != group.GetElements().end();
				 ++i)
			{
				Entity* e = Adept::NameTable::GetInstance()->FindData(*i);

				if ((e != 0) &&
					(e->IsDerivedFrom(MWObject::DefaultData) == true))
				{
					if ((can_be_dead == true) ||
						(e->IsDestroyed() == false))
					{
						MWObject* v = Cast_Object(MWObject*,e);
						Check_Object(v);
						objects.push_back(v);
					}
				}
			}}
	}

	template <class T>
	void GetAIsFromTeam(int team_number, std::vector<T*>& ais)
	{
		mwobject_list mwobjects;
		GetVehiclesFromTeam(team_number,mwobjects);

		{for (mwobject_list::const_iterator i = mwobjects.begin();
			  i != mwobjects.end();
			  ++i)
		{
			if (((*i)->GetAI() != 0) &&
				((*i)->GetAI()->IsDerivedFrom(T::DefaultData) == true))
			{
				T* p_ai = Cast_Object(T*,(*i)->GetAI());
				ais.push_back(p_ai);
			}
		}}
	}

	template <class T>
	void GetAIsFromGroup(Group::identifier group_id,
						 std::vector<T*>& ais)
	{
		Verify(Adept::NameTable::GetInstance() != 0);

		if (group_id & 0x00F00000)
		{
			GetAIsFromTeam<T>(group_id - 0x00F00000,ais);
			return;
		}

		const GroupContainer& vgc = GetGroupContainer();
		if (vgc.GroupExists(group_id) == false)
		{
			return;
		}

		const Group& group = vgc.GetGroup(group_id);

		{for (Group::element_list::const_iterator i = group.GetElements().begin();
			  i != group.GetElements().end();
			  ++i)
		{
			Entity* e = Adept::NameTable::GetInstance()->FindData(*i);

			if ((e != 0) &&
				(e->IsDestroyed() == false) &&
				(e->IsDerivedFrom(MWObject::DefaultData) == true))
			{
				MWObject* v = Cast_Object(MWObject*,e);
				Check_Object(v);

				if ((v->GetAI() != 0) &&
					(v->GetAI()->IsDerivedFrom(T::DefaultData) == true) &&
					(v->GetAI()->Dead() == false))
				{
					T* p_ai = Cast_Object(T*,v->GetAI());
					ais.push_back(p_ai);
				}
			}
		}}
	}
	
	bool IsDead(int id)
	{
		if (id < 0)
		{
			return (false);
		}

		MWObject* mwobject = GetMWObjectForID(id);

		if (mwobject != 0)
		{
			AI *who = GetAIForID(id);
			if ((who != 0) &&
				(who->Dead() == true))
			{
				return (true);
			}

			Check_Object(mwobject);
			return (mwobject->IsDestroyed());
		}

		return (true);
	}

	bool IsDead(const char* talker)
	{
		char s[5];
		{for (int i = 0; i < 4; ++i)
		{
			s[i] = talker[i];
		}}
		s[4] = 0;

		NameTable *table = NameTable::GetInstance();
		int size = table->nameTableArray[NameTable::AIArray].GetLength ();

		{for (int i=0;i<size;i++)
		{
			NameTableEntry *data = &table->nameTableArray[NameTable::AIArray][i];
			if ((data != 0) &&
				(data->dataPointer != 0) &&
				(data->dataPointer->GetCurrent() != 0))
			{
				AI* ai = Cast_Object(AI *,data->dataPointer->GetCurrent());

				if ((ai->getEntity() != 0) &&
					(ai->GetTalkerSuffix() == s) &&
					(ai->getEntity()->IsDerivedFrom(Mech::DefaultData) == true))
				{
					Mech* mech = Cast_Object(Mech*,ai->getEntity());

					if (mech->IsLanceMate() == true)
					{
						return (ai->Dead());
					}
				}
			}
		}}

		return (false);
	}

//---------------------------------------------------------------------------

	inline long popInteger (void)
	{

		getCodeToken();
		execExpression();
		long val = tos->integer;
		pop();

		return(val);
	}

//---------------------------------------------------------------------------

	inline float popReal (void)
	{

		getCodeToken();
		execExpression();
		float val = tos->real;
		pop();

		return(val);
	}

//---------------------------------------------------------------------------

	inline bool popBoolean (void)
	{

		getCodeToken();
		execExpression();
		long val = tos->integer;
		pop();

		return(val == 1);
	}

//---------------------------------------------------------------------------

	inline char* popStringPtr (void)
	{

		//--------------------------
		// Get destination string...
		getCodeToken();
		execExpression();
		char* stringPtr = (char*)tos->address;
		pop();

		return(stringPtr);
	}

//---------------------------------------------------------------------------

	inline long* popIntegerPtr (void)
	{

		getCodeToken();
		SymTableNodePtr idPtr = getCodeSymTableNodePtr();
		execVariable(idPtr, USE_REFPARAM);
		long* integerPtr = (long*)(&((StackItemPtr)tos->address)->integer);
		pop();

		return(integerPtr);
	}

//---------------------------------------------------------------------------

	inline float* popRealPtr (void)
	{

		getCodeToken();
		SymTableNodePtr idPtr = getCodeSymTableNodePtr();
		execVariable(idPtr, USE_REFPARAM);
		float* realPtr = (float*)(&((StackItemPtr)tos->address)->real);
		pop();

		return(realPtr);
	}

//---------------------------------------------------------------------------

	inline long peekInteger (void)
	{

		getCodeToken();
		execExpression();
		return(tos->integer);
	}

//---------------------------------------------------------------------------

	inline float peekReal (void)
	{

		getCodeToken();
		execExpression();
		return(tos->real);
	}

//---------------------------------------------------------------------------

	inline bool peekBoolean (void)
	{

		getCodeToken();
		execExpression();
		return(tos->integer == 1);
	}

//---------------------------------------------------------------------------

	inline char* peekStringPtr (void)
	{

		getCodeToken();
		execExpression();
		return((char*)tos->address);
	}

//---------------------------------------------------------------------------

	inline long* peekIntegerPtr (void)
	{

		getCodeToken();
		SymTableNodePtr idPtr = getCodeSymTableNodePtr();
		execVariable(idPtr, USE_REFPARAM);
		return((long*)(&((StackItemPtr)tos->address)->integer));
	}

//---------------------------------------------------------------------------

	inline float* peekRealPtr (void)
	{

		getCodeToken();
		SymTableNodePtr idPtr = getCodeSymTableNodePtr();
		execVariable(idPtr, USE_REFPARAM);
		return((float*)(&((StackItemPtr)tos->address)->real));
	}

//---------------------------------------------------------------------------

	inline void pokeInteger (long val)
	{

		tos->integer = val;
	}

//---------------------------------------------------------------------------

	inline void pokeReal (float val)
	{

		tos->real = val;
	}

//---------------------------------------------------------------------------

	inline void pokeBoolean (bool val)
	{

		tos->integer = val ? 1 : 0;
	}

//---------------------------------------------------------------------------

//---------------------------------------------------------------------------




//***************************************************************************

	TypePtr execStdReturn (SymTableNodePtr routineIdPtr)
	{

		memset(&returnValue, 0, sizeof(StackItem));
		if (CurRoutineIdPtr->typePtr)
		{
			//-----------------------------
			// Assignment to function id...
			StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr;
			long delta = level - CurRoutineIdPtr->level - 1;
			while (delta-- > 0)
				headerPtr = (StackFrameHeaderPtr)headerPtr->staticLink.address;

			StackItemPtr targetPtr = (StackItemPtr)headerPtr;
			TypePtr targetTypePtr = (TypePtr)(CurRoutineIdPtr->typePtr);
			getCodeToken();

			TypePtr baseTargetTypePtr = baseType(targetTypePtr);

			//---------------------------------------------------------------
			// Routine execExpression() leaves the expression value on top of
			// stack...
			getCodeToken();
			TypePtr expressionTypePtr = execExpression();

			//--------------------------
			// Now, do the assignment...
			if ((targetTypePtr == RealTypePtr) && (baseType(expressionTypePtr) == IntegerTypePtr))
			{
				//-------------------------
				// integer assigned to real
				targetPtr->real = (float)(tos->integer);
			}
			else if ((targetTypePtr->form == FRM_ARRAY)	/*|| (targetTypePtr->form == FRM_RECORD)*/)
			{
				//-------------------------
				// Copy the array/record...
				char* dest = (char*)targetPtr;
				char* src = tos->address;
				long size = targetTypePtr->size;
				memcpy(dest, src, size);
			}
			else if ((baseTargetTypePtr == IntegerTypePtr) || (targetTypePtr->form == FRM_ENUM))
			{
				//------------------------------------------------------
				// Range check assignment to integer or enum subrange...

// NOTE: Need to put this line back in once we implement SUBRANGES...
//			if ((targetTypePtr->form == FRM_SUBRANGE) &&
//				((tos->integer < targetTypePtr->info.subrange.min) || (tos->integer > targetTypePtr->info.subrange.max)))
//				runtimeError(ABL_ERR_RUNTIME_VALUE_OUT_OF_RANGE);

				targetPtr->integer = tos->integer;
			}
			//else if (baseTargetTypePtr == CharTypePtr) {
			//	}
			else
			{
				//-----------------------
				// Assign real to real...
				targetPtr->real = tos->real;
			}

			//-----------------------------
			// Grab the expression value...
			pop();

			//----------------------------------------------------------------------
			// Preserve the return value, in case we need it for the calling user...
			memcpy(&returnValue, targetPtr, sizeof(StackItem));

			if (debugger)
				debugger->traceDataStore(CurRoutineIdPtr, CurRoutineIdPtr->typePtr, targetPtr, targetTypePtr);
		}

		//-----------------------
		// Grab the semi-colon...
		getCodeToken();

		codeSegmentPtr = (char*)ExitRoutineCodeSegment;
		ExitWithReturn = true;

		getCodeToken();
		return NULL;
	}

//***************************************************************************

	TypePtr execStdPrint (SymTableNodePtr routineIdPtr)
	{

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		TypePtr paramTypePtr = baseType(execExpression());

		char buffer[20];
		char* s = buffer;
		if (paramTypePtr == IntegerTypePtr)
			sprintf(buffer, "%d", tos->integer);
		else if (paramTypePtr == BooleanTypePtr)
			sprintf(buffer, "%s", tos->integer ? "true" : "false");
		else if (paramTypePtr == CharTypePtr)
			sprintf(buffer, "%c", tos->byte);
		else if (paramTypePtr == RealTypePtr)
			sprintf(buffer, "%.4f", tos->real);
		else if ((paramTypePtr->form == FRM_ARRAY) && (paramTypePtr->info.array.elementTypePtr == CharTypePtr))
			s = (char*)tos->address;
		pop();

		if (debugger)
		{
			char message[512];
			sprintf(message, "PRINT:  \"%s\"", s);
			debugger->print(message);
			sprintf(message, "   MODULE %s", CurModule->getName());
			debugger->print(message);
			sprintf(message, "   FILE %s", CurModule->getSourceFile(FileNumber));
			debugger->print(message);
			sprintf(message, "   LINE %d", execLineNumber);
			debugger->print(message);
		}
#ifdef LAB_ONLY
		{
			Check_Object(Application::GetInstance());
			MWApplication::GetInstance()->SendChat(
					Connection::Local->GetID(),
					MWApplication::SystemBroadcast,
					0,
					s);
		}
#endif

#ifdef USE_IFACE
		else if (TACMAP)
		{
			aChatWindow* chatWin = TACMAP->getChatWindow();
			if (chatWin)
				chatWin->processChatString(0, s, -1);
			else
			{
#ifdef _DEBUG
				OutputDebugString(s);
#endif
			}
		}
		else
		{
#ifdef _DEBUG
			OutputDebugString(s);
#endif
		}
#endif
		getCodeToken();
		return NULL;
	}

//***************************************************************************

	TypePtr execStdConcat (SymTableNodePtr routineIdPtr)
	{

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//--------------------------
		// Get destination string...
		getCodeToken();
		execExpression();
		char* dest = (char*)tos->address;
		pop();

		//----------------------
		// Get item to append...
		getCodeToken();
		TypePtr paramTypePtr = baseType(execExpression());
		char buffer[20];
		if (paramTypePtr == IntegerTypePtr)
		{
			sprintf(buffer, "%d", tos->integer);
			strcat(dest, buffer);
		}
		else if (paramTypePtr == CharTypePtr)
		{
			sprintf(buffer, "%c", tos->byte);
			strcat(dest, buffer);
		}
		else if (paramTypePtr == RealTypePtr)
		{
			sprintf(buffer, "%.4f", tos->real);
			strcat(dest, buffer);
		}
		else if (paramTypePtr == BooleanTypePtr)
		{
			sprintf(buffer, "%s", tos->integer ? "true" : "false");
			strcat(dest, buffer);
		}
		else if ((paramTypePtr->form == FRM_ARRAY) && (paramTypePtr->info.array.elementTypePtr == CharTypePtr))
			strcat(dest, (char*)tos->address);

		tos->integer = 0;

		getCodeToken();
		return(IntegerTypePtr);
	}

//***************************************************************************

	TypePtr execStdAbs (SymTableNodePtr routineIdPtr)
	{

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		TypePtr paramTypePtr = baseType(execExpression());

		TypePtr resultTypePtr = NULL;
		if (paramTypePtr == IntegerTypePtr)
		{
			if (tos->integer < 0)
				tos->integer = -(tos->integer);
			resultTypePtr = IntegerTypePtr;
		}
		else
		{
			if (tos->real < 0.0)
				tos->real = -(tos->real);
			resultTypePtr = RealTypePtr;
		}

		getCodeToken();
		return(resultTypePtr);
	}

//***************************************************************************

	TypePtr execStdRound (SymTableNodePtr routineIdPtr)
	{

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		execExpression();

		if (tos->real > 0.0)
			tos->integer = (long)(tos->real + 0.5);
		else
			tos->integer = (long)(tos->real - 0.5);

		getCodeToken();
		return(IntegerTypePtr);
	}

//***************************************************************************

	TypePtr execStdSqrt (SymTableNodePtr routineIdPtr)
	{

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		TypePtr paramTypePtr = baseType(execExpression());

		//-------------------------------------------------------
		// If we have an integer parameter, force it to a real...
		if (paramTypePtr == IntegerTypePtr)
			tos->real = (float)tos->integer;

		if (tos->real < 0.0)
			runtimeError(ABL_ERR_RUNTIME_INVALID_FUNCTION_ARGUMENT);
		else
			tos->real	= (float)(sqrt(tos->real));

		getCodeToken();
		return(RealTypePtr);
	}

//***************************************************************************

	TypePtr execStdTrunc (SymTableNodePtr routineIdPtr)
	{

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		TypePtr paramTypePtr = baseType(execExpression());

		//------------------------------------------------------------------
		// If we have a real parameter, trunc it. Else, leave the integer as
		// it is...
		if (paramTypePtr == RealTypePtr)
			tos->integer = (long)(tos->real);

		getCodeToken();
		return(IntegerTypePtr);
	}

//***************************************************************************

	TypePtr execStdRandom (SymTableNodePtr routineIdPtr)
	{

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		execExpression();

		//---------------------------------------------------------------------
		// This is, like, a really bad number generator. But, you get the idea.
		// Once we know which pseudo-random number algorithm we want to use, we
		// should plug it in here. The range for the random number, given a
		// param of n, should be: 1<=r<=n.
		tos->integer = Random::GetLessThan(tos->integer);

		getCodeToken();
		return(IntegerTypePtr);
	}

//***************************************************************************

	TypePtr execStdGetModHandle (SymTableNodePtr routineIdPtr)
	{

		//----------------------------------------------------------
		// Return the handle of the current module being executed...
		pushInteger(CurModuleHandle);

		getCodeToken();
		return(IntegerTypePtr);
	}

//***************************************************************************

	TypePtr execStdGetModName (SymTableNodePtr routineIdPtr)
	{

		//----------------------------------------------------------
		// Return the handle of the current module being executed...
		//tos->integer = CurModuleHandle;

		//getCodeToken();
		return(NULL/*TypePtr*/);
	}

//***************************************************************************

	TypePtr execStdSetModName (SymTableNodePtr routineIdPtr)
	{

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		TypePtr paramTypePtr = baseType(execExpression());

		if ((paramTypePtr->form == FRM_ARRAY) && (paramTypePtr->info.array.elementTypePtr == CharTypePtr))
		{
			//if (ModuleRegistry[CurModuleHandle].name)
			//	systemHeap->free(ModuleRegistry[CurModuleHandle].name);
			//ModuleRegistry[CurModuleHandle].name = (char*)systemHeap->malloc(strlen((char*)tos->address) + 1);
			//strcpy(ModuleRegistry[CurModuleName].name, (char*)tos->address);
		}
		else
			runtimeError(ABL_ERR_RUNTIME_INVALID_FUNCTION_ARGUMENT);

		getCodeToken();
		return NULL;
	}

//***************************************************************************

	TypePtr execStdSetMaxLoops (SymTableNodePtr routineIdPtr)
	{

		//----------------------------------------------------------------------
		//
		//	SET MAX LOOPS function:
		//
		//		Sets the max number of loops that may occur (in a for, while or
		//		repeat loop) before an infinite loop run-time error occurs.
		//
		//		PARAMS:	integer
		//
		//		RETURN: none
		//
		//----------------------------------------------------------------------

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		execExpression();
		MaxLoopIterations = (tos->integer + 1);
		pop();

		getCodeToken();
		return(NULL);
	}

//---------------------------------------------------------------------------

	TypePtr execStdFatal (SymTableNodePtr routineIdPtr)
	{

		//----------------------------------------------------------------------
		//
		//	FATAL function:
		//
		//		If the debugger is active, this immediately jumps into debug mode.
		//		Otherwise, it causes a fatal and exits the game (displaying the
		//		string passed in).
		//
		//		PARAMS:	integer							fatal code to display
		//
		//				char[]							message
		//
		//		RETURN: none
		//
		//----------------------------------------------------------------------

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		execExpression();
		long code = tos->integer;
		pop();

		getCodeToken();
		execExpression();
		char* s = (char*)tos->address;
		pop();

		#ifdef LAB_ONLY
		char message[512];
		if (debugger)
		{
			sprintf(message, "FATAL:  [%d] \"%s\"", code, s);
			debugger->print(message);
			sprintf(message, "   MODULE (%d) %s", CurModule->getId(), CurModule->getName());
			debugger->print(message);
			sprintf(message, "   FILE %s", CurModule->getSourceFile(FileNumber));
			debugger->print(message);
			sprintf(message, "   LINE %d", execLineNumber);
			debugger->print(message);
			debugger->debugMode();
		}
		else
		{
			sprintf(message, "ABL FATAL: [%d] %s", code, s);
			ABL_Fatal(0, s);
		}
		#endif

		getCodeToken();
		return(NULL);
	}

//---------------------------------------------------------------------------

	TypePtr execStdAssert (SymTableNodePtr routineIdPtr)
	{

		//----------------------------------------------------------------------
		//
		//	ASSERT function:
		//
		//		If the debugger is active, this immediately jumps into debug mode
		//		if expression is FALSE. Otherwise, the assert statement is ignored
		//		unless the #debug directive has been issued in the module. If
		//		so, a fatal occurs and exits the game (displaying the
		//		string passed in).
		//
		//		PARAMS:	boolean							expression
		//
		//				integer							assert code to display
		//
		//				char[]							message
		//
		//		RETURN: none
		//
		//----------------------------------------------------------------------

		//-------------------
		// Grab the LPAREN...
		getCodeToken();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		execExpression();
		long expression = tos->integer;
		pop();

		//----------------------------
		// Get parameter expression...
		getCodeToken();
		execExpression();
		long code = tos->integer;
		pop();

		getCodeToken();
		execExpression();
		char* s = (char*)tos->address;
		pop();

		#ifdef LAB_ONLY
		if (!expression)
		{
			char message[512];
			if (debugger)
			{
				sprintf(message, "ASSERT:  [%d] \"%s\"", code, s);
				debugger->print(message);
				sprintf(message, "   MODULE (%d) %s", CurModule->getId(), CurModule->getName());
				debugger->print(message);
				sprintf(message, "   FILE %s", CurModule->getSourceFile(FileNumber));
				debugger->print(message);
				sprintf(message, "   LINE %d", execLineNumber);
				debugger->print(message);
				debugger->debugMode();
			}
			else
			{
				sprintf(message, "ABL ASSERT: [%d] %s", code, s);
				ABL_Fatal(0, message);
			}
		}
		#endif

		getCodeToken();
		return(NULL);
	}


//***************************************************************************

	TypePtr execSetDebugString (SymTableNodePtr routineIdPtr)
	{

		startFunction();

		long objectId = popInteger();
		long stringNum = popInteger();
		char* debugString = popStringPtr();
#if 0
#ifdef _DEBUG
		GameObjectPtr obj = getObject(objectId);
		if (obj)
		{
			MechWarriorPtr pilot = obj->getPilot();
			if (pilot)
				pilot->setDebugString(stringNum, debugString);
		}
#endif
#endif
		endFunction();
		return NULL;
	}

//***************************************************************************
	TypePtr execgetPlayer (SymTableNodePtr routineIdPtr)
	{
		Check_Object (Adept::Player::GetInstance());							//blurt
		pushInteger (Adept::Player::GetInstance()->objectID);

		endFunction ();
		return IntegerTypePtr;
	}
	TypePtr execgetSelf (SymTableNodePtr routineIdPtr)
	{
		if (CurWarrior == 0)
		{
			pushInteger(ABL_NO_UNIT);
		}
		else
		{
			Check_Object (CurWarrior);
			pushInteger (CurWarrior->objectID);
		}

		endFunction ();
		return IntegerTypePtr;
	}

	TypePtr execgetPlayerVehicle (SymTableNodePtr routineIdPtr)
	{
		int i,size;

		NameTable *table = NameTable::GetInstance();
		Check_Object (table);

		DECLARE_ABL_CONTEXT;
		int id = popInteger();
		ablREPORT (id >=0,"to low of a number to getplayervehicle");
		ablREPORT (id < 32,"to high of a number to getplayervehicle");
		Check_Object(NameTable::GetInstance());

		size = table->nameTableArray[NameTable::PlayerArray].GetLength ();

		Player *player;
		for (i=0;i<size;i++)
		{
			NameTableEntry *data;

			data = &table->nameTableArray	[NameTable::PlayerArray][i];
			if (data->dataPointer->GetCurrent ())
			{
				if (id == 0)
				{
					player = Cast_Object(Player *,data->dataPointer->GetCurrent ());
					Check_Object(player);
					pushInteger(player->vehicle->objectID);
					return IntegerTypePtr;
				}
			}
			id--;
		}
		pushInteger (ABL_NO_UNIT);
		return IntegerTypePtr;
	}

	void Group_execSetEntropyMood(Group::identifier group_id, Stuff::Scalar newmood)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			(*i)->EntropyMood(newmood);
		}}
	}
	TypePtr execsetEntropyMood (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();
		Stuff::Scalar newmood = (Stuff::Scalar)popInteger ();
		ablREPORT (newmood>=MW4AI::MOODMIN,ablERROR ("entropy mood set too low"));
		ablREPORT (newmood<=MW4AI::MOODMAX,ablERROR ("entropy mood set to high"));

		if (ObjectIDisGroup(id) == true)
		{
			Group_execSetEntropyMood(ObjectIDtoGroupID(id),newmood);
			return NULL;
		}

		AI *who = GetAIForID(id);

		ablREPORT ((long) who != -1,ablERROR ("setEntropyMood asked for non-ai object"));
		if (who)
		{
			ablREPORT (who->IsDerivedFrom (AI::DefaultData),ablERROR ("setEntropyMood asked for non-ai object"));
			Check_Object (who);

			ablREPORT (!who->Dead (),ablERROR ("setEntropyMood asked for a dead object"));
			who->EntropyMood (newmood);
		}
		return NULL;
	}
	bool Group_TargetObjectOrGroup(AI& ai, Group::identifier group_id)
	{
		if (ai.getEntity() == 0)
		{
			return (false);
		}

		mwobject_list targets;
		GetVehiclesFromGroup(group_id,targets);

		if (targets.size() == 0)
		{
			return (false);
		}

		Stuff::Scalar best_distance = -1;
		mwobject_list::const_iterator best_found = targets.end();

		{for (mwobject_list::const_iterator i = targets.begin();
			  i != targets.end();
			  ++i)
		{
			if ((*i)->GetTargetDesirability() != MWObject::desirability_never)
			{
				Stuff::Scalar distance = GetLengthSquared((Stuff::Point3D)ai.getEntity()->GetLocalToWorld(),
														  (Stuff::Point3D)(*i)->GetLocalToWorld());

				if ((best_distance < 0) ||
					(distance < best_distance))
				{
					best_distance = distance;
					best_found = i;
				}
			}
		}}

		if (best_found == targets.end())
		{
			return (false);
		}

		ai.Target(*best_found);

		return (true);
	}
	void TargetObjectOrGroup(AI& ai, ObjectID target_id)
	{
		if (target_id == ABL_NO_UNIT)
		{
			ai.Target(0);
			return;
		}

		if (ObjectIDisGroup(target_id) == true)
		{
			Group_TargetObjectOrGroup(ai,ObjectIDtoGroupID(target_id));
		}

		MWObject *target = GetMWObjectForID(target_id);
		ablREPORT ((long) target != -1,ablERROR ("tried to set the target to no object"));

		if (target == 0)
		{
			return;
		}

		Check_Object(target);

		ai.Target(target);
	}

	void Group_execSetTarget(Group::identifier group_id, ObjectID target)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			TargetObjectOrGroup(**i,target);
		}}
	}
	TypePtr execsetTarget (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();
		long target_id = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			Group_execSetTarget(ObjectIDtoGroupID(id),target_id);
			return NULL;
		}

		AI *who = GetAIForID(id);
		Verify ((long) who != -1);

		if (who)
		{
			ablREPORT(((who->vehicle == 0) || (who->vehicle->objectID != target_id)),ablERROR ("tried to set our target to ourselves"));

			if ((who != 0) &&
				(who->vehicle->objectID == target_id))
			{
				return NULL;
			}

			ablREPORT (who->IsDerivedFrom(AI::DefaultData),ablERROR ("tried to set the target for a non-ai"));
			Check_Object(who);

			ablREPORT (!who->Dead (),ablERROR ("tried to set the target for a dead ai"));
			TargetObjectOrGroup(*who,target_id);
		}
		return NULL;
	}
	TypePtr execgetTarget (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();
		ablREPORT (ObjectIDisGroup(id) == false,ablERROR ("tried to get the target for a group"));

		AI *who = GetAIForID(id);

		Verify ((long) who != -1);
		if (who)
		{
			ablREPORT (who->IsDerivedFrom (AI::DefaultData),ablERROR ("tried to get the target of a non-ai"));
			Check_Object (who);
			Entity *target;
			ablREPORT (!who->Dead (),ablERROR ("tried to get the target of a dead ai"));
			target = who->Target ();
			if (!target)
				pushInteger (ABL_NO_UNIT);
			else
			{
				Check_Object (target);
				pushInteger (target->objectID);
			}
		}
		else
			pushInteger	(ABL_NO_UNIT);

		return IntegerTypePtr;
	}
	void Group_execWhoShot(Group::identifier group_id)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			Entity* shot_by = (*i)->ShotBy(gos_GetElapsedTime() - who_shot_duration);
			if (shot_by != 0)
			{
				pushInteger(shot_by->objectID);
				return;
			}
		}}

		pushInteger(ABL_NO_UNIT);
	}
	TypePtr execwhoShot (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long objectid = popInteger ();

		if (ObjectIDisGroup(objectid) == true)
		{
			Group_execWhoShot(ObjectIDtoGroupID(objectid));
		}
		else
		{
			AI *who = GetAIForID(objectid);

			Verify ((long) who != -1);
			if (who)
			{
				ablREPORT (who->IsDerivedFrom (AI::DefaultData),ablERROR ("tried to ask for who shot a non ai"));
				Check_Object (who);

				Entity *target;
				ablREPORT (!who->Dead (),ablERROR ("tried to ask for who shot a dead ai"));
				if (who->Dead() == true)
				{
					pushInteger(ABL_NO_UNIT);
					return IntegerTypePtr;
				}

				target = who->ShotBy (gos_GetElapsedTime () - who_shot_duration);
				if (!target)
					pushInteger (ABL_NO_UNIT);
				else
				{
					Check_Object (target);
					pushInteger (target->objectID);
				}
			}
			else
				pushInteger	(ABL_NO_UNIT);
		}

		return IntegerTypePtr;
	}

	long Group_execwhoDestroyed(Group::identifier group_id)
	{
		Graveyard* graveyard = MechWarrior4::AI::GetGraveyard();

		if (graveyard == 0)
		{
			return (ABL_NO_UNIT);
		}

		mwobject_list objects;
		GetVehiclesFromGroup(group_id,objects,true);

		{for (mwobject_list::iterator i_objects = objects.begin();
			  i_objects != objects.end();
			  ++i_objects)
		{
			if ((*i_objects)->IsDestroyed() == true)
			{
				{for (grave_list::const_iterator i_graves = graveyard->GetGraves().begin();
					  i_graves != graveyard->GetGraves().end();
					  ++i_graves)
				{
					
					if ((*i_graves).id == (*i_objects)->objectID)
					{
						return ((*i_graves).destroyer);
					}
				}}
			}
		}}

		return (ABL_NO_UNIT);
	}

	TypePtr execwhoDestroyed (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			pushInteger(Group_execwhoDestroyed(ObjectIDtoGroupID(id)));
			return IntegerTypePtr;
		}
		ablREPORT (ObjectIDisGroup(id) == false,ablERROR ("tried to call WhoDestroyed() on a group"));

		Entity *who = GetAIForID(id);
		ablREPORT ((long) who != -1,ablERROR ("tried to call WhoDestroyed() on a non entity"));
		if (who)
		{
			Check_Object (who);
			who = ConvertAIToEntity (who);
			Check_Object(who);

			Graveyard* graveyard = MechWarrior4::AI::GetGraveyard();

			if (graveyard != 0)
			{
				{for (grave_list::const_iterator i = graveyard->GetGraves().begin();
					  i != graveyard->GetGraves().end();
					  ++i)
				{
					if ((*i).id == who->objectID)
					{
						pushInteger((*i).destroyer);
						return IntegerTypePtr;
					}
				}}
			}
		}

		pushInteger(ABL_NO_UNIT);

		return IntegerTypePtr;
	}
	long FindObjectForAI(AI* who,
						 int fa_alignment,
						 int ft_type,
						 int fc_criteria,
						 int ff_flags,
						 Stuff::Scalar distance_limit = MW4AI::FindObject::DISTANCE_LIMIT,
						 Adept::ObjectID* except_object = 0)
	{
		Check_Pointer(who);

		if ((who != 0) &&
				(who->getEntity() != 0) &&
				(who->getEntity()->IsDerivedFrom(MWObject::DefaultData) == true))
		{
			MWObject* object = Cast_Object(MWObject*,who->getEntity());

			if (object->GetSensor() != 0)
			{
				return(MW4AI::FindObject::Find(*object,
											   fa_alignment,
											   ft_type,
											   fc_criteria,
											   ff_flags,
											   distance_limit,
											   except_object));
			}
		}

		return(ABL_NO_UNIT);
	}

	long Return_FindNearestEnemy(AI* who)
	{
		return(FindObjectForAI(who,
							   MW4AI::FindObject::FA_ENEMY,
							   MW4AI::FindObject::FT_DEFAULT,
							   MW4AI::FindObject::FC_NEAREST,
							   0));
	}
	long Group_execGetNearestEnemy(Group::identifier group_id)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::const_iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			long rv = Return_FindNearestEnemy(*i);
			if (rv >= 0)
			{
				return(rv);
			}
		}}

		return(ABL_NO_UNIT);
	}
	TypePtr execgetNearestEnemy(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		if (ObjectIDisGroup(id) == true)
		{
			pushInteger(Group_execGetNearestEnemy(ObjectIDtoGroupID(id)));
		}
		else
		{
			AI *who = GetAIForID(id);
			if (!who)
			{
				pushInteger (ABL_NO_UNIT);
				return IntegerTypePtr;
			}
			ablREPORT ((long) who != -1,ablERROR ("tried to ask for the nearest enemy of a non-ai"));
			ablREPORT (!who->Dead (),ablERROR ("tried to ask for the nearest enemy of a dead ai"));
			int fred = Return_FindNearestEnemy(who);

			pushInteger(fred);
		}

		return IntegerTypePtr;
	}

	long Group_execFindObject(Group::identifier group_id,
							  int fa_alignment,
							  int ft_type,
							  int fc_criteria,
							  int ff_flags,
							  Stuff::Scalar distance_limit,
							  Adept::ObjectID* except_object)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::const_iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			long rv = FindObjectForAI(*i,
									  fa_alignment,
									  ft_type,
									  fc_criteria,
									  ff_flags,
									  distance_limit,
									  except_object);
			if (rv >= 0)
			{
				return(rv);
			}
		}}

		return(ABL_NO_UNIT);
	}
	TypePtr execFindObject(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		int fa_alignment = popInteger();
		int ft_type = popInteger();
		int fc_criteria = popInteger();
		int ff_flags = popInteger();
		int distance = popInteger();
		if (ObjectIDisGroup(id) == true)
		{
			pushInteger(Group_execFindObject(ObjectIDtoGroupID(id),
											 fa_alignment,
											 ft_type,
											 fc_criteria,
											 ff_flags,
											 (Stuff::Scalar)distance,
											 0));
		}
		else
		{
			AI* who = GetAIForID(id);
			if (!who)
			{
				pushInteger (ABL_NO_UNIT);
				return IntegerTypePtr;
			}
			Verify ((long) who != -1);
			ablREPORT (!who->Dead(),ablERROR ("calling findobject on a dead unit"));

			pushInteger(FindObjectForAI(who,
										fa_alignment,
										ft_type,
										fc_criteria,
										ff_flags,
										(Stuff::Scalar)distance));
		}

		return IntegerTypePtr;
	}
	TypePtr execFindObjectExcept(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		int fa_alignment = popInteger();
		int ft_type = popInteger();
		int fc_criteria = popInteger();
		int ff_flags = popInteger();
		int distance = popInteger();
		int except = popInteger();
		if (ObjectIDisGroup(id) == true)
		{
			pushInteger(Group_execFindObject(ObjectIDtoGroupID(id),
											 fa_alignment,
											 ft_type,
											 fc_criteria,
											 ff_flags,
											 (Stuff::Scalar)distance,
											 &except));
		}
		else
		{
			AI* who = GetAIForID(id);
			if (!who)
			{
				pushInteger (ABL_NO_UNIT);
				return IntegerTypePtr;
			}
			Verify ((long) who != -1);
			ablREPORT (!who->Dead(),ablERROR ("calling findobject on a dead unit"));

			pushInteger(FindObjectForAI(who,
										fa_alignment,
										ft_type,
										fc_criteria,
										ff_flags,
										(Stuff::Scalar)distance,
										&except));
		}

		return IntegerTypePtr;
	}
	void Group_execSetCurMood(Group::identifier group_id, Stuff::Scalar newmood)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			(*i)->CurrentMood(newmood);
		}}
	}
	TypePtr execsetCurMood (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		Stuff::Scalar newmood = (Stuff::Scalar)popInteger ();
		ablREPORT (newmood>=MW4AI::MOODMIN,ablERROR ("tried to set the current mood below minimum"));
		ablREPORT (newmood<=MW4AI::MOODMAX,ablERROR ("tried to set the current mood above maximum"));

		if (ObjectIDisGroup(id) == true)
		{
			Group_execSetCurMood(ObjectIDtoGroupID(id),newmood);
		}
		else
		{
			AI *who = GetAIForID(id);
			Verify ((long) who != -1);
			if (who)
			{
				Check_Object (who);
				ablREPORT (who->IsDerivedFrom (AI::DefaultData),ablERROR ("tried to set the current mood for a non-ai"));
				ablREPORT (!who->Dead (),ablERROR ("tried to set the current mood for a dead ai"));
				who->CurrentMood (newmood);
			}
		}
		return NULL;
	}
	TypePtr execgetHP (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		ablREPORT ((ObjectIDisGroup(objectid) == false),ablERROR ("called gethp on a group"));

		AI *who = GetAIForID(objectid);
		Verify ((long) who != -1);
		if (who)
		{
			Check_Object (who);
			ablREPORT (who->IsDerivedFrom (AI::DefaultData),ablERROR ("tried to get the hp for a non-ai"));
		}

	

		MWObject* object = GetMWObjectForID (objectid);
		pushInteger ((int)(object->m_HitPoints));
		return IntegerTypePtr;
	}
	Stuff::Point3D Group_execGetLocation(Group::identifier group_id)
	{
		mwobject_list objects;
		GetVehiclesFromGroup(group_id,objects);

		if (objects.size() == 0)
		{
			return(Stuff::Point3D(-1,-1,-1));
		}

		Stuff::Point3D rv(0,0,0);

		{for (mwobject_list::iterator i = objects.begin();
				 i != objects.end();
				 ++i)
			{
				rv += (Stuff::Point3D)(*i)->GetLocalToWorld();
			}}

		rv.x /= objects.size();
		rv.y /= objects.size();
		rv.z /= objects.size();

		return(rv);
	}
	TypePtr execgetLocation (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		Stuff::Point3D loc (-1,-1,-1);

		long id = popInteger ();

		long *waypoint = popIntegerPtr ();		// point to return;
		waypoint[0] = (long) 0;
		waypoint[1] = (long) 0;
		waypoint[2] = (long) 0;

		if (ObjectIDisGroup(id) == true)
		{
			loc = Group_execGetLocation(ObjectIDtoGroupID(id));
		}
		else
		{
			Entity* who = GetObjectForID<Entity>(id);
      who = ConvertAIToEntity(who);
			if (who)
			{
				Check_Object (who);
				loc = (Stuff::Point3D) who->GetLocalToWorld ();
			}
		}

		waypoint[0] = (int) loc.x;
		waypoint[1] = (int) loc.y;
		waypoint[2] = (int) loc.z;
		return NULL;
	}
	TypePtr execDistance (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		Stuff::Scalar dist;
		int dx,dz;

		long *point1 = popIntegerPtr ();		// point to return;
		long *point2 = popIntegerPtr ();		// point to return;
	  dx = point1[0] - point2[0];
		dz = point1[2] - point2[2];
		dx *= dx;
		dz *= dz;
		dist = (Stuff::Scalar) (dx + dz);
		dist = SqrtApproximate (dist);
		pushInteger ((int) dist);

		return IntegerTypePtr;
	}
	TypePtr execgetNearestPathPoint (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();
		long pathid = popInteger ();
		long *waypoint = popIntegerPtr ();		// point to return;

		Entity *entity;
		Path* path;
		ablREPORT (pathid!=-1,ablERROR ("pathid is invalid"));
		entity = NameTable::GetInstance()->FindData (pathid);
		ablREPORT (entity->IsDerivedFrom (Path::DefaultData),ablERROR ("tried to get nearest point to a path object that is not a path"));
		path = Cast_Object (Path *,entity);

		Stuff::Point3D loc;

		if (ObjectIDisGroup(id) == true)
		{
			loc = Group_execGetLocation(ObjectIDtoGroupID(id));
		}
		else
		{
			Entity* who = GetObjectForID<Entity>(id);
      who = ConvertAIToEntity(who);
			if (!who)
				return NULL;
			Check_Object (who);
			Check_Object (path);
			loc	= (Stuff::Point3D) who->GetLocalToWorld ();
		}

		Stuff::Point3D nearest = path->GetNearestPoint (loc);
		waypoint[0] = (int) nearest.x;
		waypoint[1] = (int) nearest.y;
		waypoint[2] = (int) nearest.z;
		return NULL;
	}
	long Return_execGetGreatestThreat(AI* who, Stuff::Scalar range)
	{
		return(FindObjectForAI(who,
							   MW4AI::FindObject::FA_ENEMY,
							   MW4AI::FindObject::FT_DEFAULT,
							   MW4AI::FindObject::FC_GREATEST_THREAT,
							   0,
							   range));
	}
	long Group_execGetGreatestThreat(Group::identifier group_id, Stuff::Scalar range)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::const_iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			long rv = Return_execGetGreatestThreat(*i,range);
			if (rv >= 0)
			{
				return(rv);
			}
		}}

		return(ABL_NO_UNIT);
	}
	TypePtr execgetGreatestThreat (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		long range = popInteger();
		if (ObjectIDisGroup(id) == true)
		{
			pushInteger(Group_execGetGreatestThreat(ObjectIDtoGroupID(id),(Stuff::Scalar)range));
		}
		else
		{
			AI* who = GetAIForID(id);
			if (!who)
			{
				pushInteger (ABL_NO_UNIT);
				return IntegerTypePtr;
			}
			ablREPORT (!who->Dead (),ablERROR ("tried to get the greatest threat to a dead ai"));
			pushInteger(Return_execGetGreatestThreat(who,(Stuff::Scalar)range));
		}

		return IntegerTypePtr;
	}
	long Return_execGetLeastThreat(AI* who, Stuff::Scalar range)
	{
		return(FindObjectForAI(who,
													 MW4AI::FindObject::FA_ENEMY,
													 MW4AI::FindObject::FT_DEFAULT,
													 MW4AI::FindObject::FC_LEAST_THREAT,
													 0,
													 range));
	}
	long Group_execGetLeastThreat(Group::identifier group_id, Stuff::Scalar range)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::const_iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			long rv = Return_execGetLeastThreat(*i,range);
			if (rv >= 0)
			{
				return(rv);
			}
		}}

		return(ABL_NO_UNIT);
	}
	TypePtr execgetLeastThreat (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		long range = popInteger();

		if (ObjectIDisGroup(id) == true)
		{
			pushInteger(Group_execGetLeastThreat(ObjectIDtoGroupID(id),(Stuff::Scalar)range));
		}
		else
		{
			Verify(ObjectIDisGroup(id) == false);

			AI* who = GetAIForID(id);
			if (!who)
			{
				pushInteger (ABL_NO_UNIT);
				return IntegerTypePtr;
			}
			ablREPORT (!who->Dead (),ablERROR ("tried to get the least threat for a dead ai"));
			pushInteger(FindObjectForAI(who,
																	MW4AI::FindObject::FA_ENEMY,
																	MW4AI::FindObject::FT_DEFAULT,
																	MW4AI::FindObject::FC_LEAST_THREAT,
																	0,
																	(Stuff::Scalar)range));
		}

		return IntegerTypePtr;
	}
	TypePtr execgetMechType (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		ablREPORT (ObjectIDisGroup(objectid) == false,ablERROR ("Tried to get the 'Mech type for a group"));

		MWObject* who = GetMWObjectForID(objectid);

		if ((who != 0) &&
			(who->IsDerivedFrom(Mech::DefaultData) == true))
		{
			Mech* mech = Cast_Object(Mech*,who);

			pushInteger(mech->GetGameModel()->mechID);
		}
		else
		{
			pushInteger(NoMechID);
		}
		
		return IntegerTypePtr;
	}
	TypePtr execgetAlignment (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		ablREPORT(ObjectIDisGroup(id) == false,ablERROR ("tried to get the alignment for a group"));

		MWObject* who = GetMWObjectForID(id);
		if (who == 0)
		{
			pushInteger(0);
		}
		else
		{
			Check_Object(who);
			pushInteger(who->GetAlignment());
		}
		return IntegerTypePtr;
	}

	void Group_execSetAlignment(Group::identifier id, int new_alignment)
	{
		mwobject_list objects;
		GetVehiclesFromGroup(id,objects);

		{for (mwobject_list::const_iterator i = objects.begin();
			  i != objects.end();
			  ++i)
		{
			if ((*i)->GetAlignment() != new_alignment)
			{
				(*i)->SetAlignment(new_alignment);
				if ((*i)->GetAI() != 0)
				{
					(*i)->GetAI()->NotifyAlignmentChanged();
				}
			}
		}}		
	}

	TypePtr execsetAlignment (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		int newalign = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			Group_execSetAlignment(ObjectIDtoGroupID(id),newalign);
			return NULL;
		}

		MWObject* vehicle = GetMWObjectForID(id);
		if (vehicle == 0)
		{
			pushInteger(0);
		}
		else
		{
			if (vehicle->GetAlignment() != newalign)
			{
				vehicle->SetAlignment(newalign);

				if (vehicle->GetAI() != 0)
				{
					vehicle->GetAI()->NotifyAlignmentChanged();
				}
			}
		}
		return NULL;
	}
	TypePtr execgetGunnerySkill (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long objectid = popInteger ();
		ablREPORT(ObjectIDisGroup(objectid) == false,ablERROR ("tried to get the gunnery skill of a group"));

		AI *who = GetAIForID(objectid);
		Verify ((long) who != -1);
		if (who)
		{
			Check_Object (who);
			ablREPORT (who->IsDerivedFrom (AI::DefaultData),ablERROR ("tried to get the gunnery skill of a non-ai"));

			pushInteger (who->GunnerySkill ());
		}
		else
			pushInteger	(0);
		return IntegerTypePtr;
	}
	TypePtr execgetPilotSkill (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long objectid = popInteger ();
		ablREPORT(ObjectIDisGroup(objectid) == false,ablERROR ("tried to get the pilot skill of a group"));

		AI *who = GetAIForID(objectid);
		Verify ((long) who != -1);
		if (who)
		{
			Check_Object (who);
			ablREPORT (who->IsDerivedFrom (AI::DefaultData),ablERROR ("tried to get the pilot skill of a non-ai"));

			pushInteger (who->PilotSkill ());
		}
		else
			pushInteger	(0);
		return IntegerTypePtr;
	}
#if 0
	void Group_execSetSkill(Group::identifier group_id, long pilotskill, long gunskill)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			if (pilotskill != -1)
			{
				ablREPORT ((*i)->Dead (),ablERROR ("tried to set the pilot skill of a dead ai in a group"));
					if (pilotskill < 0)
						pilotskill = 0;
				(*i)->PilotSkill(pilotskill);
			}
			if (gunskill != -1)
			{
				ablREPORT ((*i)->Dead (),ablERROR ("tried to set the gunnery skill of a dead ai in a group"));
					if (gunskill < 0)
						gunskill = 0;
				(*i)->GunnerySkill(gunskill);
			}
		}}
	}
	TypePtr execsetSkill (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		long pilotskill = popInteger ();
		long gunskill = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			Group_execSetSkill(ObjectIDtoGroupID(id),pilotskill,gunskill);
		}
		else
		{
			AI* who = GetAIForID(id);
			ablREPORT ((long) who != -1,ablERROR ("tried to set the skills for a non-ai"));
			if (who)
			{
				Check_Object (who);
				ablREPORT (who->IsDerivedFrom (AI::DefaultData),ablERROR ("tried to set the skills for a non-ai"));
				if (pilotskill != -1)
				{
					ablREPORT (!who->Dead (),ablERROR ("tried to set the pilot skill of a dead ai"));
					if (pilotskill < 0)
						pilotskill = 0;
					who->PilotSkill (pilotskill);
				}
				if (gunskill != -1)
				{
					ablREPORT (!who->Dead (),ablERROR ("tried to set the gunnery skill of a dead ai"));
					if (gunskill < 0)
						gunskill = 0;
					who->GunnerySkill (gunskill);
				}
			}
		}
		return NULL;
	}
#endif
	void Group_execSetSkillLevel(Group::identifier group_id, long pilotskill, long gunskill,long eliteskill)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			if (pilotskill != -1)
			{
				ablREPORT ((*i)->Dead (),ablERROR ("tried to set the pilot skill of a dead ai in a group"));
					if (pilotskill < 0)
						pilotskill = 0;
				(*i)->PilotSkill(pilotskill);
			}
			if (gunskill != -1)
			{
				ablREPORT ((*i)->Dead (),ablERROR ("tried to set the gunnery skill of a dead ai in a group"));
					if (gunskill < 0)
						gunskill = 0;
				(*i)->GunnerySkill(gunskill);
			}
			if (eliteskill != -1)
			{
				ablREPORT ((*i)->Dead (),ablERROR ("tried to set the elite skill of a dead ai in a group"));
					if (eliteskill < 0)
						eliteskill = 0;
				(*i)->EliteSkill(eliteskill);
			}
		}}
	}
	TypePtr execsetSkillLevel (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		long pilotskill = popInteger ();
		long gunskill = popInteger ();
		long eliteskill = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			Group_execSetSkillLevel(ObjectIDtoGroupID(id),pilotskill,gunskill,eliteskill);
		}
		else
		{
			AI* who = GetAIForID(id);
			ablREPORT ((long) who != -1,ablERROR ("tried to set the skills for a non-ai"));
			if (who)
			{
				Check_Object (who);
				ablREPORT (who->IsDerivedFrom (AI::DefaultData),ablERROR ("tried to set the skills for a non-ai"));
				if (pilotskill != -1)
				{
					ablREPORT (!who->Dead (),ablERROR ("tried to set the pilot skill of a dead ai"));
					if (pilotskill < 0)
						pilotskill = 0;
					who->PilotSkill (pilotskill);
				}
				if (gunskill != -1)
				{
					ablREPORT (!who->Dead (),ablERROR ("tried to set the gunnery skill of a dead ai"));
					if (gunskill < 0)
						gunskill = 0;
					who->GunnerySkill (gunskill);
				}
				if (eliteskill != -1)
				{
					ablREPORT (!who->Dead (),ablERROR ("tried to set the elite skill of a dead ai"));
					if (eliteskill < 0)
						eliteskill = 0;
					who->EliteSkill (eliteskill);
				}
			}
		}
		return NULL;
	}
	void Group_SetAttackThrottle(Group::identifier group_id, Stuff::Scalar throttle)
	{
		std::vector<CombatAI*> ais;
		GetAIsFromGroup<CombatAI>(group_id,ais);

		{for (std::vector<CombatAI*>::iterator i = ais.begin();
				 i != ais.end();
				 ++i)
		{
			(*i)->SetAttackThrottle(throttle);
		}}
	}
	TypePtr execSetAttackThrottle (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long object_id = popInteger();
		long throttle = popInteger();
		ablREPORT(throttle <= 100,ablERROR ("tried to set an attack throttle greater than 100"));
		ablREPORT(throttle >= 0,ablERROR ("tried to set a negative attack throttle"));

		if (ObjectIDisGroup(object_id) == true)
		{
			Group_SetAttackThrottle(ObjectIDtoGroupID(object_id),(Stuff::Scalar)throttle);
		}
		else
		{
			MechWarrior4::CombatAI* combat_ai = GetCombatAIForID(object_id);
			Verify((long)combat_ai != -1);

			if (combat_ai)
			{
				combat_ai->SetAttackThrottle((Stuff::Scalar)throttle);
			}
		}
		return NULL;
	}
	TypePtr execGetAttackThrottle (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long object_id = popInteger();
		ablREPORT(ObjectIDisGroup(object_id) == false,ablERROR ("tried to get the attack throttle for a group"));

		MechWarrior4::CombatAI* combat_ai = GetCombatAIForID(object_id);
		Verify((long)combat_ai != -1);
		if (combat_ai)
		{
			pushInteger((int)combat_ai->GetAttackThrottle());
		}
		else
		{
			ablREPORT(0,ablERROR ("attempted to get the attack throttle for an invalid object"));
			pushInteger(100);
		}

		return IntegerTypePtr;
	}
	void Group_SetIgnoreFriendlyFire(Group::identifier group_id, bool ignore)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			(*i)->SetIgnoringFriendlyFire(ignore);
		}}
	}
	TypePtr execSetIgnoreFriendlyFire (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long object_id = popInteger();
		bool ignore_friendly_fire = popBoolean();

		if (ObjectIDisGroup(object_id) == true)
		{
			Group_SetIgnoreFriendlyFire(ObjectIDtoGroupID(object_id),ignore_friendly_fire);
		}
		else
		{
			MechWarrior4::AI* ai = GetAIForID(object_id);

			Verify((long)ai != -1);
			if (ai)
			{
				ai->SetIgnoringFriendlyFire(ignore_friendly_fire);
			}
			else
			{
				ablREPORT(0,ablERROR ("Attempted to call SetIgnoreFriendlyFire() for an invalid object"));
			}
		}

		return NULL;
	}
	void Group_SetFiringDelay(Group::identifier group_id, Stuff::Scalar min_delay, Stuff::Scalar max_delay)
	{
		std::vector<CombatAI*> ais;
		GetAIsFromGroup<CombatAI>(group_id,ais);

		{for (std::vector<CombatAI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			(*i)->SetFiringDelay(min_delay,max_delay);
		}}
	}
	TypePtr execSetFiringDelay (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long object_id = popInteger();
		float min_delay = popReal();
		float max_delay = popReal();
		ablREPORT(min_delay >= 0,ablERROR ("tried to set a negative minimum firing delay"));
		ablREPORT(max_delay >= 0,ablERROR ("tried to set a negative maximum firing delay"));
		ablREPORT(min_delay <= max_delay,ablERROR ("tried to set a minimum firing delay less than the maximum firing delay"));

		if (ObjectIDisGroup(object_id) == true)
		{
			Group_SetFiringDelay(ObjectIDtoGroupID(object_id),(Stuff::Scalar)min_delay,(Stuff::Scalar)max_delay);
		}
		else
		{
			MechWarrior4::CombatAI* combat_ai = GetCombatAIForID(object_id);
			Verify((long)combat_ai != -1);

			if (combat_ai)
			{
				combat_ai->SetFiringDelay((Stuff::Scalar)min_delay,(Stuff::Scalar)max_delay);
			}
		}
		return NULL;
	}
	void Group_SetCombatLeash(Group::identifier group_id, const Stuff::Point3D& center, Stuff::Scalar radius)
	{
		std::vector<MoverAI*> ais;
		GetAIsFromGroup<MoverAI>(group_id,ais);

		{for (std::vector<MoverAI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			(*i)->SetCombatLeash(center,radius);
		}}
	}
	TypePtr execSetCombatLeash (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		Point3D curlocation;

		int object_id = popInteger ();

		getCodeToken();
		SymTableNodePtr idPtr = getCodeSymTableNodePtr();
		baseType(execVariable(idPtr, USE_REFPARAM));
		long* waypoint = (long*)(&((StackItemPtr)tos->address)->integer);
		pop();

		Point3D center;
		center.x = (float) waypoint[0];
		center.y = (float) waypoint[1];
		center.z = (float) waypoint[2];

		int radius = popInteger ();

		if (ObjectIDisGroup(object_id) == true)
		{
			Group_SetCombatLeash(ObjectIDtoGroupID(object_id),center,(Stuff::Scalar)radius);
		}
		else
		{
			MechWarrior4::MoverAI* mover_ai = GetMoverAIForID(object_id);
			Verify((long)mover_ai != -1);

			if (mover_ai)
			{
				mover_ai->SetCombatLeash(center,(Stuff::Scalar)radius);
			}
		}

		return NULL;
	}
	TypePtr execSetGUITarget(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int src_id = popInteger();
		int target_id = popInteger();

		MWObject* src = GetMWObjectForID(src_id);
		MWObject* target = 0;
		
		if (target_id != ABL_NO_UNIT)
		{
			target = GetMWObjectForID(target_id);
		}

		if ((src != 0) &&
			(src->IsDestroyed() == false) &&
			(src->vehicleInterface != 0) &&
			(src->vehicleInterface->IsDerivedFrom(MechWarrior4::VehicleInterface::DefaultData) == true))
		{
			MechWarrior4::VehicleInterface* vehicle_interface = Cast_Object(MechWarrior4::VehicleInterface*,src->vehicleInterface);

			if ((target != 0) &&
				(target->IsDestroyed() == false))
			{
				if ((vehicle_interface->vehicle != 0) &&
					(vehicle_interface->vehicle->GetSensor() != 0))
				{
					vehicle_interface->vehicle->GetSensor()->Refresh();

					if (target->IsDerivedFrom(Building::DefaultData) == true)
					{
						vehicle_interface->vehicle->GetSensor()->UpdateBuildingData();
					}
				}

				vehicle_interface->SetGUITarget(target);
			}
			else
			{
				vehicle_interface->SetGUITarget(0);
			}
		}

		return NULL;
	}

	TypePtr execGetGUITarget (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int src_id = popInteger();

		MWObject* src = GetMWObjectForID(src_id);

		if ((src != 0) &&
			(src->IsDestroyed() == false) &&
			(src->vehicleInterface != 0) &&
			(src->vehicleInterface->IsDerivedFrom(MechWarrior4::VehicleInterface::DefaultData) == true))
		{
			MechWarrior4::VehicleInterface* vehicle_interface = Cast_Object(MechWarrior4::VehicleInterface*,src->vehicleInterface);

			if (vehicle_interface->GetGUITarget() == 0)
			{
				pushInteger(ABL_NO_UNIT);
			}
			else
			{
				pushInteger(vehicle_interface->GetGUITarget()->objectID);
			}
		}
		else
		{
			pushInteger(ABL_NO_UNIT);
		}

		return IntegerTypePtr;
	}

	TypePtr execGetZoomState (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int src_id = popInteger();

		MWObject* src = GetMWObjectForID(src_id);

		if ((src != 0) &&
			(src->IsDestroyed() == false) &&
			(src->vehicleInterface != 0) &&
			(src->vehicleInterface->IsDerivedFrom(MechWarrior4::VehicleInterface::DefaultData) == true))
		{
			MechWarrior4::VehicleInterface* vehicle_interface = Cast_Object(MechWarrior4::VehicleInterface*,src->vehicleInterface);

			pushBoolean (VehicleInterface::GetInstance()->reticuleZoomShowing);
			return (BooleanTypePtr);
		}

		pushBoolean(false);
		return BooleanTypePtr;
	}

	void Group_SetCrouchState(Group::identifier group_id, bool crouch)
	{
		std::vector<CombatAI*> ais;
		GetAIsFromGroup<CombatAI>(group_id,ais);

		{for (std::vector<CombatAI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			if ((*i)->Crouching() != crouch)
			{
				(*i)->Crouch();
			}
		}}
	}

	TypePtr execSetCrouchState(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int object_id = popInteger();
		bool crouched = popBoolean();

		if (ObjectIDisGroup(object_id) == true)
		{
			Group_SetCrouchState(ObjectIDtoGroupID(object_id),crouched);
		}
		else
		{
			MechWarrior4::CombatAI* combat_ai = GetCombatAIForID(object_id);

			if (combat_ai != 0)
			{
				if (combat_ai->Crouching() != crouched)
				{
					combat_ai->Crouch();
				}
			}
		}

		return NULL;
	}

	TypePtr execGetTeamNumber(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int object_id = popInteger();

		MWObject* object = GetMWObjectForID(object_id);

		if ((object == 0) ||
			(object->IsDestroyed() == true) ||
			(object->IsDerivedFrom(MechWarrior4::Vehicle::DefaultData) == false))
		{
			pushInteger(MechWarrior4::MWApplication::No_Team);
		}
		else
		{
			MechWarrior4::Vehicle* vehicle = Cast_Object(MechWarrior4::Vehicle*,object);
			pushInteger(vehicle->teamNumber);
		}

		return IntegerTypePtr;
	}

/*
	void SetEntityToTeam(Adept::ObjectID object_id, int team)
	{
		MWObject* object = GetMWObjectForID(object_id);
		if (object != 0)
		{
			if (object->IsDerivedFrom(Vehicle::DefaultData) == true)
			{
				Vehicle* vehicle = Cast_Object(Vehicle*,object);
				vehicle->SetTeam(team);
			}
		}
		else
		{
			Flag *flag = GetFlagForID(object_id);

			if (flag != 0)
			{
				flag->SetTeam(team);
			}
		}
	}

	void Group_SetTeam(Group::identifier group_id, int team)
	{
		std::vector<MWObject*> objects;
		GetVehiclesFromGroup(group_id,objects);

		{for (std::vector<MWObject*>::iterator i = objects.begin();
			  i != objects.end();
			  ++i)
		{
			if ((*i)->IsDerivedFrom(Vehicle::DefaultData) == true)
			{
				Vehicle* vehicle = Cast_Object(Vehicle*,*i);
				vehicle->SetTeam(team);
			}
		}}
	}

	TypePtr execSetTeam(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int object_id = popInteger();
		int team = popInteger();

		ablREPORT(((team >= 0) && (team <= 7)),ablERROR ("Tried to set to a team number outside of the range 0..7"));

		if (ObjectIDisGroup(object_id) == true)
		{
			Group_SetTeam(ObjectIDtoGroupID(object_id),team);
		}
		else
		{
			SetEntityToTeam(object_id,team);
		}

		return NULL;
	}
*/

	TypePtr execTeamExists(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int team = popInteger();
		ablREPORT(((team >= 0) && (team <= 7)),ablERROR ("Tried to ask if a team outside of the range 0..7 exists"));

		if (MWApplication::GetInstance() == 0)
		{
			pushBoolean(false);
		}
		else
		{
			if ((MWApplication::GetInstance()->teams[team] == 0) ||
				(MWApplication::GetInstance()->teams[team]->GetCurrent() == 0))
			{
				pushBoolean(false);
			}
			else
			{
				pushBoolean(true);
			}
		}

		return BooleanTypePtr;
	}

	enum	// NOTE: these must EXACTLY match the constants in MWCONST.ABI!
	{
		GameParam_heatOn					= 0,
		GameParam_killLimit					= 1,
		GameParam_killLimitNumber			= 2,
		GameParam_respawnLimit				= 3,
		GameParam_respawnLimitNumber		= 4,
		GameParam_forceRespawn				= 5,
		GameParam_splashOn					= 6,
		GameParam_weaponjamOn				= 7,
		GameParam_ammobayfireOn				= 8,
// MSL 5.05 Advance Mode
		GameParam_advancemodeOn				= 9,
// MSL 5.06 Armor Mode
		GameParam_armormodeOn				= 10,
		GameParam_splashPercentage			= 11,
		GameParam_unlimitedAmmo				= 12,
		GameParam_friendlyFirePercentage	= 13,
		GameParam_allowZoom					= 14,
		GameParam_allow3rdPerson			= 15,
		GameParam_allowAutoAim				= 16,
		GameParam_allowDeadToChat			= 17,
		GameParam_invulnerableDrop			= 18,
		GameParam_isNight					= 19,
		GameParam_weather					= 20,
		GameParam_visibility				= 21,
		GameParam_reportStats				= 22,
		GameParam_serverConnection			= 23,
		GameParam_serverBandwidth			= 24,
		GameParam_onlyStockMech				= 25,
		GameParam_minimumTonnage			= 26,
		GameParam_maximumTonnage			= 27,
		GameParam_gameLength				= 28,
		GameParam_serverRecycle				= 29,
		GameParam_recycleDelay				= 30,
		GameParam_playMissionReview			= 31,
		GameParam_ruleType					= 32,
		GameParam_deadMechCantSee			= 33,
		GameParam_deadMechCantSeeOtherTeam	= 34,
		GameParam_allowdecaltransfer		= 35,
		GameParam_useMapCycle				= 36,
		GameParam_pureMapCycle				= 37,
		GameParam_teamAllowed				= 38,
		GameParam_teamCount					= 39,
		GameParam_closedGame				= 40,
		GameParam_playerLimit				= 41
	};

	TypePtr execGetGameParam(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int param_type(popInteger());

		if (Network::GetInstance() == 0)
		{
			pushInteger(-1);
			return IntegerTypePtr;
		}

		NetMissionParameters::MWNetMissionParameters* net_params = 0;

		if (Network::GetInstance()->AmIServer() == true)
		{
			net_params = MWApplication::GetInstance()->GetLocalNetParams();
		}
		else
		{
			net_params = MWApplication::GetInstance()->GetServerNetParams();
		}
		
		if (net_params == 0)
		{
			pushInteger(-1);
			return IntegerTypePtr;
		}

		#define HANDLE_GAME_PARAM(param)		\
			case GameParam_##param:	\
			{						\
				pushInteger(net_params->m_##param);	\
				break;				\
			}

		switch (param_type)
		{
			HANDLE_GAME_PARAM(heatOn);
			HANDLE_GAME_PARAM(killLimit);
			HANDLE_GAME_PARAM(killLimitNumber);
			HANDLE_GAME_PARAM(respawnLimit);
			HANDLE_GAME_PARAM(respawnLimitNumber);
			HANDLE_GAME_PARAM(forceRespawn);
			HANDLE_GAME_PARAM(splashOn);
			HANDLE_GAME_PARAM(weaponjamOn);
			HANDLE_GAME_PARAM(ammobayfireOn);
			HANDLE_GAME_PARAM(advancemodeOn);
			HANDLE_GAME_PARAM(armormodeOn);
			HANDLE_GAME_PARAM(splashPercentage);
			HANDLE_GAME_PARAM(unlimitedAmmo);
			HANDLE_GAME_PARAM(friendlyFirePercentage);
			HANDLE_GAME_PARAM(allowZoom);
			HANDLE_GAME_PARAM(allow3rdPerson);
			HANDLE_GAME_PARAM(allowAutoAim);
			HANDLE_GAME_PARAM(allowDeadToChat);
			HANDLE_GAME_PARAM(invulnerableDrop);
			HANDLE_GAME_PARAM(isNight);
			HANDLE_GAME_PARAM(weather);
			HANDLE_GAME_PARAM(visibility);
			HANDLE_GAME_PARAM(reportStats);
			HANDLE_GAME_PARAM(serverConnection);
			HANDLE_GAME_PARAM(serverBandwidth);
			HANDLE_GAME_PARAM(onlyStockMech);
			HANDLE_GAME_PARAM(minimumTonnage);
			HANDLE_GAME_PARAM(maximumTonnage);
			HANDLE_GAME_PARAM(gameLength);
			HANDLE_GAME_PARAM(serverRecycle);
			HANDLE_GAME_PARAM(recycleDelay);
			HANDLE_GAME_PARAM(playMissionReview);
			HANDLE_GAME_PARAM(ruleType);
			HANDLE_GAME_PARAM(deadMechCantSee);
			HANDLE_GAME_PARAM(deadMechCantSeeOtherTeam);
			HANDLE_GAME_PARAM(allowdecaltransfer);
			HANDLE_GAME_PARAM(useMapCycle);
			HANDLE_GAME_PARAM(pureMapCycle);
			HANDLE_GAME_PARAM(teamAllowed);
			HANDLE_GAME_PARAM(teamCount);
			default:
			{
				pushInteger(-1);
				break;
			}
		}

		#undef HANDLE_GAME_PARAM

		return IntegerTypePtr;
	}

	TypePtr execSetTeamTracking (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int object_id(popInteger());
		int track_flag(popInteger());

		// NOT YET IMPLEMENTED

		return NULL;
	}

	TypePtr execgetTimer (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long objectid = popInteger ();
		ablREPORT(ObjectIDisGroup(objectid) == false,ablERROR ("tried to get the timer for a group"));

		Check_Object (MechWarrior4::MWMission::GetInstance());
		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());

		ablREPORT (objectid >=0,ablERROR ("tried to get the timer for timer id less than min"));
		ablREPORT (objectid <MAX_MISSION_TIMERS,ablERROR ("tried to get the timer for a timer id greater than max"));
		pushInteger ((long) mission->Timer (objectid).CurrTime ());
		return IntegerTypePtr;
	}
	TypePtr execsetTimer (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long objectid = popInteger ();
		ablREPORT(ObjectIDisGroup(objectid) == false,ablERROR ("tried to set the timer for a group"));

		long timervalue = popInteger ();
		Check_Object (MechWarrior4::MWMission::GetInstance());
		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		ablREPORT (objectid >=0,ablERROR ("tried to set the timer for a timer id less than min"));
		ablREPORT (objectid <MAX_MISSION_TIMERS,ablERROR ("tried to set the timer for a timer id greater than max"));
		mission->Timer (objectid).SetTime ((Stuff::Time) timervalue);
		return NULL;
	}
	TypePtr execplayerOrder (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		pushInteger (0);			//TODO;
		return IntegerTypePtr;
	}
	TypePtr execgetEliteLevel (SymTableNodePtr routineIdPtr)
	{
		long id = popInteger ();
		ablREPORT(ObjectIDisGroup(id) == false,ablERROR ("tried to get the elite flag for a group"));

		AI *who = GetAIForID(id);
		Verify ((long) who != -1);
		if (who)
		{
			Check_Pointer (who);
			ablREPORT(who->IsDerivedFrom (AI::DefaultData),ablERROR ("tried to get the elite flag for a non-ai"));
			ablREPORT(!who->Dead (),ablERROR ("tried to get the elite flag for a dead ai"));
			pushInteger(who->EliteSkill());
		}
		else
			pushInteger	(0);
		return IntegerTypePtr;
	}
	void Group_execSetEliteLevel(Group::identifier group_id, int level)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			ablREPORT (!(*i)->Dead (),ablERROR ("tried to set the elite flag for a dead ai in a group"));
			(*i)->EliteSkill(level);
		}}
	}
	TypePtr execsetEliteLevel (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		long level = popInteger ();

		ablREPORT(level >= 0,ablERROR ("Tried to set an elite level less than 0%"));
		ablREPORT(level <= 100,ablERROR ("Tried to set an elite level greater than 100%"));

		if (ObjectIDisGroup(id) == true)
		{
			Group_execSetEliteLevel(ObjectIDtoGroupID(id),level);
		}
		else
		{
			AI *who = GetAIForID(id);
			Verify ((long) who != -1);
			if (who)
			{
				Check_Pointer (who);
				ablREPORT (!who->Dead (),ablERROR ("tried to set the elite flag for a dead ai"));
				who->EliteSkill (level);
			}
		}
		return NULL;
	}
	void Group_execClearMoveOrder(Group::identifier group_id)
	{
		std::vector<MoverAI*> ais;
		GetAIsFromGroup<MoverAI>(group_id,ais);

		{for (std::vector<MoverAI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			(*i)->ClearMoveOrder();
		}}
	}
	TypePtr execclearMoveOrder (SymTableNodePtr routineIdPtr)
	{
		long id = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			Group_execClearMoveOrder(ObjectIDtoGroupID(id));
		}
		else
		{
			MoverAI *who;
			who = GetMoverAIForID(id);
			Verify ((long) who != -1);
			if (who)
			{
				Check_Pointer (who);
				ablREPORT (who->IsDerivedFrom (MoverAI::DefaultData),ablERROR ("tried to clear a move order for a non mover"));
				ablREPORT (!who->Dead (),ablERROR ("tried to clear a move order on a dead ai"));
				who->ClearMoveOrder ();
			}
		}
		return NULL;
	}

    void ONE_SelfDestruct(int id)
    {
        MWObject* mwobject = GetMWObjectForID(id);
        if (mwobject) {
            if (mwobject->IsDerivedFrom(Vehicle::DefaultData) == true) {
                Vehicle* vehicle = Cast_Object(Vehicle*,mwobject);
                vehicle->SelfDestruct();
                return;
            }
        }
		AI *who;
		who = GetAIForID(id);
		Check_Object (who);

		who->SelfDestruct ();
    }

	TypePtr execSelfDestruct (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
            Group::identifier group_id = ObjectIDtoGroupID(id);

		    int i, nCount = MW4AI::Groups::Size(group_id);
		    Adept::ObjectID obj_id;

		    for(i = 0; i < nCount; i++)
		    {
			    if (MW4AI::Groups::GetMember(group_id, (unsigned)i, obj_id)) {
                    ONE_SelfDestruct(obj_id);
                }
            }
        } else {
            ONE_SelfDestruct(id);
        }

		return NULL;
	}

	TypePtr execIsShutdown (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();

		ablREPORT(ObjectIDisGroup(id) == false,ablERROR("Cannot call IsShutdown() on a group."));

		MWObject* mwobject = GetMWObjectForID(id);

		if ((mwobject == 0) ||
			(mwobject->IsDerivedFrom(Vehicle::DefaultData) == false))
		{
			pushBoolean(false);
		}
		else
		{
			Vehicle* vehicle = Cast_Object(Vehicle*,mwobject);
			pushBoolean(vehicle->vehicleShutDown);
		}

		return BooleanTypePtr;
	}

	void Group_execIsShot(Group::identifier group_id)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			if ((*i)->ShotBy(gos_GetElapsedTime() - who_shot_duration) != 0)
			{
				pushBoolean(true);
				return;
			}
		}}

		pushBoolean(false);
	}
	TypePtr execisShot (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			Group_execIsShot(ObjectIDtoGroupID(id));
		}
		else
		{
			AI *who = GetAIForID(id);
			Verify ((long) who != -1);
			if (who)
			{
				Check_Object (who);

				if (who->Dead())
				{
					pushBoolean(false);
					return BooleanTypePtr;
				}

				if (who->ShotBy(gos_GetElapsedTime () - who_shot_duration) != 0)
				{
					pushBoolean(true);
				}
				else
				{
					pushBoolean(false);
				}
			}
			else
			{
				pushBoolean(false);
			}
		}

		return BooleanTypePtr;
	}

	bool Group_execIsWithin(Group::identifier group_id, Entity* who, Stuff::Scalar range)
	{
		mwobject_list objects;
		GetVehiclesFromGroup(group_id,objects);

		{for (mwobject_list::iterator i = objects.begin();
				 i != objects.end();
				 ++i)
		{
			if ((*i)->IsWithin(who,range,true) == true)
			{
				return(true);
			}
		}}

		return(false);
	}

	bool Group_execIsWithin(Group::identifier group_id1, Group::identifier group_id2, Stuff::Scalar range)
	{
		mwobject_list objects;
		GetVehiclesFromGroup(group_id1,objects);

		{for (mwobject_list::iterator i = objects.begin();
				 i != objects.end();
				 ++i)
		{
			if (Group_execIsWithin(group_id2,*i,range) == true)
			{
				return(true);
			}
		}}

		return(false);
	}

	TypePtr execPlayerShooting(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		int size,i;
		Stuff::Time time = popInteger ();

		NameTable *table = NameTable::GetInstance();
		Check_Object (table);

		ablREPORT (id >=0,"to low of a number to playershooting");
		ablREPORT (id < 32,"to high of a number to playershooting");
		Check_Object(NameTable::GetInstance());

		size = table->nameTableArray[NameTable::PlayerArray].GetLength ();

		MWPlayer *player;
		for (i=0;i<size;i++)
		{
			NameTableEntry *data;

			data = &table->nameTableArray	[NameTable::PlayerArray][i];
			if (data->dataPointer->GetCurrent ())
			{
				if (id == 0)
				{
					player = Cast_Object(MWPlayer *,data->dataPointer->GetCurrent ());
					Check_Object(player);
					VehicleInterface *inter;

					inter = player->GetInterface ();
					Check_Object (inter);
					pushBoolean (inter->LastTimeShot () > (gos_GetElapsedTime() - time));

					return BooleanTypePtr;
				}
			}
			id--;
		}

		pushBoolean (false);
		return BooleanTypePtr;
	}

	TypePtr execisWithin (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long object1 = popInteger ();
		long object2 = popInteger ();
		long range = popInteger ();

		if ((object1 == ABL_NO_UNIT) ||
			(object2 == ABL_NO_UNIT))
		{
			pushBoolean(false);
			return BooleanTypePtr;
		}

		if ((ObjectIDisGroup(object1) == true) ||
			(ObjectIDisGroup(object2) == true))
		{
			bool in_range = false;

			if (ObjectIDisGroup(object1) == true)
			{
				if (ObjectIDisGroup(object2) == true)
				{
					in_range = Group_execIsWithin(ObjectIDtoGroupID(object1),ObjectIDtoGroupID(object2),(Stuff::Scalar)range);
				}
				else
				{
					Entity* who2 = GetObjectForID<Entity>(object2);
					if (!who2)
						in_range = false;
					else if (who2->IsDestroyed() == true)
					{
						in_range = false;
					}
					else
					{
						in_range = Group_execIsWithin(ObjectIDtoGroupID(object1),who2,(Stuff::Scalar)range);
					}
				}
			}
			else
			{
				Entity* who1 = GetObjectForID<Entity>(object1);

				if (!who1)
					in_range = false;
				else if (who1->IsDestroyed() == true)
				{
					in_range = false;
				}
				else
				{
					in_range = Group_execIsWithin(ObjectIDtoGroupID(object2),who1,(Stuff::Scalar)range);
				}
			}

			pushBoolean(in_range);
		}
		else
		{
			Entity* who1 = GetObjectForID<Entity>(object1);
			Entity* who2 = GetObjectForID<Entity>(object2);
      who1 = ConvertAIToEntity(who1);
      who2 = ConvertAIToEntity(who2);

			if ((who1 == 0) ||
				(who2 == 0) ||
				(who1->IsDestroyed() == true) ||
				(who2->IsDestroyed() == true))
			{
				pushBoolean(false);
			}
			else
			{
				ablREPORT(who1 != who2,ablERROR ("tried to ask if an object isWithin itself"));

				Stuff::Scalar temp;

				temp = (Stuff::Scalar) range;

				pushBoolean(who1->IsWithin(who2,temp,true));
			}
		}

		return BooleanTypePtr;
	}

	bool Group_execIsWithinLoc(Group::identifier id, const Stuff::Point3D& loc, int distance)
	{
		mwobject_list objects;
		GetVehiclesFromGroup(id,objects);

		{for (mwobject_list::iterator i = objects.begin();
				 i != objects.end();
				 ++i)
		{
			if (GetApproximateLength(loc,(Stuff::Point3D)(*i)->GetLocalToWorld()) < (Stuff::Scalar)distance)
			{
				return (true);
			}
		}}

		return (false);
	}

	TypePtr execisWithinLoc (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Stuff::Point3D loc;

		long id = popInteger ();
		getCodeToken();
		SymTableNodePtr idPtr = getCodeSymTableNodePtr();
		baseType(execVariable(idPtr, USE_REFPARAM));
		long* waypoint = (long*)(&((StackItemPtr)tos->address)->integer);
		Check_Pointer (waypoint);
		pop();

		loc.x = (float) waypoint[0];
		loc.y = (float) waypoint[1];
		loc.z = (float) waypoint[2];

		int distance = popInteger ();
		if (distance < 0) { // jcem
			distance = -distance;
			loc = Point3D::HellPoint;
		}

		if (ObjectIDisGroup(id) == true)
		{
			pushBoolean(Group_execIsWithinLoc(ObjectIDtoGroupID(id),loc,distance));
		}
		else
		{
			Entity* who1 = GetObjectForID<Entity>(id);
      who1 = ConvertAIToEntity(who1);

			if (!who1)
				pushBoolean (false);
			else if (who1->IsDestroyed() == true)
			{
				pushBoolean(false);
			}
			else
			{
				Stuff::Point3D extra,entityloc;

				entityloc = (Stuff::Point3D) who1->GetLocalToWorld ();
				entityloc.y = 0;
				loc.y = 0;
				extra.Subtract (loc,entityloc);
				distance *= distance;
				pushBoolean (distance > extra.GetLengthSquared ());
			}
		}

		return BooleanTypePtr;
	}

	TypePtr execisDead (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			pushBoolean(MW4AI::Groups::AllDead(ObjectIDtoGroupID(id)));
		}
		else
		{
			pushBoolean(IsDead(id));
		}

		return BooleanTypePtr;
	}
	TypePtr execisEqual (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		TypePtr paramTypePtr;

		getCodeToken ();
		paramTypePtr = baseType(execExpression());
		if (paramTypePtr == IntegerTypePtr)
			tos->real = (float)(tos->integer);

		float p1 = tos->real;
		pop();

		getCodeToken ();
		paramTypePtr = baseType(execExpression());
		if (paramTypePtr == IntegerTypePtr)
			tos->real = (float)(tos->integer);

		float p2 = tos->real;
		pop();
		pushBoolean (p1 == p2);
		return BooleanTypePtr;
	}
	TypePtr execisLesser (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		TypePtr paramTypePtr;
		getCodeToken ();
		paramTypePtr = baseType(execExpression());
		if (paramTypePtr == IntegerTypePtr)
			tos->real = (float)(tos->integer);

		float p1 = tos->real;
		pop();

		getCodeToken ();
		paramTypePtr = baseType(execExpression());
		if (paramTypePtr == IntegerTypePtr)
			tos->real = (float)(tos->integer);

		float p2 = tos->real;
		pop();
		pushBoolean (p1 < p2);
		return BooleanTypePtr;
	}
	TypePtr execisGreater (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		TypePtr paramTypePtr;
		getCodeToken ();
		paramTypePtr = baseType(execExpression());
		if (paramTypePtr == IntegerTypePtr)
			tos->real = (float)(tos->integer);

		float p1 = tos->real;
		pop();

		getCodeToken ();
		paramTypePtr = baseType(execExpression());
		if (paramTypePtr == IntegerTypePtr)
			tos->real = (float)(tos->integer);

		float p2 = tos->real;
		pop();
		pushBoolean (p1 > p2);
		return BooleanTypePtr;
	}
	TypePtr execequalID (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int p1 = popInteger ();
		int p2 = popInteger ();
		pushBoolean (p1 == p2);
		return BooleanTypePtr;
	}
	bool Group_execIsRammed(Group::identifier group_id)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			if ((*i)->RammedBy(gos_GetElapsedTime() - who_rammed_duration) != 0)
			{
				return (true);
			}
		}}

		return (false);
	}
	TypePtr execisRammed (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		
		if (ObjectIDisGroup(id) == true)
		{
			pushBoolean(Group_execIsRammed(ObjectIDtoGroupID(id)));
		}
		else
		{
			AI* who = GetAIForID(id);
			if (who)
			{
				Check_Object (who);

				if (who->RammedBy(gos_GetElapsedTime() - who_rammed_duration) == 0)
				{
					pushBoolean(false);
				}
				else
				{
					pushBoolean(true);
				}
			}
			else
			{
				pushBoolean (false);
			}
		}

		return BooleanTypePtr;
	}
	Adept::ObjectID Group_execWhoRammed(Group::identifier group_id)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			Entity* shot_by = (*i)->RammedBy(gos_GetElapsedTime() - who_rammed_duration);
			if (shot_by != 0)
			{
				return (shot_by->objectID);
			}
		}}

		return (ABL_NO_UNIT);
	}
	TypePtr execwhoRammed (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();

		if (ObjectIDisGroup(objectid) == true)
		{
			pushInteger(Group_execWhoRammed(ObjectIDtoGroupID(objectid)));
		}
		else
		{
			AI *who = GetAIForID(objectid);

			Verify ((long) who != -1);
			if (who)
			{
				Check_Object (who);

				Entity *target;
				target = who->RammedBy (gos_GetElapsedTime () - who_rammed_duration);
				if (!target)
				{
					pushInteger (ABL_NO_UNIT);
				}
				else
				{
					Check_Object (target);
					pushInteger (target->objectID);
				}
			}
			else
			{
				pushInteger	(ABL_NO_UNIT);
			}
		}
		return IntegerTypePtr;
	}
	bool Group_execCanSee(Group::identifier id, MWObject& who)
	{
		std::vector<CombatAI*> ais;
		GetAIsFromGroup<CombatAI>(id,ais);

		{for (std::vector<CombatAI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			if ((*i)->CanSee(who) == true)
			{
				return (true);
			}
		}}

		return (false);
	}
	TypePtr execcanSee (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		long objectid = popInteger ();

		MWObject* target = GetMWObjectForID(objectid);

		if (target == 0)
		{
			ablREPORT(1 == 0,ablERROR("Invalid target for CanSee()"));
			pushBoolean(false);
			return BooleanTypePtr;
		}

		if (ObjectIDisGroup(id) == true)
		{
			pushBoolean(Group_execCanSee(ObjectIDtoGroupID(id),*target));
			return BooleanTypePtr;
		}

		CombatAI* me = GetCombatAIForID(id);

		if (me == 0)
		{
			ablREPORT(1 == 0,ablERROR("Invalid source for CanSee()"));
			pushBoolean(false);
			return BooleanTypePtr;
		}

		pushBoolean(me->CanSee(*target));
		return BooleanTypePtr;
	}
	TypePtr execcanTarget (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		ablREPORT(ObjectIDisGroup(id) == false,ablERROR ("tried to call canTarget with a group"));
		long objectid = popInteger ();
		pushBoolean (true);			//TODO
		return BooleanTypePtr;
	}
	TypePtr execbattleValueLesser (SymTableNodePtr routineIdPtr)
	{
		long id = popInteger ();
		ablREPORT(ObjectIDisGroup(id) == false,ablERROR ("tried to call battleValueLesser with a group"));
		pushBoolean (true);			//TODO
		return BooleanTypePtr;
	}
	TypePtr execbattleValueLesserID (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		ablREPORT(ObjectIDisGroup(id) == false,ablERROR ("tried to call battleValueLesserID with a group"));
		long objectid = popInteger ();
		pushBoolean (true);			//TODO
		return BooleanTypePtr;
	}
	TypePtr exectimeLesser (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		ablREPORT ((ObjectIDisGroup(objectid) == false),ablERROR ("asked timeLesser for a group"));

		TypePtr paramTypePtr;
		getCodeToken ();
		paramTypePtr = baseType(execExpression());
		if (paramTypePtr == IntegerTypePtr)
			tos->real = (float)(tos->integer);

		float time = tos->real;
		pop();

		Check_Object (MechWarrior4::MWMission::GetInstance());
		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		ablREPORT (objectid >=0,ablERROR ("tried to check timeLesser on a timer id less than min"));
		ablREPORT (objectid <MAX_MISSION_TIMERS,ablERROR ("tried to check timeLesser on a timer id greater than max"));
		pushBoolean (mission->Timer (objectid).CurrTime () < time);
		return BooleanTypePtr;
	}
	TypePtr exectimeGreater (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		ablREPORT ((ObjectIDisGroup(objectid) == false),ablERROR ("asked timeGreater for a group"));

		TypePtr paramTypePtr;
		getCodeToken ();
		paramTypePtr = baseType(execExpression());
		if (paramTypePtr == IntegerTypePtr)
			tos->real = (float)(tos->integer);

		float time = tos->real;
		pop();

		Check_Object (MechWarrior4::MWMission::GetInstance());
		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		ablREPORT (objectid >=0,ablERROR ("tried to check timeGreater on a timer id less than min"));
		ablREPORT (objectid <MAX_MISSION_TIMERS,ablERROR ("tried to check timeGreater on a timer id greater than max"));
		pushBoolean (mission->Timer (objectid).CurrTime () > time);
		return BooleanTypePtr;
	}
	TypePtr execrand (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long low = popInteger ();
		long high = popInteger ();

		Stuff::Scalar value;

		value = Stuff::Random::GetFraction ();
		value *= (high-low);
		value += low;

		pushInteger ((int) value);
		return IntegerTypePtr;
	}
	TypePtr execplaySound (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		return NULL;
	}
	TypePtr execplaySoundOnce (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		return NULL;
	}
	TypePtr execkillSound (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		return NULL;
	}
	TypePtr execSetAudioFXEnabled (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		bool fred = popBoolean ();
		return NULL;
	}
	TypePtr execplayMusic (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Scalar volume = popInteger () / 100.0f;
		return NULL;
	}
	TypePtr execkillMusic (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		return NULL;
	}
	TypePtr execfadeInMusic (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		long time = popInteger ();
		Scalar volume = popInteger () / 100.0f;
		return NULL;
	}
	TypePtr execfadeOutMusic (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		long time = popInteger ();
		Scalar volume = popInteger () / 100.0f;
		return NULL;
	}
	TypePtr execplayEffect (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Entity *entity;
		EffectGenerator *obj;

		ablREPORT ((objectid != -1),ablERROR ("asked to playEffect for self"));
		entity = GetObjectForID<Entity>(objectid);
		if (!entity)
			return NULL;
		ablREPORT ((entity->IsDerivedFrom(EffectGenerator::DefaultData)),ablERROR ("trying to playEffect for a non effect"));
		obj = Cast_Object(EffectGenerator *, entity);
		Check_Object(obj);
		obj->executionState->RequestState(Entity::ExecutionStateEngine::AlwaysExecuteState);
		obj->PlayEffect();
		return NULL;
	}
	TypePtr execkillEffect (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Entity *entity;
		EffectGenerator *obj;

		Verify (objectid != -1);
		entity = GetObjectForID<Entity>(objectid);
		if (!entity)
			return NULL;
		ablREPORT ((entity->IsDerivedFrom(EffectGenerator::DefaultData)),ablERROR ("trying to killEffect for a non effect"));
		obj = Cast_Object(EffectGenerator *, entity);
		Check_Object(obj);
		obj->KillEffect();
		obj->executionState->RequestState(Entity::ExecutionStateEngine::NeverExecuteState);
		return NULL;
	}
	TypePtr execSetChanceLancematesEject (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int chance = popInteger();

		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		Check_Object (mission);
		mission->m_ChanceLancematesEject = chance;

		return NULL;
	}

	TypePtr execSetChanceLancematesOKWhenEjecting (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int chance = popInteger();

		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		Check_Object (mission);
		mission->m_ChanceLancematesOKWhenEjecting = chance;

		return NULL;
	}

	TypePtr execSetChanceLancematesInjuredWhenEjecting (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int chance = popInteger();

		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		Check_Object (mission);
		mission->m_ChanceLancematesInjuredWhenEjecting = chance;

		return NULL;
	}
	TypePtr execRevealLancemate (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		char *name = popStringPtr();
		MWGame* game = MWGame::GetInstance();
		if (!game)
			return NULL;
		Check_Object (game);
		LancemateManager *man = game->m_lancemates;
		man->RevealLancemate (name);

		return NULL;
	}
	TypePtr execHideLancemate (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		char *name = popStringPtr();
		MWGame* game = MWGame::GetInstance();
		if (!game)
			return NULL;
		Check_Object (game);
		LancemateManager *man = game->m_lancemates;
		man->HideLancemate (name);

		return NULL;
	}

	TypePtr execIsMissionComplete (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		char *mission_name = popStringPtr();
		bool result = false;
		if(MWGame::GetInstance())
		{
			if(MWGame::GetInstance()->m_campaign)
			{
				CampaignMissionPlug *mission_plug;
				mission_plug = MWGame::GetInstance()->m_campaign->FindMission(mission_name);
				if(mission_plug)
				{
					if(mission_plug->m_status == MWCampaign::Completed)
						result = true;
				}
			}
		}

		pushBoolean(result);
		return BooleanTypePtr;
	}

	TypePtr execrevealNavPoint (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		NavPoint *nav_point;

		nav_point = Cast_Object(NavPoint *,NameTable::GetInstance()->FindData(objectid));
		Check_Object (nav_point);
		nav_point->Reveal();
		return NULL;
	}

	TypePtr execIsNavRevealed (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		NavPoint *nav_point;

		nav_point = Cast_Object(NavPoint *,NameTable::GetInstance()->FindData(objectid));
		Check_Object (nav_point);
		pushBoolean(nav_point->IsVisible());
		return BooleanTypePtr;
	}

	TypePtr execsetNavPoint (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		NavPoint *nav_point;

		nav_point = Cast_Object(NavPoint *,NameTable::GetInstance()->FindData(objectid));

		if (nav_point == 0)
		{
			return (0);
		}

		Check_Object (nav_point);
		nav_point->Reveal();

		if (VehicleInterface::GetInstance() != 0)
		{
			Check_Object(VehicleInterface::GetInstance());
			VehicleInterface::GetInstance()->SetNavPoint(nav_point);
		}

		return NULL;
	}

	TypePtr execHideNav (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long objectid = popInteger();

		NavPoint *nav_point;

		nav_point = Cast_Object(NavPoint *,NameTable::GetInstance()->FindData(objectid));

		if (nav_point == 0)
		{
			return (0);
		}

		Check_Object (nav_point);
		nav_point->ClearVisibleFlag();
		nav_point->RemoveFromNavList();

		return NULL;
	}
	
	TypePtr execSetRadarNav (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long objectid = popInteger();
		long radarid = popInteger ();
		Verify ((radarid == -1) || ((radarid>=1)&&(radarid<=6)));

		NavPoint *nav_point;

		nav_point = Cast_Object(NavPoint *,NameTable::GetInstance()->FindData(objectid));

		if (nav_point == 0)
		{
			return (0);
		}

		Check_Object (nav_point);
		nav_point->m_RadarID = radarid;

		return NULL;
	}

	TypePtr execcreateHeatSphere (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Entity *target_entity;
		long radius = popInteger ();
		long heat = popInteger ();
		long secs = popInteger ();

		target_entity = NameTable::GetInstance()->FindData(objectid);
		Check_Object (target_entity);

		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		Check_Object (mission);
		
		Point3D center;
		center = target_entity->GetLocalToWorld();
		Scalar r_radius = (Scalar)radius;
		Scalar seconds = (Scalar)secs;
		Scalar heat_e = (Scalar)heat;
		mission->CreateNewHeatSphere(center, r_radius, seconds, heat_e);

		return NULL;
	}

	TypePtr execcreateInstantHeatSphere (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Entity *target_entity;
		long radius = popInteger ();
		long heat = popInteger ();

		target_entity = NameTable::GetInstance()->FindData(objectid);
		Check_Object (target_entity);

		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		Check_Object (mission);
		
		Point3D center;
		center = target_entity->GetLocalToWorld();
		Scalar r_radius = (Scalar)radius;
		Scalar heat_amount = (Scalar)heat;
		mission->CreateNewInstantHeatSphere(center, r_radius, heat_amount);

		return NULL;
	}

	TypePtr execcreateFogSphere (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Entity *target_entity;
		long radius = popInteger ();
		long secs = popInteger ();

		target_entity = NameTable::GetInstance()->FindData(objectid);
		Check_Object (target_entity);

		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		Check_Object (mission);
		
		Point3D center;
		center = target_entity->GetLocalToWorld();
		Scalar r_radius = (Scalar)radius;
		Scalar seconds = (Scalar)secs;
		mission->CreateNewFogSphere(center, r_radius, seconds);

		return NULL;
	}

	TypePtr execcreateRadarSphere (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Entity *target_entity;
		long radius = popInteger ();
		long radar_effic = popInteger ();
		long secs = popInteger ();

		target_entity = NameTable::GetInstance()->FindData(objectid);
		Check_Object (target_entity);

		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		Check_Object (mission);
		
		Point3D center;
		center = target_entity->GetLocalToWorld();
		Scalar r_radius = (Scalar)radius;
		Scalar seconds = (Scalar)secs;
		Scalar radar_e = (Scalar)radar_effic;
		mission->CreateNewRadarSphere(center, r_radius, seconds, radar_e);

		return NULL;
	}

	TypePtr execshowAllRevealedObjectives (SymTableNodePtr routineIdPtr)
	{
		Check_Object (ObjectiveRenderer::Instance);
		ObjectiveRenderer::Instance->ResetTime ();

		endFunction ();
		return NULL;
	}

	TypePtr execrevealObjective (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Objective *obj;

		obj = Cast_Object(Objective *,NameTable::GetInstance()->FindData(objectid));
		Check_Object (obj);
		obj->Reveal ();
		return NULL;
	}
	TypePtr exechideObjective (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Objective *obj;

		obj = Cast_Object(Objective *,NameTable::GetInstance()->FindData(objectid));
		Check_Object (obj);
		obj->Hide ();
		return NULL;
	}
	TypePtr execfailObjective (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Objective *obj;

		obj = Cast_Object(Objective *,NameTable::GetInstance()->FindData(objectid));
		Check_Object (obj);
		ablREPORT (!obj->HelpMessage (),"Tried to fail a help message");
		obj->Fail ();
		return NULL;
	}
	TypePtr execfailObjectiveAll (SymTableNodePtr routineIdPtr)
	{
		int j,size;
		NameTable *table = NameTable::GetInstance();
		Check_Object (table);

		DECLARE_ABL_CONTEXT;
		long time = popInteger ();

		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		Check_Object (mission);
		mission->SetEndMissionTime ((Stuff::Scalar) time);


		size = table->nameTableArray[NameTable::ObjectiveArray].GetLength ();
		for (j=0;j<size;j++)
		{
			NameTableEntry *data;

			data = &table->nameTableArray [NameTable::ObjectiveArray][j];

			Objective *obj;

			obj = Cast_Object (Objective *,data->dataPointer->GetCurrent());
			Check_Object (obj);
			if ((!obj->HelpMessage ()) && (obj->Status () == Objective::Objective_Neutral))
				obj->Fail ();
		}
		mission->EndMissionState (false);
		return NULL;
	}
	TypePtr execEndMission (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		bool good = popBoolean ();
		long time = popInteger ();
		
		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		Check_Object (mission);
		mission->SetEndMissionTime ((Stuff::Scalar) time);
		mission->EndMissionState (good);
		return NULL;
	}

	TypePtr execRespawnMission (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		
//		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
//		Check_Object (mission);
	//	Mission *mission = Mission::GetInstance();
	//	Check_Object (mission);
	//	mission->RespawnMission();

		#if 1
			MWApplication *mw_app = MWApplication::GetInstance();
			Check_Object(mw_app);

			mw_app->RespawnMission();
		#endif
		return NULL;
	}

	TypePtr execsaveGame (SymTableNodePtr routineIdPtr)
	{
		// no parameters or return value
		if(MWGame::GetInstance())
		{
			MWGame::GetInstance()->SaveInMissionGame();
		}
		endFunction ();
		return NULL;
	}

	TypePtr execHelpMessage (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		long time = popInteger ();
		Objective *obj;

		if (objectid == -2)
		{
			ObjectiveRenderer::Instance->Help(0,0);
		}
		else
		{
			obj = Cast_Object(Objective *,NameTable::GetInstance()->FindData(objectid));
			Check_Object (obj);
			ablREPORT (obj->HelpMessage (),"Tried to show a regular objective as a help message");
			obj->ShowHelp (time);
		}

		return NULL;
	}

	TypePtr execsuccessObjective (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Objective *obj;

		obj = Cast_Object(Objective *,NameTable::GetInstance()->FindData(objectid));
		Check_Object (obj);
		ablREPORT (!obj->HelpMessage (),"Tried to succeed a help message");
		obj->Succeed ();
		return NULL;
	}
	TypePtr execsuccessObjectiveAll (SymTableNodePtr routineIdPtr)
	{
		int j,size;
		NameTable *table = NameTable::GetInstance();
		Check_Object (table);

		DECLARE_ABL_CONTEXT;
		long time = popInteger ();

		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		Check_Object (mission);
		mission->SetEndMissionTime ((Stuff::Scalar) time);

		size = table->nameTableArray[NameTable::ObjectiveArray].GetLength ();
		for (j=0;j<size;j++)
		{
			NameTableEntry *data;

			data = &table->nameTableArray [NameTable::ObjectiveArray][j];

			Objective *obj;

			obj = Cast_Object (Objective *,data->dataPointer->GetCurrent());
			Check_Object (obj);
			if ((!obj->HelpMessage ()) && (obj->Status () == Objective::Objective_Neutral))
				obj->Succeed ();
		}
		mission->EndMissionState (true);
		return NULL;
	}

	TypePtr execcheckObjectiveCompletion (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Objective *obj;

		obj = Cast_Object(Objective *,NameTable::GetInstance()->FindData(objectid));
		Check_Object (obj);
		pushInteger (obj->Status ());
		return IntegerTypePtr;
	}

	TypePtr execisVisible (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Objective *obj;

		obj = Cast_Object(Objective *,NameTable::GetInstance()->FindData(objectid));
		Check_Object (obj);
		if (((int) obj) == -1)
			pushBoolean (false);
		else if (!obj)
			pushBoolean (false);
		else
			pushBoolean (obj->Visible ());
		return BooleanTypePtr;
	}

	void TeleportWorker (MWObject *who1, const Point3D& lookpt, int flags, Point3D& new_translation)
	{
		ablREPORT (new_translation.x > MinX,"x coordinate in teleport is less than map size");
		ablREPORT (new_translation.z > MinZ,"z coordinate in teleport is less than map size");
		ablREPORT (new_translation.x < MaxX,"x coordinate in teleport is greater than map size");
		ablREPORT (new_translation.z < MaxZ,"z coordinate in teleport is greater than map size");

		if (!(flags & 1)) // overridey
		{
			// Find the ground

			//
			// make a line...
			//
			Point3D curlocation (who1->GetLocalToWorld ());
			Stuff::Line3D line;
			line.m_length = 20.0f;
			line.m_direction = Vector3D::Down;
			line.m_origin = new_translation;
			if (curlocation.y > 0)									// if not in hell then use the vehicles y location, else you point we want to move to
				line.m_origin.y = curlocation.y + 5.0f;	// pretty harsh hill!  =)

			//
			// Prepare query
			//	
			Stuff::Normal3D normal;
			Entity::CollisionQuery query(&line, &normal, Entity::CanBeWalkedOnFlag, who1);

			//
			// 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);
			}
			else
			{
				// Damnit...then find the ground aggresivly!!!!
				line.m_origin = new_translation;
				if (curlocation.y > 0)									// if not in hell then use the vehicles y location, else you point we want to move to
					line.m_origin.y = curlocation.y + 100.0f;	// pretty harsh hill!  =)
				else
					line.m_origin.y = new_translation.y + 100.0f;
				line.m_length = 1000.0f;
				entity_hit = CollisionGrid::Instance->ProjectLine(&query);
				if (entity_hit != NULL)
				{
					line.FindEnd(&new_translation);
				}
				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);
					}
				}
				// ok stop we are way off the map
			}
		}

		LinearMatrix4D new_local_to_world;

		// from here by jcem
       if (flags & 2) {
            Stuff::Point3D rv(lookpt);
#if 1
            LinearMatrix4D mo = who1->GetLocalToWorld();

            Point3D new_trans(new_translation);
            new_trans.y = rv.y;
            mo.BuildTranslation(new_trans);

            //LinearMatrix4D mv = mo.Invert();
            //mv *= rv;
            //rv = mv;
            Vector3D vFN;
            vFN.Subtract(rv, new_trans);
            UnitVector3D vF(vFN);
            UnitVector3D vU;
            Vector3D vRN;

            mo.GetLocalUpInWorld(&vU);

            vRN.Cross(vF, vU);
            UnitVector3D vR(vRN);

            mo(FORWARD_AXIS,X_Axis) = vF.x;
            mo(FORWARD_AXIS,Y_Axis) = vF.y;
            mo(FORWARD_AXIS,Z_Axis) = vF.z;

            mo(RIGHT_AXIS,X_Axis) = vR.x;
            mo(RIGHT_AXIS,Y_Axis) = vR.y;
            mo(RIGHT_AXIS,Z_Axis) = vR.z;

            YawPitchRoll moA(mo);
            moA.pitch = 0.0f;
		    moA.roll = 0.0f;
            mo.BuildRotation(moA);

            mo.BuildTranslation(new_translation);
            new_local_to_world = mo;
#elif 1
            LinearMatrix4D mo = who1->GetLocalToWorld();

            Stuff::Scalar angle = 3.141592 / (2 * 3);
            Stuff::Scalar angle_inc = angle / 2;
			YawPitchRoll current_rotation;

            Point3D new_trans(new_translation);
            new_trans.y = rv.y;
            mo.BuildTranslation(new_trans);

            int nTimes = (int)(3.141592 * 2.0 / angle_inc) + 1;
            while(!MatrixFacesPoint(mo, rv, angle)) {
			    YawPitchRoll current_rotation;
			    current_rotation = mo;
			    current_rotation.yaw += angle_inc;
			    current_rotation.Normalize();
			    mo.BuildRotation(current_rotation);
                if (nTimes-- <= 0)
                    break;
            }

            YawPitchRoll moA(mo);
            moA.pitch = 0.0f;
		    moA.roll = 0.0f;
            mo.BuildRotation(moA);

            mo.BuildTranslation(new_translation);
            new_local_to_world = mo;
#elif 0
            LinearMatrix4D mt = who2->GetLocalToWorld();
			Point3D pt = (Point3D)mt;
            LinearMatrix4D mo = who1->GetLocalToWorld();
            Point3D po = (Point3D)mo;

            Vector3D vt(new_translation);

            LinearMatrix4D mv;
            //mv.BuildIdentity();
            mv.BuildRotation(vt);
            //mv.BuildTranslation(new_translation);

            Point3D pppp;
            pppp.Multiply(pt, mv);

            Vector3D vvv(pppp);
            LinearMatrix4D dd;
            dd.BuildIdentity();
            dd.BuildRotation(vvv);

            LinearMatrix4D qq;
            qq.Multiply(mv, dd);

            YawPitchRoll new_rotation(qq);

            new_rotation.yaw.Normalize();
            new_rotation.pitch = 0.0f;
		    new_rotation.roll = 0.0f;

		new_local_to_world.BuildRotation(new_rotation);
		    new_local_to_world.BuildTranslation(new_translation);
#else
			Vector3D vdir;
			
            static bool s_bv3d = 1;
            if (s_bv3d)
                vdir.Subtract(pt, new_translation);
            else
			    vdir.Subtract(new_translation, pt);

#define PIX 3.141592
#define R2D(x) ((((x) * 180.0)) / PIX)
            char sz[256];

            Vector3D vt(pt);
            LinearMatrix4D mv;
            mv.BuildIdentity(pt);
            mv.BuildRotation(vt);
            YawPitchRoll t_rotation(mv);

            LinearMatrix4D mx;
            mx.BuildIdentity();
            mx.BuildRotation(vdir);
            LinearMatrix4D inv_mx;
            inv_mx.Invert(mx);

            YawPitchRoll new_rotation(inv_mx);

            sprintf(sz, "t %3.2f, n %3.2f\n", R2D(t_rotation.yaw.angle), R2D(new_rotation.yaw.angle));
            ::OutputDebugString(sz);

            static int s_nAdd = 0;
            switch(s_nAdd)
            {
            case -1:
                new_rotation.yaw -= t_rotation.yaw;
                break;
            case 0:
                break;
            case +1:
                new_rotation.yaw += t_rotation.yaw;
                break;
            }

            static s_nDeg = -1;
            switch(s_nDeg)
            {
            case 0:
                new_rotation.yaw += PIX / 2.0;
                break;
            case 1:
                new_rotation.yaw += PIX;
                break;
            case 2:
                new_rotation.yaw += PIX * 3.0 / 2.0;
                break;
            case 3:
                new_rotation.yaw += PIX * 2.0;
                break;
            }
            new_rotation.yaw.Normalize();
            new_rotation.pitch = 0.0f;
		    new_rotation.roll = 0.0f;
            inv_mx.BuildRotation(new_rotation);
		    inv_mx.BuildTranslation(new_translation);

            new_local_to_world = inv_mx;
    	    //new_local_to_world.BuildRotation(new_rotation);
#endif
		} else { // original...
    		YawPitchRoll new_rotation;
			new_rotation = (YawPitchRoll) who1->GetLocalToWorld ();

		    //new_rotation.pitch = 0.0f;
		    new_rotation.roll = 0.0f;

		    new_local_to_world.BuildRotation(new_rotation);
		    new_local_to_world.BuildTranslation(new_translation);
        }
		who1->SetNewLocalToParent(new_local_to_world);
		// to here by jcem
		who1->SyncMatrices (true);
		Map::GetInstance()->UpdateZone (who1);
		who1->initialLocalToParent = who1->GetLocalToParent();
		who1->initialWorldSpaceVelocity = who1->worldSpaceVelocity,
		who1->initialWorldSpaceAcceleration = who1->worldSpaceAcceleration;

	}
	
    void Group_TeleportToHell(MWObject *who1)
	{
		Point3D hpt(Point3D::HellPoint);

		TeleportWorker (who1,Point3D::HellPoint,1,hpt);
		AI *ai;
		ai = who1->GetAI ();
		if (ai)
		{
			ai->Shutdown ();
			ai->AlwayActive (false);
//			ai->TurnOff ();
			if (ai->IsDerivedFrom(MoverAI::DefaultData))
			{
				MoverAI *move =Cast_Object (MoverAI *,ai);
				move->ClearMoveOrder ();
			}
			if (ai->IsDerivedFrom(CombatAI::DefaultData))
			{
				CombatAI *combat =Cast_Object (CombatAI *,ai);
				combat->OrderStopAttacking ();
			}
			if (ai->IsDerivedFrom (PlaneAI::DefaultData))
			{
				PlaneAI *planeai = Cast_Object (PlaneAI *,ai);
				planeai->hellteleport ();
			}
		}
    }
	TypePtr execteleportToHell (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int id = popInteger ();

        if (ObjectIDisGroup(id) == true) {
            int group_id = ObjectIDtoGroupID(id);
		    mwobject_list targets;
		    GetVehiclesFromGroup(group_id,targets);
		    {for (mwobject_list::const_iterator i = targets.begin(); i != targets.end(); ++i)
		    {
                Group_TeleportToHell(*i);
            }}
        } else {
		    MWObject *who1 = GetMWObjectForID(id);
            if (who1) {
                Group_TeleportToHell(who1);
            }
        }
		return NULL;
	}

	TypePtr execteleport (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int id = popInteger ();
        Stuff::Point3D tpt = popPoint();

		MWObject *who1 = GetMWObjectForID(id);
		if (!who1)
			return NULL;
		Verify (who1);

		TeleportWorker (who1,Point3D::HellPoint,0,tpt);
		return NULL;
	}
	TypePtr execteleportAndLook (SymTableNodePtr routineIdPtr) // jcem
	{
		DECLARE_ABL_CONTEXT;

		int id = popInteger ();
        Stuff::Point3D lookpt = popPoint();
        int flags = popInteger ();
        Stuff::Point3D tpt = popPoint();

		MWObject *who1 = GetMWObjectForID(id);
		if (!who1)
			return NULL;
		Verify (who1);

		TeleportWorker (who1,lookpt,flags,tpt);
		return NULL;
	}
	TypePtr execDisableAIJumping (SymTableNodePtr routineIdPtr)
	{
		MoverAI::DisableAIJumping ();
		endFunction ();
		return NULL;
	}

	TypePtr execplayChatter (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		return NULL;
	}
	TypePtr execplayChatterPriority (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		long priority = popInteger ();
		return NULL;
	}
	TypePtr execkillChatter (SymTableNodePtr routineIdPtr)
	{
		endFunction ();
		// no parameters or return value
		return NULL;
	}
	TypePtr execstartTimer (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Check_Object (MechWarrior4::MWMission::GetInstance());
		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		ablREPORT ((objectid >=0),ablERROR ("trying to startTimer on an invalid timer"));
		ablREPORT ((objectid <MAX_MISSION_TIMERS),ablERROR ("trying startTimer on an invalid timer"));
		mission->Timer (objectid).Start ();
		return NULL;
	}
	TypePtr execkillTimer (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Check_Object (MechWarrior4::MWMission::GetInstance());
		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		ablREPORT ((objectid >=0),ablERROR ("trying to killTimer on an invalid timer"));
		ablREPORT ((objectid <MAX_MISSION_TIMERS),ablERROR ("trying killTimer on an invalid timer"));
		mission->Timer (objectid).Stop ();
		return NULL;
	}
	TypePtr execresetTimer (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		Check_Object (MechWarrior4::MWMission::GetInstance());
		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		ablREPORT ((objectid >=0),ablERROR ("trying to resetTimer on an invalid timer"));
		ablREPORT ((objectid <MAX_MISSION_TIMERS),ablERROR ("trying resetTimer on an invalid timer"));
		mission->Timer (objectid).Stop ();
		mission->Timer (objectid).Start ();
		return NULL;
	}
	TypePtr execpauseTimer (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long objectid = popInteger ();
		bool pause = popBoolean ();
		Check_Object (MechWarrior4::MWMission::GetInstance());
		MechWarrior4::MWMission *mission = Cast_Object (MechWarrior4::MWMission*,MechWarrior4::MWMission::GetInstance());
		ablREPORT ((objectid >=0),ablERROR ("trying to pauseTimer on an invalid timer"));
		ablREPORT ((objectid <MAX_MISSION_TIMERS),ablERROR ("trying pauseTimer on an invalid timer"));
		mission->Timer (objectid).Pause (pause);
		return NULL;
	}

//orders

	TypePtr execorderDie (SymTableNodePtr routineIdPtr)
	{
		// no parameters or return value
		Check_Pointer(CurWarrior);
		CurWarrior->StopScript ();
		endFunction ();
		return NULL;
	}
	TypePtr execorderMoveLookOut (SymTableNodePtr routineIdPtr)
	{
		// no parameters or return value
		Check_Pointer(CurMoverAI);

		if (CurMoverAI->IsDerivedFrom(PlaneAI::DefaultData) == false)
		{
			ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to lookout on a non mover ai"));
			ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("asking to lookout on a dead unit"));
			CurMoverAI->orderMoveLookOut ();
		}
		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}

		endFunction ();

		return NULL;
	}

	TypePtr execorderFormOnSpot (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long GroupID = popInteger ();
		long* loc = popIntegerPtr ();
		long* dir = popIntegerPtr ();
		long speed = popInteger ();
		long form = popInteger ();
		long sparse = popInteger ();
		bool clear = popBoolean ();

		ablREPORT ((ObjectIDisGroup(GroupID)),ablERROR ("trying to form on spot for a non group"));
		Verify (loc);
		Verify (dir);

		std::vector<MoverAI*> list;
		GetAIsFromGroup<MoverAI> (ObjectIDtoGroupID(GroupID),list);

		speed = ConvertKPHtoMPS (speed);

		Form_On_Spot (list,loc,dir,speed,form,sparse,clear);
		return NULL;
	}

	TypePtr execorderFormationMove (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long GroupID = popInteger ();
		long PathId = popInteger ();
		long speed = popInteger ();
		long type = popInteger ();
		long form = popInteger ();
		long sparse = popInteger ();
		bool clear = popBoolean ();
	
		Verify (type >= 0);
		Verify (type <= PATROL_SEESAW);
		ablREPORT ((ObjectIDisGroup(GroupID)),ablERROR ("trying to formation move for a non group"));
		ablREPORT (PathId!=-1,ablERROR ("pathid is invalid"));
		Path *path = Cast_Object (Path *,NameTable::GetInstance()->FindData (PathId));
		Check_Object (path);
		Verify (path->IsDerivedFrom (Path::DefaultData));

		std::vector<MoverAI*> list;
		GetAIsFromGroup<MoverAI> (ObjectIDtoGroupID(GroupID),list);

		speed = ConvertKPHtoMPS (speed);

		pushBoolean (Form_Move (list,PathId,speed,type,form,sparse,clear));
		return BooleanTypePtr;
	}

	TypePtr execorderMoveTo (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurMoverAI);
		long PathId = popInteger ();
		long speed = popInteger ();
		long type = popInteger ();
		bool forwards = popBoolean ();
		bool clear = popBoolean ();

		ablREPORT (type >= 1,"Bad move type");
		ablREPORT (type <= PATROL_SEESAW,"Bad move type");
		ablREPORT (PathId!=-1,ablERROR ("pathid is invalid"));
		Path *path = Cast_Object (Path *,NameTable::GetInstance()->FindData (PathId));
		Check_Object (path);
		ablREPORT (path->IsDerivedFrom (Path::DefaultData),ablERROR ("unknown path in moveto"));

		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to move to for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to move to for a dead unit"));

		speed = ConvertKPHtoMPS (speed);
		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}

		pushBoolean (CurMoverAI->orderMoveToSemi (path,speed,type,forwards,clear));

		return BooleanTypePtr;
	}
	TypePtr execorderMoveToFree (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurMoverAI);
		long PathId = popInteger ();
		long speed = popInteger ();
		long type = popInteger ();
		bool forwards = popBoolean ();
		bool clear = popBoolean ();

		Verify (type >= 0);
		Verify (type <= PATROL_SEESAW);
		ablREPORT (PathId!=-1,ablERROR ("pathid is invalid"));
		Path *path = Cast_Object (Path *,NameTable::GetInstance()->FindData (PathId));
		Check_Object (path);
		ablREPORT (path->IsDerivedFrom (Path::DefaultData),ablERROR ("unknown path in moveto"));

		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to move to for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to move to for a dead unit"));

		speed = ConvertKPHtoMPS (speed);
		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}

		pushBoolean (CurMoverAI->orderMoveTo (path,speed,type,forwards,clear));

		return BooleanTypePtr;
	}
	TypePtr execorderMoveToRigid (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurMoverAI);
		long PathId = popInteger ();
		long speed = popInteger ();
		long type = popInteger ();
		bool forwards = popBoolean ();
		bool clear = popBoolean ();

		Verify (type >= 0);
		Verify (type <= PATROL_SEESAW);
		ablREPORT (PathId!=-1,ablERROR ("pathid is invalid"));
		Path *path = Cast_Object (Path *,NameTable::GetInstance()->FindData (PathId));
		Check_Object (path);
		ablREPORT (path->IsDerivedFrom (Path::DefaultData),ablERROR ("unknown path in moveto rigid"));

		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to move to rigid for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to move to rigid for a dead unit"));

		speed = ConvertKPHtoMPS (speed);
		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}

		pushBoolean (CurMoverAI->orderMoveToRigid (path,speed,type,forwards,clear));

		return BooleanTypePtr;
	}
	TypePtr execorderMoveFlee (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurMoverAI);
		long objectid = popInteger ();
		long speed = popInteger ();
		Verify (objectid != -1);
		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to flee for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to flee for a dead unit"));
		MWObject* who = GetMWObjectForID(objectid);
		if (!who)
		{
			pushInteger (0);
			return IntegerTypePtr;
		}
		Check_Object (who);
		Verify (!CurMoverAI->Dead ());
		speed = ConvertKPHtoMPS (speed);
		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}
		pushInteger (CurMoverAI->orderMoveFlee (who,speed));

		return IntegerTypePtr;
	}
	TypePtr execorderMoveResumePatrolRigid (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);
		long PathId = popInteger ();
		long speed = popInteger ();
		long type = popInteger ();
		bool forwards = popBoolean ();
		bool clear = popBoolean ();
		ablREPORT (PathId!=-1,ablERROR ("pathid is invalid"));
		Path *path = Cast_Object (Path *,NameTable::GetInstance()->FindData (PathId));
		Check_Object (path);
		ablREPORT (path->IsDerivedFrom (Path::DefaultData),ablERROR ("unknown path in resume patrol rigid"));

		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to resume patrol for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to resume patrol for a dead unit"));

		speed = ConvertKPHtoMPS (speed);
		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}
		pushBoolean(CurMoverAI->orderMoveResumePatrolRigid (path,speed,type,forwards,clear));
		return BooleanTypePtr;
	}
	TypePtr execorderMoveResumePatrol (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);
		long PathId = popInteger ();
		long speed = popInteger ();
		long type = popInteger ();
		bool forwards = popBoolean ();
		bool clear = popBoolean ();
		ablREPORT (PathId!=-1,ablERROR ("pathid is invalid"));
		Path *path = Cast_Object (Path *,NameTable::GetInstance()->FindData (PathId));
		Check_Object (path);
		ablREPORT (path->IsDerivedFrom (Path::DefaultData),ablERROR ("unknown path in resume patrol"));

		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to resume patrol for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to resume patrol for a dead unit"));

		speed = ConvertKPHtoMPS (speed);
		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}
		pushBoolean(CurMoverAI->orderMoveResumePatrolSemi (path,speed,type,forwards,clear));
		return BooleanTypePtr;
	}
	TypePtr execorderMoveResumePatrolFree (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);
		long PathId = popInteger ();
		long speed = popInteger ();
		long type = popInteger ();
		bool forwards = popBoolean ();
		bool clear = popBoolean ();
		ablREPORT (PathId!=-1,ablERROR ("pathid is invalid"));
		Path *path = Cast_Object (Path *,NameTable::GetInstance()->FindData (PathId));
		Check_Object (path);
		ablREPORT (path->IsDerivedFrom (Path::DefaultData),ablERROR ("unknown path in resume patrol"));

		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to resume patrol for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to resume patrol for a dead unit"));

		speed = ConvertKPHtoMPS (speed);
		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}
		pushBoolean(CurMoverAI->orderMoveResumePatrol (path,speed,type,forwards,clear));
		return BooleanTypePtr;
	}
	TypePtr execorderMoveFollow (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);
		long objectid = popInteger ();
		long xoffset = popInteger ();
		long zoffset = popInteger ();

		if ((xoffset > 0) && (xoffset < 30))
			xoffset = 30;
		if ((zoffset > 0) && (zoffset < 30))
			zoffset = 30;
		if ((xoffset < 0) && (xoffset > -30))
			xoffset = -30;
		if ((zoffset < 0) && (zoffset > -30))
			zoffset = -30;
		Verify (objectid != -1);
		MWObject *who = GetMWObjectForID(objectid);
		if (!who)
			return NULL;
		Check_Object (who);
		Check_Object (CurMoverAI);
		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to follow for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to follow for a dead unit"));
		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}
		CurMoverAI->orderMoveFollow (who,xoffset,zoffset,1000);
		return NULL;
	}
	TypePtr execorderMoveSit (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);
		bool shutdown = popBoolean ();
		Check_Object (CurMoverAI);
		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to sit for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to sit for a dead unit"));

		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}
		if (CurMoverAI->IsDerivedFrom(PlaneAI::DefaultData) == false)
		{
			CurMoverAI->orderMoveSit (shutdown);
		}

		return NULL;
	}
	TypePtr execorderMoveToLocPoint (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);
		Stuff::Point3D loc;

		getCodeToken();
		SymTableNodePtr idPtr = getCodeSymTableNodePtr();
		baseType(execVariable(idPtr, USE_REFPARAM));
		long* waypoint = (long*)(&((StackItemPtr)tos->address)->integer);
		Check_Pointer (waypoint);
		pop();

		loc.x = (float) waypoint[0];
		loc.y = (float) waypoint[1];
		loc.z = (float) waypoint[2];

		long speed = popInteger ();
		bool forwards = popBoolean ();
		bool clear = popBoolean ();
		Check_Object (CurMoverAI);
		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to move locpoint for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to move locpoint for a dead unit"));

		speed = ConvertKPHtoMPS (speed);
		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}
		pushBoolean (CurMoverAI->orderMoveToLocPoint (loc,speed,forwards,clear));
		return BooleanTypePtr;
	}
	TypePtr execorderMoveToObject (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);
		Check_Object (CurMoverAI);
		long objectid = popInteger ();
		long speed = popInteger ();

		Verify (objectid != -1);
		Entity* who = GetObjectForID<Entity>(objectid);
    who = ConvertAIToEntity(who);
		if (!who)
		{
			pushBoolean (false);
			return BooleanTypePtr;
		}
		Check_Object (who);
		Check_Object (CurMoverAI);
		ablREPORT ((CurMoverAI->IsDerivedFrom (MoverAI::DefaultData)),ablERROR ("trying to move object for a non mover"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to move object for a dead unit"));
		speed = ConvertKPHtoMPS (speed);

		if (CurMoverAI->IsDerivedFrom (CombatAI::DefaultData))
		{
			CombatAI *combat = Cast_Object (CombatAI *,CurMoverAI);
			if (combat->OverridingMovement () && combat->Attacking ())
			{
				combat->OrderStopAttacking ();
			}
		}
		if (who->IsDerivedFrom (Vehicle::DefaultData))
		{
			CurMoverAI->orderMoveFollow (who,0,-20,speed);
			Check_Object (CurMoverAI->getVehicle ());
			pushBoolean(CurMoverAI->getVehicle ()->IsWithin(who,40,true));
		}
		else
		{
			pushBoolean (CurMoverAI->orderMoveToObject (who,speed));
		}


		return BooleanTypePtr;
	}
	TypePtr execorderAttack (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);

		bool moveoverride = popBoolean();
		CombatAI* combat_ai = GetCombatAIForID(-1);
		if (!combat_ai)
		{
			pushBoolean (false);
			return BooleanTypePtr;
		}
		Verify(!combat_ai->Dead ());

		if ((combat_ai->Target() == 0) ||
			(combat_ai->Target()->IsDestroyed() == true))
		{
			pushBoolean(true);
		}
		else
		{
			pushBoolean(false);
  		combat_ai->OrderAttack(moveoverride);
		}

		return BooleanTypePtr;
	}
	TypePtr execorderAttackTactic (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);

		long tactic = popInteger ();
		bool moveoverride = popBoolean ();

		CombatAI* combat_ai = GetCombatAIForID(-1);
		if (!combat_ai)
		{
			pushBoolean (false);
			return BooleanTypePtr;
		}
		Verify (!combat_ai->Dead ());

		if (tactic == MW4AI::Tactics::TACTIC_PICK_BEST)
		{
			combat_ai->OrderAttack(moveoverride);
		}
		else
		{
			combat_ai->OrderAttackTactic((MW4AI::Tactics::TacticID)tactic,moveoverride);
		}

		if ((combat_ai->Target() == 0) ||
			(combat_ai->Target()->IsDestroyed() == true))
		{
			pushBoolean(true);
		}
		else
		{
			pushBoolean(false);
		}

		return BooleanTypePtr;
	}
	TypePtr execorderAttackBomb (SymTableNodePtr routineIdPtr)
	{
		Check_Pointer(CurWarrior);
		Verify (!CurWarrior->Dead ());
		pushBoolean (true);		// TODO
		endFunction ();
		return BooleanTypePtr;
	}
	TypePtr execorderStopAttacking(SymTableNodePtr routineIdPtr)
	{
		Check_Pointer(CurWarrior);
		Verify (!CurWarrior->Dead ());
		if (CurWarrior->IsDerivedFrom(CombatAI::DefaultData) == false)
		{
			ablREPORT(0,ablERROR("Cannot orderStopAttacking() on a non-combat-AI"));
		}
		else
		{
			CombatAI* combat_ai = Cast_Object(CombatAI*,CurWarrior);
			Check_Object(combat_ai);

			combat_ai->OrderStopAttacking();
		}

		endFunction();											// no parameters or return value
		return NULL;
	}
	TypePtr execorderTakeOff (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);
		int distance = popInteger ();

		Check_Object (CurMoverAI);

		if (CurMoverAI->IsDerivedFrom(PlaneAI::DefaultData) == false)
		{
			pushBoolean(true);
			return BooleanTypePtr;
		}

		ablREPORT ((CurMoverAI->IsDerivedFrom (PlaneAI::DefaultData)),ablERROR ("trying to takeoff for a non plane"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to takeoff for a dead unit"));
		PlaneAI *plane_ai = Cast_Object(PlaneAI *, CurMoverAI);
		pushBoolean (plane_ai->orderTakeOff (distance));

		return BooleanTypePtr;
	}

	TypePtr execorderLand (SymTableNodePtr routineIdPtr)
	{
		Check_Pointer(CurWarrior);

		Check_Object (CurMoverAI);
		ablREPORT ((CurMoverAI->IsDerivedFrom (PlaneAI::DefaultData)),ablERROR ("trying to land for a non plane"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to takeoff for a dead unit"));
		PlaneAI *plane_ai = Cast_Object(PlaneAI *, CurMoverAI);
		pushBoolean (plane_ai->orderLand ());
		endFunction ();

		return BooleanTypePtr;
	}
	TypePtr execorderDoorOpen (SymTableNodePtr routineIdPtr)
	{
		Check_Pointer(CurWarrior);

		Check_Object (CurMoverAI);
		ablREPORT ((CurMoverAI->IsDerivedFrom (PlaneAI::DefaultData)),ablERROR ("trying to door open for a non dropship"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to door open for a dead unit"));
		PlaneAI *plane_ai = Cast_Object(PlaneAI *, CurMoverAI);
		pushBoolean (plane_ai->orderDoorOpen ());
		endFunction ();

		return BooleanTypePtr;
	}

	TypePtr execorderDoorClose (SymTableNodePtr routineIdPtr)
	{
		Check_Pointer(CurWarrior);

		Check_Object (CurMoverAI);
		ablREPORT ((CurMoverAI->IsDerivedFrom (PlaneAI::DefaultData)),ablERROR ("trying to door close for a non dropship"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to door close for a dead unit"));
		PlaneAI *plane_ai = Cast_Object(PlaneAI *, CurMoverAI);
		pushBoolean (plane_ai->orderDoorClose ());
		endFunction ();

		return BooleanTypePtr;
	}

	TypePtr execorderShootPoint (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Pointer(CurWarrior);

		getCodeToken();
		SymTableNodePtr idPtr = getCodeSymTableNodePtr();
		baseType(execVariable(idPtr, USE_REFPARAM));
		long* waypoint = (long*)(&((StackItemPtr)tos->address)->integer);
		Check_Pointer (waypoint);
		pop();

		Stuff::Point3D loc((float) waypoint[0],
						   (float) waypoint[1],
						   (float) waypoint[2]);

		long stretch = popInteger ();
		Check_Object (CurMoverAI);
		ablREPORT ((CurMoverAI->IsDerivedFrom (CombatAI::DefaultData)),ablERROR ("trying to shootpoint for a non combat"));
		ablREPORT ((!CurMoverAI->Dead ()),ablERROR ("trying to shootpoint for a dead unit"));

		CombatAI* combat_ai = Cast_Object(CombatAI*,CurMoverAI);
		Check_Object(combat_ai);

		combat_ai->OrderShootPoint(loc,stretch);

		return NULL;
	}

	void Group_LancemateCommand(Group::identifier group_id, long command)
	{
		std::vector<CombatAI*> objects;
		GetAIsFromGroup<CombatAI>(group_id,objects);

		MW4AI::LancemateCommands::lancemate_list l;

		{for (std::vector<CombatAI*>::iterator i = objects.begin();
			  i != objects.end();
			  ++i)
		{
			l.push_back((*i)->GetSelf().objectID);
		}}

		if (l.size() > 0)
		{
			MW4AI::LancemateCommands::Execute((MW4AI::LancemateCommands::ID)command,l);
		}
	}

	TypePtr execlancemateCommand(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		long command = popInteger();

		if (ObjectIDisGroup(id) == true)
		{
			Group_LancemateCommand(ObjectIDtoGroupID(id),command);
			return NULL;
		}

		CombatAI *who = GetCombatAIForID(id);
		if (who != 0)
		{
			Check_Object(who);

			MW4AI::LancemateCommands::lancemate_list l;
			l.push_back(who->GetSelf().objectID);
			MW4AI::LancemateCommands::Execute((MW4AI::LancemateCommands::ID)command,l);
		}
		
		return NULL;
	}

	TypePtr execEnableAIStats(SymTableNodePtr routineIdPtr)
	{
		if (MW4AI::DebugRenderer::GetInstance() != 0)
		{
			MW4AI::DebugRenderer::GetInstance()->SetAIStatsRendering(MW4AI::DebugRenderer::STATS_ALL);
		}
		endFunction();
		return NULL;
	}
	TypePtr execDisableAIStats(SymTableNodePtr routineIdPtr)
	{
		if (MW4AI::DebugRenderer::GetInstance() != 0)
		{
			MW4AI::DebugRenderer::GetInstance()->SetAIStatsRendering(MW4AI::DebugRenderer::STATS_NONE);
		}
		endFunction();
		return NULL;
	}
	TypePtr execEnableMoveLines(SymTableNodePtr routineIdPtr)
	{
		if (MW4AI::DebugRenderer::GetInstance() != 0)
		{
			MW4AI::DebugRenderer::GetInstance()->SetMovementLineRendering(true);
		}
		endFunction();
		return NULL;
	}
	TypePtr execDisableMoveLines(SymTableNodePtr routineIdPtr)
	{
		if (MW4AI::DebugRenderer::GetInstance() != 0)
		{
			MW4AI::DebugRenderer::GetInstance()->SetMovementLineRendering(false);
		}
		endFunction();
		return NULL;
	}
	TypePtr execEnableGlobalInvulnerable(SymTableNodePtr routineIdPtr)
	{
		DamageDispatch::SetGlobalInvulnerability(true);
		endFunction();
		return NULL;
	}
	TypePtr execDisableGlobalInvulnerable(SymTableNodePtr routineIdPtr)
	{
		DamageDispatch::SetGlobalInvulnerability(false);
		endFunction();
		return NULL;
	}
	TypePtr execEnableInvulnerable(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		// no longer implemented  ...

		return NULL;
	}
	TypePtr execDisableInvulnerable(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		// no longer implemented  ...

		return NULL;
	}
	void Group_Destroy(Group::identifier id)
	{
		if ((Adept::Player::GetInstance() != 0) &&
			(Adept::Player::GetInstance()->IsDerivedFrom(MWPlayer::DefaultData) == true))
		{
			MWPlayer* mwplayer = Cast_Object(MWPlayer*,Adept::Player::GetInstance());

			mwobject_list objects;
			GetVehiclesFromGroup(id,objects);

			{for (mwobject_list::iterator i = objects.begin();
					 i != objects.end();
					 ++i)
			{
				mwplayer->AddObjectToDestroy((*i)->objectID);
			}}
		}
	}
	TypePtr execDestroy(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();

		if (ObjectIDisGroup(id) == true)
		{
			Group_Destroy(ObjectIDtoGroupID(id));
			return NULL;
		}

		MWObject *who = GetMWObjectForID(id);

		if ((who) &&
			(Adept::Player::GetInstance() != 0) &&
			(Adept::Player::GetInstance()->IsDerivedFrom(MWPlayer::DefaultData) == true))
		{
			MWPlayer* mwplayer = Cast_Object(MWPlayer*,Adept::Player::GetInstance());
			mwplayer->AddObjectToDestroy(who->objectID);
		}

		return NULL;
	}
	TypePtr execGOSMenuItemExec(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CallDebuggerMenuItem(popStringPtr(),gosMenu_Activated);

		return NULL;
	}
	TypePtr execGOSMenuItemChecked(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		#pragma warning(disable:4800)
		bool rv = (bool)CallDebuggerMenuItem(popStringPtr(),gosMenu_CheckMark);

		pushBoolean(rv);
		#pragma warning(default:4800)

		return BooleanTypePtr;
	}
	void Group_SetTargetDesirability(Group::identifier id, Stuff::Scalar desirability)
	{
		mwobject_list objects;
		GetVehiclesFromGroup(id,objects);

		{for (mwobject_list::iterator i = objects.begin();
				 i != objects.end();
				 ++i)
			{
				(*i)->SetTargetDesirability(desirability);
			}}
	}
	TypePtr execSetTargetDesirability(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		long desirability = popInteger();
		Stuff::Scalar real;

		if (desirability != -1)
		{
// MSL 5.05 Bug Fix
			if (desirability > 100)
				desirability = 100;
			ablREPORT(desirability >= 0,ablERROR ("SetTargetDesirability(): desirability param must be -1 or 0 <= d <= 100"));
			ablREPORT(desirability <= 100,ablERROR ("SetTargetDesirability(): desirability param must be -1 or 0 <= d <= 100"));

			real = (Stuff::Scalar)desirability / 100;
		}
		else
		{
			real = -1;
		}

		if (ObjectIDisGroup(id) == true)
		{
			Group_SetTargetDesirability(ObjectIDtoGroupID(id),real);
			return NULL;
		}

		MWObject *who = GetMWObjectForID(id);

		if (who)
		{
			Check_Object(who);
			who->SetTargetDesirability(real);
		}

		return NULL;
	}
	void Group_SetIsShotRadius(Group::identifier id, Stuff::Scalar radius)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			(*i)->SetIsShotRadius(radius);
		}}
	}
	TypePtr execSetIsShotRadius(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		long radius = popInteger();

		ablREPORT(radius >= 0,ablERROR ("Must specify a positive radius or 0 for setIsShotRadius()"));

		Stuff::Scalar scalar_radius = (Stuff::Scalar)radius;

		if (ObjectIDisGroup(id) == true)
		{
			Group_SetIsShotRadius(ObjectIDtoGroupID(id),scalar_radius);
			return NULL;
		}

    //
    // Use regulare AI pointer here, not CombatAI since trucks, etc.. may call this.
    //
    AI * aiGuy = GetAIForID(id);

		if (aiGuy)
		{
			Check_Object(aiGuy);
			aiGuy->SetIsShotRadius(scalar_radius);
		}

		return NULL;
	}

	void Group_SetSquadTargetingRadius(Group::identifier id, Stuff::Scalar radius)
	{
		std::vector<CombatAI*> ais;
		GetAIsFromGroup<CombatAI>(id,ais);

		{for (std::vector<CombatAI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			(*i)->SetSquadTargetingRadius(radius);
		}}
	}
	TypePtr execSetSquadTargetingRadius(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		long radius = popInteger();

		ablREPORT(radius >= 0,ablERROR ("Must specify a positive radius or 0 for SetSquadTargetingRadius()"));

		Stuff::Scalar scalar_radius = (Stuff::Scalar)radius;

		if (ObjectIDisGroup(id) == true)
		{
			Group_SetSquadTargetingRadius(ObjectIDtoGroupID(id),scalar_radius);
			return NULL;
		}

		CombatAI* combat_ai = GetCombatAIForID(id);

		if (combat_ai)
		{
			Check_Object(combat_ai);
			combat_ai->SetSquadTargetingRadius(scalar_radius);
		}

		return NULL;
	}

	void Group_SetSearchLight(Group::identifier id, MW4AI::SearchLightController::State state)
	{
		std::vector<CombatAI*> ais;
		GetAIsFromGroup<CombatAI>(id,ais);

		{for (std::vector<CombatAI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			(*i)->GetSearchLightController().SetState(state);
		}}
	}

	TypePtr execSetSearchLight(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		bool on = popBoolean();

		MW4AI::SearchLightController::State state;

		if (on == true)
		{
			state = MW4AI::SearchLightController::ON;
		}
		else
		{
			state = MW4AI::SearchLightController::OFF;
		}

		if (ObjectIDisGroup(id) == true)
		{
			Group_SetSearchLight(ObjectIDtoGroupID(id),state);
		}
		else
		{
			CombatAI* combat_ai = GetCombatAIForID(id);

			if (combat_ai)
			{
				Check_Object(combat_ai);
				combat_ai->GetSearchLightController().SetState(state);
			}
		}

		return NULL;
	}

	TypePtr execSetGroupAI(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		Group::identifier group_id = ObjectIDtoGroupID(popInteger());
		long group_ai = popInteger();

		ablREPORT(group_ai > MW4AI::Squad::GROUPAI_FIRST,ablERROR ("Invalid group AI specified for setGroupAI() -- see MWCONST.ABI"));
		ablREPORT(group_ai < MW4AI::Squad::GROUPAI_LAST,ablERROR ("Invalid group AI specified for setGroupAI() -- see MWCONST.ABI"));

		Verify(Adept::NameTable::GetInstance() != 0);

		GroupContainer& vgc = GetGroupContainer();
		ablREPORT(vgc.GroupExists(group_id) == true,ablERROR ("setGroupAI(): the specified group does not exist"));
		if (vgc.GroupExists(group_id) == false)
		{
			return NULL;
		}

		Group& group = vgc.GetGroup(group_id);

		if ((group.HasAI() == false) ||
			(group.GetAI()->GetID() != (MW4AI::Squad::ID)group_ai))
		{
			Stuff::Auto_Ptr<MW4AI::Squad::AI> ai_ptr(MW4AI::Squad::CreateAI((MW4AI::Squad::ID)group_ai));
			group.SetSquadAI(ai_ptr);
		}

		return NULL;
	}

	TypePtr execGetLancemate(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long lancemate_index = popInteger();

		std::vector<MWObject*> lancemates;
		MW4AI::Groups::GetLancemates(lancemates,true);

		if ((lancemate_index < 0) ||
			(lancemate_index >= lancemates.size()))
		{
			pushInteger(ABL_NO_UNIT);
		}
		else
		{
			pushInteger(lancemates[lancemate_index]->objectID);
		}

		return IntegerTypePtr;
	}

	TypePtr execNotifyGroupEnemySpotted(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long raw_group_id = popInteger();
		ablREPORT(ObjectIDisGroup(raw_group_id) == true,ablERROR("NotifyGroupEnemySpotted(): first parameter must specify a group"));

		Group::identifier group_id = ObjectIDtoGroupID(raw_group_id);
		long who_spotted = popInteger();

		if ((who_spotted == -1) &&
			(CurWarrior != 0) &&
			(CurWarrior->vehicle != 0))
		{
			who_spotted = CurWarrior->vehicle->objectID;
		}

		if (who_spotted == -1)
		{
			return NULL;
		}

		ablREPORT(ObjectIDisGroup(who_spotted) == false,ablERROR("NotifyGroupEnemySpotted(): must specify that a single unit (not a group) has been seen"));

		GroupContainer& vgc = GetGroupContainer();
		ablREPORT(vgc.GroupExists(group_id) == true,ablERROR ("NotifyGroupEnemySpotted(): the specified group does not exist"));
		if (vgc.GroupExists(group_id) == false)
		{
			return NULL;
		}

		MW4AI::Squad::AI* group_ai = vgc.GetGroup(group_id).GetAI();

		if (group_ai != 0)
		{
			group_ai->NotifyShot(vgc.GetGroup(group_id),who_spotted);
		}
		else
		{
			ablREPORT(1 == 0,ablERROR ("NotifyGroupEnemySpotted(): the specified group has no AI attached"));
		}

		return NULL;
	}

	TypePtr execTacticIsFinished (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();

		if (ObjectIDisGroup(id) == true)
		{
			ablREPORT(1 == 0,ablERROR("Group ID passed in to TacticIsFinished()"));
			pushBoolean(false);
		}
		else
		{
			MechWarrior4::CombatAI* combat_ai = GetCombatAIForID(id);

			if (combat_ai == 0)
			{
				pushBoolean(false);
			}
			else
			{
				pushBoolean(combat_ai->TacticIsFinished());
			}
		}

		return (BooleanTypePtr);
	}

	TypePtr execGroupAllDead(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		ablREPORT ((ObjectIDisGroup(id) == true),ablERROR ("asking group all dead for a non group"));

		if (ObjectIDisTeam(id) == true)
		{
			mwobject_list vehicles;
			GetVehiclesFromGroup(ObjectIDtoGroupID(id),vehicles);

			pushBoolean(vehicles.size() == 0);
			return BooleanTypePtr;
		}

		Group::identifier group_id = ObjectIDtoGroupID(id);

		pushBoolean(MW4AI::Groups::AllDead(group_id));

		return(BooleanTypePtr);
	}
	TypePtr execGroupAddObject(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		ablREPORT ((ObjectIDisGroup(id) == true),ablERROR ("asking group add object for a non group"));
		Group::identifier group_id = ObjectIDtoGroupID(id);

		Adept::ObjectID object_id = popInteger();
		if (object_id == ABL_NO_UNIT)
		{
			return NULL;
		}

		if ((object_id == -1) &&
			(CurWarrior != 0) &&
			(CurWarrior->vehicle != 0))
		{
			object_id = CurWarrior->vehicle->objectID;
		}

		if (object_id >= 0)
		{
			if (ObjectIDisGroup(object_id) == true) { // jcem - group to group add?
				int i, g_id = ObjectIDtoGroupID(object_id);
				int nSrcCount = MW4AI::Groups::Size(g_id);
				for(i = 0; i < nSrcCount; i++)
				{
					Adept::ObjectID obj_id;
					if (MW4AI::Groups::GetMember(g_id, (unsigned)i, obj_id)) {
						//if (!MW4AI::Groups::ContainsObject(obj_id, group_id)) {
							MW4AI::Groups::AddObject(obj_id,group_id);
						//}
					}
				}
			} else {
			MW4AI::Groups::AddObject(object_id,group_id);
		}
		}

		return NULL;
	}
	TypePtr execGroupRemoveObject(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		ablREPORT ((ObjectIDisGroup(id) == true),ablERROR ("asking group remove object for a non group"));
		Group::identifier group_id = ObjectIDtoGroupID(id);

		Adept::ObjectID object_id = popInteger();
		if ((object_id == -1) &&
			(CurWarrior != 0) &&
			(CurWarrior->vehicle != 0))
		{
			object_id = CurWarrior->vehicle->objectID;
		}

		if (object_id >= 0)
		{
			if (ObjectIDisGroup(object_id) == true) { // jcem - group to group add?
				int i, g_id = ObjectIDtoGroupID(object_id);
				int nSrcCount = MW4AI::Groups::Size(g_id);
				for(i = 0; i < nSrcCount; i++)
				{
					Adept::ObjectID obj_id;
					if (MW4AI::Groups::GetMember(g_id, (unsigned)i, obj_id)) {
						MW4AI::Groups::RemoveObject(obj_id,group_id);
					}
				}
			} else {
			MW4AI::Groups::RemoveObject(object_id,group_id);
		}
		}

		return NULL;
	}
	TypePtr execGroupNumDead(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		ablREPORT ((ObjectIDisGroup(id) == true),ablERROR ("asking group num dead for a non group"));
		Group::identifier group_id = ObjectIDtoGroupID(id);

		pushInteger(MW4AI::Groups::NumDead(group_id));

		return(IntegerTypePtr);
	}
	TypePtr execGroupSize(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		ablREPORT ((ObjectIDisGroup(id) == true),ablERROR ("asking group size for a non group"));
		Group::identifier group_id = ObjectIDtoGroupID(id);

		if (ObjectIDisTeam(id) == true)
		{
			mwobject_list vehicles;
			GetVehiclesFromGroup(ObjectIDtoGroupID(id),vehicles);

			pushInteger(vehicles.size());
			return IntegerTypePtr;
		}

		pushInteger(MW4AI::Groups::Size(group_id));

		return(IntegerTypePtr);
	}
	TypePtr execGroupContainsObject(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		ablREPORT ((ObjectIDisGroup(id) == true),ablERROR ("asking group contains object for a non group"));
		Group::identifier group_id = ObjectIDtoGroupID(id);

		Adept::ObjectID object_id = popInteger();

		if (object_id == ABL_NO_UNIT)
		{
			pushBoolean(false);
			return (BooleanTypePtr);
		}

		if (ObjectIDisTeam(id) == true)
		{
			MWObject* object = GetMWObjectForID(object_id);
			if (object != 0)
			{
				mwobject_list vehicles;
				GetVehiclesFromGroup(group_id,vehicles);

				{for (mwobject_list::const_iterator i = vehicles.begin();
					  i != vehicles.end();
					  ++i)
				{
					if ((*i) == object)
					{
						pushInteger(true);
						return IntegerTypePtr;
					}
				}}
			}

			pushInteger(false);
			return IntegerTypePtr;
		}

		if ((object_id == -1) &&
			(CurWarrior != 0) &&
			(CurWarrior->vehicle != 0))
		{
			object_id = CurWarrior->vehicle->objectID;
		}

		if (object_id >= 0)
		{
			pushBoolean(MW4AI::Groups::ContainsObject(object_id,group_id));
		}
		else
		{
			pushBoolean(false);
		}

		return(BooleanTypePtr);
	}
	TypePtr execGroupGetFirstGroup(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		Adept::ObjectID vehicle_id = popInteger();
		if ((vehicle_id == -1) &&
			(CurWarrior != 0) &&
			(CurWarrior->vehicle != 0))
		{
			vehicle_id = CurWarrior->vehicle->objectID;
		}

		if (vehicle_id == -1)
		{
			pushInteger(ABL_NO_UNIT);
		}
		else
		{
			Group::identifier group_id;
			if (MW4AI::Groups::GetFirstGroup(vehicle_id,group_id) == true)
			{
				pushInteger(group_id);
			}
			else
			{
				pushInteger(ABL_NO_UNIT);
			}
		}

		return(IntegerTypePtr);
	}
	TypePtr execGroupGetFirstObject(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		ablREPORT ((ObjectIDisGroup(id) == true),ablERROR ("asking group get first object for a non group"));
		Group::identifier group_id = ObjectIDtoGroupID(id);

		if (ObjectIDisTeam(id) == true)
		{
			mwobject_list vehicles;
			GetVehiclesFromGroup(group_id,vehicles);

			if (vehicles.size() == 0)
			{
				pushInteger(ABL_NO_UNIT);
			}
			else
			{
				pushInteger((*(vehicles.begin()))->objectID);
			}

			return IntegerTypePtr;
		}

		Adept::ObjectID object_id;
		if (MW4AI::Groups::GetFirstObject(group_id,object_id) == true)
		{
			pushInteger(object_id);
		}
		else
		{
			pushInteger(ABL_NO_UNIT);
		}

		return(IntegerTypePtr);
	}

	TypePtr execGroupGetObject(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		long index = popInteger();
		ablREPORT ((ObjectIDisGroup(id) == true),ablERROR ("calling GroupGetObject for a non group"));
		Group::identifier group_id = ObjectIDtoGroupID(id);

		Adept::ObjectID object_id;
		if (MW4AI::Groups::GetMember(group_id,index,object_id) == true)
		{
			pushInteger(object_id);
		}
		else
		{
			pushInteger(ABL_NO_UNIT);
		}

		return (IntegerTypePtr);
	}

	TypePtr execGroupObjectID(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		Group::identifier group_id = popInteger();
		Verify(group_id < 0x00FFFFFF);
		pushInteger((Adept::NameTable::Groups_Reserved << 24) + group_id);

		return(IntegerTypePtr);
	}
	TypePtr execGroupAllWithin(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long int_group_id = popInteger();
		long target_id = popInteger();
		Stuff::Scalar range = (Stuff::Scalar)popInteger();

		ablREPORT ((ObjectIDisGroup(int_group_id) == true),ablERROR ("asking group all within for a non group"));
		Group::identifier group_id = ObjectIDtoGroupID(int_group_id);

		mwobject_list objects;
		GetVehiclesFromGroup(group_id,objects);

		if (objects.size() == 0)
		{
			pushBoolean(false);
			return(BooleanTypePtr);
		}

		bool all_within = true;

		{for (mwobject_list::iterator i = objects.begin();
			  i != objects.end();
			  ++i)
		{
			if (ObjectIDisGroup(target_id) == true)
			{
				mwobject_list target_objects;
				GetVehiclesFromGroup(target_id,target_objects);

				{for (mwobject_list::iterator i_target = target_objects.begin();
						 i_target != target_objects.end();
						 ++i_target)
					{
						if ((*i)->IsWithin(*i_target,range,true) == false)
						{
							pushBoolean(false);
							return(BooleanTypePtr);
						}
					}}
			}
			else
			{
				Adept::Entity* target = GetObjectForID<Entity>(target_id);
				if (!target)
				{
					pushBoolean (false);
					return BooleanTypePtr;
				}
				if ((*i)->IsWithin(target,range,true) == false)
				{
					pushBoolean(false);
					return(BooleanTypePtr);
				}
			}
		}}

		pushBoolean(true);
		return(BooleanTypePtr);
	}

	TypePtr execTeamObjectID(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		Group::identifier team_id = popInteger();
		Verify(team_id < 0x00FFFFFF);
		pushInteger((Adept::NameTable::Groups_Reserved << 24) + team_id + 0x00F00000);

		return(IntegerTypePtr);
	}

	TypePtr execcinemaStart (SymTableNodePtr routineIdPtr)
	{
		endFunction ();
		// no parameters or return value

		Check_Object(CameraShipManager::Instance);

		Verify (Adept::Player::GetInstance()->IsDerivedFrom (MWPlayer::DefaultData));
		MWPlayer *player = (MWPlayer *) Adept::Player::GetInstance();
		VehicleInterface *inter = player->GetInterface ();

		if (inter->cinemaPlaying == false)
		{
			CameraShipManager::Instance->TurnOnCameras();
			inter->SetCinemaPlaying(true);
		}
		
		return NULL;
	}
	TypePtr execcinemaEnd (SymTableNodePtr routineIdPtr)
	{
		endFunction ();
		// no parameters or return value

		Check_Object(CameraShipManager::Instance);

		CameraShipManager::Instance->TurnOffCameras();

		
		Verify (Adept::Player::GetInstance()->IsDerivedFrom (MWPlayer::DefaultData));
		MWPlayer *player = (MWPlayer *) Adept::Player::GetInstance();
		VehicleInterface *inter;
		inter = player->GetInterface ();
		inter->SetCinemaPlaying(false);

		MoverAI::g_AlwaysIgnoreObstacles = false;

/*
		NameTable *table = NameTable::Instance;

		int j,size,current;
		size = table->nameTableArray[NameTable::AIArray].GetLength ();
		current = 0;
		for (j=0;j<size;j++)
		{
			NameTableEntry *data;
			Entity *ent;
			AI *ai;
			MWObject *obj;

			data = &table->nameTableArray	[NameTable::AIArray][j];
			ent = data->dataPointer->GetCurrent ();
			if (!ent)
				continue;
			ai = Cast_Object (AI *,ent);
			if (!ai->IsDerivedFrom (PlayerAI::DefaultData))
			{
				if (!ai->m_Deactive)
				{
					ent = ai->getEntity ();
					if (ent)
					{
						ai->m_Deactive = true;
						obj = Cast_Object (MWObject *,ent);
						obj->TurnOff ();
					}
				}
			}
		}
*/

		return NULL;
	}

	TypePtr execSetAlwaysIgnoreObstacles (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MoverAI::g_AlwaysIgnoreObstacles = popBoolean();

		return NULL;
	}

	TypePtr execSetIgnoreFog (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int object_id = popInteger();
		bool ignore = popBoolean();

		MechWarrior4::CombatAI* combat_ai = GetCombatAIForID(object_id);
		Verify((long)combat_ai != -1);

		if (combat_ai)
		{
			combat_ai->SetIgnoreFog(ignore);
		}

		return NULL;
	}

	TypePtr execplay2DAnim (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long animid = popInteger ();
		long priority = popInteger ();
		long screenLocX = popInteger ();
		long screenLocY = popInteger ();
		return NULL;
	}

	CameraShip *GetCameraShip(long camera_id)
	{
		int array_index = NameTableEntry::GetArrayIndex(camera_id);
		ablREPORT(array_index >= 0,ablERROR ("invalid object id from abl"));
		ablREPORT(array_index < NameTable::GetInstance()->TableSize,ablERROR ("invalid object id from abl"));
		CameraShip* camera = (CameraShip*) NameTable::GetInstance()->FindData(camera_id);
		ablREPORT (camera,ablERROR ("invalid object id from abl"));
		ablREPORT (camera->IsDerivedFrom (CameraShip::DefaultData),ablERROR ("tried to convert an objectid to the wrong type of object.  Function called needs a Camera type objectid"));


		return camera;
	}

	Entity *GetEntity(long entity_id)
	{
		int array_index = NameTableEntry::GetArrayIndex(entity_id);
		ablREPORT(array_index >= 0,ablERROR ("invalid object id from abl"));
		ablREPORT(array_index < NameTable::GetInstance()->TableSize,ablERROR ("invalid object id from abl"));
		Entity* entity = (Entity*) NameTable::GetInstance()->FindData(entity_id);
		ablREPORT (entity,ablERROR ("invalid object id from abl"));
		ablREPORT (entity->IsDerivedFrom (Entity::DefaultData),ablERROR ("tried to convert an objectid to the wrong type of object.  Function called needs an Entity type objectid"));


		return entity;
	}

	CameraShip *GetActiveCamera()
	{

		Check_Object(CameraShipManager::Instance);
		return (CameraShipManager::Instance->GetActiveCamera());
	}

	TypePtr execSetCameraFootShake (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long objectid(popInteger());
		long distance(popInteger());

		if ((objectid == ABL_NO_UNIT) ||
			(distance == 0))
		{
			objectid = ABL_NO_UNIT;
			distance = 0;
		}

		CameraShip* camera = GetActiveCamera();

		if (camera != 0)
		{
			camera->SetFootShakeParams(objectid,distance);
		}

		return NULL;
	}

	TypePtr execcinemaskip (SymTableNodePtr routineIdPtr)
	{

//		DECLARE_ABL_CONTEXT;


		

		if (gos_GetKeyStatus(KEY_SPACE) == KEY_RELEASED)
		{
			pushBoolean(true);
		}
		else if (gos_GetKeyStatus(KEY_ESCAPE) == KEY_RELEASED)
		{
			pushBoolean(true);
		}
		else
		{
			pushBoolean(false);
		}
		

		endFunction ();
		return BooleanTypePtr;
	}


	TypePtr execsetinternalcamera (SymTableNodePtr routineIdPtr)
	{

		DECLARE_ABL_CONTEXT;

		Check_Object(CameraShipManager::Instance);

		bool hud_value = popBoolean();


		CameraShipManager::Instance->SetInternalCamera(hud_value);

		return NULL;
	}

	TypePtr execsetactivecamera (SymTableNodePtr routineIdPtr)
	{

		DECLARE_ABL_CONTEXT;

		Check_Object(CameraShipManager::Instance);

		long camera_id = popInteger();


		CameraShip *camera = GetCameraShip(camera_id);

		CameraShipManager::Instance->SetActiveCamera(camera);

		return NULL;
	}

	TypePtr execsetcameraFOV (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		float fov = popReal ();
		float time = popReal ();

		CameraShip* camera = GetActiveCamera();

		if (camera != 0)
		{
			float degrees = fov * Radians_Per_Degree;
			camera->SetCameraFOV(degrees, time);
		}

		return NULL;
	}

	TypePtr execfadetoblack (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		float time = popReal ();

		CameraShip* camera = GetActiveCamera();

		if (camera != 0)
		{
			camera->FadeToBlack(time);
		}

		return NULL;
	}

	TypePtr execfadefromblack (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		float time = popReal ();

		CameraShip* camera = GetActiveCamera();

		if (camera != 0)
		{
			camera->FadeFromBlack(time);
		}

		return NULL;
	}

	TypePtr execfadetowhite (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		float time = popReal ();

		CameraShip* camera = GetActiveCamera();

		if (camera != 0)
		{
			camera->FadeToWhite(time);
		}

		return NULL;
	}

	TypePtr execfadefromwhite (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		float time = popReal ();

		CameraShip* camera = GetActiveCamera();

		if (camera != 0)
		{
			camera->FadeFromWhite(time);
		}

		return NULL;
	}

	TypePtr execcamerafollowobject (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();
		long entity_id = popInteger();
		Entity *entity = GetEntity(entity_id);

		if (camera != 0)
		{
			camera->CameraFollowObject(entity);
		}

		return NULL;
	}

	TypePtr execcamerafollowpath (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();
		
		long entity_id = popInteger ();
		long speed_kph = popInteger ();
		

		float speed_mps = ConvertKPHtoMPSFloat (speed_kph);
		
		
		Entity *entity = GetEntity(entity_id);
		ablREPORT (entity->IsDerivedFrom (Path::DefaultData),ablERROR ("tried to convert an objectid to the wrong type of object.  Function called needs an Entity type objectid"));
		Path *path = Cast_Object(Path*, entity);

		if (camera != 0)
		{
			camera->CameraFollowPath(speed_mps, path);
		}

		return NULL;
	}

	TypePtr execcameraposition (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();
		
		float x = popReal ();
		float y = popReal ();
		float z = popReal ();
		float time = popReal ();

		if (camera != 0)
		{
			camera->CameraPosition(x, y, z, time);
		}

		return NULL;
	}

	TypePtr execcameradetach (SymTableNodePtr routineIdPtr)
	{
		endFunction ();

		CameraShip* camera = GetActiveCamera();

		if (camera != 0)
		{
			camera->CameraDetach();
		}

		return NULL;
	}

	TypePtr execcameraoffset (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();
		
		float x = popReal ();
		float y = popReal ();
		float z = popReal ();
		float time = popReal ();
		bool local = popBoolean ();

		if (camera != 0)
		{
			camera->CameraOffset(x,y,z,time, local);
		}

		return NULL;
	}

	TypePtr execoverridecamerapitch (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();
		
		float deg = popReal ();
		float time = popReal ();

		float rad = deg * Radians_Per_Degree;

		if (camera != 0)
		{
			camera->OverrideCameraPitch(rad, time);
		}

		return NULL;
	}

	TypePtr execoverridecamerayaw (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();
		
		float deg = popReal ();
		float time = popReal ();

		float rad = deg * Radians_Per_Degree;

		if (camera != 0)
		{
			camera->OverrideCameraYaw(rad, time);
		}

		return NULL;
	}

	TypePtr execoverridecameraroll (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();

		float deg = popReal ();
		float time = popReal ();

		float rad = deg * Radians_Per_Degree;

		if (camera != 0)
		{
			camera->OverrideCameraRoll(rad, time);
		}

		return NULL;
	}

	TypePtr execresetcameraoverrides (SymTableNodePtr routineIdPtr)
	{
		
		endFunction ();

		CameraShip* camera = GetActiveCamera();

		if (camera != 0)
		{
			camera->ResetCameraOverrides();
		}

		return NULL;
	}

	TypePtr exectargetfollowobject (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();
		long entity_id = popInteger();
		Entity *entity = GetEntity(entity_id);

		if (camera != 0)
		{
			camera->TargetFollowObject(entity);
		}

		return NULL;
	}

	TypePtr exectargetfollowpath (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();
		
		long entity_id = popInteger ();
		long speed_kph = popInteger ();
		

		float speed_mps = ConvertKPHtoMPSFloat (speed_kph);
		
		
		Entity *entity = GetEntity(entity_id);
		ablREPORT (entity->IsDerivedFrom (Path::DefaultData),ablERROR ("tried to convert an objectid to the wrong type of object.  Function called needs an Entity type objectid"));
		Path *path = Cast_Object(Path*, entity);

		if (camera != 0)
		{
			camera->TargetFollowPath(speed_mps, path);
		}

		return NULL;
	}

	TypePtr exectargetposition (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();
		
		float x = popReal ();
		float y = popReal ();
		float z = popReal ();
		float time = popReal ();

		if (camera != 0)
		{
			camera->TargetPosition(x, y, z, time);
		}

		return NULL;
	}

	TypePtr exectargetdetach (SymTableNodePtr routineIdPtr)
	{

		endFunction ();

		CameraShip* camera = GetActiveCamera();

		if (camera != 0)
		{
			camera->TargetDetach();
		}

		return NULL;
	}

	TypePtr exectargetoffset (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CameraShip* camera = GetActiveCamera();
		
		float x = popReal ();
		float y = popReal ();
		float z = popReal ();
		float time = popReal ();
		bool local = popBoolean ();

		if (camera != 0)
		{
			camera->TargetOffset(x,y,z,time, local);
		}

		return NULL;
	}



	TypePtr execSetMemoryInteger(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();
		long index = popInteger ();
		long value = popInteger ();

		if (ObjectIDisGroup(id) == true) { // jcem - set memeory for group added
			Group::identifier gid = ObjectIDtoGroupID(id);

			std::vector<AI*> ais;
			GetAIsFromGroup<AI>(gid,ais);

			{for (std::vector<AI*>::iterator i = ais.begin(); i != ais.end(); ++i)
			{
				(*i)->IntegerMemory (index,value);
			}}
		} else {
		AI* who = GetAIForID(id);
		if (!who)
			return NULL;
		Verify ((long) who != -1);
		who->IntegerMemory (index,value);
		}
		return NULL;
	}

	TypePtr execSetMemoryReal(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();
		long index = popInteger ();
		float value = popReal ();
		if (ObjectIDisGroup(id) == true) { // jcem - set memeory for group added
			Group::identifier gid = ObjectIDtoGroupID(id);

			std::vector<AI*> ais;
			GetAIsFromGroup<AI>(gid,ais);

			{for (std::vector<AI*>::iterator i = ais.begin(); i != ais.end(); ++i)
			{
				(*i)->RealMemory (index,value);
			}}
		} else {
		AI* who = GetAIForID(id);
		if (!who)
			return NULL;
		Verify ((long) who != -1);
		who->RealMemory (index,value);
		}
		return NULL;
	}

	TypePtr execGetMemoryInteger(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();
		long index = popInteger ();
		AI* who = GetAIForID(id);
        if (who) {
		Verify ((long) who != -1);
		pushInteger (who->IntegerMemory (index));
        } else {
            pushInteger (0); // jcem - error actually^^
        }
		return IntegerTypePtr;
	}

	TypePtr execGetMemoryReal(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();
		long index = popInteger ();
		AI* who = GetAIForID(id);
        if (who) {
		Verify ((long) who != -1);
		pushReal (who->RealMemory (index));
        } else {
            pushReal (0.0f); // jcem - error actually^^
        }
		return RealTypePtr;
	}

	TypePtr execSetGlobalTrigger(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int index = popInteger();
		bool value = popBoolean();

		AI::SetGlobalTrigger(index,value);

		return NULL;
	}

	TypePtr execGetGlobalTrigger(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int index = popInteger();
		pushBoolean(AI::GetGlobalTrigger(index));

		return BooleanTypePtr;
	}

	void Group_SetSensorVisibility(Group::identifier group_id, bool visible)
	{
		mwobject_list objects;
		GetVehiclesFromGroup(group_id,objects);

		{for (mwobject_list::const_iterator i = objects.begin();
			  i != objects.end();
			  ++i)
		{
			(*i)->SetVisibleOnSensors(visible);
		}}
	}

	TypePtr execSetSensorVisibility (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int id = popInteger();
		bool visible = popBoolean();

		if (ObjectIDisGroup(id) == true)
		{
			Group_SetSensorVisibility(ObjectIDtoGroupID(id),visible);
			return NULL;
		}

		MWObject* object = GetMWObjectForID(id);
		if (object != 0)
		{
			object->SetVisibleOnSensors(visible);
		}

		return NULL;
	}

	void Group_SetAutoTargeting(Group::identifier group_id, bool enabled)
	{
		std::vector<CombatAI*> ais;
		GetAIsFromGroup<CombatAI>(group_id,ais);

		{for (std::vector<CombatAI*>::const_iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			(*i)->SetAutoTargeting(enabled);
		}}
	}

	TypePtr execSetAutoTargeting(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int id = popInteger();
		bool enabled = popBoolean();

		if (ObjectIDisGroup(id) == true)
		{
			Group_SetAutoTargeting(ObjectIDtoGroupID(id),enabled);
			return NULL;
		}

		MechWarrior4::CombatAI* combat_ai = GetCombatAIForID(id);
		if (combat_ai != 0)
		{
			combat_ai->SetAutoTargeting(enabled);
		}

		return NULL;
	}

	TypePtr execEnablePerWeaponRayCasting(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int object_id = popInteger();
		bool enable = popBoolean();

		MechWarrior4::CombatAI* combat_ai = GetCombatAIForID(object_id);

		if (combat_ai != 0)
		{
			combat_ai->EnablePerWeaponRayCasting(enable);
		}

		return NULL;
	}

	void Group_execStartup(Group::identifier group_id)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			if ((*i)->Dead() == false)
			{
				(*i)->Startup();
			}
		}}
	}

	TypePtr execstartup (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			Group_execStartup(ObjectIDtoGroupID(id));
		}
		else
		{
			AI *who = GetAIForID(id);
			if (!who)
				return NULL;
			ablREPORT ((!who->Dead ()),ablERROR ("asking to startup a dead unit"));
			Check_Object (who);

			who->Startup ();
		}

		return NULL;
	}

	void Group_execShutdown(Group::identifier group_id)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		{for (std::vector<AI*>::iterator i = ais.begin();
			  i != ais.end();
			  ++i)
		{
			if ((*i)->Dead() == false)
			{
				(*i)->Shutdown();
			}
		}}
	}
	TypePtr execshutDown (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			Group_execShutdown(ObjectIDtoGroupID(id));
		}
		else
		{
			AI *who = GetAIForID(id);
			if (!who)
				return NULL;
			Check_Object (who);
			ablREPORT ((!who->Dead ()),ablERROR ("asking to shutdown a dead unit"));
			who->Shutdown ();
		}
		return NULL;
	}


	TypePtr execPlayerAI (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		Check_Object (Adept::Player::GetInstance());

		MWPlayer *player;

		long id = popInteger ();
		bool run = popBoolean ();

		Verify (Adept::Player::GetInstance()->IsDerivedFrom (MWPlayer::DefaultData));
		player = (MWPlayer *) Adept::Player::GetInstance();
		VehicleInterface *inter;
		inter = player->GetInterface ();
		Verify (inter);
		inter->PlayerAIRun (run);

		return NULL;
	}
	void Group_execStopExecute(Group::identifier group_id)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		for (std::vector<AI*>::iterator i = ais.begin(); i != ais.end(); ++i)
		{
			Check_Object (*i);
			(*i)->StopExecute ();
		}
	}

	TypePtr execAddMechInstanceSalvage(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
	
		char *string = popStringPtr();

		if(MWGame::GetInstance())
		{
			if(MWGame::GetInstance()->m_salvageManager)
			{
				char *salv_string;
				salv_string = strlwr(string);
				MWGame::GetInstance()->GetAndAddMechInstance(salv_string);
			}
		}

		return NULL;
	}
	TypePtr execAddComponentSalvage(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
	
		char *string = popStringPtr();
		int num = popInteger();
		if(MWGame::GetInstance())
		{
			if(MWGame::GetInstance()->m_salvageManager)
			{
				char *salv_string;
				salv_string = strlwr(string);
				MWGame::GetInstance()->m_salvageManager->GetAndAddComponentSalvage(salv_string, num);
			}
		}

		return NULL;
	}
	TypePtr execAddWeaponSalvage(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
	
		char *string = popStringPtr();
		int num = popInteger();
		if(MWGame::GetInstance())
		{
			if(MWGame::GetInstance()->m_salvageManager)
			{
				char *salv_string;
				salv_string = strlwr(string);
				MWGame::GetInstance()->m_salvageManager->GetAndAddWeaponSalvage(salv_string, num);
			}
		}

		return NULL;
	}

	TypePtr execMarkBuildingAsScorable (SymTableNodePtr routineIDPtr)
	{
		DECLARE_ABL_CONTEXT;
	
		long id = popInteger ();
		MWObject *obj = GetMWObjectForID (id);
// MSL 5.04 Dropship
		ablREPORT ( (obj->IsDerivedFrom(Building::DefaultData)
			|| obj->IsDerivedFrom(Dropship::DefaultData)
			|| obj->IsDerivedFrom(Tank::DefaultData)),
			"Tried to mark non building or dropship as scorable");

		if (obj->IsDerivedFrom(Building::DefaultData))
		{
			Building * building;
			building = Cast_Object (Building*, obj);
			building->m_scoreThisBuilding = true;
		}
		else if (obj->IsDerivedFrom(Dropship::DefaultData))
		{
			Dropship * dropship;
			dropship = Cast_Object (Dropship*, obj);
			dropship->m_scoreThisDropship = true;
		}
		else if (obj->IsDerivedFrom(Tank::DefaultData))
		{
			Tank * tank;
			tank = Cast_Object (Tank*, obj);
			tank->m_scoreThisTank = true;
		}

//		ablREPORT (obj->IsDerivedFrom(Building::DefaultData), "Tried to mark non building as scorable");
//		Building * building;
//		building = Cast_Object (Building*, obj);
//		building->m_scoreThisBuilding = true;

		return NULL;
	}

	TypePtr execJump (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		long time = popInteger();

		MechWarrior4::CombatAI* combat_ai = GetCombatAIForID(id);

		if (combat_ai != 0)
		{
			combat_ai->OrderJump((Stuff::Scalar)time);
		}

		return NULL;
	}

	TypePtr execCrouch (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();

		MWObject* mwobject = GetMWObjectForID(id);

		if ((mwobject != 0) &&
			(mwobject->IsDerivedFrom(MWObject::DefaultData) == true))
		{
			Mech* mech = Cast_Object(Mech*,mwobject);

			mech->CrouchRequest();
		}

		return NULL;
	}

	TypePtr execFall (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		long fall_type = popInteger();

		MWObject* mwobject = GetMWObjectForID(id);

		if ((mwobject != 0) &&
			(mwobject->IsDerivedFrom(Mech::DefaultData) == true))
		{
			Mech* mech = Cast_Object(Mech*,mwobject);

			switch (fall_type)
			{
				case 0:
				{
					mech->Test_FallForward();
					break;
				}
				case 1:
				{
					mech->Test_FallBackward();
					break;
				}
				case 2:
				{
					mech->Test_FallLeft();
					break;
				}
				default:
				{
					mech->Test_FallRight();
					break;
				}
			}
		}

		return NULL;
	}

	TypePtr execTorsoPitch (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MechWarrior4::CombatAI* who = GetCombatAIForID(popInteger());

		float pitch = popReal();

		if (who != 0)
		{
			who->SetGoalPitch(pitch);
		}

		return NULL;
	}

	TypePtr execTorsoYaw (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MechWarrior4::CombatAI* who = GetCombatAIForID(popInteger());
		float yaw = popReal();

		if (who != 0)
		{
			who->SetGoalYaw(yaw);
		}

		return NULL;
	}

	TypePtr execSetGimped (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MWObject* mwobject = GetMWObjectForID(popInteger());
		bool gimped = popBoolean();

		if ((mwobject != 0) &&
			(mwobject->IsDerivedFrom(Mech::DefaultData) == true))
		{
			Mech* mech = Cast_Object(Mech*,mwobject);

			if (gimped == true)
			{
				mech->Test_LeftGimp();
			}
			else
			{
				mech->SetNoGimp();
			}
		}

		return NULL;
	}

	void Rotate(MWObject& who, Stuff::Scalar rotation)
	{
		YawPitchRoll new_rotation(YawPitchRoll::Identity);
		new_rotation = (YawPitchRoll) who.GetLocalToWorld();
		new_rotation.yaw = rotation;

		Point3D new_translation(who.GetLocalToWorld());

		LinearMatrix4D new_local_to_world;
		new_local_to_world.BuildTranslation(new_translation);
		new_local_to_world.BuildRotation(new_rotation);

		who.SetNewLocalToParent(new_local_to_world);
		who.SyncMatrices(true);
		Map::GetInstance()->UpdateZone(&who);
	}

	TypePtr execSetRotation (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long object_id = popInteger();
		long rotation_degrees = popInteger();

		MWObject* mwobject = GetMWObjectForID(object_id);
		if (mwobject != 0)
		{
			Rotate(*mwobject,(Scalar)rotation_degrees * Radians_Per_Degree);
		}

		return NULL;
	}

	TypePtr execSetHelicoptersIgnoreMissionBounds (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MW4AI::Actions::g_HelicoptersIgnoreMissionBounds = popBoolean();

		return NULL;
	}

	TypePtr execSetTorsoCenteringEnabled (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int src_id = popInteger();
		int enabled = popBoolean();

		MWObject* src = GetMWObjectForID(src_id);

		if ((src != 0) &&
			(src->IsDestroyed() == false) &&
			(src->vehicleInterface != 0) &&
			(src->vehicleInterface->IsDerivedFrom(MechWarrior4::VehicleInterface::DefaultData) == true))
		{
			MechWarrior4::VehicleInterface* vehicle_interface = Cast_Object(MechWarrior4::VehicleInterface*,src->vehicleInterface);

			if (enabled == false)
			{
				vehicle_interface->SetPerminateTorsoMode(VehicleInterface::LeaveTorsoAlone);
			}
			else
			{
				vehicle_interface->SetPerminateTorsoMode(VehicleInterface::CenterLegsToTorso);
			}
		}

		return NULL;
	}

	TypePtr execSetCompositingEnabled (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		popBoolean();

		// functionality intentionally removed  ...
		
		return NULL;
	}

	void Group_execSetSensorMode(Group::identifier group_id, int mode)
	{
		mwobject_list mwobjects;
		GetVehiclesFromTeam(group_id,mwobjects);

		{for (mwobject_list::const_iterator i = mwobjects.begin();
			  i != mwobjects.end();
			  ++i)
		{
			if ((*i)->GetSensor() != 0)
			{
				(*i)->GetSensor()->SetSensorMode(mode,(*i)->DoesHaveBeagle());
			}
		}}
	}

	TypePtr execSetSensorMode (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();
		long mode = popInteger();
		if (ObjectIDisGroup (id))
		{
			Group_execSetSensorMode(ObjectIDtoGroupID(id),mode);
		}
		else
		{
			MWObject* mwobject = GetMWObjectForID(id);

			if ((mwobject != 0) &&
				(mwobject->GetSensor() != 0))
			{
				mwobject->GetSensor()->SetSensorMode(mode,mwobject->DoesHaveBeagle());
			}
		}

		return NULL;
	}

	TypePtr execGetSensorMode (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger();

		MWObject* mwobject = GetMWObjectForID(id);

		if ((mwobject != 0) &&
			(mwobject->GetSensor() != 0))
		{
			pushInteger(mwobject->GetSensor()->GetSensorMode());
		}
		else
		{
			pushInteger(0);
		}

		return IntegerTypePtr;
	}

	TypePtr execSetMinSpeed (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long object_id = popInteger();
		long speed = popInteger();

		MechWarrior4::CombatAI* who = GetCombatAIForID(object_id);

		if (who != 0)
		{
			Stuff::Scalar s = (Stuff::Scalar)speed;
			s *= 0.01f;
			who->SetMinSpeed(s);
		}

		return NULL;
	}

	TypePtr execStopExecute (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		if (ObjectIDisGroup (id))
		{
			Group_execStopExecute (ObjectIDtoGroupID (id));
		}
		else
		{
			AI *who = GetAIForID(id);
			if (!who)
				return NULL;
			ablREPORT ((!who->Dead ()),ablERROR ("asking to stop execute a dead unit"));
			Check_Object (who);
			who->StopExecute ();
		}
		return NULL;
	}

	void Group_execStartExecute(Group::identifier group_id)
	{
		std::vector<AI*> ais;
		GetAIsFromGroup<AI>(group_id,ais);

		for (std::vector<AI*>::iterator i = ais.begin(); i != ais.end(); ++i)
		{
			Check_Object (*i);
			(*i)->StartExecute ();
		}
	}

	TypePtr execStartExecute (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long id = popInteger ();
		if (ObjectIDisGroup (id))
		{
			Group_execStartExecute (ObjectIDtoGroupID (id));
		}
		else
		{
			AI *who = GetAIForID(id);
			if (!who)
				return NULL;
			ablREPORT ((!who->Dead ()),ablERROR ("asking to start execute a dead unit"));
			Check_Object (who);
			who->StartExecute ();
		}
		return NULL;
	}

	TypePtr execSetActivationDistance (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		long dist = popInteger ();
		MWMission *mission;

		if (dist > 1200)
		{
			dist = 1200;
		}
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Check_Object (mission);
		mission->m_DistanceCheck = (Scalar) dist;

		return NULL;
	}

	TypePtr execFlyBy (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();

		Entity* who = GetObjectForID<Entity>(id);
    who = ConvertAIToEntity(who);

		PlaneAI *plane;

		Stuff::Point3D loc (who->GetLocalToWorld ());
		ablREPORT (CurMoverAI->IsDerivedFrom (PlaneAI::DefaultData),"Tried to issue a fly by order on a non flyer");
		plane = Cast_Object (PlaneAI *,CurMoverAI);
		pushBoolean (plane->FlyBy (loc));
		return BooleanTypePtr;
	}
	
	TypePtr execSave (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long id = popInteger ();

		return NULL;
	}

	TypePtr execGetDifficulty (SymTableNodePtr routineIdPtr)
	{
		pushInteger (MWApplication::GetInstance()->GetDifficultyLevel());
		endFunction ();
		return IntegerTypePtr;
	}
	
	TypePtr execEject (SymTableNodePtr routineIdPtr)
	{
		long id = popInteger ();

		MWObject *obj = GetMWObjectForID (id);
		ablREPORT (obj->IsDerivedFrom (Vehicle::DefaultData),"Tried to eject on a non vehicle");
		Vehicle *veh;

		veh = Cast_Object (Vehicle *,obj);
		veh->Eject ();
		return NULL;
	}

	TypePtr execAddBucket (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CBucketManager::Bucket_Type type = (CBucketManager::Bucket_Type) popInteger ();
		int id = popInteger ();
		int affects = popInteger ();
		int mod2 = popInteger ();

		ReplicatorID repid;
		if (id == -2)
		{
			repid = ReplicatorID::Null;
		}
		else
		{
			MWObject *obj = GetMWObjectForID (id);
			repid = obj->GetReplicatorID ();
		}

		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);

		pushInteger (mission->m_BucketManager->AddBucket (type,repid,affects,mod2));
		return IntegerTypePtr;
	}
	TypePtr execKillBucket (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int id = popInteger ();
		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);
		mission->m_BucketManager->KillBucket (id);
		return NULL;
	}
	TypePtr execShowBucket (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int id = popInteger ();
		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);
		mission->m_BucketManager->ShowBucket (id);
		return NULL;
	}
	TypePtr execHideBucket (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int id = popInteger ();
		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);
		mission->m_BucketManager->HideBucket (id);
		return NULL;
	}
	TypePtr execGetBucketValue (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int id = popInteger ();
		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);
		pushInteger(mission->m_BucketManager->BucketValue (id));
		return IntegerTypePtr;
	}
	TypePtr execFindBucketValue (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		CBucketManager::Bucket_Type type = (CBucketManager::Bucket_Type) popInteger ();
		int id = popInteger ();

		ReplicatorID repid;
		if (id == -2)
		{
			repid = ReplicatorID::Null;
		}
		else
		{
			MWObject *obj = GetMWObjectForID (id);
			repid = obj->GetReplicatorID ();
		}

		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);
		pushInteger(mission->m_BucketManager->FindBucketValue (type, repid));
		return IntegerTypePtr;
	}
	TypePtr execSetBucketValue (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int id = popInteger ();
		int value = popInteger ();
		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);
		mission->m_BucketManager->BucketValue (id,value);
		return NULL;
	}
	TypePtr execTrackBucket (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		CBucketManager::Bucket_Type type = (CBucketManager::Bucket_Type) popInteger ();
		int mod2 = popInteger ();
		bool visible = popBoolean ();
		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);
		mission->m_BucketManager->SetupTrack (type,mod2,visible);
		return NULL;
	}
	TypePtr execTrackObjectBucket (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		CBucketManager::Bucket_Type type = (CBucketManager::Bucket_Type) popInteger ();
		int objid = popInteger ();
		int distance = popInteger ();
		bool visible = popBoolean ();
		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);
		mission->m_BucketManager->SetupTrackObject (type,objid,distance,visible);
		return NULL;
	}
	TypePtr execFindBucket (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		CBucketManager::Bucket_Type type = (CBucketManager::Bucket_Type) popInteger ();
		int id = popInteger ();
		int affects = popInteger ();
		int mod2 = popInteger ();
		int objid = popInteger ();

		ReplicatorID repid;
		if (id == -2)
		{
			repid = ReplicatorID::Null;
		}
		else
		{
			MWObject *obj = GetMWObjectForID (id);
			repid = obj->GetReplicatorID ();
		}

		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);

		pushInteger (mission->m_BucketManager->FindBucket (type,repid,affects,mod2,objid));
		return IntegerTypePtr;
	}

	TypePtr execAddCustomBucketParameter(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int bucket_type(popInteger());
		int bucket_multiplier(popInteger());

		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);
		mission->m_BucketManager->AddCustomBucketParameter((CBucketManager::Bucket_Type)bucket_type,bucket_multiplier);

		return NULL;		
	}

	TypePtr execChatMessage(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		char *text = popStringPtr();

		if (text == 0)
		{
			return NULL;
		}

		MWApplication::GetInstance()->SendChat(
				Connection::Local->GetID(),
				MWApplication::SystemBroadcast,
				0,
				text);

		return NULL;
	}

	TypePtr execSetCustomBucketName(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		char *name = popStringPtr();

		if (name == 0)
		{
			return NULL;
		}

		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);

		mission->m_BucketManager->SetCustomBucketName(name);

		return NULL;
	}
	TypePtr execSetCustomBucketNameIndex(SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int bucket_name_index(popInteger());

		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);

		mission->m_BucketManager->SetCustomBucketName(MWApplication::GetInstance()->GetLocString(bucket_name_index));

		return NULL;
	}

	void Group_execAddPoints(Group::identifier group_id, int points, MWMission& mission)
	{
		mwobject_list objects;
		GetVehiclesFromGroup(group_id,objects);

		{for (mwobject_list::const_iterator i = objects.begin();
			  i != objects.end();
			  ++i)
		{
			mission.m_BucketManager->AddToCustomScore((*i)->GetReplicatorID(),points);
		}}
	}

	TypePtr execAddPoints (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int id = popInteger ();
		int points = popInteger ();

		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		Verify (mission->m_BucketManager);

		if (ObjectIDisTeam(id) == true)
		{
			int team = id & 0xFF;
			if (team == 0)
			{
				team = 8;
			}
			else
			{
				--team;
			}

			mission->m_BucketManager->AddTeamPoints(team,points);
		}
		else
		{
			if (ObjectIDisGroup(id))
			{
				Group_execAddPoints(ObjectIDtoGroupID(id),points,*mission);
			}
			else
			{
				MWObject* who = GetMWObjectForID(id);

				if (who != 0)
				{
					mission->m_BucketManager->AddToCustomScore(who->GetReplicatorID(),points);
				}
			}
		}

		return NULL;
	}

	TypePtr execAttachFlag (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int id = popInteger ();
		int who = popInteger ();

		Flag *flag = GetFlagForID (id);
		ablREPORT (flag,"could not find a flag with that id");
		if (flag == 0)
		{
			return NULL;
		}

		MWObject *obj = GetMWObjectForID (who);
		if (obj == 0)
		{
			return NULL;
		}
		ablREPORT (obj->IsDerivedFrom (MWObject::DefaultData),"Tried to attach a flag to a non mwobject");

		flag->Execute_AttachTo(obj);

		return NULL;
	}

	TypePtr execDropFlag (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int id = popInteger ();
		
		Flag *flag = GetFlagForID (id);
		ablREPORT (flag,"could not find a flag with that id");
		flag->Execute_Drop();

		return NULL;
	}

// MSL 5.05 Return Flag Script Command
	TypePtr execReturnFlag (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int id = popInteger ();
		
		Flag *flag = GetFlagForID (id);
		ablREPORT (flag,"could not find a flag with that id");
		flag->Execute_ReturnToOrigin();

		return NULL;
	}
	TypePtr execDeactiveFlag (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int id = popInteger ();
		int time = popInteger ();

		Flag *flag = GetFlagForID (id);
		ablREPORT (flag,"could not find a flag with that id");
		flag->DeactiveTime (time);

		return NULL;
	}

	void Group_execSetMaxFlagsCarried(Group::identifier id, int max_flags)
	{
		mwobject_list objects;
		GetVehiclesFromGroup(id,objects);

		{for (mwobject_list::const_iterator i = objects.begin();
			  i != objects.end();
			  ++i)
		{
			if ((*i)->IsDerivedFrom(Mech::DefaultData) == true)
			{
				Mech* mech = Cast_Object(Mech*,*i);

				mech->SetMaxFlagsCarried(max_flags);
			}
		}}
	}

	TypePtr execSetMaxFlagsCarried (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int id = popInteger ();
		int max_flags = popInteger ();

		if (id == ABL_NO_UNIT)
		{
			MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
			mwmission->SetMaxFlagsCarried(max_flags);
		}
		else
		{
			if (ObjectIDisGroup(id) == true)
			{
				Group_execSetMaxFlagsCarried(ObjectIDtoGroupID(id),max_flags);
			}
			else
			{
				MWObject *obj = GetMWObjectForID (id);

				if ((obj != 0) &&
					(obj->IsDerivedFrom(Mech::DefaultData) == true))
				{
					Mech* mech = Cast_Object(Mech*,obj);

					mech->SetMaxFlagsCarried(max_flags);
				}
			}
		}

		return NULL;
	}
	
	TypePtr execSetFlagDropReturnTime (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
		mwmission->SetFlagDropReturnTime(popInteger());

		return NULL;
	}

	TypePtr execSetFlagCaptureReturnTime (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
		mwmission->SetFlagCaptureReturnTime(popInteger());

		return NULL;
	}

	TypePtr execSetFlagsEnabled (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
		mwmission->SetFlagsEnabled((MWMission::FLAG_ENABLE_STATE)popInteger());

		return NULL;
	}

	TypePtr execSetFlagCaptureEnabled (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
		mwmission->SetFlagCaptureEnabled(popBoolean());

		return NULL;
	}

	TypePtr execShowFlagsAsNavPoints (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
		mwmission->SetFlagsAsNavPoints(popBoolean());

		return NULL;
	}

	TypePtr execSetViewMode (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long view_mode = popInteger();

		VehicleInterface::GetInstance()->SetCameraViewLevel(view_mode);

		return NULL;
	}

	TypePtr execGetViewMode (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MWObject* src = GetMWObjectForID(popInteger());

		if ((src != 0) &&
			(src->IsDestroyed() == false) &&
			(src->vehicleInterface != 0) &&
			(src->vehicleInterface->IsDerivedFrom(MechWarrior4::VehicleInterface::DefaultData) == true))
		{
			MechWarrior4::VehicleInterface* vehicle_interface = Cast_Object(MechWarrior4::VehicleInterface*,src->vehicleInterface);

			pushInteger(vehicle_interface->GetCameraViewLevel());
		}
		else
		{
			pushInteger(0);
		}

		return IntegerTypePtr;
	}

	TypePtr execSetInputTypeEnabled (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long type = popInteger();
		bool enabled = popBoolean();

		InputTrainer::GetInstance()->SetEnabled((InputTrainer::InputType)type,enabled);

		return NULL;
	}

	TypePtr execSetHUDComponentEnabled (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long type = popInteger();
		bool enabled = popBoolean();

		if (enabled == true)
		{
			MWGUIManager::GetInstance()->ShowHudComponent((MWGUIManager::HUDELEMENTS)type);
		}
		else
		{
			MWGUIManager::GetInstance()->HideHudComponent((MWGUIManager::HUDELEMENTS)type);
		}

		if (VehicleInterface::GetInstance() != 0)
		{
			VehicleInterface::GetInstance()->m_AIControlledHUD = true;
		}

		return NULL;
	}

	TypePtr execResetAmmo (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MWObject* src = GetMWObjectForID(popInteger());

		if (src == 0)
		{
			return NULL;
		}

		Stuff::ChainIteratorOf<MechWarrior4::Weapon*> i(&(src->weaponChain));
		MechWarrior4::Weapon* weapon = 0;
		while ((weapon = i.ReadAndNext()) != 0)
		{
			weapon->encryptedAmmoCount = ENCRYPT(weapon->initialAmmoCount);
		}

		return (NULL);
	}

	TypePtr execOverrideHeatOption (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		HeatManager::g_OverrideHeatOption = popBoolean();

		return (NULL);
	}

	TypePtr execSetMissionBounds (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		static_cast<MWMission*>(MWMission::GetInstance())->StoreOriginalBounds(); // jcem

		long id_ul = popInteger();
		long id_lr = popInteger();

		Adept::Entity* object_ul = GetObjectForID<Adept::Entity>(id_ul);
		Adept::Entity* object_lr = GetObjectForID<Adept::Entity>(id_lr);

		if ((object_ul != 0) &&
			(object_lr != 0))
		{
			Vector2DOf<Scalar> bounds_ul;
			bounds_ul.x = ((Stuff::Point3D)(object_ul->GetLocalToWorld())).x;
			bounds_ul.y = ((Stuff::Point3D)(object_ul->GetLocalToWorld())).z;
			Vector2DOf<Scalar> bounds_lr;
			bounds_lr.x = ((Stuff::Point3D)(object_lr->GetLocalToWorld())).x;
			bounds_lr.y = ((Stuff::Point3D)(object_lr->GetLocalToWorld())).z;

			Vector2DOf<Scalar> bounds_ur(bounds_ul);
			bounds_ur.x = bounds_lr.x;
			
			Vector2DOf<Scalar> bounds_ll(bounds_lr);
			bounds_ll.x = bounds_ul.x;

			DynamicArrayOf<Vector2DOf<Scalar> > bounds_list;
			bounds_list.SetLength(4);
			bounds_list[0] = bounds_ul;
			bounds_list[1] = bounds_ll;
			bounds_list[2] = bounds_lr;
			bounds_list[3] = bounds_ur;

			{for (int i = 0; i < bounds_list.GetLength(); ++i)
			{
				Map::GetInstance()->WorldToZoneCoords(bounds_list[i].x,bounds_list[i].y);
			}}

			MWMission* mission = Cast_Object(MWMission*,Adept::Mission::GetInstance());
			mission->SetMissionPolygon(bounds_list);

			bounds_list[0].x = 0;
			bounds_list[0].y = 0;
			bounds_list[1].x = 0;
			bounds_list[1].y = 0.0001f;
			bounds_list[2].x = 0.0001f;
			bounds_list[2].y = 0.0001f;
			bounds_list[3].x = 0.0001f;
			bounds_list[3].y = 0;

			mission->SetWarningPolygon(bounds_list);

			mission->m_ConstraintTopLeft = (Stuff::Point3D)object_ul->GetLocalToWorld();
			mission->m_ConstraintBottomRight = (Stuff::Point3D)object_lr->GetLocalToWorld();

			VehicleInterface::GetInstance()->SetBoundsWarningsEnabled(false);
		}

		return NULL;
	}

	void Group_execRespawn(Group::identifier id)
	{
		mwobject_list objects;
		GetVehiclesFromGroup(id,objects);

		{for (mwobject_list::const_iterator i = objects.begin();
			  i != objects.end();
			  ++i)
		{
			if ((*i)->IsDerivedFrom(Mech::DefaultData) == true)
			{
				Mech* mech = Cast_Object(Mech*,*i);
//				mech->Respawn();
			}
		}}
	}

	TypePtr execRespawn (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int id = popInteger ();

		if (ObjectIDisGroup(id) == true)
		{
			Group_execRespawn(ObjectIDtoGroupID(id));
		}
		else
		{
			MWObject *obj = GetMWObjectForID (id);

			if ((obj != 0) &&
				(obj->IsDerivedFrom(Mech::DefaultData) == true))
			{
				Mech* mech = Cast_Object(Mech*,obj);
//				mech->Respawn();
			}
		}

		return NULL;
	}

	TypePtr execResetMission (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MWApplication* mwapplication = Cast_Object(MWApplication*,MWApplication::GetInstance());
		mwapplication->ResetMission();

		return NULL;
	}

	TypePtr execIsTargeted (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		MechWarrior4::CombatAI* combat_ai = GetCombatAIForID(popInteger());
		Verify((long)combat_ai != -1);

		if (combat_ai != 0)
		{
			if (combat_ai->GetTimeTargetedByEnemy() > 0.5f)
			{
				pushBoolean(true);
				return BooleanTypePtr;
			}
		}

		pushBoolean(false);

		return BooleanTypePtr;
	}

	TypePtr execLookingToward (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		Adept::Entity* at_object = GetObjectForID<Adept::Entity>(popInteger());

		if ((at_object != 0) &&
			(VehicleInterface::GetInstance() != 0) &&
			(VehicleInterface::GetInstance()->vehicle != 0))
		{
			if (MatrixFacesPoint(VehicleInterface::GetInstance()->vehicle->GetLocalToWorld(),
								 (Stuff::Point3D)at_object->GetLocalToWorld(),
								 Stuff::Pi_Over_4) == true)
			{
				pushBoolean(true);
				return BooleanTypePtr;
			}
		}

		pushBoolean(false);
		return BooleanTypePtr;
	}

	TypePtr execFiredWeaponGroup (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int weapon_group = popInteger();

		if (weapon_group > 0)
		{
			--weapon_group;
		}

		if (VehicleInterface::GetInstance()->GetLastTimeFiredWeaponGroup(weapon_group) + 1.0f > gos_GetElapsedTime())
		{
			pushBoolean(true);
		}
		else
		{
			pushBoolean(false);
		}

		return BooleanTypePtr;
	}

	TypePtr execIsSetToNavPoint (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		long objectid = popInteger();
		NavPoint *nav_point = Cast_Object(NavPoint *,NameTable::GetInstance()->FindData(objectid));
		Check_Object(nav_point);

		if ((nav_point != 0) &&
			(VehicleInterface::GetInstance()->GetNavPoint() == nav_point))
		{
			pushBoolean(true);
		}
		else
		{
			pushBoolean(false);
		}

		return BooleanTypePtr;
	}

	TypePtr execGetDamageRating (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int who = popInteger ();

		if (who != ABL_NO_UNIT)
		{
			MechWarrior4::MWObject* object = GetMWObjectForID(who);

			if (object != 0)
			{
				Scalar damage = MW4AI::Damage::GetDamageRating(*object);

				pushInteger((int)damage);
				return IntegerTypePtr;
			}
		}

		pushInteger(0);
		return IntegerTypePtr;
	}

	TypePtr execboardDropShip (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int GroupID = popInteger ();
		int dropid = popInteger ();

		ablREPORT ((ObjectIDisGroup(GroupID)),ablERROR ("trying to board dropship for a non group"));
		Dropship *drop = Cast_Object (Dropship *,NameTable::GetInstance()->FindData (dropid));
		Check_Object (drop);
		Verify (drop->IsDerivedFrom (Dropship::DefaultData));

		std::vector<MoverAI*> list;
		GetAIsFromGroup<MoverAI> (ObjectIDtoGroupID(GroupID),list);

		pushBoolean (BoardDropShip (list,drop));
		return BooleanTypePtr;
	}

	TypePtr execDrop (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int mechID = popInteger ();

		MWObject *obj = GetMWObjectForID (mechID);
		ablREPORT (obj,"could not find the mech with that id");
		Mech *mech = Cast_Object (Mech *,obj);
		Check_Object (mech);
		Verify (mech->IsDerivedFrom (Mech::DefaultData));

		mech->StartDropping ();
		return NULL;
	}

	TypePtr execShowTimer (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int timerid,objid,timeoffset,color;
		bool timeonleft,visible;
		timerid = popInteger ();
		objid = popInteger ();
		timeoffset = popInteger ();
		timeonleft = popBoolean ();
		color = popInteger ();
		visible = popBoolean ();

		MWGUIManager *gui = MWGUIManager::GetInstance ();
		Verify (gui);
		gui->ShowTimer (visible);
		if (visible)
		{
			HUDTimer *timer;
			timer = Cast_Object (HUDTimer *,gui->Component (MWGUIManager::HUD_TIMER));
			timer->Timer (timerid);
			timer->TimeOffset (timeoffset);
			timer->TimeOnLeft (timeonleft);
			timer->Color (color);
			Objective *obj=NULL;

			if (objid)
			{
				obj = Cast_Object(Objective *,NameTable::GetInstance()->FindData(objid));
				Check_Object (obj);
			}

			timer->Objective (obj);
		}

		return NULL;
	}

	TypePtr execSetHelpArrow (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int rot = popInteger ();
		int x = popInteger();
		int y = popInteger();
		int color = popInteger();
		bool visible = popBoolean();
		int time = popInteger();

		MWGUIManager *gui = MWGUIManager::GetInstance ();
		Verify (gui);
		gui->ShowHelpArrow (visible);
		if (visible)
		{
			HUDHelpArrow *arrow = Cast_Object (HUDHelpArrow *,gui->Component (MWGUIManager::HUD_HELPARROW));
			arrow->SetParams((Scalar)rot * Radians_Per_Degree,(Scalar)x,(Scalar)y,color,time);
		}

		return NULL;
	}

	TypePtr execShowHelpArrow (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int rot,color;
		long *loc;
		bool visible;

		rot = popInteger ();
		loc = popIntegerPtr ();
		color = popInteger ();
		visible = popBoolean ();

		MWGUIManager *gui = MWGUIManager::GetInstance ();
		Verify (gui);
		gui->ShowHelpArrow (visible);
		if (visible)
		{
			HUDHelpArrow *arrow;
			arrow = Cast_Object (HUDHelpArrow *,gui->Component (MWGUIManager::HUD_HELPARROW));
			arrow->SetRot ((Scalar) rot * Radians_Per_Degree);
			Point3D locpt;
			locpt.x = (Scalar) loc[0];
			locpt.y = (Scalar) loc[1];
			locpt.z = 0.9f;
			arrow->Location (locpt);
			arrow->Color (color);
		}

		return NULL;
	}

	TypePtr execMakeColor (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int red,green,blue,alpha,toret;
		red = popInteger ();
		green = popInteger ();
		blue = popInteger ();
		alpha = popInteger ();
		toret = (alpha<<24) + (red<<16) + (green<<8) + (blue);
		pushInteger (toret);
		return IntegerTypePtr;
	}

	TypePtr execPlayLancemateSound (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		const char *soundname = popStringPtr ();
		int vo_count = popInteger ();

		if (vo_count < 1)
		{
			vo_count = 1;
		}

		bool played_any = false;
		std::vector<MWObject*> lancemates;
		
		MW4AI::Groups::GetLancemates(lancemates);

		while (lancemates.size() > 0)
		{
			int index = gos_rand() % lancemates.size();

			std::vector<MWObject*>::iterator i = lancemates.begin();

			{for (int j = 0;
				  j < index;
				  ++j)
			{
				++i;
			}}

			if (((*i)->GetAI() != 0) &&
				((*i)->GetAI()->getEntity() != 0) &&
				((*i)->GetAI()->getEntity()->IsDestroyed() == false) &&
				((*i)->GetAI()->GetLancemate() != 0))
			{
				LancematePlug* plug = (*i)->GetAI()->GetLancemate();

				MString audio_command_name(soundname);
				audio_command_name += plug->m_TalkerSuffix;
				audio_command_name += ".wav{handle}";

				MString audio_resource_name("Audio\\");
				audio_resource_name += audio_command_name;

				Resource r(audio_resource_name);

				if (r.DoesResourceExist() == true)
				{
					AudioCommand *command = AudioCommand::Create(AudioRenderer::VOType,audio_command_name,1.0f,1.0f);
					if (command)
					{
						Check_Object(command);
						command->Play();

						if (AudioManager::GetInstance() != 0)
						{
							AudioManager::GetInstance()->AddCommand(command,FindTalkerID (plug->m_TalkerSuffix));
						}
					}

					--vo_count;
					played_any = true;

					if (vo_count == 0)
					{
						pushBoolean(true);
						return BooleanTypePtr;
					}
				}
			}

			lancemates.erase(i);
		}

		pushBoolean(played_any);
		return BooleanTypePtr;
	}
	TypePtr execPlayVoiceOver (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		const char *soundname = popStringPtr ();
		int talker_id = popInteger ();

		if ((talker_id == (ELEMENTS(talker_suffixes)-1)) && (!MW4Shell::Instance->m_optionsObject->m_bettyOn))
		{
			pushBoolean (true);
			return BooleanTypePtr;
		}

		if ((AudioManager::GetInstance() != 0) &&
			(IsDead(AudioManager::GetInstance()->TalkerObjectID(talker_id)) == true))
		{
			pushBoolean (true);
			return BooleanTypePtr;
		}

		if (IsDead(talker_suffixes[talker_id]) == true)
		{
			pushBoolean(true);
			return BooleanTypePtr;
		}

		MString wav_file(soundname);
		Verify((unsigned)talker_id < ELEMENTS(talker_suffixes));
		wav_file += talker_suffixes[talker_id];
		AudioCommand *command = AudioCommand::Create(AudioRenderer::VOType, wav_file, 1.0f, 1.0f);
		if (command)
		{
			Check_Object(command);
			command->Play();

			if (AudioManager::GetInstance() != 0)
			{
				AudioManager::GetInstance()->AddCommand(command,talker_id);
			}
		}
		pushBoolean (false);
		return BooleanTypePtr;
	}

		int GetStringHash(const char* soundname, int talker)
		{
			int rv = 0;
			{for (int i = 0;
				  i < strlen(soundname);
				  ++i)
			{
				rv ^= soundname[i] << ((i & 0x03) * 8);
			}}

			rv ^= strlen(soundname);
			rv ^= (talker << 16);
			return (rv);
		}

	TypePtr execPlayVoiceOverOnce (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		const char *soundname = popStringPtr ();
		int talker_id = popInteger ();
		if ((talker_id == (ELEMENTS(talker_suffixes)-1)) && (!MW4Shell::Instance->m_optionsObject->m_bettyOn))				// this is a betty sound
		{
			pushBoolean (true);
			return BooleanTypePtr;
		}

		if (AudioManager::GetInstance() != 0)
		{
			if ((AudioManager::GetInstance()->GetVOPlayed(GetStringHash(soundname,talker_id)) == true) ||
				(IsDead(AudioManager::GetInstance()->TalkerObjectID(talker_id)) == true))
			{
				pushBoolean (true);
				return BooleanTypePtr;
			}
		}

		if (IsDead(talker_suffixes[talker_id]) == true)
		{
			pushBoolean(true);
			return BooleanTypePtr;
		}

		MString wav_file(soundname);
		Verify((unsigned)talker_id < ELEMENTS(talker_suffixes));
		wav_file += talker_suffixes[talker_id];
		AudioCommand *command = AudioCommand::Create(AudioRenderer::VOType, wav_file, 1.0f, 1.0f);
		if (command)
		{
			Check_Object(command);
			command->Play();

			if (AudioManager::GetInstance() != 0)
			{
				AudioManager::GetInstance()->AddCommand(command,talker_id);
			}

			if (AudioManager::GetInstance() != 0)
			{
				AudioManager::GetInstance()->SetVOPlayed(GetStringHash(soundname,talker_id));
			}
		}

		pushBoolean (false);
		return BooleanTypePtr;
	}
	TypePtr execKillVoiceOvers (SymTableNodePtr routineIdPtr)
	{
//		DECLARE_ABL_CONTEXT;

		if (AudioManager::GetInstance() != 0)
		{
			AudioManager::GetInstance()->DeleteAllCommands();
		}
		endFunction ();

		return NULL;
	}
	TypePtr execIsVoiceOverPlaying (SymTableNodePtr routineIdPtr)
	{
		if (AudioManager::GetInstance() != 0)
		{
			pushBoolean(AudioManager::GetInstance()->IsVoiceOverPlaying());
		}
		else
		{
			pushBoolean(false);
		}

		endFunction ();

		return BooleanTypePtr;
	}
	TypePtr execStartMusic (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		const char *soundname = popStringPtr ();
		float old_timeout = popReal ();
		float new_timein = popReal ();
		float new_volume = popInteger () / 100.0f;

		if (g_MissionMusic)
		{
			MString wav_file(soundname);
			wav_file += "_music.wav{handle}";
			AudioCommand *command = AudioCommand::Create(AudioRenderer::MusicType, wav_file, 1, 1);
			if ((command) &&
				(AudioManager::GetInstance() != 0))
			{
				AudioManager::GetInstance()->AddMusicCommand(command,old_timeout,new_timein,new_volume);
			}
		}

		return NULL;
	}
	TypePtr execIsMusicPlaying (SymTableNodePtr routineIdPtr)
	{
		if (AudioManager::GetInstance() != 0)
		{
			pushBoolean(AudioManager::GetInstance()->IsMusicPlaying());
		}
		else
		{
			pushBoolean(false);
		}

		endFunction ();

		return BooleanTypePtr;
	}
	TypePtr execPlayBettySound (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int sound_index = popInteger();

		Check_Object(VehicleInterface::GetInstance());
		VehicleInterface::GetInstance()->ReactToEvent((VehicleInterface::SOUND_TRIGGER)sound_index);

		return NULL;
	}
	TypePtr execPlayTeamBettySound (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int team_number = popInteger();
		int sound_index = popInteger();

		if ((Network::GetInstance() != 0) &&
			(MWApplication::GetInstance() != 0))
		{
			if ((team_number == 0) ||
				(team_number > MWApplication::No_Team))
			{
				return NULL;
			}

			--team_number;

			DynamicMemoryStream stream;

			stream.WriteBytes(&team_number,1);
			stream.WriteBytes(&sound_index,1);

			MWApplication* app = Cast_Object(MWApplication*,MWApplication::GetInstance());

			{
				for (int i = 0; i < Maximum_Players; ++i)
				{
					if ((app->servedConnectionData[i].clientLaunched) &&
						(app->servedConnectionData[i].clientPlayer != 0))
					{
						stream.Rewind();
						Network::GetInstance()->SendNetMessage(i, MWApplication::TeamBettyMessageID, &stream, true);
					}
				}
			}
		}

		return NULL;
	}

	TypePtr execStartMusicAll (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int	sound_index = popInteger();

		if (g_MissionMusic &&
			(Network::GetInstance() != 0) &&
			(MWApplication::GetInstance() != 0))
		{
			DynamicMemoryStream stream;
			stream.WriteBytes(&sound_index,1);

			MWApplication* app = Cast_Object(MWApplication*,MWApplication::GetInstance());

			{for (int i = 0; i < Maximum_Players; ++i)
			{
				if ((app->servedConnectionData[i].clientLaunched) &&
					(app->servedConnectionData[i].clientPlayer != 0))
				{
					stream.Rewind();
					Network::GetInstance()->SendNetMessage(i,
														   MWApplication::StartMusicMessageID,
														   &stream,
														   true);
				}
			}}
		}

		return NULL;
	}
	TypePtr execTeamSetNav (SymTableNodePtr routineIdPtr)
	{

		DECLARE_ABL_CONTEXT;

		int team_number = popInteger();
		int nav = popInteger();

		if ((Network::GetInstance() != 0) &&
			(MWApplication::GetInstance() != 0))
		{
			if (team_number == 0)
			{
				team_number = 8;
			}
			else
			{
				if ((team_number < 0) ||
					(team_number > 8))
				{
					return NULL;
				}
				else
				{
					--team_number;
				}
			}

			MWApplication* app = Cast_Object(MWApplication*,MWApplication::GetInstance());

			if (team_number == 8)
			{
				if (most_recent_no_team_nav == nav)
				{
					return NULL;
				}
			}
			else
			{
				if ((app->teams[team_number] != 0) &&
					(app->teams[team_number]->GetCurrent() != 0) &&
					(app->teams[team_number]->GetCurrent()->m_MostRecentTeamNav == nav))
				{
					return NULL;
				}
			}

			DynamicMemoryStream stream;

			stream.WriteBytes(&team_number,1);
			stream.WriteBytes(&nav,4);

			{for (int i = 0; i < Maximum_Players; ++i)
			{
				if ((app->servedConnectionData[i].clientLaunched) &&
					(app->servedConnectionData[i].clientPlayer != 0) &&
					(app->servedConnectionData[i].clientPlayer->vehicle != 0) &&
					(app->servedConnectionData[i].clientPlayer->vehicle->IsDerivedFrom(Vehicle::DefaultData) == true))
				{
					Vehicle* vehicle = Cast_Object(Vehicle*,app->servedConnectionData[i].clientPlayer->vehicle);

					if (vehicle->GetTeam() == team_number)
					{
						stream.Rewind();
						Network::GetInstance()->SendNetMessage(i,
															   MWApplication::TeamSetNavMessageID,
															   &stream,
															   true);
					}
				}
			}}

			if (team_number == 8)
			{
				most_recent_no_team_nav = nav;
			}
			else
			{
				if ((app->teams[team_number] != 0) &&
					(app->teams[team_number]->GetCurrent() != 0))
				{
					app->teams[team_number]->GetCurrent()->m_MostRecentTeamNav = nav;
				}
			}
		}

		return NULL;
	}
	TypePtr execSpecifyTalker (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int talker = popInteger();
		int object_id = popInteger();

		if (AudioManager::GetInstance() != 0)
		{
			AudioManager::GetInstance()->MapTalker(talker,object_id);
		}

		return NULL;
	}
	TypePtr execNavPointReached (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int src_id = popInteger ();
		MWObject* src = GetMWObjectForID(src_id);

		if ((src != 0) && (src->IsDestroyed() == false) && (src->vehicleInterface != 0))
		{
			MechWarrior4::VehicleInterface* vehicle_interface = Cast_Object(MechWarrior4::VehicleInterface*,src->vehicleInterface);

			vehicle_interface->ReactToEvent (VehicleInterface::NAVPOINT_REACHED);
		}
		return NULL;
	}

	TypePtr execStandardRoutineCall (SymTableNodePtr routineIdPtr)
	{
		TypePtr toret;

		if (debugger)
			debugger->traceRoutineEntry(routineIdPtr);
		long routineKey = routineIdPtr->defn.info.routine.key;

		ablREPORT ((*g_ABLFunctions)[routineKey] != NULL,ablERROR ("undefined abl function"));

		#ifdef LAB_ONLY
		double start_time(gos_GetHiResTime());
		#endif

		toret = (*g_ABLFunctions)[routineKey]->Execute (routineIdPtr);

		#ifdef LAB_ONLY
		double execute_time(gos_GetHiResTime() - start_time);
		if ((Profiler::Instance() != 0) &&
			(CurModule != 0) &&
			(Profiler::Instance()->GetActive() == true))
		{
			Profiler::Instance()->NotifyFunctionCalled(execute_time,
													  (*g_ABLFunctions)[routineKey]->Name(),
													  CurModule->getName());
		}
		#endif

		if (debugger)
			debugger->traceRoutineExit(routineIdPtr);
		return toret;
	}

	void Group_execSetDmgModifier(Group::identifier group_id, int nIdx, int nDmgFactor)
	{
		mwobject_list targets;

		GetVehiclesFromGroup(group_id,targets,true);

		if (targets.size() == 0)
		{
			return;
		}

		mwobject_list::iterator best_found = targets.end();

		{for (mwobject_list::iterator i = targets.begin(); i != targets.end(); ++i)
		{
			(*i)->SetDmgModifier(nIdx, nDmgFactor);
		}}
	}
	TypePtr execSetDmgModifier (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int nWho = popInteger();
		int nIdx = popInteger(); // 0: default, 1: splash
		int nDmgFactor = popInteger(); // should be -1(restore), 0(store), (1 <= && <= 10000)
		// real factor = nDmgFactor / 10000.0

		if (ObjectIDisGroup(nWho) == true) {
			Group_execSetDmgModifier(ObjectIDtoGroupID(nWho), nIdx, nDmgFactor);
		} else {
			MWObject* src = GetMWObjectForID(nWho);

			if (src != 0)
			{
				src->SetDmgModifier(nIdx, nDmgFactor);
			}
		}

		return (NULL);
	}

	TypePtr execRestoreOriginalBounds (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		static_cast<MWMission*>(MWMission::GetInstance())->RestoreOriginalBounds();

		return (NULL);
	}

	MechWarrior4::Path& GetPathFromID(int nPathID)
	{
		if (nPathID < 0) {
			ablREPORT (nPathID==-1,ablERROR ("nPathID should >= -1"));
			return *(MechWarrior4::Path*)NULL;
		} else {
			Entity *entity;
			MechWarrior4::Path* path;
			entity = NameTable::GetInstance()->FindData (nPathID);
			ablREPORT (entity->IsDerivedFrom (MechWarrior4::Path::DefaultData),ablERROR ("tried to set bounds using invalid path..."));
			return *Cast_Object (MechWarrior4::Path *,entity);
		}
	}

	TypePtr execSetBoundsFromPaths (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		int nMiss = popInteger();
		int nWarn = popInteger();

		static_cast<MWMission*>(MWMission::GetInstance())->SetBoundsFromPaths(GetPathFromID(nMiss), GetPathFromID(nWarn));

		return (NULL);
	}

	TypePtr execRandSelect (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		// group id - dest, group id - src, int nCount
		// if (nCount < 0) then move-to-group not add-to-group

		long dest = popInteger();
		long src = popInteger();
		int nCount = popInteger();

		ablREPORT ((ObjectIDisGroup(dest) == true),ablERROR ("execRandSelect: group id is required"));
		ablREPORT ((ObjectIDisGroup(src) == true),ablERROR ("execRandSelect: group id is required"));

		Group::identifier g_dest = ObjectIDtoGroupID(dest);
		Group::identifier g_src = ObjectIDtoGroupID(src);
		ablREPORT ((g_dest != g_src),ablERROR ("execRandSelect: should be src != dest"));

		bool bMove = false;
		if (nCount < 0) {
			nCount = -nCount;
			bMove = true;
		}
		int i, nSrcCount = MW4AI::Groups::Size(g_src);
		Adept::ObjectID* pIDs = new Adept::ObjectID[nSrcCount];
		Adept::ObjectID* p = pIDs;
		Adept::ObjectID obj_id;

		for(i = 0; i < nSrcCount; i++)
		{
			if (MW4AI::Groups::GetMember(g_src, (unsigned)i, obj_id)) {
				if (!MW4AI::Groups::ContainsObject(obj_id, g_dest))
					*p++ = obj_id;
			}
		}
		nSrcCount = p - pIDs;

		while(0 < nSrcCount)
		{
            if (nCount <= 0)
                break;
			int n = Stuff::Random::GetRandomInt() % nSrcCount;
			if (0 <= n) {
				obj_id = pIDs[n];

				nSrcCount--;
				if (n < nSrcCount)
					memcpy(&pIDs[n], &pIDs[n + 1], sizeof(Adept::ObjectID) * (nSrcCount - n));
				if (bMove) {
					MW4AI::Groups::RemoveObject(obj_id, g_src);
				}
				MW4AI::Groups::AddObject(obj_id, g_dest);

                nCount--;
			}
		}

		delete [] pIDs;

		return (NULL);
	}
	TypePtr execRespawnPosition (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		// group id - dest, group id - src, int nCount
		// if (nCount < 0) then move-to-group not add-to-group

		Adept::ObjectID id_who = popInteger();
		gosASSERT(id_who == -1); // currently single player only...
		Adept::ObjectID id_where = popInteger();
		ablREPORT ((ObjectIDisGroup(id_where) != true),ablERROR ("execRespawnPosition: group id is not allowed, only drop id required"));
		// see MWApplication::RequestRespawnMessageHandler(int connection, Stuff::MemoryStream *message)
#ifdef _DEBUG
		Check_Object(EntityManager::GetInstance());
		Adept::DropZone *zone = EntityManager::GetInstance()->GetDropZone(id_where);
		Check_Object(zone);
#endif // _DEBUG

		MWApplication *app;
		app = MWApplication::GetInstance ();

		int nSvrID = Connection::Server->GetID();
		Check_Object(app->servedConnectionData[nSvrID].clientPlayer);
		app->servedConnectionData[nSvrID].clientPlayer->dropZone = id_where;

		return (NULL);
	}

	TypePtr execGetCOOP (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

        MWMission* mission = Cast_Object(MWMission*, MWMission::GetInstance());
        gosASSERT(mission);

		int nIdx = popInteger();

        int nRet = mission->GetCOOP(nIdx);

		pushInteger(nRet);

		return IntegerTypePtr;
    }

	TypePtr execSetCOOP (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

        MWMission* mission = Cast_Object(MWMission*, MWMission::GetInstance());
        gosASSERT(mission);

		int nIdx = popInteger();
        int nParam = popInteger();

        int nRet = mission->SetCOOP(nIdx, nParam);

		pushInteger(nRet);

		return IntegerTypePtr;
    }

    TypePtr execGetTime (SymTableNodePtr routineIdPtr)
	{
		pushReal (gos_GetElapsedTime());
		endFunction ();
		return RealTypePtr;
    }

    TypePtr execGetTimeX (SymTableNodePtr routineIdPtr)
	{
        pushReal (gos_GetHiResTime());
		endFunction ();
		return RealTypePtr;
    }

    TypePtr execIGetTime (SymTableNodePtr routineIdPtr)
	{
		pushInteger ((int)(gos_GetElapsedTime() * 1000.0f));
		endFunction ();
		return IntegerTypePtr;
    }

    TypePtr execIGetTimeX (SymTableNodePtr routineIdPtr)
	{
		pushInteger ((int)(gos_GetHiResTime() * 1000.0f));
		endFunction ();
		return IntegerTypePtr;
    }

	TypePtr execPlaySoundStr (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;

		char *name = popStringPtr();
        AudioCommand *asdf = AudioCommand::Create(AudioRenderer::MechanicalType, name, 1.0f, 1.0f);
        if (asdf) {
            Check_Object(asdf);
            asdf->Play();
        }

		return NULL;
	}

	TypePtr execLogMapRespawn (SymTableNodePtr routineIdPtr)
	{
		endFunction ();
			
#if defined( STATS2_BUILD )
		MW4log2_LocalLogGeneric(va("MapRespawn"));
#else
//		MW4log_generic(MW4G_MAPRESPAWN, va("MapRespawn"));
#endif

		return NULL;
	}

	TypePtr execLogDefendingTeam (SymTableNodePtr routineIdPtr)
	{

		DECLARE_ABL_CONTEXT;
		int defending_team = popInteger();
		defending_team-=1;


#if defined( STATS2_BUILD )
		MW4log2_LocalLogGeneric(va("DefendingTeam\t%d",defending_team));
#else
//		MW4log_generic(MW4T_DEFENDINGTEAM, va("DefendingTeam\t%d",defending_team));
#endif

		return NULL;
	}


	TypePtr execLogHQDestroyed (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int team_hq = popInteger();
		int destroying_team = popInteger();

		team_hq-=1;
		destroying_team-=1;

#if defined( STATS2_BUILD )
		MW4log2_LocalLogGeneric(va("HQDestroyed\t%d\t%d",team_hq,destroying_team));
#else
//		MW4log_generic(MW4T_HQDESTROYED, va("HQDestroyed\t%d\t%d",team_hq,destroying_team));
#endif

		return NULL;
	}


	TypePtr execLogDefendTimeAward (SymTableNodePtr routineIdPtr)
	{
		DECLARE_ABL_CONTEXT;
		int team = popInteger();
		int award = popInteger();

		team-=1;


#if defined( STATS2_BUILD )
		MW4log2_LocalLogGeneric(va("DefendTimeAward\t%d\t%d",team,award));
#else
//		MW4log_generic(MW4T_HQDESTROYED, va("DefendTimeAward\t%d\t%d",team,award));
#endif

		return NULL;
	}


    int GetEnemyTyps(int id_group, char** ppNames, int* pnCounts, int nMask)
    {
		gosASSERT(ObjectIDisGroup(id_group) == true);
        Group::identifier group_id = ObjectIDtoGroupID(id_group);

		mwobject_list targets;

		GetVehiclesFromGroup(group_id,targets,true);

        MWMission* mission;
        if (MWMission::GetInstance())
            mission = Cast_Object(MWMission*, MWMission::GetInstance());
        else
            mission = NULL;
        int nSubStageNumber = mission->GetCOOP(MWMission::COOP_SUBSTAGE_NUMBER);
        bool bBonusStage = (4 < nSubStageNumber) ? true: false;

        int i;
        int nMechs = 0;
        int nTypes = 0;
        struct STypeInfo
        {
            int m_nCount;
            char m_strTypeName[64];
        }
		aTypeInfos[100];
        int nMiscs = 0;

		mwobject_list::iterator best_found = targets.end();

        MWApplication* app = MWApplication::GetInstance();
		{
			for (mwobject_list::iterator itr = targets.begin(); itr != targets.end(); ++itr)
			{
				MWObject* pObj = (*itr);

				if (pObj->IsDerivedFrom(Mech::DefaultData))
				{
					nMechs++;
				}
				else if (pObj->IsDerivedFrom(Building::DefaultData) || pObj->IsDerivedFrom(Vehicle::DefaultData))
				{
					const char* pcszName;
					if (bBonusStage && !pObj->IsDerivedFrom(Vehicle::DefaultData))
					{
						pcszName = "Buildings";
					}
					else
					{
						const MechWarrior4::MWObject::GameModel* game_model = pObj->GetGameModel();
						Check_Object(game_model);
						pcszName = app->GetLocString(game_model->m_nameIndex);
					}
	                if (0 < strlen(pcszName)) 
					{
			            for(i = 0; i < nTypes; i++)
				        {
					        if (strcmp(aTypeInfos[i].m_strTypeName, pcszName) == 0) 
							{
							    aTypeInfos[i].m_nCount++;
								break;
	                        }
		                }
			            if (i == nTypes) 
						{
					        strcpy(aTypeInfos[nTypes].m_strTypeName, pcszName);
						    aTypeInfos[nTypes].m_nCount = 1;
							nTypes++;
	                    }
		            }
					else
					{
					    nMiscs++;
	                }
		        }
				else if (pObj->IsDerivedFrom(Mech::DefaultData)) 
				{
	                nMiscs++;
		        }
			}
		}

        int nRet = 0;

        if (0 < nMechs)
		{
            FREEANDNULL(*ppNames);

            const char* strMech = "Enemy Mechs";
            char* psz = (char*)gos_Malloc(strlen(strMech) + 1);
            strcpy(psz, strMech);

            *ppNames++ = psz;
            *pnCounts++ = nMechs;
            nRet++;
        }

        for(i = 0; i < nTypes; i++)
        {
            FREEANDNULL(*ppNames);

            char* psz = (char*)gos_Malloc(strlen(aTypeInfos[i].m_strTypeName) + 1);
            strcpy(psz, aTypeInfos[i].m_strTypeName);

            *ppNames++ = psz;
            *pnCounts++ = aTypeInfos[i].m_nCount;
            nRet++;
        }

        if (0 < nMiscs)
		{
            FREEANDNULL(*ppNames);

            const char* strMisc = "Misc Enemy";
            char* psz = (char*)gos_Malloc(strlen(strMisc) + 1);
            strcpy(psz, strMisc);

            *ppNames++ = psz;
            *pnCounts++ = nMiscs;
            nRet++;
        }

        return nRet;
    }
//***************************************************************************


}
