diff --git a/block_nosteam_bhop/scripting/BlockNosteamBhop.sp b/block_nosteam_bhop/scripting/BlockNosteamBhop.sp new file mode 100755 index 00000000..9412e7fa --- /dev/null +++ b/block_nosteam_bhop/scripting/BlockNosteamBhop.sp @@ -0,0 +1,171 @@ +#pragma semicolon 1 +#pragma newdecls required + +#include +#include +#include + +#define PLUGIN_AUTHOR "jenz" +#define PLUGIN_VERSION "1.1" + +public Plugin myinfo = +{ + name = "nosteam bhop blocker", + author = PLUGIN_AUTHOR, + description = "handicaps nosteamers from bhopping (they mostly cheat) ", + version = PLUGIN_VERSION, + url = "" +}; + +bool bhop_restricted_nosteamer[MAXPLAYERS + 1]; +int buttons_old[MAXPLAYERS + 1]; +int flags_old[MAXPLAYERS + 1]; + +Database g_hDatabase; + +ConVar g_hCvar_TriggerVelocity; +ConVar g_hCvar_SlowedVelocity; + +public void OnPluginStart() +{ + g_hCvar_TriggerVelocity = CreateConVar("sm_nosteam_bhop_trigger_velocity", "300", "Horizontal velocity at which nosteamers will be slowed during bhop.", FCVAR_NONE, true, 0.0); + g_hCvar_SlowedVelocity = CreateConVar("sm_nosteam_bhop_slowed_velocity", "200", "Horizontal velocity which nosteamers will be slowed to.", FCVAR_NONE, true, 0.0); + + AutoExecConfig(); +} + +public void OnConfigsExecuted() +{ + if (!g_hDatabase) + Database.Connect(SQL_OnDatabaseConnect, "bot_surfing"); +} + +public void SQL_OnDatabaseConnect(Database db, const char[] error, any data) +{ + if(!db || strlen(error)) + { + LogError("Database error: %s", error); + return; + } + + g_hDatabase = db; + + char sQuery[512]; + Format(sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS bhop_whitelist (`steam_auth` VARCHAR(32) NOT NULL, `name` VARCHAR(64) NOT NULL, PRIMARY KEY (`steam_auth`))"); + g_hDatabase.Query(SQL_OnConnectFinished, sQuery, _, DBPrio_High); +} + +public void SQL_OnConnectFinished(Database db, DBResultSet results, const char[] error, any data) +{ + if(!db || strlen(error)) + { + LogError("Database error: %s", error); + return; + } + + for(int i = 1; i <= MaxClients; i++) + { + if (IsClientConnected(i) && IsClientAuthorized(i)) + { + char sAuthID[32]; + GetClientAuthId(i, AuthId_Steam2, sAuthID, sizeof(sAuthID)); + OnClientAuthorized(i, sAuthID); + } + } +} + +public void OnClientAuthorized(int client, const char[] sAuthID) +{ + if (!IsFakeClient(client) && !IsClientSourceTV(client) && !PM_IsPlayerSteam(client)) + { + bhop_restricted_nosteamer[client] = true; + buttons_old[client] = 0; + flags_old[client] = 0; + + char sQuery[512]; + Format(sQuery, sizeof(sQuery), "SELECT * FROM bhop_whitelist WHERE steam_auth = '%s'", sAuthID); + g_hDatabase.Query(SQL_OnQueryCompleted, sQuery, GetClientSerial(client)); + } + else + bhop_restricted_nosteamer[client] = false; +} + +public void SQL_OnQueryCompleted(Database db, DBResultSet results, const char[] error, any data) +{ + if (!db || strlen(error)) + { + LogError("Query error: %s", error); + return; + } + + int client; + if ((client = GetClientFromSerial(data)) == 0) + return; + + if (results.RowCount && results.FetchRow()) + { + int iFieldNum; + results.FieldNameToNum("name", iFieldNum); + char sName[MAX_NAME_LENGTH]; + results.FetchString(iFieldNum, sName, sizeof(sName)); + + bhop_restricted_nosteamer[client] = false; + LogMessage("%L was found as \'%s\' on the whitelist and therefore will be allowed to bhop", client, sName); + } +} + +public void OnClientDisconnect(int client) +{ + bhop_restricted_nosteamer[client] = false; + buttons_old[client] = 0; + flags_old[client] = 0; +} + +public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, + int cmdnum, int tickcount, int seed, const int mouse[2]) +{ + if (!IsValidClient(client) || !IsPlayerAlive(client) || !bhop_restricted_nosteamer[client]) return; + if (!(buttons_old[client] & IN_JUMP) && (!(buttons & IN_JUMP))) + { + flags_old[client] = GetEntityFlags(client); + return; + } + if (buttons_old[client] & IN_JUMP) + { + if (!(buttons & IN_JUMP)) + if (GetEntityFlags(client) & FL_ONGROUND) + buttons_old[client] = buttons; + return; + } + if (!(flags_old[client] & FL_ONGROUND)) + return; + + float vVel[3]; + GetEntPropVector(client, Prop_Data, "m_vecVelocity", vVel); + float fVelocity = SquareRoot(Pow(vVel[0], 2.0) + Pow(vVel[1], 2.0)); + + if (fVelocity > g_hCvar_TriggerVelocity.FloatValue) + { + float fNormalized[3]; + fNormalized[0] = vVel[0] / fVelocity; + fNormalized[1] = vVel[1] / fVelocity; + fNormalized[2] = 0.0; + + float fTargetVelocity = g_hCvar_SlowedVelocity.FloatValue; + float fFinal[3]; + fFinal[0] = fNormalized[0] * fTargetVelocity; + fFinal[1] = fNormalized[1] * fTargetVelocity; + fFinal[2] = vVel[2]; + TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, fFinal); + } + + buttons_old[client] = buttons; +} + +stock int IsValidClient(int client, bool nobots = true) +{ + if (client <= 0 || client > MaxClients || !IsClientConnected(client) || (nobots && IsFakeClient(client))) + return false; + + return IsClientInGame(client); +}