#include <amxmodx>
#include <fakemeta>
#include <engine>
new bWouldTakeDMG[33];
new JumpTiming[33][2];
new DuckTiming[33][2];
new averagefpsnum[33];
new Float:flHadChance[33];
new Float:averagefps[33];
new Float:FPSToAverage[33][32];
new Float:DistToAvg[33][32];
new Float:UserFPS[33];
new Float:AVGFPS[33][2];
public plugin_init()
{
register_plugin( "JumpBug Hack Detector", "1.0", "Ranarrr" );
register_forward( FM_CmdStart, "Player_CmdStart" );
register_forward( FM_PlayerPreThink, "Player_PreThink" );
register_forward( FM_PlayerPostThink, "Player_PostThink" );
}
public Player_PreThink( id )
{
if( !is_user_alive( id ) || is_user_bot( id ) )
return FMRES_IGNORED;
static buttons, oldbuttons[33];
buttons = pev( id, pev_button );
static Float:flClientOldSpeed[33];
new Float:flSpeed[3];
pev( id, pev_velocity, flSpeed );
if( DuckTiming[id][0] != 1 )
{
if( oldbuttons[id] & IN_DUCK && !( buttons & IN_DUCK ) )
{
DuckTiming[id][1] = -1;
DuckTiming[id][0] = 1;
}
}
if( DuckTiming[id][0] )
++DuckTiming[id][1];
if( buttons & IN_DUCK )
DuckTiming[id][0] = -1;
if( JumpTiming[id][0] != 1 )
{
if( !( oldbuttons[id] & IN_JUMP ) && buttons & IN_JUMP )
{
JumpTiming[id][1] = -1;
JumpTiming[id][0] = 1;
}
}
if( JumpTiming[id][0] )
++JumpTiming[id][1];
if( !( buttons & IN_JUMP ) )
JumpTiming[id][0] = -1;
if( flSpeed[2] <= -500.0 )
{
bWouldTakeDMG[id] = true;
if( pev( id, pev_flags ) & FL_DUCKING )
{
static Float:flOrigin[3], Float:flOrigin2[3], Float:flUserOrigin[3];
pev( id, pev_origin, flOrigin );
flUserOrigin = flOrigin;
flHadChance[0] = ( 36.0 - 2.0 + 0.03125 ); //36.03125;
flOrigin2 = flOrigin;
flOrigin2[2] -= ( flHadChance[0] * 2.0 );
engfunc( EngFunc_TraceLine, flOrigin, flOrigin2, DONT_IGNORE_MONSTERS, id, 0 );
flOrigin2[2] += flHadChance[0];
get_tr2( 0, TR_flFraction, flUserOrigin[0] );
if( flUserOrigin[0] <= 0.5 )
{
get_tr2( 0, TR_vecEndPos, flOrigin );
flOrigin[0] = ( flOrigin[2] - flOrigin2[2] );
flOrigin[1] = ( flOrigin2[2] - flOrigin[2] );
if( flOrigin[0] <= ( 2.0 - 0.03125 ) && flOrigin[0] >= 0.0 )
{
flHadChance[id] = flOrigin[0];
flHadChance[0] = ( flSpeed[2] * -1.0 );
}
else if( flOrigin[1] <= 0.03125 && flOrigin[1] >= 0.0 )
{
flHadChance[id] = flOrigin[1];
flHadChance[0] = ( flSpeed[2] * -1.0 );
}
}
if( flHadChance[id] == 0.0 )
{
if( flUserOrigin[0] != 1.0 )
{
get_tr2( 0, TR_vecEndPos, flOrigin );
}
}
}
flHadChance[0] = flClientOldSpeed[id] = ( flSpeed[2] * -1.0 );
}
else
{
flHadChance[0] = flClientOldSpeed[id];
flClientOldSpeed[id] = 0.0;
if( bWouldTakeDMG[id] )
{
if( DuckTiming[id][0] && DuckTiming[id][1] )
--DuckTiming[id][1];
else
DuckTiming[id][0] = 0;
if( JumpTiming[id][0] && JumpTiming[id][1] )
--JumpTiming[id][1];
else
JumpTiming[id][0] = 0;
}
bWouldTakeDMG[id] = false;
flHadChance[id] = 0.0;
DuckTiming[id][1] = 0;
JumpTiming[id][1] = 0;
DuckTiming[id][0] = 0;
JumpTiming[id][0] = 0;
}
flSpeed[2] = 0.0;
oldbuttons[id] = buttons;
return FMRES_HANDLED;
}
public Player_PostThink( id )
{
if( !is_user_alive( id ) || is_user_bot( id ) )
return FMRES_IGNORED;
static buttons, oldbuttons[33];
buttons = pev( id, pev_button );
static Float:fSpeed[3];
pev( id, pev_velocity, fSpeed );
if( UserFPS[id] > 48.0 && UserFPS[id] < 101.0 )
{
AVGFPS[id][0] += UserFPS[id];
++AVGFPS[id][1];
}
if( bWouldTakeDMG[id] )
{
if( distance_to_ground( id ) < ( fSpeed[2] / -10.0 ) )
{
averagefps[id] += UserFPS[id];
FPSToAverage[id][averagefpsnum[id]] = UserFPS[id];
DistToAvg[id][averagefpsnum[id]] = distance_to_ground( id );
++averagefpsnum[id];
}
}
else if( !bWouldTakeDMG[id] && averagefpsnum[id] )
{
averagefpsnum[id] = 0;
averagefps[id] = 0.0;
for( new i = 0; i < averagefpsnum[id]; ++i )
{
FPSToAverage[id][i] = 0.0;
DistToAvg[id][i] = 0.0;
}
}
if( bWouldTakeDMG[id] && !( oldbuttons[id] & IN_JUMP ) && buttons & IN_JUMP )
{
JumpTiming[id][1] = 0;
if( oldbuttons[id] & IN_DUCK && !DuckTiming[id][1] )
{
if( !( pev( id, pev_flags ) & FL_DUCKING ) )
{
if( fSpeed[2] > 200.0 ) {
static Float:avgfps1[33], Float:avgfps2[33];
avgfps1[id] = ( averagefps[id] / averagefpsnum[id] );
avgfps2[id] = ( AVGFPS[id][0] / AVGFPS[id][1] );
new name[32], SteamID[32], IPaddr[32];
get_user_name( id, name, charsmax( name ) );
get_user_authid( id, SteamID, charsmax( SteamID ) );
get_user_ip( id, IPaddr, charsmax( IPaddr ), 1 );
if( avgfps1[id] > 101.6 && averagefpsnum[id] > 1 )
client_print(id, print_chat, "%s using JumpBug Hack",name);
else if( avgfps1[id] < avgfps2[id] - 3.5 && averagefpsnum[id] > 1 )
client_print(id, print_chat, "%s using JumpBug Hack",name);
}
}
}
}
fSpeed[2] = 0.0;
oldbuttons[id] = buttons;
return FMRES_HANDLED;
}
public client_putinserver( id )
{
AVGFPS[id][0] = 0.0;
AVGFPS[id][1] = 0.0;
}
public client_disconnected( id )
{
AVGFPS[id][0] = 0.0;
AVGFPS[id][1] = 0.0;
}
public Player_CmdStart( id, uc_handle )
{
if( !is_user_alive( id ) || is_user_bot( id ) )
return FMRES_IGNORED;
UserFPS[id] = ( 1 / ( get_uc( uc_handle, UC_Msec ) * 0.001 ) );
return FMRES_IGNORED;
}
Float:distance_to_ground( id )
{
new Float:start[3], Float:end[3];
entity_get_vector( id, EV_VEC_origin, start );
if( entity_get_int( id, EV_INT_flags ) & FL_DUCKING )
{
start[2] += 18.0;
}
end[0] = start[0];
end[1] = start[1];
end[2] = start[2] - 9999.0;
new ptr = create_tr2();
engfunc( EngFunc_TraceHull, start, end, IGNORE_MONSTERS, HULL_HUMAN, id, ptr );
new Float:fraction;
get_tr2( ptr, TR_flFraction, fraction );
free_tr2( ptr );
return ( fraction * 9999.0 );
}