diff --git a/src/Ai/Base/Actions/MovementActions.cpp b/src/Ai/Base/Actions/MovementActions.cpp index 287f7ca24..8cf3320d7 100644 --- a/src/Ai/Base/Actions/MovementActions.cpp +++ b/src/Ai/Base/Actions/MovementActions.cpp @@ -3069,11 +3069,7 @@ TravelPath MovementAction::ResolveMovePath(WorldPosition const& startPos, if (needsLongPath && !sTravelNodeMap.getNodes().empty() && !bot->InBattleground()) { - // Wrap the legacy TravelPlan-populating call; the steps field on - // TravelPlan IS a TravelPath, so extract it directly. - TravelPlan tmp; - if (sTravelNodeMap.GetFullPath(tmp, startPos, bot->GetZoneId(), endPos, bot)) - out = tmp.steps; + out = sTravelNodeMap.GetFullPath(startPos, bot->GetZoneId(), endPos, bot); } else { diff --git a/src/Ai/World/Rpg/NewRpgInfo.cpp b/src/Ai/World/Rpg/NewRpgInfo.cpp index 59eaca93f..562aaea35 100644 --- a/src/Ai/World/Rpg/NewRpgInfo.cpp +++ b/src/Ai/World/Rpg/NewRpgInfo.cpp @@ -77,7 +77,6 @@ void NewRpgInfo::Reset() { data = Idle{}; startT = getMSTime(); - ClearTravel(); } NewRpgStatus NewRpgInfo::GetStatus() diff --git a/src/Ai/World/Rpg/NewRpgInfo.h b/src/Ai/World/Rpg/NewRpgInfo.h index 97f0d107d..b1cbb9222 100644 --- a/src/Ai/World/Rpg/NewRpgInfo.h +++ b/src/Ai/World/Rpg/NewRpgInfo.h @@ -78,11 +78,6 @@ struct NewRpgInfo uint32 startT{0}; // start timestamp of the current status - // Travel Node System - TravelPlan travelPlan; - bool HasActiveTravelPlan() const { return travelPlan.IsActive(); } - void ClearTravel() { travelPlan.Reset(); } - using RpgData = std::variant< Idle, GoGrind, diff --git a/src/Mgr/Travel/TravelNode.cpp b/src/Mgr/Travel/TravelNode.cpp index 009938fe7..9de265deb 100644 --- a/src/Mgr/Travel/TravelNode.cpp +++ b/src/Mgr/Travel/TravelNode.cpp @@ -1512,23 +1512,10 @@ TravelNodeRoute TravelNodeMap::FindRouteNearestNodes(WorldPosition startPos, Wor return TravelNodeRoute(); } -bool TravelNodeMap::GetFullPath(TravelPlan& plan, - WorldPosition botPos, uint32 botZoneId, +TravelPath TravelNodeMap::GetFullPath(WorldPosition botPos, uint32 botZoneId, WorldPosition destination, Unit* bot) { - // Capture previous pathToStart from the about-to-be-reset plan so we - // can try cropPathTo to reuse it across the per-tick re-resolve. - std::vector prevPathToStart; - for (auto const& pt : plan.steps.GetPathRef()) - { - if (pt.type == PathNodeType::NODE_PREPATH) - prevPathToStart.push_back(pt.point); - else - break; // PREPATH is always at the head - } - - plan.Reset(); - plan.destination = destination; + TravelPath path; // mmap-probe first: if a 40-step probe makes meaningful progress, // prefer it over the graph. Loosened from "reaches within spellDistance" @@ -1556,10 +1543,10 @@ bool TravelNodeMap::GetFullPath(TravelPlan& plan, if (closeEnough || meaningfulProgress) { - plan.steps.addPoint(botPos, PathNodeType::NODE_PREPATH); + path.addPoint(botPos, PathNodeType::NODE_PREPATH); for (size_t i = 1; i < probe.size(); ++i) - plan.steps.addPoint(probe[i], PathNodeType::NODE_PATH); - return true; + path.addPoint(probe[i], PathNodeType::NODE_PATH); + return path; } } } @@ -1595,7 +1582,7 @@ bool TravelNodeMap::GetFullPath(TravelPlan& plan, std::vector endCandidates = pickKNearest(destination, destZone); if (startCandidates.empty() || endCandidates.empty()) - return false; + return path; // empty TravelNode* startNode = nullptr; TravelNode* endNode = nullptr; @@ -1621,24 +1608,14 @@ bool TravelNodeMap::GetFullPath(TravelPlan& plan, } if (route.isEmpty() || !startNode || !endNode) - return false; + return path; // empty WorldPosition startNodePos = *startNode->getPosition(); WorldPosition endNodePos = *endNode->getPosition(); - // pathToStart: mmap-path from bot to the first node. Try cropping - // the previous pathToStart first (cmangos parity) — if it still - // reaches the chosen startNode within reactDistance we avoid a full - // re-probe. Falls back to fresh getPathTo if crop fails or invalid. + // pathToStart: fresh mmap-path from bot to the first node. std::vector pathToStart; - if (!prevPathToStart.empty()) - { - std::vector cropped = prevPathToStart; - bool ok = startNodePos.cropPathTo(cropped, sPlayerbotAIConfig.reactDistance); - if (ok && cropped.size() >= 2) - pathToStart = cropped; - } - if (pathToStart.empty() && bot && botPos.GetMapId() == startNodePos.GetMapId()) + if (bot && botPos.GetMapId() == startNodePos.GetMapId()) { std::vector probe = botPos.getPathTo(startNodePos, bot); if (probe.size() >= 2) @@ -1663,9 +1640,9 @@ bool TravelNodeMap::GetFullPath(TravelPlan& plan, if (pathToEnd.empty()) pathToEnd = {destination}; - plan.steps = route.BuildPath(pathToStart, pathToEnd, nullptr); + path = route.BuildPath(pathToStart, pathToEnd, nullptr); - return !plan.steps.empty(); + return path; } bool TravelNodeMap::cropUselessNode(TravelNode* startNode) diff --git a/src/Mgr/Travel/TravelNode.h b/src/Mgr/Travel/TravelNode.h index 0b6a47b6c..09634859b 100644 --- a/src/Mgr/Travel/TravelNode.h +++ b/src/Mgr/Travel/TravelNode.h @@ -68,7 +68,9 @@ // // GetFullPath finds nearest nodes (zone-indexed), runs A* to get a node route, then // BuildPath assembles a flat TravelPath with typed waypoints (walk, portal, transport, flight). -// ExecuteTravelPlan iterates the path by stepIdx, dispatching on each point's PathNodeType. +// MoveFarTo re-resolves a fresh TravelPath each tick; UpcommingSpecialMovement cuts +// to the head segment when special; HandleSpecialMovement dispatches the matching +// action (portal interact, area-trigger marker, transport board, flight taxi). // Cross-map travel is handled naturally by portal/transport edges in the A* graph. // // If setup cannot resolve (no node, no route, no flight), the bot teleports directly to the destination @@ -585,34 +587,6 @@ public: uint32 currentGold = 0; }; -struct TravelPlan -{ - WorldPosition destination; - - // Flat waypoint path built upfront by GetFullPath: - TravelPath steps; - uint32 stepIdx{0}; - - // Spline scratch (used by executor): - std::vector walkPoints; - uint32 expectedDuration{0}; // used to derive the lastMove delay - - // Taxi scratch: - std::vector route; - - bool IsActive() const { return !steps.empty(); } - - void Reset() - { - destination = WorldPosition(); - steps.clear(); - stepIdx = 0; - walkPoints.clear(); - expectedDuration = 0; - route.clear(); - } -}; - // The container of all nodes. class TravelNodeMap { @@ -742,8 +716,11 @@ public: // empty static vector for unknown zones. std::vector const& GetNodesInZone(uint32 zoneId) const; - bool GetFullPath(TravelPlan& plan, WorldPosition botPos, - uint32 botZoneId, WorldPosition destination, Unit* bot = nullptr); + // Resolve a full TravelPath from botPos to destination. Returns an + // empty TravelPath if no graph route + mmap stitch is reachable; + // the caller is then expected to fall back to a single-point path. + TravelPath GetFullPath(WorldPosition botPos, uint32 botZoneId, + WorldPosition destination, Unit* bot = nullptr); // Resolve A* route between two world positions (returns node vector) std::vector ResolveRoute(WorldPosition startPos,