#define FELLOWTRAVEL_NO			0
#define FELLOWTRAVEL_CAPTIVE	1
#define FELLOWTRAVEL_PASSENGER	2
#define FELLOWTRAVEL_OFFICER	3
#define FELLOWTRAVEL_COMPANION	4

#define EVENT_CHANGE_OFFICERS	"EvntChangeOfficers"
#define EVENT_CHANGE_COMPANIONS	"EvntChangeCompanions"

#define MAX_ITEM_TAKE	256

#define MSGICON_ACTIVE_TIME 10
#define MSGICON_LEVELUP	0
#define MSGICON_LOGBOOK	1
#define MSGICON_GETITEM	2

#define DOUBLE_REP_INCR 0		// LDH 30Sep06

#event_handler("evnt_MsgIconTick","proc_MsgIconTick");

bool GetShipRemovable(ref _refCharacter)
{
	if( CheckAttribute(_refCharacter,"ShipRemovable") && sti(_refCharacter.ShipRemovable)==false ) return false;
	return true;
}

void SetShipRemovable(ref _refCharacter, bool bRemovable)
{
	if(bRemovable) DeleteAttribute(_refCharacter,"ShipRemovable");
	else _refCharacter.ShipRemovable = false;
}

//
bool CharacterIsDead(ref _refCharacter)
{
	if(CheckAttribute(_refCharacter, "corpse")) return true; // NK pers. corpse 05-07-19
	return LAi_IsDead(_refCharacter);
}

bool IsCompanion(ref _refCharacter)
{
	if(!CheckAttribute(_refCharacter,"index")) return false;
	if(sti(_refCharacter.index)==-1) return false;
	int findIdx = sti(_refCharacter.index); // changed by MAXIMUS
	for(int i=0; i<4; i++)
	{
		if(GetCompanionIndex(GetMainCharacter(),i)==findIdx) return true;
	}
	return false;
}

bool IsOfficer(ref _refCharacter)
{
	if(!CheckAttribute(_refCharacter,"index")) return false;
	if(sti(_refCharacter.index)==-1) return false;
	int findIdx = sti(_refCharacter.index); // changed by MAXIMUS
	for(int i=0; i<4; i++)
	{
		if(GetOfficersIndex(GetMainCharacter(),i)==findIdx) return true;
	}
	return false;
}

// Viper - CharSheetEnh Start
bool IsOfficerCompanion(ref _refCharacter)
{
	if(!CheckAttribute(_refCharacter,"index")) return false;
	if(sti(_refCharacter.index)==-1) return false;
	int findIdx = sti(_refCharacter.index); // changed by MAXIMUS
	for(int i=1; i<4; i++)
	{
		for(int j=1; j<4; j++)
		{
			if(GetOfficersIndex(GetCharacter(GetCompanionIndex(GetMainCharacter(),i)),j)==findIdx) return true;
		}
	}
	return false;
}
// Viper - CharSheetEnh End

void SetCharacterRemovable(ref _refCharacter,bool removable)
{
	if(removable) DeleteAttribute(_refCharacter,"NonRemovable");
	else _refCharacter.NonRemovable = true;
}

bool GetRemovable(ref _refCharacter)
{
	if( CheckAttribute(_refCharacter,"NonRemovable") ) return !sti(_refCharacter.NonRemovable);
	return true;
}

// Cargo utilites
//------------------------------------------
int GetCargoLoad(ref _refCharacter)
{
	if(!CheckAttribute(_refCharacter,"Ship.Cargo.Load")) return 0;
	return sti(_refCharacter.Ship.Cargo.Load);
}

int RecalculateCargoLoad(ref _refCharacter)
{
	// NK 04-16 temp bugfix - if(!CheckAttribute(_refCharacter,"Ship.Cargo.Load")) return 0;
	if(!CheckAttribute(_refCharacter,"Ship")) return 0; // NK ditto; we return 0 _only_ if _ship_ doesn't exist; we continue if ship does but cargo doesn't
	int loadSpace = 0;
	for(int i=0; i<GOODS_QUANTITY; i++)
	{
		loadSpace = loadSpace + GetGoodWeightByType(i,GetCargoGoods(_refCharacter,i));
	}
	_refCharacter.Ship.Cargo.Load = loadSpace;
	return loadSpace;
}

int GetCargoFreeSpace(ref _refCharacter)
{
	// TIH 7-7-06 temp bugfix - if(!CheckAttribute(_refCharacter,"Ship.Cargo.Load")) return 0;
	int freeSpace = GetCargoMaxSpace(&_refCharacter) - GetCargoLoad(_refCharacter);
	return freeSpace;
}

int GetCargoMaxSpace(ref _refCharacter)
{
	if( !CheckAttribute(_refCharacter,"Ship.Type") ) return 0;
	int _ShipType = GetCharacterShipType(&_refCharacter); // PS
	if( _ShipType==SHIP_NOTUSED )
		return 0;
	aref arship; makearef(arship, _refCharacter.ship); // PRS3
	return sti(GetLocalShipAttrib(arship, &ShipsTypes[_ShipType],"Capacity")); // PRS3
}

int GetCharacterFreeSpace(ref _refCharacter,int _Goods)
{
	int weight = sti(Goods[_Goods].weight);
	int unitQ = sti(Goods[_Goods].Units);

	int retVal = unitQ * (GetCargoFreeSpace(&_refCharacter)/weight);
	return retVal;
}

int GetSquadronFreeSpace(ref _refCharacter,int _Goods)
{
	int weight = sti(Goods[_Goods].weight);
	int unitQ = sti(Goods[_Goods].Units);

	int retVal = unitQ * (GetCargoFreeSpace(&_refCharacter)/weight);
	int i,cn;
	ref chref;
	for(i=1; i<4; i++)
	{
		cn = GetCompanionIndex(&_refCharacter,i);
		if(cn!=-1)
		{
			chref = GetCharacter(cn);
			if (IsTrader(chref)) continue; // KK
			if( GetRemovable(chref) )
			{
				retVal = retVal + unitQ*(GetCargoFreeSpace(chref)/weight);
			}
		}
	}
	return retVal;
}

int GetCargoGoods(ref _refCharacter,int _Goods)
{
	string goodsName = Goods[_Goods].name;
	if(!CheckAttribute(_refCharacter,"Ship.Cargo.Goods."+goodsName))
		return 0;
	return sti(_refCharacter.Ship.Cargo.Goods.(goodsName));
}

int GetSquadronGoods(ref _refCharacter,int _Goods)
{
	int i,cn;
	ref chref;
	int retVal = GetCargoGoods(&_refCharacter,_Goods);
	for(i=1; i<4; i++)
	{
		cn = GetCompanionIndex(&_refCharacter,i);
		if(cn!=-1)
		{
			chref = GetCharacter(cn);
			if (IsTrader(chref)) continue; // KK
			if( GetRemovable(chref) || _Goods == GOOD_WHEAT || _Goods == GOOD_RUM) // LDH 13Oct06 fix for quest ships
			{
				retVal = retVal + GetCargoGoods(chref,_Goods);
			}
		}
	}
	return retVal;
}

// TIH --> new function to easily clear a cargo item
void ClearCharacterGoods(ref _refCharacter,int _Goods)
{
	if (IsTrader(_refCharacter)) return; // KK
	string goodsName = Goods[_Goods].name;
	_refCharacter.Ship.Cargo.Goods.(goodsName) = 0;
	RecalculateCargoLoad(_refCharacter);
}
// TIH <--

void SetCharacterGoods(ref _refCharacter,int _Goods,int _Quantity)
{
	if (IsTrader(_refCharacter)) return; // KK
	string goodsName = Goods[_Goods].name;
	_refCharacter.Ship.Cargo.Goods.(goodsName) = _Quantity;
	int curLoad = RecalculateCargoLoad(_refCharacter);
	int maxLoad = GetCargoMaxSpace(_refCharacter);
	if(curLoad>maxLoad)
	{
		// KK Trace("ERROR! Cargo space overup (character=" + _refCharacter.index + ",Quantity=" + _Quantity + ", curload=" + curLoad + ",maxload=" + maxLoad + ")"); // NK 05-04-06
		float overup = makefloat(maxLoad) / makefloat(curLoad); // KK
		SetCharacterGoods(_refCharacter, _Goods, makeint(_Quantity * overup)); // KK
	}
}

int AddCharacterGoods(ref _refCharacter,int _Goods,int _Quantity)
{
	int i,cn,freeQuantity;
	string goodsName = Goods[_Goods].name;

	for(i=0; i<4; i++)
	{
		cn = GetCompanionIndex(_refCharacter,i);
		if(cn!=-1)
		{
			if (IsTrader(GetCharacter(cn))) continue; // KK 
			freeQuantity = GetGoodQuantityByWeight( _Goods, GetCargoFreeSpace(&Characters[cn]) );
			if(freeQuantity>=_Quantity)
			{
				Characters[cn].Ship.Cargo.Goods.(goodsName) = sti(Characters[cn].Ship.Cargo.Goods.(goodsName)) + _Quantity;
				RecalculateCargoLoad(&Characters[cn]);
				return true;
			}
			Characters[cn].Ship.Cargo.Goods.(goodsName) = sti(Characters[cn].Ship.Cargo.Goods.(goodsName)) + freeQuantity;
			_Quantity = _Quantity - freeQuantity;
			RecalculateCargoLoad(&Characters[cn]);
		}
	}
	Trace("Overup cargo space on "+_Quantity);
	return false;
}

void AddAmmoGoods(ref _refCharacter,int _Goods,int _Quantity)
{
	if (IsTrader(_refCharacter)) return; // KK
	string goodsName = Goods[_Goods].name;
	int oldQ = 0;
	if( CheckAttribute(_refCharacter,"Ship.Cargo.Goods."+goodsName) ) {
		oldQ = sti(_refCharacter.Ship.Cargo.Goods.(goodsName));
	}
	int newQ = oldQ + _Quantity;
	int delta = newQ/20 - oldQ/20;
	if( delta==0) return;
	int nCargoLoad = 0;
	if( CheckAttribute(_refCharacter, "Ship.Cargo.Load") ) {
		nCargoLoad = sti(_refCharacter.Ship.Cargo.Load);
	}
	_refCharacter.Ship.Cargo.Load = nCargoLoad + delta*sti(Goods[_Goods].Weight);
}

int RemoveCharacterGoods(ref _refCharacter,int _Goods,int _Quantity)
{
	int i,cn,curQuantity;
	string goodsName = Goods[_Goods].name;

	for(i=0; i<4; i++)
	{
		cn = GetCompanionIndex(_refCharacter,i);
		if(cn!=-1)
		{
			if (IsTrader(GetCharacter(cn))) continue; // KK
			curQuantity = sti( Characters[cn].Ship.Cargo.Goods.(goodsName) );
			if(curQuantity>=_Quantity)
			{
				Characters[cn].Ship.Cargo.Goods.(goodsName) = curQuantity - _Quantity;
				RecalculateCargoLoad(&Characters[cn]);
				return true;
			}
			Characters[cn].Ship.Cargo.Goods.(goodsName) = 0;
			_Quantity = _Quantity - curQuantity;
			RecalculateCargoLoad(&Characters[cn]);
		}
	}
	Trace("Overup cargo space on "+_Quantity);
	return false;
}

// Cannons utilite
int GetCaracterShipCannonsType(ref _refCharacter)
{
	if(!CheckAttribute(_refCharacter,"Ship.Cannons.Type")) return CANNON_TYPE_NONECANNON;
	return sti(_refCharacter.Ship.Cannons.Type);
}
int GetCannonQuantity(ref refCharacter)
{
	int nShipType = GetCharacterShipType(refCharacter);
	if(nShipType==SHIP_NOTUSED) return 0;
	ref rShip = GetShipByType(nShipType);
	aref arship; makearef(arship, refCharacter.ship); return sti(GetLocalShipAttrib(arship, &rShip, "CurCanQty")); //NK can qty 05-04-18
	//return sti(rShip.CannonsQuantity);
}
// NK 05-04-19 -->
int GetCannonMaxQuantity(ref refCharacter)
{
	int nShipType = GetCharacterShipType(refCharacter);
	if(nShipType==SHIP_NOTUSED) return 0;
	ref rShip = GetShipByType(nShipType);
	aref arship; makearef(arship, refCharacter.ship); return sti(GetLocalShipAttrib(arship, &rShip, "MaxCanQty")); //NK can qty 05-04-18
	//return sti(rShip.CannonsQuantity);
}
// NK <--
int GetMaximumCaliber(ref refCharacter)
{
	int nShipType = GetCharacterShipType(refCharacter);
	if(nShipType==SHIP_NOTUSED) return 0;
	ref rShip = GetShipByType(nShipType);
	aref arship; makearef(arship, refCharacter.ship); // PRS3
	return sti(GetLocalShipAttrib(arship, rShip,"MaxCaliber")); // PRS3
}

// Ship utilite
int GetCharacterShipType(ref _refCharacter)
{
	// PS -->
	/*if(CheckAttribute(_refCharacter,"Ship.Type"))
	{
		if(_refCharacter.Ship.Type == SHIP_NOTUSED_TYPE_NAME) return SHIP_NOTUSED; // PS
		int iShipType = GetShipIndex(_refCharacter.Ship.Type); // PS
		if(iShipType>=0 && iShipType<SHIP_TYPES_QUANTITY_WITH_FORT)	return iShipType;
	}
	return SHIP_NOTUSED;*/
	if(!CheckAttribute(_refCharacter,"ship.type")) { return SHIP_NOTUSED; }
	if(_refCharacter.ship.type == SHIP_NOTUSED_TYPE_NAME)
	{
		_refCharacter.ship.idx = SHIP_NOTUSED;
		return SHIP_NOTUSED;
	}
	int stype = -1;
	// NK 04-09-08 now using native in GetShipIndex so that's faster.
	/*if(CheckAttribute(_refCharacter,"ship.idx")) { stype = sti(_refCharacter.ship.idx); }
	if(stype != -1 && stype != SHIP_NOTUSED && stype < SHIP_TYPES_QUANTITY)
	{
		if(ShipsTypes[stype].id == _refCharacter.ship.type) { return stype; }
	}*/
	stype = GetShipIndex(_refCharacter.ship.type);
	_refCharacter.ship.idx = stype;
	return stype;
}
string GetCharacterShipID(ref char)
{
	if(CheckAttribute(char,"Ship.Type")) return char.Ship.Type;
	return SHIP_NOTUSED_TYPE_NAME;
}
// PS <--
int GetCharacterShipHP(ref _refCharacter)
{
	int nShipType = GetCharacterShipType(_refCharacter);
	if(nShipType==SHIP_NOTUSED) return 0;
	aref arship; makearef(arship, _refCharacter.ship); // PRS3
	return sti(GetLocalShipAttrib(arship, &ShipsTypes[nShipType], "HP")); // PRS3
}
int GetCurrentShipHP(ref _refCharacter)
{
	if( CheckAttribute(_refCharacter,"ship.hp") ) return sti(_refCharacter.ship.hp);
	return 0;
}
int GetCharacterShipSP(ref _refCharacter)
{
	int nShipType = GetCharacterShipType(_refCharacter);
	if(nShipType==SHIP_NOTUSED) return 0;
	aref arship; makearef(arship, _refCharacter.ship); // PRS3
	return sti(GetLocalShipAttrib(arship, &ShipsTypes[nShipType], "SP")); // PRS3
}
string GetShipTypeName(ref _refCharacter)
{
	int nShipType = GetCharacterShipType(_refCharacter);
	if(nShipType==SHIP_NOTUSED) return SHIP_NOTUSED_TYPE_NAME;
	aref arship; makearef(arship, _refCharacter.ship); // PRS3
	return GetLocalShipAttrib(arship, &ShipsTypes[nShipType], "SName"); // PRS3
}
int GetCharacterShipClass(ref _refCharacter)
{
	int nShipType = GetCharacterShipType(_refCharacter);
	if( nShipType==SHIP_NOTUSED ) return -1;
	aref arship; makearef(arship, _refCharacter.ship); // PRS3
	return sti(GetLocalShipAttrib(arship, &ShipsTypes[nShipType], "Class")); // PRS3
}

// KK -->
string GetCharacterShipCabin(ref pchar)
{
	int nShipType = GetCharacterShipType(pchar);
	if (nShipType == SHIP_NOTUSED) return "Tutorial_Deck";
	aref ship; makearef(ship, pchar.ship);
	if (CheckShipAttribute(ship, &ShipsTypes[nShipType], "Cabin") == false) return "Tutorial_Deck";
	return GetLocalShipAttrib(ship, &ShipsTypes[nShipType], "Cabin");
}

int GetCharacterShipCannonsDeckCount(ref pchar)
{
	int nShipType = GetCharacterShipType(pchar);
	if (nShipType == SHIP_NOTUSED) return 0;
	aref ship; makearef(ship, pchar.ship);
	if (CheckShipAttribute(ship, &ShipsTypes[nShipType], "CannonsDeck") == false) return 0;
	return sti(GetLocalShipAttrib(ship, &ShipsTypes[nShipType], "CannonsDeck"));
}

int GetCharacterShipCargoHoldCount(ref pchar)
{
	int nShipType = GetCharacterShipType(pchar);
	if (nShipType == SHIP_NOTUSED) return 0;
	aref ship; makearef(ship, pchar.ship);
	if (CheckShipAttribute(ship, &ShipsTypes[nShipType], "CargoHold") == false) return 0;
	return sti(GetLocalShipAttrib(ship, &ShipsTypes[nShipType], "CargoHold"));
}

int GetCharacterShipDeckCount(ref pchar)
{
	return GetCharacterShipCannonsDeckCount(pchar) + GetCharacterShipCargoHoldCount(pchar);
}

string GetCharacterShipQDeck(ref pchar)
{
	int nShipType = GetCharacterShipType(pchar);
	if (nShipType == SHIP_NOTUSED) return "ShipDeck1";
	aref ship; makearef(ship, pchar.ship);
	if (CheckShipAttribute(ship, &ShipsTypes[nShipType], "QDeck")) {
		string loc = GetLocalShipAttrib(ship, &ShipsTypes[nShipType], "QDeck");
		if (FindLocation(loc) >= 0) return loc;
	}
	return "ShipDeck1";
}
// <-- KK
//MAXIMUS: gives possibility for upgrade player's ship -->
int GetCharacterShipLocations(ref pchar)
{
	int count = 0;
	if(GetCharacterShipCQuarters(pchar)!="") count = count + 1;
	if(GetCharacterShipCabin(pchar)!="Cabin_none" && GetCharacterShipCabin(pchar)!="Tutorial_Deck") count = count + 1;
	return count;
}

