#include < amxmodx >
#include < engine >
#include < fakemeta >
#include < cstrike >
#include < hamsandwich >
#include < xs >
#include < color >
#include < dhudmessage >

native zp_cs_get_user_money(id)
native zp_cs_set_user_money(id,value)

native zp_get_user_exp(id)
native zp_set_user_exp(id,value)

new g_MsgSync2

enum (+= 100)
{
	TASK_SHOWHUD
}

#define ID_SHOWHUD (taskid - TASK_SHOWHUD)

#define NAME		"[Boss] AlienBoss"
#define VERSION		"1.0"
#define AUTHOR		"heka"

#define PHOBOS_KILL_MONEY				30000
#define PHOBOS_KILL_EXP					50

#define PHOBOS_DMG_MONEY				500
#define PHOBOS_DAMAGE_REWARD			600

#define PHOBOS_HEALTH					400000.0
	
#define PHOSOS_DAMAGE_ATTACK			350.0
#define PHOBOS_DAMAGE_MAHADASH			1500.0
#define PHOBOS_DAMAGE_SHOCKWAVE_LOW		290.0
#define PHOBOS_DAMAGE_SHOCKWAVE_NORMAL	850.0
#define PHOBOS_DAMAGE_SHOCKWAVE_HIGH	1500.0

#define PHOBOS_ANIM_RUN					4
#define PHOBOS_ANIM_SWING				6
#define PHOBOS_ANIM_SHOCKWAVE			5
#define PHOBOS_ANIM_DUSH				7
#define PHOBOS_ANIN_DEATH				1

#define PHOBOS_SOUND_SWING				"npc/alienboss/swing.wav"
#define PHOBOS_SOUND_DUSH				"npc/alienboss/voice2.wav"
#define PHOBOS_SOUND_VOICE				"npc/alienboss/voice.wav"
#define PHOBOS_SOUND_DEATH				"npc/alienboss/death.wav"
#define PHOBOS_SOUND_SHOCKWAVE			"npc/alienboss/shokwave.wav"
#define PHOBOS_SOUND_FOOTSTEP1			"npc/alienboss/footstep_1.wav"
#define PHOBOS_SOUND_FOOTSTEP2			"npc/alienboss/footstep_2.wav"
#define PHOBOS_SOUND_FLUXING			"npc/alienboss/pull_cast.wav"

#define PHOBOS_HEALTH_SPRITE			"sprites/npc_hp_grade2.spr"

static Float:Origin[3]

static g_Alien
new HPspr
static VictimID
static Float:g_Health
static phase
static g_countdown
static Ability
new bool:GameStart
new bool:RoundEnd

new const Resource[][] = 
{
	"models/npc_hardcs/npc_alienboss.mdl",
	"sprites/blood.spr",
	"sprites/bloodspray.spr",
	"sprites/white.spr",
	"sprites/fluxing.spr"
}
static g_Resource[sizeof Resource]

new const SoundList[][] =
{
	"npc/alienboss/zombie_scenario_ready.mp3",
	"npc/alienboss/scenario_rush.mp3"
}

static bool:one, Float:g_step[512]
enum 
{
	WALK,
	MS,
	ATTACK,
	FLUXING,
	HOOK,
	SHOCKWAVE_LOW,
	SHOCKWAVE_NORMAL,
	SHOCKWAVE_HIGH
}

public plugin_init() {
	new szMapName[ 64 ];
	get_mapname( szMapName, 63 );

	if( contain( szMapName, "zp_boss_city" ) == -1 )
		return;

	register_plugin(NAME, VERSION, AUTHOR)
			
	register_think("AlienBoss", "Think_Boss")
	register_think("HP", "Think_HP")
	
	register_touch("AlienBoss", "player", "Touch_Boss") 

	register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
	register_logevent("logevent_round_end", 2, "1=Round_End")

	register_concmd("spawn_alien","spawn")

	register_event("HLTV", "Event_NewRound","a", "1=0", "2=0")

	RegisterHam(Ham_TakeDamage, "info_target", "TakeDamage")
	RegisterHam(Ham_TraceAttack, "info_target", "TraceAttack")

	set_task(1.0, "ShowHUD", TASK_SHOWHUD, _, _, "b")

	register_dictionary("zp_alienboss.txt")

	RoundEnd = false

	g_MsgSync2 = CreateHudSyncObj()
}

