
#define MAXBUILDINGS  15  // Max number of buildings that can be built in a location


// *********************** BUILDING KIT FUNCTIONS **********************
// This erects a building with optional interior in front of the "user"
// In InitItems.c must be definitions for building(as BLADE_ITEM_TYPE) and interior (as GUN_ITEM_TYPE)

void Build_here(ref user, string building, string interior, bool permanent)
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	ref chr;
	string nr = "";
	string attr;
	float x,y,z,ay;
	ref lcn = &Locations[FindLocation(user.location)];	// determines where you are
	string aigroup = user.chr_ai.group;
	
//check if a buildingslot is free
	for(int i = 1; i<=MAXBUILDINGS; i++)
	{
	  attr = "building."+i+".building"
		if( !CheckAttribute(lcn,attr) )
    {
     nr = i;
    }
	}

	if(nr == "" )	
	{
		Logit(TranslateString("","There is no building ground left anymore!"));
		return;
	}

//just earcandy :)
	PlaySound("ambient\shipyard\axe.wav");
	PlaySound("ambient\shipyard\vehicle.wav");
	PlaySound("ambient\shipyard\saw.wav");
	PlaySound("ambient\shipyard\hammer.wav");
	
	// determine position in front of user (by NK, thanks :)  )
	GetCharacterPos(user, &x, &y, &z); // get pos
	GetCharacterAy(user, &ay); // get angle
	z += cos(ay)*1; // add Z component
	x += sin(ay)*1; // add X component

	ay += PI/2; // rotate angle 90deg to get building facingdir
	ay += PI/2; // again, don't know how to turn 180deg otherwise :o

// buildinglike chr is set in front of user
	Build(nr, building, interior, x, y, z, ay, aigroup)

// save permanent building as locationattributes for reloading
  if(permanent)
  {
	lcn.building.(nr).building = building;
	lcn.building.(nr).interior = interior;
	lcn.building.(nr).x = x;
	lcn.building.(nr).y = y;
	lcn.building.(nr).z = z;
	lcn.building.(nr).ay = ay; // += PI;
	lcn.building.(nr).aigroup = aigroup;
	lcn.building.(nr).taxDay = GetDataDay();
	lcn.building.(nr).taxyear = GetDataYear();
	lcn.building.(nr).taxMonth = GetDataMonth();
  }
  
// time passing for building
	aref buildingref;
	Items_FindItem(building,&buildingref);
	//int planks = sti(buildingref.building.planks);
	WaitDate("", 0, 0, 0, sti(buildingref.building.planks), 0);
	LAi_Fade("", "");
	Logit(TranslateString("","Switch to first-person-view if your avatar is inside of the building"));
	ref PChar = GetMainCharacter();
	LAi_type_player_Init(PChar); // keeps playerview from swaying
	//LanguageCloseFile(tmpLangFileID);
}



// This adds a building to the buildinglist of a location so that it appears at next locloading
void Build_at(string locname, string building, string interior, float x, float y, float z, float ay, string aigroup)
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	string nr = "";
	string attr;
	ref lcn = &Locations[FindLocation(locname)];
	
//check if a buildingslot is free
	for(int i = 1; i<=MAXBUILDINGS; i++)
	{
		attr = "building."+i+".building"
		if( !CheckAttribute(lcn,attr) )
		{
			nr = i;
		}
	}

	if(nr == "" )	
	{
		Logit(TranslateString("","There is no building ground free at") + " " + TranslateString("",locname));
		return;
	}
	
// save permanent building as locationattributes for reloading
	lcn.building.(nr).building = building;
	lcn.building.(nr).interior = interior;
	lcn.building.(nr).x = x;
	lcn.building.(nr).y = y;
	lcn.building.(nr).z = z;
	lcn.building.(nr).ay = ay; // += PI;
	lcn.building.(nr).aigroup = aigroup;

