From 57484ee1634787cab31a0a4b6edf6b7fcaa2c5c5 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 5 Jul 2024 18:02:56 +0200 Subject: [PATCH] Server: reimplement Detour_IsGoalPolyReachable The function is simple and everything for it has been reversed. Function has been rebuilt to make debugging easier, and confirmed to work as designed. --- src/game/server/ai_utility.cpp | 43 ++++++++++++++++++++++++++++--- src/game/server/detour_impl.h | 6 ++--- src/public/game/server/ai_agent.h | 3 ++- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/game/server/ai_utility.cpp b/src/game/server/ai_utility.cpp index c7fdb9b5..d63c99a7 100644 --- a/src/game/server/ai_utility.cpp +++ b/src/game/server/ai_utility.cpp @@ -7,6 +7,7 @@ #include "core/stdafx.h" #include "tier0/fasttimer.h" #include "tier1/cvar.h" +#include "mathlib/bitvec.h" #include "engine/server/server.h" #include "public/edict.h" #include "game/server/detour_impl.h" @@ -49,18 +50,54 @@ void Detour_FreeNavMeshByType(const NavMeshType_e navMeshType) //----------------------------------------------------------------------------- // Purpose: determines whether goal poly is reachable from agent poly +// (only checks static pathing) // input : *nav - // fromRef - // goalRef - // animType - // Output : value if reachable, false otherwise //----------------------------------------------------------------------------- -uint8_t Detour_IsGoalPolyReachable(dtNavMesh* nav, dtPolyRef fromRef, dtPolyRef goalRef, TraverseAnimType_e animType) +bool Detour_IsGoalPolyReachable(dtNavMesh* const nav, const dtPolyRef fromRef, + const dtPolyRef goalRef, const TraverseAnimType_e animType) { if (navmesh_always_reachable.GetBool()) return true; - return dtNavMesh__isPolyReachable(nav, fromRef, goalRef, animType); + // Same poly is always reachable. + if (fromRef == goalRef) + return true; + + const dtMeshTile* fromTile = nullptr; + const dtMeshTile* goalTile = nullptr; + const dtPoly* fromPoly = nullptr; + const dtPoly* goalPoly = nullptr; + + nav->getTileAndPolyByRefUnsafe(fromRef, &fromTile, &fromPoly); + nav->getTileAndPolyByRefUnsafe(goalRef, &goalTile, &goalPoly); + + const unsigned short fromPolyGroupId = fromPoly->groupId; + const unsigned short goalPolyGroupId = goalPoly->groupId; + + // If we don't have an anim type, then we shouldn't use the traversal tables + // since these are used for linking separate poly islands together (which + // requires jumping or some form of animation). So instead, check if we are + // on the same poly island. + if (animType == ANIMTYPE_NONE) + return fromPolyGroupId == goalPolyGroupId; + + const int* const traversalTable = nav->m_traversalTables[NavMesh_GetTraversalTableIndexForAnimType(animType)]; + + // Traversal table doesn't exist, attempt the path finding anyways (this is + // a bug in the NavMesh, rebuild it!). + if (!traversalTable) + return true; + + const int polyGroupCount = nav->m_params.polyGroupCount; + const int fromPolyBitCell = traversalTable[calcTraversalTableCellIndex(polyGroupCount, fromPolyGroupId, goalPolyGroupId)]; + + // Check if the bit corresponding to our goal poly is set, if it isn't then + // there are no available traversal links from the current poly to the goal. + return fromPolyBitCell & BitVec_Bit(goalPolyGroupId); } //----------------------------------------------------------------------------- @@ -160,6 +197,6 @@ static ConCommand navmesh_hotswap("navmesh_hotswap", Detour_HotSwap_f, "Hot swap /////////////////////////////////////////////////////////////////////////////// void VRecast::Detour(const bool bAttach) const { - DetourSetup(&dtNavMesh__isPolyReachable, &Detour_IsGoalPolyReachable, bAttach); + DetourSetup(&v_Detour_IsGoalPolyReachable, &Detour_IsGoalPolyReachable, bAttach); DetourSetup(&v_Detour_LevelInit, &Detour_LevelInit, bAttach); } diff --git a/src/game/server/detour_impl.h b/src/game/server/detour_impl.h index 7685a3dc..c5188c8e 100644 --- a/src/game/server/detour_impl.h +++ b/src/game/server/detour_impl.h @@ -9,9 +9,9 @@ //------------------------------------------------------------------------- inline void(*v_Detour_LevelInit)(void); inline void(*v_Detour_FreeNavMesh)(dtNavMesh* mesh); +inline bool(*v_Detour_IsGoalPolyReachable)(dtNavMesh* const nav, const dtPolyRef fromPoly, const dtPolyRef goalPoly, const TraverseAnimType_e animType); inline dtStatus(*dtNavMesh__Init)(dtNavMesh* thisptr, unsigned char* data, int flags); inline dtStatus(*dtNavMesh__addTile)(dtNavMesh* thisptr, unsigned char* data, dtMeshHeader* header, int dataSize, int flags, dtTileRef lastRef); -inline uint8_t(*dtNavMesh__isPolyReachable)(dtNavMesh* thisptr, dtPolyRef poly_1, dtPolyRef poly_2, TraverseAnimType_e animType); constexpr const char* NAVMESH_PATH = "maps/navmesh/"; @@ -33,9 +33,9 @@ class VRecast : public IDetour { LogFunAdr("Detour_LevelInit", v_Detour_LevelInit); LogFunAdr("Detour_FreeNavMesh", v_Detour_FreeNavMesh); + LogFunAdr("Detour_IsGoalPolyReachable", v_Detour_IsGoalPolyReachable); LogFunAdr("dtNavMesh::Init", dtNavMesh__Init); LogFunAdr("dtNavMesh::addTile", dtNavMesh__addTile); - LogFunAdr("dtNavMesh::isPolyReachable", dtNavMesh__isPolyReachable); LogVarAdr("g_pNavMesh[ NavMeshType_e::NAVMESH_COUNT ]", g_pNavMesh); LogVarAdr("g_pNavMeshQuery", g_pNavMeshQuery); } @@ -43,9 +43,9 @@ class VRecast : public IDetour { g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 45 33 E4").GetPtr(v_Detour_LevelInit); g_GameDll.FindPatternSIMD("40 53 48 83 EC 30 48 89 6C 24 ?? 48 8B D9").GetPtr(v_Detour_FreeNavMesh); + g_GameDll.FindPatternSIMD("48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 49 63 F1").GetPtr(v_Detour_IsGoalPolyReachable); g_GameDll.FindPatternSIMD("4C 89 44 24 ?? 53 41 56 48 81 EC ?? ?? ?? ?? 0F 10 11").GetPtr(dtNavMesh__Init); g_GameDll.FindPatternSIMD("44 89 4C 24 ?? 41 55").GetPtr(dtNavMesh__addTile); - g_GameDll.FindPatternSIMD("48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 49 63 F1").GetPtr(dtNavMesh__isPolyReachable); } virtual void GetVar(void) const { diff --git a/src/public/game/server/ai_agent.h b/src/public/game/server/ai_agent.h index a99314ce..e5675ba3 100644 --- a/src/public/game/server/ai_agent.h +++ b/src/public/game/server/ai_agent.h @@ -32,7 +32,8 @@ enum TraverseAnimType_e ANIMTYPE_GOLIATH, // Not an anim type! - ANIMTYPE_COUNT + ANIMTYPE_COUNT, + ANIMTYPE_NONE = -1 // No Animtype (appears after animtype count as we don't want to count it) }; #endif // AI_AGENT_H