Add null strafe and subtick strafe (32-step analog subtick air accel)

This commit is contained in:
2026-08-05 17:40:16 +02:00
parent 1950973d96
commit 2c9d9c2cad
6 changed files with 272 additions and 4 deletions
@@ -507,7 +507,11 @@ auto CMisc::RunMovement( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void
const bool bOnGround = ( flFlags & FL_ONGROUND ) != 0; const bool bOnGround = ( flFlags & FL_ONGROUND ) != 0;
if ( Settings::Misc::AutoStrafe ) if ( Settings::Misc::SubtickStrafe )
RunSubtickStrafe( pInput , pUserCmd , pLocalPawn , bOnGround );
else if ( Settings::Misc::NullStrafe )
RunNullStrafe( pInput , pUserCmd , pLocalPawn , bOnGround );
else if ( Settings::Misc::AutoStrafe )
RunAutoStrafe( pInput , pUserCmd , pLocalPawn , bOnGround ); RunAutoStrafe( pInput , pUserCmd , pLocalPawn , bOnGround );
if ( Settings::Misc::JumpBug ) if ( Settings::Misc::JumpBug )
@@ -642,6 +646,246 @@ auto CMisc::RunAutoStrafe( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerP
GetCL_Bypass()->SetViewAngles( &NewAngles , pInput , pUserCmd ); GetCL_Bypass()->SetViewAngles( &NewAngles , pInput , pUserCmd );
} }
auto CMisc::RunNullStrafe( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void
{
if ( bOnGround )
return;
if ( !pUserCmd || !pLocalPawn )
return;
auto* pBaseCmd = pUserCmd->cmd.mutable_base();
if ( !pBaseCmd )
return;
auto* pViewAngles = CCSGOInput_GetViewAngles( pInput , 0 );
if ( !pViewAngles )
return;
const Vector3 Velocity = pLocalPawn->m_vecVelocity();
const float flSpeed = Velocity.Length2D();
if ( flSpeed <= 10.f )
return;
constexpr float k_Pi = 3.14159265358979f;
const float flVelYaw = std::atan2f( Velocity.m_y , Velocity.m_x );
const float flViewYaw = pViewAngles->m_y * ( k_Pi / 180.f );
const float flRelativeYaw = flVelYaw - flViewYaw;
const float flForward = std::clamp( -std::cosf( flRelativeYaw ) , -1.f , 1.f );
const float flLeft = std::clamp( -std::sinf( flRelativeYaw ) , -1.f , 1.f );
pBaseCmd->set_forwardmove( flForward );
pBaseCmd->set_leftmove( flLeft );
GetCL_Bypass()->AddProcessSubTick( 0 , false , 0.f , pBaseCmd->forwardmove() - m_flLastForwardMove , pBaseCmd->leftmove() - m_flLastLeftMove );
m_flLastForwardMove = pBaseCmd->forwardmove();
m_flLastLeftMove = pBaseCmd->leftmove();
}
auto CMisc::RunSubtickStrafe( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void
{
if ( bOnGround )
return;
if ( !pUserCmd || !pLocalPawn )
return;
auto* pBaseCmd = pUserCmd->cmd.mutable_base();
if ( !pBaseCmd )
return;
auto* pViewAngles = CCSGOInput_GetViewAngles( pInput , 0 );
if ( !pViewAngles )
return;
constexpr float k_Pi = 3.14159265358979f;
constexpr int k_SubtickCount = 32;
constexpr float k_TickInterval = 1.f / 64.f;
constexpr float k_FrameTime = k_TickInterval / static_cast<float>( k_SubtickCount );
constexpr float k_SvAiraccelerate = 12.f;
constexpr float k_SvAirMaxWishspeed = 30.f;
constexpr float k_SvGravity = 800.f;
constexpr float k_MaxSpeed = 250.f;
const auto uButtons = pUserCmd->button_states.buttonstate1;
const bool bLeft = ( uButtons & IN_MOVELEFT ) != 0;
const bool bRight = ( uButtons & IN_MOVERIGHT ) != 0;
float flYawOffset = 0.f;
if ( bLeft )
flYawOffset += 90.f;
if ( bRight )
flYawOffset -= 90.f;
if ( uButtons & IN_FORWARD )
flYawOffset *= 0.5f;
else if ( uButtons & IN_BACK )
flYawOffset = -flYawOffset * 0.5f + 180.f;
const float flCmdForward = pBaseCmd->forwardmove();
const float flCmdLeft = pBaseCmd->leftmove();
Vector3 VelocitySim = pLocalPawn->m_vecVelocity();
float flLastImpulseForward = m_flLastForwardMove;
float flLastImpulseLeft = m_flLastLeftMove;
for ( auto i = 0; i < k_SubtickCount; ++i )
{
pBaseCmd->set_forwardmove( flCmdForward );
pBaseCmd->set_leftmove( flCmdLeft );
float flSpeed = VelocitySim.Length2D();
if ( flSpeed > 0.0001f )
{
const float flYawRad = pViewAngles->m_y * ( k_Pi / 180.f );
const Vector3 vForward( std::cosf( flYawRad ) , std::sinf( flYawRad ) , 0.f );
const Vector3 vRight( -std::sinf( flYawRad ) , std::cosf( flYawRad ) , 0.f );
Vector3 vWishDir
{
( vForward.m_x * flCmdForward * k_MaxSpeed ) + ( vRight.m_x * flCmdLeft * k_MaxSpeed ),
( vForward.m_y * flCmdForward * k_MaxSpeed ) + ( vRight.m_y * flCmdLeft * k_MaxSpeed ),
0.f
};
float flWishSpeed = vWishDir.Length2D();
if ( flWishSpeed > 0.0001f )
{
vWishDir.m_x /= flWishSpeed;
vWishDir.m_y /= flWishSpeed;
}
flWishSpeed = std::fminf( flWishSpeed , k_MaxSpeed );
const float flCappedWish = std::fminf( flWishSpeed , k_SvAirMaxWishspeed );
const float flCurrentSpeed = ( VelocitySim.m_x * vWishDir.m_x ) + ( VelocitySim.m_y * vWishDir.m_y );
const float flAddSpeed = flCappedWish - flCurrentSpeed;
if ( flAddSpeed > 0.f )
{
const float flAccelSpeed = k_SvAiraccelerate * k_MaxSpeed * k_FrameTime;
const float flGain = std::fminf( flAccelSpeed * 0.5f , flAddSpeed );
VelocitySim.m_x += vWishDir.m_x * flGain;
VelocitySim.m_y += vWishDir.m_y * flGain;
}
}
VelocitySim.m_z -= k_SvGravity * k_FrameTime;
flSpeed = VelocitySim.Length2D();
if ( flSpeed >= 10.f )
{
pBaseCmd->set_forwardmove( 0.f );
pBaseCmd->set_leftmove( 0.f );
const float flVelocityAngle = std::atan2f( VelocitySim.m_y , VelocitySim.m_x ) * ( 180.f / k_Pi );
const float flAccelSpeed = k_SvAiraccelerate * k_MaxSpeed * k_FrameTime;
const float flOptimalFloor = std::fmaxf( flAccelSpeed * 0.5f , k_SvAirMaxWishspeed - flAccelSpeed * 0.5f );
const float flIdealAngle = std::clamp( std::atanf( flOptimalFloor / flSpeed ) * ( 180.f / k_Pi ) , 0.f , 45.f );
float flTargetYaw = pViewAngles->m_y + flYawOffset;
while ( flTargetYaw > 180.f )
flTargetYaw -= 360.f;
while ( flTargetYaw < -180.f )
flTargetYaw += 360.f;
float flVelocityDelta = flTargetYaw - flVelocityAngle;
while ( flVelocityDelta > 180.f )
flVelocityDelta -= 360.f;
while ( flVelocityDelta < -180.f )
flVelocityDelta += 360.f;
if ( ( std::fabsf( flVelocityDelta ) > 170.f && flSpeed > 80.f ) || ( flVelocityDelta > flIdealAngle && flSpeed > 80.f ) )
{
flTargetYaw = flVelocityAngle + flIdealAngle;
pBaseCmd->set_leftmove( -1.f );
}
else if ( -flIdealAngle <= flVelocityDelta || flSpeed <= 80.f )
{
if ( m_bSideSwitch )
{
flTargetYaw = flTargetYaw - flIdealAngle;
pBaseCmd->set_leftmove( -1.f );
}
else
{
flTargetYaw = flTargetYaw + flIdealAngle;
pBaseCmd->set_leftmove( 1.f );
}
}
else
{
flTargetYaw = flVelocityAngle - flIdealAngle;
pBaseCmd->set_leftmove( 1.f );
}
while ( flTargetYaw > 180.f )
flTargetYaw -= 360.f;
while ( flTargetYaw < -180.f )
flTargetYaw += 360.f;
RotateMoveToYaw( pBaseCmd , flTargetYaw , pViewAngles->m_y );
}
GetCL_Bypass()->AddProcessSubTick( 0 , false , static_cast<float>( i ) / static_cast<float>( k_SubtickCount ) , pBaseCmd->forwardmove() - flLastImpulseForward , pBaseCmd->leftmove() - flLastImpulseLeft );
flLastImpulseForward = pBaseCmd->forwardmove();
flLastImpulseLeft = pBaseCmd->leftmove();
m_bSideSwitch = !m_bSideSwitch;
}
m_flLastForwardMove = flLastImpulseForward;
m_flLastLeftMove = flLastImpulseLeft;
}
auto CMisc::RotateMoveToYaw( CBaseUserCmdPB* pBaseCmd , const float flTargetYaw , const float flViewYaw ) -> void
{
const float k_Pi = 3.14159265358979f;
const float flTargetRad = flTargetYaw * ( k_Pi / 180.f );
const float flViewRad = flViewYaw * ( k_Pi / 180.f );
const float flForwardMove = pBaseCmd->forwardmove();
const float flSideMove = pBaseCmd->leftmove();
const Vector3 vTargetForward( std::cosf( flTargetRad ) , std::sinf( flTargetRad ) , 0.f );
const Vector3 vTargetRight( -std::sinf( flTargetRad ) , std::cosf( flTargetRad ) , 0.f );
const Vector3 vViewForward( std::cosf( flViewRad ) , std::sinf( flViewRad ) , 0.f );
const Vector3 vViewRight( -std::sinf( flViewRad ) , std::cosf( flViewRad ) , 0.f );
const Vector3 vMove = vTargetForward * flForwardMove + vTargetRight * flSideMove;
const float flCorrectedForward = ( vViewForward.m_x * vMove.m_x ) + ( vViewForward.m_y * vMove.m_y );
const float flCorrectedSide = ( vViewRight.m_x * vMove.m_x ) + ( vViewRight.m_y * vMove.m_y );
pBaseCmd->set_forwardmove( std::clamp( -flCorrectedForward , -1.f , 1.f ) );
pBaseCmd->set_leftmove( std::clamp( -flCorrectedSide , -1.f , 1.f ) );
}
auto CMisc::RunTriggerbot( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void auto CMisc::RunTriggerbot( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void
{ {
auto Reset = [ & ]() auto Reset = [ & ]()
@@ -12,6 +12,7 @@ class CCSGOInput;
class CUserCmd; class CUserCmd;
class IGameEvent; class IGameEvent;
class C_CSPlayerPawn; class C_CSPlayerPawn;
class CBaseUserCmdPB;
class IMisc class IMisc
{ {
@@ -39,6 +40,9 @@ private:
auto RunMovement( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void; auto RunMovement( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void;
auto RunAutoStrafe( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void; auto RunAutoStrafe( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void;
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 RotateMoveToYaw( CBaseUserCmdPB* pBaseCmd , const float flTargetYaw , const float flViewYaw ) -> void;
private: private:
std::chrono::steady_clock::time_point m_HitTime{}; std::chrono::steady_clock::time_point m_HitTime{};
@@ -55,6 +59,10 @@ private:
std::atomic_bool m_bTriggerFiring = false; std::atomic_bool m_bTriggerFiring = false;
bool m_bWasOnGround = false; bool m_bWasOnGround = false;
bool m_bSideSwitch = false;
float m_flLastForwardMove = 0.f;
float m_flLastLeftMove = 0.f;
}; };
auto GetMisc() -> CMisc*; auto GetMisc() -> CMisc*;
@@ -333,6 +333,8 @@ auto CAndromedaMenu::RenderMiscPanel() -> void
Checkbox( "Bunnyhop" , Settings::Misc::Bunnyhop ); Checkbox( "Bunnyhop" , Settings::Misc::Bunnyhop );
Checkbox( "Auto-Strafe" , Settings::Misc::AutoStrafe ); Checkbox( "Auto-Strafe" , Settings::Misc::AutoStrafe );
Checkbox( "Null-Strafe" , Settings::Misc::NullStrafe );
Checkbox( "SubTick-Strafe" , Settings::Misc::SubtickStrafe );
Checkbox( "JumpBug" , Settings::Misc::JumpBug ); Checkbox( "JumpBug" , Settings::Misc::JumpBug );
Checkbox( "EdgeJump" , Settings::Misc::EdgeJump ); Checkbox( "EdgeJump" , Settings::Misc::EdgeJump );
Checkbox( "Fast-Stop" , Settings::Misc::FastStop ); Checkbox( "Fast-Stop" , Settings::Misc::FastStop );
@@ -45,6 +45,8 @@ namespace Settings
{ {
inline auto Bunnyhop = false; inline auto Bunnyhop = false;
inline auto AutoStrafe = false; inline auto AutoStrafe = false;
inline auto NullStrafe = false;
inline auto SubtickStrafe = false;
inline auto JumpBug = false; inline auto JumpBug = false;
inline auto EdgeJump = false; inline auto EdgeJump = false;
inline auto FastStop = false; inline auto FastStop = false;
@@ -21,7 +21,7 @@ auto CL_Bypass::PreClientCreateMove( CUserCmd* pUserCmd ) -> void
auto CL_Bypass::PostClientCreateMove( CCSGOInput* pCCSGOInput , CUserCmd* pUserCmd ) -> void auto CL_Bypass::PostClientCreateMove( CCSGOInput* pCCSGOInput , CUserCmd* pUserCmd ) -> void
{ {
for ( auto& SubTick : m_InternalSubTickList ) for ( auto& SubTick : m_InternalSubTickList )
AddSubtickMoveStep( pUserCmd , SubTick.m_Button , SubTick.m_Pressed , SubTick.m_flWhen ); AddSubtickMoveStep( pUserCmd , SubTick.m_Button , SubTick.m_Pressed , SubTick.m_flWhen , SubTick.m_flForwardDelta , SubTick.m_flLeftDelta );
int EncodeLen = 0; int EncodeLen = 0;
@@ -155,6 +155,11 @@ auto CL_Bypass::AddProcessSubTick( const uint64_t Button , const bool Pressed ,
m_InternalSubTickList.emplace_back( Button , Pressed , When ); m_InternalSubTickList.emplace_back( Button , Pressed , When );
} }
auto CL_Bypass::AddProcessSubTick( const uint64_t Button , const bool Pressed , const float When , const float ForwardDelta , const float LeftDelta ) -> void
{
m_InternalSubTickList.emplace_back( Button , Pressed , When , ForwardDelta , LeftDelta );
}
auto CL_Bypass::OnCBaseUserCmdPB( CBaseUserCmdPB* pBaseUserCmdPB ) -> void auto CL_Bypass::OnCBaseUserCmdPB( CBaseUserCmdPB* pBaseUserCmdPB ) -> void
{ {
m_Backup = *pBaseUserCmdPB; m_Backup = *pBaseUserCmdPB;
@@ -165,7 +170,7 @@ auto CL_Bypass::CalculateWhenValue() -> float
return 0.99f; return 0.99f;
} }
auto CL_Bypass::AddSubtickMoveStep( CUserCmd* pUserCmd , const uint64_t button , const bool pressed , const float when ) -> void auto CL_Bypass::AddSubtickMoveStep( CUserCmd* pUserCmd , const uint64_t button , const bool pressed , const float when , const float forward_delta , const float left_delta ) -> void
{ {
auto pRepeatedMoveSteps = reinterpret_cast<google::protobuf::RepeatedPtrField_t<CSubtickMoveStep>*>( (PBYTE)pUserCmd->cmd.mutable_base() + 0x18 ); auto pRepeatedMoveSteps = reinterpret_cast<google::protobuf::RepeatedPtrField_t<CSubtickMoveStep>*>( (PBYTE)pUserCmd->cmd.mutable_base() + 0x18 );
@@ -180,6 +185,8 @@ auto CL_Bypass::AddSubtickMoveStep( CUserCmd* pUserCmd , const uint64_t button ,
pSubtickMoveStep->set_button( button ); pSubtickMoveStep->set_button( button );
pSubtickMoveStep->set_pressed( pressed ); pSubtickMoveStep->set_pressed( pressed );
pSubtickMoveStep->set_when( when ); pSubtickMoveStep->set_when( when );
pSubtickMoveStep->set_analog_forward_delta( forward_delta );
pSubtickMoveStep->set_analog_left_delta( left_delta );
} }
} }
else else
@@ -189,6 +196,8 @@ auto CL_Bypass::AddSubtickMoveStep( CUserCmd* pUserCmd , const uint64_t button ,
pSubtickMoveStep->set_button( button ); pSubtickMoveStep->set_button( button );
pSubtickMoveStep->set_pressed( pressed ); pSubtickMoveStep->set_pressed( pressed );
pSubtickMoveStep->set_when( when ); pSubtickMoveStep->set_when( when );
pSubtickMoveStep->set_analog_forward_delta( forward_delta );
pSubtickMoveStep->set_analog_left_delta( left_delta );
ProtobufAddToRepeatedPtrElement( pRepeatedMoveSteps , pSubtickMoveStep ); ProtobufAddToRepeatedPtrElement( pRepeatedMoveSteps , pSubtickMoveStep );
} }
@@ -27,13 +27,14 @@ public:
public: public:
auto AddProcessSubTick( const uint64_t Button , const bool Pressed ) -> void; auto AddProcessSubTick( const uint64_t Button , const bool Pressed ) -> void;
auto AddProcessSubTick( const uint64_t Button , const bool Pressed , const float When ) -> void; auto AddProcessSubTick( const uint64_t Button , const bool Pressed , const float When ) -> void;
auto AddProcessSubTick( const uint64_t Button , const bool Pressed , const float When , const float ForwardDelta , const float LeftDelta ) -> void;
public: public:
auto OnCBaseUserCmdPB( CBaseUserCmdPB* pBaseUserCmdPB ) -> void; auto OnCBaseUserCmdPB( CBaseUserCmdPB* pBaseUserCmdPB ) -> void;
private: private:
auto CalculateWhenValue() -> float; auto CalculateWhenValue() -> float;
auto AddSubtickMoveStep( CUserCmd* pUserCmd , const uint64_t button , const bool pressed , const float when ) -> void; auto AddSubtickMoveStep( CUserCmd* pUserCmd , const uint64_t button , const bool pressed , const float when , const float forward_delta = 0.f , const float left_delta = 0.f ) -> void;
auto SpoofCrc() -> std::string; auto SpoofCrc() -> std::string;
private: private:
@@ -45,6 +46,8 @@ private:
uint64_t m_Button = 0; uint64_t m_Button = 0;
bool m_Pressed = false; bool m_Pressed = false;
float m_flWhen = 0.f; float m_flWhen = 0.f;
float m_flForwardDelta = 0.f;
float m_flLeftDelta = 0.f;
}; };
private: private: