#include <amxmodx>
#include <fakemeta>
#include <fakemeta>
#include <hamsandwich>
#include <fun>
#include <xs>
#include <zombieplague>

#define pev_flare pev_iuser4

#define flare_id 1337

#define is_ent_flare(%1) (pev(%1, pev_flare) == flare_id) ? 1 : 0

new const explosive_flare_model[] = "models/w_smokegrenade.mdl"

const Float:FLARE_EXPLOSION_DAMAGE = 65.0
const Float:FLARE_EXPLOSION_RADIUS = 270.0
const Float:FLARE_DAMAGE_MULTI = 1.0
const DMG_HEGRENADE = (1<<24)

new explosive_sprite2, explosive_sprite, item_explosive_flare

public plugin_precache() 
{
	precache_model(explosive_flare_model)
        explosive_sprite = precache_model("sprites/flare_exp_1.spr")
        explosive_sprite2 = precache_model("sprites/flare_exp_2.spr")
}

public plugin_init()
{
	register_plugin("[ZP]Explosive Flare", "1.0", "[Half-Life] Biohazard")

	register_forward(FM_SetModel, "explosive_model_stuff")
	
	register_forward(FM_Think, "explosive_think")

        item_explosive_flare = zp_register_extra_item("Explosive Flare", 15, ZP_TEAM_HUMAN)
}

public zp_extra_item_selected(id, item)
{
	if(item == item_explosive_flare)
	{
		give_item(id, "weapon_smokegrenade")
		
		client_print(id, print_chat, "[ZP] You bought Explosive Flare which can kill the zombies.")
	}
}

public explosive_model_stuff(ent, const model[]) 
{
	if(!pev_valid(ent) || !equal(model[9], "smokegrenade.mdl"))
		return FMRES_IGNORED

	static Float:light_origin[3]  

	pev(ent,pev_origin,light_origin)

	static classname[32]; pev(ent, pev_classname, classname, 31)

	if(equal(classname, "grenade"))
	{
		engfunc(EngFunc_SetModel, ent, explosive_flare_model)

		set_task(0.1, "make_flare_flash", ent)

                set_task(4.0, "make_flare_explode", ent)

		set_pev(ent, pev_flare,   flare_id)

		set_pev(ent, pev_nextthink, get_gametime() + 199)
		
		return FMRES_SUPERCEDE
	}
	return FMRES_IGNORED
}

public make_flare_flash(ent) 
{
	if(!pev_valid(ent))
		return FMRES_IGNORED

	static Float:light_origin[3] 
 
	pev(ent,pev_origin,light_origin)

	static classname[32]; pev(ent, pev_classname, classname, 31)

	if(equal(classname, "grenade"))
        {
		engfunc(EngFunc_SetModel, ent, explosive_flare_model)
		message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
		write_byte(27) 
		engfunc(EngFunc_WriteCoord,light_origin[0]) 
		engfunc(EngFunc_WriteCoord,light_origin[1]) 
		engfunc(EngFunc_WriteCoord,light_origin[2]) 
		write_byte(22)	// radius
		write_byte(237) // r
	        write_byte(247) // g
	        write_byte(35) // b
		write_byte(3) 	// life
		write_byte(0)	// rate
		message_end()
		set_task(0.1,"make_flare_flash",ent);
		
		return FMRES_SUPERCEDE
        }
	return FMRES_IGNORED
}

public make_flare_explode(ent)
{
    if(!pev_valid(ent))
            return

     new Float:atkOrigin[3]

     pev(ent, pev_origin, atkOrigin)

     static classname[32]; pev(ent, pev_classname, classname, 31)

     if(equal(classname, "grenade"))
     {     
	engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, atkOrigin, 0)
	write_byte(TE_EXPLOSION)
	engfunc(EngFunc_WriteCoord, atkOrigin[0])
	engfunc(EngFunc_WriteCoord, atkOrigin[1])
	engfunc(EngFunc_WriteCoord, atkOrigin[2] + 50.0)
	write_short(explosive_sprite)
	write_byte(15)
	write_byte(15)
        write_byte(10)
	message_end()

        message_begin (MSG_BROADCAST,SVC_TEMPENTITY)
        write_byte( TE_SPRITETRAIL ) 
        engfunc(EngFunc_WriteCoord, atkOrigin[ 0 ]) 
        engfunc(EngFunc_WriteCoord, atkOrigin[ 1 ])
        engfunc(EngFunc_WriteCoord, atkOrigin[ 2 ] + 200.0)
        engfunc(EngFunc_WriteCoord, atkOrigin[ 0 ]) 
        engfunc(EngFunc_WriteCoord, atkOrigin[ 1 ])
        engfunc(EngFunc_WriteCoord, atkOrigin[ 2 ] + 30.0)
        write_short(explosive_sprite2) 
        write_byte(20) 
        write_byte(random_num(1,2)) 
        write_byte(2) 
        write_byte(15) 
        write_byte(2) 
        message_end() 

        set_task(4.0, "make_flare_explode", ent)
     }
                           	
     new attacker = pev(ent, pev_owner)

     if(!is_user_connected(attacker))
     {
		engfunc(EngFunc_RemoveEntity, ent)
		return
     }
	
     new victim = -1
	
     while((victim = engfunc(EngFunc_FindEntityInSphere, victim, atkOrigin, FLARE_EXPLOSION_RADIUS)) != 0)
     {     
		if(!is_user_alive(victim) || !zp_get_user_zombie(victim)) continue;
		
		new Float:fOrigin[3], Float:fDistance, Float:fDamage

		pev(victim, pev_origin, fOrigin)

		fDistance = get_distance_f(fOrigin, atkOrigin)

		fDamage = FLARE_EXPLOSION_DAMAGE - floatmul(FLARE_EXPLOSION_DAMAGE, floatdiv(fDistance, FLARE_EXPLOSION_RADIUS))

		fDamage *= 1.0

		if(fDamage < 1.0) continue;
		
		xs_vec_sub(fOrigin, atkOrigin, fOrigin)

		xs_vec_mul_scalar(fOrigin, fDamage*FLARE_DAMAGE_MULTI, fOrigin)

		xs_vec_mul_scalar(fOrigin, FLARE_EXPLOSION_DAMAGE / xs_vec_len(fOrigin), fOrigin)

		set_pev(victim, pev_velocity, fOrigin)
		
		ExecuteHamB(Ham_TakeDamage, victim, ent, attacker, fDamage, DMG_HEGRENADE)
     }
}

public explosive_think(ent) 
{
      if(pev_valid(ent) && is_ent_flare(ent))
      {
	  engfunc(EngFunc_RemoveEntity, ent)
      }
}