string GetCharacterShipCQuarters(ref pchar)
{
	int nShipType = GetCharacterShipType(pchar);
	if(nShipType==SHIP_NOTUSED) return "";
	aref ship; makearef(ship, pchar.ship);
	if(CheckShipAttribute(ship, &ShipsTypes[nShipType], "CQuarters"))
	{
		string loc = GetLocalShipAttrib(ship, &ShipsTypes[nShipType], "CQuarters");
		if(FindLocation(loc)!=-1) return loc;
	}
	if(GetCharacterShipClass(pchar)<=6) return "Seadogs";//temporary added (till some changes in other files will done)
	return "";
}
//MAXIMUS: gives possibility for upgrade player's ship <--
float GetFleetSpeed(ref PChar)
{
	int cn;
	ref refShip, chr;
	aref arship;
	float speed, cp, ftmp;
	speed = 99.0; cp = 0.0;
	for(int i=0; i<4; i++)
	{
		cn = GetCompanionIndex(PChar,i);
		if(cn!=-1)
		{
			chr = GetCharacter(cn);
			refShip = GetShipByType(GetCharacterShipType(&chr));
			makearef(arship, chr.ship);
			ftmp = stf(GetLocalShipAttrib(&arship, &refShip, "speedrate"));
			if(ftmp < speed) speed = ftmp;
			ftmp = stf(GetLocalShipAttrib(&arship, &refShip, "ClosestPoint"));
			if(ftmp > cp) cp = ftmp;
		}
	}
	return speed * DEFAULT_CLOSESTPOINT / cp;
}
int GetMaxCrewQuantity(ref _refCharacter)
{
	if(!CheckAttribute(_refCharacter,"Ship.Type")) return 0;
	int shipType = GetCharacterShipType(&_refCharacter); // PS
	if(shipType<0) return 0;
	if(shipType>=SHIP_TYPES_QUANTITY) return 0;
	aref arship; makearef(arship, _refCharacter.ship); // PRS3
	return sti(GetLocalShipAttrib(arship, &ShipsTypes[shipType], "MaxCrew")); // PRS3
}
int GetMinCrewQuantity(ref _refCharacter)
{
	if(!CheckAttribute(_refCharacter,"Ship.Type")) return 0;
	int shipType = GetCharacterShipType(&_refCharacter); // PS
	if(shipType<0) return 0;
	if(shipType>=SHIP_TYPES_QUANTITY) return 0;
	aref arship; makearef(arship, _refCharacter.ship); // PRS3
	return sti(GetLocalShipAttrib(arship, &ShipsTypes[shipType], "MinCrew")); // PRS3
}
int GetFreeCrewQuantity(ref _refCharacter)
{
	return (GetMaxCrewQuantity(_refCharacter)-GetCrewQuantity(_refCharacter));
}
int GetFreePartyCrewQuantity(ref _refCharacter)
{
	int cn;
	int sumCrew = 0;
	for(int i=0; i<4; i++)
	{
		cn = GetCompanionIndex(_refCharacter,i);
		if(cn!=-1)
		{
			sumCrew = sumCrew + GetFreeCrewQuantity(GetCharacter(cn));
		}
	}
	return sumCrew;
}
int GetCrewQuantity(ref _refCharacter)
{
	if(!CheckAttribute(_refCharacter,"Ship.Crew.Quantity")) return 0;
	return sti(_refCharacter.Ship.Crew.Quantity);
}
int SetCrewQuantity(ref _refCharacter,int num)
{
	int maxCrew = GetMaxCrewQuantity(_refCharacter);
	if(num>maxCrew)
	{
		if(!LAi_IsBoardingProcess()) Trace("Error!!! Overup maximum crew quantity (character=" + _refCharacter.index + ")");//MAXIMUS
		_refCharacter.Ship.Crew.Quantity = maxCrew;
		return false;
	}
	_refCharacter.Ship.Crew.Quantity = num;
	return true;
}
int AddCharacterCrew(ref _refCharacter,int num)
{
	return SetCrewQuantity(_refCharacter,GetCrewQuantity(_refCharacter)+num);
}
int RemoveCharacterCrew(ref _refCharacter,int num)
{
	int curCrew = GetCrewQuantity(_refCharacter);
	if(curCrew<num)
	{
		Trace("Error!!! Remove overup crew (character=" + _refCharacter.index + ")");
		SetCrewQuantity(_refCharacter,0);
		return false;
	}
	SetCrewQuantity(_refCharacter,curCrew-num);
	return true;
}

// NK CM/DP -->
// 05-04-18 do hirecrewcost here rather than in hirecrew.c
int GetCrewHireCost(ref ch)
{
	return 18 - (GetSummonSkillFromName(&ch,SKILL_LEADERSHIP) + 3*GetOfficersPerkUsing(&ch, "IronWill")); // was 16 and no perk
}

void ResetAllLengths(ref pchar)
{
	pchar.crewstatus.explength = 0;
	int i, j, cn;
	ref chr;
	for(i = 0; i < GetPassengersQuantity(pchar); i++)
	{
		cn = GetPassenger(pchar, i);
		if(cn == -1) continue;
		chr = GetCharacter(cn);
		if(CheckAttribute(chr,"cexplength")) DeleteAttribute(chr,"cexplength");
		if(CheckAttribute(chr,"oexplength")) DeleteAttribute(chr,"oexplength");
	}
	for(i = 0; i <4; i++)
	{
		cn = GetCompanionIndex(pchar, i);
		if(cn == -1) continue;
		chr = GetCharacter(cn);
		if(CheckAttribute(chr,"cexplength")) DeleteAttribute(chr,"cexplength");
		if(CheckAttribute(chr,"oexplength")) DeleteAttribute(chr,"oexplength");
		for(j = 0; j <4; j++)
		{
			cn = GetOfficersIndex(chr, j);
			if(cn == -1) continue;
			chr = GetCharacter(cn);
			if(CheckAttribute(chr,"cexplength")) DeleteAttribute(chr,"cexplength");
			if(CheckAttribute(chr,"oexplength")) DeleteAttribute(chr,"oexplength");
		}
	}
}

bool GetFoodEver()
{
	if(CheckAttribute(GetMainCharacter(),"foodoff")) return false;
	return true;
}
//returns ratio for personal share size (including officers!) vs. total money
float GetPersonalShareRatio(ref char)
{
	return 0.05*makefloat(GetDifficulty());
}

//returns shareratio for chref (chref assumed to be, or have been, off and/or comp of pchar
float GetCharShareRatio(ref pchar, ref chref)
{
	float share = 0.0;			// LDH fix bad initialization 10Sep06, was int instead of float
	float cexplength = 0.0;
	float oexplength = 0.0;
	float explength = 1.0;
	float base = GetPersonalShareRatio(pchar);
	if(CheckAttribute(pchar,"CrewStatus.explength")) explength = sti(pchar.CrewStatus.explength);
	if(explength == 0) return 0.0;		// LDH fix for error message, was int 0
	if(CheckAttribute(chref,"cexplength")) cexplength += sti(chref.cexplength);
	if(CheckAttribute(chref,"oexplength")) oexplength += sti(chref.oexplength);
	share = base * (cexplength * COMP_MULT + oexplength) / OFF_DIV / explength * (1.5 - makefloat(GetDifficulty())/4.0);
	trace(chref.name + " " + chref.lastname + ", C" + cexplength + "/O" + oexplength + ", has SR " + share + " (" + share/GetPersonalShareRatio(pchar) + " of psr)");
	return share;
}

//returns ratio for personal share size vs. total money, minus officer/comp part of share.
float GetPersonalShareRatioC(ref char)
{
	float base = GetPersonalShareRatio(char);
	float sub = 0;
	int i, j, cn;
	ref chref;
	for(i=0; i < GetPassengersQuantity(char); i++)
	{
		cn = GetPassenger(char, i);
		if(cn!=-1) sub += GetCharShareRatio(&char, GetCharacter(cn));
	}
	for(i = 1; i < 4; i++)
	{
		cn = GetCompanionIndex(&char,i);
		if(cn!=-1)
		{
			chref = GetCharacter(cn);
			sub += GetCharShareRatio(&char, chref);
			for(j=0; j < GetPassengersQuantity(chref); j++)
			{
				cn = GetPassenger(chref, j);
				if(cn!=-1) sub += GetCharShareRatio(char, GetCharacter(cn));
			}
		}
	}
	return (base - sub);
}

//gets personal share in gp
int GetPersonalShare(ref char)
{
	return makeint(makefloat(GetCharacterMoney(&char)) * GetPersonalShareRatio(&char));
}

//gets personal share, minus officers', in gp
int GetPersonalShareC(ref char)
{
	int share = makeint(makefloat(GetCharacterMoney(&char)) * GetPersonalShareRatioC(&char));
	if(share < 0) share = 0; //just to be sure
	return share;
}

//gets character's share in gp
int GetCharShare(ref char, ref chref)
{
	return makeint(makefloat(GetCharacterMoney(&char)) * GetCharShareRatio(&char, &chref));
}

//gets individual crew share in gp.
int GetCrewShare(ref char)
{
	// NK div0 fix 05-04-17
	int cqty = GetSquadronCrewQuantity(char);
	if(!cqty) return 0; // maybe should be 99999999999?
	return makeint(makefloat(GetCharacterMoney(char)) * (1.0 - (GetPersonalShareRatio(char) + LEFTOVER_SHARE)) / makefloat(cqty));
	// NK <--
}

//gets CSR
float GetCrewShareRatio(ref char)
{
	float csr = 1.0;
	csr = makefloat(GetCrewShare(char)) / (AVG_CREW_SHARE * sqrt(stf(char.rank)) * (0.5 + makefloat(GetDifficulty())/4.0));
	return csr;
}

//gets clamped CSR
float GetCrewShareRatioC(ref char)
{
	float csr = GetCrewShareRatio(char);
	if(csr > 1.0) csr = 2.0-(1.0/csr);
	return csr;
}

//returns name for csr
string GetCrewShareName(float csr)
{
	if(csr < 0.1) return XI_ConvertString("furious");
	if(csr < 0.2) return XI_ConvertString("very angry");
	if(csr < 0.3) return XI_ConvertString("angry");
	if(csr < 0.5) return XI_ConvertString("upset");
	if(csr < 0.7) return XI_ConvertString("very disappointed");
	if(csr < 0.9) return XI_ConvertString("disappointed");
	if(csr < 1.1) return XI_ConvertString("d"+"neutral");
	if(csr < 1.3) return XI_ConvertString("pleased");
	if(csr < 1.5) return XI_ConvertString("quite pleased");
	if(csr < 1.7) return XI_ConvertString("happy");
	if(csr < 1.8) return XI_ConvertString("very happy");
	if(csr < 1.9) return XI_ConvertString("extremely happy");
	return XI_ConvertString("overjoyed");
}

// DIVIDE THE PLUNDER
void DividePlunder(ref PChar)
{
	int cn,j,q;
	ref chref,chref2;

	PChar.Crewstatus.lastcsr = GetCrewShareRatioC(PChar);
	float atcsr = 1.0;
	if(CheckAttribute(PChar,"Crewstatus.alltimecsr")) atcsr = stf(PChar.Crewstatus.alltimecsr);
	atcsr = (atcsr + GetCrewShareRatioC(PChar)) / 2.0;
	PChar.Crewstatus.alltimecsr = atcsr;
	AddWealthToCharacter(&PChar, GetPersonalShareC(PChar) * (0.75 + makefloat(GetFoodEver()) * 0.25));
	for(q = 0; q < GetPassengersQuantity(PChar); q++)
	{
		cn = GetPassenger(PChar, q);
		if(cn!=-1)
		{
			chref = GetCharacter(cn);
			AddMoneyToCharacter(&chref, GetCharShare(PChar, &chref));
		}
	}
	for(q = 1; q < 4; q++)
	{
		cn = GetCompanionIndex(&PChar,q);
		if(cn!=-1)
		{
			chref = GetCharacter(cn);
			AddMoneyToCharacter(&chref, GetCharShare(PChar, &chref2));
			for(j=0; j < GetPassengersQuantity(chref); j++)
			{
				cn = GetPassenger(chref, j);
				if(cn!=-1) 
				{
					chref2 = GetCharacter(cn);
					AddMoneyToCharacter(&chref2, GetCharShare(PChar, &chref2));
				}
			}
		}
	}
	ResetAllLengths(PChar);
	DeleteAttribute(GetMainCharacter(),"foodoff"); // reset food off toggle
	pchar.money = makeint(makefloat(GetCharacterMoney(PChar)) * LEFTOVER_SHARE);
	SetSquadronCrewQuantityTotalRatio(PChar, 0.2 * stf(PChar.Crewstatus.lastcsr) * (1.0 + makefloat(GetSummonSkillFromName(PChar, SKILL_LEADERSHIP))/5.0));
	// new to reset ship goods qtys, repair, etc. NK 05-04-24
	for(q = 0; q < 4; q++)
	{
		cn = GetCompanionIndex(&PChar,q);
		if(cn!=-1)
		{
			chref = GetCharacter(cn);
			ResetShip(&chref)
		}
	}
	// NK <--
}

// used on DP. NK 05-04-24
// will set health, cannon, etc. to max, and add autobuy goods.
void ResetShip(ref chref)
{	
	chref.ship.hp = GetCharacterShipHP(&chref);
	DeleteAttribute(&chref,"ship.blots");
	chref.ship.sp = GetCharacterShipSP(&chref);
	DeleteAttribute(&chref,"ship.sails");
	DeleteAttribute(&chref,"ship.masts");
	ResetCannons(&chref)
	SetCharacterGoods(&chref, GOOD_BALLS, makeint(makefloat(GetCannonQuantity(&chref)) * BALLS_PER));
	SetCharacterGoods(&chref, GOOD_GRAPES, makeint(makefloat(GetCannonQuantity(&chref)) * GRAPE_PER));
	SetCharacterGoods(&chref, GOOD_KNIPPELS, makeint(makefloat(GetCannonQuantity(&chref)) * CHAIN_PER));
	if (!USE_REAL_CANNONS) { SetCharacterGoods(&chref, GOOD_BOMBS, makeint(makefloat(GetCannonQuantity(&chref)) * BOMBS_PER)); }// TIH safer method 7-7-06 //SetCharacterGoods(&chref, GOOD_BOMBS, makeint(!USE_REAL_CANNONS * makefloat(GetCannonQuantity(&chref)) * BOMBS_PER));
	if (CANNONPOWDER_MOD) {// TIH --> mod toggle 7-7-06
		// added by MAXIMUS [gunpowder mod] -->
		int fireGunpowder = 0;
		ref rCannon; makeref(rCannon,Cannon[GetCaracterShipCannonsType(chref)]);
		if(CheckAttribute(rCannon,"gunpowder")) fireGunpowder = sti(rCannon.gunpowder)*sti(GetCannonCurQuantity(chref));
		float averageQty = 0.0;
		if (USE_REAL_CANNONS) 	{ averageQty = makefloat(GetCargoGoods(chref,GOOD_BALLS) + GetCargoGoods(chref,GOOD_GRAPES) + GetCargoGoods(chref,GOOD_KNIPPELS))/3; }
		else 					{ averageQty = makefloat(GetCargoGoods(chref,GOOD_BALLS) + GetCargoGoods(chref,GOOD_GRAPES) + GetCargoGoods(chref,GOOD_KNIPPELS) + GetCargoGoods(chref,GOOD_BOMBS))/4; }
		float canCharge = makefloat(averageQty/makefloat(GetCannonCurQuantity(chref)));
		SetCharacterGoods(&chref, GOOD_GUNPOWDER, makeint(makefloat(fireGunpowder * canCharge)) + makeint(sti(chref.ship.crew.quantity)*3));
		// added by MAXIMUS [gunpowder mod] <--
	}// TIH <-- mod toggle
	SetCharacterGoods(&chref, GOOD_SAILCLOTH, makeint(makefloat(GetCharacterShipHP(&chref)) * SAIL_PER));
	SetCharacterGoods(&chref, GOOD_PLANKS, makeint(makefloat(GetCharacterShipHP(&chref)) * PLANKS_PER));
	SetCharacterGoods(&chref, GOOD_WHEAT, makeint(makefloat(GetCrewQuantity(&chref)) * FOOD_PER_CREW * WHEAT_DAYS));
	SetCharacterGoods(&chref, GOOD_RUM, makeint(makefloat(GetCrewQuantity(&chref)) * FOOD_PER_CREW * RUM_DAYS));
}

//gets total crew of squadron
int GetSquadronCrewQuantity(ref mchref)
{
	int crewQ = 0;
	int i,cn;
	crewQ += GetCrewQuantity(mchref);
	ref chref;
	for(i=1; i<4; i++)
	{
		cn = GetCompanionIndex(mchref,i);
		if( cn>=0 && GetRemovable(&Characters[cn]) )
		{
			chref = GetCharacter(cn);
			crewQ += GetCrewQuantity(chref);
		}
	}
	return crewQ;
}

//sets crew based on ratio
int SetSquadronCrewQuantityRatio(ref char, float ratio)
{
	int crewQ = 0;
	int tcrewQ = 0;
	int i,cn;
	crewQ = GetCrewQuantity(char);
	SetCrewQuantity(char, makeint(crewQ*ratio));
	tcrewQ += GetCrewQuantity(char);
	ref chref;
	for(i=1; i<4; i++)
	{
		cn = GetCompanionIndex(char,i);
		if( cn>=0 && GetRemovable(&Characters[cn]) )
		{
			chref = GetCharacter(cn);
			crewQ = GetCrewQuantity(chref);
			SetCrewQuantity(chref, makeint(crewQ*ratio));
			tcrewQ += GetCrewQuantity(chref);
		}
	}
	return tcrewQ;
}

int SetSquadronCrewQuantityTotalRatio(ref char, float ratio)
{
	ratio = clampf(ratio);
	int crewQ = 0;
	int tcrewQ = 0;
	int i,cn;
	crewQ = GetMaxCrewQuantity(char);
	SetCrewQuantity(char, makeint(crewQ*ratio));
	tcrewQ += GetCrewQuantity(char);
	ref chref;
	for(i=1; i<4; i++)
	{
		cn = GetCompanionIndex(char,i);
		if( cn>=0 && GetRemovable(&Characters[cn]) )
		{
			chref = GetCharacter(cn);
			crewQ = GetMaxCrewQuantity(chref);
			if(!bSeaActive) SetCrewQuantity(chref, makeint(crewQ*ratio));
			tcrewQ += GetCrewQuantity(chref);
		}
	}
	return tcrewQ;
}


