From 8f47a7a67e3d161eb97f8faffaa612b18de4c568 Mon Sep 17 00:00:00 2001 From: mostlikely4r Date: Fri, 18 Oct 2024 15:23:30 +0200 Subject: [PATCH] Missing bot-specific pathfinder modifications to allow for travel node generation. (#701) * -Set/get-area fix: Use instanceId instead of 0 to prevent crashes when used in instances. * -Travel node generation fix: Allow pathfinder to be used without m_sourceUnit. * -Fix some old functionality being bypassed with playerbot enabled but with sourceUnit. --- src/game/MotionGenerators/PathFinder.cpp | 117 ++++++++++++++++------- src/game/MotionGenerators/PathFinder.h | 3 + 2 files changed, 85 insertions(+), 35 deletions(-) diff --git a/src/game/MotionGenerators/PathFinder.cpp b/src/game/MotionGenerators/PathFinder.cpp index 9d071ea905a..3d7a7c232a6 100644 --- a/src/game/MotionGenerators/PathFinder.cpp +++ b/src/game/MotionGenerators/PathFinder.cpp @@ -38,6 +38,9 @@ PathFinder::PathFinder(const Unit* owner, bool ignoreNormalization) : m_cachedPoints(m_pointPathLimit * VERTEX_SIZE), m_pathPolyRefs(m_pointPathLimit), m_polyLength(0), m_smoothPathPolyRefs(m_pointPathLimit), m_sourceUnit(owner), m_navMesh(nullptr), m_navMeshQuery(nullptr), m_defaultMapId(m_sourceUnit->GetMapId()), m_ignoreNormalization(ignoreNormalization) +#ifdef ENABLE_PLAYERBOTS + , m_defaultInstanceId(m_sourceUnit->GetInstanceId()) +#endif { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::PathInfo for %u \n", m_sourceUnit->GetGUIDLow()); @@ -54,7 +57,7 @@ PathFinder::PathFinder(const Unit* owner, bool ignoreNormalization) : PathFinder::PathFinder() : m_polyLength(0), m_type(PATHFIND_BLANK), m_useStraightPath(false), m_forceDestination(false), m_straightLine(false), m_pointPathLimit(MAX_POINT_PATH_LENGTH), // TODO: Fix legitimate long paths - m_sourceUnit(nullptr), m_navMesh(nullptr), m_navMeshQuery(nullptr), m_cachedPoints(m_pointPathLimit* VERTEX_SIZE), m_pathPolyRefs(m_pointPathLimit), m_smoothPathPolyRefs(m_pointPathLimit), m_defaultMapId(0) + m_sourceUnit(nullptr), m_navMesh(nullptr), m_navMeshQuery(nullptr), m_cachedPoints(m_pointPathLimit* VERTEX_SIZE), m_pathPolyRefs(m_pointPathLimit), m_smoothPathPolyRefs(m_pointPathLimit), m_defaultMapId(0), m_defaultInstanceId(0) { } @@ -62,7 +65,7 @@ PathFinder::PathFinder() : PathFinder::PathFinder(uint32 mapId, uint32 instanceId) : m_polyLength(0), m_type(PATHFIND_BLANK), m_useStraightPath(false), m_forceDestination(false), m_straightLine(false), m_pointPathLimit(MAX_POINT_PATH_LENGTH), // TODO: Fix legitimate long paths - m_sourceUnit(nullptr), m_navMesh(nullptr), m_navMeshQuery(nullptr), m_cachedPoints(m_pointPathLimit* VERTEX_SIZE), m_pathPolyRefs(m_pointPathLimit), m_smoothPathPolyRefs(m_pointPathLimit), m_defaultMapId(mapId) + m_sourceUnit(nullptr), m_navMesh(nullptr), m_navMeshQuery(nullptr), m_cachedPoints(m_pointPathLimit* VERTEX_SIZE), m_pathPolyRefs(m_pointPathLimit), m_smoothPathPolyRefs(m_pointPathLimit), m_defaultMapId(mapId), m_defaultInstanceId(instanceId) { MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); m_defaultNavMeshQuery = mmap->GetNavMeshQuery(mapId, instanceId); @@ -90,20 +93,20 @@ void PathFinder::SetCurrentNavMesh() m_navMeshQuery = m_defaultNavMeshQuery; } -#ifdef ENABLE_PLAYERBOTS if (m_navMeshQuery) m_navMesh = m_navMeshQuery->getAttachedNavMesh(); } +#ifdef ENABLE_PLAYERBOTS else if (!m_sourceUnit && MMAP::MMapFactory::IsPathfindingEnabled(m_defaultMapId, nullptr)) { MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); m_navMeshQuery = m_defaultNavMeshQuery; -#endif if (m_navMeshQuery) m_navMesh = m_navMeshQuery->getAttachedNavMesh(); } +#endif } bool PathFinder::calculate(float destX, float destY, float destZ, bool forceDest/* = false*/, bool straightLine/* = false*/) @@ -124,8 +127,10 @@ bool PathFinder::calculate(Vector3 const& start, Vector3 const& dest, bool force if (!MaNGOS::IsValidMapCoord(start.x, start.y, start.z)) return false; +#ifndef ENABLE_PLAYERBOTS if (!m_sourceUnit) return false; +#endif #ifdef BUILD_METRICS metric::duration meas("pathfinder.calculate", { @@ -149,11 +154,18 @@ bool PathFinder::calculate(Vector3 const& start, Vector3 const& dest, bool force SetCurrentNavMesh(); - DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); +#ifdef ENABLE_PLAYERBOTS + if(m_sourceUnit) +#endif + DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) +#ifdef ENABLE_PLAYERBOTS + if (!m_navMesh || !m_navMeshQuery || (m_sourceUnit && m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING)) || +#else if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING) || +#endif !HaveTile(start) || !HaveTile(dest)) { BuildShortcut(); @@ -175,7 +187,7 @@ void PathFinder::setArea(uint32 mapId, float x, float y, float z, uint32 area, f MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); - dtNavMeshQuery const* query = mmap->GetNavMeshQuery(mapId, 0); + dtNavMeshQuery const* query = mmap->GetNavMeshQuery(mapId, m_defaultInstanceId); dtNavMesh const* cnavMesh = mmap->GetNavMesh(mapId); dtNavMesh* navMesh = const_cast (cnavMesh); dtQueryFilter m_filter; @@ -231,7 +243,7 @@ uint32 PathFinder::getArea(uint32 mapId, float x, float y, float z) MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); - dtNavMeshQuery const* query = mmap->GetNavMeshQuery(mapId, 0); + dtNavMeshQuery const* query = mmap->GetNavMeshQuery(mapId, m_defaultInstanceId); dtNavMesh const* cnavMesh = mmap->GetNavMesh(mapId); dtNavMesh* navMesh = const_cast (cnavMesh); dtQueryFilter m_filter; @@ -373,11 +385,17 @@ dtPolyRef PathFinder::getPolyByLocation(const float* point, float* distance) void PathFinder::BuildPolyPath(const Vector3& startPos, const Vector3& endPos) { +#ifndef ENABLE_PLAYERBOTS if (!m_sourceUnit) return; +#endif // *** getting start/end poly logic *** +#ifndef ENABLE_PLAYERBOTS if (m_sourceUnit->GetMap()->IsDungeon()) +#else + if ((m_sourceUnit && m_sourceUnit->GetMap()->IsDungeon()) || (sMapStore.LookupEntry(m_defaultMapId) && sMapStore.LookupEntry(m_defaultMapId)->IsDungeon())) +#endif { float distance = sqrt((endPos.x - startPos.x) * (endPos.x - startPos.x) + (endPos.y - startPos.y) * (endPos.y - startPos.y) + (endPos.z - startPos.z) * (endPos.z - startPos.z)); if (distance > 300.f) @@ -406,17 +424,26 @@ void PathFinder::BuildPolyPath(const Vector3& startPos, const Vector3& endPos) DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); BuildShortcut(); - // Check for swimming or flying shortcut - if ((startPoly == INVALID_POLYREF && m_sourceUnit->GetTerrain()->IsSwimmable(startPos.x, startPos.y, startPos.z)) || - (endPoly == INVALID_POLYREF && m_sourceUnit->GetTerrain()->IsSwimmable(endPos.x, endPos.y, endPos.z))) - m_type = m_sourceUnit->CanSwim() ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; - else +#ifdef ENABLE_PLAYERBOTS + if (m_sourceUnit) { - if (m_sourceUnit->GetTypeId() != TYPEID_PLAYER) - m_type = m_sourceUnit->CanFly() ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; +#endif + // Check for swimming or flying shortcut + if ((startPoly == INVALID_POLYREF && m_sourceUnit->GetTerrain()->IsSwimmable(startPos.x, startPos.y, startPos.z)) || + (endPoly == INVALID_POLYREF && m_sourceUnit->GetTerrain()->IsSwimmable(endPos.x, endPos.y, endPos.z))) + m_type = m_sourceUnit->CanSwim() ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; else - m_type = PATHFIND_NOPATH; + { + if (m_sourceUnit->GetTypeId() != TYPEID_PLAYER) + m_type = m_sourceUnit->CanFly() ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; + else + + m_type = PATHFIND_NOPATH; + } +#ifdef ENABLE_PLAYERBOTS } +#endif + return; } @@ -428,19 +455,26 @@ void PathFinder::BuildPolyPath(const Vector3& startPos, const Vector3& endPos) DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly); bool buildShotrcut = false; - Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos; - if (m_sourceUnit->GetTerrain()->IsUnderWater(p.x, p.y, p.z)) - { - DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: underWater case\n"); - if (m_sourceUnit->CanSwim()) - buildShotrcut = true; - } - else +#ifdef ENABLE_PLAYERBOTS + if (m_sourceUnit) { - DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: flying case\n"); - if (m_sourceUnit->CanFly()) - buildShotrcut = true; +#endif + Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos; + if (m_sourceUnit->GetTerrain()->IsUnderWater(p.x, p.y, p.z)) + { + DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: underWater case\n"); + if (m_sourceUnit->CanSwim()) + buildShotrcut = true; + } + else + { + DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: flying case\n"); + if (m_sourceUnit->CanFly()) + buildShotrcut = true; + } +#ifdef ENABLE_PLAYERBOTS } +#endif #ifdef ENABLE_PLAYERBOTS if (m_sourceUnit && m_sourceUnit->IsPlayer() && IsPointHigherThan(getActualEndPosition(), getStartPosition())) @@ -499,10 +533,13 @@ void PathFinder::BuildPolyPath(const Vector3& startPos, const Vector3& endPos) // here to catch few bugs if (m_pathPolyRefs[pathStartIndex] == INVALID_POLYREF) { - sLog.outError("Invalid poly ref in BuildPolyPath. polyLength: %u, pathStartIndex: %u," - " startPos: %s, endPos: %s, mapId: %u", - m_polyLength, pathStartIndex, startPos.toString().c_str(), endPos.toString().c_str(), - m_sourceUnit->GetMapId()); +#ifdef ENABLE_PLAYERBOTS + if (m_sourceUnit) +#endif + sLog.outError("Invalid poly ref in BuildPolyPath. polyLength: %u, pathStartIndex: %u," + " startPos: %s, endPos: %s, mapId: %u", + m_polyLength, pathStartIndex, startPos.toString().c_str(), endPos.toString().c_str(), + m_sourceUnit->GetMapId()); break; } @@ -679,12 +716,19 @@ void PathFinder::BuildPolyPath(const Vector3& startPos, const Vector3& endPos) float hitPos[3]; float distanceToPoly; - hit = hit - m_sourceUnit->GetCollisionWidth(); - if (hit < 0.1f) +#ifdef ENABLE_PLAYERBOTS + if (m_sourceUnit) { - m_type = PATHFIND_NOPATH; - return; +#endif + hit = hit - m_sourceUnit->GetCollisionWidth(); + if (hit < 0.1f) + { + m_type = PATHFIND_NOPATH; + return; + } +#ifdef ENABLE_PLAYERBOTS } +#endif dtVlerp(hitPos, startPoint, endPoint, hit); dtPolyRef poly = getPolyByLocation(hitPos, &distanceToPoly); @@ -719,7 +763,10 @@ void PathFinder::BuildPolyPath(const Vector3& startPos, const Vector3& endPos) if (!m_polyLength || dtStatusFailed(dtResult)) { // only happens if we passed bad data to findPath(), or navmesh is messed up - sLog.outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); +#ifdef ENABLE_PLAYERBOTS + if (m_sourceUnit) +#endif + sLog.outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); #ifdef ENABLE_PLAYERBOTS if (m_sourceUnit && m_sourceUnit->IsPlayer() && IsPointHigherThan(getActualEndPosition(), getStartPosition())) diff --git a/src/game/MotionGenerators/PathFinder.h b/src/game/MotionGenerators/PathFinder.h index 162295b86fb..a0112f83fce 100644 --- a/src/game/MotionGenerators/PathFinder.h +++ b/src/game/MotionGenerators/PathFinder.h @@ -130,6 +130,9 @@ class PathFinder const dtNavMeshQuery* m_defaultNavMeshQuery; // the nav mesh query used to find the path uint32 m_defaultMapId; +#ifdef ENABLE_PLAYERBOTS + uint32 m_defaultInstanceId; +#endif bool m_ignoreNormalization;