#include "sea_ai\Script_defines.h"
#include "sea_ai\SeaPeople.h"

#include "sea_ai\AIGroup.c"
#include "sea_ai\AIShip.c"
#include "sea_ai\AIFort.c"
#include "sea_ai\AISea.c"
#include "sea_ai\AICameras.c"
#include "sea_ai\AIAbordage.c"

// boal Cabin 09.09.03 -->
// MAXIMUS Deck -->
#include "sea_ai\BOAL_Deck.c" // KK
#include "sea_ai\MUTINY_Deck.c"
// MAXIMUS Deck <--
// boal Cabin 09.09.03 <--

#include "sea_ai\AIFantom.c"
#include "sea_ai\AICannon.c"
#include "sea_ai\AIBalls.c"
#include "sea_ai\AIIsland.c"
#include "sea_ai\AISeaGoods.c"
#include "sea_ai\AITasks\AITasks.c"

#include "sea_ai\ShipBortFire.c"
#include "sea_ai\ShipDead.c"
#include "sea_ai\ShipWalk.c"

#include "sea_ai\Telescope.c"

#include "battle_interface\BattleInterface.c"

#event_handler("Sea_FirstInit", "Sea_FirstInit");

#define PLAYER_GROUP	"OurGroup"

string	sCurrentSeaExecute = "execute";
string	sCurrentSeaRealize = "realize";

int		iAITemplatesNum;
bool	bSeaActive;
bool 	bSkipSeaLogin = false;
bool	bIslandLoaded = false;
bool	bSeaReloadStarted = false;
bool	bNotEnoughBalls;
bool	bStorm, bTornado;
bool	bSeaQuestGroupHere = false;

int		iStormLockSeconds = 0;

object	Island, IslandReflModel;
object	Touch, AISea;
object	SeaFader;
object	Seafoam, BallSplash, SinkEffect, PeopleOnShip, Telescope, SeaOperator, Artifact;
object	Sharks;
object	SeaLighter;

object	SeaLocatorShow;
object	LoginGroupsNow;
bool	bSeaShowLocators = true;
bool	bQuestDisableMapEnter = false;
bool	bFromCoast = false;

float	SeaMapLoadX = -1570.99;
float	SeaMapLoadZ = 950.812;
float	SeaMapLoadAY = 10.54;

float	fSeaExp = 0.0;
float	fSeaExpTimer = 0.0;

int	iSeaSectionLang = -1;

bool bRecognized = false; // KK

void DeleteSeaEnvironment()
{
	ref rPlayer = GetMainCharacter();

	StopMusic();
	bSeaActive = false;
	sCurrentSeaExecute = "execute";
	sCurrentSeaRealize = "realize";

	rPlayer.Ship.Stopped = true;
	DeleteBattleInterface();

	DelEventHandler(SHIP_BORT_FIRE, "Ship_BortFire");
	DelEventHandler(BALL_FLY_UPDATE, "Ball_OnFlyUpdate");

	SendMessage(&AISea, "l", AI_MESSAGE_UNLOAD);

	DeleteSea();

	DeleteClass(&Island);
	DeleteClass(&IslandReflModel);
	DeleteClass(&Touch);
	DeleteClass(&Seafoam);
	DeleteClass(&BallSplash);
	DeleteClass(&SinkEffect);
	DeleteClass(&PeopleOnShip);
	DeleteClass(&SeaLocatorShow);
	DeleteClass(&SeaOperator);
	DeleteClass(&Telescope);
	DeleteClass(&Sharks);

	DeleteClass(&SeaLighter);

	if (IsEntity(&Artifact))
		DeleteClass(&Artifact);

	DeleteBallsEnvironment();
	DeleteCannonsEnvironment();
	DeleteSeaCamerasEnvironment();
	DeleteShipEnvironment();
	DeleteFortEnvironment();
	DeleteAbordageEnvironment();
	DeleteSeaGoodsEnvironment();

	DeleteWeatherEnvironment();

	DeleteAttribute(&AISea,"");

	LayerFreeze(SEA_EXECUTE, true);
	LayerFreeze(SEA_REALIZE, true);

	LayerFreeze("realize", false);
	LayerFreeze("execute", false);

	DeleteClass(&AISea);

	DeleteAnimals();

	// delete masts fall modules
		DeleteEntitiesByType("mast");

	// delete particle system
		DeleteParticles();

	// delete our group
		Group_DeleteGroup(PLAYER_GROUP);

	// delete fantom and dead groups
		Group_DeleteUnusedGroup();

	//
		LanguageCloseFile(iSeaSectionLang); iSeaSectionLang = -1;

	//
		Encounter_DeleteDeadQuestMapEncounters();

}

void CreateSeaEnvironment()
{
	sCurrentSeaExecute = SEA_EXECUTE;
	sCurrentSeaRealize = SEA_REALIZE;

	iSeaSectionLang = LanguageOpenFile("SeaSection.txt");

	CreateParticleEntity();

	Ship_Walk_Init();

	LayerFreeze("realize", true);
	LayerFreeze("execute", true);
	LayerCreate("sea_reflection", 1);
	LayerFreeze("sea_reflection", false);

	InterfaceStates.Buttons.Resume.enable = true;

	bSeaActive = true;
	LayerCreate(SEA_REALIZE, 1);
	LayerSetRealize(SEA_REALIZE, 1);
	LayerCreate(SEA_EXECUTE, 1);
	LayerSetExecute(SEA_EXECUTE, 1);

	LayerFreeze(SEA_EXECUTE, false);
	LayerFreeze(SEA_REALIZE, false);

	CreateSea(SEA_EXECUTE, SEA_REALIZE);			ReloadProgressUpdate();
	CreateWeather(SEA_EXECUTE, SEA_REALIZE);		ReloadProgressUpdate();

	CreateEntity(&AISea, "sea_ai");					ReloadProgressUpdate();
	LayerAddObject(SEA_EXECUTE, &AISea, 1);
	LayerAddObject(SEA_REALIZE, &AISea, -1);

	CreateEntity(&Touch, "touch");					ReloadProgressUpdate();
	LayerAddObject(SEA_EXECUTE, &Touch, 1);
	Touch.CollisionDepth = -10.0;
	//LayerAddObject(SEA_REALIZE, &Touch, -1);		// for collision debug

	CreateEntity(&BallSplash, "BallSplash");		ReloadProgressUpdate();
	LayerAddObject(SEA_EXECUTE, &BallSplash, -1);
	LayerAddObject(SEA_REALIZE, &BallSplash, 65535);

	CreateEntity(&SinkEffect, "SINKEFFECT");		ReloadProgressUpdate();
	LayerAddObject(SEA_EXECUTE, &SinkEffect, 65531);
	LayerAddObject(SEA_REALIZE, &SinkEffect, 65531);

	CreateEntity(&PeopleOnShip, "PEOPLE_ON_SHIP");	ReloadProgressUpdate();
	LayerAddObject(SEA_EXECUTE, &PeopleOnShip, 100);
	LayerAddObject(SEA_REALIZE, &PeopleOnShip, 100);

	// 1.03 - CreateEntity(&SeaLocatorShow, "SeaLocatorShow"); ReloadProgressUpdate();
	LayerAddObject(SEA_REALIZE, &SeaLocatorShow, -1);

	CreateEntity(&Telescope, "TELESCOPE");			ReloadProgressUpdate();
	LayerAddObject(SEA_EXECUTE, &Telescope, -1);
	LayerAddObject(SEA_REALIZE, &Telescope, -3);
	TelescopeInitParameters(&Telescope);

	CreateSeaAnimals();								ReloadProgressUpdate();

	// create all other environment
	CreateBallsEnvironment();						ReloadProgressUpdate();
	CreateCannonsEnvironment();						ReloadProgressUpdate();
	CreateSeaCamerasEnvironment();					ReloadProgressUpdate();
	CreateShipEnvironment();						ReloadProgressUpdate();
	CreateFortEnvironment();						ReloadProgressUpdate();
	CreateAbordageEnvironment();					ReloadProgressUpdate();
	CreateSeaGoodsEnvironment();					ReloadProgressUpdate();

	SetEventHandler(SHIP_CREATE, "Ship_Walk_Create", 0);
	SetEventHandler("MSG_TELESCOPE_REQUEST", "Telescope_Request", 0);
	SetEventHandler(SHIP_BORT_FIRE, "Ship_BortFire", 0);

	bNotEnoughBalls = false;

	if (CANNONPOWDER_MOD) {// TIH --> mod toggle 7-7-06
		ref mCh = GetMainCharacter();
		int fPwdr = 0;
		int pwdrQty = GetCargoGoodsSimple(mCh, GOOD_GUNPOWDER);
		ref rCannon; makeref(rCannon,Cannon[GetCaracterShipCannonsType(mCh)]);
		if(CheckAttribute(rCannon,"gunpowder")) fPwdr = sti(rCannon.gunpowder);
		if( pwdrQty < sti( GetCannonArcCurQty(mCh, 0)) * fPwdr || pwdrQty < sti(GetCannonArcCurQty(mCh, 2)) * fPwdr )
		{
			if(mCh.Ship.Cannons.Type != CANNON_TYPE_NONECANNON)
			{
				Log_SetStringToLog(TranslateString("","Captain, we're out of gunpowder!"));
			}
		}
	}// TIH <-- mod toggle

	Sharks.execute = SEA_EXECUTE;
	Sharks.realize = SEA_REALIZE;
	Sharks.executeModels = 75;
	Sharks.realizeModels = 75;
	Sharks.executeParticles = 78;
	Sharks.realizeParticles = 100001;

	CreateEntity(&Sharks, "Sharks");				ReloadProgressUpdate();

	PeopleOnShip.isNight = Whr_IsNight();
	chrWaitReloadLocator = "";//MAXIMUS
}

