#include <amxmodx>
#include <cstrike>
#include <engine>
#include <fakemeta_util>
#include <fun>
#include <hamsandwich>
#include <zombieplague>

// Plugin info
new const PLUGIN[] = "[ZP] Extra Item: M79 Grenade Launcher"
new const VERSION[] = "1.0"
new const AUTHOR[] = "SISA"

#define HUD_HIDE_CROSS (1<<6)

// Weapon/Grenade models
new const P_MODEL[] = "models/p_m79.mdl"
new const V_MODEL[] = "models/v_m79fix2.mdl"
new const W_MODEL[] = "models/w_m79.mdl"
new const GRENADE_MODEL[] = "models/grenade.mdl"

// Fire sound
new const GRENADE_SHOOT[] = "weapons/m79_fire1.wav"
new const GRENADE_CLIPIN[] = "weapons/m79_clipin.wav"
new const GRENADE_CLIPON[] = "weapons/m79_clipon.wav"
new const GRENADE_CLIPOUT[] = "weapons/m79_clipout.wav"
new const GRENADE_DRAW[] = "weapons/m79_draw.wav"

// Sprites
new const GRENADE_TRAIL[] = "sprites/laserbeam.spr"
new const GRENADE_EXPLOSION[] = "sprites/m79_exp.spr"
new const GRENADE_SMOKE[] = "sprites/black_smoke3.spr"

// Cached sprite indexes
new sTrail, sExplo, sSmoke

// Sprites
new gmsgWeaponList

// Bodyparts and blood
new mdl_gib_flesh, mdl_gib_head, mdl_gib_lung, mdl_gib_spine,
blood_drop, blood_spray

// Item ID
new g_m79
new m79

// Player variables
new g_hasM79[33] // whether player has M79
new g_FireM79[33] // player is shooting
new g_canShoot[33] // player can shoot
new Float:g_last_shot_time[33] // last shot time
new grenade_count[33] // current grenade count
new bool:draw_wpn[33] //выбираем пукалку
new bool:hasOnHandM79[33],bool:canfire[33],
cvar_granade_damage_radius,
cvar_granade_max_damage
// Message ID's
new g_msgScreenShake,g_msgStatusText
new gmsgDeathMsg, gmsgScoreInfo

// Customization(CHANGE HERE)
#define LAUNCHER_COST	20
new Float:delayshot = 3.0
// Tasks
#define TASK_HUDAMMO	    1337
#define TASK_FRSTSHT	    1437
#define ID_HUDAMMO (taskid - TASK_HUDAMMO)
#define ID_SHT (taskid - TASK_FRSTSHT)

enum {
	anim_idle,
	anim_shot1,
	anim_shot2,
	anim_draw,
}


// Plugin precache
public plugin_precache()
{
	// Models
	precache_model(P_MODEL)
	precache_model(V_MODEL)
	precache_model(W_MODEL)
	precache_model(GRENADE_MODEL)
	
	// Sounds
	precache_sound(GRENADE_SHOOT)
	precache_sound(GRENADE_CLIPIN)
	precache_sound(GRENADE_CLIPOUT)
	precache_sound(GRENADE_CLIPON)
	precache_sound(GRENADE_DRAW)
	precache_sound("weapons/357_cock1.wav")
	
	// Sprites
	sTrail = precache_model(GRENADE_TRAIL)
	sExplo = precache_model(GRENADE_EXPLOSION)
	sSmoke = precache_model(GRENADE_SMOKE)
	
	// Bodyparts and blood
	blood_drop = precache_model("sprites/blood.spr")
	blood_spray = precache_model("sprites/bloodspray.spr")
	mdl_gib_flesh = precache_model("models/Fleshgibs.mdl")
	mdl_gib_head = precache_model("models/GIB_Skull.mdl")
	mdl_gib_lung = precache_model("models/GIB_Lung.mdl")
	mdl_gib_spine = precache_model("models/GIB_B_Bone.mdl")

        // Sprites
        precache_generic( "sprites/weapon_m79_sisa.txt" );
        precache_generic( "sprites/640hud42.spr" );
        precache_generic( "sprites/640hud42.spr" );
        precache_generic( "sprites/640hud7x.spr" );
    
        register_clcmd("weapon_m79_sisa", "Hook_Select")

}

