mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
fix(Core/RPG): Drop over-strict MoveFarTo and MoveWorldObjectTo guards
This commit is contained in:
parent
f868b6f96b
commit
721f81a119
@ -217,26 +217,10 @@ bool NewRpgBaseAction::MoveFarTo(WorldPosition dest)
|
|||||||
// Walk the chained probe's full waypoint chain via DispatchPathPoints.
|
// Walk the chained probe's full waypoint chain via DispatchPathPoints.
|
||||||
if (!probe.empty() && probe.size() >= 2)
|
if (!probe.empty() && probe.size() >= 2)
|
||||||
{
|
{
|
||||||
WorldPosition stepDest = probe.back();
|
float endDistToDest = dest.GetExactDist(probe.back().GetPositionX(),
|
||||||
float endDistToDest = dest.GetExactDist(stepDest.GetPositionX(),
|
probe.back().GetPositionY(), probe.back().GetPositionZ());
|
||||||
stepDest.GetPositionY(), stepDest.GetPositionZ());
|
|
||||||
if (endDistToDest + 5.0f < disToDest)
|
if (endDistToDest + 5.0f < disToDest)
|
||||||
{
|
{
|
||||||
// Z gap check: if the probe's last waypoint is well below
|
|
||||||
// the requested destination Z, the chain walked the ground
|
|
||||||
// polygon graph toward an elevated target it can't reach
|
|
||||||
// (quest giver on top of Aldrassil etc.). Refuse to dispatch
|
|
||||||
// — bot waits instead of tunneling into the visual model.
|
|
||||||
// 10y tolerates normal terrain variation (ramp ends, hill
|
|
||||||
// tops) while still catching clearly unreachable elevations.
|
|
||||||
if (std::fabs(stepDest.GetPositionZ() - dest.GetPositionZ()) > 10.0f)
|
|
||||||
{
|
|
||||||
EmitDebugMove("MoveFar", "z-mismatch",
|
|
||||||
dest.GetPositionX(), dest.GetPositionY(),
|
|
||||||
dest.GetPositionZ());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Movement::PointsArray points;
|
Movement::PointsArray points;
|
||||||
points.reserve(probe.size());
|
points.reserve(probe.size());
|
||||||
for (auto const& wp : probe)
|
for (auto const& wp : probe)
|
||||||
@ -253,39 +237,18 @@ bool NewRpgBaseAction::MoveFarTo(WorldPosition dest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Probe failed or didn't progress — emit visibility whisper so
|
// Probe failed or didn't progress. Emit visibility whisper and bail.
|
||||||
// the user can see WHY mmap didn't dispatch.
|
// No straight-line fallback: dispatching a single-waypoint MoveTo
|
||||||
{
|
// here delegates to the engine's PointMovementGenerator, which on
|
||||||
bool const probeProgressed = !probe.empty() && probe.size() >= 2 &&
|
// PATHFIND_NOPATH issues a straight-line spline through any terrain.
|
||||||
(dest.GetExactDist(probe.back().GetPositionX(),
|
// That caused bots to tunnel into mountains/trees when the chained
|
||||||
probe.back().GetPositionY(), probe.back().GetPositionZ()) + 5.0f < disToDest);
|
// probe couldn't find a valid path. Better to return false and let
|
||||||
if (!probeProgressed)
|
// the caller pick a different objective.
|
||||||
{
|
|
||||||
char const* reason = (probe.empty() || probe.size() < 2) ? "mmap-empty" : "mmap-noprogress";
|
char const* reason = (probe.empty() || probe.size() < 2) ? "mmap-empty" : "mmap-noprogress";
|
||||||
EmitDebugMove("MoveFar", reason,
|
EmitDebugMove("MoveFar", reason,
|
||||||
dest.GetPositionX(), dest.GetPositionY(),
|
dest.GetPositionX(), dest.GetPositionY(),
|
||||||
dest.GetPositionZ());
|
dest.GetPositionZ());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty-probe fallback: single-waypoint MoveTo via engine PathGenerator.
|
|
||||||
// Cross-map can't be served by a single-map spline — bail.
|
|
||||||
if (bot->GetMapId() != dest.GetMapId())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// LOS gate: don't air-walk through trees/walls when the engine
|
|
||||||
// would otherwise drop to a straight-line BuildShortcut spline.
|
|
||||||
if (!bot->IsWithinLOS(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ()))
|
|
||||||
{
|
|
||||||
EmitDebugMove("MoveFar", "spline-blocked",
|
|
||||||
dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmitDebugMove("MoveFar", "spline",
|
|
||||||
dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
|
|
||||||
return MoveTo(dest.GetMapId(), dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(),
|
|
||||||
false, false, false, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NewRpgBaseAction::DispatchPathPoints(WorldPosition const& dest,
|
bool NewRpgBaseAction::DispatchPathPoints(WorldPosition const& dest,
|
||||||
@ -562,16 +525,18 @@ bool NewRpgBaseAction::MoveWorldObjectTo(ObjectGuid guid, float distance)
|
|||||||
float y = object->GetPositionY() + std::sin(angle) * distance;
|
float y = object->GetPositionY() + std::sin(angle) * distance;
|
||||||
float z = object->GetPositionZ();
|
float z = object->GetPositionZ();
|
||||||
|
|
||||||
// LOS check at eye height — bot must be able to reach the candidate.
|
// Candidate must have LOS to the GO — otherwise the bot would
|
||||||
if (!bot->IsWithinLOS(x, y, z + bot->GetCollisionHeight()))
|
// arrive at a spot where it can't interact (e.g., a tree stands
|
||||||
continue;
|
// between candidate and GO). Without this, the first angle
|
||||||
|
// (toward the bot) wins and lands the bot up against the
|
||||||
// Candidate must also have LOS to the GO itself — otherwise the
|
|
||||||
// bot arrives at a spot where it can't interact (e.g., a tree
|
|
||||||
// stands between candidate and GO). Without this, the very first
|
|
||||||
// angle (toward the bot) wins and lands the bot up against the
|
|
||||||
// obstacle instead of forcing iteration to an angle on the GO's
|
// obstacle instead of forcing iteration to an angle on the GO's
|
||||||
// far side from the blocker.
|
// far side from the blocker.
|
||||||
|
//
|
||||||
|
// Note: bot→candidate LOS is intentionally NOT checked. For
|
||||||
|
// long-distance targets (NPC across the zone, quest source
|
||||||
|
// 200y away) a direct line-of-sight through terrain almost
|
||||||
|
// always fails — bots aren't expected to see through hills.
|
||||||
|
// The mmap probe in MoveFarTo validates actual reachability.
|
||||||
if (!object->IsWithinLOS(x, y, z + bot->GetCollisionHeight()))
|
if (!object->IsWithinLOS(x, y, z + bot->GetCollisionHeight()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user