//////////////////////////////////////////////////////////////////////////////////
//
//	DoD Kill Info
//		- Version 0.1
//		- 08.10.2006
//		- diamond-optic
//
//////////////////////////////////////////////////////////////////////////////////
//
// Credits:
//
//	- Zor for the base from 'DoD Smoke Grenade' v0.7a
//	- spq for help with blocking the suicide log message
//
// Information:
//
//	- Based off my modified version of Zor's 'DoD Smoke Grenade' version 0.7a
//	- Basically what you do now is throw rocks around lol..
//	- Hitting another player with the rock does damage (enemy only unless FF is on)
//	- Rock will make a footstep sound when it lands.. Confuse the enemy on your location..
//	- When a player is killed by a rock, a hl log message is created for the rock kill
//	- 2 different size rocks with slightly different attributes
//
// CVARs:
//
//	dod_throwrocks "1"		//Turn ON(1)/OFF(0)
//	dod_throwrocks_dmg "10"		//Damage done when a rock hits a player
//	dod_throwrocks_delay "10"	//How often you can throw a rock
//	dod_throwrocks_removal "3"	//How long after coming to rest to remove the rock
//	dod_throwrocks_maxlife "15"	//Max life of rock (incase it doesnt come to rest)
//
// Commands:
//
//	throw_rock (in console or bind to key)
//
// Known Problems:
//
//	- When you kill someone with a rock it still prints in the console that it
//	  was a 'world' kill. But it does send it to the logs as a 'rock'.. But due
//	  to the fact that I have lost the ability to update my servers' psychostats,
//	  I have not been able to test whether it will get picked up as a new weapon..
//
//	- Sometimes the rock will get stuck in a spot where it doesnt totally come to
//	  rest, you'll see it just spinning around & hear it making the noise over and
//	  over again.. For this problem I added the 'dod_throwrocks_maxlife' cvar so
//	  that if for some reason the rock hasnt been removed by the normal process,
//	  it will be removed when the maxlife time has been reached..
//
// Changelog:
//
//	- 08.10.2006 Version 0.1
//		Initial release
//		
//
///////////////////////////////////////////////////////////////////////////////////////

#include <amxmodx>
#include <fakemeta>
#include <dodfun>

///////////////////////////////////////////////////////////////////////////////////////
// Globals
//
new bool:g_round_restart = false
new bool:log_block_state = false
new Float:g_finishTime[1024] = { 0.0, ... }
new Float:g_nextThrow[33] = { 0.0, ... }

new fileNames[17][] =
{
	"models/rockgibs.mdl",
	"weapons/grenthrow.wav",
	"player/pl_dirt1.wav",
	"player/pl_dirt2.wav",
	"player/pl_dirt3.wav",
	"player/pl_dirt4.wav",
	"player/damage1.wav",
	"player/damage2.wav",
	"player/damage3.wav",
	"player/damage4.wav",
	"player/damage5.wav",
	"player/damage6.wav",
	"player/damage7.wav",
	"player/damage8.wav",
	"player/damage9.wav",
	"player/damage10.wav",
	"player/damage11.wav"
}

enum
{
	model,
	throw,
	dirt1,
	dirt2,
	dirt3,
	dirt4,
	damage1,
	damage2,
	damage3,
	damage4,
	damage5,
	damage6,
	damage7,
	damage8,
	damage9,
	damage10,
	damage11
}
//
///////////////////////////////////////////////////////////////////////////////////////
// CVAR Pointers
//
new p_dod_throwrocks, p_dod_throwrocks_dmg, p_dod_throwrocks_delay, p_dod_throwrocks_removal, p_dod_throwrocks_maxlife

///////////////////////////////////////////////////////////////////////////////////////
// Initialization
//
public plugin_init()
{
	//Register plugin
	register_plugin("DoD Throw Rocks", "0.1", "AMXX DoD Team")
	
	//Register CVARS
	p_dod_throwrocks = register_cvar("dod_throwrocks", "1")			// on/off
	p_dod_throwrocks_dmg = register_cvar("dod_throwrocks_dmg", "10")		// how much dmg
	p_dod_throwrocks_delay = register_cvar("dod_throwrocks_delay", "3")	// delay between throws
	p_dod_throwrocks_removal = register_cvar("dod_throwrocks_removal", "5")	// delay after coming to rest to remove
	p_dod_throwrocks_maxlife = register_cvar("dod_throwrocks_maxlife", "15")	// max lifetime of rock, incase it gets stuck in a spot where it doesnt come to rest...
	
	//Register Client Commands
	register_clcmd("throw_rock", "throwrock")
		
	//Register Event Hooks	
	register_event("RoundState", "round_message", "a", "1=1", "1=3", "1=4")
	
	//Register Forwards
	register_forward(FM_Think, "think_rock")		//tell rock how long to live
	register_forward(FM_Touch, "touch_rock")		//when rock hits things
	register_forward(FM_AlertMessage, "log_block")		//blocks suicide message on rock death
}

