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

#define PLUGIN "[ZP] Flame XM1014"
#define VERSION "1.1"
#define AUTHOR "Javivi"

// Macro
new g_MaxPlayers
#define IsValidUser(%1) (1 <= %1 <= g_MaxPlayers)

// Weapon cost
#define WEAPON_COST 15

// ZP default Burn sounds
new const burn_sounds[ ][ ] =
{
	"zombie_plague/zombie_burn3.wav",   
	"zombie_plague/zombie_burn4.wav",
	"zombie_plague/zombie_burn5.wav",
	"zombie_plague/zombie_burn6.wav",
	"zombie_plague/zombie_burn7.wav" 
}

// Item ID,  Flame Sprite, Smoke sprite
new g_ItemID, sprFlame, sprSmoke

// Some bools
new bool:g_bFlameXM1014[ 33 ]
new bool:g_AlreadyBurn[ 33 ]

// Cvars
new cvar_MaxBurnDMG, cvar_MinBurnDMG, cvar_BurnTime, cvar_Delay, cvar_MinHealth, cvar_OneRound

// Cached Cvars
new cvar_cMaxBurnDMG, cvar_cMinBurnDMG, cvar_cBurnTime, Float:cvar_cDelay, cvar_cMinHealth
new Time[ 33 ]

public plugin_init( )
{
	register_plugin( PLUGIN, VERSION, AUTHOR )
	
	// Get maxplayers
	g_MaxPlayers = get_maxplayers( )
	
	// CVARs
	cvar_MaxBurnDMG = register_cvar( "zp_flamexm_maxdmg", "3" )
	cvar_MinBurnDMG = register_cvar( "zp_flamexm_mindmg", "1" )
	cvar_BurnTime = register_cvar( "zp_flamexm_time", "12" )    // Real Time = Time/2
	cvar_Delay = register_cvar( "zp_flamexm_delay", "4.0" )
	cvar_MinHealth = register_cvar( "zp_flamexm_minhp", "50" )
	cvar_OneRound = register_cvar( "zp_flamexm_oneround", "0" )
	
	// Cache cvars
	register_event( "HLTV", "event_round_start", "a", "1=0", "2=0" )
	
	// Hook drop
	register_clcmd( "drop", "HookDrop" )
	
	// Register the extraitem
	g_ItemID = zp_register_extra_item( "Flame XM1014", WEAPON_COST, ZP_TEAM_HUMAN )
	
	// Ham fwds
	RegisterHam( Ham_Spawn, "player", "fw_PlayerSpawn_Post", 1 )
	RegisterHam( Ham_Killed, "player", "fw_PlayerKilled_Post", 1 )
	RegisterHam( Ham_TakeDamage, "player", "fw_TakeDamage" )
	
	// Gamemonitor info
	register_cvar( "zp_flamexm_version", "v1.1 by Javivi", FCVAR_SERVER|FCVAR_SPONLY )
}

public plugin_precache( )
{
	// Precache flame/smoke sprite
	sprFlame = precache_model( "sprites/flame.spr" )
	sprSmoke = precache_model( "sprites/black_smoke3.spr" )
	
	// Precache Burn sounds
	for( new i = 0; i < sizeof burn_sounds; i++ )
		precache_sound( burn_sounds[ i ] )
}

// Cache CVARs
public event_round_start( )
{
	cvar_cMaxBurnDMG = get_pcvar_num( cvar_MaxBurnDMG )
	cvar_cMinBurnDMG = get_pcvar_num( cvar_MinBurnDMG )
	cvar_cBurnTime = get_pcvar_num( cvar_BurnTime )
	cvar_cDelay = get_pcvar_float( cvar_Delay )
	cvar_cMinHealth = get_pcvar_num( cvar_MinHealth )
}

public client_disconnect( id )
{
	if( g_bFlameXM1014[ id ] )
		g_bFlameXM1014[ id ] = false
		
	// Reset Time Counter
	Time[ id ] = 0
}

public HookDrop( id )
{
	// If some human drop the FlameXM1014
	if(is_user_alive( id ) && get_user_weapon( id ) == CSW_XM1014 && g_bFlameXM1014 [ id ] )
	{
		g_bFlameXM1014[ id ] = false
	}
}
/*========================
* Zombie Plague Forwards *
=========================*/
// When someone buy the extraitem
public zp_extra_item_selected( id, itemid )
{
	if( itemid == g_ItemID )
	{
		if( !zp_has_round_started( ) || g_bFlameXM1014[ id ] )
		{
			client_print(id, print_chat, "You can't buy the FlameXM1014 at this moment!")
			
			#if defined ZP_PLUGIN_HANDLED
			
			zp_set_user_ammo_packs( id, zp_get_user_ammo_packs(id) + WEAPON_COST )	
			
			#else
			
			return ZP_PLUGIN_HANDLED
			
			#endif
		}
		else
		{
			// Give auto-shotgun
			give_item( id, "weapon_xm1014" )
			
			// Give ammo
			give_item( id, "ammo_buckshot" )
			give_item( id, "ammo_buckshot" )
			give_item( id, "ammo_buckshot" )
			give_item( id, "ammo_buckshot" )
			
			// Set FlameXM1014
			g_bFlameXM1014[ id ] = true
		}
	}
	return PLUGIN_HANDLED;
}

