diff options
| -rw-r--r-- | src/esp.cpp | 106 | ||||
| -rw-r--r-- | src/hl2h.cpp | 7 | ||||
| -rw-r--r-- | src/hl2h.h | 4 | ||||
| -rw-r--r-- | src/menu.cpp | 30 |
4 files changed, 110 insertions, 37 deletions
diff --git a/src/esp.cpp b/src/esp.cpp index e6981f7..f7c24ce 100644 --- a/src/esp.cpp +++ b/src/esp.cpp | |||
| @@ -334,12 +334,16 @@ static QAngle angle_to(const Vector &from, const Vector &to) { | |||
| 334 | return a; | 334 | return a; |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | bool aimbot_apply(CUserCmd *cmd) { | 337 | static constexpr float AIM_MAX_FOV = 60.0f; |
| 338 | |||
| 339 | static bool select_aim_target(const QAngle &view, unsigned bone_mask, | ||
| 340 | bool vischeck, const char *tag, int &out_idx, | ||
| 341 | Vector &out_point, float &out_fov) { | ||
| 342 | out_idx = -1; | ||
| 343 | out_point = {}; | ||
| 344 | out_fov = 0.0f; | ||
| 338 | if (!g_iface.entitylist || g_net.origin < 0 || g_net.maxs < 0) | 345 | if (!g_iface.entitylist || g_net.origin < 0 || g_net.maxs < 0) |
| 339 | return false; | 346 | return false; |
| 340 | unsigned bone_mask = aimbot_bone_mask(); | ||
| 341 | if (!bone_mask) | ||
| 342 | return false; | ||
| 343 | int local = engine_get_local_player(); | 347 | int local = engine_get_local_player(); |
| 344 | if (local <= 0) | 348 | if (local <= 0) |
| 345 | return false; | 349 | return false; |
| @@ -350,14 +354,11 @@ bool aimbot_apply(CUserCmd *cmd) { | |||
| 350 | *(int *)((uintptr_t)local_ent + g_net.health) <= 0) | 354 | *(int *)((uintptr_t)local_ent + g_net.health) <= 0) |
| 351 | return false; | 355 | return false; |
| 352 | 356 | ||
| 353 | QAngle view{cmd->viewangles[0], cmd->viewangles[1], 0.0f}; | ||
| 354 | |||
| 355 | using Fn = int (*)(void *); | 357 | using Fn = int (*)(void *); |
| 356 | int hi = vfunc<Fn>(g_iface.entitylist, 6)(g_iface.entitylist); | 358 | int hi = vfunc<Fn>(g_iface.entitylist, 6)(g_iface.entitylist); |
| 357 | if (hi < 0 || hi > 4096) | 359 | if (hi < 0 || hi > 4096) |
| 358 | hi = 4096; | 360 | hi = 4096; |
| 359 | 361 | ||
| 360 | constexpr float MAX_FOV = 60.0f; // only things near the crosshair | ||
| 361 | struct Candidate { | 362 | struct Candidate { |
| 362 | int idx; | 363 | int idx; |
| 363 | float fov; | 364 | float fov; |
| @@ -398,10 +399,9 @@ bool aimbot_apply(CUserCmd *cmd) { | |||
| 398 | Vector approx{origin.x, origin.y, | 399 | Vector approx{origin.x, origin.y, |
| 399 | origin.z + maxz * ((bone_mask & (1u << 1)) ? 0.9f : 0.55f)}; | 400 | origin.z + maxz * ((bone_mask & (1u << 1)) ? 0.9f : 0.55f)}; |
| 400 | float fov = getfov(view, angle_to(g_cam_eye, approx)); | 401 | float fov = getfov(view, angle_to(g_cam_eye, approx)); |
| 401 | if (fov >= MAX_FOV) | 402 | if (fov >= AIM_MAX_FOV) |
| 402 | continue; | 403 | continue; |
| 403 | 404 | ||
| 404 | // keep candidates sorted by approximate angle, nearest first | ||
| 405 | int pos = ncands; | 405 | int pos = ncands; |
| 406 | while (pos > 0 && cands[pos - 1].fov > fov) | 406 | while (pos > 0 && cands[pos - 1].fov > fov) |
| 407 | pos--; | 407 | pos--; |
| @@ -418,15 +418,14 @@ bool aimbot_apply(CUserCmd *cmd) { | |||
| 418 | double now = esp_now(); | 418 | double now = esp_now(); |
| 419 | if (now - last_none >= 2.0) { | 419 | if (now - last_none >= 2.0) { |
| 420 | last_none = now; | 420 | last_none = now; |
| 421 | logf("aimbot: no hostile target within %.0f deg", MAX_FOV); | 421 | logf("%s: no hostile target within %.0f deg", tag, AIM_MAX_FOV); |
| 422 | } | 422 | } |
| 423 | return false; | 423 | return false; |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | // Walk targets nearest-first. On each, pick the nearest selected hitbox | ||
| 427 | // point that passes vischeck; skip to the next target if all are blocked. | ||
| 428 | int best_idx = -1; | 426 | int best_idx = -1; |
| 429 | Vector best_head{}; | 427 | Vector best_point{}; |
| 428 | float best_fov = 0.0f; | ||
| 430 | for (int ci = 0; ci < ncands && best_idx < 0; ci++) { | 429 | for (int ci = 0; ci < ncands && best_idx < 0; ci++) { |
| 431 | int idx = cands[ci].idx; | 430 | int idx = cands[ci].idx; |
| 432 | void *ent = entitylist_get(idx); | 431 | void *ent = entitylist_get(idx); |
| @@ -440,40 +439,55 @@ bool aimbot_apply(CUserCmd *cmd) { | |||
| 440 | float f = getfov(view, angle_to(g_cam_eye, pts[i])); | 439 | float f = getfov(view, angle_to(g_cam_eye, pts[i])); |
| 441 | if (f >= aim_fov) | 440 | if (f >= aim_fov) |
| 442 | continue; | 441 | continue; |
| 443 | if (aimbot_vischeck_enabled() && !is_visible(g_cam_eye, pts[i])) | 442 | if (vischeck && !is_visible(g_cam_eye, pts[i])) |
| 444 | continue; | 443 | continue; |
| 445 | aim_fov = f; | 444 | aim_fov = f; |
| 446 | aim_pt = pts[i]; | 445 | aim_pt = pts[i]; |
| 447 | } | 446 | } |
| 448 | if (aim_fov <= MAX_FOV && aim_fov < 1e8f) { | 447 | if (aim_fov <= AIM_MAX_FOV && aim_fov < 1e8f) { |
| 449 | best_idx = idx; | 448 | best_idx = idx; |
| 450 | best_head = aim_pt; | 449 | best_point = aim_pt; |
| 450 | best_fov = aim_fov; | ||
| 451 | static int sel_logs = 0; | 451 | static int sel_logs = 0; |
| 452 | if (sel_logs < 5) { | 452 | if (sel_logs < 5) { |
| 453 | sel_logs++; | 453 | sel_logs++; |
| 454 | logf("aimbot: target idx=%d points=%d fov=%.2f vischeck=%d", idx, | 454 | logf("%s: target idx=%d points=%d fov=%.2f vischeck=%d", tag, idx, |
| 455 | npoints, aim_fov, (int)aimbot_vischeck_enabled()); | 455 | npoints, aim_fov, (int)vischeck); |
| 456 | } | 456 | } |
| 457 | } | 457 | } |
| 458 | } | 458 | } |
| 459 | |||
| 460 | if (best_idx < 0) { | 459 | if (best_idx < 0) { |
| 461 | static double last_vis = 0.0; | 460 | static double last_vis = 0.0; |
| 462 | double now = esp_now(); | 461 | double now = esp_now(); |
| 463 | if (now - last_vis >= 2.0) { | 462 | if (now - last_vis >= 2.0) { |
| 464 | last_vis = now; | 463 | last_vis = now; |
| 465 | logf("aimbot: no visible aim point (vischeck=%d)", | 464 | logf("%s: no visible aim point (vischeck=%d)", tag, (int)vischeck); |
| 466 | (int)aimbot_vischeck_enabled()); | ||
| 467 | } | 465 | } |
| 468 | return false; | 466 | return false; |
| 469 | } | 467 | } |
| 468 | out_idx = best_idx; | ||
| 469 | out_point = best_point; | ||
| 470 | out_fov = best_fov; | ||
| 471 | return true; | ||
| 472 | } | ||
| 470 | 473 | ||
| 471 | QAngle desired = angle_to(g_cam_eye, best_head); | 474 | bool aimbot_apply(CUserCmd *cmd) { |
| 475 | unsigned bone_mask = aimbot_bone_mask(); | ||
| 476 | if (!bone_mask) | ||
| 477 | return false; | ||
| 478 | QAngle view{cmd->viewangles[0], cmd->viewangles[1], 0.0f}; | ||
| 479 | int target = -1; | ||
| 480 | Vector point{}; | ||
| 481 | float fov = 0.0f; | ||
| 482 | if (!select_aim_target(view, bone_mask, aimbot_vischeck_enabled(), "aimbot", | ||
| 483 | target, point, fov)) | ||
| 484 | return false; | ||
| 485 | QAngle desired = angle_to(g_cam_eye, point); | ||
| 472 | static int want_logs = 0; | 486 | static int want_logs = 0; |
| 473 | if (want_logs < 10) { | 487 | if (want_logs < 10) { |
| 474 | want_logs++; | 488 | want_logs++; |
| 475 | logf("aimbot: aim=(%.1f %.1f %.1f) want=%.2f/%.2f", best_head.x, | 489 | logf("aimbot: target=%d aim=(%.1f %.1f %.1f) fov=%.2f want=%.2f/%.2f", |
| 476 | best_head.y, best_head.z, desired.x, desired.y); | 490 | target, point.x, point.y, point.z, fov, desired.x, desired.y); |
| 477 | } | 491 | } |
| 478 | float dp = desired.x - cmd->viewangles[0]; | 492 | float dp = desired.x - cmd->viewangles[0]; |
| 479 | float dy = desired.y - cmd->viewangles[1]; | 493 | float dy = desired.y - cmd->viewangles[1]; |
| @@ -499,15 +513,11 @@ bool aimbot_apply(CUserCmd *cmd) { | |||
| 499 | cmd->viewangles[0] = np; | 513 | cmd->viewangles[0] = np; |
| 500 | cmd->viewangles[1] = ny; | 514 | cmd->viewangles[1] = ny; |
| 501 | 515 | ||
| 502 | // cmd->viewangles drives usercmd/prediction, but the rendered camera can | ||
| 503 | // stay on the pre-hook angles. Also push the smoothed angles into the | ||
| 504 | // engine's view (IVEngineClient013 slot 20 = SetViewAngles). | ||
| 505 | if (g_iface.engine) { | 516 | if (g_iface.engine) { |
| 506 | QAngle out{np, ny, 0.0f}; | 517 | QAngle out{np, ny, 0.0f}; |
| 507 | using SetViewFn = void (*)(void *, QAngle *); | 518 | using SetViewFn = void (*)(void *, QAngle *); |
| 508 | vfunc<SetViewFn>(g_iface.engine, 20)(g_iface.engine, &out); | 519 | vfunc<SetViewFn>(g_iface.engine, 20)(g_iface.engine, &out); |
| 509 | } | 520 | } |
| 510 | |||
| 511 | static int mod_logs = 0; | 521 | static int mod_logs = 0; |
| 512 | if (mod_logs < 10) { | 522 | if (mod_logs < 10) { |
| 513 | mod_logs++; | 523 | mod_logs++; |
| @@ -516,6 +526,46 @@ bool aimbot_apply(CUserCmd *cmd) { | |||
| 516 | return true; | 526 | return true; |
| 517 | } | 527 | } |
| 518 | 528 | ||
| 529 | bool silent_aim_apply(CUserCmd *cmd) { | ||
| 530 | unsigned bone_mask = aimbot_bone_mask(); | ||
| 531 | if (!bone_mask) | ||
| 532 | return false; | ||
| 533 | QAngle orig{g_cam_view.x, g_cam_view.y, g_cam_view.z}; | ||
| 534 | QAngle view{orig.x, orig.y, 0.0f}; | ||
| 535 | int target = -1; | ||
| 536 | Vector point{}; | ||
| 537 | float fov = 0.0f; | ||
| 538 | if (!select_aim_target(view, bone_mask, true, "silentaim", target, point, | ||
| 539 | fov)) | ||
| 540 | return false; | ||
| 541 | QAngle desired = angle_to(g_cam_eye, point); | ||
| 542 | float np = desired.x; | ||
| 543 | if (np > 89.0f) np = 89.0f; | ||
| 544 | if (np < -89.0f) np = -89.0f; | ||
| 545 | float ny = desired.y; | ||
| 546 | while (ny > 180.0f) ny -= 360.0f; | ||
| 547 | while (ny < -180.0f) ny += 360.0f; | ||
| 548 | |||
| 549 | cmd->viewangles[0] = np; | ||
| 550 | cmd->viewangles[1] = ny; | ||
| 551 | cmd->viewangles[2] = orig.z; | ||
| 552 | |||
| 553 | // The usercmd keeps the aim angles (shot/prediction); the rendered camera | ||
| 554 | // is restored to where the player was actually looking. | ||
| 555 | if (g_iface.engine) { | ||
| 556 | QAngle restore{orig.x, orig.y, orig.z}; | ||
| 557 | using SetViewFn = void (*)(void *, QAngle *); | ||
| 558 | vfunc<SetViewFn>(g_iface.engine, 20)(g_iface.engine, &restore); | ||
| 559 | } | ||
| 560 | cmd->buttons |= IN_ATTACK; | ||
| 561 | static int logs = 0; | ||
| 562 | if (logs < 5) { | ||
| 563 | logs++; | ||
| 564 | logf("silentaim: fire idx=%d fov=%.2f aim=%.2f/%.2f", target, fov, np, ny); | ||
| 565 | } | ||
| 566 | return true; | ||
| 567 | } | ||
| 568 | |||
| 519 | bool triggerbot_apply(CUserCmd *cmd) { | 569 | bool triggerbot_apply(CUserCmd *cmd) { |
| 520 | if (!g_iface.enginetrace || !g_iface.entitylist) | 570 | if (!g_iface.enginetrace || !g_iface.entitylist) |
| 521 | return false; | 571 | return false; |
diff --git a/src/hl2h.cpp b/src/hl2h.cpp index 7a7d32e..89d6b89 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp | |||
| @@ -262,6 +262,13 @@ static void do_move(int seq) { | |||
| 262 | note_modified(cmd, flags, vel); | 262 | note_modified(cmd, flags, vel); |
| 263 | } | 263 | } |
| 264 | } | 264 | } |
| 265 | |||
| 266 | if (feature_active(FEAT_SILENTAIM)) { | ||
| 267 | if (silent_aim_apply(cmd)) { | ||
| 268 | const float *vel = (const float *)(e + g_net.velocity); | ||
| 269 | note_modified(cmd, flags, vel); | ||
| 270 | } | ||
| 271 | } | ||
| 265 | } | 272 | } |
| 266 | 273 | ||
| 267 | // --------------------------------------------------------------------------- | 274 | // --------------------------------------------------------------------------- |
| @@ -140,12 +140,14 @@ Vector angle_forward_vector(const QAngle &angles); | |||
| 140 | float getfov(const QAngle &my_view, const QAngle &aim_ang); | 140 | float getfov(const QAngle &my_view, const QAngle &aim_ang); |
| 141 | bool aimbot_apply(CUserCmd *cmd); | 141 | bool aimbot_apply(CUserCmd *cmd); |
| 142 | bool triggerbot_apply(CUserCmd *cmd); | 142 | bool triggerbot_apply(CUserCmd *cmd); |
| 143 | bool silent_aim_apply(CUserCmd *cmd); | ||
| 143 | enum FeatureId { | 144 | enum FeatureId { |
| 144 | FEAT_BHOP = 0, | 145 | FEAT_BHOP = 0, |
| 145 | FEAT_ABH = 1, | 146 | FEAT_ABH = 1, |
| 146 | FEAT_ESP = 2, | 147 | FEAT_ESP = 2, |
| 147 | FEAT_AIMBOT = 3, | 148 | FEAT_AIMBOT = 3, |
| 148 | FEAT_TRIGGERBOT = 4 | 149 | FEAT_TRIGGERBOT = 4, |
| 150 | FEAT_SILENTAIM = 5 | ||
| 149 | }; | 151 | }; |
| 150 | enum EspOption { | 152 | enum EspOption { |
| 151 | ESP_OPT_SHOW_NEUTRAL = 0, | 153 | ESP_OPT_SHOW_NEUTRAL = 0, |
diff --git a/src/menu.cpp b/src/menu.cpp index 585695c..11ed222 100644 --- a/src/menu.cpp +++ b/src/menu.cpp | |||
| @@ -62,6 +62,7 @@ static FeatureState g_abh{true, 0}; | |||
| 62 | static FeatureState g_esp{true, 0}; | 62 | static FeatureState g_esp{true, 0}; |
| 63 | static FeatureState g_aimbot{true, 604}; // default Mouse5, rebindable in menu | 63 | static FeatureState g_aimbot{true, 604}; // default Mouse5, rebindable in menu |
| 64 | static FeatureState g_triggerbot{true, 603}; // default Mouse4 | 64 | static FeatureState g_triggerbot{true, 603}; // default Mouse4 |
| 65 | static FeatureState g_silentaim{true, 602}; // default Mouse3 | ||
| 65 | 66 | ||
| 66 | // Aimbot bone checklist. Head defaults on (v1 behaviour). | 67 | // Aimbot bone checklist. Head defaults on (v1 behaviour). |
| 67 | enum { | 68 | enum { |
| @@ -117,6 +118,9 @@ static MenuNode g_aimbot_smooth_node{NODE_VALUE, "Smoothness", false, 0, {}, nul | |||
| 117 | static MenuNode g_triggerbot_feat{NODE_FEATURE, "Triggerbot", false, 1, {}, nullptr, nullptr, nullptr}; | 118 | static MenuNode g_triggerbot_feat{NODE_FEATURE, "Triggerbot", false, 1, {}, nullptr, nullptr, nullptr}; |
| 118 | static MenuNode g_triggerbot_active{NODE_TOGGLE, "Active", false, 0, {}, &g_triggerbot.active, nullptr, nullptr}; | 119 | static MenuNode g_triggerbot_active{NODE_TOGGLE, "Active", false, 0, {}, &g_triggerbot.active, nullptr, nullptr}; |
| 119 | static MenuNode g_triggerbot_bind{NODE_BIND, "Bind", false, 0, {}, nullptr, &g_triggerbot.bind, nullptr}; | 120 | static MenuNode g_triggerbot_bind{NODE_BIND, "Bind", false, 0, {}, nullptr, &g_triggerbot.bind, nullptr}; |
| 121 | static MenuNode g_silentaim_feat{NODE_FEATURE, "Silent aim", false, 1, {}, nullptr, nullptr, nullptr}; | ||
| 122 | static MenuNode g_silentaim_active{NODE_TOGGLE, "Active", false, 0, {}, &g_silentaim.active, nullptr, nullptr}; | ||
| 123 | static MenuNode g_silentaim_bind{NODE_BIND, "Bind", false, 0, {}, nullptr, &g_silentaim.bind, nullptr}; | ||
| 120 | 124 | ||
| 121 | static MenuNode *g_visible[32]; // flattened visible nodes for arrow navigation | 125 | static MenuNode *g_visible[32]; // flattened visible nodes for arrow navigation |
| 122 | static int g_visible_count = 0; | 126 | static int g_visible_count = 0; |
| @@ -142,6 +146,9 @@ static void build_tree() { | |||
| 142 | g_triggerbot_feat.children[0] = &g_triggerbot_active; | 146 | g_triggerbot_feat.children[0] = &g_triggerbot_active; |
| 143 | g_triggerbot_feat.children[1] = &g_triggerbot_bind; | 147 | g_triggerbot_feat.children[1] = &g_triggerbot_bind; |
| 144 | g_triggerbot_feat.child_count = 2; | 148 | g_triggerbot_feat.child_count = 2; |
| 149 | g_silentaim_feat.children[0] = &g_silentaim_active; | ||
| 150 | g_silentaim_feat.children[1] = &g_silentaim_bind; | ||
| 151 | g_silentaim_feat.child_count = 2; | ||
| 145 | for (int i = 0; i < ESP_OPT_COUNT; i++) | 152 | for (int i = 0; i < ESP_OPT_COUNT; i++) |
| 146 | g_esp_feat.children[i + 1] = &g_esp_opt_nodes[i]; | 153 | g_esp_feat.children[i + 1] = &g_esp_opt_nodes[i]; |
| 147 | g_esp_feat.child_count = ESP_OPT_COUNT + 1; | 154 | g_esp_feat.child_count = ESP_OPT_COUNT + 1; |
| @@ -150,7 +157,8 @@ static void build_tree() { | |||
| 150 | g_root.children[2] = &g_esp_feat; | 157 | g_root.children[2] = &g_esp_feat; |
| 151 | g_root.children[3] = &g_aimbot_feat; | 158 | g_root.children[3] = &g_aimbot_feat; |
| 152 | g_root.children[4] = &g_triggerbot_feat; | 159 | g_root.children[4] = &g_triggerbot_feat; |
| 153 | g_root.child_count = 5; | 160 | g_root.children[5] = &g_silentaim_feat; |
| 161 | g_root.child_count = 6; | ||
| 154 | } | 162 | } |
| 155 | 163 | ||
| 156 | static int g_depth[32]; // depth of each visible row (for indentation) | 164 | static int g_depth[32]; // depth of each visible row (for indentation) |
| @@ -224,6 +232,8 @@ static void config_save() { | |||
| 224 | g_aim_bones[AIM_BONE_LLEG], g_aim_bones[AIM_BONE_RLEG]); | 232 | g_aim_bones[AIM_BONE_LLEG], g_aim_bones[AIM_BONE_RLEG]); |
| 225 | fprintf(f, "[triggerbot]\nactive=%d\nbind=%d\n", g_triggerbot.active, | 233 | fprintf(f, "[triggerbot]\nactive=%d\nbind=%d\n", g_triggerbot.active, |
| 226 | g_triggerbot.bind); | 234 | g_triggerbot.bind); |
| 235 | fprintf(f, "[silentaim]\nactive=%d\nbind=%d\n", g_silentaim.active, | ||
| 236 | g_silentaim.bind); | ||
| 227 | fprintf(f, "[esp]\nactive=%d\nbind=%d\nneutral=%d\nhealthbar=%d\n" | 237 | fprintf(f, "[esp]\nactive=%d\nbind=%d\nneutral=%d\nhealthbar=%d\n" |
| 228 | "healthnum=%d\nname=%d\nskeleton=%d\nbox=%d\n", | 238 | "healthnum=%d\nname=%d\nskeleton=%d\nbox=%d\n", |
| 229 | g_esp.active, g_esp.bind, g_esp_opt[ESP_OPT_SHOW_NEUTRAL], | 239 | g_esp.active, g_esp.bind, g_esp_opt[ESP_OPT_SHOW_NEUTRAL], |
| @@ -253,6 +263,8 @@ static void config_load() { | |||
| 253 | cur = &g_aimbot; | 263 | cur = &g_aimbot; |
| 254 | else if (strstr(line, "[triggerbot]")) | 264 | else if (strstr(line, "[triggerbot]")) |
| 255 | cur = &g_triggerbot; | 265 | cur = &g_triggerbot; |
| 266 | else if (strstr(line, "[silentaim]")) | ||
| 267 | cur = &g_silentaim; | ||
| 256 | else | 268 | else |
| 257 | cur = nullptr; | 269 | cur = nullptr; |
| 258 | in_esp = (cur == &g_esp); | 270 | in_esp = (cur == &g_esp); |
| @@ -413,9 +425,10 @@ static bool key_pressed(int sc) { | |||
| 413 | // feature gate queried from hl2h.cpp do_move(): feature must be Active AND | 425 | // feature gate queried from hl2h.cpp do_move(): feature must be Active AND |
| 414 | // its bind key held (always-on when unbound). | 426 | // its bind key held (always-on when unbound). |
| 415 | bool feature_active(int feature) { | 427 | bool feature_active(int feature) { |
| 416 | static FeatureState *feats[5] = {&g_bhop, &g_abh, &g_esp, &g_aimbot, | 428 | static FeatureState *feats[6] = {&g_bhop, &g_abh, &g_esp, |
| 417 | &g_triggerbot}; | 429 | &g_aimbot, &g_triggerbot, |
| 418 | if (feature < 0 || feature > 4) | 430 | &g_silentaim}; |
| 431 | if (feature < 0 || feature > 5) | ||
| 419 | return false; | 432 | return false; |
| 420 | FeatureState *f = feats[feature]; | 433 | FeatureState *f = feats[feature]; |
| 421 | if (!f->active) | 434 | if (!f->active) |
| @@ -492,7 +505,8 @@ static void menu_handle_input() { | |||
| 492 | MenuNode *n = g_visible[g_selected]; | 505 | MenuNode *n = g_visible[g_selected]; |
| 493 | if (n->bind_ptr) { | 506 | if (n->bind_ptr) { |
| 494 | // clear same bind from other features | 507 | // clear same bind from other features |
| 495 | FeatureState *features[] = {&g_bhop, &g_abh, &g_aimbot, &g_triggerbot}; | 508 | FeatureState *features[] = {&g_bhop, &g_abh, &g_aimbot, &g_triggerbot, |
| 509 | &g_silentaim}; | ||
| 496 | for (auto *f : features) | 510 | for (auto *f : features) |
| 497 | if (&f->bind != n->bind_ptr && f->bind == i) | 511 | if (&f->bind != n->bind_ptr && f->bind == i) |
| 498 | f->bind = 0; | 512 | f->bind = 0; |
| @@ -707,11 +721,11 @@ void outer_draw() { | |||
| 707 | draw_text(270, 10 + i * 20, "[press key]"); | 721 | draw_text(270, 10 + i * 20, "[press key]"); |
| 708 | else { | 722 | else { |
| 709 | /* stable name for current bind */ | 723 | /* stable name for current bind */ |
| 710 | static char bn[4][32]; | 724 | static char bn[5][32]; |
| 711 | static FeatureState *feats[] = {&g_bhop, &g_abh, &g_aimbot, | 725 | static FeatureState *feats[] = {&g_bhop, &g_abh, &g_aimbot, |
| 712 | &g_triggerbot}; | 726 | &g_triggerbot, &g_silentaim}; |
| 713 | int fi = 0; | 727 | int fi = 0; |
| 714 | for (int k = 0; k < 4; k++) | 728 | for (int k = 0; k < 5; k++) |
| 715 | if (n->bind_ptr == &feats[k]->bind) | 729 | if (n->bind_ptr == &feats[k]->bind) |
| 716 | fi = k; | 730 | fi = k; |
| 717 | snprintf(bn[fi], 32, "[%s]", scancode_name(*n->bind_ptr)); | 731 | snprintf(bn[fi], 32, "[%s]", scancode_name(*n->bind_ptr)); |
