// GreatZen-NK -->
float ApplyArmor(ref chr, ref attack, float dmg, bool blade)
{
	if (!CheckAttribute(chr,"name")) return 0.0;	// LDH 03Oct06
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	bool isMC = sti(chr.index) == GetMainCharacterIndex() || sti(attack.index) == GetMainCharacterIndex();
	string person = "";
	if(!isMC)
	{
		person = chr.name + " " + chr.lastname + ": ";
		isMC = isMC || ARMOR_ALWAYSSHOW;
	}
	isMC = isMC && LogsToggle;
	isMC = false;
	if(!CheckAttribute(chr,"chr_ai.coverage"))
	{
		//if(isMC) { Log_SetStringToLog("No armor"); }
		return dmg;
	}
	else
	{
		if(stf(chr.chr_ai.coverage) == 0.0) // 04-11-13 bugfix
		{
			//if(isMC) { Log_SetStringToLog("No armor"); }
			return dmg;
		}
	}
	// NK add piercing to calc 05-04-22
	float covch = stf(chr.chr_ai.coverage) * (1.0 + makefloat(GetCharacterSkill(&chr, SKILL_SNEAK)) * ARMOR_LUCK_SCALAR);
	float piercing = 0.05;
	if(CheckAttribute(attack, "chr_ai.piercing"))
	{
		piercing = stf(attack.chr_ai.piercing);
	}
	float piercech = clampf(piercing - covch);
	if(frnd() > covch || frnd() < piercech)
	{
		if(isMC)
		{
			Log_SetStringToLog(person + TranslateString("","Slips by the armor!"));
		}
		return dmg;
	}
	// NK <--
	float afrac = ARMOR_DEFAULT_FRAC;
	float astop = ARMOR_DEFAULT_STOP;
	if(blade)
	{
		afrac = stf(chr.chr_ai.bladefrac);
		astop = stf(chr.chr_ai.bladestop);
	}
	else
	{
		afrac = stf(chr.chr_ai.gunfrac);
		astop = stf(chr.chr_ai.gunstop);
	}
	if(frnd() < astop)
	{
		if(isMC)
		{
			Log_SetStringToLog(person + TranslateString("","Stopped by armor!"));
		}
		return 0.0;
	}
	if(isMC)
	{
		Log_SetStringToLog(person + TranslateString("","Reduced by armor!"));
	}
	return dmg*afrac;
}
// GreatZen-NK <--

//--------------------------------------------------------------------------------
//Blade parameters
//--------------------------------------------------------------------------------

//Получить повреждение от сабли
float LAi_BladeCalcDamage(aref attack)
{
	//Расчитываем повреждение от сабли
	float min = 10.0;
	float max = 10.0;
	if(CheckAttribute(attack, "chr_ai.dmgbldmin"))
	{
		min = stf(attack.chr_ai.dmgbldmin);
	}
	if(CheckAttribute(attack, "chr_ai.dmgbldmax"))
	{
		max = stf(attack.chr_ai.dmgbldmax);
	}
	float dmg = min + (max - min)*(rand(100)*0.01);
	return dmg;
}

//Модифицировать повреждение от сабли с учётом скилов
float LAi_BladeApplySkills(aref attack, aref enemy, float dmg)
{
	//Учитываем скилы
	float aSkill = LAi_GetCharacterFightLevel(attack);
	float eSkill = LAi_GetCharacterFightLevel(enemy);
	if(aSkill >= eSkill)
	{
		dmg = dmg*(1.0 + 2.0*(aSkill - eSkill));
	}else{
		dmg = dmg*(1.0 + 0.5*(aSkill - eSkill));
	}
	// NK -->
	dmg *= (0.75 + fRand(GetSummonSkill(attack, SKILL_SNEAK))/(40.0/3.0));
	dmg *= (1.5 - fRand(GetSummonSkill(enemy, SKILL_SNEAK))/(40.0/3.0));
	float piercing = 0.05;
	float block = 0.01;
	if(CheckAttribute(attack, "chr_ai.piercing"))
	{
		piercing = stf(attack.chr_ai.piercing);
	}
	if(CheckAttribute(enemy, "chr_ai.block"))
	{
		block = stf(enemy.chr_ai.block);
	}
	if(piercing > block*2 && piercing > 0.1) dmg *= (1.0 + fRand(piercing)/2.0);
	if(sti(attack.index) == GetMainCharacterIndex()) dmg *= (1.45 - 0.15*GetDifficulty()); // NK Diff Mod
	else { if(sti(enemy.index) == GetMainCharacterIndex()) { dmg *= (0.85 + 0.15*GetDifficulty()); } } // NK Diff Mod
	// NK <--
	return dmg;
}