// ccc Feb06  use fixed date at gamestart
	if( !CheckAttribute(Environment,"date") )
	{	
		lcn.building.(nr).taxDay = 15;
		lcn.building.(nr).taxMonth = 4;
		lcn.building.(nr).taxyear = 1690;
	}else{
		lcn.building.(nr).taxDay = GetDataDay();
		lcn.building.(nr).taxMonth = GetDataMonth();
		lcn.building.(nr).taxyear = GetDataYear();
	}
// Feb06 end 
	//LanguageCloseFile(tmpLangFileID);
}

// This deletes a building "plan" that was stored as locationattributes
void Building_delete(ref lcn, string nr)  // nr must be called as string "" !
{
  DeleteAttribute(lcn,"building."+nr);
}

// This reerects all buildings stored as attributes to a location
void Build_again(ref lcn)
{
	if(ENABLE_BUILDINGSET == 0) return;	// ccc oct06 toggle

	ref chr;
	float x,y,z,ay;
	string building;
	string interior;
	string nr;
	string attr;
	string aigroup;

	for(int i = 1; i<=MAXBUILDINGS; i++)
	{
	 nr = i;
	 attr = "building."+i+".building";
	 if(CheckAttribute(lcn,attr) )
	 {
    // load building locationattributes 
	   building = lcn.building.(nr).building;
	   interior = lcn.building.(nr).interior;
	   x = stf(lcn.building.(nr).x);
	   y = stf(lcn.building.(nr).y);
	   z = stf(lcn.building.(nr).z);
	   ay = stf(lcn.building.(nr).ay);
	   aigroup = lcn.building.(nr).aigroup;

    // buildinglike chr is set to stored pos
    	Build(nr, building, interior, x, y, z, ay, aigroup)
    }
  }
}


// This performs the actual building process
void Build(string nr, string building, string interior, float x, float y, float z, float ay, string aigroup)
{
	aref buildingref;
	Items_FindItem(building,&buildingref);
	int planks = sti(buildingref.building.planks);
	int hp = 50 +(planks *20)
	ref chr;
	chr = LAi_CreateFantomCharacterEx(false, 0, false, false, 0.0, buildingref.building.chrmodel, "man", "", "");
	LAi_SetBuildingType(chr);
	LAi_SetHP(chr, hp, hp);
	LAi_group_MoveCharacter(chr, aigroup);

// MAXIMUS 09.10.2006 [for correct names showing] -->
	string corName = XI_ConvertString(building);
	if(LanguageGetLanguage()!="Russian") corName = strcut(corName,1,strlen(corName)-1);
	chr.old.name = building;// MAXIMUS 16.10.2006
	chr.name = corName;
// MAXIMUS 09.10.2006 [for correct names showing] <--

	chr.old.lastname = nr;	// Do not assign another oldlastname!// MAXIMUS 16.10.2006
	chr.lastname = nr;	// Do not assign another lastname!
 	chr.dialog.filename = buildingref.building.dialog;

// added by MAXIMUS [for AOP towns] -->
	if(CheckAttribute(Locations[FindLoadedLocation()],"(building).status"))
	{
		if(Locations[FindLoadedLocation()].(building).status == "permanent")
		{
			LAi_SetImmortal(chr, true);
			DeleteAttribute(chr,"dialog.filename");
		}
	}
// added by MAXIMUS [for AOP towns] <--

	GiveItem2Character(chr, building);
 	GiveItem2Character(chr, interior);
 	EquipCharacterbyItem(chr, building);
 	EquipCharacterbyItem(chr, interior);

	TeleportCharacterToPosAy(chr, x, y, z, ay); // move char
}

// Building Kit end _______________________________________

