//#20190118-01
#define CBN_TOSEA_SCRN 1
#define WM_SEA_SCRN 2
#define WM_ENCOUNTER_SCRN 3
#define WM_STORM_SCRN 4
#define SEA_SAILTO_SCRN 5
#define QUEST_LOAD_SCRN 6
#define DECK_BOAT_SCRN 7
#define SEA_MAP_SCRN 8
#define LAND_MAP_SCRN 9
#define SEA_LOGIN_SCRN 10
#define SEA2SEA_SCRN 11
#define RLD_LOC_SCRN 12
#define NEW_GAME_SCRN 13

#include "_mod_on_off.h"
#include "InternalSettings.h"
#include "events.h"
#include "globals.c"
#include "animals.c"
#include "sea_ai\sea.c"
#include "ships\ships.c"
#include "Encounters\Encounters.c"
#include "worldmap\worldmap.c"
#include "locations\locations.c"
#include "Loc_ai\LAi_init.c"
#include "store\goods.h"
#include "store\initGoods.c"
#include "cannons\cannons.c"
#include "nations\nations.c"
#include "particles.c"
#include "characters\characters.c"
#include "interface\interface.h"
#include "store\storeutilite.c"
#include "dialog.c"
#include "quests\quests.c"
#include "islands\islands.c"
#include "colonies\colonies.c"
#include "reload.c"
#include "battle_interface\loginterface.c"
#include "calendar.c"
#include "teleport.c"
#include "utils.c"
#include "weather\WhrWeather.c"
#include "controls\controls.c"
#include "ITEMS\items.h"
#include "ITEMS\itemLogic.c"
#include "ITEMS\items_utilite.c"
#include "net\net.c"
#include "store\store.h"
#include "interface\interface.c"
#include "OnLoadReinit.c" //Boyer add #20170301-6
#include "extensions\Utilities.c"
#include "BUHO_CIC.c"
//#20201012-01
#include "MythFunc.c"
//#20190418-01
#include "interface\option_sl.c"
#include "Controls\init_pc.c"

extern void ShipsInit(); //Boyer add #20170301-6
extern void ExecuteConsole(); // Luke159
extern void InitBaseCannons();
extern void InitCharacters();
extern void InitBaseInterfaces();
extern void wdmInitWorldMap();
//extern void InitGoods();
extern void InitStores();
extern int InitItems();
extern void InitCharactersTables();
extern void InitCharactersNames();
extern void CreateCharacters();
extern void ActiveF4Control();
extern void ActiveF5Control();
extern void ActiveF7Control();
extern void ActiveF10Control();
extern void ActiveF12Control();
extern void ActiveINSERTControl();

native float Bring2RangeNoCheck(float fMin1, float fMax1, float fMin2, float fMax2, float fValue);
native float Bring2Range(float fMin1, float fMax1, float fMin2, float fMax2, float fValue);
native float Degree2Radian(float fDegree);
native float Clampf(float fValue);
native int RDTSC_B();
native int RDTSC_E(int iRDTSC);
native int SetTexturePath(int iLevel, string sPath);
native int SetGlowParams(float fBlurBrushSize, int Intensivity, int BlurPasses);
native int RPrint(int x, int y, string sPrint);

//Boyer add for new version #20170301-3 //#20170530-02
native bool FileDelete(string sFilePath);
native bool FileExists(string sFilePath);
native bool CreateFolder(string sFolderName);
native bool CheckFolder(string sFolderName);
native bool DeleteFolder(string sFolderName);
native bool FindFolders(string sFindTemplate,aref arFoldersList);
//#20190704-01
native bool MoveFile(string sExistName, string sNewName);
native string LanguageGetDefaultLanguage();
native string GetSaveDirectory();
native string GetResourceDirectory();
native string GetProgramDirectory();
native int GetTexture(string sFilename);
native int FindFiles(ref rObject, string sDirectory, string sMask, bool bRecursive);
//#20171106-01 Add GetFontStringWidth()
native int GetFontStringWidth(string sInput, float scale);

#library "script_library"
#library "render_script_library"

//#20170530-01 Music revolves changes
#event_handler("soundFlag1","seaMusicForNations");
#event_handler(NEW_GAME_EVENT,"NewGame");
#event_handler(GAME_OVER_EVENT,"GameOverE");
#event_handler("Control Activation","ProcessControls");
#event_handler("MainMenuKey","ProcessMainMenuKey");
#event_handler("InterfaceKey","ProcessInterfaceKey");
#event_handler("CameraPosAng","ProcessCameraPosAng");
#event_handler("Cheat","ProcessCheat");
#event_handler("SeaDogs_ClearSaveData", "ClearLocationsSaveData");
#event_handler("StopQuestCheckProcessFreeze","ProcessStopQuestCheckProcessFreeze");
//#20171009-03
#event_handler("ResetDevice", "ResetDevice");
//#20190307-01
#event_handler("ControllerActivation", "ControllerActivation");

float fHighPrecisionDeltaTime;

void ProcessStopQuestCheckProcessFreeze()
{
    bQuestCheckProcessFreeze = false;
    wdmLockReload            = false;
    QuestsCheck();

    if (rand(20) == 10)
    {
    	DoQuestCheckDelay("pchar_back_to_player", 0.5);
    }
}

void ProcessVersionCheck()
{
    ref mc = GetMainCharacter();

    if (CheckAttribute(mc, "HeroParam"))
    {
		/*Level_Complexity         = MOD_SKILL_ENEMY_RATE;
        bHardcoreGameStart       = bHardcoreGame;
        bPayForSaveLoadStart     = bPayForSaveLoad;
        bWorldAlivePauseStart    = bWorldAlivePause;  */

        if (!CheckAttribute(mc, "VersionNumber"))
    	{
            Log_Info(XI_ConvertString("MSG_seadogs_1"));
            Log_Info(XI_ConvertString("MSG_seadogs_2"));
    	}
        else
        {
            if (sti(mc.VersionNumberCompatibility) < VERSION_NUM_PRE && mc.VersionNumber != GetVerNum())
            {
                Log_Info(XI_ConvertString("MSG_seadogs_3") + mc.VersionNumber +".");
                Log_Info(XI_ConvertString("MSG_seadogs_2"));
            }
        }
    }
}

void ProcessCheat()
{
	string sCheatName;
	ref mc;
	sCheatName = GetEventData();
	mc = GetMainCharacter();

	switch(sCheatName)
	{
		case "Immortal":
			if(LAi_IsImmortal(GetMainCharacter()))
			{
				LAi_SetImmortal(GetMainCharacter(), false);
				Log_SetStringToLog("God mode OFF");
			}else{

				LAi_SetImmortal(GetMainCharacter(), true);
				Log_SetStringToLog("God mode ON");
			}
		break;
		case "ShotGun":
			if(globalSGMode != false)
			{
				globalSGMode = false;
				Log_SetStringToLog("Shotgun mode OFF");
			}else{
				globalSGMode = true;
				Log_SetStringToLog("Shotgun mode ON");
			}
		break;
		case "Gold":
			mc.money = sti(mc.money) + 100000;
			Log_SetStringToLog(" + 100000 G");
		break;
		case "Skill":
			mc.skill.freeskill = 1;
			mc.skill.freeskill = sti(mc.skill.freeskill) + 50;
			Log_SetStringToLog(" + 50 SP");
		break;
		case "Reputation":
			mc.reputation = REPUTATION_NEUTRAL;
			Log_SetStringToLog("Reputation Set to NEUTRAL");
		break;
		case "Morale":
            //
		break;
		case "Encounters":
			if(CheckAttribute(mc,"worldmapencountersoff") == 0)
			{
				mc.worldmapencountersoff = "1";
				Log_SetStringToLog("Worldmap encounters OFF");
			}
			else
			{
				if(mc.worldmapencountersoff == "1")
				{
					mc.worldmapencountersoff = "0";
					Log_SetStringToLog("Worldmap encounters ON");
				}
				else
				{
					mc.worldmapencountersoff = "1";
					Log_SetStringToLog("Worldmap encounters OFF");
				}
			}
		break;
		case "MainCharacter":
			mc.model	= "Danielle";
			mc.sex = "woman";
			mc.FaceId = 30;
			mc.model.animation = "woman";
			mc.model.height = 1.75;
		break;
		case "soundoff":
			SendMessage(&Sound,"ll",MSG_SOUND_SET_ENABLED,0);
			Log_SetStringToLog("Sound OFF");
		break;
	}
}

object Camera;

void ProcessCameraPosAng()
{
	Camera.Pos.x = GetEventData();
	Camera.Pos.y = GetEventData();
	Camera.Pos.z = GetEventData();
	Camera.Ang.x = GetEventData();
	Camera.Ang.y = GetEventData();
	Camera.Ang.z = GetEventData();
}

void proc_break_video()
{
	//trace("proc_break_video()");
	if (sti(InterfaceStates.videoIdx) != 99)
	{
		InterfaceStates.videoIdx = 99;
		Event("ievntEndVideo");
	}
}

