diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-06 16:30:10 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-06 16:30:10 +0100 |
| commit | e339d1dc45b3113648552b0002e0c15f55e61cb2 (patch) | |
| tree | 4570dc0ba1501ea26e87447d234693ad5532e813 /src/config_table.cpp | |
| parent | docs: record the esp.cpp split in the plan (diff) | |
| download | hl2h-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.
Diffstat (limited to '')
| -rw-r--r-- | src/config_table.cpp | 230 |
1 files changed, 230 insertions, 0 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 | |||
| 10 | namespace { | ||
| 11 | |||
| 12 | enum SettingType { S_BOOL, S_INT }; | ||
| 13 | |||
| 14 | struct 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 | |||
| 29 | const 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 | |||
| 161 | constexpr int kSettingCount = (int)(sizeof(kSettings) / sizeof(kSettings[0])); | ||
| 162 | |||
| 163 | const 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 | |||
| 174 | void 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 | |||
| 187 | void 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 | |||
| 222 | void 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 | } | ||