// When someone is infected
public zp_user_infected_post( id )
{
	if( g_bFlameXM1014[ id ] ) // If have a FlameXM1014
		g_bFlameXM1014[ id ] = false
}

/*==============
* Ham Forwards *
==============*/
public fw_PlayerSpawn_Post( id )
{
	if( get_pcvar_num( cvar_OneRound ) == 1 && g_bFlameXM1014[ id ] )
	{
		client_print(id, print_chat, "[ZP] FlameXM1014 bullets are over!")
		g_bFlameXM1014[ id ] = false
	}
}
public fw_PlayerKilled_Post( victim, attacker, shouldgib )
{
	if(g_bFlameXM1014[ victim ] ) // If have a FlameXM1014
		g_bFlameXM1014[ victim ] = false
}

public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
{
	if( IsValidUser( attacker ) && victim != attacker && zp_get_user_zombie( victim ) // If attacker is valid and victim is zombie
	&& g_bFlameXM1014[ attacker ] && get_user_weapon( attacker ) == CSW_XM1014 && !g_AlreadyBurn[ victim ] && get_user_health( victim ) > cvar_cMinHealth ) // If attacker have the FlameXM1014 and victim is not burned
	{
		// Burn / ON
		g_AlreadyBurn[ victim ] = true
		
		// Set burn time
		Time[ victim ] = cvar_cBurnTime
		
		// Burn victim
		Burn( victim )
		
		// Emit burn sound		
		emit_sound( victim, CHAN_VOICE, burn_sounds[random_num(0, sizeof burn_sounds - 1)], 1.0, ATTN_NORM, 0, PITCH_NORM )  
	}
}

/*======================================================*/
public Burn( victim )
{
	// Get user origin
	static Origin[ 3 ] ; get_user_origin( victim, Origin )
	
	// If burn time is over or victim are in water
	if( Time[ victim ] <= 0 || get_entity_flags( victim ) & FL_INWATER )
	{	
		// Show Smoke sprite	
		message_begin( MSG_PVS, SVC_TEMPENTITY, Origin )
		write_byte( TE_SMOKE ) // TE id
		write_coord( Origin[0] ) // x
		write_coord( Origin[1] ) // y
		write_coord( Origin[2]-50 ) // z
		write_short( sprSmoke ) // sprite
		write_byte( random_num(15, 20) ) // scale
		write_byte( random_num(10, 20) ) // framerate
		message_end( )
		
		// Delay to allow burn again
		set_task( cvar_cDelay, "Stop", victim )
		
		// Exit
		return
	}
	else
	{		
		if( cvar_cBurnTime / 2 == Time[ victim ] ) // At half-burntime
		{
			// Play another sound
			emit_sound( victim, CHAN_VOICE, burn_sounds[ random_num( 0, charsmax( burn_sounds ) ) ], 1.0, ATTN_NORM, 0, PITCH_NORM )
		}
		
		// Flame sprite	
		message_begin( MSG_PVS, SVC_TEMPENTITY, Origin )
		write_byte( TE_SPRITE ) // TE id
		write_coord( Origin[0]+random_num(-5, 5) ) // x
		write_coord( Origin[1]+random_num(-5, 5) ) // y
		write_coord( Origin[2]+random_num(-10, 10) ) // z
		write_short( sprFlame ) // sprite
		write_byte( random_num(5, 10) ) // scale
		write_byte( 200 ) // brightness
		message_end( )
			
		// Decrease Time
		Time[ victim ]--
		
		// Decrease life (random)
		set_user_health( victim, get_user_health( victim ) - random_num( cvar_cMinBurnDMG, cvar_cMaxBurnDMG ) )
		
		// Stop fire if health <= min health.
		if( get_user_health( victim ) <= cvar_cMinHealth )
		{
			g_AlreadyBurn[ victim ] = false
			return
		}
		
		// Repeat
		set_task( 0.5, "Burn", victim )
	}
}

public Stop( victim )
		g_AlreadyBurn[ victim ] = false // Allow burn again