void Main()
{
    //#20200703-02
    userOptionsInt[UOPTION_INT_BI_HUD_HEIGHT] = 900;
    //#20170530-01 Music revolves, sea uses nation-specific is false/0
    deleteTempVarFiles();

    LayerCreate("realize", 1);
	LayerCreate("sea_realize", 1);
	LayerCreate("net_realize", 1);
	LayerCreate("iRealize", 1);
	LayerCreate("fader_realize", 1);
	LayerCreate("inf_realize", 1);

	ReloadProgressStart();

	ControlsInit(GetTargetPlatform(),true);
	nTeleportLocation = 1;

	NationsInit();
	ReloadProgressUpdate();

	EncountersInit();
	ReloadProgressUpdate();

	CannonsInit();
	ReloadProgressUpdate();

	ShipsInit();
	ReloadProgressUpdate();

	IslandsInit();
	ReloadProgressUpdate();

	WeatherInit();
	ReloadProgressUpdate();

	InitPerks();
	ReloadProgressUpdate();

	//if(LoadSegment("store\initGoods.c"))
	//{
		InitGoods();
	//	UnloadSegment("store\initGoods.c");
	//}
	if(LoadSegment("Interface\BaseInterface.c"))
	{
		InitBaseInterfaces_main();
		InitBaseInterfaces();
		UnloadSegment("Interface\BaseInterface.c");
	}
	ReloadProgressUpdate();
	SetEventHandler("Control Activation","proc_break_video",0);
	InterfaceStates.Launched = false;
	SetEventHandler(EVENT_END_VIDEO,"Main_LogoVideo",0);
	InterfaceStates.videoMitigate = false;
	InterfaceStates.videoIdx = 1;
	//JA: skip intro movies -->
	LoadGameOptions();
	//<-- JA
	if (CheckAttribute(InterfaceStates, "skipintromovies") && InterfaceStates.skipintromovies == 1)
	{
		//i = 99;  //skip videos
		InterfaceStates.videoIdx = 1;
	}
	Event(EVENT_END_VIDEO);
	ReloadProgressEnd();

	SetGlowParams(1.0, 50, 2);
}

void Main_InitGame()
{
    LayerCreate("realize", 1);
	LayerCreate("sea_realize", 1);
	LayerCreate("net_realize", 1);
	LayerCreate("iRealize", 1);
	LayerCreate("fader_realize", 1);
	LayerCreate("inf_realize", 1);

	nTeleportLocation      = 1;
    bDisableLandEncounters = false;
	bDisableCharacterMenu  = false;
	bWorldAlivePause       = true;
	bPauseContrabandMetro  = false;
	bMonstersGen           = false;
	bLandEncountersGen     = true;
	chrDisableReloadToLocation = false;
	bDisableFastReload         = false;
	bDisableMapEnter           = false;
	bDisableSailTo             = false;
	bEnableIslandSailTo        = false;
	bReloadCanBe               = false;
	bMapEnter                  = false;
	bQuestDisableMapEnter      = false;
    bAbordageStarted           = false;
    bCabinStarted              = false;
	bDeckBoatStarted           = false;
	LAi_IsCapturedLocation     = false;
	LAi_IsBoarding             = false;
	LAi_restoreStates          = false;
	LAi_boarding_process       = false;
	boarding_location          = -1;

	NationsInit();
	EncountersInit();
	CannonsInit();
	ShipsInit();
	IslandsInit();
	WeatherInit();
	InitPerks();

	//if(LoadSegment("store\initGoods.c"))
	//{
		InitGoods();
	//	UnloadSegment("store\initGoods.c");
	//}
	if(LoadSegment("Interface\BaseInterface.c"))
	{
		InitBaseInterfaces_main();
		InitBaseInterfaces();
		UnloadSegment("Interface\BaseInterface.c");
	}
}
void Main_LogoVideo()
{
	int i = sti(InterfaceStates.videoIdx);
	//JA --> skip intro movies option code
	/* if (CheckAttribute(InterfaceStates, "skipintromovies") && InterfaceStates.skipintromovies == 1)
	{
		//i = 99;  //skip videos
	} */
	//<--
	switch(i)
	{
        case 1:
            InterfaceStates.videoMitigate = true;
            InterfaceStates.videoIdx = 5;
            //#20170711-01 Change Title video to .ogg for size reduction
            StartPostVideo("Title.ogg",1);
        break;
        default:
            DelEventHandler(EVENT_END_VIDEO,"Main_LogoVideo");
            DeleteClass(&aviVideoObj);
            Event("DoInfoShower","sl","game prepare",true);
            SetEventHandler("frame","Main_Start",1);
        break;
	}
}

void Main_Start()
{
	ReloadProgressStart();

	DelEventHandler("Control Activation","proc_break_video");
	DelEventHandler("frame","Main_Start");

	if( GetTargetPlatform()=="pc" )	ControlsInit(GetTargetPlatform(),false);

	ReloadProgressUpdate();
	InitGame();
	ReloadProgressUpdate();

	Environment.date.hour = worldMap.date.hour;
	Environment.date.min = worldMap.date.min;
	Environment.date.sec = worldMap.date.sec;
	Environment.time = stf(worldMap.date.hour) + stf(worldMap.date.min)/60.0 + stf(worldMap.date.sec)/3600.0;
	Environment.date.year = worldMap.date.year;
	Environment.date.month = worldMap.date.month;
	Environment.date.day = worldMap.date.day;

	InterfaceStates.Buttons.Load.enable = true;
	Event("DoInfoShower","sl","game prepare",false);
    ReloadProgressUpdate();
	StartLanguageSetting(LanguageGetLanguage());
 	LoadPlayerProfileDefault();
 	ReloadProgressUpdate();
	LaunchMainMenu();
	//LaunchNetTopListScreen();
	CharacterIsDead(GetMainCharacter());
	ReloadProgressEnd();
}

void SaveGame()
{
	string saveName = GetEventData();
	string saveData = GetEventData();
	DelEventHandler("evntSave","SaveGame");

	aref arTmp;
	if( !FindClass(arTmp,"fader") )
	{
		//implement interface
		//LaunchQuickSaveMenu();
		pchar.version_number = PCHAR_VERSION_NUM;
		pchar.scriptver = VERSION_NUMBER2;
		pchar.enginever = GetVersionString();
		SaveEngineState(saveName);
		ISetSaveData(saveName,saveData);
	}
	//hide interface
	PostEvent("DoInfoShower",1,"sl","save game",false);
	DeleteEntitiesByType("scrshoter");
	HideQuickSaveMenu();
}

void LoadGame()
{
    DelEventHandler("evntLoad","LoadGame");
    PauseParticles(true); //fix
    //DeleteFortEnvironment();  //fix

	PauseAllSounds(); // fix
    ResetSound();  // fix

    if (bSeaActive && !bAbordageStarted)
    {
		SendMessage(&AIBalls, "l", MSG_MODEL_RELEASE);
	}
	string saveName = GetEventData();
	string retStr="";
	SendMessage(&GameInterface,"lse",MSG_INTERFACE_GET_SAVE_DATA,saveName,&retStr);
	if( retStr=="" ) {return;}
    //#20210723-02
    LayerFreeze("execute",true);
	LayerFreeze("realize",true);

	DeleteEntities();
	ClearEvents();
	ClearPostEvents();
	SetTimeScale(1.0);
	TimeScaleCounter = 0;

	//#20170619-02 Function for loading screens
	string loadScr = getLoadingScreen();

	CreateEntity(&LanguageObject,"obj_strservice");
	CreateEntity(&reload_fader, "fader");
	//#20210723-02
    LayerFreeze("execute",false);
	LayerFreeze("realize",false);
	SendMessage(&reload_fader, "ls",FADER_PICTURE, loadScr);
	SendMessage(&reload_fader, "lfl", FADER_IN, RELOAD_TIME_FADE_IN, true);
	ReloadProgressStart();
	pchar.savegamename = saveName;
	SetEventHandler("frame","LoadGame_continue",1);
}

//Boyer add #20170401-02
void LoadAutoGame()
{
    PauseParticles(true); //fix
	PauseAllSounds(); // fix
    ResetSound();  // fix

    if (bSeaActive && !bAbordageStarted)
    {
		SendMessage(&AIBalls, "l", MSG_MODEL_RELEASE);
	}
	string saveName = GetEventData();
	DelEventHandler("evntLoad","LoadAutoGame");

	string retStr="";
	SendMessage(&GameInterface,"lse",MSG_INTERFACE_GET_SAVE_DATA,saveName,&retStr);
	if( retStr=="" ) {return;}

	DeleteEntities();
	//ClearEvents();
	//ClearPostEvents();
	SetTimeScale(1.0);
	TimeScaleCounter = 0;

	string loadScr="loading\Start_Loading.tga.tx";
	if(CheckAttribute(pchar, "loadscreen"))
        loadScr = pchar.loadscreen;
    else {
        //#20170619-02 Function for loading screens
        loadScr = getLoadingScreen();
    }
	CreateEntity(&LanguageObject,"obj_strservice");
	CreateEntity(&reload_fader, "fader");
	SendMessage(&reload_fader, "ls",FADER_PICTURE, loadScr);
	SendMessage(&reload_fader, "lfl", FADER_IN, RELOAD_TIME_FADE_IN, true);
	ReloadProgressStart();
	pchar.savegamename = saveName;
	SetEventHandler("frame","LoadGame_continue",1);
}