void ChangeTownNation (string townsk, int nat)		// functioncall must include townname, i.e. townsack attribute, and nationindex 
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	// NK to use forts interface in towntable.c 05-07-10
	int n;
	ref town = GetTownFromID(townsk);
	int numforts = GetTownNumForts(townsk);
	ref ch;
	for(n = 0; n < numforts; n++)
	{
		ch = GetTownFortCommander(townsk, n);
		/*ref commander = CharacterFromID(	// the fortcommander of this town
		if (townsk == "Falaise de Fleur") commander = (characterFromID("FalaisedeFleur Commander"));	// why didn't Akella...
		else if (townsk == "Isla Muelle") commander = (characterFromID("IslaMuelle Commander"));	// stick to one spelling system ? @@
		else commander = (characterFromID(townsk + " Commander"));*/

		ch.nation = nat;						// gets the nation from the functioncall
		ch.model = SelectSoldierModelByNation(nat, "Officer");	// NK was soldier. 05-07-10 - and the appropriate charmodel
	}
	SetTownNation(townsk, nat);				// town gets the nation from the functioncall

	for(n = 0; n < CHARACTERS_QUANTITY; n++)		// loop to cycle through all characters
	// NK 05-04-05 change to CHARACTERS_QUANTITY. Fantoms won't be changed, but that's OK because this won't be run when there are any.
	{
		makeref(ch, Characters[n]);		// defines ch as character who has loopindex as characterindex

		if(CheckAttribute(ch, "sound_type") && ch.sound_type == "soldier")	// if ch is a soldier
		{
			if(CheckAttribute(ch, "location") && FindLocation(Characters[ch].location) >= 0)
				// and if ch has a location
			{
				if(CheckAttribute(Locations[FindLocation(ch.location)],"townsack") && Locations[FindLocation(ch.location)].townsack == townsk)	// and if ch is in this town
				{
					ch.nation = nat				// ch gets nation from functioncall
					ch.model = SelectSoldierModelByNation(nat, "Soldier");	// and a new uniform
					facemaker(ch);				// and the appropriate facepicture
					//Log_SetStringToLog(ch.id + " changed ");

					// ccc oct 06  fix to remove St Martin siegearmies after towncapture
					ref exit;
					if(townsk=="Philipsburg" )
					{
						ChangeCharacterAddress(Ch, "none", "");	// removes soldiers

						exit = &Locations[FindLocation("Philipsburg_exit")];
						if(CheckAttribute(exit,"building") ) DeleteAttribute(exit,"building");    // removes siege guns
					}

					if(townsk=="Marigot" )
					{
						ChangeCharacterAddress(Ch, "none", "");	// removes soldiers

						exit = &Locations[FindLocation("Marigot_exit")];
						if(CheckAttribute(exit,"building") ) DeleteAttribute(exit,"building");    // removes siege guns
					}
					// ccc oct 06 end
				}
			}
		}
	}
	PlayStereoSound("notebook_event");		// notification by sound and screenmessage	
	Log_SetStringToLog(townsk + " " + TranslateString("","has been occupied by") + " " + TranslateString("",GetNationDescByType(nat)) + " " + XI_ConvertString("forces"));
	//LanguageCloseFile(tmpLangFileID);
}

void Explosion(ref chr, int damage)		// Explosion hurts character "chr" with "damage" hp
{
	float x, y, z;			// coordinates for effects...
	GetCharacterPos(chr, &x, &y, &z);	// ...are those of the chr 
	CreateParticleSystemX("blast", x, y, z, x, y, z,0);	// effects at that pos
	CreateParticleSystemX("fort_fire", x, y, z, x, y, z,5);
	Play3DSound("OBJECTS\SHIPCHARGE\cannon_fire3.wav",x,y,z);
// changed by MAXIMUS -->
	if(chr.sex == "woman") Play3DSound("OBJECTS\VOICES\DEAD\female\dead_wom5.wav",x,y,z);
	else Play3DSound("OBJECTS\VOICES\DEAD\male\dead6.wav",x,y,z);
// changed by MAXIMUS <--


	int num = FindNearCharacters(chr, 3.0, -1.0, -1.0, 0.001, false, true);
		// checks if there are other people around the initial target. 3 is the checkradius

	for(int j = 0; j <= num; j++)	// the following loop runs for each near character
	{
		int idx = sti(chrFindNearCharacters[j].index);	// defines near character as idx
		ref findCh;
		findCh = GetCharacter(idx);	// necessary? to get object for next line

    // ccc dec05 rewritten to ensure distance is correct and to keep playergroup alive
		float dist = -1.0;
  	if(GetCharacterDistByChr3D(chr, findCh, &dist) && dist<4)
    {
		LAi_ApplyCharacterDamage(findCh, damage);		// damage is applied to findCh
  	if (sti(LAi_GetCharacterHP(findCh)) < damage+1) // and if that's too much..
      { 
        if(findCh.chr_ai.group != LAI_GROUP_PLAYER)  // ..and he's not in playergroup..
        {Lai_KillCharacter(findCh);} // ..he is being killed
        else{findCh.chr_ai.hp = 10} // playergroup barely survives
      }
  	}
  }	// end of loop

	LAi_ApplyCharacterDamage(chr, damage);		// damage is applied to chr
	if(AUTO_SKILL_SYSTEM) { AddPartyExpChar(Chr, "Defence", damage*3 ); }
	else { AddPartyExp(Chr, damage*3 ); }// some expoints as compensation
	if (sti(LAi_GetCharacterHP(chr)) < damage+1) Lai_KillCharacter(chr);
		// and if that's too much he is being killed
}

