Skip to content

Commit

Permalink
Missing bot-specific pathfinder modifications to allow for travel nod…
Browse files Browse the repository at this point in the history
…e 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.
  • Loading branch information
mostlikely4r authored Oct 18, 2024
1 parent f3abf5a commit 8f47a7a
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 35 deletions.
117 changes: 82 additions & 35 deletions src/game/MotionGenerators/PathFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand All @@ -54,15 +57,15 @@ 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)
{

}

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);
Expand Down Expand Up @@ -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*/)
Expand All @@ -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<std::chrono::microseconds> meas("pathfinder.calculate", {
Expand All @@ -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();
Expand All @@ -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<dtNavMesh*> (cnavMesh);
dtQueryFilter m_filter;
Expand Down Expand Up @@ -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<dtNavMesh*> (cnavMesh);
dtQueryFilter m_filter;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
Expand All @@ -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()))
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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()))
Expand Down
3 changes: 3 additions & 0 deletions src/game/MotionGenerators/PathFinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 8f47a7a

Please sign in to comment.