// Plugin init
public plugin_init()
{
	// Register plugin
	register_plugin(PLUGIN, VERSION, AUTHOR)
	register_cvar("zp_m79_version", VERSION, FCVAR_SERVER)
	
	// Register new extra item
	g_m79 = zp_register_extra_item("M79", 50, ZP_TEAM_HUMAN)
	
	cvar_granade_damage_radius = register_cvar("granade_damage_radius","400",FCVAR_UNLOGGED)
	cvar_granade_max_damage = register_cvar("granade_max_damage","700",FCVAR_UNLOGGED)
	
	// Events
	register_event("CurWeapon", "Event_CurrentWeapon", "be", "1=1")
	register_event("HLTV", "Event_NewRound", "a", "1=0", "2=0");
	register_logevent("event_start", 2, "1=Round_Start")
	
	// Forwards
	RegisterHam(Ham_Killed, "player", "fw_PlayerKilled")
	register_forward(FM_CmdStart, "fw_CmdStart")
	register_forward(FM_PlayerPostThink, "fw_PlayerPostThink")
	register_forward(FM_UpdateClientData, "fw_UpdateClientData_Post", 1)
	register_clcmd("drop","dropcmd")
	// Messages
	g_msgScreenShake = get_user_msgid("ScreenShake")
	g_msgStatusText = get_user_msgid("StatusText")
	gmsgDeathMsg = get_user_msgid("DeathMsg")
	gmsgScoreInfo = get_user_msgid("ScoreInfo") 
        // Sprites
	RegisterHam( Ham_Item_AddToPlayer, "weapon_p228", "fw_AddToPlayer" );
	gmsgWeaponList = get_user_msgid("WeaponList")

}

public Hook_Select(id)
{
    engclient_cmd(id, "weapon_p228")
    return PLUGIN_HANDLED
}


public zp_user_infect_attempt(id, infector, nemesis)
{
	dropcmd(id)
	remove_icon(id)
	set_task(0.15,"hud_clear",id)
}

public dropcmd(id) {
	        if(g_hasM79[id] && hasOnHandM79[id]) {
		new Float:Aim[3],Float:origin[3]
		VelocityByAim(id, 64, Aim)
		entity_get_vector(id,EV_VEC_origin,origin)
		
		origin[0] += Aim[0]
		origin[1] += Aim[1]
		
		new m79 = create_entity("info_target")
		entity_set_string(m79,EV_SZ_classname,"m79")
		entity_set_model(m79,W_MODEL)	
		
		entity_set_size(m79,Float:{-2.0,-2.0,-2.0},Float:{5.0,5.0,5.0})
		entity_set_int(m79,EV_INT_solid,1)
		
		entity_set_int(m79,EV_INT_movetype,6)
		entity_set_int(m79, EV_INT_iuser1, grenade_count[id])
		entity_set_vector(m79,EV_VEC_origin,origin)
		g_hasM79[id] = false
		g_canShoot[id] = false
		grenade_count[id] = false
		hasOnHandM79[id] = false
		remowegun(id)
		remove_icon(id)
		set_task(0.15,"hud_clear",id)
		return PLUGIN_HANDLED
	} 
	        return PLUGIN_CONTINUE
}

// remove gun  and save all guns
public remowegun(id) { 
	new wpnList[32] 
	new number
	get_user_weapons(id,wpnList,number) 
	for (new i = 0;i < number ;i++) { 
		if (wpnList[i] == CSW_P228) {
			fm_strip_user_gun(id, wpnList[i])
		}
	}
} 

//play anim
public playanim(player,anim)
{
	set_pev(player, pev_weaponanim, anim)
	message_begin(MSG_ONE, SVC_WEAPONANIM, {0, 0, 0}, player)
	write_byte(anim)
	write_byte(pev(player, pev_body))
	message_end()
}


// Client connected
public client_connect(id)
{
	// Reset all
	g_hasM79[id] = false
	g_canShoot[id] = false
	g_last_shot_time[id] = 0.0
	grenade_count[id] = 0
	hasOnHandM79[id] = false
	remove_icon(id)
}