//Расчитать полученный опыт при ударе саблей
float LAi_BladeCalcExperience(aref attack, aref enemy, float dmg)
{
	//Вычисляем полученый опыт
	float ra = 1.0;
	float re = 1.0;
	if(CheckAttribute(attack, "rank"))
	{
		ra = stf(attack.rank);
	}
	if(CheckAttribute(enemy, "rank"))
	{
		re = stf(enemy.rank);
	}
	if(ra < 1.0) ra = 1.0;
	if(re < 1.0) re = 1.0;
//NK -->
	dmg = dmg*((1.0 + re*0.5)/(1.0 + ra*0.5)) * sqrt(re); //JA 8DEC06 reduced XP at high levels. (was leveling too fast up there)
	//Log_SetStringToLog("" + (dmg * 0.5));
// NK <-- 
	return dmg;
}

//Расчитать вероятность пробивки блока
float LAi_BladeFindPiercingProbability(aref attack, aref enemy, float hitDmg)
{
	float piercing = 0.05;
	float block = 0.01;
	if(CheckAttribute(attack, "chr_ai.piercing"))
	{
		piercing = stf(attack.chr_ai.piercing);
	}
	if(CheckAttribute(enemy, "chr_ai.block"))
	{
		block = stf(enemy.chr_ai.block);
	}
	float aSkill = LAi_GetCharacterFightLevel(attack);
	float eSkill = LAi_GetCharacterFightLevel(enemy);
	// NK - if(aSkill < eSkill) aSkill = eSkill;
	float p = piercing - block + (aSkill - eSkill)*0.5;
	if(p <0) p = 0; // NK
	float k = 1.0;
	if(IsCharacterPerkOn(enemy, "BasicDefense")) k = 0.75;
	if(IsCharacterPerkOn(enemy, "AdvancedDefense")) k = 0.5;
	hitDmg = hitDmg*0.5 + 0.5;
	//if(sti(enemy.index) == GetMainCharacterIndex() || sti(attack.index) == GetMainCharacterIndex()) Log_SetStringToLog("p" + p + ", k" + k + ", dmg = " + (p*k*hitDmg*hitDmg)); // NK
	p = p*k*hitDmg*hitDmg;
	return p;
}

//--------------------------------------------------------------------------------
//Gun parameters
//--------------------------------------------------------------------------------

//Расчитаем вероятность попадания
float LAi_GunCalcProbability(aref attack, float kDist)
{
	//Если близко, то попадём точно
	if(kDist >= 0.9) return 1.0;
	//Расчитаем вероятность на конце отрезка
	float pmin = 0.3;
	if(CheckAttribute(attack, "chr_ai.accuracy"))
	{
		pmin = stf(attack.chr_ai.accuracy);
	}
	//Применим разброс от скила
	float aSkill = LAi_GetCharacterFightLevel(attack);
	pmin = pmin + 0.3*aSkill;
	//Вероятность попадания в текущей позиции
	float p = pmin + (1.0 - pmin)*(kDist/0.9);
	//Учесть абилити
	if(IsCharacterPerkOn(attack, "GunProfessional"))
	{
		p = p + 0.25;
	}else{
		if(IsCharacterPerkOn(attack, "Gunman"))
		{
			p = p + 0.1;
		}
	}
	return p;
}

//Получить повреждение от пистолета
float LAi_GunCalcDamage(aref attack)
{
	//Расчитываем повреждение от сабли
	float min = 10.0;
	float max = 10.0;
	if(CheckAttribute(attack, "chr_ai.dmggunmin"))
	{
		min = stf(attack.chr_ai.dmggunmin);
	}
	if(CheckAttribute(attack, "chr_ai.dmggunmax"))
	{
		max = stf(attack.chr_ai.dmggunmax);
	}
	float dmg = min + (max - min)*(rand(100)*0.01);
	// NK -->
	dmg *= (0.75 + fRand(GetSummonSkill(attack, SKILL_SNEAK))/(40.0/3.0));
	if(sti(attack.index) == GetMainCharacterIndex()) dmg *= (1.45 - 0.15*GetDifficulty()); // NK Diff Mod
	// NK <--
	return dmg;
}

//Расчитать полученный опыт при попадании из пистолета
float LAi_GunCalcExperience(aref attack, aref enemy, float dmg)
{
	//Вычисляем полученый опыт
	float ra = 1.0;
	float re = 1.0;
	if(CheckAttribute(attack, "rank"))
	{
		ra = stf(attack.rank);
	}
	if(CheckAttribute(enemy, "rank"))
	{
		re = stf(enemy.rank);
	}	
	if(ra < 1.0) ra = 1.0;
	if(re < 1.0) re = 1.0;
//NK -->
	dmg = dmg*((1.0 + re*0.5)/(1.0 + ra*0.5)) * re;
	//Log_SetStringToLog("" + (dmg * 0.5));
// NK <-- 
	return dmg;
}

