Daemon666 / CSB Admin Menu Öffentlich

One flag-gated /admin menu for kick, ban, slay, slap, team moves, map change and the cvars you actually touch.

v1.0.0 151 Downloads GPL-3.0 Zuletzt aktualisiert Aug 23, 2026
csb_admin_menu.sma v1.0.0 502 Zeilen · 13.1 KB Rohtext
1 /*
2 * CSB Admin Menu
3 * Copyright (C) 2026 counter-strike-boost.com
4 *
5 * A central, flag-gated administration menu for AMX Mod X.
6 * Inspired by the classic "Admin Commands / amxmodmenu" plugin shipped with
7 * AMX Mod X by the AMX Mod X Development Team. This is an independent GPL
8 * re-implementation, not a copy of their source.
9 *
10 * This program is free software: you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation, either version 3 of the License, or (at your
13 * option) any later version. It is distributed in the hope that it will be
14 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details: <https://www.gnu.org/licenses/>.
17 */
18
19 #include <amxmodx>
20 #include <amxmisc>
21 #include <cstrike>
22 #include <fun>
23
24 new const PLUGIN[] = "CSB Admin Menu"
25 new const VERSION[] = "1.0.0"
26 new const AUTHOR[] = "counter-strike-boost.com"
27
28 #define ACT_KICK 1
29 #define ACT_BAN 2
30 #define ACT_SLAY 3
31 #define ACT_SLAP 4
32 #define ACT_MOVE_T 5
33 #define ACT_MOVE_CT 6
34
35 new g_pEnabled, g_pBanTime, g_pSlapDamage
36 new g_iTargetUserid[33]
37
38 new const g_szCvarName[][] =
39 {
40 "mp_friendlyfire",
41 "mp_freezetime",
42 "mp_roundtime",
43 "sv_gravity",
44 "mp_autoteambalance",
45 "sv_alltalk"
46 }
47
48 new const g_szCvarValues[][] =
49 {
50 "0 1",
51 "0 3 6 10",
52 "1.75 2.5 5",
53 "400 600 800 1000",
54 "0 1",
55 "0 1"
56 }
57
58 public plugin_init()
59 {
60 register_plugin(PLUGIN, VERSION, AUTHOR)
61
62 g_pEnabled = register_cvar("csb_adminmenu_enabled", "1")
63 g_pBanTime = register_cvar("csb_adminmenu_bantime", "30")
64 g_pSlapDamage = register_cvar("csb_adminmenu_slapdmg", "5")
65
66 register_clcmd("amx_csbmenu", "cmdMenu", ADMIN_MENU, "- opens the CSB admin menu")
67 register_clcmd("say /admin", "cmdMenu", ADMIN_MENU, "- opens the CSB admin menu")
68 register_clcmd("say_team /admin", "cmdMenu", ADMIN_MENU, "- opens the CSB admin menu")
69 }
70
71 public cmdMenu(id, level, cid)
72 {
73 if (!cmd_access(id, level, cid, 1))
74 return PLUGIN_HANDLED
75
76 if (!get_pcvar_num(g_pEnabled))
77 {
78 client_print(id, print_chat, "[CSB] The admin menu is disabled (csb_adminmenu_enabled 0).")
79 return PLUGIN_HANDLED
80 }
81
82 showMainMenu(id)
83 return PLUGIN_HANDLED
84 }
85
86 showMainMenu(id)
87 {
88 new menu = menu_create("\yCSB Admin Menu^n\wPick a category", "handlerMain")
89
90 menu_additem(menu, "Player commands", "1", 0)
91 menu_additem(menu, "Change map", "2", 0)
92 menu_additem(menu, "Server cvars", "3", 0)
93 menu_additem(menu, "Swap teams", "4", 0)
94 menu_additem(menu, "Restart round", "5", 0)
95
96 menu_setprop(menu, MPROP_EXITNAME, "Close")
97 menu_display(id, menu, 0)
98 }
99
100 public handlerMain(id, menu, item)
101 {
102 if (item == MENU_EXIT)
103 {
104 menu_destroy(menu)
105 return PLUGIN_HANDLED
106 }
107
108 new info[8], name[32], access, callback
109 menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback)
110 menu_destroy(menu)
111
112 switch (str_to_num(info))
113 {
114 case 1: showPlayerMenu(id)
115 case 2: showMapMenu(id)
116 case 3: showCvarMenu(id)
117 case 4:
118 {
119 if (!(get_user_flags(id) & ADMIN_LEVEL_A))
120 {
121 client_print(id, print_chat, "[CSB] You do not have access to team swapping.")
122 return PLUGIN_HANDLED
123 }
124 swapTeams(id)
125 }
126 case 5:
127 {
128 if (!(get_user_flags(id) & ADMIN_CVAR))
129 {
130 client_print(id, print_chat, "[CSB] You do not have access to round control.")
131 return PLUGIN_HANDLED
132 }
133 server_cmd("sv_restartround 1")
134 announce(id, "restarted the round")
135 }
136 }
137
138 return PLUGIN_HANDLED
139 }
140
141 showPlayerMenu(id)
142 {
143 new menu = menu_create("\yCSB Admin Menu^n\wSelect a player", "handlerPlayer")
144 new players[32], num, pid, pname[32], info[8], line[64]
145
146 get_players(players, num, "ch")
147
148 for (new i = 0; i < num; i++)
149 {
150 pid = players[i]
151 get_user_name(pid, pname, charsmax(pname))
152 formatex(info, charsmax(info), "%d", get_user_userid(pid))
153 formatex(line, charsmax(line), "%s \r[%s]", pname, is_user_alive(pid) ? "alive" : "dead")
154 menu_additem(menu, line, info, 0)
155 }
156
157 menu_setprop(menu, MPROP_EXITNAME, "Back")
158 menu_display(id, menu, 0)
159 }
160
161 public handlerPlayer(id, menu, item)
162 {
163 if (item == MENU_EXIT)
164 {
165 menu_destroy(menu)
166 showMainMenu(id)
167 return PLUGIN_HANDLED
168 }
169
170 new info[8], name[32], access, callback
171 menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback)
172 menu_destroy(menu)
173
174 g_iTargetUserid[id] = str_to_num(info)
175 showActionMenu(id)
176 return PLUGIN_HANDLED
177 }
178
179 showActionMenu(id)
180 {
181 new target = find_player("k", g_iTargetUserid[id])
182
183 if (!target)
184 {
185 client_print(id, print_chat, "[CSB] That player already left the server.")
186 showPlayerMenu(id)
187 return
188 }
189
190 new pname[32], title[96]
191 get_user_name(target, pname, charsmax(pname))
192 formatex(title, charsmax(title), "\yCSB Admin Menu^n\wTarget: \r%s", pname)
193
194 new menu = menu_create(title, "handlerAction")
195
196 menu_additem(menu, "Kick", "1", 0)
197 menu_additem(menu, "Ban", "2", 0)
198 menu_additem(menu, "Slay", "3", 0)
199 menu_additem(menu, "Slap", "4", 0)
200 menu_additem(menu, "Move to T", "5", 0)
201 menu_additem(menu, "Move to CT", "6", 0)
202
203 menu_setprop(menu, MPROP_EXITNAME, "Back")
204 menu_display(id, menu, 0)
205 }
206
207 public handlerAction(id, menu, item)
208 {
209 if (item == MENU_EXIT)
210 {
211 menu_destroy(menu)
212 showPlayerMenu(id)
213 return PLUGIN_HANDLED
214 }
215
216 new info[8], name[32], access, callback
217 menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback)
218 menu_destroy(menu)
219
220 new action = str_to_num(info)
221 new target = find_player("k", g_iTargetUserid[id])
222
223 if (!target)
224 {
225 client_print(id, print_chat, "[CSB] That player already left the server.")
226 return PLUGIN_HANDLED
227 }
228
229 if (get_user_flags(target) & ADMIN_IMMUNITY)
230 {
231 client_print(id, print_chat, "[CSB] That player is immune.")
232 return PLUGIN_HANDLED
233 }
234
235 new flags = get_user_flags(id)
236 new tname[32], what[64]
237 get_user_name(target, tname, charsmax(tname))
238
239 switch (action)
240 {
241 case ACT_KICK:
242 {
243 if (!(flags & ADMIN_KICK)) { noAccess(id); return PLUGIN_HANDLED; }
244 server_cmd("kick #%d ^"Kicked by an admin^"", get_user_userid(target))
245 formatex(what, charsmax(what), "kicked %s", tname)
246 }
247 case ACT_BAN:
248 {
249 if (!(flags & ADMIN_BAN)) { noAccess(id); return PLUGIN_HANDLED; }
250 new mins = get_pcvar_num(g_pBanTime)
251 server_cmd("banid %d #%d kick", mins, get_user_userid(target))
252 server_cmd("writeid")
253 formatex(what, charsmax(what), "banned %s for %d minutes", tname, mins)
254 }
255 case ACT_SLAY:
256 {
257 if (!(flags & ADMIN_SLAY)) { noAccess(id); return PLUGIN_HANDLED; }
258 if (!is_user_alive(target))
259 {
260 client_print(id, print_chat, "[CSB] %s is already dead.", tname)
261 return PLUGIN_HANDLED
262 }
263 user_kill(target, 1)
264 formatex(what, charsmax(what), "slayed %s", tname)
265 }
266 case ACT_SLAP:
267 {
268 if (!(flags & ADMIN_SLAY)) { noAccess(id); return PLUGIN_HANDLED; }
269 if (!is_user_alive(target))
270 {
271 client_print(id, print_chat, "[CSB] %s is already dead.", tname)
272 return PLUGIN_HANDLED
273 }
274 user_slap(target, get_pcvar_num(g_pSlapDamage))
275 formatex(what, charsmax(what), "slapped %s", tname)
276 }
277 case ACT_MOVE_T, ACT_MOVE_CT:
278 {
279 if (!(flags & ADMIN_LEVEL_A)) { noAccess(id); return PLUGIN_HANDLED; }
280 new CsTeams:team = (action == ACT_MOVE_T) ? CS_TEAM_T : CS_TEAM_CT
281 if (is_user_alive(target))
282 user_kill(target, 1)
283 cs_set_user_team(target, team)
284 formatex(what, charsmax(what), "moved %s to %s", tname, (action == ACT_MOVE_T) ? "Terrorists" : "Counter-Terrorists")
285 }
286 }
287
288 announce(id, what)
289 showActionMenu(id)
290 return PLUGIN_HANDLED
291 }
292
293 showMapMenu(id)
294 {
295 if (!(get_user_flags(id) & ADMIN_MAP))
296 {
297 noAccess(id)
298 return
299 }
300
301 new menu = menu_create("\yCSB Admin Menu^n\wChange map", "handlerMap")
302 new line[64], txtlen, added = 0
303
304 for (new i = 0; i < 128; i++)
305 {
306 if (!read_file("mapcycle.txt", i, line, charsmax(line), txtlen))
307 break
308
309 trim(line)
310
311 if (!line[0] || line[0] == ';' || line[0] == '/')
312 continue
313
314 if (!is_map_valid(line))
315 continue
316
317 menu_additem(menu, line, line, 0)
318 added++
319 }
320
321 if (!added)
322 {
323 menu_destroy(menu)
324 client_print(id, print_chat, "[CSB] mapcycle.txt is empty or unreadable.")
325 return
326 }
327
328 menu_setprop(menu, MPROP_EXITNAME, "Back")
329 menu_display(id, menu, 0)
330 }
331
332 public handlerMap(id, menu, item)
333 {
334 if (item == MENU_EXIT)
335 {
336 menu_destroy(menu)
337 showMainMenu(id)
338 return PLUGIN_HANDLED
339 }
340
341 new map[32], name[32], access, callback
342 menu_item_getinfo(menu, item, access, map, charsmax(map), name, charsmax(name), callback)
343 menu_destroy(menu)
344
345 if (!is_map_valid(map))
346 {
347 client_print(id, print_chat, "[CSB] %s is not a valid map on this server.", map)
348 return PLUGIN_HANDLED
349 }
350
351 new what[64]
352 formatex(what, charsmax(what), "changed the map to %s", map)
353 announce(id, what)
354
355 set_task(3.0, "taskChangeLevel", 0, map, strlen(map) + 1)
356 return PLUGIN_HANDLED
357 }
358
359 public taskChangeLevel(map[])
360 {
361 server_cmd("changelevel %s", map)
362 }
363
364 showCvarMenu(id)
365 {
366 if (!(get_user_flags(id) & ADMIN_CVAR))
367 {
368 noAccess(id)
369 return
370 }
371
372 new menu = menu_create("\yCSB Admin Menu^n\wServer cvars (click to cycle)", "handlerCvar")
373 new line[64], value[16], info[8]
374
375 for (new i = 0; i < sizeof(g_szCvarName); i++)
376 {
377 get_cvar_string(g_szCvarName[i], value, charsmax(value))
378 formatex(line, charsmax(line), "%s \r[%s]", g_szCvarName[i], value)
379 formatex(info, charsmax(info), "%d", i)
380 menu_additem(menu, line, info, 0)
381 }
382
383 menu_setprop(menu, MPROP_EXITNAME, "Back")
384 menu_display(id, menu, 0)
385 }
386
387 public handlerCvar(id, menu, item)
388 {
389 if (item == MENU_EXIT)
390 {
391 menu_destroy(menu)
392 showMainMenu(id)
393 return PLUGIN_HANDLED
394 }
395
396 new info[8], name[64], access, callback
397 menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback)
398 menu_destroy(menu)
399
400 new idx = str_to_num(info)
401
402 if (idx < 0 || idx >= sizeof(g_szCvarName))
403 return PLUGIN_HANDLED
404
405 new cur[16], next[16], what[96]
406 get_cvar_string(g_szCvarName[idx], cur, charsmax(cur))
407 nextValue(g_szCvarValues[idx], cur, next, charsmax(next))
408 set_cvar_string(g_szCvarName[idx], next)
409
410 formatex(what, charsmax(what), "set %s to %s", g_szCvarName[idx], next)
411 announce(id, what)
412
413 showCvarMenu(id)
414 return PLUGIN_HANDLED
415 }
416
417 swapTeams(id)
418 {
419 new players[32], num, pid
420 get_players(players, num, "ch")
421
422 for (new i = 0; i < num; i++)
423 {
424 pid = players[i]
425 new CsTeams:team = cs_get_user_team(pid)
426
427 if (team == CS_TEAM_T)
428 cs_set_user_team(pid, CS_TEAM_CT)
429 else if (team == CS_TEAM_CT)
430 cs_set_user_team(pid, CS_TEAM_T)
431 }
432
433 server_cmd("sv_restartround 1")
434 announce(id, "swapped the teams")
435 }
436
437 nextValue(const list[], const cur[], out[], len)
438 {
439 new piece[16], first[16], pos = 0, i, found = 0
440 new listlen = strlen(list)
441
442 first[0] = 0
443
444 while (pos < listlen)
445 {
446 i = 0
447
448 while (pos < listlen && list[pos] != ' ')
449 {
450 if (i < charsmax(piece))
451 piece[i++] = list[pos]
452 pos++
453 }
454
455 piece[i] = 0
456
457 while (pos < listlen && list[pos] == ' ')
458 pos++
459
460 if (!first[0])
461 copy(first, charsmax(first), piece)
462
463 if (found)
464 {
465 copy(out, len, piece)
466 return
467 }
468
469 if (equal(piece, cur))
470 found = 1
471 }
472
473 copy(out, len, first)
474 }
475
476 announce(id, const what[])
477 {
478 new aname[32], authid[35], buf[192]
479 get_user_name(id, aname, charsmax(aname))
480 get_user_authid(id, authid, charsmax(authid))
481
482 formatex(buf, charsmax(buf), "^x04[CSB]^x03 %s^x01 %s.", aname, what)
483
484 new players[32], num, msgid = get_user_msgid("SayText")
485 get_players(players, num, "ch")
486
487 for (new i = 0; i < num; i++)
488 {
489 message_begin(MSG_ONE, msgid, _, players[i])
490 write_byte(players[i])
491 write_string(buf)
492 message_end()
493 }
494
495 log_amx("[CSB Admin Menu] %s <%s> %s", aname, authid, what)
496 }
497
498 noAccess(id)
499 {
500 client_print(id, print_chat, "[CSB] You do not have the required access flag for that action.")
501 }
502