mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
refactor(Core/Travel): Drop TravelPlan struct; GetFullPath returns TravelPath
This commit is contained in:
parent
7ab57c184e
commit
3952ebff6e
@ -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
|
||||
{
|
||||
|
||||
@ -77,7 +77,6 @@ void NewRpgInfo::Reset()
|
||||
{
|
||||
data = Idle{};
|
||||
startT = getMSTime();
|
||||
ClearTravel();
|
||||
}
|
||||
|
||||
NewRpgStatus NewRpgInfo::GetStatus()
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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<WorldPosition> 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<TravelNode*> 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<WorldPosition> pathToStart;
|
||||
if (!prevPathToStart.empty())
|
||||
{
|
||||
std::vector<WorldPosition> 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<WorldPosition> 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)
|
||||
|
||||
@ -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<G3D::Vector3> walkPoints;
|
||||
uint32 expectedDuration{0}; // used to derive the lastMove delay
|
||||
|
||||
// Taxi scratch:
|
||||
std::vector<uint32> 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<TravelNode*> 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<TravelNode*> ResolveRoute(WorldPosition startPos,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user