#define  UTIL_BOSS_H aaa
//----------------------------------------------------------------------------
//  @brief
//        боссы
//        

//  @ingroup
    
//  2006Oct16 created. Zmanovsky Peter.
//		код частично скопирован из Тезейчика (самую малость)
//  (C) 2006    Sigma-Team
//-----------------------------------------------------------------------------


#ifndef COMMON_VEHI_H
    #include "maps\common_vehi.lgc"
#endif

//------------------------------------------------------------------------------------------
static int giBossHp = 0;
static bool gbBossDeath = false;
//
static int BossHealthBar = 0;
static int StartGammaTime = 0;
//
//уже подлетели к боссу
static bool bBossOnScreen = false;


//------------------------------------------------------------------------------------------
//длительность заморозки после попадания росянкой
#define FREEZE_VEHII_TIME                2000


//------------------------------------------------------------------------------------------
GetBoss()
{
	int ret;
	ret = FindNearestSprite(GETSPRITE_VID+425, 0, 0, 1000000);
	if(!ret)
		ret = FindNearestSprite(GETSPRITE_VID+424, 0, 0, 1000000);
	if(!ret)
		ret = FindNearestSprite(GETSPRITE_VID+441, 0, 0, 1000000);
	return ret;
}


//------------------------------------------------------------------------------------------
SetBossVidGamma_( int iVid, int iPercent, int BegGamma, int EndGamma, int iArmy )
{
	SetVidData( iVid, VID_GAMMA+iArmy, CountGamma(BegGamma,EndGamma,iPercent*255/1000) );
}


//------------------------------------------------------------------------------------------
SetBossGamma_( int iBoss, int iPercent, int BegGamma, int EndGamma )
{
	if(iBoss)
		SetBossVidGamma_( GetUnitVid(iBoss), iPercent, BegGamma, EndGamma, Action(iBoss,ACT_GET_ARMY));
}


//------------------------------------------------------------------------------------------
//ищем дуру в начале уровня (хотя это уже не надо)
InitBoss()
{
	iff(1)
	{
		int boss;
		boss = GetBoss();
		if(boss)
		{
			Log("boss found. set unlim lifetime.");
			Action(boss, ACT_SET_DEATH_TIMER, 999999);
		}
		//
		SetBossVidGamma_( 424, 0, 0, 0, 1 );
		SetBossVidGamma_( 425, 0, 0, 0, 1 );
		SetBossVidGamma_( 441, 0, 0, 0, 1 );
	}
}


//------------------------------------------------------------------------------------------
//на рождение активной дуры
F425_14(int unit)
{
	//в первый раз запоминаем сколько у ней было hp
	iff(1)
	{
		giBossHp = Action(unit, ACT_GET_HP);
		Log("init. giBossHp = " +itoa(giBossHp));
	}
	//
	//устанавливаем ей дохрена hp, чтоб сама не сдохла
	Action(unit, ACT_SET_HP, 999999);
}
F441_14(int unit) { F425_14(unit); }

//------------------------------------------------------------------------------------------
//на рождение обычной дуры
F424_14(int unit)
{
	//нельзя сдыхать без моего ведома, дура!
	if(gbBossDeath)
		Action(unit, ACT_SET_DEATH_TIMER, 999999);
}


//------------------------------------------------------------------------------------------
//на смерть активной дуры (это она типо превращается обратно в просто дуру)
//F425_15(int unit)
//{
	//во все остальные разы наоборот устанавливаем ей hp
//	Log("cur giBossHp = " +itoa(giBossHp));
//}


//------------------------------------------------------------------------------------------
BossDeathTact()
{
	if(!gbBossDeath)
		return;
	int boss; boss = GetBoss();
	if(!boss)
		return;
	//
	static int siCurDeathState = 0;
	if(siCurDeathState == 0)	//для начала навсегда превратим росянку в vid 424
	{
		if(GetUnitVid(boss) == 425 && GetAnimation(boss) != ANI_DEATH)
			Action(boss, ANI_DEATH);
		siCurDeathState = 1;
		SetEnvironment(ENV_EARTHQUAKE);
	}
	//
	static int siBeginDeathTime = 0;
	if(siBeginDeathTime == 0)
		siBeginDeathTime = GetTime();
	//
	iff(GetTime()-siBeginDeathTime > ROSJANKA_DEATH_TIME)
	{
		Action(boss, ANI_DEATH2);
		giBossDeathTime = GetTime();
		SetEnvironment(ENV_STOP|ENV_EARTHQUAKE);
	}
	//
	static int PrevTime = 0;
	if(!PrevTime || GetTime() - PrevTime >= ROSJANKA_BLOW_PERIOD)
	{
		CreateSprite(ROSJANKA_DEATH_BLOW,
						GetX(boss) + Random(2*ROSJANKA_BLOW_RAZBROS_X)-ROSJANKA_BLOW_RAZBROS_X,
						GetY(boss) + Random(2*ROSJANKA_BLOW_RAZBROS_Y)-ROSJANKA_BLOW_RAZBROS_Y,
						GetZ(boss) );
		PlaySFX(21);
		PrevTime = GetTime();
	}
}