//Расчитаем текущую скорость перезарядки пистолета
float LAi_GunReloadSpeed(aref chr)
{
	//Получим текущее состояние скорости зарядки
	float charge_dlt = LAI_DEFAULT_DLTCHRG;
	if(CheckAttribute(chr, "chr_ai.charge_dlt"))
	{
		charge_dlt = stf(chr.chr_ai.charge_dlt);
	}

     //JRH
	float F;
	float P;
	if(CheckAttribute(chr,"equip."+FLASK_ITEM_TYPE))
	{
		F = 1.05;	
	}
	else
	{
		F = 0.9;
	}
	if(CheckAttribute(chr,"equip."+POUCH_ITEM_TYPE)) 
	{	
		P = 1.05;
	}
	else
	{
		P = 0.9;
	}
     //JRH

	//Модифицируем скилом
	float skill = LAi_GetCharacterFightLevel(chr);
	//charge_dlt = charge_dlt*(1.0 + 0.25*skill);
	charge_dlt = charge_dlt*(1.0 + 0.25*skill)*F*P; //JRH
	//Учтём абилити
	if(IsCharacterPerkOn(chr, "GunProfessional"))
	{
		charge_dlt = charge_dlt*1.5;
	}else{
		if(IsCharacterPerkOn(chr, "Gunman"))
		{
			charge_dlt = charge_dlt*1.1;
		}
	}
// added by MAXIMUS 21.07.2006 [weapon will not be charged without gunpowder or proper bullets] -->
	if(ENABLE_AMMOMOD==1)
	{
	    if(GetCharacterIndex(chr.id)==GetMainCharacterIndex() || IsOfficer(chr) ) //JRH fix oct 06
   	    {
		if(CheckAttribute(chr,"equip."+GUN_ITEM_TYPE))
		{
			string weaponID = GetCharacterEquipByGroup(chr,GUN_ITEM_TYPE);
			aref weapon;
			Items_FindItem(weaponID, &weapon);
			if(CheckAttribute(weapon,"shottype"))
			{
				string ammoName;
				int gp;
				int pb;
				int pg;
				int mb;

				gp = GetCharacterItem(chr, "gunpowder");
 				pg = GetCharacterItem(chr, "pistolgrapes");
				mb = GetCharacterItem(chr, "musketbullets");
				pb = GetCharacterItem(chr, "pistolbullets");

				switch(weapon.shottype)
				{
					case "pg2": 
						ammoName = "pistolgrapes";
						if(pg <= 1 || gp <= 1) return 0.0;// JRH fix oct 06: not only when pg/gp = 0 ! 
					break;
					case "pg": 
						ammoName = "pistolgrapes"; 
						if(pg == 0 || gp == 0) return 0.0;
					break;
					case "mb": 
						ammoName = "musketbullets";
						if(mb == 0 || gp <= 1) return 0.0;
					break;
					case "pb": 
						ammoName = "pistolbullets";
						if(pb == 0 || gp == 0) return 0.0;
					break;
				}
				if(!CheckAttribute(chr,"Items.gunpowder")) chr.Items.gunpowder = 0;
				if(!CheckAttribute(chr,"Items."+ammoName) || sti(chr.Items.gunpowder)==0)
				{
					string aboutBullet = "";
					string aboutPowder = "";
					//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");

					if(!CheckAttribute(chr,"Items."+ammoName)) aboutBullet = XI_ConvertString("n"+ammoName);
					if(sti(chr.Items.gunpowder)==0) aboutPowder = XI_ConvertString("ngunpowder");
					if(!CheckAttribute(chr,"Items."+ammoName) && sti(chr.Items.gunpowder)==0) aboutPowder = TranslateString("","and gunpowder");

					if(GetCharacterIndex(chr.id)==GetMainCharacterIndex())
					{
				//		if(!LAi_IsFightMode(chr)) Log_SetStringToLog(LanguageConvertString(tmpLangFileID,"There are no") + " " + aboutBullet + " " + aboutPowder + " " + LanguageConvertString(tmpLangFileID,"left"));
						// JRH fix oct 06: outcommented for 2 reasons: annoying & doesnґt cover cases like: mtoon 2pg + 1gp
					}
					//LanguageCloseFile(tmpLangFileID);
					//return 0.0;// JRH bugfix oct 06: moved up
				}
			}
		}
	  }
	}
// added by MAXIMUS 21.07.2006 [weapon will not be charged without gunpowder or proper bullets] <--
	if(LAi_IsFightMode(chr) && CANNOT_RELOAD_WHILE_FIGHTING && CheckCharacterEquipByGroup(chr,BLADE_ITEM_TYPE) != "bladeX4"&& CheckCharacterEquipByGroup(chr,GUN_ITEM_TYPE) != "pistol10")  return 0.0; // PB: Can reload when using fists or shotgun
	return charge_dlt;
}

