fix(Core/Travel): Port cmangos makeShortCut walkability filter and bot context

This commit is contained in:
bash 2026-05-08 23:25:43 +02:00
parent 6021e397f5
commit 0e053d456a
3 changed files with 26 additions and 10 deletions

View File

@ -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

View File

@ -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<WorldPosition> 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<WorldPosition> toPath = startPos.getPathTo(beginPos, bot);
// We can not reach the new begin position. Follow the complete path.
if (!beginPos.isPathTo(toPath))

View File

@ -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();