//------------------------------------------------------------------------------------------
//на damage активной дуры
F425_DAMAGE(int unit,int beating_unit,int damage)
{
	if(gbBossDeath)
		return 1;

	Log("damage = " + itoa(damage) + ". beating_unit = " + itoa(beating_unit));
	//
	if(damage > MAX_BOSS_DAMAGE)
		damage = MAX_BOSS_DAMAGE;
	//
	if(!beating_unit && damage < MIN_BOSS_DAMAGE)
		damage = MIN_BOSS_DAMAGE;
	if(GetUnitVid(beating_unit) == 35)		//пулемет
		damage = 2;
	//
	if(!beating_unit	//это значит, что от шарика damage пришел
		|| GetUnitVid(beating_unit) == 35		//пулемет
		|| GetUnitVid(beating_unit) == 34		//ракетница
		)
	{
		giBossHp = giBossHp - damage;
		Log("damage. giBossHp = " +itoa(giBossHp));
	}
	//
	//надо проверить, вдруг уже пора сдохнуть
	if(giBossHp <= 0 && !gbBossDeath)
	{
		gbBossDeath = true;
		BossDeathTact();
		iff(1)
			PlayMusicFile("music\\mus03.ogg", 0, 300);
	}

	if(gbBossDeath)
	{
		static int prevTime = 0;
		if(!prevTime || GetTime()-prevTime>=1000)
			DestoyObjectsOnScreen(true);
		prevTime = GetTime();
	}

	//
	return 0;
}
F441_DAMAGE(int unit,int beating_unit,int damage) { return F425_DAMAGE(unit,beating_unit, damage); }


//------------------------------------------------------------------------------------------
TryMakeDeathByBoss()
{
	static int siLastDamageTime = 0;
	if(giBornTime != 0 && GetTime() - giBornTime < 1000)
		return;
	siLastDamageTime = GetTime();
	//
	Action(PlayerVehi, ANI_DEATH);
	bDeathByBoss = true;
}


