#ifndef _ScripUtils_
#define _ScripUtils_

// Interface between game and mission ai
#ifndef MISN_INTERNAL
#ifdef _GameObject_
#define MISN_INTERNAL 0
#else
#define MISN_INTERNAL 1
#endif
#endif

// DLL versioning code to make sure things are in sync between app and
// dll-- this magic # should be changed every time the misnExport
// structure changes to trap old DLLs. This magic # was chosen
// randomly, and incrementing it by 1 each time is a good update
// Changes in MisnImport do _NOT_ require changes to LATEST_DLL_VERSION
#define LATEST_DLL_VERSION 0x4C89322D
// Identifier of who last modified LATEST_DLL_VERSION, so that
// sourcesafe will catch attempts to modify from 2 people at
// once. Pick a 4-digit identifier for yourself and add to this list:
// Nathan = '~GSH'
// Brad = 'BRAD'
// Ken = 'KEN3'
#define LATEST_DLL_VERSION_MODIFIER '~GSH'

// Set of return codes from the PlayerEjected/PlayerKilled call to DLL
enum EjectKillRetCodes {
	DoEjectPilot, // Do 'standard' eject
	DoRespawnSafest, // Respawn a 'PLAYER' at safest spawnpoint
	DLLHandled, // DLL handled actions. Do nothing ingame
	DoGameOver, // Game over, man.
};

// Deathmatch01.DLL game subtypes (ivar7) list. Used to synchronize UI
// and gameplay behavior between main code and DLL
enum DeathmatchGameSubtypes {
	DMSubtype_Normal=0,
	DMSubtype_KOH,
	DMSubtype_CTF,
	DMSubtype_Loot,
	DMSubtype_RESERVED1, // For internal Pandemic use-- Andrew's work
	DMSubtype_Race1, // Race, respawn as person
	DMSubtype_Race2, // Race, respawn as vehicle
	DMSubtype_Normal2, // Normal, but respawn as vehicle (no person)
	DMSUBTYPE_COUNT,
};

// For activating the #Laps interface, and behaving like a race DLL
const bool DMIsRaceSubtype[DMSUBTYPE_COUNT]={false,false,false,false,false,true,true,false};

enum PathType;

#define DLLAPI __cdecl

#if MISN_INTERNAL
#include <stdio.h>
#include <limits.h>

class GameObject;
class AiPath;

// Make sure these are available
#ifndef FALSE
#define FALSE 0
#endif

#ifndef TRUE
#define TRUE 1
#endif

#define RGB(r,g,b) (0xFF000000|(r)<<16|(g)<<8|(b))
#define RGBA_MAKE(r, g, b, a) \
((unsigned long) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))) 

#define WHITE RGB(255,255,255)
#define GREEN RGB(0,255,0)
#define RED RGB(255,0,0)

#define SIZEOF(a) (sizeof(a)/sizeof(a[0]))

struct Vector {
	float x;
	float y;
	float z;
};

struct VECTOR_2D {
	float x;
	float z;
};

typedef float F32;
struct Matrix
{
	Vector right;
	F32 rightw;
	Vector up;
	F32 upw;
	Vector front;
	F32 frontw;
	Vector posit;
	F32 positw;
};

#define AVD_NONE 0 // don't avoid collisions
#define AVD_FORCE 1 // use force avoidance
#define AVD_PLAN 2 // plan collision avoidance

// keep this enum in sync with AiCmds.h
#include "AiCmds.h"

// functions not worth calling through dllexport
// implement utility functions in the dll (ie SPMission)
Vector Normalize_Vector (const Vector &A);

#endif

typedef char *Name;
typedef int Handle;
typedef int TeamNum;
typedef float Time;
typedef float Distance;
typedef int ScrapValue;
typedef unsigned long DWORD;
typedef DWORD DPID;
#define DPID_UNKNOWN 0xFFFFFFFF

// Max # of different teams that can be used at once; see entities.h
// for real definition
#define MAX_TEAMS 16
// # of multiple-user teams are possible in Teamplay
#define MAX_MULTIPLAYER_TEAMS 2
// # of vehicles usable out of MPVehicles.txt
#define MAX_MP_VEHICLES_ENTRIES 32

#define CTRL_BRACCEL (1<<0)
#define CTRL_STEER (1<<1)
#define CTRL_PITCH (1<<2)
#define CTRL_STRAFE (1<<3)
#define CTRL_JUMP (1<<4)
#define CTRL_DEPLOY (1<<5)
#define CTRL_EJECT (1<<6)
#define CTRL_ABANDON (1<<7)
#define CTRL_FIRE (1<<8)

struct VehicleControls {
	float braccel;
	float steer;
	float pitch;
	float strafe;
	char jump;
	char deploy;
	char eject;
	char abandon;
	char fire;
};

// functions called by mission
// Changes in MisnImport do _NOT_ require changes to LATEST_DLL_VERSION
struct MisnImport {
	float time;
	void (DLLAPI *FailMission)(Time t, char* fileName);
	void (DLLAPI *SucceedMission)(Time t, char* fileName);
	void (DLLAPI *ChangeSide)(void);
	ScrapValue (DLLAPI *AddScrap)(TeamNum t, ScrapValue v);
	ScrapValue (DLLAPI *SetScrap)(TeamNum t, ScrapValue v);
	ScrapValue (DLLAPI *GetScrap)(TeamNum t);
	ScrapValue (DLLAPI *GetMaxScrap)(TeamNum t);
	Handle (DLLAPI *GetTug)(Handle h);
	bool (DLLAPI *HasCargo)(Handle h);
	Distance (DLLAPI *GetDistanceObject)(Handle &h1, Handle &h2);
	Distance (DLLAPI *GetDistancePath)(Handle &h1, Name path, int point);
	Distance (DLLAPI *GetDistancePathPtr)(Handle &h1, AiPath *path, int point);
	Handle (DLLAPI *GetNearestObject)(Handle h);
	Handle (DLLAPI *GetNearestVehicleObject)(Handle h);
	Handle (DLLAPI *GetNearestVehiclePath)(Name path, int point);
	Handle (DLLAPI *GetNearestBuilding)(Handle h);
	Handle (DLLAPI *GetNearestEnemy)(Handle h);
};

