/*
				[ZP] Extra Server Addon : Hit Reward
				      ( Zombie Plague Edition )
						by Fry!
						
					
	Description :
	
			This plugin rewards people for hitting their enemies by giving them a certain amount of ammo packs.
			
			
	Cvars :
			
			zp_reward_head	"5"		- How much you will get by hitting in head
			zp_reward_chest "0"		- Hitting in chest
			zp_reward_stomach "0"		- Hitting in stomach
			zp_reward_left_arm "0"		- Hitting in left arm
			zp_reward_right_arm "0"		- Hitting in right arm
			zp_reward_left_leg "0"		- Hitting in left leg
			zp_reward_right_leg "0"		- Hitting in right leg
			zp_reward_dmgfactor "0.10"	- Takes damage into account when > 0.0 -- reward will be multiplied this factor and the given damage (use carefully, makes reward grow very fast - 0.10 is maximum I recommend
			zp_reward_max_reward "1000"	- Maximum reward you will get (this might be enough)
			zp_reward_msg_k <1|0>		- Send HUDmsg to killer
			zp_reward_msg_v <1|0>		- Send HUDmsg to victim
			zp_reward_msg <1|0>		- Send HUDmsg only if reward > 0

			
	Credits :
	
			MistaGee - For his Hit Reward plugin
			
	
	Changelog :
	
			03/02/2009 - v1.0 - First release
			04/02/2009 - v1.0.1 - fixed friendly fire
			24/06/2009 - v1.0.4 - fixed debug errors, removed server print msg, optimized code.
*/

#include <amxmodx>
#include <zombieplague>

#define PLUGIN "[ZP] Extra Server Addon : Hit Reward"
#define VERSION "1.0.4"
#define AUTHOR "Fry!"

new g_reward_head, g_reward_chest, g_reward_stomach, g_reward_l_arm, g_reward_r_arm,
g_reward_l_leg, g_reward_r_leg, g_reward_dmg_factor, g_reward_max_reward,
g_reward_msg_k, g_reward_msg_v, g_reward_msg_reward, g_reward_min_distance, g_reward_tadistance

public plugin_init()
{	
	register_plugin(PLUGIN, VERSION, AUTHOR)
	
	register_cvar("zp_extra_server_addon_hit_reward",VERSION,FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_UNLOGGED|FCVAR_SPONLY)
	
	g_reward_head = register_cvar("zp_reward_head", "5")
	g_reward_chest = register_cvar("zp_reward_chest", "0")
	g_reward_stomach = register_cvar("zp_reward_stomach", "0")
	g_reward_l_arm = register_cvar("zp_reward_left_arm", "0")
	g_reward_r_arm = register_cvar("zp_reward_right_arm", "0")
	g_reward_l_leg = register_cvar("zp_reward_left_leg", "0")
	g_reward_r_leg = register_cvar("zp_reward_right_leg", "0")
	g_reward_dmg_factor = register_cvar("zp_reward_dmgfactor", "0.10")
	g_reward_max_reward = register_cvar("zp_reward_max_reward", "1000")
	g_reward_msg_k = register_cvar("zp_reward_msg_k", "1")
	g_reward_msg_v = register_cvar("zp_reward_msg_v", "1")
	g_reward_msg_reward = register_cvar("zp_reward_msg", "1")
	g_reward_min_distance = register_cvar("zp_reward_min_distance", "750")
	g_reward_tadistance = register_cvar("zp_reward_ta_distance", "-1")
	
	register_event("Damage", "event_damage", "b", "2!0"/*, "3=0", "4!0"*/) // 2!0 -> Damage not zero, 3=0 -> ???, 4!0 -> xpos of player not zero
	
	register_dictionary("zp_extra_server_addon_hit_reward.txt")
}

public event_damage(vID)
{
	/*/ Read and print all given data
	for(new j = 0; j < read_datanum(); j++)
	{
		new data[32]
		read_data(j, data, 31);
		server_print("[AMXX-HRWD] [event_damage] Data field %d == %s", j, data);
	}
	*/
	
	// get attacker's ID & aiming
	new wID = 0, body = 0, kID = get_user_attacker(vID, wID, body)
	
	calc_reward(kID, vID, wID, body)
	
	return PLUGIN_CONTINUE
}