///////////////////////////////////////////////////////////////////////////////////////
// Pre-Cache the models/sprites/sounds
//
public plugin_precache() 
{
	precache_model(fileNames[model])			//model
	precache_sound(fileNames[throw])			//throwing sound
	precache_sound(fileNames[dirt1])			//dirt sound
	precache_sound(fileNames[dirt2])			//dirt sound
	precache_sound(fileNames[dirt3])			//dirt sound
	precache_sound(fileNames[dirt4])			//dirt sound
	precache_sound(fileNames[damage1])			//damage sound
	precache_sound(fileNames[damage2])			//damage sound
	precache_sound(fileNames[damage3])			//damage sound
	precache_sound(fileNames[damage4])			//damage sound
	precache_sound(fileNames[damage5])			//damage sound
	precache_sound(fileNames[damage6])			//damage sound
	precache_sound(fileNames[damage7])			//damage sound
	precache_sound(fileNames[damage8])			//damage sound
	precache_sound(fileNames[damage9])			//damage sound
	precache_sound(fileNames[damage10])			//damage sound
	precache_sound(fileNames[damage11])			//damage sound
}

///////////////////////////////////////////////////////////////////////////////////////
// Throw the rock
//
public throwrock(id) 
{
	if(get_pcvar_num(p_dod_throwrocks) != 1 || is_user_alive(id) != 1 || g_round_restart || get_gametime() < g_nextThrow[id])
		return PLUGIN_HANDLED
		
	new Float:TumbleVector[3]	
	TumbleVector[0] = random_float(500.0,-500.0)
	TumbleVector[1] = random_float(600.0,-600.0)
	TumbleVector[2] = random_float(350.0,-350.0)
	
	// create the rock
	new rockid = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
	
	if(!rockid)
		return PLUGIN_HANDLED
		
	new Float:vAngle[3]
	new Float:punchAngle[3]
	new Float:throwAngle[3]

	pev(id, pev_v_angle, vAngle)
	pev(id, pev_punchangle, punchAngle)
	throwAngle[0] = vAngle[0] + punchAngle[0] * 5

	if(throwAngle[0] < 0) 
		throwAngle[0] = -10 + throwAngle[0] * ((90 - 10) / 90.0)

	else
		throwAngle[0] = -10 + throwAngle[0] * ((90 + 10) / 90.0)

	new Float:flVel = (90 - throwAngle[0]) * 5

	// limit out velocity to a maximum of 800
	if(flVel > 800.0)	
		flVel = 800.0

	// show throw animation
	set_pev(id, pev_gaitsequence, 82)
	
	new Float:PlayerOrigin[3]
	new Float:velocity[3]

	// throw angle and velocity
	velocity_by_aim(id, floatround(flVel), velocity)
	
	// Make the throw sound
	emit_sound(id, CHAN_WEAPON, fileNames[throw], 0.9, ATTN_NORM, 0, PITCH_NORM)

	// get the player origin
	pev(id, pev_origin, PlayerOrigin)
	PlayerOrigin[2] += 32
	
	new Float:angles[3]
	pev(id, pev_v_angle, angles)
	new Float:forward_angles[3]
	angle_vector(angles, ANGLEVECTOR_FORWARD, forward_angles)

	PlayerOrigin[0] += (forward_angles[0] * 10)
	PlayerOrigin[1] += (forward_angles[1] * 10)
	PlayerOrigin[2] += (forward_angles[2] * 10)
	
	set_pev(rockid, pev_classname, "dod_rock")	
	set_pev(rockid, pev_origin, PlayerOrigin)
	engfunc(EngFunc_SetModel, rockid, fileNames[model])
		
	set_pev(rockid, pev_movetype, MOVETYPE_BOUNCE)		
	set_pev(rockid, pev_solid, SOLID_BBOX)	
	set_pev(rockid, pev_velocity, velocity)	
	set_pev(rockid, pev_avelocity, TumbleVector)	
	set_pev(rockid, pev_owner, id)	
	
	if(random_num(1,5) == 1)
		{
		set_pev(rockid, pev_body, 0)
		set_pev(rockid, pev_friction, random_float(0.70,0.75))	
		set_pev(rockid, pev_gravity, random_float(0.60,0.65))
		}
	else
		{
		set_pev(rockid, pev_body, 1)
		set_pev(rockid, pev_friction, random_float(0.65,0.70))	
		set_pev(rockid, pev_gravity, random_float(0.55,0.60))
		}
	
	// Next time to think
	set_pev(rockid, pev_nextthink, get_gametime() + 1.0)
	
	g_finishTime[rockid] = (get_gametime() + get_pcvar_num(p_dod_throwrocks_maxlife))
	g_nextThrow[id] = (get_gametime() + get_pcvar_num(p_dod_throwrocks_delay))
		
	return PLUGIN_HANDLED
}