void Sea_LandLoad()
{
	bSeaReloadStarted = true;
	PauseAllSounds();
	ResetSoundScheme();

	if (bSeaActive == false) return;
	if (bCanEnterToLand == true)
	{
		LayerFreeze("realize", false);
		LayerFreeze("execute", false);

// KK -->
		if (bDeckEnter)
		{
			AnchorDrop();
			return;
		}
// <-- KK

		// added after build 11 by KAM -->
		ref tempMainChar = GetMainCharacter();
		tempMainChar.ShipBerthing.DoInvoice = true;
		// <-- added after build 11 by KAM

// Maximus & PB: Lower sails and play sound when anchoring -->
		if(makeint(Characters[GetMainCharacterIndex()].LastSailState)!=0)
		{SendMessage(&AISea, "laf", AI_MESSAGE_SHIP_SET_SAIL_STATE, tempMainChar, 0.0);}

		PlaySound("anchor"); // NK
		if(VISIT_DECK==1) PostEvent("LAi_deck", 3000);
		else PostEvent("LAi_anchor", 3000);
	}
}

// KK -->
void Sea_ImmediateLandLoad()
{
	bSeaReloadStarted = true;
	PauseAllSounds();
	ResetSoundScheme();

	if (bSeaActive == false) return;
	if (bCanEnterToLand == true)
	{
		SeaCameras_Switch();
		SeaCameras_Switch();

		LayerFreeze("realize", false);
		LayerFreeze("execute", false);

		// added after build 11 by KAM -->
		ref tempMainChar = GetMainCharacter();
		tempMainChar.ShipBerthing.DoInvoice = true;
		// <-- added after build 11 by KAM

// Maximus & PB: Lower sails and play sound when anchoring -->
		if(makeint(Characters[GetMainCharacterIndex()].LastSailState)!=0)
		{SendMessage(&AISea, "laf", AI_MESSAGE_SHIP_SET_SAIL_STATE, tempMainChar, 0.0);}

		PlaySound("anchor"); // NK
		PostEvent("LAi_anchor", 3000);
	}
}
// <-- KK

#event_handler("LAi_deck", "GoToDeck");
void GoToDeck()
{
	Sea_DeckStartNow(GetCharacterShipQDeck(GetMainCharacter()));
}

#event_handler("LAi_anchor", "AnchorDrop");
void AnchorDrop()
{
	Reload(arIslandReload, sIslandLocator, sIslandID);
	bSeaActive = false;//MAXIMUS: used for new "Mutiny" [just to be sure]
}
// Maximus & PB: Lower sails and play sound when anchoring <--

// [abordage MOD] -->
#event_handler("Ship_BranderDetonate", "Lai_ToBlowUp");
void Lai_ToBlowUp()
{
	aref blowingLoser = GetEventData();
	Ship_Detonate(blowingLoser, true, true);
}
// [abordage MOD] <--

void Sea_MapStartFade()
{
	DelEventHandler("FaderEvent_StartFade", "Sea_MapStartFade");
	DeleteSeaEnvironment();
}

void Sea_MapEndFade()
{
	DelEventHandler("FaderEvent_EndFade", "Sea_MapEndFade");

	wdmCreateMap(SeaMapLoadX, SeaMapLoadZ, SeaMapLoadAY);

	// --> Hoist the flag code fix by Mad-h, fixed and moved to sea.c by ccc dec05
	ref rPlayer = GetMainCharacter();

// KK -->
	int cc;

	if(CheckAttribute(rPlayer,"franciarel"))	// checks if you just hoisted Jolly Roger
	{
		rPlayer.nation = rPlayer.orgnation;

		for(cc = 1; cc < 4; cc++)
		{
			int compIdx = GetCompanionIndex(GetMainCharacter(), cc); // added by MAXIMUS [checking, if you have a companions]
			if(compIdx < 0) continue; // added by MAXIMUS [checking, if you have a companions]
			if(GetRemovable(GetCharacter(GetCompanionIndex(rPlayer, cc))))
			{ 
				Characters[GetCompanionIndex(rPlayer, cc)].nation = rPlayer.nation;
			}
		} // NK so comps' nations update

		if (ENABLE_FLAGS == 0) {
			SetRMRelation(rPlayer, FRANCE, sti(rPlayer.franciarel));
			SetRMRelation(rPlayer, SPAIN, sti(rPlayer.spanyolrel));
			SetRMRelation(rPlayer, PORTUGAL, sti(rPlayer.portugalrel));
			SetRMRelation(rPlayer, HOLLAND, sti(rPlayer.hollandrel));
			SetRMRelation(rPlayer, ENGLAND, sti(rPlayer.angolrel));
			SetRMRelation(rPlayer, PIRATE, sti(rPlayer.pirarel));

			UpdateRelations();
		} else {
			SetActualRMRelation(FRANCE, sti(rPlayer.franciarel));
			SetActualRMRelation(SPAIN, sti(rPlayer.spanyolrel));
			SetActualRMRelation(PORTUGAL, sti(rPlayer.portugalrel));
			SetActualRMRelation(HOLLAND, sti(rPlayer.hollandrel));
			SetActualRMRelation(ENGLAND, sti(rPlayer.angolrel));
			SetActualRMRelation(PIRATE, sti(rPlayer.pirarel));

			HoistFlag(rPlayer.nation);
			SetRelationsForFlag(rPlayer.nation);
		}

		Trace("relations reset ");

		DeleteAttribute(rPlayer,"franciarel");	// so that rel resetting runs only once after flaghoisting	
		DeleteAttribute(rPlayer,"spanyolrel");
		DeleteAttribute(rPlayer,"portugalrel");
		DeleteAttribute(rPlayer,"hollandrel");
		DeleteAttribute(rPlayer,"angolrel");
		DeleteAttribute(rPlayer,"pirarel");

		rPlayer.orgnation = "traitor" // marker for recognizing feature

		Logit("You hide the Jolly Roger and hoist your former flag again");
	}
// <-- KK
	// <-- Hoist the flag code fix by Mad-h
}