// ccc dec05 changed to use different models based on modeltype
void Ambush(string modeltype, int bmax, string mainrel, string npcrel, string locator)		// horde of attackers appears
// bmax is number of chr, mainrel relation to player, npcrel to NPCs, Nov05 added "guards" as modeloption for local guards
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	Log_SetStringToLog(TranslateString("","ALARM !  AN AMBUSH !!!!"));
	PlaySound("OBJECTS\abordage\abordage2.wav");

	ref chr;
	ref PChar = GetMainCharacter();
	ref lcn = &Locations[FindLocation(pchar.location)];
	float hasgun;
	string ani, group, model;
	hasgun = 0.5;
	ani = "man";
	group = "ambush";
	// Julian jan08 changed to enable use of pre-defined locator
	if(locator == "") locator = LAi_FindRandomLocator(group);

	// ccc Nov05 make local guards if modeltype is "guards"
	if(modeltype == "guards")
	{
		int nat = GetCurrentLocationNation();
		group = GetCurrentSoldierGroup();
	}

	for(int i = 0; i < bmax; i++)
	{
		if(modeltype == "guards"){model = SelectSoldierModelByNation(nat, "Soldier");} 
		else {model = GetRandomModelForTypeSex(1, modeltype, "man");}

		chr = LAi_CreateFantomCharacterEx(npcrel ==  LAI_GROUP_FRIEND, 0, true, true, hasgun, model, ani, "reload", locator);
		LAi_SetWarriorType(chr);
		LAi_group_MoveCharacter(chr, group);
	}

	LAi_group_SetRelation(LAI_GROUP_PLAYER, group, mainrel);
	if(mainrel=="enemy") LAi_group_FightGroups(group, LAI_GROUP_PLAYER, true);

	LAi_group_SetRelation(LAI_GROUP_GUARDS, "ambush", npcrel);
	LAi_group_SetRelation(LAI_DEFAULT_GROUP, "ambush", npcrel);
	LAi_group_SetRelation(LAI_GROUP_MONSTERS, "ambush", npcrel);

	// ccc Nov05 set relation to local soldiers (which are NOT! LAI_GROUP_GUARDS) with NK's new function
	SetAllNormalGroupsRel("ambush", npcrel);
	
	if(npcrel=="enemy") LAi_group_FightGroups("ambush", LAI_GROUP_GUARDS, true);
}