//--------------------------------------------------------------------------------
//All
//--------------------------------------------------------------------------------

float LAi_CalcDeadExp(aref attack, aref enemy)
{
	//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
	//Вычисляем полученый опыт
	float ra = 1.0;
	float re = 1.0;
	if(CheckAttribute(attack, "rank"))
	{
		ra = stf(attack.rank);
	}
	if(CheckAttribute(enemy, "rank"))
	{
		re = stf(enemy.rank);
	}	
	if(ra < 1.0) ra = 1.0;
	if(re < 1.0) re = 1.0;		
	float dmg = (0.5 + 4.0*LAi_GetCharacterFightLevel(enemy))*LAi_GetCharacterMaxHP(enemy);
//NK -->
	dmg = dmg*((1.0 + re*0.5)/(1.0 + ra*0.5));
	dmg *= 6.0;
	//Log_SetStringToLog("" + (dmg * 0.25));
	/*DebugLog("Dead chr group: " + enemy.chr_ai.group);
	if(sti(attack.index) == GetMainCharacterIndex() && CheckAttribute(enemy,"chr_ai.group"))
	{
		AddOneSoldier(enemy.chr_ai.group);
	}*/
// NK <-- 
	//NK -->

		ref PChar = GetMainCharacter();
		ref lcn = &Locations[FindLocation(PChar.location)];
		bool AutoLoot = false;
		if(AUTOLOOT_ON) AutoLoot = true; // TIH autoloot all the time
		if(LAi_IsBoardingProcess()==true && AUTOLOOT_BOARDINGS && CORPSEMODE<4) AutoLoot = true; // PB: Automatic looting during boardings (at LDH's request) //MAXIMUS: excludes player's decks and CORPSEMODE 4
		if(sti(attack.index) != GetMainCharacterIndex()) AutoLoot = false; // TIH only main character autoloots
		if(sti(enemy.index) == GetMainCharacterIndex()) AutoLoot = false; // ccc Survival so that you don't loot yourself if being killed
		if(CheckAttribute(lcn, "abbey") && sti(lcn.abbey) == true) AutoLoot = false; // PB: Looting Maltese Knights is handled differently // KK
		if(AutoLoot)
		{
			//int idLngFile2 = LanguageOpenFile(GetStorylineDir(FindCurrentStoryline()) + "ItemsDescribe.txt"); // KK
			int q;
			aref tempitem;
			bool log = false;
			string b = "";
			string g = "";
			string m = "";
			string comp = "";
			string tempitm = ""; // PB: prevent double looting
			bool btemp = !IsOfficer(attack) && !IsOfficer(enemy);
			// SCREWFACE : to loot enemy weapons if one of your crewmember kill an enemy
			if(attack.name==XI_ConvertString("Crewmember") || enemy.name==XI_ConvertString("Crewmember")){btemp=false;}
			// END
			if(!btemp) // that is, do this if either attack || enemy is officer. Done as a ! and && because there were originally three ors to do and some nesting which POTC doesn't support.
			{
				int ethingidx;
				if(CheckAttribute(enemy, "equip.blade") && enemy.lastname != VC_MONKEY_LNAME) // ccc
				{
					//tmp += enemy.equip.blade;
					ethingidx = GetItemIndex(enemy.equip.blade);
					if(ENABLE_WEAPONSMOD && CheckAttribute(Items[ethingidx], "bladequality") && sti(Items[ethingidx].bladequality) < MIN_QUALITY_TO_KEEP+2) // NK 04-11-03 add min qual check
					{
						//do nothing
					}
					else
					{
						tempitm = GetCharacterEquipByGroup(enemy,BLADE_ITEM_TYPE);
						if(tempitm != "bladeX4")
						// PB: Don't loot fists
						{
							GiveItem2Character(GetMainCharacter(), tempitm);
							TakeItemFromCharacter(enemy, tempitm); // PB: To prevent double looting
							makearef(tempitem, Items[ethingidx]); // NK 04-09-08 now use native getindex
							log = true;
							b = " " + XI_ConvertString("a") + " " + TranslateString("",tempitem.name);
						}
					}
				}
				if(CheckAttribute(enemy, "equip.gun") && enemy.lastname != VC_MONKEY_LNAME) // ccc
				{
					ethingidx = GetItemIndex(enemy.equip.gun);
					if(ENABLE_WEAPONSMOD && CheckAttribute(Items[ethingidx], "gunquality") && sti(Items[ethingidx].gunquality) < MIN_QUALITY_TO_KEEP+2) // NK 04-11-03 add min qual check
					{
						//do nothing
					}
					else
					{
						tempitm = GetCharacterEquipByGroup(enemy,GUN_ITEM_TYPE);
						GiveItem2Character(GetMainCharacter(), tempitm);
						TakeItemFromCharacter(enemy, tempitm); // PB: To prevent double looting
						makearef(tempitem, Items[ethingidx]); // NK 04-09-08 now use native getindex
						log = true;
						if(b == "") { g = " " + XI_ConvertString("a") + " " + TranslateString("",tempitem.name);}
						else { g = " " + XI_ConvertString("and") + " " + XI_ConvertString("a") + " " + TranslateString("",tempitem.name);}
					}
				}
				if(CheckAttribute(enemy,"money") && sti(enemy.money))
				{
					AddMoneyToCharacter(GetMainCharacter(), sti(enemy.money));
					log = true;
					if(b == "" && g == "") {m = " " + sti(enemy.money) + " " + XI_ConvertString("1gold");}
					else {m = " " + XI_ConvertString("and") + " " + sti(enemy.money) + " " + XI_ConvertString("1gold");}
					enemy.money = 0; // PB: To prevent double looting
				}
				//ccc10.2 ->
				if(enemy.lastname == VC_MUMMY_LNAME) //ccc Amazone artefact
				{
					if(CORPSEMODE != 2) GiveItem2Character(GetMainCharacter(), "indian" + (1 + rand(15))); // PB: If corpsemode on, you have to loot the artifacts from the body yourself
					log = true;
					if(b == "" && g == "") {m = " " + TranslateString("","an Indian artifact");}
					else {m = " " + XI_ConvertString("and") + " " + TranslateString("","an Indian artifact");}
				}
				//ccc10.2 <-
				if(log && LOGLOOT) comp = TranslateString("","You got") + b + g + m + ". "; // LDH: Add a toggle
				Log_SetStringToLog(comp + TranslateString("","Total XP:") + " " + makeint(dmg*0.25));
				//trace(comp);
				//traceandlog("from chr " + enemy.id + " you got " + tmp + " +++++++++++++");
			}
		}
		if(enemy.lastname == VC_MONKEY_LNAME) //ccc monkeyhide
		{
			AddCharacterGoods(GetMainCharacter(), GOOD_LEATHER, 1);
			Log_SetStringToLog(TranslateString("","You got the beast's hide!"));
		}
	// NK <--
	return dmg*0.5;
}

