#include "MW4Headers.hpp"

#include "ShellFunctionHeaders.hpp"

#include "MW4Shell.hpp"
#include "MW4Headers.hpp"
#include "MWApplication.hpp"
#include "Salvage.hpp"
#include "NetParams.h"
#include "GameTypes.h"
#include "MechLabHeaders.h"
#include "MechLab.hpp"
#include "CampaignMechLab.hpp"
#include "MWApplication.hpp"
#include "MWMission.hpp"
#include "MWCampaign.hpp"
#include "MWGame.hpp"
#include "lancemate.hpp"
#include "MWTable.hpp"
#include "MWOptions.hpp"
#if !defined(NO_MR)
#include "review_playback.hpp"
#endif // !defined(NO_MR)
#include "HeatManager.hpp"

// MSL 5.06
#include "Weapon.hpp"

#include <Adept\NetStatCollector.hpp>
#include <Adept\EntityManager.hpp>
#include <Adept\Network.hpp>
#include <Adept\Application.hpp>
#include <Adept\audiorenderer.hpp>

#include <Stuff\NotationFile.hpp>
#include <direct.h>
#include <gosScript\gosScriptHeaders.hpp>
#include <gameOS\ToolOS.hpp>
#include <gameOS\Network.hpp>
#include <gameOS\GunGameList.h>
// jcem
#include <Adept\AudioCommand.hpp>
// end

#include <mbstring.h>
#include "missionlang\resource.h"
#include "..\ScriptStrings\resource.h" // scriptstrings.h - jcem

#include <MLR\MLRTexturePool.hpp>

// ngLog addition
#if !defined(NO_LOG)
#include "nglog_mw4.hpp"
#endif // !defined(NO_LOG)

#include "..\buildnum\buildnum.h"

#include "mechspecs.cpp"

// MSL 5.03 Mechview
void __stdcall CTCL_AfterBeginScene();
void __stdcall CTCL_UpdateMechView();

extern void (__stdcall *g_pfnCTCL_AfterBeginScene)();
#define MECHVIEW_GAP_TOP 20 // MechView Param - gap between top screen and mech-name-text
#define MECHVIEW_GAP_X 30 // MechView Param - left/right margin in radar(480 * 640) screen
#define MECHVIEW_GAP_Y 30 // MechView Param
#define MECHVIEW_GAP_ABOVE_MECH 20 // MechView Param - gap between mech-name-text & mech-image
#define MECHVIEW_GAP_UNDER_MECH 15 // MechView Param - gap between mech-image & text information
#define MECHVIEW_GAP_TEXTS 3 // MechView Param - gap between text information
//#define MECHVIEW_TIMETICKS 100 // MechView Param - time to display 1 still image - in msecs 
#define MECHVIEW_TIMETICKS 90 // MechView Param - time to display 1 still image - in msecs 

DWORD g_dwLastMechView = 0;
CMLCallData g_MLCallData;
////// MechView

// MSL 5.06
#define SHELLSCRIPTS_PATH "Content\\ShellScripts\\"

extern int __stdcall Mech4ReconnectGame();
void _stdcall CTCL_SetMissionParamsBy(void* pNMP, int nSize);

#define SCRIPTCALLBACK(func) int __stdcall func( void * instance, int args, void * arg[])

// jcem - start
#include <windows.h>
#include <WinBase.h>
#include <stdio.h>
#include <io.h>

#include <ddraw.h>
#include <d3d.h>

#include <GameOS\render.hpp>

#include "ctcls.h"
#include "ctcl.h"
#include "recscore.h" // jcem
#include "logreport.h"

extern char AssetsDirectory1[MAX_PATH];
typedef unsigned char* POINTER;
#include "logreport.cpp"

extern bool hsh_initialized;
// MSL 5.03 Mechview
extern int g_nMechViewType; // 0 - no mechview, 1 - on radar screen, 2 - on main screen
extern int g_nMR;
extern int g_nCoinCount;
extern int g_nCoinCountTemp;
extern int g_nCoinPerGame;
extern bool g_bUseCam;
extern bool g_bOldLOG;
extern char g_szTeslaInviter[128];

void _stdcall CTCL_SaveLogFileInfo(SYSTEMTIME& SysTime, const GUID& guid, char szPath[MAX_PATH], char szGUID[64]);
void _stdcall CTCL_SaveLogGameEnd(const SYSTEMTIME& SysTime, const GUID& guid, const char* pcszHost);
BOOL _stdcall CTCL_SaveLog(int nState, const NetMissionParameters::MWNetMissionParameters* params = NULL);

extern SCRIPTCALLBACK(CTCL_GetType);
extern SCRIPTCALLBACK(CTCL_IsConsole);
extern SCRIPTCALLBACK(CTCL_IsConsoleX);
extern SCRIPTCALLBACK(CTCL_Get);
extern SCRIPTCALLBACK(CTCL_Set);
extern SCRIPTCALLBACK(CTCL_SetCDSP);
extern SCRIPTCALLBACK(CTCL_GetTeamParams);
extern SCRIPTCALLBACK(CTCL_IsValidName);
extern SCRIPTCALLBACK(CTCL_DoMission);
extern SCRIPTCALLBACK(CTCL_AddPlayer);
extern SCRIPTCALLBACK(CTCL_GetMissionState);
extern SCRIPTCALLBACK(CTCL_DoBreak);
extern SCRIPTCALLBACK(CTCL_IsGameLoaded);
extern SCRIPTCALLBACK(CTCL_DoReprint);
extern SCRIPTCALLBACK(CTCL_CheckPlayMovie);
extern SCRIPTCALLBACK(CTCL_CheckCoinCounts);
extern SCRIPTCALLBACK(CTCL_CheckUseJPD);
extern SCRIPTCALLBACK(CTCL_GetPlayerName);
extern SCRIPTCALLBACK(CTCL_SetPlayerName);
extern SCRIPTCALLBACK(CTCL_CheckCOOP);
extern SCRIPTCALLBACK(CTCL_StartCOOP);
extern SCRIPTCALLBACK(CTCL_PosCOOP);
extern SCRIPTCALLBACK(CTCL_GetJoyInfo);
extern SCRIPTCALLBACK(CTCL_CheckCampaign);
extern SCRIPTCALLBACK(CTCL_SetDispStateCOOP);
extern SCRIPTCALLBACK(CTCL_CheckInviteCOOP);
extern SCRIPTCALLBACK(CTCL_DoInviteCOOP);
extern SCRIPTCALLBACK(CTCL_Inviter);
extern SCRIPTCALLBACK(TBL_GetResNames);
extern SCRIPTCALLBACK(CTCL_GetIncNums);
extern SCRIPTCALLBACK(CTCL_MiscFile);
extern SCRIPTCALLBACK(CTCL_GetACP);
extern SCRIPTCALLBACK(CTCL_IsBotAllowed);
// MSL 5.03 Mechview
extern SCRIPTCALLBACK(CTCL_MechViewOnMainScreen);

int g_nWhyPaused = 0; // 0: not paused - invitation in menu-state, 1: briefing, 2: score-sheet, 3: continue, 4: invited in single-game, 5: high-score(game-over?), 6: by ESC(for testing only)...
extern SCRIPTCALLBACK(CTCL_WhyPaused);
int g_nTimeList_Index = 3; // 3rd item in listbox...
int g_nTimeList_Value = 7; // 7 minutes
// MSL 5.06
int g_nMechVariant = 0; 
int g_nMechLabOp = 0;
int g_nMechPodNum = 0;
int g_nBlackMech = 0;

void CTCL_CheckMech(SPlayerInfo& PI);

Time g_fLastGameStart = 0.0;

ResourceID g_CameraResID;
const char g_szCameraShip[] = "Camera Ship";
int g_naTeamSkins[16 + 1] = { 0, 1, 2, 3, 4, 5, 6, 7, 15, 19, 26, 23, 28, 30, 36, 37, 0 };
// MSL 5.02 Set Decals Here
int g_naTeamDecals[16 + 1] = { 3, 4, 2, 5, 6, 9, 50, 10, 11, 12, 16, 20, 21, 22, 24, 27, 0 };
int g_naFFADecals[37] = { 3, 4, 2, 5, 6, 9, 50, 10, 11, 12, 16, 20, 21, 22, 24, 27, 0, };
const char g_caCamoPrefixes[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0";

// Mech Datas
char** g_ppMech;
int* g_pStockIds;

void CTCL_API CTCL_InitMechDatas();
void CTCL_API CTCL_ClearMechDatas();
extern bool g_bCOOP; // COin OPeration
void AssignShellString(void* data[], int nIdx, const char* pcsz);
void AssignShellString(char** ppShellString, const char* pcsz);

void AssignShellString(void* data[], int nIdx, const char* pcsz)
{
    AssignShellString(&STRPARM(nIdx), pcsz);
}

void AssignShellString(char** ppShellString, const char* pcsz)
{
	FREEANDNULL(*ppShellString);

    if (!pcsz) {
        pcsz = "";
    }

    int nLen = strlen(pcsz) + 1;
	*ppShellString = (char *)gos_Malloc(nLen);
	memcpy(*ppShellString, pcsz, nLen);
}

class MiscFileEntry: public Stuff::Plug
{
private:
	Stuff::MString m_FileName;
public:
	MiscFileEntry(const char* pcszFileName);
	Stuff::MString GetFileName() {Check_Object(this); return m_FileName;}
};

class MiscFileTable: public Stuff::Plug
{
public:
	typedef Stuff::SortedChainIteratorOf<MiscFileEntry*, Stuff::MString> TableIterator;
public:
    MString m_PathFormat;
    int m_nMaxFiles;
    MString m_UseDir;
    int m_nCurIndex;
public:
	MiscFileTable(const char* pcszPathFormat, int nMaxFiles = 0, const char* pcszUseDir = NULL);
	~MiscFileTable();
    void DoReadList();
	TableIterator* MakeTableIterator() {Check_Object(this); return new TableIterator(&m_table);}
	int GetTableSize() {Check_Object(this); return m_table.GetSize();}
    MiscFileEntry* GetNthItem(int num) { Check_Object(this); return m_table.GetNth(num); }
private:
	Stuff::SortedChainOf<MiscFileEntry *, Stuff::MString> m_table;
};

MiscFileEntry::MiscFileEntry(const char* pcszFileName)
    : Plug(Plug::DefaultData), m_FileName(pcszFileName)
{
}

MiscFileTable::MiscFileTable(const char* pcszPathFormat, int nMaxFiles/* = 0*/, const char* pcszUseDir/* = NULL*/)
    : Plug(Plug::DefaultData), m_table(NULL, true),
    m_PathFormat(pcszPathFormat), m_nMaxFiles(nMaxFiles), m_UseDir(pcszUseDir), m_nCurIndex(0)
{
}

MiscFileTable::~MiscFileTable()
{
}

void MiscFileTable::DoReadList()
{
    MString strDir(m_PathFormat);
    strDir.IsolateDirectory();
    const char* pcszDir = (0 < m_UseDir.GetLength()) ? m_UseDir: strDir;

	Stuff::Directory resource_directory(m_PathFormat, true);

	const char *file_name;
	int nCount = 0;
	while(((file_name = resource_directory.GetCurrentFileName()) != NULL) && ((m_nMaxFiles <= 0) || (nCount < m_nMaxFiles)))
	{
		MString FileName(pcszDir);

        FileName += file_name;

        MiscFileEntry& MFE = *new MiscFileEntry(FileName);
        m_table.AddValue(&MFE, MFE.GetFileName());
        nCount++;

		resource_directory.AdvanceCurrentFile();
	}
}

MiscFileTable* m_aMiscFileTables[3] =
{
    NULL, NULL, NULL
};

HGOSAUDIO g_MusicSound4COOP = NULL;
// jcem - end


//========================================================================
// multiplayer options screen stuff
//========================================================================
#define FREE_PTR(ptr) if ((void *)ptr) { gos_Free((void *)ptr); (ptr)=NULL; }
extern SCRIPTCALLBACK(EnterMultiplayerOptionsScreen);
extern SCRIPTCALLBACK(LeaveMultiplayerOptionsScreen);
extern const char OPTIONS_INI[];
extern const char OPTIONS_SECTION[];
extern const char OPTIONS_SERVER_SECTION[];
extern const char OPTION_PLAYERNAME[];
extern const char OPTION_TEAMNAME[];
extern const char OPTION_PASSWORD[];
extern const char OPTION_USEPASSWORD[];
extern const char OPTION_PLAYERICON[];
extern const char OPTION_TEAMICON[];
extern const char OPTION_CONNECTIONNAME[];
extern const char OPTION_ALLOWDECALTRANSFER[];
extern const char OPTION_DEFAULTSERVERNAME[];
const char OPTIONS_INI[]				= "options.ini";
const char OPTIONS_SECTION[]			= "Network Options";
const char OPTIONS_SERVER_SECTION[]		= "Server";
const char OPTION_PLAYERNAME[]			= "PlayerName";
const char OPTION_TEAMNAME[]			= "TeamName";
const char OPTION_PASSWORD[]			= "Password";
const char OPTION_USEPASSWORD[]			= "UsePassword";
const char OPTION_PLAYERICON[]			= "PlayerIcon";
const char OPTION_TEAMICON[]			= "TeamIcon";
const char OPTION_CONNECTIONNAME[]		= "DefaultConnection";
const char OPTION_ALLOWDECALTRANSFER[]	= "AllowDecalTransfer";
const char OPTION_DEFAULTSERVERNAME[]	= "DefaultServerName";
//========================================================================
// end multiplayer options screen stuff
//========================================================================


int		MW4Shell::numMechPrototypes = 0;
int		MW4Shell::numMissions = 0;
char**	MW4Shell::mechPrototypeNames = NULL;
char**	MW4Shell::mechPrototypeFilenames = NULL;
char**	MW4Shell::missionNames = NULL;
char**	MW4Shell::missionFilenames = NULL;

int		MW4Shell::vehicleID = -1;
int		MW4Shell::missionID = -1;


int MW4Shell::ServerScale = 1024;
int MW4Shell::ClientScale = 1024;
double  MW4Shell::TimeToLowerServerScale = 0;
double  MW4Shell::TimeToLowerClientScale = 0;
namespace ABL
{
	extern bool g_MissionMusic;
    extern int GetEnemyTyps(int id_group, char** ppNames, int* pnCounts, int nMask);
}

int _stdcall ImeCallback(void *, int, void *data[])
{
	int nCallId	= VALUEPARM(0);

	switch(nCallId)
	{
	case 0:	// Check if IME is enabled
		extern DWORD g_bDisableImeCompletely;
		return g_bDisableImeCompletely ? 0 : 1;
	case 1: // Call gos_SetIME
		gos_SetIMEInsertMode(INTPARM(1) ? true : false);
		return 0;
	case 2:
		return (int)gos_GetMachineInformation(gos_Info_GetIMECaretStatus);
	};
	return 0;
}

// used for call to gos_NetSetAdvertItem
//const char MAP_NAME_KEY[] = "Map Type"; // map name
//const char GAME_TYPE_KEY[] = "Game Type"; // game type name (i.e. ctf,koth,stb)

MW4Shell
	*MW4Shell::Instance = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MW4Shell::MW4Shell():
	mechPrototypeList(NULL),
	alphaMechNames(NULL, true)
{
	if (!MWApplication::GetInstance()->Win32DedicatedServer)
		gosScript_InitializeProcessor();

	gos_PushCurrentHeap(MechWarrior4::Heap);

    m_dwShellResources = gos_OpenResourceDLL("ScriptStrings.dll"); // jcem...

	m_iaMissionName = (char *)gos_Malloc(256);
	Str_Copy(m_iaMissionName, "No Mission Selected", 256);

	m_endMovieName = (char *)gos_Malloc(256);
	Str_Copy(m_endMovieName, "", 256);

	m_LastMechName = (char *)gos_Malloc(256);
	Str_Copy(m_LastMechName, "",256);
	m_lastMechIndex = 0;


	m_iaMissionCount = 0;
	m_mechCount = 0;
	m_listBoxSize = 60;

	m_didSetMPMech = false;

	shellCommand = MW4Shell::NoShellCommand;
	currentShellRunning = MW4Shell::NoShellRunning;

	missionID = -1;
	vehicleID = -1;
	missionNum = 0;

	ia_gameType = IA_MISSIONSELECTION;
	
	LoadMechPrototypes();
	LoadMissions();

	StartUp();

	alphaMechNamesWithMCSorted = NULL;

	m_doesHaveLoadGame = false;
	firstRun = true;
	loadingScript = NULL;
	statScript = NULL;
	netServerScript = NULL;
	netClientScript = NULL;
	netScoreScript = NULL;
	netMissionReviewScript = NULL;
	m_optionsFile = NULL;
	m_optionsObject = NULL;

	m_mapInfo = NULL;
	m_mapAuthor = NULL;
	m_mapLink = NULL;
	m_mapLinkAvailable = 0;

	m_skinPrefix = DefaultSkinPrefix;
	m_teamDecal = "\0";
	m_pilotDecal = "\0";

	m_currentChatCount = 0;
	m_maxChatCount = 25;
	m_outgoingChat = NULL;
	m_outgoingChatToPlayerCount = 0;


    m_gameTypeStr = NULL;

	m_chatArray = new char*[50];
	m_chatFrom = new char*[50];

	for (int i = 0; i < 50; ++i)
	{
		m_chatArray[i] = NULL;
		m_chatFrom[i] = NULL;
	}


	m_scoreNames = new char*[32];
	for (i = 0; i < 32; ++i)
	{
		m_scoreNames[i] = NULL;
		m_scoreScores[i] = 0;
		m_scoreKills[i] = 0;
		m_scoreDeaths[i] = 0;
        m_scorePlyrs[i] = 0;
	}
	for (i = 0; i < 8; ++i)
	{
		m_scoreTeamCounts[i] = 0;
		m_scoreTeamScores[i] = 0;
		m_scoreTeamKills[i] = 0;
		m_scoreTeamDeaths[i] = 0;
	}
	m_scoreRuleType = 0;
	m_scoreMapName = new char[256];
	m_scoreTeamAllowed = 0;
	m_scoreCount = 0;
    m_scorePlyrIndex = -1;

	m_serverName = new char[256];
	m_serverIP = new char[256];
	m_serverCPU = new char[256];

	pauseScript = NULL;
	pauseOptionsScript = NULL;

	m_mechIDs = NULL;
	m_stockMechIDs = NULL;
	gos_PopCurrentHeap();

	networkScenarioCount = 0;
	maxNetworkScenarioCount = 0;
	selectedScenario = -1;
	currentCycleNumber = 0;

	for (i = 0; i < 256; ++i)
	{
		scenarios[i].missionName[0] = '\0';
		scenarios[i].longMissionName[0] = '\0';
		scenarios[i].scenarioName[0] = '\0';
		scenarios[i].scenarioTag[0] = '\0';
		scenarios[i].usermissions = false;

		cycleList[i].missionName[0] = '\0';
		cycleList[i].longMissionName[0] = '\0';
		cycleList[i].scenarioName[0] = '\0';
		cycleList[i].scenarioTag[0] = '\0';
		cycleList[i].usermissions = false;
		cycleList[i].ruleType = -1;
		
	}

	lastRuleType = -1;

	InitMovieList();

    {for(int kk = 0; kk < sizeof(m_aMiscFileTables) / sizeof(m_aMiscFileTables[0]); kk++)
    {
        MiscFileTable*& pp = m_aMiscFileTables[kk];
        gosASSERT(pp == NULL);
        const char* pcszPathFormat = NULL;
        const char* pcszUseDir = NULL;
        switch(kk)
        {
        case 0:
            pcszPathFormat = "hsh\\coop\\movies\\*.avi";
            break;
        case 1:
            pcszPathFormat = "hsh\\coop\\musics\\*.wav";
            break;
        case 2:
            pcszPathFormat = "hsh\\coop\\gmusics\\*.wav";
            pcszUseDir = "content\\audio\\music\\";
            break;
        }
        MiscFileTable& tbl = *new MiscFileTable(pcszPathFormat, 0, pcszUseDir);
        tbl.DoReadList();

        pp = &tbl;
    }}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

MW4Shell::~MW4Shell()
{
    {for(int kk = 0; kk < sizeof(m_aMiscFileTables) / sizeof(m_aMiscFileTables[0]); kk++)
    {
        MiscFileTable*& pp = m_aMiscFileTables[kk];
        if (pp) {
            delete pp;
            pp = NULL;
        }
    }}

    CTCL_ClearMechDatas(); // jcem

	gos_Free(m_iaMissionName);
	gos_Free(m_endMovieName);
	gos_Free(m_LastMechName);

	for (int i = 0; i < 50; i++)
	{
		if (m_chatArray[i] != NULL)
			delete m_chatArray[i];

		if (m_chatFrom != NULL)
			delete m_chatFrom[i];
	}


	delete[] m_chatArray;
	delete[] m_chatFrom;


	for (i = 0; i < 32; i++)
	{
		if (m_scoreNames[i] != NULL)
			delete [] m_scoreNames[i];
	}

	delete[] m_scoreNames;
	delete[] m_scoreMapName;
	m_scoreCount = 0;
    m_scorePlyrIndex = -1;
	m_scoreTeamAllowed = 0;

	delete[] m_serverName;
	delete[] m_serverIP;
	delete[] m_serverCPU;

	for (i = 0; i < numMechPrototypes; i++)
		delete [] mechPrototypeNames[i];

	delete [] mechPrototypeNames;

	for (i = 0; i < numMechPrototypes; i++)
		delete [] mechPrototypeFilenames[i];

	delete [] mechPrototypeFilenames;

	for (i = 0; i < numMissions; i++)
		delete [] missionNames[i];

	delete [] missionNames;

	for (i = 0; i < numMissions; i++)
		delete [] missionFilenames[i];

	delete [] missionFilenames;

	ChainIteratorOf<MechPrototype*> prototypes(&mechPrototypeList);
	prototypes.DeletePlugs();

	ShutDown();

	if(MechLab::Instance)
	{
		delete MechLab::Instance;
		MechLab::Instance = NULL;
	}
	if(m_mechIDs)
	{
		gos_Free(m_mechIDs);
	}
	if(m_stockMechIDs)
	{
		gos_Free(m_stockMechIDs);
	}

	if (m_mapInfo)
	{
		delete m_mapInfo;
		m_mapInfo = NULL;
	}


	if (m_mapAuthor)
	{
		delete m_mapAuthor;
		m_mapAuthor = NULL;
	}

	if (m_mapLink)
	{
		delete m_mapLink;
		m_mapLink = NULL;
	}
	m_mapLinkAvailable = 0;
	ResetMovieList();

	if(m_optionsObject)
		delete m_optionsObject;
	if(m_optionsFile)
		delete m_optionsFile;
	
	alphaMechNames.DeletePlugs();
	if (alphaMechNamesWithMCSorted)
		delete [] alphaMechNamesWithMCSorted;

	if (!MWApplication::GetInstance()->Win32DedicatedServer)
		gosScript_ShutdownProcessor();
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::EndAllScripts()
{
	gosScript_EndAllScripts();

	loadingScript = NULL;
	pauseScript = NULL;
	pauseOptionsScript = NULL;
	statScript = NULL;
	
	netServerScript = NULL;
	netClientScript = NULL;
	netScoreScript = NULL;
	netMissionReviewScript = NULL;

	currentShellRunning = MW4Shell::NoShellRunning;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartUp()
{

	m_moviePlaying = 0;
	m_moviesStopped = 0;
	if (MWApplication::GetInstance()->Win32DedicatedServer)
		return;

// jcem - start
    gosScript_RegisterCallback("CTCL_GetType",&CTCL_GetType,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_IsConsole",&CTCL_IsConsole,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_IsConsoleX",&CTCL_IsConsoleX,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_Get",&CTCL_Get,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_Set",&CTCL_Set,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_SetCDSP",&CTCL_SetCDSP,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_GetTeamParams",&CTCL_GetTeamParams,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_IsValidName",&CTCL_IsValidName,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_DoMission",&CTCL_DoMission,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_AddPlayer",&CTCL_AddPlayer,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_GetMissionState",&CTCL_GetMissionState,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_DoBreak",&CTCL_DoBreak,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_IsGameLoaded",&CTCL_IsGameLoaded,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_DoReprint",&CTCL_DoReprint,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_CheckPlayMovie",&CTCL_CheckPlayMovie,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_CheckCoinCounts",&CTCL_CheckCoinCounts,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_CheckUseJPD",&CTCL_CheckUseJPD,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_GetPlayerName",&CTCL_GetPlayerName,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_SetPlayerName",&CTCL_SetPlayerName,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_CheckCOOP",&CTCL_CheckCOOP,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_StartCOOP",&CTCL_StartCOOP,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_PosCOOP",&CTCL_PosCOOP,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_GetJoyInfo",&CTCL_GetJoyInfo,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_CheckCampaign",&CTCL_CheckCampaign,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_SetDispStateCOOP",&CTCL_SetDispStateCOOP,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_CheckInviteCOOP",&CTCL_CheckInviteCOOP,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_DoInviteCOOP",&CTCL_DoInviteCOOP,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_Inviter",&CTCL_Inviter,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("TBL_GetResNames",&TBL_GetResNames,GOSVAR_INT,0,NULL);
// MSL 5.03 Mechview
    gosScript_RegisterCallback("CTCL_GetIncNums",&CTCL_GetIncNums,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_MiscFile",&CTCL_MiscFile,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_GetACP",&CTCL_GetACP,GOSVAR_INT,0,NULL);
    gosScript_RegisterCallback("CTCL_IsBotAllowed",&CTCL_IsBotAllowed,GOSVAR_INT,0,NULL);

    gosScript_RegisterCallback("CTCL_MechViewOnMainScreen",&CTCL_MechViewOnMainScreen,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CTCL_WhyPaused",&CTCL_WhyPaused,GOSVAR_INT,0,NULL);
	gosScript_RegisterVariable("g_nTimeList_Index", &g_nTimeList_Index, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("g_nTimeList_Value", &g_nTimeList_Value, GOSVAR_INT, 0, NULL);
// MSL 5.06
	gosScript_RegisterVariable("g_nMechVariant", &g_nMechVariant, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("g_nMechLabOp", &g_nMechLabOp, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("g_nMechPodNum", &g_nMechPodNum, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("g_nBlackMech", &g_nBlackMech, GOSVAR_INT, 0, NULL);
// jcem - end

	gosScript_RegisterVariable("m_moviePlaying", &m_moviePlaying, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("m_moviesStopped", &m_moviesStopped, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("m_listBoxSize", &m_listBoxSize, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("DemoMode", &MWApplication::DemoMode, GOSVAR_INT, 0, NULL);
	

	gosScript_RegisterCallback("SetNetworkMissionParamater",&SetNetworkMissionParamater,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetLocalNetworkMissionParamater",&GetLocalNetworkMissionParamater,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetServerNetworkMissionParamater",&GetServerNetworkMissionParamater,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("NetConnectedToServer",&NetConnectedToServer,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("NetClientVehicleAccepted",&NetClientVehicleAccepted,GOSVAR_INT,0,NULL);

	gosScript_RegisterCallback("GetVehicleRejectionReason",&GetVehicleRejectionReason,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetVehicleRejectionReasonCount",&GetVehicleRejectionReasonCount,GOSVAR_INT,0,NULL);

	gosScript_RegisterCallback("GetBotVehicleRejectionReason",&GetBotVehicleRejectionReason,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetBotVehicleRejectionReasonCount",&GetBotVehicleRejectionReasonCount,GOSVAR_INT,0,NULL);

	gosScript_RegisterCallback("ClearLocalRestrictions",&ClearLocalRestrictions,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("CheckForLocalRestrictions",&CheckForLocalRestrictions,GOSVAR_INT,0,NULL);


	gosScript_RegisterCallback("NetHaveMap",&NetHaveMap,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("NetLaunchBrowserMapLink",&NetLaunchBrowserMapLink,GOSVAR_INT,0,NULL);


    gosScript_RegisterCallback("GetClientReady",&GetClientReady,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SetClientReady",&SetClientReady,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SetClientUnready",&SetClientUnready,GOSVAR_INT,0,NULL);

	gosScript_RegisterCallback("SendVehicleRequest",&SendVehicleRequest,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("RequestTeam",&RequestTeam,GOSVAR_INT,0,NULL);
	
	gosScript_RegisterCallback("GetStartScreen",&GetStartScreen,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetMechName",&GetMechName,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SelectMech",&SelectMech,GOSVAR_INT,0,NULL);
	
	gosScript_RegisterCallback("SelectSkin",&SelectSkin,GOSVAR_INT,0,NULL);
	
	gosScript_RegisterCallback("SetShellCommand",&SetShellCommand,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("LoadQuickSave",&LoadQuickSave,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SaveQuickSave",&SaveQuickSave,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SetVideoRes",&SetVideoRes,GOSVAR_INT,0,NULL);

    // mdm - for game type management at the script level
    gosScript_RegisterCallback("GetGameTypeString", &GetGameTypeString, GOSVAR_INT, 0, NULL);
    gosScript_RegisterCallback("GetGameTypeFromString", &GetGameTypeFromString, GOSVAR_INT, 0, NULL);
    gosScript_RegisterVariable("m_gameTypeStr", &m_gameTypeStr, GOSVAR_STRING, 0, NULL );
	// mdm - to check the gun status for advertising a game
	gosScript_RegisterCallback("CheckGUNAdvertise", &CheckGUNAdvertise,GOSVAR_INT,0,NULL);

	gosScript_RegisterCallback("RemoveOneChat",&RemoveOneChat,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SendChat",&SendChat,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SendBroadcastChat",&SendBroadcastChat,GOSVAR_INT,0,NULL);
	gosScript_RegisterVariable("m_currentChatCount", &m_currentChatCount, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("m_maxChatCount", &m_maxChatCount, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("m_chatFrom", &m_chatFrom, GOSVAR_STRING, 50, NULL);
	gosScript_RegisterVariable("m_chatArray", &m_chatArray, GOSVAR_STRING, 50, NULL);
	gosScript_RegisterVariable("m_outgoingChat", &m_outgoingChat, GOSVAR_STRING, 0, NULL);
	gosScript_RegisterVariable("m_outgoingChatToPlayerCount", &m_outgoingChatToPlayerCount, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("m_outgiongChatToPlayer", &m_outgiongChatToPlayer, GOSVAR_INT, 32, NULL);

	gosScript_RegisterVariable("m_serverName",&m_serverName, GOSVAR_STRING,0,NULL);
	gosScript_RegisterVariable("m_serverIP",&m_serverIP, GOSVAR_STRING,0,NULL);

	gosScript_RegisterVariable("m_scoreNames", &m_scoreNames, GOSVAR_STRING, 32, NULL);
	gosScript_RegisterVariable("m_scoreCount", &m_scoreCount, GOSVAR_INT, 0, NULL);
    gosScript_RegisterVariable("m_scorePlyrIndex", &m_scorePlyrIndex, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("m_scoreScores", &m_scoreScores, GOSVAR_INT, 32, NULL);
	gosScript_RegisterVariable("m_scoreDeaths", &m_scoreDeaths, GOSVAR_INT, 32, NULL);
    gosScript_RegisterVariable("m_scorePlyrs", &m_scorePlyrs, GOSVAR_INT, 32, NULL);
	gosScript_RegisterVariable("m_scoreKills", &m_scoreKills, GOSVAR_INT, 32, NULL);
	gosScript_RegisterVariable("m_scoreTeamCounts", &m_scoreTeamCounts, GOSVAR_INT, 8, NULL);
	gosScript_RegisterVariable("m_scoreTeamScores", &m_scoreTeamScores, GOSVAR_INT, 8, NULL);
	gosScript_RegisterVariable("m_scoreTeamDeaths", &m_scoreTeamDeaths, GOSVAR_INT, 8, NULL);
	gosScript_RegisterVariable("m_scoreTeamKills", &m_scoreTeamKills, GOSVAR_INT, 8, NULL);
	gosScript_RegisterVariable("m_scoreRuleType", &m_scoreRuleType, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("m_scoreMapName", &m_scoreMapName, GOSVAR_STRING, 0, NULL);
	gosScript_RegisterVariable("m_scoreTeamAllowed", &m_scoreTeamAllowed, GOSVAR_INT, 0, NULL);
	

	
	gosScript_RegisterCallback("MyPlayerId",&MyPlayerId,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("IsPlayerConnectionValid",&IsPlayerConnectionValid,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayerConnectionName",&GetPlayerConnectionName,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayerConnectionClan",&GetPlayerConnectionClan,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayerConnectionReady",&GetPlayerConnectionReady,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayerConnectionLaunched",&GetPlayerConnectionLaunched,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayerConnectionChasis",&GetPlayerConnectionChasis,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayerConnectionTeam",&GetPlayerConnectionTeam,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayerConnectionSkin",&GetPlayerConnectionSkin,GOSVAR_INT,0,NULL);
	


	gosScript_RegisterCallback("AddBot",&AddBot,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("RemoveBot",&RemoveBot,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("RemoveAllBots",&RemoveAllBots,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SetTeamBot",&SetTeamBot,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SetMechBot",&SetMechBot,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetBotValid",&GetBotValid,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetBotName",&GetBotName,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetBotClan",&GetBotClan,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetBotChasis",&GetBotChasis,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetBotTeam",&GetBotTeam,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetBotVehicleAccepted",&GetBotVehicleAccepted,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("FillTeams",&FillTeams,GOSVAR_INT,0,NULL);
	
	gosScript_RegisterCallback("GetTimeToLaunch",&GetTimeToLaunch,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetTimeToLaunchLock",&GetTimeToLaunchLock,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetTimeToGameEnd",&GetTimeToGameEnd,GOSVAR_INT,0,NULL);

	gosScript_RegisterCallback("GetNetworkError",&GetNetworkError,GOSVAR_INT,0,NULL);



	gosScript_RegisterCallback("ServerStatsDirty",&ServerStatsDirty,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("ServerStatsScale",&ServerStatsScale,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("ClientStatsScale",&ClientStatsScale,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("ServerCleanDirtyFlag",&ServerCleanDirtyFlag,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetCurrentGameName",&GetCurrentGameName,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetCurrentMissionName",&GetCurrentMissionName,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayerCount",&GetPlayerCount,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("IsPlayerValid",&IsPlayerValid,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayerName",&GetPlayerName,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetStatisticsCount",&GetStatisticsCount,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetStatisticName",&GetStatisticName,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetStatisticbps",&GetStatisticbps,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetStatisticLifeTimeTotal",&GetStatisticLifeTimeTotal,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayersbps",&GetPlayersbps,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayerPing",&GetPlayerPing,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayersIncommingPacketsPerSecond",&GetPlayersIncommingPacketsPerSecond,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetPlayersOutgoingPacketsPerSecond",&GetPlayersOutgoingPacketsPerSecond,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetGameTime",&GetGameTime,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetRealTime",&GetRealTime,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetRealDate",&GetRealDate,GOSVAR_INT,0,NULL);


	//This is the only real one that should exist
	gosScript_RegisterCallback("Shell_CallbackHandler",&Shell_CallbackHandler,GOSVAR_INT,0,NULL);
	gosScript_RegisterVariable("m_iaMissionName", &m_iaMissionName, GOSVAR_STRING, 0, NULL);
	gosScript_RegisterVariable("m_endMovieName", &m_endMovieName, GOSVAR_STRING, 0, NULL);
	gosScript_RegisterVariable("m_iaMissionCount", &m_iaMissionCount, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("m_mechCount", &m_mechCount, GOSVAR_INT, 0, NULL);


	gosScript_RegisterVariable("m_LastMechName", &m_LastMechName, GOSVAR_STRING, 0, NULL);
	gosScript_RegisterVariable("m_lastMechIndex", &m_lastMechIndex, GOSVAR_INT, 0, NULL);


	gosScript_RegisterVariable("m_mapInfo", &m_mapInfo, GOSVAR_STRING, 0, NULL);
	gosScript_RegisterVariable("m_mapAuthor", &m_mapAuthor, GOSVAR_STRING, 0, NULL);
	gosScript_RegisterVariable("m_mapLink", &m_mapLink, GOSVAR_STRING, 0, NULL);
	gosScript_RegisterVariable("m_mapLinkAvailable", &m_mapLinkAvailable, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("m_serverCPU", &m_serverCPU, GOSVAR_STRING, 0, NULL);

	
	gosScript_RegisterVariable("networkScenarioCount", &networkScenarioCount, GOSVAR_INT, 0, NULL);
	gosScript_RegisterVariable("maxNetworkScenarioCount", &maxNetworkScenarioCount, GOSVAR_INT, 0, NULL);

	gosScript_RegisterCallback("InitNetworkScenarios",&InitNetworkScenarios,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetNetworkScenarios",&GetNetworkScenarios,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SelectNetworkScenario",&SelectNetworkScenario,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetScenarioCount",&GetScenarioCount,GOSVAR_INT,0,NULL);

	gosScript_RegisterCallback("GetDecalCount",&GetDecalCount,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("GetDecalNames",&GetDecalNames,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SetTeamDecal",&SetTeamDecal,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SetPilotDecal",&SetPilotDecal,GOSVAR_INT,0,NULL);

	gosScript_RegisterCallback( "GetWeaponStats", &gosGetWeaponStats, GOSVAR_INT, 0, NULL );

	gosScript_RegisterCallback("BanPlayer",&BanPlayer,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("BanPlayersISP",&BanPlayersISP,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("KickPlayer",&KickPlayer,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("SquelchPlayer",&SquelchPlayer,GOSVAR_INT,0,NULL);
	gosScript_RegisterCallback("IsPlayerSquelched",&IsPlayerSquelched,GOSVAR_INT,0,NULL);
	
	
	gosScript_RegisterCallback("IsMissionReviewAvailable",&IsMissionReviewAvailable,GOSVAR_INT,0,NULL);

	// ngLog additions
	gosScript_RegisterCallback("IsRegisteredForStats", &IsRegisteredForStats, GOSVAR_INT, 0, NULL);
	gosScript_RegisterCallback("ViewStatsInBrowser", &ViewStatsInBrowser, GOSVAR_INT, 0, NULL);

	gosScript_RegisterCallback("EnterMultiplayerOptionsScreen", &EnterMultiplayerOptionsScreen, GOSVAR_INT, 0, NULL);
	gosScript_RegisterCallback("LeaveMultiplayerOptionsScreen", &LeaveMultiplayerOptionsScreen, GOSVAR_INT, 0, NULL);

	gosScript_RegisterCallback("ImeCallback", &ImeCallback, GOSVAR_INT, 0, NULL);
	gos_SetIMELevel(2);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::ShutDown()
{
	if (MWApplication::GetInstance()->Win32DedicatedServer) 
		return;

	gosScript_UnregisterVariable("m_moviePlaying");
	gosScript_UnregisterVariable("m_moviesStopped");
	gosScript_UnregisterVariable("m_listBoxSize");
	gosScript_UnregisterVariable("DemoMode");

	gosScript_UnregisterVariable("SetNetworkMissionParamater");
	gosScript_UnregisterVariable("GetLocalNetworkMissionParamater");
	gosScript_UnregisterVariable("GetServerNetworkMissionParamater");
	gosScript_UnregisterVariable("NetConnectedToServer");
	gosScript_UnregisterVariable("NetClientVehicleAccepted");
	gosScript_UnregisterVariable("GetVehicleRejectionReason");
	gosScript_UnregisterVariable("GetVehicleRejectionReasonCount");


	gosScript_UnregisterVariable("GetBotVehicleRejectionReason");
	gosScript_UnregisterVariable("GetBotVehicleRejectionReasonCount");
	gosScript_UnregisterVariable("ClearLocalRestrictions");
	gosScript_UnregisterVariable("CheckForLocalRestrictions");




	gosScript_UnregisterVariable("NetHaveMap");
	gosScript_UnregisterVariable("NetLaunchBrowserMapLink");


	gosScript_UnregisterVariable("SendVehicleRequest");
	gosScript_UnregisterVariable("SetClientUnready");
	gosScript_UnregisterVariable("SetClientReady");
    gosScript_UnregisterVariable("GetClientReady");

	gosScript_UnregisterVariable("RequestTeam");
	gosScript_UnregisterVariable("SetVideoRes");	
	gosScript_UnregisterVariable("LoadQuickSave");
	gosScript_UnregisterVariable("SaveQuickSave");
	gosScript_UnregisterVariable("SetShellCommand");
	gosScript_UnregisterVariable("GetMechName");
	gosScript_UnregisterVariable("SelectMech");	
	gosScript_UnregisterVariable("SelectSkin");
	gosScript_UnregisterVariable("GetStartScreen");

	gosScript_UnregisterVariable("m_serverName");
	gosScript_UnregisterVariable("m_serverIP");

	gosScript_UnregisterCallback("RemoveOneChat");
	gosScript_UnregisterCallback("SendChat");
	gosScript_UnregisterCallback("SendBroadcastChat");
	gosScript_UnregisterVariable("m_currentChatCount");
	gosScript_UnregisterVariable("m_maxChatCount");
	gosScript_UnregisterVariable("m_chatFrom");
	gosScript_UnregisterVariable("m_chatArray");
	gosScript_UnregisterVariable("m_outgoingChat");
	gosScript_UnregisterVariable("m_outgoingChatToPlayerCount");
	gosScript_UnregisterVariable("m_outgiongChatToPlayer");
	
	gosScript_UnregisterVariable("m_scoreNames");
    gosScript_UnregisterVariable("m_scorePlyrIndex");
	gosScript_UnregisterVariable("m_scoreCount");
    gosScript_UnregisterVariable("m_scorePlyrs");
	gosScript_UnregisterVariable("m_scoreDeaths");
	gosScript_UnregisterVariable("m_scoreKills");
	gosScript_UnregisterVariable("m_scoreScores");
	gosScript_UnregisterVariable("m_scoreTeamCounts");
	gosScript_UnregisterVariable("m_scoreTeamDeaths");
	gosScript_UnregisterVariable("m_scoreTeamKills");
	gosScript_UnregisterVariable("m_scoreTeamScores");
	gosScript_UnregisterVariable("m_scoreRuleType");
	gosScript_UnregisterVariable("m_scoreMapName");
	gosScript_UnregisterVariable("m_scoreTeamAllowed");

    gosScript_UnregisterVariable("m_gameTypeStr");
	
	gosScript_UnregisterVariable("MyPlayerId");
	gosScript_UnregisterVariable("IsPlayerConnectionValid");
	gosScript_UnregisterVariable("GetPlayerConnectionName");
	gosScript_UnregisterVariable("GetPlayerConnectionClan");
	gosScript_UnregisterVariable("GetPlayerConnectionReady");
	gosScript_UnregisterVariable("GetPlayerConnectionLaunched");
	gosScript_UnregisterVariable("GetPlayerConnectionChasis");
	gosScript_UnregisterVariable("GetPlayerConnectionTeam");
	gosScript_UnregisterVariable("GetPlayerConnectionSkin");
	

	gosScript_UnregisterVariable("AddBot");
	gosScript_UnregisterVariable("RemoveBot");
	gosScript_UnregisterVariable("RemoveAllBots");
	gosScript_UnregisterVariable("SetTeamBot");
	gosScript_UnregisterVariable("SetMechBot");
	gosScript_UnregisterVariable("GetBotValid");
	gosScript_UnregisterVariable("GetBotName");
	gosScript_UnregisterVariable("GetBotClan");
	gosScript_UnregisterVariable("GetBotChasis");
	gosScript_UnregisterVariable("GetBotTeam");
	gosScript_UnregisterVariable("GetBotVehicleAccepted");
	gosScript_UnregisterVariable("FillTeams");

	gosScript_UnregisterVariable("GetTimeToLaunch");
	gosScript_UnregisterVariable("GetTimeToLaunchLock");
	gosScript_UnregisterVariable("GetTimeToGameEnd");

	gosScript_UnregisterVariable("GetNetworkError");


	gosScript_UnregisterVariable("ServerStatsDirty");
	gosScript_UnregisterVariable("ServerStatsScale");
	gosScript_UnregisterVariable("ClientStatsScale");
	gosScript_UnregisterVariable("ServerCleanDirtyFlag");
	gosScript_UnregisterVariable("GetCurrentGameName");
	gosScript_UnregisterVariable("GetCurrentMissionName");
	gosScript_UnregisterVariable("GetPlayerCount");
	gosScript_UnregisterVariable("IsPlayerValid");
	gosScript_UnregisterVariable("GetPlayerName");
	gosScript_UnregisterVariable("GetStatisticsCount");
	gosScript_UnregisterVariable("GetStatisticName");
	gosScript_UnregisterVariable("GetStatisticbps");
	gosScript_UnregisterVariable("GetStatisticLifeTimeTotal");
	gosScript_UnregisterVariable("GetPlayersbps");
	gosScript_UnregisterVariable("GetPlayerPing");
	gosScript_UnregisterVariable("GetPlayersIncommingPacketsPerSecond");
	gosScript_UnregisterVariable("GetPlayersOutgoingPacketsPerSecond");
	gosScript_UnregisterVariable("GetGameTime");
	gosScript_UnregisterVariable("GetRealTime");
	gosScript_UnregisterVariable("GetRealDate");

	//Again this in the only one that should exist
	gosScript_UnregisterCallback("Shell_CallbackHandler");
	gosScript_UnregisterVariable("m_iaMissionName");
	gosScript_UnregisterVariable("m_endMovieName");
	gosScript_UnregisterVariable("m_iaMissionCount");
	gosScript_UnregisterVariable("m_mechCount");

	gosScript_UnregisterVariable("m_LastMechName");
	gosScript_UnregisterVariable("m_lastMechIndex");


	gosScript_UnregisterVariable("m_mapInfo");
	gosScript_UnregisterVariable("m_mapAuthor");
	gosScript_UnregisterVariable("m_mapLink");
	gosScript_UnregisterVariable("m_mapLinkAvailable");
	gosScript_UnregisterVariable("m_serverCPU");

	gosScript_UnregisterVariable("networkScenarioCount");
	gosScript_UnregisterVariable("maxNetworkScenarioCount");
	gosScript_UnregisterCallback("InitNetworkScenarios");
	gosScript_UnregisterCallback("GetNetworkScenarios");
	gosScript_UnregisterCallback("SelectNetworkScenario");
	gosScript_UnregisterCallback("GetScenarioCount");

	gosScript_UnregisterCallback("GetDecalCount");
	gosScript_UnregisterCallback("GetDecalNames");
	gosScript_UnregisterCallback("SetTeamDecal");
	gosScript_UnregisterCallback("SetPilotDecal");

	gosScript_UnregisterCallback( "GetWeaponStats" );

	gosScript_UnregisterCallback("BanPlayer");
	gosScript_UnregisterCallback("BanPlayersISP");
	gosScript_UnregisterCallback("KickPlayer");
	gosScript_UnregisterCallback("SquelchPlayer");
	gosScript_UnregisterCallback("IsPlayerSquelched");

	gosScript_UnregisterCallback("IsMissionReviewAvailable");
	
	// ngLog additions
	gosScript_UnregisterCallback("IsRegisteredForStats");
	gosScript_UnregisterCallback("ViewStatsInBrowser");
	
	gosScript_UnregisterCallback("EnterMultiplayerOptionsScreen");
	gosScript_UnregisterCallback("LeaveMultiplayerOptionsScreen");

	gosScript_UnregisterCallback("ImeCallback");

// jcem - start
	gosScript_UnregisterVariable("g_nTimeList_Value");
	gosScript_UnregisterVariable("g_nTimeList_Index");
// MSL 5.06
	gosScript_UnregisterVariable("g_nBlackMech");
	gosScript_UnregisterVariable("g_nMechVariant");
	gosScript_UnregisterVariable("g_nMechLabOp");
	gosScript_UnregisterVariable("g_nMechPodNum");
	gosScript_UnregisterCallback("CTCL_WhyPaused");
// MSL 5.03 Mechview
    gosScript_UnregisterCallback("CTCL_MechViewOnMainScreen");
    gosScript_UnregisterCallback("CTCL_IsBotAllowed");
    gosScript_UnregisterCallback("CTCL_GetACP");
    gosScript_UnregisterCallback("CTCL_MiscFile");
    gosScript_UnregisterCallback("CTCL_GetIncNums");
    gosScript_UnregisterCallback("TBL_GetResNames");
    gosScript_UnregisterCallback("CTCL_Inviter");
    gosScript_UnregisterCallback("CTCL_DoInviteCOOP");
    gosScript_UnregisterCallback("CTCL_CheckInviteCOOP");
	gosScript_UnregisterCallback("CTCL_SetDispStateCOOP");
	gosScript_UnregisterCallback("CTCL_CheckCampaign");
	gosScript_UnregisterCallback("CTCL_GetJoyInfo");
	gosScript_UnregisterCallback("CTCL_PosCOOP");
	gosScript_UnregisterCallback("CTCL_StartCOOP");
	gosScript_UnregisterCallback("CTCL_CheckCOOP");
    gosScript_UnregisterCallback("CTCL_SetPlayerName");
    gosScript_UnregisterCallback("CTCL_GetPlayerName");
	gosScript_UnregisterCallback("CTCL_CheckUseJPD");
	gosScript_UnregisterCallback("CTCL_CheckCoinCounts");
	gosScript_UnregisterCallback("CTCL_CheckPlayMovie");
    gosScript_UnregisterCallback("CTCL_DoReprint");
    gosScript_UnregisterCallback("CTCL_IsGameLoaded");
    gosScript_UnregisterCallback("CTCL_DoBreak");
    gosScript_UnregisterCallback("CTCL_GetMissionState");
    gosScript_UnregisterCallback("CTCL_AddPlayer");
    gosScript_UnregisterCallback("CTCL_DoMission");
    gosScript_UnregisterCallback("CTCL_IsValidName");
    gosScript_UnregisterCallback("CTCL_GetTeamParams");
    gosScript_UnregisterCallback("CTCL_SetCDSP");
	gosScript_UnregisterCallback("CTCL_Set");
	gosScript_UnregisterCallback("CTCL_Get");
    gosScript_UnregisterCallback("CTCL_IsConsoleX");
    gosScript_UnregisterCallback("CTCL_IsConsole");
    gosScript_UnregisterCallback("CTCL_GetType");
// jcem - end
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


void MW4Shell::StartMainShell()
{
	if (MWApplication::DemoMode)
	{
		STOP(("SERVER OFF LINE"));
	}

	if (MWApplication::RunFromLobby)
	{
		gos_TerminateApplication();
	}
	else
	{
// jcem - begin
        if (CTCL_IsConsoleX()) {
#ifdef _DEBUG
            OutputDebugString("StartMainShell\n");
#endif // _DEBUG
            CTCL_SetGameStateAsIdle();
        }
// jcem - end
		ClearChat();

		gos_SetScreenMode(800,600,Environment.bitDepth,Environment.FullScreenDevice);
		gosScript_ExecuteScript(SHELLSCRIPTS_PATH"Shell.script",0x1000);
		currentShellRunning = MainShellRunning;
		Environment.DoGameLogic	= &MWApplication::DoShellLogic;
		firstRun = false;
	}
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartNetworkServerExecute()
{
	
	MWApplication *app = MWApplication::GetInstance();
	for (int i = 0; i < Maximum_Lancemates; ++i)
	{
		app->lancemateConnectionData[i].Disconnect();
	}

	if (!MWApplication::GetInstance()->Win32DedicatedServer) {
		netServerScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"NetServer.script",0x1000);
		currentShellRunning = NetServerShellRunning;
		Environment.DoGameLogic	= &MWApplication::DoShellLogic;
	}

	firstRun = false;
	//selectedScenario = -1;
	app->memoryDiffKiller.Init();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartNetworkClientExecute()
{
	MWApplication *app = MWApplication::GetInstance();
	for (int i = 0; i < Maximum_Lancemates; ++i)
	{
		app->lancemateConnectionData[i].Disconnect();
	}
	
	if (!MWApplication::GetInstance()->Win32DedicatedServer) {
		netClientScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"NetClient.script",0x1000);
		currentShellRunning = NetClientShellRunning;
		Environment.DoGameLogic	= &MWApplication::DoShellLogic;
	}	

	firstRun = false;
	app->memoryDiffKiller.Init();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	

void MW4Shell::StartNetworkScoreExecute()
{
	gos_SetScreenMode(800, 600,Environment.bitDepth,Environment.FullScreenDevice);
	netScoreScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"NetScore.script",0x1000);
	currentShellRunning = NetScoreShellRunning;
	Environment.DoGameLogic	= &MWApplication::DoShellLogic;

	firstRun = false;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartNetworkMissionReviewExecute()
{
	netMissionReviewScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"NetMissionReview.script",0x0000);
	currentShellRunning = NetMissionReviewShellRunning;
	Environment.DoGameLogic	= &MWApplication::DoShellLogic;
	
	firstRun = false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartNetworkStartupScreen()
{

	if (MWApplication::RunFromLobby)
	{
		gos_TerminateApplication();
	}
	else
	{
		gos_SetScreenMode(800, 600,Environment.bitDepth,Environment.FullScreenDevice);
		currentShellRunning = NetStartupShellRunning;
		Environment.DoGameLogic	= &MWApplication::DoShellLogic;
		firstRun = false;
		MWApplication::GetInstance()->LoadServerOptions();
		gos_NetStartGame(0, MWApplication::SecureNetGame);
	}
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MW4Shell::StopNetworkShellsExecute()
{
	if (MWApplication::GetInstance()->Win32DedicatedServer) {
		MWApplication *app = MWApplication::GetInstance();
		app->memoryDiffKiller.Uninit();
		return;
	}

	HGOSSCRIPT mechbay_1 = gosScript_GetScriptHandle("MechBay", 0);
	if (mechbay_1 != NULL)
	{
		gosScript_EndScript(mechbay_1);
		mechbay_1 = NULL;
	}

	HGOSSCRIPT mechbay_2 = gosScript_GetScriptHandle("MechBay_main", 0);
	if (mechbay_2 != NULL)
	{
		gosScript_EndScript(mechbay_2);
		mechbay_2 = NULL;
	}

	if (netServerScript != NULL)
	{
		gosScript_EndScript(netServerScript);
		netServerScript = NULL;
		currentShellRunning = NoShellRunning;
	}

	if (netClientScript != NULL)
	{
		gosScript_EndScript(netClientScript);
		netClientScript = NULL;
		currentShellRunning = NoShellRunning;
	}

	if (netScoreScript != NULL)
	{
		gosScript_EndScript(netScoreScript);
		netScoreScript = NULL;
		currentShellRunning = NoShellRunning;
	}

	if (netMissionReviewScript != NULL)
	{
		gosScript_EndScript(netMissionReviewScript);
		netMissionReviewScript = NULL;
		currentShellRunning = NoShellRunning;
	}


	HGOSSCRIPT net_1 = gosScript_GetScriptHandle("NetLobby", 0);
	if (net_1 != NULL)
	{
		gosScript_EndScript(net_1);
		net_1 = NULL;
	}

	HGOSSCRIPT net_2 = gosScript_GetScriptHandle("Mouse", 0);
	if (net_2 != NULL)
	{
		gosScript_EndScript(net_2);
		net_2 = NULL;
	}
// jcem - begin
	HGOSSCRIPT net_3 = gosScript_GetScriptHandle("ConLobby", 0);
	if (net_3 != NULL)
	{
		gosScript_EndScript(net_3);
		net_3 = NULL;
	}
// jcem - end
    if (CTCL_IsConsoleX()) {
        EndAllScripts();
    }
	MWApplication *app = MWApplication::GetInstance();
	app->memoryDiffKiller.Uninit();

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartPauseShellExecute()
{
	if (currentShellRunning == NoShellRunning)
	{
		if (MWApplication::GetInstance()->serverFlag)
			pauseScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"PauseServer.script",0x1000);
		else
			pauseScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"PauseClient.script",0x1000);
		currentShellRunning = InGameShellRunning;
		Environment.DoGameLogic	= &MWApplication::DoShellLogic;
	}

	firstRun = false;
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StopPauseShellExecute()
{
	if (pauseScript != NULL)
	{
		gosScript_EndScript(pauseScript);
		pauseScript = NULL;
	}

	currentShellRunning = NoShellRunning;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartPauseShellExecuteModal()
{
	if (currentShellRunning == NoShellRunning)
	{
		if (shellStart == InstantActionShellStart)
			gosScript_ExecuteScript(SHELLSCRIPTS_PATH"PauseModalInstantAction.script",0x2000);
		else {
			if (g_bCOOP)
				gosScript_ExecuteScript(SHELLSCRIPTS_PATH"gs_PauseModalCampaign.script", 0x2000);
		else
			gosScript_ExecuteScript(SHELLSCRIPTS_PATH"PauseModalCampaign.script", 0x2000);
	}
	}

	firstRun = false;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartPauseOptionsShellExecute()
{
	if (currentShellRunning == NoShellRunning)
	{
		if ((shellStart != InstantActionShellStart) && (shellStart != CampaignShellStart))
			pauseOptionsScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"PauseOptions.script", 0x1000);
		else
			gosScript_ExecuteScript(SHELLSCRIPTS_PATH"PauseOptionsModal.script", 0x2000);
	}

	firstRun = false;
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StopPauseOptionsShellExecute()
{
	if (pauseOptionsScript != NULL)
	{
		gosScript_EndScript(pauseOptionsScript);
		pauseOptionsScript = NULL;
	}

	currentShellRunning = NoShellRunning;
	
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartNetworkErrorExecuteModal()
{
	gosScript_ExecuteScript(SHELLSCRIPTS_PATH"NetworkError.script",0x2000);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartLoadingShell(bool multiplayer)
{
	if (!MWApplication::GetInstance()->Win32DedicatedServer)
	{
  // from here - for MechView by jcem
#if 1
        gosASSERT(!g_pfnCTCL_AfterBeginScene);
 
        bool bMechView;
        if (!multiplayer || (m_mechID == m_mechIDs[0]) || (g_nMR == 2) || (g_nMechViewType == 0))
		{
            //(CTCL_GetType() != _ECTCL_Game)
            // it's cameraship or MissionReplay...
            bMechView = false;
        }
		else if (g_nMechViewType == 1)
		{
            if (hsh_initialized && radar_device.pD3DDevice)
			{
                bMechView = true;
            }
			else
			{
                bMechView = false;
            }
        }
		else
		{
            if (g_nMechViewType == 2)
                bMechView = true;
            else
                bMechView = false;
        }

        if (bMechView)
		{
			MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
 
			NetMissionParameters::MWNetMissionParameters *params;
			if (app->serverFlag)
			{
				params = MWApplication::GetInstance()->GetLocalNetParams();
			}
			else
			{
				params = MWApplication::GetInstance()->GetServerNetParams();
			}
 
            InitMechLabScreen();
 
			MechLab::Instance->SetMech(m_mechID, m_mechShortResFile, "Resource\\Variants\\");
            int nSkinPrefix;
            
            if (params->m_teamAllowed)
			{
                int nTeamNumber = app->servedConnectionData[Connection::Local->GetID()].pilotTeam;
                if ((nTeamNumber < 0) || (MWApplication::No_Team < nTeamNumber))
                    nTeamNumber = MWApplication::No_Team;
              #if 1
                nSkinPrefix = g_caCamoPrefixes[g_naTeamSkins[nTeamNumber]];
              #else
                int nParams = 3;
                int nTeamParam = TEAM_PARAMETER;
                int nTeamSkin = TEAM_SKIN;
                void* data_teamskin[3] = {
                    &nTeamParam,
                    &nTeamNumber,
                    &nTeamSkin,
                };
                nSkinPrefix = g_caCamoPrefixes[GetNetworkMissionParamater(params, 3, data_teamskin)];
              #endif
            }
			else
			{
                nSkinPrefix = *(BYTE*)&m_skinPrefix;
            }

            void* data_skin[3] = {
                MechLab::Instance, // instance
                NULL,
                &nSkinPrefix,
            };

            MechLab::Instance->SetMechSkin(data_skin, 3);
 
            if (g_nMechViewType == 1)
			{
                g_MLCallData.Setup_MLCallData();
                g_pfnCTCL_AfterBeginScene = CTCL_AfterBeginScene;
            }
        }
		else
		{
            radar_device.m_nMechViewMax = 0; // no MechView Images...
            g_pfnCTCL_AfterBeginScene = NULL;
        }
#endif
  // to here - for MechView by jcem
 
		if (multiplayer)
			loadingScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"NetLoading.script",0x0100);
		else
			loadingScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"Loading.script",0x1000);
    }
 
	currentShellRunning = LoadingShellRunning;
	Environment.DoGameLogic = &MWApplication::DoShellLogic;

	firstRun = false;
 
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MW4Shell::StopLoadingShell()
{
	if (loadingScript != NULL)
	{
		gosScript_EndScript(loadingScript);
		loadingScript = NULL;
	}
#if 1
    // from here - for MechView by jcem
    if (g_nMechViewType)
	{
        if (g_nMechViewType == 1)
		{
            g_pfnCTCL_AfterBeginScene = NULL;
        }
		else
		{ // if (g_nMechViewType == 2)
            MW4Shell::Instance->ClearMechLab(-1);
        }
    }
    // to here - for MechView by jcem
#endif
	currentShellRunning = NoShellRunning;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::StartStatShell()
{
	if (!MWApplication::GetInstance()->Win32DedicatedServer) {
		
		gos_SetScreenMode(800, 600,Environment.bitDepth,Environment.FullScreenDevice);
		
#ifdef LAB_ONLY
		statScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"ServerStatDbg.script",0x1000);
#else
		statScript = gosScript_ExecuteScript(SHELLSCRIPTS_PATH"ServerStat.script",0x1000);
#endif		
	}
	
	firstRun = false;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MW4Shell::StopStatShell()
{
	if (statScript != NULL)
	{
		gosScript_EndScript(statScript);
		statScript = NULL;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

const char* MW4Shell::GetGameName()
{
	return NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::LoadMechPrototypes()
{
	Stuff::MString vehicles_path = "Content\\Mechs\\*.*";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(vehicles_path, true);
	Check_Object(resource_directory);
	Register_Object(resource_directory);

	Stuff::MString temp_dir_string;

	while((char *)(temp_dir_string = resource_directory->GetCurrentFolderName()) != NULL)
	{
		Stuff::MString new_directory_path = vehicles_path;
		new_directory_path.IsolateDirectory();
		new_directory_path += temp_dir_string;
		new_directory_path += "\\interface.instance";
		if(gos_DoesFileExist(new_directory_path))
		{
			MechPrototype* newMechPrototype = new MechPrototype;
			newMechPrototype->name = temp_dir_string;
			newMechPrototype->path = vehicles_path;
			newMechPrototype->path += temp_dir_string;
			newMechPrototype->path += '\\';
			newMechPrototype->path += temp_dir_string;
			newMechPrototype->path += ".instance";
			mechPrototypeList.Add(newMechPrototype);
		}
		resource_directory->AdvanceCurrentFolder();
	}
	Unregister_Object(resource_directory);
	delete resource_directory;

	Stuff::ChainIteratorOf<MechPrototype *> iterator(&mechPrototypeList);
	numMechPrototypes = iterator.GetSize();

	mechPrototypeNames = new char* [1024];
	mechPrototypeFilenames = new char* [1024];

	for (int i = 0; i < numMechPrototypes; i++)
	{
		MechPrototype *mp = iterator.ReadAndNext();
		
		mechPrototypeNames[i] = new char[mp->name.GetLength() + 1];
		Str_Copy(mechPrototypeNames[i], (char*)mp->name, mp->name.GetLength() + 1);
		mechPrototypeFilenames[i] = new char[mp->path.GetLength() + 1];
		Str_Copy(mechPrototypeFilenames[i],(char*)mp->path, mp->path.GetLength() + 1);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::LoadMissions()
{
//	char Working_Directory[128];
//	_getcwd(Working_Directory, 128);

//	Stuff::MString mission_path = Working_Directory;
	Stuff::MString mission_path = "Content\\Missions\\*.*";
//	mission_path += "\\Content\\Missions\\*.*";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(mission_path, true);
	Check_Object(resource_directory);
	Register_Object(resource_directory);

	Stuff::MString temp_dir_string;

	missionNames = new char* [1024];
	missionFilenames = new char* [1024];
	numMissions = 0;

	while((char *)(temp_dir_string = resource_directory->GetCurrentFolderName()) != NULL)
	{
		Stuff::MString new_directory_path;
		Stuff::MString temp_string;
		new_directory_path = mission_path;
		new_directory_path.IsolateDirectory();
		new_directory_path += temp_dir_string;
		new_directory_path += "\\";
		new_directory_path += temp_dir_string;
		new_directory_path += ".instance";
		Stuff::Directory *mission_directory = new Stuff::Directory(new_directory_path);
		Register_Object(mission_directory);
		while((char *)(temp_string = mission_directory->GetCurrentFileName()) != NULL)
		{
			temp_string.StripExtension();
			missionNames[numMissions] = new char[temp_string.GetLength() + 1];
			strcpy(missionNames[numMissions],(char*)temp_string);

			Stuff::MString temp_m_string;
			temp_m_string = "Content\\Missions\\";
			temp_m_string += temp_dir_string;
			temp_m_string += "\\";
			temp_m_string += temp_string;
			temp_m_string += ".instance";

			missionFilenames[numMissions] = new char[temp_m_string.GetLength() + 1];
			strcpy(missionFilenames[numMissions],(char*)temp_m_string);
			numMissions++;

			mission_directory->AdvanceCurrentFile();
		}
		Unregister_Object(mission_directory);
		delete mission_directory;
		resource_directory->AdvanceCurrentFolder();
	}
	Unregister_Object(resource_directory);
	delete resource_directory;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::GetStartScreen(void * instance, int, void *[])
{
	if (Instance->firstRun)
		return OPENINGCINEMA;

	if (Instance->shellStart == InstantActionShellStart)
		return IAWRAPUP_SCREEN;
	else if (Instance->shellStart == CampaignShellStart)
	{
		if(MWApplication::GetInstance()->m_campaignIsComplete)
			return CAMPAIGNLOBBY;
		return CAMPAIGN_REVIEW;
	}
	else if (Instance->shellStart == CampaignLoadShellStart)
		return CAMPAIGNLOBBY;
	else
		return MAINMENU;

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::SetNetworkMissionParamater(void * instance, int numParms, void **data)
{

	if (!MWApplication::GetInstance()->serverFlag)
	{
#ifdef _ARMOR
		PAUSE(("Shell Client is tring to set a parameter.  Only servers can set parameters"));
#endif
		return 0;
	}

	int param_number = INTPARM(0);

	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();


	switch (param_number)
	{
		case MAX_PLAYERS_PARAMETER:
			params->m_maxPlayers = INTPARM(1);
			break;

		case MAX_BOTS_PARAMETER:
			params->m_maxBots = INTPARM(1);
			Max_Clamp(params->m_maxBots, params->m_maxPlayers);
			break;

		case DEDICATED_SERVER_PARAMETER:
			params->m_runDedicated = INTPARM(1);
			if (params->m_runDedicated)
				gos_EnableSetting( gos_Set_LoseFocusBehavior, 3);
			else
				gos_EnableSetting( gos_Set_LoseFocusBehavior, 0);
			break;

		case CLOSED_GAME_PARAMETER:		
			params->m_closedGame = INTPARM(1);
			gos_NetServerCommands(gos_Command_LockGame, (DWORD)params->m_closedGame);
			if (params->m_closedGame)
				ServerAdvertiser::SetFlagsAllAdvertisers(ServerAdvertiser::GetFlagsAllAdvertisers() | NETFLAGS_LOCKED_FLAG);
			else
				ServerAdvertiser::SetFlagsAllAdvertisers(ServerAdvertiser::GetFlagsAllAdvertisers() & ~NETFLAGS_LOCKED_FLAG);
			break;

		case PLAYER_LIMIT_PARAMETER:
			params->m_playerLimit = INTPARM(1);
			Min_Clamp(params->m_playerLimit, Network::GetInstance()->GetPlayerCount());
			Environment.NetworkMaxPlayers = params->m_playerLimit;
			gos_NetServerCommands(gos_Commend_UpdateMaxPlayers,0);
			break;

		case JOIN_IN_PROGRESS_PARAMETER:
			params->m_joinInProgress = INTPARM(1);
			break;

		case JOIN_IN_PROGRESS_CUTOFF_PARAMETER:
			params->m_joinInProgressCutOff = INTPARM(1);
			break;

		case JOIN_IN_PROGRESS_CUTOFF_TIME_PARAMETER:
			params->m_joinInProgressCutOffTime = INTPARM(1);
			break;

		case HEAT_PARAMETER:
			params->m_heatOn = INTPARM(1);
			break;

		case KILL_LIMIT_PARAMETER:
			params->m_killLimit = INTPARM(1);
			break;

		case KILL_LIMIT_NUMBER_PARAMETER:
			params->m_killLimitNumber = INTPARM(1);
			break;

		case RESPAWN_LIMIT_PARAMETER:
			params->m_respawnLimit = INTPARM(1);
			break;

		case RESPAWN_LIMIT_NUMBER_PARAMETER:
			params->m_respawnLimitNumber = INTPARM(1);
			break;

		case FORCE_RESPAWN_PARAMETER:
			params->m_forceRespawn = INTPARM(1);
			break;

		case SPLASH_ON_PARAMETER:
			params->m_splashOn = INTPARM(1);
			break;

		case WEAPON_JAM_PARAMETER:
			params->m_weaponjamOn = INTPARM(1);
			break;

		case AMMO_BAY_FIRE_PARAMETER:
			params->m_ammobayfireOn = INTPARM(1);
			break;

// MSL 5.05 Advance Mode
		case ADVANCE_MODE_PARAMETER:
			params->m_advancemodeOn = INTPARM(1);
			break;

// MSL 5.06 Armor Mode
		case ARMOR_MODE_PARAMETER:
			params->m_armormodeOn = INTPARM(1);
			break;

		case SPLSH_PERCENTAGE_PARAMETER:
			params->m_splashPercentage = INTPARM(1);
			break;

		case UNLIMITED_AMMO_PARAMETER:
			params->m_unlimitedAmmo = INTPARM(1);
			break;

		case FRIENDLY_FIRE_PERCENTGE_PARAMETER:
			params->m_friendlyFirePercentage = INTPARM(1);
			break;

		case ALLOW_ZOOM_PERCENTAGE_PARAMETER:
			params->m_allowZoom = INTPARM(1);
			break;

		case ALLOW_3RD_PERSON_PARAMETER:
			params->m_allow3rdPerson = INTPARM(1);
			break;

		case ALLOW_AUTO_AIM_PARAMETER:
			params->m_allowAutoAim = INTPARM(1);
			break;

		case ALLOW_DEAD_CHAT_PARAMETER:
			params->m_allowDeadToChat = INTPARM(1);
			break;

		case INUVNERABLE_DROP_PARAMETER:
			params->m_invulnerableDrop = INTPARM(1);
			break;


		case ONLY_STOCK_MECH_PARAMETER:
			params->m_onlyStockMech = INTPARM(1);
			app->VerifyAllPlayerVehicles();
			break;

		case MINIMUM_TONNAGE_PARAMETER:
			params->m_minimumTonnage = INTPARM(1);
			app->VerifyAllPlayerVehicles();
			break;

		case MAXIMUM_TONNAGE_PARAMETER:
			params->m_maximumTonnage = INTPARM(1);
			app->VerifyAllPlayerVehicles();
			break;

		case ALLOWED_MECH_PARAMETER:
			{
				int offset = INTPARM(1) - FirstMechID;
				Verify(offset < 64);
				int value = INTPARM(2);

				DWORD *data;
				if (offset >= 32)
				{
					offset -= 32;
					data = &params->m_allowedMech[1];
				}
				else
				{	
					data = &params->m_allowedMech[0];
				}

				if (value)
					*data |= (0x1 << offset);
				else
					*data &= ~(0x1 << offset);
			}
			app->VerifyAllPlayerVehicles();
			break;

		case ALLOWED_BEAM_WEAPON_PARAMETER:
			{
				int offset = INTPARM(1) - FirstBeamID;
				Verify(offset < 64);
				int value = INTPARM(2);

				DWORD *data;
				if (offset >= 32)
				{
					offset -= 32;
					data = &params->m_allowedBeam[1];
				}
				else
				{	
					data = &params->m_allowedBeam[0];
				}

				if (value)
					*data |= (0x1 << offset);
				else
					*data &= ~(0x1 << offset);
			}
			app->VerifyAllPlayerVehicles();
			break;

		case ALLOWED_MISSILE_WEAPON_PARAMETER:
			{
				int offset = INTPARM(1) - FirstMissileID;
				Verify(offset < 64);
				int value = INTPARM(2);

				DWORD *data;
				if (offset >= 32)
				{
					offset -= 32;
					data = &params->m_allowedMissile[1];
				}
				else
				{	
					data = &params->m_allowedMissile[0];
				}

				if (value)
					*data |= (0x1 << offset);
				else
					*data &= ~(0x1 << offset);
			}
			app->VerifyAllPlayerVehicles();
			break;

		case ALLOWED_PROJECTILE_WEAPON_PARAMETER:
			{
				int offset = INTPARM(1) - FirstProjectileID;
				Verify(offset < 64);
				int value = INTPARM(2);

				DWORD *data;
				if (offset >= 32)
				{
					offset -= 32;
					data = &params->m_allowedProjectile[1];
				}
				else
				{	
					data = &params->m_allowedProjectile[0];
				}

				if (value)
					*data |= (0x1 << offset);
				else
					*data &= ~(0x1 << offset);
			}
			app->VerifyAllPlayerVehicles();
			break;

		case ALLOWED_GENERIC_SUBSYSTEM_PARAMETER:
			{
				int offset = INTPARM(1) - FirstGenericSubsystemID;
				Verify(offset < 64);
				int value = INTPARM(2);

				DWORD *data;
				if (offset >= 32)
				{
					offset -= 32;
					data = &params->m_allowedSubsystem[1];
				}
				else
				{	
					data = &params->m_allowedSubsystem[0];
				}

				if (value)
					*data |= (0x1 << offset);
				else
					*data &= ~(0x1 << offset);
			}
			app->VerifyAllPlayerVehicles();
			break;

		case GAME_LENGTH_PARAMETER:
			params->m_gameLength = INTPARM(1);
			break;

		case SERVER_RECYCLE_PARAMETER:
			params->m_serverRecycle = INTPARM(1);
			break;

		case RECYCLE_DELAY_PARAMETER:
			params->m_recycleDelay = INTPARM(1);
			
			if (!params->m_runDedicated)
				params->m_serverRecycle = 0;

			break;

		case PLAY_MISSION_REVIEW_PARAMETER:
			params->m_playMissionReview = INTPARM(1);
			break;

		case MAP_ID_PARAMETER:
			{
				params->m_mapID = INTPARM(1);
				
				
//				Str_Copy(params->m_mapName, MW4Shell::Instance->scenarios[params->m_mapID].missionName, 124);
				Str_Copy(params->m_mapName, MW4Shell::Instance->scenarios[params->m_mapID].longMissionName, 124);
				Str_Copy(params->m_scenarioName, MW4Shell::Instance->scenarios[params->m_mapID].scenarioName, 124);
				if (MW4Shell::Instance->scenarios[params->m_mapID].usermissions)
					Str_Copy(params->m_scenarioPath, "Resource\\Usermissions\\", 124);
				else
					Str_Copy(params->m_scenarioPath, "Resource\\Missions\\", 124);
				
				params->m_mapClientCRC = MWApplication::GetInstance()->CalculateMapMissionCRC(params->m_mapName);
                gos_NetSetAdvertItem(0, GAMELIST_KEY_MAP_TYPE, params->m_mapName);
			}
		
			break;

		case MAP_NAME_PARAMETER:
			STOP(("GetServerNetworkMissionParamater: MAP_NAME_PARAMETER NOT ALLOWED!!!!"));
			break;

		case SCENARIO_NAME_PARAMETER:
			STOP(("GetServerNetworkMissionParamater: SCENARIO_NAME_PARAMETER NOT ALLOWED!!!!"));
			break;

		case NIGHT_TIME_PARAMETER:
			params->m_isNight = INTPARM(1);
			break;

	
	

		case WEATHER_PARAMETER:
			params->m_weather = INTPARM(1);
			break;

		case RADAR_MODE_PARAMETER:
            if (CTCL_IsConsole()) {
                int n = INTPARM(1);
                switch(n) {
                case 1:
                case 2:
                case 3:
                    n--;
                    break;
                default:
                    n = 3;
                    break;
                }
                params->m_radarMode = n;
            } else {
			    params->m_radarMode = INTPARM(1);
            }
			break;

		case VISIBILITY_PARAMETER:
			params->m_visibility = INTPARM(1);
			break;

		case REPORTSTATS_PARAMETER:
			params->m_reportStats = INTPARM(1);
			break;

		case SERVER_CONNECTION_PARAMETER:
			STOP(("SetServerNetworkMissionParamater: SERVER_CONNECTION_PARAMETER NOT ALLOWED!!!!"));
			break;

		case SERVER_BANDWIDTH_PARAMETER:
			STOP(("SetServerNetworkMissionParamater: SERVER_BANDWIDTH_PARAMETER NOT ALLOWED!!!!"));
			break;

		case SERVER_CPU_PARAMETER:
			STOP(("SetServerNetworkMissionParamater: SERVER_CPU_PARAMETER NOT ALLOWED!!!!"));
			break;

		case SERVER_NAME_PARAMETER:
			{
				const char* server_name = STRPARM(1);
				Str_Copy(params->m_serverName, server_name, 256);
			}
			break;

		case SERVER_IP_PARAMETER:
			{
				const char* server_ip = STRPARM(1);
				Str_Copy(params->m_serverIP, server_ip, 256);
			}
			break;

		case DEAD_MECH_CANT_SEE_PARAMETER:
			params->m_deadMechCantSee = INTPARM(1);
			app->VerifyAllPlayerVehicles();
			break;

		case DEAD_MECH_CANT_SEE_OTHER_TEAM:
			params->m_deadMechCantSeeOtherTeam = INTPARM(1);
			break;

		case RULE_TYPE_PARAMETER:
			params->m_ruleType = INTPARM(1);
            //{
			//	char szGameType[256];
            //    // mdm - advertise the current game type
			//	_mbsncpy((unsigned char *)szGameType, (unsigned char *)GetRuleName( params->m_ruleType ), sizeof(szGameType));
            //    gos_NetSetAdvertItem(0, GAMELIST_KEY_GAME_TYPE, szGameType);
            //}
			MW4Shell::Instance->selectedScenario = -1;
			break;


		case ALLOW_DECAL_TRANSFER_PARAMETER:
			params->m_allowdecaltransfer = INTPARM(1);
			break;

		case USE_MAP_CYCLE_PARAMETER:
			params->m_useMapCycle = INTPARM(1);
			break;

		case PURE_MAP_CYCLE_PARAMETER:
			params->m_pureMapCycle = INTPARM(1);
			break;

		case TEAM_ALLOWED_PARAMETER:
			params->m_teamAllowed = INTPARM(1);
			break;

		case TEAM_COUNT_PARAMETER:
			params->m_teamCount = INTPARM(1);
			Clamp(params->m_teamCount, 2, 8);
			break;

		case SCENARIO_INFO_PARAMATER:
			STOP(("Paramater Not Allowed to be Set : SCENARIO_INFO_PARAMATER"));
			break;


		case TEAM_PARAMETER:
			{
				int team = INTPARM(1);
				int sub_param = INTPARM(2);

				Verify (team >= 0);
				Verify (team < 8);

				switch(sub_param)
				{
					case TEAM_MAX_PLAYERS:
						params->m_teamParams[team].m_maxPlayersOnTeam = INTPARM(3);
						break;
					
					case TEAM_MIN_TONNAGE:
						params->m_teamParams[team].m_minimumTonnage = INTPARM(3);
						app->VerifyAllPlayerVehicles();
						break;
					
					case TEAM_MAX_TONNAGE:
						params->m_teamParams[team].m_maximumTonnage = INTPARM(3);
						app->VerifyAllPlayerVehicles();
						break;

					case TEAM_TOTAL_MAX_TONNAGE:
						params->m_teamParams[team].m_maximumTotalTonnage = INTPARM(3);
						app->VerifyAllPlayerVehicles();
						break;
					
					case TEAM_SKIN:
						params->m_teamParams[team].m_skin = INTPARM(3);
						break;
					
					case TEAM_ALIGNMENT:
						params->m_teamParams[team].m_alignment = INTPARM(3);
						break;
					
					case TEAM_ALLOWED_MECH_PARAMETER:
						{
							int offset = INTPARM(3) - FirstMechID;
							Verify(offset < 64);
							int value = INTPARM(4);

							DWORD *data;
							if (offset >= 32)
							{
								offset -= 32;
								data = &params->m_teamParams[team].m_allowedMech[1];
							}
							else
							{	
								data = &params->m_teamParams[team].m_allowedMech[0];
							}

							if (value)
								*data |= (0x1 << offset);
							else
								*data &= ~(0x1 << offset);
						}
						app->VerifyAllPlayerVehicles();
						break;
					
					case TEAM_ALLOWED_BEAM_WEAPON_PARAMETER:
						{
							int offset = INTPARM(3) - FirstBeamID;
							Verify(offset < 64);
							int value = INTPARM(4);

							DWORD *data;
							if (offset >= 32)
							{
								offset -= 32;
								data = &params->m_teamParams[team].m_allowedBeam[1];
							}
							else
							{	
								data = &params->m_teamParams[team].m_allowedBeam[0];
							}

							if (value)
								*data |= (0x1 << offset);
							else
								*data &= ~(0x1 << offset);
						}
						app->VerifyAllPlayerVehicles();
						break;
					
					case TEAM_ALLOWED_MISSILE_WEAPON_PARAMETER:
						{
							int offset = INTPARM(3) - FirstMissileID;
							Verify(offset < 64);
							int value = INTPARM(4);

							DWORD *data;
							if (offset >= 32)
							{
								offset -= 32;
								data = &params->m_teamParams[team].m_allowedMissile[1];
							}
							else
							{	
								data = &params->m_teamParams[team].m_allowedMissile[0];
							}

							if (value)
								*data |= (0x1 << offset);
							else
								*data &= ~(0x1 << offset);
						}
						app->VerifyAllPlayerVehicles();
						break;
					
					case TEAM_ALLOWED_PROJECTILE_WEAPON_PARAMETER:
						{
							int offset = INTPARM(3) - FirstProjectileID;
							Verify(offset < 64);
							int value = INTPARM(4);

							DWORD *data;
							if (offset >= 32)
							{
								offset -= 32;
								data = &params->m_teamParams[team].m_allowedProjectile[1];
							}
							else
							{	
								data = &params->m_teamParams[team].m_allowedProjectile[0];
							}

							if (value)
								*data |= (0x1 << offset);
							else
								*data &= ~(0x1 << offset);
						}
						app->VerifyAllPlayerVehicles();
						break;
					
					case TEAM_ALLOWED_GENERIC_SUBSYSTEM_PARAMETER:
						{
							int offset = INTPARM(3) - FirstGenericSubsystemID;
							Verify(offset < 64);
							int value = INTPARM(4);

							DWORD *data;
							if (offset >= 32)
							{
								offset -= 32;
								data = &params->m_teamParams[team].m_allowedSubsystem[1];
							}
							else
							{	
								data = &params->m_teamParams[team].m_allowedSubsystem[0];
							}

							if (value)
								*data |= (0x1 << offset);
							else
								*data &= ~(0x1 << offset);
						}
						app->VerifyAllPlayerVehicles();
						break;

					default :
						STOP(("UNKOWN TEAM PARAMETER TYPE"));

				}

			}
			break;

	}


	app->parametersDirty = true;
	


	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::GetLocalNetworkMissionParamater(void * instance, int numParms, void **data)
{
	
	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();

	return GetNetworkMissionParamater(params, numParms, data);

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::GetServerNetworkMissionParamater(void * instance, int numParms, void **data)
{
	
	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	NetMissionParameters::MWNetMissionParameters *params = app->GetServerNetParams();

	return GetNetworkMissionParamater(params, numParms, data);


}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::GetNetworkMissionParamater(NetMissionParameters::MWNetMissionParameters *params, int numParms, void **data)
{
	int param_number = INTPARM(0);

	switch (param_number)
	{
		case MAX_PLAYERS_PARAMETER:
			return params->m_maxPlayers;

		case MAX_BOTS_PARAMETER:
			return params->m_maxBots;

		case DEDICATED_SERVER_PARAMETER:
			return params->m_runDedicated;

		case CLOSED_GAME_PARAMETER:		
			return params->m_closedGame;
			
		case PLAYER_LIMIT_PARAMETER:
			return params->m_playerLimit;

		case JOIN_IN_PROGRESS_PARAMETER:
			return params->m_joinInProgress;
			
		case JOIN_IN_PROGRESS_CUTOFF_PARAMETER:
			return params->m_joinInProgressCutOff;
			
		case JOIN_IN_PROGRESS_CUTOFF_TIME_PARAMETER:
			return params->m_joinInProgressCutOffTime;
			
		case HEAT_PARAMETER:
			return params->m_heatOn;

		case KILL_LIMIT_PARAMETER:
			return params->m_killLimit;
			
		case KILL_LIMIT_NUMBER_PARAMETER:
			return params->m_killLimitNumber;
			
		case RESPAWN_LIMIT_PARAMETER:
			return params->m_respawnLimit;
			
		case RESPAWN_LIMIT_NUMBER_PARAMETER:
			return params->m_respawnLimitNumber;
			
		case FORCE_RESPAWN_PARAMETER:
			return params->m_forceRespawn;
			
		case SPLASH_ON_PARAMETER:
			return params->m_splashOn;
			
		case WEAPON_JAM_PARAMETER:
			return params->m_weaponjamOn;

		case AMMO_BAY_FIRE_PARAMETER:
			return params->m_ammobayfireOn;

		case ADVANCE_MODE_PARAMETER:
			return params->m_advancemodeOn;

		case ARMOR_MODE_PARAMETER:
			return params->m_armormodeOn;

		case SPLSH_PERCENTAGE_PARAMETER:
			return params->m_splashPercentage;
			
		case UNLIMITED_AMMO_PARAMETER:
			return params->m_unlimitedAmmo;
			
		case FRIENDLY_FIRE_PERCENTGE_PARAMETER:
			return params->m_friendlyFirePercentage;
			
		case ALLOW_ZOOM_PERCENTAGE_PARAMETER:
			return params->m_allowZoom;
			
		case ALLOW_3RD_PERSON_PARAMETER:
			return params->m_allow3rdPerson;
			
		case ALLOW_AUTO_AIM_PARAMETER:
			return params->m_allowAutoAim;
			
		case ALLOW_DEAD_CHAT_PARAMETER:
			return params->m_allowDeadToChat;
			
		case INUVNERABLE_DROP_PARAMETER:
			return params->m_invulnerableDrop;
			
		case ONLY_STOCK_MECH_PARAMETER:
			return params->m_onlyStockMech;

		case MINIMUM_TONNAGE_PARAMETER:
			return params->m_minimumTonnage;

		case MAXIMUM_TONNAGE_PARAMETER:
			return params->m_maximumTonnage;




		case ALLOWED_MECH_PARAMETER:
			{
				int offset = INTPARM(1) - FirstMechID;
				Verify(offset < 64);
				
				DWORD *data;
				if (offset >= 32)
				{
					offset -= 32;
					data = &params->m_allowedMech[1];
				}
				else
				{	
					data = &params->m_allowedMech[0];
				}

				return (*data & (0x1 << offset))?1:0;
			}

		case ALLOWED_BEAM_WEAPON_PARAMETER:
			{
				int offset = INTPARM(1) - FirstBeamID;
				Verify(offset < 64);
				
				DWORD *data;
				if (offset >= 32)
				{
					offset -= 32;
					data = &params->m_allowedBeam[1];
				}
				else
				{	
					data = &params->m_allowedBeam[0];
				}

				return (*data & (0x1 << offset))?1:0;
			}

		case ALLOWED_MISSILE_WEAPON_PARAMETER:
			{
				int offset = INTPARM(1) - FirstMissileID;
				Verify(offset < 64);
				
				DWORD *data;
				if (offset >= 32)
				{
					offset -= 32;
					data = &params->m_allowedMissile[1];
				}
				else
				{	
					data = &params->m_allowedMissile[0];
				}

				return (*data & (0x1 << offset))?1:0;
			}

		case ALLOWED_PROJECTILE_WEAPON_PARAMETER:
			{
				int offset = INTPARM(1) - FirstProjectileID;
				Verify(offset < 64);
				
				DWORD *data;
				if (offset >= 32)
				{
					offset -= 32;
					data = &params->m_allowedProjectile[1];
				}
				else
				{	
					data = &params->m_allowedProjectile[0];
				}

				return (*data & (0x1 << offset))?1:0;
			}

		case ALLOWED_GENERIC_SUBSYSTEM_PARAMETER:
			{
				int offset = INTPARM(1) - FirstGenericSubsystemID;
				Verify(offset < 64);
				
				DWORD *data;
				if (offset >= 32)
				{
					offset -= 32;
					data = &params->m_allowedSubsystem[1];
				}
				else
				{	
					data = &params->m_allowedSubsystem[0];
				}

				return (*data & (0x1 << offset))?1:0;
			}

		case GAME_LENGTH_PARAMETER:
			return params->m_gameLength;
			
		case SERVER_RECYCLE_PARAMETER:
			return params->m_serverRecycle;
			
		case RECYCLE_DELAY_PARAMETER:
			return params->m_recycleDelay;
			
		case PLAY_MISSION_REVIEW_PARAMETER:
			return params->m_playMissionReview;
		
		case MAP_ID_PARAMETER:
			return params->m_mapID;

		case MAP_NAME_PARAMETER:
			//Str_Copy(MW4Shell::Instance->m_iaMissionName, params->m_mapName, 256);

			if (params->m_mapName[0] != '\0')
			{

				char **game_name  = &STRPARM(1);

				FREEANDNULL(*game_name);
				*game_name = (char *)gos_Malloc(256);
				::memset(*game_name, 0, 256);

				_mbscpy((unsigned char *)*game_name, (const unsigned char *)&params->m_mapName[0]);


				return 1;
			}
			

			return 0;

		case SCENARIO_NAME_PARAMETER:
			{
				MString scenario_name;
				//scenario_name = params->m_mapName;
				//scenario_name += " : ";
				//scenario_name += params->m_scenarioName;
				scenario_name = params->m_scenarioName;

				Str_Copy(MW4Shell::Instance->m_iaMissionName, (char*)scenario_name, 256);
				MWApplication::GetInstance()->m_currentMissionName = scenario_name;
			}
			return 0;

		case SCENARIO_PATH_PARAMETER:
			{
				char** scenario_path = &STRPARM(1);

				FREEANDNULL(*scenario_path);
				*scenario_path = (char*) gos_Malloc(256);
	
				(*scenario_path)[0] = '\0';

				char file[256];
				Str_Copy(file, params->m_scenarioPath, 256);
				Str_Cat(file, params->m_mapName, 256);
				Str_Cat(file, ".tga", 256);

				if (gos_DoesFileExist(file) == 0)
					(*scenario_path)[0] = '\0';
				else
					Str_Copy(*scenario_path, params->m_scenarioPath, 256);
			}
			return 0;			

		case SERVER_NAME_PARAMETER:
			Str_Copy(MW4Shell::Instance->m_serverName, params->m_serverName, 256);	
			return 0;

		case SERVER_IP_PARAMETER:
			Str_Copy(MW4Shell::Instance->m_serverIP, params->m_serverIP, 256);	
			return 0;

		case NIGHT_TIME_PARAMETER:
			return params->m_isNight;

		

		case WEATHER_PARAMETER:
			return params->m_weather;
		
		case RADAR_MODE_PARAMETER:
            if (CTCL_IsConsole()) {
                int n = params->m_radarMode;
                switch(n) {
                case 0:
                case 1:
                case 2:
                    return n + 1;
                default:
                    return 0;
                }
            } else {
			    return params->m_radarMode;
            }

		case VISIBILITY_PARAMETER:
			return params->m_visibility;
		
		case REPORTSTATS_PARAMETER:
			return params->m_reportStats;
		
		case SERVER_CONNECTION_PARAMETER:
			return params->m_serverConnection;

		case SERVER_BANDWIDTH_PARAMETER:
			return  params->m_serverBandwidth;

		case SERVER_CPU_PARAMETER:
			Str_Copy(MW4Shell::Instance->m_serverCPU, params->m_serverCPU, 256);
			return 0;

		case DEAD_MECH_CANT_SEE_PARAMETER:
			return params->m_deadMechCantSee;

		case DEAD_MECH_CANT_SEE_OTHER_TEAM:
			return params->m_deadMechCantSeeOtherTeam;

		case RULE_TYPE_PARAMETER:
			return params->m_ruleType;

		case ALLOW_DECAL_TRANSFER_PARAMETER:
			return params->m_allowdecaltransfer;

		case USE_MAP_CYCLE_PARAMETER:
			return params->m_useMapCycle;

		case PURE_MAP_CYCLE_PARAMETER:
			return params->m_pureMapCycle;

		case TEAM_ALLOWED_PARAMETER:
			return params->m_teamAllowed;

		case TEAM_COUNT_PARAMETER:
			return params->m_teamCount;
	
		case SCENARIO_INFO_PARAMATER:
		{
			//return params->m_teamCount;
			
			if (params->m_scenarioText[0] != '\0')
			{

				char **game_name  = &STRPARM(1);

				FREEANDNULL(*game_name);
				*game_name = (char *)gos_Malloc(1024);
				::memset(*game_name, 0, 1024);

				_mbscpy((unsigned char *)*game_name, (unsigned const char *)&params->m_scenarioText[0]);
				return true;
			}
			else
			{
			
				return false;
			}
		}


		case TEAM_PARAMETER:
			{
				int team = INTPARM(1);
				int sub_param = INTPARM(2);

				Verify (team >= 0);
				Verify (team < 8);

				switch(sub_param)
				{
					case TEAM_MAX_PLAYERS:
						return params->m_teamParams[team].m_maxPlayersOnTeam;
					
					case TEAM_MIN_TONNAGE:
						return params->m_teamParams[team].m_minimumTonnage;
						
					case TEAM_MAX_TONNAGE:
						return params->m_teamParams[team].m_maximumTonnage;
					
					case TEAM_TOTAL_MAX_TONNAGE:
						return params->m_teamParams[team].m_maximumTotalTonnage;
										
					case TEAM_SKIN:

						{
						
							char team_prefix = (char)params->m_teamParams[team].m_skin;
							int skin_id = 0;

							Check_Object(MWApplication::GetInstance()->m_skinsTable);


							MWTable::TableIterator *iterator = MWApplication::GetInstance()->m_skinsTable->MakeTableIterator();
							MWTableEntry *entry = NULL;

							while ((entry = iterator->ReadAndNext()) != NULL)
							{
								
								char *prefix = entry->GetData();
							
								if (team_prefix == *prefix)
								{
									delete iterator;
									return skin_id;
								}
								++skin_id;

							}

							delete iterator;
							return 0;
						}

						//return params->m_teamParams[team].m_skin;
						
					
					case TEAM_ALIGNMENT:
						return params->m_teamParams[team].m_alignment;
						
					
					case TEAM_ALLOWED_MECH_PARAMETER:
						{
							int offset = INTPARM(3) - FirstMechID;
							Verify(offset < 64);
							
							DWORD *data;
							if (offset >= 32)
							{
								offset -= 32;
								data = &params->m_teamParams[team].m_allowedMech[1];
							}
							else
							{	
								data = &params->m_teamParams[team].m_allowedMech[0];
							}

							return (*data & (0x1 << offset))?1:0;
						}
					
					case TEAM_ALLOWED_BEAM_WEAPON_PARAMETER:
						{
							int offset = INTPARM(3) - FirstBeamID;
							Verify(offset < 64);
							
							DWORD *data;
							if (offset >= 32)
							{
								offset -= 32;
								data = &params->m_teamParams[team].m_allowedBeam[1];
							}
							else
							{	
								data = &params->m_teamParams[team].m_allowedBeam[0];
							}

							return (*data & (0x1 << offset))?1:0;
						}
					
					case TEAM_ALLOWED_MISSILE_WEAPON_PARAMETER:
						{
							int offset = INTPARM(3) - FirstMissileID;
							Verify(offset < 64);
							
							DWORD *data;
							if (offset >= 32)
							{
								offset -= 32;
								data = &params->m_teamParams[team].m_allowedMissile[1];
							}
							else
							{	
								data = &params->m_teamParams[team].m_allowedMissile[0];
							}

							return (*data & (0x1 << offset))?1:0;
						}
					
					case TEAM_ALLOWED_PROJECTILE_WEAPON_PARAMETER:
						{
							int offset = INTPARM(3) - FirstProjectileID;
							Verify(offset < 64);
							
							DWORD *data;
							if (offset >= 32)
							{
								offset -= 32;
								data = &params->m_teamParams[team].m_allowedProjectile[1];
							}
							else
							{	
								data = &params->m_teamParams[team].m_allowedProjectile[0];
							}

							return (*data & (0x1 << offset))?1:0;
						}
					
					case TEAM_ALLOWED_GENERIC_SUBSYSTEM_PARAMETER:
						{
							int offset = INTPARM(3) - FirstGenericSubsystemID;
							Verify(offset < 64);
							
							DWORD *data;
							if (offset >= 32)
							{
								offset -= 32;
								data = &params->m_teamParams[team].m_allowedSubsystem[1];
							}
							else
							{	
								data = &params->m_teamParams[team].m_allowedSubsystem[0];
							}

							return (*data & (0x1 << offset))?1:0;
						}

					default :
						STOP(("UNKOWN TEAM PARAMETER TYPE"));

				}
			}
			break;

	}

	return -1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::NetConnectedToServer(void * instance,int, void *[])
{
	if (Connection::Server != NULL)
		return 1;
	
	return 0;
}

// DBCS-safe strncpy() that guarantees NUL terminate
//extern "C" unsigned int _stdcall IsDBCSLeadByte(BYTE TestChar);
static char* mbs_strncpy( char *strDest, const char *strSource, size_t count )
{
	char* pRet = strncpy(strDest, strSource, count);
	if (strDest) {
		strDest[count - 1] = 0;
		char* p = strDest;
		while (*p) {
			if (IsDBCSLeadByte(*p)) {
				if (p[1] == 0) {
					*p = 0;
					break;
				}
				p++;
			}
			p++;
		}
	}
	return pRet;
}

//========================================================================
// This callback checks to make sure the game advertised properly with
// GUN.  If it didn't, a message box is displayed.  This function is
// designed to be called only fromt he Host lobby script.
//========================================================================

double lastCheck = 0.0;

int MW4Shell::CheckGUNAdvertise(void *instance, int, void*[])
{

	int status = GetGUNRegStatus();

	if (status != GRS_SUCCESS)
	{
		if (gos_GetElapsedTime() - lastCheck > 10.0)
		{
			lastCheck = gos_GetElapsedTime();
			int ret = Mech4ReconnectGame();
	
			MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
			NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();
			char szGameType[256];
			mbs_strncpy(szGameType, GetRuleName( params->m_ruleType ), sizeof(szGameType));
			gos_NetSetAdvertItem(0, GAMELIST_KEY_GAME_TYPE, szGameType);
            gos_NetSetAdvertItem(0, GAMELIST_KEY_MAP_TYPE, params->m_mapName);
			return ret;
		}
		else
		{
			return false;
		}
	}


	return true;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::NetClientVehicleAccepted(void *instance, int, void*[])
{
	return MWApplication::GetInstance()->localVehicelAccepted;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetVehicleRejectionReason(void * instance, int numParms, void **data)
{

	int error = INTPARM(0);
	int *parameter = INTARRAYPARAM(1);

	*parameter = 0;

	MWApplication *app = MWApplication::GetInstance();

	if (error >= app->lastErrorCount)
		return NO_BUILDERROR;


	*parameter = app->lastErrorsParameter[error];
	return app->lastErrors[error];
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetVehicleRejectionReasonCount(void * instance, int numParms, void **data)
{

	MWApplication *app = MWApplication::GetInstance();

	return app->lastErrorCount;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetBotVehicleRejectionReason(void * instance, int numParms, void **data)
{

	int error = INTPARM(0);
	int *parameter = INTARRAYPARAM(1);

	*parameter = 0;

	MWApplication *app = MWApplication::GetInstance();

	if (error >= app->lastBotErrorCount)
		return NO_BUILDERROR;


	*parameter = app->lastBotErrorsParameter[error];
	return app->lastBotErrors[error];
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetBotVehicleRejectionReasonCount(void * instance, int numParms, void **data)
{

	MWApplication *app = MWApplication::GetInstance();

	return app->lastBotErrorCount;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::ClearLocalRestrictions(void * instance, int numParms, void **data)
{

	MWApplication *app = MWApplication::GetInstance();

	NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();


	params->m_allowedMech[0] = 0xffffffff;
	params->m_allowedBeam[0] = 0xffffffff;
	params->m_allowedMissile[0] = 0xffffffff;
	params->m_allowedProjectile[0] = 0xffffffff;
	params->m_allowedSubsystem[0] = 0xffffffff;
	params->m_allowedMech[1] = 0xffffffff;
	params->m_allowedBeam[1] = 0xffffffff;
	params->m_allowedMissile[1] = 0xffffffff;
	params->m_allowedProjectile[1] = 0xffffffff;
	params->m_allowedSubsystem[1] = 0xffffffff;


	
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::CheckForLocalRestrictions(void * instance, int numParms, void **data)
{

	MWApplication *app = MWApplication::GetInstance();

	NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();

	int count = 0;

	count += (params->m_allowedMech[0]==0xffffffff)?0:1;
	count += (params->m_allowedBeam[0]==0xffffffff)?0:1;
	count += (params->m_allowedMissile[0]==0xffffffff)?0:1;
	count += (params->m_allowedProjectile[0]==0xffffffff)?0:1;
	count += (params->m_allowedSubsystem[0]==0xffffffff)?0:1;

	count += (params->m_allowedMech[1]==0xffffffff)?0:1;
	count += (params->m_allowedBeam[1]==0xffffffff)?0:1;
	count += (params->m_allowedMissile[1]==0xffffffff)?0:1;
	count += (params->m_allowedProjectile[1]==0xffffffff)?0:1;
	count += (params->m_allowedSubsystem[1]==0xffffffff)?0:1;


	if (count)
		return 1;

	return 0;
	
}

int MW4Shell::GetClientReady(void * instance,int, void *[])
{
	MWApplication *app = MWApplication::GetInstance();
	return app->GetClientReady();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


int MW4Shell::SetClientReady(void * instance,int, void *[])
{
	
	MWApplication *app = MWApplication::GetInstance();
	app->SetClientReady();

	return 1;

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


int MW4Shell::SetClientUnready(void * instance,int, void *[])
{
	
	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	app->SetClientUnready();

	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::RequestTeam(void * instance,int, void *data[])
{

	int team = (int)*((int **)data[0]);
	
	if (team < 0)
		return 0;

	if (team > 8)
		return 0;

	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	app->SendTeamRequest(team);

	return 1;

}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::SendVehicleRequest(void * instance,int, void *[])
{
    if (!CTCL_IsConsole()) {
	if (Connection::Server != NULL)
	{
		MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
		app->SendVehicleRequest();
	}
    }

	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::GetMechName(void * instance,int numParms,void** data)
{
	int mechID = (int)*((int **)data[0]);
	if (mechID >= numMechPrototypes)
		return 0;

	if (*((char **)data[1]))
		gos_Free(*((char **)data[1]));
	*((char **) data[1]) = (char *)gos_Malloc(128);
	strcpy(*((char **) data[1]), mechPrototypeNames[mechID]);

	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::SelectMech(void * instance,int numParms,void** data)
{
	int vID = (int)*((int **)data[0]);
	if (vID >= numMechPrototypes)
		return 0;

	vehicleID = vID;

	gos_PushCurrentHeap(MechWarrior4::Heap);
	if (vehicleID >= 0)
		Instance->vehicleInstanceFile = mechPrototypeFilenames[vehicleID];
	gos_PopCurrentHeap();

	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//



int MW4Shell::SelectSkin(void * instance,int numParms,void** data)
{
    if (CTCL_IsConsole())
        return 1;
	
	int skin_id = INTPARM(0);

	Check_Object(MWApplication::GetInstance()->m_skinsTable);

	if (skin_id > MWApplication::GetInstance()->m_skinsTable->GetTableSize())
	{
		skin_id = 0;
	}


	MWTable::TableIterator *iterator = MWApplication::GetInstance()->m_skinsTable->MakeTableIterator();


	MWTableEntry *entry = NULL;

	for (int i = 0; i < skin_id; ++i)
	{
		iterator->Next();	
	}

	entry = iterator->ReadAndNext();


	if (entry != NULL)
	{
		char *prefix = entry->GetData();
		MW4Shell::Instance->m_skinPrefix = *prefix;
	}
	else
	{
		MW4Shell::Instance->m_skinPrefix = DefaultSkinPrefix;
	}

	// if our skin doesnt match we need to tell the server
	if (MWApplication::GetInstance()->servedConnectionData[Connection::Local->GetID()].pilotSkins != MW4Shell::Instance->m_skinPrefix )
	{

		MWApplication::GetInstance()->servedConnectionData[Connection::Local->GetID()].pilotSkins = MW4Shell::Instance->m_skinPrefix;

		MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
		app->SendVehicleRequest();	
	}

	delete iterator;

	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::GetSavedGameCount(void * instance, int, void *[])
{
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::GetSavedGameName(void * instance,int numParms,void** data)
{
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::LoadSavedGame(void * instance,int numParms,void** data)
{
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::SetShellCommand(void * instance,int numParms,void** type)
{
	Instance->shellCommand = int(type[0]);

	//SPEWALWAYS(("jerryeds", "SHELL COMMAND : %d", Instance->shellCommand));

	switch (Instance->shellCommand)
	{
		case ExitToWindowsShellCommand:
		case StartSinglePlayerGameCommand:
		case StartNetworkShellsCommand:
		case StartNetworkGameCommand:
		case ExitMissionCommand:
		case DisconnectCommand:
		case DisconnectLobbyCommand:
		case ExitToMainMenuCommand:
		case ResumeMissionCommand:
		case SetPauseOptionResCommand:
		case UnsetPauseOptionResCommand:
			break;
	default:
		return 0;
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::LoadQuickSave(void* instance, int, void *[])
{
	Adept::ReceiverDataMessageOf<int>	message(Application::LoadQuickGameMessageID,
												sizeof(Adept::ReceiverDataMessageOf<int>),
												0,
												0,
												NULL);

	Application::GetInstance()->Receive(&message);
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::SaveQuickSave(void* instance, int, void *[])
{
	Adept::ReceiverDataMessageOf<int>	message(Application::SaveQuickGameMessageID,
												sizeof(Adept::ReceiverDataMessageOf<int>),
												0,
												0,
												NULL);

	Application::GetInstance()->Receive(&message);
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::SetVideoRes(void * instance, int numParms, void** data)
{
	int res = int(data[0]);

	switch (res)
	{
		case VIDEORES_600_480:
			gos_SetScreenMode(640,480,Environment.bitDepth,Environment.FullScreenDevice);
			break;
		case VIDEORES_800_600:
			gos_SetScreenMode(800,600,Environment.bitDepth,Environment.FullScreenDevice);
			break;
		case VIDEORES_1024_768:
			gos_SetScreenMode(1024,768,Environment.bitDepth,Environment.FullScreenDevice);
			break;
		default:
			return 0;
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::ServerStatsScale(void * instance,int numParms,void* data[])
{

	Check_Object(Network::GetInstance());

	int total = 0;

	for (int i = 0; i < Network::NetStatCount-4; ++i)
	{
		total += Network::GetInstance()->netStatCollector[i].GetPublishedStatTotal();
	}

	if (total > ServerScale)
	{
		ServerScale = 1024;
		while (total > ServerScale)
			ServerScale = ServerScale * 2;
	}
	else
	{
		if (total < (ServerScale*0.5f))
		{
			if (gos_GetElapsedTime() - TimeToLowerServerScale > 3.0f)
			{
				ServerScale = 1024;
				while (total > ServerScale)
					ServerScale = ServerScale * 2;
			}
		}
		else
		{
			TimeToLowerServerScale = gos_GetElapsedTime();
		}
	}

	return ServerScale;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::ClientStatsScale(void * instance,int numParms,void* data[])
{

	Check_Object(Network::GetInstance());

	int total = 0;	
	for (int player_id = 0; player_id < Maximum_Players; ++player_id)
	{
		int sub_total = 0;
		for (int stat_id = 0; stat_id < Network::NetStatCount-4; ++stat_id)
		{
			sub_total += Network::GetInstance()->netStatCollector[stat_id].GetPublishedStat(player_id);
		}

		if (sub_total > total)
		{
			total = sub_total;
		}
	}

	

	if (total > ClientScale)
	{
		ClientScale = 1024;
		while (total > ClientScale)
			ClientScale = ClientScale * 2;
	}
	else
	{
		if (total < (ClientScale*0.5f))
		{
			if (gos_GetElapsedTime() - TimeToLowerClientScale > 5.0f)
			{
				ClientScale = 1024;
				while (total > ClientScale)
					ClientScale = ClientScale * 2;
			}
		}
		else
		{
			TimeToLowerClientScale = gos_GetElapsedTime();
		}
	}

	return ClientScale;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::ServerStatsDirty(void * instance,int numParms,void* data[])
{

	Check_Object(Network::GetInstance());

	bool dirty = false;
	for (int i = 0; i < Network::NetStatCount; ++i)
	{
		if (Network::GetInstance()->netStatCollector[i].IsDirty())
		{
			dirty = true;
			break;
		}
	}

	return dirty;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::ServerCleanDirtyFlag(void * instance,int numParms,void* data[])
{

	Check_Object(Network::GetInstance());

	for (int i = 0; i < Network::NetStatCount; ++i)
	{
		Network::GetInstance()->netStatCollector[i].ClearDirty();
	}

	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetCurrentGameName(void * instance,int numParms,void* data[])
{
	Check_Object(Network::GetInstance());
	Check_Object(Application::GetInstance());

	if (*((char **)data[0])) gos_Free(*((char **)data[0]));
		*((char **) data[0]) = (char *)gos_Malloc(128);
		strcpy(*((char **) data[0]), Network::GetInstance()->GetGameName());

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetCurrentMissionName(void * instance,int numParms,void* data[])
{
	Check_Object(Network::GetInstance());
	Check_Object(Application::GetInstance());

	Stuff::MString short_mission_name;
	Stuff::MString mission_name = MWApplication::GetInstance()->GetMissionName();
	short_mission_name = mission_name.StripDirectory().StripExtension();


	if (*((char **)data[0])) gos_Free(*((char **)data[0]));
		*((char **) data[0]) = (char *)gos_Malloc(128);
		strcpy(*((char **) data[0]), short_mission_name);

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayerCount(void * instance,int numParms,void* data[])
{
	Check_Object(Network::GetInstance());

	return Maximum_Players;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//



int _stdcall MW4Shell::IsPlayerValid(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int player_number = (int)*((int **)data[0]);
	
	if (player_number < 2)
		return 0;
	if (player_number >= Maximum_Players)
		return 0;

	Connection	*connection = Network::GetInstance()->GetConnection(player_number);

	if (connection == NULL)
		return 0;

	return 1;

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayerName(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int player_number = (int)*((int **)data[0]);
	if (player_number < 0)
		return 0;
	if (player_number >= Maximum_Players)
		return 0;

	Connection	*connection = Network::GetInstance()->GetConnection(player_number);
	if (connection == NULL)
		return 0;

	if (*((char **)data[1])) gos_Free(*((char **)data[1]));
	*((char **) data[1]) = (char *)gos_Malloc(256);
	strcpy(*((char **) data[1]), connection->GetConnectionName());



	return 1;
}





//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//





int _stdcall MW4Shell::GetStatisticsCount(void * instance,int numParms,void* data[])
{
	// skip the first two from the stat trackers...
	return Network::NetStatCount - 4;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetStatisticName(void * instance,int numParms,void* data[])
{

	Check_Object(Network::GetInstance());

	int stat_number = (int)*((int **)data[0]);
	
	if (stat_number > Network::NetStatCount)
		return 0;

	if (stat_number < 0)
		return 0;

	// all the stats are done together so we can just use one of thier
	// index to find the mech...
	

	if (*((char **)data[1])) gos_Free(*((char **)data[1]));
	*((char **) data[1]) = (char *)gos_Malloc(128);
	strcpy(*((char **) data[1]), Network::GetInstance()->netStatCollector[stat_number].GetName());


	return 1;
}	

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetStatisticbps(void * instance,int numParms,void* data[])
{

	int stat_number = (int)*((int **)data[0]);
	
	if (stat_number > Network::NetStatCount)
		return 0;

	if (stat_number < 0)
		return 0;


	int player_number = (int)*((int **)data[1]);
	
	if (player_number > Maximum_Players)
		return 0;
	if (player_number < -1)
		return 0;



	if (player_number == -1)
	{
		return Network::GetInstance()->netStatCollector[stat_number].GetPublishedStatTotal();
	}

	return Network::GetInstance()->netStatCollector[stat_number].GetPublishedStat(player_number);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetStatisticLifeTimeTotal(void * instance,int numParms,void* data[])
{

	int stat_number = (int)*((int **)data[0]);
	
	if (stat_number > Network::NetStatCount)
		return 0;

	if (stat_number < -1)
		return 0;


	int player_number = (int)*((int **)data[1]);
	
	if (player_number > Maximum_Players)
		return 0;
	if (player_number < 0)
		return 0;


	if (player_number == -1)
	{
		return Network::GetInstance()->netStatCollector[stat_number].GetLifetimeTotal();
	}

	return Network::GetInstance()->netStatCollector[stat_number].GetPublishedStatLifetimeTotal(player_number);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayersbps(void * instance,int numParms,void* data[])
{

	int player_number = (int)*((int **)data[0]);
	
	if (player_number > Maximum_Players)
		return 0;
	if (player_number < -1)
		return 0;


	int total = 0;

	if (player_number == -1)
	{
		for (int i = 0; i < Network::NetStatCount-4; ++i)
		{
			total += Network::GetInstance()->netStatCollector[i].GetPublishedStatTotal();
		}
	}
	else
	{
		for (int i = 0; i < Network::NetStatCount-4; ++i)
		{
			total += Network::GetInstance()->netStatCollector[i].GetPublishedStat(player_number);
		}
	}



	return total;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayerPing(void * instance,int numParms,void* data[])
{

	int player_number = (int)*((int **)data[0]);
	
	
	if (player_number < 0)
		return 0;
	if (player_number >= Maximum_Players)
		return 0;


	return (int)MWApplication::GetInstance()->servedConnectionData[player_number].effectivePing;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayersIncommingPacketsPerSecond(void * instance,int numParms,void* data[])
{
	int player_number = (int)*((int **)data[0]);
	
	if (player_number < -1)
		return 0;
	if (player_number >= Maximum_Players)
		return 0;


	if (player_number == -1)
	{
		return Network::GetInstance()->netStatCollector[Network::IncomingPacketCountStat].GetPublishedStatTotal();
	}

	return Network::GetInstance()->netStatCollector[Network::IncomingPacketCountStat].GetPublishedStat(player_number);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayersOutgoingPacketsPerSecond(void * instance,int numParms,void* data[])
{

	int player_number = (int)*((int **)data[0]);
	
	if (player_number < -1)
		return 0;
	if (player_number >= Maximum_Players)
		return 0;


	if (player_number == -1)
	{
		return Network::GetInstance()->netStatCollector[Network::OutgoingPacketCountStat].GetPublishedStatTotal();
	}

	return Network::GetInstance()->netStatCollector[Network::OutgoingPacketCountStat].GetPublishedStat(player_number);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetGameTime(void * instance,int numParms,void* data[])
{

	

	MWMission *mission = Cast_Object(MWMission*, MWMission::GetInstance());
	Stuff::Scalar time = mission->GetEndMissionTime();
	
	int hours = (int)(time / 3600);
	time -= (hours * 3600);

	int minutes = (int)(time / 60);
	time -= (minutes * 60);

	int seconds = (int)(time);

	
	if (*((char **)data[0])) gos_Free(*((char **)data[0]));
	*((char **) data[0]) = (char *)gos_Malloc(128);
	

	char buffer[128];
	
	sprintf(buffer,"%02d:%02d:%02d", hours, minutes, seconds);

	strcpy(*((char **) data[0]), buffer);



	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetRealTime(void * instance,int numParms,void* data[])
{

	if (*((char **)data[0])) gos_Free(*((char **)data[0]));
	*((char **) data[0]) = (char *)gos_Malloc(128);
	

	strcpy(*((char **) data[0]), gos_GetFormattedTime());


	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetRealDate(void * instance,int numParms,void* data[])
{

	if (*((char **)data[0])) gos_Free(*((char **)data[0]));
	*((char **) data[0]) = (char *)gos_Malloc(128);
	

	strcpy(*((char **) data[0]), gos_GetFormattedDate( false));


	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::Shell_CallbackHandler(void* instance, int count, void* data[])
{
	Check_Pointer(Instance);

	switch(CALLBACKID)
	{
	case ShellGetDummyData:
		return Instance->GetDummyData(count, data);
	case ShellDataGetMissionNames:
		return Instance->GetMissionNames(count, data);
	case ShellInitIAScreen:
		return Instance->InitIAScreen();
	case ShellInitCampaignScreen:
		return Instance->InitCampaignScreen();
	case ShellInitMechLabScreen:
		return Instance->InitMechLabScreen();
	case ShellClearMechLabScreen:
		return Instance->ClearMechLab(1);
	case ShellDataGetMechs:
		return Instance->GetMechs(data, count);
	case ShellSetMech:
		return Instance->SetMech(data, count);
	case ShellInitMPScreen:
		return Instance->InitMPScreen();
	case ShellSetTime:
		return Instance->SetTime(data, count);
	case ShellStartCampaignMission:
		return Instance->StartCampaignMission();
	case ShellCampaignGetPilotData:
		return Instance->GetLancemates(data, count);
	case ShellCampaignSetPilotData:
		return Instance->SetLancemate(data, count);
	case ShellInitCampaignMechLab:
		return Instance->InitCampaignMechLab();
	case ShellCampaignSelectPilot:
		return Instance->SelectCurrentPilot(data, count);
	case ShellCampaignVerifyLaunchData:
		return Instance->VerifyLaunchData();
	case ShellCampaignGetPilotMechData:
		return Instance->GetPilotMechData(data, count);
	case  ShellCampaignGetMechs:
		return Instance->GetCampaignMechs(data, count);
	case ShellCampaignSetMech:
		return Instance->SetCampaignMech(data, count);
	case ShellCreateNewPilot:
		return Instance->CreateNewPilot(data, count);
	case ShellClonePilot:
		return Instance->ClonePilot(data, count);
	case ShellSelectPilot:
		return Instance->SelectPilot(data, count);
	case ShellDeletePilot:
		return Instance->DeletePilot(data, count);
	case ShellRenamePilot:
		return Instance->RenamePilot(data, count);
	case ShellGetPilotList:
		return Instance->GetPilotList(data, count);
	case ShellGetDifficultyLevel:
		return Instance->GetDifficultyLevel(data, count);
	case ShellSetDifficultyLevel:
		return Instance->SetDifficultyLevel(data, count);
	case ShellGetPilotName:
		return Instance->GetCurrentPilotName(data, count);
	case ShellCampaignGetLanceStats:
		return Instance->GetLanceStats(data, count);
	case ShellCampaignGetMechStats:
		return Instance->GetMechStats(data, count);
	case ShellCampaignGetMissionRegionCount:
		return Instance->GetMissionRegionCount(data, count);
	case ShellCampaignGetMissionRegionIDs:
		return Instance->GetMissionRegionIDs(data, count);
	case ShellCampaignGetMissionRegionData:
		return Instance->GetMissionRegionData(data, count);
	case ShellGetMovieFilename:
		return Instance->GetMovieFilename(data, count);
	case ShellAdvanceMovie:
		return Instance->AdvanceMovie(data, count);
	case ShellTriggerMovie:
		return Instance->TriggerMovie();
	case ShellCampaignSetMission:
		return Instance->SetCampaignMissionName(data, count);
	case ShellCampaignGetMissionNavCount:
		return Instance->GetMissionNavPointCount(data, count);
	case ShellCampaignGetMissionInfoCount:
		return Instance->GetMissionInfoPointCount(data, count);
	case ShellCampaignGetMissionDropCount:
		return Instance->GetMissionDropPointCount(data, count);
	case ShellCampaginGetMissionNavPoints:
		return Instance->GetMissionNavPoints(data, count);
	case ShellCampaginGetMissionInfoPoints:
		return Instance->GetMissionInfoPoints(data, count);
	case ShellCampaginGetMissionDropPoints:
		return Instance->GetMissionDropPoints(data, count);
	case ShellCampaignGetMissionGeneralInfoPoints:
		return Instance->GetMissionGeneralInfoPoints(data, count);
	case ShellCampaignGetOpData:
		return Instance->GetCampaignOpData(data, count);
	case ShellCampaignGetMissionData:
		return Instance->GetMissionData(data, count);
	case ShellOptionsGetToggleValue:
		return Instance->GetOptionsToggleValue(data, count);
	case ShellOptionsSetToggleValue:
		return Instance->SetOptionsToggleValue(data, count);
	case ShellOptionsGetSliderValue:
		return Instance->GetOptionsSliderValue(data, count);
	case ShellOptionsSetSliderValue:
		return Instance->SetOptionsSliderValue(data, count);
	case ShellSetOptionValue:
		return Instance->SetOptionsValue(data, count);
	case ShellGetOptionValue:
		return Instance->GetOptionsValue(data, count);
	case ShellCampaignGetMissionGeneralInfoCount:
		return Instance->GetGeneralInfoPointCount(data, count);
	case ShellSaveOptions:
		return Instance->SaveOptions();
	case ShellLoadDefaultOptions:
		return Instance->LoadDefaultOptions();
	case ShellDoesHavePilot:
		return Instance->DoesHavePilotLoaded(data, count);
	case ShellIASetMissionType:
		return Instance->SetIAMissionType(data, count);
	case ShellIASetLancemate:
		return Instance->SetIALancemate(data, count);
	case ShellIASetLancemateMech:
		return Instance->SetIALancemateMech(data, count);
	case ShellIAGetWaveMissions:
		return Instance->GetWaveMissions(data, count);
	case ShellIASetWaveMission:
		return Instance->SetWaveMission(data, count);
	case ShellIAAddMechToEnemyInWave:
		return Instance->AddMechToEnemyAI(data, count);
	case ShellIARemoveEnemyFromWave:
		return Instance->RemoveEnemyAIFromWave(data, count);
	case ShellIAGetWaveAITypes:
		return Instance->GetWaveAITypes(data, count);
	case ShellIASetEnemyWaveCount:
		return Instance->SetEnemyWaveCount(data, count);
	case ShellIASetEnemyCount:
		return Instance->SetEnemyCount(data, count);
	case ShellIASetWavePlayerRespawns:
		return Instance->SetWavePlayerRespawns(data, count);
	case ShellIAGetTrainingMissions:
		return Instance->GetTrainingMissions(data, count);
	case ShellIASetTrainingMission:
		return Instance->SetTrainingMission(data, count);
	case ShellIAGetEnemyChassis:
		return Instance->GetEnemyMechChassis(data, count);
	case ShellGetTimeOfDay:
		return Instance->GetTimeOfDay(data, count);
	case ShellSetIAMissionName:
		return Instance->SetIAMissionName(data, count);
	case ShellIAGetMissionMapInfo:
		return Instance->ShellIAGetMapInfo(data, count);
	case ShellIAGetDifficulty:
		return Instance->IAGetDifficulty(data, count);
	case ShellIASetDifficulty:
		return Instance->IASetDifficulty(data, count);
	case ShellIAGetWavePlayerRespawns:
		return Instance->IAGetWavePlayerRespawns(data, count);
	case ShellIAGetEnemyWaveCount:
		return Instance->IAGetEnemyWaveCount(data, count);
	case ShellIASetMasterTrial:
		return Instance->IASetupMasterTrials(data, count);
	case ShellIAGetMasterTrialMissions:
		return Instance->IAGetMasterTrialMissions(data, count);
	case ShellCampaignGetPlayerStatus:
		return Instance->CampaignGetPlayerStatus(data, count);
	case ShellCampaignGetLanceStatus:
		return Instance->CampaignGetLanceStatus(data, count);
	case ShellCampaignGetMechSalvage:
		return Instance->CampaignGetMechSalvage(data, count);
	case ShellCampaignGetWeaponSalvage:
		return Instance->CampaignGetWeaponSalvage(data, count);
	case ShellCampaignGetCampaignResults:
		return Instance->CampaignGetResults(data, count);
	case ShellExitDedicatedServer:
		return Instance->ExitDedicatedServer(data, count);
	case ShellDisconnectDedicatedServer:
		return Instance->DisconnectDedicatedServer(data, count);
	case ShellCampaignGetGames:
		return Instance->CampaignGetSavedGames(data, count);
	case ShellCampaignLoadGame:
		return Instance->CampaignLoadGame(data, count);
	case ShellControlSetDefault:
		return Instance->ControlSetDefault(data, count);
	case ShellControlAssignValue:
		return Instance->ControlAssignValue(data, count);
	case ShellControlAcceptChanges:
		return Instance->ControlAcceptChanges(data, count);
	case ShellControlCancelChanges:
		return Instance->ControlCancelChanges(data, count);
	case ShellControlGetMapping:
		return Instance->ControlGetMapping(data, count);
	case ShellControlGetValue:
		return Instance->ControlGetValue(data, count);
	case ShellControlScanKeyboard:
		return Instance->ControlScanKeyboard(data, count);
	case ShellIAGetResults:
		return Instance->IAGetResults(data, count);
	case ShellLoadMissionName:
		return Instance->GetLoadMissionName(data, count);
	case ShellIAGetMissionRegionData:
		return Instance->GetIAMissionRegionData(data, count);
	case ShellCampaignPlayIntro:
		return Instance->CampaignPlayIntro(data, count);
	case ShellCampaignPlayEnd:
		return Instance->CampaignPlayEnd(data, count);
	case ShellCampaignGetMechBars:
		return Instance->CampaignGetMechBars(data, count);
	case ShellIAGetStockMechs:
		return Instance->IAGetStockMechs(data, count);
	case ShellIAGetMechsWithEmpty:
		return Instance->IAGetMechsWithSpace(data, count);
	case ShellIAGetMechBars:
		return Instance->IAGetMechBars(data, count);
#if !defined(NO_MR)
	case MissionReviewSpeedUp:																				// these take no data
		return NMissionReview::SpeedUp ();
	case MissionReviewSlowDown:
		return NMissionReview::SlowDown ();
	case MissionReviewRewind:
		return NMissionReview::Rewind ();
	case MissionReviewPause:
		return NMissionReview::Pause ();
	case MissionReviewCenterOn:
		return NMissionReview::CenterOn (data,count);
#endif // !defined(NO_MR)
	case ShellIAMasterSetPlayerMech:
		return Instance->SetMasterTrialPlayerMech(data, count);
	case GetJoyStickNames:
		return Instance->ControlGetJoyStickNames(data, count);
	case GetJoyStickInvert:
		return Instance->ControlGetJoyStickInvert(data, count);
	case GetMouseInvert:
		return Instance->ControlGetMouseInvert(data, count);
	case GetJoyStick:
		return Instance->ControlGetJoyStick(data, count);
	case GetMouse:
		return Instance->ControlGetMouse(data, count);
	case GetJoyStickShift:
		return Instance->ControlGetJoyStickShift(data, count);
	case GetJoyListSelected:
		return Instance->ControlGetJoyListSelected(data, count);
	case SetJoyListSelected:
		return Instance->ControlSetJoyListSelected(data, count);
	case GetForce:
		return Instance->ControlGetForce(data, count);
	case SetForce:
		return Instance->ControlSetForce(data, count);
	case SetJoyStickInvert:
		return Instance->ControlSetJoyStickInvert(data, count);
	case SetMouseInvert:
		return Instance->ControlSetMouseInvert(data, count);
	case SetJoyStickShift:
		return Instance->ControlSetJoyStickShift(data, count);
	case SetJoyStick:
		return Instance->ControlSetJoyStick(data, count);
	case SetMouse:
		return Instance->ControlSetMouse(data, count);
	case SetJoyShiftValue:
		return Instance->ControlSetJoyShiftValue(data, count);
	case GetJoyShiftValue:
		return Instance->ControlGetJoyShiftValue(data, count);
	case GetMouseSensitivity:
		return Instance->ControlGetMouseSensitivity(data, count);
	case SetMouseSensitivity:
		return Instance->ControlSetMouseSensitivity(data, count);
	case SaveSettings:
		return Instance->ControlSaveSettings(data, count);
	case RestoreSetting:
		return Instance->ControlRestoreSettings(data, count);
	case GetJoyXAxis:
		return Instance->ControlGetJoyXAxis(data, count);
	case GetJoyRudderAxis:
		return Instance->ControlGetJoyRudderAxis(data, count);
	case GetMouseXAxis:
		return Instance->ControlGetMouseXAxis(data, count);
	case SetJoyXAxis:
		return Instance->ControlSetJoyXAxis(data, count);
	case SetJoyRudderAxis:
		return Instance->ControlSetJoyRudderAxis(data, count);
	case SetMouseXAxis:
		return Instance->ControlSetMouseXAxis(data, count);
	case ShellIATrainingSetPlayerMech:
		return Instance->SetTrainingPlayerMech();
	case ShellGetTrainingMechBars:
		return Instance->GetTrainingMechBars(data, count);
	case ShellGetMasterMechBars:
		return Instance->GetMasterMechBars(data, count);
	case ShellGetClosingCinema:
		return Instance->GetClosingCinema(data, count);
	case ShellGetLastPlayerMech:
		return Instance->GetLastPlayerMech(data, count);
	case ShellSetMasterTrialsDifficulty:
		return Instance->SetMasterTrialDifficutly(data, count);
	case ShellLaunchTrainingMission:
		return Instance->LaunchTrainingMission();
	case ShellGetSupportedResolutions:
		return Instance->GetSupportedRes(data, count);
	case ShellGetIsResourceEnglish:
		return Instance->GetIsResourceEnglish(data, count);
	case SetJoyStickThrottle:
		return Instance->ControlSetJoyStickThrottle(data, count);
	case GetJoyStickThrottle:
		return Instance->ControlGetJoyStickThrottle(data, count);
	}
	return 1;
}

int MW4Shell::GetIsResourceEnglish(void* data[], int count)
{
	extern DWORD gLanguageDLL;

	if (stricmp(gos_GetResourceString(gLanguageDLL, 0), "English") == 0)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int MW4Shell::ExitDedicatedServer(void* data[], int count)
{
	Instance->shellCommand = ExitMissionCommand;
	Instance->currentShellRunning = StatShellRunning;
	Environment.DoGameLogic	= &MWApplication::DoShellLogic;

	return 1;
}


int MW4Shell::DisconnectDedicatedServer(void* data[], int count)
{
	Instance->shellCommand = DisconnectCommand;
	Instance->currentShellRunning = StatShellRunning;
	Environment.DoGameLogic	= &MWApplication::DoShellLogic;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetMissionNames(int count, void* data[])
{
	Check_Pointer(this);
	Check_Object(MWCampaign::Instance);
	gos_PushCurrentHeap(MechWarrior4::Heap);

	char **name_array = STRARRAYPARAM(1);
	int *num_missions = INTARRAYPARAM(2);
	
	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::Instance->m_missions);
//	Verify(m_iaMissionCount == iterator.GetSize());

	CampaignMissionPlug * mission;
	int i = 0;
	while(((mission = iterator.ReadAndNext()) != NULL) && (i < MAX_MISSIONS))
	{
		if(mission->m_status > 0)
		{
			Check_Object(mission);
			FREEANDNULL(name_array[i]);
			name_array[i] = (char *)gos_Malloc(128);
			MString mission_name;
			mission_name = MWApplication::GetInstance()->GetLocString(mission->m_displayNameIndex);
			mission_name.StripDirectory().StripExtension();
			Str_Copy(
				name_array[i],
				(const char *)mission_name,
				mission_name.GetLength() + 1
			);
			i++;
		}
	}

	Stuff::MString missions_path = "Resource\\UserMissions\\*.mw4";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(missions_path, true);
	Check_Object(resource_directory);
	const char *file_name;
	int mission_exists = false;
	while(((file_name = resource_directory->GetCurrentFileName()) != NULL) &&
		(i < MAX_MISSIONS))
	{
		mission_exists = false;

		MString nfo_name = file_name;
		nfo_name.StripExtension();
		nfo_name = "Resource\\UserMissions\\" + nfo_name + ".nfo";
		if (gos_DoesFileExist(nfo_name))
		{		
			NotationFile notefile(nfo_name);		
	
			Page *page = notefile.FindPage("ruleset");
			if (page != NULL)
			{
				ChainIteratorOf<Note*> *note_iterator = page->MakeNoteIterator();

				Note *note;
				while ((note = note_iterator->ReadAndNext()) != NULL)
				{
					if (_stricmp(note->GetName(), "type") == 0)
					{
						int rule_set;
						note->GetEntry(&rule_set);
						if (rule_set == SinglePlayer)
						{
							mission_exists = true;
							break;
						}
					}
				}
				delete note_iterator;
			}
		}
		else
			mission_exists = true;

		if (mission_exists)
		{
			FREEANDNULL(name_array[i]);
			name_array[i] = (char *)gos_Malloc(128);
			MString mission_name;
			mission_name = file_name;
			mission_name.StripDirectory().StripExtension();
			Str_Copy(
				name_array[i],
				(const char *)mission_name,
				mission_name.GetLength() + 1
			);
			i++;
		}

		resource_directory->AdvanceCurrentFile();
	}
	delete resource_directory;
	*num_missions = i;
	gos_PopCurrentHeap();

	return 1;
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::InitIAScreen()
{
	Check_Object(m_optionsObject);

	NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams();
	params->ResetParameters();

	MWApplication::GetInstance()->InitializeOptions(m_optionsObject);

	MWApplication::GetInstance()->m_currentMissionStatus = 0;
	MWApplication::GetInstance()->m_iaDisplayGameType = 0;

	if(MWGame::GetInstance())
	{
		delete MWGame::GetInstance();
		GlobalPointers::ClearPointer(MWGameGlobalPointerIndex);
	}
	if(MWCampaign::Instance)
	{
		delete MWCampaign::Instance;
		MWCampaign::Instance = NULL;
	}
	if(SalvageManager::GetInstance())
	{
		delete SalvageManager::GetInstance();
		GlobalPointers::ClearPointer(SalvageManagerGlobalPointerIndex);
	}

	if(MWCampaign::TrainingInstance)
	{
		delete MWCampaign::TrainingInstance;
		MWCampaign::TrainingInstance = NULL;
	}

	if(MWCampaign::WaveInstance)
	{
		delete MWCampaign::WaveInstance;
		MWCampaign::WaveInstance = NULL;
	}

	if(MWCampaign::MasterTrialsInstance)
	{
		delete MWCampaign::MasterTrialsInstance;
		MWCampaign::MasterTrialsInstance = NULL;
	}

	Verify(!MWCampaign::Instance);
	MWCampaign::Instance = MWCampaign::MakeNewCampaign("Content\\Campaigns\\InstantAction.campaign");
	Check_Pointer(MWCampaign::Instance);
	Verify(!MWCampaign::TrainingInstance);
	MWCampaign::TrainingInstance = MWCampaign::MakeNewCampaign("Content\\Campaigns\\Training.campaign");
	Check_Pointer(MWCampaign::TrainingInstance);
	Verify(!MWCampaign::WaveInstance);
	MWCampaign::WaveInstance = MWCampaign::MakeNewCampaign("Content\\Campaigns\\Wave.campaign");
	Check_Pointer(MWCampaign::WaveInstance);
	Verify(!MWCampaign::MasterTrialsInstance);
	MWCampaign::MasterTrialsInstance = MWCampaign::MakeNewCampaign("Content\\Campaigns\\MasterTrials.campaign");
	Check_Pointer(MWCampaign::MasterTrialsInstance);
	GlobalPointers::AddGlobalPointer(SalvageManager::MakeNewSalvageManager(ResourceID::Null), SalvageManagerGlobalPointerIndex);
	Check_Pointer(SalvageManager::GetInstance());

	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::Instance->m_missions);
	m_iaMissionCount = GetNumberOfMissionsInMissionPlay();

	m_mechCount = GetMechCount();

	m_waves = 1;
	m_botsPerWave = 0;
	m_lancePerWave = 0;
	m_playerLives = 1;

	//You can default to this since we don't store what was going on before.
	ia_gameType = IA_MISSIONSELECTION;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::InitCampaignScreen()
{
	
	Check_Object(MWApplication::GetInstance());
	Check_Object(m_optionsObject);
	ResetMovieList();

	MWApplication::GetInstance()->InitializeCampaignGame();

	Check_Object(MWCampaign::Instance);

	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::Instance->m_missions);
	m_iaMissionCount = iterator.GetSize();

	ia_gameType = IA_MISSIONSELECTION;
	//This will eventually only list the mechs that came from mech lab construction
	//I.E will get this count from MWGame::Instance
	m_mechCount = GetCampaignMechCount();

	MWApplication::GetInstance()->m_isNight = false;
	MWApplication::GetInstance()->InitializeOptions(m_optionsObject);

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::InitMPScreen()
{
	MWApplication::GetInstance()->InitializeOptions(m_optionsObject);
	m_mechCount = GetMechCount();

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::InitMechLabScreen()
{
	if (Network::GetInstance() == NULL)
	{
		Verify(!Network::GetInstance());
		GlobalPointers::AddGlobalPointer(new Network, NetworkGlobalPointerIndex);
		Register_Object(Network::GetInstance());
	}

	if(MechLab::Instance)
	{
		delete MechLab::Instance;
		MechLab::Instance = NULL;
	}

	MechLab::Instance = new MechLab;
	MechLab::Instance->StartUp();
	Environment.UpdateRenderers	= &MechLab::UpdateDisplay;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::InitCampaignMechLab()
{
	if (Network::GetInstance() == NULL)
	{
		Verify(!Network::GetInstance());
		GlobalPointers::AddGlobalPointer(new Network, NetworkGlobalPointerIndex);
		Register_Object(Network::GetInstance());
	}

	if(MechLab::Instance)
	{
		delete MechLab::Instance;
		MechLab::Instance = NULL;
	}

	CampaignMechLab *camp_lab = new CampaignMechLab;
	MechLab::Instance = camp_lab;
	MechLab::Instance->StartUp();
	Environment.UpdateRenderers	= &MechLab::UpdateDisplay;	

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::ClearMechLab(int nMode/* = 0*/)
{
    // nMode: -1 = stop loading, 0 - stop game, 1 - from script, 2 - start game
	Check_Pointer(this);

	if(MechLab::Instance)
	{
		Check_Object(EntityManager::GetInstance());

        if (!CTCL_IsConsole()) {// jcem
            if (nMode != -1) {
		        if (MWApplication::GetInstance()->networkingFlag)
		        {
			        Connection::Local->DeleteChildren();
		        }
            } else {
                MechLab::Instance->Exit();
                MechLab::Instance->FreeReplicators();
            }
		if(Network::GetInstance() != NULL && !MWApplication::GetInstance()->networkingFlag)
		{
			delete Network::GetInstance();
			GlobalPointers::ClearPointer(NetworkGlobalPointerIndex);
		}
        }

        if (nMode != -1) {
		delete MechLab::Instance;
		MechLab::Instance = NULL;
        } else {
            MidLevelRenderer::MLRTexturePool* pOld = MidLevelRenderer::MLRTexturePool::Instance;
            MidLevelRenderer::MLRTexturePool::Instance = NULL;
		    delete MechLab::Instance;
		    MechLab::Instance = NULL;
            MidLevelRenderer::MLRTexturePool::Instance = pOld;
        }

		Environment.UpdateRenderers	= &MWApplication::UpdateDisplay;
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MString MW4Shell::GetMissionInstanceFilename()
{
	MString return_name;
	if(!strstr(m_iaMissionName, "UserMissions"))
	{
		return_name = "Missions\\";
		return_name += m_iaMissionName;
		return_name += "\\";
		return_name += m_iaMissionName;
		return_name += ".instance";
	}
	else
	{
		//Will already have the UserMissions on the front of this.
		return_name = m_iaMissionName;
		return_name += "\\";
		return_name += ".instance";
	}

	return return_name;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetNumberOfMissionsInMissionPlay()
{
	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::Instance->m_missions);

	CampaignMissionPlug * mission;
	int i = 0;
	while((mission = iterator.ReadAndNext()) != NULL)
	{
		if(mission->m_status > 0)
		{
			i++;
		}
	}

	Stuff::MString missions_path = "Resource\\UserMissions\\*.mw4";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(missions_path, true);
	Check_Object(resource_directory);
	i += resource_directory->fileEntries.GetSize();
	delete resource_directory;

	return i;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetLastPlayerMech(void *data[], int count)
{
    gosASSERT(!CTCL_IsConsole());
	int *selected_mech_index = INTARRAYPARAM(1);

	MWApplication *app = MWApplication::GetInstance();
	Check_Object(app);

	int index = app->m_lastMechID;

	//THIS FUNCTION WILL NOT PERSERVE A CAMERA SHIP SELECTION
	if ((m_didSetMPMech) && (app->networkingFlag) && (index == 0))
	{
		index = 1;
	}

	// if coming from instant action to networking, increase the index count by 1
	if ((!m_didSetMPMech) && (app->networkingFlag))
	{
		if (index > -1)
			index++;
		m_didSetMPMech = true;
	}

	// if coming from networking to instant action, decrease the index count by 1
	if((m_didSetMPMech) && (!app->networkingFlag))
	{
		if (index > 0)
			index--;
		m_didSetMPMech = false;
	}

	// This section to handle -1 index value(coming from mechlab) or out-of-range values
	if ((index < 0) || (index >= m_mechCount))
	{	
		// reset the index first
		if (app->networkingFlag)
			index = 1;
		else
			index = 0;

		//This means we have to used the mech name and find the index!
		for (int count = index; count < m_mechCount; count++)
		{
			MString alpha_name = alphaMechNamesWithMCSorted[count];
			if(alpha_name == app->m_lastMechName)
			{
				index = count;
				break;
			}
		}
	}

	*selected_mech_index = index;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetMechs(void* data[], int count)
{
	Check_Pointer(this);

	char **name_array = STRARRAYPARAM(1);
	int *stock_array = INTARRAYPARAM(2);

	alphaMechNames.DeletePlugs();

	if (alphaMechNamesWithMCSorted)
		delete [] alphaMechNamesWithMCSorted;
	alphaMechNamesWithMCSorted = new MString[m_mechCount];

	if(m_mechIDs)
	{
		gos_Free(m_mechIDs);
		m_mechIDs = NULL;
	}
	m_mechIDs = (ResourceID *)gos_Malloc(m_mechCount * sizeof(ResourceID));

  if (CTCL_IsConsole()) {// jcem
      if (g_CameraResID == ResourceID::Null) {
		MString mech_name;
		mech_name = "vehicles\\ObservationVehicle\\ObservationVehicle.instance";
		Resource obs_resource(mech_name);
		g_CameraResID = obs_resource.GetResourceID();
      }
  } else {
	if (MWApplication::GetInstance()->networkingFlag)
	{		
		FREEANDNULL(name_array[0]);
		name_array[0] = (char *)gos_Malloc(128);
		
		MString mech_name;
		mech_name = "vehicles\\ObservationVehicle\\ObservationVehicle.instance";
		Resource obs_resource(mech_name);
		mech_name = g_szCameraShip;
		Str_Copy(
			name_array[0],
			(const char *)mech_name,
			mech_name.GetLength() + 1
		);
		alphaMechNamesWithMCSorted[0] = mech_name;
		
		m_mechIDs[0] = obs_resource.GetResourceID();
		stock_array[0] = 1;
	}
  }

	MWTable::TableIterator *mech_iterator;
	Check_Object(MWApplication::GetInstance()->m_mechTable);

	mech_iterator = MWApplication::GetInstance()->m_mechTable->MakeTableIterator();
	MWTableEntry *mech_entry;
	while((mech_entry = mech_iterator->ReadAndNext()) != NULL)
	{
		Check_Object(mech_entry);
		PlugOf<MString> *name_plug = new PlugOf<MString>(mech_entry->GetEntryName());
		alphaMechNames.AddValue(name_plug, mech_entry->GetEntryName());
	}
	
	delete mech_iterator;

	Stuff::MString mechs_path = "Resource\\Variants\\*.mw4";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(mechs_path, true);
	Check_Object(resource_directory);
	const char *file_name;
	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{
		MString mech_name;
		mech_name = file_name;
		mech_name.StripDirectory().StripExtension();

		PlugOf<MString> *name_plug = new PlugOf<MString>(mech_name);
		alphaMechNames.AddValue(name_plug, mech_name);

		resource_directory->AdvanceCurrentFile();
	}

	
	// Sort Mad Cat correctly
	SortedChainIteratorOf<PlugOf<MString> *, MString> mech_name_iterator(&alphaMechNames);
	PlugOf<MString> *mstring_plug;
	int mech_index = 0;
  if (!CTCL_IsConsole()) {// jcem
	if (MWApplication::GetInstance()->networkingFlag)
		mech_index = 1;
  }
	while((mstring_plug = mech_name_iterator.ReadAndNext()) != NULL)
	{
		if (mech_index == m_mechCount)
			break;	// Boundary Check

		alphaMechNamesWithMCSorted[mech_index] = mstring_plug->GetItem();
		mech_index ++;
	}
	int mc2_start = 0;
	while (_strnicmp(alphaMechNamesWithMCSorted[mc2_start], "Mad Cat MKII", 12) != 0)
	{
		mc2_start++;
	}
	int mc2_end = mc2_start;
	while (_strnicmp(alphaMechNamesWithMCSorted[mc2_end], "Mad Cat MKII", 12) == 0)
	{
		mc2_end++;
	}
	int mc_end = mc2_end;
	while (_strnicmp(alphaMechNamesWithMCSorted[mc_end], "Mad Cat", 7) == 0)
	{
		mc_end++;
	}
	int mc2_i = mc2_end - mc2_start;
	int mc_i = mc_end - mc2_end;
	MString* mc2_string = new MString[mc2_i];
	for (int i = 0; i < mc2_i; i++)
		mc2_string[i] = alphaMechNamesWithMCSorted[mc2_start + i];
	for (i = 0; i < mc_i; i++)
		alphaMechNamesWithMCSorted[mc2_start + i] = alphaMechNamesWithMCSorted[mc2_end + i];
	for (i = 0; i < mc2_i; i++)
		alphaMechNamesWithMCSorted[mc2_start + mc_i + i] = mc2_string[i];
	delete [] mc2_string;

	// now return the sorted strings
	mech_index = 0;
  if (!CTCL_IsConsole()) {// jcem
	if (MWApplication::GetInstance()->networkingFlag)
		mech_index = 1;
  }
	while (mech_index < m_mechCount)
	{
		MString alpha_names = alphaMechNamesWithMCSorted[mech_index];
		FREEANDNULL(name_array[mech_index]);
		name_array[mech_index] = (char *)gos_Malloc(128);
		Str_Copy(
			name_array[mech_index],
			(const char *)alpha_names,
			alpha_names.GetLength() + 1
		);

		MWTableEntry *mech_table_entry = MWApplication::GetInstance()->m_mechTable->FindEntry(alpha_names);
		if(mech_table_entry)
		{
			m_mechIDs[mech_index] = mech_table_entry->GetEntryResourceID();
			stock_array[mech_index] = 1;
		}
		else
		{
			m_mechIDs[mech_index] = ResourceID::Null;
			stock_array[mech_index] = 0;
		}
		mech_index ++;
	}

	delete resource_directory;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::IAGetStockMechs(void* data[], int count)
{
	Check_Pointer(this);

	char **name_array = STRARRAYPARAM(1);
	int *num_mechs = INTARRAYPARAM(2);

	if(m_stockMechIDs)
	{
		gos_Free(m_stockMechIDs);
		m_stockMechIDs = NULL;
	}
	m_stockMechIDs = (ResourceID *)gos_Malloc((LastMechID + 1) * sizeof(ResourceID));

	int i = 0;

	MWTable::TableIterator *mech_iterator;
	Check_Object(MWApplication::GetInstance()->m_mechTable);

	mech_iterator = MWApplication::GetInstance()->m_mechTable->MakeTableIterator();
	MWTableEntry *mech_entry;
	while((mech_entry = mech_iterator->ReadAndNext()) != NULL)
	{
		Check_Object(mech_entry);
		
		FREEANDNULL(name_array[i]);
		name_array[i] = (char *)gos_Malloc(128);

		Str_Copy(
			name_array[i],
			(const char *)mech_entry->GetEntryName(),
			mech_entry->GetEntryName().GetLength() + 1
		);

		m_stockMechIDs[i] = mech_entry->GetEntryResourceID();
		i++;
	}
	
	*num_mechs = i;
	delete mech_iterator;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetCampaignMechs(void* data[], int count)
{
	Check_Pointer(this);
	Check_Object(MWGame::GetInstance());

	int *lance_id = INTARRAYPARAM(1);		//What lance we need a list for
	char **mech_names = STRARRAYPARAM(2);	//The list of names
	int *status_array = INTARRAYPARAM(3);
	int *selected_name = INTARRAYPARAM(4);	//What name is currently selected
	int *mech_id = INTARRAYPARAM(5);
	int *num_names = INTARRAYPARAM(6);

//	#if defined(_ARMOR)
//		int array_size = VALUEPARM(6);
//	#endif

	if(m_mechCount > 0)
	{
		if(m_mechIDs)
		{
			gos_Free(m_mechIDs);
			m_mechIDs = NULL;
		}
		m_mechIDs = (ResourceID *)gos_Malloc(m_mechCount * sizeof(ResourceID));
	}

	SortedChainIteratorOf<MechTablePlug*, MString> iterator(&MWGame::GetInstance()->m_mechTable);
	MechTablePlug *mech_plug;
	PilotPlug *pilot_plug = MWGame::GetInstance()->GetPilot(*lance_id);
	Check_Object(pilot_plug);
	MString current_mech_name;

	*selected_name = 0;
	*mech_id = NoMechID;
	if(pilot_plug->GetMechPlug())
	{
		//we have a pilot plug and we need to get what we are set to
		current_mech_name = pilot_plug->GetMechPlug()->GetMechName();
		*mech_id = pilot_plug->GetMechPlug()->GetMechID();
	}

	//Set the first entry to "";

	FREEANDNULL(mech_names[0]);
	mech_names[0] = (char *)gos_Malloc(128);

	Str_Copy(
		mech_names[0],
		"",
		1
	);

	int i=1;
	while((mech_plug = iterator.ReadAndNext()) != NULL)
	{
		if(mech_plug->GetStatus() != MechTablePlug::DestroyedStatus)
		{
			FREEANDNULL(mech_names[i]);
			mech_names[i] = (char *)gos_Malloc(128);
		
			Str_Copy(
				mech_names[i],
				(const char *)mech_plug->GetMechName(),
				mech_plug->GetMechName().GetLength() + 1
			);
			status_array[i] = mech_plug->GetStatus();
			m_mechIDs[i] = mech_plug->GetMechResourceID();
			if(current_mech_name)
			{
				if(current_mech_name == mech_plug->GetMechName())
					*selected_name = i;
			}

			i ++;
		}
//		Verify(i<array_size);
	}

	*num_names = i;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetMechCount()
{
	Check_Pointer(this);

	int i = 0;

	Check_Object(MWApplication::GetInstance()->m_mechTable);
	i += MWApplication::GetInstance()->m_mechTable->GetTableSize();

	Stuff::MString mechs_path = "Resource\\Variants\\*.mw4";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(mechs_path, true);
	Check_Object(resource_directory);
	i += resource_directory->fileWalker->GetSize();
	delete resource_directory;

  if (!CTCL_IsConsole()) {// jcem
	if (MWApplication::GetInstance()->networkingFlag)
	{
		++i;
	}
  }

	//Max_Clamp(i, MAX_MECHS);
	return i;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetCampaignMechCount()
{
	Check_Pointer(this);
	Check_Object(MWGame::GetInstance());

	return MWGame::GetInstance()->m_mechTable.GetSize() + 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetCampaignMech(void* data[], int count)
{
	Check_Pointer(this);
	Check_Object(MWGame::GetInstance());

	int *lance_id = INTARRAYPARAM(1);
	const char *mech_name = STRPARM(2);

	MWGame::GetInstance()->SetLancemateMech(*lance_id, (char *)mech_name);
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetTime(void *data[], int count)
{
	Check_Object(MWApplication::GetInstance());

	int *time_of_day = INTARRAYPARAM(1);
	switch(*time_of_day)
	{
	case 0:
		MWApplication::GetInstance()->m_isNight = false;
		break;
	default:
		MWApplication::GetInstance()->m_isNight = true;
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetTimeOfDay(void *data[], int count)
{
	Check_Object(MWApplication::GetInstance());

	int *time_of_day = INTARRAYPARAM(1);

	*time_of_day = MWApplication::GetInstance()->m_isNight;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetMech(void *data[], int count)
{
	//For right now we are going to just create a known mech

	int mech_index = INTPARM(1);
	m_mechID = m_mechIDs[mech_index];
	const char *mech_name = STRPARM(2);
	m_mechShortResFile = mech_name; // jcem
	//const char *skin_name = STRPARM(3);
	MWApplication *app = MWApplication::GetInstance();
	app->m_lastMechID = mech_index;
	app->m_lastMechName = "";

	if(m_mechID == ResourceID::Null)
	{	
		//
		//-----------------------------------------------------------------
		//This means that we have a user made mech in its own resource file
		//-----------------------------------------------------------------
		//
		m_mechResourceFile = "Resource\\Variants\\";
		m_mechResourceFile += mech_name;
		m_mechResourceFile += ".mw4";
	}
	else
	{

#if 0
		//
		//------------------------------------------------------------
		//This is for E3 we are going to look for the resource by name
		//------------------------------------------------------------
		//
		if(_stricmp("ops", skin_name))
		{
			m_mechResourceFile = mech_name;
			MString mech_file = "Mechs\\";
			mech_file += mech_name;
			mech_file += "\\";
			mech_file += skin_name;
			mech_file += "_";
			mech_file += mech_name;
			mech_file += ".instance";

			Resource mech_resource(mech_file);
			Verify(mech_resource.DoesResourceExist());
			m_mechID = mech_resource.GetResourceID();
		}
#endif

	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetTrainingPlayerMech()
{
	MWTableEntry *mech_table_entry = MWApplication::GetInstance()->m_mechTable->FindEntry("shadow cat");
	Check_Object(mech_table_entry);

	m_mechID = mech_table_entry->GetEntryResourceID();

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::AddChat(BYTE from, BYTE type, BYTE players_sent_to, char *message)
{

	if (m_currentChatCount > m_maxChatCount)
	{
		RemoveChat();
	}

	Connection *connection = Network::GetInstance()->GetConnection(from);

	if (connection != NULL)
	{
		m_chatArray[m_currentChatCount] = new char[256];
		m_chatFrom[m_currentChatCount] = new char[256];
	
		
		if (type != MWApplication::SystemBroadcast)
		{
			if (type == MWApplication::LobbyTeamBroadcast)
			{
				char* team_chat_id_str = Application::GetInstance()->GetLocString(IDS_MP_TEAMCHAT);
				int team_chat_str_len = strlen(team_chat_id_str) + 1;

				Str_Copy(m_chatArray[m_currentChatCount], &(message[team_chat_str_len]), 256);

				char teamChatFrom[256];
				char* team_str = Application::GetInstance()->GetLocString(IDS_TEAMCHAT);
				Str_Copy(teamChatFrom, team_str, strlen(team_str) + 1);
				Str_Cat(teamChatFrom, connection->GetConnectionName(), 256);
				Str_Copy(m_chatFrom[m_currentChatCount], teamChatFrom, 256);
			}
			else
			{
				Str_Copy(m_chatArray[m_currentChatCount], message, 256);
				Str_Copy(m_chatFrom[m_currentChatCount], connection->GetConnectionName(), 256);
			}
		}
		else
		{
			Str_Copy(m_chatArray[m_currentChatCount], message, 256);
			Str_Copy(m_chatFrom[m_currentChatCount], "", 256);
		}

		++m_currentChatCount;
	}
	
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::RemoveChat()
{
	
	delete m_chatArray[0];
	delete m_chatFrom[0];

	for (int i=1; i < m_currentChatCount; ++i)
	{
		m_chatArray[i-1] = m_chatArray[i];
		m_chatFrom[i-1] = m_chatFrom[i];
	}

	m_chatArray[m_currentChatCount-1] = NULL;
	m_chatArray[m_currentChatCount-1] = NULL;

	m_currentChatCount--;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::ClearChat()
{
	
	for (int i = 0; i < 50; i++)
	{
		if (m_chatArray[i] != NULL)
		{
			delete m_chatArray[i];
			m_chatArray[i] = NULL;
		}

		if (m_chatFrom != NULL){
			delete m_chatFrom[i];
			m_chatFrom[i] = NULL;
		}
	}


	m_currentChatCount = 0;
	

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::RemoveOneChat(void * instance,int numParms,void* data[])
{
	MW4Shell::Instance->RemoveChat();

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
	

void MW4Shell::SetMapInfo(const char *info, const char *author, const char *link)
{
	if (m_mapInfo)
	{
		delete m_mapInfo;
		m_mapInfo = NULL;
	}


	if (m_mapAuthor)
	{
		delete m_mapAuthor;
		m_mapAuthor = NULL;
	}

	if (m_mapLink)
	{
		delete m_mapLink;
		m_mapLink = NULL;
	}
	m_mapLinkAvailable = 0;

	if (author != NULL)
	{
		m_mapInfo = new char [strlen(author)+1];
		strcpy(m_mapInfo, author);
	}

	if (info != NULL)
	{
		m_mapAuthor = new char [strlen(info)+1];
		strcpy(m_mapAuthor, info);
	}

	if (link != NULL)
	{
		m_mapLink = new char [strlen(link)+1];
		strcpy(m_mapLink, link);
		m_mapLinkAvailable = 1;
	}
	else
	{
		m_mapLinkAvailable = -1;
	}	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int _stdcall MW4Shell::NetHaveMap(void * instance, int, void *[])
{	
	return MWApplication::GetInstance()->haveNetworkMap;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int _stdcall MW4Shell::NetLaunchBrowserMapLink(void * instance, int, void *[])
{
	if (MW4Shell::Instance->m_mapLink != NULL)
	{
		gos_EnableSetting(gos_Set_TriggerBrowser, (unsigned long)MW4Shell::Instance->m_mapLink);
	}
	return 1;
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::SendChat(void * instance,int numParms,void* data[])
{
	
	if (MW4Shell::Instance->m_outgoingChat == NULL)
		return -1;

	if (MW4Shell::Instance->m_outgoingChatToPlayerCount <= 0)
		return -1;


	Verify(MW4Shell::Instance->m_outgoingChatToPlayerCount < 32);

	BYTE chat_to[32];
	BYTE adjusted_count = 0;
		
	for (int i = 0; i < MW4Shell::Instance->m_outgoingChatToPlayerCount; ++i )
	{
		int connection_number = MW4Shell::Instance->m_outgiongChatToPlayer[i];

		Connection *connection = NULL;

		if (connection_number != -1)
			connection = Network::GetInstance()->GetConnection(connection_number);

		if (connection != NULL)
		{
			chat_to[adjusted_count] = connection->GetID();
			adjusted_count++;
		}
		
	}

	char* team_chat_id_str = Application::GetInstance()->GetLocString(IDS_MP_TEAMCHAT);
	int team_chat_str_len = strlen(team_chat_id_str);

	if ((_mbsnicmp((unsigned char*) MW4Shell::Instance->m_outgoingChat, (unsigned char*)team_chat_id_str, team_chat_str_len) == 0) && (MW4Shell::Instance->m_outgoingChat[team_chat_str_len] == ' '))
	{
		MWApplication::GetInstance()->SendChat(
			Connection::Local->GetID(),
			MWApplication::LobbyTeamBroadcast,
			0,
			MW4Shell::Instance->m_outgoingChat);
	}
	else
	{
		MWApplication::GetInstance()->SendChat(
			Connection::Local->GetID(),
			MWApplication::LobbyBroadcast,
			0,
			MW4Shell::Instance->m_outgoingChat);
	}
	
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::SendBroadcastChat(void * instance,int numParms,void* data[])
{
	
	if (MW4Shell::Instance->m_outgoingChat == NULL)
		return -1;

	if (MW4Shell::Instance->m_outgoingChatToPlayerCount <= 0)
		return -1;


	Verify(MW4Shell::Instance->m_outgoingChatToPlayerCount < 32);

	BYTE chat_to[32];
	BYTE adjusted_count = 0;
		
	for (int i = 0; i < MW4Shell::Instance->m_outgoingChatToPlayerCount; ++i )
	{
		int connection_number = MW4Shell::Instance->m_outgiongChatToPlayer[i];

		Connection *connection = NULL;

		if (connection_number != -1)
			connection = Network::GetInstance()->GetConnection(connection_number);

		if (connection != NULL)
		{
			chat_to[adjusted_count] = connection->GetID();
			adjusted_count++;
		}
		
	}
	
	MWApplication::GetInstance()->SendChat(
			Connection::Local->GetID(),
			MWApplication::SystemBroadcast,
			0,
			MW4Shell::Instance->m_outgoingChat);

	
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetDummyData(int count, void *data[])
{
	Check_Pointer(this);

	char **name_array = STRARRAYPARAM(1);
	int array_size = VALUEPARM(2);

	for(int i=0; i<array_size; i++)
	{
		FREEANDNULL(name_array[i]);
		name_array[i] = (char *)gos_Malloc(128);
		MString mech_name = "I Love Mech 4";
		Str_Copy(
			name_array[i],
			(const char *)mech_name,
			mech_name.GetLength() + 1
		);
	}
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::InitNetworkScenarios(void *instance, int, void *[])
{

	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();

	if (params->m_useMapCycle)
	{

		MW4Shell::Instance->LoadMapCycle();


	
		if (MW4Shell::Instance->totalCycleEntries > 0)
		{

			if (MW4Shell::Instance->currentCycleNumber >= MW4Shell::Instance->totalCycleEntries)
			{
				MW4Shell::Instance->currentCycleNumber = 0;
			}

			// go to the next cycle map...
			MW4Shell::Instance->networkScenarioCount = 1;
			MW4Shell::Instance->maxNetworkScenarioCount = 1;
			strncpy(MW4Shell::Instance->scenarios[0].missionName, MW4Shell::Instance->cycleList[MW4Shell::Instance->currentCycleNumber].missionName, 127);
			strncpy(MW4Shell::Instance->scenarios[0].longMissionName, MW4Shell::Instance->cycleList[MW4Shell::Instance->currentCycleNumber].longMissionName, 127);
			strncpy(MW4Shell::Instance->scenarios[0].scenarioName, MW4Shell::Instance->cycleList[MW4Shell::Instance->currentCycleNumber].longMissionName, 127);
			strncat(MW4Shell::Instance->scenarios[0].scenarioName, " - ", 127);
			strncat(MW4Shell::Instance->scenarios[0].scenarioName, MW4Shell::Instance->cycleList[MW4Shell::Instance->currentCycleNumber].scenarioName, 127);
			strncpy(MW4Shell::Instance->scenarios[0].scenarioTag, MW4Shell::Instance->cycleList[MW4Shell::Instance->currentCycleNumber].scenarioTag, 127);
			MW4Shell::Instance->scenarios[0].usermissions = MW4Shell::Instance->cycleList[MW4Shell::Instance->currentCycleNumber].usermissions;

			params->m_ruleType = MW4Shell::Instance->cycleList[MW4Shell::Instance->currentCycleNumber].ruleType;
			params->m_mapID = 0;

			MW4Shell::Instance->selectedScenario = -1;

			SelectNetworkScenarioDirect(0);
			return 0;
		}
		else
		{
			params->m_useMapCycle = false;
		}


		

	}
	if (params->m_ruleType == MW4Shell::Instance->lastRuleType)
	{
		return 0;
	}

	MW4Shell::Instance->lastRuleType = params->m_ruleType;
	MW4Shell::Instance->networkScenarioCount = 0;
	MW4Shell::Instance->maxNetworkScenarioCount = 0;


	{
		Stuff::MString missions_path = "Resource\\Missions\\*.nfo";
		Stuff::Directory *resource_directory;
		resource_directory = new Stuff::Directory(missions_path, true);
		Check_Object(resource_directory);
		const char *file_name;
		
	
	
		while((file_name = resource_directory->GetCurrentFileName()) != NULL)
		{
		
			Stuff::MString full_name;
			full_name = "Resource\\Missions\\";
			full_name += file_name;
		
		
			NotationFile notefile(full_name);

			
			Page *info_page = notefile.FindPage("info");

			if (info_page != NULL)
			{
				const char *long_mission_name;
				if (info_page->GetEntry("longname",&long_mission_name))
				{

					Page *page = notefile.FindPage("scenarios");
					if (page != NULL)
					{
						ChainIteratorOf<Note*> *note_iterator = page->MakeNoteIterator();

						Note *note;
						while ((note = note_iterator->ReadAndNext()) != NULL)
						{

							NotationFile scenario_file;
							note->GetEntry(&scenario_file);

							
							Page *server_page = scenario_file.FindPage("server");
							if (server_page)
							{
								int rule_set;
								const char *scenario_read_name = NULL;

								if (server_page->GetEntry("ruleset",&rule_set) && server_page->GetEntry("name",&scenario_read_name))
								{
									if (rule_set == params->m_ruleType)
									{


										MString mission_name = file_name;
										MString scenario_name = note->GetName();

										mission_name.StripDirectory().StripExtension();

										strncpy(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].missionName, mission_name, 127);
										strncpy(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].longMissionName, long_mission_name, 127);
										strncpy(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].scenarioName, long_mission_name, 127);
										strncat(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].scenarioName, " - ", 127);
										strncat(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].scenarioName, scenario_read_name, 127);
										strncpy(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].scenarioTag, scenario_name, 127);
										MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].usermissions = false;

										++MW4Shell::Instance->networkScenarioCount;

									}

									++MW4Shell::Instance->maxNetworkScenarioCount;
								}
							}
						}
						delete note_iterator;
					}
				}
			}

			resource_directory->AdvanceCurrentFile();
		}
		delete resource_directory;

	}


	{
		Stuff::MString missions_path = "Resource\\UserMissions\\*.nfo";
		Stuff::Directory *resource_directory;
		resource_directory = new Stuff::Directory(missions_path, true);
		Check_Object(resource_directory);
		const char *file_name;
		
	
	
		while((file_name = resource_directory->GetCurrentFileName()) != NULL)
		{
		
			Stuff::MString full_name;
			full_name = "Resource\\UserMissions\\";
			full_name += file_name;
		
		
			NotationFile notefile(full_name);

			
			Page *info_page = notefile.FindPage("info");

			if (info_page != NULL)
			{
				const char *long_mission_name;
				if (info_page->GetEntry("longname",&long_mission_name))
				{

					Page *page = notefile.FindPage("scenarios");
					if (page != NULL)
					{
						ChainIteratorOf<Note*> *note_iterator = page->MakeNoteIterator();

						Note *note;
						while ((note = note_iterator->ReadAndNext()) != NULL)
						{

							NotationFile scenario_file;
							note->GetEntry(&scenario_file);

							
							Page *server_page = scenario_file.FindPage("server");
							if (server_page)
							{
								int rule_set;
								const char *scenario_read_name = NULL;

								if (server_page->GetEntry("ruleset",&rule_set) && server_page->GetEntry("name",&scenario_read_name))
								{
									if (rule_set == params->m_ruleType)
									{


										MString mission_name = file_name;
										MString scenario_name = note->GetName();

										mission_name.StripDirectory().StripExtension();

										strncpy(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].missionName, mission_name, 127);
										strncpy(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].longMissionName, long_mission_name, 127);
										strncpy(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].scenarioName, long_mission_name, 127);
										strncat(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].scenarioName, " - ", 127);
										strncat(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].scenarioName, scenario_read_name, 127);
										strncpy(MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].scenarioTag, scenario_name, 127);
										MW4Shell::Instance->scenarios[MW4Shell::Instance->networkScenarioCount].usermissions = true;

										++MW4Shell::Instance->networkScenarioCount;
									}

									++MW4Shell::Instance->maxNetworkScenarioCount;
								}
							}
						}
						delete note_iterator;
					}
				}
			}

			resource_directory->AdvanceCurrentFile();
		}
		delete resource_directory;

	}

	MW4Shell::SelectNetworkScenarioDirect(0);



	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::LoadMapCycle()
{

	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();
	params->m_pureMapCycle = true;

	totalCycleEntries = 0;

	//this is messed up all to hell!!!!

	if (gos_DoesFileExist("servercycle.txt"))
	{
		NotationFile notefile("servercycle.txt");

		
		Page *cycle_page = notefile.FindPage("cycle");
		if (cycle_page)
		{

			Page::NoteIterator *notes = cycle_page->MakeNoteIterator();
			Check_Object(notes);

			Note *note;
			while ((note = notes->ReadAndNext()) != NULL)
			{
				MString current_name = note->GetName();
				if (current_name == "map")
				{
					const char *temp;
					note->GetEntry(&temp);

					MString nfo_text = temp;
					MString scenario_text;

					char *pointer = strstr((char*)nfo_text, "::" );
					if (pointer && pointer != (char*)nfo_text)
					{
						*pointer = '\0';
						pointer += 2;

						if (pointer != NULL && *pointer != '\0')
						{
							scenario_text = pointer;

							Stuff::MString info_file_name;
							info_file_name = "Resource\\Missions\\";
							info_file_name += nfo_text;
						
							if (gos_DoesFileExist(info_file_name))
							{
								NotationFile nfo_file(info_file_name);


								Page *info_page = nfo_file.FindPage("info");
								if (info_page != NULL)
								{
										
									const char *long_mission_name;
									if (info_page->GetEntry("longname",&long_mission_name))
									{

										Page *scenario_page = nfo_file.FindPage("scenarios");
										
										if (scenario_page)
										{
											NotationFile scenario_file;
											if (scenario_page->GetEntry(scenario_text,&scenario_file))
											{
												
												Page *server_page = scenario_file.FindPage("server");
												if (server_page)
												{
													//we have an info file with the scenario...
													int rule;
													const char *scenario_read_text;
													if (server_page->GetEntry("ruleset", &rule) && server_page->GetEntry("name", &scenario_read_text))
													{

														nfo_text.StripExtension();
														strncpy(cycleList[totalCycleEntries].missionName, (char*)nfo_text, 127);
														strncpy(cycleList[totalCycleEntries].longMissionName, (char*)long_mission_name, 127);
														strncpy(cycleList[totalCycleEntries].scenarioTag, (char*)scenario_text, 127);
														strncpy(cycleList[totalCycleEntries].scenarioName, (char*)scenario_read_text, 127);
														cycleList[totalCycleEntries].usermissions = false;

														cycleList[totalCycleEntries].ruleType = rule;

														totalCycleEntries++;
													}
												}
											}
										}
									}
								}
							}
							else
							{
								info_file_name = "Resource\\UserMissions\\";
								info_file_name += nfo_text;
							
								if (gos_DoesFileExist(info_file_name))
								{
									NotationFile nfo_file(info_file_name);


									Page *info_page = nfo_file.FindPage("info");
									if (info_page != NULL)
									{
											
										const char *long_mission_name;
										if (info_page->GetEntry("longname",&long_mission_name))
										{

											Page *scenario_page = nfo_file.FindPage("scenarios");
											
											if (scenario_page)
											{
												NotationFile scenario_file;
												if (scenario_page->GetEntry(scenario_text,&scenario_file))
												{
													
													Page *server_page = scenario_file.FindPage("server");
													if (server_page)
													{
														//we have an info file with the scenario...
														int rule;
														const char *scenario_read_text;
														if (server_page->GetEntry("ruleset", &rule) && server_page->GetEntry("name", &scenario_read_text))
														{

															nfo_text.StripExtension();
															strncpy(cycleList[totalCycleEntries].missionName, (char*)nfo_text, 127);
															strncpy(cycleList[totalCycleEntries].longMissionName, (char*)long_mission_name, 127);
															strncpy(cycleList[totalCycleEntries].scenarioTag, (char*)scenario_text, 127);
															strncpy(cycleList[totalCycleEntries].scenarioName, (char*)scenario_read_text, 127);
															cycleList[totalCycleEntries].usermissions = true;

															cycleList[totalCycleEntries].ruleType = rule;

															totalCycleEntries++;
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
			delete notes;
		}

		// figure out if they all use the same rules...
		int rule=-1;
		for (int i = 0; i < totalCycleEntries; ++i)
		{
			if (cycleList[i].ruleType == -1)
			{
				rule = cycleList[i].ruleType;
			}
			else
			{
				if (rule != cycleList[i].ruleType)
				{
					params->m_pureMapCycle = false;
					break;
				}
			}
		}

	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetNetworkScenarios(void *instance, int, void *data[])
{


	gos_PushCurrentHeap(MechWarrior4::Heap);

	char **name_array = STRARRAYPARAM(0);
	
	for (int i = 0; i < MW4Shell::Instance->networkScenarioCount; ++i)
	{
		FREEANDNULL(name_array[i]);
		name_array[i] = (char *)gos_Malloc(128);
		MString scenario_name;
		//scenario_name = MW4Shell::Instance->scenarios[i].missionName;
		//scenario_name += " : ";
		//scenario_name += MW4Shell::Instance->scenarios[i].scenarioName;
		scenario_name = MW4Shell::Instance->scenarios[i].scenarioName;

		Str_Copy(
			name_array[i],
			(const char *)scenario_name,
			scenario_name.GetLength() + 1
		);
	}



	gos_PopCurrentHeap();
	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SelectNetworkScenario(void *instance, int, void *data[])
{
	// set the map name...
	int number = INTPARM(0);

	SelectNetworkScenarioDirect(number);

	int* intParam[1];
	int temp = RULE_TYPE_PARAMETER;
	intParam[0] = &temp;
	int gameType = MW4Shell::GetLocalNetworkMissionParamater(NULL, 1, (void**)intParam);
    if (CTCL_IsNone() || CTCL_IsCOOP()) {
	    int* botIds = INTARRAYPARAM(1);
	    int* mechIds = INTARRAYPARAM(2);

	    if ((gameType>=0 && gameType<=3) || gameType>=13)
		    return AddBots(number, botIds, mechIds);
    }

	return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SelectNetworkScenarioDirect(int number)
{

	if (number > MW4Shell::Instance->networkScenarioCount && number < 0)
	{
		return 0;
	}


	if (MW4Shell::Instance->selectedScenario != number)
	{
		MW4Shell::Instance->selectedScenario = number;

		// load that maps options...
		Stuff::MString full_name;
		full_name = "Resource\\Missions\\";
		full_name += MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].missionName;
		full_name += ".nfo";
		
		NotationFile notefile(full_name);

		Page *page = notefile.FindPage("scenarios");
		
		if (page != NULL)
		{
			NotationFile scenario_file;
			MString scenario_name;
			page->GetEntry(MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].scenarioTag,&scenario_file);
			
			MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
			NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();
			
			int rule_type = params->m_ruleType;
			
			app->LoadServerOptions();
			params->LoadOverideParameters(&scenario_file);
			
			params->m_ruleType = rule_type;
		}
		else
		{
			full_name = "Resource\\UserMissions\\";
			full_name += MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].missionName;
			full_name += ".nfo";
			
			NotationFile notefile(full_name);

			Page *page = notefile.FindPage("scenarios");
			
			if (page != NULL)
			{
				NotationFile scenario_file;
				MString scenario_name;
				page->GetEntry(MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].scenarioTag,&scenario_file);
				
				MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
				NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();
				
				int rule_type = params->m_ruleType;
				
				app->LoadServerOptions();
				params->LoadOverideParameters(&scenario_file);
				
				params->m_ruleType = rule_type;
			}
		}
		
		FREEANDNULL(MW4Shell::Instance->m_iaMissionName);


		MW4Shell::Instance->m_iaMissionName = (char *)gos_Malloc(256);
		Str_Copy(MW4Shell::Instance->m_iaMissionName, MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].longMissionName, 256);
		MWApplication::GetInstance()->m_currentMissionName = MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].scenarioName;

        if (!CTCL_IsConsole()) {
		MWApplication *app = MWApplication::GetInstance();
		app->VerifyAllPlayerVehicles();
		app->UnreadyPlayers();
		app->RemovePlayersFromTeam();
        }
	}
	else
	{
		FREEANDNULL(MW4Shell::Instance->m_iaMissionName);
		MW4Shell::Instance->m_iaMissionName = (char *)gos_Malloc(256);
		Str_Copy(MW4Shell::Instance->m_iaMissionName, MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].longMissionName, 256);
		MWApplication::GetInstance()->m_currentMissionName = MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].scenarioName;
	}

	if (true)
	{
		MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
		NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();
		
		if (true)
		{
			char szGameType[256];
			// mdm - advertise the current game type
			mbs_strncpy(szGameType, GetRuleName( params->m_ruleType ), sizeof(szGameType));
			gos_NetSetAdvertItem(0, GAMELIST_KEY_GAME_TYPE, szGameType);
		}
	}

	return 1;

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::GetDecalCount(void *instance,int numParms,void* data[])
{

#if 0
	Stuff::MString missions_path = "Content\\Textures\\stockdecals\\*.tga";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(missions_path, true);
	Check_Object(resource_directory);
	const char *file_name;
	
	
	int count = 0;

	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{

		++count;

		resource_directory->AdvanceCurrentFile();
	}
	delete resource_directory;

#endif

	int count = 64;


	Stuff::MString missions_path = "Content\\Textures\\customdecals\\*.tga";
	Stuff::Directory *resource_directory = new Stuff::Directory(missions_path, true);
	Check_Object(resource_directory);
	const char *file_name;
	
	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{

		Stuff::MString full_name;
		full_name = "Content\\Textures\\customdecals\\";
		full_name += file_name;


		if (gos_FileSize(full_name) < MWApplication::MaxDecalSize)
		{
			Stuff::FileStream test(full_name);

			if (gos_CheckValidTGA((unsigned char *)test.GetPointer(), test.GetSize()))
			{

				++count;
			}
		}

		resource_directory->AdvanceCurrentFile();
	}
	delete resource_directory;


	Max_Clamp(count, MAX_DECALS);


	return count;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::GetDecalNames(void *instance,int numParms,void* data[])
{
	gos_PushCurrentHeap(MechWarrior4::Heap);

	char **name_array = STRARRAYPARAM(0);
	char **full_name_array = STRARRAYPARAM(1);
	
#if 0
	Stuff::MString missions_path = "Content\\Textures\\stockdecals\\*.tga";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(missions_path, true);
	Check_Object(resource_directory);
	const char *file_name;
	
	
	int count = 0;

	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{
		FREEANDNULL(name_array[count]);
		name_array[count] = (char *)gos_Malloc(256);
		
		MString short_file_name = file_name;
		short_file_name.StripExtension();

		Str_Copy(
			name_array[count],
			(char*)short_file_name,
			strlen((char*)short_file_name) + 1
		);

		FREEANDNULL(full_name_array[count]);
		full_name_array[count] = (char *)gos_Malloc(512);

		Stuff::MString full_name;
		full_name = "Content\\Textures\\stockdecals\\";
		full_name += file_name;

		Str_Copy(
			full_name_array[count],
			(char*)full_name,
			strlen((char*)full_name) + 1
		);

		++count;
		resource_directory->AdvanceCurrentFile();
	}
	delete resource_directory;
#endif

	int count = 0;


	for (int i = 0; i < 64; ++i)
	{
		char decal_name[256];
		sprintf(&decal_name[0],"decal_%02d.tga",i);


		FREEANDNULL(name_array[count]);
		name_array[count] = (char *)gos_Malloc(256);
		
		MString short_file_name = decal_name;
		short_file_name.StripExtension();

		Str_Copy(
			name_array[count],
			(char*)short_file_name,
			strlen((char*)short_file_name) + 1
		);

		FREEANDNULL(full_name_array[count]);
		full_name_array[count] = (char *)gos_Malloc(512);

		Stuff::MString full_name;
		full_name = "Content\\Textures\\stockdecals\\";
		full_name += decal_name;

		Str_Copy(
			full_name_array[count],
			(char*)full_name,
			strlen((char*)full_name) + 1
		);

		++count;
	}






	Stuff::MString missions_path = "Content\\Textures\\customdecals\\*.tga";
	Stuff::Directory *resource_directory = new Stuff::Directory(missions_path, true);
	Check_Object(resource_directory);
	const char *file_name;

	
	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{
		Stuff::MString full_name;
		full_name = "Content\\Textures\\customdecals\\";
		full_name += file_name;

		if (gos_FileSize(full_name) < MWApplication::MaxDecalSize)
		{
			Stuff::FileStream test(full_name);

			if (gos_CheckValidTGA((unsigned char *)test.GetPointer(), test.GetSize()))
			{
				CalculateCustomPNGCRC(const_cast<char*>(file_name));
			}
		}
		resource_directory->AdvanceCurrentFile();
	}
	delete resource_directory;


	resource_directory = new Stuff::Directory(missions_path, true);
	Check_Object(resource_directory);

	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{
		Stuff::MString full_name;
		full_name = "Content\\Textures\\customdecals\\";
		full_name += file_name;

		if (gos_FileSize(full_name) < MWApplication::MaxDecalSize)
		{
			Stuff::FileStream test(full_name);

			if (gos_CheckValidTGA((unsigned char *)test.GetPointer(), test.GetSize()))
			{

				FREEANDNULL(name_array[count]);
				name_array[count] = (char *)gos_Malloc(256);
				
				MString short_file_name = file_name;
				GetShortFileName(short_file_name);

				Str_Copy(
					name_array[count],
					(char*)short_file_name,
					strlen((char*)short_file_name) + 1
				);

				FREEANDNULL(full_name_array[count]);
				full_name_array[count] = (char *)gos_Malloc(512);



				Str_Copy(
					full_name_array[count],
					(char*)full_name,
					strlen((char*)full_name) + 1
				);

				++count;

				if (count == MAX_DECALS)
					break;
			}
		}
		resource_directory->AdvanceCurrentFile();
	
	}
	delete resource_directory;



	gos_PopCurrentHeap();
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::CalculateCustomPNGCRC(char *file_name)
{
	//bool __stdcall gos_RenameFile( const char* FileNameFrom, const char* FileNameTo );
	
	MString temp_file_name = file_name;
	temp_file_name.StripExtension();

	char *sub_pointer = strstr((char*)temp_file_name, "_##");
	if (sub_pointer)
	{
		// verify it is _## + 8 leters
		if (strlen(sub_pointer) == 11)
		{
			return;
		}

		// else we just null out the old one

		*sub_pointer = '\0';
	}

	unsigned int crc = 0;

	MString full_file_name;
	full_file_name = "Content\\Textures\\customdecals\\";
	full_file_name += file_name;


	{
	
		Stuff::FileStream file_stream(full_file_name);


		while (file_stream.GetBytesRemaining())
		{
			unsigned short byte = 0;
			file_stream.ReadBytes(&byte, 1);

			crc = crc + byte;
		}
		
	}

	MString new_file_name = temp_file_name;
	new_file_name += "_##";

	char text_buffer[16];
	sprintf(text_buffer, "%08x.tga",crc);

	new_file_name += text_buffer;

	//SPEW(("jerryeds", "decal '%s'", (char*)new_file_name));

	MString new_full_file_name;
	new_full_file_name = "Content\\Textures\\customdecals\\";
	new_full_file_name += new_file_name;


	//SPEW(("jerryeds", "fulldecal '%s'", (char*)new_full_file_name));


	gos_RenameFile( full_file_name,  new_full_file_name);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::GetShortFileName(MString &string)
{
	
	//remove number and extension
	char *sub_pointer = strstr((char*)string, "_##");
	if (sub_pointer)
	{
		*sub_pointer = '\0';
	}
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::SetTeamDecal(void *instance,int numParms,void* data[])
{
	const char *text = STRPARM(0);
	if (text != NULL)
	{
		MW4Shell::Instance->m_teamDecal = text;
	}
	else
	{
		MW4Shell::Instance->m_teamDecal = "\0";
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::SetPilotDecal(void *instance,int numParms,void* data[])
{
	const char *text = STRPARM(0);
	
	if (text != NULL)
	{
		MW4Shell::Instance->m_pilotDecal = text;
	}
	else
	{
		MW4Shell::Instance->m_teamDecal = "\0";
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::StartCampaignMission()
{
	//We need to tell the game that we are starting and what mission we are going
	//to play.  This will cause our save (overwriting the last save game we had)
	//and will set up the stuff in the campaign!
	Check_Object(MWGame::GetInstance());
	MWGame::GetInstance()->StartMission(m_iaMissionName);

	MWApplication::GetInstance()->m_currentMissionName =
		MWApplication::GetInstance()->GetLocString(
			MWGame::GetInstance()->m_campaign->m_currentMissionPlug->m_displayNameIndex);

	ClearMechLab(2);

	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


int MW4Shell::GetMovieFilename(void* data[], int count)
{
	if(m_movieCount > 0)
	{
		Verify(m_movieCount > 0);
		Verify(m_currentMovieIndex < m_movieCount);
		Verify(count == 3);

		Verify(m_movieList[m_currentMovieIndex] != NULL);
		INTPARM(2) = m_currentMovieIndex;
		char** ppString = &STRPARM(1);
		FREEANDNULL(*ppString);
		*ppString = (char*) gos_Malloc(strlen(m_movieList[m_currentMovieIndex]) + 1);

		strcpy(*ppString, m_movieList[m_currentMovieIndex]);
		return 1;
	}
	
	return 0;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int MW4Shell::AdvanceMovie(void* data[], int count)
{
	if(m_movieCount > 0)
	{
		Verify(m_currentMovieIndex < m_movieCount);
		Verify(count == 2);

		int nWay = INTPARM(1);
		if (nWay == ADVANCE_MOVIE_FORWARD)
		{
			if (m_currentMovieIndex + 1 < m_movieCount)
				++m_currentMovieIndex;
		}
		else if (nWay == ADVANCE_MOVIE_REVERSE)
		{
			if (m_currentMovieIndex)
				--m_currentMovieIndex;
		}
		else if (nWay == ADVANCE_MOVIE_END)
		{
			m_currentMovieIndex = m_movieCount - 1;
		}
		return 1;
	}
	return 0;
}


// holo.avi
// skiing.avi

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MW4Shell::AddNewMovie(const char* szFileName)
{
	Check_Pointer(szFileName);
	Verify(m_movieCount <= MAX_MOVIES_IN_MISSION);

	m_currentMovieIndex = m_movieCount++;
	m_movieList[m_currentMovieIndex] = new char[strlen(szFileName) + 1];
	strcpy(m_movieList[m_currentMovieIndex], szFileName);

	//  Mail a message to gosScript indicating they should begin to play this
	HGOSSCRIPT hMovie = gosScript_GetScriptHandle("CampaignScreen", 0);
	if (hMovie)
	{
		int	nMsg = nMSG_PLAYMOVIE;
		//Mail message to main
		gosScript_Command(hMovie, "@CampaignScreen@Screen", gosScript_Cmd_MAILBOX, &nMsg);	// processed this instant!
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


int MW4Shell::TriggerMovie()
{
	static int count = 0;

#if 0
	count++;
	if (count & 1)
	{
		AddNewMovie("RathBurneTest.avi");
	}
	else
	{
		AddNewMovie("karl4.avi");
	}
#endif
	return 1;
}

void MW4Shell::InitMovieList()
{
	for (int i = 0; i < MAX_MOVIES_IN_MISSION; ++i)
	{
		m_movieList[i] = NULL;
	}
	m_movieCount = 0;
	m_currentMovieIndex = 0;
	m_moviePlaying = 0;
	m_moviesStopped = 0;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


void MW4Shell::ResetMovieList()
{
	for (int i = 0; i < m_movieCount; ++i)
	{
		delete[] m_movieList[i];
		m_movieList[i] = NULL;
	}
	m_movieCount = 0;
	m_currentMovieIndex = 0;
	m_moviePlaying = 0;
	m_moviesStopped = 0;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::MyPlayerId(void * instance, int numParms, void*data[])
{

	if (Connection::Local == NULL)
		return 0;

	Verify(Connection::Local);
	return Connection::Local->GetID();

}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


int _stdcall MW4Shell::IsPlayerConnectionValid(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_id = (int)*((int **)data[0]);
	if (connection_id > 255)
		return 0;
	if (connection_id < 1)
		return 0;

	Connection	*connection = Network::GetInstance()->GetConnection(connection_id);

	if (connection == NULL)
		return 0;

	return 1;

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayerConnectionName(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_number = (int)*((int **)data[0]);
	if (connection_number > 255)
		return 0;
	if (connection_number < 0)
		return 0;

	
	Connection	*connection = Network::GetInstance()->GetConnection(connection_number);

	if (*((char **)data[1])) gos_Free(*((char **)data[1]));
	*((char **) data[1]) = (char *)gos_Malloc(256);
	strcpy(*((char **) data[1]), connection->GetConnectionName());



	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayerConnectionClan(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int player_number = (int)*((int **)data[0]);
	if (player_number < 0)
		return 0;
	if (player_number >= Maximum_Players)
		return 0;

	Connection	*connection = Network::GetInstance()->GetConnection(player_number);
	if (connection == NULL)
		return 0;

	MWApplication *app = MWApplication::GetInstance();

	if (app->servedConnectionData[player_number].clanName == NULL)
	{
		return 0;
	}

	if (*((char **)data[1])) gos_Free(*((char **)data[1]));
	*((char **) data[1]) = (char *)gos_Malloc(128);
	strcpy(*((char **) data[1]), app->servedConnectionData[player_number].clanName);



	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayerConnectionReady(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_number = (int)*((int **)data[0]);
	if (connection_number > 255)
		return 0;
	if (connection_number < 0)
		return 0;

	if (!MWApplication::GetInstance()->servedConnectionData[connection_number].clientConnected)
		return 0;


	return MWApplication::GetInstance()->servedConnectionData[connection_number].clientReady;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayerConnectionLaunched(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_number = (int)*((int **)data[0]);
	if (connection_number > 255)
		return 0;
	if (connection_number < 0)
		return 0;

	if (!MWApplication::GetInstance()->servedConnectionData[connection_number].clientConnected)
		return 0;


	return MWApplication::GetInstance()->servedConnectionData[connection_number].clientLaunched;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayerConnectionChasis(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_number = (int)*((int **)data[0]);
	if (connection_number > 255)
		return M_CameraShip;
	if (connection_number < 0)
		return M_CameraShip;

	if (!MWApplication::GetInstance()->servedConnectionData[connection_number].clientConnected)
		return M_CameraShip;

	if (MWApplication::GetInstance()->servedConnectionData[connection_number].mechChasisID == EmptyMechID)
		return M_CameraShip;


	return MWApplication::GetInstance()->servedConnectionData[connection_number].mechChasisID;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayerConnectionTeam(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_number = (int)*((int **)data[0]);
	if (connection_number > 255)
		return 0;
	if (connection_number < 0)
		return 0;

	if (!MWApplication::GetInstance()->servedConnectionData[connection_number].clientConnected)
		return MWApplication::No_Team;

	return MWApplication::GetInstance()->servedConnectionData[connection_number].pilotTeam;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetPlayerConnectionSkin(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_number = (int)*((int **)data[0]);
	if (connection_number > 255)
		return 0;
	if (connection_number < 0)
		return 0;

	if (!MWApplication::GetInstance()->servedConnectionData[connection_number].clientConnected)
		return 0;


	int skin_id = 0;

	Check_Object(MWApplication::GetInstance()->m_skinsTable);


	MWTable::TableIterator *iterator = MWApplication::GetInstance()->m_skinsTable->MakeTableIterator();
	MWTableEntry *entry = NULL;

	while ((entry = iterator->ReadAndNext()) != NULL)
	{
		
		char *prefix = entry->GetData();
	
		if (MWApplication::GetInstance()->servedConnectionData[connection_number].pilotSkins == *prefix)
		{
			delete iterator;
			return skin_id;
		}
		++skin_id;

	}

	delete iterator;


	return 0;
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetLancemates(void* data[], int count)
{
	Check_Object(MWGame::GetInstance());

	int *lance_id = INTARRAYPARAM(1);		//What lance we need a list for
	char **lance_names = STRARRAYPARAM(2);	//The list of names
	int *selected_name = INTARRAYPARAM(3);	//What name is currently selected
	int *num_names = INTARRAYPARAM(4);
	int *lance_icon = INTARRAYPARAM(5);

	#if defined(_ARMOR)
		int array_size = VALUEPARM(5);
	#endif

	ChainIteratorOf<LancematePlug*> iterator(&MWGame::GetInstance()->m_lancemates->m_lancemates);
	LancematePlug *lance_plug;
	PilotPlug *pilot_plug = MWGame::GetInstance()->GetPilot(*lance_id);
	Check_Object(pilot_plug);
	MString current_pilot_name;

	*selected_name = 0;
	*lance_icon = -1;
	if(pilot_plug->GetPilot())
	{
		//Check to make sure that this guy is still with us and not dead.
		if((pilot_plug->GetPilot()->State() == LancematePlug::OK) &&
			(pilot_plug->GetPilot()->Joined()))
		{
			if(pilot_plug->GetMechPlug())
			{
				if(pilot_plug->GetMechPlug()->GetStatus() == MechTablePlug::DestroyedStatus)
				{
					pilot_plug->SetMech(NULL);
				}
			}
			//we have a pilot plug and we need to get what we are set to
			current_pilot_name = pilot_plug->GetPilot()->m_lancemateName;
			*lance_icon = pilot_plug->GetPilot()->GetLanceIDBasedOnSuffix();
		}
		//If he is dead...take away his mech.
		else
		{
			pilot_plug->SetMech(NULL);
			pilot_plug->SetLancePlug(NULL);
		}
	}

	//Set the first entry to "";
	
	FREEANDNULL(lance_names[0]);
	lance_names[0] = (char *)gos_Malloc(128);

	Str_Copy(
		lance_names[0],
		"",
		1
	);

	int i=1;
	while((lance_plug = iterator.ReadAndNext()) != NULL)
	{
		if((lance_plug->State() == LancematePlug::OK) &&
			(lance_plug->Joined()))
		{
			FREEANDNULL(lance_names[i]);
			lance_names[i] = (char *)gos_Malloc(128);
			Str_Copy(
				lance_names[i],
				(const char *)lance_plug->m_lancemateName,
				lance_plug->m_lancemateName.GetLength() + 1
			);

			if(current_pilot_name)
			{
				if(current_pilot_name == lance_plug->m_lancemateName)
					*selected_name = i;
			}

			i ++;
			Verify(i<array_size);
		}
	}

	*num_names = i;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::SetLancemate(void* data[], int count)
{
	Check_Object(MWGame::GetInstance());
	
	int *lance_id = INTARRAYPARAM(1);		//What lance we need a list for
	const char *lance_name = STRPARM(2);	//The list of names

	MWGame::GetInstance()->SetPilot(*lance_id, lance_name);
	
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::SelectCurrentPilot(void* data[], int count)
{
	Check_Object(MWGame::GetInstance());
	
	int *lance_id = INTARRAYPARAM(1);
	PilotPlug *pilot_plug = MWGame::GetInstance()->GetPilot(*lance_id);
	Check_Object(pilot_plug);

	MWGame::GetInstance()->m_currentPilot = pilot_plug;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::VerifyLaunchData()
{
	Check_Object(MWGame::GetInstance());

	return MWGame::GetInstance()->VerifyLaunchData();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetPilotMechData(void *data[], int count)
{
	int *lance_id = INTARRAYPARAM(1);		//What lance we need a list for
	char **mech_name = &STRPARM(2);	//The list of names
	int *mech_id = INTARRAYPARAM(3);	//What name is currently selected

	Check_Object(MWGame::GetInstance());
	PilotPlug *pilot_plug = MWGame::GetInstance()->GetPilot(*lance_id);
	Check_Object(pilot_plug);

	if(!*mech_name)
	{
		FREEANDNULL(*mech_name);
		*mech_name = (char *)gos_Malloc(128);
	}
	if(pilot_plug->GetMechPlug())
	{
		MString name = pilot_plug->GetMechName();

		Str_Copy(
			*mech_name,
			(const char *)name,
			name.GetLength() + 1
		);
	}
	else
	{
		Str_Copy(
			*mech_name,
			" ",
			3
		);
	}

//	if(pilot_plug->GetChassisID() == -1)
//	{
		*mech_id = NoMechID;
//	}
//	else
//	{
//		*mech_id = pilot_plug->GetChassisID();
//	}

	return 1;
}




//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//



int _stdcall MW4Shell::BanPlayer(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_id = (int)*((int **)data[0]);
	if (connection_id > 255)
		return 0;
	if (connection_id < 2)
		return 0;

	Connection	*connection = Network::GetInstance()->GetConnection(connection_id);

	if (connection == NULL)
		return 0;


	MWApplication::GetInstance()->BanPlayer(connection_id);


	return 1;

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//



int _stdcall MW4Shell::BanPlayersISP(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_id = (int)*((int **)data[0]);
	if (connection_id > 255)
		return 0;
	if (connection_id < 21)
		return 0;

	Connection	*connection = Network::GetInstance()->GetConnection(connection_id);

	if (connection == NULL)
		return 0;


	MWApplication::GetInstance()->BanPlayersISP(connection_id);


	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//



int _stdcall MW4Shell::KickPlayer(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_id = (int)*((int **)data[0]);
	if (connection_id > 255)
		return 0;
	if (connection_id < 2)
		return 0;

	Connection	*connection = Network::GetInstance()->GetConnection(connection_id);

	if (connection == NULL)
		return 0;


	MWApplication::GetInstance()->KickPlayer(connection_id);


	return 1;

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//



int _stdcall MW4Shell::SquelchPlayer(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_id = (int)*((int **)data[0]);
	if (connection_id > 255)
		return 0;
	if (connection_id < 2)
		return 0;

	Connection	*connection = Network::GetInstance()->GetConnection(connection_id);

	if (connection == NULL)
		return 0;


	MWApplication::GetInstance()->SquelchPlayer(connection_id);


	return 1;

}




int _stdcall MW4Shell::IsPlayerSquelched(void * instance,int numParms,void* data[])
{	

	Check_Object(Network::GetInstance());

	int connection_id = (int)*((int **)data[0]);
	if (connection_id > 255)
		return 0;
	if (connection_id < 1)
		return 0;

	Connection	*connection = Network::GetInstance()->GetConnection(connection_id);

	if (connection == NULL)
		return 0;


	return MWApplication::GetInstance()->servedConnectionData[connection_id].clientSquelched;

}



int _stdcall MW4Shell::IsMissionReviewAvailable(void *instance,int numParms,void* data[])
{
#if !defined(NO_MR)
	return MWApplication::GetInstance()->missionReviewAvailable;
#else // defined(NO_MR)
    return false;
#endif // !defined(NO_MR)
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// ngLog addition
int _stdcall MW4Shell::IsRegisteredForStats(void *instance,int numParms,void* data[])
{
#if !defined(NO_LOG)
#if 0
	// Old options.ini parsing
	NotationFile options_ini("options.ini", NotationFile::Standard, true);
	Page *page = options_ini.FindPage("Network Options");
	if(page) {
		const char *my_password = "\0";
		const char *my_name = "\0";
		const char *my_usepassword = "\0";

		page->GetEntry("password", &my_password);
		page->GetEntry("playername", &my_name);
		page->GetEntry("usepassword", &my_usepassword);

		if(*my_usepassword && *my_usepassword != 'n' && *my_usepassword != 'N' && *my_password && *my_name) {
			return(1);
		}
	}
#else
	if(MW4Shell::Instance &&
	  MW4Shell::Instance->m_optionsObject->m_password && MW4Shell::Instance->m_optionsObject->m_password[0] &&
	  MW4Shell::Instance->m_optionsObject->m_playerName && MW4Shell::Instance->m_optionsObject->m_playerName[0]) {
		return(1);
	}
#endif
#endif // !defined(NO_LOG)

	return(0);

}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// ngLog addition
int _stdcall MW4Shell::ViewStatsInBrowser(void *instance,int numParms,void* data[])
{
#if !defined(NO_LOG)
	GUID password_guid;

	memset(&password_guid, 0, sizeof(GUID));

#if 0
	// Old options.ini parsing
	NotationFile options_ini("options.ini", NotationFile::Standard, true);
	Page *page = options_ini.FindPage("Network Options");
	if (page) {
		MD5_CTX resource_context;
		unsigned char *buf = (unsigned char *)&password_guid;
		const char *my_password = "\0";
		const char *my_name = "\0";
		const char *my_usepassword = "\0";


		page->GetEntry("password", &my_password);
		page->GetEntry("playername", &my_name);
		page->GetEntry("usepassword", &my_usepassword);

		if(*my_usepassword && *my_usepassword != 'n' && *my_usepassword != 'N' && *my_password && *my_name) {
			char my_hash[128];

			
			MD5Init(&resource_context);
			MD5Update(&resource_context, (unsigned char *) my_name, strlen(my_name));
			MD5Update(&resource_context, (unsigned char *) my_password, strlen(my_password));
			MD5Final(buf, &resource_context);

			my_hash[0] = 0;
			for(int i=0; i<sizeof(GUID); i++) {
				strcat(my_hash, va("%02x", buf[i]));
			}

			gos_EnableSetting(gos_Set_TriggerBrowser,
				(DWORD)va("http://stats.zone.com/fcgi-bin/Search?gt=MW4&gm=all&page=m&view=p&data=%s&type=hash&Nick=%s",
				my_hash, my_name));
		}
	} else {
		return(0);
	}
#else
	if(!MW4Shell::Instance) {
		return(0);
	}

	
	MD5_CTX resource_context;
	unsigned char *buf = (unsigned char *)&password_guid;
	char my_name[64] = {0};
	char my_pass[64] = {0};


	if(MW4Shell::Instance->m_optionsObject->m_password) {
		strncpy(my_pass, MW4Shell::Instance->m_optionsObject->m_password, sizeof(my_pass)-1);
		my_pass[sizeof(my_pass)-1] = 0;
	}

	if(MW4Shell::Instance->m_optionsObject->m_playerName) {
		strncpy(my_name, MW4Shell::Instance->m_optionsObject->m_playerName, sizeof(my_name)-1);
		my_pass[sizeof(my_name)-1] = 0;
	}

	if(my_pass[0] && my_name[0]) {
		char tmp[1024], my_hash[128];

		
		MD5Init(&resource_context);
		MD5Update(&resource_context, (unsigned char *)&my_name, strlen(my_name));
		MD5Update(&resource_context, (unsigned char *)&my_pass, strlen(my_pass));
		MD5Final(buf, &resource_context);

		my_hash[0] = 0;
		for(int i=0; i<sizeof(GUID); i++) {
			sprintf(tmp, "%02x", buf[i]);
			strcat(my_hash, tmp);
		}

		sprintf(tmp,
				"http://stats.zone.com/fcgi-bin/Search?gt=MW4&gm=all&page=m&view=p&data=%s&type=hash&Nick=%s",
				my_hash, my_name);

		gos_EnableSetting(gos_Set_TriggerBrowser, (DWORD)tmp);
	} else {
		return(0);
	}
#endif
#endif // !defined(NO_LOG)

	return(1);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MW4Shell::SelectLastUsedPilot()
{
	//Ok so we need to run through all the Pilots...if there is not one then we need
	//to create a default one.

	bool make_new_pilot = false;
	MString new_pilot_directory = "Resource\\Pilots\\";
	if(!gos_DoesFileExist(new_pilot_directory))
	{
		//This means we have no pilots
		gos_CreateDirectory(new_pilot_directory);
		make_new_pilot = true;
	}
	
	new_pilot_directory += "*.*";
	Stuff::Directory *pilot_directory;
	pilot_directory = new Stuff::Directory(new_pilot_directory, true);
	Check_Object(pilot_directory);
	MString file_name = pilot_directory->GetCurrentFolderName();
	MString selected_pilot;
	__int64 selected_time_stamp = 0;

	while(file_name)
	{
		MString current_pilot_path = "Resource\\Pilots\\";
		current_pilot_path += file_name;
		current_pilot_path += "\\*.mw4";
		Stuff::Directory *current_pilot_directory;
		current_pilot_directory = new Stuff::Directory(current_pilot_path, false);
		MString newest_options_file = current_pilot_directory->currentDirectoryString;
		MString options_file = current_pilot_directory->GetNewestFile();
		if(options_file)
		{
			newest_options_file += options_file;
			__int64 current_file_time = gos_FileTimeStamp((const char *)newest_options_file);
			if(current_file_time > selected_time_stamp)
			{
				selected_pilot = file_name;
				selected_time_stamp = current_file_time;
			}
		}
		delete current_pilot_directory;

		pilot_directory->AdvanceCurrentFolder();
		file_name = pilot_directory->GetCurrentFolderName();
	}

	delete pilot_directory;

	if(selected_time_stamp == 0)
		make_new_pilot = true;

	if(make_new_pilot)
	{
		CreateNewPilot("Default");
		SelectPilot("Default");
	}
	else
	{
		SelectPilot((const char *)selected_pilot);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::SelectPilot(const char *pilot_name)
{
	Check_Object(MWApplication::GetInstance());

	MWApplication::GetInstance()->m_pilotName = pilot_name;

	//Here we also need to load up the options file for the pilot.
	MString new_pilot_directory = "Resource\\Pilots\\";
	if(!gos_DoesFileExist(new_pilot_directory))
		gos_CreateDirectory(new_pilot_directory);
	new_pilot_directory += pilot_name;
	new_pilot_directory += "\\";

	if(m_optionsFile)
		delete m_optionsFile;

	MString options_file_name = new_pilot_directory;
	options_file_name += "options.mw4";

	bool need_create_new = true;
	if(gos_DoesFileExist(options_file_name))
	{
		//if the file exists then open it
		m_optionsFile = ResourceManager::Instance->OpenResourceFile(
			options_file_name,
			NULL,
			OptionsResourceFileID,
			VER_CONTENTVERSION,
			false,
			false,
			false
		);

		//Check to see if the options are there (possible build failure)
		Resource temp_resource("{Player Options}", m_optionsFile);
		if(temp_resource.DoesResourceExist())
			need_create_new = false;
		else
		{
#if defined(LAB_ONLY)
			PAUSE(("Options out of Date, Rebuilding with Default Stream"));
#endif
			delete m_optionsFile;
		}
	}
	if(need_create_new)
	{
		//the file got zapped somehow...create one
		m_optionsFile = ResourceManager::Instance->OpenResourceFile(
			options_file_name,
			NULL,
			OptionsResourceFileID,
			VER_CONTENTVERSION,
			false,
			true,
			false
		);

		DynamicMemoryStream options_stream;
		//By passing a NULL in here...we will get a default stream created.
		MWOptions::ConstructOptionsStream(NULL, &options_stream);
		Resource options_resource("{Player Options}", m_optionsFile);
		options_stream.Rewind();
		options_resource.Save(&options_stream, NULL);
		m_optionsObject = new MWOptions(&options_resource);
		Check_Object(m_optionsObject);

		g_ControlList->LoadDefault ();
		Resource control_resource("{Control Options}", m_optionsFile);
		DynamicMemoryStream control_stream;
		g_ControlList->SaveList (control_stream);
		control_stream.Rewind ();
		control_resource.Save (&control_stream,NULL);
		
		m_optionsFile->Save();
	}

	if(m_optionsObject)
		delete m_optionsObject;

	Resource options_resource("{Player Options}", m_optionsFile);
	options_resource.LoadData();
	Verify(options_resource.DoesResourceExist());

	m_optionsObject = new MWOptions(&options_resource);
	Check_Object(m_optionsObject);
// jcem - begin
	ChannelType::s_sfxVolume = m_optionsObject->m_sfxVolume / 100.0f;
	ChannelType::s_musicVolume = m_optionsObject->m_musicVolume / 100.0f;
// jcem - end
	if(m_optionsObject->m_closingCinemaName)
	{
		Str_Copy(m_endMovieName, 
			(char *)m_optionsObject->m_closingCinemaName, 
			256
		);
	}

	Resource control_resource("{Control Options}", m_optionsFile);
	control_resource.LoadData();
	Verify(control_resource.DoesResourceExist());
	g_ControlList->LoadList (control_resource);

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::SelectPilot(void *data[], int count)
{
	Check_Pointer(this);
	
	const char *pilot_name = STRPARM(1);
	return SelectPilot(pilot_name);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetCurrentPilotName(void *data[], int count)
{
	char **mech_name = &STRPARM(1);

	FREEANDNULL(*mech_name);
	*mech_name = (char *)gos_Malloc(128);

	Str_Copy(
		*mech_name,
		(const char *)MWApplication::GetInstance()->m_pilotName,
		MWApplication::GetInstance()->m_pilotName.GetLength() + 1
	);

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::DeletePilot(void *data[], int count)
{
	Check_Pointer(this);
	
	if(m_optionsObject)
	{
		delete m_optionsObject;
		m_optionsObject = NULL;
	}

	if(m_optionsFile)
	{
		delete m_optionsFile;
		m_optionsFile = NULL;
	}

	if(MWGame::GetInstance())
	{
		delete MWGame::GetInstance();
		GlobalPointers::ClearPointer(MWGameGlobalPointerIndex);
	}

	const char *mech_name = STRPARM(1);
	MString pilot_directory = "Resource\\Pilots\\";
	pilot_directory += mech_name;
	pilot_directory += "\\";

	MString games_directory = pilot_directory;
	games_directory += "Games\\";
	MString games_path = games_directory;
	games_path += "*.*";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(games_path, true);
	Check_Object(resource_directory);
	const char *file_name;
	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{
		MString file = games_directory;
		file += file_name;
		gos_DeleteFile(file);
		resource_directory->AdvanceCurrentFile();
	}
	delete resource_directory;

	games_path.IsolateDirectory();
	gos_DeleteDirectory(games_path);

	MString pilot_path = pilot_directory;
	pilot_path += "*.*";
	resource_directory = new Stuff::Directory(pilot_path, true);
	Check_Object(resource_directory);
	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{
		MString file = pilot_directory;
		file += file_name;
		gos_DeleteFile(file);
		resource_directory->AdvanceCurrentFile();
	}
	delete resource_directory;
	gos_DeleteDirectory(pilot_directory);

	if(!_stricmp((char *)MWApplication::GetInstance()->m_pilotName, mech_name))
		MWApplication::GetInstance()->m_pilotName = "";

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::RenamePilot(void *data[], int count)
{
	Check_Pointer(this);
	
	const char *mech_name = STRPARM(1);
	const char *new_mech_name = STRPARM(2);

	if(m_optionsObject)
	{
		delete m_optionsObject;
		m_optionsObject = NULL;
	}

	if(m_optionsFile)
	{
		delete m_optionsFile;
		m_optionsFile = NULL;
	}

	MString old_pilot_directory = "Resource\\Pilots\\";
	old_pilot_directory += mech_name;
	MString new_pilot_directory = "Resource\\Pilots\\";
	new_pilot_directory += new_mech_name;

	int return_value = 0;
	if ((MWApplication::ValidateName((char*)new_mech_name, true)) && (MWApplication::ValidatePath(new_pilot_directory, true)))
		return_value = gos_RenameFile(old_pilot_directory, new_pilot_directory);

	if (!return_value)
		return -1;

	return return_value;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::ClonePilot(void *data[], int count)
{
	Check_Pointer(this);

	const char *from_pilot_name = STRPARM(1);
	const char *to_pilot_name = STRPARM(2);

	// Select the pilot to be cloned
	SelectPilot(from_pilot_name);
	
	MString new_pilot_directory = "Resource\\Pilots\\";
	//Check the name for slashes that will screw with directory structure
	if(strstr(to_pilot_name, "\\"))
		return -1;
	if(!gos_DoesFileExist(new_pilot_directory))
		gos_CreateDirectory(new_pilot_directory);
	new_pilot_directory += to_pilot_name;
	new_pilot_directory += "\\";

	bool return_value = false;

	if(!gos_DoesFileExist(new_pilot_directory))
	{

		if ((MWApplication::ValidateName((char*)to_pilot_name, true)) && (MWApplication::ValidatePath(new_pilot_directory, true)))
			return_value = gos_CreateDirectory(new_pilot_directory);
		else
			return -1;

		MString options_file_name = new_pilot_directory;
		options_file_name += "options.mw4";

		if(!MWApplication::ValidatePath(options_file_name, false))
			return -1;

		m_optionsFile = ResourceManager::Instance->OpenResourceFile(
			options_file_name,
			NULL,
			OptionsResourceFileID,
			VER_CONTENTVERSION,
			false,
			true,
			false
		);

		DynamicMemoryStream options_stream;

		Resource options_resource("{Player Options}", m_optionsFile);
		m_optionsObject->SaveToStream(&options_stream);
		options_resource.Save(&options_stream, NULL);

		Resource control_resource("{Control Options}", m_optionsFile);
		DynamicMemoryStream control_stream;
		g_ControlList->SaveList (control_stream);
		control_stream.Rewind ();
		control_resource.Save (&control_stream,NULL);

		Check_Object(m_optionsObject);
		m_optionsFile->Save();

	}
	else
	{
		return -1;
	}

	//Clean up because we will get a select after this!
	if(m_optionsFile)
	{
		delete m_optionsFile;
		m_optionsFile = NULL;
	}
	if(m_optionsObject)
	{
		delete m_optionsObject;
		m_optionsObject = NULL;
	}
	return return_value;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::CreateNewPilot(const char *pilot_name, int difficulty)
{
	Check_Pointer(this);

	MString new_pilot_directory = "Resource\\Pilots\\";
	//Check the name for slashes that will screw with directory structure
	if(strstr(pilot_name, "\\"))
		return -1;
	if(!gos_DoesFileExist(new_pilot_directory))
		gos_CreateDirectory(new_pilot_directory);
	new_pilot_directory += pilot_name;
	new_pilot_directory += "\\";

	bool return_value = false;

	if(!gos_DoesFileExist(new_pilot_directory))
	{

		if ((MWApplication::ValidateName((char*)pilot_name, true)) && (MWApplication::ValidatePath(new_pilot_directory, true)))
			return_value = gos_CreateDirectory(new_pilot_directory);
		else
			return -1;

		//When we create a new pilot...we need to create a new options file
		if(m_optionsFile)
			delete m_optionsFile;
		if(m_optionsObject)
			delete m_optionsObject;

		MString options_file_name = new_pilot_directory;
		options_file_name += "options.mw4";

		if((!MWApplication::ValidatePath(options_file_name, false)) || (!return_value))
			return -1;

		m_optionsFile = ResourceManager::Instance->OpenResourceFile(
			options_file_name,
			NULL,
			OptionsResourceFileID,
			VER_CONTENTVERSION,
			false,
			true,
			false
		);

		DynamicMemoryStream options_stream;
		DynamicMemoryStream initial_stream;
		//By passing a NULL in here...we will get a default stream created.
		MWOptions::ConstructOptionsStream(NULL, &initial_stream);

		initial_stream.Rewind();
		Resource options_resource("{Player Options}", m_optionsFile);
		m_optionsObject = new MWOptions(&initial_stream);
		m_optionsObject->m_difficultyLevel = difficulty;
		m_optionsObject->m_playerName = pilot_name;

		NotationFile options_ini("options.ini", NotationFile::Standard, true);
		Page *page = options_ini.FindPage("graphics options");
		if(page)
		{
			int screen_width = 800;
			page->GetEntry("screenwidth", &screen_width);

			switch(screen_width)
			{
			case 1600:
				m_optionsObject->m_resolution=MWOptions::Res1600x1200;
				break;

			case 1280:
				m_optionsObject->m_resolution=MWOptions::Res1280x1024;
				break;
			
			case 1024:
				m_optionsObject->m_resolution=MWOptions::Res1024x768;
				break;
			
			case 800:
				m_optionsObject->m_resolution=MWOptions::Res800x600;
				break;
			
			case 640:
				m_optionsObject->m_resolution=MWOptions::Res640x480;
				break;
			}
		}
		m_optionsObject->SaveToStream(&options_stream);
		options_resource.Save(&options_stream, NULL);

		g_ControlList->LoadDefault ();
		Resource control_resource("{Control Options}", m_optionsFile);
		DynamicMemoryStream control_stream;
		g_ControlList->SaveList (control_stream);
		control_stream.Rewind ();
		control_resource.Save (&control_stream,NULL);
		Check_Object(m_optionsObject);
		m_optionsFile->Save();

	}
	else
	{
		return -1;
	}

	//Clean up because we will get a select after this!
	if(m_optionsFile)
	{
		delete m_optionsFile;
		m_optionsFile = NULL;
	}
	if(m_optionsObject)
	{
		delete m_optionsObject;
		m_optionsObject = NULL;
	}
	return return_value;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::CreateNewPilot(void *data[], int count)
{
	Check_Pointer(this);

	const char *pilot_name = STRPARM(1);
	int difficulty = INTPARM(2);

	return CreateNewPilot(pilot_name, difficulty);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetPilotList(void *data[], int count)
{
	Check_Pointer(this);

	char **pilot_names = STRARRAYPARAM(1);
	int *num_pilots = INTARRAYPARAM(2);

	Stuff::MString mechs_path = "Resource\\Pilots\\*.*";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(mechs_path, true);
	Check_Object(resource_directory);
	const char *file_name;
	int i = 0;
	while((file_name = resource_directory->GetCurrentFolderName()) != NULL)
	{
		FREEANDNULL(pilot_names[i]);
		pilot_names[i] = (char *)gos_Malloc(128);

		Str_Copy(
			pilot_names[i],
			(const char *)file_name,
			strlen(file_name) + 1
		);

		resource_directory->AdvanceCurrentFolder();
		i ++;
	}
	delete resource_directory;
	
	*num_pilots = i;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetDifficultyLevel(void *data[], int count)
{
	int *level = INTARRAYPARAM(1);	

	*level = MWApplication::GetInstance()->GetDifficultyLevel();
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::SetDifficultyLevel(void *data[], int count)
{
	int *level = INTARRAYPARAM(1);

	MWApplication::GetInstance()->SetDifficultyLevel(*level);
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetLanceStats(void *data[], int count)
{
	int *lance_id = INTARRAYPARAM(1);
	int *stats = INTARRAYPARAM(2);

	Check_Object(MWGame::GetInstance());
	PilotPlug *pilot_plug = MWGame::GetInstance()->GetPilot(*lance_id);
	Check_Object(pilot_plug);

	for(int i=0; i<4; i++)
	{
		stats[i] = 0;
	}

	if(pilot_plug->GetPilot())
	{
		stats[0] = pilot_plug->GetPilot()->GunnerySkill();
		Clamp(stats[0], 0, 100);
		stats[1] = pilot_plug->GetPilot()->PilotSkill();
		Clamp(stats[1], 0, 100);
		int sensor = (10 - pilot_plug->GetPilot()->SensorSkill()) * 10;
		stats[2] = sensor;
		Clamp(stats[2], 0, 100);
		stats[3] = pilot_plug->GetPilot()->BlindFightingSkill() / 2;
		Clamp(stats[3], 0, 100);
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetMechStats(void *data[], int count)
{
	int *lance_id = INTARRAYPARAM(1);
	int *stats = INTARRAYPARAM(2);

	Check_Object(MWGame::GetInstance());
	PilotPlug *pilot_plug = MWGame::GetInstance()->GetPilot(*lance_id);
	Check_Object(pilot_plug);

	for(int i=0; i<4; i++)
	{
		stats[i] = 0;
	}

	if(pilot_plug->GetMechPlug())
	{
		stats[0] = 60;
		stats[1] = 50;
		stats[2] = 80;
		stats[3] = 60;
	}

	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetMissionRegionCount(void *data[], int count)
{
	int *region_count = INTARRAYPARAM(1);

	Check_Object(MWGame::GetInstance());
	Check_Object(MWGame::GetInstance()->m_campaign);

	*region_count = MWGame::GetInstance()->m_campaign->GetOPMissionCount();
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetMissionRegionIDs(void *data[], int count)
{
	int *region_ids = INTARRAYPARAM(1);
	int *selected_region = INTARRAYPARAM(2);

	Check_Object(MWGame::GetInstance());
	Check_Object(MWGame::GetInstance()->m_campaign);

	CampaignMissionPlug *mission;
	ChainIteratorOf<CampaignMissionPlug *> iterator(&MWGame::GetInstance()->m_campaign->m_missions);
	int num = 0;
	int current_op = MWGame::GetInstance()->m_campaign->m_currentOp;
	while((mission = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(mission);
		if((mission->m_status != MWCampaign::Hidden) && (mission->m_opNumber == current_op))
		{
			Verify(num < MWGame::GetInstance()->m_campaign->GetOPMissionCount());
			region_ids[num] = mission->m_displayNameIndex;
			num ++;
		}
	}
	
	*selected_region = MWGame::GetInstance()->m_campaign->m_currentMissionPlug->m_displayNameIndex;
	MString name = MWGame::GetInstance()->m_campaign->m_currentMissionPlug->m_missionName;
	name.StripDirectory();
	name.StripExtension();
	Str_Copy(m_iaMissionName, (char *)name, 256);
	MWApplication::GetInstance()->m_currentMissionName = name;
	
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetMissionData(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	char **icon_name = &STRPARM(2);
	char **texture_name = &STRPARM(3);
	int *change_time = INTARRAYPARAM(4);

	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	Resource mission_region(mission_plug->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

	FREEANDNULL(*icon_name);
	*icon_name = (char *)gos_Malloc(128);

	Str_Copy(
		*icon_name,
		(const char *)interface_plug->GetIconName(),
		interface_plug->GetIconName().GetLength() + 1
	);

	FREEANDNULL(*texture_name);
	*texture_name = (char *)gos_Malloc(128);

	Str_Copy(
		*texture_name,
		(const char *)interface_plug->GetMapTextureName(),
		interface_plug->GetMapTextureName().GetLength() + 1
	);

	*change_time = mission_plug->m_canChangeTime;

	delete interface_plug;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetMissionRegionData(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	int *x_location = INTARRAYPARAM(2);
	int *y_location = INTARRAYPARAM(3);
	int *height = INTARRAYPARAM(4);
	int *width = INTARRAYPARAM(5);
	int *status = INTARRAYPARAM(6);
	int *num_lance = INTARRAYPARAM(7);
	char **region_name = &STRPARM(8);
	char **rollover_name = &STRPARM(9);
	char **rclick_name = &STRPARM(10);


	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	Resource mission_region(mission_plug->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

	*x_location = interface_plug->GetXLocation();
	*y_location = interface_plug->GetYLocation();
	*height = interface_plug->GetHeight();
	*width = interface_plug->GetWidth();
	
	*status = mission_plug->m_status;
	*num_lance = mission_plug->m_NumLancemates;

	FREEANDNULL(*region_name);
	*region_name = (char *)gos_Malloc(128);

	MString region_loc_name = MWApplication::GetInstance()->GetLocString(mission_plug->m_displayNameIndex);
	Str_Copy(
		*region_name,
		(const char *)region_loc_name,
		region_loc_name.GetLength() + 1
	);

	FREEANDNULL(*rollover_name);
	*rollover_name = (char *)gos_Malloc(512);

	region_loc_name = MWApplication::GetInstance()->GetLocString(interface_plug->GetRollOverID());
	Str_Copy(
		*rollover_name,
		(const char *)region_loc_name,
		region_loc_name.GetLength() + 1
	);

	FREEANDNULL(*rclick_name);
	*rclick_name = (char *)gos_Malloc(512);

	region_loc_name = MWApplication::GetInstance()->GetLocString(interface_plug->GetRightClickID());
	Str_Copy(
		*rclick_name,
		(const char *)region_loc_name,
		region_loc_name.GetLength() + 1
	);

	

	delete interface_plug;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::SetCampaignMissionName(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);

	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	MWGame::GetInstance()->m_campaign->m_currentMissionPlug = mission_plug;
	MString name = mission_plug->m_missionName;
	name.StripDirectory();
	name.StripExtension();
	Str_Copy(m_iaMissionName, (char *)name, 256);
	MWApplication::GetInstance()->m_currentMissionName = name;

	MWGame::GetInstance()->m_campaign->m_movieManager->ExecuteMissionSelection(name);

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetMissionNavPointCount(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	int *point_count = INTARRAYPARAM(2);

	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	Resource mission_region(mission_plug->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

	*point_count = interface_plug->m_navPoints.GetSize();

	delete interface_plug;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetMissionDropPointCount(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	int *point_count = INTARRAYPARAM(2);

	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	Resource mission_region(mission_plug->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

	*point_count = interface_plug->m_dropPoints.GetSize();

	delete interface_plug;

	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetMissionInfoPointCount(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	int *point_count = INTARRAYPARAM(2);

	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	Resource mission_region(mission_plug->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

	*point_count = interface_plug->m_infoPoints.GetSize();

	delete interface_plug;

	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetGeneralInfoPointCount(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	int *point_count = INTARRAYPARAM(2);

	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	Resource mission_region(mission_plug->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

	*point_count = interface_plug->m_generalInfoPoints.GetSize();

	delete interface_plug;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetMissionNavPoints(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	int *x_location = INTARRAYPARAM(2);
	int *y_location = INTARRAYPARAM(3);
	int *height = INTARRAYPARAM(4);
	int *width = INTARRAYPARAM(5);
	char **point_name = STRARRAYPARAM(6);
	char **rollover_name = STRARRAYPARAM(7);
	char **rclick_name = STRARRAYPARAM(8);

	#if defined(_ARMOR)
		int array_size = VALUEPARM(9);
	#endif

	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	Resource mission_region(mission_plug->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);
	ChainIteratorOf<MWMissionMapPoint *> nav_iterator(&interface_plug->m_navPoints);
	MWMissionMapPoint *nav_point;
	int point_count = 0;
	while((nav_point = nav_iterator.ReadAndNext()) != NULL)
	{
		Verify(point_count < array_size);
		Check_Object(nav_point);
		x_location[point_count] = nav_point->m_xLoc;
		y_location[point_count] = nav_point->m_yLoc;
		width[point_count] = nav_point->m_width;
		height[point_count] = nav_point->m_height;

		FREEANDNULL(point_name[point_count]);
		point_name[point_count] = (char *)gos_Malloc(128);

		MString loc_name = MWApplication::GetInstance()->GetLocString(nav_point->m_textID);
		Str_Copy(
			point_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);

		FREEANDNULL(rollover_name[point_count]);
		rollover_name[point_count] = (char *)gos_Malloc(512);

		loc_name = MWApplication::GetInstance()->GetLocString(nav_point->m_rolltextID);
		Str_Copy(
			rollover_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);

		FREEANDNULL(rclick_name[point_count]);
		rclick_name[point_count] = (char *)gos_Malloc(512);

		loc_name = MWApplication::GetInstance()->GetLocString(nav_point->m_rclicktextID);
		Str_Copy(
			rclick_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);
		
		point_count ++;
	}
	delete interface_plug;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetMissionInfoPoints(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	int *x_location = INTARRAYPARAM(2);
	int *y_location = INTARRAYPARAM(3);
	int *height = INTARRAYPARAM(4);
	int *width = INTARRAYPARAM(5);
	char **point_name = STRARRAYPARAM(6);
	char **rollover_name = STRARRAYPARAM(7);
	char **rclick_name = STRARRAYPARAM(8);
	char **icon_name = STRARRAYPARAM(9);
	#if defined(_ARMOR)
		int array_size = VALUEPARM(10);
	#endif

	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	Resource mission_region(mission_plug->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);
	ChainIteratorOf<MWMissionMapPoint *> info_iterator(&interface_plug->m_infoPoints);
	MWMissionMapPoint *info_point;
	int point_count = 0;
	while((info_point = info_iterator.ReadAndNext()) != NULL)
	{
		Verify(point_count < array_size);
		Check_Object(info_point);
		x_location[point_count] = info_point->m_xLoc;
		y_location[point_count] = info_point->m_yLoc;
		width[point_count] = info_point->m_width;
		height[point_count] = info_point->m_height;

		FREEANDNULL(point_name[point_count]);
		point_name[point_count] = (char *)gos_Malloc(128);

		MString loc_name = MWApplication::GetInstance()->GetLocString(info_point->m_textID);
		Str_Copy(
			point_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);

		FREEANDNULL(rollover_name[point_count]);
		rollover_name[point_count] = (char *)gos_Malloc(512);

		loc_name = MWApplication::GetInstance()->GetLocString(info_point->m_rolltextID);
		Str_Copy(
			rollover_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);

		FREEANDNULL(rclick_name[point_count]);
		rclick_name[point_count] = (char *)gos_Malloc(512);

		loc_name = MWApplication::GetInstance()->GetLocString(info_point->m_rclicktextID);
		Str_Copy(
			rclick_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);

		FREEANDNULL(icon_name[point_count]);
		icon_name[point_count] = (char *)gos_Malloc(256);

		Str_Copy(
			icon_name[point_count],
			(const char *)info_point->m_iconName,
			info_point->m_iconName.GetLength() + 1
		);
		
		point_count ++;
	}
	delete interface_plug;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetMissionDropPoints(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	int *x_location = INTARRAYPARAM(2);
	int *y_location = INTARRAYPARAM(3);
	int *height = INTARRAYPARAM(4);
	int *width = INTARRAYPARAM(5);
	char **point_name = STRARRAYPARAM(6);
	char **rollover_name = STRARRAYPARAM(7);
	char **rclick_name = STRARRAYPARAM(8);
	#if defined(_ARMOR)
		int array_size = VALUEPARM(9);
	#endif

	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	Resource mission_region(mission_plug->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);
	ChainIteratorOf<MWMissionMapPoint *> drop_iterator(&interface_plug->m_dropPoints);
	MWMissionMapPoint *drop_point;
	int point_count = 0;
	while((drop_point = drop_iterator.ReadAndNext()) != NULL)
	{
		Verify(point_count < array_size);
		Check_Object(drop_point);
		x_location[point_count] = drop_point->m_xLoc;
		y_location[point_count] = drop_point->m_yLoc;
		width[point_count] = drop_point->m_width;
		height[point_count] = drop_point->m_height;

		FREEANDNULL(point_name[point_count]);
		point_name[point_count] = (char *)gos_Malloc(512);

		MString loc_name = MWApplication::GetInstance()->GetLocString(drop_point->m_textID);
		Str_Copy(
			point_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);

		FREEANDNULL(rollover_name[point_count]);
		rollover_name[point_count] = (char *)gos_Malloc(512);

		loc_name = MWApplication::GetInstance()->GetLocString(drop_point->m_rolltextID);
		Str_Copy(
			rollover_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);

		FREEANDNULL(rclick_name[point_count]);
		rclick_name[point_count] = (char *)gos_Malloc(512);

		loc_name = MWApplication::GetInstance()->GetLocString(drop_point->m_rclicktextID);
		Str_Copy(
			rclick_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);
		
		point_count ++;
	}
	delete interface_plug;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetMissionGeneralInfoPoints(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	int *x_location = INTARRAYPARAM(2);
	int *y_location = INTARRAYPARAM(3);
	int *height = INTARRAYPARAM(4);
	int *width = INTARRAYPARAM(5);
	char **point_name = STRARRAYPARAM(6);
	char **rollover_name = STRARRAYPARAM(7);
	char **rclick_name = STRARRAYPARAM(8);
	char **icon_name = STRARRAYPARAM(9);
	#if defined(_ARMOR)
		int array_size = VALUEPARM(10);
	#endif

	CampaignMissionPlug *mission_plug = MWGame::GetInstance()->m_campaign->FindMission(*region_id);
	Check_Object(mission_plug);

	Resource mission_region(mission_plug->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);
	ChainIteratorOf<MWMissionMapPoint *> info_iterator(&interface_plug->m_generalInfoPoints);
	MWMissionMapPoint *info_point;
	int point_count = 0;
	while((info_point = info_iterator.ReadAndNext()) != NULL)
	{
		Verify(point_count < array_size);
		Check_Object(info_point);
		x_location[point_count] = info_point->m_xLoc;
		y_location[point_count] = info_point->m_yLoc;
		width[point_count] = info_point->m_width;
		height[point_count] = info_point->m_height;

		FREEANDNULL(point_name[point_count]);
		point_name[point_count] = (char *)gos_Malloc(256);

		MString loc_name = MWApplication::GetInstance()->GetLocString(info_point->m_textID);
		Str_Copy(
			point_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);

		FREEANDNULL(rollover_name[point_count]);
		rollover_name[point_count] = (char *)gos_Malloc(512);

		loc_name = MWApplication::GetInstance()->GetLocString(info_point->m_rolltextID);
		Str_Copy(
			rollover_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);

		FREEANDNULL(rclick_name[point_count]);
		rclick_name[point_count] = (char *)gos_Malloc(512);

		loc_name = MWApplication::GetInstance()->GetLocString(info_point->m_rclicktextID);
		Str_Copy(
			rclick_name[point_count],
			(const char *)loc_name,
			loc_name.GetLength() + 1
		);

		FREEANDNULL(icon_name[point_count]);
		icon_name[point_count] = (char *)gos_Malloc(256);

		Str_Copy(
			icon_name[point_count],
			(const char *)info_point->m_iconName,
			info_point->m_iconName.GetLength() + 1
		);
		
		point_count ++;
	}
	delete interface_plug;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetCampaignOpData(void *data[], int count)
{
	char **op_name = &STRPARM(1);
	char **texture_name = &STRPARM(2);

	int current_op = MWGame::GetInstance()->m_campaign->m_currentOp;
	OperationPlug *op_plug = MWGame::GetInstance()->m_campaign->m_operations.Find(current_op);
	Check_Object(op_plug);

	FREEANDNULL(*op_name);
	*op_name = (char *)gos_Malloc(128);

	MString loc_name = MWApplication::GetInstance()->GetLocString(op_plug->GetNameIndex());
	Str_Copy(
		*op_name,
		(const char *)loc_name,
		loc_name.GetLength() + 1
	);

	FREEANDNULL(*texture_name);
		*texture_name = (char *)gos_Malloc(128);

	Str_Copy(
		*texture_name,
		(const char *)op_plug->GetMapTextureName(),
		op_plug->GetMapTextureName().GetLength() + 1
	);

	return 1;
}


/*
    Sets the m_gameTypeStr to be the abbreviated name for the rule type
    enumeration specified in data[0] (which is expected to be an int variable,
    not a literal value).

    m_gameTypeStr is advertised to the scripts via the registered variable
    "m_gameTypeStr".
*/
int MW4Shell::GetGameTypeString(void * instance, int numParms, void* data[])
{
    const char * ruleName;
    if ( numParms == 2 ) {
        int compareVal;
        switch(VALUEPARM(0))
        {
        case 0:
            compareVal = VALUEPARM(1);
            break;
        case 1:
            compareVal = INTPARM(1);
            break;
        default: // case 2:
            gosASSERT(VALUEPARM(0) == 2);
            compareVal = *INTARRAYPARAM(1);
            break;
        }
        ruleName = GetRuleName( compareVal);
    } else {
        ruleName = NULL;
    }
    m_gameTypeStr = s_gameTypeStr;
    if (ruleName)
    {
        strcpy(s_gameTypeStr, (char *) ruleName);
    return 0;
    } else {
        strcpy(s_gameTypeStr,"");
        return -1;
    }
}


int MW4Shell::GetGameTypeFromString(void * instance, int numParms, void* data[])
{
    if ( numParms == 0 )
    {
        return -1;
    }

    for (int i = 0; i < GameTypeCount; i++)
    {
        if ( !stricmp(STRPARM(0), GetRuleName( i ) ) )
        {
            return i;
        }
    }
    return -1; // not found
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
/*
    author: mdm
    Description: Maps rule type enumeration to a descriptive string.  String
    is designed to be minimal in length.
*/
const char * MW4Shell::GetRuleName( int ruleType )
{
	if ((unsigned int)ruleType >= GameTypeCount)
		return NULL;

	return Application::GetInstance()->GetLocString(IDS_RULENAME_BASE + ruleType);
}

void * __cdecl GetMech4SpecialGameData(int data_type, ...)
{
	if (data_type == 0)
	{
		int ruleType	= ((int *)&data_type)[1];
		int size		= ((int *)&data_type)[2];
		char *buffer	= ((char **)&data_type)[3];

		if ((unsigned int)ruleType >= GameTypeCount)
		{
			if (buffer)
				buffer[0]=0;
			return NULL;
		}

		if (buffer)
			mbs_strncpy(buffer, Application::GetInstance()->GetLocString(IDS_RULENAME_SHORT_BASE + ruleType), size);
		return (void *)1;
	}
	else if (data_type == 1)
	{
		int ruleType	= ((int *)&data_type)[1];
		int size		= ((int *)&data_type)[2];
		char *buffer	= ((char **)&data_type)[3];

		if ((unsigned int)ruleType >= GameTypeCount)
		{
			if (buffer)
				buffer[0]=0;
			return NULL;
		}

		if (buffer)
			mbs_strncpy(buffer, Application::GetInstance()->GetLocString(IDS_RULENAME_BASE + ruleType), size);
		return (void *)1;
	}


	return NULL;
}

char MW4Shell::s_gameTypeStr[128] = ""; // mdm - for game type string is gosscript
char * MW4Shell::m_gameTypeStr = s_gameTypeStr;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetOptionsToggleValue(void *data[], int count)
{
	int toggle_id = (int)data[1];
	int *toggle_value = INTARRAYPARAM(2);
	Check_Object(m_optionsObject);

	*toggle_value = 0;

	switch(toggle_id)
	{
	case MWO_HEAT:
		*toggle_value = m_optionsObject->m_useHeat;
		break;
	case MWO_INVINCIBILITY:
		*toggle_value = m_optionsObject->m_useInvincibility;
		break;
	case MWO_UNLIMITEDAMMO:
		*toggle_value = m_optionsObject->m_unlimmitedAmmo;
		break;
	case MWO_FRIENDLYFIRE:
		*toggle_value = m_optionsObject->m_friendlyFire;
		break;
	case MWO_SPLASHDAMAGE:
		*toggle_value = m_optionsObject->m_splashDamage;
		break;
	case MWO_WEAPONJAM:
		*toggle_value = m_optionsObject->m_weaponJam;
		break;
	case MWO_AMMOBAYFIRE:
		*toggle_value = m_optionsObject->m_ammobayFire;
		break;
// MSL 5.05 Advance Mode
	case MWO_ADVANCEMODE:
		*toggle_value = m_optionsObject->m_advanceMode;
		break;
// MSL 5.06 Armor Mode
	case MWO_ARMORMODE:
		*toggle_value = m_optionsObject->m_armorMode;
		break;
	case MWO_DEFAULTVIEW:
		*toggle_value = m_optionsObject->m_defaultView;
		break;
	case MWO_BETTYSOUND:
		*toggle_value = m_optionsObject->m_bettyOn;
		break;
	case MWO_AUDIOHARDWARE:
		*toggle_value = m_optionsObject->m_audioHardware;
	}
	return 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetOptionsToggleValue(void *data[], int count)
{
	int toggle_id = (int)data[1];
	int *toggle_value = INTARRAYPARAM(2);
	Check_Object(m_optionsObject);

	switch(toggle_id)
	{
	case MWO_HEAT:
		m_optionsObject->m_useHeat = *toggle_value;
		break;
	case MWO_INVINCIBILITY:
		m_optionsObject->m_useInvincibility = *toggle_value;
		break;
	case MWO_UNLIMITEDAMMO:
		m_optionsObject->m_unlimmitedAmmo = *toggle_value;
		break;
	case MWO_FRIENDLYFIRE:
		m_optionsObject->m_friendlyFire = *toggle_value;
		break;
	case MWO_SPLASHDAMAGE:
		m_optionsObject->m_splashDamage = *toggle_value;
		break;
	case MWO_WEAPONJAM:
		m_optionsObject->m_weaponJam = *toggle_value;
		break;
	case MWO_AMMOBAYFIRE:
		m_optionsObject->m_ammobayFire = *toggle_value;
		break;
// MSL 5.05 Advance Mode
	case MWO_ADVANCEMODE:
		m_optionsObject->m_advanceMode = *toggle_value;
		break;
// MSL 5.06 Armor Mode
	case MWO_ARMORMODE:
		m_optionsObject->m_armorMode = *toggle_value;
		break;
	case MWO_DEFAULTVIEW:
		m_optionsObject->m_defaultView = *toggle_value;
		break;
	case MWO_BETTYSOUND:
		m_optionsObject->m_bettyOn = *toggle_value;
		break;
	case MWO_AUDIOHARDWARE:
		m_optionsObject->m_audioHardware = *toggle_value;
		break;
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetOptionsSliderValue(void *data[], int count)
{
	int slider_id = (int)data[1];
	int *slider_value = INTARRAYPARAM(2);

	Check_Object(m_optionsObject);

	switch(slider_id)
	{
	case MWO_GAMMA:
		*slider_value = (int)(m_optionsObject->m_gamma * 100);
		break;
	case MWO_BRIGHTNESS:
		*slider_value = (int)(m_optionsObject->m_brightness * 100);
		break;
	case MWO_CONTRAST:
		*slider_value = (int)(m_optionsObject->m_contrast * 100);
		break;
	case MWO_SFXVOLUME:
		*slider_value = m_optionsObject->m_sfxVolume;
		break;
	case MWO_MUSICVOLUME:
		*slider_value = m_optionsObject->m_musicVolume;
		break;
	default:
		*slider_value = 50;
		return -1;
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetOptionsSliderValue(void *data[], int count)
{
	int slider_id = (int)data[1];
	int *slider_value = INTARRAYPARAM(2);

	Check_Object(m_optionsObject);

	switch(slider_id)
	{
	case MWO_GAMMA:
		{
			Min_Clamp(*slider_value, 1);
			m_optionsObject->m_gamma = (Scalar)(*slider_value / 100.0f);
			Scalar gamma = m_optionsObject->m_gamma * 1.7f + 0.8f;
			gos_SetGammaValue(gamma);
			break;
		}
	case MWO_BRIGHTNESS:
		{
			m_optionsObject->m_brightness = (Scalar)(*slider_value / 100.0f);
			int brightness = (int)(m_optionsObject->m_brightness * 10000);
			gos_SetBrightnessValue((DWORD) brightness );		
			break;
		}
	case MWO_CONTRAST:
		{
			m_optionsObject->m_contrast = (Scalar)(*slider_value / 100.0f);
			int contrast = (int)(m_optionsObject->m_contrast * 20000);
			gos_SetContrastValue((DWORD)contrast);	
			break;
		}
	case MWO_SFXVOLUME:
		m_optionsObject->m_sfxVolume = *slider_value;
		break;
	case MWO_MUSICVOLUME:
		m_optionsObject->m_musicVolume = *slider_value;
//		ABL::g_MissionMusic = (slider_value != 0);
		break;
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetOptionsValue(void *data[], int count)
{
	int option_id = (int)data[1];
	int *option_value = INTARRAYPARAM(2);
	
	Check_Object(m_optionsObject);
	switch(option_id)
	{
	case MWO_DIFFICULTY:
		m_optionsObject->m_difficultyLevel = *option_value;
		break;
	case MWO_SCREENRESOLUTION:
		m_optionsObject->m_resolution = *option_value;
		break;
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetOptionsValue(void *data[], int count)
{
	int option_id = (int)data[1];
	int *option_value = INTARRAYPARAM(2);
	
	Check_Object(m_optionsObject);
	switch(option_id)
	{
	case MWO_DIFFICULTY:
		*option_value = m_optionsObject->m_difficultyLevel;
		break;
	case MWO_SCREENRESOLUTION:
		*option_value = m_optionsObject->m_resolution;
		break;
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SaveOptions()
{
	if(m_optionsObject)
	{
		DynamicMemoryStream options_stream;
		m_optionsObject->SaveToStream(&options_stream);
		options_stream.Rewind();
		Resource options_resource("{Player Options}", m_optionsFile);
		Verify(options_resource.DoesResourceExist());
		options_resource.Save(&options_stream, NULL);

		DynamicMemoryStream control_stream;
		g_ControlList->SaveList (control_stream);
		control_stream.Rewind ();
		Resource control_resource("{Control Options}", m_optionsFile);
		Verify(control_resource.DoesResourceExist());
		control_resource.Save(&control_stream, NULL);
		
		m_optionsFile->Save();

		MWApplication::GetInstance()->InitializeOptions(m_optionsObject);
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::LoadDefaultOptions()
{
	if(m_optionsObject)
	{
		DynamicMemoryStream options_stream;
		MWOptions::ConstructOptionsStream(NULL, &options_stream);
		options_stream.Rewind();
		Resource options_resource("{Player Options}", m_optionsFile);
		Verify(options_resource.DoesResourceExist());
		options_resource.Save(&options_stream, NULL);

		g_ControlList->LoadDefault ();
		Resource control_resource("{Control Options}", m_optionsFile);
		DynamicMemoryStream control_stream;
		g_ControlList->SaveList (control_stream);
		control_stream.Rewind ();
		control_resource.Save (&control_stream,NULL);


		m_optionsFile->Save();
		delete m_optionsObject;
		m_optionsObject = new MWOptions(&options_stream);
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int _stdcall MW4Shell::AddBot(void *instance, int numParams, void* data[])
{
    gosASSERT(!CTCL_IsConsole());
	MWApplication *app = MWApplication::GetInstance();

	// Check to see if we have a full game
	int bot_count = 0;
	int player_count = 0;
	for (int i = 0; i < MWApplication::Maximum_Lancemates; i++)
	{
		if (app->lancemateConnectionData[i].lancemateConnected)
			bot_count++;
	}
	player_count = Network::GetInstance()->GetPlayerCount();
	NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();
	if (params->m_runDedicated)
	{
		// Somehow dedicated server has a player_count of 1 even though there is no player in it
		if ((player_count + bot_count - 1) >= params->m_maxPlayers)
			return -1;
	}
	else
	{
		if ((player_count + bot_count) >= params->m_maxPlayers)
			return -1;
	}

	if (bot_count >= params->m_maxBots)
		return -1;

	int bot_number = app->GetNextLancemateID();
	
	if (bot_number < 0)
		return -1;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return -1;

	app->lancemateConnectionData[bot_number].lancemateConnected = true;
	app->lancemateConnectionData[bot_number].lancemateVehicleAccepted = false;


	int diff_level = INTPARM(0);
	const char *text = STRPARM(1);
	const char *clan = STRPARM(2);
	
	Str_Copy(app->lancemateConnectionData[bot_number].lancemateName, text, ELEMENTS(app->lancemateConnectionData[bot_number].lancemateName));
	Str_Copy(app->lancemateConnectionData[bot_number].lancemateClan, clan, ELEMENTS(app->lancemateConnectionData[bot_number].lancemateClan));

	switch (diff_level)
	{
	case 0:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\WussyBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 1:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\EasyBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 2:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\RookieDodgeBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 3:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\RookieSniperBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 4:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\RookieBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 5:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\DodgeBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 6:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\SniperBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 7:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\KillerBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 8:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\SlaughterBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 9:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\UberBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	default:
		STOP(("INVALID BOT LEVEL <0-9> : %f ", diff_level));
	}

	Resource res("AIPlayers\\MechAI\\mechai.data");

	Verify(res.DoesResourceExist());

	app->lancemateConnectionData[bot_number].aiModel = res.GetResourceID();

	ServerAdvertiser::AddPlayerAll(bot_number+256, text, true);	
	return bot_number;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::RemoveBot(void *instance, int numParams, void* data[])
{


	int bot_number = INTPARM(0);
	
	if (bot_number < 0)
		return -1;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return -1;
	
	MWApplication *app = MWApplication::GetInstance();
	
	int pilotTeam = app->lancemateConnectionData[bot_number].pilotTeam;
	app->lancemateConnectionData[bot_number].Disconnect();

	ServerAdvertiser::RemovePlayerAll(bot_number+256, NULL, true);	
		
	// send a tally on team members to everyone
	if (pilotTeam != MWApplication::No_Team)
	{
		char* message = app->GetTeamCount();
		if (message)
		{
			app->SendChat(
				Connection::Local->GetID(),
				MWApplication::SystemBroadcast,
				0,
				message);
			delete [] message;
		}
	}

	app->ReverifyDeniedVehicles();
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::RemoveAllBots(void *instance, int numParams, void* data[])
{
	MWApplication *app = MWApplication::GetInstance();

	for (int i = 0; i < MWApplication::Maximum_Lancemates; i++) {
	 	
		app->lancemateConnectionData[i].Disconnect();
		ServerAdvertiser::RemovePlayerAll(i+256, NULL, true);	
	}
	// no need to send a tally on team members to clients because
	// the only case RemoveAllBots() is called is when the server
	// changes map.  That means all team will be reset as well.

		
	app->ReverifyDeniedVehicles();
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::SetTeamBot(void *instance, int numParams, void* data[])
{
    gosASSERT(!CTCL_IsConsole());
	int bot_number = INTPARM(0);
	int team_number = INTPARM(1);

	
	if (bot_number < 0)
		return 0;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return 0;
	if (team_number < 0)
		return 0;
	if (team_number > 8)
		return 0;

	MWApplication *app = MWApplication::GetInstance();
		
	app->RequestLancemateTeam(bot_number, team_number);


	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::SetMechBot(void *instance, int numParams, void* data[])
{

	int bot_number = INTPARM(0);
	int mech_index = INTPARM(1);
	const char *mech_name = STRPARM(2);
	
	if (bot_number < 0)
		return 0;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return 0;
	
	MWApplication *app = MWApplication::GetInstance();

	ResourceID mech_id;
	
	mech_id = MW4Shell::Instance->m_mechIDs[mech_index];

	MString resource_file;
	if(mech_id == ResourceID::Null)
	{	
		//
		//-----------------------------------------------------------------
		//This means that we have a user made mech in its own resource file
		//-----------------------------------------------------------------
		//
		resource_file = "Resource\\Variants\\";
		resource_file += mech_name;
		resource_file += ".mw4";
	}
	app->RequestLancemateMech(bot_number, mech_id, resource_file);

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetBotValid(void *instance, int numParams, void* data[])
{


	int bot_number = INTPARM(0);
	
	if (bot_number < 0)
		return 0;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return 0;
	
	MWApplication *app = MWApplication::GetInstance();

	return app->lancemateConnectionData[bot_number].lancemateConnected;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetBotName(void *instance, int numParams, void* data[])
{


	int bot_number = INTPARM(0);
	
	if (bot_number < 0)
		return 0;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return 0;
	
	MWApplication *app = MWApplication::GetInstance();

	if (!app->lancemateConnectionData[bot_number].lancemateConnected)
		return 0;

	if (*((char **)data[1])) gos_Free(*((char **)data[1]));
	*((char **) data[1]) = (char *)gos_Malloc(256);
	strcpy(*((char **) data[1]), app->lancemateConnectionData[bot_number].lancemateName);


	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetBotClan(void *instance, int numParams, void* data[])
{


	int bot_number = INTPARM(0);
	
	if (bot_number < 0)
		return 0;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return 0;
	
	MWApplication *app = MWApplication::GetInstance();

	if (!app->lancemateConnectionData[bot_number].lancemateConnected)
		return 0;

	if (*((char **)data[1])) gos_Free(*((char **)data[1]));
	*((char **) data[1]) = (char *)gos_Malloc(256);
	strcpy(*((char **) data[1]), app->lancemateConnectionData[bot_number].lancemateClan);


	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetBotChasis(void *instance, int numParams, void* data[])
{

	int bot_number = INTPARM(0);
	
	if (bot_number < 0)
		return M_CameraShip;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return M_CameraShip;
	
	MWApplication *app = MWApplication::GetInstance();

	if (app->lancemateConnectionData[bot_number].mechChasisID == EmptyMechID)
		return M_CameraShip;

	return app->lancemateConnectionData[bot_number].mechChasisID;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetBotTeam(void *instance, int numParams, void* data[])
{

	int bot_number = INTPARM(0);
	
	if (bot_number < 0)
		return 0;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return 0;
	
	MWApplication *app = MWApplication::GetInstance();

	return app->lancemateConnectionData[bot_number].pilotTeam;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::GetBotVehicleAccepted(void *instance, int numParams, void* data[])
{

	int bot_number = INTPARM(0);
	
	if (bot_number < 0)
		return 0;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return 0;
	
	MWApplication *app = MWApplication::GetInstance();

	return app->lancemateConnectionData[bot_number].lancemateVehicleAccepted;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

int _stdcall MW4Shell::FillTeams(void *instance, int numParams, void* data[])
{

	int* botIds = INTARRAYPARAM(0);
	int* mechIds = INTARRAYPARAM(1);
	
	return FillBotsForAllTeams(botIds, mechIds);

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int _stdcall MW4Shell::GetTimeToLaunch(void *instance, int numParams, void* data[])
{
	MWApplication *app = MWApplication::GetInstance();

	int *seconds = INTARRAYPARAM(0);
	*seconds = 0;

	if (!app->recycleTimer)
		return 0;

	
	*seconds = (int)app->recycleTimerVal;

	return 1;

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int _stdcall MW4Shell::GetTimeToLaunchLock(void *instance, int numParams, void* data[])
{
	MWApplication *app = MWApplication::GetInstance();

	int *seconds = INTARRAYPARAM(0);
	*seconds = 0;


	if (!app->lockTimer)
		return 0;

	*seconds = (int)app->lockTimerVal;

	return 1;

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int _stdcall MW4Shell::GetTimeToGameEnd(void *instance, int numParams, void* data[])
{
	MWApplication *app = MWApplication::GetInstance();

	int *seconds = INTARRAYPARAM(0);
	*seconds = 0;


	if (!app->gameTimer)
		return 0;

	*seconds = (int)app->gameTimerVal;

	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int _stdcall MW4Shell::GetNetworkError(void *instance, int numParams, void* data[])
{
	MWApplication *app = MWApplication::GetInstance();

	return app->networkExitCode;


}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::DoesHavePilotLoaded(void *data[], int count)
{
	int *does_have_pilot = INTARRAYPARAM(1);

	*does_have_pilot = 0;
	if(m_optionsObject)
		*does_have_pilot = 1;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetIAMissionType(void *data[], int count)
{
	int *ia_mission_type = INTARRAYPARAM(1);
	
	ia_gameType = *ia_mission_type;
	MWApplication::GetInstance()->m_isMasterTrial = false;
	MWApplication::GetInstance()->m_iaDisplayGameType = ia_gameType;

	MWApplication *app = MWApplication::GetInstance();


	NetMissionParameters::MWNetMissionParameters *net_params = MWApplication::GetInstance()->GetLocalNetParams();
	if((ia_gameType == IA_WAVEBATTLE) || (ia_gameType == IA_MASTERTRIAL))
	{
		
		MWApplication::GetInstance()->servedConnectionData[1].pilotTeam = 0;
		
		//This is seven to accomadate clearing out all lances and all bots just to make sure.
		for(int i=0; i<7; i++)
		{
			app->lancemateConnectionData[i].lancemateConnected = false;
		}
		net_params->m_teamAllowed = true;
		net_params->m_teamCount = 2;
		m_lancePerWave = 0;
		m_botsPerWave = 0;
		
		if(ia_gameType == IA_MASTERTRIAL)
			MWApplication::GetInstance()->m_isMasterTrial = true;
	}
	else
	{
		MWApplication::GetInstance()->servedConnectionData[1].pilotTeam = MWApplication::No_Team;

		//This is seven to accomadate clearing out all lances and all bots just to make sure.
		for(int i=0; i<7; i++)
		{
			app->lancemateConnectionData[i].lancemateConnected = false;
		}
		net_params->m_teamAllowed = false;
		net_params->m_teamCount = 0;
		m_lancePerWave = 0;
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetIALancemate(void *data[], int count)
{
	int *lance_id = INTARRAYPARAM(1);
	int *ai_id = INTARRAYPARAM(2);

	MWApplication *app = MWApplication::GetInstance();

	int bot_number = *lance_id + MWApplication::LanceConnectionStart;

	if (bot_number < 0)
		return -1;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return -1;
	

	if(app->lancemateConnectionData[bot_number].lancemateConnected == false)
	{
		Verify(m_lancePerWave < 3);
		m_lancePerWave ++;
	}
	app->lancemateConnectionData[bot_number].lancemateConnected = true;
	//app->lancemateConnectionData[bot_number].lancemateVehicleAccepted = false;
	app->lancemateConnectionData[bot_number].buildName = true;
	if(ia_gameType == IA_WAVEBATTLE)
		app->lancemateConnectionData[bot_number].pilotTeam = 0;

	char text[128];
	sprintf(text, "%d", bot_number);
	Str_Copy(app->lancemateConnectionData[bot_number].lancemateName, text, ELEMENTS(app->lancemateConnectionData[bot_number].lancemateName));

	switch (*ai_id)
	{
	case 0:
		app->lancemateConnectionData[bot_number].lancemateConnected = false;
		m_lancePerWave --;
		break;
	case 1:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\RookieSniperBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 2:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\SniperBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 3:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\UberBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	}

	Resource res("AIPlayers\\MechAI\\mechai.data");

	Verify(res.DoesResourceExist());

	app->lancemateConnectionData[bot_number].aiModel = res.GetResourceID();
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetIALancemateMech(void *data[], int count)
{
	int *lance_id = INTARRAYPARAM(1);
	int *mech_index = INTARRAYPARAM(2);
	char **mech_name =&STRPARM(3);

	MWApplication *app = MWApplication::GetInstance();

	int bot_number = *lance_id + MWApplication::LanceConnectionStart;

	if (bot_number < 0)
		return -1;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return -1;

	ResourceID mech_id = MW4Shell::Instance->m_mechIDs[*mech_index - 1];

	MString resource_file;
	if(mech_id == ResourceID::Null)
	{
		resource_file = "Resource\\Variants\\";
		resource_file += *mech_name;
		resource_file += ".mw4";
	}
	app->RequestLancemateMech(bot_number, mech_id, resource_file);
	
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetWaveMissions(void *data[], int count)
{
	Check_Pointer(this);
	Check_Object(MWCampaign::WaveInstance);
	gos_PushCurrentHeap(MechWarrior4::Heap);

	char **name_array = STRARRAYPARAM(1);
	int *num_missions = INTARRAYPARAM(2);
	
	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::WaveInstance->m_missions);

	CampaignMissionPlug * mission;
	int i = 0;
	while(((mission = iterator.ReadAndNext()) != NULL) && (i < MAX_MISSIONS))
	{
		if(mission->m_status > 0)
		{
			Check_Object(mission);
			FREEANDNULL(name_array[i]);
			name_array[i] = (char *)gos_Malloc(256);
			MString mission_name;
			mission_name = MWApplication::GetInstance()->GetLocString(mission->m_displayNameIndex);
			mission_name.StripDirectory().StripExtension();
			Str_Copy(
				name_array[i],
				(const char *)mission_name,
				mission_name.GetLength() + 1
			);
			i++;
		}
	}

	*num_missions = i;
	gos_PopCurrentHeap();
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetWaveMission(void *data[], int count)
{
	int *mission_index = INTARRAYPARAM(1);
	int *mission_id = INTARRAYPARAM(2);

	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::WaveInstance->m_missions);

	*mission_id = -1;
	//We are less then so we are in the chain
	CampaignMissionPlug *mission = iterator.GetNth(*mission_index);
	Check_Object(mission);

	MString mission_path_name = mission->m_missionName;
	mission_path_name.StripDirectory();
	mission_path_name.StripExtension();
	
	Str_Copy(m_iaMissionName, (char *)mission_path_name, 128);
	MWApplication::GetInstance()->m_currentMissionName = MWApplication::GetInstance()->GetLocString(mission->m_displayNameIndex);
	*mission_id = mission->m_displayNameIndex;

	MWApplication::GetInstance()->m_isNight = false;

	return 1;
}

	
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::AddMechToEnemyAI(void *data[], int count)
{
	int *bot_index = INTARRAYPARAM(1);
	int *mech_index = INTARRAYPARAM(2);
	char **mech_name =&STRPARM(3);
	
	MWApplication *app = MWApplication::GetInstance();

	int bot_number = MWApplication::BotConnectionStart + *bot_index;

	if (bot_number < 0)
		return 0;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return 0;
	
	if(*mech_index == 0)
	{
		//Here we need to clear out the mech that was there...we selected a blank
		app->lancemateConnectionData[bot_number].lancemateConnected = false;
		m_botsPerWave --;
		return 1;
	}
	//This minus one is because the first entry is blank

	//Ok first we have to make sure we are setup as an ai
	if(app->lancemateConnectionData[bot_number].lancemateConnected == false)
	{
		m_botsPerWave ++;
		Verify(m_botsPerWave <= 4);
	}
	app->lancemateConnectionData[bot_number].lancemateConnected = true;
	app->lancemateConnectionData[bot_number].lancemateVehicleAccepted = false;
	app->lancemateConnectionData[bot_number].buildName = true;
	app->lancemateConnectionData[bot_number].pilotTeam = 1;

	char text[128];
	sprintf(text, "%d", bot_number);
	Str_Copy(app->lancemateConnectionData[bot_number].lancemateName, text, ELEMENTS(app->lancemateConnectionData[bot_number].lancemateName));
	Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\KillerBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
	
	Resource res("AIPlayers\\MechAI\\mechai.data");

	Verify(res.DoesResourceExist());

	app->lancemateConnectionData[bot_number].aiModel = res.GetResourceID();

	//Second we need assign the mech
	ResourceID mech_id = MW4Shell::Instance->m_mechIDs[*mech_index - 1];
	MString resource_file;
	if(mech_id == ResourceID::Null)
	{
		resource_file = "Resource\\Variants\\";
		resource_file += *mech_name;
		resource_file += ".mw4";
	}
	
	app->RequestLancemateMech(bot_number, mech_id, resource_file);
	
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetEnemyMechChassis(void *data[], int count)
{
	int *bot_number = INTARRAYPARAM(1);
	int *chassis_id = INTARRAYPARAM(2);
	
	if (*bot_number < 0)
		*chassis_id = -1;
	if (*bot_number >= MWApplication::Maximum_Lancemates)
		*chassis_id = -1;
	
	MWApplication *app = MWApplication::GetInstance();


	*chassis_id = app->lancemateConnectionData[*bot_number].mechChasisID;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::RemoveEnemyAIFromWave(void *data[], int count)
{
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetWaveAITypes(void *data[], int count)
{
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::IAGetMechsWithSpace(void* data[], int count)
{
	Check_Pointer(this);

	char **name_array = STRARRAYPARAM(1);
	int *stock_array = INTARRAYPARAM(2);

	SortedChainOf<PlugOf<MString>*, MString> alpha_mech_names(NULL, true);
	MString* alpha_mech_names_with_mc = new MString[m_mechCount];

	FREEANDNULL(name_array[0]);
	name_array[0] = (char *)gos_Malloc(128);
	Str_Copy(
		name_array[0],
		(const char *)" ",
		3
	);
	stock_array[0] = 1;

	MWTable::TableIterator *mech_iterator;
	Check_Object(MWApplication::GetInstance()->m_mechTable);

	mech_iterator = MWApplication::GetInstance()->m_mechTable->MakeTableIterator();
	MWTableEntry *mech_entry;
	while((mech_entry = mech_iterator->ReadAndNext()) != NULL)
	{
		Check_Object(mech_entry);
		PlugOf<MString> *name_plug = new PlugOf<MString>(mech_entry->GetEntryName());
		alpha_mech_names.AddValue(name_plug, mech_entry->GetEntryName());
	}
	
	delete mech_iterator;

	Stuff::MString mechs_path = "Resource\\Variants\\*.mw4";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(mechs_path, true);
	Check_Object(resource_directory);
	const char *file_name;
	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{
		MString mech_name;
		mech_name = file_name;
		mech_name.StripDirectory().StripExtension();

		PlugOf<MString> *name_plug = new PlugOf<MString>(mech_name);
		alpha_mech_names.AddValue(name_plug, mech_name);

		resource_directory->AdvanceCurrentFile();
	}
	
	// Sort Mad Cat correctly
	SortedChainIteratorOf<PlugOf<MString> *, MString> mech_name_iterator(&alpha_mech_names);
	PlugOf<MString> *mstring_plug;
	int mech_index = 0;
	while((mstring_plug = mech_name_iterator.ReadAndNext()) != NULL)
	{
		if (mech_index == m_mechCount)
			break;	// Boundary Check

		alpha_mech_names_with_mc[mech_index] = mstring_plug->GetItem();
		mech_index ++;
	}
	int mc2_start = 0;
	while (_strnicmp(alpha_mech_names_with_mc[mc2_start], "Mad Cat MKII", 12) != 0)
	{
		mc2_start++;
	}
	int mc2_end = mc2_start;
	while (_strnicmp(alpha_mech_names_with_mc[mc2_end], "Mad Cat MKII", 12) == 0)
	{
		mc2_end++;
	}
	int mc_end = mc2_end;
	while (_strnicmp(alpha_mech_names_with_mc[mc_end], "Mad Cat", 7) == 0)
	{
		mc_end++;
	}
	int mc2_i = mc2_end - mc2_start;
	int mc_i = mc_end - mc2_end;
	MString* mc2_string = new MString[mc2_i];
	for (int i = 0; i < mc2_i; i++)
		mc2_string[i] = alpha_mech_names_with_mc[mc2_start + i];
	for (i = 0; i < mc_i; i++)
		alpha_mech_names_with_mc[mc2_start + i] = alpha_mech_names_with_mc[mc2_end + i];
	for (i = 0; i < mc2_i; i++)
		alpha_mech_names_with_mc[mc2_start + mc_i + i] = mc2_string[i];
	delete [] mc2_string;

	// now return the sorted strings
	mech_index = 0;
	while (mech_index < m_mechCount)
	{
		MString alpha_names = alpha_mech_names_with_mc[mech_index];
		FREEANDNULL(name_array[mech_index + 1]);
		name_array[mech_index + 1] = (char *)gos_Malloc(128);
		Str_Copy(
			name_array[mech_index + 1],
			(const char *)alpha_names,
			alpha_names.GetLength() + 1
		);

		MWTableEntry *mech_table_entry = MWApplication::GetInstance()->m_mechTable->FindEntry(alpha_names);
		if(mech_table_entry)
			stock_array[mech_index + 1] = 1;
		else
			stock_array[mech_index + 1] = 0;
		mech_index ++;
	}

	alpha_mech_names.DeletePlugs();
	delete [] alpha_mech_names_with_mc;
	delete resource_directory;

	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetEnemyWaveCount(void *data[], int count)
{
	int *wave_count = INTARRAYPARAM(1);
	
	if(*wave_count == 5)
		m_waves = -1; //Unlimmited
	else
		m_waves = *wave_count + 1;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetEnemyCount(void *data[], int count)
{
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetWavePlayerRespawns(void *data[], int count)
{
	int *player_lives = INTARRAYPARAM(1);

	if(*player_lives == 5)
		m_playerLives = -1; //Unlimmited!
	else
		m_playerLives = *player_lives + 1;
	return 1;
}

//Training Support
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetTrainingMissions(void *data[], int count)
{
	Check_Pointer(this);
	Check_Object(MWCampaign::TrainingInstance);
	gos_PushCurrentHeap(MechWarrior4::Heap);

	char **name_array = STRARRAYPARAM(1);
	int *num_missions = INTARRAYPARAM(2);
	
	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::TrainingInstance->m_missions);

	CampaignMissionPlug * mission;
	int i = 0;
	while(((mission = iterator.ReadAndNext()) != NULL) && (i < MAX_MISSIONS))
	{
		if(mission->m_status > 0)
		{
			Check_Object(mission);
			FREEANDNULL(name_array[i]);
			name_array[i] = (char *)gos_Malloc(256);
			MString mission_name;
			mission_name = MWApplication::GetInstance()->GetLocString(mission->m_displayNameIndex);
			mission_name.StripDirectory().StripExtension();
			Str_Copy(
				name_array[i],
				(const char *)mission_name,
				mission_name.GetLength() + 1
			);
			i++;
		}
	}

	*num_missions = i;
	gos_PopCurrentHeap();
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetTrainingMission(void *data[], int count)
{
	int *mission_index = INTARRAYPARAM(1);
	int *mission_id = INTARRAYPARAM(2);

	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::TrainingInstance->m_missions);

	*mission_id = -1;
	//We are less then so we are in the chain
	CampaignMissionPlug *mission = iterator.GetNth(*mission_index);
	Check_Object(mission);

	MString mission_path_name = mission->m_missionName;
	mission_path_name.StripDirectory();
	mission_path_name.StripExtension();
	
	Str_Copy(m_iaMissionName, (char *)mission_path_name, 128);
	MWApplication::GetInstance()->m_currentMissionName = MWApplication::GetInstance()->GetLocString(mission->m_displayNameIndex);
	*mission_id = mission->m_displayNameIndex;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetIAMissionName(void *data[], int count)
{
	Check_Pointer(this);
	
	char **mission_name = &STRPARM(1);
	int *mission_index = INTARRAYPARAM(2);
	int *mission_id = INTARRAYPARAM(3);


	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::Instance->m_missions);

	MWApplication *app = MWApplication::GetInstance();

	for (int i = 0; i < MWApplication::Maximum_Lancemates; ++i)
	{
		app->lancemateConnectionData[i].Recycle();
	}

	*mission_id = -1;
	if(*mission_index < iterator.GetSize())
	{
		//We are less then so we are in the chain
		CampaignMissionPlug *mission = iterator.GetNth(*mission_index);
		Check_Object(mission);

		MString mission_path_name = mission->m_missionName;
		mission_path_name.StripDirectory();
		mission_path_name.StripExtension();
		
		Str_Copy(m_iaMissionName, (char *)mission_path_name, 128);
		MWApplication::GetInstance()->m_currentMissionName = MWApplication::GetInstance()->GetLocString(mission->m_displayNameIndex);
		*mission_id = mission->m_displayNameIndex;

		MWApplication::GetInstance()->m_isNight = false;
	}
	else
	{
		MString user_mission_name = "UserMissions\\";
		user_mission_name += *mission_name;
		Str_Copy(m_iaMissionName, (char *)user_mission_name, 256);
		MWApplication::GetInstance()->m_currentMissionName = m_iaMissionName;
		MWApplication::GetInstance()->m_isNight = false;
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::ShellIAGetMapInfo(void *data[], int count)
{
	Check_Pointer(this);

	int *mission_index = INTARRAYPARAM(1);
	char **map_name = &STRPARM(2);
	int *does_have_map = INTARRAYPARAM(3);
	int *num_lancemates = INTARRAYPARAM(4);
	int *allow_time = INTARRAYPARAM(5);

	*allow_time = 1;
	switch(ia_gameType)
	{
		case IA_MISSIONSELECTION:
		{
			
			if(*mission_index > -1)
			{
				CampaignMissionPlug *mission_plug = MWCampaign::Instance->FindMission(*mission_index);
				Check_Object(mission_plug);

				Resource mission_region(mission_plug->m_interfacePlugID);
				Verify(mission_region.DoesResourceExist());
				MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

				FREEANDNULL(*map_name);
				*map_name = (char *)gos_Malloc(128);

				Str_Copy(
					*map_name,
					(const char *)interface_plug->GetMapTextureName(),
					interface_plug->GetMapTextureName().GetLength() + 1
				);

				*num_lancemates = mission_plug->m_NumLancemates;
				*does_have_map = 1;
				*allow_time = mission_plug->m_canChangeTime;

				delete interface_plug;
			}
			else
			{
				*does_have_map = 0;
				*num_lancemates = 3;
			}
			break;
		}
		case IA_WAVEBATTLE:
		{
			if(*mission_index > -1)
			{
				CampaignMissionPlug *mission_plug = MWCampaign::WaveInstance->FindMission(*mission_index);
				Check_Object(mission_plug);

				Resource mission_region(mission_plug->m_interfacePlugID);
				Verify(mission_region.DoesResourceExist());
				MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

				FREEANDNULL(*map_name);
				*map_name = (char *)gos_Malloc(128);

				Str_Copy(
					*map_name,
					(const char *)interface_plug->GetMapTextureName(),
					interface_plug->GetMapTextureName().GetLength() + 1
				);

				*num_lancemates = 3;
				*allow_time = mission_plug->m_canChangeTime;
				if(interface_plug->GetMapTextureName())
					*does_have_map = 1;
				else
					*does_have_map = 0;

				delete interface_plug;
			}
			break;
		}
		case IA_TRAININGMISSION:
		{
			Stuff::ChainIteratorOf<CampaignMissionPlug*>
				iterator(&MWCampaign::TrainingInstance->m_missions);

			//We are less then so we are in the chain
			CampaignMissionPlug *mission_plug = iterator.GetNth(0);

			Resource mission_region(mission_plug->m_interfacePlugID);
			Verify(mission_region.DoesResourceExist());
			MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

			FREEANDNULL(*map_name);
			*map_name = (char *)gos_Malloc(256);

			Str_Copy(
				*map_name,
				(const char *)interface_plug->GetMapTextureName(),
				interface_plug->GetMapTextureName().GetLength() + 1
			);

			*allow_time = mission_plug->m_canChangeTime;
			*num_lancemates = 0;
			*does_have_map = 1;

			delete interface_plug;
			break;
		}
		case IA_MASTERTRIAL:
		{
			*does_have_map = 0;
			*num_lancemates = 0;
			break;
		}
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::IAGetDifficulty(void *data[], int count)
{
	Check_Pointer(this);

	int *difficulty_level = INTARRAYPARAM(1);

	*difficulty_level = MWApplication::GetInstance()->GetDifficultyLevel();
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::IASetDifficulty(void *data[], int count)
{
	Check_Pointer(this);

	int *difficulty_level = INTARRAYPARAM(1);

	MWApplication::GetInstance()->SetDifficultyLevel(*difficulty_level);

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::IAGetWavePlayerRespawns(void *data[], int count)
{
	Check_Pointer(this);

	int *player_respawns = INTARRAYPARAM(1);

	if(m_playerLives == -1)
		*player_respawns = 5;   //Unlimmited
	else
		*player_respawns = m_playerLives - 1;

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::IAGetEnemyWaveCount(void *data[], int count)
{
	Check_Pointer(this);

	int *waves = INTARRAYPARAM(1);

	if(m_waves == -1)
		*waves = 5;   //Unlimmited
	else
		*waves = m_waves - 1;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::IASetupMasterTrials(void *data[], int count)
{
	Check_Pointer(this);
	int *mission_index = INTARRAYPARAM(1);
	int *mission_id	= INTARRAYPARAM(2);
	int *mech_1_index = INTARRAYPARAM(3);
	int *mech_2_index = INTARRAYPARAM(4);
	int *mech_3_index = INTARRAYPARAM(5);
	int *time = INTARRAYPARAM(6);
	char **map_name = &STRPARM(7);
	

	//THIS IS TO FAKE THE SYSTEM!
	ia_gameType = IA_WAVEBATTLE;

	m_playerLives = 3;

	//First Setup the mission
	Check_Object(MWCampaign::MasterTrialsInstance);
	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::MasterTrialsInstance->m_missions);

	*mission_id = -1;
	//We are less then so we are in the chain
	CampaignMissionPlug *mission = iterator.GetNth(*mission_index);
	Check_Object(mission);

	Resource mission_region(mission->m_interfacePlugID);
	Verify(mission_region.DoesResourceExist());
	MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

	FREEANDNULL(*map_name);
	*map_name = (char *)gos_Malloc(128);

	Str_Copy(
		*map_name,
		(const char *)interface_plug->GetMapTextureName(),
		interface_plug->GetMapTextureName().GetLength() + 1
	);

	MString mission_path_name = mission->m_missionName;
	mission_path_name.StripDirectory();
	mission_path_name.StripExtension();
	
	Str_Copy(m_iaMissionName, (char *)mission_path_name, 128);
	MWApplication::GetInstance()->m_currentMissionName = MWApplication::GetInstance()->GetLocString(mission->m_displayNameIndex);

	*mission_id = mission->m_displayNameIndex;
	//Next we need to setup 3 mechs...
	SetUpMasterMech(0, *mech_1_index);
	SetUpMasterMech(1, *mech_2_index);
	SetUpMasterMech(2, *mech_3_index);

	//Last setup the time of day
	switch(*time)
	{
	case 0:
		MWApplication::GetInstance()->m_isNight = false;
		break;
	default:
		MWApplication::GetInstance()->m_isNight = true;
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::IAGetMasterTrialMissions(void *data[], int count)
{
	Check_Pointer(this);
	Check_Object(MWCampaign::MasterTrialsInstance);
	gos_PushCurrentHeap(MechWarrior4::Heap);

	char **name_array = STRARRAYPARAM(1);
	int *num_missions = INTARRAYPARAM(2);
	
	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&MWCampaign::MasterTrialsInstance->m_missions);

	CampaignMissionPlug * mission;
	int i = 0;
	while(((mission = iterator.ReadAndNext()) != NULL) && (i < MAX_MISSIONS))
	{
		if(mission->m_status > 0)
		{
			Check_Object(mission);
			FREEANDNULL(name_array[i]);
			name_array[i] = (char *)gos_Malloc(128);
			MString mission_name;
			mission_name = MWApplication::GetInstance()->GetLocString(mission->m_displayNameIndex);
			mission_name.StripDirectory().StripExtension();
			Str_Copy(
				name_array[i],
				(const char *)mission_name,
				mission_name.GetLength() + 1
			);
			i++;
		}
	}

	*num_missions = i;
	gos_PopCurrentHeap();
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::SetMasterTrialPlayerMech(void *data[], int count)
{
	//For right now we are going to just create a known mech

	int mech_index = INTPARM(1);
	m_mechID = m_stockMechIDs[mech_index];
	const char *mech_name = STRPARM(2);
	//const char *skin_name = STRPARM(3);

	if(m_mechID == ResourceID::Null)
	{	
		//
		//-----------------------------------------------------------------
		//This means that we have a user made mech in its own resource file
		//-----------------------------------------------------------------
		//
		m_mechResourceFile = "Resource\\Variants\\";
		m_mechResourceFile += mech_name;
		m_mechResourceFile += ".mw4";
	}
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MW4Shell::SetUpMasterMech(int bot_index, int mech_index)
{
	Check_Pointer(this);

	MWApplication *app = MWApplication::GetInstance();

	int bot_number = MWApplication::BotConnectionStart + bot_index;

	if (bot_number < 0)
		return;
	if (bot_number >= MWApplication::Maximum_Lancemates)
		return;
	
	//This minus one is because the first entry is blank

	//Ok first we have to make sure we are setup as an ai
	if(app->lancemateConnectionData[bot_number].lancemateConnected == false)
	{
		m_botsPerWave ++;
		Verify(m_botsPerWave < 4);
	}
	app->lancemateConnectionData[bot_number].lancemateConnected = true;
	app->lancemateConnectionData[bot_number].lancemateVehicleAccepted = false;
	app->lancemateConnectionData[bot_number].buildName = true;
	app->lancemateConnectionData[bot_number].pilotTeam = 1;

	char text[128];
	sprintf(text, "%d", bot_number);
	Str_Copy(app->lancemateConnectionData[bot_number].lancemateName, text, ELEMENTS(app->lancemateConnectionData[bot_number].lancemateName));
	
	switch(MWApplication::GetInstance()->GetDifficultyLevel())
	{
	case 0:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\SniperBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 1:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\KillerBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	case 2:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\SlaughterBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		break;
	default:
		Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\UberBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
	}
	
	Resource res("AIPlayers\\MechAI\\mechai.data");

	Verify(res.DoesResourceExist());

	app->lancemateConnectionData[bot_number].aiModel = res.GetResourceID();

	//Second we need assign the mech
	Clamp(mech_index, 0, LastMechID);
	ResourceID mech_id = MW4Shell::Instance->m_stockMechIDs[mech_index];

	MString resource_file;
	app->RequestLancemateMech(bot_number, mech_id, resource_file);
	
}



//========================================================================
//========================================================================
#define UNUSED(x) (x)=(x)
SCRIPTCALLBACK(EnterMultiplayerOptionsScreen)
{
	gosASSERT(args == 10);

	char **	szName			= (char **)arg[0];
	char **	szTeam			= (char **)arg[1];
	int *	nPassToggle		= (int *)arg[2];
	char **	szPass			= (char **)arg[3];
	int *	nPlayerI		= (int *)arg[4];
	int *	nTeamI			= (int *)arg[5];
	char **	szInsignia		= (char **)arg[6];
	char **	szInsigniaFull	= (char **)arg[7];
	int *	nInsigTotal		= (int *)arg[8];
	int *	nAllowDecal		= (int *)arg[9];

	UNUSED(szInsignia);
	//UNUSED(szInsigniaFull);
	//UNUSED(nInsigTotal);

	FREE_PTR(*szName);
	FREE_PTR(*szTeam);
	FREE_PTR(*szPass);

	*szName = (char *)gos_Malloc(256);
	*szTeam = (char *)gos_Malloc(256);
	*szPass = (char *)gos_Malloc(256);

	char *s;

	//
	// prepare to read from options file
	//
	NotationFile startup_ini(OPTIONS_INI, NotationFile::Standard, true);
	Page *page = startup_ini.FindPage(OPTIONS_SECTION);
	if (!page)
		page = startup_ini.AddPage(OPTIONS_SECTION);

#if 0
	// player name
	if (page && page->GetEntry(OPTION_PLAYERNAME, (const char **)&s, false))
		strcpy(*szName, s);
	else
		strcpy(*szName, MWApplication::GetInstance()->m_pilotName);

	// team name
	if (page && page->GetEntry(OPTION_TEAMNAME, (const char **)&s, false))
		strcpy(*szTeam, s);
	else
		strcpy(*szTeam, "Default Team");

	// password
	if (page && page->GetEntry(OPTION_PASSWORD, (const char **)&s, false))
		strcpy(*szPass, s);
	else
		strcpy(*szPass, "");

	// other
	if (page && page->GetEntry(OPTION_USEPASSWORD, (const char **)&s, false))
		*nPassToggle	= *s=='y' || *s=='Y';
	else
		*nPassToggle	= 0;
#else
	(*szName)[0]=0;
	(*szTeam)[0]=0;
	(*szPass)[0]=0;

	char *p;
	p=(char *)MW4Shell::Instance->m_optionsObject->m_playerName;
	if (p) strcpy(*szName, p);
	p=(char *)MW4Shell::Instance->m_optionsObject->m_teamName;
	if (p) strcpy(*szTeam, p);
	p=(char *)MW4Shell::Instance->m_optionsObject->m_password;
	if (p) strcpy(*szPass, p);

	if (szPass[0][0])
		*nPassToggle	= 1;
	else
		*nPassToggle	= 0;

#endif

	if (page && page->GetEntry(OPTION_PLAYERICON, (const char **)&s, false))
	{
		//
		// we've got the name of a file, check to see what index it
		// is in the list
		//
		for (*nPlayerI=0 ; *nPlayerI<*nInsigTotal ; (*nPlayerI)++)
		{
			if (!stricmp(s, szInsigniaFull[*nPlayerI]))
				break;
		}
		if (*nPlayerI == *nInsigTotal)
			*nPlayerI = 0;
	}
	else
		*nPlayerI		= 0;

	if (page && page->GetEntry(OPTION_TEAMICON, (const char **)&s, false))
	{
		//
		// we've got the name of a file, check to see what index it
		// is in the list
		//
		for (*nTeamI=0 ; *nTeamI<*nInsigTotal ; (*nTeamI)++)
		{
			if (!stricmp(s, szInsigniaFull[*nTeamI]))
				break;
		}
		if (*nTeamI == *nInsigTotal)
			*nTeamI = 0;
	}
	else
		*nTeamI		= 0;

	Page *page2 = startup_ini.FindPage(OPTIONS_SERVER_SECTION);

	if (page2 && page2->GetEntry(OPTION_ALLOWDECALTRANSFER, (const char **)&s, false))
		*nAllowDecal	= atoi(s);
	else
		*nAllowDecal	= 0;

#if 0
	if (true)
	{
		int iDecalCount;
		void *args[2];
		char **pszFullNames;

		iDecalCount = MW4Shell::GetDecalCount(NULL, 0, NULL);
		pszFullNames = (char **)gos_Malloc(sizeof(char *) * iDecalCount);

		for (int i=0 ; i<iDecalCount ; i++)
		{
			FREE_PTR(szIcon[i]);
			szIcon[i]		= (char *)gos_Malloc(256);
			pszFullNames[i]	= (char *)gos_Malloc(256);
		}

		args[0] = szIcon;
		args[1] = pszFullNames;

		MW4Shell::GetDecalNames(NULL, 2, args);

		for (i=0 ; i<iDecalCount ; i++)
		{
			FREE_PTR(pszFullNames[i]);
		}
		FREE_PTR(pszFullNames);
	}
#endif
	startup_ini.Save();

	return 0;
}

//========================================================================
//========================================================================
SCRIPTCALLBACK(LeaveMultiplayerOptionsScreen)
{
	gosASSERT(args == 10);

	const char **	szName				= (const char **)arg[0];
	char **			szTeam				= (char **)arg[1];
	int *			nPassToggle			= (int *)arg[2];
	char **			szPass				= (char **)arg[3];
	int *			nPlayerI			= (int *)arg[4];
	int *			nTeamI				= (int *)arg[5];
	char **			szInsignia			= (char **)arg[6];
	char **			szInsigniaFull		= (char **)arg[7];
	int *			nInsigTotal			= (int *)arg[8];
	int *			nAllowDecal			= (int *)arg[9];

	UNUSED(szInsignia);
	//UNUSED(szInsigniaFull);
	UNUSED(nInsigTotal);

	if (!MWApplication::ValidateName((char*)*szName, true))
		return -1;

#define SAVE_VALUES
#ifdef SAVE_VALUES
	//
	// prepare to read from options file
	//
	NotationFile startup_ini(OPTIONS_INI, NotationFile::Standard, true);
	Page *page = startup_ini.FindPage(OPTIONS_SECTION);
	if (!page)
		page = startup_ini.AddPage(OPTIONS_SECTION);

	//
	// player name
	//

#if 0
	//Kill the bad one that we read in without the @
	//page->DeleteNote(OPTION_PLAYERNAME);

	//MString name_entry = "@";
	//name_entry += OPTION_PLAYERNAME;
	//page->SetEntry((const char *)name_entry, *szName);
	page->SetEntry(OPTION_PLAYERNAME, *szName);

	//Kill the bad one that we read in without the @
	//page->DeleteNote(OPTION_TEAMNAME);

	//name_entry = "@";
	//name_entry += OPTION_TEAMNAME;
	//page->SetEntry((const char *)name_entry, *szTeam);
	page->SetEntry(OPTION_TEAMNAME, *szTeam);

	page->SetEntry(OPTION_PASSWORD, *szPass);
	if (*nPassToggle)
		page->SetEntry(OPTION_USEPASSWORD, "Yes");
	else
		page->SetEntry(OPTION_USEPASSWORD, "No");
#else
	MW4Shell::Instance->m_optionsObject->m_playerName	= *szName;
	MW4Shell::Instance->m_optionsObject->m_teamName		= *szTeam;

	if (*nPassToggle)
		MW4Shell::Instance->m_optionsObject->m_password		= *szPass;
	else
		MW4Shell::Instance->m_optionsObject->m_password		= "";
	MW4Shell::Instance->SaveOptions();
#endif

#if 0
	char sz[5];
	sprintf(sz, "%d", *nPlayerI);
	page->SetEntry(OPTION_PLAYERICON, sz);
	sprintf(sz, "%d", *nTeamI);
	page->SetEntry(OPTION_TEAMICON, sz);
#else
	page->SetEntry(OPTION_PLAYERICON, szInsigniaFull[*nPlayerI]);
	page->SetEntry(OPTION_TEAMICON, szInsigniaFull[*nTeamI]);
#endif

	Page *page2 = startup_ini.SetPage(OPTIONS_SERVER_SECTION);

	if (*nAllowDecal)
		page2->SetEntry(OPTION_ALLOWDECALTRANSFER, "1");
	else
		page2->SetEntry(OPTION_ALLOWDECALTRANSFER, "0");

	//
	// save the ini file
	//
	startup_ini.Save();

#else
	szName = szName;
	szTeam = szTeam;
	nPassToggle = nPassToggle;
	szPass = szPass;
	nPlayerI = nPlayerI;
	nTeamI = nTeamI;


#endif



	return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::CampaignGetPlayerStatus(void *data[], int count)
{
	//Here we need to ask the game for the player data
	Check_Object(MWGame::GetInstance());
	char **player_mech = &STRPARM(1);
	int *mech_status = INTARRAYPARAM(2);

	PilotPlug *player_plug = MWGame::GetInstance()->GetPilotLeader();
	Check_Object(player_plug);
	
	FREEANDNULL(*player_mech);
	*player_mech = (char *)gos_Malloc(128);
	Str_Copy(
		*player_mech,
		(const char *)player_plug->GetMechName(),
		player_plug->GetMechName().GetLength() + 1
	);
	
	*mech_status = player_plug->GetMechPlug()->GetStatus();
	
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::CampaignGetLanceStatus(void *data[], int count)
{
	//Here we need to walk throught he current lancemates
	Check_Object(MWGame::GetInstance());
	char **lance_names = STRARRAYPARAM(1);
	int *lance_status = INTARRAYPARAM(2);
	int *base_gunnery = INTARRAYPARAM(3);
	int *new_gunnery = INTARRAYPARAM(4);
	int *base_piloting = INTARRAYPARAM(5);
	int *new_piloting = INTARRAYPARAM(6);
	char **lance_mechs = STRARRAYPARAM(7);
	int *mech_status = INTARRAYPARAM(8);
	int *num_lance = INTARRAYPARAM(9);

	SortedChainIteratorOf<PilotPlug *, int> iterator(&MWGame::GetInstance()->m_lancePilots);
	PilotPlug *pilot;
	int i = 0;
	while((pilot = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(pilot);

		//WE don't want the player here
		if(!pilot->IsPlayer())
		{
			//Make sure we were valid and were in the last mission too
			if(pilot->GetMechPlug() && pilot->GetPilot())
			{
				//Lance Name Enter here
				FREEANDNULL(lance_names[i]);
				lance_names[i] = (char *)gos_Malloc(128);
				Str_Copy(
					lance_names[i],
					(const char *)pilot->GetPilot()->m_lancemateName,
					pilot->GetPilot()->m_lancemateName.GetLength() + 1
				);

				lance_status[i] = pilot->GetPilot()->State();
				base_gunnery[i] = pilot->GetPilot()->GetStartGunnerySkill();
				new_gunnery[i] = pilot->GetPilot()->GunnerySkill();
				base_piloting[i] = pilot->GetPilot()->GetStartPilotSkill();
				new_piloting[i] = pilot->GetPilot()->PilotSkill();
				
				FREEANDNULL(lance_mechs[i]);
				lance_mechs[i] = (char *)gos_Malloc(128);
				Str_Copy(
					lance_mechs[i],
					(const char *)pilot->GetMechName(),
					pilot->GetMechName().GetLength() + 1
				);
				
				mech_status[i] = pilot->GetMechPlug()->GetStatus();

				i++;
			}
		}
	}

	*num_lance = i;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::CampaignGetMechSalvage(void *data[], int count)
{
	//Here we need to get the salvage gotten
	char **mech_name = STRARRAYPARAM(1);
	int *mech_count = INTARRAYPARAM(2);
	int *num_mechs = INTARRAYPARAM(3);

	//Run through the Mechtable looking for new mechs
	Check_Object(MWGame::GetInstance());
	Check_Object(MWGame::GetInstance()->m_campaign);
	int i = 0;

	if(MWGame::GetInstance()->m_campaign->m_currentMissionPlug->m_status == MWCampaign::Completed)
	{
		SortedChainIteratorOf<MechTablePlug *, MString> iterator(&MWGame::GetInstance()->m_mechTable);
		MechTablePlug *mech_plug;
		while((mech_plug = iterator.ReadAndNext()) != NULL)
		{
			Check_Object(mech_plug);
			if(mech_plug->IsNew())
			{
				FREEANDNULL(mech_name[i]);
				mech_name[i] = (char *)gos_Malloc(128);
				Str_Copy(
					mech_name[i],
					(const char *)mech_plug->GetMechName(),
					mech_plug->GetMechName().GetLength() + 1
				);

				mech_count[i] = 1;
				i++;
			}
		}
	}
	*num_mechs = i;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::CampaignGetWeaponSalvage(void *data[], int count)
{
	char **salvage_name = STRARRAYPARAM(1);
	int *salvage_count = INTARRAYPARAM(2);
	int *num_salvage = INTARRAYPARAM(3);

	//Run through the Mechtable looking for new mechs
	Check_Object(MWGame::GetInstance());
	Check_Object(MWGame::GetInstance()->m_salvageManager);
	Check_Object(MWGame::GetInstance()->m_campaign);
	int i = 0;

	if(MWGame::GetInstance()->m_campaign->m_currentMissionPlug->m_status == MWCampaign::Completed)
	{
		SortedChainIteratorOf<SalvagePlug *, int> iterator(&MWGame::GetInstance()->m_salvageManager->m_salvageList);
		SalvagePlug *salvage_plug;
		
		while((salvage_plug = iterator.ReadAndNext()) != NULL)
		{
			Check_Object(salvage_plug);
			if(salvage_plug->m_newCount > 0)
			{
				FREEANDNULL(salvage_name[i]);
				salvage_name[i] = (char *)gos_Malloc(128);
				Str_Copy(
					salvage_name[i],
					(const char *)salvage_plug->m_salvageName,
					salvage_plug->m_salvageName.GetLength() + 1
				);

				salvage_count[i] = salvage_plug->m_newCount;
				i++;
			}
		}
	}
	*num_salvage = i;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::CampaignGetResults(void *data[], int count)
{
	//Here we get the general results including the objectives?  I hope we still have these somewhere
	Check_Object(MWGame::GetInstance());
	Check_Object(MWGame::GetInstance()->m_campaign);

	int *mission_status = INTARRAYPARAM(1);

	*mission_status = MWGame::GetInstance()->m_campaign->m_currentMissionPlug->m_status;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::CampaignGetSavedGames(void *data[], int count)
{
	char **game_names = STRARRAYPARAM(1);
	int *num_games = INTARRAYPARAM(2);

	Stuff::MString games_path = "Resource\\Pilots\\";
	games_path += MWApplication::GetInstance()->m_pilotName;
	games_path += "\\Games\\*.mw4";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(games_path, true);
	Check_Object(resource_directory);
	int i = 0;
	const char *file_name;
	while((file_name = resource_directory->GetNewestFile()) != NULL)
	{
		FREEANDNULL(game_names[i]);
		game_names[i] = (char *)gos_Malloc(256);

		MString game_name;
		game_name = file_name;
		game_name.StripDirectory().StripExtension();
		Str_Copy(
			game_names[i],
			(const char *)game_name,
			game_name.GetLength() + 1
		);
		i++;

		Directory::DirectoryEntry *entry = resource_directory->fileEntries.Find(file_name);
		Check_Object(entry);
		delete entry;
		//resource_directory->AdvanceCurrentFile();
	}

	*num_games = i;
	delete resource_directory;

	return 1;
}

//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::CampaignLoadGame(void *data[], int count)
{
	char **game_name = &STRPARM(1);
	
	if(*game_name)
	{
		if(MWCampaign::Instance)
		{
			delete MWCampaign::Instance;
			MWCampaign::Instance = NULL;
		}

		if(MWGame::GetInstance())
		{
			delete MWGame::GetInstance();
			GlobalPointers::ClearPointer(MWGameGlobalPointerIndex);
		}
		GlobalPointers::AddGlobalPointer(new MWGame(*game_name), MWGameGlobalPointerIndex);
		Check_Object(MWGame::GetInstance());
		m_doesHaveLoadGame = true;

		MWCampaign::Instance = MWGame::GetInstance()->GetCampaign();
	}

	Instance->shellStart = CampaignLoadShellStart;
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::GetLoadMissionName(void *data[], int count)
{
	char **game_name  = &STRPARM(1);

	FREEANDNULL(*game_name);
	*game_name = (char *)gos_Malloc(256);
	::memset(*game_name, 0, 256);

	MString name = MWApplication::GetInstance()->m_currentMissionName;
	if (!(!name))
		Str_Copy(*game_name,(const char *)name, name.GetLength() + 1);
	
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Takes no parameters.  Restores default mapping of input.
int MW4Shell::ControlSetDefault(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	Adept::g_ControlList->GetList(true);
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// In:  int Row - row is relative to group previously selected by
//      int Type - Key, Mouse, Joystick
//      int value (device specific)
//
// Out: Device remapped, 1-2 mail messages sent to reflect changes to script side

static int sm_row = 0;
static int sm_col = 0;

int MW4Shell::ControlAssignValue(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	int row = INTPARM(1);
	int type = INTPARM(2);
	int value = INTPARM(3);
	
	gosASSERT(type == MAP_KEY || type == MAP_JOY || type == MAP_MOUSE);

	int modifier = 0;
	int alteredRow = 0;

	switch (type)
	{
		case MAP_KEY:

			value >>= 8;
			if (value == KEY_ESCAPE)
				return 1;
			modifier = INTPARM(4);
			modifier = modifier >> 8;
			switch (modifier)
			{
				case KEY_LCONTROL:
				case (KEY_LCONTROL|0x100):
					modifier = ControlsManager::CtrlFlag;
					break;
			
				case KEY_LMENU:
					modifier = ControlsManager::AltFlag;
					break;

				case KEY_LSHIFT:
					modifier = ControlsManager::ShiftFlag;
					break;

				case 0:
					modifier = ControlsManager::PlainFlag;
					break;

				default:
					gosASSERT(!"Unknown modifier");
					modifier = ControlsManager::PlainFlag;
			}

			alteredRow = Adept::g_ControlList->AssignControlKey(VehicleInterface::GetInstance(), row, value, modifier);
			break;

		case MAP_JOY:
			modifier = INTPARM(4);
			if (modifier)
				modifier = ControlsManager::ShiftFlag;
			else
				modifier = ControlsManager::PlainFlag;
			alteredRow = Adept::g_ControlList->AssignControlJoy(VehicleInterface::GetInstance(), row, value, modifier);
			break;

		case MAP_MOUSE:
			alteredRow = Adept::g_ControlList->AssignControlMouse(VehicleInterface::GetInstance(), row, value);
			break;
	}


	int msg = nMSG_UPDATE_MAP;

	sm_row = row;
	sm_col = type;

	_SCRIPT* handle = gosScript_GetScriptHandle("OM_Controls", 0);
	if (handle == NULL)
		handle = gosScript_GetScriptHandle("OM_Controls", NET_SCRIPT_PRIORITY);

	gosScript_Command(handle, "@OM_Controls@", gosScript_Cmd_MAILBOX,(void *) &msg);



	if (alteredRow != row)
	{
		sm_row = alteredRow;
		gosScript_Command(handle, "@OM_Controls@", gosScript_Cmd_MAILBOX, (void *) &msg);
	}
	
	
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// In:  No parameters
//
// Out: Any changes made previously with AssignValue are implemented in the remapping code

int MW4Shell::ControlAcceptChanges(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	Adept::g_ControlList->SetList(VehicleInterface::GetInstance());
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// In:  No parameters
//
// Out: Any changes made previously with AssignValue are discarded, and the internal state returns
//      to what is presently implemented on the input remapping.  No mailing occurs - the script
//      must call GetMapping again to sync its state.
//
int MW4Shell::ControlCancelChanges(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	Adept::g_ControlList->GetList(false);
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::ControlSaveSettings(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	Adept::g_ControlList->SaveList(m_memoryStream);
	m_memoryStream.Rewind();
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::ControlRestoreSettings(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	Adept::g_ControlList->LoadList(m_memoryStream);
	Adept::g_ControlList->GetList(false);
	m_memoryStream.Rewind();
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  In:  Category	// BUGBUG:DAN - needs to be defined
//       Command String Array (used as output)
//       Key String Array (used as output)
//       Mouse String Array (used as output)
//       Joy String Array (used as output)
//       count (used as output)
#define DF_STR_BUFFER_SIZE 128

int MW4Shell::ControlGetMapping(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	
//	int category = INTPARM(1);		// BUGBUG:DAN
	char** name_array = STRARRAYPARAM(2);
	char** key_array = STRARRAYPARAM(3);
	char** mouse_array = STRARRAYPARAM(4);
	char** joy_array = STRARRAYPARAM(5);

	int listCount = Adept::g_ControlList->DefListSize();
	if (listCount == 0)
	{
		Adept::g_ControlList->GetList(false);
		listCount = Adept::g_ControlList->DefListSize();
	}

	INTPARM(6) = listCount;

	MWApplication* app = MWApplication::GetInstance();
	for (int i = 0; i < listCount; ++i)
	{
		if (name_array[i])
			FREEANDNULL(name_array[i]);
		name_array[i] = (char*) gos_Malloc(DF_STR_BUFFER_SIZE + 1);
		int nameresid = Adept::g_ControlList->GetControlDef(i).nameresid;
		const char* str = "";
		if (nameresid != 0)
		{
			str = app->GetLocString (nameresid);
		}
		Str_Copy(name_array[i], str, DF_STR_BUFFER_SIZE);

		if (key_array[i])
			FREEANDNULL(key_array[i]);
		key_array[i] = (char*) gos_Malloc(DF_STR_BUFFER_SIZE + 1);
		int nkey = Adept::g_ControlList->GetControlDef(i).nKey;
		Str_Copy(key_array[i], Adept::g_ControlList->GetControlDef(i).KeyName(), DF_STR_BUFFER_SIZE);
		nkey++;
//		if (mouse_array[i])
		FREEANDNULL(mouse_array[i]);
		mouse_array[i] = (char*) gos_Malloc(DF_STR_BUFFER_SIZE + 1);
		if (Adept::g_ControlList->GetControlDef(i).cd_mouse_valid)
		{
			int nMouse = Adept::g_ControlList->GetControlDef(i).nMouse;
			if (nMouse == 512)
			{
				Str_Copy(mouse_array[i], Application::GetInstance()->GetLocString(IDS_MOUSE_WHEEL_DOWN), DF_STR_BUFFER_SIZE);
			}
			else if (nMouse == 513)
			{
				Str_Copy(mouse_array[i], Application::GetInstance()->GetLocString(IDS_MOUSE_WHEEL_UP), DF_STR_BUFFER_SIZE);
			}
			else
			{
				Str_Copy(mouse_array[i], Adept::g_ControlList->GetControlDef(i).MouseName(), DF_STR_BUFFER_SIZE);
			}
		}
		else
		{
			FREEANDNULL(mouse_array[i]);
//			mouse_array[i] = 0;
		}
		
		if (joy_array[i])
			FREEANDNULL(joy_array[i]);
		joy_array[i] = (char*) gos_Malloc(DF_STR_BUFFER_SIZE + 1);
		Str_Copy(joy_array[i], Adept::g_ControlList->GetControlDef(i).JoyName(), DF_STR_BUFFER_SIZE);
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  In:  Row - relative to category
//       Column (Type) - (0-3)  Name Key Mouse Joy
//       String (used as output)
//  ***** note **** mail message must send out row & column!

int MW4Shell::ControlGetValue(void* data[], int count)
{
	INTPARM(1) = sm_row;
	INTPARM(2) = sm_col;
	char** string = &STRPARM(3);

	gosASSERT(sm_row >= 0);
	gosASSERT(sm_col <= 3);

	int type = sm_col;
	gosASSERT(type >= 0  && type <= 3);
	gosASSERT(Adept::g_ControlList != NULL);

//	int size = Adept::g_ControlList->DefListSize();
//	gosASSERT(row < size);

	if (*string)
	{
		FREEANDNULL(*string);
	}

	*string = (char *)gos_Malloc(DF_STR_BUFFER_SIZE + 1);


	// Row += categoryOffset		//BUGBUG - needed?
	switch (type)
	{
		case MAP_CONTROL_NAME:
		{
			int nameresid = Adept::g_ControlList->GetControlDef(sm_row).nameresid;
			const char* str = "none";
			if (nameresid != 0)
			{
				MWApplication* app = MWApplication::GetInstance();
				str = app->GetLocString (nameresid);
			}
			Str_Copy(*string, str, DF_STR_BUFFER_SIZE);
			break;
		}

		case MAP_KEY:
			Str_Copy(*string, Adept::g_ControlList->GetControlDef(sm_row).KeyName(), DF_STR_BUFFER_SIZE);
			break;

		case MAP_MOUSE:
			if (Adept::g_ControlList->GetControlDef(sm_row).cd_mouse_valid)
			{
				int nMouse = Adept::g_ControlList->GetControlDef(sm_row).nMouse;
				if (nMouse == 512)
				{
					Str_Copy(*string, Application::GetInstance()->GetLocString(IDS_MOUSE_WHEEL_DOWN), DF_STR_BUFFER_SIZE);
				}
				else if (nMouse == 513)
				{
					Str_Copy(*string, Application::GetInstance()->GetLocString(IDS_MOUSE_WHEEL_UP), DF_STR_BUFFER_SIZE);
				}
				else
				{
					Str_Copy(*string, Adept::g_ControlList->GetControlDef(sm_row).MouseName(), DF_STR_BUFFER_SIZE);
				}
			}
			else
				*string = 0;
			break;

		case MAP_JOY:
			Str_Copy(*string, Adept::g_ControlList->GetControlDef(sm_row).JoyName(), DF_STR_BUFFER_SIZE);
			break;

		default:
			break;

	}
	return 1;
}


	// Callbacks for input remapping support
int
MW4Shell::ControlGetJoyStickNames(void* data[], int count)
{
	static int joystickCount = -1;

	gosASSERT(Adept::g_ControlList != NULL);
	if (joystickCount == -1)
		joystickCount = gosJoystick_CountJoysticks(false);

	char** name_array = STRARRAYPARAM(2);
	for (int i = 0; i < joystickCount; ++i)
	{
		gosJoystick_Info ji;
		gosJoystick_GetInfo(i, &ji);

		if (name_array[i])
			FREEANDNULL(name_array[i]);
		name_array[i] = (char*) gos_Malloc(strlen(ji.lpstrName) + 1);
		Str_Copy(name_array[i], ji.lpstrName, strlen(ji.lpstrName) + 1);
	}
	INTPARM(1) = joystickCount;
	return 1;
}

int
MW4Shell::ControlGetJoyStickInvert(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = g_ControlList->IsJoyYInverted();
	return 1;
}

int
MW4Shell::ControlGetMouseInvert(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = !g_ControlList->IsMouseYInverted();
	return 1;
}

int
MW4Shell::ControlGetJoyStick(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = g_ControlList->IsJoyStickAllowed();
	return 1;
}

int
MW4Shell::ControlGetMouse(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = g_ControlList->IsMouseAllowed();
	return 1;
}

int
MW4Shell::ControlGetJoyStickShift(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = g_ControlList->IsJoyStickShiftAllowed();
	return 1;
}

int
MW4Shell::ControlGetJoyListSelected(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = g_ControlList->Joystick();
	return 1;
}

int
MW4Shell::ControlSetJoyListSelected(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	g_ControlList->Joystick(INTPARM(1), VehicleInterface::GetInstance());
	return 1;
}

int
MW4Shell::ControlSetJoyStickInvert(void* data[], int count)
{
	bool joyState = (INTPARM(1) != 0);
	g_ControlList->SetJoyYInvert(joyState, VehicleInterface::GetInstance());
	return 1;
}


int
MW4Shell::ControlSetMouseInvert(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	bool mouseState = (INTPARM(1) == 0);
	g_ControlList->SetMouseYInvert(mouseState, VehicleInterface::GetInstance());
	return 1;
}

int
MW4Shell::ControlSetForce(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	bool forceState = (INTPARM(1) != 0);
	g_ControlList->ForceFeedBack(forceState, VehicleInterface::GetInstance());
	return 1;
}

int
MW4Shell::ControlGetForce(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = g_ControlList->ForceFeedBack();
	return 1;
}

int
MW4Shell::ControlSetJoyStickShift(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	bool flag = INTPARM(1) != 0;


	int index1, index2;
	int msgCount = g_ControlList->SetJoyStickShiftAllowed(flag, VehicleInterface::GetInstance(), &index1, &index2);

	if (msgCount)
	{
		int msg = nMSG_UPDATE_MAP;
		sm_row = index1;
		sm_col = MAP_JOY;

		_SCRIPT* handle = gosScript_GetScriptHandle("OM_Controls", 0);
		if (handle == NULL)
			handle = gosScript_GetScriptHandle("OM_Controls", NET_SCRIPT_PRIORITY);

		gosScript_Command(handle, "@OM_Controls@", gosScript_Cmd_MAILBOX, (void *) &msg);

		if (msgCount == 2)
		{
			sm_row = index2;
			gosScript_Command(handle, "@OM_Controls@", gosScript_Cmd_MAILBOX, (void *) &msg);
		}
	}
	return 1;
}

int
MW4Shell::ControlSetJoyStick(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	bool flag = (INTPARM(1) != 0);
	g_ControlList->SetJoyStickAllowed(flag, VehicleInterface::GetInstance());
	return 1;
}

int
MW4Shell::ControlSetMouse(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	bool flag = (INTPARM(1) != 0);
	g_ControlList->SetMouseAllowed(flag, VehicleInterface::GetInstance());
	return 1;
}


int
MW4Shell::ControlSetJoyShiftValue(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	int index1, index2;
	int msgCount = g_ControlList->SetJoyStickShiftValue(INTPARM(1), VehicleInterface::GetInstance(), &index1, &index2);

	if (msgCount)
	{
		int msg = nMSG_UPDATE_MAP;
		sm_row = index1;
		sm_col = MAP_JOY;

		_SCRIPT* handle = gosScript_GetScriptHandle("OM_Controls", 0);
		if (handle == NULL)
			handle = gosScript_GetScriptHandle("OM_Controls", NET_SCRIPT_PRIORITY);

		gosScript_Command(handle, "@OM_Controls@", gosScript_Cmd_MAILBOX, (void *) &msg);

		if (msgCount == 2)
		{
			sm_row = index2;
			gosScript_Command(handle, "@OM_Controls@", gosScript_Cmd_MAILBOX, (void *) &msg);
		}
	}
	return 1;
}

int
MW4Shell::ControlGetJoyShiftValue(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = g_ControlList->GetJoyStickShiftValue();
	return 1;
}

int
MW4Shell::ControlSetMouseSensitivity(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	float value = static_cast<float>(INTPARM(1)) / 100;
	g_ControlList->MouseSensitivity(value, VehicleInterface::GetInstance());
	return 1;
}

int
MW4Shell::ControlGetMouseSensitivity(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	float value = static_cast<float>(INTPARM(1)) / 100;
	value = g_ControlList->MouseSensitivity();
	INTPARM(1) = static_cast<int>(100.0 * value);
	return 1;
}

int
MW4Shell::ControlGetJoyXAxis(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = g_ControlList->JoystickXAxis();
	return 1;
}

int
MW4Shell::ControlGetJoyRudderAxis(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = g_ControlList->JoystickRudderAxis();
	return 1;
}

int
MW4Shell::ControlGetMouseXAxis(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	INTPARM(1) = g_ControlList->MouseXAxis();
	return 1;
}

int
MW4Shell::ControlSetJoyXAxis(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	g_ControlList->JoystickXAxis(INTPARM(1), VehicleInterface::GetInstance());
	return 1;
}


int
MW4Shell::ControlSetJoyRudderAxis(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	g_ControlList->JoystickRudderAxis(INTPARM(1), VehicleInterface::GetInstance());
	return 1;
}


int
MW4Shell::ControlSetMouseXAxis(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);
	g_ControlList->MouseXAxis(INTPARM(1), VehicleInterface::GetInstance());
	return 1;
}

int
MW4Shell::ControlScanKeyboard(void* data[], int count)
{
	const int MyCtrl = 1;
	const int MyShift = 2;
	const int MyAlt = 4;

	static const int Flags[] = {
		ControlsManager::PlainFlag,
		ControlsManager::CtrlFlag,
		ControlsManager::ShiftFlag,
		ControlsManager::CtrlShiftFlag,
		ControlsManager::AltFlag,
		ControlsManager::CtrlAltFlag,
		ControlsManager::ShiftAltFlag,
		ControlsManager::CtrlShiftAltFlag
	};

	//  If no key pressed, return
	DWORD value = gos_GetKey();
	if (value == 0)
		return 0;

	// If key is a modifier, ignore it
	if (value == KEY_LSHIFT || value == KEY_LMENU || value == KEY_LCONTROL)
		return 0;

	//  Key is probably valid here.  Scan for any modifiers currently held down

	int flag = 0;
	gosEnum_KeyStatus status = gos_GetKeyStatus( KEY_LSHIFT );
	if (status == KEY_PRESSED || status == KEY_HELD)
		flag |= MyShift;

	status = gos_GetKeyStatus( KEY_LCONTROL );
	if (status == KEY_PRESSED || status == KEY_HELD)
		flag |= MyCtrl;

	status = gos_GetKeyStatus( KEY_LMENU );
	if (status == KEY_PRESSED || status == KEY_HELD)
		flag |= MyAlt;

	int modifier = Flags[flag];
	int row = INTPARM(1);

	int alteredRow = Adept::g_ControlList->AssignControlKey(VehicleInterface::GetInstance(), row, value, modifier);
	int msg = nMSG_UPDATE_MAP;

	sm_row = row;
	sm_col = MAP_KEY;

	gosScript_Command(gosScript_GetScriptHandle("OM_Controls", NULL),
					  "@OM_Controls@",
					  gosScript_Cmd_MAILBOX,
					  (void *) &msg);



	if (alteredRow != row)
	{
		sm_row = alteredRow;
		gosScript_Command(gosScript_GetScriptHandle("OM_Controls", NULL),
						  "@OM_Controls@",
						  gosScript_Cmd_MAILBOX,
						  (void *) &msg);
	}
	
	return 1;
}




//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::IAGetResults(void *data[], int count)
{
	//This is for the end screen of the Instant Action section.
	
	char **mission_name  = &STRPARM(1);
	char **player_name = &STRPARM(2);
	int *deaths = INTARRAYPARAM(3);
	int *kills = INTARRAYPARAM(4);
	int *status = INTARRAYPARAM(5);
	int *game_type = INTARRAYPARAM(6);
	int *difficulty = INTARRAYPARAM(7);

	FREEANDNULL(*mission_name);
	*mission_name = (char *)gos_Malloc(256);

	MString name = MWApplication::GetInstance()->m_currentMissionName;
	Str_Copy(*mission_name,(const char *)name, name.GetLength() + 1);

	FREEANDNULL(*player_name);
	*player_name = (char *)gos_Malloc(128);

	MString pilot_name = MWApplication::GetInstance()->m_pilotName;
	Str_Copy(*player_name,(const char *)pilot_name, pilot_name.GetLength() + 1);

	*status = MWApplication::GetInstance()->m_currentMissionStatus;

	//*deaths = MWApplication::GetInstance->servedConnectionData[Connection::Local->GetID() ].clientPlayer
	*deaths = MWApplication::GetInstance()->m_lastMissionDeaths;
	*kills = MWApplication::GetInstance()->m_lastMissionKills;

	*game_type = MWApplication::GetInstance()->m_iaDisplayGameType;

	*difficulty = MWApplication::GetInstance()->GetDifficultyLevel();

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetIAMissionRegionData(void *data[], int count)
{
	int *region_id = INTARRAYPARAM(1);
	char **rollover_name = &STRPARM(2);

	CampaignMissionPlug *mission_plug = MWCampaign::Instance->FindMission(*region_id);
	if(mission_plug)
	{
		Resource mission_region(mission_plug->m_interfacePlugID);
		Verify(mission_region.DoesResourceExist());
		MWCampaignInterfacePlug *interface_plug = new MWCampaignInterfacePlug(&mission_region);

		FREEANDNULL(*rollover_name);
		*rollover_name = (char *)gos_Malloc(512);

		MString region_loc_name = MWApplication::GetInstance()->GetLocString(interface_plug->GetRollOverID());
		Str_Copy(
			*rollover_name,
			(const char *)region_loc_name,
			region_loc_name.GetLength() + 1
		);

		delete interface_plug;
		return 1;
	}
	return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::CampaignPlayIntro(void *data[], int count)
{
	Check_Object(MWGame::GetInstance());
	int return_value = MWGame::GetInstance()->m_isNewGame;
	MWGame::GetInstance()->m_isNewGame = false;
	return return_value;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::CampaignPlayEnd(void *data[], int count)
{
	char **movie_name = &STRPARM(1);
	
	if(MWApplication::GetInstance()->m_campaignIsComplete)
	{
		MString movie_string;
		Check_Object(MWGame::GetInstance());
		Check_Object(MWGame::GetInstance()->m_campaign);
		
		movie_string = MWGame::GetInstance()->m_campaign->m_finalMovieName;
		if(!movie_string)
			return 0;

		FREEANDNULL(*movie_name);
		*movie_name = (char *)gos_Malloc(256);

		Str_Copy(
			*movie_name,
			(const char *)movie_string,
			movie_string.GetLength() + 1
		);

		if(m_optionsObject)
		{
			m_optionsObject->m_closingCinemaName = movie_string;
			SaveOptions();
		}

		MWApplication::GetInstance()->m_campaignIsComplete = false;
		return 1;
	}
	return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::CampaignGetMechBars(void *data[], int count)
{
	char **mech_name = &STRPARM(1);
	int *stats = INTARRAYPARAM(2);

	Check_Object(MWGame::GetInstance());

	MString name = *mech_name;
	name.ToLower();
	MechTablePlug *mech_plug = MWGame::GetInstance()->m_mechTable.Find(name);
	if(mech_plug)
	{

		Resource mech_instance_resource(mech_plug->GetMechResourceID());
		Verify(mech_instance_resource.DoesResourceExist());

		Mech::CreateMessage *mech_message = Cast_Pointer(Mech::CreateMessage *, mech_instance_resource.GetPointer());
		
		stats[0] = mech_message->m_powerBar;
		stats[1] = mech_message->m_armorBar;
		stats[2] = mech_message->m_speedBar;
		stats[3] = mech_message->m_heatBar;
	}
	else
	{
		stats[0] = 0;
		stats[1] = 0;
		stats[2] = 0;
		stats[3] = 0;
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::IAGetMechBars(void *data[], int count)
{
	char **mech_name = &STRPARM(1);
	int *mech_index = INTARRAYPARAM(2);
	int *stats = INTARRAYPARAM(3);
	int *mech_icon_id = INTARRAYPARAM(4);

	if(*mech_index >= 0)
	{
		ResourceFile *res_file = NULL;
		ResourceID mech_id = m_mechIDs[*mech_index];
		if(mech_id == ResourceID::Null)
		{	

			//
			//-----------------------------------------------------------------
			//This means that we have a user made mech in its own resource file
			//-----------------------------------------------------------------
			//
			MString path_name = "Resource\\Variants\\";
			path_name += *mech_name;
			MString res_name = path_name;
			res_name += ".mw4";
			Check_Object(ResourceManager::Instance);
			res_file = ResourceManager::Instance->OpenResourceFile(
				res_name,
				NULL,
				MechResourceFileID,
				VER_CONTENTVERSION,
				false,
				false
			);
			Check_Object(res_file);
			ResourceID temp_id(MechResourceFileID, 1);
			mech_id = temp_id;
		}
			
		Resource *mech_instance_resource = new Resource(mech_id);
		Verify(mech_instance_resource->DoesResourceExist());

		Mech::CreateMessage *mech_message = Cast_Pointer(Mech::CreateMessage *, mech_instance_resource->GetPointer());
		
		stats[0] = mech_message->m_powerBar;
		stats[1] = mech_message->m_armorBar;
		stats[2] = mech_message->m_speedBar;
		stats[3] = mech_message->m_heatBar;

		*mech_icon_id = mech_message->m_mechID;
		Clamp(*mech_icon_id, 0, LastMechID);

		if(mech_instance_resource)
			delete mech_instance_resource;
		if(res_file)
			delete res_file;
	}
	else
	{
		stats[0] = 0;
		stats[1] = 0;
		stats[2] = 0;
		stats[3] = 0;

		*mech_icon_id = NoMechID;
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetMasterMechBars(void *data[], int count)
{
	int *mech_index = INTARRAYPARAM(1);
	int *stats = INTARRAYPARAM(2);
	int *mech_icon_id = INTARRAYPARAM(3);

	if(*mech_index >= 0)
	{
		ResourceID mech_id = m_stockMechIDs[*mech_index];
		Verify(mech_id != ResourceID::Null);
			
		Resource *mech_instance_resource = new Resource(mech_id);
		Verify(mech_instance_resource->DoesResourceExist());

		Mech::CreateMessage *mech_message = Cast_Pointer(Mech::CreateMessage *, mech_instance_resource->GetPointer());
		
		stats[0] = mech_message->m_powerBar;
		stats[1] = mech_message->m_armorBar;
		stats[2] = mech_message->m_speedBar;
		stats[3] = mech_message->m_heatBar;

		*mech_icon_id = mech_message->m_mechID;
		Clamp(*mech_icon_id, 0, LastMechID);

		if(mech_instance_resource)
			delete mech_instance_resource;
	}
	else
	{
		stats[0] = 0;
		stats[1] = 0;
		stats[2] = 0;
		stats[3] = 0;

		*mech_icon_id = NoMechID;
	}

	return 1;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetTrainingMechBars(void *data[], int count)
{
	int *stats = INTARRAYPARAM(1);

	MWTable *mech_table = MWApplication::GetInstance()->m_mechTable;
	MWTableEntry *mech_entry = mech_table->FindEntry("Shadow cat");
	ResourceID mech_id = mech_entry->GetEntryResourceID();

	if(mech_id != ResourceID::Null)
	{
		Resource *mech_instance_resource = new Resource(mech_id);
		Verify(mech_instance_resource->DoesResourceExist());

		Mech::CreateMessage *mech_message = Cast_Pointer(Mech::CreateMessage *, mech_instance_resource->GetPointer());
		
		stats[0] = mech_message->m_powerBar;
		stats[1] = mech_message->m_armorBar;
		stats[2] = mech_message->m_speedBar;
		stats[3] = mech_message->m_heatBar;

		delete mech_instance_resource;
	}
	else
	{
		stats[0] = 0;
		stats[1] = 0;
		stats[2] = 0;
		stats[3] = 0;
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetClosingCinema(void *data[], int count)
{
	char **movie_name = &STRPARM(1);

	if(m_optionsObject)
	{
		if(m_optionsObject->m_closingCinemaName)
		{
			FREEANDNULL(*movie_name);
			*movie_name = (char *)gos_Malloc(256);

			Str_Copy(
				*movie_name,
				(const char *)m_optionsObject->m_closingCinemaName,
				m_optionsObject->m_closingCinemaName.GetLength() + 1
			);
			return 1;
		}
	}
	return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::SetMasterTrialDifficutly(void *data[], int count)
{
	int *difficulty = INTARRAYPARAM(1);

	MWApplication::GetInstance()->SetDifficultyLevel(*difficulty);

	MWApplication *app = MWApplication::GetInstance();

	for(int i=0; i<3; i++)
	{
		int bot_number = MWApplication::BotConnectionStart + i;

		if (bot_number < 0)
			return 0;
		if (bot_number >= MWApplication::Maximum_Lancemates)
			return 0;
	
		switch(MWApplication::GetInstance()->GetDifficultyLevel())
		{
		case 0:
			Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\SniperBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
			break;
		case 1:
			Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\KillerBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
			break;
		case 2:
			Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\SlaughterBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
			break;
		default:
			Str_Copy(app->lancemateConnectionData[bot_number].scriptName, "Content\\ABLScripts\\Bots\\UberBot.abl", ELEMENTS(app->lancemateConnectionData[bot_number].scriptName));
		}
	}
	return 1;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::LaunchTrainingMission()
{
	MWTableEntry *mech_table_entry = MWApplication::GetInstance()->m_mechTable->FindEntry("shadow cat");
	Check_Object(mech_table_entry);

	m_mechID = mech_table_entry->GetEntryResourceID();

	MWCampaign *training_campaign = MWCampaign::MakeNewCampaign("Content\\Campaigns\\Training.campaign");
	Check_Pointer(training_campaign);

	Stuff::ChainIteratorOf<CampaignMissionPlug*>
		iterator(&training_campaign->m_missions);

	CampaignMissionPlug *mission = iterator.GetNth(0);
	Check_Object(mission);

	MString mission_path_name = mission->m_missionName;
	mission_path_name.StripDirectory();
	mission_path_name.StripExtension();

	Str_Copy(m_iaMissionName, (char *)mission_path_name, 128);
	MWApplication::GetInstance()->m_currentMissionName = MWApplication::GetInstance()->GetLocString(mission->m_displayNameIndex);

	HeatManager::g_OverrideHeatOption = true;

	delete training_campaign;
	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::GetSupportedRes(void *data[], int count)
{
	char **res_list = STRARRAYPARAM(1);
	int *num_res = INTARRAYPARAM(2);

	int num = 0;

	if(gos_GetMachineInformation( gos_Info_ValidMode, Environment.FullScreenDevice, 640, 480 ))
	{
		FREEANDNULL(res_list[num]);
		res_list[num] = (char *)gos_Malloc(128);
		MString res_name = "640 x 480";
		Str_Copy(
			res_list[num],
			(const char *)res_name,
			res_name.GetLength() + 1
		);
		num ++;
	}

	if(gos_GetMachineInformation( gos_Info_ValidMode, Environment.FullScreenDevice, 800, 600 ))
	{
		FREEANDNULL(res_list[num]);
		res_list[num] = (char *)gos_Malloc(128);
		MString res_name = "800 x 600";
		Str_Copy(
			res_list[num],
			(const char *)res_name,
			res_name.GetLength() + 1
		);
		num ++;
	}

	if(gos_GetMachineInformation( gos_Info_ValidMode, Environment.FullScreenDevice, 1024, 768 ))
	{
		FREEANDNULL(res_list[num]);
		res_list[num] = (char *)gos_Malloc(128);
		MString res_name = "1024 x 768";
		Str_Copy(
			res_list[num],
			(const char *)res_name,
			res_name.GetLength() + 1
		);
		num ++;
	}

	if(gos_GetMachineInformation( gos_Info_ValidMode, Environment.FullScreenDevice, 1280, 1024 ))
	{
		FREEANDNULL(res_list[num]);
		res_list[num] = (char *)gos_Malloc(128);
		MString res_name = "1280 x 1024";
		Str_Copy(
			res_list[num],
			(const char *)res_name,
			res_name.GetLength() + 1
		);
		num ++;
	}

	if(gos_GetMachineInformation( gos_Info_ValidMode, Environment.FullScreenDevice, 1600, 1200 ))
	{
		FREEANDNULL(res_list[num]);
		res_list[num] = (char *)gos_Malloc(128);
		MString res_name = "1600 x 1200";
		Str_Copy(
			res_list[num],
			(const char *)res_name,
			res_name.GetLength() + 1
		);
		num ++;
	}

	*num_res = num;
	return 1;
}

int
MW4Shell::ControlSetJoyStickThrottle(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);

	Scalar joystick_throttle_center = g_ControlList->JoyStickThrottleCenter();
	Scalar joystick_throttle_dead_low = g_ControlList->JoyStickThrottleLow();

	// If center and low are close enough, then currently throttle goes one way only,
	// toggle will change throttle to two way
	if (Close_Enough(joystick_throttle_center, joystick_throttle_dead_low)) {
		NotationFile startup_ini("options.ini", NotationFile::Standard, true);
		Stuff::Page *joypage = startup_ini.FindPage("joystick");
		Verify(joypage);
		Scalar center, low, high;
		joypage->GetEntry("BiThrottleCenter", &center);
		joypage->GetEntry("BiThrottleLow", &low);
		joypage->GetEntry("BiThrottleHigh", &high);
		g_ControlList->JoyStickThrottleCenter(center, VehicleInterface::GetInstance());
		g_ControlList->JoyStickThrottleLow(low, VehicleInterface::GetInstance());
		g_ControlList->JoyStickThrottleHigh(high, VehicleInterface::GetInstance());
	}

	// Otherwise throttle is currently two way, toggle will change it to one way
	else {
		NotationFile startup_ini("options.ini", NotationFile::Standard, true);
		Stuff::Page *joypage = startup_ini.FindPage("joystick");
		Verify(joypage);
		Scalar center, high;
		joypage->GetEntry("OneThrottleCenter", &center);
		joypage->GetEntry("OneThrottleHigh", &high);
		
		g_ControlList->JoyStickThrottleCenter(center, VehicleInterface::GetInstance());
		g_ControlList->JoyStickThrottleLow(center, VehicleInterface::GetInstance());
		g_ControlList->JoyStickThrottleHigh(high, VehicleInterface::GetInstance());
	}
	return 1;
}

int
MW4Shell::ControlGetJoyStickThrottle(void* data[], int count)
{
	gosASSERT(Adept::g_ControlList != NULL);

	Scalar joystick_throttle_center = g_ControlList->JoyStickThrottleCenter();
	Scalar joystick_throttle_dead_low = g_ControlList->JoyStickThrottleLow();

	// Throttle is one way
	if (Close_Enough(joystick_throttle_center, joystick_throttle_dead_low)) {
		INTPARM(1) = 1;
	}

	// Throttle is two way
	else {
		INTPARM(1) = 0;
	}

	return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MW4Shell::AddBots(int number, int* botIds, int* mechIds)
{
    gosASSERT(!CTCL_IsConsole());
	if (number > MW4Shell::Instance->networkScenarioCount && number < 0)
	{
		return 0;
	}
	
	// load that maps options...
	Stuff::MString full_name;
	full_name = "Resource\\Missions\\";
	full_name += MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].missionName;
	full_name += ".nfo";
	
	NotationFile notefile(full_name);
	
	Page *page = notefile.FindPage("scenarios");

	int botNum = 0;
	if (page != NULL)
	{
		NotationFile scenario_file;
		MString scenario_name;
		page->GetEntry(MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].scenarioTag,&scenario_file);

		Page *serverPage = scenario_file.FindPage("server");
		ChainOf<Note*> *list = serverPage->MakeNoteChain("bot_");
		Check_Object(list);
		Page::NoteIterator notes(list);
		Note *botNote = notes.ReadAndNext();
		while (botNote)
		{
			NotationFile bot_file;
			botNote->GetEntry(&bot_file);
			Page *botPage = bot_file.FindPage("botdata");
			if (botPage)
				botNum = botNum + AddBots(botPage, botIds+botNum, mechIds+botNum);
			botNote = notes.ReadAndNext();
		}
		delete list;
	}
	else
	{

		full_name = "Resource\\UserMissions\\";
		full_name += MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].missionName;
		full_name += ".nfo";
		
		NotationFile notefile(full_name);
		
		Page *page = notefile.FindPage("scenarios");

		if (page != NULL)
		{
			NotationFile scenario_file;
			MString scenario_name;
			page->GetEntry(MW4Shell::Instance->scenarios[MW4Shell::Instance->selectedScenario].scenarioTag,&scenario_file);

			Page *serverPage = scenario_file.FindPage("server");
			ChainOf<Note*> *list = serverPage->MakeNoteChain("bot_");
			Check_Object(list);
			Page::NoteIterator notes(list);
			Note *botNote = notes.ReadAndNext();
			while (botNote)
			{
				NotationFile bot_file;
				botNote->GetEntry(&bot_file);
				Page *botPage = bot_file.FindPage("botdata");
				if (botPage)
					botNum = botNum + AddBots(botPage, botIds+botNum, mechIds+botNum);
				botNote = notes.ReadAndNext();
			}
			delete list;
		}


	}
	return botNum;	
}

// If you update the names here, please update Content\Shellscripts\callsign.h as well!
#define NUM_CALLSIGNS 64
char* BotNames[NUM_CALLSIGNS] = {
	"Firestorm",	"Scarab",		"Pocus",		"Hacksaw",
	"Gnaw",			"Darklord",		"Spice",		"Rocker",
	"Leepus",		"Coolhand",		"Piotr",		"Propwash",
	"Mecca",		"Rusty",		"Faith",		"Thomcat",
	"kilo romeo",	"Tryptic",		"Isis",			"Suredude",
	"PAINGOD",		"Lucky",		"Gothmog",		"Synth boy",
	"Arioch",		"Dark Priest",	"Splotch",		"Paladin",
	"Macleod",		"Super",		"BooYah",		"Von",
	"azero",		"Wraith",		"Undead",		"mantis",
	"Wicced",		"TINY",			"Crusher",		"Darkman",
	"ULMEERA",		"Morfane",		"Darkheart",	"Joker",
	"Mouse",		"Greywolf",		"Pyrotech",		"Elengil",
	"Undomiel",		"Marz",			"Kuroshii",		"Crow",
	"Conn Man",		"Lysosome",		"Dax",			"HamHouke",
	"Intrepid",		"Toad",			"oObeaner",		"Apophis",
	"Thor",			"Sauron",		"Pharaoh",		"Dicion"
};
int BotLevels[NUM_CALLSIGNS] = {
	9,9,9,8,
	6,9,9,2,
	5,6,7,8,
	5,2,7,4,
	3,2,4,7,
	1,0,3,9,
	4,0,5,6,
	7,9,9,6,
	0,1,8,6,
	3,1,9,9,
	9,9,1,9,
	5,9,8,8,
	5,6,5,8,
	9,5,4,4,
	4,4,4,4,
	4,8,9,8
};

// If you update the names here, please update Content\Shellscripts\callsign.h as well!

int 
MW4Shell::AddBots(Stuff::Page* botPage, int* botIds, int* mechIds)
{
    gosASSERT(!CTCL_IsConsole());
	int number;
	if (!botPage->GetEntry("botcount", &number))
		return 0;
	
	int maxLevel = 9;
	int minLevel = 0; 
	int maxTonnage = 100; 
	int minTonnage = 25;
	int maxTotalTonnage = 1600;
	int teamId = -1;

	botPage->GetEntry("maximumlevel", &maxLevel);
	botPage->GetEntry("minimumlevel", &minLevel);
	Clamp(maxLevel, 0, 9);
	Clamp(minLevel, 0, maxLevel);

	botPage->GetEntry("team", &teamId);
	teamId--;
	botPage->GetEntry("maximumTonnage", &maxTonnage);
	botPage->GetEntry("minimumTonnage", &minTonnage);
	Clamp(maxTonnage, 25, 100);
	Clamp(minTonnage, 25, maxTonnage);
	
	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	NetMissionParameters::MWNetMissionParameters *netParams = app->GetLocalNetParams();

	if (netParams->m_teamAllowed && teamId>=0 && teamId<netParams->m_teamCount) {
		int teamMinTonnage = netParams->m_teamParams[teamId].m_minimumTonnage;
		int teamMaxTonnage = netParams->m_teamParams[teamId].m_maximumTonnage;
		
		if (teamMinTonnage > minTonnage)
			minTonnage = teamMinTonnage;
		if (teamMaxTonnage < maxTonnage)
			maxTonnage = teamMaxTonnage;

		maxTotalTonnage = netParams->m_teamParams[teamId].m_maximumTotalTonnage;
	}

	if (minTonnage > maxTonnage)
		return 0;

	for (int i=0; i<number; i++)
	{
		// Deal with team tonnage limits
		if (netParams->m_teamAllowed && teamId>=0 && teamId<netParams->m_teamCount) {

			Stuff::Scalar currentTotalTonnage = netParams->m_teamParams[teamId].m_currentTotalTonnage;

			// No more mech can be added within the total tonnage limit
			if (maxTotalTonnage - currentTotalTonnage < Max(minTonnage, 30.0) )
				break;
		}

		int numPasses = 0;
		while (numPasses<20) 
		{
			if (AddOneBot(&botIds[i], &mechIds[i], teamId, minTonnage, maxTonnage, minLevel, maxLevel)>=0)
			{
				if (app->lancemateConnectionData[botIds[i]].lancemateVehicleAccepted)
					break;
				
				app->lancemateConnectionData[botIds[i]].Disconnect();
				ServerAdvertiser::RemovePlayerAll(botIds[i]+256, NULL, true);				
			}
			numPasses++;
		} 
	}
	return i;
}

int 
MW4Shell::FillBotsForAllTeams(int* botIds, int* mechIds)
{		
	if (!MWApplication::GetInstance()->serverFlag)
		return 0;

	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	NetMissionParameters::MWNetMissionParameters *netParams = app->GetLocalNetParams();

	int numPasses = 0;
	int botNumber = 0;
	bool ret = false;
	while (!ret) {
		// Check to see if we have a full game
		for (int i = 0; i < MWApplication::Maximum_Lancemates; i++)
		{
			if (app->lancemateConnectionData[i].lancemateConnected && 
				!app->lancemateConnectionData[i].lancemateVehicleAccepted)
			{
				app->lancemateConnectionData[i].Disconnect();
				ServerAdvertiser::RemovePlayerAll(i+256, NULL, true);				
			}
		}
		app->UpdateAllTeamTotalTonnages();
		numPasses ++;
		if (numPasses>=20)
			break;

		int player_count = 0;
		for (i = 0; i < MWApplication::Maximum_Lancemates; i++)
		{
			if (app->lancemateConnectionData[i].lancemateConnected)
				player_count++;
		}
		player_count += Network::GetInstance()->GetPlayerCount();
		int bots_to_add = 0;
		if (netParams->m_runDedicated)
		{
			// Somehow dedicated server has a player_count of 1 even though there is no player in it
			bots_to_add = netParams->m_maxBots - (player_count-1);
		}
		else
		{
			bots_to_add = netParams->m_maxBots - player_count;
		}
		if (bots_to_add<=0)
			break;
		
		for (i=0; i<bots_to_add; i++)
		{
			int teamId = -1;
			int minTonnage = 25;
			int maxTonnage = 100;
			if (netParams->m_teamAllowed) {
				teamId = FindTeamWithLeastTonnage();
				// All teams are full
				if (teamId < 0) {
					ret = true;
					break;
				}
				minTonnage = netParams->m_teamParams[teamId].m_minimumTonnage;
				maxTonnage = netParams->m_teamParams[teamId].m_maximumTonnage;
			}
			else {

				minTonnage = netParams->m_minimumTonnage;
				maxTonnage = netParams->m_maximumTonnage;
			}

			AddOneBot(&botIds[botNumber], &mechIds[botNumber], teamId, minTonnage, maxTonnage, 0, 9);
			botNumber++;

			// We've tried enough
			if (botNumber >= 256) {
				ret = true;
				break;
			}
		}
	}

	// update everybody's status
	app->SendLobbyStatus();
	
	// send a tally on team members to everyone
	char* message = app->GetTeamCount();
	if (message)
	{
		app->SendChat(
			Connection::Local->GetID(),
			MWApplication::SystemBroadcast,
			0,
			message);
		delete [] message;
	}
	return botNumber;
}

int 
MW4Shell::AddOneBot(int* botId, int* mechId, int teamId, int minTon, int maxTon, int minLev, int maxLev)
{
    gosASSERT(!CTCL_IsConsole());
	if (!MWApplication::GetInstance()->serverFlag)
		return -1;
	
	if (minTon > maxTon)
		return -1;

	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	NetMissionParameters::MWNetMissionParameters *netParams = app->GetLocalNetParams();
	
	// Ramdonly pick a mech
	int mechIndex = rand()%MW4Shell::Instance->m_mechCount;
	while (mechIndex==0 || 
		MW4Shell::Instance->m_mechIDs[mechIndex] == ResourceID::Null)
		mechIndex = rand()%MW4Shell::Instance->m_mechCount;

	int maxTotalTonnage = 1600;
	Stuff::Scalar currentTotalTonnage = 0.0f;
	if (netParams->m_teamAllowed && teamId>=0 && teamId<netParams->m_teamCount) {
		
		int maxTotalTonnage = netParams->m_teamParams[teamId].m_maximumTotalTonnage;
		Stuff::Scalar currentTotalTonnage = netParams->m_teamParams[teamId].m_currentTotalTonnage;
		
		// No more mech can be added within the total tonnage limit
		if (maxTotalTonnage - currentTotalTonnage < Max(minTon, 30.0) )
			return -1;
						
	}
	
	MWTable::TableIterator *mech_iterator;
	Check_Object(MWApplication::GetInstance()->m_mechTable);			
	mech_iterator = MWApplication::GetInstance()->m_mechTable->MakeTableIterator();
	MWTableEntry *mech_entry;

	int stockMechIndex = 0;
	while((mech_entry = mech_iterator->ReadAndNext()) != NULL)
	{
		Check_Object(mech_entry);			
		if (MW4Shell::Instance->m_mechIDs[mechIndex] == mech_entry->GetEntryResourceID())
			break;
		stockMechIndex++;
	}
	
	int numPasses = 0;
	while (mechIndex==0 || 
		MW4Shell::Instance->m_mechIDs[mechIndex] == ResourceID::Null ||
		stockMechIndex > LastMechID ||
		g_aMechSpecs[stockMechIndex].m_fTonnage > Min(maxTotalTonnage-currentTotalTonnage, maxTon) ||
		g_aMechSpecs[stockMechIndex].m_fTonnage < minTon) {
		mechIndex = rand()%MW4Shell::Instance->m_mechCount;
		stockMechIndex = 0;
		mech_iterator->First();
		while((mech_entry = mech_iterator->ReadAndNext()) != NULL)
		{
			Check_Object(mech_entry);			
			if (MW4Shell::Instance->m_mechIDs[mechIndex] == mech_entry->GetEntryResourceID())
				break;
			stockMechIndex++;
		}	
		numPasses++;

		// try not to loop forever
		if (numPasses>20) {
			delete mech_iterator;
			return -1;
		}
	}

	delete mech_iterator;

	DWORD langResources = gos_OpenResourceDLL("ScriptStrings.dll");
	char* clan = (char*)gos_Malloc(256);
	int level;
	if (maxLev == minLev) 
		level = maxLev;
	else
		level = rand()%(maxLev-minLev+1) + minLev;
	sprintf(clan, "%s%d", gos_GetResourceString(langResources, IDS_MP_LOBBY_BOT_LEVEL), level);
	
	char* name = BotNames[rand()%NUM_CALLSIGNS];
	char* mechName = "";
	
	void* params[3];
	params[0] = (void*)&level;
	params[1] = (void*)&name;
	params[2] = (void*)&clan;
	
	int botNumber = MW4Shell::AddBot(NULL, 3, params);				
	params[0] = (void**)&botNumber;
	
	if (botNumber != -1)
	{
		params[1] = (void**)&mechIndex;
		params[2] = (void**)&mechName;
		
		MW4Shell::SetMechBot(NULL, 3, params);
		
		if (netParams->m_teamAllowed && teamId>=0 && teamId<netParams->m_teamCount) 
		{		
			params[1] = (void**)&teamId;
			SetTeamBot(NULL, 2, (void**)params);
		}
	}
	
	*botId = botNumber;
	*mechId = mechIndex;

	gos_CloseResourceDLL(langResources);
	FREE_PTR(clan);

	return botNumber;
}

int 
MW4Shell::FindTeamWithLeastTonnage()
{
	if (!MWApplication::GetInstance()->serverFlag)
		return 0;
	
	MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	NetMissionParameters::MWNetMissionParameters *netParams = app->GetLocalNetParams();

	if (!netParams->m_teamAllowed)
		return -1;

	int teamId = -1;
	Stuff::Scalar tonnagePercent = 1.0f;

	for (int i=0; i<netParams->m_teamCount; i++) {
		
		int amount_on_requested_team = 0;
		for (int j = 0; j < Maximum_Players; ++j)
		{
			if (app->servedConnectionData[j].clientConnected && app->servedConnectionData[j].pilotTeam == i)
			{
				++amount_on_requested_team;
			}
		}
		
		for (j = 0; j < Maximum_Lancemates; ++j)
		{
			if (app->lancemateConnectionData[j].lancemateConnected && app->lancemateConnectionData[j].pilotTeam == i)
			{
				++amount_on_requested_team;
			}
		}
		
		if ((amount_on_requested_team + 1) <= netParams->m_teamParams[i].m_maxPlayersOnTeam)
		{
			
			int minTonnage = netParams->m_teamParams[i].m_minimumTonnage;
			int maxTotalTonnage = netParams->m_teamParams[i].m_maximumTotalTonnage;
			Stuff::Scalar currentTotalTonnage = netParams->m_teamParams[i].m_currentTotalTonnage;
			
			if (currentTotalTonnage/maxTotalTonnage < tonnagePercent &&
				maxTotalTonnage - currentTotalTonnage >= Max(minTonnage, 30.0)){
				
				tonnagePercent = currentTotalTonnage/maxTotalTonnage;
				teamId = i;
			}
		}
	}

	return teamId;
}

int 
MW4Shell::GetScenarioCount(void *instance, int, void *data[])
{
	int ruleType = INTPARM(0);

	int networkScenarioCount = 0;
	
	Stuff::MString missions_path = "Resource\\Missions\\*.nfo";
	Stuff::Directory *resource_directory;
	resource_directory = new Stuff::Directory(missions_path, true);
	Check_Object(resource_directory);
	const char *file_name;		
	

	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{
		
		Stuff::MString full_name;
		full_name = "Resource\\Missions\\";
		full_name += file_name;
		
		
		NotationFile notefile(full_name);
		
		
		Page *info_page = notefile.FindPage("info");
		
		if (info_page != NULL)
		{
			const char *long_mission_name;
			if (info_page->GetEntry("longname",&long_mission_name))
			{
				
				Page *page = notefile.FindPage("scenarios");
				if (page != NULL)
				{
					ChainIteratorOf<Note*> *note_iterator = page->MakeNoteIterator();
					
					Note *note;
					while ((note = note_iterator->ReadAndNext()) != NULL)
					{
						
						NotationFile scenario_file;
						note->GetEntry(&scenario_file);
						
						
						Page *server_page = scenario_file.FindPage("server");
						if (server_page)
						{
							int rule_set;
							const char *scenario_read_name = NULL;
							
							if (server_page->GetEntry("ruleset",&rule_set) && server_page->GetEntry("name",&scenario_read_name))
							{
								if (rule_set == ruleType)
								{
									++networkScenarioCount;
								}
							}
						}
					}
					delete note_iterator;
				}
			}
		}
		
		resource_directory->AdvanceCurrentFile();
	}
	delete resource_directory;
	

	missions_path = "Resource\\UserMissions\\*.nfo";
	resource_directory = new Stuff::Directory(missions_path, true);
	Check_Object(resource_directory);
	
	
	while((file_name = resource_directory->GetCurrentFileName()) != NULL)
	{
		
		Stuff::MString full_name;
		full_name = "Resource\\UserMissions\\";
		full_name += file_name;
		
		
		NotationFile notefile(full_name);
		
		
		Page *info_page = notefile.FindPage("info");
		
		if (info_page != NULL)
		{
			const char *long_mission_name;
			if (info_page->GetEntry("longname",&long_mission_name))
			{
				
				Page *page = notefile.FindPage("scenarios");
				if (page != NULL)
				{
					ChainIteratorOf<Note*> *note_iterator = page->MakeNoteIterator();
					
					Note *note;
					while ((note = note_iterator->ReadAndNext()) != NULL)
					{
						
						NotationFile scenario_file;
						note->GetEntry(&scenario_file);
						
						
						Page *server_page = scenario_file.FindPage("server");
						if (server_page)
						{
							int rule_set;
							const char *scenario_read_name = NULL;
							
							if (server_page->GetEntry("ruleset",&rule_set) && server_page->GetEntry("name",&scenario_read_name))
							{
								if (rule_set == ruleType)
								{
									++networkScenarioCount;
								}
							}
						}
					}
					delete note_iterator;
				}
			}
		}
		
		resource_directory->AdvanceCurrentFile();
	}
	delete resource_directory;
	return networkScenarioCount;
}
// jcem begin
char* MW4Shell::GetShellString(int index)
{
	Verify(m_dwShellResources);

	return gos_GetResourceString(m_dwShellResources, index);
}

int __stdcall CTCL_IsValidName(void* instance, int args, void* data[])
{
    const char* pcsz = STRPARM(0);
    char c;
    BOOL bAllSpace = TRUE;

    while((c = *pcsz++) != '\0') {
        switch(c) {
		case '\"':
		case  '*':
		case  '?':
		case  '/':
		case  ':':
		case  '<':
		case  '>':
		case  '|':
		case  '&':
		case '\\':
        case ',':
            return 0;
        case  ' ':
            break;
        default:
            if (c < 0x20)
                return 0;
            bAllSpace = FALSE;
            break;
        }
    }

    return !bAllSpace;
}

int __stdcall CTCL_GetTeamParams(void* instance, int args, void* data[])
{
    int* team_count = INTARRAYPARAM(0); // [8]

    MWApplication* app = MWApplication::GetInstance();
    NetMissionParameters::MWNetMissionParameters* params = app->GetLocalNetParams();
    if (params->m_teamAllowed) {
        int i, nTeamCount = params->m_teamCount;
        for(i = 0; i < nTeamCount; i++) {
            team_count[i] = params->m_teamParams[i].m_maxPlayersOnTeam;
        }
        return nTeamCount;
    }

    return 0;
}

int __stdcall CTCL_SetCDSP(void* instance, int args, void* data[])
{
    ASSERT(CTCL_IsConsole());
	CTCL_DefaultHostSetup(1);
    return 0;
}

void CTCL_API CTCL_InitMechDatas()
{
    //CTCL_ClearMechDatas();
    if (!g_ppMech) {
        MW4Shell::Instance->InitMPScreen();

        int k, nMechCount = MW4Shell::Instance->m_mechCount;
        g_ppMech = (char**)malloc(sizeof(char*) * nMechCount);
        g_pStockIds = (int*)malloc(sizeof(int) * nMechCount);
        for(k = 0; k < nMechCount; k++) {
            g_ppMech[k] = NULL;
            g_pStockIds[k] = 0;
        }
	    void* data0[3] = {
            0,
		    (void*)g_ppMech,
		    g_pStockIds,
	    };
        MW4Shell::Instance->GetMechs(data0, 3);
    }
}

void CTCL_API CTCL_ClearMechDatas()
{
    if (g_ppMech) {
        free(g_ppMech);
        g_ppMech = NULL;
    }
    if (g_pStockIds) {
        free(g_pStockIds);
        g_pStockIds = NULL;
    }
}

void CTCL_API CTCL_CheckNetConnectedToServer()
{
    if (MW4Shell::NetConnectedToServer(NULL, 0, NULL)) {
        //MWApplication* app = MWApplication::GetInstance();

		//$$COOP
        CTCL_InitMechDatas();
        if (g_bIsServer) {
            MW4Shell::Instance->InitNetworkScenarios(NULL, 0, (void**)NULL);

		    g_nMech4Comm = 3;
        } else {
            if (g_bCOOP)
                g_nMech4Comm = 0;
            else
            g_nMech4Comm = 4;
        }
    } else {
        if (25.0f <= (gos_GetElapsedTime() - g_fLastGameStart)) {
            g_nMech4Comm = 0;
          if (!g_bCOOP) {
            if (g_bIsServer)
                CTCL_DoSendGameReturn(_EGR_ErrCreateSession);
            else
                CTCL_DoSendGameReturn(_EGR_ErrJoinSession);
          }
            Application::GetInstance()->QueStopGame();
        }
    }
}

void _stdcall CTCL_SetMissionParamsBy(void* pNMP, int nSize)
{
    gosASSERT(MW4Shell::NetConnectedToServer(NULL, 0, NULL));

        MWApplication* app = MWApplication::GetInstance();

        NetMissionParameters::MWNetMissionParameters* lparams = app->GetLocalNetParams();

        NetMissionParameters::MWNetMissionParameters params;

        MemoryStream stream(pNMP, nSize, 0);
        params.LoadParameters(&stream);

        int param, value;
        void *data_int[2] = {
            &param,
            &value,
        };

        //if (lparams->m_ruleType != params.m_ruleType) {
            param = RULE_TYPE_PARAMETER;
            value = params.m_ruleType;
            MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);

            MW4Shell::Instance->InitNetworkScenarios(NULL, 0, NULL);
            //return;
        //}

        //if (!app->haveNetworkMap || (MW4Shell::Instance->selectedScenario != params.m_mapID) || (lparams->m_mapID != params.m_mapID)) {
            param = MAP_ID_PARAMETER;
            value = params.m_mapID;
            MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);

	        MW4Shell::Instance->selectedScenario = -1;
	        MW4Shell::SelectNetworkScenarioDirect(value);
            //return;
        //}

        //if (lparams->m_weather != params.m_weather) {
            param = WEATHER_PARAMETER;
            value = params.m_weather;
            MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);
            //return;
        //}

        //if (lparams->m_visibility != params.m_visibility) {
            param = VISIBILITY_PARAMETER;
            value = params.m_visibility;
            MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);
            //return;
        //}

        //if (lparams->m_isNight != params.m_isNight) {
            param = NIGHT_TIME_PARAMETER;
            value = params.m_isNight;
            MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);
            //return;
        //}
        app->m_isNight = params.m_isNight ? true: false;

        //if (lparams->m_gameLength != params.m_gameLength) {
            param = GAME_LENGTH_PARAMETER;
            value = params.m_gameLength;
            MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);
            //return;
        //}
        lparams->m_killLimit = params.m_killLimit;
        lparams->m_killLimitNumber = params.m_killLimitNumber;
        lparams->m_respawnLimit = params.m_respawnLimit;
        lparams->m_respawnLimitNumber = params.m_respawnLimitNumber;
        //params->m_isNight = params.m_isNight;
        lparams->m_onlyStockMech = params.m_onlyStockMech;
        lparams->m_playMissionReview = 0; // params.m_playMissionReview;
        lparams->m_unlimitedAmmo = params.m_unlimitedAmmo;
        lparams->m_heatOn = params.m_heatOn;
        lparams->m_friendlyFirePercentage = params.m_friendlyFirePercentage; // or 0
        lparams->m_splashOn = params.m_splashOn;
        lparams->m_weaponjamOn = params.m_weaponjamOn;
        lparams->m_ammobayfireOn = params.m_ammobayfireOn;
// MSL 5.05 Advance Mode
        lparams->m_advancemodeOn = params.m_advancemodeOn;
// MSL 5.06 Armor Mode
        lparams->m_armormodeOn = params.m_armormodeOn;
/*
KILL_LIMIT_NUMBER_PARAMETER;
RESPAWN_LIMIT_NUMBER_PARAMETER;
ONLY_STOCK_MECH_PARAMETER;
PLAY_MISSION_REVIEW_PARAMETER;
MAXIMUM_TONNAGE_PARAMETER;
KILL_LIMIT_PARAMETER;
RESPAWN_LIMIT_PARAMETER;
*/
        //if (lparams->m_radarMode != params.m_radarMode) {
            param = RADAR_MODE_PARAMETER;
            value = params.m_radarMode;
            MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);
            //return;
        //}

        MW4Shell* shl = MW4Shell::Instance;
#if 0
        param = params.m_ruleType; // param = RULE_TYPE_PARAMETER, value = params.m_ruleType;
        shl->GetGameTypeString(NULL, 1, data_int);
#else
        strcpy(MW4Shell::s_gameTypeStr, shl->GetRuleName(params.m_ruleType));
        MW4Shell::m_gameTypeStr = MW4Shell::s_gameTypeStr;
#endif
}

void CTCL_API CTCL_SetMissionParams()
{
    if (MW4Shell::NetConnectedToServer(NULL, 0, NULL)) {
        MWApplication* app = MWApplication::GetInstance();

		if (g_bCOOP) {
			int param, value;
			void *data_int[2] = {
				&param,
				&value,
			};

			//if (lparams->m_ruleType != params.m_ruleType) {
				param = RULE_TYPE_PARAMETER;
				value = StockAttrition;
				MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);

				MW4Shell::Instance->InitNetworkScenarios(NULL, 0, NULL);
				//return;
			//}

			//if (!app->haveNetworkMap || (MW4Shell::Instance->selectedScenario != params.m_mapID) || (lparams->m_mapID != params.m_mapID)) {
				param = MAP_ID_PARAMETER;
				value = 0;
				for(int i = 0; i < MW4Shell::Instance->networkScenarioCount; i++)
				{
					if (strcmp(MW4Shell::Instance->scenarios[i].longMissionName, "ScarabStronghold") == 0) {
						value = i;
						break;
					}
				}
				MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);

				MW4Shell::Instance->selectedScenario = -1;
				MW4Shell::SelectNetworkScenarioDirect(value);
				//return;
			//}
			/*//if (lparams->m_weather != params.m_weather) {
				param = WEATHER_PARAMETER;
				value = 1; // 1-on,0-off
				MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);
				//return;
			//}*/

			/*//if (lparams->m_visibility != params.m_visibility) {
				param = VISIBILITY_PARAMETER;
				value = 0;
				MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);
				//return;
			//}*/

			//if (lparams->m_isNight != params.m_isNight) {
				param = NIGHT_TIME_PARAMETER;
				value = 0; // 0-day, 1-night
				MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);
				//return;
			//}
			app->m_isNight = value ? true: false;

			//if (lparams->m_gameLength != params.m_gameLength) {
				param = GAME_LENGTH_PARAMETER;
				extern int g_nTimeList_Value;
#ifdef _DEBUG
				value = g_nTimeList_Value; // 0; // in minute
#else // !_DEBUG
				value = g_nTimeList_Value; // in minute
#endif // _DEBUG
				MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);
				//return;
			//}
			NetMissionParameters::MWNetMissionParameters* lparams = app->GetLocalNetParams();

			lparams->m_killLimit = 0; // no kill limit - target value
			lparams->m_killLimitNumber = 0;
			lparams->m_respawnLimit = 0; // apply a respawn limit?
			lparams->m_respawnLimitNumber = 0; // number of lives
			//params->m_isNight = params.m_isNight;
			lparams->m_onlyStockMech = FALSE;
			lparams->m_playMissionReview = 0; // params.m_playMissionReview;
			lparams->m_unlimitedAmmo = 1;
			lparams->m_heatOn = 0;
			lparams->m_friendlyFirePercentage = 0; // 100 or 0
			lparams->m_splashOn = 0;
			lparams->m_weaponjamOn = 0;
			lparams->m_ammobayfireOn = 0;
// MSL 5.05 Advance Mode
			lparams->m_advancemodeOn = 0;
// MSL 5.06 Armor Mode
			lparams->m_armormodeOn = 0;
/*
KILL_LIMIT_NUMBER_PARAMETER;
RESPAWN_LIMIT_NUMBER_PARAMETER;
ONLY_STOCK_MECH_PARAMETER;
PLAY_MISSION_REVIEW_PARAMETER;
MAXIMUM_TONNAGE_PARAMETER;
KILL_LIMIT_PARAMETER;
RESPAWN_LIMIT_PARAMETER;
*/
			//if (lparams->m_radarMode != params.m_radarMode) {
				param = RADAR_MODE_PARAMETER;
				value = 3; // unlimited;
				MW4Shell::SetNetworkMissionParamater(NULL, 2, data_int);
				//return;
			//}
			lparams->m_joinInProgress = 0;

			app->parametersDirty = true;
		} else {
			int nSize;
			void* pNMP = CTCL_LoadNMP(nSize);
			ASSERT(pNMP);

			CTCL_SetMissionParamsBy(pNMP, nSize);

			app->parametersDirty = true;

			//$$COOP
			CTCL_DoSendGameReturn(_EGR_OkCreateSession);
		}
        g_nMech4Comm = 5;
    }
}

void CTCL_API CTCL_CheckMissionParams()
{
    if (MW4Shell::NetConnectedToServer(NULL, 0, NULL)) {
        MWApplication* app = MWApplication::GetInstance();

		//$$COOP
        if (app->haveNetworkMap) {
            NetMissionParameters::MWNetMissionParameters* sparams = app->GetServerNetParams();

            int nSize;
            void* pNMP = CTCL_LoadNMP(nSize);
            ASSERT(pNMP);

            NetMissionParameters::MWNetMissionParameters params;
            MemoryStream stream(pNMP, nSize, 0);
            params.LoadParameters(&stream);

            int param, value;
            void *data_int[2] = {
                &param,
                &value,
            };

            BOOL bDiff = FALSE;
            bDiff = sparams->m_ruleType != params.m_ruleType ? TRUE: bDiff;
            bDiff = sparams->m_mapID != params.m_mapID ? TRUE: bDiff;
            bDiff = sparams->m_visibility != params.m_visibility ? TRUE: bDiff;
            bDiff = sparams->m_weather != params.m_weather ? TRUE: bDiff;
            bDiff = sparams->m_isNight != params.m_isNight ? TRUE: bDiff;
            bDiff = sparams->m_gameLength != params.m_gameLength ? TRUE: bDiff;
            bDiff = sparams->m_radarMode != params.m_radarMode ? TRUE: bDiff;
            bDiff = sparams->m_onlyStockMech != params.m_onlyStockMech ? TRUE: bDiff;
            //bDiff = sparams->m_playMissionReview = 0;
            bDiff = sparams->m_killLimit != params.m_killLimit ? TRUE: bDiff;
            bDiff = sparams->m_killLimitNumber != params.m_killLimitNumber ? TRUE: bDiff;
            bDiff = sparams->m_respawnLimit != params.m_respawnLimit ? TRUE: bDiff;
            bDiff = sparams->m_respawnLimitNumber != params.m_respawnLimitNumber ? TRUE: bDiff;
            bDiff = sparams->m_unlimitedAmmo != params.m_unlimitedAmmo ? TRUE: bDiff;
            bDiff = sparams->m_heatOn != params.m_heatOn ? TRUE: bDiff;
            bDiff = sparams->m_friendlyFirePercentage != params.m_friendlyFirePercentage ? TRUE: bDiff; // or 0
            bDiff = sparams->m_splashOn != params.m_splashOn ? TRUE: bDiff;
            bDiff = sparams->m_weaponjamOn != params.m_weaponjamOn ? TRUE: bDiff;
            bDiff = sparams->m_ammobayfireOn != params.m_ammobayfireOn ? TRUE: bDiff;
// MSL 5.05 Advance Mode
            bDiff = sparams->m_advancemodeOn != params.m_advancemodeOn ? TRUE: bDiff;
// MSL 5.06 Armor Mode
            bDiff = sparams->m_armormodeOn != params.m_armormodeOn ? TRUE: bDiff;
            if (!bDiff) {
                MW4Shell* shl = MW4Shell::Instance;
#if 0
                param = params.m_ruleType; // param = RULE_TYPE_PARAMETER, value = params.m_ruleType;
                shl->GetGameTypeString(NULL, 1, data_int);
#else
                strcpy(MW4Shell::s_gameTypeStr, shl->GetRuleName(params.m_ruleType));
                MW4Shell::m_gameTypeStr = MW4Shell::s_gameTypeStr;
#endif
                param = SCENARIO_NAME_PARAMETER;
                shl->GetNetworkMissionParamater(sparams, 1, data_int);

                g_nMech4Comm = 5;
            }
        } else {
            /*static Time s_elapsed_time = 0.0;
		    Time elapsed_time = gos_GetElapsedTime() - s_elapsed_time;
		    if (elapsed_time > 2.0f)
		    {
			    // this only sends to lobby players..
			    s_elapsed_time = gos_GetElapsedTime();
                Network::GetInstance()->SendNetMessage(Connection::Server->GetID(), MWApplication::RequestMissionParameterMessageID, NULL, true);
            }*/
        }
	} else {
	}
}

void CTCL_CheckMech(SPlayerInfo& PI)
{
    MW4Shell* shl = MW4Shell::Instance;

    if (!((0 <= PI.m_nMechIndex) && (PI.m_nMechIndex < shl->m_mechCount))) {
		char* pszMech = &PI.m_szMech[0];
		if (!*pszMech) {
			strcpy(pszMech, "$err");
		}
		int nLen = strlen(pszMech);
		int kk;
		for(kk = 0; kk < shl->m_mechCount; kk++)
		{
			const char* pcszMech2 = g_ppMech[kk];
			if (*pszMech == '$') {
				int nLen2 = strlen(pcszMech2);
				int nPos = nLen2 - nLen;
				if ((0 < nPos) && (strcmpi(pszMech, &pcszMech2[nPos]) == 0)) {
					break;
				}
			} else {
				if (strcmpi(pszMech, pcszMech2) == 0) {
					break;
				}
			}
		}
		PI.m_nMechIndex = (kk < shl->m_mechCount) ? kk: shl->m_mechCount - 1;
	}
        const Adept::ResourceID& ResID = shl->m_mechIDs[PI.m_nMechIndex];
			PI.m_fileID = ResID.GetFileID();
			PI.m_recordID = ResID.GetRecordID();
			strcpy(&PI.m_szMech[0], g_ppMech[PI.m_nMechIndex]);
}

void CTCL_API CTCL_SetMechs()
{
    if (MW4Shell::NetConnectedToServer(NULL, 0, NULL)) {
        MWApplication* app = MWApplication::GetInstance();
        MW4Shell* shl = MW4Shell::Instance;

		//$$COOP
        if (g_bIsServer) {
            if (app->parametersDirty)
                return;
        }
        NetMissionParameters::MWNetMissionParameters* params = g_bIsServer ? app->GetLocalNetParams(): app->GetServerNetParams();

        BOOL bTeam;
        bTeam = !!params->m_teamAllowed;

        int nRet;

	    int k, nMechIndex;
	    char* pszMechName;

        CTCL_CheckMech(g_aPlayerInfos[0]);
        pszMechName = &g_aPlayerInfos[0].m_szMech[0];
        nMechIndex = g_aPlayerInfos[0].m_nMechIndex;
	    void* data_mech[3] = {
            0,
		    &nMechIndex,
		    &pszMechName,
	    };
	    shl->SetMech(data_mech, 3);
        if (bTeam)
		{
            app->SendTeamRequest(g_aPlayerInfos[0].m_nTeamOrSkin);
        }
		else
		{
            int nSkin = g_aPlayerInfos[0].m_nTeamOrSkin;
	        void* data_skin[1] = {&nSkin,};
            shl->SelectSkin(NULL, 1, data_skin);
        }
        app->SendVehicleRequest();

        if (g_bIsServer) {
            for(int i = 1; i < g_nPlayerInfos; i++) {
                SPlayerInfo& PI = g_aPlayerInfos[i];
                if (!PI.m_bBot)
                    continue;
			    char* pszName = &PI.m_szName[0];
                int nBotLevel = PI.m_nLevelOrTesla + 1;
                void* data_clan[3] = {
                    &nBotLevel,
                    &pszName,
                    &pszName, //clan
                };
			    
			    nRet = MW4Shell::AddBot(NULL/*instance*/, 3/*numParams*/, data_clan);
                if (nRet != -1) {
			        int bot_number = nRet;
                    CTCL_CheckMech(PI);
                    pszMechName = &PI.m_szMech[0];
                    nMechIndex = PI.m_nMechIndex;
                    void* data_mech_bot[3] = {
                        &bot_number,
                        &nMechIndex,
                        &pszMechName,
                    };
			        nRet = MW4Shell::SetMechBot(NULL, 3, data_mech_bot);

                    if (bTeam) {
                        app->RequestLancemateTeam(bot_number, PI.m_nTeamOrSkin);
                    } else {
                    }
                } else {
                    //...
                }
            }
        } else {
        }
        g_nMech4Comm = 7;
    } else {
    }
}

void CTCL_API CTCL_CheckClientReady()
{
	//$$COOP
    MWApplication* app = MWApplication::GetInstance();
    if ((Connection::Server != NULL) && (Connection::Local != NULL)) {
        if (app->localVehicelAccepted == VEHICLE_ACCEPTED) {
            if (app->haveNetworkMap) {
                if (g_bIsServer) {
                    g_nMech4Comm = 8;
                } else {
                    app->SetClientReady();
                    CTCL_DoSendGameReturn(_EGR_OkJoinSession);
                    g_nMech4Comm = 0;
                }
            }
        } else {
        }
    }
}

void CTCL_API CTCL_CheckServerReady()
{
	//$$COOP
    MWApplication* app = MWApplication::GetInstance();
    int i, nOK, nCount = Network::GetInstance()->GetPlayerCount();

    BOOL bOK = FALSE;
    if (nCount == (g_nTeslas + 1)) { // when all clients are connected...
	    for(nOK = 0, i = 0; i < Maximum_Players; ++i) {
            if (i != Connection::Server->GetID()) {
                const MechWarrior4::ServedConnectionData& scd = app->servedConnectionData[i];
                if (scd.clientReady && scd.clientVehicleAccepted) {
                    nOK++;
                }
            }
        }
        if (g_nTeslas == nOK) {
	        for(nOK = 0, i = 0; i < Maximum_Lancemates; i++) {
                const MechWarrior4::LancemateConnectionData& lcd = app->lancemateConnectionData[i];
		        if (lcd.lancemateConnected && lcd.lancemateVehicleAccepted) {
                    nOK++;
                }
            }
            if (nOK == g_nBOTs) {
                bOK = TRUE;
            }
        }
        if (!bOK) {
            app->VerifyAllPlayerVehicles();
        }
    }

    if (bOK) {
        CTCL_StartGame(FALSE);
    }
}

void CTCL_API CTCL_DefaultHostSetup(int nMode)
{
    // nMode - 0 // CTCL_DoCreateGame()
    // nMode - 1 // CTCL_SetCDSP from ConLonbby.script
    // nMode - 2 // LoadServerOptions()
    // nMode - 3 // LoadOverideParameters()
    // nMode - 4 // CTCL_DoMission(0, ...)
    if (CTCL_IsNone())
        return;
    MWApplication* app = MWApplication::GetInstance();
    NetMissionParameters::MWNetMissionParameters* params = app->GetLocalNetParams();

    // hostgame1.script
    extern int AdvertiseThisGame;
    AdvertiseThisGame = 0;

    params->m_reportStats = 0;
    params->m_joinInProgress = 1;
    params->m_joinInProgressCutOff = 0;
    params->m_joinInProgressCutOffTime = 1000;
    params->m_runDedicated = 0;
    params->m_serverRecycle = 0;
    params->m_recycleDelay = 30;
    params->m_useMapCycle = 0;
    params->m_allowdecaltransfer = 0;
    if (g_bCOOP) {
      Environment.NetworkMaxPlayers = 16;
      //if (CTCL_GetTeslaCount() < CTCL_GetTeslaCountAll()) {
          // any cameraship installed... so 1 more player can join
          //params->m_maxPlayers = 9;
          //params->m_maxBots = 8;
      //} else {
          params->m_maxPlayers = 9;
          params->m_maxBots = 8;
      //}
    } else {
    params->m_maxPlayers = 16;
    Environment.NetworkMaxPlayers = 16;
    params->m_maxBots = 16;
    }
    params->m_allow3rdPerson = 1;
    if ((nMode != 0) && (nMode != 4)) {
        params->m_isNight = false;
        params->m_minimumTonnage = 25;
        params->m_maximumTonnage = 100;
        if (g_bCOOP) {
            params->m_gameLength = g_nTimeList_Value;
        } else {
            // g_nTimeList_{Index}|{Value} will be used in ConLobbyMission.script
        params->m_gameLength = 7;
        }
        params->m_visibility = 1; // clear
        params->m_weather = false; // off
        params->m_radarMode = 3; // unlimited

        params->m_unlimitedAmmo = 1;
        params->m_heatOn = 0;
        params->m_friendlyFirePercentage = 0; // 100;
        params->m_splashOn = 0;
        params->m_weaponjamOn = 0;
        params->m_ammobayfireOn = 0;
// MSL 5.05 Advance Mode
        params->m_advancemodeOn = 0;
// MSL 5.06 Armor Mode
        params->m_armormodeOn = 0;
        params->m_respawnLimit = 0;
    }
    params->m_respawnLimitNumber = 0;
    params->m_forceRespawn = 1;
    params->m_allowDeadToChat = 0;
    params->m_deadMechCantSee = 0;
    params->m_deadMechCantSeeOtherTeam = 1;
    params->m_killLimit = 0;
    params->m_killLimitNumber = 1;
    params->m_onlyStockMech = 0;

    NetMissionParameters::TeamParameters* pTP = &params->m_teamParams[0];
    for(int i = 0; i < 8; i++) {
        pTP->m_skin = g_caCamoPrefixes[g_naTeamSkins[i]];
        pTP++;
    }

    if (CTCL_IsConsoleX() && (nMode == 0))
        strcpy(params->m_serverIP, (char*)gos_NetInformation(gos_MyIPAddress));
}

int __stdcall CTCL_DoMission(void* instance, int args, void* data[])
{
    int nDo = VALUEPARM(0);

    if (nDo == 1) { // load
        MW4Shell* shl = MW4Shell::Instance;

        if (!shl->m_mechIDs)
            return 999;

        MWApplication* app = MWApplication::GetInstance();
        NetMissionParameters::MWNetMissionParameters* params = app->GetLocalNetParams();

        BOOL bTeamGame = params->m_teamAllowed ? TRUE: FALSE;
        int i, k, nCameraship, n1stTesla;
		int nNormalTeslas = 0;
        g_nServer = -1;
        nCameraship = -1;
        n1stTesla = -1;
        g_nTeslas = 0;
        int nErr = 0;
        for(i = 0; !nErr && (i < g_nPlayerInfos); i++) {
            SPlayerInfo& PI = g_aPlayerInfos[i];
            BOOL bCameraShip = FALSE;
            PI.m_bTeam = bTeamGame;
            if (PI.m_nLevelOrTesla < 0) {
                // bot - level
                PI.m_bBot = TRUE;
                PI.m_nLevelOrTesla++;
                PI.m_nLevelOrTesla = -PI.m_nLevelOrTesla;
                if (!((0 <= PI.m_nLevelOrTesla) && (PI.m_nLevelOrTesla < 9))) {
                    nErr = 1;
                    continue;
                }
            } else {
                // tesla player - index
                PI.m_bBot = FALSE;
                if (!((0 <= PI.m_nLevelOrTesla) && (PI.m_nLevelOrTesla < CTCL_GetTeslaCountAll()))) {
                    nErr = 2;
                    continue;
                }
                if (PI.m_nLevelOrTesla < CTCL_GetTeslaCount()) {
                    if (!((1 <= PI.m_nMechIndex) && (PI.m_nMechIndex <= shl->m_mechCount))) {
                        nErr = 4;
                        continue;
                    }
                } else {
                    if (PI.m_nMechIndex != 0) {
                        nErr = 5;
                        continue;
                    }
                    if (nCameraship == -1) {
                        nCameraship = i;
                    }
                    if (bTeamGame)
                        PI.m_nTeamOrSkin = 8;
                    else
                        PI.m_nTeamOrSkin = 0;

                    bCameraShip = TRUE;
                }
                if (!bCameraShip) {
                    if (n1stTesla == -1) {
                        n1stTesla = i;
                    }
					nNormalTeslas++;
                }
                g_nTeslas++;
            }
            if ((PI.m_bBot || bCameraShip)/* && !PI.m_szName[0]*/) {
                int n, nOld = -1;
                const char* pcszBotName = NULL;
                while(!pcszBotName) {
                    while((n = rand() % NUM_CALLSIGNS) == nOld)
                        ;
                    nOld = n;
                    pcszBotName = BotNames[n];
                    for(k = 0; k < g_nPlayerInfos; k++) {
                        if (k != i) {
                            const SPlayerInfo& PI2 = g_aPlayerInfos[k];
                        if (strcmp(PI2.m_szName, pcszBotName) == 0) {
                            break;
                        }
                    }
                    }
                    if (k == g_nPlayerInfos) {
                        strcpy(PI.m_szName, pcszBotName);
                    } else {
                        pcszBotName = NULL;
                    }
                }
            } else {
                if (!PI.m_szName[0]) {
                    nErr = 3;
                    continue;
                }
            }
            if (bCameraShip) {
	            PI.m_fileID = g_CameraResID.GetFileID();
	            PI.m_recordID = g_CameraResID.GetRecordID();
            } else {
                const Adept::ResourceID& ResID = shl->m_mechIDs[PI.m_nMechIndex];
	            PI.m_fileID = ResID.GetFileID();
	            PI.m_recordID = ResID.GetRecordID();
            }
            if (bTeamGame)
			{
// MSL 5.03 decal
//                if ((0 <= PI.m_nTeamOrSkin) && (PI.m_nTeamOrSkin <= 8))
                if ((0 <= PI.m_nDecal) && (PI.m_nDecal <= 16))
                    PI.m_nDecal = g_naFFADecals[PI.m_nDecal];
                else
                    PI.m_nDecal = 0;
            }
			else
			{
// MSL 5.05 decal
                if ((0 <= PI.m_nDecal) && (PI.m_nDecal < 37))
                    PI.m_nDecal = g_naFFADecals[PI.m_nDecal];
                else
                    PI.m_nDecal = 0;
            }
        }
        if (!nErr) {
            gosASSERT(g_nServer == -1);
            if (g_nTeslas > 0) {
                if (nCameraship != -1) {
                    g_nServer = nCameraship;
                } else {
                    gosASSERT(n1stTesla != -1);
                    g_nServer = n1stTesla;
                }
                g_nTeslas--;
            } else {
                nErr = 6;
            }
        }
        if (!nErr) {
            for(k = 0; !nErr && (k < g_nPlayerInfos); k++) {
                SPlayerInfo& PI = g_aPlayerInfos[k];
                for(int k2 = 0; !nErr && (k2 < g_nPlayerInfos); k2++) {
                    if (k != k2) {
                        SPlayerInfo& PI2 = g_aPlayerInfos[k2];
                        if (strcmp(PI.m_szName, PI2.m_szName) == 0) {
                            nErr = 7;
                        }
                    }
                }
            }
        }
        g_guidGameDatas = gos_GenerateUniqueGUID();
        if (!nErr) {
			//$$COOP

            extern SYSTEMTIME g_SysTime;
            GetLocalTime(&g_SysTime); // GetSystemTime

            CTCL_DefaultHostSetup(4);

            DynamicMemoryStream stream;
            params->SaveParameters(&stream);
	        stream.WriteByteAlign();
	        stream.Rewind();

            CTCL_SaveNMP(stream.GetPointer(), stream.GetBufferBytesUsed());

            if (CTCL_SaveLog(0, params)) {
				g_nMech4Comm = 1;
			} else {
				nErr = 9;
				g_nMech4Comm = 0;
			}
        }
        return nErr;
    } else if (nDo == 2) { // launch
		//$$COOP
        g_nMech4Comm = 10;
        CTCL_SaveLog(1);
    } else { // 0 - prepare
        gosASSERT(nDo == 0);
        g_nPlayerInfos = 0;
        int i;
        int* pTeamCamos = INTARRAYPARAM(1);
        int* pTeamDecals = INTARRAYPARAM(2);
// MSL 5.03 decal
//        for(i = 0; i < 8; i++) {
        for(i = 0; i < 16; i++) {
            g_naTeamSkins[i] = *pTeamCamos++;
            g_naTeamDecals[i] = *pTeamDecals++;
        }
        int* pFFADecals = INTARRAYPARAM(3);
        for(i = 0; i < 37; i++) {
            g_naFFADecals[i] = *pFFADecals++;
        }
        g_nPrintOut = INTPARM(4);
        g_nMissionReview = INTPARM(5);
    }

    return 0;
}

int __stdcall CTCL_AddPlayer(void* instance, int args, void* data[])
{
    SPlayerInfo& PI = g_aPlayerInfos[g_nPlayerInfos++];

    PI.m_nLevelOrTesla = INTPARM(0); // level or tesla index

    const char* pcszName = STRPARM(1);
    if (pcszName) {
        char c;
        while((c = *pcszName) == ' ')
            pcszName++;
        strcpy(PI.m_szName, pcszName); // player name

        char* pszName2 = PI.m_szName;
        pszName2 += strlen(pszName2);
        while(PI.m_szName < pszName2) {
            if (pszName2[-1] == ' ')
                *--pszName2 = '\0';
            else
                break;
        }
    } else {
        PI.m_szName[0] = '\0';
    }

    int mech_index = INTPARM(2); // mech index
    PI.m_nMechIndex = ++mech_index;
    if (mech_index == 0) {
        strcpy(PI.m_szMech, g_szCameraShip); // mech name
    } else {
        strcpy(PI.m_szMech, STRPARM(3));
    }
    PI.m_nTeamOrSkin = INTPARM(4); // team or skin

// MSL 5.05 decal
    PI.m_nDecal = INTPARM(5); // decal
    return 0;
}

int __stdcall CTCL_GetMissionState(void* instance, int args, void* data[])
{
    int nLaunchState = INTPARM(0);
    switch(nLaunchState) {
    case 3:
        if (g_nMech4Comm == 9) {
            return +1;
        } else {
            if (g_nMech4Comm == 0) {
                CTCL_SaveLog(-1);
                return -1;
            }
        }
        break;
    case 5:
        if (g_nMech4Comm == 0) {
            return +1; // all ok...
        } else {
        }
        break;
    }

    // processing...
    return 0;
}

int __stdcall CTCL_DoBreak(void* instance, int args, void* data[])
{
#ifdef _DEBUG
    static int s_nBreak0 = 0;
    static int s_nBreak1 = 1;
    static int s_nBreak2 = 2;
    if (s_nBreak0 == VALUEPARM(0)) {
        s_nBreak0++;
        s_nBreak0--;
    }
    if (s_nBreak1 == VALUEPARM(0)) {
        s_nBreak1++;
        s_nBreak1--;
    }
    if (s_nBreak2 == VALUEPARM(0)) {
        s_nBreak2++;
        s_nBreak2--;
    }
    switch(VALUEPARM(0))
    {
    case 0:
        break;
    case 1:
        break;
    case 2:
        break;
    case 3:
        break;
    case 4:
        break;
    case 5:
        break;
    }
#endif // _DEBUG
    return 0;
}

int __stdcall CTCL_IsGameLoaded(void* instance, int args, void* data[])
{
    if (g_nMR != 2) {
        MWApplication* app = MWApplication::GetInstance();
        if (app && Connection::Local) {
            int nID = Connection::Local->GetID();
            if (app->servedConnectionData[nID].clientConnected && app->servedConnectionData[nID].clientLoaded)
                return 1;
        }
    }

    return 0;
}

void _stdcall CTCL_SaveLogFileInfo(SYSTEMTIME& SysTime, const GUID& guid, char szPath[MAX_PATH], char szGUID[64])
{
	AdjustSysTimeForLog(SysTime);

    sprintf(szPath, "c:\\mw4files\\%02d_%02d_%d%s", SysTime.wMonth, SysTime.wDay, SysTime.wYear, g_bOldLOG ? ".log": ".rpt");

    sprintf(szGUID, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
        guid.Data1, guid.Data2, guid.Data3,
        guid.Data4[0], guid.Data4[1],
        guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
}

void _stdcall CTCL_SaveLogGameEnd(const SYSTEMTIME& SysTime, const GUID& guid, const char* pcszHost)
{
    char szPath[MAX_PATH];
    char szGUID[64];

	SYSTEMTIME SysTime2(SysTime);
    CTCL_SaveLogFileInfo(SysTime2, guid, szPath, szGUID);

	if (g_bOldLOG) {
		WritePrivateProfileString(szGUID, "@Host", pcszHost, szPath);
		WritePrivateProfileString(szGUID, "@Launched", NULL, szPath);
	} else {
		SLogReport* pRPT = SLogReport::OpenLogReport(szPath, SysTime2);
		if (pRPT) {
			SLogItem* pItem = pRPT->GetLogItem(guid);
			if (pItem) {
				strcpy(pItem->m_szHost, pcszHost);
				pItem->m_nLaunched = 0;
				pRPT->Fix();
				pRPT->WriteFile(szPath, SysTime2);
			} else {
			}
			SLogReport::FreeLogReport(pRPT);
		} else {
		}
	}
}

BOOL _stdcall CTCL_SaveLog(int nState, const NetMissionParameters::MWNetMissionParameters* params/* = NULL*/)
{
    extern SYSTEMTIME g_SysTime;
    int i;
    char szPath[MAX_PATH];
    char szGUID[64];

	SYSTEMTIME SysTime2(g_SysTime);
    CTCL_SaveLogFileInfo(SysTime2, g_guidGameDatas, szPath, szGUID);

    char szBuf[256], szInt[24];
    char* psz;

	SLogReport* pRPT;
	if (g_bOldLOG) {
		pRPT = NULL;
	} else {
		pRPT = SLogReport::OpenLogReport(szPath, SysTime2);
	}
	SLogItem* pItem = NULL;

    if (nState == 0) {
        gosASSERT(params);

		if (g_bOldLOG) {
			sprintf(szInt, "%02d:%02d", g_SysTime.wHour, g_SysTime.wMinute);
			WritePrivateProfileString(szGUID, "Time", szInt, szPath);
		}

        int nBOTs = 0;
        int nCameraships = 0;
        int nPlayers = 0;

		if (g_bOldLOG) {
			szBuf[0] = '\0';
		}
        psz = &szBuf[0];
        for(i = 0; i < g_nPlayerInfos; i++) {
            const SPlayerInfo& PI = g_aPlayerInfos[i];
            if (PI.m_bBot) {
                nBOTs++;
            } else {
                if ((PI.m_fileID == g_CameraResID.GetFileID()) && (PI.m_recordID == g_CameraResID.GetRecordID())) {
                    nCameraships++;
                } else {
					if (g_bOldLOG) {
						if (nPlayers != 0) {
							strcpy(psz, ",");
							psz = &psz[strlen(psz)];
						}
						strcpy(psz, PI.m_szName);
						psz = &psz[strlen(psz)];
					} else {
						strcpy(psz, PI.m_szName);
						psz = &psz[strlen(psz) + 1];
					}

                    nPlayers++;
                }
            }
        }
		if (!g_bOldLOG) {
			*psz = '\0';
		}

		if (g_bOldLOG) {
			sprintf(szInt, "%d", nPlayers);
			WritePrivateProfileString(szGUID, "Player Count", szInt, szPath);
			WritePrivateProfileString(szGUID, "Players", szBuf, szPath);
			sprintf(szInt, "%d", nBOTs);
			WritePrivateProfileString(szGUID, "BOT Count", szInt, szPath);
		} else if (pRPT) {
			SLogReport* pRPT2;
			pRPT2 = pRPT->AddLogItem(g_guidGameDatas, psz - &szBuf[0], pItem);
			if (pRPT2) {
				pRPT = pRPT2;
				pItem->m_Time = g_SysTime;
				pItem->m_nPlayers = nPlayers;
				pItem->m_nBOTs = nBOTs;
				memcpy(&pItem->m_szPlayers[0], &szBuf[0], pItem->m_uSize + 1/* '\0' */);
				pRPT->Fix();
			}
		}
    } else if (g_bOldLOG) {
		if (nState == 1) {
			int nPlayers = 0;
			for(i = 0; i < g_nPlayerInfos; i++) {
				const SPlayerInfo& PI = g_aPlayerInfos[i];
				if (!PI.m_bBot) {
					if (!((PI.m_fileID == g_CameraResID.GetFileID()) && (PI.m_recordID == g_CameraResID.GetRecordID()))) {
						nPlayers++;
					}
				}
			}
			WritePrivateProfileString(szGUID, "@Launched", "1", szPath);
		} else if (nState == -1) {
			WritePrivateProfileString(szGUID, "@err", "1", szPath);
		}
	} else if (pRPT) {
		SLogItem* pItem = pRPT->GetLogItem(g_guidGameDatas);
		if (pItem) {
			if (nState == 1) {
				pItem->m_nLaunched = 1;
			} else if (nState == -1) {
				pItem->m_nErr = 1;
			}
			pRPT->Fix();
		} else {
			// error?
			SLogReport::FreeLogReport(pRPT);
			pRPT = NULL;
		}
	}

	if (pRPT) {
		pRPT->WriteFile(szPath, SysTime2);
		SLogReport::FreeLogReport(pRPT);
	}

	return TRUE;
}

int __stdcall CTCL_GetJoyInfo(void* instance, int args, void* data[])
{
	int nJoy = INTPARM(0);
    int* pJoyInfos = INTARRAYPARAM(1); // [3 + 5] = joy.x, joy.y, joy.z, joy.b0~joy.b4

	gosJoystick_SetPolling(nJoy,true);
	int nValX;
	float valx = gosJoystick_GetAxis(nJoy,JOY_XAXIS);
	if (valx <= -1.0f)
		nValX = -1000;
	else if (+1.0f <= valx)
		nValX = +1000;
	else
		nValX = (int)(1000 * valx);

	int nValY;
	float valy = gosJoystick_GetAxis(nJoy,JOY_YAXIS);
	if (valy <= -1.0f)
		nValY = -1000;
	else if (+1.0f <= valy)
		nValY = +1000;
	else
		nValY = (int)(1000 * valy);

	int nValZ = 0;
/*
	float valz = gosJoystick_GetAxis(nJoy,JOY_ZAXIS);
	if (valz <= -.1f)
		nValZ = -1000;
	else if (+.1f <= valz)
		nValZ = +1000;
	else
		nValZ = (int)(1000 * valz);
*/
	pJoyInfos[0] = nValX;
	pJoyInfos[1] = nValY;
	pJoyInfos[2] = nValZ;
/*
	char szBuf[100];
	sprintf(szBuf, "l : %d, r: %d\n", nValX, nValY);
	::OutputDebugString(szBuf);
*/
	pJoyInfos += 3;

	gosJoystick_Info ji;
	gosJoystick_GetInfo(0, &ji);
	for(unsigned int i=0; i < 5; i++)
	{
		if ( i < ji.nButtons )
			pJoyInfos[i] = gosJoystick_ButtonStatus(0,i);
		else
			pJoyInfos[i] = 0;
	}

	return 0;
}

int __stdcall CTCL_WhyPaused(void* instance, int args, void* data[])
{
	return g_nWhyPaused;
}

struct SScoreInfo
{
    char m_szName[32];
    int m_nValues[7];
    bool m_bLast;
};

int __cdecl qsort_ScoreInfos(const void *elem1, const void *elem2)
{
    const SScoreInfo& a = *(const SScoreInfo*)elem1;
    const SScoreInfo& b = *(const SScoreInfo*)elem2;

    const int naOrders[] = { 1, 0, 2, 3, 6, 4, -1 }; // score, stage, kill, death, success, time
    const int* p = &naOrders[0];
    int nIndex;

    while((nIndex = *p++) != (-1))
    {
        int nRet = -(a.m_nValues[nIndex] - b.m_nValues[nIndex]);
        if (nRet != 0) {
            if (nIndex == 3) // death?
                return -nRet;
            return nRet;
        }
    }

    return 0;
}

int __stdcall CTCL_CheckCampaign(void* instance, int args, void* data[])
{
#define MAX_SCORES 10

	extern int GetScore4Player(int& nKills, int& nDeaths);
    extern bool GetEnemyInfo(int nWhich, int& nDead, int& nEnemyCount); // ablxstd.cpp

	MWApplication *app;
	app = MWApplication::GetInstance ();
    MWMission* mission;
    if (MWMission::GetInstance())
        mission = Cast_Object(MWMission*, MWMission::GetInstance());
    else
        mission = NULL;

	if (VALUEPARM(0) == 1) {
		int nScore, nKills, nDeaths;

		nScore = GetScore4Player(nKills, nDeaths);

		nScore += app->m_nCamp_Score;
		nKills += app->m_nCamp_Kills;
		nDeaths += app->m_nCamp_Deaths;

        Stuff::Time	t = mission->Timer(6).CurrTime();
        int nTimePlayTotal = (int)t;

        POINT ptDeadAndEnemy;
        if (!mission->GetCOOP(MWMission::COOP_ENEMY_GROUP, &ptDeadAndEnemy))
            ptDeadAndEnemy.x = ptDeadAndEnemy.y = 0;

		INTPARM(1) = nScore;
		INTPARM(2) = nKills;
		INTPARM(3) = nDeaths;
        INTPARM(4) = ptDeadAndEnemy.x;
        INTPARM(5) = ptDeadAndEnemy.y;
        INTPARM(6) = nTimePlayTotal;
        INTPARM(7) = mission->GetCOOP(MWMission::COOP_SUBSTAGE_TIMEGOAL);
        INTPARM(8) = mission->GetCOOP(MWMission::COOP_SUBSTAGE_SCORE_OLD);
        INTPARM(9) = app->m_nCamp_Stage;
        INTPARM(10) = mission->GetCOOP(MWMission::COOP_SUBSTAGE_NUMBER);
    } else if (VALUEPARM(0) == 2) {
		INTPARM(1) = app->m_nCamp_Score;
		INTPARM(2) = app->m_nCamp_Kills;
		INTPARM(3) = app->m_nCamp_Deaths;
        INTPARM(4) = app->m_nCamp_Time;
        INTPARM(5) = app->m_nCamp_Mech;
        INTPARM(6) = app->m_bCamp_Success;
    } else if (VALUEPARM(0) == 3) {
        app->m_nCamp_Stage = VALUEPARM(1); // store invitation result
    } else if (VALUEPARM(0) == 4) {
        Stuff::Scalar fRepair = *SCALARARRAYPARAM(1);
        if (fRepair != 0) {
            VehicleInterface* pvi = VehicleInterface::GetInstance();
            if (pvi) {
                Vehicle* pv = pvi->vehicle;
                if (pv) {
                    Mech* mech = Cast_Object(Mech*, pv);
                    mech->RepairForCOOP();
                    pv->RepairDamage (fRepair);
                }
            }
        }
        app->m_nCamp_Score += INTPARM(2);
    } else if (VALUEPARM(0) == 5) {
        char** ppNames = STRARRAYPARAM(1);
        int* pnCounts = INTARRAYPARAM(2);
        INTPARM(3) = mission->GetCOOP(MWMission::COOP_SUBSTAGE_TIMEGOAL);
        INTPARM(4) = app->m_nCamp_Stage;
        INTPARM(5) = mission->GetCOOP(MWMission::COOP_SUBSTAGE_NUMBER);
        return ABL::GetEnemyTyps(mission->m_naCOOPs[MWMission::COOP_ENEMY_GROUP], ppNames, pnCounts, 0); // don't use - GetCOOP(MWMission::COOP_ENEMY_GROUP)
    } else if (VALUEPARM(0) == 6) {
        // load high score
        int nMaxScores = INTPARM(1); // nLastIndex Contains Maximum score array size
        gosASSERT(1 <= nMaxScores);
        gosASSERT(nMaxScores <= MAX_SCORES);

        NotationFile highscore_ini("highscore.ini", NotationFile::Standard, true);
		Page *page = highscore_ini.SetPage("single");

        struct SScoreInfo
        {
            char m_szName[32];
            int m_nValues[7];
            bool m_bLast;
        } aSIs[MAX_SCORES];

        if (MAX_SCORES < nMaxScores) {
            nMaxScores = MAX_SCORES;
        }
        int nSIs = 0;

        int nRECs;
        for(nRECs = -1; nRECs < nMaxScores; nRECs++)
        {
            char sz[128];
            Note* pNote;
            if (nRECs == -1) {
                pNote = page->SetNote("last"); // MWGame::ReactToEndMission(bool success)
            } else {
                sprintf(sz, "%d", nRECs);
                pNote = page->SetNote(sz);
            }
            const char* pcsz;
            pNote->GetEntry(&pcsz);
            if(!pcsz || !*pcsz)
                continue;
            const char* pcszComma;
            int nComma;
            bool bDone = false;
            for(nComma = 0; !bDone; nComma++)
            {
                pcszComma = strchr(pcsz, ',');
                if (pcszComma) {
                    if (7 <= nComma)
                        break;
                } else {
                    if (nComma < 7)
                        break;
                    pcszComma = &pcsz[strlen(pcsz)];
                }
                int nLen = &pcszComma[1] - pcsz;
                memcpy(sz, pcsz, nLen);
                sz[nLen - 1] = '\0';

                if (nComma == 0) {
                    // sync w/ MAX_STR_TYPE_LEN 16 in gs_multi_id.script
                    if (nRECs == -1) {
                        if (*sz != '\0')
                            break;
                    } else {
                        if (*sz == '\0')
                            break;
                    }
                    if (16 < strlen(sz))
                        break;
                    strcpy(aSIs[nSIs].m_szName, sz);
                } else {
                    aSIs[nSIs].m_nValues[nComma - 1] = atoi(sz);
                }
                if (nComma == 7) {
                    bDone = true;
                    break;
                }
                pcsz = &pcszComma[1];
            }
            if (bDone) {
                aSIs[nSIs].m_bLast = (nRECs == -1);
                nSIs++;
                if (nMaxScores <= nSIs)
                    break;
            }
        }
        qsort(&aSIs[0], nSIs, sizeof(aSIs[0]), qsort_ScoreInfos);
        char** ppNames = STRARRAYPARAM(2);
        int* pnStages = INTARRAYPARAM(3);
        int* pnScores = INTARRAYPARAM(4);
        int* pnKills = INTARRAYPARAM(5);
        int* pnDeaths = INTARRAYPARAM(6);
        int* pnTime = INTARRAYPARAM(7);
        int* pnMech = INTARRAYPARAM(8);
        int* pnSuccess = INTARRAYPARAM(9);
        int nLastIdx = -1;
        for(int i = 0; i < nSIs; i++)
        {
            FREEANDNULL(*ppNames);
            *ppNames = (char*)gos_Malloc(strlen(aSIs[i].m_szName) + 1);
            strcpy(*ppNames, aSIs[i].m_szName);
            ppNames++;

            const int* pv = &aSIs[i].m_nValues[0];
            *pnStages++ = *pv++;
            *pnScores++ = *pv++;
            *pnKills++ = *pv++;
            *pnDeaths++ = *pv++;
            *pnTime++ = *pv++;
            *pnMech++ = *pv++;
            *pnSuccess++ = *pv++;

            if (aSIs[i].m_bLast)
                nLastIdx = i;
        }
        INTPARM(1) = nLastIdx;

        return nSIs;
    } else if (VALUEPARM(0) == 7) {
        // save high score
        NotationFile highscore_ini("highscore.ini", NotationFile::Standard, true);
		Page *page = highscore_ini.SetPage("single");

        int nSIs = INTPARM(1);
        char** ppNames = STRARRAYPARAM(2);
        int* pnStages = INTARRAYPARAM(3);
        int* pnScores = INTARRAYPARAM(4);
        int* pnKills = INTARRAYPARAM(5);
        int* pnDeaths = INTARRAYPARAM(6);
        int* pnTime = INTARRAYPARAM(7);
        int* pnMech = INTARRAYPARAM(8);
        int* pnSuccess = INTARRAYPARAM(9);

        int nRECs;
        for(nRECs = -1; nRECs < MAX_SCORES; nRECs++)
        {
            char sz[128];
            Note* pNote;
            if (nRECs == -1) {
                pNote = page->SetNote("last"); // MWGame::ReactToEndMission(bool success)
            } else {
                sprintf(sz, "%d", nRECs);
                pNote = page->SetNote(sz);
            }
            if ((0 <= nRECs) && (nRECs < nSIs)) {
                sprintf(sz, "%s,%d,%d,%d,%d,%d,%d,%d",
                    *ppNames++,
                    *pnStages++,*pnScores++, *pnKills++, *pnDeaths++,
                    *pnTime++, *pnMech++, *pnSuccess++);
                pNote->SetEntry(sz);
            } else {
                pNote->SetEntry("");
            }
        }

        highscore_ini.Save();
    } else if (VALUEPARM(0) == 8) {
        // Inviter Name...
		char** ppInviter = &STRPARM(1);
        int nLen = strlen(g_szTeslaInviter) + 1;

		FREEANDNULL(*ppInviter);
		*ppInviter = (char *)gos_Malloc(nLen);
		strcpy(*ppInviter, g_szTeslaInviter);
    } else if (VALUEPARM(0) == 9) {
        if (g_bUseCam)
            return 1;
        return 0;
    }

	return app->m_nCamp_Stage;
#undef MAX_SCORES
}

int __stdcall TBL_GetResNames(void* instance, int args, void* data[])
{
    // STRARRAYPARAM(0), nID+   <<== last nID should be (-1)
    //
    // 0 <= nID: predefined type
    //        0: Mech Names
    //        1: ...
    //       99: reserved 1...
    //-1 == nID: end of params
    // nID < -1: resource id...

    char** ppResNamesOrg = STRARRAYPARAM(0);
    gosASSERT(ppResNamesOrg);
    char** ppResNames = ppResNamesOrg;

    int nIdx, nID, nNames;
    char* pszName;
    char* pszName2;

    enum {
        ResNames_MechNames = 0,
        ResNames_TopSpeed,
        ResNames_Tonnages,
        ResNames_Class,
        ResNames_Tech,
        ResNames_InfoString,
        ResNames_BotNames,

        ResNames_MAX,

        ResNames_ReserveCount = 98,
        ResNames_Reserve1 = 99,
    };
    gosASSERT(NoMechID == (LastMechID - FirstMechID + 1));
    
    MW4Shell* shl = MW4Shell::Instance;
    gosASSERT(shl);

    nNames = 0;
    for(nIdx = 1; (nID = VALUEPARM(nIdx)) != -1; nIdx++)
    {
        if (0 <= nID) {
            if (nID < ResNames_MAX) {
                int n, nMax;
                const SMechSpec* pMIs = &g_aMechSpecs[0];
                char** ppNames;
                static char sz[1024];

                switch(nID)
                {
                case ResNames_MechNames:
                case ResNames_TopSpeed:
                case ResNames_Tonnages:
                case ResNames_Class:
                case ResNames_Tech:
                case ResNames_InfoString:
                    nMax = NoMechID;
                    for(n = 0; n < nMax; n++)
                    {
                        switch(nID)
                        {
                        case ResNames_MechNames:
                            pszName = shl->GetShellString(pMIs[n].m_nNameID);
                            break;
                        case ResNames_TopSpeed:
                            sprintf(sz, "%f", pMIs[n].m_fTopSpeed);
                            pszName = &sz[0];
                            break;
                        case ResNames_Tonnages:
                            sprintf(sz, "%f", pMIs[n].m_fTonnage);
                            pszName = &sz[0];
                            break;
                        case ResNames_Class:
                            pszName = shl->GetShellString(pMIs[n].m_nClass);
                            break;
                        case ResNames_Tech:
                            pszName = shl->GetShellString(pMIs[n].m_nTech);
                            break;
                        case ResNames_InfoString:
                            pszName = shl->GetShellString(pMIs[n].m_nNameID);
                            pszName2 = shl->GetShellString(pMIs[n].m_nInfo);
                            break;
                        default:
                            gosASSERT(FALSE);
                            break;
                        }
                        FREEANDNULL(*ppResNames);

                        gosASSERT(pszName);
                        int nBufLen = (int)strlen(pszName);

                        if (nID == ResNames_InfoString) {
                            gosASSERT(pszName2);
                            int nBufLen2 = (int)strlen(pszName2);

                            char* pszDestOrg = (char*)gos_Malloc(nBufLen + 1/* \n */ + nBufLen2 + 1/* '\0' */);
                            char* pszDest = pszDestOrg;

                            memcpy(pszDest, pszName, nBufLen);
                            pszDest = &pszDest[nBufLen];
                            *pszDest++ = '\n';
                            strcpy(pszDest, pszName2);

                            *ppResNames = pszDestOrg;
                        } else {
		                    *ppResNames = (char*)gos_Malloc(nBufLen + 1);

		                    Str_Copy(*ppResNames, (const char *)pszName, nBufLen + 1);
                        }

                        ppResNames++;
                    }
                    break;
                case ResNames_BotNames:
                    nMax = NUM_CALLSIGNS;
                    ppNames = &BotNames[0];
                    for(n = 0; n < nMax; n++)
                    {
                        pszName = ppNames[n];
                        gosASSERT(pszName);

                        FREEANDNULL(*ppResNames);

                        int nBufLen = (int)strlen(pszName);

		                *ppResNames = (char*)gos_Malloc(nBufLen + 1);

		                Str_Copy(*ppResNames, (const char *)pszName, nBufLen + 1);

                        ppResNames++;
                    }
                    break;
                case ResNames_ReserveCount:
                    nIdx++;
                    nID = VALUEPARM(nIdx);
                    gosASSERT(1 <= nID);
                    ppResNames += nID;
                    break;
                case ResNames_Reserve1:
                    ppResNames++;
                    break;
                default:
                    gosASSERT(FALSE);
                    break;
                }
            } else {
                pszName = "";
                goto as_string1;
            }
        } else {
            pszName = shl->GetShellString(-nID);
as_string1:
            gosASSERT(pszName);

            FREEANDNULL(*ppResNames);

            int nBufLen = (int)(strlen(pszName) + 1);

		    *ppResNames = (char*)gos_Malloc(nBufLen);

		    Str_Copy(*ppResNames, (const char *)pszName, nBufLen);

            ppResNames++;
        }
    }

    return ppResNames - ppResNamesOrg;
}

int __stdcall CTCL_GetIncNums(void* instance, int args, void* data[])
{
    int nHop = INTPARM(0);
    int nStart = INTPARM(1);
    int nEnd = INTPARM(2);
    int* pValuesOrg = INTARRAYPARAM(3);
    int* pValues = pValuesOrg;

    int nDiff, nDir;
    if (nStart < nEnd) {
        nDiff = nEnd - nStart;
        nDir = 1;
    } else {
        nDiff = nStart - nEnd;
        nDir = -1;
    }
    nDiff++;
    if (nDiff < nHop) {
        nHop = nDiff;
    }

    if (nHop <= 1) {
        *pValues++ = nStart;
        *pValues++ = nEnd;
    } else {
        int nLast = nStart - nDir;
        for(int n = 0; n < nHop; n++)
        {
            int nNew = nStart + (nDiff * n / nHop) * nDir;
            if (nLast != nNew) {
                *pValues++ = nNew;
                nLast = nNew;
            }
        }
        *pValues++ = nEnd;
    }

    return pValues - pValuesOrg;
}

int __stdcall CTCL_MiscFile(void* instance, int args, void* data[])
{
    int nIdx = VALUEPARM(0);
    gosASSERT((0 <= nIdx) && (nIdx < sizeof(m_aMiscFileTables) / sizeof(m_aMiscFileTables[0])));
    MiscFileTable& tbl = *m_aMiscFileTables[nIdx];

    int nCount = tbl.GetTableSize();
    switch(VALUEPARM(1))
    {
    case 0: // count
        return nCount;
    case 1: // read & next...
    case 2: // read current
        if (0 < nCount) {
            MiscFileEntry& entry = *tbl.GetNthItem(tbl.m_nCurIndex);
            AssignShellString(data, 2, entry.GetFileName());
            if (VALUEPARM(1) == 1) {
                if (++tbl.m_nCurIndex >= nCount) {
                    tbl.m_nCurIndex = 0;
                }
            }
            return +1;
        }
        return 0;
    case 3: // get index...
        return tbl.m_nCurIndex;
    case 4: // set index...
        if ((0 <= INTPARM(2)) && (INTPARM(2) < nCount)) {
            tbl.m_nCurIndex = INTPARM(2);
            return +1;
        }
        return 0;
    }

    return 0;
}

int __stdcall CTCL_GetACP(void* instance, int args, void* data[])
{
    return GetACP();
}

int __stdcall CTCL_IsBotAllowed(void* instance, int args, void* data[])
{
    gosASSERT(args == 1);
    // see MWApplication::BotsAllowed()
	switch(INTPARM(0))
	{
	case StockDestruction:
	case StockTeamDestruction:
	case StockAttrition:
	case StockTeamAttrition:

	case CustomDestruction:
	case CustomTeamDestruction:
	case CustomAttrition:
	case CustomTeamAttrition:
		return 1;
	}

	return 0;
}

int __stdcall CTCL_MechViewOnMainScreen(void* instance, int args, void* data[])
{
    if (g_nMechViewType == 2)
	{
        if (MechLab::Instance && (g_nMR != 2) && (radar_device.m_nMechViewMax <= 0))
            return 1;
    }

    return 0;
}

void _stdcall CTCL_DoStopMusic()
{
    if (g_MusicSound4COOP)
        gosAudio_DestroyResource(&g_MusicSound4COOP);
}

void _stdcall CTCL_DoPlayMusic()
{
	MWApplication *app = MWApplication::GetInstance ();
    
    if (g_bCOOP) {
        MiscFileTable& tbl = *m_aMiscFileTables[2]; // game musics
        int nCount = tbl.GetTableSize();
        if (0 < nCount) {
            if (app->networkingFlag) {
                const BYTE* pb = (const BYTE*)&g_guidGameDatas;
                const BYTE* pbEnd = &pb[sizeof(g_guidGameDatas)];
                BYTE bCRC = 0;
                while(pb < pbEnd)
                {
                    bCRC += *pb;
                    pb++;
                }

                tbl.m_nCurIndex = bCRC % nCount;
            } else {
                if ((2 < nCount) && (Random::GetInt() % 2)) {
                    if (++tbl.m_nCurIndex >= nCount) {
                        tbl.m_nCurIndex = 0;
                    }
                }
            }

            MiscFileEntry& entry = *tbl.GetNthItem(tbl.m_nCurIndex);
            MString strFile(entry.GetFileName());
            if (++tbl.m_nCurIndex >= nCount) {
                tbl.m_nCurIndex = 0;
            }

            CTCL_DoStopMusic();
#if 0
			gosAudio_CreateResource(&g_MusicSound4COOP, gosAudio_StreamedFile, strFile, 0,0,0, true);
            if (g_MusicSound4COOP) {
                gosAudio_AssignResourceToChannel(0, g_MusicSound4COOP);
			    gosAudio_SetChannelPlayMode(0,gosAudio_Loop);
                gosAudio_SetChannelSlider(0, gosAudio_Volume, (float) 40.0f / 100.0f );
            }
#else
            strFile += "{handle}";

		    AudioCommand *command;
		    command = AudioCommand::Create(AudioRenderer::MusicType,strFile,1.0f,1.0f);
		    Check_Object(command);
		    if (command)
		    {
			    command->Play(gosAudio_Loop);
			    if ((AudioRenderer::Instance != 0) &&
				    (AudioRenderer::Instance->m_channelTypes.GetLength() > AudioRenderer::MusicType))
			    {
				    AudioRenderer::Instance->m_channelTypes[AudioRenderer::MusicType].SetVolume(40.0f / 100.0f);
			    }
		    }
#endif
        }
    }
}

void __stdcall CTCL_AfterBeginScene()
{
    extern LPDIRECTDRAWSURFACE7 BackBufferSurface;

    gosASSERT(radar_device.m_ptMechViewDim.x % 4 == 0);
    gosASSERT(radar_device.m_ptMechViewDim.y % 4 == 0);
    gosASSERT(radar_device.m_ptMechViewSize.x % 4 == 0);
    gosASSERT(radar_device.m_ptMechViewSize.y % 4 == 0);

    gosASSERT(radar_device.m_pDDSMechView);

    int nXCount = radar_device.m_ptMechViewDim.x / radar_device.m_ptMechViewSize.x;
    int nYCount = radar_device.m_ptMechViewDim.y / radar_device.m_ptMechViewSize.y;
    int nCount = nXCount * nYCount;

    RECT rcTarget;
    SetRect(&rcTarget, 0, 0, radar_device.m_ptMechViewSize.x * nXCount, radar_device.m_ptMechViewSize.y * nYCount);

    radar_device.m_nMechViewMax = 0;

	DDSURFACEDESC2 desc={0,};
	desc.dwSize=sizeof(desc);
	radar_device.m_pDDSMechView->Lock(&rcTarget,&desc,DDLOCK_WAIT|DDLOCK_NOSYSLOCK|DDLOCK_WRITEONLY,NULL);
    if (desc.lpSurface) {
        for(int qq = 0; qq < nCount; qq++)
        {
            gos_SetupViewport(1,1.0,1,0x00000000,0.0,0.0,1.0,1.0 );

            MechLab::Instance->Execute();
            MechLab::Instance->UpdateDisplay();

            RECT rcSource;
            rcSource.left = (800 - radar_device.m_ptMechViewSize.x) / 2;
            rcSource.top = (600 - radar_device.m_ptMechViewSize.y) / 2;
            rcSource.right = rcSource.left + radar_device.m_ptMechViewSize.x;
            rcSource.bottom = rcSource.top + radar_device.m_ptMechViewSize.y;

	        DDSURFACEDESC2 desc2={0,};
	        desc2.dwSize=sizeof(desc2);
            BackBufferSurface->Lock(&rcSource,&desc2,DDLOCK_WAIT|DDLOCK_NOSYSLOCK|DDLOCK_READONLY,NULL);
            if (desc2.lpSurface) {
                int nX = (radar_device.m_nMechViewMax % nXCount) * radar_device.m_ptMechViewSize.x;
                int nY = (radar_device.m_nMechViewMax / nXCount) * radar_device.m_ptMechViewSize.y;

                const BYTE* pSrc = &((const BYTE*)desc2.lpSurface)[0]; // [rcSource.top * desc2.lPitch + rcSource.left * 2];
                BYTE* pDst = &((BYTE*)desc.lpSurface)[nY * desc.lPitch + nX * 2];
                int nX2 = nX + radar_device.m_ptMechViewSize.x;
                int nY2 = nY + radar_device.m_ptMechViewSize.y;
                while(nY < nY2)
                {
                    memcpy(pDst, pSrc, sizeof(WORD) * radar_device.m_ptMechViewSize.x);
                    pDst = &pDst[desc.lPitch];
                    pSrc = &pSrc[desc2.lPitch];

                    nY++;
                }
                radar_device.m_nMechViewMax++;

                BackBufferSurface->Unlock(&rcSource);
            } else {
                STOP(("BackBufferSurface->Lock(&rcSource..."));
            }
        }
        radar_device.m_pDDSMechView->Unlock(&rcTarget);
    }
	else
	{
        STOP(("radar_device.m_pDDSMechView->Lock(&rcTarget,&desc,DDLOCK_WAIT|DDLOCK_NO..."));
    }

    MW4Shell::Instance->ClearMechLab(-1);

    radar_device.m_nMechViewCurs = -1;
    g_dwLastMechView = 0;
    g_pfnCTCL_AfterBeginScene = CTCL_UpdateMechView;

    radar_device.pD3DDevice->SetTexture(0,radar_device.pDDSTexture);
}

void __stdcall CTCL_UpdateMechView()
{
    extern LPDIRECTDRAWSURFACE7 BackBufferSurface;
    
    if (0 < radar_device.m_nMechViewMax) {
        if ((radar_device.m_nMechViewCurs < 0) || (g_dwLastMechView == 0) || (g_dwLastMechView <= GetTickCount())) {
            radar_device.m_nMechViewCurs++;
            g_dwLastMechView = GetTickCount() + MECHVIEW_TIMETICKS;
        }
        if (radar_device.m_nMechViewMax <= radar_device.m_nMechViewCurs)
            radar_device.m_nMechViewCurs = 0;

        int nXCount = radar_device.m_ptMechViewDim.x / radar_device.m_ptMechViewSize.x;
        int nYCount = radar_device.m_ptMechViewDim.y / radar_device.m_ptMechViewSize.y;
        int nCount = nXCount * nYCount;

        // see render.cpp for fonts....
        // Header Text
        SIZE szH;
        CHSHFont& FontH = radar_device.pFont[2]; // arial 20pixel?
        FontH.GetTextExtent("", &szH);
        int nHeightH = szH.cy + MECHVIEW_GAP_TEXTS;

        // Normal Text
        SIZE szT;
        CHSHFont& FontT = radar_device.pFont[3]; // arial 16pixel?
        FontT.GetTextExtent("", &szT);
        int nHeightT = szT.cy + MECHVIEW_GAP_TEXTS;

        char sz[128];
        char* pszName;
        MW4Shell* shl = MW4Shell::Instance;
        int nX, nY;

        // draw MechView background if exist
		RECT rc={0,0,480,640};
        if (radar_device.pDDSMechViewBkgnd)
		    radar_device.pDDSTarget->BltFast(0,0,radar_device.pDDSMechViewBkgnd,&rc,0);

        // --------- draw mech image - start
		radar_device.pD3DDevice->SetTexture(0,radar_device.m_pDDSMechView);

		float tw = radar_device.tw;
        float th = radar_device.th;

        radar_device.tw = radar_device.m_ptMechViewDim.x;
        radar_device.th = radar_device.m_ptMechViewDim.y;

        nX = (480 - radar_device.m_ptMechViewSize.x) / 2;
        nY = MECHVIEW_GAP_TOP + nHeightH/*mech name*/ + MECHVIEW_GAP_ABOVE_MECH;

        int nTX = (radar_device.m_nMechViewCurs % nXCount) * radar_device.m_ptMechViewSize.x;
        int nTY = (radar_device.m_nMechViewCurs / nXCount) * radar_device.m_ptMechViewSize.y;

        radar_device.DrawTexture((float)nX,(float)nY,0xFFFFFFFF, (float)nTX,(float)nTY,(float)(nTX+radar_device.m_ptMechViewSize.x),(float)(nTY+radar_device.m_ptMechViewSize.y));

        radar_device.th = th;
        radar_device.tw = tw;

        nY += radar_device.m_ptMechViewSize.y; // bottom of mech-image
        // --------- draw mech image - end

        nX = 480 / 2;
       // draw mech name on top/center of mech-image(????)
        pszName = shl->GetShellString(g_aMechSpecs[g_MLCallData.mech_id].m_nNameID);
        sprintf(sz, "%s", pszName);
        FontH.DrawText((float)nX,MECHVIEW_GAP_Y,0xFFFFFF00,sz,TEXTALIGN_HCENTER);

        // draw mech equipment below mech-image(????)
        nY += MECHVIEW_GAP_UNDER_MECH;

        bool bAnyEquipped = false;
        strcpy(sz, "");

		radar_device.pD3DDevice->SetTexture(0,radar_device.pDDSTexture);

        if (g_MLCallData.beagle_installed && g_MLCallData.can_have_beagle) {
//            if (bAnyEquipped)
//                strcat(sz, " / ");
//            strcat(sz, "Beagle");
//            bAnyEquipped = true;
		radar_device.DrawTexture(60,437,0xFFFFFFFF,3,265,74,283);
        }

        if (g_MLCallData.ecm_installed && g_MLCallData.can_have_ecm) {
//            if (bAnyEquipped)
//                strcat(sz, " / ");
//            strcat(sz, "ECM");
//            bAnyEquipped = true;
		radar_device.DrawTexture(132,437,0xFFFFFFFF,3,285,74,303);
        }

        if (g_MLCallData.jumpjets_installed && g_MLCallData.can_have_jump) {
//			if (bAnyEquipped)
//				strcat(sz, " / ");
//			strcat(sz, "Jump Jet");
//			bAnyEquipped = true;
		radar_device.DrawTexture(204,437,0xFFFFFFFF,3,305,74,323);
        }

        if (g_MLCallData.lams_installed && g_MLCallData.can_have_lams) {
//            if (bAnyEquipped)
//                strcat(sz, " / ");
//            strcat(sz, "AMS");
//            bAnyEquipped = true;
		radar_device.DrawTexture(276,437,0xFFFFFFFF,3,325,74,343);
        }

        if (g_MLCallData.light_installed && g_MLCallData.can_have_light) {
//			if (bAnyEquipped)
//				strcat(sz, " / ");
//			strcat(sz, "Light Amp");
//			bAnyEquipped = true;
		radar_device.DrawTexture(348,437,0xFFFFFFFF,3,345,74,363);
        }

        if (g_MLCallData.ams_installed && g_MLCallData.can_have_ams) {
//            if (bAnyEquipped)
//                strcat(sz, " / ");
//            strcat(sz, "AMS");
//            bAnyEquipped = true;
        }


        FontT.DrawText(nX,nY,0xFFFFFF00,sz,TEXTALIGN_HCENTER);

        nY += nHeightH+15;

        int nYSaved = nY;

        // draw left-pane information
        nX = 40 + MECHVIEW_GAP_X;

        pszName = shl->GetShellString(g_aMechSpecs[g_MLCallData.mech_id].m_nTech);
        sprintf(sz, "Tech: %s", pszName);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        pszName = shl->GetShellString(g_aMechSpecs[g_MLCallData.mech_id].m_nClass);
        sprintf(sz, "Class: %s", pszName);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        sprintf(sz, "Accel (m/sec): %3.2f", g_MLCallData.acceleration);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        sprintf(sz, "Decel (m/sec): %3.2f", g_MLCallData.deacceleration);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        sprintf(sz, "Turn Rate (deg/sec): %3.2f", g_MLCallData.turn_rate);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        sprintf(sz, "Torso Range: %3.2f", g_MLCallData.torso_twist*2);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        sprintf(sz, "Twist Speed: %3.2f", g_MLCallData.twist_speed);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        // draw right-pane information
        nY = nYSaved;
        nX = 300 - MECHVIEW_GAP_X;

        sprintf(sz, "Fire power: %d", g_MLCallData.battle_value);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        sprintf(sz, "Armor: %d", g_MLCallData.armor_value);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        sprintf(sz, "Speed: %d", g_MLCallData.speed_value);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        sprintf(sz, "Heat Efficiency: %d", g_MLCallData.heat_eff);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

        sprintf(sz, "Tonnage (tons): %3.2f", g_MLCallData.mech_max_tonnage);
        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
        nY += nHeightT;

//        sprintf(sz, "Current Tonnage: %3.2f", g_MLCallData.mech_tonnage);
//        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
//        nY += nHeightT;

//        sprintf(sz, "Available Tonnage: %3.2f", g_MLCallData.mech_max_tonnage - g_MLCallData.mech_tonnage);
//        FontT.DrawText(nX,nY,0xFF03E829,sz,TEXTALIGN_LEFT);
//        nY += nHeightT;

        //sprintf(sz, "Frame: %d/%d", radar_device.m_nMechViewCurs, radar_device.m_nMechViewMax);
        //radar_device.pFont[0].DrawText(10.0,10.0,0xFFFFFFFF,sz);

        // restore radar background image for safety...
        radar_device.pD3DDevice->SetTexture(0,radar_device.pDDSTexture);

        if (g_pfnCTCL_AfterBeginScene == CTCL_UpdateMechView) {
            extern int g_nTypeOfMFDs; // 0 - no MFDs, 1 - orginal(5+1=dual & single), 2 - B&W(3 + 1=1 dual), 3 - color(3 + 1=2 dual)
		    switch(g_nTypeOfMFDs)
            {
		    case 1:
			    sh_step = 6;
			    break;
		    case 2:
				radar_device.EndScene();
				//radar_device.pDDSFront->Flip(0,DDFLIP_DONOTWAIT|DDFLIP_NOVSYNC );
				mfd_device.BeginScene();
			    sh_step = 4;
                break;
		    case 4:
			    // Same 7-step cadence as mode 1.
			    sh_step = 6;
			    break;
            }
        }
		else
		{
        }
    }
}

// jcem end

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MW4Shell::gosGetWeaponStats(void *instance, int numParams, void* data[])
{
	int *id = INTARRAYPARAM(0);
	Scalar *damage_array = SCALARARRAYPARAM(1);
	Scalar *range_array = SCALARARRAYPARAM(2);
	Scalar *heat_array = SCALARARRAYPARAM(3);
	Scalar *recycle_array = SCALARARRAYPARAM(4);
	Scalar *tonnage_array = SCALARARRAYPARAM(5);
	
	MWTable::TableIterator *iterator = MWApplication::GetInstance()->m_weaponsTable->MakeTableIterator();
	MWTableEntry *weapon_entry;
	
	while((weapon_entry = iterator->ReadAndNext()) != NULL)
	{
		Check_Object(weapon_entry);		
		Resource modelResource;
		Entity::GetGameModelResourceFromDataListID (&modelResource, weapon_entry->GetEntryResourceID());
		Verify (modelResource.DoesResourceExist());

		const Weapon::GameModel *weaponModel = 
			Cast_Pointer(Weapon::GameModel *, modelResource.GetPointer());
		Check_Pointer(weaponModel);

		if ( weaponModel->itemID == *id )
		{
			*damage_array = weaponModel->damageAmount * weaponModel->numFire;
			if(weaponModel->itemID == W_ArtilleryStrike)
				*damage_array = 40.0f;
			*range_array = weaponModel->maxDistance;
			*heat_array = weaponModel->heat * 2.0f;
			*recycle_array = weaponModel->reloadTime;
			*tonnage_array = weaponModel->tonage;
		}
	}

	delete iterator;

	return 1;
}