void LoadGame_continue()
{
	DelEventHandler("frame","LoadGame_continue");
	FreezeGroupControls(curKeyGroupName,true);
	LoadEngineState(pchar.savegamename);
}

//Boyer add AutoReload #20170401-02
void AutoReloadGame()
{
    //#20171214-02 Bug fix for sitting down at tavern and autosave collision traps in sitting animation
    if (CheckAttribute(&InterfaceStates, "AutoReloadDisable"))  { return; }
    if (bAbordageStarted) { return; }

	if(LAi_IsBoardingProcess()) { return; }

	if( CharacterIsDead(pchar) ) { return; }

	//{
		int idxLoadLoc = FindLoadedLocation();
	    if (idxLoadLoc != -1 )
	    {
	        if (Locations[idxLoadLoc].id == "Ship_deck" || Locations[idxLoadLoc].id == "Deck_Near_Ship")
	        {
	            { return; }
	        }
	    }
	//}
    //if(CheckAttribute(pchar,"abordage_active_count"))
    //    return;

    //if( InterfaceStates.Launched != 0 ) {return;}
	aref arScrShoter;
	if( !FindClass(&arScrShoter,"scrshoter") ) {
		SetEventHandler("makescrshot","AutoReloadGameCont",0);
		CreateScreenShoter();
		PostEvent("makescrshot",1);
	} //else { return; }
}

void AutoReloadGameCont()
{
    DelEventHandler("makescrshot","AutoReloadGameCont");
    //#20190704-01
    string saveDir = GetSaveDirectory() + PlayerProfile.name + "\";
    string saveName = PlayerProfile.name + " AutoReloadSave";
    string tmpFile = saveName + "_";
    string tmpPath = saveDir + tmpFile;
    string strdata;
    aref arScrShoter;

	SendMessage(&GameInterface,"ls",MSG_INTERFACE_DELETE_SAVE_FILE,tmpPath);
	string sSaveDescriber = GetSaveDataString(GetCurLocationName());

	aref arTmp;
	//if( !FindClass(arTmp,"fader") )
	//{
		pchar.version_number = PCHAR_VERSION_NUM;
		pchar.scriptver = VERSION_NUMBER2;
		pchar.enginever = GetVersionString();
		SaveEngineState(tmpPath);
		ISetSaveData(tmpPath, sSaveDescriber);
		if(!FindClass(&arScrShoter,"scrshoter")) {
            CreateScreenShoter();
		}
        if(FindClass(&arScrShoter,"scrshoter")) {
            SendMessage(arScrShoter, "lsse", MSG_SCRSHOT_READ, saveDir, tmpFile, &strdata);
            if( strdata == "" ) { //Corrupted
                FileDelete(tmpPath);
                return;
            }
            else {
                if(!MoveFile(tmpPath, saveDir + saveName))
                    return;
            }
        }
	//}
	PostEvent("DoInfoShower",1,"sl","save game",false);

    //End Autosave, now reload
    MakeAutoReload();
}
//End Boyer add AutoReload

void InterfaceDoExit()
{
	DelEventHandler("frame","InterfaceDoExit");
	InterfaceStates.Launched=false;
	if(sti(InterfaceStates.doUnFreeze)==true)
	{
		SendMessage(&GameInterface,"l",MSG_INTERFACE_RELEASE);
		if(!IsEntity(&aviVideoObj))
		{
			if( bSeaActive && !bAbordageStarted )
			{
				LayerFreeze("sea_realize",false);
				LayerFreeze("sea_execute",false);
			}
			else
			{
				LayerFreeze("realize",false);
				LayerFreeze("execute",false);
			}
		}
		DeleteAttribute(&GameInterface,"");
	}
	switch(interfaceResultCommand)
	{
		case RC_INTERFACE_FORTCAPTURE_EXIT:
			ReloadAfterFortCapture();
			break;
		case RC_INTERFACE_DO_NOTHING:
			break;
		case RC_INTERFACE_MAIN_MENU_EXIT:
			break;
		case RC_INTERFACE_DO_NEW_GAME:
			InterfaceStates.doUnFreeze = false;
			DeleteEntities();
			//DeleteSeaEnvironment();
			ResetSound();  // fix
			ClearEvents();
			ClearPostEvents();

            if (CheckAttribute(pchar, "HeroParam"))
            {
				//trace("Main_InitGame");
				Main_InitGame();
			}
			else
			{
				if(LoadSegment("Interface\BaseInterface.c"))
				{
					InitBaseInterfaces_main();
					InitBaseInterfaces();
					UnloadSegment("Interface\BaseInterface.c");
				}
			}
			LaunchSelectCharacter();
            break;
		case RC_INTERFACE_DO_LOAD_GAME:
			if(CheckAttribute(&InterfaceStates,"Buttons.Resume.enable") && sti(InterfaceStates.Buttons.Resume.enable) == true)
			{
				LaunchLoadGame(false);
			}
			else
			{
				LaunchLoadGame(true);
			}
			break;
		case RC_INTERFACE_DO_SAVE_GAME:
			LaunchSaveGame();
			break;
		case RC_INTERFACE_DO_OPTIONS:
			LaunchOptionScreen();
			break;
		/*case RC_INTERFACE_DO_CONTROLS:
			LaunchControlsScreen();
			break;
			*/
		case RC_INTERFACE_DO_CREDITS:
		    LaunchAboutScreen();
            break;
		case RC_INTERFACE_DO_RESUME_GAME:
            break;
		//#20170318-67
		case RC_INTERFACE_RANSACK_MAIN_EXIT:
			Return2SeaAfterAbordage();
			break;
		case RC_INTERFACE_CHARACTER_SELECT_EXIT:
			DeleteEntities();
			ClearEvents();
			SetEventHandler("frame","NewGame",1);
			InterfaceStates.doUnFreeze = false;
            break;
		case RC_INTERFACE_SPEAK_EXIT_AND_CAPTURE://Philippe, unlocked
			string sTargetChr = pchar.speakchr;
			pchar.abordage = 1;
			Sea_AbordageStartNow(SHIP_ABORDAGE, GetCharacterIndex(sTargetChr), true, true);
			SetTimeScale(1.0);
			TimeScaleCounter = 0;
			DelPerkFromActiveList("TimeSpeed");
			pchar.speakchr = 0;
			pchar.whospeak = 0;
            break;
		case RC_INTERFACE_SPEAK_EXIT_AND_TRADE://Philippe, unlocked
			LaunchStore(SHIP_STORE);
            break;
		case RC_INTERFACE_TO_CHAR:
			pchar = GetMainCharacter();
			LaunchCharacter(pchar);
            break;
		/*
		case RC_INTERFACE_TO_PASS:
			pchar = GetMainCharacter();
			LaunchPassengers(pchar);
            break;
		*/
		case RC_INTERFACE_TO_SHIP:
			LaunchShipState();
            break;
		/*
		case RC_INTERFACE_TO_TRADEBOOK:
			LaunchTradeBook();
		break;
		*/
		case RC_INTERFACE_TO_LOGBOOK:
			LaunchQuestBook();
            break;
		case RC_INTERFACE_TO_ITEMS:
			LaunchItems(); // to_do
            break;
		case RC_INTERFACE_LAUNCH_GAMEMENU:
			LaunchGameMenuScreen();
			break;
        //#20170318-67
  		case RC_INTERFACE_DO_BOAL_BETA:
		     LaunchBoalBetaScreen();
            break;
	}
}

void EngineLayersOffOn(bool on)
{
	on = !on;
	if( on ) {
		LayerFreeze("realize",on);
		LayerFreeze("execute",on);
		LayerFreeze("sea_realize",on);
		LayerFreeze("sea_execute",on);
	} else {
		if(bSeaActive && !bAbordageStarted) {
			LayerFreeze("sea_realize",on);
			LayerFreeze("sea_execute",on);
		} else {
			LayerFreeze("realize",on);
			LayerFreeze("execute",on);
		}
	}
}

string seadogs_saveFrom = "";

void OnSave()
{
	seadogs_saveFrom = "";

	if(IsEntity(&worldMap))
	{
		seadogs_saveFrom = "world map";
	}
	else
	{
	    int ldLoc = FindLoadedLocation();
	    if(IsEntity(&AISea) && ldLoc < 0)
		{
			Sea_Save();
			seadogs_saveFrom = "sea";
		}
		else
		{
			if(ldLoc >= 0)
			{
				seadogs_saveFrom = "location";
				SendMessage(&Locations[ldLoc], "l", MSG_LOCATION_SETCHRPOSITIONS);
				LAi_SaveInfo();
				PostEvent("SeaDogs_ClearSaveData", 400, "a", &Locations[ldLoc]);
			}
			else
			{
				Trace("OnSave() -> unknown character location");
			}
		}
	}
}

//#20180226-01
bool CanSave()
{
    bool bReturn = false;
    if(IsEntity(&worldMap) != 0)
	{
		bReturn = true;
	}
	else
	{
		if(IsEntity(&AISea) != 0)
		{
			bReturn = true;
		}
		else
		{
			int ldLoc = FindLoadedLocation();
			if(ldLoc >= 0)
			{
				bReturn = true;
			}
		}
	}
	return bReturn;
}

void ClearLocationsSaveData()
{
	aref loc = GetEventData();
	//Boyer fix #20170318-38
	if (loc) SendMessage(loc, "l", MSG_LOCATION_CLRCHRPOSITIONS);
}

