From 007f866cbf44d49af6f2c3955d3677bca8ad0a55 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 22 Jul 2026 09:07:02 -0300 Subject: [PATCH] fix(Core/Movement): let melee pets attack targets whose chase point is unpathable (#26726) --- .../TargetedMovementGenerator.cpp | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 188578ea0..1747d75c3 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -104,15 +104,40 @@ bool ChaseMovementGenerator::DispatchSplineToPosition(T* owner, float x, floa if (owner->IsHovering()) owner->UpdateAllowedPositionZ(x, y, z); - bool success = i_path->CalculatePath(x, y, z, forceDest); - uint32 pathType = i_path->GetPathType(); - bool pathFailed = !success || (pathType & PATHFIND_NOPATH); + auto isPathUsable = [&]() + { + uint32 pathType = i_path->GetPathType(); + if (pathType & PATHFIND_NOPATH) + return false; - // For pets, treat incomplete paths as failures to avoid clipping through geometry - // Players and Player-controlled units have more erratic movement, skip failure - if (cOwner && (cOwner->IsPet() || cOwner->IsControlledByPlayer()) && !GetTarget()->IsCharmedOwnedByPlayerOrPlayer()) - if (pathType & PATHFIND_INCOMPLETE) - pathFailed = true; + // For pets, treat incomplete paths as failures to avoid clipping through geometry + // Players and Player-controlled units have more erratic movement, skip failure + if (cOwner && (cOwner->IsPet() || cOwner->IsControlledByPlayer()) + && !GetTarget()->IsCharmedOwnedByPlayerOrPlayer()) + if (pathType & PATHFIND_INCOMPLETE) + return false; + + return true; + }; + + bool pathFailed = !i_path->CalculatePath(x, y, z, forceDest) || !isPathUsable(); + + // Targets with an oversized combat reach can stand entirely over unwalkable space + // (e.g. Kologarn) so pathing to their center or to an angled near point (pets chase + // to behind the target, which may hang over the void) fails even though the melee + // ring covers the navmesh. Retry against the nearest point on the ring, ignoring the + // chase angle, via GetNearPoint2D: GetNearPoint's LoS repositioning must be avoided + // here, it can rotate the point to the far side of the target. + if (pathFailed && (!_range || _range->MaxRange <= CONTACT_DISTANCE) + && !GetTarget()->IsCharmedOwnedByPlayerOrPlayer() && GetTarget()->GetCombatReach() > NOMINAL_MELEE_RANGE) + { + GetTarget()->GetNearPoint2D(owner, x, y, 0.0f, GetTarget()->GetAngle(owner)); + z = GetTarget()->GetPositionZ(); + owner->UpdateAllowedPositionZ(x, y, z); + pathFailed = !i_path->CalculatePath(x, y, z, forceDest) || !isPathUsable(); + // the destination already lies on the melee ring, nothing to cut + cutPath = false; + } if (pathFailed) {