/*
float GetSquadronGoodsRatio(ref _refCharacter,int _Goods)
{
	int i,cn;
	int retVal[4];
	int total = 0;
	for(i = 0; i<4; i++) retVal[i] = 0;
	retVal[0] = GetCargoGoods(&_refCharacter,_Goods);
	total += GetCargoGoods(&_refCharacter,_Goods);
	for(i=1; i<4; i++)
	{
		cn = GetCompanionIndex(&_refCharacter,i);
		if(cn!=-1)
		{
			retVal[i] = GetCargoGoods(&Characters[cn],_Goods);
			total += GetCargoGoods(&Characters[cn],_Goods);
		}
	}
	float real_ret[4];
	for(i = 0; i<4; i++) realret[i] = retVal[i]/total;
	return real_ret; return retval;
}

void SetSquadronGoodsRatio(ref _refCharacter,int _Goods, int quantity, float ratio[4])
{
	SetCharacterGoods(_refCharacter, _Goods, makeint(quantity/ratio[0]));
	for(i=1; i<4; i++)
	{
		cn = GetCompanionIndex(&_refCharacter,i);
		if(cn!=-1)
		{
			SetCharacterGoods(&Characters[cn], _Goods, makeint(quantity/ratio[i]));
		}
	}
}
*/
// NK CM/DP <--

float GetSailPercent(ref _refCharacter)
{
	if( !CheckAttribute(_refCharacter,"Ship.SP") ) return 100.0;
	int iSP = GetCharacterShipSP(_refCharacter);
	if(iSP<=0) return 100.0;
	float fpsp = 100.0*stf(_refCharacter.Ship.SP)/iSP;
	return fpsp;
}
float GetHullPercent(ref _refCharacter)
{
	if(!CheckAttribute(_refCharacter,"Ship.HP")) return 100.0;
	int iHP = GetCharacterShipHP(_refCharacter);
	if(iHP<=0) return 100.0;
	float fphp = 100.0*stf(_refCharacter.Ship.HP)/iHP;
	return fphp;
}
float GetSailRPD(ref _refCharacter) // процент ремонта парусов в день
{
	int repairSkill = GetSummonSkillFromName(_refCharacter,SKILL_REPAIR);
	float damagePercent = 100.0 - GetSailPercent(_refCharacter);
	if(damagePercent==0.0) return 0.0;
	return repairSkill*10.0 / damagePercent;
}
float GetHullRPD(ref _refCharacter) // процент ремонта корпуса в день
{
	int repairSkill = GetSummonSkillFromName(_refCharacter,SKILL_REPAIR);
	float damagePercent = 100.0 - GetHullPercent(_refCharacter);
	if(damagePercent==0.0) return 0.0;
	return repairSkill*10.0 / damagePercent;
}
int GetSailSPP(ref _refCharacter) // количество парусины на один процент починки
{
	return 8-GetCharacterShipClass(_refCharacter);
}
int GetHullPPP(ref _refCharacter) // количество досок на один процент починки
{
	return 8-GetCharacterShipClass(_refCharacter);
}

// Fellowtravels utilites
// работа с пассажирами
int GetPassengersQuantity(ref _refCharacter)
{
	if(!CheckAttribute(_refCharacter,"Fellows.Passengers.Quantity")) return 0;
	return sti(_refCharacter.Fellows.Passengers.Quantity);
}

int GetNotCaptivePassengersQuantity(ref _refCharacter)
{
	int result, idx;
	result = 0;
	idx = 0;
	if(!CheckAttribute(_refCharacter,"Fellows.Passengers.Quantity")) return 0;
	for (int i=0; i <sti(_refCharacter.Fellows.Passengers.Quantity); i++)
	{
		idx = GetNotCaptivePassenger( _refCharacter,i);
		if (idx >0) result = result+1;
	}
	return result;
}

int GetPassenger(ref _refCharacter,int idx)
{
	if(idx<0) return -1;
	if(idx>=GetPassengersQuantity(_refCharacter)) return -1;

	string PsgAttrName = "id"+(idx+1);
	if(!CheckAttribute(_refCharacter,"Fellows.Passengers."+PsgAttrName)) return -1;
	return sti(_refCharacter.Fellows.Passengers.(PsgAttrName));
}
int GetPassengerNumber(ref _refCharacter,int findCharacterIdx)
{
	int psgQuant = GetPassengersQuantity(_refCharacter);
	int cn;
	ref cr;
	for(int i=0; i<psgQuant; i++)
	{
		cn = GetPassenger(_refCharacter,i);
		if(cn==-1) break;
		cr = GetCharacter(cn);
		if(findCharacterIdx==sti(cr.index)) return i;
	}
	return -1;
}
int GetNotCaptivePassenger(ref _refCharacter,int idx)
{
	if(idx<0) return -1;
	int psgQuant = GetPassengersQuantity(_refCharacter);

	int curIdx=0;
	ref curChar;
	int cn;
	for(int i=0;i<psgQuant;i++)
	{
		cn = GetPassenger(_refCharacter,i);
		if(cn==-1) break;

		curChar = GetCharacter(cn);
		if(CheckAttribute(curChar,"prisoned"))
		{
			if(sti(curChar.prisoned)==true) continue;
		}
		if(curIdx==idx)	return sti(curChar.index);
		curIdx++;
	}
	return -1;
}
int ChangePassenger(ref _refCharacter,int idx, int psngIdx)
{
	int retVal = GetPassenger(&_refCharacter,idx);
	if(idx>=0)
	{
		string PsgAttrName = "id"+(idx+1);
		_refCharacter.Fellows.Passengers.(PsgAttrName) = psngIdx;
	}
	return retVal;
}
int AddPassenger(ref _refCharacter,ref _refPassenger, int prisonFlag)
{
	int PsgQuantity = GetPassengersQuantity(_refCharacter);
	if(PsgQuantity<PASSENGERS_MAX)
	{
		aref tmpRef; makearef(tmpRef,_refCharacter.Fellows.Passengers);
		string PsgAttrName;
		for(int i=0;i<PsgQuantity;i++)
		{
			PsgAttrName = "id"+(i+1);
			if(tmpRef.(PsgAttrName)==_refPassenger.index) return PsgQuantity;
		}
		PsgQuantity++;
		tmpRef.Quantity = PsgQuantity;
		PsgAttrName = "id"+PsgQuantity;
		tmpRef.(PsgAttrName) = _refPassenger.index;
		if(prisonFlag==true)	_refPassenger.prisoned = true;
	}
	else	trace("Overup maximum passengers quantity");
	return PsgQuantity;
}
int RemovePassenger(ref _refCharacter,ref _refPassenger)
{
	RemoveOfficersIndex(_refCharacter,sti(_refPassenger.index));
	int PsgQuantity = GetPassengersQuantity(_refCharacter);
	int psgNum = GetPassengerNumber(_refCharacter,sti(_refPassenger.index));
	if(psgNum==-1) return PsgQuantity;

	aref tmpRef;
	makearef(tmpRef,_refCharacter.Fellows.Passengers);
	string inPsgAttrName,outPsgAttrName;
	for(int i=(psgNum+1); i<PsgQuantity; i++)
	{
		inPsgAttrName = "id"+i;
		outPsgAttrName = "id"+(i+1);
		tmpRef.(inPsgAttrName) = tmpRef.(outPsgAttrName);
	}

	outPsgAttrName = "id"+PsgQuantity;
	DeleteAttribute(tmpRef,outPsgAttrName);
	PsgQuantity--;
	tmpRef.Quantity = PsgQuantity;
	return PsgQuantity;
}
int FindFellowtravellers(ref _refCharacter,ref _refFindCharacter)
{
	int i;
	string stmp;
	aref atmp;
	aref curref;

	if(sti(_refFindCharacter.index)==-1) return FELLOWTRAVEL_NO;
	if(CheckAttribute(_refFindCharacter,"prisoned"))
	{
		if(sti(_refFindCharacter.prisoned)==true) return FELLOWTRAVEL_CAPTIVE;
	}
	for(i=1;i<4;i++)
	{
		if( sti(_refFindCharacter.index) == GetOfficersIndex(_refCharacter,i) )	return FELLOWTRAVEL_OFFICER;
	}
	for(i=0;i<GetPassengersQuantity(_refCharacter);i++)
	{
		if(sti(_refFindCharacter.index)==GetPassenger(_refCharacter,i))	return FELLOWTRAVEL_PASSENGER;
	}
	for(i=1;i<4;i++)
	{
		if( GetCompanionIndex(_refCharacter,i)==sti(_refFindCharacter.index) )	return FELLOWTRAVEL_COMPANION;
	}
	return FELLOWTRAVEL_NO;
}

// 04-12-06 to find if char is in party. Searches officers, companions, and companion officers.
bool IsInParty(int mchridx, int chridx)
{
	int i,j;
	if(chridx == -1 || mchridx == -1) return false;
	ref mchr;
	for(j = 0; j < 4; j++)
	{
		if(GetCompanionIndex(GetCharacter(mchridx),j) == -1) continue;
		mchr = GetCharacter(GetCompanionIndex(GetCharacter(mchridx),j));
		for(i=0;i<4;i++)
		{
			if(GetOfficersIndex(mchr,i) == chridx) return true;
		}
	}
	return false;
}

// работа с компаньонами
int SetCompanionIndex(ref _refCharacter,int _CompanionNum, int _CompanionIdx)
{
    if(_CompanionNum == -1)
	{
		for(int i=1; i<4; i++)
		{
			if(GetCompanionIndex(_refCharacter, i) == -1)
			{
				_CompanionNum = i;
				break;
			}
		}
	}
	if(_CompanionNum<1) return _CompanionIdx;
	if(_CompanionNum>3) return _CompanionIdx;

	if(_CompanionIdx!=-1)
	{
		for(i=0;i<4;i++)
		{
			if(GetCompanionIndex(_refCharacter,i)==_CompanionIdx) return -1;
		}
	}

	string compName = "id"+_CompanionNum;
	int retVal = GetCompanionIndex(_refCharacter,_CompanionNum);
	_refCharacter.Fellows.Companions.(compName) = _CompanionIdx;

	if( _CompanionIdx>=0 && CheckAttribute(&Characters[_CompanionIdx],"nation") ) {
		Characters[_CompanionIdx].prev_nation = Characters[_CompanionIdx].nation;
		Characters[_CompanionIdx].nation = _refCharacter.nation;
	}
	if( retVal>=0 && CheckAttribute(&Characters[retVal],"prev_nation") ) {
		Characters[retVal].nation = Characters[retVal].prev_nation;
	}

	Event(EVENT_CHANGE_COMPANIONS,"");
	return retVal;
}
int RemoveCharacterCompanion(ref _refCharacter, ref refCompanion)
{
	string compName;
	int i;

	aref refComps;
	makearef(refComps,_refCharacter.Fellows.Companions);
	for(i=1; i<4; i++)
	{
		compName = "id"+i;
		if(CheckAttribute(refComps,compName) && refComps.(compName)==refCompanion.index)
		{
			refComps.(compName) = -1;
			refCompanion.location = _refCharacter.location;
			refCompanion.location.group = _refCharacter.location.group;
			refCompanion.location.locator = _refCharacter.location.locator;
			Event(EVENT_CHANGE_COMPANIONS,"");
			return i;
		}
	}
	return -1;
}
int GetCompanionIndex(ref _refCharacter,int _CompanionNum)
{
	if(_CompanionNum<0) return -1;
	if(_CompanionNum>3) return -1;
	if(_CompanionNum==0)
	{
		if(CheckAttribute(_refCharacter,"index")) return sti(_refCharacter.index);
	}

	string compName = "id"+_CompanionNum;
	if(!CheckAttribute(_refCharacter,"Fellows.Companions."+compName)) return -1;
	return sti(_refCharacter.Fellows.Companions.(compName));
}
int GetCompanionNumber(ref _refCharacter,int _CompanionIdx)
{
	for(int i=0; i<4; i++)
	{
		if( GetCompanionIndex(_refCharacter,i) == _CompanionIdx ) return i;
	}
	return -1;
}
int GetCompanionQuantity(ref _refCharacter)
{
	int qn = 1;
	for(int i=1; i<4; i++)
	{
		if( GetCompanionIndex(_refCharacter,i)>=0 ) qn++;
	}
	return qn;
}

// работа с офицерами
int GetOfficersQuantity(ref _refCharacter)
{
	int idx=0;
	for(int i=1; i<4; i++)
	{
		if( GetOfficersIndex(_refCharacter,i)!=-1 ) idx++;
	}
	return idx;
}
int GetOfficersIndex(ref _refCharacter,int _OfficerNum)
{
	if(_OfficerNum<0) return -1;
	if(_OfficerNum>3) return -1;
	if(_OfficerNum==0)
	{
		if(CheckAttribute(_refCharacter,"index")) return MakeInt(_refCharacter.index);
	}

	string compName = "id"+_OfficerNum;
	if(!CheckAttribute(_refCharacter,"Fellows.Passengers.Officers."+compName)) return -1;
	return sti(_refCharacter.Fellows.Passengers.Officers.(compName));
}
int SetOfficersIndex(ref _refCharacter,int _OfficerNum, int _OfficerIdx)
{
	int i;
    if(_OfficerNum == -1)
	{
		for(i=1; i<4; i++)
		{
			if(GetOfficersIndex(_refCharacter, i) == -1)
			{
				_OfficerNum = i;
				break;
			}
		}
	}
	if(_OfficerNum<1) return _OfficerIdx;
	if(_OfficerNum>3) return _OfficerIdx;

	if(_OfficerIdx!=-1)
	{
		for(i=0;i<4;i++)
		{
			if(GetOfficersIndex(_refCharacter,i)==_OfficerIdx) return -1;
		}
		AddPassenger(_refCharacter,GetCharacter(_OfficerIdx),false);
	}

	string compName = "id"+_OfficerNum;
	int retVal = GetOfficersIndex(_refCharacter,_OfficerNum);
	_refCharacter.Fellows.Passengers.Officers.(compName) = _OfficerIdx;
	if(_OfficerIdx>=0)
	{
		LAi_SetOfficerType(GetCharacter(_OfficerIdx));
		Characters[_OfficerIdx].location = _refCharacter.location;
	}
	if(retVal>=0)
	{
		LAi_SetCitizenTypeNoGroup(GetCharacter(retVal));
		Characters[retVal].location = "none";
	}
	Event(EVENT_CHANGE_OFFICERS,"");
	return retVal;
}
bool RemoveOfficersIndex(ref _refCharacter, int _OfficerIdx)
{
	if(_OfficerIdx==-1) return false;
	for(int i=1; i<4; i++)
	{
		if(GetOfficersIndex(_refCharacter,i) == _OfficerIdx)
		{
			SetOfficersIndex(_refCharacter,i,-1);
			return true;
		}
	}
	return false;
}

// table service
//MAXIMUS -->
string GetTranslatedReputationForSex(ref xi_refCharacter, string repName)
{
	if(!CheckAttribute(xi_refCharacter,"sex")) return XI_ConvertString("i"+repName);

	string chReputation = "";
	switch(xi_refCharacter.sex)
	{
		case "man": chReputation = XI_ConvertString("i"+repName); break;
		case "woman": chReputation = XI_ConvertString("w"+repName); break;
		chReputation = XI_ConvertString("i"+repName);
	}
	return chReputation;
}
//MAXIMUS <--

string GetReputationName(int reputation)
{
    if(reputation<11)
        return ReputationTable[REPUTATIONT_HORROR];
    if(reputation<21)
        return ReputationTable[REPUTATIONT_BASTARD];
    if(reputation<31)
        return ReputationTable[REPUTATIONT_SWINDLER];
    if(reputation<41)
        return ReputationTable[REPUTATIONT_RASCAL];
    if(reputation<51)
        return ReputationTable[REPUTATIONT_NEUTRAL];
    if(reputation<61)
        return ReputationTable[REPUTATIONT_PLAIN];
    if(reputation<71)
        return ReputationTable[REPUTATIONT_GOOD];
    if(reputation<81)
        return ReputationTable[REPUTATIONT_VERYGOOD];
    if(reputation<90)
        return ReputationTable[REPUTATIONT_HERO];
	return "";
}

string GetMoraleName(int morale)
{
	if(morale<10)
		return MoraleTable[MORALET_TREACHEROUS];
	if(morale<20)
		return MoraleTable[MORALET_AWFUL];
	if(morale<30)
		return MoraleTable[MORALET_LOW];
	if(morale<40)
		return MoraleTable[MORALET_POOR];
	if(morale<50)
		return MoraleTable[MORALET_NORMAL];
	if(morale<60)
		return MoraleTable[MORALET_ELATED];
	if(morale<70)
		return MoraleTable[MORALET_GOOD];
	if(morale<80)
		return MoraleTable[MORALET_HIGH];
	if(morale<90)
		return MoraleTable[MORALET_EXCELLENT];
	if(morale<100)
		return MoraleTable[MORALET_HEROIC];
	return "";
}

// skill and expirence service
string GetSkillName(int _SkillType)
{
	switch(_SkillType)
	{
	case 0:
		return SKILL_LEADERSHIP;
		break;
	case 1:
		return SKILL_FENCING;
		break;
	case 2:
		return SKILL_SAILING;
		break;
	case 3:
		return SKILL_ACCURACY;
		break;
	case 4:
		return SKILL_CANNONS;
		break;
	case 5:
		return SKILL_GRAPPLING;
		break;
	case 6:
		return SKILL_REPAIR;
		break;
	case 7:
		return SKILL_DEFENCE;
		break;
	case 8:
		return SKILL_COMMERCE;
		break;
	case 9:
		return SKILL_SNEAK;
		break;
	}
	return "";
}

int GetCharacterSkill(ref _refCharacter, string skillName)
{
	if( !CheckAttribute(_refCharacter,"Skill."+skillName) ) return 0;
	int skillN = sti(_refCharacter.Skill.(skillName));
	// GZ/NK -->
	int mod = 0;
	string tempattr = "Skill." + skillName + ".mod"; 
	if(CheckAttribute(_refCharacter,tempattr))
	{
		mod = sti(_refCharacter.(tempattr));
		if(skillN + mod > 10) skillN = 10;
		else skillN += mod;
	}
	else
	{
		int i, qty, lowest;
		lowest = 11;
		mod = 0;
		ref itm;
		bool uselow = false;
		//uncomment these if you want to disallow stacking different items. See below for more.
		//bool canchange = true;
		//bool temp = false;
		for(i = 0; i < SKILLITEMS_QUANTITY; i++)
		{
			itm = &Items[NativeFindCharacter(&Items, SkillItems[i].id)];
			if(!CheckAttribute(itm,"skill."+skillName)) continue;
			qty = GetCharacterItem(_refCharacter, itm.id);
			if( qty >= sti(itm.skill.num)) // *.skill.num = num required for effect. Default = 1
			{
				if(CheckAttribute(itm,"groupID"))
				{
					string tstr = itm.groupID;
					if(!CheckAttribute(_refCharacter,"equip."+tstr)) continue;
					if(_refCharacter.equip.(tstr) != itm.id) continue; // if equipable and not equipped, skip
				}
				//uncomment below lines if you want to disallow stacking different items
				//temp = canchange;

				//if(CheckAttribute(itm,"skill.diffstack") && sti(itm.skill.diffstack)) temp = true;
				//if(temp)
				//{
					// *.stack = num of item that can be stacked together. Default = 1
					if(sti(itm.skill.stack) >= qty/sti(itm.skill.num)) { mod += sti(itm.skill.(skillName)) * qty/sti(itm.skill.num); }
					else { mod += sti(itm.skill.(skillName)) * sti(itm.skill.stack) / sti(itm.skill.num); }
					if(CheckAttribute(itm,"skill."+skillName+".set"))
					{
						if(sti(itm.skill.(skillName).set) < lowest) lowest = sti(itm.skill.(skillName).set);
						uselow = true;
					}
					//canchange = false;
				//}
			}
		}

		if(mod > MAX_SKILL_INCREASE) mod = MAX_SKILL_INCREASE; // PB: UNTESTED!
		if(uselow)
		{
			_refCharacter.(tempattr) = lowest + mod - skillN;
			if(lowest + mod > 10) skillN = 10;
			else skillN = lowest + mod;
		}
		else
		{
			if(skillN + mod > 10) skillN = 10;
			else skillN += mod;
			_refCharacter.(tempattr) = mod;
		}
	}
	// GZ/NK <--
	if( skillN<=10 ) return skillN;
	trace("Character ID = "+_refCharacter.id + "have skill "+skillName + " = "+skillN);
	return 10;
}

