From e9054d01499f5d4440a25ddbee8d353b2b81ff59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ph=E1=BA=A1m=20Minh=20D=C6=B0=C6=A1ng?= <47449032+thisis2838@users.noreply.github.com> Date: Thu, 29 Jan 2026 00:15:15 +0700 Subject: [PATCH 1/3] Implement demo jump jitter fix --- CMakeLists.txt | 1 + spt/features/game_fixes/demo_jump_jitter.cpp | 145 +++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 spt/features/game_fixes/demo_jump_jitter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 648651e5..3d8132ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,6 +110,7 @@ set(SPT_SOURCES spt/features/game_fixes/snapshot_overflow.cpp spt/features/game_fixes/vag_crash.cpp spt/features/game_fixes/visual_fixes.cpp + spt/features/game_fixes/demo_jump_jitter.cpp spt/features/visualizations/draw_ent_collides.cpp spt/features/visualizations/draw_line.cpp spt/features/visualizations/draw_seams.cpp diff --git a/spt/features/game_fixes/demo_jump_jitter.cpp b/spt/features/game_fixes/demo_jump_jitter.cpp new file mode 100644 index 00000000..782e0924 --- /dev/null +++ b/spt/features/game_fixes/demo_jump_jitter.cpp @@ -0,0 +1,145 @@ +#include "stdafx.hpp" +#include "..\generic.hpp" +#include "..\sptlib-wrapper.hpp" +#include "..\cvars.hpp" +#include "signals.hpp" +#include "dbg.h" +#include "interfaces.hpp" +#include +#include "thirdparty/x86.h" + +static void DemoJumpJitterFixCvarCallback(CON_COMMAND_CALLBACK_ARGS); + +ConVar y_spt_demo_jump_jitter_fix("y_spt_demo_jump_jitter_fix", + "0", + 0, + "Disables all extra movement on flashlight.", + DemoJumpJitterFixCvarCallback); + +namespace patterns +{ + PATTERNS( + m_iv_vecViewOffset__TargetString, + "1", + "43 5F 42 61 73 65 50 6C 61 79 65 72 3A 3A 6D 5F 69 76 5F 76 65 63 56 69 65 77 4F 66 66 73 65 74"); + PATTERNS( + Client__StringReferences, + "1", + "68", + "2", + "C7" + ); +} // namespace patterns + + +class DemoJumpJitterFixFeature : public FeatureWrapper +{ +public: + void Toggle(bool enabled); + +protected: + virtual bool ShouldLoadFeature() override; + virtual void LoadFeature() override; + virtual void InitHooks() override; + virtual void UnloadFeature() override; + +private: + uintptr_t ORIG_m_iv_vecViewOffset__TargetString = 0; + std::vector MATCHES_Client__StringReferences; + + DECL_BYTE_REPLACE(InterpTypePush, 1, 0x12); +}; +static DemoJumpJitterFixFeature spt_demojumpjitterfix; + +bool DemoJumpJitterFixFeature::ShouldLoadFeature() +{ + return interfaces::engine_client != nullptr; +} + +void DemoJumpJitterFixFeature::InitHooks() +{ + FIND_PATTERN(client, m_iv_vecViewOffset__TargetString); + FIND_PATTERN_ALL(client, Client__StringReferences); +} + +void DemoJumpJitterFixFeature::LoadFeature() +{ + if (!ORIG_m_iv_vecViewOffset__TargetString || MATCHES_Client__StringReferences.empty()) + return; + + GET_MODULE(client); + + /* + * we're looking the following call: + * AddVar( &m_vecViewOffset, &m_iv_vecViewOffset, LATCH_SIMULATION_VAR ); + * and changing LATCH_SIMULATION_VAR to LATCH_SIMULATION_VAR | INTERPOLATE_LINEAR_ONLY ((1 << 1) | (1 << 4)) + * + * m_iv_vecViewOffset is an IInterpolatedVar which requires a debug name on most versions + * so we'll hinge our search for that call from its string reference. + */ + for (auto match : MATCHES_Client__StringReferences) + { + auto strRefPtr = match.ptr; + uintptr_t refLocation = *(uintptr_t*)(strRefPtr + ((*(uint8_t*)strRefPtr == 0x68) ? 1 : 3)); + if (refLocation != (uintptr_t)ORIG_m_iv_vecViewOffset__TargetString) + continue; + + uint8_t* addr = (uint8_t*)strRefPtr; + for (int lenLeft = 0x200; lenLeft > 0;) + { + int len = x86_len(addr); + addr += len; + lenLeft -= len; + + // outside of function now + if (addr[0] == X86_INT || addr[0] == X86_NOP) + goto end; + + int offset = 1; + bool found = + // search for push 02 (6A 02) + (addr[0] == X86_PUSHI8 && addr[1] == 2) + // search for mov [reg + off],02 (c7 ?? ?? ?? 02 00 00 00) + || (addr[0] == X86_MOVMIW && (offset = 4, (*(uint32_t*)(addr + 4)) == 2)); + if (found) + { + DevMsg("Found C_BasePlayer::m_iv_vecViewOffset AddVar() type argument push at %p\n", addr); + INIT_BYTE_REPLACE(InterpTypePush, (uintptr_t)(addr + offset)); + InitConcommandBase(y_spt_demo_jump_jitter_fix); + return; + } + } + } + +end:; + DevWarning("Couldn't find C_BasePlayer::m_iv_vecViewOffset AddVar() type argument push!\n"); +} + +void DemoJumpJitterFixFeature::Toggle(bool enabled) +{ + if (!PTR_InterpTypePush) + { + Warning("The demo jitter jump fix isn't functional at the moment.\n"); + } + + if (enabled) + { + DO_BYTE_REPLACE(InterpTypePush); + } + else + { + UNDO_BYTE_REPLACE(InterpTypePush); + } + + Msg("Please restart the current map or reload a save or replay the demo for the change to take effect.\n"); +} + +void DemoJumpJitterFixCvarCallback(CON_COMMAND_CALLBACK_ARGS) +{ + spt_demojumpjitterfix.Toggle(((ConVar*)var)->GetBool()); +} + +void DemoJumpJitterFixFeature::UnloadFeature() +{ + DESTROY_BYTE_REPLACE(InterpTypePush); +} From e4122bfe1f5b21354e57102ae1fc10d8cc5c25af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ph=E1=BA=A1m=20Minh=20D=C6=B0=C6=A1ng?= <47449032+thisis2838@users.noreply.github.com> Date: Thu, 29 Jan 2026 01:24:00 +0700 Subject: [PATCH 2/3] Add extra warning --- spt/features/game_fixes/demo_jump_jitter.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spt/features/game_fixes/demo_jump_jitter.cpp b/spt/features/game_fixes/demo_jump_jitter.cpp index 782e0924..eb73aee2 100644 --- a/spt/features/game_fixes/demo_jump_jitter.cpp +++ b/spt/features/game_fixes/demo_jump_jitter.cpp @@ -122,16 +122,17 @@ void DemoJumpJitterFixFeature::Toggle(bool enabled) Warning("The demo jitter jump fix isn't functional at the moment.\n"); } + Msg("Please restart the current map or reload a save or replay the demo for the change to take effect.\n"); + if (enabled) { DO_BYTE_REPLACE(InterpTypePush); + Warning("REMEMBER TO TURN THIS OFF FOR NORMAL GAMEPLAY!\n"); } else { UNDO_BYTE_REPLACE(InterpTypePush); } - - Msg("Please restart the current map or reload a save or replay the demo for the change to take effect.\n"); } void DemoJumpJitterFixCvarCallback(CON_COMMAND_CALLBACK_ARGS) From 6b6ba1090b770a7864e638af3f982e452a092f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ph=E1=BA=A1m=20Minh=20D=C6=B0=C6=A1ng?= <47449032+thisis2838@users.noreply.github.com> Date: Thu, 29 Jan 2026 05:20:35 +0700 Subject: [PATCH 3/3] Remove y_ prefix for cvars --- spt/features/game_fixes/demo_jump_jitter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spt/features/game_fixes/demo_jump_jitter.cpp b/spt/features/game_fixes/demo_jump_jitter.cpp index eb73aee2..309d135e 100644 --- a/spt/features/game_fixes/demo_jump_jitter.cpp +++ b/spt/features/game_fixes/demo_jump_jitter.cpp @@ -10,7 +10,7 @@ static void DemoJumpJitterFixCvarCallback(CON_COMMAND_CALLBACK_ARGS); -ConVar y_spt_demo_jump_jitter_fix("y_spt_demo_jump_jitter_fix", +ConVar spt_demo_jump_jitter_fix("spt_demo_jump_jitter_fix", "0", 0, "Disables all extra movement on flashlight.", @@ -105,7 +105,7 @@ void DemoJumpJitterFixFeature::LoadFeature() { DevMsg("Found C_BasePlayer::m_iv_vecViewOffset AddVar() type argument push at %p\n", addr); INIT_BYTE_REPLACE(InterpTypePush, (uintptr_t)(addr + offset)); - InitConcommandBase(y_spt_demo_jump_jitter_fix); + InitConcommandBase(spt_demo_jump_jitter_fix); return; } }