public logevent_round_end(ent) 
{	
	RoundEnd = true
}

public force_team(id)
{
	engclient_cmd(id, "jointeam", "2", "3")
}

public client_disconnect()
{
	remove_task(TASK_SHOWHUD)
}

public event_round_start()
{
	if(!RoundEnd) 
	{
		set_task(1.0, "countdown", 4441223, _, _, "b")
		g_countdown = 45
	}
	else
	{
		set_task(5.0, "change_map")
	}
}	

public countdown()
{
	if(!g_countdown)
	{
		remove_task(4441223)
		return
	}

	client_print(0, print_center, "%L", LANG_PLAYER, "PREPARE_BATTLE",g_countdown)
	
	if(g_countdown <= 5)
	{
		new sound[32]
		format(sound, 31, "city/other/%d.wav", g_countdown)
		
		client_cmd(0, "spk ^"%s^"", sound)
	}

	if(g_countdown == 20)
	{
		client_cmd(0, "mp3 play ^"sound/%s^"", SoundList[0])
	}

	if(g_countdown == 1)
	{
		client_print(0, print_center, "%L", LANG_PLAYER, "START_BATTLE")
		client_cmd(0, "mp3 play ^"sound/%s^"", SoundList[1])

		spawn()	
	}
	
	g_countdown--
}

public ShowHUD(taskid)
{
	set_dhudmessage(255, 255, 0, -1.0, 0.0, 0, 0.0, 1.1, 0.0, 0.0)
	show_dhudmessage(ID_SHOWHUD, "%L", LANG_PLAYER, "BONUS_HUD")
}

public RandomAbility(taskid) 
{
	if (Ability != WALK)
		return
	
	switch(phase)
	{
		case 1:
		{
			Ability = SHOCKWAVE_LOW
		}
		case 2:
		{
			switch(random_num(0, 1)) 
			{
				case 0: Ability = SHOCKWAVE_LOW
				case 1: Ability = SHOCKWAVE_NORMAL
			}							
		}
		case 3:
		{
			switch(random_num(0, 3)) 
			{
				case 0: Ability = SHOCKWAVE_LOW
				case 1: Ability = SHOCKWAVE_NORMAL
				case 2: Ability = SHOCKWAVE_HIGH
				case 3: Ability = MS
			}							
		}
	}
}

public spawn() {
	g_Alien = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
	HPspr = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))

	engfunc(EngFunc_SetModel, g_Alien, Resource[0])
	engfunc(EngFunc_SetSize, g_Alien, { -32.0, -32.0, -36.0 }, { 32.0, 32.0, 96.0 })
	Origin[0] = -317.0
	Origin[1] = 17.0
	Origin[2] = 424.0

	engfunc(EngFunc_SetOrigin, g_Alien, Origin)
	
	set_pev(g_Alien, pev_classname, "AlienBoss")
	set_pev(g_Alien, pev_solid, SOLID_BBOX)
	set_pev(g_Alien, pev_movetype, MOVETYPE_PUSHSTEP)
	set_pev(g_Alien, pev_takedamage, DAMAGE_YES)
	set_pev(g_Alien, pev_health, PHOBOS_HEALTH)
	set_pev(g_Alien, pev_deadflag, DEAD_NO)
	set_pev(g_Alien, pev_gravity, 10.0)
	set_pev(g_Alien, pev_nextthink, get_gametime())

	Origin[2] += 300.0
	pev(g_Alien, pev_origin, Origin)
	engfunc(EngFunc_SetOrigin, HPspr, Origin)
	engfunc(EngFunc_SetModel, HPspr, PHOBOS_HEALTH_SPRITE)
	entity_set_float(HPspr, EV_FL_scale, 0.6)
	set_pev(HPspr, pev_classname, "HP")
	set_pev(HPspr, pev_solid, SOLID_NOT)
	set_pev(HPspr, pev_movetype, MOVETYPE_NOCLIP)
	set_pev(HPspr, pev_frame, 100.0)
	set_pev(HPspr, pev_nextthink, get_gametime())

	g_step[g_Alien] = 0.0
	
	Anim(g_Alien, 2)
	Ability = FLUXING
	phase = 1
	PrintChatColor(0,print_chat,"!g[ZP] %L!", LANG_PLAYER, "ALIEN_PHASE", phase)

	one = true
	GameStart = true

	set_task(10.0, "RandomAbility", 1337, _, _, "b")
}

