Port navmesh debug renderer from primedev (#626)
Adds support for rendering navmeshes in-game using debug overlay Cherry-picked from primedev, originally written by F1F7Y Co-authored-by: F1F7Y <filip.bartos07@proton.me> Co-authored-by: Maya <11448698+RoyalBlue1@users.noreply.github.com>
This commit is contained in:
parent
edf013952c
commit
73262ca616
|
@ -16,6 +16,7 @@ add_library(
|
|||
"client/debugoverlay.cpp"
|
||||
"client/demofixes.cpp"
|
||||
"client/diskvmtfixes.cpp"
|
||||
"client/entity_client_tools.cpp"
|
||||
"client/languagehooks.cpp"
|
||||
"client/latencyflex.cpp"
|
||||
"client/localchatwriter.cpp"
|
||||
|
@ -41,7 +42,9 @@ add_library(
|
|||
"core/math/bits.h"
|
||||
"core/math/color.cpp"
|
||||
"core/math/color.h"
|
||||
"core/math/math_pfns.h"
|
||||
"core/math/vector.h"
|
||||
"core/math/vplane.h"
|
||||
"core/hooks.cpp"
|
||||
"core/hooks.h"
|
||||
"core/macros.h"
|
||||
|
@ -53,6 +56,8 @@ add_library(
|
|||
"core/sourceinterface.h"
|
||||
"core/tier0.cpp"
|
||||
"core/tier0.h"
|
||||
"core/tier1.cpp"
|
||||
"core/tier1.h"
|
||||
"dedicated/dedicated.cpp"
|
||||
"dedicated/dedicated.h"
|
||||
"dedicated/dedicatedlogtoclient.cpp"
|
||||
|
@ -116,6 +121,10 @@ add_library(
|
|||
"server/auth/serverauthentication.cpp"
|
||||
"server/auth/serverauthentication.h"
|
||||
"server/alltalk.cpp"
|
||||
"server/ai_helper.cpp"
|
||||
"server/ai_helper.h"
|
||||
"server/ai_navmesh.cpp"
|
||||
"server/ai_navmesh.h"
|
||||
"server/buildainfile.cpp"
|
||||
"server/r2server.cpp"
|
||||
"server/r2server.h"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "toolframework/itoolentity.h"
|
||||
|
||||
inline IClientTools* g_pClientTools = nullptr;
|
|
@ -1,6 +1,9 @@
|
|||
#include "debugoverlay.h"
|
||||
|
||||
#include "dedicated/dedicated.h"
|
||||
#include "core/convar/cvar.h"
|
||||
#include "core/math/vector.h"
|
||||
#include "server/ai_helper.h"
|
||||
|
||||
AUTOHOOK_INIT()
|
||||
|
||||
|
@ -122,48 +125,13 @@ struct OverlaySphere_t : public OverlayBase_t
|
|||
bool m_bWireframe;
|
||||
};
|
||||
|
||||
typedef bool (*OverlayBase_t__IsDeadType)(OverlayBase_t* a1);
|
||||
static OverlayBase_t__IsDeadType OverlayBase_t__IsDead;
|
||||
typedef void (*OverlayBase_t__DestroyOverlayType)(OverlayBase_t* a1);
|
||||
static OverlayBase_t__DestroyOverlayType OverlayBase_t__DestroyOverlay;
|
||||
static bool (*OverlayBase_t__IsDead)(OverlayBase_t* a1);
|
||||
static void (*OverlayBase_t__DestroyOverlay)(OverlayBase_t* a1);
|
||||
|
||||
static ConVar* Cvar_enable_debug_overlays;
|
||||
|
||||
LPCRITICAL_SECTION s_OverlayMutex;
|
||||
|
||||
// Render Line
|
||||
typedef void (*RenderLineType)(const Vector3& v1, const Vector3& v2, Color c, bool bZBuffer);
|
||||
static RenderLineType RenderLine;
|
||||
|
||||
// Render box
|
||||
typedef void (*RenderBoxType)(
|
||||
const Vector3& vOrigin, const QAngle& angles, const Vector3& vMins, const Vector3& vMaxs, Color c, bool bZBuffer, bool bInsideOut);
|
||||
static RenderBoxType RenderBox;
|
||||
|
||||
// Render wireframe box
|
||||
static RenderBoxType RenderWireframeBox;
|
||||
|
||||
// Render swept box
|
||||
typedef void (*RenderWireframeSweptBoxType)(
|
||||
const Vector3& vStart, const Vector3& vEnd, const QAngle& angles, const Vector3& vMins, const Vector3& vMaxs, Color c, bool bZBuffer);
|
||||
RenderWireframeSweptBoxType RenderWireframeSweptBox;
|
||||
|
||||
// Render Triangle
|
||||
typedef void (*RenderTriangleType)(const Vector3& p1, const Vector3& p2, const Vector3& p3, Color c, bool bZBuffer);
|
||||
static RenderTriangleType RenderTriangle;
|
||||
|
||||
// Render Axis
|
||||
typedef void (*RenderAxisType)(const Vector3& vOrigin, float flScale, bool bZBuffer);
|
||||
static RenderAxisType RenderAxis;
|
||||
|
||||
// I dont know
|
||||
typedef void (*RenderUnknownType)(const Vector3& vUnk, float flUnk, bool bUnk);
|
||||
static RenderUnknownType RenderUnknown;
|
||||
|
||||
// Render Sphere
|
||||
typedef void (*RenderSphereType)(const Vector3& vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer);
|
||||
static RenderSphereType RenderSphere;
|
||||
|
||||
OverlayBase_t** s_pOverlays;
|
||||
|
||||
int* g_nRenderTickCount;
|
||||
|
@ -317,6 +285,11 @@ void, __fastcall, (bool bRender))
|
|||
}
|
||||
}
|
||||
|
||||
if (bRender && Cvar_enable_debug_overlays->GetBool())
|
||||
{
|
||||
g_pAIHelper->DrawNavmeshPolys();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(s_OverlayMutex);
|
||||
}
|
||||
|
||||
|
@ -324,17 +297,17 @@ ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", DebugOverlay, ConVar, (CModule module)
|
|||
{
|
||||
AUTOHOOK_DISPATCH()
|
||||
|
||||
OverlayBase_t__IsDead = module.Offset(0xACAC0).RCast<OverlayBase_t__IsDeadType>();
|
||||
OverlayBase_t__DestroyOverlay = module.Offset(0xAB680).RCast<OverlayBase_t__DestroyOverlayType>();
|
||||
OverlayBase_t__IsDead = module.Offset(0xACAC0).RCast<decltype(OverlayBase_t__IsDead)>();
|
||||
OverlayBase_t__DestroyOverlay = module.Offset(0xAB680).RCast<decltype(OverlayBase_t__DestroyOverlay)>();
|
||||
|
||||
RenderLine = module.Offset(0x192A70).RCast<RenderLineType>();
|
||||
RenderBox = module.Offset(0x192520).RCast<RenderBoxType>();
|
||||
RenderWireframeBox = module.Offset(0x193DA0).RCast<RenderBoxType>();
|
||||
RenderWireframeSweptBox = module.Offset(0x1945A0).RCast<RenderWireframeSweptBoxType>();
|
||||
RenderTriangle = module.Offset(0x193940).RCast<RenderTriangleType>();
|
||||
RenderAxis = module.Offset(0x1924D0).RCast<RenderAxisType>();
|
||||
RenderSphere = module.Offset(0x194170).RCast<RenderSphereType>();
|
||||
RenderUnknown = module.Offset(0x1924E0).RCast<RenderUnknownType>();
|
||||
RenderLine = module.Offset(0x192A70).RCast<decltype(RenderLine)>();
|
||||
RenderBox = module.Offset(0x192520).RCast<decltype(RenderBox)>();
|
||||
RenderWireframeBox = module.Offset(0x193DA0).RCast<decltype(RenderWireframeBox)>();
|
||||
RenderWireframeSweptBox = module.Offset(0x1945A0).RCast<decltype(RenderWireframeSweptBox)>();
|
||||
RenderTriangle = module.Offset(0x193940).RCast<decltype(RenderTriangle)>();
|
||||
RenderAxis = module.Offset(0x1924D0).RCast<decltype(RenderAxis)>();
|
||||
RenderSphere = module.Offset(0x194170).RCast<decltype(RenderSphere)>();
|
||||
RenderUnknown = module.Offset(0x1924E0).RCast<decltype(RenderUnknown)>();
|
||||
|
||||
s_OverlayMutex = module.Offset(0x10DB0A38).RCast<LPCRITICAL_SECTION>();
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
// Render Line
|
||||
inline void (*RenderLine)(const Vector3& v1, const Vector3& v2, Color c, bool bZBuffer);
|
||||
|
||||
// Render box
|
||||
inline void (*RenderBox)(
|
||||
const Vector3& vOrigin, const QAngle& angles, const Vector3& vMins, const Vector3& vMaxs, Color c, bool bZBuffer, bool bInsideOut);
|
||||
|
||||
// Render wireframe box
|
||||
inline void (*RenderWireframeBox)(
|
||||
const Vector3& vOrigin, const QAngle& angles, const Vector3& vMins, const Vector3& vMaxs, Color c, bool bZBuffer, bool bInsideOut);
|
||||
|
||||
// Render swept box
|
||||
inline void (*RenderWireframeSweptBox)(
|
||||
const Vector3& vStart, const Vector3& vEnd, const QAngle& angles, const Vector3& vMins, const Vector3& vMaxs, Color c, bool bZBuffer);
|
||||
|
||||
// Render Triangle
|
||||
inline void (*RenderTriangle)(const Vector3& p1, const Vector3& p2, const Vector3& p3, Color c, bool bZBuffer);
|
||||
|
||||
// Render Axis
|
||||
inline void (*RenderAxis)(const Vector3& vOrigin, float flScale, bool bZBuffer);
|
||||
|
||||
// I dont know
|
||||
inline void (*RenderUnknown)(const Vector3& vUnk, float flUnk, bool bUnk);
|
||||
|
||||
// Render Sphere
|
||||
inline void (*RenderSphere)(const Vector3& vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer);
|
|
@ -0,0 +1,13 @@
|
|||
#include "toolframework/itoolentity.h"
|
||||
#include "client/cdll_client_int.h"
|
||||
#include "core/tier1.h"
|
||||
|
||||
class CClientTools : public IClientTools
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
ON_DLL_LOAD("client.dll", ClientClientTools, (CModule module))
|
||||
{
|
||||
g_pClientTools = Sys_GetFactoryPtr("client.dll", "VCLIENTTOOLS001").RCast<IClientTools*>();
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
inline float FastSqrt(float x)
|
||||
{
|
||||
__m128 root = _mm_sqrt_ss(_mm_load_ss(&x));
|
||||
return *(reinterpret_cast<float*>(&root));
|
||||
}
|
|
@ -1,47 +1,331 @@
|
|||
#include <cmath>
|
||||
|
||||
#pragma once
|
||||
|
||||
union Vector3
|
||||
#include "bits.h"
|
||||
#include "math_pfns.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#define DEG2RAD(a) (a) * (3.14159265358979323846f / 180.0f)
|
||||
#define RAD2DEG(a) (a) * (180.0f / 3.14159265358979323846f)
|
||||
|
||||
class Vector3
|
||||
{
|
||||
struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
public:
|
||||
float x, y, z;
|
||||
|
||||
float raw[3];
|
||||
Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
|
||||
Vector3(float _f) : x(_f), y(_f), z(_f) {}
|
||||
Vector3() : x(0.0f), y(0.0f), z(0.0f) {}
|
||||
|
||||
void MakeValid()
|
||||
inline bool IsValid()
|
||||
{
|
||||
for (auto& fl : raw)
|
||||
if (std::isnan(fl))
|
||||
fl = 0;
|
||||
return IsFinite(x) && IsFinite(y) && IsFinite(z);
|
||||
}
|
||||
|
||||
inline void Init(float fX = 0.0f, float fY = 0.0f, float fZ = 0.0f)
|
||||
{
|
||||
x = fX;
|
||||
y = fY;
|
||||
z = fZ;
|
||||
}
|
||||
|
||||
inline float Length()
|
||||
{
|
||||
return FastSqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
inline float DistTo(const Vector3& vOther)
|
||||
{
|
||||
Vector3 vDelta;
|
||||
vDelta.x = vOther.x - x;
|
||||
vDelta.y = vOther.y - y;
|
||||
vDelta.z = vOther.z - z;
|
||||
|
||||
return vDelta.Length();
|
||||
}
|
||||
|
||||
float Dot(const Vector3& vOther) const
|
||||
{
|
||||
return x * vOther.x + y * vOther.y + z * vOther.z;
|
||||
}
|
||||
|
||||
// Cross product between two vectors.
|
||||
Vector3 Cross(const Vector3& vOther) const;
|
||||
|
||||
void Normalize();
|
||||
|
||||
bool operator==(const Vector3& v) const;
|
||||
bool operator!=(const Vector3& v) const;
|
||||
|
||||
FORCEINLINE Vector3& operator+=(const Vector3& v);
|
||||
FORCEINLINE Vector3& operator-=(const Vector3& v);
|
||||
FORCEINLINE Vector3& operator*=(const Vector3& v);
|
||||
FORCEINLINE Vector3& operator*=(float s);
|
||||
FORCEINLINE Vector3& operator/=(const Vector3& v);
|
||||
FORCEINLINE Vector3& operator/=(float s);
|
||||
FORCEINLINE Vector3& operator+=(float fl); ///< broadcast add
|
||||
FORCEINLINE Vector3& operator-=(float fl);
|
||||
|
||||
// arithmetic operations
|
||||
Vector3 operator-(void) const;
|
||||
|
||||
Vector3 operator+(const Vector3& v) const;
|
||||
Vector3 operator-(const Vector3& v) const;
|
||||
Vector3 operator*(const Vector3& v) const;
|
||||
Vector3 operator/(const Vector3& v) const;
|
||||
Vector3 operator*(float fl) const;
|
||||
Vector3 operator/(float fl) const;
|
||||
};
|
||||
|
||||
FORCEINLINE void VectorAdd(const Vector3& a, const Vector3& b, Vector3& result);
|
||||
FORCEINLINE void VectorSubtract(const Vector3& a, const Vector3& b, Vector3& result);
|
||||
FORCEINLINE void VectorMultiply(const Vector3& a, float b, Vector3& result);
|
||||
FORCEINLINE void VectorMultiply(const Vector3& a, const Vector3& b, Vector3& result);
|
||||
FORCEINLINE void VectorDivide(const Vector3& a, float b, Vector3& result);
|
||||
FORCEINLINE void VectorDivide(const Vector3& a, const Vector3& b, Vector3& result);
|
||||
|
||||
inline bool Vector3::operator==(const Vector3& src) const
|
||||
{
|
||||
return (src.x == x) && (src.y == y) && (src.z == z);
|
||||
}
|
||||
|
||||
inline bool Vector3::operator!=(const Vector3& src) const
|
||||
{
|
||||
return (src.x != x) || (src.y != y) || (src.z != z);
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator+=(const Vector3& v)
|
||||
{
|
||||
x += v.x;
|
||||
y += v.y;
|
||||
z += v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator-=(const Vector3& v)
|
||||
{
|
||||
x -= v.x;
|
||||
y -= v.y;
|
||||
z -= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator*=(float fl)
|
||||
{
|
||||
x *= fl;
|
||||
y *= fl;
|
||||
z *= fl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator*=(const Vector3& v)
|
||||
{
|
||||
x *= v.x;
|
||||
y *= v.y;
|
||||
z *= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// this ought to be an opcode.
|
||||
FORCEINLINE Vector3& Vector3::operator+=(float fl)
|
||||
{
|
||||
x += fl;
|
||||
y += fl;
|
||||
z += fl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator-=(float fl)
|
||||
{
|
||||
x -= fl;
|
||||
y -= fl;
|
||||
z -= fl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator/=(float fl)
|
||||
{
|
||||
float oofl = 1.0f / fl;
|
||||
x *= oofl;
|
||||
y *= oofl;
|
||||
z *= oofl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE Vector3& Vector3::operator/=(const Vector3& v)
|
||||
{
|
||||
x /= v.x;
|
||||
y /= v.y;
|
||||
z /= v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator-(void) const
|
||||
{
|
||||
return Vector3(-x, -y, -z);
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator+(const Vector3& v) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorAdd(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator-(const Vector3& v) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorSubtract(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator*(float fl) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorMultiply(*this, fl, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator*(const Vector3& v) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorMultiply(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator/(float fl) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorDivide(*this, fl, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator/(const Vector3& v) const
|
||||
{
|
||||
Vector3 res;
|
||||
VectorDivide(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector3 operator*(float fl, const Vector3& v)
|
||||
{
|
||||
return v * fl;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::Cross(const Vector3& vOther) const
|
||||
{
|
||||
return Vector3(y * vOther.z - z * vOther.y, z * vOther.x - x * vOther.z, x * vOther.y - y * vOther.x);
|
||||
}
|
||||
|
||||
inline void Vector3::Normalize()
|
||||
{
|
||||
float fLen = Length();
|
||||
x /= fLen;
|
||||
y /= fLen;
|
||||
z /= fLen;
|
||||
}
|
||||
|
||||
inline Vector3 StringToVector(char* pString)
|
||||
{
|
||||
Vector3 vRet;
|
||||
|
||||
int length = 0;
|
||||
while (pString[length])
|
||||
{
|
||||
if ((pString[length] == '<') || (pString[length] == '>'))
|
||||
pString[length] = '\0';
|
||||
length++;
|
||||
}
|
||||
|
||||
int startOfFloat = 1;
|
||||
int currentIndex = 1;
|
||||
|
||||
while (pString[currentIndex] && (pString[currentIndex] != ','))
|
||||
currentIndex++;
|
||||
pString[currentIndex] = '\0';
|
||||
vRet.x = std::stof(&pString[startOfFloat]);
|
||||
startOfFloat = ++currentIndex;
|
||||
|
||||
while (pString[currentIndex] && (pString[currentIndex] != ','))
|
||||
currentIndex++;
|
||||
pString[currentIndex] = '\0';
|
||||
vRet.y = std::stof(&pString[startOfFloat]);
|
||||
startOfFloat = ++currentIndex;
|
||||
|
||||
while (pString[currentIndex] && (pString[currentIndex] != ','))
|
||||
currentIndex++;
|
||||
pString[currentIndex] = '\0';
|
||||
vRet.z = std::stof(&pString[startOfFloat]);
|
||||
startOfFloat = ++currentIndex;
|
||||
|
||||
return vRet;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorAdd(const Vector3& a, const Vector3& b, Vector3& c)
|
||||
{
|
||||
c.x = a.x + b.x;
|
||||
c.y = a.y + b.y;
|
||||
c.z = a.z + b.z;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorSubtract(const Vector3& a, const Vector3& b, Vector3& c)
|
||||
{
|
||||
c.x = a.x - b.x;
|
||||
c.y = a.y - b.y;
|
||||
c.z = a.z - b.z;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorMultiply(const Vector3& a, float b, Vector3& c)
|
||||
{
|
||||
c.x = a.x * b;
|
||||
c.y = a.y * b;
|
||||
c.z = a.z * b;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorMultiply(const Vector3& a, const Vector3& b, Vector3& c)
|
||||
{
|
||||
c.x = a.x * b.x;
|
||||
c.y = a.y * b.y;
|
||||
c.z = a.z * b.z;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorDivide(const Vector3& a, float b, Vector3& c)
|
||||
{
|
||||
float oob = 1.0f / b;
|
||||
c.x = a.x * oob;
|
||||
c.y = a.y * oob;
|
||||
c.z = a.z * oob;
|
||||
}
|
||||
|
||||
FORCEINLINE void VectorDivide(const Vector3& a, const Vector3& b, Vector3& c)
|
||||
{
|
||||
c.x = a.x / b.x;
|
||||
c.y = a.y / b.y;
|
||||
c.z = a.z / b.z;
|
||||
}
|
||||
|
||||
class QAngle
|
||||
{
|
||||
public:
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
QAngle(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
|
||||
QAngle(float _f) : x(_f), y(_f), z(_f) {}
|
||||
QAngle() : x(0.0f), y(0.0f), z(0.0f) {}
|
||||
|
||||
Vector3 GetNormal() const;
|
||||
|
||||
// todo: more operators maybe
|
||||
bool operator==(const Vector3& other)
|
||||
bool operator==(const QAngle& other)
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
};
|
||||
|
||||
union QAngle
|
||||
inline Vector3 QAngle::GetNormal() const
|
||||
{
|
||||
struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
float raw[4];
|
||||
|
||||
// todo: more operators maybe
|
||||
bool operator==(const QAngle& other)
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z && w == other.w;
|
||||
}
|
||||
};
|
||||
Vector3 ret(cos(DEG2RAD(y)), sin(DEG2RAD(y)), -sin(DEG2RAD(x)));
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
#pragma once
|
||||
|
||||
typedef int SideType;
|
||||
|
||||
// Used to represent sides of things like planes.
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
|
||||
#define VP_EPSILON 0.01f
|
||||
|
||||
class VPlane
|
||||
{
|
||||
public:
|
||||
VPlane();
|
||||
VPlane(const Vector3& vNormal, float dist);
|
||||
VPlane(const Vector3& vPoint, const QAngle& ang);
|
||||
|
||||
void Init(const Vector3& vNormal, float dist);
|
||||
|
||||
// Return the distance from the point to the plane.
|
||||
float DistTo(const Vector3& vVec) const;
|
||||
|
||||
// Copy.
|
||||
VPlane& operator=(const VPlane& thePlane);
|
||||
|
||||
// Returns SIDE_ON, SIDE_FRONT, or SIDE_BACK.
|
||||
// The epsilon for SIDE_ON can be passed in.
|
||||
SideType GetPointSide(const Vector3& vPoint, float sideEpsilon = VP_EPSILON) const;
|
||||
|
||||
// Returns SIDE_FRONT or SIDE_BACK.
|
||||
SideType GetPointSideExact(const Vector3& vPoint) const;
|
||||
|
||||
// Get a point on the plane (normal*dist).
|
||||
Vector3 GetPointOnPlane() const;
|
||||
|
||||
// Snap the specified point to the plane (along the plane's normal).
|
||||
Vector3 SnapPointToPlane(const Vector3& vPoint) const;
|
||||
|
||||
public:
|
||||
Vector3 m_Normal;
|
||||
float m_Dist;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inlines.
|
||||
//-----------------------------------------------------------------------------
|
||||
inline VPlane::VPlane() {}
|
||||
|
||||
inline VPlane::VPlane(const Vector3& vNormal, float dist)
|
||||
{
|
||||
m_Normal = vNormal;
|
||||
m_Dist = dist;
|
||||
}
|
||||
|
||||
inline VPlane::VPlane(const Vector3& vPoint, const QAngle& ang)
|
||||
{
|
||||
m_Normal = ang.GetNormal();
|
||||
m_Dist = vPoint.x * m_Normal.x + vPoint.y * m_Normal.y + vPoint.z * m_Normal.z;
|
||||
}
|
||||
|
||||
inline void VPlane::Init(const Vector3& vNormal, float dist)
|
||||
{
|
||||
m_Normal = vNormal;
|
||||
m_Dist = dist;
|
||||
}
|
||||
|
||||
inline float VPlane::DistTo(const Vector3& vVec) const
|
||||
{
|
||||
return vVec.Dot(m_Normal) - m_Dist;
|
||||
}
|
||||
|
||||
inline VPlane& VPlane::operator=(const VPlane& thePlane)
|
||||
{
|
||||
m_Normal = thePlane.m_Normal;
|
||||
m_Dist = thePlane.m_Dist;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3 VPlane::GetPointOnPlane() const
|
||||
{
|
||||
return m_Normal * m_Dist;
|
||||
}
|
||||
|
||||
inline Vector3 VPlane::SnapPointToPlane(const Vector3& vPoint) const
|
||||
{
|
||||
return vPoint - m_Normal * DistTo(vPoint);
|
||||
}
|
||||
|
||||
inline SideType VPlane::GetPointSide(const Vector3& vPoint, float sideEpsilon) const
|
||||
{
|
||||
float fDist;
|
||||
|
||||
fDist = DistTo(vPoint);
|
||||
if (fDist >= sideEpsilon)
|
||||
return SIDE_FRONT;
|
||||
else if (fDist <= -sideEpsilon)
|
||||
return SIDE_BACK;
|
||||
else
|
||||
return SIDE_ON;
|
||||
}
|
||||
|
||||
inline SideType VPlane::GetPointSideExact(const Vector3& vPoint) const
|
||||
{
|
||||
return DistTo(vPoint) > 0.0f ? SIDE_FRONT : SIDE_BACK;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#include "tier1.h"
|
||||
|
||||
// Note: this file is tier1/interface.cpp in primedev, but given that tier0 is yet to be split
|
||||
// I am following the existing "pattern" and putting this here
|
||||
|
||||
CMemoryAddress Sys_GetFactoryPtr(const std::string& svModuleName, const std::string& svFactoryName)
|
||||
{
|
||||
HMODULE hModule = GetModuleHandleA(svModuleName.c_str());
|
||||
|
||||
if (!hModule)
|
||||
{
|
||||
spdlog::error("Failed to get module handle of '{}'!", svModuleName.c_str());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
CreateInterfaceFn fnCreateInterface = reinterpret_cast<CreateInterfaceFn>(GetProcAddress(hModule, CREATEINTERFACE_PROCNAME));
|
||||
|
||||
return fnCreateInterface(svFactoryName.c_str(), NULL);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
// Note: this file is tier1/interface.h in primedev, but given that tier0 is yet to be split
|
||||
// I am following the existing "pattern" and putting this here
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
#define CREATEINTERFACE_PROCNAME "CreateInterface"
|
||||
|
||||
typedef void* (*CreateInterfaceFn)(const char* pName, int* pReturnCode);
|
||||
|
||||
CMemoryAddress Sys_GetFactoryPtr(const std::string& svModuleName, const std::string& svFact);
|
|
@ -59,42 +59,6 @@ struct CSVData
|
|||
|
||||
std::unordered_map<std::string, CSVData> CSVCache;
|
||||
|
||||
Vector3 StringToVector(char* pString)
|
||||
{
|
||||
Vector3 vRet;
|
||||
|
||||
int length = 0;
|
||||
while (pString[length])
|
||||
{
|
||||
if ((pString[length] == '<') || (pString[length] == '>'))
|
||||
pString[length] = '\0';
|
||||
length++;
|
||||
}
|
||||
|
||||
int startOfFloat = 1;
|
||||
int currentIndex = 1;
|
||||
|
||||
while (pString[currentIndex] && (pString[currentIndex] != ','))
|
||||
currentIndex++;
|
||||
pString[currentIndex] = '\0';
|
||||
vRet.x = std::stof(&pString[startOfFloat]);
|
||||
startOfFloat = ++currentIndex;
|
||||
|
||||
while (pString[currentIndex] && (pString[currentIndex] != ','))
|
||||
currentIndex++;
|
||||
pString[currentIndex] = '\0';
|
||||
vRet.y = std::stof(&pString[startOfFloat]);
|
||||
startOfFloat = ++currentIndex;
|
||||
|
||||
while (pString[currentIndex] && (pString[currentIndex] != ','))
|
||||
currentIndex++;
|
||||
pString[currentIndex] = '\0';
|
||||
vRet.z = std::stof(&pString[startOfFloat]);
|
||||
startOfFloat = ++currentIndex;
|
||||
|
||||
return vRet;
|
||||
}
|
||||
|
||||
// var function GetDataTable( asset path )
|
||||
REPLACE_SQFUNC(GetDataTable, (ScriptContext::UI | ScriptContext::CLIENT | ScriptContext::SERVER))
|
||||
{
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
#include "ai_helper.h"
|
||||
|
||||
#include "client/debugoverlay.h"
|
||||
#include "client/cdll_client_int.h"
|
||||
#include "engine/hoststate.h"
|
||||
|
||||
#include "core/math/vplane.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
const int AINET_VERSION_NUMBER = 57;
|
||||
const int AINET_SCRIPT_VERSION_NUMBER = 21;
|
||||
const int PLACEHOLDER_CRC = 0;
|
||||
|
||||
static ConVar* Cvar_navmesh_debug_hull;
|
||||
static ConVar* Cvar_navmesh_debug_camera_radius;
|
||||
static ConVar* Cvar_navmesh_debug_lossy_optimization;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Get navmesh pointer for hull
|
||||
// Output : navmesh*, nullptr if out of range
|
||||
//-----------------------------------------------------------------------------
|
||||
dtNavMesh* GetNavMeshForHull(int nHull)
|
||||
{
|
||||
if (nHull < 1 || nHull > 4)
|
||||
return nullptr;
|
||||
|
||||
return g_pNavMesh[nHull - 1];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Packs two vectors into a __m128i
|
||||
// Input : &v1 -
|
||||
// &v2 -
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
__m128i PackVerticesSIMD16(const Vector3& v1, const Vector3& v2)
|
||||
{
|
||||
short x1, x2, y1, y2, z1, z2;
|
||||
x1 = static_cast<short>(v1.x);
|
||||
x2 = static_cast<short>(v2.x);
|
||||
y1 = static_cast<short>(v1.y);
|
||||
y2 = static_cast<short>(v2.y);
|
||||
z1 = static_cast<short>(v1.z);
|
||||
z2 = static_cast<short>(v2.z);
|
||||
|
||||
__m128i xRes = _mm_set_epi16(x1, x2, y1, y2, z1, z2, 0, 0);
|
||||
|
||||
if (x1 < x2)
|
||||
xRes = _mm_shufflehi_epi16(xRes, _MM_SHUFFLE(2, 3, 1, 0));
|
||||
|
||||
if (y1 < y2)
|
||||
xRes = _mm_shufflehi_epi16(xRes, _MM_SHUFFLE(3, 2, 0, 1));
|
||||
|
||||
if (z1 < z2)
|
||||
xRes = _mm_shufflelo_epi16(xRes, _MM_SHUFFLE(2, 3, 1, 0));
|
||||
|
||||
return xRes;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draw navmesh polys using debug overlay
|
||||
// Input : *pNavMesh
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_Helper::DrawNavmeshPolys(dtNavMesh* pNavMesh)
|
||||
{
|
||||
if (!pNavMesh)
|
||||
pNavMesh = GetNavMeshForHull(Cvar_navmesh_debug_hull->GetInt());
|
||||
if (!pNavMesh)
|
||||
return;
|
||||
|
||||
Vector3 vCamera;
|
||||
QAngle aCamera;
|
||||
float fFov;
|
||||
g_pClientTools->GetLocalPlayerEyePosition(vCamera, aCamera, fFov);
|
||||
|
||||
const VPlane CullPlane(vCamera - aCamera.GetNormal() * 256.0f, aCamera);
|
||||
|
||||
const float fCamRadius = Cvar_navmesh_debug_camera_radius->GetFloat();
|
||||
const bool bOptimize = Cvar_navmesh_debug_lossy_optimization->GetBool();
|
||||
|
||||
// Used for lossy optimization ( z is ignored when checking for duplicates )
|
||||
// [Fifty]: On a release build i gained around 12 fps on a 1050 ti
|
||||
std::unordered_set<int64_t> sOutlines;
|
||||
|
||||
for (int i = 0; i < pNavMesh->m_maxTiles; ++i)
|
||||
{
|
||||
const dtMeshTile* pTile = &pNavMesh->m_tiles[i];
|
||||
|
||||
if (!pTile->header)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < pTile->header->polyCount; j++)
|
||||
{
|
||||
const dtPoly* pPoly = &pTile->polys[j];
|
||||
|
||||
if (vCamera.DistTo(pPoly->org) > fCamRadius)
|
||||
continue;
|
||||
|
||||
if (CullPlane.GetPointSide(pPoly->org) != SIDE_FRONT)
|
||||
continue;
|
||||
|
||||
const unsigned int ip = (unsigned int)(pPoly - pTile->polys);
|
||||
|
||||
if (pPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||||
{
|
||||
const dtOffMeshConnection* pCon = &pTile->offMeshConnections[ip - pTile->header->offMeshBase];
|
||||
RenderLine(pCon->origin, pCon->dest, Color(255, 250, 50, 255), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
const dtPolyDetail* pDetail = &pTile->detailMeshes[ip];
|
||||
|
||||
Vector3 v[3];
|
||||
|
||||
for (int k = 0; k < pDetail->triCount; ++k)
|
||||
{
|
||||
const unsigned char* t = &pTile->detailTris[(pDetail->triBase + k) * 4];
|
||||
for (int l = 0; l < 3; ++l)
|
||||
{
|
||||
if (t[l] < pPoly->vertCount)
|
||||
{
|
||||
float* pfVerts = &pTile->verts[pPoly->verts[t[l]] * 3];
|
||||
v[l] = Vector3(pfVerts[0], pfVerts[1], pfVerts[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
float* pfVerts = &pTile->detailVerts[(pDetail->vertBase + t[l] - pPoly->vertCount) * 3];
|
||||
v[l] = Vector3(pfVerts[0], pfVerts[1], pfVerts[2]);
|
||||
}
|
||||
}
|
||||
|
||||
RenderTriangle(v[0], v[1], v[2], Color(110, 200, 220, 160), true);
|
||||
|
||||
auto r = sOutlines.insert(_mm_extract_epi64(PackVerticesSIMD16(v[0], v[1]), 1));
|
||||
if (r.second || !bOptimize)
|
||||
RenderLine(v[0], v[1], Color(0, 0, 150), true);
|
||||
|
||||
r = sOutlines.insert(_mm_extract_epi64(PackVerticesSIMD16(v[1], v[2]), 1));
|
||||
if (r.second || !bOptimize)
|
||||
RenderLine(v[1], v[2], Color(0, 0, 150), true);
|
||||
|
||||
r = sOutlines.insert(_mm_extract_epi64(PackVerticesSIMD16(v[2], v[0]), 1));
|
||||
if (r.second || !bOptimize)
|
||||
RenderLine(v[2], v[0], Color(0, 0, 150), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ON_DLL_LOAD("server.dll", ServerAIHelper, (CModule module))
|
||||
{
|
||||
Cvar_navmesh_debug_hull = new ConVar("navmesh_debug_hull", "0", FCVAR_RELEASE, "0 = NONE");
|
||||
Cvar_navmesh_debug_camera_radius =
|
||||
new ConVar("navmesh_debug_camera_radius", "1000", FCVAR_RELEASE, "Radius in which to draw navmeshes");
|
||||
Cvar_navmesh_debug_lossy_optimization =
|
||||
new ConVar("navmesh_debug_lossy_optimization", "1", FCVAR_RELEASE, "Whether to enable lossy navmesh debug draw optimizations");
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "server/ai_navmesh.h"
|
||||
|
||||
dtNavMesh* GetNavMeshForHull(int nHull);
|
||||
|
||||
class CAI_Helper
|
||||
{
|
||||
public:
|
||||
void DrawNavmeshPolys(dtNavMesh* pNavMesh = nullptr);
|
||||
};
|
||||
|
||||
inline CAI_Helper* g_pAIHelper = nullptr;
|
|
@ -0,0 +1,6 @@
|
|||
#include "ai_navmesh.h"
|
||||
|
||||
ON_DLL_LOAD("server.dll", ServerAiNavMesh, (CModule module))
|
||||
{
|
||||
g_pNavMesh = module.Offset(0x105F5D0).RCast<dtNavMesh**>();
|
||||
}
|
|
@ -0,0 +1,260 @@
|
|||
#pragma once
|
||||
|
||||
// [Fifty]: Taken from https://github.com/ASpoonPlaysGames/r2recast
|
||||
|
||||
#include "core/math/vector.h"
|
||||
|
||||
struct dtMeshHeader;
|
||||
struct dtMeshTile;
|
||||
struct dtPoly;
|
||||
struct dtBVNode;
|
||||
struct dtLink;
|
||||
|
||||
typedef unsigned int dtPolyRef;
|
||||
|
||||
/// The maximum number of vertices per navigation polygon.
|
||||
/// @ingroup detour
|
||||
static const int DT_VERTS_PER_POLYGON = 6;
|
||||
|
||||
/// Flags representing the type of a navigation mesh polygon.
|
||||
enum dtPolyTypes
|
||||
{
|
||||
/// The polygon is a standard convex polygon that is part of the surface of the mesh.
|
||||
DT_POLYTYPE_GROUND = 0,
|
||||
/// The polygon is an off-mesh connection consisting of two vertices.
|
||||
DT_POLYTYPE_OFFMESH_CONNECTION = 1,
|
||||
};
|
||||
|
||||
/// Configuration parameters used to define multi-tile navigation meshes.
|
||||
/// The values are used to allocate space during the initialization of a navigation mesh.
|
||||
/// @see dtNavMesh::init()
|
||||
/// @ingroup detour
|
||||
struct dtNavMeshParams
|
||||
{
|
||||
float orig[3]; ///< The world space origin of the navigation mesh's tile space. [(x, y, z)]
|
||||
float tileWidth; ///< The width of each tile. (Along the x-axis.)
|
||||
float tileHeight; ///< The height of each tile. (Along the z-axis.)
|
||||
int maxTiles; ///< The maximum number of tiles the navigation mesh can contain. This and maxPolys are used to calculate how many bits
|
||||
///< are needed to identify tiles and polygons uniquely.
|
||||
int maxPolys; ///< The maximum number of polygons each tile can contain. This and maxTiles are used to calculate how many bits are
|
||||
///< needed to identify tiles and polygons uniquely.
|
||||
//
|
||||
//// i hate this
|
||||
int disjointPolyGroupCount = 0;
|
||||
int reachabilityTableSize = 0;
|
||||
int reachabilityTableCount = 0;
|
||||
};
|
||||
|
||||
/// Defines an navigation mesh off-mesh connection within a dtMeshTile object.
|
||||
/// An off-mesh connection is a user defined traversable connection made up to two vertices.
|
||||
struct dtOffMeshConnection
|
||||
{
|
||||
/// The endpoints of the connection.
|
||||
Vector3 origin;
|
||||
Vector3 dest;
|
||||
|
||||
/// The radius of the endpoints. [Limit: >= 0]
|
||||
float rad;
|
||||
|
||||
/// The polygon reference of the connection within the tile.
|
||||
unsigned short poly;
|
||||
|
||||
/// Link flags.
|
||||
/// @note These are not the connection's user defined flags. Those are assigned via the
|
||||
/// connection's dtPoly definition. These are link flags used for internal purposes.
|
||||
unsigned char flags;
|
||||
|
||||
/// End point side.
|
||||
unsigned char side;
|
||||
|
||||
/// The id of the offmesh connection. (User assigned when the navigation mesh is built.)
|
||||
unsigned int userId;
|
||||
|
||||
float unk[3];
|
||||
float another_unk;
|
||||
};
|
||||
|
||||
/// A navigation mesh based on tiles of convex polygons.
|
||||
/// @ingroup detour
|
||||
class dtNavMesh
|
||||
{
|
||||
public:
|
||||
dtMeshTile** m_posLookup; ///< Tile hash lookup.
|
||||
dtMeshTile* m_nextFree; ///< Freelist of tiles.
|
||||
dtMeshTile* m_tiles; ///< List of tiles.
|
||||
|
||||
void* disjointPolyGroup;
|
||||
int** reachabilityTable;
|
||||
|
||||
__int64 unk;
|
||||
dtNavMeshParams m_params; ///< Current initialization params. TODO: do not store this info twice.
|
||||
float m_orig[3]; ///< Origin of the tile (0,0)
|
||||
float m_tileWidth, m_tileHight; ///< Dimensions of each tile.
|
||||
int m_pad;
|
||||
int m_maxTiles; ///< Max number of tiles.
|
||||
|
||||
int m_tileLutSize; ///< Tile hash lookup size (must be pot).
|
||||
int m_tileLutMask; ///< Tile hash lookup mask.
|
||||
|
||||
int m_saltBits; ///< Number of salt bits in the tile ID.
|
||||
int m_tileBits; ///< Number of tile bits in the tile ID.
|
||||
int m_polyBits; ///< Number of poly bits in the tile ID.
|
||||
};
|
||||
|
||||
/// Defines the location of detail sub-mesh data within a dtMeshTile.
|
||||
struct dtPolyDetail
|
||||
{
|
||||
unsigned int vertBase; ///< The offset of the vertices in the dtMeshTile::detailVerts array.
|
||||
unsigned int triBase; ///< The offset of the triangles in the dtMeshTile::detailTris array.
|
||||
unsigned char vertCount; ///< The number of vertices in the sub-mesh.
|
||||
unsigned char triCount; ///< The number of triangles in the sub-mesh.
|
||||
};
|
||||
|
||||
/// Defines a navigation mesh tile.
|
||||
/// @ingroup detour
|
||||
struct dtMeshTile
|
||||
{
|
||||
int salt; ///< Counter describing modifications to the tile.
|
||||
unsigned int linksFreeList; ///< Index to the next free link.
|
||||
dtMeshHeader* header; ///< The tile header.
|
||||
dtPoly* polys; ///< The tile polygons. [Size: dtMeshHeader::polyCount]
|
||||
void* unkPolyThing;
|
||||
float* verts; ///< The tile vertices. [Size: dtMeshHeader::vertCount]
|
||||
dtLink* links; ///< The tile links. [Size: dtMeshHeader::maxLinkCount]
|
||||
dtPolyDetail* detailMeshes; ///< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount]
|
||||
|
||||
/// The detail mesh's unique vertices. [(x, y, z) * dtMeshHeader::detailVertCount]
|
||||
float* detailVerts;
|
||||
|
||||
/// The detail mesh's triangles. [(vertA, vertB, vertC, triFlags) * dtMeshHeader::detailTriCount].
|
||||
/// See dtDetailTriEdgeFlags and dtGetDetailTriEdgeFlags.
|
||||
unsigned char* detailTris;
|
||||
|
||||
/// The tile bounding volume nodes. [Size: dtMeshHeader::bvNodeCount]
|
||||
/// (Will be null if bounding volumes are disabled.)
|
||||
dtBVNode* bvTree;
|
||||
|
||||
dtOffMeshConnection* offMeshConnections; ///< The tile off-mesh connections. [Size: dtMeshHeader::offMeshConCount]
|
||||
void* data; ///< The tile data. (Not directly accessed under normal situations.)
|
||||
int dataSize; ///< Size of the tile data.
|
||||
int flags; ///< Tile flags. (See: #dtTileFlags)
|
||||
dtMeshTile* next; ///< The next free tile, or the next tile in the spatial grid.
|
||||
__int64 unk;
|
||||
};
|
||||
|
||||
/// Provides high level information related to a dtMeshTile object.
|
||||
/// @ingroup detour
|
||||
struct dtMeshHeader
|
||||
{
|
||||
int magic; ///< Tile magic number. (Used to identify the data format.)
|
||||
int version; ///< Tile data format version number.
|
||||
int x; ///< The x-position of the tile within the dtNavMesh tile grid. (x, y, layer)
|
||||
int y; ///< The y-position of the tile within the dtNavMesh tile grid. (x, y, layer)
|
||||
int layer; ///< The layer of the tile within the dtNavMesh tile grid. (x, y, layer)
|
||||
unsigned int userId; ///< The user defined id of the tile.
|
||||
int polyCount; ///< The number of polygons in the tile.
|
||||
int sth_per_poly;
|
||||
int vertCount; ///< The number of vertices in the tile.
|
||||
int maxLinkCount; ///< The number of allocated links.
|
||||
|
||||
int detailMeshCount;
|
||||
|
||||
/// The number of unique vertices in the detail mesh. (In addition to the polygon vertices.)
|
||||
int detailVertCount;
|
||||
|
||||
int detailTriCount; ///< The number of triangles in the detail mesh.
|
||||
int bvNodeCount; ///< The number of bounding volume nodes. (Zero if bounding volumes are disabled.)
|
||||
int offMeshConCount; ///< The number of off-mesh connections.
|
||||
// int unk1;
|
||||
int offMeshBase; ///< The index of the first polygon which is an off-mesh connection.
|
||||
|
||||
float walkableHeight; ///< The height of the agents using the tile.
|
||||
float walkableRadius; ///< The radius of the agents using the tile.
|
||||
float walkableClimb; ///< The maximum climb height of the agents using the tile.
|
||||
float bmin[3]; ///< The minimum bounds of the tile's AABB. [(x, y, z)]
|
||||
float bmax[3]; ///< The maximum bounds of the tile's AABB. [(x, y, z)]
|
||||
|
||||
/// The bounding volume quantization factor.
|
||||
float bvQuantFactor;
|
||||
};
|
||||
|
||||
/// Defines a polygon within a dtMeshTile object.
|
||||
/// @ingroup detour
|
||||
struct dtPoly
|
||||
{
|
||||
/// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.)
|
||||
unsigned int firstLink;
|
||||
|
||||
/// The indices of the polygon's vertices.
|
||||
/// The actual vertices are located in dtMeshTile::verts.
|
||||
unsigned short verts[DT_VERTS_PER_POLYGON];
|
||||
|
||||
/// Packed data representing neighbor polygons references and flags for each edge.
|
||||
unsigned short neis[DT_VERTS_PER_POLYGON];
|
||||
|
||||
/// The user defined polygon flags.
|
||||
unsigned short flags;
|
||||
|
||||
/// The number of vertices in the polygon.
|
||||
unsigned char vertCount;
|
||||
|
||||
/// The bit packed area id and polygon type.
|
||||
/// @note Use the structure's set and get methods to acess this value.
|
||||
unsigned char areaAndtype;
|
||||
|
||||
unsigned short disjointSetId;
|
||||
unsigned short unk; // IDK but looks filled
|
||||
Vector3 org; //
|
||||
|
||||
/// Sets the user defined area id. [Limit: < #DT_MAX_AREAS]
|
||||
inline void setArea(unsigned char a)
|
||||
{
|
||||
areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f);
|
||||
}
|
||||
|
||||
/// Sets the polygon type. (See: #dtPolyTypes.)
|
||||
inline void setType(unsigned char t)
|
||||
{
|
||||
areaAndtype = (areaAndtype & 0x3f) | (t << 6);
|
||||
}
|
||||
|
||||
/// Gets the user defined area id.
|
||||
inline unsigned char getArea() const
|
||||
{
|
||||
return areaAndtype & 0x3f;
|
||||
}
|
||||
|
||||
/// Gets the polygon type. (See: #dtPolyTypes)
|
||||
inline unsigned char getType() const
|
||||
{
|
||||
return areaAndtype >> 6;
|
||||
}
|
||||
};
|
||||
|
||||
/// Defines a link between polygons.
|
||||
/// @note This structure is rarely if ever used by the end user.
|
||||
/// @see dtMeshTile
|
||||
struct dtLink
|
||||
{
|
||||
dtPolyRef ref; ///< Neighbour reference. (The neighbor that is linked to.)
|
||||
unsigned int next; ///< Index of the next link.
|
||||
unsigned char edge; ///< Index of the polygon edge that owns this link.
|
||||
unsigned char side; ///< If a boundary link, defines on which side the link is.
|
||||
unsigned char bmin; ///< If a boundary link, defines the minimum sub-edge area.
|
||||
unsigned char bmax; ///< If a boundary link, defines the maximum sub-edge area.
|
||||
unsigned char jumpType;
|
||||
unsigned char otherUnk;
|
||||
unsigned short reverseLinkIndex;
|
||||
};
|
||||
|
||||
/// Bounding volume node.
|
||||
/// @note This structure is rarely if ever used by the end user.
|
||||
/// @see dtMeshTile
|
||||
struct dtBVNode
|
||||
{
|
||||
unsigned short bmin[3]; ///< Minimum bounds of the node's AABB. [(x, y, z)]
|
||||
unsigned short bmax[3]; ///< Maximum bounds of the node's AABB. [(x, y, z)]
|
||||
int i; ///< The node's index. (Negative for escape sequence.)
|
||||
};
|
||||
|
||||
inline dtNavMesh** g_pNavMesh = nullptr;
|
|
@ -222,16 +222,24 @@ void, __fastcall, (void* buf, void* pCmd_move, void* pCmd_from)) // 4C 89 44 24
|
|||
"ReadUsercmd (command_number delta: " + std::to_string(cmd->command_number - fromCmd->command_number) + "): ";
|
||||
|
||||
// fix invalid player angles
|
||||
cmd->worldViewAngles.MakeValid();
|
||||
cmd->attackangles.MakeValid();
|
||||
cmd->localViewAngles.MakeValid();
|
||||
if (!cmd->worldViewAngles.IsValid())
|
||||
cmd->worldViewAngles.Init();
|
||||
|
||||
if (!cmd->attackangles.IsValid())
|
||||
cmd->attackangles.Init();
|
||||
|
||||
if (!cmd->localViewAngles.IsValid())
|
||||
cmd->localViewAngles.Init();
|
||||
|
||||
// Fix invalid camera angles
|
||||
cmd->cameraPos.MakeValid();
|
||||
cmd->cameraAngles.MakeValid();
|
||||
if (!cmd->cameraPos.IsValid())
|
||||
cmd->cameraPos.Init();
|
||||
if (!cmd->cameraAngles.IsValid())
|
||||
cmd->cameraAngles.Init();
|
||||
|
||||
// Fix invaid movement vector
|
||||
cmd->move.MakeValid();
|
||||
if (!cmd->move.IsValid())
|
||||
cmd->move.Init();
|
||||
|
||||
if (cmd->frameTime <= 0 || cmd->tick_count == 0 || cmd->command_time <= 0)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/math/vector.h"
|
||||
|
||||
class IClientTools // : public IBaseInterface
|
||||
{
|
||||
public:
|
||||
virtual void sub_1805E4960() = 0;
|
||||
virtual void sub_1805E4B10() = 0;
|
||||
virtual void sub_1805E4C50() = 0;
|
||||
virtual void sub_1805E5670() = 0;
|
||||
virtual void sub_1805E66C0() = 0;
|
||||
virtual void sub_1805E5910() = 0;
|
||||
virtual void sub_1805E59A0() = 0;
|
||||
virtual void sub_1805E6B10() = 0;
|
||||
virtual void sub_1805E8580() = 0;
|
||||
virtual void sub_1805E59D0() = 0;
|
||||
virtual void sub_1805E57B0() = 0;
|
||||
virtual void sub_1805E5860() = 0;
|
||||
virtual void sub_1805E55A0() = 0;
|
||||
virtual void sub_1805E49C0() = 0;
|
||||
virtual void sub_1805E7580() = 0;
|
||||
virtual void sub_1805E86A0() = 0;
|
||||
virtual void sub_1805E69B0() = 0;
|
||||
virtual void sub_1805E4D70() = 0; // IClientTools::DrawSprite
|
||||
virtual void* GetLocalPlayer() = 0; // return type unknown probably CBasePlayer*
|
||||
virtual bool GetLocalPlayerEyePosition(Vector3& org, QAngle& ang, float& fov) = 0;
|
||||
virtual void sub_1805E5960() = 0;
|
||||
virtual void sub_1805E5650() = 0;
|
||||
virtual void sub_1805E5920() = 0;
|
||||
virtual void sub_1805E64E0() = 0;
|
||||
virtual void sub_1805E63C0() = 0;
|
||||
virtual void sub_1805E64C0() = 0;
|
||||
virtual void sub_1805E6520() = 0;
|
||||
virtual void sub_1805E6770() = 0;
|
||||
virtual void sub_1805E67B0() = 0;
|
||||
virtual void sub_1805E67F0() = 0;
|
||||
virtual void sub_1805E66A0() = 0;
|
||||
virtual void sub_1805E6500() = 0;
|
||||
virtual void sub_1805E63B0() = 0;
|
||||
virtual void sub_1805E54C0() = 0;
|
||||
virtual void sub_1805E53E0() = 0;
|
||||
virtual void sub_1805E6D70() = 0;
|
||||
virtual void sub_1805E50D0() = 0;
|
||||
virtual void sub_1805E65C0() = 0;
|
||||
};
|
Loading…
Reference in New Issue