// functions called by game. Whenever this structure changes, bump up
// LATEST_DLL_VERSION to trap old DLLs that don't agree with expected API
// Changes in MisnImport do _NOT_ require changes to LATEST_DLL_VERSION
struct MisnExport {
	MisnImport *misnImport;
	unsigned long version; // For version # sanity checking... should be LATEST_DLL_VERSION.
	unsigned long VersionModifier; // For version # sanity checking... should be LATEST_DLL_VERSION_MODIFIER.

	// Function called just after DLL loaded. Do any initial setup stuff here.
	void (DLLAPI *InitialSetup)(void);

	bool (DLLAPI *Save)(bool missionSave);
	bool (DLLAPI *Load)(bool missionSave);
	bool (DLLAPI *PostLoad)(bool missionSave);
	void (DLLAPI *AddObject)(Handle h);
	void (DLLAPI *DeleteObject)(Handle h);
	void (DLLAPI *Update)(void);
	void (DLLAPI *PostRun)(void);

	// AddPlayer is called when someone is added to the game. If
	// IsJoiningPlayer is FALSE, then they're "already" in the game
	// (e.g. server player is already "in" the game when a client
	// joins); IsJoiningPlayer is TRUE when a new client joins. Creating
	// objects should _ONLY_ be done when TRUE is passed in, unless you
	// make sure all versions of the DLL on all machines will behave
	// identic.
	//
	// Returns FALSE if not to be allowed into the game (full,
	// singleplayer, etc) ShouldCreateThem is true if a dll should build
	// objects for this player, false if the server's already created
	// them, and we should use the id for informational purposes only
	bool (DLLAPI *AddPlayer)(DPID id, int Team, bool ShouldCreateThem);

	// Notification call tht someone's leaving the game
	void (DLLAPI *DeletePlayer)(DPID id);

	// Player's bailing out or getting killed. See definition of EjectKillRetCodes for more info
	EjectKillRetCodes (DLLAPI *PlayerEjected)(Handle DeadObjectHandle);
	EjectKillRetCodes (DLLAPI *ObjectKilled)(Handle DeadObjectHandle, Handle KillersHandle);
	EjectKillRetCodes (DLLAPI *ObjectSniped)(Handle DeadObjectHandle, Handle KillersHandle);
	// If PlayerEjected/Killed returned DoRandomRespawnSafest, DLL gets
	// queried as to what ODF to build. This is ONLY called if that's
	// returned; you can default this to returning "PLAYER" or something
	// else if DLL doesn't support that.
	char *(DLLAPI *GetNextRandomVehicleODF)(int ForTeam);
	void (DLLAPI *SetWorld)(int nextWorld);

	// interface handler
	void (DLLAPI *ProcessCommand)(unsigned long crc);

	// Random # seed setter. Called at top of frame
	void (DLLAPI *SetRandomSeed)(unsigned long seed);
};

#if MISN_INTERNAL
extern MisnImport misnImport;
extern "C" MisnExport __declspec(dllexport) * DLLAPI GetMisnAPI(MisnImport *import);
#define DLLEXPORT __declspec( dllimport )
#else
extern MisnExport *misnExport;
void FillMisnImport(MisnImport &misnImport);
#define DLLEXPORT __declspec( dllexport )
#endif

#if MISN_INTERNAL

inline void FailMission(Time t, char* fileName = NULL)
{
	misnImport.FailMission(t, fileName);
}

inline void SucceedMission(Time t, char* fileName = NULL)
{
	misnImport.SucceedMission(t, fileName);
}

inline void ChangeSide(void)
{
	misnImport.ChangeSide();
}

inline ScrapValue AddScrap(TeamNum t, ScrapValue v)
{
	return misnImport.AddScrap(t, v);
}

inline ScrapValue SetScrap(TeamNum t, ScrapValue v)
{
	return misnImport.SetScrap(t, v);
}

inline ScrapValue GetScrap(TeamNum t)
{
	return misnImport.GetScrap(t);
}

inline ScrapValue GetMaxScrap(TeamNum t)
{
	return misnImport.GetMaxScrap(t);
}

inline Time GetTime(void)
{
	return misnImport.time;
}

// tug = GetTug(cargo);
// if (tug != 0)
// Attack(tank1, tug);
inline Handle GetTug(Handle h)
{
	return misnImport.GetTug(h);
}

// if (HasCargo(tug1))
// Attack(tank1, tug1);
inline bool HasCargo(Handle h)
{
	return misnImport.HasCargo(h);
}

inline Distance GetDistance(Handle &h1, Handle &h2)
{
	return misnImport.GetDistanceObject(h1, h2);
}

inline Distance GetDistance(Handle &h1, Name path, int point = 0)
{
	return misnImport.GetDistancePath(h1, path, point);
}

inline Distance GetDistance(Handle &h1, AiPath *path, int point = 0)
{
	return misnImport.GetDistancePathPtr(h1, path, point);
}

inline Handle GetNearestObject(Handle h)
{
	return misnImport.GetNearestObject(h);
}

