#define  UTIL_EXP_H aaa
//----------------------------------------------------------------------------
//  @brief
//		

//  @ingroup
    
//  2007Aug20 created. Zmanovsky Peter.
//  (C) 2007    Sigma-Team
//-----------------------------------------------------------------------------

#define MAX_SKILL_VALUE			10
//
#define MAX_EXP_LEVELS			100

//------------------------------------------------------------------------------------------
static int ciExpLevels[MAX_EXP_LEVELS];
int giExpToNextLevel = 0;
int giExpBetweenLevel = 0;
//
int giPlayerMaxHp0 = 0;
int giAmmoCnt0[20];
int giWpnAim0[20];
//
int giBulletScale0[10];
int giWpnDmg0[10];
int giDeathRange0[10];
int giInitGamma[10];
int giBulletsCnt0[10];
int giReload0[10];

//
//------------------------------------------------------------------------------------------
//объект, который наносит damage
int ciBulletVids[9] = {
	168,	//1-пистолет
	100,	//2-ружье
	175,	//3-ракетница
	156,	//4-пулемет
	113,	//5-ракета
	937,	//6-заморозка
	112,	//7-плазма
	904,	//8-огнемет
	129		//9-магма
};
//пуля - визуальный объект
int ciVisualBulletVids[9] = {
	168,	//1-пистолет
	100,	//2-ружье
	134,	//3-ракетница
	156,	//4-пулемет
	113,	//5-ракета
	145,	//6-заморозка
	112,	//7-плазма
	141,	//8-огнемет
	129		//9-магма
};
//пуля - визуальный объект 2
int ciVisualBulletVids2[9] = {
	0,	//1-пистолет
	0,	//2-ружье
	0,	//3-ракетница
	0,	//4-пулемет
	0,	//5-ракета
	146,	//6-заморозка
	0,	//7-плазма
	0,	//8-огнемет
	0		//9-магма
};
//номера видов объектов, которые рожают пули
int ciFlameVids[9] = {
	104,	//1-пистолет
	126,	//2-ружье
	 13,	//3-ракетница
	137,	//4-пулемет
	 15,	//5-ракета
	 16,	//6-заморозка
	114,	//7-плазма
	142,	//8-огнемет
	132		//9-магма
};
//номера видов торсов
int ciTorseVids[9] = {
	11,		//1-пистолет
	12,		//2-ружье
	13,		//3-ракетница
	14,		//4-пулемет
	15,		//5-ракета
	16,		//6-заморозка
	17,		//7-плазма
	18,		//8-огнемет
	19		//9-магма
};

//------------------------------------------------------------------------------------------
static int giInitSkills[SKILLS_CNT];

//------------------------------------------------------------------------------------------
GetExpToNextLevel()
{
	giExpToNextLevel = 999999;
	//
	int i;
	for(i = 0; i < MAX_EXP_LEVELS; i++)
	{
		if(giExpa < ciExpLevels[i])
		{
			giExpToNextLevel = ciExpLevels[i] - giExpa;
            if ( i )
                giExpBetweenLevel = ciExpLevels[i] - ciExpLevels[i - 1];
            else
                giExpBetweenLevel = ciExpLevels[i];
			break;
		}
	}
}