// ccc Captain's Challenge, function to equip chref from new weapons locker
// NK 05-05-10 add armor, make 1 log line, use less variables
void EquipFromLocker(ref chref)
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	aref arItm;
	ref loc = &locations[FindLocation("Tutorial_Deck")];
	//int lngid = LanguageOpenFile(GetStorylineDir(FindCurrentStoryline()) + "ItemsDescribe.txt"); // KK
	string logstr = "";
	string curitemname;
	int curitemnr;
	DeleteAttribute(&chref, "items"); // NK 05-07-18 delete all items from chref.
	
	// blade
	string curitem = FindLockerItemByGroup(chref, BLADE_ITEM_TYPE); 
	if (curitem != "") 
	{
		GiveItem2Character(chref, curitem);
		EquipCharacterByItem(chref, curitem);

		// NK get weaps back 05-05-10 - if(GET_WEAPONS_BACK == 1) GiveItem2Character(GetMainCharacter(), curitem);

		Items_FindItem(curitem,&arItm);
		curitemname = TranslateString("",arItm.name);
		logstr = "a "+curitemname;

		curitemnr = sti(loc.WeaponsLocker.items.(curitem)) - 1; // KK
		if(curitemnr<=0) DeleteAttribute(&loc,"WeaponsLocker.items."+curitem); // KK
		else loc.WeaponsLocker.items.(curitem) = curitemnr; // KK
	}
	else
	{
		GiveItem2Character(chref, BOARDER_SPAREBLADE);
		EquipCharacterByItem(chref, BOARDER_SPAREBLADE);	// spare weapon if next line yields no blade
	}

	// gun
	curitem = FindLockerItemByGroup(chref, GUN_ITEM_TYPE); 
	if (curitem != "") 
	{
		GiveItem2Character(chref, curitem);
		EquipCharacterByItem(chref, curitem);

		// NK get weaps back 05-05-10 - if(GET_WEAPONS_BACK == 1) GiveItem2Character(GetMainCharacter(), curitem);

		Items_FindItem(curitem,&arItm);
		curitemname = TranslateString("",arItm.name);
		if(logstr == "") { logstr = XI_ConvertString("a") + " " + curitemname; }
		else { logstr += " " + XI_ConvertString("and") + " " + XI_ConvertString("a") + " "+curitemname; }

		curitemnr = sti(loc.WeaponsLocker.items.(curitem)) - 1; // KK
		if(curitemnr<=0) DeleteAttribute(&loc,"WeaponsLocker.items."+curitem); // KK
		else loc.WeaponsLocker.items.(curitem) = curitemnr; // KK
	}
	
	// armor NK 05-05-10
	curitem = FindLockerItemByGroup(chref, ARMOR_ITEM_TYPE);
	if (curitem != "")
	{
		GiveItem2Character(chref, curitem);
		EquipCharacterByItem(chref, curitem);

		// NK get weaps back 05-05-10 - if(GET_WEAPONS_BACK == 1) GiveItem2Character(GetMainCharacter(), curitem);

		Items_FindItem(curitem,&arItm);
		curitemname = TranslateString("",arItm.name);
		if(logstr == "") { logstr = curitemname; }
		else { logstr += " " + XI_ConvertString("and") + " " + curitemname; }

		curitemnr = sti(loc.WeaponsLocker.items.(curitem)) - 1; // KK
		if(curitemnr<=0) DeleteAttribute(&loc,"WeaponsLocker.items."+curitem); // KK
		else loc.WeaponsLocker.items.(curitem) = curitemnr; // KK
	}
	if(LogsToggle && logstr != "")
	{
		logit(TranslateString("","Your crewman") + " " + GetMySimpleName(chref) + " "+XI_ConvertString("took")+" " + logstr + " "+TranslateString("","from the locker")+".");
	}
	//LanguageCloseFile(lngid); // NK 05-05-10 close file again
	//LanguageCloseFile(tmpLangFileID);
}