int GetSummonSkillFromName(ref _refCharacter, string skillName)
{
	int sumSkill = GetCharacterSkill(_refCharacter,skillName);
	int i,cn,curSkill;
	for(i=1;i<4;i++)
	{
		cn = GetOfficersIndex(&_refCharacter,i);
		if(cn!=-1)
		{
			curSkill = GetCharacterSkill(GetCharacter(cn),skillName);
			if(sumSkill<curSkill)
			{
				sumSkill = curSkill;
			}
		}
	}
	return sumSkill;
}

// NK -->
int GetAverageSkill(ref chr, string skl)
{
	return (GetCharacterSkill(&chr, skl) + GetSummonSkillFromName(&chr, skl))/2;
}

int GetSkillBool(ref chr, string skill, bool summon) //will return summon if bool summon == true, else return normal GCS.
{
	if(summon) return GetSummonSkillFromName(&chr, skill);
	return GetCharacterSkill(&chr, skill);
}
// NK <--

int GetSummonSkill(ref _refCharacter,int _SkillType)
{
	return GetSummonSkillFromName(&_refCharacter,GetSkillName(_SkillType));
}

string GetBasicSkill(ref _refCharacter)
{
	aref refSkill;
	makearef(refSkill,_refCharacter.Skill);
	string skillName;

	int i=0;
	int maxSkillValue = -1;
	string maxSkillName;
	for(i=0; i<10; i++)
	{
		skillName = GetSkillName(i);
		if(MakeInt(refSkill.(skillName))>maxSkillValue)
		{
			maxSkillName = skillName;
			maxSkillValue = MakeInt(refSkill.(skillName));
		}
	}
	return maxSkillName;
}

// NK -->
void AddPartyExp(ref chref, int _exp)
{
	int cn,cn2,i,j, myindex;
	myindex = sti(chref.index);
	float sxmult = 1.0 + GetOfficersPerkUsing(chref,"SharedExperience");
	AddCharacterExpNS(chref, _exp);
	if(IsOfficer(chref) || IsCompanion(chref)) { chref = GetMainCharacter(); AddCharacterExpNS(chref, _exp); }
	for(i=0; i < GetPassengersQuantity(chref); i++)
	{
		cn = GetPassenger(chref, i);
		if(cn == -1 || cn == myindex) continue;
		if(CheckAttribute(Characters[cn],"prisoned") && sti(Characters[cn].prisoned)) continue;
		if(IsOfficer(Characters[cn])) {AddCharacterExpNS(&Characters[cn], _exp);}
		else {AddCharacterExpNS(&Characters[cn], _exp * 0.5 * sxmult);}
	}
	if(GetCompanionQuantity(chref) > 1)
	{
		for(i=1; i < 4; i++)
		{
			cn = GetCompanionIndex(chref, i);
			if(cn == -1) continue;
			for(j=0; j<4; j++)
			{
				cn2 = GetOfficersIndex(&Characters[cn], j);
				if(cn2 == -1 || cn2 == myindex) continue;
				AddCharacterExpNS(&Characters[cn2], _exp);
			}
		}
	}
}
// NK <--

void AddExpAndShow(ref chref, int _exp)
{
	Log_SetStringToLog("+" + _exp + XI_ConvertString("add experience"));
	AddCharacterExp(chref, _exp);
}

// NK -->
int AddCharacterExp(ref _refCharacter,int _exp)
{
	ref chref;
	int i, cn, myindex;
	myindex = sti(_refCharacter.index);
	makeref(chref, _refCharacter);
	AddCharacterExpNS(chref, _exp);
	if(IsOfficer(chref)) chref = GetMainCharacter();
	float sxmult = 1.0 + GetOfficersPerkUsing(chref,"SharedExperience");
	//Log_SetStringToLog("Mult " + sxmult);
	//if(myindex != sti(chref.index)) AddCharacterExpNS(chref, _exp*0.5*sxmult);
	/*for(i=0; i <= GetPassengersQuantity(chref); i++)
	{
		cn = GetPassenger(chref, i);
		if(cn == -1 || myindex == cn) continue;
		if(CheckAttribute(Characters[cn],"prisoned") && sti(Characters[cn].prisoned)) continue;
		if(CheckAttribute(Characters[cn],"officerboss"))
		{
			Log_SetStringToLog(Characters[cn].name + " " + Characters[cn].lastname + " is officer");
			AddCharacterExpNS(Characters[cn], _exp * 0.5 * sxmult);
		}
		else
		{
			Log_SetStringToLog(Characters[cn].name + " " + Characters[cn].lastname + " is just passenger");
			AddCharacterExpNS(Characters[cn], _exp * 0.25 * sxmult);
		}
	}*/
	//Log_SetStringToLog("1");
	for(i=0; i < 4; i++)
	{
		cn = GetOfficersIndex(chref, i);
		if(cn == -1) { /*Log_SetStringToLog("off " + i + " not");*/ continue; }
		if(cn == myindex) { /*Log_SetStringToLog("off " + i + " already");*/ continue; }
		//Log_SetStringToLog(Characters[cn].name + " " + Characters[cn].lastname + " is officer, getting " + makeint(makefloat(_exp) * 0.5 * sxmult));
		AddCharacterExpNS(&Characters[cn], makeint(makefloat(_exp) * 0.5 * sxmult));
	}
	if(!CheckAttribute(_refCharacter,"Experience")) _refCharacter.Experience = 1; // MAXIMUS 28.07.2006
	return sti(_refCharacter.Experience);
}

int AddCharacterExpNS(ref _refCharacter,int _exp)
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	if(_exp < 1) return 0;
	int retVal = false;
	//if(CheckCharacterPerk(_refCharacter,"SharedExperience")) _exp *= 1.25;
	if(LogsToggle && _exp > 10 * makeint(_refCharacter.rank) && _exp > 25 && !CheckAttribute(_refCharacter,"donotshowXP")) { Log_SetStringToLog(_refCharacter.name + " " + _refCharacter.lastname + " " + TranslateString("","Gained") + " " + makeint(_exp) + " " + XI_ConvertString("XP")); }
	if(!CheckAttribute(_refCharacter,"Experience")) _refCharacter.Experience = 1; // MAXIMUS 28.07.2006
	int curExp = sti(_refCharacter.Experience) + makeint(_exp);
	_refCharacter.Experience = curExp;
	int nextExp = CalculateExperienceFromRank(sti(_refCharacter.rank)+1);
	while(curExp>=nextExp)
	{
		_refCharacter.rank = sti(_refCharacter.rank) + 1;
		_refCharacter.Skill.FreeSkill = sti(_refCharacter.Skill.FreeSkill) + ADD_SKILLPOINTS_PERLEVEL; // TIH changed to user configurable setting Nov14'06
		if(CheckAttribute(_refCharacter,"perks.FreePoints"))
		{	_refCharacter.perks.FreePoints = sti(_refCharacter.perks.FreePoints) + 1;
		}
		else
		{	_refCharacter.perks.FreePoints = 1;
		}
		nextExp = CalculateExperienceFromRank(sti(_refCharacter.rank)+1);
		ResetHP(&_refCharacter); // NK 05-07-03 -
		/*float mhp = LAi_GetCharacterMaxHP(_refCharacter) + 5.0;
		if(CheckAttribute(_refCharacter,"officer")) mhp = LAi_GetCharacterMaxHP(_refCharacter) + makeint(11-GetDifficulty());
		LAi_SetHP(_refCharacter,LAi_GetCharacterHP(_refCharacter),mhp);*/
		if(CheckAttribute(_refCharacter,"quest.officerprice")) _refCharacter.quest.officerprice = sti(_refCharacter.quest.officerprice) + 200 * OPRICE_LEVEL_MULT;
		retVal = true;
		Log_SetStringToLog(_refCharacter.name + " " + _refCharacter.lastname + " " + TranslateString("","has gained a new level! (Now level") + " " + _refCharacter.rank + ")");
		PlayStereoSound("interface\new_level.wav");
	}
	if(retVal)
	{
		if(IsOfficer(_refCharacter) || IsCompanion(_refCharacter))
		{
			AddMsgToCharacter(_refCharacter,MSGICON_LEVELUP);
		}
	}
	return retVal;
	//LanguageCloseFile(tmpLangFileID);
}
// NK <--

int CalculateExperienceFromRank(int _Rank)
{
	if(_Rank<2) return 0;
	int retVal = (MakeInt(1000 * pow(_Rank-1,2.3))/1000)*1000;
	return retVal;
}

// NK -->
int GetCharacterMoney(ref rChr)
{
	if( CheckAttribute(rChr,"money") ) return sti(rChr.money);
	return 0;
}

int GetRandCharMoney(ref char, float scalar)
{
	scalar *= 5.0;
	return makeint((floatRet(rand(makeint(scalar/2.0)) + scalar/2.0 > 1,rand(makeint(scalar/2.0)) + scalar/2.0,1)) * (sti(char.rank)/2.0 + fRand(sti(char.rank)) * (fRand(GetSummonSkill(GetMainCharacter(), SKILL_SNEAK)-1)+1))+0.5);
}

/**
 * Returns the ransom of a captive.
 * 
 * If ransom is not set at calltime, it will be calculated.
 * 
 * @param   captive  Reference to captive, whose ransom to return.
 * @return  The ransom, you get for the captive.
 */
int GetPrisonRansomCost(ref captive)
{
	//ref char = CharacterFromID(refCharacter.id); // Swindler: We create a refernce by using a reference to the same object?
	if(!CheckAttribute(captive, "ransom"))
	{
		// Swindler 2006-07-10 -->
		// Calculation code moved to function CalculatePrisonRansomCost(ref character)
		captive.ransom = CalculatePrisonRansomCost(&captive)
		// Swindler <--
	}
	
	return sti(captive.ransom);
}

/**
 * Calculates the ransom of a captive.
 *
 * @param   captive  Reference to captive, whose ransom to calculate.
 * @return  The ransom, you get for the captive.
 */
// Swindler 2006-07-10 -->
// Bugfixing and refactoring of code, previously in GetPrisonRansomCost(ref captive)
int CalculatePrisonRansomCost(ref captive)
{
	// ref shipt = GetShipByType(0); // NK bugfix 04-06 - Swindler 2006-07-10: not necessary anymore, as GetShipByType() now does this check. 
	float srank = sqrt(sqrt(pow(sti(captive.rank),3.0)));
	float sclass;
	float sweight;
	
	if (CheckAttribute(captive, "shiptype"))
	{
		ref shipt = GetShipByID(captive.shiptype);
		sclass = makefloat(10 - sti(shipt.Class));
		sweight = sqrt(makefloat(sti(shipt.Weight)) / 10000 * 508); // This not changed by PRS3 sadly.Changed 04-09-19 to be more accurate, was simply /19.7
	}
	else
	{
		sclass = 6.0;
		sweight = 22.0;
	}
	
	return makeint(sclass * sweight * srank * makefloat(50 + rand(50 + GetSummonSkillFromName(GetMainCharacter(), SKILL_SNEAK)*10))/10.0);
}
// Swindler <--

int GetLevel(ref chref) { if(CheckAttribute(chref,"rank")) { return sti(chref.rank); } return 0; }
// NK <--


// DP mod -->
float CalcOffScalar()
{
	return (1.0 - (makefloat(GetCharacterSkill(GetMainCharacter(),SKILL_LEADERSHIP))*makefloat(1.0+GetCharacterPerkUsing(GetMainCharacter(),"IronWill"))/40.0)) * (0.5 + makefloat(GetDifficulty())*0.5);
}

//JA 26Nov06 -> Update salary system. Pay computed daily for crew and all officers.
int CalcSquadronPayment(ref mchref)
{
	int PaymentQ = CalcOfficerPayOwed(mchref);
	PaymentQ += CalcCrewPayment(&mchref, GetSquadronCrewQuantity(mchref));
	return PaymentQ;
}

int CalcOfficerPayOwed(ref mchref)
{
	int i, j, cn, on;
	float PaymentQ = 0
	for(i = 0; i < 4; i++)
	{
		cn = GetCompanionIndex(mchref, i);
		if(cn == -1) continue;
		if(cn != mchref.index && CheckAttribute(Characters[cn],"quest.OfficerPrice") && GetRemovable(&Characters[cn]))
		{
			if(CheckAttribute(Characters[cn],"quest.OfficerPayOwed")) PaymentQ += sti(Characters[cn].quest.OfficerPayOwed);
		}
		
		for(j = 1; j < 4; j++)
		{
			on = GetOfficersIndex(Characters[cn], j);
			if(on == -1) continue;
			if(CheckAttribute(Characters[on],"quest.OfficerPrice") && GetRemovable(&Characters[on]))
			{
				if(CheckAttribute(Characters[on],"quest.OfficerPayOwed")) PaymentQ += sti(Characters[on].quest.OfficerPayOwed);
			}
		}
	}
	for(i = 0; i < GetPassengersQuantity(mchref); i++)
	{
		cn = GetPassenger(mchref, i);
		if(cn == -1) continue;
		ref curChar = GetCharacter(cn);
		if(CheckAttribute(curChar,"prisoned") || IsOfficer(curChar)) continue;
		if(CheckAttribute(curChar,"quest.OfficerPrice") && GetRemovable(curChar))
		{
			if(CheckAttribute(Characters[cn],"quest.OfficerPayOwed")) PaymentQ += sti(Characters[cn].quest.OfficerPayOwed);
		}
	}
	return makeint(PaymentQ); 
}	

int CalcCrewPayment(ref mchref, int crewQ)
{
	int PaymentQ = 0
	if(CheckAttribute(mchref,"quest.CrewPayOwed")) PaymentQ = stf(mchref.quest.CrewPayOwed);

	int LeaderShip = GetSummonSkillFromName(mchref,SKILL_LEADERSHIP);
	PaymentQ *= (1.0 - (makefloat(LeaderShip)*makefloat(1.0+GetOfficersPerkUsing(mchref,"IronWill"))/40.0)) * (0.5 + makefloat(GetDifficulty())*0.5);
	return makeint(PaymentQ);
}

void DoDailyCrewPay()
{
	int i, j, cn, on;
	float fOffScalar = CalcOffScalar() * SALARY_MULTIPLIER;
	ref mchref = GetMainCharacter();
	int CrewQ = GetSquadronCrewQuantity(mchref);

	for(i = 0; i < 4; i++)
	{
		cn = GetCompanionIndex(mchref, i);
		if(cn == -1) continue;
		if(cn!=sti(mchref.index)) AddDailyOfficerPay(&Characters[cn], COMP_PRICE_SCALAR*fOffScalar);
		for(j = 1; j < 4; j++)
		{
			on = GetOfficersIndex(Characters[cn], j);
			if(on == -1) continue;
			AddDailyOfficerPay(&Characters[on], OFF_PRICE_SCALAR*fOffScalar);	
		}
	}
	for(i = 0; i < GetPassengersQuantity(mchref); i++)
	{
		cn = GetPassenger(mchref, i);
		if(cn == -1) continue;
		ref curChar = GetCharacter(cn);
		if(CheckAttribute(curChar,"prisoned") || IsOfficer(curChar) || IsCompanion(curChar)) continue;
		AddDailyOfficerPay(curChar, PASSENGER_PRICE_SCALAR*fOffScalar);	
	}
	float fCrewPay = 0;
	//add crew pay owed:
	int LeaderShip = GetSummonSkillFromName(mchref,SKILL_LEADERSHIP);
	float fCrewScalar = (1.0 - (makefloat(LeaderShip)*makefloat(1.0+GetOfficersPerkUsing(mchref,"IronWill"))/40.0)) * (0.5 + makefloat(GetDifficulty())*0.5);
	if(CheckAttribute(mchref,"quest.CrewPayOwed")) fCrewPay = stf(mchref.quest.CrewPayOwed);
	fCrewPay += crewQ*BASE_CREW_PAY *12/365 * fCrewScalar * SALARY_MULTIPLIER;
	mchref.quest.CrewPayOwed = fCrewPay;
}

void AddDailyOfficerPay(ref curChar, int PayMult)
{
	if(CheckAttribute(curChar,"quest.OfficerPrice") && GetRemovable(curChar)) //check that officer should be paid
	{
		float fOPay = 0;
		if(CheckAttribute(curChar,"quest.OfficerPayOwed")) fOPay = stf(curChar.quest.OfficerPayOwed);
		fOPay += stf(curChar.quest.OfficerPrice)*PayMult*12/365;
		curChar.quest.OfficerPayOwed = fOPay;
	}
}

int GetEstimatedOfficerPay()
{
	int i, j, cn, on;
	float fOffScalar = CalcOffScalar() * SALARY_MULTIPLIER;
	ref mchref = GetMainCharacter();
	float fEstTotalPay = 0;
	for(i = 0; i < 4; i++)
	{
		cn = GetCompanionIndex(mchref, i);
		if(cn == -1) continue;
		if(cn!=sti(mchref.index)) fEstTotalPay += stf(Characters[cn].quest.OfficerPrice)*COMP_PRICE_SCALAR*fOffScalar;
		for(j = 1; j < 4; j++)
		{
			on = GetOfficersIndex(Characters[cn], j);
			if(on == -1) continue;
			fEstTotalPay += stf(Characters[on].quest.OfficerPrice)*OFF_PRICE_SCALAR*fOffScalar;
		}
	}
	for(i = 0; i < GetPassengersQuantity(mchref); i++)
	{
		cn = GetPassenger(mchref, i);
		if(cn == -1) continue;
		ref curChar = GetCharacter(cn);
		if(CheckAttribute(curChar,"prisoned") || IsOfficer(curChar) || IsCompanion(curChar)) continue;
		fEstTotalPay += stf(Characters[cn].quest.OfficerPrice)*PASSENGER_PRICE_SCALAR*fOffScalar;
	}
	return makeint(fEstTotalPay);
}