public client_putinserver(id)
{
	if(GameStart) set_pdata_int(id, 365, 1)
}

public Event_NewRound()
{
	remove_entity_name("AlienBoss")
	remove_entity_name("HP")
	remove_task(3007)
	remove_task(1337)
}

public Think_Boss(Ent) {
	if (pev(Ent, pev_deadflag) == DEAD_DYING)
		return

	if(pev(Ent, pev_health)  <= PHOBOS_HEALTH / 2.0 && phase == 1)
	{
		phase = 2
		PrintChatColor(0,print_chat,"!g[ZP] %L!", LANG_PLAYER, "ALIEN_PHASE", phase)
	}
	if(pev(Ent, pev_health)  <= PHOBOS_HEALTH / 4.0 && phase == 2)
	{
		phase = 3
		PrintChatColor(0,print_chat,"!g[ZP] %L!", LANG_PLAYER, "ALIEN_PHASE", phase)
	}

	switch ( Ability ) {
		case WALK: {
			new Float:Velocity[3], Float:Angle[3]
			static Target
			if (!is_user_alive(Target)) {
				Target = GetRandomAlive(random_num(1, GetAliveCount()))
				set_pev(Ent, pev_nextthink, get_gametime() + 0.1)
				return
			}
			if (one) {
				set_pev(Ent, pev_movetype, MOVETYPE_PUSHSTEP)
				Anim(Ent, PHOBOS_ANIM_RUN)
				one = false
			}
			new Len, LenBuff = 99999
			for(new i = 1; i <= get_maxplayers(); i++) {
				if (!is_user_alive(i) || is_user_bot(i))
					continue

				Len = Move(Ent, i, 500.0, Velocity, Angle)
				if (Len < LenBuff) {
					LenBuff = Len
					Target = i
				}
			}
			for(new i = 1; i < get_maxplayers(); i++)
			{
				if(is_user_alive(i) && entity_range(i, Ent) <= 500.0)
				{
					message_begin(MSG_ONE, get_user_msgid("ScreenShake"),{0,0,0}, i)
					write_short(1<<14)
					write_short(1<<13)
					write_short(1<<13)
					message_end()
				}
			}    
			set_rendering(Ent)
			Move(Ent, Target, 250.0, Velocity, Angle)
			Velocity[2] = 0.0
			set_pev(Ent, pev_velocity, Velocity)
			set_pev(Ent, pev_angles, Angle)
			set_pev(Ent, pev_nextthink, get_gametime() + 0.1)
		}
		case ATTACK: {
			static num	
			switch (num) {
				case 0: {
					set_pev(Ent, pev_velocity, Float:{0.0, 0.0, -0.1})
					Anim(Ent, PHOBOS_ANIM_SWING)
					num++
					set_pev(Ent, pev_nextthink, get_gametime() + 0.2)
					PlaySound(0, PHOBOS_SOUND_SWING)
					return
				}
				case 1: {
					static Float:OriginA[3], Float:OriginA2[3], Float:LenA, Float:Vector[3], Float:Velocity[3]
					
					pev(g_Alien, pev_origin, OriginA)
					pev(VictimID, pev_origin, OriginA2)
					
					xs_vec_sub(OriginA2, OriginA, Velocity)
					xs_vec_sub(OriginA, OriginA2, Vector)
						
					LenA = xs_vec_len(Vector)
					
					if (LenA <= 400) 
					{
						//ExecuteHamB(Ham_TakeDamage, VictimID, 0, VictimID, PHOSOS_DAMAGE_ATTACK, DMG_BLAST)
						boss_damage(VictimID, PHOSOS_DAMAGE_ATTACK)
						ScreenShake(VictimID)
						ScreenFade(VictimID, 3, {255, 0, 0}, 120)
					}
				}
			}
			num = 0
			one = true
			Ability = WALK
			set_pev(Ent, pev_nextthink, get_gametime() + 1.2)
		}
		case MS: {
			static num, Float:Origin[3], Float:Origin2[3], Float:Vector[3], Float:Angle[3]
			switch ( num ) {
				case 0: {
					new MS_Attack = GetRandomAlive(random_num(1, GetAliveCount()))
					
					pev(MS_Attack, pev_origin, Origin)
					pev(Ent, pev_origin, Origin2)

					set_pev(g_Alien, pev_gravity, 1.0)
					
					xs_vec_sub(Origin, Origin2, Vector)
					vector_to_angle(Vector, Angle)
					xs_vec_normalize(Vector, Vector)
					xs_vec_mul_scalar(Vector, 1200.0, Vector)
					Angle[0] = 0.0
					Angle[2] = 0.0
					Vector[2] = 0.0
					set_pev(Ent, pev_angles, Angle)
					set_pev(Ent, pev_movetype, MOVETYPE_NONE)
					Anim(Ent, PHOBOS_ANIM_DUSH)
					set_pev(Ent, pev_nextthink, get_gametime() + 1.0)
					PlaySound(0, PHOBOS_SOUND_DUSH)
					num++
					return
				}
				case 1: {
					set_pev(Ent, pev_movetype, MOVETYPE_FLY)
					set_pev(Ent, pev_velocity, Vector)
					set_pev(Ent, pev_nextthink, get_gametime() + 0.7)

					num++
					return
				}
			}
			set_pev(Ent, pev_nextthink, get_gametime() + 0.1)
			num = 0
			Ability = WALK
			one = true
			return
		}
		case FLUXING:
		{
			static num, FluxSpr, Float:Origin[3]
			switch ( num ) {
				case 0: {
					Anim(Ent, 2)
					FluxSpr = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_sprite"))
					pev(Ent, pev_origin, Origin)
					Origin[2] += 70
					engfunc(EngFunc_SetOrigin, FluxSpr, Origin)
					engfunc(EngFunc_SetModel, FluxSpr, Resource[4])
					set_pev(FluxSpr, pev_solid, SOLID_NOT)
					set_pev(FluxSpr, pev_movetype, MOVETYPE_NOCLIP)
					set_rendering(FluxSpr, kRenderFxFadeSlow, 255, 255, 255, kRenderTransAdd, 255)
					set_rendering(Ent, kRenderFxGlowShell, 255, 255, 255, kRenderNormal, 30)
					set_pev(FluxSpr, pev_framerate, 5.0)
					dllfunc(DLLFunc_Spawn, FluxSpr)
					PlaySound(0, PHOBOS_SOUND_FLUXING)
					set_pev(Ent, pev_nextthink, get_gametime() + 0.2)
					num++
					return 
				}
				case 1..9: {
					static Float:originF[3],  victim = -1;
					pev(Ent, pev_origin, originF);
					
					while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, 1000.0)) != 0)
					{
						if (!is_user_alive(victim))
							continue;
				
						new Float:fl_Velocity[3];
						new vicOrigin[3], originN[3];
				
						get_user_origin(victim, vicOrigin);
						originN[0] = floatround(originF[0]);
						originN[1] = floatround(originF[1]);
						originN[2] = floatround(originF[2]);
						
						new distance = get_distance(originN, vicOrigin);
				
						if (distance > 1)
						{
							new Float:fl_Time = distance / 900.0;
				
							fl_Velocity[0] = (originN[0] - vicOrigin[0]) / fl_Time;
							fl_Velocity[1] = (originN[1] - vicOrigin[1]) / fl_Time;
							fl_Velocity[2] = (originN[2] - vicOrigin[2]) / fl_Time;
						} 
						else
						{
							fl_Velocity[0] = 0.0
							fl_Velocity[1] = 0.0
							fl_Velocity[2] = 0.0
						}
				
						entity_set_vector(victim, EV_VEC_velocity, fl_Velocity);
					}

					set_pev(Ent, pev_nextthink, get_gametime() + 0.2)
					num++
					return
				}
				case 10: {
					engfunc(EngFunc_RemoveEntity, FluxSpr)
					set_rendering(Ent)
					switch(phase)
					{
						case 1:
						{
							switch(random_num(0, 1)) 
							{
								case 0: Ability = ATTACK
								case 1: Ability = SHOCKWAVE_LOW
							}
						}
						case 2:
						{
							switch(random_num(0, 2)) 
							{
								case 0: Ability = ATTACK
								case 1: Ability = SHOCKWAVE_LOW
								case 2: Ability = SHOCKWAVE_NORMAL
							}							
						}
						case 3:
						{
							switch(random_num(0, 4)) 
							{
								case 0: Ability = ATTACK
								case 1: Ability = SHOCKWAVE_LOW
								case 2: Ability = SHOCKWAVE_NORMAL
								case 3: Ability = SHOCKWAVE_HIGH
								case 4: Ability = MS
							}							
						}
					}
					one = true
					num = 0
					set_pev(Ent, pev_nextthink, get_gametime() + 0.1)
					return
				}
			}
		}
		case HOOK:
		{
			static num
			switch ( num ) {
				case 0: {
					Anim(Ent, 2)
					set_rendering(Ent, kRenderFxGlowShell, 255, 255, 255, kRenderNormal, 30)
					PlaySound(0, PHOBOS_SOUND_FLUXING)
					set_pev(Ent, pev_nextthink, get_gametime() + 0.2)
					num++
					return 
				}
				case 1..9: {
					static Float:originF[3],  victim = -1;
					pev(Ent, pev_origin, originF);
					
					while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, 1000.0)) != 0)
					{
						if (!is_user_alive(victim))
							continue;
				
						new Float:fl_Velocity[3];
						new vicOrigin[3], originN[3];
				
						get_user_origin(victim, vicOrigin);
						originN[0] = floatround(originF[0]);
						originN[1] = floatround(originF[1]);
						originN[2] = floatround(originF[2]);
						
						new distance = get_distance(originN, vicOrigin);
				
						if (distance > 1)
						{
							new Float:fl_Time = distance / 900.0;
				
							fl_Velocity[0] = (originN[0] - vicOrigin[0]) / fl_Time;
							fl_Velocity[1] = (originN[1] - vicOrigin[1]) / fl_Time;
							fl_Velocity[2] = (originN[2] - vicOrigin[2]) / fl_Time;
						} 
						else
						{
							fl_Velocity[0] = 0.0
							fl_Velocity[1] = 0.0
							fl_Velocity[2] = 0.0
						}
				
						entity_set_vector(victim, EV_VEC_velocity, fl_Velocity);
					}

					set_pev(Ent, pev_nextthink, get_gametime() + 0.2)
					num++
					return
				}
				case 10: {
					set_rendering(Ent)
					switch(phase)
					{
						case 1:
						{
							switch(random_num(0, 1)) 
							{
								case 0: Ability = ATTACK
								case 1: Ability = SHOCKWAVE_LOW
							}
						}
						case 2:
						{
							switch(random_num(0, 2)) 
							{
								case 0: Ability = ATTACK
								case 1: Ability = SHOCKWAVE_LOW
								case 2: Ability = SHOCKWAVE_NORMAL
							}							
						}
						case 3:
						{
							switch(random_num(0, 4)) 
							{
								case 0: Ability = ATTACK
								case 1: Ability = SHOCKWAVE_LOW
								case 2: Ability = SHOCKWAVE_NORMAL
								case 3: Ability = SHOCKWAVE_HIGH
								case 4: Ability = MS
							}							
						}
					}
					one = true
					num = 0
					set_pev(Ent, pev_nextthink, get_gametime() + 0.1)
					return
				}
			}
		}
		case SHOCKWAVE_LOW: {
			static num
			switch ( num ) {
				case 0: {
					set_pev(Ent, pev_velocity, Float:{0.0, 0.0, -0.1})
					Anim(Ent, PHOBOS_ANIM_SHOCKWAVE)
					PlaySound(0, PHOBOS_SOUND_VOICE)
					set_pev(Ent, pev_nextthink, get_gametime() + 2.2)
					num++
					return
				}
				case 1: {
					static Float:Orig[3]
					pev(Ent, pev_origin, Orig)
					
					ShockWave(Orig, 750.0, {174, 87, 0}) // 450
					PlaySound(0, PHOBOS_SOUND_SHOCKWAVE)
					
					for(new id = 1; id <= get_maxplayers(); id++) 
					{
						if (!is_user_alive(id))
							continue

						if (~pev(id, pev_flags) & FL_ONGROUND)
         						continue		

						static Float:gOrigin[3], Float:Vec[3], Float:Len
						pev(id, pev_origin, gOrigin)
						xs_vec_sub(Orig, gOrigin, Vec)
						Len = xs_vec_len(Vec)
						if (Len <= 550.0) 
						{
							//ExecuteHamB(Ham_TakeDamage, id, 0, id, PHOBOS_DAMAGE_SHOCKWAVE_LOW, DMG_BLAST)
							boss_damage(id, PHOBOS_DAMAGE_SHOCKWAVE_LOW)
							ScreenFade(id, 3, {174, 87, 0}, 120)
							client_cmd(id, "drop")
							ScreenShake(id)
						}
					}
					Ability = WALK
					one = true
					num = 0
					set_pev(Ent, pev_nextthink, get_gametime() + 0.6)
					return
				}
			}
		}
		case SHOCKWAVE_NORMAL: {
			static num
			switch ( num ) {
				case 0: {
					set_pev(Ent, pev_velocity, Float:{0.0, 0.0, -0.1})
					Anim(Ent, PHOBOS_ANIM_SHOCKWAVE)
					PlaySound(0, PHOBOS_SOUND_VOICE)
					set_rendering(Ent, kRenderFxGlowShell, 27, 141, 35, kRenderNormal, 30)
					set_pev(Ent, pev_nextthink, get_gametime() + 2.2)
					num++
					return
				}
				case 1: {
					static Float:Orig[3]
					pev(Ent, pev_origin, Orig)
					
					ShockWave(Orig, 950.0, {27, 141, 35}) // 450
					PlaySound(0, PHOBOS_SOUND_SHOCKWAVE)
					
					for(new id = 1; id <= get_maxplayers(); id++) {
						if (!is_user_alive(id))
							continue

						if (~pev(id, pev_flags) & FL_ONGROUND)
         						continue	
	
						static Float:gOrigin[3], Float:Vec[3], Float:Len
						pev(id, pev_origin, gOrigin)
						xs_vec_sub(Orig, gOrigin, Vec)
						Len = xs_vec_len(Vec)
						if (Len <= 800.0) 
						{
							//ExecuteHamB(Ham_TakeDamage, id, 0, id, PHOBOS_DAMAGE_SHOCKWAVE_NORMAL, DMG_BLAST)
							boss_damage(id, PHOBOS_DAMAGE_SHOCKWAVE_NORMAL)
							client_cmd(id, "drop")
							ScreenShake(id)
							ScreenFade(id, 3, {27, 141, 35}, 120)
						}
					}
					Ability = WALK
					one = true
					num = 0
					set_pev(Ent, pev_nextthink, get_gametime() + 0.6)
					return
				}
			}
		}
		case SHOCKWAVE_HIGH: {
			static num
			switch ( num ) {
				case 0: {
					set_pev(Ent, pev_velocity, Float:{0.0, 0.0, -0.1})
					Anim(Ent, PHOBOS_ANIM_SHOCKWAVE)
					PlaySound(0, PHOBOS_SOUND_VOICE)
					set_rendering(Ent, kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 30)
					set_pev(Ent, pev_nextthink, get_gametime() + 2.2)
					num++
					return
				}
				case 1: {
					static Float:Orig[3]
					pev(Ent, pev_origin, Orig)
					
					ShockWave(Orig, 1650.0, {255, 0, 0}) // 450
					PlaySound(0, PHOBOS_SOUND_SHOCKWAVE)
					
					for(new id = 1; id <= get_maxplayers(); id++) 
					{
						if (!is_user_alive(id))
							continue

						if (~pev(id, pev_flags) & FL_ONGROUND)
         						continue
		
						static Float:gOrigin[3], Float:Vec[3], Float:Len
						pev(id, pev_origin, gOrigin)
						xs_vec_sub(Orig, gOrigin, Vec)
						Len = xs_vec_len(Vec)
						if (Len <= 1400.0) 
						{
							//ExecuteHamB(Ham_TakeDamage, id, 0, id, PHOBOS_DAMAGE_SHOCKWAVE_HIGH, DMG_BLAST)
							boss_damage(id, PHOBOS_DAMAGE_MAHADASH)
							client_cmd(id, "drop")
							ScreenShake(id)
							ScreenFade(id, 3, {255, 0, 0}, 120)
						}	
					}
					Ability = WALK
					one = true
					num = 0
					set_pev(Ent, pev_nextthink, get_gametime() + 0.6)
					return
				}
			}
		}
	}
}