// ccc Captain's Challenge, function to check if chref can be equiped from new weapons locker
string FindLockerItemByGroup(ref chref, string groupID)
{
	// TIH --> new method that only loops through what is IN the weapons locker, not ALL items in the game Aug31'06
	// this also will first pick out things that are better than others, so it helps ignore junk
	// if you have BLADEDAMAGE mod on, dont put 'worn' items in your locker if you dont want them breaking!
	ref loc = &Locations[FindLocation("Tutorial_Deck")]; // ? -> NK not reget this each time 05-05-10
	if (CheckAttribute(loc,"WeaponsLocker.items")) // KK
	{
		aref lockerItems;
		makearef(lockerItems, loc.WeaponsLocker.items); // KK
		if ( GetAttributesNum(lockerItems) > 0 )
		{
			int i,n;
			int itmqual;
			int high = -1;
			string highid = "";
			string curId = "";

			for (i = GetAttributesNum(lockerItems)-1; i >= 0; i--)// go through the locker items
			{
				aref refItm;
				curId = GetAttributeName(GetAttributeN(lockerItems, i));
				n = Items_FindItem(curId,&refItm);// returns item index and fills aref refItm

				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 ( sti(loc.WeaponsLocker.items.(curId)) < 1 ) 		continue;// not enough in box // KK

				if ( groupID == GUN_ITEM_TYPE )// must check requisits on guns
				{
					if( !CheckAttribute(refItm,"chargeQ") ) { continue; }// invalid gun
					if( sti(refItm.chargeQ) >= 2 && !IsCharacterPerkOn(chref,"Gunman") ) { continue; }// no requisite
					if( sti(refItm.chargeQ) >= 4 && !IsCharacterPerkOn(chref,"GunProfessional") ) { continue; }// no requisite
				}

				// now we compare by 'n', but using sorted 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; }
				// this only happens with blades, and only if the blade damage mod is enabled for the second check
				if (groupID == BLADE_ITEM_TYPE)
				{
					itmqual = GetItemQualityByID(refItm.id);
					if (itmqual > -1) // some blades dont have quality set (or weapons mod is off) so dont check those
					{
						if (itmqual == 0) { continue; }
						if (BLADEDAMAGE_ENABLED && itmqual == 1) { continue; }
					}
				}
				// now set the high to be used for further iteration compares
				high = n;
				highid = curId;
			}
			Trace("BOARDING: FindLockerItemByGroup grabbed: "+ highid );
			if(high > -1) return highid;
		}
	}
	return "";

	/* old method left here for tracking purposes
	int i,n;
	ref refItm;
	ref loc = &Locations[FindLocation("Tutorial_Deck")]; // NK not reget this each time 05-05-10
	for(i=MAX_ITEMS-1; i>=0; i--)
	{
		refItm = &Items[i];
		string itid = refItm.id
		if( !CheckAttribute(refItm,"groupID") ) continue;
		if(refItm.groupID!=groupID) continue;
		if( !CheckAttribute(loc,"WeaponsLocker.items."+refItm.id) ) continue; // KK
		if( sti(loc.WeaponsLocker.items.(itid) )<1 ) continue; // KK

		if(groupID==GUN_ITEM_TYPE)
		{
			if( !CheckAttribute(refItm,"chargeQ") ) continue;
			n = sti(refItm.chargeQ);
			if(n<2) {return refItm.id;}
			if(n<4)
			{
				if( IsCharacterPerkOn(chref,"Gunman") ) {return refItm.id;}
				else continue;
			}
			if( IsCharacterPerkOn(chref,"GunProfessional") )	{return refItm.id;}
			continue;
		}
		return refItm.id;
	}
	return "";
	*/
	// TIH <--
}

// ccc

