From 0e053d456a43a77484d5e0220904fcb3e7902e39 Mon Sep 17 00:00:00 2001 From: bash Date: Fri, 8 May 2026 23:25:43 +0200 Subject: [PATCH] fix(Core/Travel): Port cmangos makeShortCut walkability filter and bot context --- src/Ai/World/Rpg/Action/NewRpgBaseAction.cpp | 2 +- src/Mgr/Travel/TravelNode.cpp | 22 +++++++++++++------- src/Mgr/Travel/TravelNode.h | 12 ++++++++++- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/Ai/World/Rpg/Action/NewRpgBaseAction.cpp b/src/Ai/World/Rpg/Action/NewRpgBaseAction.cpp index 138b82830..b6ee79995 100644 --- a/src/Ai/World/Rpg/Action/NewRpgBaseAction.cpp +++ b/src/Ai/World/Rpg/Action/NewRpgBaseAction.cpp @@ -101,7 +101,7 @@ bool NewRpgBaseAction::MoveFarTo(WorldPosition dest) if (lastBack.distance(dest) < maxDistChange && distFromBotToBack > 10.0f) { WorldPosition botPos(bot); - lastMove.lastPath.makeShortCut(botPos, sPlayerbotAIConfig.reactDistance); + lastMove.lastPath.makeShortCut(botPos, sPlayerbotAIConfig.reactDistance, bot); // makeShortCut may clear the path if the bot drifted // too far off (>reactDistance from any waypoint). In diff --git a/src/Mgr/Travel/TravelNode.cpp b/src/Mgr/Travel/TravelNode.cpp index 02f0fd1d1..1386a9259 100644 --- a/src/Mgr/Travel/TravelNode.cpp +++ b/src/Mgr/Travel/TravelNode.cpp @@ -678,7 +678,7 @@ void TravelNode::print([[maybe_unused]] bool printFailed) } // Attempts to move ahead of the path. -bool TravelPath::makeShortCut(WorldPosition startPos, float maxDist) +bool TravelPath::makeShortCut(WorldPosition startPos, float maxDist, Unit* bot) { if (GetPath().empty()) return false; @@ -691,10 +691,10 @@ bool TravelPath::makeShortCut(WorldPosition startPos, float maxDist) for (auto& p : fullPath) // cycle over the full path { - // if (p.point.GetMapId() != startPos.GetMapId()) - // continue; - - if (p.point.GetMapId() == startPos.GetMapId()) + // Walkability filter (cmangos parity): portals/transports/taxis + // aren't valid anchor points — picking one as the new start of + // the trimmed path would leave the bot anchored on a hop. + if (p.point.GetMapId() == startPos.GetMapId() && p.isWalkable()) { float curDist = p.point.sqDistance(startPos); @@ -737,8 +737,10 @@ bool TravelPath::makeShortCut(WorldPosition startPos, float maxDist) WorldPosition beginPos = newPath.begin()->point; - // The old path seems to be the best. - if (beginPos.distance(firstNode) < sPlayerbotAIConfig.tooCloseDistance) + // The old path seems to be the best — either the closest walkable + // point IS the original front, or it's within tooCloseDistance. + if (newPath.front() == fullPath.front() || + beginPos.distance(firstNode) < sPlayerbotAIConfig.tooCloseDistance) return false; // We are (nearly) on the new path. Just follow the rest. @@ -748,7 +750,11 @@ bool TravelPath::makeShortCut(WorldPosition startPos, float maxDist) return true; } - std::vector toPath = startPos.getPathTo(beginPos, nullptr); + // Pass the bot into getPathTo so PathGenerator picks up its + // collision / swimming / flying flags. cmangos parity — passing + // nullptr here drops to a default mover and can produce a path + // the bot itself can't actually walk. + std::vector toPath = startPos.getPathTo(beginPos, bot); // We can not reach the new begin position. Follow the complete path. if (!beginPos.isPathTo(toPath)) diff --git a/src/Mgr/Travel/TravelNode.h b/src/Mgr/Travel/TravelNode.h index e37abd251..86e08137e 100644 --- a/src/Mgr/Travel/TravelNode.h +++ b/src/Mgr/Travel/TravelNode.h @@ -427,6 +427,16 @@ struct PathNodePoint WorldPosition point; PathNodeType type = PathNodeType::NODE_PATH; uint32 entry = 0; + + bool operator==(const PathNodePoint& p1) const + { + return point == p1.point && type == p1.type && entry == p1.entry; + } + // A "walkable" node is one we traverse on foot. Portals/transports/ + // taxis/teleports are entry/exit hops, not points to anchor a + // shortcut on. Used by makeShortCut to skip them when picking the + // closest-point-on-path to the bot. + bool isWalkable() const { return (uint8)type <= (uint8)PathNodeType::NODE_NODE; } }; // A complete list of points the bots has to walk to or teleport to. @@ -481,7 +491,7 @@ public: return retVec; } - bool makeShortCut(WorldPosition startPos, float maxDist); + bool makeShortCut(WorldPosition startPos, float maxDist, Unit* bot = nullptr); std::ostringstream const print();