Prodvigat server

Initial release 1.0.0

Browse Source
1.0.0 - Initial release.
Daemon666 committed commit 068fe144254398baef71d3abe94c538c0c53a511
4 changed files with 282 additions and 0 deletions
+3 -0 CHANGELOG.md A
@@ -0,0 +1,3 @@
1 +## 1.0.0 (2026-05-26)
2 +
3 +1.0.0 - Initial release.
+1 -0 README.md A
@@ -0,0 +1 @@
1 +<p><strong>CSB Accuracy Tracker</strong> counts every shot fired (via <code>Ham_Weapon_PrimaryAttack</code>) and every bullet that lands on an enemy (via <code>Ham_TakeDamage</code>) per weapon. Per-map totals live in memory; lifetime totals are persisted per SteamID in nVault. Typing <code>/acc</code> prints a console table with map and lifetime accuracy for every weapon you have used.</p><p>Inspired by the accuracy reporting of AMXX StatsX; independent GPL re-implementation.</p><h2>Features</h2><ul><li>All 24 gun classnames tracked (grenades and knife excluded).</li><li>Team damage is never counted as a hit.</li><li>Lifetime data survives map changes via nVault.</li></ul><h2>Installation</h2><ol><li>Enable the <code>hamsandwich</code> and <code>nvault</code> modules.</li><li>Compile, install, add to <code>plugins.ini</code>, change map.</li></ol>
+241 -0 addons/amxmodx/scripting/csb_accuracy_tracker.sma A
@@ -0,0 +1,241 @@
1 +/*
2 + * CSB Accuracy Tracker
3 + * Copyright (C) 2026 counter-strike-boost.com
4 + *
5 + * Counts shots fired (Ham_Weapon_PrimaryAttack) and bullet hits
6 + * (Ham_TakeDamage with DMG_BULLET) per weapon for every player, keeps per-map
7 + * and lifetime totals (lifetime persisted in nVault per SteamID) and prints a
8 + * console table with /acc. Useful on public servers for spotting who actually
9 + * hits what they shoot at.
10 + *
11 + * Inspired by the weapon accuracy reporting of AMXX StatsX; independent GPL
12 + * re-implementation, no original code reused.
13 + *
14 + * This program is free software: you can redistribute it and/or modify it under
15 + * the terms of the GNU General Public License as published by the Free Software
16 + * Foundation, either version 3 of the License, or (at your option) any later
17 + * version. It is distributed in the hope that it will be useful, but WITHOUT
18 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 + * FOR A PARTICULAR PURPOSE. See <https://www.gnu.org/licenses/> for details.
20 + */
21 +
22 +#include <amxmodx>
23 +#include <hamsandwich>
24 +#include <fakemeta>
25 +#include <nvault>
26 +
27 +new const PLUGIN[] = "CSB Accuracy Tracker"
28 +new const VERSION[] = "1.0.0"
29 +new const AUTHOR[] = "counter-strike-boost.com"
30 +
31 +#if !defined DMG_BULLET
32 +#define DMG_BULLET (1<<1)
33 +#endif
34 +
35 +#define MAX_WEAPONS 24
36 +
37 +new const g_szWeapons[][] =
38 +{
39 + "weapon_glock18", "weapon_usp", "weapon_p228", "weapon_deagle",
40 + "weapon_fiveseven", "weapon_elite", "weapon_m3", "weapon_xm1014",
41 + "weapon_tmp", "weapon_mac10", "weapon_mp5navy", "weapon_ump45",
42 + "weapon_p90", "weapon_galil", "weapon_famas", "weapon_ak47",
43 + "weapon_m4a1", "weapon_scout", "weapon_sg552", "weapon_aug",
44 + "weapon_awp", "weapon_sg550", "weapon_g3sg1", "weapon_m249"
45 +}
46 +
47 +new g_iMapShots[33][MAX_WEAPONS]
48 +new g_iMapHits[33][MAX_WEAPONS]
49 +new g_iLifeShots[33][MAX_WEAPONS]
50 +new g_iLifeHits[33][MAX_WEAPONS]
51 +
52 +new g_iLastWeapon[33]
53 +new g_iVault
54 +
55 +public plugin_init()
56 +{
57 + register_plugin(PLUGIN, VERSION, AUTHOR)
58 +
59 + register_cvar("csb_acc_enabled", "1")
60 +
61 + for (new w = 0; w < MAX_WEAPONS; w++)
62 + RegisterHam(Ham_Weapon_PrimaryAttack, g_szWeapons[w], "OnFire", 1)
63 +
64 + RegisterHam(Ham_TakeDamage, "player", "OnDamage", 1)
65 +
66 + register_clcmd("say /acc", "cmdAcc")
67 + register_clcmd("say_team /acc", "cmdAcc")
68 +
69 + g_iVault = nvault_open("csb_accuracy")
70 +}
71 +
72 +public plugin_end()
73 +{
74 + if (g_iVault != -1)
75 + nvault_close(g_iVault)
76 +}
77 +
78 +public client_putinserver(id)
79 +{
80 + for (new w = 0; w < MAX_WEAPONS; w++)
81 + {
82 + g_iMapShots[id][w] = 0
83 + g_iMapHits[id][w] = 0
84 + g_iLifeShots[id][w] = 0
85 + g_iLifeHits[id][w] = 0
86 + }
87 +
88 + loadPlayer(id)
89 +}
90 +
91 +public client_disconnect(id)
92 +{
93 + savePlayer(id)
94 +}
95 +
96 +public OnFire(ent)
97 +{
98 + new id = pev(ent, pev_owner)
99 +
100 + if (id < 1 || id > 32 || !is_user_connected(id))
101 + return HAM_IGNORED
102 +
103 + new w = weaponIndex(ent)
104 +
105 + if (w == -1)
106 + return HAM_IGNORED
107 +
108 + g_iLastWeapon[id] = w
109 + g_iMapShots[id][w]++
110 + g_iLifeShots[id][w]++
111 +
112 + return HAM_IGNORED
113 +}
114 +
115 +public OnDamage(victim, inflictor, attacker, Float:damage, damagetype)
116 +{
117 + if (attacker < 1 || attacker > 32 || attacker == victim)
118 + return HAM_IGNORED
119 +
120 + if (!(damagetype & DMG_BULLET))
121 + return HAM_IGNORED
122 +
123 + if (get_user_team(attacker) == get_user_team(victim))
124 + return HAM_IGNORED
125 +
126 + new w = g_iLastWeapon[attacker]
127 +
128 + if (w < 0 || w >= MAX_WEAPONS)
129 + return HAM_IGNORED
130 +
131 + g_iMapHits[attacker][w]++
132 + g_iLifeHits[attacker][w]++
133 +
134 + return HAM_IGNORED
135 +}
136 +
137 +weaponIndex(ent)
138 +{
139 + static cls[32]
140 + pev(ent, pev_classname, cls, charsmax(cls))
141 +
142 + for (new w = 0; w < MAX_WEAPONS; w++)
143 + {
144 + if (equal(cls, g_szWeapons[w]))
145 + return w
146 + }
147 +
148 + return -1
149 +}
150 +
151 +public cmdAcc(id)
152 +{
153 + client_print(id, print_console, " ")
154 + client_print(id, print_console, "----- CSB Accuracy (this map / lifetime) -----")
155 +
156 + for (new w = 0; w < MAX_WEAPONS; w++)
157 + {
158 + if (g_iMapShots[id][w] == 0 && g_iLifeShots[id][w] == 0)
159 + continue
160 +
161 + new name[24]
162 + copy(name, charsmax(name), g_szWeapons[w])
163 + replace(name, charsmax(name), "weapon_", "")
164 +
165 + new Float:mAcc = g_iMapShots[id][w] > 0
166 + ? 100.0 * float(g_iMapHits[id][w]) / float(g_iMapShots[id][w]) : 0.0
167 + new Float:lAcc = g_iLifeShots[id][w] > 0
168 + ? 100.0 * float(g_iLifeHits[id][w]) / float(g_iLifeShots[id][w]) : 0.0
169 +
170 + client_print(id, print_console, "%-12s map %4d/%4d (%5.1f%%) life %5d/%5d (%5.1f%%)",
171 + name, g_iMapHits[id][w], g_iMapShots[id][w], mAcc,
172 + g_iLifeHits[id][w], g_iLifeShots[id][w], lAcc)
173 + }
174 +
175 + client_print(id, print_chat, "[CSB] Accuracy table printed to your console.")
176 + return PLUGIN_HANDLED
177 +}
178 +
179 +loadPlayer(id)
180 +{
181 + if (g_iVault == -1)
182 + return
183 +
184 + new auth[36], key[44], data[1536]
185 + get_user_authid(id, auth, charsmax(auth))
186 +
187 + if (auth[0] == 0 || equal(auth, "STEAM_ID_PENDING"))
188 + return
189 +
190 + formatex(key, charsmax(key), "acc_%s", auth)
191 +
192 + if (nvault_get(g_iVault, key, data, charsmax(data)) < 1)
193 + return
194 +
195 + /* data: "shots0 hits0 shots1 hits1 ..." */
196 + new pos = 0, w = 0
197 + new val[16]
198 +
199 + while (w < MAX_WEAPONS)
200 + {
201 + pos = argparse(data, pos, val, charsmax(val))
202 +
203 + if (pos == -1)
204 + break
205 +
206 + g_iLifeShots[id][w] = str_to_num(val)
207 +
208 + pos = argparse(data, pos, val, charsmax(val))
209 +
210 + if (pos == -1)
211 + break
212 +
213 + g_iLifeHits[id][w] = str_to_num(val)
214 + w++
215 + }
216 +}
217 +
218 +savePlayer(id)
219 +{
220 + if (g_iVault == -1)
221 + return
222 +
223 + new auth[36], key[44]
224 + get_user_authid(id, auth, charsmax(auth))
225 +
226 + if (auth[0] == 0 || equal(auth, "STEAM_ID_PENDING"))
227 + return
228 +
229 + formatex(key, charsmax(key), "acc_%s", auth)
230 +
231 + new data[1536], len
232 + len = 0
233 +
234 + for (new w = 0; w < MAX_WEAPONS; w++)
235 + {
236 + len += formatex(data[len], charsmax(data) - len, "%d %d ",
237 + g_iLifeShots[id][w], g_iLifeHits[id][w])
238 + }
239 +
240 + nvault_set(g_iVault, key, data)
241 +}
+37 -0 csb.json A
@@ -0,0 +1,37 @@
1 +{
2 + "name": "CSB Accuracy Tracker",
3 + "category": "stats",
4 + "tags": "accuracy, shots, hits",
5 + "image": "",
6 + "original_author": "AMX Mod X StatsX",
7 + "original_url": "",
8 + "license": "GPL-3.0",
9 + "title": "CSB Accuracy Tracker",
10 + "short_desc": "Counts shots and hits per weapon, keeps per-map and lifetime accuracy in nVault, shown with /acc.",
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": "hamsandwich,fakemeta,nvault",
20 + "install_notes": "1. Compile the .sma (or use the site compiler)\n2. Put the .amxx in addons/amxmodx/plugins/\n3. Add it to addons/amxmodx/configs/plugins.ini\n4. Change map",
21 + "known_conflicts": "",
22 + "cvars": [
23 + {
24 + "name": "csb_acc_enabled",
25 + "default": "1",
26 + "description": "Reserved toggle for the tracker."
27 + }
28 + ],
29 + "commands": [
30 + {
31 + "name": "say /acc",
32 + "access": "",
33 + "description": "Print your per-weapon accuracy table to console."
34 + }
35 + ],
36 + "main": "addons/amxmodx/scripting/csb_accuracy_tracker.sma"
37 +}
0 38