#include <amxmodx>
#include <fakemeta_util>
#include <hamsandwich>
#include <ColorChat>
#include <codmod>

enum any:DeathStreaks
{
	DS_NONE,
	DS_PAINKILLER,
	DS_MARTYRDOM,
	DS_COPYCAT,
	DS_LASTSTAND,
	DS_JUICED,
	DS_REVENGE,
	DS_HOLLOWPOINTS,
	DS_DEADMANHAND
}

enum any:PluginModels
{
	P_DETONATOR,
	V_DETONATOR,
	P_HEGRENADE
}

new const gszDeathStreaksNames[DeathStreaks][64] =
{
	"None",
	"Painkiller", "Martyrdom", "Copycat", "Last Stand",
	"Juiced", "Revenge", "Hollow Points", "Dead Man's Hand"
}

new const gszDeathStreaksDesc[DeathStreaks][256] =
{
	"Brak",
	"Dostajesz wiecej zycia przy nastepnym respawnie. (wym. 3 death'ow)", 
	"Zostawiasz odbezpieczony granat przy zgonie. (wym. 4 death'ow)",
	"Mozesz skopiowac ekwipunek swojego zabojcy. (wym. 4 death'ow)",
	"Zamiast ginac, krwawisz i mozesz uzywac swojej broni drugorzednej.\nJezeli wytrzymasz 20s, bedziesz mogl kontynuowac rozgrywke. (wym. 4 death'ow)",
	"Przy respawnie biegasz szybciej przez 7.5s. (wym. 4 death'ow)",
	"Na radarze widzisz gracza ktory ostatnio cie zabil ( trwa do jego smierci/disconnectu ). (wym. 5 death'ow)",
	"Zadajesz 2x wiecej obrazen + int. na jedno zabojstwo. (wym. 5 death'ow)",
	"Zanim zginiesz mozesz zdetonowac ladunek C4 zabijajac graczy blisko ciebie. (wym. 6 death'ow)"
}

new const gszModels[PluginModels][128] =
{
	"models/p_satchel_radio.mdl",
	"models/v_satchel_radio.mdl",
	"models/w_hegrenade.mdl"
}


new giUserDeathStreak[33], giUserDeaths[33], giUserOtherInfo[33], giUserSprite[33];
new Float:gfUserNextThink[33];

new gmsgHostage[2];
new gsprBlast;

public plugin_init() {
	register_plugin("DeathStreaks", "0.1 CoD Edition", "MarWit")
	register_event("DeathMsg", "eventDeathMsg", "a")
	
	__RegisterPluginCommands();

	RegisterHam(Ham_Spawn, "player", "fwSpawnPost", 1);
	RegisterHam(Ham_TakeDamage, "player", "fwTakeDamage");
	
	register_forward(FM_PlayerPostThink, "fwPlayerPostThink");
	register_forward(FM_CmdStart, "fwCmdStart");
	register_forward(FM_AddToFullPack, "fwAddToFullPackPost", 1)
	
	gmsgHostage[0] = get_user_msgid("HostagePos");
	gmsgHostage[1] = get_user_msgid("HostageK");
}

public plugin_precache()
{
	for(new i=0; i<PluginModels; i++)
		engfunc(EngFunc_PrecacheModel, gszModels[i]);
		
	engfunc(EngFunc_PrecacheModel, "sprites/deathstreak.spr");
	engfunc(EngFunc_PrecacheModel, "sprites/zerogxplode.spr");
	
	engfunc(EngFunc_PrecacheSound, "weapons/he_bounce-1.wav")
	engfunc(EngFunc_PrecacheSound, "misc/gasping.wav")
}

public client_connect(id)
{
	giUserDeathStreak[id] = giUserDeaths[id] = DS_NONE;
	giUserOtherInfo[id] = -1;
}

public cmdPluginInfo(id)
{
	new iMenu = menu_create("\yDeathStreaks", "cmdPluginInfoH");
	
	for(new i=1; i<DeathStreaks; i++)
		menu_additem(iMenu, gszDeathStreaksNames[i])
		
	menu_addblank(iMenu)
	menu_additem(iMenu, "Wyjdz")
		
	menu_addtext(iMenu, "^nCoded by \yMarWit ^n\rAll right reversed");
	menu_setprop(iMenu, MPROP_PERPAGE, 0)
	
	menu_display(id, iMenu);
}