void Sea_MapLoadXZ_AY(float x, float z, float ay)
{
	bSkipSeaLogin = true; // NK fix 05-07-16 to be sure we don't hit the getseatime<3 hack.
	Sea_MapLoad();

	SeaMapLoadX = x;
	SeaMapLoadZ = z;
	SeaMapLoadAY = ay;
}

void Sea_MapLoad()
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	if(GetSeaTime() < 3 && !bSkipSeaLogin) { LogIt(TranslateString("","Wait a sec while I get out the chart, captain!")); PlaySound("interface\knock.wav"); return; } // NK so you must be on sea >= 3 seconds. 05-04-23
	bSeaReloadStarted = true;
	PauseAllSounds();

	ResetSoundScheme();

	SetEventHandler("FaderEvent_StartFade", "Sea_MapStartFade", 0);
	SetEventHandler("FaderEvent_EndFade", "Sea_MapEndFade", 0);

	CreateEntity(&SeaFader, "fader");
	SendMessage(&SeaFader, "lfl", FADER_OUT, 0.7, true);
	SendMessage(&SeaFader, "l", FADER_STARTFRAME);
	SendMessage(&SeaFader, "ls", FADER_PICTURE, FindReloadPicture("sea.tga")); // KK

	bSkipSeaLogin = true;

	ref rPlayer = GetMainCharacter();

	SeaMapLoadX = stf(rPlayer.Ship.Pos.x);
	SeaMapLoadZ = stf(rPlayer.Ship.Pos.z);
	SeaMapLoadAY = stf(rPlayer.Ship.Ang.y);
	//LanguageCloseFile(tmpLangFileID);
	ResetTimeToNormal();//MAXIMUS: removes time-acceleration and sets normal time
}

void Land_MapLoad()
{
	bSeaReloadStarted = true;
	PauseAllSounds();

	ResetSoundScheme();

	SetEventHandler("FaderEvent_StartFade", "Land_MapStartFade", 0);
	SetEventHandler("FaderEvent_EndFade", "Sea_MapEndFade", 0);

	CreateEntity(&SeaFader, "fader");
	SendMessage(&SeaFader, "lfl", FADER_OUT, 0.7, true);
	SendMessage(&SeaFader, "l", FADER_STARTFRAME);
	SendMessage(&SeaFader, "ls", FADER_PICTURE, FindReloadPicture("sea.tga"));

	bSkipSeaLogin = true;

	SeaMapLoadX = stf(characters[GetMainCharacterIndex()].Ship.Pos.x);
	SeaMapLoadZ = stf(characters[GetMainCharacterIndex()].Ship.Pos.z);
	SeaMapLoadAY = stf(characters[GetMainCharacterIndex()].Ship.Ang.y);
}

void Land_MapStartFade()
{
	DelEventHandler("FaderEvent_StartFade", "Land_MapStartFade");
	ref PChar = GetMainCharacter();
	if(CheckAttribute(PChar,"location") && PChar.location!="" && FindLocation(PChar.location)!=-1)
	{
		UnloadLocation(&locations[FindLocation(PChar.location)]);
	}
	ResetTimeToNormal();
}

string	sTaskList[2];

void Sea_FreeTaskList()
{
	ref rMassive;
	makeref(rMassive, sTaskList);
	SetArraySize(rMassive, 2);
}

void Sea_AddGroup2TaskList(string sGroupID)
{
	ref rMassive;
	makeref(rMassive, sTaskList);
	int iSize = GetArraySize(rMassive);
	SetArraySize(rMassive, iSize + 1);
	sTaskList[iSize-2] = sGroupID;
}

void Sea_LoginGroupNow(string sGroupID)
{
	LoginGroupsNow.QuestGroups = "";
	aref arGroups; makearef(arGroups, LoginGroupsNow.QuestGroups);
	string sID = "n" + GetAttributesNum(arGroups);
	arGroups.(sID) = sGroupID;
}


