summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-06 16:30:10 +0100
committersalmonik <salmonik@tuta.io>2026-11-06 16:30:10 +0100
commite339d1dc45b3113648552b0002e0c15f55e61cb2 (patch)
tree4570dc0ba1501ea26e87447d234693ad5532e813
parentdocs: record the esp.cpp split in the plan (diff)
downloadhl2h-e339d1dc45b3113648552b0002e0c15f55e61cb2.tar.gz
hl2h-e339d1dc45b3113648552b0002e0c15f55e61cb2.zip
Config: generate save/load/reset from one settings table
Every persisted setting now lives in a single descriptor table (config_table.cpp) with its section, key, type, default and clamp range. config_save(), config_load() and config_reset_defaults() iterate it, so the three functions can no longer disagree about defaults or bounds, and the old hand-written 350-line parser is gone. Section and key names are unchanged, so existing config files keep loading, and the duplicated [view] scalar clamp block is replaced by per-entry limits.
-rw-r--r--src/config_table.cpp230
-rw-r--r--src/features.h5
-rw-r--r--src/menu.cpp513
3 files changed, 238 insertions, 510 deletions
diff --git a/src/config_table.cpp b/src/config_table.cpp
new file mode 100644
index 0000000..f688d12
--- /dev/null
+++ b/src/config_table.cpp
@@ -0,0 +1,230 @@
1// config_table.cpp — every persisted setting in one descriptor table.
2//
3// config_save(), config_load() and config_reset_defaults() are generated from
4// this table, so adding an option no longer means editing three functions (and
5// getting the clamp bounds out of sync between them).
6#include "hl2h.h"
7
8#include <cstdlib>
9
10namespace {
11
12enum SettingType { S_BOOL, S_INT };
13
14struct SettingDesc {
15 const char *section;
16 const char *key;
17 SettingType type;
18 void *ptr;
19 int def;
20 int lo;
21 int hi;
22};
23
24// A FeatureState is persisted as the usual active/bind pair.
25#define FEAT(sec, state, def_active, def_bind) \
26 {sec, "active", S_BOOL, &(state).active, def_active, 0, 1}, \
27 {sec, "bind", S_INT, &(state).bind, def_bind, 0, 1000}
28
29const SettingDesc kSettings[] = {
30 // movement
31 FEAT("bhop", g_bhop, 1, 0),
32 {"bhop", "autostrafe", S_BOOL, &g_bhop_autostrafe, 1, 0, 1},
33 FEAT("abh", g_abh, 1, 0),
34 FEAT("jumpbug", g_jumpbug, 1, 0),
35 {"jumpbug", "assist", S_BOOL, &g_jumpbug_assist, 0, 0, 1},
36 FEAT("melee", g_melee, 1, 0),
37 {"movement", "crouchjump", S_BOOL, &g_auto_crouchjump, 0, 0, 1},
38 {"movement", "edgejump", S_BOOL, &g_edge_jump, 0, 0, 1},
39
40 // spread
41 FEAT("spread", g_spread, 1, 0),
42 {"spread", "no_spread", S_BOOL, &g_spread_no_spread, 1, 0, 1},
43 {"spread", "engine", S_BOOL, &g_spread_engine, 1, 0, 1},
44
45 // aim
46 FEAT("aimbot", g_aimbot, 1, 604),
47 {"aimbot", "smooth", S_INT, &g_aim_smooth, 5, 1, 45},
48 {"aimbot", "vischeck", S_BOOL, &g_aim_vischeck, 1, 0, 1},
49 {"aimbot", "fov", S_INT, &g_aim_fov, 60, 1, 180},
50 {"aimbot", "fov_circle", S_BOOL, &g_aim_fov_circle, 1, 0, 1},
51 {"aimbot", "punch", S_BOOL, &g_aim_punch, 1, 0, 1},
52 {"aimbot", "bone_head", S_BOOL, &g_aim_bones[AIM_BONE_HEAD], 1, 0, 1},
53 {"aimbot", "bone_torso", S_BOOL, &g_aim_bones[AIM_BONE_TORSO], 0, 0, 1},
54 {"aimbot", "bone_larm", S_BOOL, &g_aim_bones[AIM_BONE_LARM], 0, 0, 1},
55 {"aimbot", "bone_rarm", S_BOOL, &g_aim_bones[AIM_BONE_RARM], 0, 0, 1},
56 {"aimbot", "bone_lleg", S_BOOL, &g_aim_bones[AIM_BONE_LLEG], 0, 0, 1},
57 {"aimbot", "bone_rleg", S_BOOL, &g_aim_bones[AIM_BONE_RLEG], 0, 0, 1},
58 FEAT("triggerbot", g_triggerbot, 1, 603),
59 FEAT("silentaim", g_silentaim, 1, 602),
60
61 // view
62 {"view", "fov", S_INT, &g_fov_camera, 75, 40, 140},
63 {"view", "vmfov", S_INT, &g_fov_viewmodel, 54, 20, 120},
64 {"view", "tonemap", S_INT, &g_tonemap, 0, 0, 30},
65
66 // esp
67 FEAT("esp", g_esp, 1, 0),
68 {"esp", "neutral", S_BOOL, &g_esp_opt[ESP_OPT_SHOW_NEUTRAL], 1, 0, 1},
69 {"esp", "healthbar", S_BOOL, &g_esp_opt[ESP_OPT_SHOW_HEALTHBAR], 1, 0, 1},
70 {"esp", "healthnum", S_BOOL, &g_esp_opt[ESP_OPT_SHOW_HEALTHNUM], 1, 0, 1},
71 {"esp", "name", S_BOOL, &g_esp_opt[ESP_OPT_SHOW_NAME], 1, 0, 1},
72 {"esp", "skeleton", S_BOOL, &g_esp_opt[ESP_OPT_SHOW_SKELETON], 1, 0, 1},
73 {"esp", "box", S_BOOL, &g_esp_opt[ESP_OPT_SHOW_BOX], 1, 0, 1},
74 {"esp", "speedgraph", S_BOOL, &g_esp_opt[ESP_OPT_SHOW_SPEEDGRAPH], 1, 0, 1},
75 {"esp", "dmg", S_BOOL, &g_esp_opt[ESP_OPT_DAMAGE_TAGS], 1, 0, 1},
76 {"esp", "alert", S_BOOL, &g_esp_opt[ESP_OPT_ALERT], 1, 0, 1},
77 {"esp", "weapon", S_BOOL, &g_esp_opt[ESP_OPT_WEAPON], 1, 0, 1},
78 {"esp", "arrows", S_BOOL, &g_esp_opt[ESP_OPT_ARROWS], 1, 0, 1},
79 {"esp", "hr", S_INT, &g_esp_col_hostile[0], 255, 0, 255},
80 {"esp", "hg", S_INT, &g_esp_col_hostile[1], 60, 0, 255},
81 {"esp", "hb", S_INT, &g_esp_col_hostile[2], 60, 0, 255},
82 {"esp", "nr", S_INT, &g_esp_col_neutral[0], 220, 0, 255},
83 {"esp", "ng", S_INT, &g_esp_col_neutral[1], 220, 0, 255},
84 {"esp", "nb", S_INT, &g_esp_col_neutral[2], 220, 0, 255},
85 {"esp", "fr", S_INT, &g_esp_col_friendly[0], 60, 0, 255},
86 {"esp", "fg", S_INT, &g_esp_col_friendly[1], 255, 0, 255},
87 {"esp", "fb", S_INT, &g_esp_col_friendly[2], 60, 0, 255},
88
89 // items
90 FEAT("items", g_item_esp, 1, 0),
91 {"items", "health", S_BOOL, &g_item_health, 1, 0, 1},
92 {"items", "ammo", S_BOOL, &g_item_ammo, 1, 0, 1},
93 {"items", "armor", S_BOOL, &g_item_armor, 1, 0, 1},
94 {"items", "weapons", S_BOOL, &g_item_weapons, 1, 0, 1},
95 {"items", "crates", S_BOOL, &g_item_crates, 1, 0, 1},
96 {"items", "distance", S_BOOL, &g_item_distance, 1, 0, 1},
97 {"items", "usable", S_BOOL, &g_item_usable, 1, 0, 1},
98 {"items", "max_dist", S_INT, &g_item_max_dist, 5000, 0, 10000},
99
100 // projectiles
101 FEAT("projectiles", g_projectiles, 1, 0),
102 {"projectiles", "fuse", S_BOOL, &g_proj_fuse, 1, 0, 1},
103 {"projectiles", "radius", S_BOOL, &g_proj_radius, 1, 0, 1},
104 {"projectiles", "trajectory", S_BOOL, &g_proj_traj, 1, 0, 1},
105
106 // chams
107 FEAT("chams", g_chams, 0, 0),
108#define CHAMS_GROUP(sec, grp, von, vr, vg, vb, ion, ir, ig, ib) \
109 {sec, "vis", S_BOOL, &(grp).vis_on, von, 0, 1}, \
110 {sec, "vis_mat", S_INT, &(grp).vis_mat, 3, 0, 6}, \
111 {sec, "vis_r", S_INT, &(grp).vis_rgb[0], vr, 0, 255}, \
112 {sec, "vis_g", S_INT, &(grp).vis_rgb[1], vg, 0, 255}, \
113 {sec, "vis_b", S_INT, &(grp).vis_rgb[2], vb, 0, 255}, \
114 {sec, "vis_a", S_INT, &(grp).vis_rgb[3], 255, 0, 255}, \
115 {sec, "inv", S_BOOL, &(grp).inv_on, ion, 0, 1}, \
116 {sec, "inv_mat", S_INT, &(grp).inv_mat, 3, 0, 6}, \
117 {sec, "inv_r", S_INT, &(grp).inv_rgb[0], ir, 0, 255}, \
118 {sec, "inv_g", S_INT, &(grp).inv_rgb[1], ig, 0, 255}, \
119 {sec, "inv_b", S_INT, &(grp).inv_rgb[2], ib, 0, 255}, \
120 {sec, "inv_a", S_INT, &(grp).inv_rgb[3], 255, 0, 255}
121 CHAMS_GROUP("chams_hostile", g_chams_hostile, 1, 255, 60, 60, 1, 255, 60,
122 60),
123 CHAMS_GROUP("chams_neutral", g_chams_neutral, 1, 220, 220, 220, 0, 220, 220,
124 220),
125 CHAMS_GROUP("chams_friendly", g_chams_friendly, 1, 60, 255, 60, 0, 60, 255,
126 60),
127#undef CHAMS_GROUP
128 {"chams_vm", "on", S_BOOL, &g_chams_viewmodel, 0, 0, 1},
129 {"chams_vm", "mat", S_INT, &g_chams_vm_mat, 3, 0, 6},
130 {"chams_vm", "r", S_INT, &g_chams_vm_rgb[0], 200, 0, 255},
131 {"chams_vm", "g", S_INT, &g_chams_vm_rgb[1], 200, 0, 255},
132 {"chams_vm", "b", S_INT, &g_chams_vm_rgb[2], 255, 0, 255},
133 {"chams_vm", "a", S_INT, &g_chams_vm_rgb[3], 255, 0, 255},
134
135 // visuals
136 FEAT("fullbright", g_fullbright, 0, 0),
137 FEAT("worldtint", g_world_tint, 0, 0),
138 {"worldtint", "world", S_BOOL, &g_tint_world_on, 1, 0, 1},
139 {"worldtint", "sky", S_BOOL, &g_tint_sky_on, 1, 0, 1},
140 {"worldtint", "prop", S_BOOL, &g_tint_prop_on, 1, 0, 1},
141 {"worldtint", "wr", S_INT, &g_tint_world_rgb[0], 255, 0, 255},
142 {"worldtint", "wg", S_INT, &g_tint_world_rgb[1], 255, 0, 255},
143 {"worldtint", "wb", S_INT, &g_tint_world_rgb[2], 255, 0, 255},
144 {"worldtint", "sr", S_INT, &g_tint_sky_rgb[0], 255, 0, 255},
145 {"worldtint", "sg", S_INT, &g_tint_sky_rgb[1], 255, 0, 255},
146 {"worldtint", "sb", S_INT, &g_tint_sky_rgb[2], 255, 0, 255},
147 {"worldtint", "pr", S_INT, &g_tint_prop_rgb[0], 255, 0, 255},
148 {"worldtint", "pg", S_INT, &g_tint_prop_rgb[1], 255, 0, 255},
149 {"worldtint", "pb", S_INT, &g_tint_prop_rgb[2], 255, 0, 255},
150 FEAT("fog", g_fog, 0, 0),
151 {"fog", "r", S_INT, &g_fog_rgb[0], 160, 0, 255},
152 {"fog", "g", S_INT, &g_fog_rgb[1], 170, 0, 255},
153 {"fog", "b", S_INT, &g_fog_rgb[2], 190, 0, 255},
154 {"fog", "start", S_INT, &g_fog_start, 200, 0, 8000},
155 {"fog", "end", S_INT, &g_fog_end, 3000, 0, 20000},
156 {"fog", "skybox", S_BOOL, &g_fog_skybox, 1, 0, 1},
157 {"fog", "disable", S_BOOL, &g_fog_disable, 0, 0, 1},
158 FEAT("skybox", g_skybox, 0, 0),
159};
160
161constexpr int kSettingCount = (int)(sizeof(kSettings) / sizeof(kSettings[0]));
162
163const SettingDesc *find_setting(const char *section, const char *key) {
164 for (int i = 0; i < kSettingCount; i++) {
165 if (strcmp(kSettings[i].section, section) == 0 &&
166 strcmp(kSettings[i].key, key) == 0)
167 return &kSettings[i];
168 }
169 return nullptr;
170}
171
172} // namespace
173
174void settings_save(FILE *f) {
175 const char *section = nullptr;
176 for (int i = 0; i < kSettingCount; i++) {
177 const SettingDesc &s = kSettings[i];
178 if (!section || strcmp(section, s.section) != 0) {
179 fprintf(f, "\n[%s]\n", s.section);
180 section = s.section;
181 }
182 int v = s.type == S_BOOL ? (*(bool *)s.ptr ? 1 : 0) : *(int *)s.ptr;
183 fprintf(f, "%s=%d\n", s.key, v);
184 }
185}
186
187void settings_load(FILE *f) {
188 char line[256];
189 char section[64] = "";
190 while (fgets(line, sizeof(line), f)) {
191 line[strcspn(line, "\r\n")] = 0;
192 if (line[0] == '[') {
193 const char *end = strchr(line, ']');
194 if (!end)
195 continue;
196 size_t n = (size_t)(end - line - 1);
197 if (n >= sizeof(section))
198 n = sizeof(section) - 1;
199 memcpy(section, line + 1, n);
200 section[n] = 0;
201 continue;
202 }
203 char *eq = strchr(line, '=');
204 if (!eq)
205 continue;
206 *eq = 0;
207 const SettingDesc *d = find_setting(section, line);
208 if (!d)
209 continue; // [gui] and unknown keys belong to other readers
210 int v = atoi(eq + 1);
211 if (v < d->lo)
212 v = d->lo;
213 if (v > d->hi)
214 v = d->hi;
215 if (d->type == S_BOOL)
216 *(bool *)d->ptr = v != 0;
217 else
218 *(int *)d->ptr = v;
219 }
220}
221
222void settings_reset_defaults() {
223 for (int i = 0; i < kSettingCount; i++) {
224 const SettingDesc &s = kSettings[i];
225 if (s.type == S_BOOL)
226 *(bool *)s.ptr = s.def != 0;
227 else
228 *(int *)s.ptr = s.def;
229 }
230}
diff --git a/src/features.h b/src/features.h
index 6890aa6..b4616a1 100644
--- a/src/features.h
+++ b/src/features.h
@@ -133,4 +133,9 @@ QAngle gui_frozen_view();
133void gui_config_init(); 133void gui_config_init();
134void gui_config_write(FILE *f); 134void gui_config_write(FILE *f);
135 135
136// Declarative settings persistence (config_table.cpp).
137void settings_save(FILE *f);
138void settings_load(FILE *f);
139void settings_reset_defaults();
140
136#endif 141#endif
diff --git a/src/menu.cpp b/src/menu.cpp
index f3a9bb9..d2f6787 100644
--- a/src/menu.cpp
+++ b/src/menu.cpp
@@ -203,91 +203,7 @@ void config_save() {
203 toastf(TOAST_ERROR, "Config save failed: %s", path.c_str()); 203 toastf(TOAST_ERROR, "Config save failed: %s", path.c_str());
204 return; 204 return;
205 } 205 }
206 fprintf(f, "[bhop]\nactive=%d\nbind=%d\nautostrafe=%d\n", g_bhop.active, 206 settings_save(f);
207 g_bhop.bind, g_bhop_autostrafe);
208 fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind);
209 fprintf(f, "[jumpbug]\nactive=%d\nbind=%d\nassist=%d\n",
210 g_jumpbug.active, g_jumpbug.bind, (int)g_jumpbug_assist);
211 fprintf(f, "[melee]\nactive=%d\nbind=%d\n", g_melee.active, g_melee.bind);
212 fprintf(f, "[spread]\nactive=%d\nbind=%d\nno_spread=%d\nengine=%d\n",
213 g_spread.active, g_spread.bind, (int)g_spread_no_spread,
214 (int)g_spread_engine);
215 fprintf(f, "[aimbot]\nactive=%d\nbind=%d\nsmooth=%d\nvischeck=%d\n"
216 "fov=%d\nfov_circle=%d\npunch=%d\n"
217 "bone_head=%d\nbone_torso=%d\nbone_larm=%d\nbone_rarm=%d\n"
218 "bone_lleg=%d\nbone_rleg=%d\n",
219 g_aimbot.active, g_aimbot.bind, g_aim_smooth,
220 (int)g_aim_vischeck, g_aim_fov, (int)g_aim_fov_circle,
221 (int)g_aim_punch, g_aim_bones[AIM_BONE_HEAD],
222 g_aim_bones[AIM_BONE_TORSO], g_aim_bones[AIM_BONE_LARM],
223 g_aim_bones[AIM_BONE_RARM], g_aim_bones[AIM_BONE_LLEG],
224 g_aim_bones[AIM_BONE_RLEG]);
225 fprintf(f, "[triggerbot]\nactive=%d\nbind=%d\n", g_triggerbot.active,
226 g_triggerbot.bind);
227 fprintf(f, "[silentaim]\nactive=%d\nbind=%d\n", g_silentaim.active,
228 g_silentaim.bind);
229 fprintf(f, "[fullbright]\nactive=%d\nbind=%d\n", g_fullbright.active,
230 g_fullbright.bind);
231 fprintf(f, "[worldtint]\nactive=%d\nbind=%d\nworld=%d\nsky=%d\n"
232 "prop=%d\nwr=%d\nwg=%d\nwb=%d\nsr=%d\nsg=%d\nsb=%d\n"
233 "pr=%d\npg=%d\npb=%d\n",
234 g_world_tint.active, g_world_tint.bind, (int)g_tint_world_on,
235 (int)g_tint_sky_on, (int)g_tint_prop_on, g_tint_world_rgb[0],
236 g_tint_world_rgb[1], g_tint_world_rgb[2], g_tint_sky_rgb[0],
237 g_tint_sky_rgb[1], g_tint_sky_rgb[2], g_tint_prop_rgb[0],
238 g_tint_prop_rgb[1], g_tint_prop_rgb[2]);
239 fprintf(f, "[fog]\nactive=%d\nbind=%d\nr=%d\ng=%d\nb=%d\n"
240 "start=%d\nend=%d\nskybox=%d\ndisable=%d\n",
241 g_fog.active, g_fog.bind, g_fog_rgb[0], g_fog_rgb[1], g_fog_rgb[2],
242 g_fog_start, g_fog_end, (int)g_fog_skybox, (int)g_fog_disable);
243 fprintf(f, "[skybox]\nactive=%d\nbind=%d\n", g_skybox.active,
244 g_skybox.bind);
245 fprintf(f, "[projectiles]\nactive=%d\nbind=%d\nfuse=%d\nradius=%d\n"
246 "trajectory=%d\n",
247 g_projectiles.active, g_projectiles.bind, (int)g_proj_fuse,
248 (int)g_proj_radius, (int)g_proj_traj);
249 fprintf(f, "[chams]\nactive=%d\nbind=%d\n", g_chams.active, g_chams.bind);
250 auto save_chams = [&](const char *name, const ChamsGroup &g) {
251 fprintf(f, "[%s]\nvis=%d\nvis_mat=%d\nvis_r=%d\nvis_g=%d\nvis_b=%d\n"
252 "vis_a=%d\ninv=%d\ninv_mat=%d\ninv_r=%d\ninv_g=%d\ninv_b=%d\n"
253 "inv_a=%d\n",
254 name, (int)g.vis_on, g.vis_mat, g.vis_rgb[0], g.vis_rgb[1],
255 g.vis_rgb[2], g.vis_rgb[3], (int)g.inv_on, g.inv_mat,
256 g.inv_rgb[0], g.inv_rgb[1], g.inv_rgb[2], g.inv_rgb[3]);
257 };
258 save_chams("chams_hostile", g_chams_hostile);
259 save_chams("chams_neutral", g_chams_neutral);
260 save_chams("chams_friendly", g_chams_friendly);
261 fprintf(f, "[chams_vm]\non=%d\nmat=%d\nr=%d\ng=%d\nb=%d\na=%d\n",
262 (int)g_chams_viewmodel, g_chams_vm_mat, g_chams_vm_rgb[0],
263 g_chams_vm_rgb[1], g_chams_vm_rgb[2], g_chams_vm_rgb[3]);
264 fprintf(f, "[items]\nactive=%d\nbind=%d\nhealth=%d\nammo=%d\n"
265 "armor=%d\nweapons=%d\ncrates=%d\ndistance=%d\nmax_dist=%d\n"
266 "usable=%d\n",
267 g_item_esp.active, g_item_esp.bind, (int)g_item_health,
268 (int)g_item_ammo, (int)g_item_armor, (int)g_item_weapons,
269 (int)g_item_crates, (int)g_item_distance, g_item_max_dist,
270 (int)g_item_usable);
271 fprintf(f, "[esp]\nactive=%d\nbind=%d\nneutral=%d\nhealthbar=%d\n"
272 "healthnum=%d\nname=%d\nskeleton=%d\nbox=%d\nspeedgraph=%d\n"
273 "dmg=%d\nalert=%d\nweapon=%d\narrows=%d\n"
274 "hr=%d\nhg=%d\nhb=%d\nnr=%d\nng=%d\nnb=%d\n"
275 "fr=%d\nfg=%d\nfb=%d\n",
276 g_esp.active, g_esp.bind, g_esp_opt[ESP_OPT_SHOW_NEUTRAL],
277 g_esp_opt[ESP_OPT_SHOW_HEALTHBAR],
278 g_esp_opt[ESP_OPT_SHOW_HEALTHNUM], g_esp_opt[ESP_OPT_SHOW_NAME],
279 g_esp_opt[ESP_OPT_SHOW_SKELETON], g_esp_opt[ESP_OPT_SHOW_BOX],
280 g_esp_opt[ESP_OPT_SHOW_SPEEDGRAPH],
281 g_esp_opt[ESP_OPT_DAMAGE_TAGS], g_esp_opt[ESP_OPT_ALERT],
282 g_esp_opt[ESP_OPT_WEAPON], g_esp_opt[ESP_OPT_ARROWS],
283 g_esp_col_hostile[0], g_esp_col_hostile[1], g_esp_col_hostile[2],
284 g_esp_col_neutral[0], g_esp_col_neutral[1], g_esp_col_neutral[2],
285 g_esp_col_friendly[0], g_esp_col_friendly[1],
286 g_esp_col_friendly[2]);
287 fprintf(f, "[view]\nfov=%d\nvmfov=%d\ntonemap=%d\n", g_fov_camera,
288 g_fov_viewmodel, g_tonemap);
289 fprintf(f, "[movement]\ncrouchjump=%d\nedgejump=%d\n",
290 (int)g_auto_crouchjump, (int)g_edge_jump);
291 gui_config_write(f); 207 gui_config_write(f);
292 bool ok = ferror(f) == 0; 208 bool ok = ferror(f) == 0;
293 if (fflush(f) != 0) 209 if (fflush(f) != 0)
@@ -306,351 +222,7 @@ static bool config_load() {
306 FILE *f = fopen(config_path().c_str(), "r"); 222 FILE *f = fopen(config_path().c_str(), "r");
307 if (!f) 223 if (!f)
308 return false; 224 return false;
309 char line[256]; 225 settings_load(f);
310 FeatureState *cur = nullptr;
311 bool in_esp = false, in_bhop = false, in_aim = false,
312 in_jumpbug = false, in_spread = false, in_items = false,
313 in_tint = false, in_fog = false, in_view = false, in_movement = false,
314 in_proj = false;
315 ChamsGroup *chams_grp = nullptr;
316 bool in_chams_vm = false;
317 while (fgets(line, sizeof(line), f)) {
318 line[strcspn(line, "\r\n")] = 0;
319 if (line[0] == '[') {
320 chams_grp = nullptr;
321 in_chams_vm = false;
322 if (strstr(line, "[bhop]"))
323 cur = &g_bhop;
324 else if (strstr(line, "[abh]"))
325 cur = &g_abh;
326 else if (strstr(line, "[jumpbug]"))
327 cur = &g_jumpbug;
328 else if (strstr(line, "[melee]"))
329 cur = &g_melee;
330 else if (strstr(line, "[spread]"))
331 cur = &g_spread;
332 else if (strstr(line, "[esp]"))
333 cur = &g_esp;
334 else if (strstr(line, "[items]"))
335 cur = &g_item_esp;
336 else if (strstr(line, "[fullbright]"))
337 cur = &g_fullbright;
338 else if (strstr(line, "[worldtint]"))
339 cur = &g_world_tint;
340 else if (strstr(line, "[fog]"))
341 cur = &g_fog;
342 else if (strstr(line, "[skybox]"))
343 cur = &g_skybox;
344 else if (strstr(line, "[projectiles]"))
345 cur = &g_projectiles;
346 else if (strstr(line, "[chams]"))
347 cur = &g_chams;
348 else if (strstr(line, "[chams_hostile]")) {
349 cur = nullptr;
350 chams_grp = &g_chams_hostile;
351 } else if (strstr(line, "[chams_neutral]")) {
352 cur = nullptr;
353 chams_grp = &g_chams_neutral;
354 } else if (strstr(line, "[chams_friendly]")) {
355 cur = nullptr;
356 chams_grp = &g_chams_friendly;
357 } else if (strstr(line, "[chams_vm]")) {
358 cur = nullptr;
359 in_chams_vm = true;
360 }
361 else if (strstr(line, "[aimbot]"))
362 cur = &g_aimbot;
363 else if (strstr(line, "[triggerbot]"))
364 cur = &g_triggerbot;
365 else if (strstr(line, "[silentaim]"))
366 cur = &g_silentaim;
367 else if (strstr(line, "[view]"))
368 cur = nullptr;
369 else if (strstr(line, "[movement]"))
370 cur = nullptr;
371 else
372 cur = nullptr;
373 in_esp = (cur == &g_esp);
374 in_bhop = (cur == &g_bhop);
375 in_aim = (cur == &g_aimbot);
376 in_jumpbug = (cur == &g_jumpbug);
377 in_spread = (cur == &g_spread);
378 in_items = (cur == &g_item_esp);
379 in_tint = (cur == &g_world_tint);
380 in_fog = (cur == &g_fog);
381 in_view = strstr(line, "[view]") != nullptr;
382 in_movement = strstr(line, "[movement]") != nullptr;
383 in_proj = (cur == &g_projectiles);
384 } else if (cur || in_view || in_movement || chams_grp ||
385 in_chams_vm) {
386 char *eq = strchr(line, '=');
387 if (!eq)
388 continue;
389 *eq = 0;
390 const char *key = line, *val = eq + 1;
391 if (in_bhop && strcmp(key, "autostrafe") == 0) {
392 g_bhop_autostrafe = atoi(val) != 0;
393 }
394 if (in_jumpbug && strcmp(key, "assist") == 0) {
395 g_jumpbug_assist = atoi(val) != 0;
396 }
397 if (in_spread) {
398 if (strcmp(key, "no_spread") == 0)
399 g_spread_no_spread = atoi(val) != 0;
400 else if (strcmp(key, "engine") == 0)
401 g_spread_engine = atoi(val) != 0;
402 }
403 if (in_items) {
404 if (strcmp(key, "health") == 0)
405 g_item_health = atoi(val) != 0;
406 else if (strcmp(key, "ammo") == 0)
407 g_item_ammo = atoi(val) != 0;
408 else if (strcmp(key, "armor") == 0)
409 g_item_armor = atoi(val) != 0;
410 else if (strcmp(key, "weapons") == 0)
411 g_item_weapons = atoi(val) != 0;
412 else if (strcmp(key, "crates") == 0)
413 g_item_crates = atoi(val) != 0;
414 else if (strcmp(key, "distance") == 0)
415 g_item_distance = atoi(val) != 0;
416 else if (strcmp(key, "usable") == 0)
417 g_item_usable = atoi(val) != 0;
418 else if (strcmp(key, "max_dist") == 0) {
419 int v = atoi(val);
420 if (v < 0) v = 0; // 0 = unlimited
421 if (v > 10000) v = 10000;
422 g_item_max_dist = v;
423 }
424 }
425 if (in_proj) {
426 if (strcmp(key, "fuse") == 0)
427 g_proj_fuse = atoi(val) != 0;
428 else if (strcmp(key, "radius") == 0)
429 g_proj_radius = atoi(val) != 0;
430 else if (strcmp(key, "trajectory") == 0)
431 g_proj_traj = atoi(val) != 0;
432 }
433 if (chams_grp) {
434 ChamsGroup &g = *chams_grp;
435 if (strcmp(key, "vis") == 0)
436 g.vis_on = atoi(val) != 0;
437 else if (strcmp(key, "vis_mat") == 0) {
438 int v = atoi(val);
439 if (v < 0) v = 0;
440 if (v > 6) v = 6;
441 g.vis_mat = v;
442 } else if (strcmp(key, "vis_r") == 0 || strcmp(key, "vis_g") == 0 ||
443 strcmp(key, "vis_b") == 0 || strcmp(key, "vis_a") == 0) {
444 int v = atoi(val);
445 if (v < 0) v = 0;
446 if (v > 255) v = 255;
447 int idx = key[4] == 'r' ? 0 : key[4] == 'g' ? 1
448 : key[4] == 'b' ? 2 : 3;
449 g.vis_rgb[idx] = v;
450 } else if (strcmp(key, "inv") == 0)
451 g.inv_on = atoi(val) != 0;
452 else if (strcmp(key, "inv_mat") == 0) {
453 int v = atoi(val);
454 if (v < 0) v = 0;
455 if (v > 6) v = 6;
456 g.inv_mat = v;
457 } else if (strcmp(key, "inv_r") == 0 || strcmp(key, "inv_g") == 0 ||
458 strcmp(key, "inv_b") == 0 || strcmp(key, "inv_a") == 0) {
459 int v = atoi(val);
460 if (v < 0) v = 0;
461 if (v > 255) v = 255;
462 int idx = key[4] == 'r' ? 0 : key[4] == 'g' ? 1
463 : key[4] == 'b' ? 2 : 3;
464 g.inv_rgb[idx] = v;
465 }
466 }
467 if (in_chams_vm) {
468 if (strcmp(key, "on") == 0)
469 g_chams_viewmodel = atoi(val) != 0;
470 else if (strcmp(key, "mat") == 0) {
471 int v = atoi(val);
472 if (v < 0) v = 0;
473 if (v > 6) v = 6;
474 g_chams_vm_mat = v;
475 } else if (strcmp(key, "r") == 0 || strcmp(key, "g") == 0 ||
476 strcmp(key, "b") == 0 || strcmp(key, "a") == 0) {
477 int v = atoi(val);
478 if (v < 0) v = 0;
479 if (v > 255) v = 255;
480 int idx = key[0] == 'r' ? 0 : key[0] == 'g' ? 1
481 : key[0] == 'b' ? 2 : 3;
482 g_chams_vm_rgb[idx] = v;
483 }
484 }
485 if (in_aim) {
486 if (strcmp(key, "smooth") == 0) {
487 int v = atoi(val);
488 if (v < 1) v = 1;
489 if (v > 45) v = 45;
490 g_aim_smooth = v;
491 } else if (strcmp(key, "bone_head") == 0) {
492 g_aim_bones[AIM_BONE_HEAD] = atoi(val) != 0;
493 } else if (strcmp(key, "bone_torso") == 0) {
494 g_aim_bones[AIM_BONE_TORSO] = atoi(val) != 0;
495 } else if (strcmp(key, "bone_larm") == 0) {
496 g_aim_bones[AIM_BONE_LARM] = atoi(val) != 0;
497 } else if (strcmp(key, "bone_rarm") == 0) {
498 g_aim_bones[AIM_BONE_RARM] = atoi(val) != 0;
499 } else if (strcmp(key, "bone_lleg") == 0) {
500 g_aim_bones[AIM_BONE_LLEG] = atoi(val) != 0;
501 } else if (strcmp(key, "bone_rleg") == 0) {
502 g_aim_bones[AIM_BONE_RLEG] = atoi(val) != 0;
503 } else if (strcmp(key, "vischeck") == 0) {
504 g_aim_vischeck = atoi(val) != 0;
505 } else if (strcmp(key, "fov") == 0) {
506 int v = atoi(val);
507 if (v < 1) v = 1;
508 if (v > 180) v = 180;
509 g_aim_fov = v;
510 } else if (strcmp(key, "fov_circle") == 0) {
511 g_aim_fov_circle = atoi(val) != 0;
512 } else if (strcmp(key, "punch") == 0) {
513 g_aim_punch = atoi(val) != 0;
514 }
515 }
516 if (in_view) {
517 int *dst = nullptr;
518 int lo = 0, hi = 0, stock = 0;
519 if (strcmp(key, "fov") == 0) {
520 dst = &g_fov_camera;
521 lo = 40;
522 hi = 140;
523 stock = 75;
524 } else if (strcmp(key, "vmfov") == 0) {
525 dst = &g_fov_viewmodel;
526 lo = 20;
527 hi = 120;
528 stock = 54;
529 } else if (strcmp(key, "tonemap") == 0) {
530 dst = &g_tonemap;
531 lo = 0;
532 hi = 30;
533 stock = 0;
534 }
535 if (dst) {
536 int v = atoi(val);
537 if (v <= 0)
538 v = stock; // old configs used 0 as "off"
539 if (v < lo) v = lo;
540 if (v > hi) v = hi;
541 *dst = v;
542 }
543 }
544 if (in_movement) {
545 if (strcmp(key, "crouchjump") == 0)
546 g_auto_crouchjump = atoi(val) != 0;
547 else if (strcmp(key, "edgejump") == 0)
548 g_edge_jump = atoi(val) != 0;
549 }
550 if (in_tint) {
551 if (strcmp(key, "world") == 0)
552 g_tint_world_on = atoi(val) != 0;
553 else if (strcmp(key, "sky") == 0)
554 g_tint_sky_on = atoi(val) != 0;
555 else if (strcmp(key, "prop") == 0)
556 g_tint_prop_on = atoi(val) != 0;
557 else if (strcmp(key, "wr") == 0 || strcmp(key, "wg") == 0 ||
558 strcmp(key, "wb") == 0) {
559 int v = atoi(val);
560 if (v < 0) v = 0;
561 if (v > 255) v = 255;
562 g_tint_world_rgb[key[1] == 'r' ? 0 : key[1] == 'g' ? 1 : 2] = v;
563 } else if (strcmp(key, "sr") == 0 || strcmp(key, "sg") == 0 ||
564 strcmp(key, "sb") == 0) {
565 int v = atoi(val);
566 if (v < 0) v = 0;
567 if (v > 255) v = 255;
568 g_tint_sky_rgb[key[1] == 'r' ? 0 : key[1] == 'g' ? 1 : 2] = v;
569 } else if (strcmp(key, "pr") == 0 || strcmp(key, "pg") == 0 ||
570 strcmp(key, "pb") == 0) {
571 int v = atoi(val);
572 if (v < 0) v = 0;
573 if (v > 255) v = 255;
574 g_tint_prop_rgb[key[1] == 'r' ? 0 : key[1] == 'g' ? 1 : 2] = v;
575 }
576 }
577 if (in_fog) {
578 if (strcmp(key, "r") == 0 || strcmp(key, "g") == 0 ||
579 strcmp(key, "b") == 0) {
580 int v = atoi(val);
581 if (v < 0) v = 0;
582 if (v > 255) v = 255;
583 g_fog_rgb[key[0] == 'r' ? 0 : key[0] == 'g' ? 1 : 2] = v;
584 } else if (strcmp(key, "start") == 0) {
585 int v = atoi(val);
586 if (v < 0) v = 0;
587 if (v > 8000) v = 8000;
588 g_fog_start = v;
589 } else if (strcmp(key, "end") == 0) {
590 int v = atoi(val);
591 if (v < 0) v = 0;
592 if (v > 20000) v = 20000;
593 g_fog_end = v;
594 } else if (strcmp(key, "skybox") == 0) {
595 g_fog_skybox = atoi(val) != 0;
596 } else if (strcmp(key, "disable") == 0) {
597 g_fog_disable = atoi(val) != 0;
598 }
599 }
600 if (in_esp) {
601 if (strcmp(key, "neutral") == 0)
602 g_esp_opt[ESP_OPT_SHOW_NEUTRAL] = atoi(val) != 0;
603 else if (strcmp(key, "healthbar") == 0)
604 g_esp_opt[ESP_OPT_SHOW_HEALTHBAR] = atoi(val) != 0;
605 else if (strcmp(key, "healthnum") == 0)
606 g_esp_opt[ESP_OPT_SHOW_HEALTHNUM] = atoi(val) != 0;
607 else if (strcmp(key, "name") == 0)
608 g_esp_opt[ESP_OPT_SHOW_NAME] = atoi(val) != 0;
609 else if (strcmp(key, "skeleton") == 0)
610 g_esp_opt[ESP_OPT_SHOW_SKELETON] = atoi(val) != 0;
611 else if (strcmp(key, "box") == 0)
612 g_esp_opt[ESP_OPT_SHOW_BOX] = atoi(val) != 0;
613 else if (strcmp(key, "speedgraph") == 0)
614 g_esp_opt[ESP_OPT_SHOW_SPEEDGRAPH] = atoi(val) != 0;
615 else if (strcmp(key, "dmg") == 0)
616 g_esp_opt[ESP_OPT_DAMAGE_TAGS] = atoi(val) != 0;
617 else if (strcmp(key, "alert") == 0)
618 g_esp_opt[ESP_OPT_ALERT] = atoi(val) != 0;
619 else if (strcmp(key, "weapon") == 0)
620 g_esp_opt[ESP_OPT_WEAPON] = atoi(val) != 0;
621 else if (strcmp(key, "arrows") == 0)
622 g_esp_opt[ESP_OPT_ARROWS] = atoi(val) != 0;
623 else if (strcmp(key, "hr") == 0 || strcmp(key, "hg") == 0 ||
624 strcmp(key, "hb") == 0) {
625 int v = atoi(val);
626 if (v < 0) v = 0;
627 if (v > 255) v = 255;
628 g_esp_col_hostile[key[1] == 'r' ? 0 : key[1] == 'g' ? 1 : 2] = v;
629 } else if (strcmp(key, "nr") == 0 || strcmp(key, "ng") == 0 ||
630 strcmp(key, "nb") == 0) {
631 int v = atoi(val);
632 if (v < 0) v = 0;
633 if (v > 255) v = 255;
634 g_esp_col_neutral[key[1] == 'r' ? 0 : key[1] == 'g' ? 1 : 2] = v;
635 } else if (strcmp(key, "fr") == 0 || strcmp(key, "fg") == 0 ||
636 strcmp(key, "fb") == 0) {
637 int v = atoi(val);
638 if (v < 0) v = 0;
639 if (v > 255) v = 255;
640 g_esp_col_friendly[key[1] == 'r' ? 0 : key[1] == 'g' ? 1 : 2] = v;
641 }
642 }
643 // Scalar-only sections ([view], [movement], [chams_*]) intentionally
644 // leave cur == nullptr. A stray active=/bind= line in one of them must
645 // not be dereferenced (hand-edited or corrupt config).
646 if (!cur)
647 continue;
648 if (strcmp(key, "active") == 0)
649 cur->active = atoi(val) != 0;
650 else if (strcmp(key, "bind") == 0)
651 cur->bind = atoi(val);
652 }
653 }
654 fclose(f); 226 fclose(f);
655 return true; 227 return true;
656} 228}
@@ -679,86 +251,7 @@ const char *config_file_cstr(const char *name) {
679} 251}
680 252
681void config_reset_defaults() { 253void config_reset_defaults() {
682 g_bhop = {true, 0}; 254 settings_reset_defaults();
683 g_bhop_autostrafe = true;
684 g_abh = {true, 0};
685 g_jumpbug = {true, 0};
686 g_jumpbug_assist = false;
687 g_melee = {true, 0};
688 g_spread = {true, 0};
689 g_spread_no_spread = true;
690 g_esp = {true, 0};
691 for (int i = 0; i < ESP_OPT_COUNT; i++)
692 g_esp_opt[i] = true;
693 g_item_esp = {true, 0};
694 g_fullbright = {false, 0};
695 g_world_tint = {false, 0};
696 g_tint_world_on = true;
697 g_tint_sky_on = true;
698 g_tint_prop_on = true;
699 g_tint_world_rgb[0] = g_tint_world_rgb[1] = g_tint_world_rgb[2] = 255;
700 g_tint_sky_rgb[0] = g_tint_sky_rgb[1] = g_tint_sky_rgb[2] = 255;
701 g_tint_prop_rgb[0] = g_tint_prop_rgb[1] = g_tint_prop_rgb[2] = 255;
702 g_fog = {false, 0};
703 g_fog_skybox = true;
704 g_fog_disable = false;
705 g_fog_rgb[0] = 160;
706 g_fog_rgb[1] = 170;
707 g_fog_rgb[2] = 190;
708 g_fog_start = 200;
709 g_fog_end = 3000;
710 g_skybox = {false, 0};
711 g_projectiles = {true, 0};
712 g_proj_fuse = true;
713 g_proj_radius = true;
714 g_proj_traj = true;
715 g_chams = {false, 0};
716 g_chams_hostile = {true, 3, {255, 60, 60, 255}, true, 3,
717 {255, 60, 60, 255}};
718 g_chams_neutral = {true, 3, {220, 220, 220, 255}, false, 3,
719 {220, 220, 220, 255}};
720 g_chams_friendly = {true, 3, {60, 255, 60, 255}, false, 3,
721 {60, 255, 60, 255}};
722 g_chams_viewmodel = false;
723 g_chams_vm_mat = 3;
724 g_chams_vm_rgb[0] = 200;
725 g_chams_vm_rgb[1] = 200;
726 g_chams_vm_rgb[2] = 255;
727 g_chams_vm_rgb[3] = 255;
728 g_item_health = true;
729 g_item_ammo = true;
730 g_item_armor = true;
731 g_item_weapons = true;
732 g_item_crates = true;
733 g_item_distance = true;
734 g_item_usable = true;
735 g_item_max_dist = 5000;
736 g_aimbot = {true, 604};
737 g_triggerbot = {true, 603};
738 g_silentaim = {true, 602};
739 for (int i = 0; i < AIM_BONE_COUNT; i++)
740 g_aim_bones[i] = false;
741 g_aim_bones[AIM_BONE_HEAD] = true;
742 g_aim_smooth = 5;
743 g_aim_vischeck = true;
744 g_aim_fov = 60;
745 g_aim_fov_circle = true;
746 g_aim_punch = true;
747 g_spread_engine = true;
748 g_auto_crouchjump = false;
749 g_edge_jump = false;
750 g_fov_camera = 75;
751 g_fov_viewmodel = 54;
752 g_tonemap = 0;
753 g_esp_col_hostile[0] = 255;
754 g_esp_col_hostile[1] = 60;
755 g_esp_col_hostile[2] = 60;
756 g_esp_col_neutral[0] = 220;
757 g_esp_col_neutral[1] = 220;
758 g_esp_col_neutral[2] = 220;
759 g_esp_col_friendly[0] = 60;
760 g_esp_col_friendly[1] = 255;
761 g_esp_col_friendly[2] = 60;
762 config_save(); 255 config_save();
763} 256}
764 257