void:calc_reward(kID, vID, wID, body)
{
	if (!is_user_alive(kID))
		return
		
	// This function gives rewards to the given killer ID for hitting parts of the body.
	// I exported this to another function because I intended to make the script react on DeathMsg as well but encountered probs... maybe of use in later versions though
	
	// No body or no killer passed or killer attacked himself (eg by falling down somewhere) or script disabled -> cancel
	if (!body || !kID || (kID == vID)) 
		return
	
	// Init a few vars... ( I like doing many things in a single line :p )
	new bool:hits[7] = false, bool:ta = false, absreward = 0, reward = 0, kName[32] = 0, vName[32] = 0, Float:dmgfact = get_pcvar_float(g_reward_dmg_factor), damage = read_data(2), maxreward = get_pcvar_num(g_reward_max_reward)
	
	// Get killer's & victim's name
	get_user_name(kID, kName, 31)
	get_user_name(vID, vName, 31)

	/* Parts of body are in array: 
	 *	head 			0
	 *	chest 			1
	 *	stomach 		2
	 *	left arm 		3
	 *	right arm 		4
	 *	left leg 		5
	 *	right leg 		6
	 */
	
	ta = (get_user_team(vID) != get_user_team(kID)) // either true (TA) or false (no TA)!
	
	new mindist = get_pcvar_num(g_reward_min_distance), maxtadist = get_pcvar_num(g_reward_tadistance), kOrigin[3] = 0, vOrigin[3] = 0
	
	get_user_origin(kID, kOrigin, 0)
	get_user_origin(vID, vOrigin, 0)
	
	new curdist = get_distance(kOrigin, vOrigin)
	// Make maxtadist usable if < 0
	
	if (maxtadist < 0) 
		maxtadist = mindist
	
	if ((!ta && mindist && (curdist < mindist) ) || (ta && maxtadist && (curdist > maxtadist) ))
		return
	
	// body (mass ^^ ) index must be put into an array of bool which tells us exactly where the player was hit
	// falsify array completely (should be obsolete after initialization, but I want to be sure), then set the certain "slot" to true
	for (new i = 0; i <= 6; i++) 
		hits[i] = false
	
	hits[body - 1] = true
	
	// Get basic reward value from CVars
	// Heady
	if(hits[0])	reward = get_pcvar_num(g_reward_head)
	// Chest
	if(hits[1])	reward = get_pcvar_num(g_reward_chest)
	// Stomach
	if(hits[2])	reward = get_pcvar_num(g_reward_stomach)
	// Arm left
	if(hits[3])	reward = get_pcvar_num(g_reward_l_arm)
	// Arm right
	if(hits[4])	reward = get_pcvar_num(g_reward_r_arm)
	// Leg left
	if(hits[5])	reward = get_pcvar_num(g_reward_l_leg)
	// Leg right
	if(hits[6])	reward = get_pcvar_num(g_reward_r_leg)
	
	// If damage shall be taken into account, multiply the given dmg with the factor and multiply this value with the reward
	// e.g. If you want to multiply the reward with half of the given damage, set the factor to 0.5
	if (dmgfact > 0) reward *= floatround(floatmul(dmgfact, float(damage)))
	
	// Save the absolute value of reward to make sure a msg is displayed if a user gets money taken away (reward < 0)
	absreward = reward
		
	// Check if maximum reward is set and make sure reward is not greater
	if ((maxreward > 0) && (reward > maxreward)) 
		reward = maxreward
		
	// If there be TA you still will get reward
	if (ta)
		reward *= 1
		
	// Give the killer his money
	zp_set_user_ammo_packs(kID, (zp_get_user_ammo_packs(kID) + reward))

	// Format HUD message
	set_hudmessage(255, 0, 0, 0.05, 0.35, 0, 1.0, 5.0, 0.1, 0.1, 3)
	
	// Get strings for "this was ... tk" and "hit you in your ..."
	new pref_ta[11], bodypart[21], wName[21]

	// Send to killer if enabled and rwd > 0 or rwd not necessary
	if (get_pcvar_num(g_reward_msg_k) && (!get_pcvar_num(g_reward_msg_reward) || (absreward > 0)))
	{ 	// Compare absolute value of reward to also dsp a msg if user gets money taken away
		format(bodypart, 20, "%L", kID, (hits[0]?"HEAD": (hits[1]?"CHEST": (hits[2]?"STOMACH": (hits[3]?"ARM_L": (hits[4]?"ARM_R": (hits[5]?"LEG_L": (hits[6]?"LEG_R": "PENIS" ) ) ) ) ) ) ) ) // Penis is only sent if nothing else was found, so hopefully NEVER EVER !!!
		format(pref_ta, 10, "%L", kID, (ta?"ATA":"NTA"))
		show_hudmessage(kID, "%L", kID, "KMSG", vName, bodypart, damage, pref_ta, reward)
	}
	
	// Send to victim if enabled and rwd > 0 or rwd not necessary
	if (get_pcvar_num(g_reward_msg_v) && (!get_pcvar_num(g_reward_msg_reward) || (absreward > 0)))
	{ 	// Compare absolute value of reward to also dsp a msg if user gets money taken away
		get_weaponname(wID, wName, 20);	// Show the victim which weapon his attacker uses - weapon_ must be stripped, so start dsp'ing from char #7
		format(bodypart, 20, "%L", vID, (hits[0]?"HEAD": (hits[1]?"CHEST": (hits[2]?"STOMACH": (hits[3]?"ARM_L": (hits[4]?"ARM_R": (hits[5]?"LEG_L": (hits[6]?"LEG_R": "PENIS" ) ) ) ) ) ) ) )
		format(pref_ta, 10, "%L", vID, (ta?"ATA":"NTA"))
		show_hudmessage(vID, "%L", vID, "VMSG", kName, bodypart, wName[7], damage, pref_ta, reward)
	}
	return
}
