Finish RayTrace plugin

This commit is contained in:
SlynxCZ 2026-01-14 11:41:53 +04:00
parent 5ccf6494e1
commit cae6b08ffe
7 changed files with 115 additions and 56 deletions

View file

@ -27,16 +27,9 @@
"linux": "55 48 89 E5 41 55 49 89 CD 41 54 49 89 FC" "linux": "55 48 89 E5 41 55 49 89 CD 41 54 49 89 FC"
} }
}, },
"CBaseModelEntity_SetModel": {
"signatures": {
"library": "server",
"windows": "40 53 48 83 EC ? 48 8B D9 4C 8B C2 48 8B 0D ? ? ? ? 48 8D 54 24 ? 48 8B 01 FF 50 ? 48 8B 44 24 ? 48 8D 54 24 ? 48 8B CB 48 89 44 24 ? E8 ? ? ? ? 48 83 C4 ? 5B C3 CC CC CC CC CC 48 89 5C 24",
"linux": "55 48 89 F2 48 89 E5 53 48 89 FB 48 8D 7D ? 48 83 EC ? 48 8D 05 ? ? ? ? 48 8B 30 48 8B 06 FF 50 ? 48 8B 45 ? 48 8D 75 ? 48 89 DF 48 89 45 ? E8 ? ? ? ? 48 8B 5D ? C9 C3 CC CC CC 55"
}
},
"CNavPhysicsInterface_TraceShape": { "CNavPhysicsInterface_TraceShape": {
"offsets": { "offsets": {
"windows": 1, "windows": 5,
"linux": 5 "linux": 5
} }
}, },
@ -52,6 +45,12 @@
"linux": 190 "linux": 190
} }
}, },
"CBaseEntity_Teleport":{
"offsets": {
"windows": 168,
"linux": 167
}
},
"GameEntitySystem": { "GameEntitySystem": {
"offsets": { "offsets": {
"windows": 88, "windows": 88,

View file

@ -1,10 +1,7 @@
#pragma once #pragma once
#include "vector.h"
#include "entityinstance.h"
#include "gametrace.h"
#include "trace.h"
#include "cmodel.h"
#include <optional> #include <optional>
#include "vector.h"
#include "gametrace.h"
#define RAYTRACE_INTERFACE_VERSION "CRayTraceInterface001" #define RAYTRACE_INTERFACE_VERSION "CRayTraceInterface001"
@ -54,24 +51,117 @@ enum class InteractionLayers : uint64_t
FUNPLAY_IGNORE_PLAYER = (0x8000000000ull << 1) FUNPLAY_IGNORE_PLAYER = (0x8000000000ull << 1)
}; };
inline InteractionLayers operator|(InteractionLayers a, InteractionLayers b) constexpr InteractionLayers operator|(InteractionLayers a, InteractionLayers b)
{ {
return static_cast<InteractionLayers>( return static_cast<InteractionLayers>(
static_cast<uint64_t>(a) | static_cast<uint64_t>(b) static_cast<uint64_t>(a) | static_cast<uint64_t>(b)
); );
} }
inline InteractionLayers& operator|=(InteractionLayers& a, InteractionLayers b) constexpr InteractionLayers operator&(InteractionLayers a, InteractionLayers b)
{
return static_cast<InteractionLayers>(
static_cast<uint64_t>(a) & static_cast<uint64_t>(b)
);
}
constexpr InteractionLayers operator~(InteractionLayers a)
{
return static_cast<InteractionLayers>(
~static_cast<uint64_t>(a)
);
}
constexpr InteractionLayers& operator|=(InteractionLayers& a, InteractionLayers b)
{ {
a = a | b; a = a | b;
return a; return a;
} }
/// Custom base (0x2C3011, using this as default in my plugins)
constexpr InteractionLayers MASK_SHOT_PHYSICS =
InteractionLayers::Solid |
InteractionLayers::PlayerClip |
InteractionLayers::Window |
InteractionLayers::PassBullets |
InteractionLayers::Player |
InteractionLayers::NPC |
InteractionLayers::Physics_Prop;
/// Only hitboxes (headshots etc.)
constexpr InteractionLayers MASK_SHOT_HITBOX =
InteractionLayers::Hitboxes |
InteractionLayers::Player |
InteractionLayers::NPC;
/// Physics + hitboxes (full bullet trace)
constexpr InteractionLayers MASK_SHOT_FULL =
MASK_SHOT_PHYSICS |
InteractionLayers::Hitboxes;
/// World only (no entities)
constexpr InteractionLayers MASK_WORLD_ONLY =
InteractionLayers::Solid |
InteractionLayers::Window |
InteractionLayers::PassBullets;
/// Grenade trace
constexpr InteractionLayers MASK_GRENADE =
InteractionLayers::Solid |
InteractionLayers::Window |
InteractionLayers::Physics_Prop |
InteractionLayers::PassBullets;
/// Brush only
constexpr InteractionLayers MASK_BRUSH_ONLY =
InteractionLayers::Solid |
InteractionLayers::Window;
/// Movement (player)
constexpr InteractionLayers MASK_PLAYER_MOVE =
InteractionLayers::Solid |
InteractionLayers::Window |
InteractionLayers::PlayerClip |
InteractionLayers::PassBullets;
/// Movement (NPC)
constexpr InteractionLayers MASK_NPC_MOVE =
InteractionLayers::Solid |
InteractionLayers::Window |
InteractionLayers::NPCClip |
InteractionLayers::PassBullets;
static_assert(
static_cast<uint64_t>(MASK_SHOT_PHYSICS) == 0x2c3011,
"MASK_SHOT_PHYSICS mismatch!"
);
constexpr InteractionLayers RemovePlayers(InteractionLayers m)
{
return static_cast<InteractionLayers>(
static_cast<uint64_t>(m) &
~static_cast<uint64_t>(InteractionLayers::Player)
);
}
constexpr InteractionLayers BuildShotMask(bool includePlayers, bool includeHitboxes)
{
InteractionLayers m = MASK_SHOT_PHYSICS;
if (!includePlayers)
m = RemovePlayers(m);
if (includeHitboxes)
m |= InteractionLayers::Hitboxes;
return m;
}
struct TraceOptions struct TraceOptions
{ {
std::optional<InteractionLayers> InteractsWith{static_cast<InteractionLayers>(0x2c3011)}; std::optional<InteractionLayers> InteractsWith{ MASK_SHOT_PHYSICS };
std::optional<InteractionLayers> InteractsExclude{}; std::optional<InteractionLayers> InteractsExclude{};
bool DrawBeam{false}; bool DrawBeam{ false };
}; };
struct TraceResult struct TraceResult
@ -83,7 +173,8 @@ struct TraceResult
Vector Normal{}; Vector Normal{};
}; };
class CRayTraceInterface { class CRayTraceInterface
{
public: public:
virtual ~CRayTraceInterface() = default; virtual ~CRayTraceInterface() = default;

View file

@ -107,7 +107,7 @@ namespace RayTracePlugin
void *IPlugin::OnMetamodQuery(const char *iface, int *ret) { void *IPlugin::OnMetamodQuery(const char *iface, int *ret) {
if (strcmp(iface, RAYTRACE_INTERFACE_VERSION) == 0) { if (strcmp(iface, RAYTRACE_INTERFACE_VERSION) == 0) {
*ret = META_IFACE_OK; *ret = META_IFACE_OK;
FP_INFO("CRayTraceInterface001 accessed."); FP_INFO("{} accessed.", RAYTRACE_INTERFACE_VERSION);
return &RayTrace::g_CRayTrace; return &RayTrace::g_CRayTrace;
} }

View file

@ -13,6 +13,8 @@
namespace RayTracePlugin::RayTrace namespace RayTracePlugin::RayTrace
{ {
CRayTrace g_CRayTrace;
using TraceShapeFn = bool(*)(void* pThis, using TraceShapeFn = bool(*)(void* pThis,
Ray_t& ray, Ray_t& ray,
Vector& start, Vector& start,

View file

@ -17,12 +17,12 @@ namespace RayTracePlugin::RayTrace
: CTraceFilter(static_cast<CEntityInstance*>(entityToIgnore), : CTraceFilter(static_cast<CEntityInstance*>(entityToIgnore),
entityToIgnore ? entityToIgnore->m_hOwnerEntity.Get() : nullptr, entityToIgnore ? entityToIgnore->m_hOwnerEntity.Get() : nullptr,
entityToIgnore ? entityToIgnore->m_pCollision()->m_collisionAttribute().m_nHierarchyId() : static_cast<uint16>(0xFFFFFFFF), entityToIgnore ? entityToIgnore->m_pCollision()->m_collisionAttribute().m_nHierarchyId() : static_cast<uint16>(0xFFFFFFFF),
0x2c3011, static_cast<uint64_t>(MASK_SHOT_PHYSICS),
COLLISION_GROUP_DEFAULT, true) COLLISION_GROUP_DEFAULT, true)
{ {
} }
CTraceFilterEx() : CTraceFilter(0x2c3011, COLLISION_GROUP_DEFAULT, true) CTraceFilterEx() : CTraceFilter(static_cast<uint64_t>(MASK_SHOT_PHYSICS), COLLISION_GROUP_DEFAULT, true)
{ {
} }
}; };
@ -78,5 +78,5 @@ namespace RayTracePlugin::RayTrace
} }
}; };
inline CRayTrace g_CRayTrace; extern CRayTrace g_CRayTrace;
} }

