diff options
| author | salmonik <salmonik@tuta.io> | 2026-10-26 15:44:45 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-10-26 15:44:45 +0100 |
| commit | 15e4d33220bedb62beac635580fa4d222a7f5863 (patch) | |
| tree | 46cd1ee202b7d9d0597b7a91b6716ce4bef6d1a3 | |
| parent | ESP: vertical health bar right of the box, HP number beside it (diff) | |
| download | hl2h-15e4d33220bedb62beac635580fa4d222a7f5863.tar.gz hl2h-15e4d33220bedb62beac635580fa4d222a7f5863.zip | |
ESP: menu toggles for neutral/healthbar/healthnum/name
Diffstat (limited to '')
| -rw-r--r-- | src/esp.cpp | 15 | ||||
| -rw-r--r-- | src/hl2h.h | 8 | ||||
| -rw-r--r-- | src/menu.cpp | 44 |
3 files changed, 59 insertions, 8 deletions
diff --git a/src/esp.cpp b/src/esp.cpp index 3914342..4462f07 100644 --- a/src/esp.cpp +++ b/src/esp.cpp | |||
| @@ -280,6 +280,8 @@ void esp_draw() { | |||
| 280 | esp_collect(engine_get_local_player()); | 280 | esp_collect(engine_get_local_player()); |
| 281 | for (int i = 0; i < g_ntargets; i++) { | 281 | for (int i = 0; i < g_ntargets; i++) { |
| 282 | const EspTarget &t = g_targets[i]; | 282 | const EspTarget &t = g_targets[i]; |
| 283 | if (t.neutral && !esp_option(ESP_OPT_SHOW_NEUTRAL)) | ||
| 284 | continue; | ||
| 283 | if (t.friendly) surf_color(60, 255, 60, 255); | 285 | if (t.friendly) surf_color(60, 255, 60, 255); |
| 284 | else if (t.neutral) surf_color(220, 220, 220, 255); | 286 | else if (t.neutral) surf_color(220, 220, 220, 255); |
| 285 | else surf_color(255, 60, 60, 255); | 287 | else surf_color(255, 60, 60, 255); |
| @@ -289,7 +291,10 @@ void esp_draw() { | |||
| 289 | int top = (int)(t.sy - t.h); | 291 | int top = (int)(t.sy - t.h); |
| 290 | int bot = (int)t.sy; | 292 | int bot = (int)t.sy; |
| 291 | surf_rect(0, left, top, right, bot); | 293 | surf_rect(0, left, top, right, bot); |
| 292 | if (t.show_health) { | 294 | bool draw_bar = t.show_health && esp_option(ESP_OPT_SHOW_HEALTHBAR); |
| 295 | bool draw_num = t.show_health && esp_option(ESP_OPT_SHOW_HEALTHNUM); | ||
| 296 | int num_x = right + 3; | ||
| 297 | if (draw_bar) { | ||
| 293 | float frac = t.health / (t.maxhealth > 1.0f ? t.maxhealth : 100.0f); | 298 | float frac = t.health / (t.maxhealth > 1.0f ? t.maxhealth : 100.0f); |
| 294 | if (frac > 1) frac = 1; | 299 | if (frac > 1) frac = 1; |
| 295 | if (frac < 0) frac = 0; | 300 | if (frac < 0) frac = 0; |
| @@ -304,10 +309,14 @@ void esp_draw() { | |||
| 304 | else surf_color(255, 40, 40, 255); | 309 | else surf_color(255, 40, 40, 255); |
| 305 | if (fill_top < bot) | 310 | if (fill_top < bot) |
| 306 | surf_rect(1, bx0, fill_top, bx1, bot); | 311 | surf_rect(1, bx0, fill_top, bx1, bot); |
| 312 | num_x = bx1 + 3; | ||
| 313 | } | ||
| 314 | if (draw_num) { | ||
| 307 | char hptext[16]; | 315 | char hptext[16]; |
| 308 | snprintf(hptext, sizeof(hptext), "%d", (int)t.health); | 316 | snprintf(hptext, sizeof(hptext), "%d", (int)t.health); |
| 309 | draw_text_col(bx1 + 3, top, hptext, 255, 255, 255); | 317 | draw_text_col(num_x, top, hptext, 255, 255, 255); |
| 310 | } | 318 | } |
| 311 | draw_text_col(left, top - 14, t.name, 255, 255, 255); | 319 | if (esp_option(ESP_OPT_SHOW_NAME)) |
| 320 | draw_text_col(left, top - 14, t.name, 255, 255, 255); | ||
| 312 | } | 321 | } |
| 313 | } | 322 | } |
| @@ -136,6 +136,13 @@ extern Vector g_cam_eye; | |||
| 136 | extern Vector g_cam_view; | 136 | extern Vector g_cam_view; |
| 137 | QAngle vector_angles(const Vector &forward); | 137 | QAngle vector_angles(const Vector &forward); |
| 138 | enum FeatureId { FEAT_BHOP = 0, FEAT_ABH = 1, FEAT_ESP = 2 }; | 138 | enum FeatureId { FEAT_BHOP = 0, FEAT_ABH = 1, FEAT_ESP = 2 }; |
| 139 | enum EspOption { | ||
| 140 | ESP_OPT_SHOW_NEUTRAL = 0, | ||
| 141 | ESP_OPT_SHOW_HEALTHBAR = 1, | ||
| 142 | ESP_OPT_SHOW_HEALTHNUM = 2, | ||
| 143 | ESP_OPT_SHOW_NAME = 3, | ||
| 144 | ESP_OPT_COUNT = 4 | ||
| 145 | }; | ||
| 139 | 146 | ||
| 140 | // --------------------------------------------------------------------------- | 147 | // --------------------------------------------------------------------------- |
| 141 | // cross-file declarations | 148 | // cross-file declarations |
| @@ -153,6 +160,7 @@ int server_model_index(void *base); | |||
| 153 | void find_modules(); | 160 | void find_modules(); |
| 154 | void init_conmsg(); | 161 | void init_conmsg(); |
| 155 | bool feature_active(int feature); | 162 | bool feature_active(int feature); |
| 163 | bool esp_option(int opt); | ||
| 156 | void *entitylist_get(int idx); | 164 | void *entitylist_get(int idx); |
| 157 | int engine_get_local_player(); | 165 | int engine_get_local_player(); |
| 158 | void draw_text_col(int x, int y, const char *s, int r, int g, int b); | 166 | void draw_text_col(int x, int y, const char *s, int r, int g, int b); |
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 | ||
