/* * CSB Anti Retry * Copyright (C) 2026 counter-strike-boost.com * * Caches a player's team, frags, deaths and money on disconnect (keyed by * SteamID) and restores it if they reconnect within a short window, so the * classic 'retry to reset' trick can't be used to escape a losing state. * * 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 #include new const PLUGIN[] = "CSB Anti Retry" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" #define MAX_RECORDS 64 new g_pEnabled, g_pWindow new g_szAuth[MAX_RECORDS][35] new g_iTeam[MAX_RECORDS] new g_iFrags[MAX_RECORDS] new g_iDeaths[MAX_RECORDS] new g_iMoney[MAX_RECORDS] new g_iStamp[MAX_RECORDS] new bool:g_bUsed[MAX_RECORDS] new g_iCount = 0 public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) g_pEnabled = register_cvar("csb_antiretry_enabled", "1") g_pWindow = register_cvar("csb_antiretry_window", "90") } public client_disconnected(id) { if (!get_pcvar_num(g_pEnabled) || is_user_bot(id) || is_user_hltv(id)) return new authid[35] get_user_authid(id, authid, charsmax(authid)) if (!authid[0] || equal(authid, "STEAM_ID_PENDING")) return new slot = findRecord(authid) if (slot == -1) slot = newRecord() if (slot == -1) return copy(g_szAuth[slot], charsmax(g_szAuth[]), authid) g_iTeam[slot] = _:cs_get_user_team(id) g_iFrags[slot] = get_user_frags(id) g_iDeaths[slot] = cs_get_user_deaths(id) g_iMoney[slot] = cs_get_user_money(id) g_iStamp[slot] = get_systime() g_bUsed[slot] = true } public client_putinserver(id) { if (!get_pcvar_num(g_pEnabled) || is_user_bot(id) || is_user_hltv(id)) return // wait for the join to settle before touching team/money set_task(2.0, "taskRestore", id) } public taskRestore(id) { if (!is_user_connected(id)) return new authid[35] get_user_authid(id, authid, charsmax(authid)) new slot = findRecord(authid) if (slot == -1) return if (get_systime() - g_iStamp[slot] > get_pcvar_num(g_pWindow)) { g_bUsed[slot] = false return } new CsTeams:team = CsTeams:g_iTeam[slot] if (team == CS_TEAM_T || team == CS_TEAM_CT) cs_set_user_team(id, team) set_user_frags(id, g_iFrags[slot]) cs_set_user_deaths(id, g_iDeaths[slot]) cs_set_user_money(id, g_iMoney[slot]) g_bUsed[slot] = false client_print(id, print_chat, "[CSB] Your previous state was restored - retry can't be used to reset it.") log_amx("[CSB AntiRetry] restored state for %s", authid) } findRecord(const authid[]) { for (new i = 0; i < g_iCount; i++) { if (g_bUsed[i] && equal(g_szAuth[i], authid)) return i } return -1 } newRecord() { for (new i = 0; i < g_iCount; i++) { if (!g_bUsed[i]) return i } if (g_iCount < MAX_RECORDS) return g_iCount++ return -1 }