int GetEstimatedCrewPay()
{
	ref mchref = GetMainCharacter();
	float fEstCrewPay = 0;
	//add crew pay owed:
	int LeaderShip = GetSummonSkillFromName(mchref,SKILL_LEADERSHIP);
	float fCrewScalar = (1.0 - (makefloat(LeaderShip)*makefloat(1.0+GetOfficersPerkUsing(mchref,"IronWill"))/40.0)) * (0.5 + makefloat(GetDifficulty())*0.5);
	fEstCrewPay += GetSquadronCrewQuantity(mchref)*BASE_CREW_PAY * fCrewScalar * SALARY_MULTIPLIER;
	return makeint(fEstCrewPay);
}

// <-- JA

int AddMoneyToCharacter(ref _refCharacter,int _Money)
{
	if(CheckAttribute(_refCharacter,"Money")) int newMoney = sti(_refCharacter.Money) + _Money;
	if(newMoney<0) newMoney=0;
	_refCharacter.Money = newMoney;
	return newMoney;
}

// RM Put these in Char_ut.c -->
/*NEW PROPERTY:
char.wealth = personal wealth; default to 4000gp (200x20)
char.land = personal land, in acres; default to 0.
Add interface on char sheet--or maybe talk to qm?--to let you loan money to party.
Change quests so the personal ones pay the character personally. (i.e Patric)?
*/
int GetCharacterWealth(ref char)
{
	int wealth = 500;
	if(CheckAttribute(char,"wealth")) wealth = sti(char.wealth);
	char.wealth = wealth;
	return sti(char.wealth);
}

int AddWealthToCharacter(ref _refCharacter, int _wealth)
{
	int newwealth = GetCharacterWealth(_refCharacter) + _wealth;
	if(newwealth<0) newwealth=0;
	_refCharacter.wealth = newwealth;
	return newwealth;
}

int GetCharacterLand(ref char)
{
	int land = 0;
	if( CheckAttribute(char,"land") ) land = sti(char.land);
	char.land = land;
	return sti(char.land);
}


int AddLandToCharacter(ref _refCharacter,int _land)
{
	int newland = GetCharacterLand(_refCharacter) + _land;
	if(newland<0) newland=0;
	_refCharacter.land = newland;
	return newland;
}


//returns char's rank with nation
int GetRank(ref char, int iNation)
{
	int rank = 0;
	string sNation = iNation;
	if(CheckAttribute(char,"nations."+sNation+".Rank"))
		rank = sti(char.nations.(sNation).Rank);
	return rank;
}

//returns char's OLD rank with nation; oldrank assigned on LeaveService()
int GetOldRank(ref char, int iNation)
{
	int rank = 0;
	string sNation = iNation;
	if(CheckAttribute(char,"nations."+sNation+".OldRank"))
		rank = sti(char.nations.(sNation).OldRank);
	return rank;
}

//gets best rank
int GetBestRank(ref char)
{
	int bestrank = 0;
	for(int i = 0; i < MAX_NATIONS; i++)
	{
		if(GetRank(char, i) > bestrank)
		{
			bestrank = GetRank(char, i);
		}
	}
	return bestrank;
}

//returns the name of char's rank with nation.
string GetRankName(ref char, int iNation)
{
	string rn = GetRank(char, iNation);
	if(GetRank(char, iNation) && CheckAttribute(Nations[iNation],"Ranks."+rn)) return Nations[iNation].Ranks.(rn);
	// 05-07-18 fix to use getmyaddress
	object tempchar;
	tempchar.nation = iNation;
	return GetMyAddressForm(&tempchar, &char, ADDR_CIVIL, false, false);
}

//returns the name of rank in iNation
string GetRankNameDirect(ref char, int iNation, int rank)
{
//	if(iNation == PIRATE && rank < 1) rank = 1;
	// LDH 08Oct06 fix for "Known as mister" at rank 13
	if(iNation == PIRATE) rank = iclamp(1, sti(Nations[iNation].Ranks.Quantity), rank);
	string rn = rank;
	if(CheckAttribute(Nations[iNation],"Ranks."+rn)) return Nations[iNation].Ranks.(rn);
	// 05-07-18 fix to use getmyaddress
	object tempchar;
	tempchar.nation = iNation;
	return GetMyAddressForm(&tempchar, &char, ADDR_CIVIL, false, false);
}

/*NEW PROPERTY: char.title. Use this instead of firstname in dialogs if(char.title != "")
for now, I'm backing up char.name to char.firstname and setting char.name to char.title,
so I don't have to rewrite all that dialog.
*/

//updates title by checking for best rank. Overwrites name, puts actual name in firstname
int UpdateTitle(ref char)
{
	int bestrank = 0;
	for(int i = 0; i < MAX_NATIONS; i++)
	{
		if(GetRank(char, i) > bestrank)
		{
			bestrank = GetRank(char, i);
			char.title = GetRankName(char, i);
			if(!CheckAttribute(char,"firstname")) char.firstname = char.name;
			if (XI_ConvertString(char.title) == "")
				char.name = char.title;//MAXIMUS
			else
				char.name = XI_ConvertString(char.title);
		}
	}
	if(!bestrank && CheckAttribute(char,"firstname"))
	{
		if (XI_ConvertString(char.firstname) == "")
			char.name = char.firstname;//MAXIMUS
		else
			char.name = XI_ConvertString(char.firstname);
		DeleteAttribute(&char, "title");
		// KK DeleteAttribute(&char,"firstname"); // This line removed first name leaving only surname.
	}
	return bestrank;
}

/*promotes char in service of iNation (if possible) and returns new rank; also adds
reqnextrank * GOVREL_RANKSCALAR points to govrel.
returns -1 if not possible. Also sets char.title to best title, and backs up char.name
to char.firstname (if it hasn't already), and sets char.name to char.title. */
int Promote(ref char, ref gov, int iNation)
{
	string sNation = iNation;
	int curRank = GetRank(char, iNation);
	if(curRank >= sti(Nations[iNation].Ranks.Quantity)) return false;
	ChangeGovRelation(&char, &gov, GOVREL_RANKSCALAR*RequiredNextRank(char, iNation));
	curRank++;
	char.nations.(sNation).Rank = curRank;
	AddLandToCharacter(&char, curRank*LAND_PER_RANK);
	UpdateTitle(&char);
	GivePromotionReward(); // PB
	return curRank;
}

bool PromoteCanBe(ref char, int iNation)
{
	if(GetRank(char, iNation) >= sti(Nations[iNation].Ranks.Quantity)) return false;
	return true;
}
//finds land given to char by nation by the time char is this rank
int GetLandFromRank(int rank)
{
	int land = 0;
	for(int i = 1; i <= rank; i++) land += i*LAND_PER_RANK;
	return land;
}

//sets rank of char in service of iNation to newrank, and sets points to that rank
float SetRank(ref char, int iNation, int newrank)
{
	string sNation = iNation;
	char.nations.(sNation).Rank = newrank;
	UpdateTitle(&char);
	float points = RequiredNextRankDirect(newrank);
	SetRMRelation(&char, iNation, points);
// KK -->
	if (ENABLE_FLAGS == 1) {
		ReceiveLetterOfMarque(iNation);
		SetActualRMRelation(iNation, points);
	}
// <-- KK
	return points;
}

//sets rank of char in service of iNation to newrank, and does not change points
void SetRankDirect(ref char, int iNation, int newrank)
{
	string sNation = iNation;
	char.nations.(sNation).Rank = newrank;
	UpdateTitle(&char);
}

//sets old rank to oldrank
void SetOldRank(ref char, int iNation, int oldrank)
{
	string sNation = iNation;
// KK -->
	aref arTmp;
	makearef(arTmp, char.nations.(sNation));
	arTmp.OldRank = oldrank;
// <-- KK
}

//chooses best flag for char
int ChooseBestFlag(ref char)
{
	int bestnat = RMGetHighestRelation(&char); // 04-12-06 moved the code here to this function back in nations.c
	char.nation = bestnat;
	return bestnat;
}

//removes char from service of iNation: sets rank to 0, puts old rank in nation.OldRank, updates title, sets
//rmrelation to after_attack. If rep < min, confiscates land, sets RMrel to war, sets soldiers hostile, does
//not give char oldrank
bool LeaveService(ref char, int iNation, bool override)
{
	bool leavebad = false;
	if(sti(char.reputation) < REP_LEAVEMIN) leavebad = true;
	if(override) leavebad = true;
	string sNation = iNation;
	int curRank = GetRank(char, iNation);
	char.nations.(sNation).Rank = 0;
	char.nations.(sNation).OldRank = 0;
	if(curRank)
	{
		aref arTmp; // KK
		if(leavebad)
		{
			if(GetCharacterLand(char) >= GetLandFromRank(curRank)) AddLandToCharacter(&char, -GetLandFromRank(curRank));
			curRank = 0;
		}
// KK -->
		makearef(arTmp, char.nations.(sNation));
		arTmp.OldRank = curRank;
// <-- KK
	}
	UpdateTitle(&char);
	if(leavebad)
	{
		if(GetRMRelation(&char, iNation) > REL_WAR) SetRMRelation(&char, iNation, REL_WAR);
// KK -->
		if (ENABLE_FLAGS == 1)
			if(GetActualRMRelation(iNation) > REL_WAR) SetActualRMRelation(iNation, REL_WAR);

// <-- KK
		//if(GetRMKills(&char, iNation) < RM_GROUP_MINKILLS) SetRMKills(&Char, iNation, RM_GROUP_MINKILLS);
		LAi_group_SetRelation(GetSoldiersName(iNation)+"_SOLDIERS", LAI_GROUP_PLAYER, LAI_GROUP_ENEMY);
		//SetAllSoldierGroups(&char);
	}
	else {
		if(GetRMRelation(&char, iNation) > REL_AFTERATTACK) SetRMRelation(&char, iNation, REL_AFTERATTACK);
// KK -->
		if (ENABLE_FLAGS == 1) {
			if(GetActualRMRelation(iNation) > REL_AFTERATTACK) SetActualRMRelation(iNation, REL_AFTERATTACK);
		}
// <-- KK
	}

// KK -->
	// Lost LoM
	if (ENABLE_FLAGS == 1) {
		LooseLetterOfMarque(iNation);
		HoistFlag(sti(char.nation));
	}
// <-- KK

	//choose new flag
// KK -->
	if (ENABLE_FLAGS == 0) {
		if(sti(char.nation) == iNation && iNation != PIRATE) ChooseBestFlag(&char);
	}
// <-- KK
	if(leavebad) return true;
	return false;
}


//returns points required for next rank of char in service of nation.
float RequiredNextRank(ref char, int iNation)
{
	float nextrank = makefloat(GetRank(char, iNation)) + 1.0 + NEXTRANK_ADD;
	nextrank *= NEXTRANK_COEFF;
	float retVal = pow(nextrank,NEXTRANK_POW);
	return retVal * NEXTRANK_SCALAR;
}

//returns points required for specified rank
float RequiredNextRankDirect(int rank)
{
	float nextrank = makefloat(rank) + NEXTRANK_ADD; // NK bugfix 04-09-08
	nextrank *= NEXTRANK_COEFF;
	float retVal = pow(nextrank,NEXTRANK_POW);
	return retVal * NEXTRANK_SCALAR;
}

//returns rank, based on points
int GetRankFromPoints(float points) // NK change to int func 04-09-16. Stupid typo.
{
	int rank = 0;
	for(rank = 0; rank <= MAX_RANK; rank++)
	{
		if(points < RequiredNextRankDirect(rank)) { break; }
	}
	return rank;
}

//returns fame. If iNation == -1, interprets this as getting fame for general purposes (i.e. crew)
float GetFame(ref pchar, int iNation)
{
	bool crew = (iNation == -1);
	int rank = sti(pchar.rank);
	int i;
	int PerkIron;
	int PerkChar;
	int PerkWC;
	int skillLead;
	int skillLuck;
	float nrank = 1.0;
	int numnat;
	if(crew)
	{
		PerkIron = GetOfficersPerkUsing(pchar,"IronWill");
		PerkChar = GetOfficersPerkUsing(pchar,"Charisma"); //to be added, prereq iron will
		PerkWC = GetOfficersPerkUsing(pchar,"WitCharm"); //to be added, prereq charisma
		skillLead = GetSummonSkillFromName(pchar,SKILL_LEADERSHIP);
		skillLuck = GetSummonSkillFromName(pchar,SKILL_SNEAK);
		nrank = 0;
		numnat = 0;
		for(i = 0; i < MAX_NATIONS; i++)
		{
			if(GetRank(pchar, i))
			{
				numnat++;
				nrank += makefloat(GetRank(pchar, i))/24.0;
			}
		}
		if(numnat>0) { nrank = (nrank / makefloat(numnat)) * sqrt(numnat); }
		else { nrank = 0; }
	}
	else
	{
		PerkIron = GetCharacterPerkUsing(pchar,"IronWill");
		PerkChar = GetCharacterPerkUsing(pchar,"Charisma"); //to be added, prereq iron will
		PerkWC = GetCharacterPerkUsing(pchar,"WitCharm"); //to be added, prereq charisma
		skillLead = GetCharacterSkill(pchar,SKILL_LEADERSHIP);
		skillLuck = GetCharacterSkill(pchar,SKILL_SNEAK);
		if(iNation == PIRATE) // new code 04-09-06, so if querying pirate fame you get extra for having ranks.
		{
			for(i = 0; i < MAX_NATIONS; i++)
			{
				if(GetRank(pchar, i))
				{
					numnat++;
					nrank += makefloat(GetRank(pchar, i))/24.0;
				}
			}
			if(numnat>0) { nrank = (nrank / makefloat(numnat)) * sqrt(numnat); }
			else { nrank = 0; }
		}
		else
		{
			nrank = makefloat(GetRank(pchar, iNation))/12.0;
		}
	}
	
	float lastcsr = 1.0;
	if(CheckAttribute(pchar,"Crewstatus.lastcsr")) lastcsr = stf(pchar.CrewStatus.lastcsr);
	else pchar.CrewStatus.lastcsr = lastcsr;
	//unclamp lastcsr
	if(lastcsr > 1.0) lastcsr = 1.0/(2.0-lastcsr);
	//mult csr
	if(lastcsr > 1) lastcsr = 1.0 + (lastcsr-1.0) * FAME_CSR_SCALE;
	//else lastcsr = 1 - ((1 - lastcsr) * FAME_CSR_SCALE);

	//clamp csr to min/max
	if(lastcsr < FAME_CSR_MIN) lastcsr = FAME_CSR_MIN;
	if(lastcsr > FAME_CSR_MAX) lastcsr = FAME_CSR_MAX;

	int gold = GetCharacterWealth(pchar);
	int land = GetCharacterLand(pchar);

	float perkscale = 0.0;
	if(PerkIron)
	{
		perkscale = 0.25;
		if(PerkChar)
		{
			perkscale = 0.5;
			if(PerkWC) { perkscale = 1.0; }
		}
	}

	float points = 1.0;
	//calc points; 200 good for lvl10 char with 5/5, 300k gp, 1k acres
	points *= (1.0 + skillLead/10.0 + rand(skillLuck)/20.0 + perkscale);
	points *= sqrt(rank)/2.0;
	points *= (1.0 + nrank);
	points *= (sqrt(makefloat(gold))/20.0 + floatret(!crew,3.0*sqrt(pow(land/100.0,1.25)),0));
	if(crew) points *= lastcsr;
	if(iNation == PIRATE) { points *= (FAME_PIRNATION_CSR_BASE+ lastcsr * FAME_PIRNATION_CSR_SCALAR); } // NK 04-09-06 so if querying fame with nation pirate, csr counts.
	points *= FAME_SCALAR;
	if(crew) points = 0.1 + sqrt(sqrt(pow(points,1.5))) / 10.0;
	return points;
}

//returns character's score
float GetScore(ref char)
{
	int i;
	float score = 0;
	for(i = 0; i < MAX_NATIONS; i++) score += GetFame(char, i);
	score /= MAX_NATIONS;
	score = sqrt(score)*10; // - (6 + sti(char.rank)*0);
	if(CheckAttribute(char,"married"))
	{
		if(sti(char.married))
		{
			score += MRGetMarPoints(CharacterFromID(char.married.id)) + MRGetTalkPoints(CharacterFromID(char.married.id));
		}
	}
	if(CheckAttribute(char,"Mistress"))
	{
		aref mist;
		ref cmist;
		makearef(mist,char.mistress);
		if(GetAttributesNum(mist))
		{
			for(i = 0; i < GetAttributesNum(mist); i++)
			{
				cmist = CharacterFromID(GetAttributeName(GetAttributeN(mist, i)));
				score += MR_MIST_FAME_SCL * (MRGetMarPoints(cmist) + MRGetTalkPoints(cmist));
			}
		}
	}
	score *= (0.5 + makefloat(GetDifficulty())/6.0);
	float atcsr = 1.0;
	if(CheckAttribute(char,"Crewstatus.alltimecsr")) { atcsr = stf(char.Crewstatus.alltimecsr); }
	else { char.Crewstatus.alltimecsr = atcsr; }
	//clamp csr to max 1.5
	if(atcsr > 1.0) atcsr = 1.0 + (atcsr-1.0) / 2.0;
	score *= atcsr;
	score = score - (6.0 + stf(char.rank)*2);
	if(score<1.0) score = 1.0;
	return score;
}

// start Marr. relations

/*New Property: gov.MR (marriageable relations; for governors).
MR.quantity = number of relations for that gov
add property MR.(i) (where i is the number of the Marriageable Relation, as above) = that relation's char id

that relation has property
char.relationtype = niece or daughter.
char.father = gov id.
char.relnum = relation number.
char.reqpoints = required points for that relation to be available.
char.marpoints  = required points to marry (see below)
char.talkpoints = points based on num times talked to; incremented in char's dialog.*/

/* old functions; maybe I'll use them instead of SetupMR some day...
int GetMRIndex(ref gov, int iRelnum)
{
	string relnum = iRelnum;
	if(!CheckAttribute(gov,"MR."+relnum)) return -1;
	else return GetCharacterIndex(gov.MR.(relnum));
}


ref GetMR(ref gov, int iRelnum)
{
	string relnum = iRelnum;
	return CharacterFromID(gov.MR.(relnum));
}


//returns object of all available relations. For use in gov dialog, to make them appear.
//note: for now, fixed to getGovR*2 + RMRel/2, && getgr >= 0
object FindAvailMR(ref char, ref gov)
{
	object MRs;
	int i, size;
	string ta;
	size = 0;
	MRs.quantity = size;
	if(!CheckAttribute(gov,"MR.quantity")) return MRs;
	if(sti(gov.MR.quantity) == 0) return MRs;
	if(GetGovRelation(char, gov) <= 0) return MRs;
	int MRqty = sti(gov.MR.quantity);
	for(i = 0; i < MRqty; i++)
	{
		if(GetGovRelation(char, gov)*2.0 + GetRMRelation(char, sti(gov.nation))/2.0 >= stf(Characters[GetMRIndex(gov, i)].reqpoints))
		{
			size++;
			ta = i;
			MRs.quantity = size;
			MRs.(ta) = gov.MR.("MR"+i);
		}
	}
	return MRs;
}
*/

