Add configurable triggerbot (mode/key/delay/hold, hitbox filter, scoped-only, indicator)

This commit is contained in:
2026-08-05 16:42:17 +02:00
parent 483dd5cb59
commit 9b9659e152
6 changed files with 309 additions and 1 deletions
@@ -1,5 +1,6 @@
#include "CMisc.hpp" #include "CMisc.hpp"
#include <algorithm>
#include <cstdio> #include <cstdio>
#include <ctime> #include <ctime>
#include <mmsystem.h> #include <mmsystem.h>
@@ -18,7 +19,11 @@
#include <AndromedaClient/Render/CRenderStackSystem.hpp> #include <AndromedaClient/Render/CRenderStackSystem.hpp>
#include <GameClient/CL_Players.hpp> #include <GameClient/CL_Players.hpp>
#include <GameClient/CL_Weapons.hpp>
#include <GameClient/CL_Trace.hpp>
#include <GameClient/CL_Bypass.hpp>
#include <GameClient/CEntityCache/CEntityCache.hpp> #include <GameClient/CEntityCache/CEntityCache.hpp>
#include <CS2/SDK/Types/CBaseTypes.hpp>
#include <ImGui/imgui.h> #include <ImGui/imgui.h>
@@ -91,7 +96,7 @@ auto CMisc::OnClientOutput() -> void
const auto ObserverMode = pObserverServices->m_iObserverMode(); const auto ObserverMode = pObserverServices->m_iObserverMode();
if ( ObserverMode != 4 && ObserverMode != 5 ) if ( ObserverMode != OBS_MODE_IN_EYE && ObserverMode != OBS_MODE_CHASE )
continue; continue;
if ( pObserverServices->m_hObserverTarget() != LocalPawnHandle ) if ( pObserverServices->m_hObserverTarget() != LocalPawnHandle )
@@ -109,6 +114,20 @@ auto CMisc::OnClientOutput() -> void
} }
} }
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 ( Settings::Misc::Hitmarker )
{ {
if ( m_HitTime.time_since_epoch().count() > 0 ) if ( m_HitTime.time_since_epoch().count() > 0 )
@@ -137,6 +156,9 @@ auto CMisc::OnCreateMove( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void
if ( !pUserCmd ) if ( !pUserCmd )
return; return;
if ( Settings::Triggerbot::Active )
RunTriggerbot( pInput , pUserCmd );
if ( Settings::Misc::Bunnyhop ) if ( Settings::Misc::Bunnyhop )
{ {
auto* pLocalPawn = GetCL_Players()->GetLocalPlayerPawn(); auto* pLocalPawn = GetCL_Players()->GetLocalPlayerPawn();
@@ -170,6 +192,164 @@ auto CMisc::OnCreateMove( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void
} }
} }
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;
}
const auto Result = GetCL_Trace()->TraceToHitGroup( pInput );
auto* pTargetPawn = reinterpret_cast<C_CSPlayerPawn*>( 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;
}
}
}
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;
}
}
auto CMisc::OnFrameStageNotify( int FrameStage ) -> void auto CMisc::OnFrameStageNotify( int FrameStage ) -> void
{ {
if ( FrameStage != 6 ) if ( FrameStage != 6 )
@@ -3,6 +3,7 @@
#include <Common/Common.hpp> #include <Common/Common.hpp>
#include <chrono> #include <chrono>
#include <atomic>
class CCSGOInput; class CCSGOInput;
class CUserCmd; class CUserCmd;
@@ -27,9 +28,22 @@ public:
virtual void OnFrameStageNotify( int FrameStage ) override; virtual void OnFrameStageNotify( int FrameStage ) override;
virtual void OnFireEventClientSide( IGameEvent* pGameEvent ) override; virtual void OnFireEventClientSide( IGameEvent* pGameEvent ) override;
private:
auto RunTriggerbot( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void;
private: private:
std::chrono::steady_clock::time_point m_HitTime{}; std::chrono::steady_clock::time_point m_HitTime{};
std::chrono::steady_clock::time_point m_HitSoundTime{}; std::chrono::steady_clock::time_point m_HitSoundTime{};
private:
bool m_bTriggerToggledOn = false;
bool m_bTriggerKeyDown = false;
bool m_bTriggerShooting = false;
std::chrono::steady_clock::time_point m_TriggerArmTime{};
std::chrono::steady_clock::time_point m_ShotStartTime{};
std::atomic_bool m_bTargetInCrosshair = false;
std::atomic_bool m_bTriggerFiring = false;
}; };
auto GetMisc() -> CMisc*; auto GetMisc() -> CMisc*;
@@ -350,6 +350,61 @@ auto CAndromedaMenu::RenderMiscPanel() -> void
Checkbox( "Hitmarker" , Settings::Misc::Hitmarker ); Checkbox( "Hitmarker" , Settings::Misc::Hitmarker );
Checkbox( "Hit Sound" , Settings::Misc::HitSound ); Checkbox( "Hit Sound" , Settings::Misc::HitSound );
ImGui::SeparatorText( "Triggerbot" );
Checkbox( "Triggerbot" , Settings::Triggerbot::Active );
if ( Settings::Triggerbot::Active )
{
const char* TriggerModeItems[] =
{
"Hold Key" , "Always" , "Toggle"
};
Combo( "Mode" , Settings::Triggerbot::Mode , TriggerModeItems , IM_ARRAYSIZE( TriggerModeItems ) );
static const char* TriggerKeyItems[] =
{
"Alt" , "Shift" , "Ctrl" , "Mouse 4" , "Mouse 5" , "Q" , "E" , "F" , "X" , "C" , "V" , "B" , "Space"
};
static const int TriggerKeys[] =
{
VK_MENU , VK_SHIFT , VK_CONTROL , 0x04 , 0x05 , 0x51 , 0x45 , 0x46 , 0x58 , 0x43 , 0x56 , 0x42 , VK_SPACE
};
int iKeyIdx = 0;
for ( int i = 0; i < IM_ARRAYSIZE( TriggerKeys ); i++ )
{
if ( TriggerKeys[ i ] == Settings::Triggerbot::Key )
{
iKeyIdx = i;
break;
}
}
if ( Combo( "Key" , iKeyIdx , TriggerKeyItems , IM_ARRAYSIZE( TriggerKeyItems ) ) )
Settings::Triggerbot::Key = TriggerKeys[ iKeyIdx ];
SliderInt( "Delay (ms)" , Settings::Triggerbot::Delay , 0 , 300 );
SliderInt( "Hold Time (ms)" , Settings::Triggerbot::HoldTime , 0 , 200 );
ImGui::Separator();
Checkbox( "Nur gescoped (Sniper)" , Settings::Triggerbot::ScopedOnly );
Checkbox( "Teammates ignorieren" , Settings::Triggerbot::IgnoreTeammates );
Checkbox( "Fadenkreuz-Indikator" , Settings::Triggerbot::DrawIndicator );
ImGui::Separator();
Checkbox( "Kopf" , Settings::Triggerbot::Hitbox_Head );
Checkbox( "Brust" , Settings::Triggerbot::Hitbox_Chest );
Checkbox( "Bauch" , Settings::Triggerbot::Hitbox_Stomach );
Checkbox( "Arme" , Settings::Triggerbot::Hitbox_Arms );
Checkbox( "Beine" , Settings::Triggerbot::Hitbox_Legs );
}
} }
auto CAndromedaMenu::RenderConfigPanel() -> void auto CAndromedaMenu::RenderConfigPanel() -> void
@@ -52,6 +52,22 @@ namespace Settings
inline auto Hitmarker = true; inline auto Hitmarker = true;
inline auto HitSound = true; inline auto HitSound = true;
} }
namespace Triggerbot
{
inline auto Active = false;
inline auto Mode = 0; // 0 = Hold Key, 1 = Always, 2 = Toggle
inline auto Key = VK_MENU; // Alt
inline auto Delay = 50; // ms
inline auto HoldTime = 30; // ms
inline auto ScopedOnly = false;
inline auto IgnoreTeammates = true;
inline auto Hitbox_Head = true;
inline auto Hitbox_Chest = true;
inline auto Hitbox_Stomach = true;
inline auto Hitbox_Arms = false;
inline auto Hitbox_Legs = false;
inline auto DrawIndicator = true;
}
namespace Colors namespace Colors
{ {
namespace Visual namespace Visual
@@ -84,6 +84,42 @@ auto CL_Trace::TraceToEntityEndPos( const Vector3* vEnd ) -> C_BaseEntity*
return nullptr; return nullptr;
} }
auto CL_Trace::TraceToHitGroup( CCSGOInput* pInput ) -> TriggerTraceResult_t
{
TriggerTraceResult_t Result;
auto pLocalPlayerPawn = GetCL_Players()->GetLocalPlayerPawn();
if ( !pLocalPlayerPawn || !pInput )
return Result;
Vector3 vForward;
Ray_t Ray;
CGameTrace GameTrace;
CTraceFilter Filter( 0x1C1003 , pLocalPlayerPawn , 3 , 15 );
const auto vStart = GetCL_Players()->GetLocalEyeOrigin();
QAngle ViewAngles = *CCSGOInput_GetViewAngles( pInput , 0 );
Math::AngleVectors( ViewAngles , vForward );
vForward *= 8192.f;
const auto vEnd = vStart + vForward;
if ( IGamePhysicsQuery_TraceShape( SDK::Pointers::CVPhys2World() , Ray , vStart , vEnd , &Filter , &GameTrace ) )
{
if ( GameTrace.pHitEntity && GameTrace.pHitBox )
{
Result.pHitEntity = GameTrace.pHitEntity;
Result.nHitGroup = GameTrace.pHitBox->nGroupId;
}
}
return Result;
}
auto GetCL_Trace() -> CL_Trace* auto GetCL_Trace() -> CL_Trace*
{ {
return &g_CL_Trace; return &g_CL_Trace;
@@ -11,11 +11,18 @@ class Vector3;
class CCSGOInput; class CCSGOInput;
class C_BaseEntity; class C_BaseEntity;
struct TriggerTraceResult_t
{
C_BaseEntity* pHitEntity = nullptr;
int nHitGroup = 0;
};
class CL_Trace final class CL_Trace final
{ {
public: public:
auto TraceToBoneEntity( CCSGOInput* pInput , const QAngle* AngleCorrection , QAngle* ViewAngleCorrection ) -> std::pair<uint64_t , C_BaseEntity*>; auto TraceToBoneEntity( CCSGOInput* pInput , const QAngle* AngleCorrection , QAngle* ViewAngleCorrection ) -> std::pair<uint64_t , C_BaseEntity*>;
auto TraceToEntityEndPos( const Vector3* vEnd ) -> C_BaseEntity*; auto TraceToEntityEndPos( const Vector3* vEnd ) -> C_BaseEntity*;
auto TraceToHitGroup( CCSGOInput* pInput ) -> TriggerTraceResult_t;
}; };
auto GetCL_Trace() -> CL_Trace*; auto GetCL_Trace() -> CL_Trace*;