diff --git a/README.md b/README.md index 08335ab..0a12ca7 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ public: virtual bool TraceShape( const Vector* pOrigin, const QAngle* pViewAngles, - CBaseEntity* pIgnorePlayer, + CBaseEntity* pIgnoreEntity, const TraceOptions* pOpts, TraceResult* pOutResult ) = 0; @@ -57,7 +57,17 @@ public: virtual bool TraceEndShape( const Vector* pOrigin, const Vector* pEndOrigin, - CBaseEntity* pIgnorePlayer, + CBaseEntity* pIgnoreEntity, + const TraceOptions* pOpts, + TraceResult* pOutResult + ) = 0; + + virtual bool TraceHullShape( + const Vector* pVecStart, + const Vector* pVecEnd, + const Vector* pHullMins, + const Vector* pHullMaxs, + CBaseEntity* pIgnoreEntity, const TraceOptions* pOpts, TraceResult* pOutResult ) = 0; @@ -196,10 +206,10 @@ public void DoTrace(CCSPlayerController player) Due to C++ ABI differences: -| Platform | TraceShape index | TraceEndShape index | -| ------------------- | ---------------- | ------------------- | -| Linux (Itanium ABI) | 2 | 3 | -| Windows (MSVC ABI) | 1 | 2 | +| Platform | TraceShape index | TraceEndShape index | TraceHullShape index | +| ------------------- | ---------------- | ------------------- |----------------------| +| Linux (Itanium ABI) | 2 | 3 | 4 | +| Windows (MSVC ABI) | 1 | 2 | 3 | `public/Example.cs` applies Itanium offsets by default. diff --git a/public/CRayTraceInterface.h b/public/CRayTraceInterface.h index 908e679..61c8e02 100644 --- a/public/CRayTraceInterface.h +++ b/public/CRayTraceInterface.h @@ -136,6 +136,7 @@ static_assert( struct TraceOptions { + uint64_t InteractsAs = 0; uint64_t InteractsWith = static_cast(MASK_SHOT_PHYSICS); uint64_t InteractsExclude = 0; int DrawBeam = 0; @@ -158,7 +159,7 @@ public: virtual bool TraceShape( const Vector* origin, const QAngle* viewangles, - CBaseEntity* ignorePlayer, + CBaseEntity* ignoreEntity, const TraceOptions* opts, TraceResult* outResult ) = 0; @@ -166,7 +167,17 @@ public: virtual bool TraceEndShape( const Vector* origin, const Vector* endOrigin, - CBaseEntity* ignorePlayer, + CBaseEntity* ignoreEntity, + const TraceOptions* opts, + TraceResult* outResult + ) = 0; + + virtual bool TraceHullShape( + const Vector* vecStart, + const Vector* vecEnd, + const Vector* hullMins, + const Vector* hullMaxs, + CBaseEntity* ignoreEntity, const TraceOptions* opts, TraceResult* outResult ) = 0; diff --git a/public/Example.cs b/public/Example.cs index 1e05f3a..c1578e5 100644 --- a/public/Example.cs +++ b/public/Example.cs @@ -62,22 +62,25 @@ namespace RayTrace MASK_NPC_MOVE = Solid | Window | NPCClip | PassBullets } - [StructLayout(LayoutKind.Explicit, Size = 24)] + [StructLayout(LayoutKind.Explicit, Size = 32)] public struct TraceOptions { - [FieldOffset(0)] public ulong InteractsWith; - [FieldOffset(8)] public ulong InteractsExclude; - [FieldOffset(16)] public int DrawBeam; + [FieldOffset(0)] public ulong InteractsAs; + [FieldOffset(8)] public ulong InteractsWith; + [FieldOffset(16)] public ulong InteractsExclude; + [FieldOffset(24)] public int DrawBeam; public TraceOptions() { + InteractsAs = 0; InteractsWith = (ulong)InteractionLayers.MASK_SHOT_PHYSICS; InteractsExclude = 0; DrawBeam = 0; } - public TraceOptions(InteractionLayers interactsWith, InteractionLayers interactsExclude = 0, bool drawBeam = false) + public TraceOptions(InteractionLayers interactsAs, InteractionLayers interactsWith, InteractionLayers interactsExclude = 0, bool drawBeam = false) { + InteractsAs = (ulong)interactsAs; InteractsWith = (ulong)interactsWith; InteractsExclude = (ulong)interactsExclude; DrawBeam = drawBeam ? 1 : 0; @@ -111,6 +114,7 @@ namespace RayTrace private static Func? _traceShape; private static Func? _traceEndShape; + private static Func? _traceHullShape; public static void Init() { @@ -127,6 +131,7 @@ namespace RayTrace { _traceShape = VirtualFunction.Create(g_pRayTraceHandle, 2); _traceEndShape = VirtualFunction.Create(g_pRayTraceHandle, 3); + _traceHullShape = VirtualFunction.Create(g_pRayTraceHandle, 4); } public static unsafe bool TraceShape(Vector origin, QAngle angles, CBaseEntity? ignoreEntity, TraceOptions options, out TraceResult result) @@ -170,5 +175,28 @@ namespace RayTrace result = resultBuffer; return success; } + + public static unsafe bool TraceHullShape(Vector vecStart, Vector vecEnd, Vector hullMins, Vector hullMaxs, CBaseEntity? ignoreEntity, TraceOptions options, out TraceResult result) + { + result = default; + + if (!g_bRayTraceLoaded || g_pRayTraceHandle == nint.Zero) + return false; + + TraceResult resultBuffer = default; + TraceOptions optionsBuffer = options; + + bool success = _traceHullShape!(g_pRayTraceHandle, + vecStart.Handle, + vecEnd.Handle, + hullMins.Handle, + hullMaxs.Handle, + ignoreEntity?.Handle ?? nint.Zero, + (nint)(&optionsBuffer), + (nint)(&resultBuffer)); + + result = resultBuffer; + return success; + } } } diff --git a/src/RayTrace.cpp b/src/RayTrace.cpp index dc6e4a3..865bf0a 100644 --- a/src/RayTrace.cpp +++ b/src/RayTrace.cpp @@ -82,7 +82,7 @@ namespace RayTracePlugin::RayTrace std::optional TraceShape( const Vector& origin, const QAngle& viewangles, - CBaseEntity* ignorePlayer, + CBaseEntity* ignoreEntity, const TraceOptions* opts) { Vector forward; @@ -93,14 +93,18 @@ namespace RayTracePlugin::RayTrace origin.z + forward.z * 8192.f }; - CTraceFilterEx filter = ignorePlayer ? CTraceFilterEx(ignorePlayer) : CTraceFilterEx(); + CTraceFilterEx filter = ignoreEntity ? CTraceFilterEx(ignoreEntity) : CTraceFilterEx(); + filter.m_nInteractsAs = 0; filter.m_nInteractsWith = static_cast(MASK_SHOT_PHYSICS); filter.m_nInteractsExclude = 0; if (opts) { - if (opts->InteractsWith != 0) + if (opts->InteractsAs != 0) + filter.m_nInteractsAs = opts->InteractsAs; + + if (opts->InteractsWith != static_cast(MASK_SHOT_PHYSICS)) filter.m_nInteractsWith = opts->InteractsWith; if (opts->InteractsExclude != 0) @@ -122,17 +126,21 @@ namespace RayTracePlugin::RayTrace std::optional TraceEndShape( const Vector& origin, const Vector& endOrigin, - CBaseEntity* ignorePlayer, + CBaseEntity* ignoreEntity, const TraceOptions* opts) { - CTraceFilterEx filter = ignorePlayer ? CTraceFilterEx(ignorePlayer) : CTraceFilterEx(); + CTraceFilterEx filter = ignoreEntity ? CTraceFilterEx(ignoreEntity) : CTraceFilterEx(); + filter.m_nInteractsAs = 0; filter.m_nInteractsWith = static_cast(MASK_SHOT_PHYSICS); filter.m_nInteractsExclude = 0; if (opts) { - if (opts->InteractsWith != 0) + if (opts->InteractsAs != 0) + filter.m_nInteractsAs = opts->InteractsAs; + + if (opts->InteractsWith != static_cast(MASK_SHOT_PHYSICS)) filter.m_nInteractsWith = opts->InteractsWith; if (opts->InteractsExclude != 0) @@ -150,4 +158,37 @@ namespace RayTracePlugin::RayTrace return res; } + + std::optional TraceHullShape(const Vector &vecStart, const Vector &vecEnd, const Vector &hullMins, + const Vector &hullMaxs, CBaseEntity *ignoreEntity, const TraceOptions *opts) { + CTraceFilterEx filter = ignoreEntity ? CTraceFilterEx(ignoreEntity) : CTraceFilterEx(); + + filter.m_nInteractsAs = 0; + filter.m_nInteractsWith = static_cast(MASK_SHOT_PHYSICS); + filter.m_nInteractsExclude = 0; + + if (opts) + { + if (opts->InteractsAs != 0) + filter.m_nInteractsAs = opts->InteractsAs; + + if (opts->InteractsWith != static_cast(MASK_SHOT_PHYSICS)) + filter.m_nInteractsWith = opts->InteractsWith; + + if (opts->InteractsExclude != 0) + filter.m_nInteractsExclude = opts->InteractsExclude; + } + + Ray_t ray; + ray.Init(hullMins, hullMaxs); + auto res = TraceShapeEx(vecStart, vecEnd, filter, ray); + + if (opts && opts->DrawBeam) + { + Color col = res.has_value() ? colors::Red().ToValveColor() : colors::Green().ToValveColor(); + DrawBeam(vecStart, res ? res->EndPos : vecEnd, col); + } + + return res; + } } diff --git a/src/RayTrace.h b/src/RayTrace.h index f7c156a..9c73d73 100644 --- a/src/RayTrace.h +++ b/src/RayTrace.h @@ -32,13 +32,21 @@ namespace RayTracePlugin::RayTrace std::optional TraceShape( const Vector& origin, const QAngle& viewangles, - CBaseEntity* ignorePlayer = nullptr, + CBaseEntity* ignoreEntity = nullptr, const TraceOptions* opts = nullptr); std::optional TraceEndShape( const Vector& origin, const Vector& endOrigin, - CBaseEntity* ignorePlayer = nullptr, + CBaseEntity* ignoreEntity = nullptr, + const TraceOptions* opts = nullptr); + + std::optional TraceHullShape( + const Vector& vecStart, + const Vector& vecEnd, + const Vector& hullMins, + const Vector& hullMaxs, + CBaseEntity* ignoreEntity = nullptr, const TraceOptions* opts = nullptr); std::optional TraceShapeEx( @@ -53,11 +61,11 @@ namespace RayTracePlugin::RayTrace bool TraceShape( const Vector* origin, const QAngle* viewangles, - CBaseEntity* ignorePlayer, + CBaseEntity* ignoreEntity, const TraceOptions* opts, TraceResult* outResult) override { - auto result = RayTrace::TraceShape(*origin, *viewangles, ignorePlayer, opts); + auto result = RayTrace::TraceShape(*origin, *viewangles, ignoreEntity, opts); if (!result.has_value()) return false; @@ -68,11 +76,28 @@ namespace RayTracePlugin::RayTrace bool TraceEndShape( const Vector* origin, const Vector* endOrigin, - CBaseEntity* ignorePlayer, + CBaseEntity* ignoreEntity, const TraceOptions* opts, TraceResult* outResult) override { - auto result = RayTrace::TraceEndShape(*origin, *endOrigin, ignorePlayer, opts); + auto result = RayTrace::TraceEndShape(*origin, *endOrigin, ignoreEntity, opts); + if (!result.has_value()) + return false; + + *outResult = result.value(); + return true; + } + + bool TraceHullShape( + const Vector* vecStart, + const Vector* vecEnd, + const Vector* hullMins, + const Vector* hullMaxs, + CBaseEntity* ignoreEntity, + const TraceOptions* opts, + TraceResult* outResult) override + { + auto result = RayTrace::TraceHullShape(*vecStart, *vecEnd, *hullMins, *hullMaxs, ignoreEntity, opts); if (!result.has_value()) return false;