Initial release 1.0.0
Browse Source1.0.0 - Initial release.
4 changed files
with 229 additions and 0 deletions
A
CHANGELOG.md
+3 -0
A
README.md
+1 -0
A
addons/amxmodx/scripting/csb_aimbot_detect.sma
+174 -0
A
csb.json
+51 -0
CHANGELOG.md
A
| @@ -0,0 +1,3 @@ | ||
| 1 | +## 1.0.0 (2026-04-01) | |
| 2 | + | |
| 3 | +1.0.0 - Initial release. |
README.md
A
| @@ -0,0 +1 @@ | ||
| 1 | +<p><strong>CSB Aimbot Detection</strong> watches for the two things aim assistance does that humans cannot. Every frame it samples each alive player's view angle (<code>pev_v_angle</code> via fakemeta) and measures how far it moved in that single frame. When a kill lands on a frame where the view snapped more than <code>csb_aim_snapangle</code> degrees, a snap counter goes up; enough of those and the player is flagged. A second, independent signal is a sustained headshot ratio above <code>csb_aim_hsratio</code> percent over at least <code>csb_aim_minkills</code> kills. Suspects are logged with the exact evidence and online admins are alerted.</p><p><strong>This is a heuristic aid, not an auto-banner.</strong> It never kicks or bans on its own — false positives happen with flick-heavy legit players, so a human should always review the log evidence before acting.</p><h2>Features</h2><ul><li>Per-frame view-angle sampling with correct 180-degree wrap handling.</li><li>Impossible-snap counter tied to the killing frame.</li><li>Inhuman headshot-ratio signal with a minimum-sample guard.</li><li>Evidence written to the AMXX log; admins (<code>ADMIN_KICK</code>) alerted in chat.</li><li>Each player is flagged at most once to avoid alert spam.</li></ul><h2>Installation</h2><ol><li>Compile <code>csb_aimbot_detect.sma</code> and copy it to <code>addons/amxmodx/plugins/</code>.</li><li>Add it to <code>plugins.ini</code> and change the map.</li></ol><p>Treat every flag as a lead to review, not a verdict. Tune the thresholds to your player base before trusting them.</p> |
addons/amxmodx/scripting/csb_aimbot_detect.sma
A
| @@ -0,0 +1,174 @@ | ||
| 1 | +/* | |
| 2 | + * CSB Aimbot Detection | |
| 3 | + * Copyright (C) 2026 counter-strike-boost.com | |
| 4 | + * | |
| 5 | + * A heuristic aim-assist detector. Every frame it samples each alive player's | |
| 6 | + * view angle (fakemeta pev_v_angle) and measures the single-frame angular | |
| 7 | + * change. When a kill lands in the same frame as an impossibly large snap, a | |
| 8 | + * snap counter is raised; a sustained inhuman headshot ratio is a second | |
| 9 | + * signal. Suspects are logged with the evidence and admins are alerted. This is | |
| 10 | + * a heuristic aid for human review, not an automatic punisher. | |
| 11 | + * | |
| 12 | + * This program is free software: you can redistribute it and/or modify it under | |
| 13 | + * the terms of the GNU General Public License as published by the Free Software | |
| 14 | + * Foundation, either version 3 of the License, or (at your option) any later | |
| 15 | + * version. It is distributed in the hope that it will be useful, but WITHOUT | |
| 16 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 17 | + * FOR A PARTICULAR PURPOSE. See <https://www.gnu.org/licenses/> for details. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#include <amxmodx> | |
| 21 | +#include <amxmisc> | |
| 22 | +#include <fakemeta> | |
| 23 | + | |
| 24 | +new const PLUGIN[] = "CSB Aimbot Detection" | |
| 25 | +new const VERSION[] = "1.0.0" | |
| 26 | +new const AUTHOR[] = "counter-strike-boost.com" | |
| 27 | + | |
| 28 | +new g_pEnabled, g_pSnapAngle, g_pSnapHits, g_pHsRatio, g_pMinKills | |
| 29 | + | |
| 30 | +new Float:g_fLast[33][2] | |
| 31 | +new bool:g_bValid[33] | |
| 32 | +new Float:g_fFrameDelta[33] | |
| 33 | + | |
| 34 | +new g_iKills[33] | |
| 35 | +new g_iHs[33] | |
| 36 | +new g_iSnapKills[33] | |
| 37 | +new bool:g_bFlagged[33] | |
| 38 | + | |
| 39 | +public plugin_init() | |
| 40 | +{ | |
| 41 | + register_plugin(PLUGIN, VERSION, AUTHOR) | |
| 42 | + | |
| 43 | + g_pEnabled = register_cvar("csb_aim_enabled", "1") | |
| 44 | + g_pSnapAngle = register_cvar("csb_aim_snapangle", "40.0") | |
| 45 | + g_pSnapHits = register_cvar("csb_aim_snaphits", "4") | |
| 46 | + g_pHsRatio = register_cvar("csb_aim_hsratio", "90") | |
| 47 | + g_pMinKills = register_cvar("csb_aim_minkills", "15") | |
| 48 | + | |
| 49 | + register_forward(FM_PlayerPreThink, "fwThink") | |
| 50 | + register_event("DeathMsg", "evDeath", "a", "1>0") | |
| 51 | +} | |
| 52 | + | |
| 53 | +public client_putinserver(id) | |
| 54 | +{ | |
| 55 | + g_bValid[id] = false | |
| 56 | + g_fFrameDelta[id] = 0.0 | |
| 57 | + g_iKills[id] = 0 | |
| 58 | + g_iHs[id] = 0 | |
| 59 | + g_iSnapKills[id] = 0 | |
| 60 | + g_bFlagged[id] = false | |
| 61 | +} | |
| 62 | + | |
| 63 | +public fwThink(id) | |
| 64 | +{ | |
| 65 | + if (!get_pcvar_num(g_pEnabled) || !is_user_connected(id)) | |
| 66 | + return FMRES_IGNORED | |
| 67 | + | |
| 68 | + if (is_user_bot(id) || is_user_hltv(id)) | |
| 69 | + return FMRES_IGNORED | |
| 70 | + | |
| 71 | + if (!is_user_alive(id)) | |
| 72 | + { | |
| 73 | + g_bValid[id] = false | |
| 74 | + return FMRES_IGNORED | |
| 75 | + } | |
| 76 | + | |
| 77 | + new Float:ang[3] | |
| 78 | + pev(id, pev_v_angle, ang) | |
| 79 | + | |
| 80 | + if (g_bValid[id]) | |
| 81 | + { | |
| 82 | + new Float:dp = ang[0] - g_fLast[id][0] | |
| 83 | + new Float:dy = ang[1] - g_fLast[id][1] | |
| 84 | + | |
| 85 | + while (dy > 180.0) dy -= 360.0 | |
| 86 | + while (dy < -180.0) dy += 360.0 | |
| 87 | + while (dp > 180.0) dp -= 360.0 | |
| 88 | + while (dp < -180.0) dp += 360.0 | |
| 89 | + | |
| 90 | + g_fFrameDelta[id] = floatsqroot(dp * dp + dy * dy) | |
| 91 | + } | |
| 92 | + else | |
| 93 | + { | |
| 94 | + g_bValid[id] = true | |
| 95 | + g_fFrameDelta[id] = 0.0 | |
| 96 | + } | |
| 97 | + | |
| 98 | + g_fLast[id][0] = ang[0] | |
| 99 | + g_fLast[id][1] = ang[1] | |
| 100 | + | |
| 101 | + return FMRES_IGNORED | |
| 102 | +} | |
| 103 | + | |
| 104 | +public evDeath() | |
| 105 | +{ | |
| 106 | + if (!get_pcvar_num(g_pEnabled)) | |
| 107 | + return | |
| 108 | + | |
| 109 | + new killer = read_data(1) | |
| 110 | + new victim = read_data(2) | |
| 111 | + new hs = read_data(3) | |
| 112 | + | |
| 113 | + if (killer < 1 || killer > 32 || killer == victim) | |
| 114 | + return | |
| 115 | + | |
| 116 | + if (is_user_bot(killer) || is_user_hltv(killer)) | |
| 117 | + return | |
| 118 | + | |
| 119 | + g_iKills[killer]++ | |
| 120 | + | |
| 121 | + if (hs) | |
| 122 | + g_iHs[killer]++ | |
| 123 | + | |
| 124 | + /* snap heuristic: a very large single-frame view change on the killing frame */ | |
| 125 | + new Float:snapAngle = get_pcvar_float(g_pSnapAngle) | |
| 126 | + | |
| 127 | + if (g_fFrameDelta[killer] >= snapAngle) | |
| 128 | + { | |
| 129 | + g_iSnapKills[killer]++ | |
| 130 | + | |
| 131 | + log_amx("[CSB Aim] snap on kill by %N - %.1f deg in one frame (snap kills: %d)", | |
| 132 | + killer, g_fFrameDelta[killer], g_iSnapKills[killer]) | |
| 133 | + | |
| 134 | + if (!g_bFlagged[killer] && g_iSnapKills[killer] >= get_pcvar_num(g_pSnapHits)) | |
| 135 | + flagSuspect(killer, "repeated impossible aim snaps") | |
| 136 | + } | |
| 137 | + | |
| 138 | + /* headshot-ratio heuristic */ | |
| 139 | + new minKills = get_pcvar_num(g_pMinKills) | |
| 140 | + | |
| 141 | + if (!g_bFlagged[killer] && g_iKills[killer] >= minKills) | |
| 142 | + { | |
| 143 | + new pct = (g_iHs[killer] * 100) / g_iKills[killer] | |
| 144 | + | |
| 145 | + if (pct >= get_pcvar_num(g_pHsRatio)) | |
| 146 | + flagSuspect(killer, "inhuman headshot ratio") | |
| 147 | + } | |
| 148 | +} | |
| 149 | + | |
| 150 | +flagSuspect(id, const reason[]) | |
| 151 | +{ | |
| 152 | + g_bFlagged[id] = true | |
| 153 | + | |
| 154 | + new name[32], authid[35] | |
| 155 | + get_user_name(id, name, charsmax(name)) | |
| 156 | + get_user_authid(id, authid, charsmax(authid)) | |
| 157 | + | |
| 158 | + new pct = g_iKills[id] ? (g_iHs[id] * 100) / g_iKills[id] : 0 | |
| 159 | + | |
| 160 | + log_amx("[CSB Aim] SUSPECT %s <%s> - %s (kills %d, hs %d = %d%%, snap kills %d)", | |
| 161 | + name, authid, reason, g_iKills[id], g_iHs[id], pct, g_iSnapKills[id]) | |
| 162 | + | |
| 163 | + /* alert online admins */ | |
| 164 | + new players[32], num, pid | |
| 165 | + get_players(players, num, "ch") | |
| 166 | + | |
| 167 | + for (new i = 0; i < num; i++) | |
| 168 | + { | |
| 169 | + pid = players[i] | |
| 170 | + | |
| 171 | + if (get_user_flags(pid) & ADMIN_KICK) | |
| 172 | + client_print(pid, print_chat, "[CSB Aim] Possible aimbot: %s (%s). Please review.", name, reason) | |
| 173 | + } | |
| 174 | +} |
csb.json
A
| @@ -0,0 +1,51 @@ | ||
| 1 | +{ | |
| 2 | + "name": "CSB Aimbot Detection", | |
| 3 | + "category": "anticheat", | |
| 4 | + "tags": "aimbot, detection, heuristics", | |
| 5 | + "image": "", | |
| 6 | + "original_author": "", | |
| 7 | + "original_url": "", | |
| 8 | + "license": "GPL-3.0", | |
| 9 | + "title": "CSB Aimbot Detection", | |
| 10 | + "short_desc": "Heuristic aim detector: measures per-frame view-angle snaps around kills and flags impossible snaps and inhuman headshot ratios for admin review.", | |
| 11 | + "version": "1.0.0", | |
| 12 | + "amxx_min": "1.9", | |
| 13 | + "amxx_compile_default": "1.9", | |
| 14 | + "rehlds_ok": true, | |
| 15 | + "hlds_ok": true, | |
| 16 | + "regamedll_required": false, | |
| 17 | + "metamod_flavor": "any", | |
| 18 | + "reapi_required": false, | |
| 19 | + "modules": "fakemeta", | |
| 20 | + "install_notes": "1. Put csb_aimbot_detect.amxx in addons/amxmodx/plugins/\n2. Add it to addons/amxmodx/configs/plugins.ini\n3. Change map", | |
| 21 | + "known_conflicts": "", | |
| 22 | + "cvars": [ | |
| 23 | + { | |
| 24 | + "name": "csb_aim_enabled", | |
| 25 | + "default": "1", | |
| 26 | + "description": "Enable aimbot heuristics." | |
| 27 | + }, | |
| 28 | + { | |
| 29 | + "name": "csb_aim_snapangle", | |
| 30 | + "default": "40.0", | |
| 31 | + "description": "Single-frame view change (degrees) counted as a snap." | |
| 32 | + }, | |
| 33 | + { | |
| 34 | + "name": "csb_aim_snaphits", | |
| 35 | + "default": "4", | |
| 36 | + "description": "Snap-kills before a player is flagged." | |
| 37 | + }, | |
| 38 | + { | |
| 39 | + "name": "csb_aim_hsratio", | |
| 40 | + "default": "90", | |
| 41 | + "description": "Headshot ratio percent that flags a player." | |
| 42 | + }, | |
| 43 | + { | |
| 44 | + "name": "csb_aim_minkills", | |
| 45 | + "default": "15", | |
| 46 | + "description": "Minimum kills before the ratio check applies." | |
| 47 | + } | |
| 48 | + ], | |
| 49 | + "commands": [], | |
| 50 | + "main": "addons/amxmodx/scripting/csb_aimbot_detect.sma" | |
| 51 | +} | |
| 0 | 52 |