// NK get weaps back 05-05-10 -->
void GiveItemsBack(ref chr)
{
	string stmp;
	ref loc = &Locations[FindLocation("Tutorial_Deck")];

	// TIH --> rewritten to use proper equip function Aug31'06
	stmp = GetCharacterEquipByGroup(&chr, BLADE_ITEM_TYPE);
	if( stmp != "" )
	{
		if(CheckAttribute(loc, "WeaponsLocker.items."+stmp)) { loc.WeaponsLocker.items.(stmp) = sti(loc.WeaponsLocker.items.(stmp)) + 1; } // KK
		else { loc.WeaponsLocker.items.(stmp) = 1; } // KK
		Trace("BOARDING: GiveItemsBack blade returned: "+ stmp );
	}
	stmp = GetCharacterEquipByGroup(&chr, GUN_ITEM_TYPE);
	if( stmp != "" )
	{
		if(CheckAttribute(loc, "WeaponsLocker.items."+stmp)) { loc.WeaponsLocker.items.(stmp) = sti(loc.WeaponsLocker.items.(stmp)) + 1; } // KK
		else { loc.WeaponsLocker.items.(stmp) = 1; } // KK
		Trace("BOARDING: GiveItemsBack gun returned: "+ stmp );
	}
	if (!LAi_IsDead(chr)) // do not do if the character died... their armor is considered busted
	{
		stmp = GetCharacterEquipByGroup(&chr, ARMOR_ITEM_TYPE);
		if( stmp != "" )
		{
			if(CheckAttribute(loc, "WeaponsLocker.items."+stmp)) { loc.WeaponsLocker.items.(stmp) = sti(loc.WeaponsLocker.items.(stmp)) + 1; } // KK
			else { loc.WeaponsLocker.items.(stmp) = 1; } // KK
			Trace("BOARDING: GiveItemsBack armor returned: "+ stmp );
		}
	}
	/* prior method kept for tracking purposes
	if(CheckAttribute(chr,"equip.blade") && chr.equip.blade != "")
	{
		stmp = chr.equip.blade;
		if(CheckAttribute(loc, "WeaponsLocker.items."+stmp)) { loc.WeaponsLocker.items.(stmp) = sti(loc.WeaponsLocker.items.(stmp)) + 1; } // KK
		else { loc.WeaponsLocker.items.(stmp) = 1; } // KK
	}
	if(CheckAttribute(chr,"equip.gun") && chr.equip.gun != "")
	{
		stmp = chr.equip.gun;
		if(CheckAttribute(loc, "WeaponsLocker.items."+stmp)) { loc.WeaponsLocker.items.(stmp) = sti(loc.WeaponsLocker.items.(stmp)) + 1; } // KK
		else { loc.WeaponsLocker.items.(stmp) = 1; } // KK
	}
	if(CheckAttribute(chr,"equip.armor") && chr.equip.armor != "")
	{
		stmp = chr.equip.armor;
		if(CheckAttribute(loc, "WeaponsLocker.items."+stmp)) { loc.WeaponsLocker.items.(stmp) = sti(loc.WeaponsLocker.items.(stmp)) + 1; } // KK
		else { loc.WeaponsLocker.items.(stmp) = 1; } // KK
	}
	*/
}
// NK <--

// ccc skillearning
void skillearning(ref chr, string skillnm, int lp)
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	int step = 10;
	int skillpt = sti(chr.skill.(skillnm));
	if(skillpt>9) return;

	switch(skillnm)
	{
	case "Fencing": step = 20; break;
	case "leadership": step = 40; break;
	case "defense": step = 20; break;

	}
	if(!CheckAttribute(chr,"skill."+skillnm+".lp")) chr.skill.(skillnm).lp = 0; // NK
	chr.skill.(skillnm).lp = sti(chr.skill.(skillnm).lp) + lp;

	if(sti(chr.skill.(skillnm).lp) > skillpt*skillpt*step)
	{
		chr.skill.(skillnm) = skillpt + 1;
		chr.skill.(skillnm).lp = 0;
		logit(chr.name + " " + chr.lastname + TranslateString("","'s") + " " + XI_ConvertString(skillnm) + " " + TranslateString("","skill has improved to") + " " + chr.skill.(skillnm) );
		PlayStereoSound("interface\new_level.wav");
	}
	//LanguageCloseFile(tmpLangFileID);
/*
	if (sti(chr.index) == GetMainCharacterIndex())
	{

	logit(chr.lastname + "'s " + skillnm + "skill is now " + chr.skill.(skillnm) + " lp: "  + chr.skill.(skillnm).lp);
	PlaySound("INTERFACE\button3.wav");	
	}
*/
}

// NK -->

// 05-07-10
// set citizens and guards (rel) to targetgroup. Done both for generic DEFAULT and GUARDS group, plus also local guards/citizens (if applicable)
void SetAllNormalGroupsRel(string targetgroup, string rel)
{
	string citgroup = GetCurrentCitizenGroup();
	string solgroup = GetCurrentSoldierGroup();
	if(citgroup != LAI_DEFAULT_GROUP) LAi_group_SetRelation(LAI_DEFAULT_GROUP, targetgroup, rel);
	if(solgroup != LAI_GROUP_GUARDS) LAi_group_SetRelation(LAI_GROUP_GUARDS, targetgroup, rel);
	LAi_group_SetRelation(citgroup, targetgroup, rel);				
	LAi_group_SetRelation(solgroup, targetgroup, rel);
}

