#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>

#define PLUGIN_NAME "Anti Flashbang Bug"
#define PLUGIN_VERSION "1.0"
#define PLUGIN_AUTHOR "Numb"

new Float:old_gametime;
new mp_friendlyfire;
new owner;

public plugin_init()
{
	register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR);
	
	RegisterHam(Ham_Think, "grenade", "Ham_FEThink_grenade", 0);
	
	register_forward(FM_FindEntityInSphere, "fm_FEFindEntityInSphere", 0);
	
	mp_friendlyfire = get_cvar_pointer("mp_friendlyfire");
}

public Ham_FEThink_grenade(ent)
{
	static model[32];
	pev(ent, pev_model, model, 31);
	if( equal(model, "models/w_flashbang.mdl") )
	{
		if( (owner=pev(ent, pev_owner))<1 )
			owner = 0;
		
		old_gametime = get_gametime();
	}
	else
	{
		owner = 0;
		old_gametime = 0.0;
	}
}

public fm_FEFindEntityInSphere(start, Float:origin[3], Float:radius)
{
	if( radius!=1500.0 || old_gametime!=get_gametime() )
		return FMRES_IGNORED;
	
	static hit, trace, Float:user_origin[3], Float:absmax[3], Float:fraction, ff, owner_team;
	hit = start;
	ff = clamp(get_pcvar_num(mp_friendlyfire), 0, 1);
	if( owner )
		owner_team = get_user_team(owner);
	else
		owner_team = -1;
	
	// run the same check to see what its result will be
	while( (hit=engfunc(EngFunc_FindEntityInSphere, hit, origin, radius))>0 )
	{
		// hit a non- or dead-player
		if( !is_user_alive(hit) )
		{
			forward_return(FMV_CELL, hit);
			return FMRES_SUPERCEDE;
		}
		
		// aim for the body eyes
		pev(hit, pev_origin, user_origin);
		pev(hit, pev_absmax, absmax);
		user_origin[2] = (absmax[2]-20.0);
		engfunc(EngFunc_TraceLine, origin, user_origin, DONT_IGNORE_MONSTERS, 0, trace);
		
		// hit player eyes, grenade ok
		if( get_tr2(trace, TR_pHit)==hit )
		{
			// start backup check (de_dust2 B bug - outmap bug)
			engfunc(EngFunc_TraceLine, user_origin, origin, DONT_IGNORE_MONSTERS, hit, trace);
			
			// hit player eyes with backup check
			get_tr2(trace, TR_flFraction, fraction);
			if( fraction==1.0 )
			{
				if( ff || owner==hit || owner_team!=get_user_team(hit) )
				{
					forward_return(FMV_CELL, hit);
					return FMRES_SUPERCEDE;
				}
			}
		}
	}
	
	// grenade could not hit anyones eyes, cancel the check
	forward_return(FMV_CELL, -1);
	return FMRES_SUPERCEDE;
}