public Think_HP(Ent)
 {
	static Float:Origin[3], num
	pev(g_Alien, pev_origin, Origin)
	Origin[2] += 300.0
	set_pev(Ent, pev_origin, Origin)
	switch ( num ) {
		case 0: {
			num++
		}
		case 1: {
			static Float:frame
			frame = g_Health * 100.0 / PHOBOS_HEALTH
			
			if (frame)
				set_pev(Ent, pev_frame, frame)

			if (pev(g_Alien, pev_deadflag) == DEAD_DYING) 
			{
				engfunc(EngFunc_RemoveEntity, Ent)
				return
			}
		}
	}
	set_pev(Ent, pev_nextthink, get_gametime() + 0.1)
}

public TraceAttack(victim, attacker, Float:damage, Float:direction[3], th, dt) {
	static Float:End[3], ClassName[32]
	pev(victim, pev_classname, ClassName, charsmax(ClassName))
	if (equal(ClassName, "AlienBoss")) {
		get_tr2(th, TR_vecEndPos, End)
		Blood(End)
	}
}

public TakeDamage(victim, weapon, attacker, Float:damage, damagetype) {
	static ClassName[32], Float:dmg_buffer[33]
	pev(victim, pev_classname, ClassName, charsmax(ClassName))
	if (equal(ClassName, "AlienBoss")) 
	{
		pev(victim, pev_health, g_Health)
		if (g_Health <= damage) 
		{
			set_pev(victim, pev_velocity, Float:{0.0, 0.0, -0.1})
			Anim(victim, PHOBOS_ANIN_DEATH)	
			PlaySound(0, PHOBOS_SOUND_DEATH)
			set_pev(victim, pev_movetype, MOVETYPE_FLY)
			set_pev(victim, pev_solid, SOLID_NOT)
			set_pev(victim, pev_velocity, {0.0, 0.0, 0.0})
			set_pev(victim, pev_deadflag, DEAD_DYING)

			zp_cs_set_user_money(attacker, zp_cs_get_user_money(attacker) + PHOBOS_KILL_MONEY)	
			zp_set_user_exp(attacker, zp_get_user_exp(attacker) + PHOBOS_KILL_EXP)

			new szKillerName[32]
			get_user_name(attacker, szKillerName, 31)
	
			set_hudmessage(255, 255, 0, 0.12, 0.5, 0, 5.0, 5.0)
			ShowSyncHudMsg(0, g_MsgSync2, "%L", LANG_PLAYER, "ALIEN_DEATH_KILLER", szKillerName, PHOBOS_KILL_EXP,PHOBOS_KILL_MONEY)

			PrintChatColor(0,print_chat,"!g[ZP] %L", LANG_PLAYER, "ALIEN_DEATH")

			remove_task(1337)
			remove_task(3007)

			set_task(5.0, "change_map")
			return HAM_SUPERCEDE
		}
		if(g_Health >= damage)
		{
			dmg_buffer[attacker] += damage
			if(dmg_buffer[attacker] >= PHOBOS_DAMAGE_REWARD)
			{
				dmg_buffer[attacker] = 0.0
				zp_cs_set_user_money(attacker, zp_cs_get_user_money(attacker) + PHOBOS_DMG_MONEY)
			}

		}
	}
	return HAM_HANDLED
}

