Daemon666 / CSB Rules Menu Public

A /rules menu of server rules loaded from an ini, shown per-section as an MOTD, with a connect reminder and admin reload.

v1.0.0 143 descărcări GPL-3.0 Ultima actualizare Aug 24, 2026
csb_rules_menu.sma v1.0.0 174 linii · 4.5 KB Brut
1 /*
2 * CSB Rules Menu
3 * Copyright (C) 2026 counter-strike-boost.com
4 *
5 * "say /rules" opens a menu of the server rules, loaded from an ini split into
6 * [Section] blocks. Selecting a section shows its text in an MOTD window. Players
7 * who just connected get a short one-line reminder to read the rules, and admins
8 * can reload the ini without changing the map with amx_reloadrules.
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 <amxmisc>
20
21 new const PLUGIN[] = "CSB Rules Menu"
22 new const VERSION[] = "1.0.0"
23 new const AUTHOR[] = "counter-strike-boost.com"
24
25 #define MAX_SECTIONS 16
26
27 new g_szTitle[MAX_SECTIONS][48]
28 new g_szBody[MAX_SECTIONS][512]
29 new g_iSections
30
31 public plugin_init()
32 {
33 register_plugin(PLUGIN, VERSION, AUTHOR)
34
35 register_clcmd("say /rules", "cmdRules")
36 register_clcmd("say_team /rules", "cmdRules")
37
38 register_concmd("amx_reloadrules", "cmdReload", ADMIN_CFG, "- reload the server rules ini")
39 }
40
41 public plugin_cfg()
42 {
43 loadRules()
44 }
45
46 loadRules()
47 {
48 g_iSections = 0
49
50 new cfgdir[128], path[160]
51 get_localinfo("amxx_configsdir", cfgdir, charsmax(cfgdir))
52 formatex(path, charsmax(path), "%s/csb_rules.ini", cfgdir)
53
54 if (!file_exists(path))
55 {
56 /* fall back to a built-in rule set so the menu is never empty */
57 copy(g_szTitle[0], charsmax(g_szTitle[]), "General")
58 copy(g_szBody[0], charsmax(g_szBody[]),
59 "1. Respect all players and admins.^n2. No cheating of any kind.^n3. No advertising or spam.^n4. Admin decisions are final.")
60 g_iSections = 1
61 return
62 }
63
64 new f = fopen(path, "rt")
65
66 if (!f)
67 return
68
69 new line[256], cur = -1
70
71 while (!feof(f) && g_iSections < MAX_SECTIONS)
72 {
73 fgets(f, line, charsmax(line))
74 trim(line)
75
76 if (!line[0] || line[0] == ';' || line[0] == '#')
77 continue
78
79 if (line[0] == '[')
80 {
81 new title[48]
82 copy(title, charsmax(title), line[1])
83
84 new close = contain(title, "]")
85 if (close != -1)
86 title[close] = 0
87
88 trim(title)
89
90 cur = g_iSections
91 copy(g_szTitle[cur], charsmax(g_szTitle[]), title)
92 g_szBody[cur][0] = 0
93 g_iSections++
94 }
95 else if (cur >= 0)
96 {
97 if (g_szBody[cur][0])
98 add(g_szBody[cur], charsmax(g_szBody[]), "^n")
99
100 add(g_szBody[cur], charsmax(g_szBody[]), line)
101 }
102 }
103
104 fclose(f)
105
106 if (!g_iSections)
107 {
108 copy(g_szTitle[0], charsmax(g_szTitle[]), "General")
109 copy(g_szBody[0], charsmax(g_szBody[]), "Be excellent to each other.")
110 g_iSections = 1
111 }
112 }
113
114 public client_putinserver(id)
115 {
116 set_task(12.0, "taskReminder", id)
117 }
118
119 public taskReminder(id)
120 {
121 if (is_user_connected(id))
122 client_print(id, print_chat, "[CSB] Type /rules to read the server rules.")
123 }
124
125 public cmdRules(id)
126 {
127 new menu = menu_create("\yServer Rules\w - pick a section:", "rulesHandler")
128
129 new info[8]
130 for (new i = 0; i < g_iSections; i++)
131 {
132 num_to_str(i, info, charsmax(info))
133 menu_additem(menu, g_szTitle[i], info, 0)
134 }
135
136 menu_setprop(menu, MPROP_EXIT, MEXIT_ALL)
137 menu_display(id, menu, 0)
138 return PLUGIN_HANDLED
139 }
140
141 public rulesHandler(id, menu, item)
142 {
143 if (item == MENU_EXIT)
144 {
145 menu_destroy(menu)
146 return PLUGIN_HANDLED
147 }
148
149 new info[8], name[48], access, callback
150 menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback)
151 menu_destroy(menu)
152
153 new sec = str_to_num(info)
154
155 if (sec < 0 || sec >= g_iSections)
156 return PLUGIN_HANDLED
157
158 new head[64]
159 formatex(head, charsmax(head), "Rules - %s", g_szTitle[sec])
160 show_motd(id, g_szBody[sec], head)
161 return PLUGIN_HANDLED
162 }
163
164 public cmdReload(id, level, cid)
165 {
166 if (!cmd_access(id, level, cid, 1))
167 return PLUGIN_HANDLED
168
169 loadRules()
170 console_print(id, "[CSB] Reloaded %d rule section(s).", g_iSections)
171 client_print(id, print_chat, "[CSB] Rules reloaded (%d sections).", g_iSections)
172 return PLUGIN_HANDLED
173 }
174