// 05-07-26
// for corpse and stun, mostly
void LAI_group_SetRelationWithAllStock(string targetgroup, string rel)
{
	string citgroup = GetCurrentCitizenGroup();
	string solgroup = GetCurrentSoldierGroup();
	if(citgroup != LAI_DEFAULT_GROUP) LAi_group_SetRelation(LAI_DEFAULT_GROUP, targetgroup, rel);
	if(solgroup != LAI_GROUP_GUARDS) LAi_group_SetRelation(LAI_GROUP_GUARDS, targetgroup, rel);
	LAi_group_SetRelation(citgroup, targetgroup, rel);				
	LAi_group_SetRelation(solgroup, targetgroup, rel);
	LAi_group_SetRelation(LAI_GROUP_PLAYER, targetgroup, rel);
	LAi_group_SetRelation(LAI_GROUP_MONSTERS, targetgroup, rel);
}

float GetAttackLuckMod(ref chr)
{
	return (0.75 + (makefloat(GetCharacterSkill(&chr, SKILL_SNEAK))/50.0));
}

void LAi_AttemptSteal(aref attack, aref enemy, aref weapon)
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	if(CheckAttribute(enemy,"itemtrade")) // Jul05 for streetmerchants only
	{
		Logit(TranslateString("","The Merchantguild's watchmen are very vigilant..."));
		Ambush("rn_warnt18_2", 4, "enemy", "friend",""); // 4 cops attack you
	}

	if(frnd() < stf(weapon.steal)*GetAttackLuckMod(&attack)) // chance of successful theft are 75% + luckskill
	{
		bEnemyExchange = true; // added by MAXIMUS
		LaunchCharacterItemChange(enemy);	// ccc jun 05 stealinterface

		LAi_SetCitizenTypeNoGroup(enemy);	// makes disarmed victim flee
		PlaySound("INTERFACE\took_item.wav");
	} else {
		if(enemy.sex == "man") {PlaySound("VOICE\" + LanguageGetLanguage() + "\Eng_m_a_067.wav"); }	// victim raises alarm
		else{PlaySound("VOICE\" + LanguageGetLanguage() + "\Eng_f_c_016.wav"); }
		ChangeCharacterReputation(attack, -3);		// rephit for being caught 
		LAi_group_Attack(attack, enemy); // NK do this too
		SetAllNormalGroupsRel(LAI_GROUP_PLAYER, LAI_GROUP_ENEMY); // NK do this in one function 05-07-10
	}
	//LanguageCloseFile(tmpLangFileID);
}

void LAi_PlayHitGFX(aref attack, aref enemy, aref weapon, string effects_to_play)
{
	int i;
	float x, y, z;			// coordinates for effects
	GetCharacterPos(ARefChrToRef(enemy), &x, &y, &z);	// determines position of initial target
	string tmpstr;
	string cureff = GetSubString(effects_to_play, " ", 0);
	int cureffnum = 0;
	while(cureff != "")
	{
		if(CheckAttribute(weapon, cureff+".FX.qty"))
		{
			for(i = 0; i < sti(weapon.(cureff).FX.qty); i++)
			{
				tmpstr = "effect"+i;
				CreateParticleSystem(weapon.(cureff).fx.(tmpstr), x, y+1, z, 0.0, 0.0, 0.0, sti(weapon.(cureff).fx.(tmpstr).time));
			}
		}
		cureffnum++;
		cureff = GetSubString(effects_to_play, " ", cureffnum);
	}
}
// NK <--

// PB -->
#event_handler("PlaySoundAfterDelay_event", "PlaySoundAfterDelay")
void PlaySoundAfterDelay()
{
	string soundname = GetEventData();
	PlaySound(soundname);
}
// PB <--
