#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <fakemeta>
#include <fun>

#define PLUGIN_NAME "Kill Rewards"
#define PLUGIN_VERSION "1.4"

#define CSA_FLASHBANG		11
#define CSA_HEGRENADE		12
#define CSA_SMOKEGRENADE	13

// For ammo refil
new const g_weapons_id[] = { CSW_P228, CSW_SCOUT, CSW_XM1014, CSW_MAC10, CSW_AUG, CSW_ELITE, CSW_FIVESEVEN, CSW_UMP45,
	CSW_SG550, CSW_GALIL, CSW_FAMAS, CSW_USP, CSW_GLOCK18, CSW_AWP, CSW_MP5NAVY, CSW_M249, CSW_M3,
	CSW_M4A1, CSW_TMP, CSW_G3SG1, CSW_DEAGLE, CSW_SG552, CSW_AK47, CSW_P90	}

new const g_weapons_names2[][] = { "weapon_p228", "weapon_scout", "weapon_xm1014", "weapon_mac10", "weapon_aug", "weapon_elite",
	"weapon_fiveseven", "weapon_ump45", "weapon_sg550", "weapon_galil", "weapon_famas", "weapon_usp",
	"weapon_glock18", "weapon_awp", "weapon_mp5navy", "weapon_m249", "weapon_m3", "weapon_m4a1", "weapon_tmp", 
	"weapon_g3sg1", "weapon_deagle", "weapon_sg552", "weapon_ak47", "weapon_p90" }

new const g_weapons_names[][] = { "p228", "scout", "xm1014", "mac10", "aug", "elite", "fiveseven", "ump45", "sg550", 
	"galil", "famas", "usp", "glock18", "awp", "mp5navy", "m249", "m3", "m4a1", "tmp", "g3sg1", "deagle", "sg552", "ak47", "p90" }

new const g_weapons_no_ammo[][] = { "knife", "hegrenade", "c4" }

new const g_max_clip[] = { 13, 10, 7, 30, 30, 30, 20, 25, 30, 35, 25, 12, 20, 10, 30, 100, 8, 30, 30, 20, 7, 30, 30, 50 }

// For cvars
new c_ff_enable, ff_enable;
new c_hp_enable, c_hp_add, c_hphs_add, c_hp_max, hp_enable, hp_add, hp_hsadd, hp_max;
new c_gren_enable, c_maxhe, c_maxflash, c_maxsmokes, c_gren_hs, gren_enable, max_he, max_flash, max_smokes, gren_hs;
new c_cash_enable, c_norm_cash, c_hs_cash, cash_enable, norm_cash, hs_cash;
new c_knife_enable, c_knife_cash,c_knife_hp, knife_enable, knife_cash, knife_hp;
new c_armor_enable, c_arm_type, c_arm_add, c_arm_hsadd, c_arm_max, armor_enable, CsArmorType:arm_type, arm_add, arm_hsadd, arm_max;
new c_refill_enable, c_refill_prc, c_refill_prchs, refill_enable, refill_prc, refill_prchs;

public plugin_init(){
	register_plugin( PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR );
	register_cvar( "kill_rewards", PLUGIN_VERSION, FCVAR_SERVER | FCVAR_SPONLY );
	
	// cvars
	c_ff_enable = register_cvar("amxr_ff_on", "0");
	
	c_hp_enable = register_cvar("amxr_hp_on", "1");
	c_hp_add = register_cvar("amxr_hp", "20");
	c_hphs_add = register_cvar("amxr_hp_hs", "40");
	c_hp_max = register_cvar("amxr_max_hp", "200");
	
	c_gren_enable = register_cvar("amxr_grenade_on", "1");
	c_gren_hs = register_cvar("amxr_only_hs","1");
	c_maxhe = register_cvar("amxr_he_limit","3");
	c_maxflash = register_cvar("amxr_flash_limit","2");
	c_maxsmokes = register_cvar("amxr_smoke_limit","1");
	
	c_cash_enable = register_cvar("amxr_cash_on", "1");
	c_norm_cash = register_cvar("amxr_normal_cash", "25");
	c_hs_cash = register_cvar("amxr_hs_cash", "100");
	
	c_knife_enable = register_cvar("amxr_knife_on", "1");
	c_knife_cash = register_cvar("amxr_knife_cash", "1000");
	c_knife_hp = register_cvar("amxr_knife_hp", "15");
	
	c_armor_enable = register_cvar("amxr_armor_on", "1");
	c_arm_type = register_cvar("amxr_armor_type", "1");
	c_arm_add = register_cvar("amxr_armor", "3");
	c_arm_hsadd = register_cvar("amxr_armor_hs", "5");
	c_arm_max = register_cvar("amxr_armor_max", "150");
	
	c_refill_enable = register_cvar("amxr_refill_on", "1");
	c_refill_prc = register_cvar("amxr_refill_prc", "50");
	c_refill_prchs = register_cvar("amxr_refill_prchs", "90");
	
	// events
	register_event("DeathMsg", "hook_death", "a", "1!2" );
	register_event("HLTV", "update_cvars", "a", "1=0", "2=0");
	
	// messages
	register_message(get_user_msgid("WeaponList"),"weaponlist");
}