//--------------------------------------------------------------------------------
//Calculate
//--------------------------------------------------------------------------------


//Начисление повреждений при незаблокированной атаке
void LAi_ApplyCharacterAttackDamage(aref attack, aref enemy, float attackDmg, float hitDmg)
{
	LAi_ApplyCharacterBladeDamage(attack, enemy, attackDmg, hitDmg, false);
}

//Начисление повреждений при заблокированной атаке
void LAi_ApplyCharacterBlockDamage(aref attack, aref enemy, float attackDmg, float hitDmg)
{
	LAi_ApplyCharacterBladeDamage(attack, enemy, attackDmg, hitDmg, true);
}

//Начисление повреждений при атаке мечём
void LAi_ApplyCharacterBladeDamage(aref attack, aref enemy, float attackDmg, float hitDmg, bool isBlocked)
{
	//Если неубиваемый, то нетрогаем его
	if(CheckAttribute(enemy, "chr_ai.immortal"))
	{
		if(sti(enemy.chr_ai.immortal) != 0) return;
	}
	//Применяем абилити
	float pBreak = 0.0;
	float critical = 0.0;
	if(IsCharacterPerkOn(attack, "SwordplayProfessional"))
	{
		pBreak = pBreak + 0.25;
		if(rand(100) <= 25)
		{
			if(CheckAttribute(enemy, "rank"))
			{
				critical = 20.0 + stf(enemy.rank)*2.0;
			}
		}
	}else{
		if(IsCharacterPerkOn(attack, "CriticalHit"))
		{
			if(rand(100) <= 5)
			{
				if(CheckAttribute(enemy, "rank"))
				{
					critical = 20.0 + stf(enemy.rank)*1.5;
				}
			}
		}
	}
	float kDmg = 1.0;
	if(IsCharacterPerkOn(attack, "Rush"))
	{
		kDmg = 1.5;
		pBreak = pBreak + 0.5;
	}
	if(IsCharacterPerkOn(enemy, "Rush"))
	{
		pBreak = pBreak + 0.9;
	}
	if(critical > 0.0)
	{
		if(sti(attack.index) == GetMainCharacterIndex())
		{
			Log_SetStringToLog(XI_ConvertString("Critical Hit"));
		}
	}
	isBlocked = isBlocked && CheckAttribute(enemy,"equip.blade") && GetCharacterEquipByGroup(enemy,BLADE_ITEM_TYPE) != "bladeX4";
	// PB: Disable blocking for enemies with either no sword or their fists equiped
	if(isBlocked)
	{
		//Вероятность пробивки
		float p = LAi_BladeFindPiercingProbability(attack, enemy, hitDmg);
		p = p + pBreak;
		//Если шансов пробить нет, то ненаносим провреждения
		if(p < 0.0) return;
		//Если шансов пробить нет, то ненаносим провреждения
		if(rand(10000) > p*10000)
		{
			// HawkerT Feb07 Blockdamage -->
			if(BLOCKDAMAGE > 0)
			{
				int curBlockDamage = 2*rand(makeint(attack.skill.Fencing));
				int actBlockDamage = BLOCKDAMAGE;
				if(curBlockDamage > BLOCKDAMAGE)
				{
					actBlockDamage = curBlockDamage;
				}

				if(GetCharacterEquipByGroup(attack, BLADE_ITEM_TYPE) != "bladeX4")
				{
					if(!LAi_IsImmortal(enemy))
					{
						LAi_ApplyCharacterDamage(enemy, actBlockDamage);
						LAi_CheckKillCharacter(enemy);
						return;
					}
				}else{
					if(!LAi_IsImmortal(attack))
					{
						LAi_ApplyCharacterDamage(attack, actBlockDamage);
						LAi_CheckKillCharacter(attack);
						return;
					}
				}
				return;
			}
			// HawkerT Feb07 Blockdamage <--
		}
	}
	//Вычисляем повреждение
	float dmg = LAi_BladeCalcDamage(attack);
	dmg = dmg*kDmg;
	//Аттака своей группы
	bool noExp = false;
	if(CheckAttribute(attack, "chr_ai.group"))
	{
		if(CheckAttribute(enemy, "chr_ai.group"))
		{
			if(attack.chr_ai.group == enemy.chr_ai.group && !CheckAttribute(GetMainCharacter(),"TrainingFight") && !HasSubStr(attack.id,"TrainingFight_") && !HasSubStr(enemy.id,"TrainingFight_"))//MAXIMUS
			{
			// ccc mar05 REPLOSS tweak added
				LAi_ChangeReputation(attack, - REPLOSS);	// ccc rephit for attacking friends
				dmg = 0.0;
				critical = 0.0;
				noExp = true;
			}
		}
	}
	kDmg = 1.0;
	if(IsCharacterPerkOn(enemy, "BasicDefense")) kDmg = 0.9;
	if(IsCharacterPerkOn(enemy, "AdvancedDefense")) kDmg = 0.8;
	if(IsCharacterPerkOn(enemy, "SwordplayProfessional")) kDmg = 0.6;
	dmg = dmg*kDmg;
	float damage = LAi_BladeApplySkills(attack, enemy, dmg);
	if(isBlocked)
	{
		damage = damage*0.3;
	}
	// TIH --> do not show XP messages for other characters, its annoying! Aug24'06
	bool resetshowXP = false;
	if(sti(attack.index) != GetMainCharacterIndex())
	{
		attack.donotshowXP = true;
		resetshowXP = true;
	}
	// TIH <--
	// if(!LAi_IsFightMode(enemy) && attack.equip.blade=="blade5") {damage = damage*(rand(5)+sti(attack.skill.Sneak)+5);}	// ccc sneakmod backstab

	//Наносим повреждение
	LAi_ApplyCharacterDamage(enemy, MakeInt(ApplyArmor(enemy, attack, damage + critical, true) + 0.5)); // GreatZen-NK
	//Проверим на смерть
	LAi_CheckKillCharacter(enemy);
	//Есть ли оружие у цели
	bool isSetBalde = (SendMessage(enemy, "ls", MSG_CHARACTER_EX_MSG, "IsSetBalde") != 0);
	//Начисляем опыта
	float exp = LAi_BladeCalcExperience(attack, enemy, dmg);
	if(LAi_IsDead(enemy))
	{
		//Начислим за убийство
		exp = exp + LAi_CalcDeadExp(attack, enemy);
		if(!isSetBalde)
		{
			// ccc mar05 REPLOSS tweak added
			if(enemy.chr_ai.group != LAi_monsters_group) LAi_ChangeReputation(attack, - REPLOSS*3); // NK tempfix for un-drawn blades 04-17
		}
	}
	if(AUTO_SKILL_SYSTEM) { if(!LAi_IsDead(enemy)) { AddCharacterExpChar(enemy, "Defence", MakeInt(stf(exp*0.5 + 0.5))/2); } }// MAXIMUS!
	if(!isSetBalde)
	{
		// ccc mar05 REPLOSS tweak added
		if(enemy.chr_ai.group != LAi_monsters_group) LAi_ChangeReputation(attack, - REPLOSS); // NK tempfix for un-drawn blades 04-17
		exp = 0.0;
	}

	if(!noExp) { if(AUTO_SKILL_SYSTEM) { AddCharacterExpChar(attack, "Fencing", MakeInt(exp*0.5 + 0.5)); }else{ AddCharacterExp(attack, MakeInt(exp*0.5 + 0.5)); } }
	if ( resetshowXP ) { DeleteAttribute(attack,"donotshowXP"); } // TIH do not show other characters XP increases
}