public cmdPluginInfoH(id, iMenu, iItem)
{
	if(iItem > 7 || iItem < 1)
		return PLUGIN_HANDLED
	
	ColorChat(id, RED, "[DeathStreaks]^x04 Nazwa:^x01 %s", gszDeathStreaksNames[iItem+1])
	
	if(strfind(gszDeathStreaksDesc[iItem+1], "\n") != -1)
	{
		new szBuffer[2][128]
		split(gszDeathStreaksDesc[iItem+1], szBuffer[0], 127, szBuffer[1], 127, "\n")
		
		ColorChat(id, RED, "[DeathStreaks]^x04 Opis:^x01 %s", szBuffer[0])
		ColorChat(id, RED, "[DeathStreaks]^x04^x01 %s", szBuffer[1])
	} else {	
		ColorChat(id, RED, "[DeathStreaks]^x04 Opis:^x01 %s", gszDeathStreaksDesc[iItem+1])
	}
	
	cmdPluginInfo(id)
	
	return PLUGIN_CONTINUE
}

public eventDeathMsg()
{
	
	new iKiller = read_data(1);
	new iVictim = read_data(2);
	
	if(giUserDeathStreak[iKiller] == DS_DEADMANHAND || giUserDeathStreak[iKiller] == DS_LASTSTAND)
		client_cmd(iKiller, "-duck")	
	else if(giUserDeathStreak[iVictim] == DS_DEADMANHAND || giUserDeathStreak[iVictim] == DS_LASTSTAND)
		client_cmd(iVictim, "-duck")
		
	if(giUserDeathStreak[iVictim] == DS_JUICED)
		cod_set_user_bonus_trim(iVictim, cod_get_user_trim(iVictim, 0, 0) - 250)
	else if(giUserDeathStreak[iKiller] == DS_JUICED)
		cod_set_user_bonus_trim(iKiller, cod_get_user_trim(iKiller, 0, 0) - 250);
	
	giUserDeaths[iKiller] = giUserDeathStreak[iKiller] = DS_NONE;
	giUserOtherInfo[iKiller] = giUserDeathStreak[iVictim] = -1;
	giUserDeaths[iVictim]++;
	
	if(task_exists(iVictim)) remove_task(iVictim);
	
	CheckDeathStreaks(iVictim);
	ApplyDeathStreak(iVictim, iKiller)
	
	return PLUGIN_CONTINUE;
}

public fwSpawnPost(id)
{
	switch(giUserDeathStreak[id])
	{
		case DS_COPYCAT:
		{
			if(giUserOtherInfo[id] == -1)
				return HAM_IGNORED;
				
			fm_give_item2(id, giUserOtherInfo[id]);
		
			giUserDeathStreak[id] = DS_NONE;
			giUserOtherInfo[id] = -1;
		
			engclient_cmd(id, "slot1");
		}
		
		case DS_PAINKILLER:
		{
			new Float:fHealth;
			pev(id, pev_health, fHealth);
		
			fHealth += 100.0;
			set_pev(id, pev_health, fHealth);
		}
		
		case DS_JUICED:
		{
			cod_set_user_bonus_trim(id, cod_get_user_trim(id, 0, 0) + 250);
			set_task(7.5, "_RemoveUseless", id);
		}
		
		case DS_REVENGE: { }
		case DS_HOLLOWPOINTS: { }
		
		default: return HAM_IGNORED;
	}
	
	DisplaySprite(id, "sprites/deathstreak.spr", 0.1, giUserDeathStreak[id], 35, 2.5);
	
	return HAM_IGNORED;
}

