/* * CSB Spinbot Detection * Copyright (C) 2026 counter-strike-boost.com * * Samples pev_v_angle each frame and flags spinbot / anti-aim: a yaw that * rotates faster than a human can move the mouse, or a pitch outside the legal * -89..89 range, over several sustained frames. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. It is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See for details. */ #include #include new const PLUGIN[] = "CSB Spinbot Detection" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" new g_pEnabled, g_pMaxYaw, g_pStrikes, g_pAction new Float:g_fLastYaw[33] new bool:g_bHasLast[33] new g_iStrikes[33] public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) g_pEnabled = register_cvar("csb_spin_enabled", "1") g_pMaxYaw = register_cvar("csb_spin_maxyaw", "50.0") g_pStrikes = register_cvar("csb_spin_strikes", "10") g_pAction = register_cvar("csb_spin_action", "0") register_forward(FM_PlayerPreThink, "fwPreThink") } public client_putinserver(id) { g_bHasLast[id] = false g_iStrikes[id] = 0 } public fwPreThink(id) { if (!get_pcvar_num(g_pEnabled) || !is_user_alive(id) || is_user_bot(id)) return FMRES_IGNORED new Float:angles[3] pev(id, pev_v_angle, angles) new bool:bad = false new reason[24] // legal pitch is clamped to [-89, 89]; anything beyond is a hack angle if (angles[0] > 89.5 || angles[0] < -89.5) { bad = true copy(reason, charsmax(reason), "illegal pitch") } else if (g_bHasLast[id]) { new Float:delta = angles[1] - g_fLastYaw[id] // normalise to the shortest signed turn while (delta > 180.0) delta -= 360.0 while (delta < -180.0) delta += 360.0 if (delta < 0.0) delta = -delta if (delta > get_pcvar_float(g_pMaxYaw)) { bad = true copy(reason, charsmax(reason), "impossible yaw speed") } } g_fLastYaw[id] = angles[1] g_bHasLast[id] = true if (bad) { g_iStrikes[id]++ if (g_iStrikes[id] >= get_pcvar_num(g_pStrikes)) { flag(id, reason) g_iStrikes[id] = 0 } } else if (g_iStrikes[id] > 0) { g_iStrikes[id]-- } return FMRES_IGNORED } flag(id, const reason[]) { new name[32], authid[35] get_user_name(id, name, charsmax(name)) get_user_authid(id, authid, charsmax(authid)) log_amx("[CSB Spinbot] %s <%s> flagged: %s", name, authid, reason) if (get_pcvar_num(g_pAction) == 1) { server_cmd("kick #%d ^"CSB: spinbot / anti-aim detected^"", get_user_userid(id)) server_exec() } else { client_print(0, print_chat, "[CSB] %s is suspected of using spinbot / anti-aim (%s).", name, reason) } }