From f2de90e74c71d218a19b2cc130cef34fbf19a40e Mon Sep 17 00:00:00 2001 From: luis Date: Thu, 12 Mar 2026 21:35:53 -0300 Subject: [PATCH] CRITICAL FIX: Correct destination Z to ground level to prevent flying or underground movement --- .../Playerbot/Movement/BotMovementUtil.cpp | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/modules/Playerbot/Movement/BotMovementUtil.cpp b/src/modules/Playerbot/Movement/BotMovementUtil.cpp index d5b9444a7..23595dd84 100644 --- a/src/modules/Playerbot/Movement/BotMovementUtil.cpp +++ b/src/modules/Playerbot/Movement/BotMovementUtil.cpp @@ -189,6 +189,15 @@ bool BotMovementUtil::MoveToPosition(Player* bot, Position const& destination, u bot->GetName(), distToDestination2D, distToDestination3D, zDifference, minDistanceChange, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); + // CRITICAL FIX: Correct destination Z to ground level to prevent flying or underground movement + Position correctedDestination = destination; + CorrectPositionToGround(bot, correctedDestination); + + // Recalculate distances with corrected Z + distToDestination2D = bot->GetExactDist2d(correctedDestination.GetPositionX(), correctedDestination.GetPositionY()); + distToDestination3D = bot->GetExactDist(correctedDestination); + zDifference = std::abs(bot->GetPositionZ() - correctedDestination.GetPositionZ()); + // MINE/CAVE FIX: Use 3D distance for "already at destination" check // This ensures bots will still move if there's significant vertical distance // even if horizontal distance is small (e.g., mine entrance above spawn inside) @@ -277,9 +286,9 @@ bool BotMovementUtil::MoveToPosition(Player* bot, Position const& destination, u if (splineDestination != G3D::Vector3::zero()) { float splineDestDist = std::sqrt( - (splineDestination.x - destination.GetPositionX()) * (splineDestination.x - destination.GetPositionX()) + - (splineDestination.y - destination.GetPositionY()) * (splineDestination.y - destination.GetPositionY()) + - (splineDestination.z - destination.GetPositionZ()) * (splineDestination.z - destination.GetPositionZ()) + (splineDestination.x - correctedDestination.GetPositionX()) * (splineDestination.x - correctedDestination.GetPositionX()) + + (splineDestination.y - correctedDestination.GetPositionY()) * (splineDestination.y - correctedDestination.GetPositionY()) + + (splineDestination.z - correctedDestination.GetPositionZ()) * (splineDestination.z - correctedDestination.GetPositionZ()) ); // If spline destination is close to requested destination (< 10 yards), let it continue @@ -295,7 +304,7 @@ bool BotMovementUtil::MoveToPosition(Player* bot, Position const& destination, u TC_LOG_DEBUG("module.playerbot.movement", "🔄 BotMovement: Bot {} spline going WRONG DIRECTION! Spline dest ({:.1f},{:.1f},{:.1f}) is {:.1f}yd from requested ({:.1f},{:.1f},{:.1f}) - INTERRUPTING", bot->GetName(), splineDestination.x, splineDestination.y, splineDestination.z, splineDestDist, - destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); + correctedDestination.GetPositionX(), correctedDestination.GetPositionY(), correctedDestination.GetPositionZ()); // Fall through to start new movement } } @@ -326,12 +335,12 @@ bool BotMovementUtil::MoveToPosition(Player* bot, Position const& destination, u // MotionMaster::MovePoint() is the safer approach, and we maintain deduplication above // by checking if a spline is already active before calling this. TC_LOG_DEBUG("module.playerbot.movement", "🚶 BotMovement: Bot {} STARTING MOVEMENT to ({:.2f},{:.2f},{:.2f}) - {:.1f}yd (3D)", - bot->GetName(), destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ(), + bot->GetName(), correctedDestination.GetPositionX(), correctedDestination.GetPositionY(), correctedDestination.GetPositionZ(), distToDestination3D); // Use MotionMaster for thread-safe movement initiation // The deduplication check above prevents the "60+ MovePoint calls/second" bug - mm->MovePoint(pointId, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); + mm->MovePoint(pointId, correctedDestination.GetPositionX(), correctedDestination.GetPositionY(), correctedDestination.GetPositionZ()); return true; }