//Начисление повреждений при попадании
void LAi_ApplyCharacterFireDamage(aref attack, aref enemy, float kDist)
{
	//Если неубиваемый, то нетрогаем его
	if(CheckAttribute(enemy, "chr_ai.immortal"))
	{
		if(sti(enemy.chr_ai.immortal) != 0) return;
	}
	//Вероятность поподания
	float p = LAi_GunCalcProbability(attack, kDist);
	//Если промахнулись, то выйдем
	if(rand(10000) > p*10000) return;	
	//Начисляем повреждение
	float damage = LAi_GunCalcDamage(attack);
	//Аттака своей группы
	bool noExp = false;
	if(CheckAttribute(attack, "chr_ai.group"))
	{
		if(CheckAttribute(enemy, "chr_ai.group"))
		{
			if(attack.chr_ai.group == enemy.chr_ai.group && !CheckAttribute(GetMainCharacter(),"TrainingFight") && !HasSubStr(attack.id,"TrainingFight_") && !HasSubStr(enemy.id,"TrainingFight_"))//MAXIMUS
			{
				LAi_ChangeReputation(attack, -1);
				damage = 0.0;
				noExp = true;
			}
		}
	}
	LAi_ApplyCharacterDamage(enemy, ApplyArmor(enemy, attack, damage, false) + 0.5)); // GreatZen-NK
	//Проверим на смерть

	// ccc sep05, keeps player & officers barely alive
	if(stf(enemy.chr_ai.hp)<1.0 && enemy.chr_ai.group==LAI_GROUP_PLAYER) enemy.chr_ai.hp = MIN_GUNATTACK_HP;

	LAi_CheckKillCharacter(enemy);
	//Есть ли оружие у цели
	bool isSetBalde = (SendMessage(enemy, "ls", MSG_CHARACTER_EX_MSG, "IsSetBalde") != 0);
	//Начисляем опыт
	float exp = LAi_GunCalcExperience(attack, enemy, damage);
	if(LAi_IsDead(enemy))
	{
		//Начислим за убийство
		exp = exp + LAi_CalcDeadExp(attack, enemy);
		if(!isSetBalde)
		{
			// ccc mar05 REPLOSS tweak added
			if(enemy.chr_ai.group != LAi_monsters_group) LAi_ChangeReputation(attack, - REPLOSS*3); // NK tempfix for un-drawn blades 04-17
			exp = exp*0.05;
		}
	}
	if(AUTO_SKILL_SYSTEM) { if(!LAi_IsDead(enemy)) { AddCharacterExpChar(enemy, "Defence", MakeInt(stf(exp*0.5 + 0.5))/2); } }// MAXIMUS!
	if(!isSetBalde)
	{
		// ccc mar05 REPLOSS tweak added
		if (!CheckAttribute(enemy,"chr_ai.group")) exp = 0.0;	// LDH 03Oct06
		if(enemy.chr_ai.group != LAi_monsters_group) LAi_ChangeReputation(attack, -REPLOSS); // NK tempfix for un-drawn blades 04-17
		exp = 0.0;
	}
	if(!noExp) { if(AUTO_SKILL_SYSTEM) { AddCharacterExpChar(attack, "Accuracy", MakeInt(exp*0.5 + 0.5)); }else{ AddCharacterExp(attack, MakeInt(exp*0.5 + 0.5)); } }
}