inline Handle GetNearestVehicle(Handle h)
{
	return misnImport.GetNearestVehicleObject(h);
}

inline Handle GetNearestVehicle(Name path,int point)
{
	return misnImport.GetNearestVehiclePath(path, point);
}

inline Handle GetNearestBuilding(Handle h)
{
	return misnImport.GetNearestBuilding(h);
}

inline Handle GetNearestEnemy(Handle h)
{
	return misnImport.GetNearestEnemy(h);
}

#else

// IN GAME DEFINITIONS

void LoadScriptUtils(void);
void PostLoadScriptUtils(void);
void SaveScriptUtils(void);

void DLLAPI FailMission(Time t, char* fileName = NULL);
void DLLAPI SucceedMission(Time t, char* fileName = NULL);
void DLLAPI ChangeSide(void);

void SetAIP(Name n);

#endif

// Handle friend2 = BuildObject("svturr", 2, friend1);
DLLEXPORT Handle DLLAPI BuildObject(char *odf, int team, Handle h);

// Handle friend2 = BuildObject("svturr", 2, "attack_start");
DLLEXPORT Handle DLLAPI BuildObject(char *odf, int team, Name path);

// AiPath *attack_start = AiPath::Find("attack_start");
// Handle friend2 = BuildObject("svturr", 2, attack_start);
DLLEXPORT Handle DLLAPI BuildObject(char *odf, int team, AiPath *path);

// Vector x = { 0, 0, 0 };
// Handle turret1 = BuildObjectPoint("svturr", 2, x);
DLLEXPORT Handle DLLAPI BuildObject(char *odf, int team, Vector &pos);
DLLEXPORT Handle DLLAPI BuildObject(char *odf, int team, Matrix &mat);

// Handle temp = GetHandle("drone");
// RemoveObject(temp);
DLLEXPORT void DLLAPI RemoveObject(Handle h);

DLLEXPORT int DLLAPI GetFirstEmptyGroup(void);
DLLEXPORT void DLLAPI SetGroup(Handle h, int group);

// Attack(friend1, enemy1);
DLLEXPORT void DLLAPI Attack(Handle me, Handle him, int priority = 1);

// Service(friend1, enemy1);
DLLEXPORT void DLLAPI Service(Handle me, Handle him, int priority = 1);

// Goto(friend1, "attack_path");
DLLEXPORT void DLLAPI Goto(Handle me, Name path, int priority = 1);

// Goto(friend1, friend2);
DLLEXPORT void DLLAPI Goto(Handle me, Handle him, int priority = 1);

// Mine
DLLEXPORT void DLLAPI Mine(Handle me, Name path, int priority = 1);

// Follow(friend1, friend2);
DLLEXPORT void DLLAPI Follow(Handle me, Handle him, int priority = 1);

// Defend(friend1);
DLLEXPORT void DLLAPI Defend(Handle me, int priority = 1);

// Defend(friend1, friend2);
DLLEXPORT void DLLAPI Defend2(Handle me, Handle him, int priority = 1);

// Stop(friend1);
DLLEXPORT void DLLAPI Stop(Handle me, int priority = 1);

// Patrol(friend1, "patrol_path");
DLLEXPORT void DLLAPI Patrol(Handle me, Name path, int priority = 1);

// Retreat(friend1, "retreat_path");
DLLEXPORT void DLLAPI Retreat(Handle me, Name path, int priority = 1);

// Retreat(friend1, friend2);
DLLEXPORT void DLLAPI Retreat(Handle me, Handle him, int priority = 1);

// GetIn(friend1, apc1);
DLLEXPORT void DLLAPI GetIn(Handle me, Handle him, int priority = 1);

// Pickup(friend1, object1);
DLLEXPORT void DLLAPI Pickup(Handle me, Handle him, int priority = 1);

// Dropoff(tug1, "return_path");
DLLEXPORT void DLLAPI Dropoff(Handle me, Name path, int priority = 1);

// Build(rig, "sbsilo");
DLLEXPORT void DLLAPI Build(Handle me, char *odf, int priority = 1);

// LookAt(leader1, follow1);
DLLEXPORT void DLLAPI LookAt(Handle me, Handle him, int priority = 1);

// everybody on a team look at somebody
DLLEXPORT void DLLAPI AllLookAt(int team, Handle him, int priority = 1);

// if (IsOdf(enemy1, "svturr"))
// Attack(friend1, enemy1);
DLLEXPORT bool DLLAPI IsOdf(Handle h, char *odf);

// Returns 'i' or 'f' depending on the vehicle's race. Returns 0
// ('\0') if bad handle
DLLEXPORT char DLLAPI GetRace(Handle h);

// get a handle to the player
DLLEXPORT Handle DLLAPI GetPlayerHandle(void);

// see if a unit is alive and is still pilot controlled
DLLEXPORT bool DLLAPI IsAlive(Handle &h);

// see if a unit is tagged as flying
DLLEXPORT bool DLLAPI IsFlying(Handle &h);

// ??
DLLEXPORT bool DLLAPI IsAliveAndPilot(Handle &h);

// see if a unit still exists
DLLEXPORT bool DLLAPI IsAround(Handle h);

// return the building a unit is in or 0 if no building
DLLEXPORT Handle DLLAPI InBuilding(Handle h);

// return the building of the terminal a unit is at
DLLEXPORT Handle DLLAPI AtTerminal(Handle h);

// Handle friend1 = GetHandle("wave1_turret");
DLLEXPORT Handle DLLAPI GetHandle(Name n);

DLLEXPORT Handle DLLAPI GetHandle(int seqNo);