float MRGetMarpoints(ref mchar)
{
	return stf(mchar.marpoints);
}

float MRGetTalkpoints(ref mchar)
{
	return stf(mchar.talkpoints);
}

float MRCalcMarpoints(ref pchar, int iNation)
{
	float mp = GetFame(pchar, iNation);
	mp *= MR_MPCOEFF;
	if(MR_MPPOW < 1.0) //because POTC does NOT support exponents of less than 1, strangely...
	{
		if(MR_MPPOW > 0.5) { mp = sqrt(pow(mp,MR_MPPOW*2)); }
		else { mp = sqrt(sqrt(pow(mp,MR_MPPOW*4))); } // so pow must be >= 0.25!
	}
	else {mp = pow(mp, MR_MPPOW); }
	mp *= MR_MPSCALAR;
	mp += MR_MPOFFSET;
	mp *= (MR_MPBASESCALE + frnd()*MR_MPRANDSCALE);
	if(mp< MR_MPMIN) mp = MR_MPMIN;
	return mp;
}

int MRGetWifeIndex() { return GetCharacterIndex(Characters[GetMainCharacterIndex()].married.id); };

ref MRGetWife() {return GetCharacter(MRGetWifeIndex()); }


// find if char can marry mchar. Based on fame with mchar's nation, and points from
// previous chats. prop is for if this is a proposal, or if just talking (check to
// make informant.)
bool MRCanMarry(ref char, ref mchar, bool prop)
{
	return (MRCanMarryRatio(&char, &mchar, prop) >= 1.0);
}


float MRCanMarryRatio(ref char, ref mchar, bool prop)
{
	//init vars
	prop = !prop;
	float marpoints = stf(mchar.marpoints) * (1.0 + makefloat(prop)*MR_NONPROP_SCALAR);
	float current = GetFame(&char, sti(mchar.nation));
	if(CheckAttribute(mchar,"talkpoints")) current += stf(mchar.talkpoints);
	
	return  current / marpoints; 
}

float MRGetAddTalkpoints(ref char, ref mchar)
{
	float skillLead = GetCharacterSkill(char,SKILL_LEADERSHIP);
	int skillLuck = GetCharacterSkill(char,SKILL_SNEAK);
	bool PerkIron = GetCharacterPerkUsing(char,"IronWill");
	bool PerkChar = 0; //GetCharacterPerkUsing(char,"Charisma"); //to be added, prereq iron will
	bool PerkWC = 0; //GetCharacterPerkUsing(char,"WitCharm"); //to be added, prereq charisma
	return MRTALKPOINTS_SCALAR*(skillLead/5.0 * floatRet(PerkIron, floatRet(PerkChar, floatRet(PerkWC, 2.0, 1.5), 1.25), 1.0) + makefloat(rand(skillLuck))/10.0);
}

float MRAddTalkpoints(ref char, ref mchar)
{
	float curpoints = 0;
	if(CheckAttribute(mchar,"talkpoints")) curpoints = stf(mchar.talkpoints);

	curpoints += MRGetAddTalkpoints(&char, &mchar);
	mchar.talkpoints = curpoints;
	return curpoints;
}

// end Marr. relations


//find if merch will allow char to trade, based on char's RMRel with merch's
//nation, and char's rep.
bool TradeCheck(ref char, ref merch, bool first)
{
	if (LAi_IsCapturedLocation) return true; // KK
	int mNation = sti(merch.nation);
	int rep = sti(char.reputation);
	float rel = 0.;
// KK -->
	if (ENABLE_FLAGS == 0)
		rel = GetRMRelation(char, mNation);
	else
		rel = GetFlagRMRelation(mNation);
// <-- KK
	//find loc
	bool strengthcomp;
	int locIdx = FindLoadedLocation();
	if(locIdx<0) return true;
	if( !CheckAttribute(&Locations[locIdx],"townsack") ) return true;
	
	//town fight strength vs. squadron fight strength.
	int ttroops = GetTownNumTroops(Locations[locIdx].townsack);
	int ptroops = GetSquadronCrewQuantity(char);
	if(ttroops > ptroops * 4) strengthcomp = true;
	if(ptroops > ttroops * 3) strengthcomp = true;

	//actual checks
	if(mNation == PIRATE) return true;
	if(rel > REL_NEUTRAL && rep > TRADEREP_MIN) return true;
	if(rel > REL_WAR  && rep > TRADEREP_NEUTRAL) return true;
	if(rep > TRADEREP_WAR && strengthcomp && rep > TRADEREP_STRENGTH) return true;
	if(rep > TRADEREP_ALL) return true;
//MAXIMUS -[we are here already, why we can't complete our mission?]->
	if(first && CheckQuestAttribute("generate_trade_quest_progress", "begin") || CheckQuestAttribute("generate_trade_quest_progress",  "failed"))
	{
		if(CheckQuestAttribute("generate_trade_quest.iTradeNation", GetCurrentLocationNation()) && char.quest.generate_trade_quest.iTradeColony == GetCurrentTownID()) return true;
	}
//MAXIMUS <-[we are here already, why we can't complete our mission?]-
	return false;
}


void SetBaseShipData(ref refCharacter)
{
	int  i;
	aref refShip;
	int  nShipType;
	ref  refBaseShip;

	if (!CheckAttribute(refCharacter, "index")) return;
	if(CheckAttribute(refCharacter,"Ship"))
	{
		makearef(refShip,refCharacter.Ship);

		nShipType = GetCharacterShipType(refCharacter);
		if(nShipType==SHIP_NOTUSED) return;
		if(!CheckAttribute(refShip,"stats")) {
//KB - Tuning ships - changed call to SetRandomStatsToShip
			SetRandomStatsToShip(sti(refCharacter.index), nShipType, sti(refCharacter.nation)); // PRS3
//KB - orig SetRandomStatsToShip(refShip, nShipType, sti(refCharacter.nation)); // PRS3
		}
		refBaseShip = GetShipByType(nShipType);

		refShip.HP = GetLocalShipAttrib(refShip, refBaseShip, "HP");
		refShip.SP = GetLocalShipAttrib(refShip, refBaseShip, "SP");

		refShip.Pos.x = 0;
		refShip.Pos.z = 0;
		refShip.Ang = "";
		refShip.Cannons.Borts = "";
		if(USE_REAL_CANNONS) refShip.Cannons.Charge.Type = GOOD_BALLS; // KNB
		else refShip.Cannons.Charge.Type = GOOD_BOMBS;
		if(!CheckAttribute(refShip,"Cannons.Type")) { refShip.Cannons.Type = MakeInt(GetLocalShipAttrib(refShip, refBaseShip, "Cannon")); }

		if(!CheckAttribute(refShip,"Crew.Morale"))	{ refShip.Crew.Morale = 45;	}
		if(!CheckAttribute(refShip,"Crew.Quantity")) { refShip.Crew.Quantity = GetLocalShipAttrib(refShip, refBaseShip, "MaxCrew"); }
	// TIH --> code cleanup, and missing bracket fix 7-7-06
		string goodsName;
		if(GetCargoLoad(refCharacter)<=0)
		{
			refCharacter.Ship.Cargo.Load = 0;
			for(i=0; i<GOODS_QUANTITY; i++)
			{
				goodsName = Goods[i].Name;
				refCharacter.Ship.Cargo.Goods.(goodsName) = 0;
			}

			// TIH --> ships need food and rum if mod is on Aug31'06
			if (FOOD_ON) {
				int goodSum = 0;
				i = GetCharacterFreeSpace(refCharacter,GOOD_WHEAT);
				if(i>0) 
				{ 
					goodSum = makeint(2 + sti(refCharacter.ship.crew.quantity) * FOOD_PER_CREW * WHEAT_DAYS);// at least 2 wheat
					if(i>=goodSum)	{ SetCharacterGoods(refCharacter,GOOD_WHEAT,goodSum); }
					else  			{ SetCharacterGoods(refCharacter,GOOD_WHEAT,makeint(i/2)); }
				}
				i = GetCharacterFreeSpace(refCharacter,GOOD_RUM);
				if(i>0) 
				{ 
					goodSum = makeint(2 + sti(refCharacter.ship.crew.quantity) * FOOD_PER_CREW * RUM_DAYS);// at least 2 rum
					if(i>=goodSum)	{ SetCharacterGoods(refCharacter,GOOD_RUM,goodSum); }
					else  			{ SetCharacterGoods(refCharacter,GOOD_RUM,i); }
				}
			}
			// TIH <--

			// cannonballs
			i = GetCharacterFreeSpace(refCharacter,GOOD_BALLS);
			if(i>0)
			{
				if(i>=DEFAULT_NUM_BALLS) 	{ SetCharacterGoods(refCharacter,GOOD_BALLS,DEFAULT_NUM_BALLS); }
				else 						{ SetCharacterGoods(refCharacter,GOOD_BALLS,i); }
			}
			
			// grapes
			i = GetCharacterFreeSpace(refCharacter,GOOD_GRAPES);
			if(i>0)
			{
				if(i>=DEFAULT_NUM_GRAPE) 	{ SetCharacterGoods(refCharacter,GOOD_GRAPES,DEFAULT_NUM_GRAPE); }
				else 						{ SetCharacterGoods(refCharacter,GOOD_GRAPES,i); }
			}
			
			// knippels
			i = GetCharacterFreeSpace(refCharacter,GOOD_KNIPPELS);
			if(i>0)
			{
				if(i>=DEFAULT_NUM_KNIPPELS) { SetCharacterGoods(refCharacter,GOOD_KNIPPELS,DEFAULT_NUM_KNIPPELS); }
				else 						{ SetCharacterGoods(refCharacter,GOOD_KNIPPELS,i); }
			}
			
			// bombs // fixed 05-04-09 NK to use DEFAULT in the cargocheck too, and KNB no bombs. // TIH added mod toggle 7-7-06
			if (!USE_REAL_CANNONS)
			{
				i = GetCharacterFreeSpace(refCharacter,GOOD_BOMBS);
				if(i>0)
				{
					if(i>=DEFAULT_NUM_BOMBS) 	{ SetCharacterGoods(refCharacter,GOOD_BOMBS,DEFAULT_NUM_BOMBS); }
					else 						{ SetCharacterGoods(refCharacter,GOOD_BOMBS,i); }
				}
			}
			
			// added by MAXIMUS [gunpowder mod] -->
			// gunpowder
			if (CANNONPOWDER_MOD) // TIH --> mod toggle 7-7-06
			{
				i = GetCharacterFreeSpace(refCharacter,GOOD_GUNPOWDER);
				if(i>0)
				{
					ref rCannon; makeref(rCannon,Cannon[GetCaracterShipCannonsType(refCharacter)]);
					int basePwdr = 0;
					if(CheckAttribute(rCannon,"gunpowder")) basePwdr = makeint(sti(rCannon.gunpowder) * sti(GetCannonCurQuantity(refCharacter)));
					float averageQty = 0.0;
					if (USE_REAL_CANNONS) 	{ averageQty = makefloat(GetCargoGoods(refCharacter,GOOD_BALLS) + GetCargoGoods(refCharacter,GOOD_GRAPES) + GetCargoGoods(refCharacter,GOOD_KNIPPELS))/3; }
					else 					{ averageQty = makefloat(GetCargoGoods(refCharacter,GOOD_BALLS) + GetCargoGoods(refCharacter,GOOD_GRAPES) + GetCargoGoods(refCharacter,GOOD_KNIPPELS) + GetCargoGoods(refCharacter,GOOD_BOMBS))/4; }
					float canCharge = 0;
					if(sti(GetCannonCurQuantity(refCharacter))>0) canCharge = makefloat(averageQty/makefloat(GetCannonCurQuantity(refCharacter)));
					int loadPwdr = makeint(makefloat(basePwdr * canCharge)) + makeint(sti(refCharacter.ship.crew.quantity)*3);
					if(i>=loadPwdr) {
						SetCharacterGoods(refCharacter, GOOD_GUNPOWDER, loadPwdr);
					} else {
						SetCharacterGoods(refCharacter, GOOD_GUNPOWDER, i);
					}
				}
			}
			// TIH <-- mod toggle
			// added by MAXIMUS [gunpowder mod] <--
		}
	// TIH <-- code cleanup
	}
}

void SetBaseFellows(object refCharacter)
{
	aref tmpRef;

	makearef(tmpRef,refCharacter.Fellows.Companions);
	tmpRef.id1 = -1;
	tmpRef.id2 = -1;
	tmpRef.id3 = -1;

	makearef(tmpRef,refCharacter.Fellows.Passengers);
	tmpRef.Quantity = 0;
	tmpRef.id1 = -1;
	tmpRef.id2 = -1;
	tmpRef.id3 = -1;
	tmpRef.id4 = -1;
	tmpRef.id5 = -1;
	tmpRef.id6 = -1;
	tmpRef.id7 = -1;
	tmpRef.id8 = -1;

	makearef(tmpRef,refCharacter.Fellows.Passengers.Officers);
	tmpRef.id1 = -1;
	tmpRef.id2 = -1;
	tmpRef.id3 = -1;
}

// statistics utilite
void DoShipKilledStatistics(int killerCharacterIdx,int deadCharacterIdx)
{
	ref killer = GetCharacter(killerCharacterIdx);
	ref dead = GetCharacter(deadCharacterIdx);

	string attrName = Nations[sti(dead.nation)].Name;
	int oldValue = GetNationShipKilled(killer,attrName);
	killer.Statistics.KilledShip.Nation.(attrName) = oldValue+1;

	oldValue = GetClassShipKilled(GetCharacterShipClass(dead));
	attrName = "" + GetCharacterShipClass(dead);
	killer.Statistics.KilledShip.Class.(attrName) = oldValue+1;
}

void DoShipCaptureStatistics(int killerCharacterIdx,int captiveCharacterIdx)
{
	ref killer = GetCharacter(killerCharacterIdx);
	ref captive = GetCharacter(captiveCharacterIdx);

	string attrName = Nations[sti(captive.nation)].Name;
	int oldValue = GetNationShipCaptured(killer,attrName);
	killer.Statistics.CapturedShip.Nation.(attrName) = oldValue+1;

	oldValue = GetClassShipCaptured(killer,GetCharacterShipClass(captive));
	attrName = "" + GetCharacterShipClass(captive);
	killer.Statistics.CapturedShip.Class.(attrName) = oldValue+1;
}

int GetNationShipKilled(ref _refCharacter,string nation)
{
	if( CheckAttribute(_refCharacter,"Statistics.KilledShip.Nation." + nation) )
		return sti(_refCharacter.Statistics.KilledShip.Nation.(nation));
	return 0;
}
int GetClassShipKilled(ref _refCharacter,int classNum)
{
	string className = "" + classNum;
	if( CheckAttribute(_refCharacter,"Statistics.KilledShip.Class." + classNum) )
		return sti(_refCharacter.Statistics.KilledShip.Class.(className));
	return 0;
}

int GetNationShipCaptured(ref _refCharacter,string nation)
{
	if( CheckAttribute(_refCharacter,"Statistics.CapturedShip.Nation." + nation) )
		return sti(_refCharacter.Statistics.CapturedShip.Nation.(nation));
	return 0;
}
int GetClassShipCaptured(ref _refCharacter,int classNum)
{
	string className = "" + classNum;
	if( CheckAttribute(_refCharacter,"Statistics.CapturedShip.Class." + classNum) )
		return sti(_refCharacter.Statistics.CapturedShip.Class.(className));
	return 0;
}

// Items Utilite
int GetChrItemQuantity(ref _refCharacter)
{
	aref ar; makearef(ar,_refCharacter.items);
	return GetAttributesNum(ar);
}
bool GiveItem2Character(ref _refCharacter,string itemName)
{
	return TakeNItems(_refCharacter,itemName,1);
}
void TakeItemFromCharacter(ref _refCharacter,string itemName)
{
	TakeNItems(_refCharacter,itemName,-1);
}
bool CheckCharacterItem(ref _refCharacter,string itemName)
{
	if( CheckAttribute(_refCharacter,"Items."+itemName) && sti(_refCharacter.Items.(itemName))>0 )	return true;
	else	return false;
}
int GetCharacterItem(ref _refCharacter,string itemName)
{
	if(CheckAttribute(_refCharacter,"Items."+itemName))
	{
		return sti(_refCharacter.Items.(itemName));
	}
	return 0;
}
bool ReplaceItem(ref _refTakingCharacter,ref _refGivingCharacter,string itemName)
{
	bool retVal = CheckCharacterItem(_refGivingCharacter,itemName);
	if( TakeNItems(_refTakingCharacter,itemName,1) )
		TakeNItems(_refGivingCharacter,itemName,-1);
	return retVal;
}
bool TakeNItems(ref _refCharacter,string itemName, int n)
{
	if(itemName == "") return false;
	int q;
	aref arItm;
	if( Items_FindItem(itemName,&arItm)<0 )
	{
		trace("WARNING!!! Item id = "+itemName+" not implemented");
		return false;
	}
	if( CheckAttribute(arItm,"gold") )
	{
		if( CheckAttribute(_refCharacter,"Money") )	q = sti(_refCharacter.Money);
		else q = 0;
		q += n*sti(arItm.gold);
		if(q<0) {q=0;}
		_refCharacter.Money = q;
		return true;
	}
	if( CheckAttribute(arItm,"price") && sti(arItm.price)==0 )
	{
		if(sti(_refCharacter.index)==GetMainCharacterIndex() && IsEntity(_refCharacter))
		{
			if(n>0)	{Log_SetStringToLog(XI_ConvertString("You take item"));}
			if(n<0)	{Log_SetStringToLog(XI_ConvertString("You give item"));}
			PlayStereoSound("interface\important_item.wav");
		}
		if( n>0 && IsOfficer(_refCharacter) || IsCompanion(_refCharacter) ) {
			AddMsgToCharacter(_refCharacter,MSGICON_GETITEM);
		}
	}
	if(CheckAttribute(arItm, "skill") && !CheckAttribute(_refCharacter, "skiprecalcskill")) // NK 05-06-27 for auto change of 
	{
		for(int sn = 0; sn < 10; sn++)
		{
			DeleteAttribute(&_refCharacter, "skill." + GetSkillName(sn) + ".mod");
			GetCharacterSkill(&_refCharacter, GetSkillName(sn));
		}
	}
	q = GetCharacterItem(_refCharacter,itemName);
	if(q+n<=0) DeleteAttribute(_refCharacter,"Items."+itemName);
	else
	{
		if(q<=0 && GetChrItemQuantity(_refCharacter)>=MAX_ITEM_TAKE) return false;
		_refCharacter.Items.(itemName) = q+n;
	}
	return true;
}