int actLoadFlag = 0;

void OnLoad()
{
	actLoadFlag = 1;

	//#20200703-02
    if(userOptionsInt[UOPTION_INT_BI_HUD_HEIGHT] < 50)
       userOptionsInt[UOPTION_INT_BI_HUD_HEIGHT] = BI_COMPARE_HEIGHT;
	//#20170530-01 Music revolves changes
	int seaMusic = 0;
	LoadVariable(SEA_MUSIC_NATIONS, &seaMusic);
    userOptionsInt[UOPTION_INT_SEAUSENATION] = seaMusic;

	//Boyer add #20170301-6
	onLoadReInit();
	//Boyer change #20170418-01
	restoreQuestItems();
	//End Boyer add
	DeleteAttribute( pchar, "abordage_active_count" );
	//FreezeGroupControls(curKeyGroupName,false);

	if( CharacterIsDead(pchar) ) {
		pchar.chr_ai.hp = 1.0;
	}
	Nation_InitAfterLoading();
	ResetSound();

	//CreateClass("dummy");

	if(LoadSegment("Interface\BaseInterface.c"))
	{
		//InitBaseInterfaces_main();
		InitBaseInterfaces();
		ReloadProgressUpdate();
		InitInterfaceTables();
		ReloadProgressUpdate();
		UnloadSegment("Interface\BaseInterface.c");
	}
	ReloadProgressUpdate();

	DialogsInit();
	//IslandsInit();
	//LocationInit();

	ReloadProgressUpdate();

	//Boyer add to fix missing ship init #20170301-6
	ShipsInit();
	ReloadProgressUpdate();

	InitCharacterEvents();
	ReloadProgressUpdate();

	QuestsInit();
	ReloadProgressUpdate();

	InitTeleport();
	ReloadProgressUpdate();

	InitParticles();
	ReloadProgressUpdate();
	//ImportFuncTest();

	WeatherInit();
	ReloadProgressUpdate();

	InterfaceStates.Buttons.Resume.enable = true;
	InterfaceStates.Buttons.Save.enable = true;
	InterfaceStates.Buttons.Load.enable = true;

	//#20190327-01
	if(!CheckAttribute(pchar, "camEye"))
        pchar.camEye = 0;
	if(seadogs_saveFrom == "location")
	{
		ref mainchar;
		mainchar = GetMainCharacter();
		// actLoadFlag  //mainchar.isload = 1;
		LoadMainCharacterInFirstLocation(mainchar.location,"", mainchar.location.from_sea);

		int ldLoc = FindLoadedLocation();
		if(ldLoc >= 0)
		{
			SendMessage(&Locations[ldLoc], "l", MSG_LOCATION_TLPCHRPOSITIONS);
		}
	}
	else
	{
		if (seadogs_saveFrom == "sea")
		{
			Sea_Load();
 		}
		else
		{
			if(seadogs_saveFrom == "world map")
			{
				wdmLoadSavedMap();
			}
			else
			{
				Trace("Unknown seadogs_saveFrom == " + seadogs_saveFrom);
			}
		}
	}
	//ReloadEndFade();
	EngineLayersOffOn(true);
	//NewGame();
	DialogRun = false;
	InterfaceStates.Launched = false;
	ReloadProgressUpdate();

	PerkLoad();
	ReloadProgressUpdate();

	//#20190418-01
	if(CheckAttribute(&InterfaceStates, "useXBox"))
        InterfaceStates.useXBox = false;
	LoadGameOptions();
	setLocGrassQuality();
	FreezeGroupControls(curKeyGroupName,false);
	ReloadProgressEnd();
    //#20200519-02
    BattleInterface.ShifInfoVisible = InterfaceStates.enabledshipmarks;
    BattleInterface.battleborder.used = InterfaceStates.ShowBattleMode;
	if( CheckAttribute(&InterfaceStates,"WorldSituationUpdateStep") &&
		sti(InterfaceStates.WorldSituationUpdateStep) < 10 )
	{
		Event("EvSituationsUpdate", "l", sti(InterfaceStates.WorldSituationUpdateStep));
	}
	actLoadFlag = 0;
	ProcessVersionCheck();
	//#20181015-02
	if(bSeaActive && !bMapEnter)
        Sound_OnSeaAlarm555(seaAlarmed, true);
    if(!CheckAttribute(pchar, "ishiding"))
        pchar.ishiding = false;
    if(!CheckAttribute(pchar, "isspotted"))
        pchar.isspotted = false;
    if (!CheckAttribute(pchar, "BIHoldCommence"))
        pchar.BIHoldCommence = 0;
}

void NewGame()
{
	DeleteEntities();
	DelEventHandler("frame","NewGame");

	CreateEntity(&LanguageObject,"obj_strservice");
	CreateEntity(&reload_fader, "fader");
	//#20190118-01
	SendMessage(&reload_fader, "ls",FADER_PICTURE, rndLoadingScreens(NEW_GAME_SCRN));
	SendMessage(&reload_fader, "lfl", FADER_IN, RELOAD_TIME_FADE_IN, true);

	SetEventHandler("frame","NewGame_continue",1);
}

void NewGame_continue()
{
	DeleteAttribute( pchar, "abordage_active_count" );

	ReloadProgressStart();

	DelEventHandler("frame","NewGame_continue");

	if(LoadSegment("Interface\BaseInterface.c"))
	{
		InitBaseInterfaces();
		UnloadSegment("Interface\BaseInterface.c");
	}
	InitGame();
	ReloadProgressUpdate();

	CreateColonyCommanders();
	ReloadProgressUpdate();

	SetNames();
	ReloadProgressUpdate();

	Environment.date.hour = worldMap.date.hour;
	Environment.date.min = worldMap.date.min;
	Environment.date.sec = worldMap.date.sec;
	Environment.time = stf(worldMap.date.hour) + stf(worldMap.date.min)/60.0 + stf(worldMap.date.sec)/3600.0;
	Environment.date.year = worldMap.date.year;
	Environment.date.month = worldMap.date.month;
	Environment.date.day = worldMap.date.day;

	InterfaceStates.WorldSituationUpdateStep = 100;
	InterfaceStates.Buttons.Resume.enable = true;
	InterfaceStates.Buttons.Save.enable = true;
	InterfaceStates.Buttons.Load.enable = true;

	pchar = GetMainCharacter(); //fix
	//#20190327-01
    pchar.camEye = 0;
	initNewMainCharacter();
	ReloadProgressUpdate();

	InitPsHeroes();
	ReloadProgressUpdate();

    RumourInit();
	ReloadProgressUpdate();

	//ActivateTimeEvents(); //Empty, unused
	ReloadProgressUpdate();

	//LoadMainCharacterInFirstLocation(sTeleportLocName, sTeleportLocator, sTeleportLocName);
	startGameWeather = true;
	if (Pchar.questTemp.CapBloodLine != true)
	{
		InterfaceStates.startGameWeather = FindWeather("11 Hour");
		LoadMainCharacterInFirstLocationGroup("Ship_deck_Low", "goto", "goto4");
    }
    else
    {
        RemoveCharacterEquip(pchar, BLADE_ITEM_TYPE);
		RemoveCharacterEquip(pchar, GUN_ITEM_TYPE);
		RemoveCharacterEquip(pchar, SPYGLASS_ITEM_TYPE);
		RemoveCharacterEquip(pchar, PATENT_ITEM_TYPE);
		RemoveCharacterEquip(pchar, CIRASS_ITEM_TYPE);
		RemoveCharacterEquip(pchar, MAPS_ITEM_TYPE);
		DeleteAttribute(pchar, "items");
		InterfaceStates.startGameWeather = FindWeather("20 Hour");
		LoadMainCharacterInFirstLocationGroup("Estate", "reload", "reload1");
    }
	ReloadProgressUpdate();

	//InitTowns();
	UpdateCrewInColonies();
	ReloadProgressUpdate();

	//SetQuestForMenInTavernWhoGiveUsInfo(); // to_do

	//#20170625-01 Fix missing Cayman Grotto
    pchar.fix20170625 = true;
	//#20170626-01 Randomize cabins for small/medium
    pchar.fix20170627 = true;
    //#20170705-01 Add new cabins (big and medium)
    pchar.fix20170705 = true;
    //#20170801-02
    pchar.fix20170801 = true;
	//#20171209-01 Location texture paths for ERAS 2.8
    pchar.fix20171209 = true;
    //#20180119-03 New small cabin
	pchar.fix20180119 = true;
    pchar.fix20180321 = true;
	//#20180530-01
	pchar.fix20180707 = true;
	//#20180920-02
    pchar.fix20180920 = true;
    //#20180922-01
    pchar.fix20180922 = true;
    //#20180930-01
    pchar.fix20180929 = true;
    //#20180713-01 New Portugal nation
	pchar.fix20181026 = true;
    //#2019012-01
    pchar.fix20190112 = true;
    //#20190113-03
    pchar.fix20190113 = true;
    //#20190113-03
    pchar.fix20190119 = true;
    //#20190208-01
    pchar.fix20190208 = true;
    //#20190311-02
    pchar.fix20190311 = true;
    pchar.fix20190405 = true;
    //#20190424-01
    pchar.fix20190424 = true;
    //#20190709-01
    pchar.fix20190709 = true;
    pchar.fix20190727 = true;
    pchar.fix20190728 = true;
    //#20190909-01
    pchar.fix20190909 = true;
    pchar.fix20191008 = true;
    //#20191113-01
    pchar.fix20191113 = true;
    //#20191115-01
    pchar.fix20191115 = true;
    //#20191110-01
    pchar.fix20191120 = true;
     //#20200106-01
    pchar.fix20200106 = true;
    //#20200215-01
    pchar.fix20200215 = true;
    //#20200228-01
    pchar.fix20200228 = true;
    pchar.fix20200229 = true;
    //#20200318-01
    pchar.fix20200318 = true;
    //#20200323-01
    pchar.fix20200323 = true;
    //#20200401-01
    pchar.fix20200401 = true;
    //#20200619-01
    pchar.fix20200619 = true;
    //20201013-01
    pchar.fix20201013 = true;
    //#20201125-01
    pchar.fix20201125 = true;
     //#20210215-02
    pchar.fix20210215 = true;
    //#20220511-01
    pchar.fix20220511 = true;
    //#20220817-01
    pchar.fix20220818 = true;
    pchar.fix20220902 = true;
	//InitSmuggling();
	ReloadProgressEnd();
	pchar.BIHoldCommence = 0;
}