///////////////////////////////////////////////////////////////////////////////////////
// Have the rock think
//
public think_rock(rockid) 
{	
   if(!pev_valid(rockid))
	return PLUGIN_CONTINUE

   new classname[32]
   pev(rockid,pev_classname, classname, 31)
	
   if(equali(classname,"dod_rock"))
	{
	if(rockid == 0 || g_round_restart)
		return PLUGIN_CONTINUE
			
	if(get_gametime() < g_finishTime[rockid])
		{
		if(pev(rockid, pev_flags) & FL_ONGROUND)
			{
			set_pev(rockid, pev_nextthink, get_gametime() + get_pcvar_num(p_dod_throwrocks_removal))
			g_finishTime[rockid] = get_gametime() + get_pcvar_num(p_dod_throwrocks_removal)
			}
		else
			set_pev(rockid, pev_nextthink, get_gametime() + 1.0)
			
		}
	else
		set_pev(rockid, pev_flags, pev(rockid, pev_flags) | FL_KILLME)

	}
   return PLUGIN_CONTINUE 
}

///////////////////////////////////////////////////////////////////////////////////////
// Check if the rock has hit a wall or ground
//
public touch_rock(rockid, object)
{
   if(!get_pcvar_num(p_dod_throwrocks) || !pev_valid(rockid)) // || !pev_valid(object))
	return PLUGIN_CONTINUE

   new classname[32]
   pev(rockid,pev_classname, classname, 31)
	
   if(equali(classname,"dod_rock"))
	{		
	new obj_classname[32]
	pev(object,pev_classname, obj_classname, 31)
		
	// add friction
	if(!equali(obj_classname,"player"))
		{
		// get the current vector
		new Float:NewVector[3]
		pev(rockid, pev_velocity, NewVector)
			
		// add a bit of static friction (slows it down)
		NewVector[0] *= random_float(0.6,0.8)	//0.7
		NewVector[1] *= random_float(0.6,0.8)	//0.7
		NewVector[2] *= random_float(0.6,0.8)	//0.7	
			
		set_pev(rockid, pev_velocity, NewVector)
				
		switch(random_num(1, 4))
			{
			case 1:	emit_sound(rockid, CHAN_BODY, fileNames[dirt1], 1.0, ATTN_NORM, 0, PITCH_NORM)
			case 2:	emit_sound(rockid, CHAN_BODY, fileNames[dirt2], 1.0, ATTN_NORM, 0, PITCH_NORM)
			case 3:	emit_sound(rockid, CHAN_BODY, fileNames[dirt3], 1.0, ATTN_NORM, 0, PITCH_NORM)
			case 4:	emit_sound(rockid, CHAN_BODY, fileNames[dirt4], 1.0, ATTN_NORM, 0, PITCH_NORM)
			}
		}
	else if(is_user_connected(object) && is_user_alive(object))
		{		
		new owner = pev(rockid, pev_owner)
		set_pev(rockid, pev_owner, object)
			
		new team = get_user_team(owner)
		new other_team = get_user_team(object)

		if(pev(object, pev_health) <= get_pcvar_num(p_dod_throwrocks_dmg) && (team != other_team || (team == other_team && get_cvar_num("mp_friendlyfire") == 1)))
			{
			switch(random_num(1, 11))
				{
				case 1:	emit_sound(object, CHAN_VOICE, fileNames[damage1], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 2:	emit_sound(object, CHAN_VOICE, fileNames[damage2], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 3:	emit_sound(object, CHAN_VOICE, fileNames[damage3], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 4:	emit_sound(object, CHAN_VOICE, fileNames[damage4], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 5:	emit_sound(object, CHAN_VOICE, fileNames[damage5], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 6:	emit_sound(object, CHAN_VOICE, fileNames[damage6], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 7:	emit_sound(object, CHAN_VOICE, fileNames[damage7], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 8:	emit_sound(object, CHAN_VOICE, fileNames[damage8], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 9:	emit_sound(object, CHAN_VOICE, fileNames[damage9], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 10: emit_sound(object, CHAN_VOICE, fileNames[damage10], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 11: emit_sound(object, CHAN_VOICE, fileNames[damage11], 1.0, ATTN_NORM, 0, PITCH_NORM)
				}
				
			switch(random_num(1, 4))
				{
				case 1:	emit_sound(rockid, CHAN_BODY, fileNames[dirt1], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 2:	emit_sound(rockid, CHAN_BODY, fileNames[dirt2], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 3:	emit_sound(rockid, CHAN_BODY, fileNames[dirt3], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 4:	emit_sound(rockid, CHAN_BODY, fileNames[dirt4], 1.0, ATTN_NORM, 0, PITCH_NORM)
				}
				
			set_msg_block(get_user_msgid("DeathMsg"),BLOCK_ONCE)
			log_block_state = true
			user_kill(object)
			log_block_state = false
										
			message_begin(MSG_ALL, get_user_msgid("DeathMsg"),{500, 500, 500}, 0)
			write_byte(owner)
			write_byte(object)
			write_byte(0)
			message_end()
			
			new steam[32], teamname[32], name[32]
			new steam2[32], teamname2[32], name2[32]
			get_user_authid(owner, steam, 31)
			get_user_authid(object, steam2, 31)
			dod_get_pl_teamname(owner, teamname, 31)
			dod_get_pl_teamname(object, teamname2, 31)
			get_user_name(owner, name, 31)
			get_user_name(object, name2, 31)
				
			log_message("^"%s<%d><%s><%s>^" killed ^"%s<%d><%s><%s>^" with ^"rock^"", name, get_user_userid(owner), steam, teamname, name2, get_user_userid(object), steam2, teamname2)
		
			dod_set_user_kills(owner, dod_get_user_kills(owner) + 1)
			//dod_set_pl_deaths(object, dod_get_pl_deaths(object) + 1)
			}

		else if(team != other_team || (team == other_team && get_cvar_num("mp_friendlyfire") == 1))
			{					
			set_pev(object, pev_health, float(pev(object, pev_health) - get_pcvar_num(p_dod_throwrocks_dmg)))
						
			switch(random_num(1, 11))
				{
				case 1:	emit_sound(object, CHAN_VOICE, fileNames[damage1], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 2:	emit_sound(object, CHAN_VOICE, fileNames[damage2], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 3:	emit_sound(object, CHAN_VOICE, fileNames[damage3], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 4:	emit_sound(object, CHAN_VOICE, fileNames[damage4], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 5:	emit_sound(object, CHAN_VOICE, fileNames[damage5], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 6:	emit_sound(object, CHAN_VOICE, fileNames[damage6], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 7:	emit_sound(object, CHAN_VOICE, fileNames[damage7], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 8:	emit_sound(object, CHAN_VOICE, fileNames[damage8], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 9:	emit_sound(object, CHAN_VOICE, fileNames[damage9], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 10: emit_sound(object, CHAN_VOICE, fileNames[damage10], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 11: emit_sound(object, CHAN_VOICE, fileNames[damage11], 1.0, ATTN_NORM, 0, PITCH_NORM)
				}
				
			switch(random_num(1, 4))
				{
				case 1:	emit_sound(rockid, CHAN_BODY, fileNames[dirt1], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 2:	emit_sound(rockid, CHAN_BODY, fileNames[dirt2], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 3:	emit_sound(rockid, CHAN_BODY, fileNames[dirt3], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 4:	emit_sound(rockid, CHAN_BODY, fileNames[dirt4], 1.0, ATTN_NORM, 0, PITCH_NORM)
				}
			}
		else
			{
			switch(random_num(1, 4))
				{
				case 1:	emit_sound(rockid, CHAN_BODY, fileNames[dirt1], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 2:	emit_sound(rockid, CHAN_BODY, fileNames[dirt2], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 3:	emit_sound(rockid, CHAN_BODY, fileNames[dirt3], 1.0, ATTN_NORM, 0, PITCH_NORM)
				case 4:	emit_sound(rockid, CHAN_BODY, fileNames[dirt4], 1.0, ATTN_NORM, 0, PITCH_NORM)
				}	
			}
		}
	}
   return PLUGIN_CONTINUE
}

///////////////////////////////////////////////////////////////////////////////////////
// Trap the round message and handle
//
public round_message() 
{
	if(!get_pcvar_num(p_dod_throwrocks))
		return PLUGIN_CONTINUE 
		
	if(read_data(1) == 1)
	{
	    g_round_restart = false
	}
		
	if(read_data(1) == 3 || read_data(1) == 4)
	{
	    g_round_restart = true
	    
	    //check to see if there are any rocks out
	    new rockid = engfunc(EngFunc_FindEntityByString, -1, "classname", "dod_rock")
	    while((rockid = engfunc(EngFunc_FindEntityByString, -1, "classname", "dod_rock")) > 0)
		{    
		set_pev(rockid, pev_flags, pev(rockid, pev_flags) | FL_KILLME)
		}
	}
	return PLUGIN_CONTINUE
}

///////////////////////////////////////////////////////////////////////////////////////
// Block suicide log
//
public log_block(type, msg[])
{
	return(log_block_state?FMRES_SUPERCEDE:FMRES_IGNORED)
}
/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1033\\ f0\\ fs16 \n\\ par }
*/
