From f2482195b46b49ad1082d48ff4f612b101cd82ef Mon Sep 17 00:00:00 2001 From: whitehai11 Date: Wed, 5 Aug 2026 17:57:39 +0200 Subject: [PATCH] Add CS2-valid movement features (W release, instant strafe, snap tap, minijump, subtick-perfect crouch jump) --- .../AndromedaClient/Features/CMisc/CMisc.cpp | 135 +++++++++++++++++- .../AndromedaClient/Features/CMisc/CMisc.hpp | 13 ++ .../AndromedaClient/GUI/CAndromedaMenu.cpp | 4 + .../AndromedaClient/Settings/Settings.hpp | 4 + 4 files changed, 155 insertions(+), 1 deletion(-) diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CMisc/CMisc.cpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CMisc/CMisc.cpp index 642f542..c82918e 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CMisc/CMisc.cpp +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CMisc/CMisc.cpp @@ -537,6 +537,9 @@ auto CMisc::RunMovement( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void const bool bOnGround = ( flFlags & FL_ONGROUND ) != 0; + if ( Settings::Misc::SnapTap ) + RunSnapTap( pUserCmd ); + if ( Settings::Misc::SubtickStrafe ) RunSubtickStrafe( pInput , pUserCmd , pLocalPawn , bOnGround ); else if ( Settings::Misc::NullStrafe ) @@ -565,12 +568,30 @@ auto CMisc::RunMovement( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void } } + const bool bJumpHeld = ( pUserCmd->button_states.buttonstate1 & IN_JUMP ) != 0; + const bool bJumpEdge = bJumpHeld && !m_bWasJumping; + if ( Settings::Misc::JumpCrouch ) { - if ( bOnGround && ( pUserCmd->button_states.buttonstate1 & IN_JUMP ) ) + if ( bOnGround && bJumpHeld ) + { pUserCmd->button_states.buttonstate1 |= IN_DUCK; + pUserCmd->cmd.mutable_base()->mutable_buttons_pb()->set_buttonstate1( pUserCmd->button_states.buttonstate1 ); + + GetCL_Bypass()->AddProcessSubTick( IN_DUCK , true , 0.0f ); + GetCL_Bypass()->AddProcessSubTick( IN_JUMP , true , 0.0f ); + } } + if ( Settings::Misc::WRelease ) + RunWRelease( pUserCmd , bOnGround ); + + if ( Settings::Misc::InstantStrafe ) + RunInstantStrafe( pUserCmd , bOnGround , bJumpEdge ); + + if ( Settings::Misc::Minijump ) + RunMinijump( pUserCmd , bOnGround , bJumpEdge ); + if ( Settings::Misc::LongJump ) { if ( !bOnGround ) @@ -636,6 +657,7 @@ auto CMisc::RunMovement( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void pUserCmd->button_states.buttonstate1 |= IN_SPEED; m_bWasOnGround = bOnGround; + m_bWasJumping = ( pUserCmd->button_states.buttonstate1 & IN_JUMP ) != 0; } auto CMisc::RunAutoStrafe( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void @@ -928,6 +950,117 @@ auto CMisc::RotateMoveToYaw( CBaseUserCmdPB* pBaseCmd , const float flTargetYaw pBaseCmd->set_leftmove( std::clamp( -flCorrectedSide , -1.f , 1.f ) ); } +auto CMisc::RunSnapTap( CUserCmd* pUserCmd ) -> void +{ + if ( !pUserCmd ) + return; + + auto& uButtons = pUserCmd->button_states.buttonstate1; + + const bool bLeft = ( uButtons & IN_MOVELEFT ) != 0; + const bool bRight = ( uButtons & IN_MOVERIGHT ) != 0; + const bool bForward = ( uButtons & IN_FORWARD ) != 0; + const bool bBack = ( uButtons & IN_BACK ) != 0; + + // Newest key wins: pressing A while D is held releases D and vice versa. + if ( bLeft && m_bRightHeld && !m_bLeftHeld ) + uButtons &= ~IN_MOVERIGHT; + + if ( bRight && m_bLeftHeld && !m_bRightHeld ) + uButtons &= ~IN_MOVELEFT; + + if ( bForward && m_bBackHeld && !m_bForwardHeld ) + uButtons &= ~IN_BACK; + + if ( bBack && m_bForwardHeld && !m_bBackHeld ) + uButtons &= ~IN_FORWARD; + + pUserCmd->cmd.mutable_base()->mutable_buttons_pb()->set_buttonstate1( uButtons ); + + m_bLeftHeld = ( uButtons & IN_MOVELEFT ) != 0; + m_bRightHeld = ( uButtons & IN_MOVERIGHT ) != 0; + m_bForwardHeld = ( uButtons & IN_FORWARD ) != 0; + m_bBackHeld = ( uButtons & IN_BACK ) != 0; +} + +auto CMisc::RunWRelease( CUserCmd* pUserCmd , bool bOnGround ) -> void +{ + if ( !pUserCmd ) + return; + + constexpr int k_ReleaseTicks = 2; + + if ( bOnGround ) + { + if ( pUserCmd->button_states.buttonstate1 & IN_JUMP ) + m_iWReleaseTicks = k_ReleaseTicks; + else + m_iWReleaseTicks = 0; + + return; + } + + if ( m_iWReleaseTicks > 0 ) + { + auto& uButtons = pUserCmd->button_states.buttonstate1; + + uButtons &= ~IN_FORWARD; + + pUserCmd->cmd.mutable_base()->set_forwardmove( 0.f ); + pUserCmd->cmd.mutable_base()->mutable_buttons_pb()->set_buttonstate1( uButtons ); + + GetCL_Bypass()->AddProcessSubTick( IN_FORWARD , false , 0.01f , 0.f , 0.f ); + + --m_iWReleaseTicks; + } +} + +auto CMisc::RunInstantStrafe( CUserCmd* pUserCmd , bool bOnGround , bool bJumpEdge ) -> void +{ + if ( !pUserCmd ) + return; + + if ( !bOnGround || !bJumpEdge ) + return; + + const auto uButtons = pUserCmd->button_states.buttonstate1; + + if ( uButtons & IN_MOVELEFT ) + GetCL_Bypass()->AddProcessSubTick( IN_MOVELEFT , true , 0.01f ); + + if ( uButtons & IN_MOVERIGHT ) + GetCL_Bypass()->AddProcessSubTick( IN_MOVERIGHT , true , 0.01f ); + + if ( uButtons & IN_FORWARD ) + GetCL_Bypass()->AddProcessSubTick( IN_FORWARD , true , 0.01f ); + + if ( uButtons & IN_BACK ) + GetCL_Bypass()->AddProcessSubTick( IN_BACK , true , 0.01f ); +} + +auto CMisc::RunMinijump( CUserCmd* pUserCmd , bool bOnGround , bool bJumpEdge ) -> void +{ + if ( !pUserCmd ) + return; + + if ( bOnGround && bJumpEdge ) + { + // Crouch-jump for a single tiny hop (minijump) instead of a full jump. + GetCL_Bypass()->AddProcessSubTick( IN_DUCK , true , 0.0f ); + GetCL_Bypass()->AddProcessSubTick( IN_JUMP , true , 0.0f ); + + m_iMinijumpForceRelease = 2; + } + + if ( m_iMinijumpForceRelease > 0 ) + { + if ( !bOnGround ) + GetCL_Bypass()->SetDontJump( pUserCmd , true ); + + --m_iMinijumpForceRelease; + } +} + auto CMisc::RunEdgeBug( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void { if ( bOnGround ) diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CMisc/CMisc.hpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CMisc/CMisc.hpp index 132856a..36cd088 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CMisc/CMisc.hpp +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CMisc/CMisc.hpp @@ -43,6 +43,10 @@ private: auto RunNullStrafe( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void; auto RunSubtickStrafe( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void; auto RunEdgeBug( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void; + auto RunSnapTap( CUserCmd* pUserCmd ) -> void; + auto RunWRelease( CUserCmd* pUserCmd , bool bOnGround ) -> void; + auto RunInstantStrafe( CUserCmd* pUserCmd , bool bOnGround , bool bJumpEdge ) -> void; + auto RunMinijump( CUserCmd* pUserCmd , bool bOnGround , bool bJumpEdge ) -> void; auto RotateMoveToYaw( CBaseUserCmdPB* pBaseCmd , const float flTargetYaw , const float flViewYaw ) -> void; private: @@ -64,6 +68,15 @@ private: bool m_bSideSwitch = false; float m_flLastForwardMove = 0.f; float m_flLastLeftMove = 0.f; + + bool m_bWasJumping = false; + int m_iWReleaseTicks = 0; + int m_iMinijumpForceRelease = 0; + + bool m_bLeftHeld = false; + bool m_bRightHeld = false; + bool m_bForwardHeld = false; + bool m_bBackHeld = false; }; auto GetMisc() -> CMisc*; diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/GUI/CAndromedaMenu.cpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/GUI/CAndromedaMenu.cpp index 31ede1a..45b204e 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/GUI/CAndromedaMenu.cpp +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/GUI/CAndromedaMenu.cpp @@ -336,10 +336,14 @@ auto CAndromedaMenu::RenderMiscPanel() -> void Checkbox( "Auto-Strafe" , Settings::Misc::AutoStrafe ); Checkbox( "Null-Strafe" , Settings::Misc::NullStrafe ); Checkbox( "SubTick-Strafe" , Settings::Misc::SubtickStrafe ); + Checkbox( "W-Release" , Settings::Misc::WRelease ); + Checkbox( "Instant Strafe" , Settings::Misc::InstantStrafe ); + Checkbox( "Snap Tap" , Settings::Misc::SnapTap ); Checkbox( "JumpBug" , Settings::Misc::JumpBug ); Checkbox( "EdgeBug" , Settings::Misc::EdgeBug ); Checkbox( "EdgeJump" , Settings::Misc::EdgeJump ); Checkbox( "JumpCrouch" , Settings::Misc::JumpCrouch ); + Checkbox( "Minijump" , Settings::Misc::Minijump ); Checkbox( "Fast-Stop" , Settings::Misc::FastStop ); Checkbox( "LongJump" , Settings::Misc::LongJump ); Checkbox( "Pixel Surf" , Settings::Misc::PixelSurf ); diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Settings/Settings.hpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Settings/Settings.hpp index c4ca382..f5b85f9 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Settings/Settings.hpp +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Settings/Settings.hpp @@ -48,10 +48,14 @@ namespace Settings inline auto AutoStrafe = false; inline auto NullStrafe = false; inline auto SubtickStrafe = false; + inline auto WRelease = false; + inline auto InstantStrafe = false; + inline auto SnapTap = false; inline auto JumpBug = false; inline auto EdgeBug = false; inline auto EdgeJump = false; inline auto JumpCrouch = false; + inline auto Minijump = false; inline auto FastStop = false; inline auto LongJump = false; inline auto PixelSurf = false;