summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-26 15:44:45 +0100
committersalmonik <salmonik@tuta.io>2026-10-26 15:44:45 +0100
commit15e4d33220bedb62beac635580fa4d222a7f5863 (patch)
tree46cd1ee202b7d9d0597b7a91b6716ce4bef6d1a3 /src
parentESP: vertical health bar right of the box, HP number beside it (diff)
downloadhl2h-15e4d33220bedb62beac635580fa4d222a7f5863.tar.gz
hl2h-15e4d33220bedb62beac635580fa4d222a7f5863.zip
ESP: menu toggles for neutral/healthbar/healthnum/name
Diffstat (limited to '')
-rw-r--r--src/esp.cpp15
-rw-r--r--src/hl2h.h8
-rw-r--r--src/menu.cpp44
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}
diff --git a/src/hl2h.h b/src/hl2h.h
index b693617..50b5525 100644
--- a/src/hl2h.h
+++ b/src/hl2h.h
@@ -136,6 +136,13 @@ extern Vector g_cam_eye;
136extern Vector g_cam_view; 136extern Vector g_cam_view;
137QAngle vector_angles(const Vector &forward); 137QAngle vector_angles(const Vector &forward);
138enum FeatureId { FEAT_BHOP = 0, FEAT_ABH = 1, FEAT_ESP = 2 }; 138enum FeatureId { FEAT_BHOP = 0, FEAT_ABH = 1, FEAT_ESP = 2 };
139enum 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);
153void find_modules(); 160void find_modules();
154void init_conmsg(); 161void init_conmsg();
155bool feature_active(int feature); 162bool feature_active(int feature);
163bool esp_option(int opt);
156void *entitylist_get(int idx); 164void *entitylist_get(int idx);
157int engine_get_local_player(); 165int engine_get_local_player();
158void draw_text_col(int x, int y, const char *s, int r, int g, int b); 166void 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
56static FeatureState g_abh{true, 0}; 56static FeatureState g_abh{true, 0};
57static FeatureState g_esp{true, 0}; 57static FeatureState g_esp{true, 0};
58
59// ESP sub-options (menu "ESP" children). Defaults match the pre-option
60// behaviour: everything on.
61static bool g_esp_opt[ESP_OPT_COUNT] = {true, true, true, true};
62
58// tree 63// tree
59static MenuNode g_root{NODE_ROOT, "HL2hake", true, 0, {}, nullptr, nullptr, nullptr}; 64static MenuNode g_root{NODE_ROOT, "HL2hake", true, 0, {}, nullptr, nullptr, nullptr};
60static MenuNode g_bhop_feat{NODE_FEATURE, "Bunnyhop", true, 1, {}, nullptr, nullptr, nullptr}; 65static 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
63static MenuNode g_abh_active{NODE_TOGGLE, "Active", false, 0, {}, &g_abh.active, nullptr, nullptr}; 68static MenuNode g_abh_active{NODE_TOGGLE, "Active", false, 0, {}, &g_abh.active, nullptr, nullptr};
64static MenuNode g_esp_feat{NODE_FEATURE, "ESP", true, 1, {}, nullptr, nullptr, nullptr}; 69static MenuNode g_esp_feat{NODE_FEATURE, "ESP", true, 1, {}, nullptr, nullptr, nullptr};
65static MenuNode g_esp_active{NODE_TOGGLE, "Active", false, 0, {}, &g_esp.active, nullptr, nullptr}; 70static MenuNode g_esp_active{NODE_TOGGLE, "Active", false, 0, {}, &g_esp.active, nullptr, nullptr};
71static 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
67static MenuNode *g_visible[16]; // flattened visible nodes for arrow navigation 78static MenuNode *g_visible[32]; // flattened visible nodes for arrow navigation
68static int g_visible_count = 0; 79static int g_visible_count = 0;
69static int g_selected = 0; 80static int g_selected = 0;
70bool g_menu_open = false; 81bool 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
83static int g_depth[16]; // depth of each visible row (for indentation) 97static int g_depth[32]; // depth of each visible row (for indentation)
84 98
85static void flatten(MenuNode *node, int depth) { 99static 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
318bool esp_option(int opt) {
319 return opt >= 0 && opt < ESP_OPT_COUNT && g_esp_opt[opt];
320}
321
288static void menu_handle_input() { 322static void menu_handle_input() {
289 poll_keyboard(); 323 poll_keyboard();
290 324