void InitGame()
{
	LayerCreate("realize", 1);
	LayerCreate("sea_realize", 1);
	LayerCreate("iRealize", 1);
	LayerCreate("fader_realize", 1);
	LayerCreate("inf_realize", 1);

	InitSound();
	ReloadProgressUpdate();

	DeleteSeaEnvironment();
	//CharactersInit();
	if(LoadSegment("worldmap\worldmap_init.c"))
	{
		wdmInitWorldMap();
		UnloadSegment("worldmap\worldmap_init.c");
	}
    InitPerks();
    ReloadProgressUpdate();

	IslandsInit();
	ReloadProgressUpdate();

	LocationInit();
	ReloadProgressUpdate();

	DialogsInit();
	ReloadProgressUpdate();

	InitTeleport();
	ReloadProgressUpdate();

	InitParticles();
	ReloadProgressUpdate();

    if(LoadSegment("items\initItems.c"))
	{
		InitItems();
		UnloadSegment("items\initItems.c");
	}
	ReloadProgressUpdate();

	//Boyer change #20170301-6...CharactersInit assigns RealShips, and after a bunch of 'New' games in a
	//session, RealShips array overflows, so call new function to reset
	ResetRealShipArray();
	ReloadProgressUpdate();

	CharactersInit();
	ReloadProgressUpdate();

	ColoniesInit();
	ReloadProgressUpdate();

	if(LoadSegment("store\initStore.c"))
	{
		InitStores();
		UnloadSegment("store\initStore.c");
	}
	ReloadProgressUpdate();

	QuestsInit();
	ReloadProgressUpdate();

	SeaAIGroupsInit();
	ReloadProgressUpdate();

	InitQuestMapEncounters();
	ReloadProgressUpdate();

	//InitLandRandomEncounters();
	//ReloadProgressUpdate();

	//SetNextWeather("10 Hours");

	ResetQuestMovie();
	ReloadProgressUpdate();

	LoadGameOptions();
	ReloadProgressUpdate();

	InfoShowSetting();
	ReloadProgressUpdate();
}