DLLEXPORT void DLLAPI GetPosition(Handle h, Vector &pos);
inline Vector GetPosition(Handle h)
{
	Vector v;
	GetPosition(h, v);
	return v;
}

// Like GetPosition, but uses the slower search to find handles of
// things that just got blown up. Useful for callbacks from
// ObjectKilled/ObjectSniped/etc.
DLLEXPORT void DLLAPI GetPosition2(Handle h, Vector &pos);

DLLEXPORT void DLLAPI GetFront(Handle h, Vector &dir);
inline Vector GetFront(Handle h)
{
	Vector v;
	GetFront(h, v);
	return v;
}

DLLEXPORT void DLLAPI GetPosition(Handle h, Matrix &m);
DLLEXPORT void DLLAPI SetPosition(Handle h, Matrix &m);

// cause object to take damage
DLLEXPORT void DLLAPI Damage(Handle him, long amt);

// if (GetHealth(friend1) < 0.5f)
// Retreat(friend1, "retreat_path");
DLLEXPORT float DLLAPI GetHealth(Handle h);

DLLEXPORT long DLLAPI GetCurHealth(Handle h);
DLLEXPORT long DLLAPI GetMaxHealth(Handle h);
DLLEXPORT void DLLAPI SetCurHealth(Handle h, long NewHealth);
DLLEXPORT void DLLAPI SetMaxHealth(Handle h, long NewHealth);

DLLEXPORT void DLLAPI AddHealth(Handle h, long health);

DLLEXPORT float DLLAPI GetAmmo(Handle h);
DLLEXPORT void DLLAPI AddAmmo(Handle h, long ammo);

DLLEXPORT long DLLAPI GetCurAmmo(Handle h);
DLLEXPORT long DLLAPI GetMaxAmmo(Handle h);
DLLEXPORT void DLLAPI SetCurAmmo(Handle h, long NewAmmo);
DLLEXPORT void DLLAPI SetMaxAmmo(Handle h, long NewAmmo);

// get the team number of a unit
DLLEXPORT TeamNum DLLAPI GetTeamNum(Handle h);

// set the team number of a unit
DLLEXPORT void DLLAPI SetTeamNum(Handle h, TeamNum t);

DLLEXPORT void DLLAPI SetPosition(Handle h, Name path);
DLLEXPORT void DLLAPI SetVectorPosition(Handle h, Vector where);
DLLEXPORT void DLLAPI SetVelocity(Handle h, const Vector &vel);

DLLEXPORT void DLLAPI SetControls(Handle h, const VehicleControls &controls, unsigned long whichControls = -1);

DLLEXPORT Handle DLLAPI GetWhoShotMe(Handle h);
DLLEXPORT float DLLAPI GetLastEnemyShot(Handle h);
DLLEXPORT float DLLAPI GetLastFriendShot(Handle h);

DLLEXPORT void DLLAPI DefaultAllies(void);
DLLEXPORT void DLLAPI TeamplayAllies(void);
DLLEXPORT void DLLAPI Ally(TeamNum t1, TeamNum t2);
DLLEXPORT void DLLAPI UnAlly(TeamNum t1, TeamNum t2);
DLLEXPORT bool DLLAPI IsAlly(Handle me, Handle him);

DLLEXPORT int DLLAPI AudioMessage(const char *msg, bool purge = false);
DLLEXPORT bool DLLAPI IsAudioMessageDone(int msg);
DLLEXPORT void DLLAPI StopAudioMessage(int Msg);
DLLEXPORT void DLLAPI PreloadAudioMessage(const char *msg);
DLLEXPORT void DLLAPI PurgeAudioMessage(const char *msg);

DLLEXPORT void DLLAPI PreloadMusicMessage(const char *msg);
DLLEXPORT void DLLAPI PurgeMusicMessage(const char *msg);
DLLEXPORT void DLLAPI LoadJukeFile(char *msg);
DLLEXPORT void DLLAPI SetMusicIntensity(int intensity);

DLLEXPORT AiPath *DLLAPI FindAiPath(const Vector &start, const Vector &goal);
DLLEXPORT void DLLAPI FreeAiPath(AiPath *path);
DLLEXPORT void DLLAPI GetAiPaths(int &pathCount, char **&pathNames);

// SetPathType("patrol_path", LOOP_PATH);
DLLEXPORT void DLLAPI SetPathType(Name path, PathType pathType);

// int low = 0;
// int high = 1;
// SetIndependence(friend1, low);
DLLEXPORT void DLLAPI SetIndependence(Handle me, int independence);

DLLEXPORT bool DLLAPI IsInfo(Name odf);

// start the cockpit timer
DLLEXPORT void DLLAPI StartCockpitTimer(long time, long warn = LONG_MIN, long alert = LONG_MIN);

// start the cockpit timer
DLLEXPORT void DLLAPI StartCockpitTimerUp(long time, long warn = LONG_MAX, long alert = LONG_MAX);

// stop the cockpit timer
DLLEXPORT void DLLAPI StopCockpitTimer(void);

DLLEXPORT void DLLAPI HideCockpitTimer(void);

// get the cockpit timer
DLLEXPORT long DLLAPI GetCockpitTimer(void);

// start an earthquake
DLLEXPORT void DLLAPI StartEarthQuake(float magnitude);

// update an earthquake
DLLEXPORT void DLLAPI UpdateEarthQuake(float magnitude);

// stop an earthquake
DLLEXPORT void DLLAPI StopEarthQuake(void);

