From 19521e1d4c0ae34627f6d62104657b7d18f72d51 Mon Sep 17 00:00:00 2001 From: _or_75 Date: Mon, 20 Oct 2025 14:39:17 +0300 Subject: [PATCH] add visible check, trace, bones, player box --- Andromeda-CS2-Base/Andromeda-CS2-Base.vcxproj | 6 ++ .../Andromeda-CS2-Base.vcxproj.filters | 18 ++++ .../AndromedaClient/CAndromedaClient.cpp | 2 + .../Features/CVisual/CVisual.cpp | 92 +++++++++++++++++++ .../Features/CVisual/CVisual.hpp | 11 +++ .../AndromedaClient/Settings/Settings.hpp | 14 +++ .../GameClient/CL_Bones.cpp | 44 +++++++++ .../GameClient/CL_Bones.hpp | 18 ++++ .../GameClient/CL_Players.cpp | 20 ++++ .../GameClient/CL_Players.hpp | 4 + .../GameClient/CL_Trace.cpp | 90 ++++++++++++++++++ .../GameClient/CL_Trace.hpp | 21 +++++ .../GameClient/CL_VisibleCheck.cpp | 74 +++++++++++++++ .../GameClient/CL_VisibleCheck.hpp | 18 ++++ 14 files changed, 432 insertions(+) create mode 100644 Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Bones.cpp create mode 100644 Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Bones.hpp create mode 100644 Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Trace.cpp create mode 100644 Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Trace.hpp create mode 100644 Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_VisibleCheck.cpp create mode 100644 Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_VisibleCheck.hpp diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base.vcxproj b/Andromeda-CS2-Base/Andromeda-CS2-Base.vcxproj index 62d939c..d849fa4 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base.vcxproj +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base.vcxproj @@ -241,9 +241,12 @@ + + + @@ -451,9 +454,12 @@ + + + diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base.vcxproj.filters b/Andromeda-CS2-Base/Andromeda-CS2-Base.vcxproj.filters index c496531..05d47a4 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base.vcxproj.filters +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base.vcxproj.filters @@ -450,6 +450,15 @@ Andromeda-CS2-Base\AndromedaClient\Features + + Andromeda-CS2-Base\GameClient + + + Andromeda-CS2-Base\GameClient + + + Andromeda-CS2-Base\GameClient + @@ -1076,5 +1085,14 @@ Andromeda-CS2-Base\Common + + Andromeda-CS2-Base\GameClient + + + Andromeda-CS2-Base\GameClient + + + Andromeda-CS2-Base\GameClient + \ No newline at end of file diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/CAndromedaClient.cpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/CAndromedaClient.cpp index 77fbb11..d220b68 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/CAndromedaClient.cpp +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/CAndromedaClient.cpp @@ -64,6 +64,8 @@ auto CAndromedaClient::OnClientOutput() -> void auto CAndromedaClient::OnCreateMove( CCSGOInput* pInput , CUserCmd* pUserCmd ) -> void { + GetVisual()->OnCreateMove(); + DEV_LOG( "%s\n" , pUserCmd->cmd.DebugString().c_str() ); } diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CVisual/CVisual.cpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CVisual/CVisual.cpp index 197bf6a..fc4c220 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CVisual/CVisual.cpp +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CVisual/CVisual.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include static CVisual g_CVisual{}; @@ -48,7 +50,63 @@ auto CVisual::OnRender() -> void auto CVisual::OnRenderPlayerEsp( CCSPlayerController* pCCSPlayerController , const Rect_t& bBox , const bool bVisible ) -> void { + if ( !pCCSPlayerController->m_bPawnIsAlive() ) + return; + auto* pC_CSPlayerPawn = pCCSPlayerController->m_hPawn().Get(); + + if ( !pC_CSPlayerPawn || !pC_CSPlayerPawn->IsPlayerPawn() ) + return; + + auto IsEnemy = false; + + if ( auto* pLocalPlayerController = GetCL_Players()->GetLocalPlayerController(); pLocalPlayerController ) + IsEnemy = pCCSPlayerController->m_iTeamNum() != pLocalPlayerController->m_iTeamNum(); + + const ImVec2 min = { bBox.x, bBox.y }; + const ImVec2 max = { bBox.w, bBox.h }; + + std::vector PlayerItemIconList; + + auto Draw = false; + + if ( Settings::Visual::Team && !IsEnemy ) + Draw = true; + + if ( Settings::Visual::Enemy && IsEnemy ) + Draw = true; + + if ( Draw ) + { + if ( Settings::Visual::PlayerBox ) + { + auto PlayerColor = ImColor( 255 , 255 , 255 ); + + if ( pCCSPlayerController->m_iTeamNum() == TEAM_TT ) + { + PlayerColor = ImColor( Settings::Colors::Visual::PlayerBoxTT[0] , Settings::Colors::Visual::PlayerBoxTT[1] , Settings::Colors::Visual::PlayerBoxTT[2] , Settings::Colors::Visual::PlayerBoxTT[3] ); + + if ( bVisible ) + PlayerColor = ImColor( Settings::Colors::Visual::PlayerBoxTT_Visible[0] , Settings::Colors::Visual::PlayerBoxTT_Visible[1] , Settings::Colors::Visual::PlayerBoxTT_Visible[2] , Settings::Colors::Visual::PlayerBoxTT_Visible[3] ); + } + else if ( pCCSPlayerController->m_iTeamNum() == TEAM_CT ) + { + PlayerColor = ImColor( Settings::Colors::Visual::PlayerBoxCT[0] , Settings::Colors::Visual::PlayerBoxCT[1] , Settings::Colors::Visual::PlayerBoxCT[2] , Settings::Colors::Visual::PlayerBoxCT[3] ); + + if ( bVisible ) + PlayerColor = ImColor( Settings::Colors::Visual::PlayerBoxCT_Visible[0] , Settings::Colors::Visual::PlayerBoxCT_Visible[1] , Settings::Colors::Visual::PlayerBoxCT_Visible[2] , Settings::Colors::Visual::PlayerBoxCT_Visible[3] ); + } + + if ( Settings::Visual::PlayerBoxType == EVisualBoxType_t::BOX ) + GetRenderStackSystem()->DrawBox( min , max , PlayerColor ); + else if ( Settings::Visual::PlayerBoxType == EVisualBoxType_t::OUTLINE_BOX ) + GetRenderStackSystem()->DrawOutlineBox( min , max , PlayerColor ); + else if ( Settings::Visual::PlayerBoxType == EVisualBoxType_t::COAL_BOX ) + GetRenderStackSystem()->DrawCoalBox( min , max , PlayerColor ); + else if ( Settings::Visual::PlayerBoxType == EVisualBoxType_t::OUTLINE_COAL_BOX ) + GetRenderStackSystem()->DrawOutlineCoalBox( min , max , PlayerColor ); + } + } } auto CVisual::OnClientOutput() -> void @@ -56,6 +114,40 @@ auto CVisual::OnClientOutput() -> void OnRender(); } +auto CVisual::OnCreateMove() -> void +{ + if ( !Settings::Visual::Active ) + return; + + const auto CachedVec = GetEntityCache()->GetCachedEntity(); + + for ( auto& CachedEntity : *CachedVec ) + { + auto pEntity = CachedEntity.m_Handle.Get(); + + if ( !pEntity ) + continue; + + auto hEntity = pEntity->pEntityIdentity()->Handle(); + + if ( hEntity != CachedEntity.m_Handle ) + continue; + + switch ( CachedEntity.m_Type ) + { + case CachedEntity_t::PLAYER_CONTROLLER: + { + auto* pCCSPlayerController = reinterpret_cast( pEntity ); + + CachedEntity.m_bVisible = GetCL_VisibleCheck()->IsPlayerControllerVisible( pCCSPlayerController ); + } + break; + default: + break; + } + } +} + auto CVisual::CalculateBoundingBoxes() -> void { if ( !SDK::Interfaces::EngineToClient()->IsInGame() ) diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CVisual/CVisual.hpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CVisual/CVisual.hpp index bcd401e..2389fce 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CVisual/CVisual.hpp +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Features/CVisual/CVisual.hpp @@ -11,6 +11,7 @@ class IVisual public: virtual void OnRender() = 0; virtual void OnClientOutput() = 0; + virtual void OnCreateMove() = 0; }; class CVisual final : public IVisual @@ -18,8 +19,18 @@ class CVisual final : public IVisual public: virtual void OnRender() override; virtual void OnClientOutput() override; + virtual void OnCreateMove() override; private: + enum EVisualBoxType_t : int32_t + { + BOX , + OUTLINE_BOX , + COAL_BOX , + OUTLINE_COAL_BOX , + CIRCLE_3D , + }; + auto OnRenderPlayerEsp( CCSPlayerController* pCCSPlayerController , const Rect_t& bBox , const bool bVisible ) -> void; public: 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 a880cb5..5009db5 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Settings/Settings.hpp +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/AndromedaClient/Settings/Settings.hpp @@ -7,11 +7,25 @@ namespace Settings namespace Visual { inline auto Active = true; + inline auto Team = true; + inline auto Enemy = true; inline auto PlayerBox = true; + + inline auto PlayerBoxType = 3; } namespace Misc { inline auto MenuAlpha = 200; inline auto MenuStyle = 0; } + namespace Colors + { + namespace Visual + { + inline float PlayerBoxTT[4] = { 255.f / 255.f , 75.f / 255.f , 75.f / 255.f , 1.f }; + inline float PlayerBoxTT_Visible[4] = { 0 , 1.f , 0.f , 1.f }; + inline float PlayerBoxCT[4] = { 65.f / 255.f , 200 / 255.f , 255.f / 255.f , 1.f }; + inline float PlayerBoxCT_Visible[4] = { 0 , 1.f , 0.f , 1.f }; + } + } } diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Bones.cpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Bones.cpp new file mode 100644 index 0000000..fb9be4f --- /dev/null +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Bones.cpp @@ -0,0 +1,44 @@ +#include "CL_Bones.hpp" + +#include + +static CL_Bones g_CL_Bones{}; + +std::vector g_AllTraceVisibleCheckBones = +{ + "head_0", + "pelvis", + "arm_lower_r", + "arm_lower_l", + "ankle_r", + "ankle_l", +}; + +auto CL_Bones::GetBonePositionByName( C_CSPlayerPawn* pC_CSPlayerPawn , const char* szBoneName ) -> Vector3 +{ + Vector3 BonePosition; + + if ( auto* pSkeletonInstance = pC_CSPlayerPawn->m_pGameSceneNode()->GetSkeletonInstance(); pSkeletonInstance ) + { + pSkeletonInstance->CalcWorldSpaceBones( FLAG_ALL_BONE_FLAGS ); + + const auto& Model = pSkeletonInstance->m_modelState().m_hModel(); + + if ( !Model.is_valid() ) + return BonePosition; + + const auto BoneIndex = pC_CSPlayerPawn->GetBoneIdByName( szBoneName ); + + if ( BoneIndex != -1 && pSkeletonInstance->GetBonePosition( BoneIndex , BonePosition ) ) + return BonePosition; + else + DEV_LOG( "[error] GetBoneIdByName: %s\n" , szBoneName ); + } + + return BonePosition; +} + +auto GetCL_Bones() -> CL_Bones* +{ + return &g_CL_Bones; +} diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Bones.hpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Bones.hpp new file mode 100644 index 0000000..6abcdee --- /dev/null +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Bones.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +#include + +class C_CSPlayerPawn; + +extern std::vector g_AllTraceVisibleCheckBones; + +class CL_Bones final +{ +public: + auto GetBonePositionByName( C_CSPlayerPawn* pC_CSPlayerPawn , const char* szBoneName ) -> Vector3; +}; + +auto GetCL_Bones() -> CL_Bones*; diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Players.cpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Players.cpp index 381229e..fff9371 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Players.cpp +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Players.cpp @@ -26,6 +26,26 @@ auto CL_Players::GetLocalPlayerPawn() -> C_CSPlayerPawn* return nullptr; } +auto CL_Players::GetLocalOrigin() -> Vector3 +{ + auto pLocalPlayerPawn = GetLocalPlayerPawn(); + + if ( pLocalPlayerPawn ) + return pLocalPlayerPawn->GetOrigin(); + + return Vector3(); +} + +auto CL_Players::GetLocalEyeOrigin() -> Vector3 +{ + auto pLocalPlayerPawn = GetLocalPlayerPawn(); + + if ( pLocalPlayerPawn ) + return GetLocalOrigin() + pLocalPlayerPawn->m_vecViewOffset(); + + return Vector3(); +} + auto CL_Players::IsLocalPlayerAlive() -> bool { auto pLocalPlayerController = GetLocalPlayerController(); diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Players.hpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Players.hpp index 1eda7f6..5cc8393 100644 --- a/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Players.hpp +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Players.hpp @@ -13,6 +13,10 @@ public: auto GetLocalPlayerController() -> CCSPlayerController*; auto GetLocalPlayerPawn() -> C_CSPlayerPawn*; +public: + auto GetLocalOrigin()->Vector3; + auto GetLocalEyeOrigin()->Vector3; + public: auto IsLocalPlayerAlive() -> bool; }; diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Trace.cpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Trace.cpp new file mode 100644 index 0000000..749c0cb --- /dev/null +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Trace.cpp @@ -0,0 +1,90 @@ +#include "CL_Trace.hpp" + +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +static CL_Trace g_CL_Trace{}; + +auto CL_Trace::TraceToBoneEntity( CCSGOInput* pInput , const QAngle* AngleCorrection , QAngle* ViewAngleCorrection ) -> std::pair +{ + auto pLocalPlayerPawn = GetCL_Players()->GetLocalPlayerPawn(); + + if ( !pLocalPlayerPawn ) + return { 0 , nullptr }; + + 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 ); + + if ( AngleCorrection ) + ViewAngles += ( *AngleCorrection * 2.f ); + + if ( ViewAngleCorrection ) + *ViewAngleCorrection = ViewAngles; + + 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.pHitBox && GameTrace.pHitBox->szBoneName && + hash_64_fnv1a_const( GameTrace.pHitBox->szBoneName ) != hash_64_fnv1a_const( "invalid_bone" ) ) + { + //DEV_LOG( "Trace: %s\n" , GameTrace.pHitBox->szBoneName ); + + return { hash_64_fnv1a_const( GameTrace.pHitBox->szBoneName ) , GameTrace.pHitEntity }; + } + } + + return { 0 , nullptr }; +} + +auto CL_Trace::TraceToEntityEndPos( const Vector3* vEnd ) -> C_BaseEntity* +{ + auto pLocalPlayerPawn = GetCL_Players()->GetLocalPlayerPawn(); + + if ( !pLocalPlayerPawn ) + return nullptr; + + Ray_t Ray; + CGameTrace GameTrace; + CTraceFilter Filter( 0x1C1003 , pLocalPlayerPawn , 3 , 15 ); + + const auto vStart = GetCL_Players()->GetLocalEyeOrigin(); + + if ( IGamePhysicsQuery_TraceShape( SDK::Pointers::CVPhys2World() , Ray , vStart , *vEnd , &Filter , &GameTrace ) ) + { + if ( GameTrace.pHitBox && GameTrace.pHitEntity && GameTrace.pHitBox->szBoneName && + hash_64_fnv1a_const( GameTrace.pHitBox->szBoneName ) != hash_64_fnv1a_const( "invalid_bone" ) ) + { + return GameTrace.pHitEntity; + } + } + + return nullptr; +} + +auto GetCL_Trace() -> CL_Trace* +{ + return &g_CL_Trace; +} diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Trace.hpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Trace.hpp new file mode 100644 index 0000000..b6bb3d0 --- /dev/null +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_Trace.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +#include "CL_Bones.hpp" + +class QAngle; +class Vector3; + +class CCSGOInput; +class C_BaseEntity; + +class CL_Trace final +{ +public: + auto TraceToBoneEntity( CCSGOInput* pInput , const QAngle* AngleCorrection , QAngle* ViewAngleCorrection ) -> std::pair; + auto TraceToEntityEndPos( const Vector3* vEnd ) -> C_BaseEntity*; +}; + +auto GetCL_Trace() -> CL_Trace*; diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_VisibleCheck.cpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_VisibleCheck.cpp new file mode 100644 index 0000000..1e54539 --- /dev/null +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_VisibleCheck.cpp @@ -0,0 +1,74 @@ +#include "CL_VisibleCheck.hpp" + +#include + +#include +#include + +static CL_VisibleCheck g_CL_VisibleCheck{}; + +auto CL_VisibleCheck::IsPlayerControllerVisible( CCSPlayerController* pCCSPlayerController ) -> bool +{ + auto Visible = false; + + if ( pCCSPlayerController ) + Visible = IsPlayerPawnVisible( pCCSPlayerController->m_hPawn().Get() ); + + return Visible; +} + +auto CL_VisibleCheck::IsPlayerPawnVisible( C_CSPlayerPawn* pC_CSPlayerPawn ) -> bool +{ + auto Visible = false; + + if ( pC_CSPlayerPawn && pC_CSPlayerPawn->IsPlayerPawn() ) + { + bool IsBoneVisible = false; + + for ( const auto& BoneName : g_AllTraceVisibleCheckBones ) + { + const Vector3 BonePos = GetCL_Bones()->GetBonePositionByName( pC_CSPlayerPawn , BoneName.c_str() ); + + if ( !BonePos.IsZero() ) + { + const auto* pTracedEntity = GetCL_Trace()->TraceToEntityEndPos( &BonePos ); + + if ( pTracedEntity == pC_CSPlayerPawn ) + IsBoneVisible = true; + else + continue; + } + else + { + IsBoneVisible = false; + } + } + + Visible = IsBoneVisible; + } + + return Visible; +} + +auto CL_VisibleCheck::IsBoneVisible( C_CSPlayerPawn* pC_CSPlayerPawn , const Vector3& BonePos ) -> bool +{ + auto Visible = false; + + if ( pC_CSPlayerPawn && pC_CSPlayerPawn->IsPlayerPawn() ) + { + if ( !BonePos.IsZero() ) + { + const auto* pTracedEntity = GetCL_Trace()->TraceToEntityEndPos( &BonePos ); + + if ( pTracedEntity == pC_CSPlayerPawn ) + Visible = true; + } + } + + return Visible; +} + +auto GetCL_VisibleCheck() -> CL_VisibleCheck* +{ + return &g_CL_VisibleCheck; +} diff --git a/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_VisibleCheck.hpp b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_VisibleCheck.hpp new file mode 100644 index 0000000..1b456dd --- /dev/null +++ b/Andromeda-CS2-Base/Andromeda-CS2-Base/GameClient/CL_VisibleCheck.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include + +class CCSPlayerController; +class C_CSPlayerPawn; + +class CL_VisibleCheck final +{ +public: + auto IsPlayerControllerVisible( CCSPlayerController* pCCSPlayerController ) -> bool; + auto IsPlayerPawnVisible( C_CSPlayerPawn* pC_CSPlayerPawn ) -> bool; + auto IsBoneVisible( C_CSPlayerPawn* pC_CSPlayerPawn , const Vector3& BonePos ) -> bool; +}; + +auto GetCL_VisibleCheck() -> CL_VisibleCheck*;