public change_map()
{
	server_cmd("changelevel zp_outskirts")
}

public Touch_Boss(Ent, WorldEnt) {
	if (Ability == MS) {
		static victim = -1, Float:Origin[3]
		pev(Ent, pev_origin, Origin)
		while((victim = engfunc(EngFunc_FindEntityInSphere, victim, Origin, 500.0)) != 0) {
			if (!is_user_alive(victim))
				continue
			
			//ExecuteHamB(Ham_TakeDamage, victim, 0, victim, PHOBOS_DAMAGE_MAHADASH, DMG_BLAST)
			boss_damage(victim, PHOBOS_DAMAGE_MAHADASH)
			ScreenFade(victim, 3, {255, 0, 0} ,120)
		}
	}
	
	if (Ability == WALK) {
		Ability = ATTACK
		VictimID = WorldEnt
	}
}

boss_damage(victim, Float:damage) 
{
	if (pev(victim, pev_health) - damage <= 0) ExecuteHamB(Ham_Killed, victim, victim, 1)
	else ExecuteHamB(Ham_TakeDamage, victim, 0, victim, damage, DMG_BLAST)
}

public plugin_precache() {
	new szMapName[ 64 ];
	get_mapname( szMapName, 63 );

	if( contain( szMapName, "zp_boss_city" ) == -1 )
		return;

	for(new i; i <= charsmax(Resource); i++)
		g_Resource[i] = precache_model(Resource[i])

	for(new e; e <= charsmax(SoundList); e++)
		precache_sound(SoundList[e])

	precache_sound(PHOBOS_SOUND_SWING)
	precache_sound(PHOBOS_SOUND_DUSH)
	precache_sound(PHOBOS_SOUND_VOICE)
	precache_sound(PHOBOS_SOUND_DEATH)
	precache_sound(PHOBOS_SOUND_SHOCKWAVE)
	precache_sound(PHOBOS_SOUND_FOOTSTEP1)
	precache_sound(PHOBOS_SOUND_FOOTSTEP2)
	precache_model(PHOBOS_HEALTH_SPRITE)
}