View file

@ -44,8 +44,6 @@ namespace RayTracePlugin::Listeners {
void SourceHooks::Hook_GameFrame(bool simulating, bool bFirstTick, bool bLastTick) void SourceHooks::Hook_GameFrame(bool simulating, bool bFirstTick, bool bLastTick)
{ {
Tasks::Tick(simulating); Tasks::Tick(simulating);
if (!shared::getGlobalVars())
return;
} }
void SourceHooks::Hook_StartupServer(const GameSessionConfiguration_t& config, void SourceHooks::Hook_StartupServer(const GameSessionConfiguration_t& config,

View file

@ -30,37 +30,6 @@ RayTracePlugin
SCHEMA_FIELD(float32, m_flShadowStrength) SCHEMA_FIELD(float32, m_flShadowStrength)
void SetModel(const char* model)
{
using SetModel_t = void (*)(CBaseModelEntity*, const char*);
static SetModel_t s_SetModel = nullptr;
if (!s_SetModel)
{
SetModel_t addr =
DynLibUtils::CModule(shared::g_pServer)
.FindPattern(shared::g_pGameConfig->GetSignature("CBaseModelEntity_SetModel"))
.RCast<SetModel_t>();
if (!addr) return;
s_SetModel = addr;
}
s_SetModel(this, model);
}
void SetBodyGroup(std::string name, int value)
{
char bodygroupStr[64];
g_SMAPI->Format(bodygroupStr, sizeof(bodygroupStr), "%s,%i", name.c_str(), value);
this->AcceptInput(
"SetBodyGroup",
this,
this,
bodygroupStr
);
}
CUtlSymbolLarge GetModelName() CUtlSymbolLarge GetModelName()
{ {
if (m_CBodyComponent == nullptr) return CUtlSymbolLarge(); if (m_CBodyComponent == nullptr) return CUtlSymbolLarge();