// Extra item selected
public zp_extra_item_selected(id, itemid)
{
	// Our item
	if (itemid == g_m79)
	{
		// Already has our weapon
		if (g_hasM79[id])
		{
			print(id, "^x04[SERVER]^x01 Вы купили 10 гранат для M79!")
			grenade_count[id] += 10
			zp_set_user_ammo_packs(id, zp_get_user_ammo_packs(id) + LAUNCHER_COST - 15)
			set_task(0.1, "hud_init", id+TASK_HUDAMMO)
		}
		else
		{	
			if(m79 < 2)
			{		
				give_weapon(id, 10)
				m79++
			}
			else
			{
				print(id, "^x04[SERVER]^x01 Максимальное количество М79 в туре (2) была достигнута!")
				zp_set_user_ammo_packs(id, zp_get_user_ammo_packs(id) + LAUNCHER_COST)
			}
		}
	}
}

// User has been injected
public zp_user_infected_post(id, infector, nemesis)
{
	if (g_hasM79[id])
	{
		// Reset all
		g_hasM79[id] = false
		g_canShoot[id] = false
		g_FireM79[id] = false
		g_last_shot_time[id] = 0.0
		grenade_count[id] = 0

		remove_icon(id)
		set_task(0.15,"hud_clear",id)
		
		// Remove HUD
		remove_task(id+TASK_HUDAMMO)
	}
}