int counter = 0;
void ProcessControls()
{
	string ControlName;
	ControlName = GetEventData();
 	//aref  arItm;
    int   itmIdx;
	//if (bBettaTestMode) Log_QuestInfo(ControlName);
	//trace("ProcessControls() : " + ControlName);

    if (ControlName == "QuickSave") { MakeQuickSave(); return; }
    if (ControlName == "QuickLoad") { MakeQuickLoad(); return; }

    if (dialogRun) return;
	if (sti(InterfaceStates.Launched)==true) return;

	if (ControlName == "WhrPrevWeather")	{ Whr_LoadNextWeather(-1); return; }
	if (ControlName == "WhrNextWeather")	{ Whr_LoadNextWeather(1); return; }
	if (ControlName == "WhrUpdateWeather")	{ Whr_UpdateWeather(true); return; }

	//if (ControlName == "Help") RunHelpChooser();

	if(bSeaActive && !bAbordageStarted)
	{
		switch(ControlName)
		{
		    case "Ship_Fire": Ship_DoFire(); return; break;
		    case "Interface": ProcessInterfaceKey(); return; break;
			case "MainMenu": ProcessMainMenuKey();	return; break;
			case "MainMenuDouble": ProcessMainMenuKey(); return; break;
			case "Sea_CameraSwitch": SeaCameras_Switch(); return; break;
			case "Tele": Sea_ReloadStart(); return; break;
			//#20180226-02
            case "CIC_LoadBalls" :
                Log_SetStringToLog(xiStr("MSG_AIShip_19"));
                CIC_SendCommand(ControlName);
                return;
            break;
            case "CIC_LoadGrapes" :
                Log_SetStringToLog(xiStr("MSG_AIShip_20"));
                CIC_SendCommand(ControlName);
                return;
            break;
            case "CIC_LoadChain" :
                Log_SetStringToLog(xiStr("MSG_AIShip_21"));
                CIC_SendCommand(ControlName);
                return;
            break;
            case "CIC_LoadBombs" :
                Log_SetStringToLog(xiStr("MSG_AIShip_22"));
                CIC_SendCommand(ControlName);
                return;
            break;
            case "CIC_HoldCommenceFire" :
                if (sti(pchar.BIHoldCommence)) //Resume fire
                    Log_SetStringToLog(xiStr("MSG_AIShip_35"));
                else
                    Log_SetStringToLog(xiStr("MSG_AIShip_34"));
                CIC_SendCommand(ControlName);
                pchar.BIHoldCommence = !sti(pchar.BIHoldCommence);
                return;
            break;
            case "CIC_LoadAtWill" :
                Log_SetStringToLog(xiStr("MSG_AIShip_23"));
                CIC_SendCommand(ControlName);
                return;
            break;
            case "CIC_SailAway" :
                Log_SetStringToLog(xiStr("MSG_AIShip_24"));
                CIC_SendCommand(ControlName);
                return;
            break;
            case "CIC_LowerSails" :
                Log_SetStringToLog(xiStr("MSG_AIShip_25"));
                CIC_SendCommand(ControlName);
                return;
            break;
            case "CIC_ProtFlagship" :
                Log_SetStringToLog(xiStr("MSG_AIShip_26"));
                CIC_SendCommand(ControlName);
                return;
            break;
            //#20230304-01
            case "CIC_StandFast" :
                Log_SetStringToLog(xiStr("MSG_AIShip_36"));
                CIC_SendCommand(ControlName);
                return;
            break;
            case "CIC_FollowDirect" :
                Log_SetStringToLog(xiStr("MSG_AIShip_37"));
                CIC_SendCommand(ControlName);
                return;
            break;
		}
	}
	else
	{
	    switch(ControlName)
		{
		    //#20180926-02
            case "ChrForward":
                 if(CheckAttribute(&InterfaceStates,"alwaysrun") && sti(InterfaceStates.alwaysrun)==true && CheckAttribute(pchar, "ovrloadmsg"))
                    Log_SetStringToLog(xiStr("You are overloaded"));
                 return;
            break;
            case "ChrRun":
                 if(CheckAttribute(pchar, "ovrloadmsg"))
                    Log_SetStringToLog(xiStr("You are overloaded"));
                 return;
            break;
            case "ChrBackward": //ChrStrafeLeft ChrStrafeRight
                if (bLandInterfaceStart && LAi_IsFightMode(pchar))
                {
                    pchar.chr_ai.energy = stf(pchar.chr_ai.energy) - 2;
                    if (stf(pchar.chr_ai.energy) < 0) pchar.chr_ai.energy = 0;
                }
                return;
            break;
            case "ChrStrafeLeft":
                //#20190313-02
                if (bLandInterfaceStart && LAi_IsFightMode(pchar) && !LAi_CheckRunMode(pchar))
                {
                    pchar.chr_ai.energy = stf(pchar.chr_ai.energy) - 2;
                    if (stf(pchar.chr_ai.energy) < 0) pchar.chr_ai.energy = 0;
                }
                return;
            break;
            case "ChrStrafeRight":
                //#20190313-02
                if (bLandInterfaceStart && LAi_IsFightMode(pchar) && !LAi_CheckRunMode(pchar))
                {
                    pchar.chr_ai.energy = stf(pchar.chr_ai.energy) - 2;
                    if (stf(pchar.chr_ai.energy) < 0) pchar.chr_ai.energy = 0;
                }
                return;
            break;
            case "BOAL_UsePotion": // boal KEY_X
                if (bLandInterfaceStart) {
                    bool PotionUsed = false;
                    if(LAi_IsPoison(pchar)) {
                        //use antidote potion, otherwise use health pot
                        if (UseBestPotion(pchar, true) == 0) {
                            if (UseBestPotion(pchar, false) == 0) {
                                Log_SetStringToLog(xiStr("No Potion Found"));
                            }
                        }
                    }
                    else {
                        if(LAi_IsBottleWork(pchar))
                        {
                            PlaySound("Knock");
                            Log_SetStringToLog(xiStr("Potion still working"));
                        }
                        else
                        {
                            //use health potion, otherwise use antidote pot
                            if (UseBestPotion(pchar, false) == 0)
                            {
                                if (UseBestPotion(pchar, true) == 0)
                                {
                                    Log_SetStringToLog(xiStr("No Potion Found"));
                                }
                            }
                        }
                    }
                }
                return;
            break;
            //#20191008-01
            case "chrUseSpinach": // KEY_Z
                if (bLandInterfaceStart) {
                    int nSpinUse = UseSpinach(pchar)
                    switch(nSpinUse)
                    {
                        case 1: Log_SetStringToLog(xiStr("No Herb Found"));
                        break;
                        case 2: Log_SetStringToLog(xiStr("PerkCooldownWait"));
                        break;
                    }
                }
                return;
            break;
            case "BOAL_ActivateRush":  // boal KEY_F
                if (bLandInterfaceStart && GetCharacterPerkUsing(pchar, "Rush"))
                {
                    ActivateCharacterPerk(pchar, "Rush");
                }
                else
                {
                    if (bLandInterfaceStart && curKeyGroupName == "FightModeControls")
                    {
                        PlaySound("knock");
                    }
                }
                return;
            break;
            case "OfficersCharge":
                pchar.OfficerAttRange = 35.0;
                OfficersFollow();
                Log_SetStringToLog(xiStr("MSG_AIChar_1"));
                return;
            break;
            case "OfficersFollow":
                pchar.OfficerAttRange = 7.0;
                OfficersFollow();
                Log_SetStringToLog(xiStr("MSG_AIChar_2"));
                return;
            break;
            case "OfficersHold":
                pchar.OfficerAttRange = 7.0;
                OfficersHold();
                Log_SetStringToLog(xiStr("MSG_AIChar_3"));
                return;
            break;
			case "MainMenu": ProcessMainMenuKey();	return; break;
			case "MainMenuDouble": ProcessMainMenuKey(); return; break;
			case "Interface": ProcessInterfaceKey();return; break;
			case "Tele":
				StartQuickTeleport();
                return;
            break;
			case "TeleBack": Teleport(-1); return; break;
			case "Action":
				//DumpAttributes(loadedLocation/*loadedLocation.reload.reload1.x*/);
				//trace("Y: " + loadedLocation.reload.reload1.y);
				//trace("Z: " + loadedLocation.reload.reload1.z);
                return;
            break;
		}
	}
  	if (ControlName=="TimeScaleFaster" || ControlName == "TimeScaleSlower")
  	{
        //Boyer change #20170318-38
        if (CheckAttribute(&loadedLocation, "type") && loadedLocation.type == "underwater") return;
		DeleteAttribute(pchar, "pause");
		if (ControlName == "TimeScaleFaster")
     	{
			if (TimeScaleCounter >= 12)
			{
			    TimeScaleCounter += 4;
			}
			else
			{
                if (TimeScaleCounter >= 4)
				{
				    TimeScaleCounter += 2;
				}
				else
				{
					TimeScaleCounter++;
				}
			}
		}
     	else
     	{
            if (TimeScaleCounter >= 16)
			{
			    TimeScaleCounter -= 4;
			}
			else
			{
                if (TimeScaleCounter >= 6)
				{
				    TimeScaleCounter -= 2;
				}
				else
				{
					TimeScaleCounter--;
				}
			}
		}
		if (true) // MOD_SKILL_ENEMY_RATE > 1) // 0.25
        {
		   if (!bBettaTestMode && TimeScaleCounter < -2) TimeScaleCounter = -2;
		}
        if (bDisableMapEnter)
        {
            if (TimeScaleCounter > 20) TimeScaleCounter = 20;
        }
        else
        {
            if (bSeaActive && !bAbordageStarted )
            {
            	if (TimeScaleCounter > 28) TimeScaleCounter = 28;
            }
            else
            {
            	if (TimeScaleCounter > 8) TimeScaleCounter = 8;
            }
        }
        if (IsEntity(worldMap))
        {
            if (TimeScaleCounter > 6) TimeScaleCounter = 6;
        }
     	float newTimeScale = 1 + (TimeScaleCounter)*0.25; // GetSeaTimeScale()
     	if (newTimeScale < 0) //don't wanna crash the game
     	{
        		TimeScaleCounter = -4;
        		newTimeScale = 0;
     	}
     	Log_SetStringToLog("x" + newTimeScale);
     	if (TimeScaleCounter == 0) //back to normal
     	{
			if(IsPerkIntoList("TimeSpeed"))
        	{
        		SetTimeScale(1.0);
        		DelPerkFromActiveList("TimeSpeed");
        	}
     	}
     	else
     	{
        	SetTimeScale(newTimeScale);
        	//if perk not in list
        	if(!IsPerkIntoList("TimeSpeed"))
        	{
				AddPerkToActiveList("TimeSpeed");
			}
     	}
        return;
	}
	switch(ControlName)
	{
        case "TimeScale":
            DeleteAttribute(pchar, "pause");
            //Boyer change #20170318-38
            if (CheckAttribute(&loadedLocation, "type") && loadedLocation.type == "Underwater") {
				return;
			}
			if(IsPerkIntoList("TimeSpeed"))
			{
				SetTimeScale(1.0);
				TimeScaleCounter = 0;
                Log_SetStringToLog("Time x1");
				DelPerkFromActiveList("TimeSpeed");
			}
			else
			{
				SetTimeScale(GetSeaTimeScale());
				TimeScaleCounter = 4;
                Log_SetStringToLog("Time x2");
				AddPerkToActiveList("TimeSpeed");
			}
		break;
		case "VK_PAUSETimePause":
			if (!CheckAttribute(pchar, "pause"))
			{
				pchar.pause = true;
				SetTimeScale(0.0);
			    TimeScaleCounter = -3;
			    AddPerkToActiveList("TimeSpeed");
			}
			else
			{
                DeleteAttribute(pchar, "pause");
				SetTimeScale(1.0);
				DelPerkFromActiveList("TimeSpeed");
				TimeScaleCounter = 0;
			}
		break;
		case "WMapCancel":
			if(IsEntity(&worldMap))
			{
				pchar.space_press = 1;
				DeleteAttribute(pchar, "SkipEshipIndex");
			}
		break;
		case "PaperMap":
			LaunchPaperMapScreen();
		break;
        //JA 16/8/09 -->
	    case "BOAL_DeadSearch":  // KEY_1
			if (bLandInterfaceStart)
            {
				itmIdx = Dead_FindCloseBody_WithLoot();
				if (itmIdx == -1) {
                itmIdx = Dead_FindCloseBody();
				}
			    if (itmIdx != -1)
			    {
					Dead_OpenBoxProcedureOnCharID(itmIdx);
				}
				else
				{
                    Log_Info(XI_ConvertString("MSG_seadogs_4"));
				}
		    }
	    break;//<--JA
		case "BOAL_SetCamera":
		    // F10
		    //CameraHoldPos();
		    if (MOD_BETTATESTMODE == "On")
		    {
                if(LoadSegment("Debuger.c"))
            	{
                    ActiveF10Control();
            		UnloadSegment("Debuger.c");
            	}
		    }
		break;
        case "BOAL_Control":
		    //  F11
		    if (MOD_BETTATESTMODE == "On" || MOD_BETTATESTMODE == "Test")
		    {
		       LaunchDebuderMenu();
		    }
		break;
		case "BOAL_Control3":
		    // F9
		    if (MOD_BETTATESTMODE == "On")
		    {
		       //LaunchBoalDebugScreenSecond();
		    }
		break;
        case "TeleportActive":
		    if (MOD_BETTATESTMODE == "On")
		    {
                if(LoadSegment("Debuger.c"))
            	{
                    ActiveF4Control();
            		UnloadSegment("Debuger.c");
            	}
		    }
		break;
		case "BOAL_ControF5":
		    if (MOD_BETTATESTMODE == "On")
		    {
                if(LoadSegment("Debuger.c"))
            	{
                    ActiveF5Control();
            		UnloadSegment("Debuger.c");
            	}
		    }
		break;
		case "BOAL_ControF7":
		    // F7
		    if (MOD_BETTATESTMODE == "On")
		    {
                if(LoadSegment("Debuger.c"))
            	{
                    ActiveF7Control();
            		UnloadSegment("Debuger.c");
            	}
		    }
		break;
		case "executeconsole":
			if(LoadSegment("console.c"))
			{
				ExecuteConsole();
				UnloadSegment("console.c");
			}
		break;
        case "BOAL_Control2": // F12
            if(LoadSegment("Debuger.c"))
        	{
                ActiveF12Control();
        		UnloadSegment("Debuger.c");
        	}
        break;
        case "BOAL_ControlDebug": // VK_INSERT
            if (MOD_BETTATESTMODE == "On")
		    {
                if(LoadSegment("Debuger.c"))
            	{
                    ActiveINSERTControl();
            		UnloadSegment("Debuger.c");
            	}
        	}
        break;
	}
}