public plugin_precache()
	precache_sound("items/9mmclip1.wav");

public plugin_cfg(){
	new cfgdir[32];
	get_configsdir(cfgdir, charsmax(cfgdir));
	server_cmd("exec %s/kill_rewards.cfg", cfgdir);
	server_exec();
	update_cvars();
}

public update_cvars(){
	ff_enable = get_pcvar_num(c_ff_enable);
	
	hp_add = get_pcvar_num(c_hp_add);
	hp_max = get_pcvar_num(c_hp_max);
	hp_hsadd = get_pcvar_num(c_hphs_add);
	hp_enable = get_pcvar_num(c_hp_enable);
	
	max_he = get_pcvar_num(c_maxhe);
	gren_hs = get_pcvar_num(c_gren_hs);
	max_flash = get_pcvar_num(c_maxflash);
	max_smokes = get_pcvar_num(c_maxsmokes);
	gren_enable = get_pcvar_num(c_gren_enable);
	
	hs_cash = get_pcvar_num(c_hs_cash);
	norm_cash = get_pcvar_num(c_norm_cash);
	cash_enable = get_pcvar_num(c_cash_enable);
	
	knife_hp = get_pcvar_num(c_knife_hp);
	knife_cash = get_pcvar_num(c_knife_cash);
	knife_enable = get_pcvar_num(c_knife_enable);
	
	armor_enable = get_pcvar_num(c_armor_enable);
	arm_max = ( get_pcvar_num(c_arm_max) > 255 ) ? 255 : get_pcvar_num(c_arm_max);
	arm_add = get_pcvar_num(c_arm_add);
	arm_type = ( get_pcvar_num(c_arm_type) > 0 ) ? CS_ARMOR_VESTHELM : CS_ARMOR_KEVLAR;
	arm_hsadd = get_pcvar_num(c_arm_hsadd);
	
	refill_enable = get_pcvar_num(c_refill_enable);
	refill_prc = get_pcvar_num(c_refill_prc);
	refill_prchs = get_pcvar_num(c_refill_prchs);
}

public weaponlist(msg_id, msg_dest, msg_entity){
	switch(get_msg_arg_int(8)){
		case CSW_HEGRENADE: set_msg_arg_int(3,1,max_he);
		case CSW_FLASHBANG: set_msg_arg_int(3,1,max_flash);
		case CSW_SMOKEGRENADE: set_msg_arg_int(3,1,max_smokes);
	}
}

public hook_death(){
	new i, weapon[32], g_killer = read_data(1);
	
	if(!is_user_connected(g_killer)) return;
	if(cs_get_user_team(g_killer) == cs_get_user_team(read_data(2)) && !ff_enable) return;
	
	read_data(4, weapon,charsmax(weapon));
	new args[4];	args[0] = g_killer;	args[1] = read_data(3); args[2] = equal(weapon,"knife") ? 1 : 0;
	for(i=0;i<sizeof(g_weapons_no_ammo);i++)
		if(equal(weapon,g_weapons_no_ammo[i])) args[3] =  0;
	
	for(i=0; i<sizeof(g_weapons_names); i++)
		if(equal(weapon,g_weapons_names[i])) args[3] = g_weapons_id[i];
			
	set_task(0.0,"call_rewards",0,args,4);
}

public call_rewards(args[]){
	if(hp_enable) health_bonus(args[0], args[1]);
	if(gren_enable) grenade_bonus(args[0], args[1]);
	if(cash_enable) cash_bonus(args[0], args[1]);
	if(knife_enable && args[2]) knife_bonus(args[0]);
	if(armor_enable) armor_bonus(args[0], args[1]);
	if(refill_enable && args[3]) weapon_refill(args[0], args[1], args[3]);
}

public grenade_bonus(id, mode){
	if(gren_hs && !mode || !is_user_alive(id)) return;
	
	new he_ammo = cs_get_user_bpammo(id, CSW_HEGRENADE);
	new fl_ammo = cs_get_user_bpammo(id, CSW_FLASHBANG);
	new sm_ammo = cs_get_user_bpammo(id, CSW_SMOKEGRENADE);
	
	if( he_ammo < max_he ){
		if(he_ammo > 0){
			gren_pick(id,CSA_HEGRENADE);
			cs_set_user_bpammo(id, CSW_HEGRENADE, he_ammo+1);
			emit_sound(id, CHAN_WEAPON , "items/9mmclip1.wav" , 1.0 , ATTN_NORM , 0 , PITCH_NORM);
		}else	give_item(id, "weapon_hegrenade");
	}
	if( fl_ammo < max_flash ){
		if(fl_ammo > 0){
			gren_pick(id,CSA_FLASHBANG);
			cs_set_user_bpammo(id, CSW_FLASHBANG, fl_ammo+1);
			emit_sound(id, CHAN_WEAPON , "items/9mmclip1.wav" , 1.0 , ATTN_NORM , 0 , PITCH_NORM);
		}else	give_item(id, "weapon_flashbang");
	}
	if( sm_ammo < max_smokes ){
		if(sm_ammo > 0){
			gren_pick(id,CSA_SMOKEGRENADE);
			cs_set_user_bpammo(id, CSW_SMOKEGRENADE, sm_ammo+1);
			emit_sound(id, CHAN_WEAPON , "items/9mmclip1.wav" , 1.0 , ATTN_NORM , 0 , PITCH_NORM);
		}else	give_item(id, "weapon_smokegrenade");
	}
}

