diff options
| author | salmonik <salmonik@tuta.io> | 2026-10-26 15:56:03 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-10-26 15:56:03 +0100 |
| commit | 164bdcbf3e8ed2b7377351b619150586012e1007 (patch) | |
| tree | 63660fc6f33c0e77e81f73a5d544418307e1b7e5 /src/menu.cpp | |
| parent | ESP: menu toggles for neutral/healthbar/healthnum/name (diff) | |
| download | hl2h-164bdcbf3e8ed2b7377351b619150586012e1007.tar.gz hl2h-164bdcbf3e8ed2b7377351b619150586012e1007.zip | |
Bhop: uni-directional auto-strafe for all movement directions
- derive the desired air direction from the raw W/S/A/D input (view-relative)
- pick the velocity perpendicular that rotates toward that target, so S/A/D
work instead of only forward and A/D no longer spin in circles
- no keys: accelerate along the crosshair
- menu label now "Uni-directional auto-strafe"; state column moved to x=270
Diffstat (limited to '')
| -rw-r--r-- | src/menu.cpp | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/src/menu.cpp b/src/menu.cpp index 2caf0aa..c8dffc9 100644 --- a/src/menu.cpp +++ b/src/menu.cpp | |||
| @@ -52,6 +52,7 @@ struct FeatureState { | |||
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | static FeatureState g_bhop{true, 0}; | 54 | static FeatureState g_bhop{true, 0}; |
| 55 | static bool g_bhop_autostrafe = true; | ||
| 55 | 56 | ||
| 56 | static FeatureState g_abh{true, 0}; | 57 | static FeatureState g_abh{true, 0}; |
| 57 | static FeatureState g_esp{true, 0}; | 58 | static FeatureState g_esp{true, 0}; |
| @@ -64,6 +65,7 @@ static bool g_esp_opt[ESP_OPT_COUNT] = {true, true, true, true}; | |||
| 64 | static MenuNode g_root{NODE_ROOT, "HL2hake", true, 0, {}, nullptr, nullptr, nullptr}; | 65 | static MenuNode g_root{NODE_ROOT, "HL2hake", true, 0, {}, nullptr, nullptr, nullptr}; |
| 65 | static MenuNode g_bhop_feat{NODE_FEATURE, "Bunnyhop", true, 1, {}, nullptr, nullptr, nullptr}; | 66 | static MenuNode g_bhop_feat{NODE_FEATURE, "Bunnyhop", true, 1, {}, nullptr, nullptr, nullptr}; |
| 66 | static MenuNode g_bhop_active{NODE_TOGGLE, "Active", false, 0, {}, &g_bhop.active, nullptr, nullptr}; | 67 | static MenuNode g_bhop_active{NODE_TOGGLE, "Active", false, 0, {}, &g_bhop.active, nullptr, nullptr}; |
| 68 | static MenuNode g_bhop_autostrafe_node{NODE_TOGGLE, "Uni-directional auto-strafe", false, 0, {}, &g_bhop_autostrafe, nullptr, nullptr}; | ||
| 67 | static MenuNode g_abh_feat{NODE_FEATURE, "ABH", true, 1, {}, nullptr, nullptr, nullptr}; | 69 | static MenuNode g_abh_feat{NODE_FEATURE, "ABH", true, 1, {}, nullptr, nullptr, nullptr}; |
| 68 | static MenuNode g_abh_active{NODE_TOGGLE, "Active", false, 0, {}, &g_abh.active, nullptr, nullptr}; | 70 | static MenuNode g_abh_active{NODE_TOGGLE, "Active", false, 0, {}, &g_abh.active, nullptr, nullptr}; |
| 69 | static MenuNode g_esp_feat{NODE_FEATURE, "ESP", true, 1, {}, nullptr, nullptr, nullptr}; | 71 | static MenuNode g_esp_feat{NODE_FEATURE, "ESP", true, 1, {}, nullptr, nullptr, nullptr}; |
| @@ -83,6 +85,8 @@ bool g_menu_open = false; | |||
| 83 | static bool g_bind_mode = false; | 85 | static bool g_bind_mode = false; |
| 84 | static void build_tree() { | 86 | static void build_tree() { |
| 85 | g_bhop_feat.children[0] = &g_bhop_active; | 87 | g_bhop_feat.children[0] = &g_bhop_active; |
| 88 | g_bhop_feat.children[1] = &g_bhop_autostrafe_node; | ||
| 89 | g_bhop_feat.child_count = 2; | ||
| 86 | g_abh_feat.children[0] = &g_abh_active; | 90 | g_abh_feat.children[0] = &g_abh_active; |
| 87 | g_esp_feat.children[0] = &g_esp_active; | 91 | g_esp_feat.children[0] = &g_esp_active; |
| 88 | for (int i = 0; i < ESP_OPT_COUNT; i++) | 92 | for (int i = 0; i < ESP_OPT_COUNT; i++) |
| @@ -151,7 +155,8 @@ static void config_save() { | |||
| 151 | FILE *f = fopen(config_path().c_str(), "w"); | 155 | FILE *f = fopen(config_path().c_str(), "w"); |
| 152 | if (!f) | 156 | if (!f) |
| 153 | return; | 157 | return; |
| 154 | fprintf(f, "[bhop]\nactive=%d\nbind=%d\n", g_bhop.active, g_bhop.bind); | 158 | fprintf(f, "[bhop]\nactive=%d\nbind=%d\nautostrafe=%d\n", g_bhop.active, |
| 159 | g_bhop.bind, g_bhop_autostrafe); | ||
| 155 | fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); | 160 | fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); |
| 156 | fprintf(f, "[esp]\nactive=%d\nbind=%d\nneutral=%d\nhealthbar=%d\n" | 161 | fprintf(f, "[esp]\nactive=%d\nbind=%d\nneutral=%d\nhealthbar=%d\n" |
| 157 | "healthnum=%d\nname=%d\n", | 162 | "healthnum=%d\nname=%d\n", |
| @@ -167,7 +172,7 @@ static void config_load() { | |||
| 167 | return; | 172 | return; |
| 168 | char line[256]; | 173 | char line[256]; |
| 169 | FeatureState *cur = nullptr; | 174 | FeatureState *cur = nullptr; |
| 170 | bool in_esp = false; | 175 | bool in_esp = false, in_bhop = false; |
| 171 | while (fgets(line, sizeof(line), f)) { | 176 | while (fgets(line, sizeof(line), f)) { |
| 172 | line[strcspn(line, "\r\n")] = 0; | 177 | line[strcspn(line, "\r\n")] = 0; |
| 173 | if (line[0] == '[') { | 178 | if (line[0] == '[') { |
| @@ -180,12 +185,16 @@ static void config_load() { | |||
| 180 | else | 185 | else |
| 181 | cur = nullptr; | 186 | cur = nullptr; |
| 182 | in_esp = (cur == &g_esp); | 187 | in_esp = (cur == &g_esp); |
| 188 | in_bhop = (cur == &g_bhop); | ||
| 183 | } else if (cur) { | 189 | } else if (cur) { |
| 184 | char *eq = strchr(line, '='); | 190 | char *eq = strchr(line, '='); |
| 185 | if (!eq) | 191 | if (!eq) |
| 186 | continue; | 192 | continue; |
| 187 | *eq = 0; | 193 | *eq = 0; |
| 188 | const char *key = line, *val = eq + 1; | 194 | const char *key = line, *val = eq + 1; |
| 195 | if (in_bhop && strcmp(key, "autostrafe") == 0) { | ||
| 196 | g_bhop_autostrafe = atoi(val) != 0; | ||
| 197 | } | ||
| 189 | if (in_esp) { | 198 | if (in_esp) { |
| 190 | if (strcmp(key, "neutral") == 0) | 199 | if (strcmp(key, "neutral") == 0) |
| 191 | g_esp_opt[ESP_OPT_SHOW_NEUTRAL] = atoi(val) != 0; | 200 | g_esp_opt[ESP_OPT_SHOW_NEUTRAL] = atoi(val) != 0; |
| @@ -319,6 +328,8 @@ bool esp_option(int opt) { | |||
| 319 | return opt >= 0 && opt < ESP_OPT_COUNT && g_esp_opt[opt]; | 328 | return opt >= 0 && opt < ESP_OPT_COUNT && g_esp_opt[opt]; |
| 320 | } | 329 | } |
| 321 | 330 | ||
| 331 | bool bhop_autostrafe_enabled() { return g_bhop_autostrafe; } | ||
| 332 | |||
| 322 | static void menu_handle_input() { | 333 | static void menu_handle_input() { |
| 323 | poll_keyboard(); | 334 | poll_keyboard(); |
| 324 | 335 | ||
| @@ -557,10 +568,10 @@ void outer_draw() { | |||
| 557 | draw_text(x, 10 + i * 20, line); | 568 | draw_text(x, 10 + i * 20, line); |
| 558 | // right-aligned state | 569 | // right-aligned state |
| 559 | if (n->type == NODE_TOGGLE) { | 570 | if (n->type == NODE_TOGGLE) { |
| 560 | draw_text(200, 10 + i * 20, *n->active_ptr ? "[on]" : "[off]"); | 571 | draw_text(270, 10 + i * 20, *n->active_ptr ? "[on]" : "[off]"); |
| 561 | } else if (n->type == NODE_BIND) { | 572 | } else if (n->type == NODE_BIND) { |
| 562 | if (g_bind_mode && i == g_selected) | 573 | if (g_bind_mode && i == g_selected) |
| 563 | draw_text(200, 10 + i * 20, "[press key]"); | 574 | draw_text(270, 10 + i * 20, "[press key]"); |
| 564 | else { | 575 | else { |
| 565 | /* stable name for current bind */ | 576 | /* stable name for current bind */ |
| 566 | static char bn[2][32]; | 577 | static char bn[2][32]; |
| @@ -570,7 +581,7 @@ void outer_draw() { | |||
| 570 | if (n->bind_ptr == &feats[k]->bind) | 581 | if (n->bind_ptr == &feats[k]->bind) |
| 571 | fi = k; | 582 | fi = k; |
| 572 | snprintf(bn[fi], 32, "[%s]", scancode_name(*n->bind_ptr)); | 583 | snprintf(bn[fi], 32, "[%s]", scancode_name(*n->bind_ptr)); |
| 573 | draw_text(200, 10 + i * 20, bn[fi]); | 584 | draw_text(270, 10 + i * 20, bn[fi]); |
| 574 | } | 585 | } |
| 575 | } | 586 | } |
| 576 | } | 587 | } |