void Teleport(int step)
{
	nTeleportLocation = nTeleportLocation + step;
	if(nTeleportLocation >=	nLocationsNum) nTeleportLocation = 1;
	if(nTeleportLocation <=	0) nTeleportLocation = nLocationsNum - 1;

	sTeleportLocName = Locations[nTeleportLocation].id;
	Trace("Teleport to '" + sTeleportLocName + "'");

    ReleaseSound(0);
	ClearEvents();
	ClearPostEvents();
	DeleteEntities();
	SetEventHandler("frame","NewGame",1);
}

void ProcessMainMenuKey()
{
	if (interfacestates.buttons.resume.enable == "1")
	{
		//LaunchMainMenu();
		LaunchGameMenuScreen();
	}
}

void ProcessInterfaceKey()
{
	if( CharacterIsDead(GetMainCharacter()) ) {return;}
	if(bSeaActive && !bAbordageStarted)
	{
		if( CheckAttribute(&BattleInterface,"ComState") && sti(BattleInterface.ComState) != 0 )
			{return;}
	}
	else
	{
		if( SendMessage(GetMainCharacter(),"ls",MSG_CHARACTER_EX_MSG,"IsFightMode") != 0 )
			{return;}
		if( CheckAttribute(&objLandInterface,"ComState") && sti(objLandInterface.ComState) != 0 )
			{return;}
	}
	if (bDisableCharacterMenu)
	{
		Log_SetStringToLog(XI_ConvertString("You can`t launch menu"));
		return;
	}
	if (bAbordageStarted && !bCabinStarted && !bDeckBoatStarted)
	{
		Log_SetStringToLog(XI_ConvertString("You can`t launch menu"));
		return;
	}
	LaunchSelectMenu();
}

void GameOverE()
{
	if (bSeaActive && !bAbordageStarted)
    {
		PauseParticles(true); //fix
		SendMessage(&AIBalls, "l", MSG_MODEL_RELEASE);
	}
	GameOver("sea");
	DeleteSeaEnvironment();
}

void GameOver(string sName)
{
	ref mc;
	int nSelect;
	string sFileName;
	//ResetSoundScheme();
	PauseAllSounds();
	ResetSound();
	EngineLayersOffOn(false);

	mc = GetMainCharacter();

	//Boyer add chance for mutiny death to be thrown overboard and wash ashore #20170318-32
	bool bSurvive = false;
    if(CheckAttribute(mc, "GenQuest.MunityStart")){
        int nChance = rand(99);
        int nStart = sti(mc.GenQuest.MunityStart);
        if(nChance < 40 && nStart == 1){
            LAi_SetFightMode(mc, false);
            DeleteAttribute(mc, "GenQuest.MunityStart");
            bSurvive = true;
        }
    }
    //End Boyer add #20170318-32
    if(!bSurvive){
        ClearEvents();
        ClearPostEvents();
        DeleteEntities();
    }
    if(sti(InterfaceStates.Launched)) {
        UnloadSegment(Interfaces[CurrentInterface].SectionName);
    }
    if(LoadSegment("Interface\BaseInterface.c"))
    {
        InitBaseInterfaces();
        UnloadSegment("Interface\BaseInterface.c");
    }
    if(!bSurvive){
        InterfaceStates.showGameMenuOnExit = false;
        InterfaceStates.Buttons.Resume.enable = false;
        InterfaceStates.Buttons.Save.enable = false;
    }
    InitSound();

    if(bSurvive){
        DoQuestCheckDelay("SurviveSinkingWashAshore", 9.0); //quests_reaction.c case label
        return;
    }
	SetEventHandler(EVENT_END_VIDEO,"LaunchMainMenu_afterVideo",0);
	FadeOutMusic(3);
	PlayStereoOGG("music_ship_dead");

	//#20190118-01
	float fDelaytime = 5.0;
    string endPic = rndGameOverScreens(sName, &fDelayTime);
	StartPictureAsVideo(endPic, fDelayTime);
}

string its(int iNumber)
{
	string sText = iNumber;
	return sText;
}

bool QuickSaveGameEnabledHardcore()
{
    bool TmpBool = false;
    ref mchref = GetMainCharacter();

	if (bHardcoreGame)
	{
		int idxLoadLoc = FindLoadedLocation();
	    if( idxLoadLoc!=-1 )
	    {
	        if (CheckAttribute(&Locations[idxLoadLoc], "type"))
	        {
	            if (Locations[idxLoadLoc].type == "church" || Locations[idxLoadLoc].id == "GloriaChurch")
	            {
	                TmpBool = true;
	            }
	        }
	    }
    }
    else
    {
        TmpBool = true;
    }

    return TmpBool;
}

bool CheckSaveGameEnabled()
{
    bool TmpBool = true;
    ref mchref = GetMainCharacter();

    if (CheckAttribute(&InterfaceStates, "Buttons.Save.enable"))
	{
		if(InterfaceStates.Buttons.Save.enable != 1)
		{
			TmpBool = false;
		}
	}
	else
	{
		TmpBool = false;
	}
	if (bAbordageStarted) {TmpBool = false;}

	if(LAi_IsBoardingProcess()) {TmpBool = false;}

	if( CharacterIsDead(mchref) ) {TmpBool = false;}

	if (TmpBool)
	{
		int idxLoadLoc = FindLoadedLocation();
	    if (idxLoadLoc != -1 )
	    {
	        if (Locations[idxLoadLoc].id == "Ship_deck" || Locations[idxLoadLoc].id == "Deck_Near_Ship")
	        {
	            TmpBool = false;
	        }
	    }
	}
    return TmpBool;
}

//Boyer change #20170418-01
void restoreQuestItems()
{
    ref		rItemRef;
    if(CheckAttribute(pchar, "restoreLSCKeymasterKey")){
        //From reaction_functions.c
        rItemRef =  ItemsFromID(pchar.restoreLSCKeymasterKey);
        rItemRef.shown = true;
        //From initItems.c
        rItemRef.startLocation = "Villemstad_houseSp5";
        rItemRef.startLocator = "item2";
    }
    if(CheckAttribute(pchar, "restoreLSCTrustLetter")){
        //From RelationAgent_dialog.c
        ChangeItemName(pchar.restoreLSCTrustLetter, "itmname_letter_LSC_1");
        ChangeItemDescribe(pchar.restoreLSCTrustLetter, "itmdescr_letter_LSC_1");
        rItemRef =  ItemsFromID(pchar.restoreLSCTrustLetter);
        rItemRef.shown = true;
        rItemRef.startLocation = "Marigo_houseH2";
        rItemRef.startLocator = "item1";
    }
    int n;
    //#20170620-01 LSC island fix for reinit
    //From items_utilite.c QuestCheckTakeItem()
    /*
    if(CheckAttribute(pchar, "restoreLSCIsland")){
        n = FindIsland("LostShipsCity");
        Islands[n].visible = true;
        Islands[n].reload_enable = true;
        Islands[n].alwaysStorm = true;
        Islands[n].MaxSeaHeight = 2.0;
        Islands[n].storm = true;
        Islands[n].tornado = true;
    }
    //From reaction_functions.c
    if(CheckAttribute(pchar, "restoreLSCIsland2")){
        n = FindIsland("LostShipsCity");
        Islands[n].visible = true;
        Islands[n].reload_enable = true;
    }
    if(CheckAttribute(pchar, "restoreLSCIsland3")){
        LSC_BigStormIsBegin();
    }
    if(CheckAttribute(pchar, "restoreLSCIsland4")){
        LSC_BigStormIsBegin();
        LSC_takeStormIsland("");
    }
    */
}

//Boyer change #20170418-01
void removeQuestItemAttribute(string itemID)
{
    switch(itemID)
    {
        case "keyQuestLSC":
            DeleteAttribute(pchar, "restoreLSCKeymasterKey");
        break;
        case "letter_LSC":
            DeleteAttribute(pchar, "restoreLSCTrustLetter");
        break;
    }
}

//#20170530-01 Music revolves changes
void seaMusicForNations()
{
    int SeaMusic = 1;
    SaveVariable(SEA_MUSIC_NATIONS, SeaMusic);
}

void deleteTempVarFiles()
{
	FileDelete(SEA_MUSIC_NATIONS);
	return;
}

