From 849d205a3afb553eb49296393fad44671cc03494 Mon Sep 17 00:00:00 2001 From: salmonik Date: Mon, 26 Oct 2026 17:35:13 +0100 Subject: Silent aim: restore view at FRAME_RENDER_START; preserve movement - hook CHLClient::FrameStageNotify (vtable slot 35) and at FRAME_RENDER_START re-apply the player's original view angles after the engine has consumed the aimed usercmd; this fixes the slow pull with high-RPM weapons and the revolver leaving the view on the target - silent aim also rewrites forwardmove/sidemove so the world-space movement wish vector is unchanged by the temporary aim angles --- src/hl2h.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'src/hl2h.cpp') diff --git a/src/hl2h.cpp b/src/hl2h.cpp index 89d6b89..0491fd9 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp @@ -278,6 +278,31 @@ static void do_move(int seq) { using CreateMoveFn = bool (*)(void *, int, float, bool); static CreateMoveFn oCreateMove = nullptr; +using FrameStageFn = void (*)(void *, int); +static FrameStageFn oFrameStageNotify = nullptr; +static QAngle g_silent_restore_angles{}; +static bool g_silent_restore_pending = false; + +void set_silent_restore(const QAngle &angles) { + g_silent_restore_angles = angles; + g_silent_restore_pending = true; +} + +// FRAME_RENDER_START (ClientFrameStage_t: -1 undefined, 0 START, ..., +// 4 NET_UPDATE_END, 5 RENDER_START). +static void hkdFrameStageNotify(void *self, int stage) { + if (oFrameStageNotify) + oFrameStageNotify(self, stage); + if (stage == 5 && g_silent_restore_pending) { + g_silent_restore_pending = false; + if (g_iface.engine) { + QAngle a = g_silent_restore_angles; + using SetViewFn = void (*)(void *, QAngle *); + vfunc(g_iface.engine, 20)(g_iface.engine, &a); + } + } +} + using DrawPrintTextFn = void (*)(void *self, const wchar_t *text, int len, int drawType); static DrawPrintTextFn oDrawPrintText = nullptr; using PaintTraverseExFn = void (*)(void *, long, bool); @@ -345,9 +370,13 @@ static void install_hook() { memcpy(newvt, vt, SLOTS * sizeof(void *)); oCreateMove = (CreateMoveFn)vt[21]; newvt[21] = (void *)&hkdCreateMove; + oFrameStageNotify = (FrameStageFn)vt[35]; + newvt[35] = (void *)&hkdFrameStageNotify; VTABLE(g_iface.client) = newvt; - logf("hook installed: CreateMove %p -> %p (orig %p)", vt[21], - (void *)&hkdCreateMove, (void *)oCreateMove); + logf("hook installed: CreateMove %p -> %p (orig %p), FrameStageNotify %p " + "-> %p (orig %p)", + vt[21], (void *)&hkdCreateMove, (void *)oCreateMove, vt[35], + (void *)&hkdFrameStageNotify, (void *)oFrameStageNotify); } // --------------------------------------------------------------------------- -- cgit v1.2.3