void SeaLogin(ref Login)
{
	Trace("SEA: SeaLogin begin");
	int		i, j, iShipType;
	float	x, y, z, ay;
	ref		rCharacter, rGroup, rEncounter;
	aref	rRawGroup;
	aref	arQCGroups;
	string	sGName;
	int		iNumQCGroups;

	int iRDTSC = RDTSC_B();

	// clear load groups now object
	DeleteAttribute(&LoginGroupsNow, "");

	iStormLockSeconds = 0;
	iNumFantoms = 0;
	bSkipSeaLogin = false;
	bSeaReloadStarted = false;
	bSeaQuestGroupHere = false;
	bIslandLoaded = false;

	fSeaExp = 0.0;
	fSeaExpTimer = 0.0;
	// NK 04-09-21 timeupdate
	if(TIMEUPDATE_BLOCK_LAND)
	{
		AddTimeToCurrent(0, (locTmpTime * TIMESCALAR_LAND)/60);
	}
	locTmpTime = 0.0;
	// NK <--

	Sea_FreeTaskList();
	Encounter_DeleteDeadQuestMapEncounters();

	// weather parameters
	WeatherParams.Tornado = false;
	WeatherParams.Storm = false;
	if (CheckAttribute(&Login,"Storm")) { WeatherParams.Storm = Login.Storm; }
	if (CheckAttribute(&Login,"Tornado")) { WeatherParams.Tornado = Login.Tornado; }
	bStorm = sti(WeatherParams.Storm);
	bTornado = sti(WeatherParams.Tornado);
	if (bStorm)
	{
		iStormLockSeconds = 60;
	}

	// Island
	int iIslandIndex = FindIsland(Login.Island);
	//Trace("Island id = " + Login.Island + ", Island index = " + iIslandIndex);
	string sIslandID = "";
	if (iIslandIndex != -1) { sIslandID = Islands[iIslandIndex].id; }

	// main character
	ref rPlayer = GetMainCharacter();
	rPlayer.Ship.Stopped = false;
	DeleteAttribute(rPlayer,"LastSailState"); // NK 05-04-20 so it doesn't say it during loading
	rPlayer.Ship.POS.Mode = SHIP_SAIL;
	rPlayer.location = sIslandID;

	// clear old fantom relations in our character
	if (CheckAttribute(rPlayer, "Relation"))
	{
		aref	arRelations; makearef(arRelations, rPlayer.Relation);
		int		iNumRelations = GetAttributesNum(arRelations);
		for (i=0; i<iNumRelations; i++)
		{
			aref arRelation = GetAttributeN(arRelations, i);
			string sRName = GetAttributeName(arRelation);
			if (sti(sRName) >= FANTOM_CHARACTERS)
			{
				DeleteAttribute(arRelations, sRName);
				iNumRelations--;
				i--;
			}
		}
	}

	// Quest check
	Event(EVENT_SEA_LOGIN, "");
	if (bSkipSeaLogin) return;

// KK -->
	if (ENABLE_FLAGS == 1)
	{
		int MyFlag = GetCurrentFlag();
		bRecognized = false;
		if (iForceDetectionFalseFlag == 0) {
			if ((frnd() >= GetChanceDetectFalseFlag()) || (MyFlag == PERSONAL_NATION)) {
				MyFlag = GetCurrentFlag();
			} else {
				MyFlag = PERSONAL_NATION;
				bRecognized = true;
				Log_SetStringToLog(TranslateString("", "We are recognized, captain!"));
			}
		}
		if (iForceDetectionFalseFlag == 1)
		{
				MyFlag = PERSONAL_NATION;
				bRecognized = true;
				Log_SetStringToLog(TranslateString("", "We are recognized, captain!"));
		}
		HoistFlag(MyFlag);
		SetRelationsForFlag(MyFlag);
	}

	if (!IsEntity(&SeaFader)) {
		// Sea Fader start
		if (!CheckAttribute(&Login,"ImageName")) Login.ImageName = "sea.tga";
	
		CreateEntity(&SeaFader, "fader");
		SendMessage(&SeaFader, "lfl", FADER_IN, 0.5, true);
		SendMessage(&SeaFader, "ls", FADER_PICTURE0, FindReloadPicture(Login.ImageName));
	}
// <-- KK

	// create all sea modules
	CreateSeaEnvironment();

	// delete our group
	Group_DeleteGroup(PLAYER_GROUP);

	// set commander to group
	Group_SetGroupCommander(PLAYER_GROUP, Characters[GetMainCharacterIndex()].id);

	// set our group position
	Group_SetXZ_AY(PLAYER_GROUP, stf(Login.PlayerGroup.x), stf(Login.PlayerGroup.z), stf(Login.PlayerGroup.ay) );
	//Trace("Set group : " + PLAYER_GROUP + ", x = " + Login.PlayerGroup.x + ", z = " + Login.PlayerGroup.z + ", ay = " + Login.PlayerGroup.ay);

	Sea.MaxSeaHeight = 50.0;

	ReloadProgressUpdate();
	
	float wdmBaseX, wdmBaseZ; // WM base coords for fleets 05-05-02

	// login island if exist
	if (sIslandID != "")
	{
		trace("SEA: sealogin loading island " + sIslandID);
		CreateEntity(&Island, "Island");
		Island.LightingPath = GetLightingPath();

		if (GetTargetPlatform() != "xbox")
		{
			//CreateEntity(&SeaLighter, "lighter");
			SendMessage(&SeaLighter, "ss", "ModelsPath", Islands[iIslandIndex].filespath.models);
			SendMessage(&SeaLighter, "ss", "LightPath", GetLightingPath());
		}

		SendMessage(&Island, "lsss", MSG_ISLAND_LOAD_GEO, "islands", Islands[iIslandIndex].filespath.models, Islands[iIslandIndex].model);
		LayerAddObject(SEA_REALIZE, &Island, 65529);
		LayerAddObject("mast_island_trace", &Island, 1);
		LayerAddObject("sun_trace", &Island, 1);

		CreateEntity(&IslandReflModel, "MODELR");
		string sReflModel = Islands[iIslandIndex].filespath.models + "\\" + Islands[iIslandIndex].refl_model;
		SendMessage(&IslandReflModel, "ls", MSG_MODEL_SET_LIGHT_PATH, GetLightingPath());
		SendMessage(&IslandReflModel, "ls", MSG_MODEL_LOAD_GEO, sReflModel);
		LayerAddObject("sea_reflection", &IslandReflModel, -1);
		SendMessage(SeaLighter, "ssi", "AddModel", Islands[iIslandIndex].refl_model, &IslandReflModel);

		bIslandLoaded = true;

		SendMessage(&SeaLocatorShow, "a", &Islands[iIslandIndex]);
		Fort_Login(iIslandIndex);

		Sea.MaxSeaHeight = 3.0;
		// WM base coords for fleets 05-05-02 -->
		// 05-05-03 get correct wdm name for island.
		string wdmisland = wdmGetIslandNameFromID(sIslandID);
		if(wdmisland != "" && CheckAttribute(worldMap,".islands."+wdmisland))
		{
			wdmBaseX = MakeFloat(worldMap.islands.(wdmisland).position.rx);
			wdmBaseZ = MakeFloat(worldMap.islands.(wdmisland).position.rz);
		}
		else { wdmBaseX = makefloat(worldMap.playerShipX); wdmBaseZ = makefloat(worldMap.playerShipZ); }
	}
	else { wdmBaseX = makefloat(worldMap.playerShipX); wdmBaseZ = makefloat(worldMap.playerShipZ); } // WM base coords for fleets 05-05-02 <--
	AISea.Island = sIslandID;

	// clear some of group attributes
	for (i=0; i<MAX_SHIP_GROUPS; i++)
	{
		rGroup = Group_GetGroupByIndex(i);
		if (CheckAttribute(rGroup, "AlreadyLoaded")) { DeleteAttribute(rGroup, "AlreadyLoaded"); }
	}

	ReloadProgressUpdate();

	// from coast check (move / stop)
	bFromCoast = false;
	if (CheckAttribute(&Login, "FromCoast")) { bFromCoast = sti(Login.FromCoast); }

	// login main player and his friends
	int iMainCharacter,iCompanionIndex;
	iMainCharacter = GetMainCharacterIndex();

	rPlayer.SeaAI.Group.Name = PLAYER_GROUP;
	rPlayer.Ship.Type = Characters[iMainCharacter].Ship.Type;
	rPlayer.Ship.Stopped = false;
	Ship_Add2Sea(iMainCharacter, bFromCoast, "");
	trace("SEA: added pchar to sea");
	Group_AddCharacter(PLAYER_GROUP, Characters[iMainCharacter].id);
	for (i=1; i<COMPANION_MAX; i++)
	{
		iCompanionIndex = GetCompanionIndex(&Characters[iMainCharacter],i);
		if (iCompanionIndex == -1) { continue; }
		Characters[iCompanionIndex].SeaAI.Group.Name = PLAYER_GROUP;
		Ship_Add2Sea(iCompanionIndex, bFromCoast, "");

		// add companion to player group
		Group_AddCharacter(PLAYER_GROUP, Characters[iCompanionIndex].id);
	}
	//trace("added comps to sea");

	// set ship for sea camera
	SeaCameras_SetShipForSeaCamera(&rPlayer);

	// login encounters
	object oResult;
	int iFantomIndex;

	// login quest group if island exist 
	ReloadProgressUpdate();
	if (AUTOCREATE_CR == 1 && sIslandID != "") { SetCoastTraffic(sIslandID); }		// ccc CR
	trace("SEA: Did CRs");
	if (sIslandID != "")
	{
		for (i=0; i<MAX_SHIP_GROUPS; i++)
		{
			rGroup = Group_GetGroupByIndex(i);
			if (!CheckAttribute(rGroup,"AlreadyLoaded")) { DeleteAttribute(rGroup,"AlreadyLoaded");	} // NK: HUH!?

			if (!CheckAttribute(rGroup, "id")) { continue; }
			if (!CheckAttribute(rGroup, "location")) { continue; }
			if (rGroup.location != sIslandID) { continue; }

			Sea_LoginGroup(rGroup.id);
		}
	}
	trace("SEA: Did any groups");

	// login quest groups to sea
	if (CheckAttribute(&Login, "QuestGroups"))
	{
		arQCGroups; makearef(arQCGroups, Login.QuestGroups);
		iNumQCGroups = GetAttributesNum(arQCGroups);
		for (i=0; i<iNumQCGroups; i++)
		{
			Sea_LoginGroup(GetAttributeValue(GetAttributeN(arQCGroups, i)));
		}
	}

	ReloadProgressUpdate();

	// login quest groups to sea from LoginGroupsNow object
	if (CheckAttribute(&LoginGroupsNow, "QuestGroups"))
	{
		makearef(arQCGroups, LoginGroupsNow.QuestGroups);
		iNumQCGroups = GetAttributesNum(arQCGroups);
		for (i=0; i<iNumQCGroups; i++)
		{
			Sea_LoginGroup(GetAttributeValue(GetAttributeN(arQCGroups, i)));
		}
	}

	ReloadProgressUpdate();

	// login fantom groups
	aref arEncounters;
	makearef(arEncounters,Login.Encounters);
	int iNumGroups = GetAttributesNum(arEncounters);

	for (i=0; i<iNumGroups; i++)
	{
		rRawGroup = GetAttributeN(arEncounters, i);
		rEncounter = GetMapEncounterRef(sti(rRawGroup.type));
		sGName = rEncounter.GroupName;

		x = stf(rRawGroup.x);
		z = stf(rRawGroup.z);
		ay = stf(rRawGroup.ay);

		ReloadProgressUpdate();

		// check for Quest fantom
		if (CheckAttribute(rEncounter, "qID"))
		{
			Trace("SEA: Login quest encounter " + rEncounter.qID);
			Group_SetAddressNone(rEncounter.qID);
			Group_SetXZ_AY(rEncounter.qID, x, z, ay);
			Sea_LoginGroup(rEncounter.qID);

			continue;
		}

		// NK disable this, it kills encounters if there are local ships -- if (bSeaQuestGroupHere) { continue; }
		Sea_AddGroup2TaskList(sGName);

		rGroup = Group_GetGroupByIndex(Group_CreateGroup(sGName));
		Group_SetXZ_AY(sGName, x, z, ay);
		Group_SetType(sGName, rEncounter.Type);
		Group_DeleteAtEnd(sGName);

		// copy task attributes from map encounter to fantom group
		if (CheckAttribute(rEncounter, "Task"))							{ rGroup.Task = rEncounter.Task; }
		if (CheckAttribute(rEncounter, "Task.Target"))					{ rGroup.Task.Target = rEncounter.Task.Target; }
		if (CheckAttribute(rEncounter, "Task.Pos"))
		{
			rGroup.Task.Target.Pos.x = rEncounter.Task.Pos.x;
			rGroup.Task.Target.Pos.z = rEncounter.Task.Pos.z;
		}
		if (CheckAttribute(rEncounter, "Lock") && sti(rEncounter.Lock)) { Group_LockTask(sGName); }

		int iEncounterType = sti(rEncounter.RealEncounterType);
		int iNumShips = Fantom_GenerateEncounter(sGName, &oResult, iEncounterType, sti(rEncounter.Nation)); // NK

		Trace("SEA: Set group : " + sGName + ", x = " + x + ", z = " + z);

		// load ship to sea
		if (iNumShips) {
			for (j=0; j<iNumShips; j++)
			{
				iFantomIndex = FANTOM_CHARACTERS + iNumFantoms - iNumShips + j;
				ref rFantom = &Characters[iFantomIndex];

				rFantom.id = "fenc_" + iFantomIndex;
				rFantom.isFantom = true; // TIH used to easily tell a generated shipchar from a stored shipchar Aug27'06

				// set commander to group
				if (j==0) { Group_SetGroupCommander(sGName, Characters[iFantomIndex].id); }

				// set random character and ship names, face id
				rFantom.sex = "man";
				rFantom.Nation = rEncounter.Nation;

				SetRandomNameToCharacter(rFantom);
				SetRandomNameToShip(rFantom);
				SetRandomFaceToCharacter(rFantom);

// KK -->
				rFantom.location = "none";
				rFantom.location.group = "";
				rFantom.location.locator = "";
// <-- KK

				//Fantom_SetRandomSkills(rFantom, rFantom.fantomtype); // NK
// added by MAXIMUS -->
				Fantom_SetRandomModel(rFantom, rFantom.fantomtype);
// ! DO NOT COMMENT THIS OUT ! IT IS REQUIRED ! Aug24'06 // commented out by MAXIMUS 28.07.2006
				switch(Rand(7))
				{
					case 0: rFantom.quest.officertype = OFFIC_TYPE_BOATSWAIN; break;
					case 1: rFantom.quest.officertype = OFFIC_TYPE_CANNONEER; break;
					case 2: rFantom.quest.officertype = OFFIC_TYPE_QMASTER; break;
					case 3: rFantom.quest.officertype = OFFIC_TYPE_NAVIGATOR; break;
					case 4: rFantom.quest.officertype = OFFIC_TYPE_FIRSTMATE; break;
					case 5: rFantom.quest.officertype = OFFIC_TYPE_CARPENTER; break;
					case 6: rFantom.quest.officertype = OFFIC_TYPE_DOCTOR; break;
					case 7: rFantom.quest.officertype = OFFIC_TYPE_ABORDAGE; break;
				}
				LAi_Create_Officer(rand(8), &rFantom);
				rFantom.quest.officerprice = makeint((sti(rPlayer.rank) * 2 + 10)*100) - 330 + rand(40)*15 + rand(10);
				LAi_NPC_Equip(rFantom, sti(rFantom.rank), true, 0.5);
// added by MAXIMUS <--
//				LAi_Create_Officer(0, rFantom); // NK
				Fantom_SetRandomMoney(rFantom, rFantom.fantomtype);
				Ship_SetFantomData(rFantom); // KK
				Fantom_SetCannons(rFantom, rFantom.fantomtype);
				Fantom_SetSails(rFantom, rFantom.fantomtype);

				rFantom.SeaAI.Group.Name = sGName;
// START MOD Code by Stone-D : 01/08/2003
// Stone-D : This cunting lot was nuking my skill calculations
//				rFantom.Experience = 0;
//				rFantom.Skill.FreeSkill = 0;

				rFantom.Features.GeraldSails = false;
				if (CheckAttribute(rEncounter, "GeraldSails")) { rFantom.Features.GeraldSails = sti(rEncounter.GeraldSails); }

//				int iSClass = GetCharacterShipClass(rFantom);

//				rFantom.Rank = MakeInt(sti(rPlayer.rank) + rand(4) - 2 + (7 - iSClass) / 2);
//				if (sti(rFantom.Rank) < 1) { rFantom.Rank = 1; }

				// restore fantom HP
//				LAi_SetHP(rFantom, LAI_DEFAULT_HP_MAX, 50.0 + stf(rFantom.rank) * 3.0);
//				LAi_SetCurHPMax(rFantom);
// END MOD Code by Stone-D : 01/08/2003

// KK -->
				if (CheckAttribute(rFantom, "after_1st_sailto")) DeleteAttribute(rFantom, "after_1st_sailto");
				RestoreCharacter(rFantom);
// <-- KK

				// add fantom
				Group_AddCharacter(sGName, rFantom.id);

				// add to sea
				Ship_Add2Sea(iFantomIndex, 0, rFantom.fantomtype);
			}
		}
	}
	trace("SEA: added ships");

	ReloadProgressUpdate();

	// set tasks 2 all groups
	int c; //NK bugfix 5-1
	for (i=0; i<GetArraySize(&sTaskList)-2; i++)
	{
		string sGroupID = sTaskList[i];

		rGroup = Group_GetGroupByID(sGroupID);

		// set task
		switch (sti(rGroup.Task))
		{
			case AITASK_RUNAWAY:
				Group_SetTaskRunAway(sGroupID);
			break;
			case AITASK_ATTACK:
				Group_SetTaskAttack(sGroupID, rGroup.Task.Target);
			break;
			case AITASK_MOVE:
				if (CheckAttribute(rGroup, "Task.Target.Pos"))
				{
					Group_SetTaskMove(sGroupID, stf(rGroup.Task.Target.Pos.x), stf(rGroup.Task.Target.Pos.z));
				}
				else
				{
					x = 10000.0 * sin(stf(rGroup.Pos.ay));
					z = 10000.0 * cos(stf(rGroup.Pos.ay));
					Group_SetTaskMove(sGroupID, x, z);
				}
			break;
		}

		rCharacter = Group_GetGroupCommanderR(rGroup);
		int iRelation = GetRelation(GetMainCharacterIndex(), sti(rCharacter.index));

		// set relations to all characters in this group
		c = 0; // NK bugfix, they used to use i (!!!) here.
		while (true)
		{
			int iCharacterIndex = Group_GetCharacterIndexR(rGroup, c);
			c++; // KK
			if (iCharacterIndex < 0) { break; }
			SetCharacterRelationBoth(iCharacterIndex, GetMainCharacterIndex(), iRelation);
		}
	}
	trace("SEA: Set tasks");

	// update AISea
	AISea.isDone = "";

	InitBattleInterface();							ReloadProgressUpdate();
	StartBattleInterface();							ReloadProgressUpdate();
	RefreshBattleInterface();						ReloadProgressUpdate();

	CreateEntity(&Seafoam,"Seafoam");				ReloadProgressUpdate();
	LayerAddObject(SEA_EXECUTE, &Seafoam, -1);
	LayerAddObject(SEA_REALIZE, &Seafoam, -1);
	if (Whr_IsStorm()) { Seafoam.storm = "true"; }

	/*CreateEntity(&SeaOperator, "SEA_OPERATOR");
	LayerAddObject(SEA_EXECUTE, &SeaOperator, -1);
	LayerAddObject(SEA_REALIZE, &SeaOperator, 3);*/

	SendMessage(&Telescope, "leee", MSG_TELESCOPE_INIT_ARRAYS, &Nations, &ShipsTypes, &Goods);

	PostEvent(SHIP_CHECK_RELOAD_ENABLE, 100);

	SetSchemeForSea();								ReloadProgressUpdate();

	iRDTSC = RDTSC_E(iRDTSC);
	//Trace("SeaLogin RDTSC = " + iRDTSC);
	//Trace("iNumShips = " + iNumShips);

	PostEvent("Sea_FirstInit", 100);
	Trace("SEA: SeaLogin end");
}