// KK -->
int FindCharacterMap(ref _refCharacter, int number)
{
	if (number <= 0) return -1;
	if (!CheckAttribute(_refCharacter, "Items")) return -1;
	aref curItem,arItem;
	aref rootItems; makearef(rootItems, _refCharacter.Items);
	int num = GetAttributesNum(rootItems);
	int n = 0;
	for (int i = 0; i < num; i++) {
		curItem = GetAttributeN(rootItems, i);
		if (Items_FindItem(GetAttributeName(curItem), &arItem) >= 0) {
			if (CheckAttribute(arItem, "groupID")) {
				if (arItem.groupID == MAP_ITEM_TYPE) n++;
				if (n == number) return sti(arItem.index);
			}
		}
	}
	return -1;
}
// <-- KK

// работа с контрабандой
int FindFirstContrabandGoods(ref _refCharacter)
{
	int i;
	int curStoreIdx = GetCharacterCurrentStore(_refCharacter);
	if(curStoreIdx>=0)
	{
		_refCharacter.FindContrabandGoods.StoreIdx = curStoreIdx;
		for(i=0; i<GOODS_QUANTITY; i++)
		{
			if( GetStoreGoodsType(&Stores[curStoreIdx],i) == TRADE_TYPE_CONTRABAND_NAME )
			{
				if( GetSquadronGoods(_refCharacter,i)>0 )
				{
					_refCharacter.FindContrabandGoods.GoodsIdx = i;
					return i;
				}
			}
		}
		DeleteAttribute(_refCharacter,"FindContrabandGoods");
		return -1;
	}
	int curLocIdx = FindLocation(_refCharacter.location);
	if(curLocIdx<0) return -1;
	int curIslandIdx = GetIslandIdxByLocationIdx(curLocIdx);
	if(curIslandIdx<0) return -1;
	aref islRef; makearef(islRef,Islands[curIslandIdx].Trade.Contraband);
	int n;
	for(i=0;i<GetAttributesNum(islRef);i++)
	{
		n = sti(GetAttributeValue(GetAttributeN(islRef,0)));
		if( GetSquadronGoods(_refCharacter,n)>0 )
		{
			_refCharacter.FindContrabandGoods.IslandIdx = curIslandIdx;
			_refCharacter.FindContrabandGoods.GoodsIdx = i;
			return n;
		}
	}
	return -1;
}

int FindNextContrabandGoods(ref _refCharacter)
{
	int i,n;
	if(CheckAttribute(_refCharacter,"FindContrabandGoods.StoreIdx"))
	{
		if(CheckAttribute(_refCharacter,"FindContrabandGoods.GoodsIdx"))
		{
			int curStoreIdx = sti(_refCharacter.FindContrabandGoods.StoreIdx);
			if(curStoreIdx>=0)
			{
				for(i=sti(_refCharacter.FindContrabandGoods.GoodsIdx)+1; i<GOODS_QUANTITY; i++)
				{
					if( GetStoreGoodsType(&Stores[curStoreIdx],i) == TRADE_TYPE_CONTRABAND_NAME )
					{
						if( GetSquadronGoods(_refCharacter,i)>0 )
						{
							_refCharacter.FindContrabandGoods.GoodsIdx = i;
							return i;
						}
					}
				}
			}
		}
	}
	else
	{
		if(CheckAttribute(_refCharacter,"FindContrabandGoods.IslandIdx"))
		{
			if(CheckAttribute(_refCharacter,"FindContrabandGoods.GoodsIdx"))
			{
				int curIslandIdx = sti(_refCharacter.FindContrabandGoods.IslandIdx);
				if(curIslandIdx>=0)
				{
					int curGoodsNum = sti(_refCharacter.FindContrabandGoods.GoodsIdx) + 1;
					aref islRef; makearef(islRef,Islands[curIslandIdx].Trade.Contraband);
					for(i=curGoodsNum; i<GetAttributesNum(islRef); i++)
					{
						n = GetAttributeValue(GetAttributeN(islRef,i));
						if( GetSquadronGoods(_refCharacter,n)>0 )
						{
							_refCharacter.FindContrabandGoods.GoodsIdx = i;
							return n;
						}
					}
				}
			}
		}
	}
	DeleteAttribute(_refCharacter,"FindContrabandGoods");
	return -1;
}

int GetCharacterCurrentIsland(ref _refCharacter)
{
// KK -->
	/*int curLocNum = FindLocation(Characters[GetMainCharacterIndex()].location);
	if(curLocNum<0) return -1;
	return GetIslandIdxByLocationIdx(curLocNum);*/
	if (!CheckAttribute(_refCharacter, "location")) return -1;
	int locidx = FindLocation(_refCharacter.location);
	if (locidx < 0) return -1;
	return GetIslandIdxByLocationIdx(locidx);
// <-- KK
}
// NK new func for just IDs 05-03-28
string GetIslandIDByLocationID(string locid)
{
	int locIdx = FindLocation(locid);
	if(CheckAttribute(Locations[locIdx],"island")) { return Islands[FindIsland(Locations[locIdx].island)].id; } // NK bugfix 05-04-02
	/*aref rootar,ar;
	makearef(rootar,Locations[0].IslandsList);
	for(int i=0; i<GetAttributesNum(rootar); i++)
	{
		ar = GetAttributeN(rootar,i);
		if( locIdx>=sti(ar.begin) && locIdx<=sti(ar.end) )
		{
			return GetAttributeName(ar);
		}
	}*/
	return "";
}
// NK <--
	
int GetIslandIdxByLocationIdx(int locIdx)
{
	//NK new loc tags 04-08-29
	/*
	//following commented out because it's unnecessary; if loc doesn't have attrib island, then obviously we haven't init'd the new loc tags yet.
	//if things go bang, uncomment it. :)
	ref pchar = GetMainCharacter();
	if(CheckAttribute(pchar,"newloctags"))
	{
		if(sti(pchar.newloctags))
		{*/
			if(CheckAttribute(Locations[locIdx],"island")) { return FindIsland(Locations[locIdx].island); }
		//}
	//}
	// NK <--
	aref rootar,ar;
	makearef(rootar,Locations[0].IslandsList);
	for(int i=0; i<GetAttributesNum(rootar); i++)
	{
		ar = GetAttributeN(rootar,i);
		if( locIdx>=sti(ar.begin) && locIdx<=sti(ar.end) )
		{
			return FindIsland(GetAttributeName(ar));
		}
	}
	return -1;
}

string GetIslandNameByLocationID(string locid)
{
	return FindIslandName(GetIslandIDByLocationID(locid));
}

int GetCharacterCurrentStore(ref _refCharacter)
{
	int i;
	int curLocNum = FindLocation(Characters[GetMainCharacterIndex()].location);
	if(curLocNum<0) return -1;
	if(CheckAttribute(&Locations[curLocNum],"townsack")) return GetTownStoreIndex(Locations[curLocNum].townsack); // NK 05-04-17 use towntable
	if( CheckAttribute(&Locations[curLocNum],"fastreload") )
	{
		string locGroupId = Locations[curLocNum].fastreload;
		for(i=0; i<STORE_QUANTITY; i++)
		{
			if(Stores[i].group==locGroupId)
			{
				return i;
			}
		}
	}
	else
	{
		curLocNum = GetIslandIdxByLocationIdx(curLocNum);
		if(curLocNum<0)	{return -1;}
		for(i=0; i<STORE_QUANTITY; i++)
		{
			if(stores[i].Island==Islands[curLocNum].id)
			{
				return i;
			}
		}
	}

	return  -1;
}

// NK 05-04-19 -->
// make single function for char-mod price. summ = use officers too.
float GetCharPriceMod(ref ch, int priceType, bool summ)
{
	float skillModify = 1.0;
	float skillDelta;
	if(summ) skillDelta = GetSummonSkillFromName(&ch,SKILL_COMMERCE);
	else skillDelta = GetCharacterSkill(&ch,SKILL_COMMERCE);
	if(priceType==PRICE_TYPE_BUY)
	{
		skillModify = 1.4 - skillDelta*0.019;
		if(CheckOfficersPerk(&ch,"AdvancedCommerce"))	{ skillModify -= 0.2; }
		else
		{
			if(CheckOfficersPerk(&ch,"BasicCommerce"))	{ skillModify -= 0.1; }
		}
	}
	else
	{
		skillModify = 0.75 + skillDelta*0.019;
		if(CheckOfficersPerk(&ch,"AdvancedCommerce"))	skillModify += 0.05;
	}
	return skillModify;
}
int GetCurrentIslandGoodsPrice(int GoodsType)
{
	int curStoreIdx = GetCharacterCurrentStore(GetMainCharacter());
	if(curStoreIdx<0) return 0;
	// NK to use global store's town aref. 05-04-15
	string tn = GetTownIDFromGroup(Stores[curStoreIdx].group);
	//if(tn != "") { rStoreTown = GetTownFromID(tn); }
	// NK <--
	return GetStoreGoodsPrice(&Stores[curStoreIdx],GoodsType,PRICE_TYPE_SELL,GetMainCharacter(), 0); // NK
}

int GetCurrentLocationNation()
{
	int curLocNum = FindLocation(Characters[GetMainCharacterIndex()].location);
	if(curLocNum<0) return -1;
	return GetLocationNation(&Locations[curLocNum]);
}

void SetRandomNameToCharacter(ref rCharacter)
{
	if (sti(rCharacter.index) == GetMainCharacterIndex()) return;	// TIH random name on death fix 7-7-06
// MAXIMUS random name on death fix 24.11.2006 -->
	if(HasSubStr(GetMySimpleOldName(rCharacter),"soldier") || HasSubStr(GetMySimpleOldName(rCharacter),XI_ConvertString("soldier")))
	{
		int tmpNameFileID = LanguageOpenFile("characters_names.txt");
		if(LanguageConvertString(tmpNameFileID,rCharacter.old.name)!="") { rCharacter.name = LanguageConvertString(tmpNameFileID,rCharacter.old.name); }
		else { rCharacter.name = rCharacter.old.name; }
		if(LanguageConvertString(tmpNameFileID,rCharacter.old.lastname)!="") { rCharacter.lastname = LanguageConvertString(tmpNameFileID,rCharacter.old.lastname); }
		else { rCharacter.lastname = rCharacter.old.lastname; }
		LanguageCloseFile(tmpNameFileID);
		return;
	}
	if(CheckAttribute(rCharacter,"old.name"))
	{
		if(rCharacter.old.name=="Malcolm")
		{
			if(CheckAttribute(rCharacter,"old.lastname"))
			{
				if(rCharacter.old.lastname=="Hatcher")
				{
					rCharacter.id = "Malcolm Hatcher";
					return;
				}
			}
		}
	}
// MAXIMUS random name on death fix 24.11.2006 <--

	int iNation = sti(rCharacter.nation);
	if(iNation == -1) iNation = PIRATE;
	string allNations = "0,1,2,4,5";// MAXIMUS
	if(iNation == PIRATE) { iNation = sti(GetRandSubString(allNations)); }//rand(MAX_NATIONS - 1); }// MAXIMUS

	ref rNames, rLastNames;

	switch(iNation)
	{
		case ENGLAND:
			rNames = &sEnManNames;
			if(rCharacter.sex != "man") rNames = &sEnWomenNames;
			rLastNames = &sEnFamilies;
		break;
		case FRANCE:
			rNames = &sFrManNames;
			if(rCharacter.sex != "man") rNames = &sFrWomenNames;
			rLastNames = &sFrFamilies;
		break;
		case SPAIN:
			rNames = &sSpManNames;
			if(rCharacter.sex != "man") rNames = &sSpWomenNames;
			rLastNames = &sSpFamilies;
		break;
		case HOLLAND:
			rNames = &sHoManNames;
			if(rCharacter.sex != "man") rNames = &sHoWomenNames;
			rLastNames = &sHoFamilies;
		break;
		case PORTUGAL:
			rNames = &sPoManNames;
			if(rCharacter.sex != "man") rNames = &sPoWomenNames;
			rLastNames = &sPoFamilies;
		break;
		// KK default:
			rNames = &sEnManNames;
			if(rCharacter.sex != "man") rNames = &sEnWomenNames;
			rLastNames = &sEnFamilies;
	}

	if (GetArraySize(rNames) >= 2) //Quiliooto Fix
	{
		rCharacter.nation.name = iNation;//MAXIMUS: used in GetCharacterAddressForm
		rCharacter.name = GetRandSubString(rNames[rand(GetArraySize(rNames) - 2)]);
		rCharacter.lastname = GetRandSubString(rLastNames[rand(GetArraySize(rLastNames) - 2)]);
// KK -->
		if (!CheckAttribute(rCharacter, "old.name") || rCharacter.old.name == "") rCharacter.old.name = rCharacter.name;
		if (!CheckAttribute(rCharacter, "old.lastname") || rCharacter.old.lastname == "") rCharacter.old.lastname = rCharacter.lastname;
// <-- KK
	}
}

//=============================================================================
//  EQUIP SECTION
//=============================================================================
// NK rewrite this to not page through entire array. 05-05-11
// fixed 05-06-28 OOPS!
string FindCharacterItemByGroup(ref chref, string groupID)
{
	// TIH --> new method that uses the blade/guns sorted arrays Aug24'06
	if(!CheckAttribute(chref,"items")) return "";

	int i,n;
	int itmqual;
	int high = -1;
	string highid = "";
	string curId = "";

	aref chit; makearef(chit, chref.items);
	for(i = GetAttributesNum(chit)-1; i >= 0; i--)
	{
		aref refItm;
		curId = GetAttributeName(GetAttributeN(chit, i));
		n = Items_FindItem(curId,&refItm);// returns item index and fills aref refItm

		// check to see if this item is even something we can bother with selecting
		if ( n < 0 ) 								continue;// invalid item
		if ( !CheckAttribute(refItm,"id") ) 		continue;// no valid id
		if ( !CheckAttribute(refItm,"groupID") ) 	continue;// no valid groupid
		if ( refItm.groupID != groupID ) 			continue;// not what we are looking for, move along now
		
		if ( groupID == GUN_ITEM_TYPE )// must check requisits on guns
		{
			if( !CheckAttribute(refItm,"chargeQ") ) { continue; }// invalid gun
			if( sti(refItm.chargeQ) > 1 && !IsCharacterPerkOn(chref,"Gunman") ) { continue; }// no requisite
			if( sti(refItm.chargeQ) >= 4 && !IsCharacterPerkOn(chref,"GunProfessional") ) { continue; }// no requisite
		}

		// now we compare by 'n', but using different arrays to do it
		switch (groupID)
		{
			case BLADE_ITEM_TYPE:
				n = NativeFindCharacter(&BladeItems, curId);
			break;
			case GUN_ITEM_TYPE:
				n = NativeFindCharacter(&GunItems, curId);
			break;
			//default:
				// armor has no special sorted arrays to compare too
				// n is already set
		}

		if (n <= high) { continue; }
		// TIH --> bladedamage mod: we skip broken blades for all, and bad blades for mainchar Aug31'06
		// this only happens with blades, and only if the blade damage mod is enabled for the second check
		if (groupID == BLADE_ITEM_TYPE && BLADEDAMAGE_ENABLED)
		{
			itmqual = GetItemQualityByID(refItm.id);
			if (itmqual == 0) { continue; }
			if (itmqual == 1 && sti(chref.index) == GetMainCharacterIndex()) { continue; }
		}
		// TIH <--
		// now set the high to be used for further iterations
		high = n;
		highid = curId;
	}
	// if the high number was actually set to something, we return the highid set
	if(high > -1) return highid;
	return "";
	// TIH <--
	/* old method - doesnt use sorted arrays for guns and blades
	// DO NOT DELETE THIS COMMENTED CODE - left for tracking reasons
	int i,n;
	ref refItm;
	int high = -1;
	//for(i=ITEMS_QUANTITY-1; i>=0; i--)
	if(!CheckAttribute(chref,"items")) return "";
	aref chit; makearef(chit, chref.items);
	for(i = GetAttributesNum(chit)-1; i >= 0; i--)
	{
		aref curitmar = GetAttributeN(chit, i);
		string curitmid = GetAttributeName(curitmar);
		int oldhigh = high;
		n = GetItemIndex(curitmid);
		if(n <= high) continue;
		high = n;
		refItm = &Items[n];
		if( !CheckAttribute(refItm,"groupID") ) {high = oldhigh; continue; }
		if(refItm.groupID!=groupID) {high = oldhigh; continue; }
		// done above - if( !CheckAttribute(chref,"items."+refItm.id) ) continue;
		if(groupID==GUN_ITEM_TYPE)
		{
			if( !CheckAttribute(refItm,"chargeQ") ) {high = oldhigh; continue; }
			n = sti(refItm.chargeQ);
			//if(n<2) {return refItm.id;}
			//if(n<4)
			if(n>=4)
			{
				if( !IsCharacterPerkOn(chref,"GunProfessional") )
				{
					high = oldhigh;
					continue;
				}
			}
			else
			{
				if(n > 1)
				{
					if(!IsCharacterPerkOn(chref,"Gunman") )
					{
						high = oldhigh;
						continue;
					}
				}
			}
		}
	}
	if(high > -1) return Items[high].id;
	return "";
	*/
}

bool IsEquipCharacterByItem(ref chref, string itemID)
{
	aref arEquip;
	makearef(arEquip,chref.equip);
	int q = GetAttributesNum(arEquip);
	for(int i=0; i<q; i++)
	{	if(GetAttributeValue(GetAttributeN(arEquip,i))==itemID) return true;
	}
	return false;
}

string GetCharacterEquipByGroup(ref chref, string groupID)
{
	if( CheckAttribute(chref,"equip."+groupID) ) return chref.equip.(groupID);
	return "";
}

// PB -->
string CheckCharacterEquipByGroup(ref chref, string groupID)
{
	string item = GetCharacterEquipByGroup(chref,groupID);
	if(CheckCharacterItem(chref,item)) return item;
	return "";
}
// PB <--

void RemoveCharacterEquip(ref chref, string groupID)
{
	DeleteAttribute(chref,"equip."+groupID);
	SetEquipedItemToCharacter(chref,groupID,"");
}

