From 92d388116cc19ef728d66ac67eaa4f584e63d895 Mon Sep 17 00:00:00 2001 From: salmonik Date: Mon, 26 Oct 2026 17:30:29 +0100 Subject: Silent aim: exact usercmd angle + fire, restore rendered view - new top-level Silent aim feature (Active + Bind, default Mouse3) - reuses the shared aim-target selection (bone checklist, nearest selected point, world-only MASK_VISIBLE vischeck) - writes the exact target angle into cmd->viewangles, sets IN_ATTACK for the shot, then immediately restores engine view angles to the player's input view (g_cam_view) so the camera stays where it was - shares the vischeck/bone selection with the aimbot; independent of the aimbot/triggerbot binds - config [silentaim] active/bind --- src/esp.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 28 deletions(-) (limited to 'src/esp.cpp') 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) { return a; } -bool aimbot_apply(CUserCmd *cmd) { +static constexpr float AIM_MAX_FOV = 60.0f; + +static bool select_aim_target(const QAngle &view, unsigned bone_mask, + bool vischeck, const char *tag, int &out_idx, + Vector &out_point, float &out_fov) { + out_idx = -1; + out_point = {}; + out_fov = 0.0f; if (!g_iface.entitylist || g_net.origin < 0 || g_net.maxs < 0) return false; - unsigned bone_mask = aimbot_bone_mask(); - if (!bone_mask) - return false; int local = engine_get_local_player(); if (local <= 0) return false; @@ -350,14 +354,11 @@ bool aimbot_apply(CUserCmd *cmd) { *(int *)((uintptr_t)local_ent + g_net.health) <= 0) return false; - QAngle view{cmd->viewangles[0], cmd->viewangles[1], 0.0f}; - using Fn = int (*)(void *); int hi = vfunc(g_iface.entitylist, 6)(g_iface.entitylist); if (hi < 0 || hi > 4096) hi = 4096; - constexpr float MAX_FOV = 60.0f; // only things near the crosshair struct Candidate { int idx; float fov; @@ -398,10 +399,9 @@ bool aimbot_apply(CUserCmd *cmd) { Vector approx{origin.x, origin.y, origin.z + maxz * ((bone_mask & (1u << 1)) ? 0.9f : 0.55f)}; float fov = getfov(view, angle_to(g_cam_eye, approx)); - if (fov >= MAX_FOV) + if (fov >= AIM_MAX_FOV) continue; - // keep candidates sorted by approximate angle, nearest first int pos = ncands; while (pos > 0 && cands[pos - 1].fov > fov) pos--; @@ -418,15 +418,14 @@ bool aimbot_apply(CUserCmd *cmd) { double now = esp_now(); if (now - last_none >= 2.0) { last_none = now; - logf("aimbot: no hostile target within %.0f deg", MAX_FOV); + logf("%s: no hostile target within %.0f deg", tag, AIM_MAX_FOV); } return false; } - // Walk targets nearest-first. On each, pick the nearest selected hitbox - // point that passes vischeck; skip to the next target if all are blocked. int best_idx = -1; - Vector best_head{}; + Vector best_point{}; + float best_fov = 0.0f; for (int ci = 0; ci < ncands && best_idx < 0; ci++) { int idx = cands[ci].idx; void *ent = entitylist_get(idx); @@ -440,40 +439,55 @@ bool aimbot_apply(CUserCmd *cmd) { float f = getfov(view, angle_to(g_cam_eye, pts[i])); if (f >= aim_fov) continue; - if (aimbot_vischeck_enabled() && !is_visible(g_cam_eye, pts[i])) + if (vischeck && !is_visible(g_cam_eye, pts[i])) continue; aim_fov = f; aim_pt = pts[i]; } - if (aim_fov <= MAX_FOV && aim_fov < 1e8f) { + if (aim_fov <= AIM_MAX_FOV && aim_fov < 1e8f) { best_idx = idx; - best_head = aim_pt; + best_point = aim_pt; + best_fov = aim_fov; static int sel_logs = 0; if (sel_logs < 5) { sel_logs++; - logf("aimbot: target idx=%d points=%d fov=%.2f vischeck=%d", idx, - npoints, aim_fov, (int)aimbot_vischeck_enabled()); + logf("%s: target idx=%d points=%d fov=%.2f vischeck=%d", tag, idx, + npoints, aim_fov, (int)vischeck); } } } - if (best_idx < 0) { static double last_vis = 0.0; double now = esp_now(); if (now - last_vis >= 2.0) { last_vis = now; - logf("aimbot: no visible aim point (vischeck=%d)", - (int)aimbot_vischeck_enabled()); + logf("%s: no visible aim point (vischeck=%d)", tag, (int)vischeck); } return false; } + out_idx = best_idx; + out_point = best_point; + out_fov = best_fov; + return true; +} - QAngle desired = angle_to(g_cam_eye, best_head); +bool aimbot_apply(CUserCmd *cmd) { + unsigned bone_mask = aimbot_bone_mask(); + if (!bone_mask) + return false; + QAngle view{cmd->viewangles[0], cmd->viewangles[1], 0.0f}; + int target = -1; + Vector point{}; + float fov = 0.0f; + if (!select_aim_target(view, bone_mask, aimbot_vischeck_enabled(), "aimbot", + target, point, fov)) + return false; + QAngle desired = angle_to(g_cam_eye, point); static int want_logs = 0; if (want_logs < 10) { want_logs++; - logf("aimbot: aim=(%.1f %.1f %.1f) want=%.2f/%.2f", best_head.x, - best_head.y, best_head.z, desired.x, desired.y); + logf("aimbot: target=%d aim=(%.1f %.1f %.1f) fov=%.2f want=%.2f/%.2f", + target, point.x, point.y, point.z, fov, desired.x, desired.y); } float dp = desired.x - cmd->viewangles[0]; float dy = desired.y - cmd->viewangles[1]; @@ -499,15 +513,11 @@ bool aimbot_apply(CUserCmd *cmd) { cmd->viewangles[0] = np; cmd->viewangles[1] = ny; - // cmd->viewangles drives usercmd/prediction, but the rendered camera can - // stay on the pre-hook angles. Also push the smoothed angles into the - // engine's view (IVEngineClient013 slot 20 = SetViewAngles). if (g_iface.engine) { QAngle out{np, ny, 0.0f}; using SetViewFn = void (*)(void *, QAngle *); vfunc(g_iface.engine, 20)(g_iface.engine, &out); } - static int mod_logs = 0; if (mod_logs < 10) { mod_logs++; @@ -516,6 +526,46 @@ bool aimbot_apply(CUserCmd *cmd) { return true; } +bool silent_aim_apply(CUserCmd *cmd) { + unsigned bone_mask = aimbot_bone_mask(); + if (!bone_mask) + return false; + QAngle orig{g_cam_view.x, g_cam_view.y, g_cam_view.z}; + QAngle view{orig.x, orig.y, 0.0f}; + int target = -1; + Vector point{}; + float fov = 0.0f; + if (!select_aim_target(view, bone_mask, true, "silentaim", target, point, + fov)) + return false; + QAngle desired = angle_to(g_cam_eye, point); + float np = desired.x; + if (np > 89.0f) np = 89.0f; + if (np < -89.0f) np = -89.0f; + float ny = desired.y; + while (ny > 180.0f) ny -= 360.0f; + while (ny < -180.0f) ny += 360.0f; + + cmd->viewangles[0] = np; + cmd->viewangles[1] = ny; + cmd->viewangles[2] = orig.z; + + // The usercmd keeps the aim angles (shot/prediction); the rendered camera + // is restored to where the player was actually looking. + if (g_iface.engine) { + QAngle restore{orig.x, orig.y, orig.z}; + using SetViewFn = void (*)(void *, QAngle *); + vfunc(g_iface.engine, 20)(g_iface.engine, &restore); + } + cmd->buttons |= IN_ATTACK; + static int logs = 0; + if (logs < 5) { + logs++; + logf("silentaim: fire idx=%d fov=%.2f aim=%.2f/%.2f", target, fov, np, ny); + } + return true; +} + bool triggerbot_apply(CUserCmd *cmd) { if (!g_iface.enginetrace || !g_iface.entitylist) return false; -- cgit v1.2.3