void Sea_LoginGroup(string sGroupID)
{
	if (!isEntity(&Sea)) { Trace("SEA: Error: Sea_LoginGroup sGroupID = " + sGroupID + ", but Sea is not active!"); return; }

	if (Group_FindGroup(sGroupID) < 0)
	{
		Trace("SEA: Not find group '" + sGroupID + "' in groups massive, but login try spotted");
		return;
	}

	ref rGroup = Group_GetGroupByID(sGroupID);
	if (!CheckAttribute(rGroup, "Quest"))			{ Trace("SEA: Error: Sea_LoginGroup sGroupID = " + sGroupID + ", but group doesn't contain any quest ships!"); return; }
	if (CheckAttribute(rGroup, "AlreadyLoaded"))	{ Trace("SEA: Error: Group sGroupID = " + sGroupID + ", already loaded... check for duplicate group login"); return; }

	aref arQuestShips; makearef(arQuestShips, rGroup.Quest);

	int iNumShips = GetAttributesNum(arQuestShips);
	if (iNumShips == 0) { return; }

	float x, z, ay; x = 0.0; z = 0.0; ay = 0.0;

	// find group position
	if (CheckAttribute(rGroup, "location") && CheckAttribute(rGroup, "location.group") && rGroup.location != "none")
	{
		string sLocationGroup = rGroup.location.group;
		string sLocationLocator = rGroup.location.locator;

		ref rIsland = GetIslandByID(rGroup.location);

		string sTst = sLocationGroup + "." + sLocationLocator + ".x";
		if (CheckAttribute(rIsland, sTst))
		{
			x = stf(rIsland.(sLocationGroup).(sLocationLocator).x);
			z = stf(rIsland.(sLocationGroup).(sLocationLocator).z);
			ay = stf(rIsland.(sLocationGroup).(sLocationLocator).ay);
		}
		else
		{
			x = 0.0; z = 0.0; ay = 0.0;
			Trace("SEA: Error: Group " + sGroupID + ", Island " + rGroup.location);
			Trace("SEA: Error: Find locators Group " + sLocationGroup + ", Locator " + sLocationLocator);
		}
	}
	else
	{
		if (CheckAttribute(rGroup, "Pos"))
		{
			x = stf(rGroup.Pos.x);
			z = stf(rGroup.Pos.z);
			ay = stf(rGroup.Pos.ay);
		}
		else
		{
			Trace("SEA: Error: Sea_LoginGroup sGroupID = " + sGroupID + ", I can't find any locators or position for this group, maybe you can check this???");
		}
	}

	// set group position
	Group_SetXZ_AY(sGroupID, x, z, ay);

	// set group commander
	ref rGroupCommander = Group_GetGroupCommander(sGroupID);
	// update commander for SEA AI
	Group_SetGroupCommander(sGroupID, rGroupCommander.id);

	// set location near
	if (CheckAttribute(rGroup, "location.neargroup"))
	{
		Group_SetPursuitGroup(sGroupID, rGroup.location.neargroup);
	}

	// load group ships
	int iNumDeadCharacters = 0;
	for (int i=0; i<iNumShips; i++)
	{
		if(iNumShips >= MAX_SHIPS_ON_SEA) 
		{
			Trace("SEA: Sea_LoginGroup iNumShips over MAX: "+ iNumShips);
			return; // NK bugfix
		}
		aref arShip;

		arShip = GetAttributeN(arQuestShips, i);
		ref rCharacter = GetCharacter(GetCharacterIndex(GetAttributeValue(arShip)));
		int iCharacterIndex = sti(rCharacter.index);

		if (CharacterIsDead(rCharacter)) { iNumDeadCharacters++; continue; }
		if (CheckAttribute(rCharacter, "surrendered") == true && sti(rCharacter.surrendered) == true) { iNumDeadCharacters++; continue; } // KK
		if (iCharacterIndex == GetMainCharacterIndex()) { Trace("SEA: Error: You assigned main character to quest group... This is a error!"); continue; }

		rCharacter.SeaAI.Group.Name = sGroupID;

		Ship_Add2Sea(sti(rCharacter.index), bFromCoast, "");

		ReloadProgressUpdate();
	}

	rGroup.AlreadyLoaded = "";

	if (iNumDeadCharacters == iNumShips)
	{
		Trace("SEA: Warn: I am automatically deleting group '" + sGroupID +"', because it's empty");
		Group_DeleteAtEnd(sGroupID);
		//Group_DeleteGroup(sGroupID);
		return;
	}

	bSeaQuestGroupHere = true;

	Sea_AddGroup2TaskList(sGroupID);
}

