Per-map aggregates (rounds, T/CT wins, plants, defuses, average round time) in nVault, shown with /mapstats.
csb_map_stats.sma v1.0.0
1
/*
2
* CSB Map Stats
3
* Copyright (C) 2026 counter-strike-boost.com
4
*
5
* Records per-map aggregates into nVault keyed by map name: rounds played,
6
* terrorist/counter-terrorist round wins, bombs planted, bombs defused and
7
* total round time. /mapstats prints the numbers for the current map, and at
8
* every round end a short chat line notes which side is dominating the map.
9
*
10
* This program is free software: you can redistribute it and/or modify it under
11
* the terms of the GNU General Public License as published by the Free Software
12
* Foundation, either version 3 of the License, or (at your option) any later
13
* version. It is distributed in the hope that it will be useful, but WITHOUT
14
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
* FOR A PARTICULAR PURPOSE. See <https://www.gnu.org/licenses/> for details.
16
*/
17
18
#include <amxmodx>
19
#include <nvault>
20
21
new const PLUGIN[] = "CSB Map Stats"
22
new const VERSION[] = "1.0.0"
23
new const AUTHOR[] = "counter-strike-boost.com"
24
25
new g_iRounds
26
new g_iTWins
27
new g_iCTWins
28
new g_iPlants
29
new g_iDefuses
30
new g_iTotalSecs
31
32
new Float:g_fRoundStart
33
new bool:g_bRoundLive
34
35
new g_iVault
36
new g_szMap[32]
37
38
public plugin_init()
39
{
40
register_plugin(PLUGIN, VERSION, AUTHOR)
41
42
register_cvar("csb_mapstats_enabled", "1")
43
44
get_mapname(g_szMap, charsmax(g_szMap))
45
46
register_logevent("onRoundStart", 2, "1=Round_Start")
47
register_logevent("onRoundEnd", 2, "1=Round_End")
48
register_event("SendAudio", "onTWin", "a", "2&%!MRAD_terwin")
49
register_event("SendAudio", "onCTWin", "a", "2&%!MRAD_ctwin")
50
register_logevent("onPlant", 3, "2=Planted_The_Bomb")
51
register_logevent("onDefuse", 3, "2=Defused_The_Bomb")
52
53
register_clcmd("say /mapstats", "cmdStats")
54
register_clcmd("say_team /mapstats", "cmdStats")
55
56
g_iVault = nvault_open("csb_mapstats")
57
58
loadMap()
59
}
60
61
public plugin_end()
62
{
63
saveMap()
64
65
if (g_iVault != -1)
66
nvault_close(g_iVault)
67
}
68
69
public onRoundStart()
70
{
71
g_fRoundStart = get_gametime()
72
g_bRoundLive = true
73
}
74
75
public onRoundEnd()
76
{
77
if (g_bRoundLive)
78
{
79
g_iRounds++
80
g_iTotalSecs += floatround(get_gametime() - g_fRoundStart)
81
g_bRoundLive = false
82
83
printDominance()
84
}
85
}
86
87
public onTWin()
88
{
89
g_iTWins++
90
}
91
92
public onCTWin()
93
{
94
g_iCTWins++
95
}
96
97
public onPlant()
98
{
99
g_iPlants++
100
}
101
102
public onDefuse()
103
{
104
g_iDefuses++
105
}
106
107
printDominance()
108
{
109
new total = g_iTWins + g_iCTWins
110
111
if (total < 5)
112
return
113
114
if (g_iTWins > g_iCTWins * 3 / 2)
115
{
116
client_print(0, print_chat,
117
"[CSB] %s is T-sided so far: T %d - %d CT.", g_szMap, g_iTWins, g_iCTWins)
118
}
119
else if (g_iCTWins > g_iTWins * 3 / 2)
120
{
121
client_print(0, print_chat,
122
"[CSB] %s is CT-sided so far: CT %d - %d T.", g_szMap, g_iCTWins, g_iTWins)
123
}
124
}
125
126
public cmdStats(id)
127
{
128
new Float:avg = g_iRounds > 0 ? float(g_iTotalSecs) / float(g_iRounds) : 0.0
129
130
client_print(id, print_console, "----- CSB Map Stats: %s -----", g_szMap)
131
client_print(id, print_console, "rounds played: %d (average %.0f s)", g_iRounds, avg)
132
client_print(id, print_console, "T wins: %d CT wins: %d", g_iTWins, g_iCTWins)
133
client_print(id, print_console, "bombs planted: %d defused: %d", g_iPlants, g_iDefuses)
134
client_print(id, print_chat, "[CSB] Map stats printed to your console.")
135
136
return PLUGIN_HANDLED
137
}
138
139
loadMap()
140
{
141
if (g_iVault == -1)
142
return
143
144
new data[96]
145
146
if (nvault_get(g_iVault, g_szMap, data, charsmax(data)) < 1)
147
return
148
149
new a[12], b[12], c[12], d[12], e[12], f[12]
150
parse(data,
151
a, charsmax(a), b, charsmax(b), c, charsmax(c),
152
d, charsmax(d), e, charsmax(e), f, charsmax(f))
153
154
g_iRounds = str_to_num(a)
155
g_iTWins = str_to_num(b)
156
g_iCTWins = str_to_num(c)
157
g_iPlants = str_to_num(d)
158
g_iDefuses = str_to_num(e)
159
g_iTotalSecs = str_to_num(f)
160
}
161
162
saveMap()
163
{
164
if (g_iVault == -1)
165
return
166
167
new data[96]
168
formatex(data, charsmax(data), "%d %d %d %d %d %d",
169
g_iRounds, g_iTWins, g_iCTWins, g_iPlants, g_iDefuses, g_iTotalSecs)
170
171
nvault_set(g_iVault, g_szMap, data)
172
}
173









