From e3ec6d01c6012cfe0b96211bb6a56ac5d3c5a2fd Mon Sep 17 00:00:00 2001 From: bash Date: Thu, 14 May 2026 21:56:54 +0200 Subject: [PATCH] fix(Core/Travel): LOS check before trusting raw cmangos waypoints --- src/Ai/Base/Actions/MovementActions.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Ai/Base/Actions/MovementActions.cpp b/src/Ai/Base/Actions/MovementActions.cpp index c5154cb12..df08b6382 100644 --- a/src/Ai/Base/Actions/MovementActions.cpp +++ b/src/Ai/Base/Actions/MovementActions.cpp @@ -3234,14 +3234,29 @@ bool MovementAction::RefineWalkPoints(std::vector& walkPoints) // active. When AC mmap can't validate the segment (empty // result, or IsPathCheating rejects a 2-point shortcut / // steep hop), fall back to dispatching the raw (A, B) pair - // instead of aborting the plan. Common cases: cmangos - // waypoints landing in 1y navmesh gaps from AC extractor - // differences, tile-edge artifacts at zone borders. - bool const trustRaw = segPath.empty() || + // instead of aborting the plan — but only if vmap LOS is + // clear between A and B. Without LOS check, "trust raw" + // tunnels through visual-only obstacles (trees, models) that + // aren't in the navmesh. + bool const mmapFail = segPath.empty() || TravelPath::IsPathCheating(segPath, aPos.distance(bPos)); - if (trustRaw) + if (mmapFail) { + Map* m = bot->GetMap(); + bool const inLos = m && m->isInLineOfSight( + a.x, a.y, a.z + 1.0f, + b.x, b.y, b.z + 1.0f, + bot->GetPhaseMask(), LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::Nothing); + + if (!inLos) + { + // Visual obstacle between A and B — don't tunnel. + // Abort the plan so MoveFarTo can re-derive a route + // that mmap can verify. + return false; + } + if (i == 0) refined.emplace_back(a); refined.emplace_back(b);