summaryrefslogtreecommitdiffstats
path: root/src/hl2h.cpp
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-26 17:35:13 +0100
committersalmonik <salmonik@tuta.io>2026-10-26 17:35:13 +0100
commit849d205a3afb553eb49296393fad44671cc03494 (patch)
tree6ae394857d7ba71f8a03e1a9ef7056e9d4557a6c /src/hl2h.cpp
parentSilent aim: exact usercmd angle + fire, restore rendered view (diff)
downloadhl2h-849d205a3afb553eb49296393fad44671cc03494.tar.gz
hl2h-849d205a3afb553eb49296393fad44671cc03494.zip
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
Diffstat (limited to '')
-rw-r--r--src/hl2h.cpp33
1 files changed, 31 insertions, 2 deletions
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) {
278using CreateMoveFn = bool (*)(void *, int, float, bool); 278using CreateMoveFn = bool (*)(void *, int, float, bool);
279static CreateMoveFn oCreateMove = nullptr; 279static CreateMoveFn oCreateMove = nullptr;
280 280
281using FrameStageFn = void (*)(void *, int);
282static FrameStageFn oFrameStageNotify = nullptr;
283static QAngle g_silent_restore_angles{};
284static bool g_silent_restore_pending = false;
285
286void set_silent_restore(const QAngle &angles) {
287 g_silent_restore_angles = angles;
288 g_silent_restore_pending = true;
289}
290
291// FRAME_RENDER_START (ClientFrameStage_t: -1 undefined, 0 START, ...,
292// 4 NET_UPDATE_END, 5 RENDER_START).
293static void hkdFrameStageNotify(void *self, int stage) {
294 if (oFrameStageNotify)
295 oFrameStageNotify(self, stage);
296 if (stage == 5 && g_silent_restore_pending) {
297 g_silent_restore_pending = false;
298 if (g_iface.engine) {
299 QAngle a = g_silent_restore_angles;
300 using SetViewFn = void (*)(void *, QAngle *);
301 vfunc<SetViewFn>(g_iface.engine, 20)(g_iface.engine, &a);
302 }
303 }
304}
305
281using DrawPrintTextFn = void (*)(void *self, const wchar_t *text, int len, int drawType); 306using DrawPrintTextFn = void (*)(void *self, const wchar_t *text, int len, int drawType);
282static DrawPrintTextFn oDrawPrintText = nullptr; 307static DrawPrintTextFn oDrawPrintText = nullptr;
283using PaintTraverseExFn = void (*)(void *, long, bool); 308using PaintTraverseExFn = void (*)(void *, long, bool);
@@ -345,9 +370,13 @@ static void install_hook() {
345 memcpy(newvt, vt, SLOTS * sizeof(void *)); 370 memcpy(newvt, vt, SLOTS * sizeof(void *));
346 oCreateMove = (CreateMoveFn)vt[21]; 371 oCreateMove = (CreateMoveFn)vt[21];
347 newvt[21] = (void *)&hkdCreateMove; 372 newvt[21] = (void *)&hkdCreateMove;
373 oFrameStageNotify = (FrameStageFn)vt[35];
374 newvt[35] = (void *)&hkdFrameStageNotify;
348 VTABLE(g_iface.client) = newvt; 375 VTABLE(g_iface.client) = newvt;
349 logf("hook installed: CreateMove %p -> %p (orig %p)", vt[21], 376 logf("hook installed: CreateMove %p -> %p (orig %p), FrameStageNotify %p "
350 (void *)&hkdCreateMove, (void *)oCreateMove); 377 "-> %p (orig %p)",
378 vt[21], (void *)&hkdCreateMove, (void *)oCreateMove, vt[35],
379 (void *)&hkdFrameStageNotify, (void *)oFrameStageNotify);
351} 380}
352 381
353// --------------------------------------------------------------------------- 382// ---------------------------------------------------------------------------