public fwTakeDamage(id,  iInflictor, iAttacker, Float:fDamage, iDamageBits)
{
	if(!is_user_alive(id) || !is_user_alive(iAttacker) || id == iAttacker)
		return HAM_IGNORED
	
	if(giUserDeathStreak[iAttacker] == DS_HOLLOWPOINTS)
	{
		SetHamParamFloat(4, (fDamage * 2.0) + (cod_get_user_intelligence(iAttacker) * 0.2))
		DisplaySprite(iAttacker, "sprites/deathstreak.spr", 0.1, giUserDeathStreak[iAttacker], 35, 2.5);
			
		return HAM_HANDLED;
	}
	
	switch(giUserDeathStreak[id])
	{
		case DS_MARTYRDOM:
		{
			if(fDamage < pev(id, pev_health))
				return HAM_IGNORED;
			
			if(task_exists(id)) return HAM_SUPERCEDE;
			
			cod_give_weapon(id, CSW_HEGRENADE);
			engclient_cmd(id, "weapon_hegrenade")
			
			set_pev(id, pev_angles, { 88.0, 0.0, 0.0 });
			set_pev(id, pev_fixangle, 1)
			
			new iGrenade = fm_find_ent_by_owner(-1, "weapon_hegrenade", id) 
			ExecuteHamB(Ham_Weapon_PrimaryAttack, iGrenade);
			
			giUserOtherInfo[id] = iAttacker
			set_task(1.0, "_RemoveUseless", id)
			
			DisplaySprite(id, "sprites/deathstreak.spr", 0.1, giUserDeathStreak[id], 35, 2.5);
			
			return HAM_SUPERCEDE
		}
		
		case DS_LASTSTAND: 
		{
			if(fDamage < pev(id, pev_health) || giUserOtherInfo[id] == 100111 || task_exists(id))
				return HAM_IGNORED;
				
			set_pev(id, pev_health, 65.0);
			
			fm_strip_user_weapons(id);
			cod_give_weapon(id, get_user_team(id) == 1 ? CSW_GLOCK18 : CSW_USP)
			
			giUserOtherInfo[id] = 100111;
			set_task(20.0, "_RemoveUseless", id)
			
			DisplaySprite(id, "sprites/deathstreak.spr", 0.1, giUserDeathStreak[id], 35, 2.5);
			
			return HAM_SUPERCEDE
		}
		
		case DS_DEADMANHAND:
		{
			if(fDamage < pev(id, pev_health) || giUserOtherInfo[id] == 110011 || task_exists(id))
				return HAM_IGNORED
				
			set_pev(id, pev_health, 65.0)
			
			fm_strip_user_weapons(id)
			cod_give_weapon(id, CSW_KNIFE);
			engclient_cmd(id, "weapon_knife");
			
			set_pev(id, pev_weaponmodel2, gszModels[P_DETONATOR])
			set_pev(id, pev_viewmodel2, gszModels[V_DETONATOR])
			
			setWeaponAnim(id, 2);
			
			giUserOtherInfo[id] = 110011;
			set_task(7.5, "_RemoveUseless", id)	
			
			DisplaySprite(id, "sprites/deathstreak.spr", 0.1, giUserDeathStreak[id], 35, 2.5);
			
			return HAM_SUPERCEDE
		}
	}
	
	return HAM_IGNORED;
}

public fwPlayerPostThink(id)
{
	if(!is_user_alive(id) || giUserOtherInfo[id] == -1)
		return FMRES_IGNORED;
	
	if(giUserDeathStreak[id] == DS_REVENGE)
	{
		
		if(get_gametime() <= gfUserNextThink[id])
			return FMRES_IGNORED
		
		if(!is_user_connected(giUserOtherInfo[id]))
		{
			giUserDeathStreak[id] = DS_NONE;
			giUserOtherInfo[id] = -1;
			
			return FMRES_IGNORED
		}
		
		new iOrigin[3];
		get_user_origin(giUserOtherInfo[id], iOrigin);
		
		message_begin(MSG_ONE_UNRELIABLE, gmsgHostage[0], { 0, 0, 0 }, id);
		write_byte(id);
		write_byte(giUserOtherInfo[id]);
		write_coord(iOrigin[0]);
		write_coord(iOrigin[1]);
		write_coord(iOrigin[2]);
		message_end();
		
		message_begin(MSG_ONE_UNRELIABLE, gmsgHostage[1], { 0, 0, 0 }, id);
		write_byte(giUserOtherInfo[id]);
		message_end();
		
		gfUserNextThink[id] = get_gametime() + 0.25;
	}
	
	if((giUserDeathStreak[id] == DS_LASTSTAND && giUserOtherInfo[id] == 100111) || (giUserDeathStreak[id] == DS_DEADMANHAND && giUserOtherInfo[id] == 110011))
	{
		if(pev(id, pev_waterlevel) != 5)
		{
			set_pev(id, pev_waterlevel, 5)
			engfunc(EngFunc_DropToFloor, id)
			
			client_cmd(id, "+duck");
		}
		
		
		if(get_gametime() <= gfUserNextThink[id])
			return FMRES_IGNORED
		
		message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("ScreenFade"), { 0, 0, 0 }, id)
		write_short(2 << 12);
		write_short(1 << 16);
		write_short(1 << 1);
		write_byte(255);
		write_byte(0);
		write_byte(0);
		write_byte(random_num(125, 255));
		message_end();
		
		emit_sound(id, CHAN_VOICE, "misc/gasping.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
		
		gfUserNextThink[id] = get_gametime() + 1.8;
	}
	
	return FMRES_IGNORED;
}

