mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
refactor(Core/Movement): DispatchPathPoints → DispatchMovement (TravelPath sig + transport sandwich)
This commit is contained in:
parent
d00ad8d327
commit
dae09388ad
@ -338,7 +338,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
|||||||
|
|
||||||
// Path-aware funnel: ResolveMovePath → makeShortCut →
|
// Path-aware funnel: ResolveMovePath → makeShortCut →
|
||||||
// UpcommingSpecialMovement/HandleSpecialMovement → ClipPath →
|
// UpcommingSpecialMovement/HandleSpecialMovement → ClipPath →
|
||||||
// DispatchPathPoints. Matches the reference's MoveTo2 flow.
|
// DispatchMovement. Matches the reference's MoveTo2 flow.
|
||||||
return MoveTo2(WorldPosition(mapId, x, y, z),
|
return MoveTo2(WorldPosition(mapId, x, y, z),
|
||||||
idle, react, false, ignoreEnemyTargets, priority, lessDelay);
|
idle, react, false, ignoreEnemyTargets, priority, lessDelay);
|
||||||
}
|
}
|
||||||
@ -2993,12 +2993,7 @@ bool MovementAction::MoveTo2(WorldPosition endPos,
|
|||||||
botAI->TellMasterNoFacing(tlog);
|
botAI->TellMasterNoFacing(tlog);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<WorldPosition> const& pts = path.getPointPath();
|
if (path.empty())
|
||||||
Movement::PointsArray points;
|
|
||||||
points.reserve(pts.size());
|
|
||||||
for (auto const& wp : pts)
|
|
||||||
points.emplace_back(wp.GetPositionX(), wp.GetPositionY(), wp.GetPositionZ());
|
|
||||||
if (points.empty())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!bot->IsMounted() && !bot->IsInCombat() &&
|
if (!bot->IsMounted() && !bot->IsInCombat() &&
|
||||||
@ -3006,7 +3001,7 @@ bool MovementAction::MoveTo2(WorldPosition endPos,
|
|||||||
botAI->DoSpecificAction("check mount state", Event(), true);
|
botAI->DoSpecificAction("check mount state", Event(), true);
|
||||||
|
|
||||||
bool const dispatched =
|
bool const dispatched =
|
||||||
DispatchPathPoints(endPos, points, "walk", priority, lessDelay);
|
DispatchMovement(path, endPos, "walk", priority, lessDelay);
|
||||||
|
|
||||||
if (dispatched && !idle)
|
if (dispatched && !idle)
|
||||||
ClearIdleState();
|
ClearIdleState();
|
||||||
@ -3014,12 +3009,20 @@ bool MovementAction::MoveTo2(WorldPosition endPos,
|
|||||||
return dispatched;
|
return dispatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MovementAction::DispatchPathPoints(WorldPosition const& dest,
|
bool MovementAction::DispatchMovement(TravelPath const& path,
|
||||||
Movement::PointsArray& points,
|
WorldPosition const& dest,
|
||||||
char const* label,
|
char const* label,
|
||||||
MovementPriority priority,
|
MovementPriority priority,
|
||||||
bool lessDelay)
|
bool lessDelay)
|
||||||
{
|
{
|
||||||
|
// Build the PointsArray from the TravelPath. Done here (not at the
|
||||||
|
// caller) so DispatchMovement can be invoked with a TravelPath
|
||||||
|
// directly, matching the reference's signature.
|
||||||
|
std::vector<WorldPosition> const& pts = path.getPointPath();
|
||||||
|
Movement::PointsArray points;
|
||||||
|
points.reserve(pts.size());
|
||||||
|
for (auto const& wp : pts)
|
||||||
|
points.emplace_back(wp.GetPositionX(), wp.GetPositionY(), wp.GetPositionZ());
|
||||||
if (points.empty())
|
if (points.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -3080,11 +3083,22 @@ bool MovementAction::DispatchPathPoints(WorldPosition const& dest,
|
|||||||
if (bot->IsNonMeleeSpellCast(true))
|
if (bot->IsNonMeleeSpellCast(true))
|
||||||
bot->InterruptNonMeleeSpells(true);
|
bot->InterruptNonMeleeSpells(true);
|
||||||
|
|
||||||
// Per-point terrain clamp.
|
// Per-point terrain clamp with transport-passenger conversion
|
||||||
|
// sandwich: when on a transport, path coords are in transport-local
|
||||||
|
// space; UpdateAllowedPositionZ samples world terrain, so we convert
|
||||||
|
// local→world, snap, world→local. Without the sandwich, snapping a
|
||||||
|
// transport-relative point against world terrain produces garbage.
|
||||||
|
Transport* transport = bot->GetTransport();
|
||||||
for (auto& pt : points)
|
for (auto& pt : points)
|
||||||
|
{
|
||||||
|
if (transport)
|
||||||
|
transport->CalculatePassengerPosition(pt.x, pt.y, pt.z);
|
||||||
bot->UpdateAllowedPositionZ(pt.x, pt.y, pt.z);
|
bot->UpdateAllowedPositionZ(pt.x, pt.y, pt.z);
|
||||||
|
if (transport)
|
||||||
|
transport->CalculatePassengerOffset(pt.x, pt.y, pt.z);
|
||||||
|
}
|
||||||
|
|
||||||
// mm.Clear → MovePoint(last) → MoveSplinePath → WaitForReach.
|
// mm.Clear → MovePoint(last) → MoveSplinePath.
|
||||||
MotionMaster* mm = bot->GetMotionMaster();
|
MotionMaster* mm = bot->GetMotionMaster();
|
||||||
mm->Clear();
|
mm->Clear();
|
||||||
|
|
||||||
@ -3102,7 +3116,8 @@ bool MovementAction::DispatchPathPoints(WorldPosition const& dest,
|
|||||||
|
|
||||||
// WaitForReach equivalent: cache the dispatched target + duration on
|
// WaitForReach equivalent: cache the dispatched target + duration on
|
||||||
// lastMove. Leave ~10y headroom on long paths so we re-evaluate
|
// lastMove. Leave ~10y headroom on long paths so we re-evaluate
|
||||||
// before arrival.
|
// before arrival. (Reference also calls WaitForReach here, which
|
||||||
|
// blocks the AI loop; we omit that — see header comment.)
|
||||||
float waitDist = totalDist > sPlayerbotAIConfig.reactDistance
|
float waitDist = totalDist > sPlayerbotAIConfig.reactDistance
|
||||||
? std::max(totalDist - 10.0f, 0.0f) : totalDist;
|
? std::max(totalDist - 10.0f, 0.0f) : totalDist;
|
||||||
UnitMoveType const speedType = (moveMode == FORCED_MOVEMENT_WALK) ? MOVE_WALK : MOVE_RUN;
|
UnitMoveType const speedType = (moveMode == FORCED_MOVEMENT_WALK) ? MOVE_WALK : MOVE_RUN;
|
||||||
|
|||||||
@ -65,7 +65,7 @@ protected:
|
|||||||
// with makeShortCut, handles special head segments
|
// with makeShortCut, handles special head segments
|
||||||
// (portal/area-trigger/transport/flight) via HandleSpecialMovement,
|
// (portal/area-trigger/transport/flight) via HandleSpecialMovement,
|
||||||
// clips at hostile creatures via ClipPath (unless ignoreEnemyTargets),
|
// clips at hostile creatures via ClipPath (unless ignoreEnemyTargets),
|
||||||
// and dispatches the resulting walk via DispatchPathPoints.
|
// and dispatches the resulting walk via DispatchMovement.
|
||||||
// MoveTo(mapId,...) delegates here unless an intentional bypass
|
// MoveTo(mapId,...) delegates here unless an intentional bypass
|
||||||
// (exact_waypoint / disableMoveSplinePath / flying / swimming /
|
// (exact_waypoint / disableMoveSplinePath / flying / swimming /
|
||||||
// backwards) routes the move straight to DoMovePoint.
|
// backwards) routes the move straight to DoMovePoint.
|
||||||
@ -75,16 +75,27 @@ protected:
|
|||||||
MovementPriority priority = MovementPriority::MOVEMENT_NORMAL,
|
MovementPriority priority = MovementPriority::MOVEMENT_NORMAL,
|
||||||
bool lessDelay = false);
|
bool lessDelay = false);
|
||||||
|
|
||||||
// Centralized walk dispatch. Applies inactive-bot teleport carve-out,
|
// Centralized walk dispatch. Mirrors the reference's DispatchMovement
|
||||||
// masterWalking mode, pre-dispatch state cleanup (clear emote, stand,
|
// shape: takes a TravelPath, builds the PointsArray internally,
|
||||||
// interrupt cast), per-point UpdateAllowedPositionZ, mm.Clear →
|
// applies inactive-bot teleport carve-out, masterWalking mode,
|
||||||
// MovePoint(last) → MoveSplinePath, and a WaitForReach equivalent
|
// pre-dispatch state cleanup (clear emote, stand, interrupt cast),
|
||||||
// that caches the destination + duration on lastMove.
|
// transport-passenger coordinate sandwich
|
||||||
bool DispatchPathPoints(WorldPosition const& dest,
|
// (CalculatePassengerPosition → UpdateAllowedPositionZ → Offset)
|
||||||
Movement::PointsArray& points,
|
// around the per-point Z snap, mm.Clear → MovePoint(last) →
|
||||||
char const* label,
|
// MoveSplinePath. Caches the destination + duration on lastMove.
|
||||||
MovementPriority priority = MovementPriority::MOVEMENT_NORMAL,
|
//
|
||||||
bool lessDelay = false);
|
// Divergence from reference: reference ends with WaitForReach(size)
|
||||||
|
// which blocks the AI loop until the move completes. AC's combat
|
||||||
|
// callers (ReachCombatTo) currently funnel through MoveTo → MoveTo2
|
||||||
|
// → DispatchMovement; blocking the AI loop here would suspend combat
|
||||||
|
// re-evaluation for the full move duration. Until combat dispatch is
|
||||||
|
// restructured to bypass MoveTo2, the WaitForReach is deliberately
|
||||||
|
// omitted.
|
||||||
|
bool DispatchMovement(TravelPath const& path,
|
||||||
|
WorldPosition const& dest,
|
||||||
|
char const* label,
|
||||||
|
MovementPriority priority = MovementPriority::MOVEMENT_NORMAL,
|
||||||
|
bool lessDelay = false);
|
||||||
bool MoveTo(WorldObject* target, float distance = 0.0f,
|
bool MoveTo(WorldObject* target, float distance = 0.0f,
|
||||||
MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
||||||
bool MoveNear(WorldObject* target, float distance = sPlayerbotAIConfig.contactDistance,
|
bool MoveNear(WorldObject* target, float distance = sPlayerbotAIConfig.contactDistance,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user