DLLEXPORT void DLLAPI ConvertHandles(Handle *h_array, int h_count);
DLLEXPORT bool DLLAPI Read(void *ptr, int bytesize);
DLLEXPORT bool DLLAPI Read(bool *b_array, int b_count);
DLLEXPORT bool DLLAPI Read(float *f_array, int f_count);
// DLLEXPORT bool Read(Handle *h_array, int h_count);
DLLEXPORT bool DLLAPI Read(int *i_array, int i_count);
DLLEXPORT bool DLLAPI Write(void *ptr, int bytesize);
DLLEXPORT bool DLLAPI Write(bool *b_array, int b_count);
DLLEXPORT bool DLLAPI Write(float *f_array, int f_count);
// DLLEXPORT bool Write(Handle *h_array, int h_count);
DLLEXPORT bool DLLAPI Write(int *i_array, int i_count);

DLLEXPORT bool DLLAPI IsPerson(Handle h);


DLLEXPORT int DLLAPI GetCurWorld(void);
DLLEXPORT const char * DLLAPI GetVarItemStr(char *VarItemName);
DLLEXPORT const int DLLAPI GetVarItemInt(char *VarItemName);

// Gets one of the client-settable variables, based on a player with
// the specified team #. Idx is the civar%d read in; see
// network\vars.txt for explanations/contents
DLLEXPORT const int DLLAPI GetCVarItemInt(int TeamNum,int Idx);
DLLEXPORT const char * DLLAPI GetCVarItemStr(int TeamNum,int Idx);

// Helps preload assets by letting the DLL say what ODFs
// (e.g. "avrecy") will be used, and be loaded before anything else
DLLEXPORT void DLLAPI PreloadODF(char *cfg);

// Get height of terrain at this location
DLLEXPORT float DLLAPI TerrainFindFloor(float x,float z);

// Adds in a pilot if needed to an object
DLLEXPORT void DLLAPI AddPilotByHandle(Handle h);

// Dumps a string to the console
DLLEXPORT void DLLAPI PrintConsoleMessage(char *msg);

DLLEXPORT float DLLAPI GetRandomFloat(float range);

DLLEXPORT bool DLLAPI IsDeployed(Handle h);
DLLEXPORT void DLLAPI Deploy(Handle h);
DLLEXPORT bool DLLAPI IsSelected(Handle h);

#define HP1_ON 1
#define HP2_ON 2
#define HP3_ON 4
#define HP4_ON 8
#define HP5_ON 16

DLLEXPORT void DLLAPI SetWeaponMask(Handle me, long mask);

DLLEXPORT void DLLAPI GiveWeapon(Handle me, Name weapon);

DLLEXPORT void DLLAPI FireAt(Handle me, Handle him = 0, bool doAim = false);

DLLEXPORT bool DLLAPI IsFollowing(Handle h);
DLLEXPORT Handle DLLAPI WhoFollowing(Handle h);

// set and get the user's target
DLLEXPORT void DLLAPI SetUserTarget(Handle h);

// set and get the user's target
DLLEXPORT Handle DLLAPI GetUserTarget(void);

// make somebody look like they are on a particular team
DLLEXPORT void DLLAPI SetPerceivedTeam(Handle h, TeamNum t);

// see what command a unit is working on
//
// AiCommand what = GetCurrentCommand(friend1);
// if (what == CMD_NONE)
// Attack(friend1, enemy1);
DLLEXPORT AiCommand DLLAPI GetCurrentCommand(Handle me);

// get the target of a units current command
DLLEXPORT Handle DLLAPI GetCurrentWho(Handle me);

// EjectPilot(friend1);
DLLEXPORT void DLLAPI EjectPilot(Handle h);

// make a pilot hop out
DLLEXPORT void DLLAPI HopOut(Handle h);

// what could this possibly do? [Warning-- calls DLL with sniped]
DLLEXPORT void DLLAPI KillPilot(Handle h);

// Removes a vehicle's AI process w/o exploding the pilot (i.e. DLL call)
DLLEXPORT void DLLAPI RemovePilotAI(Handle h);

// see which vehicle a pilot hopped out of
DLLEXPORT Handle DLLAPI HoppedOutOf(Handle h);

// Get the current position and heading of the camera
DLLEXPORT void DLLAPI GetCameraPosition(Vector &pos, Vector &dir);

// Set the current position and heading of the camera
DLLEXPORT void DLLAPI SetCameraPosition(const Vector &pos, const Vector &dir);

// maka camera current and prev positions equals 
DLLEXPORT void DLLAPI ResetCameraPosition();



// find the crc of a string
DLLEXPORT unsigned long DLLAPI CalcCRC(Name n);

// load an interface definition
DLLEXPORT void DLLAPI IFace_Exec(Name n);

// activate a control
DLLEXPORT void DLLAPI IFace_Activate(Name n);

// deactivate a control
DLLEXPORT void DLLAPI IFace_Deactivate(Name n);

// create a mission command
DLLEXPORT void DLLAPI IFace_CreateCommand(Name n);

// create a mission string variable
DLLEXPORT void DLLAPI IFace_CreateString(Name name, Name value);
DLLEXPORT void DLLAPI IFace_SetString(Name name, Name value);
DLLEXPORT void DLLAPI IFace_GetString(Name name, Name value, int maxSize);

// create a mission integer variable
DLLEXPORT void DLLAPI IFace_CreateInteger(Name name, int value);
DLLEXPORT void DLLAPI IFace_SetInteger(Name name, int value);
DLLEXPORT int DLLAPI IFace_GetInteger(Name name);

// set the range of a mission integer variable
DLLEXPORT void DLLAPI IFace_SetIntegerRange(Name name, int low, int high);