void Sea_FirstInit()
{
	RefreshBattleInterface();

	// PB: First Contact Quest -->
	ref pchar = GetMainCharacter();
	if(CheckQuestAttribute("Firstcontact", "start_davyencounter"))
	{
	//	SetNextWeather("Day Storm");
		Sea_DeckStartNow(GetCharacterShipQDeck(pchar));
	}
	// PB: First Contact Quest <--
}

void Sea_Reload()
{
	DelEventHandler("Sea_Reload", "Sea_Reload");

	object Login;
	Login.PlayerGroup.ay = 0.0;
	Login.PlayerGroup.x = 0.0; 
	Login.PlayerGroup.y = 0.0;
	Login.PlayerGroup.z = 0.0;
	Login.Island = Characters[0].location;

	ref rPlayer = GetMainCharacter();							// ccc Survival, NK 05-04-16 bugfix didn't have = GetMainCharacter();
//TIH -->
	if (CheckAttribute(rPlayer,"lifeboatlaunch")) {
		int testIsleIdx = FindIsland(Login.Island);
		if (testIsleIdx != -1) {
			Ship_SetSailState(GetMainCharacterIndex(), 0.0);//TIH - lowers the sails
			Login.FromCoast = true; //TIH - makes the lifeboat not run into the islands at full speed!
		}
		DeleteAttribute(rPlayer,"lifeboatlaunch");
	}
//TIH <--
	SeaLogin(&Login);
}