void SetEquipedItemToCharacter(ref chref, string groupID, string itemID)
{
	//traceandlog("running seteq, grp " + groupID + ", item " + itemID);
	object emptyItm;
	aref arItm;
	string modelName = "";
	makearef(arItm,emptyItm);
	if(itemID!="")
	{
		if( !CheckCharacterItem(chref,itemID) ) return;
		Items_FindItem(itemID,&arItm);
	}

	switch(groupID)
	{
	// GreatZen -->
	case ARMOR_ITEM_TYPE:
		if(itemID == "")
		{
			// TIH -->
			if(CheckAttribute(chref,"chr_ai.coverage")) chref.chr_ai.coverage = 0.0;
			if(CheckAttribute(chref,"chr_ai.bladestop")) chref.chr_ai.bladestop = 0.0;
			if(CheckAttribute(chref,"chr_ai.bladefrac")) chref.chr_ai.bladefrac = 1.0;
			if(CheckAttribute(chref,"chr_ai.gunstop")) chref.chr_ai.gunstop = 0.0;
			if(CheckAttribute(chref,"chr_ai.gunfrac")) chref.chr_ai.gunfrac = 1.0;
			// NK 05-04-12 add model armor changing code -->
			if(!CheckAttribute(chref,"armoroverride") && CheckAttribute(chref,"noarmormodel"))
			{
				//traceandlog("resetting noarmormodel");
				chref.model = chref.noarmormodel;
				DeleteAttribute(&chref,"noarmormodel");
				DeleteAttribute(&chref, "curarmormodellevel");
				chref.armoroverride = true;
				SetModel(&chref, chref.model, chref.model.animation, chref.sex, stf(chref.model.height), FindLoadedLocation() != -1);
				ExecuteCharacterEquip(&chref);
				DeleteAttribute(&chref, "armoroverride");
			}
				
		}
		else
		{
			if(CheckAttribute(arItm,"coverage")) { chref.chr_ai.coverage = stf(arItm.coverage)/100.0; }
			else { chref.chr_ai.coverage = 0.0; }
			if(CheckAttribute(arItm,"bladestop")) { chref.chr_ai.bladestop = stf(arItm.bladestop)/100.0; }
			else { chref.chr_ai.bladestop = 0.0; }
			if(CheckAttribute(arItm,"bladefrac")) { chref.chr_ai.bladefrac = stf(arItm.bladefrac)/100.0; }
			else { chref.chr_ai.bladefrac = 1.0; }
			if(CheckAttribute(arItm,"gunstop")) { chref.chr_ai.gunstop = stf(arItm.gunstop)/100.0; }
			else { chref.chr_ai.gunstop = 0.0; }
			if(CheckAttribute(arItm,"gunfrac")) { chref.chr_ai.gunfrac = stf(arItm.gunfrac)/100.0; }
			else { chref.chr_ai.gunfrac = 1.0; }
			// NK again
			if(!CheckAttribute(chref,"armoroverride") && CheckAttribute(arItm,"cmodel") && !checkAttribute(arItm, "modelitem"))
			{
				//trace("starting changemodel check");
				string mdname = chref.model;
				string oldmodel = mdname; if(CheckAttribute(chref, "noarmormodel")) oldmodel = chref.noarmormodel;
				int newarmorlevel = sti(arItm.cmodel);
				int curarmorlevel = -2; if(CheckAttribute(chref, "curarmormodellevel")) curarmorlevel = sti(chref.curarmormodellevel);
				int slen = strlen(mdname);
				if(slen >= 4) // find orig model
				{
					if(curarmorlevel == -2 || oldmodel == mdname)
					{
						if(GetSymbol(oldmodel, slen-3) == "_" && GetSymbol(oldmodel, slen-2) == "A") // is already armor
						{
							curarmorlevel = sti(GetSymbol(oldmodel, slen-1));
							chref.curarmormodellevel = curarmorlevel; // save it so we don't have to look again next time
							if(oldmodel == mdname)
							{
								oldmodel = strcut(mdname, 0, slen-4);
							}
						}
					}
				}
				if(curarmorlevel == -2) curarmorlevel = -1;
				if(curarmorlevel == newarmorlevel) // then we don't have to do anything
				{
					//chref.noarmormodel = oldmodel; // save it in case we didn't have it there before
					break;
				}
				int modidx = GetModelIndex(oldmodel + "_A"+newarmorlevel);
				int i;
				chref.curarmormodellevel = newarmorlevel;
				chref.noarmormodel = oldmodel; // save it so we don't have to look again next time
				if(modidx == -1)  // then we need to find a substitute
				{
					for(i = newarmorlevel-1; i >= 0; i--) // find exisitng lower-quality armored model
					{
						modidx = GetModelIndex(oldmodel + "_A"+i);
						if(modidx != -1) break;
					}
					if(modidx == -1)
					{
						for(i = newarmorlevel+1; i <= 3; i++) // if no lower one, look for higher. There may eventually be more than 3 though.
						{
							modidx = GetModelIndex(oldmodel + "_A"+i);
							if(modidx != -1) break;
						}
					}
				}
				if(modidx != -1 && Models[modidx].model != oldmodel) // we finally found one
				{
					chref.model = Models[modidx].model;
					/*chref.model.animation = Models[modidx].ani;
					chref.sex = Models[modidx].sex;
					chref.model.height = Models[modidx].height;*/
					chref.armoroverride = true;
					//traceandlog("setting armormodel");
					SetModel(&chref, chref.model, chref.model.animation, chref.sex, stf(chref.model.height), FindLoadedLocation() != -1);
					ExecuteCharacterEquip(&chref);
					DeleteAttribute(&chref, "armoroverride");
				}
			}
		}
	break;
	// GreatZen <--
	case SPYGLASS_ITEM_TYPE:
		if(CheckAttribute(arItm,"id"))
		{
			setTelescopeInitParameters(&Telescope,arItm);
		}
	break;

	case GUN_ITEM_TYPE:
		if(CheckAttribute(arItm,"model"))	{modelName = arItm.model;}
		SendMessage(chref,"ls",MSG_CHARACTER_SETGUN,modelName);
		if(CheckAttribute(arItm,"chargeQ"))
		{	LAi_GunSetChargeQuant(chref,sti(arItm.chargeQ));
		} else
		{	LAi_GunSetChargeQuant(chref,0);
		}
		if(CheckAttribute(arItm,"chargespeed") && stf(arItm.chargespeed)>0.0)
		{
			LAi_GunSetChargeSpeed(chref,1.0/stf(arItm.chargespeed));
		} else
		{	LAi_GunSetChargeSpeed(chref,0.0);
		}
		if(CheckAttribute(arItm,"dmg_min"))
		{	LAi_GunSetDamageMin(chref,stf(arItm.dmg_min));
		} else
		{	LAi_GunSetDamageMin(chref,0.0);
		}
		if(CheckAttribute(arItm,"dmg_max"))
		{	LAi_GunSetDamageMax(chref,stf(arItm.dmg_max));
		} else
		{	LAi_GunSetDamageMax(chref,0.0);
		}
		if(CheckAttribute(arItm,"accuracy"))
		{	LAi_GunSetAccuracy(chref,stf(arItm.accuracy)*0.01);
		} else
		{	LAi_GunSetAccuracy(chref,0.0);
		}
	break;

	case BLADE_ITEM_TYPE:
		float liveTime = 0.1;
		int colors = argb(64, 64, 64, 64);
		int colore = argb(0, 32, 32, 32);
		if(CheckAttribute(arItm,"model"))	{modelName = arItm.model;}
		if(CheckAttribute(arItm, "blade.time"))	{liveTime = stf(arItm.blade.time);}
		if(CheckAttribute(arItm, "blade.colorstart"))	{colors = sti(arItm.blade.colorstart);}
		if(CheckAttribute(arItm, "blade.colorend"))	{colore = sti(arItm.blade.colorend);}
		SendMessage(chref, "lsfll", MSG_CHARACTER_SETBLADE, modelName, liveTime, colors, colore);
		if(CheckAttribute(arItm,"dmg_min"))
		{	LAi_BladeSetDamageMin(chref,stf(arItm.dmg_min));
		} else
		{	LAi_BladeSetDamageMin(chref,0.0);
		}
		if(CheckAttribute(arItm,"dmg_max"))
		{	LAi_BladeSetDamageMax(chref,stf(arItm.dmg_max));
		} else
		{	LAi_BladeSetDamageMax(chref,0.0);
		}
		if(CheckAttribute(arItm,"piercing"))
		{	LAi_BladeSetPiercing(chref,stf(arItm.piercing)*0.01);
		} else
		{	LAi_BladeSetPiercing(chref,0.0);
		}
		if(CheckAttribute(arItm,"block"))
		{	LAi_BladeSetBlock(chref,stf(arItm.block)*0.01);
		} else
		{	LAi_BladeSetBlock(chref,0.0);
		}
	break;
	}
}

void EquipCharacterByItem(ref chref, string itemID)
{
	aref arItm;

	if( !CheckCharacterItem(chref, itemID) ) return;
	//trace("has item");
	if( Items_FindItem(itemID, &arItm)<0 )	return;
	//trace("found item");
	if( !CheckAttribute(arItm, "groupID") ) return;
	//trace("has gid");

	string groupName = arItm.groupID;
	string oldItemID = GetCharacterEquipByGroup(chref, groupName);
	// for now just comment this. 05-07-06 - if(oldItemID==itemID && !CheckAttribute(chref,"armoroverride")) return; // NK bugfix to armor model switching. 05-07-06
	chref.equip.(groupName) = itemID;

	if(IsEntity(chref))
	{
		//trace("is entity");
		SetEquipedItemToCharacter(chref, groupName, itemID);
	}
	// ccc special weapons, so that distanceweapons are precharged if equiped
	// must be activated by setting PRECHARGE = 1 in buildsettings_2.h	
	if(groupName==GUN_ITEM_TYPE && sti(chref.index)==GetMainCharacterIndex() && PRECHARGE != 1)
	{	LAi_GunSetUnload(chref);
	}

// added by MAXIMUS 21.07.2006 [weapon will not be charged without gunpowder or proper bullets][changed 24.11.2006] -->
	if(ENABLE_AMMOMOD==1)
	{
	    if(GetCharacterIndex(chref.id)==GetMainCharacterIndex() || IsOfficer(chref) ) //JRH fix oct 06: crewmembers
    	{
			aref weapon;
			string weaponID = GetCharacterEquipByGroup(chref,GUN_ITEM_TYPE);
			Items_FindItem(weaponID, &weapon);
			if(CheckAttribute(weapon,"shottype"))
			{
				string ammoName;
				switch(weapon.shottype)
				{
					case "pg2": ammoName = "pistolgrapes"; break;
					case "pg": ammoName = "pistolgrapes"; break;
					case "mb": ammoName = "musketbullets"; break;
					case "pb": ammoName = "pistolbullets"; break;
				}
				if(!CheckAttribute(chref,"Items.gunpowder")) chref.Items.gunpowder = 0;
				if(!CheckAttribute(chref,"Items."+ammoName)) chref.Items.(ammoName) = 0;
				if(sti(chref.Items.(ammoName))==0 || sti(chref.Items.gunpowder)==0) LAi_GunSetUnload(chref);
				else
				{
					if(CheckAttribute(weapon,"chargeQ"))
					{
						if(sti(chref.Items.(ammoName))<sti(weapon.chargeQ)) LAi_GunSetUnload(chref);
						if(sti(chref.Items.gunpowder)<sti(weapon.chargeQ)) LAi_GunSetUnload(chref);
					}
				}
			}
	    }
	}
// added by MAXIMUS 21.07.2006 [weapon will not be charged without gunpowder or proper bullets][changed 24.11.2006] <--
}

void ExecuteCharacterEquip(ref chref)
{
	// NK fix; the stmp declaration was _below_ its first use!!! Also add armor. 05-04-12
	//trace("exing chr equip");
	string stmp = GetCharacterEquipByGroup(chref,BLADE_ITEM_TYPE);
	if(stmp!="")	{SetEquipedItemToCharacter(chref, BLADE_ITEM_TYPE, stmp);}
	stmp = GetCharacterEquipByGroup(chref,GUN_ITEM_TYPE);
	if(stmp!="")	{SetEquipedItemToCharacter(chref, GUN_ITEM_TYPE, stmp);}
	stmp = GetCharacterEquipByGroup(chref,ARMOR_ITEM_TYPE);
	SetEquipedItemToCharacter(chref, ARMOR_ITEM_TYPE, stmp); // yes even if it's "".
	//trace("done exing");
	// NK <--
}

bool IsCanEquiping(ref chref, string equiping_group)
{
	if( CheckAttribute(chref,"equip.disabled_group."+equiping_group)
		&& sti(chref.equip.disabled_group.(equiping_group))==true ) return false;
	return true;
}

void EnableEquip(ref chref, string equiping_group, bool enable)
{
	if(enable)
	{	if(equiping_group=="")
		{	DeleteAttribute(chref,"equip.disabled_group");
		}
		else
		{	DeleteAttribute(chref,"equip.disabled_group."+equiping_group);
		}
	}
	else
	{	if(equiping_group=="")
		{
			string stmp;
			stmp = GUN_ITEM_TYPE;		chref.equip.disabled_group.(stmp) = true;
			stmp = BLADE_ITEM_TYPE;		chref.equip.disabled_group.(stmp) = true;
			stmp = SPYGLASS_ITEM_TYPE;	chref.equip.disabled_group.(stmp) = true;
			stmp = ARMOR_ITEM_TYPE;	chref.equip.disabled_group.(stmp) = true; // NK 05-04-13
		}
		else
		{
			chref.equip.disabled_group.(equiping_group) = true;
		}
	}
}

// NK 04-09-06 -->
// to check if rep == "none"
int GetCharacterReputation(ref chr)
{
	if(CheckAttribute(chr,"reputation")) {if(chr.reputation != "none") { return sti(chr.reputation); } }
	return REPUTATION_NEUTRAL;
}
// NK <--
int ChangeCharacterReputation(ref chref, int incr) // TIH changed BACK to int ! got rid of float problems Aug29'06
{
	bool isDonation = false;
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	if(sti(chref.index) == GetMainCharacterIndex()) { traceandlog(TranslateString("","CHANGE REP FOR PLAYER:") + " " + intRet(incr==9999,1,incr) + stringRet(DOUBLE_REP_INCR," x2","")); } // NK find rep bug
	/*int prevVal = REPUTATION_NEUTRAL;
	if( CheckAttribute(chref,"reputation") )	prevVal = sti(chref.reputation);*/
	int prevVal = GetCharacterReputation(&chref); // NK 04-09-06

	// LDH 25Sep06 simplify rep code for donations
	if (incr == 9999) {
		incr = 1;	// for donations, see quests_reaction.c
		isDonation = true;
	} else {
		if (DOUBLE_REP_INCR) incr *= 2;
	}

	int newVal = iclamp(REPUTATION_MIN, REPUTATION_MAX, prevVal + incr);
	chref.reputation = newVal;

	// LDH 19Sep06 - change officers' reputation as well
	if(!isDonation && sti(chref.index) == GetMainCharacterIndex())
	{
		int incrOfficer = incr;
		if (iabs(incr) != 1) incrOfficer /= 2;	// officers get half the increase unless incr is just 1
		for (int i = 1; i < 4; i++)
		{
			int idx = GetOfficersIndex(GetMainCharacter(), i);
			if (idx > 0)
			{
				ref chOfficer = &Characters[idx];
				chOfficer.reputation = iclamp(REPUTATION_MIN, REPUTATION_MAX, GetCharacterReputation(chOfficer)+incrOfficer);
				trace("Change of rep for " + chOfficer.name + " " + incrOfficer + " (" + chOfficer.reputation + ")");
			}
		}
	}

	if( sti(chref.index) != GetMainCharacterIndex() ) return newVal;

	string prevName = GetReputationName(prevVal);
	string newName = GetReputationName(newVal);
	if(prevName!=newName)
	{
		string outString = XI_ConvertString("Your reputation")+" ";
		if(incr>0)	{outString+=XI_ConvertString("increase");}
		else	{outString+=XI_ConvertString("decrease");}
		outString += " "+XI_ConvertString("to")+" "+XI_ConvertString("i" + newName);
		traceandlog(outString);
	}
	//LanguageCloseFile(tmpLangFileID);
	return newVal;
}

bool Character_IsAbordageEnable(ref rCharacter)
{
	if(CheckAttribute(rCharacter, "Abordage.Enable")) { return sti(rCharacter.Abordage.Enable); }
	return true;
}

void Character_SetAbordageEnable(ref rCharacter, bool bEnable)
{
	rCharacter.Abordage.Enable = bEnable;
}

void Character_SetCompanionEnemyEnable(ref rCharacter, bool bEnable)
{
	rCharacter.CompanionEnemyEnable = bEnable;
}

void AddMsgToCharacter(ref chref, int nMsg)
{
	string msgName = "msg"+nMsg;
	bool bStartEvent = !CheckAttribute(chref,"MessageIcons."+msgName);
	chref.MessageIcons.(msgName).pic = nMsg;
	chref.MessageIcons.(msgName) = MSGICON_ACTIVE_TIME;
	if(bStartEvent) PostEvent("evnt_MsgIconTick",1000,"ll",nMsg,sti(chref.index));
}

void DelMsgFromCharacter(ref chref, int nMsg)
{
	DeleteAttribute(chref,"MessageIcons.msg"+nMsg);
}

void proc_MsgIconTick()
{
	int nMsg = GetEventData();
	int chrIdx = GetEventData();
	if(DialogRun!=0) {
		PostEvent("evnt_MsgIconTick",1000,"ll",nMsg,chrIdx);
		return;
	}
	ref chref = GetCharacter(chrIdx);
	string msgName = "msg"+nMsg;
	int nTime = 0;

	if( CheckAttribute(chref,"MessageIcons."+msgName) )
	{
		nTime = sti(chref.MessageIcons.(msgName));
		if(nTime>0)
		{
			chref.MessageIcons.(msgName) = nTime-1;
			PostEvent("evnt_MsgIconTick",1000,"ll",nMsg,chrIdx);
			return;
		}
		DelMsgFromCharacter(chref,nMsg);
	}
}

// Stone-D Surrender Mod -->
int GetPrisonerQuantity(ref _refCharacter)
{
	int qn = 0;
	ref Char;
	for(int i=0; i<GetPassengersQuantity(_refCharacter); i++)
	{
		Char=GetCharacter(GetPassenger(_refCharacter,i));
		if (CheckAttribute(Char, "prisoned") == true && sti(Char.prisoned) == true) qn++; // KK
	}
	return qn;
}
// Stone-D Surrender Mod <--

// KK -->
int GetPrisoner(ref _refCharacter, int n)
{
	int c = -1;
	int q = GetPrisonerQuantity(_refCharacter);
	if (n < 0 || n >= q) return -1;
	for (int i = 0; i < GetPassengersQuantity(_refCharacter); i++) {
		int idx = GetPassenger(_refCharacter, i);
		if (idx == -1) continue;
		ref Char = GetCharacter(idx);
		if (CheckAttribute(Char, "prisoned") == true && sti(Char.prisoned) == true) c++;
		if (c == n) return idx;
	}
	return -1;
}

bool IsTrader(ref _refCharacter)
{
	int findIdx = -1; // KK
	if (CheckAttribute(_refCharacter, "index"))
		findIdx = sti(_refCharacter.index); // changed by MAXIMUS
	else
		return false;
	ref mc = GetMainCharacter();
	for (int i=1; i<4; i++)
	{
		if (GetCompanionIndex(mc, i) == findIdx && CheckAttribute(&Characters[findIdx], "quest.officertype") == true && Characters[findIdx].quest.officertype == OFFIC_TYPE_TRADER) return true;
	}
	return false;
}
// <-- KK