public fwCmdStart(id, uc_handle)
{
	if(!is_user_alive(id))
		return FMRES_IGNORED;
		
	if(giUserDeathStreak[id] != DS_DEADMANHAND || giUserOtherInfo[id] != 110011)
		return FMRES_IGNORED;
		
	new iButton = get_uc(uc_handle, UC_Buttons);
	new iOldButton = pev(id, pev_oldbuttons);
	
	if(iButton & ( IN_ATTACK | IN_ATTACK2 ) && !(iOldButton & ( IN_ATTACK | IN_ATTACK2 ))) _DeadManHandBoom(id)
		
	return FMRES_IGNORED;
}

public fwAddToFullPackPost(iEntState, iE, iEnt, iHost, iHostFlags, iPlayer, chSet)
{
	if(!is_user_connected(iHost) || iEnt != giUserSprite[iHost] || !pev_valid(iEnt))
		return FMRES_IGNORED;
		
	if(pev(iEnt, pev_ltime) <= get_gametime())
	{
		engfunc(EngFunc_RemoveEntity, iEnt)
		giUserSprite[iHost] = -1;
		
		return FMRES_IGNORED
	}
	
	new Float:fOrigin[3], Float:fTemp[3];
	
	pev(iHost, pev_origin, fOrigin);
	pev(iHost, pev_view_ofs, fTemp);
	
	xs_vec_add(fOrigin, fTemp, fOrigin);
	velocity_by_aim(iHost, pev(iEnt, pev_iuser1), fTemp);
	xs_vec_add(fOrigin, fTemp, fOrigin);
	
	fOrigin[2] += 10.0
	
	engfunc(EngFunc_SetOrigin, iEnt, fOrigin);
	set_es(iEntState, ES_Origin, fOrigin);
	
	set_es(iEntState, ES_RenderMode, kRenderNormal);
	set_es(iEntState, ES_RenderAmt, 200.0);
	
	return FMRES_IGNORED
}

public ApplyDeathStreak(id, iKiller)
{
	switch(giUserDeathStreak[id])
	{
		case DS_COPYCAT: 
		{
			new szBuffer[128]
			
			get_user_name(iKiller, szBuffer, 127)
			format(szBuffer, 127, "Czy chcesz skopiowac ekwpipunek gracza %s?", szBuffer)
			
			new iMenu = menu_create(szBuffer, "_CopycatAsk")
			
			num_to_str(iKiller, szBuffer, 127)
			menu_additem(iMenu, "Tak", szBuffer)
			menu_setprop(iMenu, MPROP_EXITNAME, "Nie")
			
			menu_display(id, iMenu)
		}
		
		case DS_REVENGE: giUserOtherInfo[id] = iKiller;
		
		default: return;
	}
}

public CheckDeathStreaks(id)
{
	if(giUserDeaths[id] < 3)
		giUserDeathStreak[id] = DS_NONE;
	
	if(giUserDeaths[id] == 3)
		giUserDeathStreak[id] = DS_PAINKILLER;	
	else if(giUserDeaths[id] == 4)
		giUserDeathStreak[id] = random_num(DS_MARTYRDOM, DS_JUICED);	
	else if(giUserDeaths[id] == 5)
		giUserDeathStreak[id] = random_num(DS_HOLLOWPOINTS, DS_REVENGE);
	else if(giUserDeaths[id] >= 6)
		giUserDeathStreak[id] = DS_DEADMANHAND;
}

public _CopycatAsk(id, iMenu, iItem)
{
	new iAccess, iCallback;
	new szInfo[128], szName[33];
	
	menu_item_getinfo(iMenu, iItem, iAccess, szInfo, 127, szName, 32, iCallback)
	
	if(iItem == MENU_EXIT)
		return PLUGIN_CONTINUE;
	else
		giUserOtherInfo[id] = pev(str_to_num(szInfo), pev_weapons)
		
	return PLUGIN_CONTINUE
}