//------------------------------------------------------------------------------------------
GenExpLevelsIfNeed()
{
	iff(1)
	{
		int i;
		//
		//old version
		//ciExpLevels[0] = 1000;
		//for(i = 1; i < MAX_EXP_LEVELS; i++)
		//	ciExpLevels[i] = ciExpLevels[i-1] * 2;
		//
		//новая версия заполнения
		int j = 0;
		for(i = 0; i < 10; i++)
		{
			if(j==0)
			{
				ciExpLevels[j] = LevelUpExpa[i] / 2;
				ciExpLevels[j+1] = LevelUpExpa[i];
			}
			else
			{
				ciExpLevels[j] = ciExpLevels[j-1] + LevelUpExpa[i] / 2;
				ciExpLevels[j+1] = ciExpLevels[j-1] + LevelUpExpa[i];
			}
			//
			j += 2;
		}
		for(i = j; i < MAX_EXP_LEVELS; i++)
			ciExpLevels[j] = LevelUpExpa[9];
		//
		if(Z_DEBUG)
		{
			Log2("ciExpLevels");
			for(i = 0; i < 30; i++)
				Log2("ciExpLevels["+itoa(i)+"] = " + itoa(ciExpLevels[i]));
		}
		//
		GetExpToNextLevel();
		//
		if(gsPlayer_Sex=="male" || DEMO_VERSION)
		{
			for(i = 0; i < SKILLS_CNT; i++)
				giInitSkills[i] = MALE_INIT_SKILL[i];
		}
		else
		{
			for(i = 0; i < SKILLS_CNT; i++)
				giInitSkills[i] = FEMALE_INIT_SKILL[i];
		}
	}
}


int giExpEffect = 0;
int giExpEffectZ = 0;
//------------------------------------------------------------------------------------------
ExpEffectTact()
{
	if(giExpEffect)
	{
		int x = GetX(Flagman(0));
		int y = GetY(Flagman(0));
		int z = GetZ(Flagman(0));
		//giExpEffectZ += 30*giLastTactTime;
		Action(giExpEffect, ACT_CHANGE_COOR, x, y, giExpEffectZ / 1000);
	}
}


//------------------------------------------------------------------------------------------
CreateExpEffect()
{
	if(!giExpEffect)
	{
		giExpEffect = CreateSprite(1001, 0, 0, 80);
		giExpEffectZ = 80 * 1000;
	}
	ExpEffectTact();
}


//------------------------------------------------------------------------------------------
F1001_DESTROY(int unit)
{
	giExpEffect = 0;
}


//------------------------------------------------------------------------------------------
ExpTact()
{
	ExpEffectTact();
}


//------------------------------------------------------------------------------------------
IncreaseExpa(int iExp, bool bMonst = false)
{
	if(iExp == 0 || LevelNumber <= 0)
		return;
#ifdef NEW_SURVIVE
	return;
#endif
	//
	//if(bMonst && LevelNumber >= 1 && !TEST_FOR_EXPA)
	//	iExp = iExp + iExp * ExpAddCoef[LevelNumber-1] / 100;
	//
	int iPrevExpa = giExpa;
	giExpa += iExp;
	giExpToNextLevel -= iExp;
	//
	if(giExpToNextLevel <= 0)
	{
		giExpLevels += 1;
		GetExpToNextLevel();
		Log2("giExpLevels = " + itoa(giExpLevels));
		CreateExpEffect();
		//
		MessageText(GetString("items","LevelUp"),-1,-1);
	}
}


//------------------------------------------------------------------------------------------
RememberInitialVidValues()
{
	iff(1)
	{
		giPlayerMaxHp0    = GetVidData(9,VID_MAXHP0);
		giPlayerMaxSpeed0 = GetVidData(9,VID_SPEED);
		int i;
		for(i = 12; i < 20; i++) 
		{
			giAmmoCnt0[i] = GetVidData(i, VID_AMMO);
			//Log2("giAmmoCnt0[i] = " + itoa(giAmmoCnt0[i]));
			giWpnAim0[i] = GetVidData(i, VID_WEAPONAIM);
		}
		for(i = 0; i < 9; i++)
		{
			giBulletScale0[i] = GetVidData(ciVisualBulletVids[i],VID_SCALE_X);
			giWpnDmg0[i] = GetVidData(ciBulletVids[i],VID_DAMAGE);
			giDeathRange0[i] = GetVidData(ciBulletVids[i],VID_DEATHRANGE);
			//
			giInitGamma[i] = GetVidData(ciVisualBulletVids[i], VID_GAMMA);
			//Log2("giInitGamma = " + itoa(giInitGamma[i]));
			//
			giBulletsCnt0[i] = GetVidData(ciFlameVids[i],VID_NO_CHILD+ANI_FIGHT);
			giReload0[i] = GetVidData(ciTorseVids[i],VID_RELOAD_TIME);
		}
	}
}