//--------------------------------------------------------------------------------
//NPC parameters
//--------------------------------------------------------------------------------

#event_handler("NPC_Event_GetAttackActive","LAi_NPC_GetAttackActive");
#event_handler("NPC_Event_GetDefenceActive","LAi_NPC_GetAttackDefence");
#event_handler("NPC_Event_GetAggresive","LAi_NPC_GetAggresive");
#event_handler("NPC_Event_GetFireActive","LAi_NPC_GetFireActive");
#event_handler("NPC_Event_EnableFire","LAi_NPC_EnableFire");

float npc_return_tmp;
bool npc_return_tmpb;

// NK 05-05-12:
// remember, level is 0...1, NOT 0...10

// for high level characters, should _always_ be doing something, either attack or block.

// dunno whether 1.0 = always do something, or if >1.0 value is needed.
//probability of attack. Value per sec. > 0
float LAi_NPC_GetAttackActive()
{
	aref chr = GetEventData();
	float level = LAi_GetCharacterFightLevel(chr);
	/*npc_return_tmp = 0.3 + level*0.7;
	if(!bArcadeMode)
	{*/
		npc_return_tmp = (0.3 + level*0.7) * 3;
	//}
	float tmp = 0.3 + level*0.7;
	npc_return_tmp = (npc_return_tmp * GetDifficulty() + (5-GetDifficulty()) * tmp) / 5;
	// debug - npc_return_tmp = 9999;
	//trace("for chr " + chr.id + " of level " + level + " set attackactive " + npc_return_tmp);
	return npc_return_tmp;
}

