#include "CMisc.hpp" #include #include #include #include #include #include #pragma comment( lib , "winmm.lib" ) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { // Deterministic Valve RNG (matches the game's math::random_seed generator). class CValveRng { public: auto Seed( int s ) -> void { m_State = -std::abs( s ); m_Index = 0; m_bSeeded = false; } auto Generate() -> int { if ( !m_bSeeded ) { auto v = -m_State; if ( v < 1 ) v = 1; for ( int j = 39; j >= 0; --j ) { v = LCG( v ); if ( j < 32 ) m_Table[ j ] = v; } m_State = v; m_Index = m_Table[ 0 ]; m_bSeeded = true; } m_State = LCG( m_State ); const auto Index = m_Index / 0x4000000; m_Index = m_Table[ Index ]; m_Table[ Index ] = m_State; return m_Index; } auto RandomFloat( float Min = 0.f , float Max = 1.f ) -> float { const auto Raw = Generate(); const auto Norm = std::fminf( 0.99999988f , static_cast( Raw ) * 4.6566129e-10f ); return Min + Norm * ( Max - Min ); } private: static auto LCG( int State ) -> int { const auto k = State / 127773; auto Result = 16807 * ( State - k * 127773 ) - 2836 * k; if ( Result < 0 ) Result += 2147483647; return Result; } int m_State = 0; int m_Index = 0; int m_Table[ 32 ]{}; bool m_bSeeded = false; }; // Minimal SHA-1 (for computing the spread seed from angles + tick). class CSha1 { public: auto Reset() -> void { m_State[ 0 ] = 0x67452301; m_State[ 1 ] = 0xEFCDAB89; m_State[ 2 ] = 0x98BADCFE; m_State[ 3 ] = 0x10325476; m_State[ 4 ] = 0xC3D2E1F0; m_Count = 0; } auto Update( const void* pData , std::size_t Len ) -> void { const auto* pBytes = static_cast( pData ); auto Index = static_cast( m_Count & 63 ); m_Count += Len; std::size_t i = 0; if ( Index ) { auto PartLen = 64 - Index; if ( Len >= PartLen ) { std::memcpy( m_Buffer + Index , pBytes , PartLen ); Transform( m_Buffer ); i = PartLen; } else { std::memcpy( m_Buffer + Index , pBytes , Len ); return; } } for ( ; i + 64 <= Len; i += 64 ) Transform( pBytes + i ); if ( i < Len ) std::memcpy( m_Buffer , pBytes + i , Len - i ); } auto Final() -> void { uint8_t Padding[ 64 ]{}; Padding[ 0 ] = 0x80; const auto Index = static_cast( m_Count & 63 ); const auto PadLen = ( Index < 56 ) ? ( 56 - Index ) : ( 120 - Index ); const auto BitCount = m_Count * 8; Update( Padding , PadLen ); uint8_t Bits[ 8 ]{}; for ( int i = 0; i < 8; ++i ) Bits[ 7 - i ] = static_cast( BitCount >> ( i * 8 ) ); Update( Bits , 8 ); for ( int i = 0; i < 5; ++i ) { m_Digest[ i * 4 + 0 ] = static_cast( m_State[ i ] >> 24 ); m_Digest[ i * 4 + 1 ] = static_cast( m_State[ i ] >> 16 ); m_Digest[ i * 4 + 2 ] = static_cast( m_State[ i ] >> 8 ); m_Digest[ i * 4 + 3 ] = static_cast( m_State[ i ] ); } } auto GetFirstUInt32() const -> uint32_t { uint32_t Result; std::memcpy( &Result , m_Digest , sizeof Result ); return Result; } private: static auto RotL( uint32_t v , int n ) -> uint32_t { return ( v << n ) | ( v >> ( 32 - n ) ); } auto Transform( const uint8_t* pBlock ) -> void { uint32_t w[ 80 ]{}; for ( int i = 0; i < 16; ++i ) w[ i ] = static_cast( pBlock[ i * 4 ] ) << 24 | static_cast( pBlock[ i * 4 + 1 ] ) << 16 | static_cast( pBlock[ i * 4 + 2 ] ) << 8 | static_cast( pBlock[ i * 4 + 3 ] ); for ( int i = 16; i < 80; ++i ) w[ i ] = RotL( w[ i - 3 ] ^ w[ i - 8 ] ^ w[ i - 14 ] ^ w[ i - 16 ] , 1 ); auto a = m_State[ 0 ]; auto b = m_State[ 1 ]; auto c = m_State[ 2 ]; auto d = m_State[ 3 ]; auto e = m_State[ 4 ]; for ( int i = 0; i < 80; ++i ) { uint32_t f , k; if ( i < 20 ) { f = ( b & c ) | ( ( ~b ) & d ); k = 0x5A827999; } else if ( i < 40 ) { f = b ^ c ^ d; k = 0x6ED9EBA1; } else if ( i < 60 ) { f = ( b & c ) | ( b & d ) | ( c & d ); k = 0x8F1BBCDC; } else { f = b ^ c ^ d; k = 0xCA62C1D6; } const auto Temp = RotL( a , 5 ) + f + e + k + w[ i ]; e = d; d = c; c = RotL( b , 30 ); b = a; a = Temp; } m_State[ 0 ] += a; m_State[ 1 ] += b; m_State[ 2 ] += c; m_State[ 3 ] += d; m_State[ 4 ] += e; } uint32_t m_State[ 5 ]{}; std::uint64_t m_Count = 0; uint8_t m_Buffer[ 64 ]{}; uint8_t m_Digest[ 20 ]{}; }; auto NormalizeAngle( float Angle ) -> float { return Angle - std::floorf( Angle * 0.0027777778f + 0.5f ) * 360.0f; } auto QuantizeAngle( float Angle ) -> float { return std::floorf( NormalizeAngle( Angle ) * 2.0f ) * 0.5f; } auto GetSpreadSeed( const QAngle& ViewAngles , int Tick ) -> uint32_t { struct { float Pitch; float Yaw; int PlayerRenderTick; } Buffer{}; Buffer.Pitch = QuantizeAngle( ViewAngles.m_x ); Buffer.Yaw = QuantizeAngle( ViewAngles.m_y ); Buffer.PlayerRenderTick = Tick; CSha1 Hash; Hash.Reset(); Hash.Update( &Buffer , 12 ); Hash.Final(); return Hash.GetFirstUInt32(); } struct SeedSpread2_t { float x = 0.f; float y = 0.f; }; auto CalculateSeedSpread( int Seed , float Inaccuracy , float Spread , int ItemDefIdx ) -> SeedSpread2_t { constexpr auto k_RevolverId = 64; constexpr auto k_NegevId = 28; constexpr auto k_TwoPi = 6.2831853f; CValveRng Rng; Rng.Seed( Seed ); auto InacR = Rng.RandomFloat( 0.f , 1.f ); const auto InacA = Rng.RandomFloat( 0.f , k_TwoPi ); if ( ItemDefIdx == k_RevolverId ) InacR = 1.f - ( InacR * InacR ); else if ( ItemDefIdx == k_NegevId ) InacR = 1.f - ( InacR * InacR ); InacR *= Inaccuracy; auto SprR = Rng.RandomFloat( 0.f , 1.f ); const auto SprA = Rng.RandomFloat( 0.f , k_TwoPi ); if ( ItemDefIdx == k_RevolverId ) SprR = 1.f - ( SprR * SprR ); else if ( ItemDefIdx == k_NegevId ) SprR = 1.f - ( SprR * SprR ); SprR *= Spread; return { std::cosf( SprA ) * SprR + std::cosf( InacA ) * InacR, std::sinf( SprA ) * SprR + std::sinf( InacA ) * InacR }; } } static CMisc g_CMisc{}; auto CMisc::OnRender() -> void { if ( !Settings::Misc::Watermark && !Settings::Misc::Speedometer ) return; auto& pFont = GetFontManager()->m_VerdanaFont; float Y = 8.f; if ( Settings::Misc::Speedometer ) { auto* pLocalPawn = GetCL_Players()->GetLocalPlayerPawn(); if ( pLocalPawn && pLocalPawn->IsAlive() ) { const float flSpeed = pLocalPawn->m_vecVelocity().Length2D() * 0.05f; char szBuffer[ 64 ]; std::snprintf( szBuffer , sizeof szBuffer , XorStr( "%.0f u/s" ) , flSpeed ); pFont.DrawString( 8 , Y , ImColor( 255 , 255 , 255 ) , FW1_LEFT , "%s" , szBuffer ); } Y += pFont.GetFontSize(); } if ( !Settings::Misc::Watermark ) return; const auto t = std::time( nullptr ); std::tm tm{}; localtime_s( &tm , &t ); char szBuffer[ 128 ]; std::snprintf( szBuffer , sizeof szBuffer , XorStr( "Evicted | FPS: %.0f | %02d:%02d:%02d" ) , ImGui::GetIO().Framerate , tm.tm_hour , tm.tm_min , tm.tm_sec ); pFont.DrawString( 8 , Y , ImColor( 255 , 255 , 0 ) , FW1_LEFT , "%s" , szBuffer ); } auto CMisc::OnClientOutput() -> void { if ( !SDK::Interfaces::EngineToClient()->IsInGame() ) return; if ( Settings::Misc::SpectatorList ) { auto* pLocalController = GetCL_Players()->GetLocalPlayerController(); auto* pFont = &GetFontManager()->m_VerdanaFont; if ( pLocalController && pFont ) { const CHandle LocalPawnHandle = pLocalController->m_hPawn(); const auto DisplaySize = ImGui::GetIO().DisplaySize; const float ListX = DisplaySize.x - 8.f; float ListY = pFont->GetFontSize() + 12.f; const auto& CachedVec = GetEntityCache()->GetCachedEntity(); std::scoped_lock Lock( GetEntityCache()->GetLock() ); for ( const auto& CachedEntity : *CachedVec ) { if ( CachedEntity.m_Type != CachedEntity_t::PLAYER_CONTROLLER ) continue; auto* pEntity = CachedEntity.m_Handle.Get(); if ( !pEntity ) continue; auto* pController = reinterpret_cast( pEntity ); if ( pController == pLocalController ) continue; auto* pPawn = pController->m_hPawn().Get(); if ( !pPawn || !pPawn->IsPlayerPawn() ) continue; auto* pObserverServices = pPawn->m_pObserverServices(); if ( !pObserverServices ) continue; const auto ObserverMode = pObserverServices->m_iObserverMode(); if ( ObserverMode != OBS_MODE_IN_EYE && ObserverMode != OBS_MODE_CHASE ) continue; if ( pObserverServices->m_hObserverTarget() != LocalPawnHandle ) continue; const char* szName = pController->m_sSanitizedPlayerName(); if ( !szName || !szName[ 0 ] ) continue; GetRenderStackSystem()->DrawString( pFont , ImVec2( ListX , ListY ) , FW1_RIGHT | FW1_TOP , ImColor( 255 , 255 , 255 ) , "%s" , szName ); ListY += pFont->GetFontSize() + 2.f; } } } if ( Settings::Triggerbot::Active && Settings::Triggerbot::DrawIndicator ) { if ( m_bTargetInCrosshair ) { const auto DisplaySize = ImGui::GetIO().DisplaySize; const ImVec2 Center( DisplaySize.x * 0.5f , DisplaySize.y * 0.5f ); const ImColor IndicatorColor = m_bTriggerFiring ? ImColor( 0 , 255 , 0 ) : ImColor( 255 , 200 , 0 ); GetRenderStackSystem()->DrawCircleFilled( Center , 3.f , IndicatorColor ); } } if ( Settings::Misc::Hitmarker ) { if ( m_HitTime.time_since_epoch().count() > 0 ) { const auto Elapsed = std::chrono::duration( std::chrono::steady_clock::now() - m_HitTime ).count(); if ( Elapsed <= 0.25f ) { const auto DisplaySize = ImGui::GetIO().DisplaySize; const ImVec2 Center( DisplaySize.x * 0.5f , DisplaySize.y * 0.5f ); const float Size = 6.f; GetRenderStackSystem()->DrawLine( ImVec2( Center.x - Size , Center.y - Size ) , ImVec2( Center.x - 2.f , Center.y - 2.f ) , ImColor( 255 , 255 , 255 ) , 1.5f ); GetRenderStackSystem()->DrawLine( ImVec2( Center.x + Size , Center.y - Size ) , ImVec2( Center.x + 2.f , Center.y - 2.f ) , ImColor( 255 , 255 , 255 ) , 1.5f ); GetRenderStackSystem()->DrawLine( ImVec2( Center.x - Size , Center.y + Size ) , ImVec2( Center.x - 2.f , Center.y + 2.f ) , ImColor( 255 , 255 , 255 ) , 1.5f ); GetRenderStackSystem()->DrawLine( ImVec2( Center.x + Size , Center.y + Size ) , ImVec2( Center.x + 2.f , Center.y + 2.f ) , ImColor( 255 , 255 , 255 ) , 1.5f ); } } } } auto CMisc::OnCreateMove( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void { if ( !pUserCmd ) return; if ( Settings::Triggerbot::Active ) RunTriggerbot( pInput , pUserCmd ); if ( Settings::Misc::Bunnyhop ) { auto* pLocalPawn = GetCL_Players()->GetLocalPlayerPawn(); if ( pLocalPawn && pLocalPawn->IsAlive() ) { constexpr auto FL_ONGROUND = 1u; const bool bOnGround = ( pLocalPawn->m_fFlags() & FL_ONGROUND ) != 0; const bool bHoldingJump = ( pUserCmd->button_states.buttonstate1 & IN_JUMP ) != 0; if ( bHoldingJump ) { if ( bOnGround ) { if ( Settings::Misc::PerfectBhop ) GetCL_Bypass()->SetJump( pUserCmd , true ); else pUserCmd->button_states.buttonstate1 |= IN_JUMP; } else { pUserCmd->button_states.buttonstate1 &= ~IN_JUMP; } } } } RunMovement( pInput , pUserCmd ); if ( Settings::Misc::FOVChanger ) { auto* pLocalPawn = GetCL_Players()->GetLocalPlayerPawn(); if ( pLocalPawn ) { if ( auto* pCameraServices = pLocalPawn->m_pCameraServices(); pCameraServices ) pCameraServices->m_iFOV() = static_cast( Settings::Misc::FOV ); } } } auto CMisc::RunMovement( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void { auto* pLocalPawn = GetCL_Players()->GetLocalPlayerPawn(); if ( !pLocalPawn || !pLocalPawn->IsAlive() ) { m_bWasOnGround = false; return; } const auto flFlags = pLocalPawn->m_fFlags(); constexpr uint32 FL_ONGROUND = 1u; const bool bOnGround = ( flFlags & FL_ONGROUND ) != 0; 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 ); if ( Settings::Misc::JumpBug ) { if ( !bOnGround && pLocalPawn->m_flFallVelocity() > 430.f ) { pUserCmd->button_states.buttonstate1 &= ~IN_DUCK; GetCL_Bypass()->SetJump( pUserCmd , true ); } } if ( Settings::Misc::EdgeBug ) RunEdgeBug( pInput , pUserCmd , pLocalPawn , bOnGround ); if ( Settings::Misc::EdgeJump ) { if ( m_bWasOnGround && !bOnGround ) { if ( pUserCmd->button_states.buttonstate1 & ( IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT ) ) GetCL_Bypass()->SetJump( pUserCmd , true ); } } if ( Settings::Misc::JumpCrouch ) { if ( bOnGround && ( pUserCmd->button_states.buttonstate1 & IN_JUMP ) ) pUserCmd->button_states.buttonstate1 |= IN_DUCK; } if ( Settings::Misc::LongJump ) { if ( !bOnGround ) pUserCmd->button_states.buttonstate1 |= IN_DUCK; } if ( Settings::Misc::PixelSurf ) { if ( !bOnGround ) { pUserCmd->button_states.buttonstate1 |= IN_DUCK; } else { if ( pUserCmd->button_states.buttonstate1 & ( IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT ) ) GetCL_Bypass()->SetJump( pUserCmd , true ); } } if ( Settings::Misc::FastStop ) { if ( bOnGround ) { if ( !( pUserCmd->button_states.buttonstate1 & ( IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT ) ) ) { const Vector3 Velocity = pLocalPawn->m_vecVelocity(); const float flSpeed = Velocity.Length2D(); if ( flSpeed > 5.f ) { constexpr float k_Pi = 3.14159265358979f; const float flVelYaw = std::atan2f( Velocity.m_y , Velocity.m_x ) * ( 180.f / k_Pi ); auto* pViewAngles = CCSGOInput_GetViewAngles( pInput , 0 ); if ( pViewAngles ) { float flDelta = flVelYaw - pViewAngles->m_y; while ( flDelta > 180.f ) flDelta -= 360.f; while ( flDelta < -180.f ) flDelta += 360.f; if ( flDelta > -45.f && flDelta <= 45.f ) pUserCmd->button_states.buttonstate1 |= IN_BACK; else if ( flDelta > 45.f && flDelta <= 135.f ) pUserCmd->button_states.buttonstate1 |= IN_MOVELEFT; else if ( flDelta > 135.f || flDelta <= -135.f ) pUserCmd->button_states.buttonstate1 |= IN_FORWARD; else pUserCmd->button_states.buttonstate1 |= IN_MOVERIGHT; } } } } } if ( Settings::Misc::SlowWalk ) pUserCmd->button_states.buttonstate1 |= IN_SPEED; m_bWasOnGround = bOnGround; } auto CMisc::RunAutoStrafe( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void { if ( bOnGround ) return; if ( pUserCmd->button_states.buttonstate1 & ( IN_FORWARD | IN_BACK ) ) return; const Vector3 Velocity = pLocalPawn->m_vecVelocity(); const float flSpeed = Velocity.Length2D(); if ( flSpeed < 0.1f ) return; constexpr float k_Pi = 3.14159265358979f; const float flVelYaw = std::atan2f( Velocity.m_y , Velocity.m_x ) * ( 180.f / k_Pi ); auto* pViewAngles = CCSGOInput_GetViewAngles( pInput , 0 ); if ( !pViewAngles ) return; float flDelta = flVelYaw - pViewAngles->m_y; while ( flDelta > 180.f ) flDelta -= 360.f; while ( flDelta < -180.f ) flDelta += 360.f; constexpr float k_TurnSpeed = 5.f; QAngle NewAngles = *pViewAngles; if ( flDelta > 0.f ) { NewAngles.m_y += k_TurnSpeed; pUserCmd->button_states.buttonstate1 |= IN_MOVERIGHT; } else { NewAngles.m_y -= k_TurnSpeed; pUserCmd->button_states.buttonstate1 |= IN_MOVELEFT; } 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( 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( i ) / static_cast( 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::RunEdgeBug( CCSGOInput* pInput , CUserCmd* pUserCmd , C_CSPlayerPawn* pLocalPawn , bool bOnGround ) -> void { if ( bOnGround ) return; if ( !pUserCmd || !pLocalPawn ) return; const Vector3 Velocity = pLocalPawn->m_vecVelocity(); if ( Velocity.m_z >= 0.f ) return; constexpr float k_Pi = 3.14159265358979f; constexpr float k_TickInterval = 1.f / 64.f; constexpr float k_HalfWidth = 16.f; constexpr float k_ProbeDist = 32.f; const Vector3 vOrigin = pLocalPawn->m_vOldOrigin(); const Vector3 vNextPos { vOrigin.m_x + Velocity.m_x * k_TickInterval, vOrigin.m_y + Velocity.m_y * k_TickInterval, vOrigin.m_z + Velocity.m_z * k_TickInterval }; const float flVelocityYaw = std::atan2f( Velocity.m_y , Velocity.m_x ) * ( 180.f / k_Pi ); const Vector3 vOffsets[] { Vector3( 0.f , 0.f , 0.f ), Vector3( k_HalfWidth , k_HalfWidth , 0.f ), Vector3( k_HalfWidth , -k_HalfWidth , 0.f ), Vector3( -k_HalfWidth , k_HalfWidth , 0.f ), Vector3( -k_HalfWidth , -k_HalfWidth , 0.f ) }; Ray_t Ray; CGameTrace GameTrace; CTraceFilter Filter( 0x1C1003 , pLocalPawn , 3 , 15 ); Vector3 vEdgeNormal; bool bFoundEdge = false; for ( const auto& vOffset : vOffsets ) { const Vector3 vProbeStart { vNextPos.m_x + vOffset.m_x, vNextPos.m_y + vOffset.m_y, vNextPos.m_z }; // Ground probe straight down below this corner. Ray.Start = vProbeStart; Ray.End = vProbeStart; Ray.End.m_z -= k_ProbeDist; if ( !IGamePhysicsQuery_TraceShape( SDK::Pointers::CVPhys2World() , Ray , Ray.Start , Ray.End , &Filter , &GameTrace ) ) continue; const float flGroundFraction = GameTrace.flFraction; // Wall probe in the direction of travel at the same height. Ray.Start = vProbeStart; Ray.Start.m_z -= 2.f; Ray.End = Ray.Start; Ray.End.m_x += std::cosf( flVelocityYaw * ( k_Pi / 180.f ) ) * k_ProbeDist; Ray.End.m_y += std::sinf( flVelocityYaw * ( k_Pi / 180.f ) ) * k_ProbeDist; if ( !IGamePhysicsQuery_TraceShape( SDK::Pointers::CVPhys2World() , Ray , Ray.Start , Ray.End , &Filter , &GameTrace ) ) continue; // Open ground below + wall ahead = pixel / edge surface. if ( flGroundFraction > 0.9f && GameTrace.flFraction < 0.95f ) { bFoundEdge = true; vEdgeNormal = GameTrace.vecNormal; break; } } if ( !bFoundEdge ) return; // Only assist when the edge is below us (steep / vertical-ish face). if ( vEdgeNormal.m_z > 0.7f ) return; GetCL_Bypass()->SetJump( pUserCmd , true ); } auto CMisc::RunTriggerbot( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void { auto Reset = [ & ]() { m_bTriggerShooting = false; m_TriggerArmTime = {}; m_ShotStartTime = {}; m_bTargetInCrosshair = false; m_bTriggerFiring = false; }; auto* pLocalPawn = GetCL_Players()->GetLocalPlayerPawn(); if ( !pLocalPawn || !pLocalPawn->IsAlive() ) { Reset(); return; } const auto WeaponType = GetCL_Weapons()->GetLocalWeaponType(); const bool bIsGun = WeaponType == CSWeaponType_t::WEAPONTYPE_PISTOL || WeaponType == CSWeaponType_t::WEAPONTYPE_SUBMACHINEGUN || WeaponType == CSWeaponType_t::WEAPONTYPE_RIFLE || WeaponType == CSWeaponType_t::WEAPONTYPE_SHOTGUN || WeaponType == CSWeaponType_t::WEAPONTYPE_SNIPER_RIFLE || WeaponType == CSWeaponType_t::WEAPONTYPE_MACHINEGUN || WeaponType == CSWeaponType_t::WEAPONTYPE_TASER; if ( !bIsGun ) { Reset(); return; } if ( Settings::Triggerbot::ScopedOnly ) { if ( WeaponType == CSWeaponType_t::WEAPONTYPE_SNIPER_RIFLE && !pLocalPawn->m_bIsScoped() ) { Reset(); return; } } bool bShouldRun = false; switch ( Settings::Triggerbot::Mode ) { case 1: { bShouldRun = true; } break; case 2: { const bool bKeyDown = ( GetAsyncKeyState( Settings::Triggerbot::Key ) & 0x8000 ) != 0; if ( bKeyDown && !m_bTriggerKeyDown ) m_bTriggerToggledOn = !m_bTriggerToggledOn; m_bTriggerKeyDown = bKeyDown; bShouldRun = m_bTriggerToggledOn; } break; default: { const bool bKeyDown = ( GetAsyncKeyState( Settings::Triggerbot::Key ) & 0x8000 ) != 0; bShouldRun = bKeyDown; } break; } if ( !bShouldRun ) { Reset(); return; } TriggerTraceResult_t Result; if ( Settings::Triggerbot::SeedTrigger ) { Vector3 vDirection; if ( CalculateSeedDirection( pInput , pUserCmd , &vDirection ) ) Result = GetCL_Trace()->TraceDirectionToHitGroup( &vDirection ); } else { Result = GetCL_Trace()->TraceToHitGroup( pInput ); } auto* pTargetPawn = reinterpret_cast( Result.pHitEntity ); bool bTargetValid = false; if ( pTargetPawn && pTargetPawn->IsPlayerPawn() && pTargetPawn != pLocalPawn && pTargetPawn->IsAlive() ) { if ( !Settings::Triggerbot::IgnoreTeammates || pTargetPawn->m_iTeamNum() != pLocalPawn->m_iTeamNum() ) { switch ( Result.nHitGroup ) { case 1: bTargetValid = Settings::Triggerbot::Hitbox_Head; break; case 2: bTargetValid = Settings::Triggerbot::Hitbox_Chest; break; case 3: bTargetValid = Settings::Triggerbot::Hitbox_Stomach; break; case 4: case 5: bTargetValid = Settings::Triggerbot::Hitbox_Arms; break; case 6: case 7: bTargetValid = Settings::Triggerbot::Hitbox_Legs; break; default: bTargetValid = true; break; } if ( bTargetValid && !Settings::Triggerbot::SeedTrigger && Settings::Triggerbot::Hitchance > 0 ) { const QAngle ViewAngles = *CCSGOInput_GetViewAngles( pInput , 0 ); const float flHitchance = CalculateHitchance( pInput , pTargetPawn , ViewAngles , Settings::Triggerbot::HitchanceSamples ); if ( ( flHitchance * 100.f ) < static_cast( Settings::Triggerbot::Hitchance ) ) bTargetValid = false; } } } m_bTargetInCrosshair = bTargetValid; if ( !bTargetValid ) { m_bTriggerShooting = false; m_TriggerArmTime = {}; m_ShotStartTime = {}; m_bTriggerFiring = false; return; } const auto Now = std::chrono::steady_clock::now(); const auto DelayMs = std::chrono::milliseconds( std::max( 0 , Settings::Triggerbot::Delay ) ); const auto HoldMs = std::chrono::milliseconds( std::max( 0 , Settings::Triggerbot::HoldTime ) ); if ( !m_bTriggerShooting ) { if ( m_TriggerArmTime.time_since_epoch().count() == 0 ) m_TriggerArmTime = Now; if ( ( Now - m_TriggerArmTime ) >= DelayMs ) { m_bTriggerShooting = true; m_ShotStartTime = Now; m_TriggerArmTime = {}; } } else { if ( ( Now - m_ShotStartTime ) >= HoldMs ) { m_bTriggerShooting = false; m_TriggerArmTime = Now; } } if ( m_bTriggerShooting ) { GetCL_Bypass()->SetAttack( pUserCmd , true ); m_bTriggerFiring = true; } else { m_bTriggerFiring = false; } } static thread_local std::mt19937 g_TriggerRng( std::random_device{}() ); auto CMisc::CalculateHitchance( CCSGOInput* pInput , C_CSPlayerPawn* pTarget , const QAngle& ViewAngles , const int Samples ) -> float { if ( !pTarget || Samples <= 0 ) return 0.f; auto* pWeapon = GetCL_Weapons()->GetLocalActiveWeapon(); if ( !pWeapon ) return 0.f; const float flInaccuracy = C_CSWeaponBaseGun_GetInaccuracy( pWeapon , nullptr , nullptr ); const float flSpread = C_CSWeaponBaseGun_GetSpread( pWeapon ); const float flAccuracy = flInaccuracy + flSpread; if ( flAccuracy <= 0.f ) return 1.f; Vector3 vForward , vRight , vUp; Math::AngleVectors( ViewAngles , vForward , vRight , vUp ); const auto vStart = GetCL_Players()->GetLocalEyeOrigin(); std::uniform_real_distribution distAngle( 0.f , 6.2831853f ); std::uniform_real_distribution distRadius( 0.f , 1.f ); int Hits = 0; for ( int i = 0; i < Samples; i++ ) { const float flAngle = distAngle( g_TriggerRng ); const float flRadius = flAccuracy * std::sqrt( distRadius( g_TriggerRng ) ); const Vector3 vDirection = ( vForward + vRight * ( std::cos( flAngle ) * flRadius ) + vUp * ( std::sin( flAngle ) * flRadius ) ).Normalized(); const Vector3 vEnd = vStart + vDirection * 8192.f; if ( GetCL_Trace()->TraceToEntityEndPos( &vEnd ) == reinterpret_cast( pTarget ) ) Hits++; } return static_cast( Hits ) / static_cast( Samples ); } auto CMisc::CalculateSeedDirection( CCSGOInput* pInput , CUserCmd* pUserCmd , Vector3* vOutDirection ) -> bool { if ( !pInput || !vOutDirection ) return false; auto* pWeapon = GetCL_Weapons()->GetLocalActiveWeapon(); if ( !pWeapon ) return false; const QAngle ViewAngles = *CCSGOInput_GetViewAngles( pInput , 0 ); int iSeed = 0; if ( pUserCmd && pUserCmd->cmd.base().has_random_seed() ) { iSeed = pUserCmd->cmd.base().random_seed(); } else { int iTick = 0; if ( pUserCmd && pUserCmd->cmd.base().has_client_tick() ) iTick = pUserCmd->cmd.base().client_tick(); iSeed = static_cast( GetSpreadSeed( ViewAngles , iTick ) ); } const float flInaccuracy = C_CSWeaponBaseGun_GetInaccuracy( pWeapon , nullptr , nullptr ); const float flSpread = C_CSWeaponBaseGun_GetSpread( pWeapon ); const auto ItemDefIdx = GetCL_Weapons()->GetLocalWeaponDefinitionIndex(); const auto sv = CalculateSeedSpread( iSeed + 1 , flInaccuracy , flSpread , ItemDefIdx ); Vector3 vForward , vRight , vUp; Math::AngleVectors( ViewAngles , vForward , vRight , vUp ); *vOutDirection = ( vForward + vRight * -sv.x + vUp * sv.y ).Normalized(); return true; } auto CMisc::OnFrameStageNotify( int FrameStage ) -> void { if ( FrameStage != 6 ) return; if ( !Settings::Misc::NoFlash ) return; auto* pLocalPawn = GetCL_Players()->GetLocalPlayerPawn(); if ( !pLocalPawn ) return; pLocalPawn->m_flFlashDuration() = 0.f; pLocalPawn->m_flFlashMaxAlpha() = 0.f; } auto CMisc::OnFireEventClientSide( IGameEvent* pGameEvent ) -> void { if ( !pGameEvent ) return; if ( _strcmpi( pGameEvent->GetName() , XorStr( "player_hurt" ) ) != 0 ) return; auto* pLocalController = GetCL_Players()->GetLocalPlayerController(); if ( !pLocalController ) return; auto* pAttackerController = pGameEvent->GetPlayerController( XorStr( "attacker" ) ); if ( pAttackerController != pLocalController ) return; const auto Now = std::chrono::steady_clock::now(); if ( Settings::Misc::Hitmarker ) m_HitTime = Now; if ( Settings::Misc::HitSound ) { if ( ( Now - m_HitSoundTime ) > std::chrono::milliseconds( 50 ) ) { m_HitSoundTime = Now; PlaySoundW( L"SystemHand" , nullptr , SND_ALIAS | SND_ASYNC | SND_NODEFAULT ); } } } auto GetMisc() -> CMisc* { return &g_CMisc; }