public health_bonus(id, mode){
	if(!is_user_alive(id)) return;
	
	new g_hptoadd = (mode > 0) ? hp_hsadd : hp_add;
	new g_killer_hp = get_user_health(id);
	g_killer_hp += g_hptoadd;
	
	if (g_killer_hp > hp_max) g_killer_hp = hp_max;
	if (g_killer_hp % 256 == 0 || g_killer_hp % 255 == 0 ) g_killer_hp++;
	
	set_user_health(id, g_killer_hp);
	
	set_hudmessage(0, 255, 0, -1.0, 0.15, 0, 1.0, 1.0, 0.1, 0.1, -1);
	show_hudmessage(id, "Healed +%d HP", g_hptoadd);
	
	fade_msg(id, 0, 0, 200, 75);
}

public knife_bonus(id){
	cs_set_user_money(id, cs_get_user_money(id) + knife_cash);
	if(is_user_alive(id)){
		set_user_health(id, ( get_user_health(id) + knife_hp ) > hp_max ? hp_max : get_user_health(id) + knife_hp );
		set_hudmessage(0, 255, 0, -1.0, 0.15, 0, 1.0, 1.0, 0.1, 0.1, -1);
		show_hudmessage(id, "Knife kill +%d HP", knife_hp);
		fade_msg(id, 150, 50, 200, 100);
	}
}

public armor_bonus(id, mode){
	if(!is_user_alive(id)) return;
	
	new CsArmorType:ArmorType;
	new g_armor = cs_get_user_armor(id, ArmorType);
	new g_armtoadd = g_armor + ( ( mode > 0 ) ? arm_hsadd : arm_add );
	
	if( g_armtoadd > arm_max ) g_armtoadd = arm_max;
	
	cs_set_user_armor(id, g_armtoadd, (g_armor > 0) ? CsArmorType : arm_type );
}

public cash_bonus(id, mode)
	cs_set_user_money(id, cs_get_user_money(id) + ((mode > 0) ? hs_cash : norm_cash) );

public weapon_refill(id, mode, wpid){
	new weapon = fm_get_weapon_ent(id, wpid);
	
	for(new a=0;a<=sizeof(g_weapons_id);a++){
		if( wpid == g_weapons_id[a] ){
			new newammo, maxammo = get_weapon_maxclip(wpid);
			if(maxammo){
				emit_sound(id, CHAN_WEAPON , "items/9mmclip1.wav" , 1.0 , ATTN_NORM , 0 , PITCH_NORM);
				
				newammo = floatround( maxammo / 100.0 * ( ( mode ) ? refill_prchs : refill_prc ) );
				newammo += cs_get_weapon_ammo(weapon);
				if(newammo > maxammo) newammo = maxammo;
				
				cs_set_weapon_ammo(weapon, newammo);
			}
			return;
		}
	}
}

stock fade_msg(u_id, r, g, b, a){
	message_begin(MSG_ONE, get_user_msgid("ScreenFade"), {0,0,0}, u_id);
	write_short(1<<10);
	write_short(1<<10);
	write_short(0x0000);
	write_byte(r);
	write_byte(g);
	write_byte(b);
	write_byte(a);
	message_end();
}

stock gren_pick(id,ammoid){
	message_begin(MSG_ONE,get_user_msgid("AmmoPickup"),_,id);
	write_byte(ammoid);
	write_byte(1);
	message_end();
}

stock get_weapon_maxclip(wpnid){
	for(new a = 0;a<sizeof(g_weapons_id);a++)
		if (wpnid == g_weapons_id[a])
			return g_max_clip[a];

	return false;
}

fm_get_weapon_ent(id, wpnid = 0){
	for(new a=0;a<=sizeof(g_weapons_id);a++)
		if(wpnid == g_weapons_id[a])
			return fm_find_ent_by_owner(get_maxplayers(), g_weapons_names2[a], id)
	
	return false;
}

fm_find_ent_by_owner(id, const classname[], owner, jghgtype = 0){
	new strtype[16] = "classname";
	new ent = id;

	switch (jghgtype){
		case 1: strtype = "target";
		case 2: strtype = "targetname";
	}

	while ((ent = engfunc(EngFunc_FindEntityByString, ent, strtype, classname)) && pev(ent, pev_owner) != owner){
	}

	return ent;
}
