/* * CSB Map Stats * Copyright (C) 2026 counter-strike-boost.com * * Records per-map aggregates into nVault keyed by map name: rounds played, * terrorist/counter-terrorist round wins, bombs planted, bombs defused and * total round time. /mapstats prints the numbers for the current map, and at * every round end a short chat line notes which side is dominating the map. * * 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 Map Stats" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" new g_iRounds new g_iTWins new g_iCTWins new g_iPlants new g_iDefuses new g_iTotalSecs new Float:g_fRoundStart new bool:g_bRoundLive new g_iVault new g_szMap[32] public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) register_cvar("csb_mapstats_enabled", "1") get_mapname(g_szMap, charsmax(g_szMap)) register_logevent("onRoundStart", 2, "1=Round_Start") register_logevent("onRoundEnd", 2, "1=Round_End") register_event("SendAudio", "onTWin", "a", "2&%!MRAD_terwin") register_event("SendAudio", "onCTWin", "a", "2&%!MRAD_ctwin") register_logevent("onPlant", 3, "2=Planted_The_Bomb") register_logevent("onDefuse", 3, "2=Defused_The_Bomb") register_clcmd("say /mapstats", "cmdStats") register_clcmd("say_team /mapstats", "cmdStats") g_iVault = nvault_open("csb_mapstats") loadMap() } public plugin_end() { saveMap() if (g_iVault != -1) nvault_close(g_iVault) } public onRoundStart() { g_fRoundStart = get_gametime() g_bRoundLive = true } public onRoundEnd() { if (g_bRoundLive) { g_iRounds++ g_iTotalSecs += floatround(get_gametime() - g_fRoundStart) g_bRoundLive = false printDominance() } } public onTWin() { g_iTWins++ } public onCTWin() { g_iCTWins++ } public onPlant() { g_iPlants++ } public onDefuse() { g_iDefuses++ } printDominance() { new total = g_iTWins + g_iCTWins if (total < 5) return if (g_iTWins > g_iCTWins * 3 / 2) { client_print(0, print_chat, "[CSB] %s is T-sided so far: T %d - %d CT.", g_szMap, g_iTWins, g_iCTWins) } else if (g_iCTWins > g_iTWins * 3 / 2) { client_print(0, print_chat, "[CSB] %s is CT-sided so far: CT %d - %d T.", g_szMap, g_iCTWins, g_iTWins) } } public cmdStats(id) { new Float:avg = g_iRounds > 0 ? float(g_iTotalSecs) / float(g_iRounds) : 0.0 client_print(id, print_console, "----- CSB Map Stats: %s -----", g_szMap) client_print(id, print_console, "rounds played: %d (average %.0f s)", g_iRounds, avg) client_print(id, print_console, "T wins: %d CT wins: %d", g_iTWins, g_iCTWins) client_print(id, print_console, "bombs planted: %d defused: %d", g_iPlants, g_iDefuses) client_print(id, print_chat, "[CSB] Map stats printed to your console.") return PLUGIN_HANDLED } loadMap() { if (g_iVault == -1) return new data[96] if (nvault_get(g_iVault, g_szMap, data, charsmax(data)) < 1) return new a[12], b[12], c[12], d[12], e[12], f[12] parse(data, a, charsmax(a), b, charsmax(b), c, charsmax(c), d, charsmax(d), e, charsmax(e), f, charsmax(f)) g_iRounds = str_to_num(a) g_iTWins = str_to_num(b) g_iCTWins = str_to_num(c) g_iPlants = str_to_num(d) g_iDefuses = str_to_num(e) g_iTotalSecs = str_to_num(f) } saveMap() { if (g_iVault == -1) return new data[96] formatex(data, charsmax(data), "%d %d %d %d %d %d", g_iRounds, g_iTWins, g_iCTWins, g_iPlants, g_iDefuses, g_iTotalSecs) nvault_set(g_iVault, g_szMap, data) }