// Current weapon player is holding
public Event_CurrentWeapon(id)
{
	// Ignore zombie/Nemesis
	if (zp_get_user_zombie(id) || zp_get_user_nemesis(id) || is_user_bot(id))
		return

	if(!is_user_connected(id))
		return
	
	// Read weapon ID
	new weaponID = read_data(2)
	
	if (weaponID == CSW_P228)
	{
		if (g_hasM79[id])
		{
			message_begin(MSG_ONE, get_user_msgid("CurWeapon"), {0,0,0}, id) 
			write_byte(1) 
			write_byte(CSW_KNIFE) 
			write_byte(0) 
			message_end()
			hasOnHandM79[id] = true
			remove_task(id+TASK_FRSTSHT)

        		message_begin(MSG_ONE,get_user_msgid("StatusIcon"),{0,0,0},id);
        		write_byte(1); // status (0=hide, 1=show, 2=flash)
        		write_string("item_battery"); // sprite name
        		write_byte(210) 
        		write_byte(105)
        		write_byte(30)
        		message_end()

			set_task(0.1, "hud_init", id+TASK_HUDAMMO)

			if(!draw_wpn[id])
			{
				playanim(id, anim_draw)
				emit_sound(id, CHAN_WEAPON, GRENADE_DRAW, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
				// View model
				entity_set_string(id, EV_SZ_viewmodel, V_MODEL)
				
				// Player model
				entity_set_string(id, EV_SZ_weaponmodel, P_MODEL)
				canfire[id] = false
				draw_wpn[id] = true
				set_task(1.6,"delayshottsk", id+TASK_FRSTSHT)
			}
			else if(get_gametime() - g_last_shot_time[id] > delayshot) playanim(id, anim_idle)
		}
		else
		{
			// View model
			entity_set_string(id, EV_SZ_viewmodel, "models/v_p228.mdl")
			
			// Player model
			entity_set_string(id, EV_SZ_weaponmodel, "models/p_p228.mdl")
			hasOnHandM79[id] = false
			remove_icon(id)
			set_task(0.15,"hud_clear",id)
		}
	} 
	else 
	{
		draw_wpn[id] = false
		hasOnHandM79[id] = false
		remove_icon(id)
		set_task(0.15,"hud_clear",id)
	}
}

public fw_AddToPlayer( iEnt, Player )
{
    if( pev_valid( iEnt ) && is_user_connected( Player ) )
    {
            if(g_hasM79[Player])
            Sprite(Player)
    }
} 


public remove_icon(id) 
{
	if(!is_user_connected(id))
		return

	message_begin(MSG_ONE,get_user_msgid("StatusIcon"),{0,0,0},id)
	write_byte(0) 
	write_string("item_battery") // sprite name
	message_end()
	return
}

public delayshottsk(taskid){
	canfire[ID_SHT] = true
}

// New round started
public Event_NewRound(id)
{// Strip from M79 if game have been restarted
    for (new i = 0; i < get_maxplayers(); i++)
    {
    g_hasM79[i] = false
    }
    m79 = 0
    draw_wpn[id] = false
    Event_CurrentWeapon(id)
}

public Sprite(id)
{
    
    message_begin(MSG_ONE, gmsgWeaponList, {0,0,0}, id)
    
    write_string("weapon_m79_sisa")
        
    write_byte(9)
    write_byte(52)
    write_byte(-1)
    write_byte(-1)
    write_byte(1)
    write_byte(3)
    write_byte(1)
    write_byte(0)
    message_end()

}



public event_start()
{
	m79 = 0
	remove_m79()
}

public remove_m79() {
	new nextitem = find_ent_by_class(-1, "m79")
	while ((nextitem = find_ent_by_class(-1, "m79")) != 0) {
		remove_entity(nextitem)
	}
	return PLUGIN_CONTINUE
}		

// Player killed
public fw_PlayerKilled(victim, attacker, shouldgib)
{
	if (g_hasM79[victim])		
	{
		// Reset all
		g_hasM79[victim] = false
		g_canShoot[victim] = false
		g_FireM79[victim] = false
		grenade_count[victim] = 0
		
		// Remove HUD
		remove_task(victim+TASK_HUDAMMO)
		remowegun(victim)
		remove_icon(victim)
	}
}




//give wpn
public give_weapon(id, ammo){
	g_hasM79[id] = true
	g_canShoot[id] = true
	g_FireM79[id] = false
	give_item(id,"weapon_p228")
	if(ammo == -1) grenade_count[id] = 10
	else grenade_count[id] = ammo
	set_task(0.1, "hud_init", id+TASK_HUDAMMO)
}


// Command start
public fw_CmdStart(id, uc_handle, seed) 
{
	// Don't have our weapon	
	if (!hasOnHandM79[id] || !is_user_alive(id) || zp_get_user_zombie(id) || zp_get_user_nemesis(id)){
		g_FireM79[id] = false
		return FMRES_IGNORED
		}
	// Get buttons	
	new buttons = get_uc(uc_handle, UC_Buttons)
	
	// Attack1 button pressed
	if(buttons & IN_ATTACK)
	{
		g_FireM79[id] = true
	
		// Remove attack button from their button mask
		buttons &= ~IN_ATTACK
		set_uc(uc_handle, UC_Buttons, buttons)
	}
	else 
		g_FireM79[id] = false	
		
	return FMRES_HANDLED
}

// Player think after
public fw_PlayerPostThink(id)
{
	// Don't have our weapon	
	if (!g_hasM79[id])
		return FMRES_IGNORED
		
	// ignore dead
	if (!is_user_alive(id))
		return FMRES_IGNORED
		
	// Ignore zombies/nemesis	
	if (zp_get_user_zombie(id) || zp_get_user_nemesis(id))
		return FMRES_IGNORED
	
	// If player is firing	
	if (g_FireM79[id] && hasOnHandM79[id])
	{
		// Grenades are more or equal to 1
		if (grenade_count[id] >= 1)
		{
			// Player can shoot
			if (get_gametime() - g_last_shot_time[id] > delayshot && canfire[id])
			{
				// Fire!!!
				FireGrenade(id)
				
				// Decrease nade count
				grenade_count[id]--
				
				// Without this HUD is not updating correctly
				set_task(0.1, "hud_init", id+TASK_HUDAMMO)
				
				// Remember last shot time
				g_last_shot_time[id] = get_gametime()
			}
		}
		else
		{
			// Don't have nades
			client_print(id, print_center, "У вас больше нет гранат!")
		}
	}
	
	return FMRES_IGNORED
}


//block anim standart wpn 
public fw_UpdateClientData_Post(id, sendweapons, cd_handle) 
{
	// Don't have our weapon	
	if (!hasOnHandM79[id] || !is_user_alive(id)) return FMRES_IGNORED
	// Block default sounds	
	if (hasOnHandM79[id] && g_hasM79[id] && g_canShoot[id]) set_cd(cd_handle, CD_flNextAttack, halflife_time() + 0.001 ); 
	return FMRES_HANDLED
}

// Fire gremade
public FireGrenade(id)
{
	// Set animation
	if(grenade_count[id]>1){ 
		playanim(id, anim_shot1)
		set_task(0.4,"reloadsnd",id)
		set_task(1.6,"reloadin",id)
		set_task(2.3,"reloadon",id)
	} else { 
		playanim(id, anim_shot2)
	}
	// Get origin. angle and velocity
	new Float:fAngle[3], Float:fVelocity[3]
	pev(id, pev_v_angle, fAngle)
	
	// Create ent
	new grenade = create_entity("info_target")
	
	// Not grenade
	if (!grenade) return PLUGIN_HANDLED
	
	// Classname
	entity_set_string(grenade, EV_SZ_classname, "m79_grenade")
	
	// Model
	entity_set_model(grenade, GRENADE_MODEL)
	
	new Float:vOrigin[3],Float:vUp[3]
	pev(id, pev_origin, vOrigin)
	
	global_get(glb_v_up, vUp)
	new up = 17
	vOrigin[0] = vOrigin[0] + vUp[0] * up
	vOrigin[1] = vOrigin[1] + vUp[1] * up
	vOrigin[2] = vOrigin[2] + vUp[2] * up
	
	// Origin
	entity_set_origin(grenade, vOrigin)
	
	// Angles
	entity_set_vector(grenade, EV_VEC_angles, fAngle)
	
	// Size
	new Float:MinBox[3] = {-1.0, -1.0, -1.0}
	new Float:MaxBox[3] = {1.0, 1.0, 1.0}
	entity_set_vector(grenade, EV_VEC_mins, MinBox)
	entity_set_vector(grenade, EV_VEC_maxs, MaxBox)
	
	// Interaction
	entity_set_int(grenade, EV_INT_solid, SOLID_SLIDEBOX)
	
	// Movetype
	entity_set_int(grenade, EV_INT_movetype, MOVETYPE_TOSS)
	
	// Owner
	entity_set_edict(grenade, EV_ENT_owner, id)
	
	// Effects
	entity_set_int(grenade, EV_INT_effects, EF_BRIGHTLIGHT)
	
	// Velocity
	VelocityByAim(id, 1500, fVelocity)
	
	
	entity_set_vector(grenade, EV_VEC_velocity, fVelocity)
	
	// Launch sound
	emit_sound(grenade, CHAN_WEAPON, GRENADE_SHOOT, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
	
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_BEAMFOLLOW) // Temporary entity ID
	write_short(grenade) // Entity
	write_short(sTrail) // Sprite index
	write_byte(3) // Life
	write_byte(1) // Line width
	write_byte(255) // Red
	write_byte(255) // Green
	write_byte(255) // Blue
	write_byte(255) // Alpha
	message_end() 
	return PLUGIN_CONTINUE
}	

public reloadsnd(id){
	emit_sound(id, CHAN_WEAPON, GRENADE_CLIPOUT, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
}
public reloadin(id){
	emit_sound(id, CHAN_WEAPON, GRENADE_CLIPIN, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
}
public reloadon(id){
	emit_sound(id, CHAN_WEAPON, GRENADE_CLIPON, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
}

// We hit something!!!
public pfn_touch(ptr, ptd)
{
	// If ent is valid
	if (pev_valid(ptr))
	{	
		// Get classnames
		static classname[32], classnameptd[32]
		pev(ptr, pev_classname, classname, 31)
		
		
		// Our ent
		if(equal(classname, "m79_grenade"))
		{
			// Get it's origin
			new Float:originF[3]
			pev(ptr, pev_origin, originF)

			// Draw explosion
			message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
			write_byte(TE_EXPLOSION) // Temporary entity ID
			engfunc(EngFunc_WriteCoord, originF[0]) // engfunc because float
			engfunc(EngFunc_WriteCoord, originF[1])
			engfunc(EngFunc_WriteCoord, originF[2])
			write_short(sExplo) // Sprite index
			write_byte(50) // Scale
			write_byte(15) // Framerate
			write_byte(0) // Flags
			message_end()
			
			// Draw smoke
			message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
			write_byte(TE_SMOKE) // Temporary entity IF
			engfunc(EngFunc_WriteCoord, originF[0]) // Pos X
			engfunc(EngFunc_WriteCoord, originF[1]) // Pos Y
			engfunc(EngFunc_WriteCoord, originF[2]) // Pos Z
			write_short(sSmoke) // Sprite index
			write_byte(75) // Scale
			write_byte(15) // Framerate
			message_end()
			
			// Get owner
			new owner = pev(ptr, pev_owner)
			
			new Max_Damage = get_pcvar_num(cvar_granade_max_damage)
			new Damage_Radius = get_pcvar_num(cvar_granade_damage_radius)
			
			// Loop through all players
			for(new i = 1; i < get_maxplayers(); i++)
			{
				// Alive...
				if (is_user_alive(i) == 1 && is_user_connected(owner))
				{
					
					// A zombie/nemesis
					if (zp_get_user_zombie(i) || zp_get_user_nemesis(i))
					{
						// Get victims origin and distance
						new VictimOrigin[3], Distance , origin[3]
						get_user_origin(i, VictimOrigin)
						// Get distance between victim and epicenter
	
						origin[0] = floatround(originF[0])
						origin[1] = floatround(originF[1])
						origin[2] = floatround(originF[2])
						
						Distance = get_distance(VictimOrigin, origin)
						
						if (Distance <= Damage_Radius)
						{
							// Start screen shake
							message_begin(MSG_ONE, g_msgScreenShake, {0,0,0}, i)
							write_short(1<<14) // Amount
							write_short(1<<14) // Duration
							write_short(1<<14) // Frequency
							message_end()
							new Damage
							Damage = Max_Damage - floatround(floatmul(float(Max_Damage), floatdiv(float(Distance), float(Damage_Radius))))
							make_knockback(i, originF, 1.5*float(Damage))	
							do_victim(i,owner,Damage)					
						}
					}
				}
				// Destroy ent
				set_pev(ptr, pev_flags, FL_KILLME)
			}
			// We hit breakable
			if(pev_valid(ptd)){
				pev(ptd, pev_classname, classnameptd, 31)
				if (equali(classnameptd, "func_breakable"))
				{
					// Destroy it
					force_use(ptr,ptd)
				}
		}	}
	}	
	if(is_valid_ent(ptr)) {
		new classname[32]
		entity_get_string(ptr,EV_SZ_classname,classname,31)
		
		if(equal(classname, "m79")) {
			if(is_valid_ent(ptd)) {
				new id = ptd
				if(id > 0 && id < 34) {
					if(allowed_toucher(id))
					{
						// Pick up weapon
						give_weapon(id,entity_get_int(ptr, EV_INT_iuser1))
						remove_entity(ptr)
					}
				}
			}
		}
	}
}	

public do_victim (victim,attacker,Damage) {

	new namek[32],namev[32],authida[35],authidv[35],teama[32],teamv[32]

	get_user_name(victim,namev,31)
	get_user_name(attacker,namek,31)
	get_user_authid(victim,authidv,34)
	get_user_authid(attacker,authida,34)
	get_user_team(victim,teamv,31)
	get_user_team(attacker,teama,31)
	static DamageTake[33]
	if(Damage >= get_user_health(victim)) {

		if(get_cvar_num("mp_logdetail") == 3) {
			
			log_message("^"%s<%d><%s><%s>^" attacked ^"%s<%d><%s><%s>^" with ^"grenade^" (hit ^"chest^") (Damage ^"%d^") (health ^"0^")",
			namek,get_user_userid(attacker),authida,teama,namev,get_user_userid(victim),authidv,teamv,Damage)
		
		}

		set_user_frags(attacker,get_user_frags(attacker) + 1 )
		zp_set_user_ammo_packs(attacker, zp_get_user_ammo_packs(attacker) + 1)
		
		set_msg_block(gmsgDeathMsg,BLOCK_ONCE)
		set_msg_block(gmsgScoreInfo,BLOCK_ONCE)

		ExecuteHamB(Ham_Killed, victim, attacker, 0)
		
		replace_dm(attacker,victim,0)

		log_message("^"%s<%d><%s><%s>^" killed ^"%s<%d><%s><%s>^" with ^"grenade^"",
		namek,get_user_userid(attacker),authida,teama,namev,get_user_userid(victim),authidv,teamv)
		
	}

	else {
		set_user_health(victim,get_user_health(victim) - Damage )

		if(get_cvar_num("mp_logdetail") == 3) {
			
			log_message("^"%s<%d><%s><%s>^" attacked ^"%s<%d><%s><%s>^" with ^"missile^" (hit ^"chest^") (Damage ^"%d^") (health ^"%d^")",
			namek,get_user_userid(attacker),authida,teama,namev,get_user_userid(victim),authidv,teamv,Damage,get_user_health(victim))
		
		}

	}
	if(DamageTake[attacker] >= 5000){
		zp_set_user_ammo_packs(attacker, zp_get_user_ammo_packs(attacker)+1)
		DamageTake[attacker] -= 5000
	} else DamageTake[attacker] += Damage
	
}

public replace_dm (id,tid,tbody) {

	//Update killers scorboard with new info
	message_begin(MSG_ALL,gmsgScoreInfo)
	write_byte(id)
	write_short(get_user_frags(id))
	write_short(get_user_deaths(id))
	write_short(0)
	write_short(get_user_team(id))
	message_end()

	//Update victims scoreboard with correct info
	message_begin(MSG_ALL,gmsgScoreInfo)
	write_byte(tid)
	write_short(get_user_frags(tid))
	write_short(get_user_deaths(tid))
	write_short(0)
	write_short(get_user_team(tid))
	message_end()

	//Headshot Kill
	if (tbody == 1) {

		message_begin( MSG_ALL, gmsgDeathMsg,{0,0,0},0)
		write_byte(id)
		write_byte(tid)
		write_string("grenade")
		message_end()
		
	}

	//Normal Kill
	else {
		
		message_begin( MSG_ALL, gmsgDeathMsg,{0,0,0},0)
		write_byte(id)
		write_byte(tid)
		write_byte(0)
		write_string("grenade")
		message_end()
		
	}

	return PLUGIN_CONTINUE
	
}
	
stock make_knockback(victim, Float:origin[3], Float:maxspeed)
{
	// Get and set velocity
	new Float:fVelocity[3];
	kickback(victim, origin, maxspeed, fVelocity)
	entity_set_vector(victim, EV_VEC_velocity, fVelocity);

	return (1);
}

// Extra calulation for knockback
stock kickback(ent, Float:fOrigin[3], Float:fSpeed, Float:fVelocity[3])
{
	// Find origin
	new Float:fEntOrigin[3];
	entity_get_vector( ent, EV_VEC_origin, fEntOrigin );

	// Do some calculations
	new Float:fDistance[3];
	fDistance[0] = fEntOrigin[0] - fOrigin[0];
	fDistance[1] = fEntOrigin[1] - fOrigin[1];
	fDistance[2] = fEntOrigin[2] - fOrigin[2];
	new Float:fTime = (vector_distance( fEntOrigin,fOrigin ) / fSpeed);
	fVelocity[0] = fDistance[0] / fTime;
	fVelocity[1] = fDistance[1] / fTime;
	fVelocity[2] = fDistance[2] / fTime;

	return (fVelocity[0] && fVelocity[1] && fVelocity[2]);
}	
	
// HUD init	
public hud_init(taskid)
{
	new HudAmmo[65]
	
	format(HudAmmo, 64, "Grenades Left: [%d]", grenade_count[ID_HUDAMMO])
	
	message_begin(MSG_ONE, g_msgStatusText, {0,0,0}, ID_HUDAMMO)
	write_byte(0)
	write_string(HudAmmo) // Text
	message_end()
	
}
public hud_clear(id)
{
	message_begin(MSG_ONE, g_msgStatusText, {0,0,0}, id)
	write_byte(0)
	write_string("") // Text
	message_end()
}
//get weapon id
stock get_weapon_ent(id,wpnid=0,wpnName[]="")
{
	// who knows what wpnName will be
	static newName[24];

	// need to find the name
	if(wpnid) get_weaponname(wpnid,newName,23);

	// go with what we were told
	else formatex(newName,23,"%s",wpnName);

	// prefix it if we need to
	if(!equal(newName,"weapon_",7))
		format(newName,23,"weapon_%s",newName);

	return fm_find_ent_by_owner(get_maxplayers(),newName,id);
} 

// Allowed toucher
stock allowed_toucher(player)
{
	// Zombie/Nemesis/Already has it
	if (zp_get_user_zombie(player) || zp_get_user_nemesis(player) || g_hasM79[player] || zp_get_user_survivor(player))
		return false
	
	return true
}

// Blood and bodyparts
stock create_blood(const Float:origin[3])
{
	// Head
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_MODEL)
	engfunc(EngFunc_WriteCoord, origin[0])
	engfunc(EngFunc_WriteCoord, origin[1])
	engfunc(EngFunc_WriteCoord, origin[2])
	write_coord(random_num(-100,100))
	write_coord(random_num(-100,100))
	write_coord(random_num(100,200))
	write_angle(random_num(0,360))
	write_short(mdl_gib_head) // Sprite index
	write_byte(0) // bounce
	write_byte(500) // life
	message_end()
	
	// Spine
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_MODEL)
	engfunc(EngFunc_WriteCoord, origin[0])
	engfunc(EngFunc_WriteCoord, origin[1])
	engfunc(EngFunc_WriteCoord, origin[2])
	write_coord(random_num(-100,100))
	write_coord(random_num(-100,100))
	write_coord(random_num(100,200))
	write_angle(random_num(0,360))
	write_short(mdl_gib_spine)
	write_byte(0) // bounce
	write_byte(500) // life
	message_end()
	
	// Lung
	for(new i = 0; i < random_num(1,2); i++) 
	{
		message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
		write_byte(TE_MODEL)
		engfunc(EngFunc_WriteCoord, origin[0])
		engfunc(EngFunc_WriteCoord, origin[1])
		engfunc(EngFunc_WriteCoord, origin[2])
		write_coord(random_num(-100,100))
		write_coord(random_num(-100,100))
		write_coord(random_num(100,200))
		write_angle(random_num(0,360))
		write_short(mdl_gib_lung)
		write_byte(0) // bounce
		write_byte(500) // life
		message_end()
	}
	
	// Parts, 10 times
	for(new i = 0; i < 10; i++) 
	{
		message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
		write_byte(TE_MODEL)
		engfunc(EngFunc_WriteCoord, origin[0])
		engfunc(EngFunc_WriteCoord, origin[1])
		engfunc(EngFunc_WriteCoord, origin[2])
		write_coord(random_num(-100,100))
		write_coord(random_num(-100,100))
		write_coord(random_num(100,200))
		write_angle(random_num(0,360))
		write_short(mdl_gib_flesh)
		write_byte(0) // bounce
		write_byte(500) // life
		message_end()
	}
	
	// Blood
	for(new i = 0; i < 3; i++) 
	{
		new x,y,z
		x = random_num(-100,100)
		y = random_num(-100,100)
		z = random_num(0,100)
		for(new j = 0; j < 3; j++)
		{
			message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
			write_byte(TE_BLOODSPRITE)
			engfunc(EngFunc_WriteCoord, origin[0]+(x*j))
			engfunc(EngFunc_WriteCoord, origin[1]+(y*j))
			engfunc(EngFunc_WriteCoord, origin[2]+(z*j))
			write_short(blood_spray)
			write_short(blood_drop)
			write_byte(229) // color index
			write_byte(15) // size
			message_end()
		}
	}
}

stock print(const id, const input[], any:...)
{
    
    new iCount = 1, iPlayers[32]
    
    static szMsg[191]
    vformat(szMsg, charsmax(szMsg), input, 3)
    
    replace_all(szMsg, 190, "^x04", "^4") // green txt
    replace_all(szMsg, 190, "^x01", "^1") // orange txt
    replace_all(szMsg, 190, "^x03", "^3") // team txt
    replace_all(szMsg, 190, "^x00", "^0") // team txt
    
    if(id) iPlayers[0] = id
    else get_players(iPlayers, iCount, "ch")
        
    for (new i = 0; i < iCount; i++)
    {
        if (is_user_connected(iPlayers[i]))
        {
            message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("SayText"), _, iPlayers[i])
            write_byte(iPlayers[i])
            write_string(szMsg)
            message_end()
        }
    }
}  