//------------------------------------------------------------------------------------------
GetWpnUpgradeScale(int wpn, int upgr)
{
	if(wpn <= 0 || wpn > 9 || upgr <= 0 || upgr > 3)
		return 0;
	//
	upgr--;
	if(wpn == 1)
		return WPN1_UPGRADE_SCALE[upgr];
	if(wpn == 2)
		return WPN2_UPGRADE_SCALE[upgr];
	if(wpn == 3)
		return WPN3_UPGRADE_SCALE[upgr];
	if(wpn == 4)
		return WPN4_UPGRADE_SCALE[upgr];
	if(wpn == 5)
		return WPN5_UPGRADE_SCALE[upgr];
	if(wpn == 6)
		return WPN6_UPGRADE_SCALE[upgr];
	if(wpn == 7)
		return WPN7_UPGRADE_SCALE[upgr];
	if(wpn == 8)
		return WPN8_UPGRADE_SCALE[upgr];
	if(wpn == 9)
		return WPN9_UPGRADE_SCALE[upgr];
	//
	return 0;
}


//------------------------------------------------------------------------------------------
GetWpnUpgradeDamage(int wpn, int upgr)
{
	if(wpn <= 0 || wpn > 9 || upgr <= 0 || upgr > 3)
		return 0;
	//
	upgr--;
	if(wpn == 1)
		return WPN1_UPGRADE_DAMAGE[upgr];
	if(wpn == 2)
		return WPN2_UPGRADE_DAMAGE[upgr];
	if(wpn == 3)
		return WPN3_UPGRADE_DAMAGE[upgr];
	if(wpn == 4)
		return WPN4_UPGRADE_DAMAGE[upgr];
	if(wpn == 5)
		return WPN5_UPGRADE_DAMAGE[upgr];
	if(wpn == 6)
		return WPN6_UPGRADE_DAMAGE[upgr];
	if(wpn == 7)
		return WPN7_UPGRADE_DAMAGE[upgr];
	if(wpn == 8)
		return WPN8_UPGRADE_DAMAGE[upgr];
	if(wpn == 9)
		return WPN9_UPGRADE_DAMAGE[upgr];
	//
	return 0;
}


//------------------------------------------------------------------------------------------
GetWpnUpgradeRange(int wpn, int upgr)
{
	if(wpn <= 0 || wpn > 9 || upgr <= 0 || upgr > 3)
		return 0;
	//
	upgr--;
	if(wpn == 1)
		return WPN1_UPGRADE_RANGE[upgr];
	if(wpn == 2)
		return WPN2_UPGRADE_RANGE[upgr];
	if(wpn == 3)
		return WPN3_UPGRADE_RANGE[upgr];
	if(wpn == 4)
		return WPN4_UPGRADE_RANGE[upgr];
	if(wpn == 5)
		return WPN5_UPGRADE_RANGE[upgr];
	if(wpn == 6)
		return WPN6_UPGRADE_RANGE[upgr];
	if(wpn == 7)
		return WPN7_UPGRADE_RANGE[upgr];
	if(wpn == 8)
		return WPN8_UPGRADE_RANGE[upgr];
	if(wpn == 9)
		return WPN9_UPGRADE_RANGE[upgr];
	//
	return 0;
}


