new const npc_mdl[] = "models/fallen_titan/fallen_titan.mdl"
new const hp_spr[] = "sprites/fallen_titan/fallen_titanhp.spr"
new const npc_sound[12][] = 
{		
	"fallen_titan/death.wav",
	"fallen_titan/footstep1.wav",
	"fallen_titan/footstep2.wav",
	"fallen_titan/zbs_fail.wav",
	"fallen_titan/zbs_clear.wav",
	"fallen_titan/zbs_attack1.wav",
	"fallen_titan/zbs_attack2.wav",
	"fallen_titan/hurt2.wav",
	"fallen_titan/zbs_idle1.wav",
	"fallen_titan/scene_appear3.wav",
	"fallen_titan/scene_howling.wav",
	"fallen_titan/zbs_cannon1.wav"
}
#define npc_healthpoints 50000.0	// Fallen Titan health
#define npc_mh_damage 1000.0		// Fallen Titan dash damage in percentage (1000.0 instant kill)
#define npc_simple_attack_damage 50.0	// Fallen Titan simple attack damage in percentage
#define npc_hollow_damage 10.0		// Fallen Titan hollow damage
#define npc_rocket_damage 10.0		// Fallen Titan rocket damage
#define npc_appear_damage 10.0		// Fallen Titan appear damage
#define npc_start_think 1
#define npc_clear 2
#define npc_restart 3
#define npc_create 4
#define npc_ability 5
#define npc_think_player 6
#define npc_set_attack3 7
#define npc_idle 8
#define npc_reload_skill 9
#define npc_skill3 10
#define npc_run 11
#define npc_stop 12
#define npc_simple_attack 13
#define npc_simple_attack2 14
#define map_music 15
#define FALL_VELOCITY 350.0
#define RefreshPlayersList()    get_players(g_iPlayers, g_iNum, g_szAliveFlags)
static y_ids
new bool:g_bRestoreVel
new Float:g_vecVel[3]
new g_cvarPainShockFree
new g_fmPlayerPreThink
new g_fmPlayerPreThink_Post
new hologramas
new semiclip, cache_explo
const MAX_PLAYERS = 32
new g_iPlayers[MAX_PLAYERS], g_iNum, g_iPlayer, i
new const g_szAliveFlags[] = "a"
new y_think, y_bleeding[2], y_run, y_hpbar
new y_npc_mdl, y_start_npc, y_start_thinking
new Float:HAngles[3], Float:VAngles[3], Float:y_spawn_points[3]
new const map_sound[2][] = {
	"sound/fallen_titan/scenario_ready.mp3",
	"sound/fallen_titan/scenario_start.mp3"
}
#define PLUGIN "NPC Fallen Titan"		// Fallen Titan
#define VERSION "Public"
#define AUTHOR "Glamurnaya Kisa"
#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <fakemeta_+>			// Fakemeta_Util + Sql
#include <hamsandwich>
#include <xs>
#include <cstrike>
#include <fun>
public plugin_init()
{
	register_clcmd("get_position", "npc_position")
	register_clcmd("make_fallentitan", "create_fallentitan")
	register_clcmd("npc_attack_mh", "npc_attack_mh_ent")
	register_think("npc_fallentitan", "npc_fallentitan_think")
	register_touch("npc_fallentitan", "*", "npc_fallentitan_touch")
	register_event("HLTV", "event_newround", "a", "1=0", "2=0")
	register_logevent("event_roundstart", 2, "1=Round_Start")
	register_logevent("event_roundend", 2, "1=Round_End")
	RegisterHam(Ham_Spawn, "player", "player_spawn", 1)
	g_cvarPainShockFree = register_cvar("amx_painshockfree", "1", FCVAR_SERVER)
	g_fmPlayerPreThink = register_forward(FM_PlayerPreThink, "onPlayerPreThink")
	g_fmPlayerPreThink_Post = register_forward(FM_PlayerPreThink, "onPlayerPreThink_Post", 1)
    	register_forward(FM_AddToFullPack, "FM_client_AddToFullPack_Post", 1)
    	RegisterHam(Ham_Player_PreThink, "player", "Ham_CBasePlayer_PreThink_Post", 1)
	hologramas = register_cvar("hologram","0")
    	semiclip = register_cvar("semiclip","1") 
	register_plugin(PLUGIN, VERSION, AUTHOR)
	if(!cvar_exists("mp_falldamage")) 
	{
    	register_cvar("mp_falldamage", "0")
	set_lights("h")
  	}
}
public FM_client_AddToFullPack_Post(es, e, iEnt, id, hostflags, player, pSet)
{
    if( player && id != iEnt && get_orig_retval() && is_user_alive(id) )
    {
        if( get_pcvar_num(semiclip) == 1)
        {
            set_es(es, ES_Solid, SOLID_NOT)
	}
	if( get_pcvar_num(hologramas) == 1 )
        {
            set_es(es, ES_RenderMode, kRenderTransAdd)
            set_es(es, ES_RenderAmt, 80)
            set_es(es, ES_RenderColor, 0, 0, 0)
            set_es(es, ES_RenderFx, kRenderFxDistort)
        } 
        if(is_user_alive(id) && get_pcvar_num(semiclip) == 0 )
        {
            set_pev(id, pev_solid, SOLID_SLIDEBOX)
        }     
    }   
}
public Ham_CBasePlayer_PreThink_Post(id)
{
    if( !is_user_alive(id)  )
    {
        return
    }
    if(get_pcvar_num(semiclip) == 1)
    {    
    RefreshPlayersList()

    for(i = 0; i<g_iNum; i++)
    {
        g_iPlayer = g_iPlayers[i]
        if( id != g_iPlayer )
        {
            set_pev(g_iPlayer, pev_solid, SOLID_NOT)
        }
    }
    }
}
public plugin_end()
{
	if(g_fmPlayerPreThink)
		unregister_forward(FM_PlayerPreThink, g_fmPlayerPreThink)
	if(g_fmPlayerPreThink_Post)
		unregister_forward(FM_PlayerPreThink, g_fmPlayerPreThink_Post, 1)
}
public onPlayerPreThink(id)
{
	if(get_pcvar_num(g_cvarPainShockFree))
	{
		if(pev_valid(id) && is_user_alive(id) 
		&& (FL_ONGROUND & pev(id, pev_flags)))
		{
			pev(id, pev_velocity, g_vecVel)
			g_bRestoreVel = true
		}
		return FMRES_HANDLED
	}
	return FMRES_IGNORED
}
public onPlayerPreThink_Post(id)
{
	if(g_bRestoreVel)
	{
		g_bRestoreVel = false
		if(!(FL_ONTRAIN & pev(id, pev_flags)))
		{
			static iGEnt
			iGEnt = pev(id, pev_groundentity)
			if(pev_valid(iGEnt) && (FL_CONVEYOR & pev(iGEnt, pev_flags)))
			{
				static Float:vecTemp[3]
				pev(id, pev_basevelocity, vecTemp)
				g_vecVel[0] += vecTemp[0]
				g_vecVel[1] += vecTemp[1]
				g_vecVel[2] += vecTemp[2]
			}				
			set_pev(id, pev_velocity, g_vecVel)
			return FMRES_HANDLED
		}
	}
	return FMRES_IGNORED
}
new bool:falling[33]
public client_PreThink(id) 
{
  if(get_cvar_num("mp_falldamage") == 0 
  && is_user_alive(id) 
  && is_user_connected(id)) {
    if(entity_get_float(id, EV_FL_flFallVelocity) >= FALL_VELOCITY) 
{
      falling[id] = true
    } else {
      falling[id] = false
    }
  }
}
public client_PostThink(id) 
{
  if(get_cvar_num("mp_falldamage") == 0 
  && is_user_alive(id) 
  && is_user_connected(id)) 
{
    if(falling[id]) {
      entity_set_int(id, EV_INT_watertype, -3)
    }
    if(get_pcvar_num(semiclip) == 1)
    { 
    RefreshPlayersList()

    for(i = 0; i<g_iNum; i++)
    {
        g_iPlayer = g_iPlayers[i]
        if( g_iPlayer != id )
        {
            set_pev(g_iPlayer, pev_solid, SOLID_SLIDEBOX)
        }
    }
    }	
  }	
}
public player_spawn(id)
{
	if(is_user_connected(id))
	{
		cs_set_user_money(id, 16000)
	}
}
public enemy_distance(entid)
{
	new Float:range2
	new Float:maxrange=2000.0
	new indexid=0
	for(new i=1;i<=get_maxplayers();i++)
	{
		if(is_user_alive(i) && is_valid_ent(i) && attacking1(entid, i))
		{
			range2 = entity_range(entid, i)
			if(range2 <= maxrange)
			{
				maxrange=range2
				indexid=i
			}
		}			
	}	
	return (indexid) ? indexid : 0
}
public follow_player(ent, Float:ent_place[3], target, Float:player_place[3]) 
{
	if(target) 
	{
		new Float:newAngle[3]
		entity_get_vector(ent, EV_VEC_angles, newAngle)
		new Float:x = player_place[0] - ent_place[0]
		new Float:z = player_place[1] - ent_place[1]
		new Float:radians = floatatan(z/x, radian)
		newAngle[1] = radians * (180 / 3.14)
		if (player_place[0] < ent_place[0])
			newAngle[1] -= 180.0
       		entity_set_vector(ent, EV_VEC_v_angle, newAngle)
		entity_set_vector(ent, EV_VEC_angles, newAngle)
	}
}
public bool:attacking1(entindex1, entindex2)
{
	if (!entindex1 || !entindex2)
		return false
	if (pev_valid(entindex1) && pev_valid(entindex1))
	{
		new flags = pev(entindex1, pev_flags)
		if (flags & EF_NODRAW || flags & FL_NOTARGET)
		{
			return false
		}
		new Float:lookerOrig[3]
		new Float:targetBaseOrig[3]
		new Float:targetOrig[3]
		new Float:temp[3]
		pev(entindex1, pev_origin, lookerOrig)
		pev(entindex1, pev_view_ofs, temp)
		lookerOrig[0] += temp[0]
		lookerOrig[1] += temp[1]
		lookerOrig[2] += temp[2]
		pev(entindex2, pev_origin, targetBaseOrig)
		pev(entindex2, pev_view_ofs, temp)
		targetOrig[0] = targetBaseOrig [0] + temp[0]
		targetOrig[1] = targetBaseOrig [1] + temp[1]
		targetOrig[2] = targetBaseOrig [2] + temp[2]
		engfunc(EngFunc_TraceLine, lookerOrig, targetOrig, 0, entindex1, 0)
		if (get_tr2(0, TraceResult:TR_InOpen) && get_tr2(0, TraceResult:TR_InWater))
		{
			return false
		} 
		else 
		{
			new Float:flFraction
			get_tr2(0, TraceResult:TR_flFraction, flFraction)
			if (flFraction == 1.0 || (get_tr2(0, TraceResult:TR_pHit) == entindex2))
			{
				return true
			}
			else
			{
				targetOrig[0] = targetBaseOrig [0]
				targetOrig[1] = targetBaseOrig [1]
				targetOrig[2] = targetBaseOrig [2]
				engfunc(EngFunc_TraceLine, lookerOrig, targetOrig, 0, entindex1, 0)
				get_tr2(0, TraceResult:TR_flFraction, flFraction)
				if (flFraction == 1.0 || (get_tr2(0, TraceResult:TR_pHit) == entindex2))
				{
					return true
				}
				else
				{
					targetOrig[0] = targetBaseOrig [0]
					targetOrig[1] = targetBaseOrig [1]
					targetOrig[2] = targetBaseOrig [2] - 17.0
					engfunc(EngFunc_TraceLine, lookerOrig, targetOrig, 0, entindex1, 0)
					get_tr2(0, TraceResult:TR_flFraction, flFraction)
					if (flFraction == 1.0 || (get_tr2(0, TraceResult:TR_pHit) == entindex2))
					{
						return true
					}
				}
			}
		}
	}
	return false
}
public control_ai(ent, victim, Float:speed)
{
	static Float:fl_Velocity[3]
	static Float:VicOrigin[3], Float:EntOrigin[3]
	pev(ent, pev_origin, EntOrigin)
	pev(victim, pev_origin, VicOrigin)
	static Float:distance_f
	distance_f = get_distance_f(EntOrigin, VicOrigin)
	if (distance_f > 60.0)
	{
		new Float:fl_Time = distance_f / speed

		fl_Velocity[0] = (VicOrigin[0] - EntOrigin[0]) / fl_Time
		fl_Velocity[1] = (VicOrigin[1] - EntOrigin[1]) / fl_Time
		fl_Velocity[2] = 0.0
	} else
	{
		fl_Velocity[0] = 0.0
		fl_Velocity[1] = 0.0
		fl_Velocity[2] = 0.0
	}
	entity_set_vector(ent, EV_VEC_velocity, fl_Velocity)
}
public event_roundstart()
{
	client_cmd(0, "mp3 play %s", map_sound[1])
	set_task(0.0, "create_fallentitan", npc_create)
	set_task(50.0, "replay_music", map_music)
	set_task(1.0, "player1", npc_think_player, _, _, "b")
}
public player1()
{
	static player[32], player_num
	get_players(player, player_num, "a")
	if(player_num <= 0)
	{
		client_cmd(0, "stopsound")	
		client_cmd(0, "spk %s", npc_sound[4])
		set_task(3.0, "replay_game")
		remove_task(npc_think_player)
	} else {
		if(pev_valid(y_think) && pev(y_think, pev_iuser3) == 1)
		{
			client_cmd(0, "stopsound")	
			client_cmd(0, "spk %s", npc_sound[3])
			set_task(3.0, "replay_game")
			remove_task(npc_think_player)
		}
	}
}
public replay_game()
{
	server_cmd("sv_restartround 15")
}
public event_roundend()
{
	client_cmd(0, "stopsound")	
	remove_task(map_music)
}
public replay_music()
{
	client_cmd(0, "mp3 play %s", map_sound[1])	
	set_task(50.0, "replay_music", map_music)
}
public event_newround()
{	
	if(pev_valid(y_think))
	{
		remove_task(y_think+npc_run)
		remove_task(y_think+npc_stop)
		remove_task(y_think+npc_set_attack3)
		remove_task(y_think+npc_reload_skill)			
		remove_task(y_think+npc_start_think)
		remove_task(y_think+npc_clear)	
		remove_task(y_think+npc_restart)
		remove_entity_name("npc_fallentitan")	
	}
	remove_task(npc_create)
	remove_task(map_music)
	remove_task(npc_think_player)
	if(pev_valid(y_hpbar)) remove_entity(y_hpbar)
	client_cmd(0, "mp3 play %s", map_sound[0])	
}
public npc_position(id)
{
	pev(id, pev_origin, HAngles)
	pev(id, pev_angles, VAngles)
	VAngles[0] = 0.0
}
public plugin_cfg()						// Cvar's goes here
{
	server_cmd("mp_buytime 9999.0")
	server_cmd("mp_freezetime 20.0")
	server_cmd("sv_restartround 5")
	server_cmd("mp_timelimit 9999.0")
}
public plugin_precache()
{
	cache_explo = engfunc(EngFunc_PrecacheModel, "sprites/fallen_titan/nade.spr")
	y_npc_mdl = precache_model(npc_mdl)
	precache_model(hp_spr)
	for(new i = 0; i < sizeof(npc_sound); i++)
		precache_sound(npc_sound[i])
	for(new i = 0; i < sizeof(map_sound); i++)
		precache_generic(map_sound[i])	
	y_bleeding[0] = precache_model("sprites/blood.spr")
	y_bleeding[1] = precache_model("sprites/bloodspray.spr")	
	static mapname[64]
	get_mapname(mapname, sizeof(mapname))			// Fallen Titan spawn points 
	if(equal(mapname, "zs_construction"))			// Can be added manually with waypoint util
	{
		y_spawn_points[0] = -431.0
		y_spawn_points[1] = -33.0 
		y_spawn_points[2] = 1075.0
	}
}
public npc_attack_mh_ent() npc_attack_mh(y_think)
public npc_attack_simple(ent)
{
	if(!pev_valid(ent) || y_start_thinking)
		return	
	y_start_thinking = 1
	anim(ent, random_num(11, 12))
	set_pev(ent, pev_movetype, MOVETYPE_NONE)
	set_task(1.0, "fallentitan_simple", ent)
	set_task(1.1, "simple_dmg", ent)
	set_task(3.0, "simple_attack_reload", ent+npc_simple_attack2)
}
public simple_dmg(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 200.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 5, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_simple_attack_damage, DMG_SLASH)
		}
	}
}
public simple_attack_reload(ent)
{
	ent -= npc_simple_attack2
	y_start_thinking = 0
}
public npc_hollow(ent)
{
	if(!pev_valid(ent) || y_start_thinking)
		return	
	y_start_thinking = 1
	anim(ent, 4)
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
		}
	}
	set_pev(ent, pev_takedamage, DAMAGE_NO)
	set_rendering(ent,kRenderFxNone,255,255,255,kRenderTransAdd,200)
	set_pev(ent, pev_movetype, MOVETYPE_NONE)
	set_task(1.5, "hollow_dmg", ent)
	set_task(2.0, "hollow_dmg", ent)
	set_task(2.5, "hollow_dmg", ent)
	set_task(3.0, "hollow_dmg", ent)
	set_task(3.5, "hollow_dmg", ent)
	set_task(4.0, "hollow_dmg", ent)
	set_task(4.5, "hollow_dmg", ent)
	set_task(4.6, "hollow_reload", ent)
}
public hollow_dmg(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_hollow_damage, DMG_BULLET)
		}
	}
}
public hollow_reload(ent)
{
	y_start_thinking = 0
	set_pev(ent, pev_takedamage, DAMAGE_YES)
}
public npc_rocket(ent)
{
	if(!pev_valid(ent) || y_start_thinking)
		return	
	y_start_thinking = 1
	anim(ent, 16)
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
		}
	}
	set_pev(ent, pev_takedamage, DAMAGE_NO)
	set_rendering(ent,kRenderFxNone,255,255,255,kRenderTransAdd,200)
	set_pev(ent, pev_movetype, MOVETYPE_NONE)
	set_task(1.5, "rocket_dmg", ent)
	set_task(2.0, "rocket_dmg1", ent)
	set_task(2.5, "rocket_dmg2", ent)
	set_task(3.0, "rocket_dmg3", ent)
	set_task(3.5, "rocket_dmg4", ent)
	set_task(4.0, "rocket_dmg5", ent)
	set_task(4.5, "rocket_dmg6", ent)
	set_task(5.0, "rocket_dmg7", ent)
	set_task(5.0, "rocket_dmg8", ent)
	set_task(6.0, "rocket_reload", ent)
}
public rocket_dmg(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_rocket_damage, DMG_BULLET)
		}
	}
	{
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION) 
	write_coord(-731) 
	write_coord(-432) 
	write_coord(612) 
	write_short(cache_explo)
	write_byte(20)	
	write_byte(15) 	
	write_byte(TE_EXPLFLAG_NONE)
	message_end()
	}
}
public rocket_dmg1(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_rocket_damage, DMG_BULLET)
		}
	}
	{
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION)
	write_coord(-427) 
	write_coord(-153) 
	write_coord(612)
	write_short(cache_explo)
	write_byte(10)	
	write_byte(15) 	
	write_byte(TE_EXPLFLAG_NONE)
	message_end()
	}
}
public rocket_dmg2(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_rocket_damage, DMG_BULLET)
		}
	}
	{
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION)
	write_coord(-724) 
	write_coord(146)
	write_coord(612) 
	write_short(cache_explo)
	write_byte(20)	
	write_byte(15) 	
	write_byte(TE_EXPLFLAG_NONE)	
	message_end()
	}
}
public rocket_dmg3(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_rocket_damage, DMG_BULLET)
		}
	}
	{
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION) 
	write_coord(-501)
	write_coord(534) 
	write_coord(612) 
	write_short(cache_explo)	
	write_byte(10)	
	write_byte(15) 	
	write_byte(TE_EXPLFLAG_NONE)
	message_end()
	}
}
public rocket_dmg4(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_rocket_damage, DMG_BULLET)
		}
	}
	{
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION) 
	write_coord(15) 
	write_coord(536) 
	write_coord(612) 
	write_short(cache_explo)	
	write_byte(20)			
	write_byte(15) 	
	write_byte(TE_EXPLFLAG_NONE)
	message_end()
	}
}
public rocket_dmg5(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_rocket_damage, DMG_BULLET)
		}
	}
	{
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION) 
	write_coord(320) 
	write_coord(118) 
	write_coord(612) 
	write_short(cache_explo)
	write_byte(10)	
	write_byte(15) 	
	write_byte(TE_EXPLFLAG_NONE) 
	message_end()
	}
}
public rocket_dmg6(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_rocket_damage, DMG_BULLET)
		}
	}
	{
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION) 
	write_coord(363)
	write_coord(-339)
	write_coord(612) 
	write_short(cache_explo)
	write_byte(20)	
	write_byte(15) 	
	write_byte(TE_EXPLFLAG_NONE)
	message_end()
	}
}
public rocket_dmg7(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_rocket_damage, DMG_BULLET)
		}
	}
	{
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION) 
	write_coord(-72)
	write_coord(-509)
	write_coord(612) 
	write_short(cache_explo)
	write_byte(10)	
	write_byte(15) 	
	write_byte(TE_EXPLFLAG_NONE)
	message_end()
	}
}
public rocket_dmg8(ent)
{
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000.0)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_rocket_damage, DMG_BULLET)
		}
	}
	{
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION) 
	write_coord(-42)
	write_coord(-115)
	write_coord(612) 
	write_short(cache_explo)
	write_byte(20)	
	write_byte(15) 	
	write_byte(TE_EXPLFLAG_NONE)
	message_end()
	}
}
public rocket_reload(ent)
{
	y_start_thinking = 0
	set_pev(ent, pev_takedamage, DAMAGE_YES)
}
public fallentitan_simple(ent)
{
	static Float:OriginA[3], Float:OriginA2[3], Float:xls, Float:Vector[3], Float:Velocity[3]	
	pev(ent, pev_origin, OriginA)
	pev(y_ids, pev_origin, OriginA2)
	xs_vec_sub(OriginA2, OriginA, Velocity)
	xs_vec_sub(OriginA, OriginA2, Vector)
	xls = xs_vec_len(Vector)
	if (xls <= 200) {
		xs_vec_normalize(Velocity, Velocity)
		Velocity[2] = 0.5
		xs_vec_mul_scalar(Velocity, 1000.0, Velocity)
		set_pev(y_ids, pev_velocity, Velocity)
	}
}
public npc_attack_mh(ent)
{
	if(!pev_valid(ent) || y_start_thinking)
		return	
	y_start_thinking = 1
	y_run = 0
	anim(ent, 8)
	set_pev(ent, pev_takedamage, DAMAGE_NO)
	set_rendering(ent,kRenderFxNone,255,255,255,kRenderTransAdd,200)
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000)
		{
			mega_shake_screen(i)
			ScreenFade(i, 10, {255, 0, 0}, 120)
		}
	}
	set_pev(ent, pev_movetype, MOVETYPE_NONE)
	set_task(2.0, "run_now", ent+npc_run)
	set_task(2.5, "stop_run", ent+npc_stop)	
}
public run_now(ent)
{	
	ent -= npc_run
	if(!pev_valid(ent))
		return		
	y_run = 1
	anim(ent, 9)
	set_rendering (ent,kRenderFxNone,255,255,255,kRenderNormal,16)
	set_pev(ent, pev_movetype, MOVETYPE_PUSHSTEP)
	static Float:Origin[3]
	get_position(ent, 1000.0, 0.0, 0.0, Origin)
	control_ai2(ent, Origin, 2000.0)
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000)
		{
			mega_shake_screen(i)
		}
	}
}
public npc_fallentitan_touch(ent, id)
{
	if(!pev_valid(id))
		return
	if(!y_run)
		return
	y_run = 0
	remove_task(ent+npc_stop)
	set_task(0.1, "stop_run", ent+npc_stop)
	if(is_user_alive(id))
	{
		ExecuteHam(Ham_TakeDamage, id, 0, id, npc_mh_damage, DMG_SLASH)
		shake_screen(id)
		ScreenFade(id, 10, {255, 0, 0}, 120)
	}
}
public stop_run(ent)
{
	ent -= npc_stop
	y_run = 0
	y_start_thinking = 1
	anim(ent, 10)
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000)
		{
			shake_screen(i)
		}
	}
	set_pev(ent, pev_movetype, MOVETYPE_NONE)
	set_pev(ent, pev_takedamage, DAMAGE_YES)
	set_task(1.0, "reload_run", ent)
}
public reload_run(ent)
{
	y_start_thinking = 0
	anim(ent, 5)
	set_pev(ent, pev_movetype, MOVETYPE_NONE)
}
public create_fallentitan()
{
	new ent = create_entity("info_target")
	y_think = ent
	static Float:Origin[3]
	Origin[0] = y_spawn_points[0]
	Origin[1] = y_spawn_points[1]
	Origin[2] = y_spawn_points[2]
	entity_set_origin(ent, Origin)
	entity_set_float(ent, EV_FL_takedamage, 1.0)
	entity_set_float(ent, EV_FL_health, npc_healthpoints + 1000.0)
	entity_set_string(ent, EV_SZ_classname, "npc_fallentitan")
	entity_set_model(ent, npc_mdl)
	entity_set_int(ent, EV_INT_solid, SOLID_BBOX)
	entity_set_int(ent, EV_INT_movetype, MOVETYPE_PUSHSTEP)
	new Float:maxs[3] = {25.0, 50.0, 200.0}
	new Float:mins[3] = {-25.0, -50.0, -35.0}
	entity_set_size(ent, mins, maxs)
	entity_set_int(ent, EV_INT_modelindex, y_npc_mdl)
	anim(ent, 2)
	set_rendering(ent,kRenderFxNone,255,255,255,kRenderTransAdd,200)
	set_task(1.0, "fallentitan_done", ent+npc_start_think)			// Fallen Titan prepare time
	if(!y_start_npc)
	{
		y_start_npc = 1
		RegisterHamFromEntity(Ham_TakeDamage, ent, "fallentitan_take_damage", 1)
	}
	y_hpbar = create_entity("env_sprite")
	set_pev(y_hpbar, pev_scale, 0.4)
	set_pev(y_hpbar, pev_owner, ent)
	engfunc(EngFunc_SetModel, y_hpbar, hp_spr)	
	set_task(0.1, "fallentitan_ready", ent+npc_restart, _, _, "b")
	set_task(random_float(7.0, 15.0), "punish", npc_ability)
}
public punish()
{
	static ent
	ent = y_think
	if(!pev_valid(ent))
		return
	static victim
	victim = pev(ent, pev_iuser4)
	set_task(random_float(5.0, 15.0), "punish", npc_ability)
	if(!is_user_alive(victim))
		return
	static random_skill
	random_skill = random_num(0, 4)		
	switch(random_skill)
	{
		case 0: npc_attack_mh(ent)
		case 1: npc_hollow(ent)
		case 2: npc_rocket(ent)		
	} 

}
public fallentitan_ready(ent)
{
	ent -= npc_restart
	if(!pev_valid(ent))
	{
		remove_task(ent+npc_restart)
		return
	}
	static Float:Origin[3], Float:fallentitan_health
	pev(ent, pev_origin, Origin)
	Origin[2] += 200.0	
	engfunc(EngFunc_SetOrigin, y_hpbar, Origin)
	pev(ent, pev_health, fallentitan_health)
	if(npc_healthpoints < (fallentitan_health - 1000.0))
	{
		set_pev(y_hpbar, pev_frame, 100.0)
	}
	else
	{
		set_pev(y_hpbar, pev_frame, 0.0 + ((((fallentitan_health - 1000.0) - 1 ) * 100) / npc_healthpoints))
	}		
}
public fallentitan_done(ent)
{
	ent -= npc_start_think
	anim(ent, 3)
	for(new i = 0; i < get_maxplayers(); i++)
	{
		if(is_user_alive(i) && entity_range(ent, i) <= 4000)
		{
			mega_shake_screen(i)
			ScreenFade(i, 15, {255, 0, 0}, 120)
			ExecuteHam(Ham_TakeDamage, i, 0, i, npc_appear_damage, DMG_BULLET)
		}
	}
	set_pev(ent, pev_movetype, MOVETYPE_NONE)
	set_pev(ent, pev_nextthink, get_gametime() + 6.0)
}
public npc_fallentitan_think(ent)
{
	if(!pev_valid(ent))
		return
	if(pev(ent, pev_iuser3))
		return
	if(pev(ent, pev_health) - 1000.0 < 0.0)
	{
		fallentitan_death(ent)
		set_pev(ent, pev_iuser3, 1)
		return
	}
	if(!y_start_thinking)
	{
		static victim
		static Float:Origin[3], Float:VicOrigin[3], Float:distance
		victim = enemy_distance(ent)
		pev(ent, pev_origin, Origin)
		pev(victim, pev_origin, VicOrigin)
		distance = get_distance_f(Origin, VicOrigin)
		if(is_user_alive(victim))
		{
			if(distance <= 150.0)
			{
				npc_attack_simple(ent)
				set_pev(ent, pev_nextthink, get_gametime() + 0.1)
			} else {
				if(pev(ent, pev_sequence) != 7)
					anim(ent, 7)
				for(new i = 0; i < get_maxplayers(); i++)
				{
					if(is_user_alive(i) && entity_range(ent, i) <= 500)
					{
						shake_screen(i)
					}
				}
				set_pev(ent, pev_movetype, MOVETYPE_PUSHSTEP)
				set_rendering (ent,kRenderFxNone,255,255,255,kRenderNormal,16)
				new Float:ent_place[3], Float:player_place[3]
				pev(ent, pev_origin, ent_place)
				pev(victim, pev_origin, player_place)
				follow_player(ent, ent_place, victim, player_place)
				control_ai(ent, victim, 200.0)
				if(pev(ent, pev_iuser4) != victim)
					set_pev(ent, pev_iuser4, victim)
				set_pev(ent, pev_nextthink, get_gametime() + 0.0)
			}
		} else {
			if(pev(ent, pev_sequence) != 5)
				anim(ent, 5)
			set_pev(ent, pev_nextthink, get_gametime() + 0.0)
		}		
	} else {
		set_pev(ent, pev_nextthink, get_gametime() + 0.0)
	}
	return
}
public fallentitan_death(ent)
{
	y_start_thinking = 0	
	anim(ent, 19)
	set_rendering(ent,kRenderFxNone,255,255,255,kRenderTransAdd,200)
        set_pev(ent, pev_movetype, MOVETYPE_FLY)
        set_pev(ent, pev_solid, SOLID_NOT)
        set_pev(ent, pev_velocity, {0.0, 0.0, 0.0})
        set_pev(ent, pev_deadflag, DEAD_DYING)
        remove_task(npc_ability)
	set_task(13.0, "delete_fallentitan", ent)
        return HAM_SUPERCEDE	
}
public delete_fallentitan(ent)
{
	remove_entity(ent)
	remove_entity(y_hpbar)
}
public fallentitan_take_damage(victim, inflictor, attacker, Float:damage, damagebits)
{
	static Float:Origin[3]
	fm_get_aim_origin(attacker, Origin)
	create_blood(Origin)
	emit_sound(victim, CHAN_BODY, npc_sound[7], 1.0, ATTN_NORM, 0, PITCH_NORM)	
}
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()
}
stock shake_screen(id)
{
	message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("ScreenShake"), _, id)
	write_short(1<<14)
	write_short(1<<12)
	write_short(1<<12)
	message_end()
}
stock mega_shake_screen(id)
{
	message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("ScreenShake"), _, id)
	write_short(14<<14)
	write_short(12<<12)
	write_short(12<<12)
	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 control_ai2(ent, Float:VicOrigin[3], Float:speed)
{
	static Float:fl_Velocity[3]
	static Float:EntOrigin[3]
	pev(ent, pev_origin, EntOrigin)
	static Float:distance_f
	distance_f = get_distance_f(EntOrigin, VicOrigin)
	if (distance_f > 60.0)
	{
		new Float:fl_Time = distance_f / speed
		fl_Velocity[0] = (VicOrigin[0] - EntOrigin[0]) / fl_Time
		fl_Velocity[1] = (VicOrigin[1] - EntOrigin[1]) / fl_Time
		fl_Velocity[2] = (VicOrigin[2] - EntOrigin[2]) / fl_Time
	} else {
		fl_Velocity[0] = 0.0
		fl_Velocity[1] = 0.0
		fl_Velocity[2] = 0.0
	}
	entity_set_vector(ent, EV_VEC_velocity, fl_Velocity)
}
stock get_position(ent, Float:forw, Float:right, Float:up, Float:vStart[])
{
	new Float:vOrigin[3], Float:vAngle[3], Float:vForward[3], Float:vRight[3], Float:vUp[3]
	pev(ent, pev_origin, vOrigin)
	pev(ent, pev_view_ofs,vUp)
	xs_vec_add(vOrigin,vUp,vOrigin)
	pev(ent, pev_v_angle, vAngle)
	vAngle[0] = 0.0
	angle_vector(vAngle,ANGLEVECTOR_FORWARD,vForward)
	angle_vector(vAngle,ANGLEVECTOR_RIGHT,vRight)
	angle_vector(vAngle,ANGLEVECTOR_UP,vUp)
	vStart[0] = vOrigin[0] + vForward[0] * forw + vRight[0] * right + vUp[0] * up
	vStart[1] = vOrigin[1] + vForward[1] * forw + vRight[1] * right + vUp[1] * up
	vStart[2] = vOrigin[2] + vForward[2] * forw + vRight[2] * right + vUp[2] * up
}
stock create_blood(const Float:origin[3])
{
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY) 
	write_byte(TE_BLOODSPRITE)
	engfunc(EngFunc_WriteCoord, origin[0])
	engfunc(EngFunc_WriteCoord, origin[1])
	engfunc(EngFunc_WriteCoord, origin[2])
	write_short(y_bleeding[1])
	write_short(y_bleeding[0])
	write_byte(100)
	write_byte(7)
	message_end()
}