DLLEXPORT void DLLAPI IFace_CreateFloat(Name name, float value);
DLLEXPORT void DLLAPI IFace_SetFloat(Name name, float value);
DLLEXPORT float DLLAPI IFace_GetFloat(Name name);

DLLEXPORT void DLLAPI IFace_ClearListBox(Name name);
DLLEXPORT void DLLAPI IFace_AddTextItem(Name name, Name value);
DLLEXPORT void DLLAPI IFace_GetSelectedItem(Name name, Name value, int maxSize);


DLLEXPORT void DLLAPI SetSkill(Handle h,int s);

DLLEXPORT void DLLAPI SetPlan(char *cfg, int team = -1);

DLLEXPORT void DLLAPI LogFloat(float v);

DLLEXPORT int DLLAPI GetInstantMyForce(void);
DLLEXPORT int DLLAPI GetInstantCompForce(void);
DLLEXPORT int DLLAPI GetInstantDifficulty(void);
DLLEXPORT int DLLAPI GetInstantGoal(void);
DLLEXPORT int DLLAPI GetInstantType(void);
DLLEXPORT int DLLAPI GetInstantFlag(void);
DLLEXPORT int DLLAPI GetInstantMySide(void);

DLLEXPORT bool DLLAPI StoppedPlayback(void);

/*
CameraReady()
Gets the camera ready to be
used by CameraPath or CameraObject()
This function should only be called once at
the start of a camera sequence.
*/
DLLEXPORT bool DLLAPI CameraReady(void);

/*
CameraPath()
This tells the camera to follow the path Name
at a speed and height (in cm).
The camera will always point toward the target.
Returns true when the path is done.
*/
DLLEXPORT bool DLLAPI CameraPath(Name path_name,int height,int speed,Handle target_handle);

DLLEXPORT bool DLLAPI CameraPathDir(Name path_name,int height,int speed);

/*
PanDone()
Returns true on the frame that the
Camera has finished going down the path.
*/
DLLEXPORT bool DLLAPI PanDone(void);

/*
CameraObject()
This is a camera from the object pointing toward
the target.
i,j,k are the offset in centimeters.
*/
DLLEXPORT bool DLLAPI CameraObject(Handle object_handle,float i,float j,float k,Handle target_handle);

/*
CameraFinish()
Always call this once when you are done with the camera.
*/
DLLEXPORT bool DLLAPI CameraFinish(void);

/*
test to see if user cancelled the cineractive
*/
DLLEXPORT bool DLLAPI CameraCancelled(void);

DLLEXPORT bool DLLAPI FreeCamera(void);
DLLEXPORT bool DLLAPI FreeFinish(void);

DLLEXPORT bool DLLAPI PlayMovie(char name[20]);
DLLEXPORT void DLLAPI StopMovie(void);
DLLEXPORT bool DLLAPI PlayMove(void);
DLLEXPORT bool DLLAPI PlayRecording(char name[20]);
DLLEXPORT bool DLLAPI PlayRecording(char name[20], bool updateCam);
DLLEXPORT bool DLLAPI PlaybackVehicle(char name[20]);

// set the current animation (animType: 0 == loop, 1 == 2way)
// return max frames
DLLEXPORT float DLLAPI SetAnimation(Handle h, Name n, int animType = 0);
DLLEXPORT float DLLAPI GetAnimationFrame(Handle h, Name n);

// start the current animation for an object
DLLEXPORT void DLLAPI StartAnimation(Handle h);

// start/stop emitter effects
DLLEXPORT void DLLAPI MaskEmitter(Handle h, DWORD mask);
DLLEXPORT void DLLAPI StartEmitter(Handle h, int slot);
DLLEXPORT void DLLAPI StopEmitter(Handle h, int slot);

DLLEXPORT void DLLAPI SaveObjects(char *&buffer, unsigned long &size);
DLLEXPORT void DLLAPI LoadObjects(char *buffer, unsigned long size);
DLLEXPORT void DLLAPI IgnoreSync(bool on);
DLLEXPORT bool DLLAPI IsRecording(void);

DLLEXPORT void DLLAPI SetObjectiveOn(Handle h);
DLLEXPORT void DLLAPI SetObjectiveOff(Handle h);
DLLEXPORT void DLLAPI SetObjectiveName(Handle h, Name n);

// clear all objectives
DLLEXPORT void DLLAPI ClearObjectives(void);

// add an objective
DLLEXPORT void DLLAPI AddObjective(char *name, long color, float showTime = 8.0f);

DLLEXPORT bool DLLAPI IsWithin(Handle &h1, Handle &h2, Distance d);
DLLEXPORT int DLLAPI CountUnitsNearObject(Handle h, Distance d, TeamNum t, char *odf);

DLLEXPORT void DLLAPI SetAvoidType(Handle h, int avoidType);

// hit somebody to draw attention
DLLEXPORT void DLLAPI Annoy(Handle me, Handle him);

// don't let a unit apply thrust
DLLEXPORT void DLLAPI ClearThrust(Handle h);

// make a unit talkative even if scripted
DLLEXPORT void DLLAPI SetVerbose(Handle h, bool on);

DLLEXPORT void DLLAPI ClearIdleAnims(Handle h);
DLLEXPORT void DLLAPI AddIdleAnim(Handle h, Name anim);

DLLEXPORT bool DLLAPI IsIdle(Handle h);

DLLEXPORT void DLLAPI CountThreats(Handle h, int &here, int &coming);

DLLEXPORT void DLLAPI SpawnBirds(int group, int count, Name odf, TeamNum t, Name path);
DLLEXPORT void DLLAPI SpawnBirds(int group, int count, Name odf, TeamNum t, Handle startObj, Handle destObj);
DLLEXPORT void DLLAPI RemoveBirds(int group);