//------------------------------------------------------------------------------------------
GetWpnUpgradeGamma(int wpn, int upgr)
{
	if(wpn <= 0 || wpn > 9 || upgr <= 0 || upgr > 3)
		return 0;
	//
	upgr--;
	upgr *= 3;
	if(wpn == 1)
		return GammaEncodeToDword(WPN1_UPGRADE_GAMMA_[upgr], WPN1_UPGRADE_GAMMA_[upgr+1], WPN1_UPGRADE_GAMMA_[upgr+2]);
	if(wpn == 2)
		return GammaEncodeToDword(WPN2_UPGRADE_GAMMA_[upgr], WPN2_UPGRADE_GAMMA_[upgr+1], WPN2_UPGRADE_GAMMA_[upgr+2]);
	if(wpn == 3)
		return GammaEncodeToDword(WPN3_UPGRADE_GAMMA_[upgr], WPN3_UPGRADE_GAMMA_[upgr+1], WPN3_UPGRADE_GAMMA_[upgr+2]);
	if(wpn == 4)
		return GammaEncodeToDword(WPN4_UPGRADE_GAMMA_[upgr], WPN4_UPGRADE_GAMMA_[upgr+1], WPN4_UPGRADE_GAMMA_[upgr+2]);
	if(wpn == 5)
		return GammaEncodeToDword(WPN5_UPGRADE_GAMMA_[upgr], WPN5_UPGRADE_GAMMA_[upgr+1], WPN5_UPGRADE_GAMMA_[upgr+2]);
	if(wpn == 6)
		return GammaEncodeToDword(WPN6_UPGRADE_GAMMA_[upgr], WPN6_UPGRADE_GAMMA_[upgr+1], WPN6_UPGRADE_GAMMA_[upgr+2]);
	if(wpn == 7)
		return GammaEncodeToDword(WPN7_UPGRADE_GAMMA_[upgr], WPN7_UPGRADE_GAMMA_[upgr+1], WPN7_UPGRADE_GAMMA_[upgr+2]);
	if(wpn == 8)
		return GammaEncodeToDword(WPN8_UPGRADE_GAMMA_[upgr], WPN8_UPGRADE_GAMMA_[upgr+1], WPN8_UPGRADE_GAMMA_[upgr+2]);
	if(wpn == 9)
		return GammaEncodeToDword(WPN9_UPGRADE_GAMMA_[upgr], WPN9_UPGRADE_GAMMA_[upgr+1], WPN9_UPGRADE_GAMMA_[upgr+2]);
	//
	return 0;
}


//------------------------------------------------------------------------------------------
GetWpnUpgradeBulCnt(int wpn, int upgr)
{
	if(wpn <= 0 || wpn > 9 || upgr <= 0 || upgr > 3)
		return 0;
	//
	upgr--;
	if(wpn == 1)
		return WPN1_UPGRADE_BULCNT[upgr];
	if(wpn == 2)
		return WPN2_UPGRADE_BULCNT[upgr];
	if(wpn == 3)
		return WPN3_UPGRADE_BULCNT[upgr];
	if(wpn == 4)
		return WPN4_UPGRADE_BULCNT[upgr];
	if(wpn == 5)
		return WPN5_UPGRADE_BULCNT[upgr];
	if(wpn == 6)
		return WPN6_UPGRADE_BULCNT[upgr];
	if(wpn == 7)
		return WPN7_UPGRADE_BULCNT[upgr];
	if(wpn == 8)
		return WPN8_UPGRADE_BULCNT[upgr];
	if(wpn == 9)
		return WPN9_UPGRADE_BULCNT[upgr];
	//
	return 0;
}

//------------------------------------------------------------------------------------------
GetWpnUpgradeReload(int wpn, int upgr)
{
	if(wpn <= 0 || wpn > 9 || upgr <= 0 || upgr > 3)
		return 0;
	//
	upgr--;
	if(wpn == 1)
		return WPN1_UPGRADE_RELOAD[upgr];
	if(wpn == 2)
		return WPN2_UPGRADE_RELOAD[upgr];
	if(wpn == 3)
		return WPN3_UPGRADE_RELOAD[upgr];
	if(wpn == 4)
		return WPN4_UPGRADE_RELOAD[upgr];
	if(wpn == 5)
		return WPN5_UPGRADE_RELOAD[upgr];
	if(wpn == 6)
		return WPN6_UPGRADE_RELOAD[upgr];
	if(wpn == 7)
		return WPN7_UPGRADE_RELOAD[upgr];
	if(wpn == 8)
		return WPN8_UPGRADE_RELOAD[upgr];
	if(wpn == 9)
		return WPN9_UPGRADE_RELOAD[upgr];
	//
	return 0;
}