public _RemoveUseless(id)
{
	switch(giUserDeathStreak[id])
	{
		case DS_MARTYRDOM:
		{
			if(is_user_connected(giUserOtherInfo[id]))
				ExecuteHamB(Ham_Killed, id, giUserOtherInfo[id], 2);
			
			giUserOtherInfo[id] = -1;
			giUserDeathStreak[id] = DS_NONE
		}
		
		case DS_JUICED:
		{
			cod_set_user_bonus_trim(id, cod_get_user_trim(id, 0, 0) - 250);
			
			giUserDeathStreak[id] = DS_NONE
			giUserOtherInfo[id] = -1;
		}
		
		case DS_LASTSTAND:
		{
			set_pev(id, pev_health, 100.0);
			
			giUserDeathStreak[id] = DS_NONE
			giUserOtherInfo[id] = -1;
			
			client_cmd(id, "-duck")
		}
		
		case DS_DEADMANHAND:
		{
			_DeadManHandBoom(id);
			
			giUserDeathStreak[id] = DS_NONE
			giUserOtherInfo[id] = -1;
			
			client_cmd(id, "-duck")
		}
	}
}

public _DeadManHandBoom(id)
{	
	new Float:fOrigin[3];
	pev(id, pev_origin, fOrigin);
		
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
	write_byte(TE_EXPLOSION);
		
	engfunc(EngFunc_WriteCoord, fOrigin[0])
	engfunc(EngFunc_WriteCoord, fOrigin[1])
	engfunc(EngFunc_WriteCoord, fOrigin[2])
		
	write_short(gsprBlast);
	write_byte(32);
	write_byte(20); 
	write_byte(0);
	message_end();
		
	new iEnt = -1;
		
	while((iEnt = engfunc(EngFunc_FindEntityInSphere, iEnt, fOrigin, 350.0)) != 0)
	{
		if(pev_valid(iEnt) && pev(iEnt, pev_flags) & ( FL_CLIENT | FL_FAKECLIENT | FL_MONSTER ) && is_user_alive(iEnt) && get_user_team(iEnt) != get_user_team(id))
			ExecuteHamB(Ham_Killed, iEnt, id, 2)
			
		continue;
	}
		
	user_kill(id);
}

public __RegisterPluginCommands()
{
	register_clcmd("say /deathstreak", "cmdPluginInfo");
	register_clcmd("say_team /deathstreak", "cmdPluginInfo");
	
	register_clcmd("say /dh", "cmdPluginInfo");
	register_clcmd("say_team /dh", "cmdPluginInfo");
}

stock fm_give_item2(id, iWeapons)
{
	for(new i=1; i<30; i++)
	{
		if(i==2) continue;

		if(iWeapons & ( 1 << i )) cod_give_weapon(id, i);
	}
}

stock DisplaySprite(id, const szSprite[], Float:fSize, iFrame, iDistance, Float:fHoldTime)
{
	if(!is_user_connected(id) || pev_valid(giUserSprite[id]))
		return;
		
	giUserSprite[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_sprite"));
	
	engfunc(EngFunc_SetModel, giUserSprite[id], szSprite);
	
	set_pev(giUserSprite[id], pev_solid, SOLID_NOT);
	set_pev(giUserSprite[id], pev_movetype, MOVETYPE_NONE);
	set_pev(giUserSprite[id], pev_ltime, get_gametime() + fHoldTime);
	set_pev(giUserSprite[id], pev_iuser1, iDistance);
	
	set_pev(giUserSprite[id], pev_rendermode, kRenderTransAlpha);
	set_pev(giUserSprite[id], pev_renderamt, 0.0);
	
	set_pev(giUserSprite[id], pev_frame, float(iFrame));
	set_pev(giUserSprite[id], pev_scale, fSize);
	
	set_hudmessage(255, 0, 0, -1.0, 0.35, 0, 0.1, fHoldTime, 0.1, 0.1)
	show_hudmessage(id, "%s", gszDeathStreaksNames[iFrame])	
}

stock setWeaponAnim(id, anim) {
	set_pev(id, pev_weaponanim, anim)
	
	message_begin(MSG_ONE, SVC_WEAPONANIM, {0, 0, 0}, id)
	write_byte(anim)
	write_byte(pev(id, pev_body))
	message_end()
} 