mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
Compare commits
2 Commits
1e07ef3d02
...
1ee7d5fdfe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ee7d5fdfe | ||
|
|
1e55842c36 |
@ -226,73 +226,66 @@ TravelNodePath* TravelNode::BuildPath(TravelNode* endNode, Unit* bot, bool postP
|
|||||||
|
|
||||||
bool canPath = endPos->isPathTo(path); // Check if we reached our destination.
|
bool canPath = endPos->isPathTo(path); // Check if we reached our destination.
|
||||||
|
|
||||||
// Reject long final segments. Catches both BuildShortcut 2-point
|
// Walk → portal/transport cheat: forward stalled but we got within
|
||||||
// teleports (start → end straight line) and chained-probe stalls
|
// 20y of the dest. Add a midpoint waypoint (if the gap is >1y) plus
|
||||||
// where mmap "teleported" to the destination as the final waypoint
|
// the endpoint and accept. Must run before the IsPathCheating 2-point
|
||||||
// after the chain dead-ended. Bot would air-walk that jump.
|
// reject so the appended points lift size above 2.
|
||||||
if (canPath && path.size() >= 2 && path[path.size() - 2].distance(&path.back()) > 75.0f)
|
if (!canPath && !isTransport() && !isPortal() &&
|
||||||
canPath = false;
|
(endNode->isPortal() || endNode->isTransport()))
|
||||||
|
{
|
||||||
|
if (endPos->isPathTo(path, 20.0f))
|
||||||
|
{
|
||||||
|
if (path.back().distance(endPos) > 1.0f)
|
||||||
|
{
|
||||||
|
float mx = (endPos->GetPositionX() + path.back().GetPositionX()) * 0.5f;
|
||||||
|
float my = (endPos->GetPositionY() + path.back().GetPositionY()) * 0.5f;
|
||||||
|
float mz = (endPos->GetPositionZ() + path.back().GetPositionZ()) * 0.5f;
|
||||||
|
path.emplace_back(endPos->GetMapId(), mx, my, mz);
|
||||||
|
}
|
||||||
|
path.push_back(*endPos);
|
||||||
|
canPath = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reject too-short or too-steep results — geometry shortcut that
|
// Reject too-short or too-steep results — geometry shortcut that
|
||||||
// mmap returns but a player can't actually walk.
|
// mmap returns but a player can't actually walk.
|
||||||
if (canPath && TravelPath::IsPathCheating(path, getPosition()->distance(endNode->getPosition())))
|
if (canPath && TravelPath::IsPathCheating(path, getPosition()->distance(endNode->getPosition())))
|
||||||
canPath = false;
|
canPath = false;
|
||||||
|
|
||||||
if (!canPath && endNode->hasLinkTo(this)) // Unable to find a path? See if the reverse is possible.
|
// Persist the partial forward attempt before we try the reverse —
|
||||||
|
// the recursive endNode->BuildPath below may itself check our state.
|
||||||
|
returnNodePath->setPath(path);
|
||||||
|
returnNodePath->setComplete(canPath);
|
||||||
|
|
||||||
|
// Ensure the reverse path exists, recursively building it if needed.
|
||||||
|
// The recursion is bounded: BuildPath returns immediately when the
|
||||||
|
// reverse path is already marked complete.
|
||||||
|
TravelNodePath* backNodePath = nullptr;
|
||||||
|
if (!endNode->hasPathTo(this))
|
||||||
|
backNodePath = endNode->BuildPath(this, bot, postProcess);
|
||||||
|
else
|
||||||
|
backNodePath = endNode->getPathTo(this);
|
||||||
|
|
||||||
|
// Forward attempt failed — try to salvage with the reverse:
|
||||||
|
// * if the reverse is complete, flip it and use it
|
||||||
|
// * if the reverse is also partial but the two partials end near
|
||||||
|
// each other (<5y), stitch them into one path
|
||||||
|
if (!canPath && backNodePath)
|
||||||
{
|
{
|
||||||
TravelNodePath backNodePath = *endNode->getPathTo(this);
|
std::vector<WorldPosition> backPath = backNodePath->GetPath();
|
||||||
|
if (!backPath.empty())
|
||||||
if (backNodePath.getPathType() == TravelNodePathType::walk)
|
|
||||||
{
|
{
|
||||||
std::vector<WorldPosition> bPath = backNodePath.GetPath();
|
if (backNodePath->getComplete())
|
||||||
|
|
||||||
if (!backNodePath.getComplete()) // Build it if it's not already complete.
|
|
||||||
{
|
{
|
||||||
if (bPath.empty())
|
std::reverse(backPath.begin(), backPath.end());
|
||||||
bPath = {*endNode->getPosition()}; // Start the path from the end Node.
|
path = backPath;
|
||||||
|
|
||||||
WorldPosition* thisPos = getPosition(); // Build the path to this Node.
|
|
||||||
|
|
||||||
bPath = thisPos->getPathFromPath(bPath, bot); // Pathfind from the existing path to the this Node.
|
|
||||||
|
|
||||||
canPath = thisPos->isPathTo(bPath); // Check if we reached our destination.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
canPath = true;
|
canPath = true;
|
||||||
|
|
||||||
if (canPath)
|
|
||||||
{
|
|
||||||
std::reverse(bPath.begin(), bPath.end());
|
|
||||||
path = bPath;
|
|
||||||
}
|
}
|
||||||
}
|
else if (!path.empty() && path.back().distance(&backPath.back()) < 5.0f)
|
||||||
}
|
|
||||||
|
|
||||||
// Transports are (probably?) not solid at this moment. We need to walk over them so we need extra code for this.
|
|
||||||
// Some portals are 'too' solid so we can't properly walk in them. Again we need to bypass this.
|
|
||||||
if (!isTransport() && !isPortal() && (endNode->isPortal() || endNode->isTransport()))
|
|
||||||
{
|
|
||||||
if (endNode->isTransport() && path.back().isInWater()) // Do not swim to boats.
|
|
||||||
canPath = false;
|
|
||||||
else if (!canPath && endPos->isPathTo(path, 20.0f)) // Cheat a little for transports and portals.
|
|
||||||
{
|
|
||||||
path.push_back(*endPos);
|
|
||||||
canPath = true;
|
|
||||||
|
|
||||||
if (!endNode->hasPathTo(this) || !endNode->getPathTo(this)->getComplete())
|
|
||||||
{
|
{
|
||||||
std::vector<WorldPosition> reversePath = path;
|
std::reverse(backPath.begin(), backPath.end());
|
||||||
std::reverse(reversePath.begin(), reversePath.end());
|
path.insert(path.end(), backPath.begin(), backPath.end());
|
||||||
|
canPath = true;
|
||||||
TravelNodePath* backNodePath = endNode->setPathTo(this, TravelNodePath(), false);
|
|
||||||
|
|
||||||
backNodePath->setComplete(canPath);
|
|
||||||
|
|
||||||
endNode->setLinkTo(this, true);
|
|
||||||
|
|
||||||
backNodePath->setPath(reversePath);
|
|
||||||
|
|
||||||
backNodePath->calculateCost(!postProcess);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user