diff options
Diffstat (limited to '')
| -rw-r--r-- | src/menu.cpp | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/src/menu.cpp b/src/menu.cpp index 302eab3..2caf0aa 100644 --- a/src/menu.cpp +++ b/src/menu.cpp | |||
| @@ -37,7 +37,7 @@ struct MenuNode { | |||
| 37 | const char *label; | 37 | const char *label; |
| 38 | bool expanded; // for root/feature: whether children are visible | 38 | bool expanded; // for root/feature: whether children are visible |
| 39 | int child_count; | 39 | int child_count; |
| 40 | MenuNode *children[4]; // max children per node | 40 | MenuNode *children[8]; // max children per node |
| 41 | 41 | ||
| 42 | // leaf data | 42 | // leaf data |
| 43 | bool *active_ptr; // NODE_TOGGLE: pointer to the active flag | 43 | bool *active_ptr; // NODE_TOGGLE: pointer to the active flag |
| @@ -55,6 +55,11 @@ static FeatureState g_bhop{true, 0}; | |||
| 55 | 55 | ||
| 56 | static FeatureState g_abh{true, 0}; | 56 | static FeatureState g_abh{true, 0}; |
| 57 | static FeatureState g_esp{true, 0}; | 57 | static FeatureState g_esp{true, 0}; |
| 58 | |||
| 59 | // ESP sub-options (menu "ESP" children). Defaults match the pre-option | ||
| 60 | // behaviour: everything on. | ||
| 61 | static bool g_esp_opt[ESP_OPT_COUNT] = {true, true, true, true}; | ||
| 62 | |||
| 58 | // tree | 63 | // tree |
| 59 | static MenuNode g_root{NODE_ROOT, "HL2hake", true, 0, {}, nullptr, nullptr, nullptr}; | 64 | static MenuNode g_root{NODE_ROOT, "HL2hake", true, 0, {}, nullptr, nullptr, nullptr}; |
| 60 | static MenuNode g_bhop_feat{NODE_FEATURE, "Bunnyhop", true, 1, {}, nullptr, nullptr, nullptr}; | 65 | static MenuNode g_bhop_feat{NODE_FEATURE, "Bunnyhop", true, 1, {}, nullptr, nullptr, nullptr}; |
| @@ -63,8 +68,14 @@ static MenuNode g_abh_feat{NODE_FEATURE, "ABH", true, 1, {}, nullptr, nullptr, n | |||
| 63 | static MenuNode g_abh_active{NODE_TOGGLE, "Active", false, 0, {}, &g_abh.active, nullptr, nullptr}; | 68 | static MenuNode g_abh_active{NODE_TOGGLE, "Active", false, 0, {}, &g_abh.active, nullptr, nullptr}; |
| 64 | static MenuNode g_esp_feat{NODE_FEATURE, "ESP", true, 1, {}, nullptr, nullptr, nullptr}; | 69 | static MenuNode g_esp_feat{NODE_FEATURE, "ESP", true, 1, {}, nullptr, nullptr, nullptr}; |
| 65 | static MenuNode g_esp_active{NODE_TOGGLE, "Active", false, 0, {}, &g_esp.active, nullptr, nullptr}; | 70 | static MenuNode g_esp_active{NODE_TOGGLE, "Active", false, 0, {}, &g_esp.active, nullptr, nullptr}; |
| 71 | static MenuNode g_esp_opt_nodes[ESP_OPT_COUNT] = { | ||
| 72 | {NODE_TOGGLE, "Show neutral", false, 0, {}, &g_esp_opt[ESP_OPT_SHOW_NEUTRAL], nullptr, nullptr}, | ||
| 73 | {NODE_TOGGLE, "Show healthbar", false, 0, {}, &g_esp_opt[ESP_OPT_SHOW_HEALTHBAR], nullptr, nullptr}, | ||
| 74 | {NODE_TOGGLE, "Show healthnum", false, 0, {}, &g_esp_opt[ESP_OPT_SHOW_HEALTHNUM], nullptr, nullptr}, | ||
| 75 | {NODE_TOGGLE, "Show name", false, 0, {}, &g_esp_opt[ESP_OPT_SHOW_NAME], nullptr, nullptr}, | ||
| 76 | }; | ||
| 66 | 77 | ||
| 67 | static MenuNode *g_visible[16]; // flattened visible nodes for arrow navigation | 78 | static MenuNode *g_visible[32]; // flattened visible nodes for arrow navigation |
| 68 | static int g_visible_count = 0; | 79 | static int g_visible_count = 0; |
| 69 | static int g_selected = 0; | 80 | static int g_selected = 0; |
| 70 | bool g_menu_open = false; | 81 | bool g_menu_open = false; |
| @@ -74,16 +85,19 @@ static void build_tree() { | |||
| 74 | g_bhop_feat.children[0] = &g_bhop_active; | 85 | g_bhop_feat.children[0] = &g_bhop_active; |
| 75 | g_abh_feat.children[0] = &g_abh_active; | 86 | g_abh_feat.children[0] = &g_abh_active; |
| 76 | g_esp_feat.children[0] = &g_esp_active; | 87 | g_esp_feat.children[0] = &g_esp_active; |
| 88 | for (int i = 0; i < ESP_OPT_COUNT; i++) | ||
| 89 | g_esp_feat.children[i + 1] = &g_esp_opt_nodes[i]; | ||
| 90 | g_esp_feat.child_count = ESP_OPT_COUNT + 1; | ||
| 77 | g_root.children[0] = &g_bhop_feat; | 91 | g_root.children[0] = &g_bhop_feat; |
| 78 | g_root.children[1] = &g_abh_feat; | 92 | g_root.children[1] = &g_abh_feat; |
| 79 | g_root.children[2] = &g_esp_feat; | 93 | g_root.children[2] = &g_esp_feat; |
| 80 | g_root.child_count = 3; | 94 | g_root.child_count = 3; |
| 81 | } | 95 | } |
| 82 | 96 | ||
| 83 | static int g_depth[16]; // depth of each visible row (for indentation) | 97 | static int g_depth[32]; // depth of each visible row (for indentation) |
| 84 | 98 | ||
| 85 | static void flatten(MenuNode *node, int depth) { | 99 | static void flatten(MenuNode *node, int depth) { |
| 86 | if (g_visible_count >= 16) | 100 | if (g_visible_count >= 32) |
| 87 | return; | 101 | return; |
| 88 | node->type = (depth == 0) ? NODE_ROOT | 102 | node->type = (depth == 0) ? NODE_ROOT |
| 89 | : (node->child_count > 0) ? NODE_FEATURE | 103 | : (node->child_count > 0) ? NODE_FEATURE |
| @@ -139,7 +153,11 @@ static void config_save() { | |||
| 139 | return; | 153 | return; |
| 140 | fprintf(f, "[bhop]\nactive=%d\nbind=%d\n", g_bhop.active, g_bhop.bind); | 154 | fprintf(f, "[bhop]\nactive=%d\nbind=%d\n", g_bhop.active, g_bhop.bind); |
| 141 | fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); | 155 | fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); |
| 142 | fprintf(f, "[esp]\nactive=%d\nbind=%d\n", g_esp.active, g_esp.bind); | 156 | fprintf(f, "[esp]\nactive=%d\nbind=%d\nneutral=%d\nhealthbar=%d\n" |
| 157 | "healthnum=%d\nname=%d\n", | ||
| 158 | g_esp.active, g_esp.bind, g_esp_opt[ESP_OPT_SHOW_NEUTRAL], | ||
| 159 | g_esp_opt[ESP_OPT_SHOW_HEALTHBAR], | ||
| 160 | g_esp_opt[ESP_OPT_SHOW_HEALTHNUM], g_esp_opt[ESP_OPT_SHOW_NAME]); | ||
| 143 | fclose(f); | 161 | fclose(f); |
| 144 | } | 162 | } |
| 145 | 163 | ||
| @@ -149,6 +167,7 @@ static void config_load() { | |||
| 149 | return; | 167 | return; |
| 150 | char line[256]; | 168 | char line[256]; |
| 151 | FeatureState *cur = nullptr; | 169 | FeatureState *cur = nullptr; |
| 170 | bool in_esp = false; | ||
| 152 | while (fgets(line, sizeof(line), f)) { | 171 | while (fgets(line, sizeof(line), f)) { |
| 153 | line[strcspn(line, "\r\n")] = 0; | 172 | line[strcspn(line, "\r\n")] = 0; |
| 154 | if (line[0] == '[') { | 173 | if (line[0] == '[') { |
| @@ -160,12 +179,23 @@ static void config_load() { | |||
| 160 | cur = &g_esp; | 179 | cur = &g_esp; |
| 161 | else | 180 | else |
| 162 | cur = nullptr; | 181 | cur = nullptr; |
| 182 | in_esp = (cur == &g_esp); | ||
| 163 | } else if (cur) { | 183 | } else if (cur) { |
| 164 | char *eq = strchr(line, '='); | 184 | char *eq = strchr(line, '='); |
| 165 | if (!eq) | 185 | if (!eq) |
| 166 | continue; | 186 | continue; |
| 167 | *eq = 0; | 187 | *eq = 0; |
| 168 | const char *key = line, *val = eq + 1; | 188 | const char *key = line, *val = eq + 1; |
| 189 | if (in_esp) { | ||
| 190 | if (strcmp(key, "neutral") == 0) | ||
| 191 | g_esp_opt[ESP_OPT_SHOW_NEUTRAL] = atoi(val) != 0; | ||
| 192 | else if (strcmp(key, "healthbar") == 0) | ||
| 193 | g_esp_opt[ESP_OPT_SHOW_HEALTHBAR] = atoi(val) != 0; | ||
| 194 | else if (strcmp(key, "healthnum") == 0) | ||
| 195 | g_esp_opt[ESP_OPT_SHOW_HEALTHNUM] = atoi(val) != 0; | ||
| 196 | else if (strcmp(key, "name") == 0) | ||
| 197 | g_esp_opt[ESP_OPT_SHOW_NAME] = atoi(val) != 0; | ||
| 198 | } | ||
| 169 | if (strcmp(key, "active") == 0) | 199 | if (strcmp(key, "active") == 0) |
| 170 | cur->active = atoi(val) != 0; | 200 | cur->active = atoi(val) != 0; |
| 171 | else if (strcmp(key, "bind") == 0) | 201 | else if (strcmp(key, "bind") == 0) |
| @@ -285,6 +315,10 @@ bool feature_active(int feature) { | |||
| 285 | return f->bind == 0 || key_held(f->bind); | 315 | return f->bind == 0 || key_held(f->bind); |
| 286 | } | 316 | } |
| 287 | 317 | ||
| 318 | bool esp_option(int opt) { | ||
| 319 | return opt >= 0 && opt < ESP_OPT_COUNT && g_esp_opt[opt]; | ||
| 320 | } | ||
| 321 | |||
| 288 | static void menu_handle_input() { | 322 | static void menu_handle_input() { |
| 289 | poll_keyboard(); | 323 | poll_keyboard(); |
| 290 | 324 | ||