stock Blood(Float:Orig[3]) {	
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
	write_byte(TE_BLOODSPRITE);
	engfunc(EngFunc_WriteCoord, Orig[0])
	engfunc(EngFunc_WriteCoord, Orig[1])
	engfunc(EngFunc_WriteCoord, Orig[2])
	write_short(g_Resource[1])
	write_short(g_Resource[2])
	write_byte(218)
	write_byte(random_num(1, 2))
	message_end();
}

stock Anim(ent, sequence) 
{
	set_pev(ent, pev_sequence, sequence)
	set_pev(ent, pev_animtime, halflife_time())
	set_pev(ent, pev_framerate, 1.0)	
}

stock ShockWave(Float:Orig[3], Float:Radius, Color[3]) {
	engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, Orig, 0)
	write_byte(TE_BEAMCYLINDER) // TE id
	engfunc(EngFunc_WriteCoord, Orig[0]) // x
	engfunc(EngFunc_WriteCoord, Orig[1]) // y
	engfunc(EngFunc_WriteCoord, Orig[2]-24.0) // z
	engfunc(EngFunc_WriteCoord, Orig[0]) // x axis
	engfunc(EngFunc_WriteCoord, Orig[1]) // y axis
	engfunc(EngFunc_WriteCoord, Orig[2]+Radius) // z axis
	write_short(g_Resource[3]) // sprite
	write_byte(0) // startframe
	write_byte(0) // framerate
	write_byte(5) // life (4)
	write_byte(30) // width (20)
	write_byte(0) // noise
	write_byte(Color[0]) // red
	write_byte(Color[1]) // green
	write_byte(Color[2]) // blue
	write_byte(255) // brightness
	write_byte(0) // speed
	message_end()
}