void Sea_ReloadStart()
{
	if (!bSeaActive) { return; }
	DeleteSeaEnvironment();
	SetEventHandler("Sea_Reload", "Sea_Reload", 0);
	PostEvent("Sea_Reload", 1);
}
// ccc CR ->
void SetCoastTraffic(string islandstr)
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	// no longer needed if(islandstr == "KhaelRoa") return; // NK tempfix 04-09-09
	if(GetCharacterIndex("Cr" + islandstr+"1") == -1) return; //if no CR chars, return
	if(CheckAttribute(Islands[FindIsland(islandstr)],"skipCR")) { if(sti(Islands[FindIsland(islandstr)].skipCR)) return; } // NK 04-09-14
	ref Pchar, CurIsland, cr;
	string chrstr;
	int crnation;
	ref crgchar; // NK
	string sFantomType;
	Pchar = GetMainCharacter();
	int grpidx;
	int i = 1 ;
	int j;
	CurIsland = GetIslandByIndex(FindIsland(islandstr));	
	chrstr = "Cr" + islandstr;

	for( j = 1; j <7 ; j++)	//Loop to reset relation BEFORE groupcreation
	{
		if(GetCharacterIndex(chrstr + j)==-1) continue;//MAXIMUS
		cr = CharacterFromID(chrstr + j);
		SetCharacterRelationBoth(sti(cr.index), GetMainCharacterIndex(), RELATION_NEUTRAL);
	}

	while(i < 6-(REDUCE_CR*2 + (sti(CurIsland.smuggling_nation) == PIRATE)*2))		// 1st loop to create 3 groups for 2 ships each, NK to reduce at pirate islands
	{
		string crg = chrstr + i;
		crgchar = CharacterFromID(crg); // NK 04-09-09
		grpidx = Group_FindGroup(crg); // NK bugfix to not delete not-existing group 05-05-02
		if(grpidx != -1) Group_DeleteGroup(crg);				//to clear for SeaLogin
		string pos = "Quest_Ship_"  + (1 + rand(16));			//random position

		Group_CreateGroup(crg);
		Group_SetGroupCommander(crg, crg);
		Group_SetAddress(crg, islandstr, "Quest_Ships", pos);
		if (frnd() < COASTRAIDER_CHANCE)
		{
			// NK 04-08-27 -->
			if(frnd() < NAVYRAIDER_CHANCE)
			{
				crnation = FindEnemyNation2Nation(sti(CurIsland.smuggling_nation));
				if(crnation != PIRATE) sFantomType = "war"; //have to check, because PIRATE is a nation
				else sFantomType = "pirate";
			}
			else
			{
				crnation= PIRATE;
				sFantomType = "pirate";
			}
		}
		else
		{
			// NK 04-09-09 add coastguard and other trade nation cases
			if(frnd() < COASTGUARD_CHANCE)
			{
				sFantomType = "war"; //NK now that PRS3 uses Fantom_GetShip call, must also choose whether trade or war
				crnation =  sti(CurIsland.smuggling_nation);
			}
			else
			{
				sFantomType = "trade";
				crnation = FindFriendlyNation2Nation(sti(CurIsland.smuggling_nation));
				if(frnd() < TRADE_OTHERNATIONCHANCE && crnation != -1)
				{
					//nothing
				}
				else { crnation = sti(CurIsland.smuggling_nation); }
				if (GetRMRelationType(GetRMRelation(GetMainCharacter(),crnation)) == RELATION_ENEMY) // NK change to use RM
				{
					Group_SetTaskRunAway(crg);
					Group_LockTask(crg);
				}
				else
				{
					Group_SetTaskMove(crg, 10000.0, 10000.0);
				}
			}
			// NK 04-09-09 <--
				
			// NK 04-08-27 <--
			// crg is string, not object - crg.nation = crnation;						//nation for group
		}

		for( j = 0; j <2 ; j++)	// 2nd loop to create 2 ships for each group
		{
			cr = CharacterFromID(chrstr + (i+j));
			//trace(".");
			//string trstr = "SetCoastTraffic: Char " + cr.id + " of type " + sFantomType + " and nation " + GetNationNameByType(sti(cr.nation));
			// NK to reuse existing if within a week 04-09-09
			bool bDead = CharacterIsDead(cr); // KK
			if (sti(cr.nation) == NEUTRAL_NATION) bDead = true; // KK
			//if(bDead) trstr += " is dead";
			// KK if(bDead) SetCharacterShipLocation(cr, "");
			bool bgennew = bDead && frnd() < DEAD_GENNEW_CR;
			//if(bgennew) trstr += " and will be regen'd from dead";
			if(!bgennew)
			{
				//trstr += " and we'll check to see if we regen";
				bgennew = true;
				if(CheckAttribute(cr, "crmonth"))
				{
					if(cr.crmonth == environment.date.month)
					{
						if(CheckAttribute(cr, "crday"))
						{
							//yes I know this will not properly handle ends of months, but I don't want to use GetPastTime() because it's too detailed.
							//trstr += "(dates are m" + cr.crmonth + " d" + cr.crday + ")";
							if(sti(environment.date.day) < sti(cr.crday) + CR_PERSIST) { bgennew = false;}
						}
					}
				}
			}
			//if(bgennew) trstr += ": yes.";
			//else trstr += ": no.";
			//trace(trstr);
			//trstr = "";
			int crship;
			if(GetCharacterShipType(cr) == SHIP_NOTUSED && !bDead) bgennew = true;
			if(bgennew)
			{
				cr.crmonth = environment.date.month;
				cr.crday = environment.date.day;
				if(crnation == PIRATE) sFantomType = "pirate"; // NK 04-09-12 because for QC pirates are coastguard!
				//trstr = "New dates!m" + cr.crmonth + " d" + cr.crday + ".";
				// NK <--
				cr.nation	= crnation;						//nation for character
				SetRandomNameToCharacter(cr);

// KK -->
				cr.location = "none";
				cr.location.group = "";
				cr.location.locator = "";
// <-- KK

				cr.quest.officertype = CaptainTypeFromFantomType(sFantomType); // NK 04-08-27
				cr.FantomType = sFantomType;

				// NK 04-09-09 move this till after find shiptype LAi_Create_Officer(0, cr);
				//cr.rank = makeint(Pchar.rank) + Rand(5);			//sets NEW rank! // NK, disabled, leads to weird XP bug...
				
				// PRS3 now back to using Fantom_GetShipType, should be fast enough now.
				/*int skip = -10 + sti(Pchar.rank) + GetDifficulty()*2;
				if(skip > 30) skip = 30;

				crship = skip + Rand(70 + GetDifficulty()*5) + Rand(70 + GetDifficulty()*5);		//select shiptype
				if (crship>150) crship = 162 + Rand(30);
				if(crship < 0) crship = 0;
				while(true)
				{
					if(crship < SHIP_TYPES_QUANTITY)
					{
						if(sti(ShipsTypes[crship].CanEncounter) && ShipsTypes[crship].id != "BlackPearl")
						{
							if(crnation != PIRATE) { break; }
							if(sti(ShipsTypes[crship].class) >= MAXPIRATECLASS) { break; }
						}
					}
					crship = skip + Rand(70 + GetDifficulty()*5) + Rand(70 + GetDifficulty()*5);		//select shiptype
					if (crship>150) crship = 162 + Rand(30);
					if(crship < 0) crship = 0;
				}*/
				/*int crship = makeint(cr.rank)*10 + 20 -Rand(30) ;		//select shiptype
				if (crship>167) crship = makeint(170+Rand(15) );*/

				// PRS3 new get ship call
				int minclass = MIN_CLASS;
				//scale minclass between 7 and CR_MAX_MINCLASS based on PChar level
				if(GetLevel(&Pchar) < (MIN_CLASS-CR_MAX_MINCLASS)*CR_MINCLASS_PERLEVEL) minclass = (MIN_CLASS - makeint(makefloat(GetLevel(&Pchar)) / CR_MINCLASS_PERLEVEL));
				int maxclass = MAX_CLASS;

				switch(sFantomType)
				{
					case "pirate": maxclass = CR_MAXPIRATECLASS; break;
					case "trade": maxclass = MAXMERCHANTCLASS; break;
					case "war": if(crnation == sti(CurIsland.smuggling_nation)) { maxclass = MAXCOASTGUARDCLASS; } break;
				}
				// cap if GetShipCap()
				if(GetShipCap() && maxclass < GetCharacterShipClass(Pchar) - CR_CLASS_ABOVE_PCHAR) maxclass = GetCharacterShipClass(Pchar) - CR_CLASS_ABOVE_PCHAR;
				if(GetShipCap() && maxclass < (MIN_CLASS+1)-GetLevel(Pchar) - CR_CLASS_ABOVE_PCHAR) maxclass = (MIN_CLASS+1) - GetLevel(Pchar) - CR_CLASS_ABOVE_PCHAR;
				if(maxclass < MAX_CLASS) maxclass = MAX_CLASS;
				//trstr += " Maxclass " + maxclass + ", minclass " + minclass;
				crship = Force_GetShipType(maxclass, minclass, sFantomType, crnation);
				//trstr += ". Ship ID " + GetShipID(crship);
				Ship_CreateForCharacter(cr, crship, "Coaster");
				LAi_Create_Officer(0, cr);
				// NK PRS3 getshiptype <--

				 //equip ship
				Ship_SetFantomData(cr);
				Fantom_SetCannons(cr, sFantomType);
				Fantom_SetSails(cr, sFantomType);
				Fantom_ClearCargo(cr); // TIH clear out prior slot cargo
				Fantom_SetBalls(cr, sFantomType);
				Fantom_SetGoods(cr, sFantomType);
				Fantom_SetRandomMoney(cr, sFantomType);
				
				SetRandomNameToShip(cr);

				if (crnation== PIRATE)
				{
					cr.perks.list.ShipSpeedUp = true;
					cr.Ship.crew.quantity = GetMaxCrewQuantity(cr);
				}
				// move down - SetCharacterRelationBoth(sti(cr.index), GetMainCharacterIndex(), GetRMRelationType(GetRMRelation(GetMainCharacter(), sti(cr.nation)))); // NK set base relation to avoid gray icon
				//trace(trstr);
			}
			else { crship = GetCharacterShipType(cr); /*trace("resuming old ship type, " + cr.ship.type);*/ }
			if(bDead) // 04-09-15 remove from group if dead. Seems to work OK without, but let's be sure.
			{
				Group_DelCharacter(crg, cr.id);
			}
			else
			{
				//trace(cr.id + " is not dead, adding.");
				// NK 04-09-20 if group cmdr is not same nation
				ref gcmdr = CharacterFromID(crg);
				if(sti(gcmdr.index) != sti(cr.index))
				{
					//trace("crs not same");
					if(CharacterIsDead(gcmdr) || gcmdr.nation != cr.nation) // KK
					{
						//trace("create new grp");
						Group_DelCharacter(crg, cr.id);
						Group_AddCharacter(crg + "_1", cr.id);
						Group_SetGroupCommander(crg + "_1", cr.id);
						Group_SetType(crg + "_1", sFantomType);
						Group_SetAddress(crg + "_1", islandstr, "Quest_Ships", pos);
					}
					else
					{
						//trace("not need create new group")
						Group_ChangeCharacter(crg, cr.id);
						//Group_SetGroupCommander(crg, cr.id);
						bool t2 = Group_GetType(crg) != "war" || sFantomType = "war";
						if(!t2) t2 = Group_GetType(crg) != "pirate" || sFantomType = "pirate";
						if(t2) Group_SetType(crg, sFantomType);
					}
				}
				else
				{
					//trace("crs same");
					Group_ChangeCharacter(crg, cr.id);
					Group_SetGroupCommander(crg, cr.id);
					Group_SetType(crg, sFantomType);
				}
// changed by MAXIMUS -->
				int chkNation;
				if(CheckAttribute(cr,"nation")) chkNation = sti(cr.nation);
				if(chkNation<=6) SetCharacterRelationBoth(sti(cr.index), GetMainCharacterIndex(), GetRMRelationType(GetRMRelation(GetMainCharacter(), sti(cr.nation)))); // NK set base relation to avoid gray icon
				else
				{
					if(chkNation == sti(Pchar.nation))	SetCharacterRelationBoth(sti(cr.index), GetMainCharacterIndex(), RELATION_NEUTRAL);
					else
					{
						if(chkNation==7) SetCharacterRelationBoth(sti(cr.index), GetMainCharacterIndex(), RELATION_NEUTRAL);
						else SetCharacterRelationBoth(sti(cr.index), GetMainCharacterIndex(), RELATION_ENEMY);
					}
				}
// changed by MAXIMUS <--
				//UpdateRelations();
				// NK 04-09-20 <--
				if(sti(cr.Ship.Cannons.Type) != CANNON_TYPE_NONECANNON) cr.ship.cannons.charge.type = GOOD_BALLS; // NK 04-09-20 for ammo bugfix, KNB

				// NK to convert shipname to nice string
				if(LogsToggle) {
					Log_SetStringToLog(XI_ConvertString("BA") + " " + XI_ConvertString(ShipsTypes[crship].sname) + " " + XI_ConvertString("flying") + " " + XI_ConvertString("1"+GetNationDescByType(sti(cr.nation))) + " " + TranslateString("","colors sighted at") + " " +  XI_ConvertString(FindIslandName(islandstr)));  // KK
					Log_SetStringToLog("-");
				}

				if(bgennew)
				{
					// NK fix this to only do correct one. 05-07-11
					switch(islandstr)
					{
						case "QuebradasCostillas": setCharacterShipLocation(cr,"QC_port"); break;
						case "IslaMuelle": setCharacterShipLocation(cr,"Muelle_port"); break;
						case "FalaiseDeFleur": setCharacterShipLocation(cr, "Falaise_de_fleur_port_01"); break;
						setCharacterShipLocation(cr, islandstr + "_port"); // default case
					}
					// NK <--
				}
// KK -->
				if (CheckAttribute(cr, "after_1st_sailto")) DeleteAttribute(cr, "after_1st_sailto");
				RestoreCharacter(cr);
// <-- KK
			}
			// NK <--
		}
		//if (Group_GetCharactersNum(crg) == 0 && Group_FindGroup(crg) != -1) Group_DeleteGroup(crg); // KK

		i=i+2		//doublestep for grouploop
	}
	//LanguageCloseFile(tmpLangFileID);
}
// ccc CR <-
