mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
fix(Core/Travel): Path-type bitmask, loop-breaker convergence, LaunchWalkSpline LOS-cull
This commit is contained in:
parent
b7437170b4
commit
10495682a7
@ -3232,39 +3232,6 @@ bool MovementAction::LaunchWalkSpline(TravelPlan& state)
|
||||
for (auto& pt : state.walkPoints)
|
||||
bot->UpdateAllowedPositionZ(pt.x, pt.y, pt.z);
|
||||
|
||||
// Drop waypoints whose segment from the previous point crosses
|
||||
// solid geometry. Z-snapping each point to ground is necessary
|
||||
// but not sufficient — two ground-level waypoints A and B with a
|
||||
// mountain between them produce a spline that linearly
|
||||
// interpolates straight through the mountain. vmap LoS check on
|
||||
// each segment catches that. We only drop the offending B
|
||||
// (skipping it) — if A→C is also blocked, the loop drops C too,
|
||||
// until either the path becomes contiguous or empties out.
|
||||
if (Map* losMap = bot->GetMap())
|
||||
{
|
||||
uint32 const phaseMask = bot->GetPhaseMask();
|
||||
for (size_t i = 1; i < state.walkPoints.size(); /* incremented in body */)
|
||||
{
|
||||
G3D::Vector3 const& a = state.walkPoints[i - 1];
|
||||
G3D::Vector3 const& b = state.walkPoints[i];
|
||||
// +2y on Z so the raycast starts/ends near the bot's
|
||||
// chest level rather than ground (avoids false positives
|
||||
// from sub-floor poly).
|
||||
if (!losMap->isInLineOfSight(a.x, a.y, a.z + 2.0f, b.x, b.y, b.z + 2.0f,
|
||||
phaseMask, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::Nothing))
|
||||
{
|
||||
state.walkPoints.erase(state.walkPoints.begin() + i);
|
||||
continue;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (state.walkPoints.size() < 2)
|
||||
{
|
||||
state.walkPoints.clear();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Mount up
|
||||
if (!bot->IsMounted() && !bot->IsInCombat() && bot->IsOutdoors() && bot->IsAlive())
|
||||
botAI->DoSpecificAction("check mount state", Event(), true);
|
||||
|
||||
@ -78,12 +78,25 @@ void NewRpgInfo::Reset()
|
||||
data = Idle{};
|
||||
startT = getMSTime();
|
||||
ClearTravel();
|
||||
recentMoveFarAttempts.clear();
|
||||
// recentMoveFarAttempts is intentionally NOT cleared. Reset() runs
|
||||
// on every state change (ChangeToDoQuest, ChangeToIdle, etc.) and
|
||||
// the do-quest action oscillates through transitions during a
|
||||
// failure cycle — wiping the deque here would prevent the
|
||||
// MoveFarTo loop-breaker (nF >= 3 AND mF >= 3 → bothExhausted)
|
||||
// from converging. CountRecentAttempts already filters by
|
||||
// destination (within 10y), so stale entries for previous quests
|
||||
// don't affect new ones.
|
||||
}
|
||||
|
||||
void NewRpgInfo::RecordMoveFarAttempt(WorldPosition const& dest, bool wasNodeTravel)
|
||||
{
|
||||
if (recentMoveFarAttempts.size() >= 3)
|
||||
// Cap at 6 (3 node + 3 mmap). The loop-breaker in MoveFarTo
|
||||
// requires nF >= 3 AND mF >= 3 to declare bothExhausted. Each
|
||||
// MoveFarTo failure cycle records BOTH a node attempt and a mmap
|
||||
// attempt, so a single 3-cap deque would pop the older type
|
||||
// before its count reached 3, structurally preventing
|
||||
// bothExhausted from triggering.
|
||||
if (recentMoveFarAttempts.size() >= 6)
|
||||
recentMoveFarAttempts.pop_front();
|
||||
MoveFarAttempt a;
|
||||
a.dest = dest;
|
||||
|
||||
@ -739,7 +739,14 @@ std::vector<WorldPosition> WorldPosition::getPathStepFrom(WorldPosition startPos
|
||||
if (tempCreature)
|
||||
delete tempCreature;
|
||||
|
||||
if (type == PATHFIND_INCOMPLETE || type == PATHFIND_NORMAL)
|
||||
// PathType is a bitmask (PathGenerator.h). Detour can return e.g.
|
||||
// PATHFIND_INCOMPLETE | PATHFIND_FARFROMPOLY_END (0x84) when the
|
||||
// destination is a few yards off the nearest polygon — a strict
|
||||
// `== PATHFIND_INCOMPLETE` check would reject the perfectly usable
|
||||
// partial path and the chained probe would terminate empty on the
|
||||
// very first call. PathGenerator's own internal code uses bitwise
|
||||
// tests like `!(_type & PATHFIND_INCOMPLETE)`.
|
||||
if (type & (PATHFIND_NORMAL | PATHFIND_INCOMPLETE))
|
||||
return fromPointsArray(points);
|
||||
|
||||
return {};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user