DLLEXPORT void DLLAPI SetColorFade(float ratio, float rate, unsigned long color);

DLLEXPORT void DLLAPI StopCheats(void);

DLLEXPORT void DLLAPI CalcCliffs(Handle h1, Handle h2, float radius);
DLLEXPORT void DLLAPI CalcCliffs(Name path);

DLLEXPORT int DLLAPI StartSoundEffect(const char *file, Handle h = 0);
DLLEXPORT int DLLAPI FindSoundEffect(const char *file, Handle h = 0);
DLLEXPORT void DLLAPI StopSoundEffect(int sound);


// base buildings
const int DLL_TEAM_SLOT_RECYCLER = 1;
const int DLL_TEAM_SLOT_FACTORY = 2;
const int DLL_TEAM_SLOT_ARMORY = 3;
const int DLL_TEAM_SLOT_TRAINING = 4;
const int DLL_TEAM_SLOT_BOMBERBAY = 5;

// Returns the handle of a given object based on team# and slot, as specified above
DLLEXPORT Handle DLLAPI GetObjectByTeamSlot(int TeamNum, int Slot);


// Translate a string via localize.odf
DLLEXPORT void DLLAPI TranslateString(Name Dst, Name Src);

// Functions to do various transcendental math functions in a way that
// they'll return bitwise-identical values across various CPU
// types. While these may not be needed for SP missions, for any
// multiplayer DLLs, this should be done instead of the regular
// compiler-provided functions to avoid sync errors. 
DLLEXPORT float DLLAPI portable_sin(const float ang);
DLLEXPORT float DLLAPI portable_cos(const float ang);
DLLEXPORT float DLLAPI portable_atan2(const float x,const float y);
DLLEXPORT float DLLAPI portable_asin(const float x);
DLLEXPORT float DLLAPI portable_acos(const float x);

// ----------------------- Multiplayer Functions -----------------------------

// Network status queries. 
DLLEXPORT bool DLLAPI IsNetworkOn(void);
DLLEXPORT bool DLLAPI ImServer(void); // Note: returns FALSE if network not on
DLLEXPORT bool DLLAPI ImDedicatedServer(void);
DLLEXPORT bool DLLAPI IsTeamplayOn(void);

// Returns the # of players actively playing the game.
DLLEXPORT int DLLAPI CountPlayers(void);

// Returns the handle of a local or remote player based on the team #
// passed in.
DLLEXPORT Handle DLLAPI GetPlayerHandle(int Team);

// Same as GetRace(Handle), but takes a team number instead
DLLEXPORT char DLLAPI GetRaceOfTeam(int TeamNum);

// Returns true if this is a local or remotely-controlled player
DLLEXPORT bool DLLAPI IsPlayer(Handle h);

// Returns the user's name for the given vehicle
DLLEXPORT const char * DLLAPI GetPlayerName(Handle h);

// Returns the teamgroup (0..MAX_MULTIPLAYER_TEAMS) for a given team,
// or an illegal value (0xA5A5A5A5) if the team doesn't fit on any
// normal group
DLLEXPORT int DLLAPI WhichTeamGroup(int Team);

// Returns how many allies this team has that are playing. The count
// does NOT include the specified team. I.e. in non-teamplay, this
// will return 0
DLLEXPORT int DLLAPI CountAllies(int Team);

// In teamplay, returns the commander's team # for whatever teamgroup
// the specified Team is. In non-teamplay, simply returns Team back--
// everyone is their own commander
DLLEXPORT int DLLAPI GetCommanderTeam(int Team);

// Returns the ranges (inclusive) of team #s allied with a specified
// team.  Note: these teams may have no players on them; check if
// GetPlayerHandle(x) returns anything to see if the team # is
// actually in use
DLLEXPORT int DLLAPI GetFirstAlliedTeam(int Team);
DLLEXPORT int DLLAPI GetLastAlliedTeam(int Team);

// Alternat to above -- qeries the game for the teamplay team # ranges
// based on which team-group (0,1) is asked
DLLEXPORT void DLLAPI GetTeamplayRanges(int WhichTeam,int &DefenseTeamNum,int &OffenseMinTeamNum,int &OffenseMaxTeamNum);

// Sets the specified craft to a random angle (in 2D-only). Normally,
// craft are always built facing due north; this spices things up.
DLLEXPORT void DLLAPI SetRandomHeadingAngle(Handle h);

// Teamcolor functions-- talk to Ken about these.
DLLEXPORT void DLLAPI ClearTeamColors(void); 
DLLEXPORT void DLLAPI DefaultTeamColors(void);
DLLEXPORT void DLLAPI TeamplayTeamColors(void);

DLLEXPORT void DLLAPI SetTeamColor(int team, int red, int green, int blue);
DLLEXPORT void DLLAPI ClearTeamColor(int team);



// Sets the specified craft to be invisible, uncollidable, w/o
// weapons, etc. Used for a dedicated server's fake-vehicle.
DLLEXPORT void DLLAPI MakeInert(Handle h);

// Returns a position 'near' Pos, in the ring between MinRadiusAway
// and MaxRadiusAway, and with roughly the same terrain height as the
// terrain at the original position. This is used to place allies near
// their starting point, and randomize respawns near a location so
// it's harder to multi-kill by firing at a fixed location
DLLEXPORT Vector DLLAPI GetPositionNear(Vector Pos, const float MinRadiusAway, const float MaxRadiusAway);

