diff options
| author | salmonik <salmonik@tuta.io> | 2026-10-27 12:43:59 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-10-27 12:43:59 +0100 |
| commit | 5adb4303c8ac4969312fa1afd4f254cba65f6ecc (patch) | |
| tree | 5a82f08cef4ae7b9d344826c7b96710eb46db101 /src/menu.cpp | |
| parent | Bones: ignore uninitialized/zero bone matrices (diff) | |
| download | hl2h-5adb4303c8ac4969312fa1afd4f254cba65f6ecc.tar.gz hl2h-5adb4303c8ac4969312fa1afd4f254cba65f6ecc.zip | |
Aimbot/silent aim: settable FOV, FOV circle, target locking
- Aimbot -> FOV and Silent aim -> FOV values (1..180 deg from the crosshair)
- Aimbot -> Show FOV circle: projects the FOV cone through the engine's
world->screen transform (hidden for >=89 deg since the boundary is behind
the eye)
- target lock: while a feature has a bind and the key is held, the acquired
target is kept while it is alive and has a visible selected hitbox point;
it only re-acquires when the target dies/leaves visibility or the key is
released. With bind = None both features keep selecting the nearest target.
Diffstat (limited to '')
| -rw-r--r-- | src/menu.cpp | 72 |
1 files changed, 59 insertions, 13 deletions
diff --git a/src/menu.cpp b/src/menu.cpp index 41d3321..49dd886 100644 --- a/src/menu.cpp +++ b/src/menu.cpp | |||
| @@ -81,6 +81,9 @@ static bool g_aim_bones[AIM_BONE_COUNT] = {true, false, false, | |||
| 81 | false, false, false}; | 81 | false, false, false}; |
| 82 | static int g_aim_smooth = 5; // degrees per tick | 82 | static int g_aim_smooth = 5; // degrees per tick |
| 83 | static bool g_aim_vischeck = true; | 83 | static bool g_aim_vischeck = true; |
| 84 | static int g_aim_fov = 60; // angular distance from the crosshair | ||
| 85 | static bool g_aim_fov_circle = true; | ||
| 86 | static int g_silent_fov = 60; | ||
| 84 | 87 | ||
| 85 | // ESP sub-options (menu "ESP" children). Defaults match the pre-option | 88 | // ESP sub-options (menu "ESP" children). Defaults match the pre-option |
| 86 | // behaviour: everything on. | 89 | // behaviour: everything on. |
| @@ -118,14 +121,19 @@ static MenuNode g_aimbot_bone_nodes[AIM_BONE_COUNT] = { | |||
| 118 | }; | 121 | }; |
| 119 | static MenuNode g_aimbot_smooth_node{NODE_VALUE, "Smoothness", false, 0, {}, nullptr, | 122 | static MenuNode g_aimbot_smooth_node{NODE_VALUE, "Smoothness", false, 0, {}, nullptr, |
| 120 | nullptr, nullptr, &g_aim_smooth, 1, 45, 1}; | 123 | nullptr, nullptr, &g_aim_smooth, 1, 45, 1}; |
| 124 | static MenuNode g_aimbot_fov_node{NODE_VALUE, "FOV", false, 0, {}, nullptr, | ||
| 125 | nullptr, nullptr, &g_aim_fov, 1, 180, 1}; | ||
| 126 | static MenuNode g_aimbot_fov_circle_node{NODE_TOGGLE, "Show FOV circle", false, 0, {}, &g_aim_fov_circle, nullptr, nullptr}; | ||
| 121 | static MenuNode g_triggerbot_feat{NODE_FEATURE, "Triggerbot", false, 1, {}, nullptr, nullptr, nullptr}; | 127 | static MenuNode g_triggerbot_feat{NODE_FEATURE, "Triggerbot", false, 1, {}, nullptr, nullptr, nullptr}; |
| 122 | static MenuNode g_triggerbot_active{NODE_TOGGLE, "Active", false, 0, {}, &g_triggerbot.active, nullptr, nullptr}; | 128 | static MenuNode g_triggerbot_active{NODE_TOGGLE, "Active", false, 0, {}, &g_triggerbot.active, nullptr, nullptr}; |
| 123 | static MenuNode g_triggerbot_bind{NODE_BIND, "Bind", false, 0, {}, nullptr, &g_triggerbot.bind, nullptr}; | 129 | static MenuNode g_triggerbot_bind{NODE_BIND, "Bind", false, 0, {}, nullptr, &g_triggerbot.bind, nullptr}; |
| 124 | static MenuNode g_silentaim_feat{NODE_FEATURE, "Silent aim", false, 1, {}, nullptr, nullptr, nullptr}; | 130 | static MenuNode g_silentaim_feat{NODE_FEATURE, "Silent aim", false, 1, {}, nullptr, nullptr, nullptr}; |
| 125 | static MenuNode g_silentaim_active{NODE_TOGGLE, "Active", false, 0, {}, &g_silentaim.active, nullptr, nullptr}; | 131 | static MenuNode g_silentaim_active{NODE_TOGGLE, "Active", false, 0, {}, &g_silentaim.active, nullptr, nullptr}; |
| 126 | static MenuNode g_silentaim_bind{NODE_BIND, "Bind", false, 0, {}, nullptr, &g_silentaim.bind, nullptr}; | 132 | static MenuNode g_silentaim_bind{NODE_BIND, "Bind", false, 0, {}, nullptr, &g_silentaim.bind, nullptr}; |
| 133 | static MenuNode g_silentaim_fov_node{NODE_VALUE, "FOV", false, 0, {}, nullptr, | ||
| 134 | nullptr, nullptr, &g_silent_fov, 1, 180, 1}; | ||
| 127 | 135 | ||
| 128 | static MenuNode *g_visible[32]; // flattened visible nodes for arrow navigation | 136 | static MenuNode *g_visible[48]; // flattened visible nodes for arrow navigation |
| 129 | static int g_visible_count = 0; | 137 | static int g_visible_count = 0; |
| 130 | static int g_selected = 0; | 138 | static int g_selected = 0; |
| 131 | bool g_menu_open = false; | 139 | bool g_menu_open = false; |
| @@ -142,7 +150,9 @@ static void build_tree() { | |||
| 142 | g_aimbot_feat.children[2] = &g_aimbot_vischeck_node; | 150 | g_aimbot_feat.children[2] = &g_aimbot_vischeck_node; |
| 143 | g_aimbot_feat.children[3] = &g_aimbot_bones_feat; | 151 | g_aimbot_feat.children[3] = &g_aimbot_bones_feat; |
| 144 | g_aimbot_feat.children[4] = &g_aimbot_smooth_node; | 152 | g_aimbot_feat.children[4] = &g_aimbot_smooth_node; |
| 145 | g_aimbot_feat.child_count = 5; | 153 | g_aimbot_feat.children[5] = &g_aimbot_fov_node; |
| 154 | g_aimbot_feat.children[6] = &g_aimbot_fov_circle_node; | ||
| 155 | g_aimbot_feat.child_count = 7; | ||
| 146 | for (int i = 0; i < AIM_BONE_COUNT; i++) | 156 | for (int i = 0; i < AIM_BONE_COUNT; i++) |
| 147 | g_aimbot_bones_feat.children[i] = &g_aimbot_bone_nodes[i]; | 157 | g_aimbot_bones_feat.children[i] = &g_aimbot_bone_nodes[i]; |
| 148 | g_aimbot_bones_feat.child_count = AIM_BONE_COUNT; | 158 | g_aimbot_bones_feat.child_count = AIM_BONE_COUNT; |
| @@ -151,7 +161,8 @@ static void build_tree() { | |||
| 151 | g_triggerbot_feat.child_count = 2; | 161 | g_triggerbot_feat.child_count = 2; |
| 152 | g_silentaim_feat.children[0] = &g_silentaim_active; | 162 | g_silentaim_feat.children[0] = &g_silentaim_active; |
| 153 | g_silentaim_feat.children[1] = &g_silentaim_bind; | 163 | g_silentaim_feat.children[1] = &g_silentaim_bind; |
| 154 | g_silentaim_feat.child_count = 2; | 164 | g_silentaim_feat.children[2] = &g_silentaim_fov_node; |
| 165 | g_silentaim_feat.child_count = 3; | ||
| 155 | for (int i = 0; i < ESP_OPT_COUNT; i++) | 166 | for (int i = 0; i < ESP_OPT_COUNT; i++) |
| 156 | g_esp_feat.children[i + 1] = &g_esp_opt_nodes[i]; | 167 | g_esp_feat.children[i + 1] = &g_esp_opt_nodes[i]; |
| 157 | g_esp_feat.child_count = ESP_OPT_COUNT + 1; | 168 | g_esp_feat.child_count = ESP_OPT_COUNT + 1; |
| @@ -164,10 +175,10 @@ static void build_tree() { | |||
| 164 | g_root.child_count = 6; | 175 | g_root.child_count = 6; |
| 165 | } | 176 | } |
| 166 | 177 | ||
| 167 | static int g_depth[32]; // depth of each visible row (for indentation) | 178 | static int g_depth[48]; // depth of each visible row (for indentation) |
| 168 | 179 | ||
| 169 | static void flatten(MenuNode *node, int depth) { | 180 | static void flatten(MenuNode *node, int depth) { |
| 170 | if (g_visible_count >= 32) | 181 | if (g_visible_count >= 48) |
| 171 | return; | 182 | return; |
| 172 | node->type = (depth == 0) ? NODE_ROOT | 183 | node->type = (depth == 0) ? NODE_ROOT |
| 173 | : (node->child_count > 0) ? NODE_FEATURE | 184 | : (node->child_count > 0) ? NODE_FEATURE |
| @@ -284,17 +295,18 @@ static void config_save() { | |||
| 284 | g_bhop.bind, g_bhop_autostrafe); | 295 | g_bhop.bind, g_bhop_autostrafe); |
| 285 | fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); | 296 | fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); |
| 286 | fprintf(f, "[aimbot]\nactive=%d\nbind=%d\nsmooth=%d\nvischeck=%d\n" | 297 | fprintf(f, "[aimbot]\nactive=%d\nbind=%d\nsmooth=%d\nvischeck=%d\n" |
| 298 | "fov=%d\nfov_circle=%d\n" | ||
| 287 | "bone_head=%d\nbone_torso=%d\nbone_larm=%d\nbone_rarm=%d\n" | 299 | "bone_head=%d\nbone_torso=%d\nbone_larm=%d\nbone_rarm=%d\n" |
| 288 | "bone_lleg=%d\nbone_rleg=%d\n", | 300 | "bone_lleg=%d\nbone_rleg=%d\n", |
| 289 | g_aimbot.active, g_aimbot.bind, g_aim_smooth, | 301 | g_aimbot.active, g_aimbot.bind, g_aim_smooth, |
| 290 | (int)g_aim_vischeck, | 302 | (int)g_aim_vischeck, g_aim_fov, (int)g_aim_fov_circle, |
| 291 | g_aim_bones[AIM_BONE_HEAD], g_aim_bones[AIM_BONE_TORSO], | 303 | g_aim_bones[AIM_BONE_HEAD], g_aim_bones[AIM_BONE_TORSO], |
| 292 | g_aim_bones[AIM_BONE_LARM], g_aim_bones[AIM_BONE_RARM], | 304 | g_aim_bones[AIM_BONE_LARM], g_aim_bones[AIM_BONE_RARM], |
| 293 | g_aim_bones[AIM_BONE_LLEG], g_aim_bones[AIM_BONE_RLEG]); | 305 | g_aim_bones[AIM_BONE_LLEG], g_aim_bones[AIM_BONE_RLEG]); |
| 294 | fprintf(f, "[triggerbot]\nactive=%d\nbind=%d\n", g_triggerbot.active, | 306 | fprintf(f, "[triggerbot]\nactive=%d\nbind=%d\n", g_triggerbot.active, |
| 295 | g_triggerbot.bind); | 307 | g_triggerbot.bind); |
| 296 | fprintf(f, "[silentaim]\nactive=%d\nbind=%d\n", g_silentaim.active, | 308 | fprintf(f, "[silentaim]\nactive=%d\nbind=%d\nfov=%d\n", g_silentaim.active, |
| 297 | g_silentaim.bind); | 309 | g_silentaim.bind, g_silent_fov); |
| 298 | fprintf(f, "[esp]\nactive=%d\nbind=%d\nneutral=%d\nhealthbar=%d\n" | 310 | fprintf(f, "[esp]\nactive=%d\nbind=%d\nneutral=%d\nhealthbar=%d\n" |
| 299 | "healthnum=%d\nname=%d\nskeleton=%d\nbox=%d\n", | 311 | "healthnum=%d\nname=%d\nskeleton=%d\nbox=%d\n", |
| 300 | g_esp.active, g_esp.bind, g_esp_opt[ESP_OPT_SHOW_NEUTRAL], | 312 | g_esp.active, g_esp.bind, g_esp_opt[ESP_OPT_SHOW_NEUTRAL], |
| @@ -310,7 +322,7 @@ static void config_load() { | |||
| 310 | return; | 322 | return; |
| 311 | char line[256]; | 323 | char line[256]; |
| 312 | FeatureState *cur = nullptr; | 324 | FeatureState *cur = nullptr; |
| 313 | bool in_esp = false, in_bhop = false, in_aim = false; | 325 | bool in_esp = false, in_bhop = false, in_aim = false, in_silent = false; |
| 314 | while (fgets(line, sizeof(line), f)) { | 326 | while (fgets(line, sizeof(line), f)) { |
| 315 | line[strcspn(line, "\r\n")] = 0; | 327 | line[strcspn(line, "\r\n")] = 0; |
| 316 | if (line[0] == '[') { | 328 | if (line[0] == '[') { |
| @@ -331,6 +343,7 @@ static void config_load() { | |||
| 331 | in_esp = (cur == &g_esp); | 343 | in_esp = (cur == &g_esp); |
| 332 | in_bhop = (cur == &g_bhop); | 344 | in_bhop = (cur == &g_bhop); |
| 333 | in_aim = (cur == &g_aimbot); | 345 | in_aim = (cur == &g_aimbot); |
| 346 | in_silent = (cur == &g_silentaim); | ||
| 334 | } else if (cur) { | 347 | } else if (cur) { |
| 335 | char *eq = strchr(line, '='); | 348 | char *eq = strchr(line, '='); |
| 336 | if (!eq) | 349 | if (!eq) |
| @@ -360,8 +373,21 @@ static void config_load() { | |||
| 360 | g_aim_bones[AIM_BONE_RLEG] = atoi(val) != 0; | 373 | g_aim_bones[AIM_BONE_RLEG] = atoi(val) != 0; |
| 361 | } else if (strcmp(key, "vischeck") == 0) { | 374 | } else if (strcmp(key, "vischeck") == 0) { |
| 362 | g_aim_vischeck = atoi(val) != 0; | 375 | g_aim_vischeck = atoi(val) != 0; |
| 376 | } else if (strcmp(key, "fov") == 0) { | ||
| 377 | int v = atoi(val); | ||
| 378 | if (v < 1) v = 1; | ||
| 379 | if (v > 180) v = 180; | ||
| 380 | g_aim_fov = v; | ||
| 381 | } else if (strcmp(key, "fov_circle") == 0) { | ||
| 382 | g_aim_fov_circle = atoi(val) != 0; | ||
| 363 | } | 383 | } |
| 364 | } | 384 | } |
| 385 | if (in_silent && strcmp(key, "fov") == 0) { | ||
| 386 | int v = atoi(val); | ||
| 387 | if (v < 1) v = 1; | ||
| 388 | if (v > 180) v = 180; | ||
| 389 | g_silent_fov = v; | ||
| 390 | } | ||
| 365 | if (in_esp) { | 391 | if (in_esp) { |
| 366 | if (strcmp(key, "neutral") == 0) | 392 | if (strcmp(key, "neutral") == 0) |
| 367 | g_esp_opt[ESP_OPT_SHOW_NEUTRAL] = atoi(val) != 0; | 393 | g_esp_opt[ESP_OPT_SHOW_NEUTRAL] = atoi(val) != 0; |
| @@ -485,18 +511,32 @@ static bool key_pressed(int sc) { | |||
| 485 | 511 | ||
| 486 | // feature gate queried from hl2h.cpp do_move(): feature must be Active AND | 512 | // feature gate queried from hl2h.cpp do_move(): feature must be Active AND |
| 487 | // its bind key held (always-on when unbound). | 513 | // its bind key held (always-on when unbound). |
| 488 | bool feature_active(int feature) { | 514 | static FeatureState *feature_state(int feature) { |
| 489 | static FeatureState *feats[6] = {&g_bhop, &g_abh, &g_esp, | 515 | static FeatureState *feats[6] = {&g_bhop, &g_abh, &g_esp, |
| 490 | &g_aimbot, &g_triggerbot, | 516 | &g_aimbot, &g_triggerbot, |
| 491 | &g_silentaim}; | 517 | &g_silentaim}; |
| 492 | if (feature < 0 || feature > 5) | 518 | if (feature < 0 || feature > 5) |
| 493 | return false; | 519 | return nullptr; |
| 494 | FeatureState *f = feats[feature]; | 520 | return feats[feature]; |
| 495 | if (!f->active) | 521 | } |
| 522 | |||
| 523 | bool feature_active(int feature) { | ||
| 524 | FeatureState *f = feature_state(feature); | ||
| 525 | if (!f || !f->active) | ||
| 496 | return false; | 526 | return false; |
| 497 | return f->bind == 0 || key_held(f->bind); | 527 | return f->bind == 0 || key_held(f->bind); |
| 498 | } | 528 | } |
| 499 | 529 | ||
| 530 | bool feature_has_bind(int feature) { | ||
| 531 | FeatureState *f = feature_state(feature); | ||
| 532 | return f && f->bind != 0; | ||
| 533 | } | ||
| 534 | |||
| 535 | bool feature_bind_held(int feature) { | ||
| 536 | FeatureState *f = feature_state(feature); | ||
| 537 | return f && f->bind != 0 && key_held(f->bind); | ||
| 538 | } | ||
| 539 | |||
| 500 | bool esp_option(int opt) { | 540 | bool esp_option(int opt) { |
| 501 | return opt >= 0 && opt < ESP_OPT_COUNT && g_esp_opt[opt]; | 541 | return opt >= 0 && opt < ESP_OPT_COUNT && g_esp_opt[opt]; |
| 502 | } | 542 | } |
| @@ -524,6 +564,12 @@ int aimbot_smooth_step() { return g_aim_smooth; } | |||
| 524 | 564 | ||
| 525 | bool aimbot_vischeck_enabled() { return g_aim_vischeck; } | 565 | bool aimbot_vischeck_enabled() { return g_aim_vischeck; } |
| 526 | 566 | ||
| 567 | int aimbot_fov() { return g_aim_fov; } | ||
| 568 | |||
| 569 | int silentaim_fov() { return g_silent_fov; } | ||
| 570 | |||
| 571 | bool aimbot_fov_circle() { return g_aim_fov_circle; } | ||
| 572 | |||
| 527 | static void menu_handle_input() { | 573 | static void menu_handle_input() { |
| 528 | poll_keyboard(); | 574 | poll_keyboard(); |
| 529 | 575 | ||