//------------------------------------------------------------------------------------------
int aUnitToDestr[20];
BossTact()
{
	int boss; boss = GetBoss();

	//проверяем, на экране ли босс
	if(!bBossOnScreen && boss)
	{
		iff( ToScreenY(GetY(boss), GetZ(boss)) >= 0)
		{
			bBossOnScreen = true;
			if(GetUnitVid(boss) == 424)
				Action(boss, ACT_SET_DEATH_TIMER, GetVidData(424, VID_LIFETIME));
			PlayMusicFile("music\\mus02.ogg", 1, 300);
		}
	}

    //BossHealthBar is released sometimes (after pressing tab)
    if( boss && !BossHealthBar && bBossOnScreen)
        BossHealthBar = CreateSprite(1250, ScreenX() / 2 - 128 , 50, 0, 0 );

    if( BossHealthBar )
    {
        if( boss )
        {
            int val, maxhp, hp;
            hp = giBossHp;
            //
			maxhp = GetVidData(GetUnitVid(boss), VID_MAXHP);
            if(GetUnitVid(boss) == 424)
            {
            	hp = giBossHp;
				if(hp==0 && !gbBossDeath)
					hp = GetVidData(425, VID_MAXHP);
				maxhp = GetVidData(425, VID_MAXHP);
			}
            if( hp < 0 )
                hp = 0;
			//
            val = 0;
            if( hp && maxhp )
                val = 255 - 255 * hp / maxhp;
            if( val > 250 )		//250 - standard HACK
                val = 250;
            Action( BossHealthBar, ACT_CHANGE_DIRECTION, val );
            if( !hp )
            {
                Destroy( BossHealthBar );
                BossHealthBar = 0;
            }
        }
        else
        {
            Destroy( BossHealthBar );
            BossHealthBar = 0;
        }
    }
    //
    if( StartGammaTime )
    {
    	int iDelta;
    	iDelta = GetTime() - StartGammaTime;
    	//
    	if( iDelta < BOSS_GAMMA_TIME1 && boss )
    		SetBossGamma_( boss, iDelta * 1000 / BOSS_GAMMA_TIME1, 0, BOSS_DAMAGE_GAMMA );
		else
    	if( iDelta < BOSS_GAMMA_TIME1 + BOSS_GAMMA_TIME2  && boss )
    		SetBossGamma_( boss, (iDelta-BOSS_GAMMA_TIME1) * 1000 / BOSS_GAMMA_TIME2, BOSS_DAMAGE_GAMMA, 0 );
		else
		{
			StartGammaTime = 0;
			SetBossVidGamma_( 424, 0, 0, 0, 1 );
			SetBossVidGamma_( 425, 0, 0, 0, 1 );
			SetBossVidGamma_( 441, 0, 0, 0, 1 );
		}
    }
    //
    //if( GetKey() == 'o' )
    //	StartGammaTime = GetTime();	
    if(boss && (GetUnitVid(boss) == 425 || GetUnitVid(boss) == 441) && PlayerVehi)
    {
    	int dirToPlayer;
    	dirToPlayer = DirectionTo(boss, GetX(PlayerVehi), GetY(PlayerVehi));
    	//Log(itoa(dirToPlayer));
    	Action(boss, ACT_CHANGE_DIRECTION, dirToPlayer);
    }

    //атака росянки. сделана, чтобы стрелять немного подальше игрока - чтобы пули за экран улетали
    if(boss && PlayerVehi && (GetUnitVid(boss) == 425 || GetUnitVid(boss) == 441)/*&& !Z_DEBUG*/)
    {
    	int dx, dy;
    	dx = GetX(boss)-GetX(PlayerVehi);
    	dy = GetY(boss)-GetY(PlayerVehi);
	    Action(boss, ACT_COOR_ATTACK, GetX(boss)-2*dx, GetY(boss)-2*dy);
    }

    //
	//пуля босса-статУи - damage бите
	if((/*DamageVehiByBullet(429) || */DamageVehiByBullet(439)) && PlayerVehi)
	{
		TryMakeDeathByBoss();
		CreateSprite(ROSJANKA_DEATH_BLOW, GetX(PlayerVehi), GetY(PlayerVehi), GetZ(PlayerVehi) );
	}
	//пуля росянки - заморозка биты
	if(DamageVehiByBullet(429) && PlayerVehi)
	{
		FreezeVehi(FREEZE_VEHII_TIME);
		//CreateSprite(ROSJANKA_DEATH_BLOW, GetX(PlayerVehi), GetY(PlayerVehi), GetZ(PlayerVehi) );
	}
	//
	if(DamageVehiByBullet(916) && PlayerVehi)
		TryMakeDeathByBoss();
	
	//сбивание пуль шариками
	int ball, unit;
	for(ball = FirstUnit(U_UNIT); ball; ball = NextUnit())
	{
		if( GetVidData(GetUnitVid(ball), VID_CLASS) == B_BALL)
		{
			unit = FindNearestSprite(GETSPRITE_VID+429, GetX(ball), GetY(ball)-GetZ(ball), 200);
			if(!unit)
				unit = FindNearestSprite(GETSPRITE_VID+439, GetX(ball), GetY(ball)-GetZ(ball), 200);
			if(unit && IntersectObjObj(ball, unit, true)
						&& GetAnimation(unit) != ANI_DEATH && GetAnimation(unit) != ANI_DEATH2)
			{
				Action(unit, ANI_DEATH);
			}
		}
	}

	//уничтожаем улетевшие с экрана пули
	int num; num = 0;
	int y; y = FromScreenY(ScreenY());
	for(unit=FirstInBox(-400,y+10,ScreenX()+400,y + 500); unit; unit=NextInBox())
	{
		if( (GetUnitVid(unit) == 429 || GetUnitVid(unit) == 439) && num < 20 && GetY(unit)-GetZ(unit) > y+10 )
		{
			aUnitToDestr[num] = unit;
			num++;
		}
	}
	int i;
	for(i = 0; i < num; i++)
       Action(aUnitToDestr[i], ANI_DEATH2);
	//
	BossDeathTact();
}


//------------------------------------------------------------------------------------------
F425_7(int unit)
{
	if( !StartGammaTime )
		StartGammaTime = GetTime();	
}
F441_7(int unit) { F425_7(unit); }


//------------------------------------------------------------------------------------------
//пуля росянки
F429_COLLISION(int unit,int crushed_unit)
{
	/*if(crushed_unit && GetUnitVid(crushed_unit) == )
	{
	    Action(crushed_unit, ACT_DAMAGE, 100);
		return 1;
	}*/
	//никогда не наносим damage, потому что зачем-то убивали объекты с vid->PropCrush()
	return 1;
}
F439_COLLISION(int unit,int crushed_unit) { return F429_COLLISION(unit, crushed_unit); }


//------------------------------------------------------------------------------------------
CheatBossDeath()
{
	int boss; boss = GetBoss();
	if(boss)
		F425_DAMAGE(boss,1,1000);
}