// same here - 1.0 max???
//probability of defence. Value per sec. > 0
float LAi_NPC_GetAttackDefence()
{
	aref chr = GetEventData();
	float level = LAi_GetCharacterFightLevel(chr);
	/*npc_return_tmp = 0.008 + level*0.08;
	if(!bArcadeMode)
	{*/
		npc_return_tmp = (0.333 + frnd()*0.1 + level*0.5) * randmult(0.1); //npc_return_tmp+ 0.5;
		//if (npc_return_tmp >0.9) npc_return_tmp = 0.9;
	//}
	float tmp = 0.008 + level*0.08;
	npc_return_tmp = (npc_return_tmp * GetDifficulty() + (5-GetDifficulty()) * tmp) / 5;
	//trace("for chr " + chr.id + " of level " + level + " set attackdefense " + npc_return_tmp);
	return npc_return_tmp;
}

//balance between defence and attack 0..1
float LAi_NPC_GetAggresive()
{
	aref chr = GetEventData();
	float level = LAi_GetCharacterFightLevel(chr);
	/*npc_return_tmp = rand(10)*0.1*(0.4 + level*0.6);
	if(!bArcadeMode)
	{*/
		//if(IsOfficer(&chr))
		npc_return_tmp = pow2(0.67 * randmult(0.1)-level*0.1, 1.0 + level*2.0);
		if(npc_return_tmp < 0.2) npc_return_tmp = pow2(npc_return_tmp, 0.33 + level/3.0);
		// NK
		//npc_return_tmp = npc_return_tmp+ 0.05;
		//if (npc_return_tmp >0.4) npc_return_tmp = 0.4;
	//}
	float tmp = rand(10)*0.1*(0.4 + level*0.6);
	npc_return_tmp = (npc_return_tmp * GetDifficulty() + (5-GetDifficulty()) * tmp) / 5;
	//trace("for chr " + chr.id + " of level " + level + " set aggressive " + npc_return_tmp);
	return npc_return_tmp;
}

//probability of fire. Value per sec. > 0
float LAi_NPC_GetFireActive()
{
	aref chr = GetEventData();
	float level = LAi_GetCharacterFightLevel(chr);
	/*npc_return_tmp = 0.001 + level*0.06;
	if(!bArcadeMode)
	{*/
		npc_return_tmp = (npc_return_tmp+ 0.1) * 2.0; // NK add 2.0
		if (npc_return_tmp >0.5) npc_return_tmp = 0.5;
	//}
	float tmp = 0.001 + level*0.06;
	npc_return_tmp = (npc_return_tmp * GetDifficulty() + (5-GetDifficulty()) * tmp) / 5;
	//trace("for chr " + chr.id + " of level " + level + " set fireactive " + npc_return_tmp);
	return npc_return_tmp;
}

//is fire enable?
bool LAi_NPC_EnableFire()
{
	aref chr = GetEventData();
	/*float level = LAi_GetCharacterFightLevel(chr);
	npc_return_tmpb = false;
	if(!bArcadeMode)
	{*/
		npc_return_tmpb = true; // NK
		/*level = level + 0.02;
	}
	if(level > 0.1) npc_return_tmpb = true;*/
	//trace("for chr " + chr.id + " of level " + level + " set enablefire " + npc_return_tmpb);
	if(ENABLE_AMMOMOD==1 && sti(RecalcCharacterGun(chr))<=0) { npc_return_tmpb = false; }//MAXIMUS: character will not fire with not loaded gun
	return npc_return_tmpb;
}

#event_handler("Location_CharacterSGFire","LAi_Location_CharacterSGFire");
void LAi_Location_CharacterSGFire()
{
	aref attack = GetEventData();
	aref enemy = GetEventData();
	float kDmg = GetEventData();
	if(LAi_IsDead(enemy)) return;
	//Реакция груп на атаку
	LAi_group_Attack(attack, enemy);
	if(AUTO_SKILL_SYSTEM) { AddCharacterExpChar(attack, "Accuracy", 100*kDmg); }
	else { AddCharacterExp(attack, 100*kDmg); }
	//Наносим повреждение
	LAi_ApplyCharacterDamage(enemy, MakeInt((5 + rand(5))*kDmg));
	//Проверим на смерть
	LAi_CheckKillCharacter(enemy);
}