//#20170619-02 Function for loading screens
string getLoadingScreen()
{
    //#20170318-68 ERAS fix
    switch (rand(41))
    {
        case 0 :
			return "loading\Start_Loading.tga.tx";
		break;
		case 1 :
			return "loading\SeaF.tga.tx";
		break;
		case 2 :
			return "loading\battle.tga.tx";
		break;
		case 3 :
			return "loading\shipcannon.tga.tx";
		break;
		case 4 :
			return "loading\rescue.tga.tx";
		break;
		case 5 :
			return "loading\Start_Loading1.tga.tx";
		break;
		case 6 :
			return "loading\seaStand1.tga.tx";
		break;
		case 7 :
			return "loading\battle1.tga.tx";
		break;
		case 8 :
			return "loading\rescue1.tga.tx";
		break;
		case 9 :
			return "loading\Start_Loading2.tga.tx";
		break;
		case 10 :
			return "loading\seaStand2.tga.tx";
		break;
		case 11 :
			return "loading\rescue2.tga.tx";
		break;
		case 12 :
			return "loading\seaStand3.tga.tx";
		break;
		case 13 :
			return "loading\battle2.tga.tx";
		break;
		case 14 :
			return "loading\seaX.tga.tx";
		break;
		case 15 :
			return "loading\shipcannon1.tga.tx";
		break;
		case 16 :
			return "loading\shipcannon2.tga.tx";
		break;
		case 17 :
			return "loading\sea6.tga.tx";
		break;
		case 18 :
			return "loading\battle4.tga.tx";
		break;
		case 19 :
			return "loading\BarbaryBattle.tga.tx";
		break;
		case 20 :
			return "loading\SpanishTown3.tga.tx";
		break;
		case 21 :
			return "loading\SpanishTown4.tga.tx";
		break;
		case 22 :
			return "loading\rescue3.tga.tx";
		break;
		case 23 :
			return "loading\battle5.tga.tx";
		break;
		case 24 :
			return "loading\shipcannon3.tga.tx";
		break;
		case 25 :
			return "loading\rescue4.tga.tx";
		break;
		case 26 :
			return "loading\storm1.tga.tx";
		break;
		case 27 :
			return "loading\storm2.tga.tx";
		break;
		case 28 :
			return "loading\rescue5.tga.tx";
		break;
		case 29 :
			return "loading\Battle7.tga.tx";
		break;
		case 30 :
			return "loading\SpanishShore2.tga.tx";
		break;
		case 31 :
			return "loading\boat7.tga.tx";
		break;
		case 32 :
			return "loading\battle13.tga.tx";
		break;
		case 33 :
			return "loading\SpanishScene1.tga.tx";
		break;
		case 34 :
			return "loading\Twister.tga.tx";
		break;
		case 35 :
			return "loading\BattleT.tga.tx";
		break;
		case 36 :
			return "loading\SeaIS.tga.tx";
		break;
		case 37 :
			return "loading\SeaP.tga.tx";
		break;
		case 38 :
			return "loading\SeaV.tga.tx";
		break;
		case 39 :
			return "loading\SeaZ.tga.tx";
		break;
		case 40 :
			return "loading\Storm7.tga.tx";
		break;
		case 41 :
			return "loading\battle3.tga.tx";
		break;
	}
	return "loading\Start_Loading.tga.tx";
}
//#20190118-01
string rndLoadingScreens(int scrnType)
{
    switch(scrnType)
    {
    case CBN_TOSEA_SCRN:
        switch(rand(2))
        {
        case 0:
            return "loading\sea.tga.tx";
            break;
        case 1:
            return "loading\SeaA.tga.tx";
            break;
        case 2:
            return "loading\seaStand.tga.tx";
            break;
        }
        break;
    case WM_SEA_SCRN:
        switch(rand(5))
        {
        case 0:
            return "loading\sea.tga.tx";
            break;
        case 1:
            return "loading\sea1.tga.tx";
            break;
        case 2:
            return "loading\seaStand2.tga.tx";
            break;
        case 3:
            return "loading\rescue6.tga.tx";
            break;
        case 4:
            return "loading\rescue.tga.tx";
            break;
        case 5:
            return "loading\sea4.tga.tx";
            break;
        }
        break;
    case WM_ENCOUNTER_SCRN:
        switch(rand(5))
        {
        case 0:
            return "loading\battle.tga.tx";
            break;
        case 1:
            return "loading\battle1.tga.tx";
            break;
        case 2:
            return "loading\battle2.tga.tx";
            break;
        case 3:
            return "loading\battle8.tga.tx";
            break;
        case 4:
            return "loading\battle9.tga.tx";
            break;
        case 5:
            return "loading\battle4.tga.tx";
            break;
        }
        break;
    case WM_STORM_SCRN:
        switch(rand(3))
        {
        case 0:
            return "loading\storm.tga.tx";
            break;
        case 1:
            return "loading\storm1.tga.tx";
            break;
        case 2:
            return "loading\storm1.tga.tx";
            break;
        case 3:
            return "loading\stormE.tga.tx";
            break;
        }
        break;
    case SEA_SAILTO_SCRN:
        switch(rand(3))
        {
        case 0:
            return "loading\sea.tga.tx";
            break;
        case 1:
            return "loading\sea3.tga.tx";
            break;
        case 2:
            return "loading\SpanishScene1.tga.tx";
            break;
        case 3:
            return "loading\seaX.tga.tx";
            break;
        }
        break;
    case QUEST_LOAD_SCRN:
        switch(rand(5))
        {
        case 0:
            return "loading\sea.tga.tx";
            break;
        case 1:
            return "loading\sea4.tga.tx";
            break;
        case 2:
            return "loading\seaStand1.tga.tx";
            break;
        case 3:
            return "loading\seaStand2.tga.tx";
            break;
        case 4:
            return "loading\seaX.tga.tx";
            break;
        case 5:
            return "loading\seaStand1.tga.tx";
            break;
        }
        break;
    case DECK_BOAT_SCRN:
        switch(rand(3))
        {
        case 0:
            return "loading\boat.tga.tx";
            break;
        case 1:
            return "loading\boat1.tga.tx";
            break;
        case 2:
            return "loading\boat2.tga.tx";
            break;
        case 3:
            return "loading\seaStand3.tga.tx";
            break;
        }
        break;
    case SEA_MAP_SCRN:
        switch(rand(2))
        {
        case 0:
            return "loading\sea.tga.tx";
            break;
        case 1:
            return "loading\sea1.tga.tx";
            break;
        case 2:
            return "loading\SeaA.tga.tx";
            break;
        }
        break;
    case LAND_MAP_SCRN:
        switch(rand(2))
        {
        case 0:
            return "loading\sea.tga.tx";
            break;
        case 1:
            return "loading\sea3.tga.tx";
            break;
        case 2:
            return "loading\SeaIS.tga.tx";
            break;
        }
        break;
    case SEA_LOGIN_SCRN:
        switch(rand(2))
        {
        case 0:
            return "loading\sea.tga.tx";
            break;
        case 1:
            return "loading\SeaA.tga.tx";
            break;
        case 2:
            return "loading\SeaIS.tga.tx";
            break;
        }
        break;
    case SEA2SEA_SCRN:
        switch(rand(1))
        {
        case 0:
            return "loading\art\open_sea_clear.tga.tx";
            break;
        case 1:
            return "loading\art\open_sea_clear1.tga.tx";
            break;
        }
        break;
    case RLD_LOC_SCRN:
        switch(rand(3))
        {
        case 0:
            return "loading\seaStand.tga.tx";
            break;
        case 1:
            return "loading\shipcannon1.tga.tx";
            break;
        case 2:
            return "loading\shipcannon3.tga.tx";
            break;
        case 3:
            return "loading\SpanishTown3.tga.tx";
            break;
        }
        break;
    case NEW_GAME_SCRN:
        switch(rand(2))
        {
        case 0:
            return "loading\battle1.tga.tx";
            break;
        case 1:
            return "loading\Start_Loading.tga.tx";
            break;
        case 2:
            return "loading\seaStand3.tga.tx";
            break;
        }
        break;
    }
    return "loading\sea.tga.tx";
}
//#20190118-01
string rndGameOverScreens(string endType, ref delayTime)
{
    delayTime = 9.1;
    switch(endType)
	{
		case "sea":
		    return "loading\seadeath.tga.tx";
		break;
		case "boarding":
		    switch(rand(3))
		    {
            case 0:
                return "loading\seadeath.tga.tx";
                break;
            case 1:
                return "loading\seadeath1.tga.tx";
                break;
            case 2:
                return "loading\SeaDeath2.tga.tx";
                break;
            case 3:
                return "loading\death2.tga.tx";
                break;
		    }
		break;
		case "mutiny":
		    return "loading\death2.tga.tx";
		break;
		case "town":
		    delayTime = 8.9;
		    switch(rand(3))
		    {
            case 0:
                return "loading\finalbad1.tga.tx";
                break;
            case 1:
                return "loading\finalbad4.tga.tx";
                break;
            case 2:
                return "loading\finalbad6.tga.tx";
                break;
            case 3:
                return "loading\finalbad2.tga.tx";
                break;
		    }
		break;
		case "blood":
		    delayTime = 3.9;
			return "loading\finalbad3.tga.tx";
		break;
		//Default
		//case "land":
		    switch(rand(4))
		    {
            case 0:
                return "loading\death.tga.tx";
                break;
            case 1:
                return "loading\death1.tga.tx";
                break;
            case 2:
                return "loading\death3.tga.tx";
                break;
            case 3:
                return "loading\death4.tga.tx";
                break;
            case 4:
                return "loading\death8.tga.tx";
                break;
		    }
	}
	return "loading\death.tga.tx";
}

void DeleteBackEnvironment()
{
    aref iFaceBackScene;
    GetEntity("InterfaceBackScene", &iFaceBackScene));

	DeleteClass(&iFaceBackScene);
}

extern void SetCurrentProfile( string profileName );
//#20171009-03
void ResetDevice()
{
	if(InterfaceStates.Launched == true) {
        if(CurrentInterface == INTERFACE_SAVELOAD) {
            SetCurrentProfile( PlayerProfile.name );
        }
	}
	else {
        //Call twice to remove/replace
        ChangeShowIntarface();
        ChangeShowIntarface();
	}
}
//#20190307-01
void ControllerActivation()
{
    SetNodeUsing("USECONTROLLER_CHECKBOX", true);
}

#include "globals2.c"