// Given a Team number, returs the ODF appropriate to the race for
// this ODF. Warning: this returns a temp string, please do NOT cache
// this pointer or assume its contents will be unmodified if you call
// it twice in a row. The RandomizeType is specified below:
enum RandomizeType {
	Randomize_None, // Don't modify what they selected in the shell.
	Randomize_ByRace,
	Randomize_Any,
};
DLLEXPORT char * DLLAPI GetPlayerODF(int TeamNum, RandomizeType RType=Randomize_None);

// Builds an unpiloted new craft 'near' a handle, with a given team. 
DLLEXPORT Handle DLLAPI BuildEmptyCraftNear(Handle h, char *ODF, int Team, float MinRadiusAway, float MaxRadiusAway);

// Function to have the game calculate a new position around a central
// point-- this allows us to use the portable_sin and portable_cos
// functions to get around an inconsistent FPU. The y-posn is the
// terrain at that location
DLLEXPORT void DLLAPI SetCircularPos(const Vector &CenterPos, const float Radius, const float Angle, Vector &NewPos);


// Get safest, closest spawnpoint or next closest spawnpoint to a
// given position. Location is filled with a null vector (0,0,0) if no
// spawnpoints available
DLLEXPORT Vector DLLAPI GetSafestSpawnpoint(void);
// Returns the first spawnpoint found with the specified team #. If
// no team# found, returns same as randomsafest
DLLEXPORT Vector DLLAPI GetSpawnpoint(int TeamNum);
DLLEXPORT Handle DLLAPI GetSpawnpointHandle(int TeamNum);

// Returns a random spawnpoint that 'looks' safe. [Nobody within 100 meters]
DLLEXPORT Vector DLLAPI GetRandomSpawnpoint(int TeamNum = -1);

// Sets the message in the timer box (e.g. "Time Left: 03:14") to the
// specified string
DLLEXPORT void DLLAPI SetTimerBox(const char *message);

// Prints the specified string to the messages box (where chat
// messages, etc go)
DLLEXPORT void DLLAPI AddToMessagesBox(const char *message);

// The Get* functions return 0 if an invalid handle is passed in; the
// Set* functions do nothing if an invalide handle is passed in. [A

// A handle is invalid if it doesn't point to a valid object, or it
// points to an object on a team that has no human players.]
DLLEXPORT int DLLAPI GetDeaths(Handle h);
DLLEXPORT int DLLAPI GetKills(Handle h);
DLLEXPORT int DLLAPI GetScore(Handle h);
DLLEXPORT void DLLAPI SetDeaths(Handle h, const int NewValue);
DLLEXPORT void DLLAPI SetKills(Handle h, const int NewValue);
DLLEXPORT void DLLAPI SetScore(Handle h, const int NewValue);

// Alternate functions that add a specified amount to the score
DLLEXPORT void DLLAPI AddDeaths(Handle h, const int DeltaValue);
DLLEXPORT void DLLAPI AddKills(Handle h, const int DeltaValue);
DLLEXPORT void DLLAPI AddScore(Handle h, const int DeltaValue);


// Set an Handle'd object as a local or remote user, depending on what
// team they're on. This must be called after building a new craft on
// entry or respawn
DLLEXPORT void DLLAPI SetAsUser(Handle h, int Team);


// Set or clear an object's flags
DLLEXPORT void DLLAPI SetNoScrapFlagByHandle(Handle h);
DLLEXPORT void DLLAPI ClearNoScrapFlagByHandle(Handle h);

// See comment in NetMgr.h
DLLEXPORT int DLLAPI GetLocalPlayerTeamNumber(void);
DLLEXPORT DPID DLLAPI GetLocalPlayerDPID(void);

DLLEXPORT void DLLAPI FlagSteal(Handle flag, Handle holder);
DLLEXPORT void DLLAPI FlagRecover(Handle flag, Handle holder);
DLLEXPORT void DLLAPI FlagScore(Handle flag, Handle holder);
DLLEXPORT void DLLAPI MoneyScore(int amount, Handle bagman);

// Tells the NetManager to put up the 'Timelimit' end of game screen
DLLEXPORT void DLLAPI NoteGameoverByTimelimit(void);
// Tells the NetManager to put up the 'Game Ended - %s hit killlimit' end of game screen
DLLEXPORT void DLLAPI NoteGameoverByKillLimit(Handle h);
// Tells the NetManager to put up the 'Game Ended - %s won' end of game screen
DLLEXPORT void DLLAPI NoteGameoverByScore(Handle h);
// Tells the NetManager to put up the 'Game Ended - %s destroyed enemy bases' end of game screen
DLLEXPORT void DLLAPI NoteGameoverByLastWithBase(Handle h);
// Tells the NetManager to put up the 'Game Ended - Team %s destroyed
// enemy bases' end of game screen. Teamgroup is 0..MAX_MULTIPLAYER_TEAMS
DLLEXPORT void DLLAPI NoteGameoverByLastTeamWithBase(int Teamgroup);
// Tells the NetManager to put up the 'Game Ended - no bases' end of game screen
DLLEXPORT void DLLAPI NoteGameoverByNoBases(void);

// Finishes the current game in x SecondsFromNow. Should be called
// after one of the NoteGameoverBy*() functions that'll put up the
// appropriate post-game info. This is used in MP games so that only
// the server quits, and that pulls everyone else back to the shell
DLLEXPORT void DLLAPI DoGameover(float SecondsFromNow);


// In Teamplay, this is a reporting by the DLL that a teamgroup (0,1)
// has built a recycler (or otherwise locked in a race) of the given
// race ('i' or 'f')
DLLEXPORT void DLLAPI SetMPTeamRace(int WhichTeamGroup, char RaceIdentifier);

#endif