stock ScreenShake(id) {
	message_begin(MSG_ONE, get_user_msgid("ScreenShake"),{0,0,0}, id)
	write_short(1<<14)
	write_short(1<<13)
	write_short(1<<13)
	message_end()
}

stock ScreenFade(id, Timer, Colors[3], Alpha) {	
	message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("ScreenFade"), _, id);
	write_short((1<<12) * Timer)
	write_short(1<<12)
	write_short(0)
	write_byte(Colors[0])
	write_byte(Colors[1])
	write_byte(Colors[2])
	write_byte(Alpha)
	message_end()
}

GetRandomAlive(target_index) {			// :3
	new iAlive
	for (new id = 1; id <= get_maxplayers(); id++) {
		if (is_user_alive(id)) iAlive++
		if (iAlive == target_index) return id
	}
	return -1
}

stock Move(Start, End, Float:speed, Float:Velocity[], Float:Angles[]) {
	new Float:Origin[3], Float:Origin2[3], Float:Angle[3], Float:Vector[3], Float:Len
	pev(Start, pev_origin, Origin2)
	pev(End, pev_origin, Origin)
	xs_vec_sub(Origin, Origin2, Vector)
	Len = xs_vec_len(Vector)
	vector_to_angle(Vector, Angle)
	Angles[0] = 0.0
	Angles[1] = Angle[1]
	Angles[2] = 0.0
	xs_vec_normalize(Vector, Vector)
	xs_vec_mul_scalar(Vector, speed, Velocity)
	return floatround(Len, floatround_round)
}

GetAliveCount() {				// ^^
	new iAlive
	for (new id = 1; id <= get_maxplayers(); id++) if (is_user_alive(id)) iAlive++
	return iAlive
}

PlaySound(id, const sound[])
{
	client_cmd(id, "spk ^"%s^"", sound)
}
/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1049\\ f0\\ fs16 \n\\ par }
*/