//------------------------------------------------------------------------------------------
ResetHeroSpeed()
{
	//увеличение скорости
	int iNewSpeed = giPlayerMaxSpeed0 + giPlayerMaxSpeed0 * giSkills[2] * MAXSPEED_INC_PERCENT / MAX_SKILL_VALUE / 100;
	//
	if(giHeroSpeedDecr1000 > 0)
	{
		iNewSpeed = iNewSpeed - giHeroSpeedDecr1000/1000;
		if(iNewSpeed < DS_MIN_SPEED)
			iNewSpeed = DS_MIN_SPEED;
	}
	//
	SetVidData(9,VID_SPEED,iNewSpeed);
	//if(Z_DEBUG)
	//	Log3("iNewSpeed="+itoa(iNewSpeed));
}


//------------------------------------------------------------------------------------------
ResetSkills()
{
#ifdef NEW_SURVIVE
	return;
#endif	
	//увеличение жизни
	int iNewMaxHp = giPlayerMaxHp0 + giPlayerMaxHp0 * giSkills[0] * MAXHP_INC_PERCENT / MAX_SKILL_VALUE / 100;
	SetVidData(9,VID_MAXHP0,iNewMaxHp);
	Log2("iNewMaxHp = " + itoa(iNewMaxHp));	
	//
	ResetHeroSpeed();
	//
	//увеличения силы (максимального количества патронов)
	int i;
	for(i = 12; i < 20; i++)
	{
		int iNewAmmo = giAmmoCnt0[i] + giAmmoCnt0[i] * giSkills[1] * MAXAMMO_INC_PERCENT / MAX_SKILL_VALUE / 100;
		Log2("iNewAmmo = " + itoa(iNewAmmo) + ", giSkills[1] = " + itoa(giSkills[1]));
		SetVidData(i,VID_AMMO,iNewAmmo);
		Log2("GetVidData("+itoa(i)+",VID_AMMO) = " + itoa(GetVidData(i,VID_AMMO)));
	}
	//
	//увеличение точности
	for(i = 12; i < 20; i++)
	{
		int skill = giSkills[3] * 2;
		if(skill > 10)	//при прокачке скилла на пять - максимальную точность делаем
			skill = 10;
		//
		int iMinAim = 3;
		int iMaxAim = giWpnAim0[i];
		if(iMaxAim < iMinAim)
			iMaxAim = iMinAim;
		//
		int iNewAim = iMaxAim - (iMaxAim-iMinAim) * skill / 10;
		//
		if(i == 12 && iNewAim < 20)
			iNewAim = 20;
		//
		Log2("iNewAim = " + itoa(iNewAim));
		SetVidData(i,VID_WEAPONAIM,iNewAim);
	}

	//увеличение повреждений при увеличенной точности
	int k1 = giSkills[3] * MAXDAMAGE_INC_PERCENT;
	int k2 = MAX_SKILL_VALUE * 100;
	//заморозка
	//ciFreezeBulletDamage = 30 + 30 * k1 / k2;
	//
	for(i = 0; i < 9; i++)
	{
		int iNewDmg = giWpnDmg0[i] + giWpnDmg0[i] * k1 / k2;
		SetVidData(ciBulletVids[i],VID_DAMAGE, iNewDmg);
		Log2("iNewDmg = " + itoa(iNewDmg));
	}
	//
	//применяем апгрейды оружия
	for(i = 0; i < 9; i++)
	{
		int iUpgrade = WpnUpgrade[i+1];
		if(gibCheatUpgrade[i+1] != -1)
			iUpgrade = gibCheatUpgrade[i+1];
	#ifdef SURVIVE_MAP
		iUpgrade = 2;
	#endif
		if(iUpgrade == 0 && gibCheatUpgrade[i+1] != -1)	//отладочный чит врублен был
		{
			Log2("iUpgrade == 0");
			//
			SetVidData(ciVisualBulletVids[i],VID_SCALE_X, giBulletScale0[i]);
			SetVidData(ciVisualBulletVids[i],VID_SCALE_Y, giBulletScale0[i]);
			SetVidData(ciVisualBulletVids[i],VID_SCALE_Z, giBulletScale0[i]);
			//
			//VID_DAMAGE итак сбрасывается из-за прокачки героя
			//SetVidData(ciBulletVids[i],VID_DAMAGE, giWpnDmg0[i]);
			//
			SetVidData(ciBulletVids[i],VID_DEATHRANGE, giDeathRange0[i]);
			//
			SetVidData(ciVisualBulletVids[i], VID_GAMMA, giInitGamma[i]);
			//
			//if(ciVisualBulletVids[i] == 134)
			//	Log2("ggg = " + itoa(giInitGamma[i]));
			//
			if(ciVisualBulletVids2[i])
				SetVidData(ciVisualBulletVids2[i], VID_GAMMA, giInitGamma[i]);
			//
			SetVidData(ciFlameVids[i],VID_NO_CHILD+ANI_FIGHT, giBulletsCnt0[i]);
			//
			SetVidData(ciTorseVids[i],VID_RELOAD_TIME, giReload0[i]);
		}
		if(iUpgrade > 0)
		{
			//scale
			int scale = giBulletScale0[i] * (1000 + GetWpnUpgradeScale(i+1, iUpgrade) * 10) / 1000;
			SetVidData(ciVisualBulletVids[i], VID_SCALE_X, scale);
			SetVidData(ciVisualBulletVids[i], VID_SCALE_Y, scale);
			SetVidData(ciVisualBulletVids[i], VID_SCALE_Z, scale);
			Log2("scale = " + itoa(scale) + ". giBulletScale0[i] = " + itoa(giBulletScale0[i]));

			//damage
			int iAddDamage = GetWpnUpgradeDamage(i+1, iUpgrade);
			int iNewDmg = GetVidData(ciBulletVids[i],VID_DAMAGE) * (100 + iAddDamage) / 100;
			//
			SetVidData(ciBulletVids[i],VID_DAMAGE, iNewDmg);
			Log2("iNewDmg2 = " + itoa(iNewDmg) + ". wpn = " + itoa(ciBulletVids[i]));

			//damage range
			int iAddRange = GetWpnUpgradeRange(i+1, iUpgrade);
			int iNewRange = giDeathRange0[i] * (100 + iAddRange) / 100;
			//
			SetVidData(ciBulletVids[i],VID_DEATHRANGE, iNewRange);
			Log2("iNewRange = " + itoa(iNewRange) + ". wpn = " + itoa(ciBulletVids[i]));

			//gamma
			int iGamma = GetWpnUpgradeGamma(i+1, iUpgrade);
			SetVidData(ciVisualBulletVids[i], VID_GAMMA, iGamma);
			if(ciVisualBulletVids2[i])
				SetVidData(ciVisualBulletVids2[i], VID_GAMMA, iGamma);

			//количество пуль
			int iBulCnt = GetWpnUpgradeBulCnt(i+1, iUpgrade);
			if(!iBulCnt)
				iBulCnt = giBulletsCnt0[i];
			SetVidData(ciFlameVids[i],VID_NO_CHILD+ANI_FIGHT, iBulCnt);
			
			//
			int iReload = GetWpnUpgradeReload(i+1, iUpgrade);
			if(!iReload)
				iReload = giReload0[i];
			else
				iReload = giReload0[i] * (100-iReload) / 100;
			SetVidData(ciTorseVids[i],VID_RELOAD_TIME, iReload);
        }
	}
}

