# Visual Explanation: Creature Trigger Movement Fix ## The Problem (Before Fix) ### Broken Calculation ``` Bot Position A: (-8869.6, -237.9, 81.9) Target Position B: (unknown, 139.9 yards away) Safe Distance: 11 yards BROKEN CODE: angleFromBot = bot->GetRelativeAngle(targetObject) ← Angle FROM A toward B closePos = bot->GetNearPoint(bot, ..., 11yd, angleFromBot) ← Point near A RESULT: A (Bot) B (Target) o------> closePos o |________|__________________________________| 11 yards 128+ yards Bot moves to closePos (11 yards from A), but still ~128 yards from target! Next update: Same problem repeats. Bot stuck forever. ``` ### Observable Symptom ``` [Update 1] Distance: 139.9yd → Issued movement command [Update 2] Distance: 139.9yd → Issued movement command (STUCK!) [Update 3] Distance: 139.9yd → Issued movement command (STUCK!) ... infinite loop ... ``` ## The Solution (After Fix) ### Correct Calculation ``` Bot Position A: (-8869.6, -237.9, 81.9) Target Position B: (unknown, 139.9 yards away) Safe Distance: 11 yards FIXED CODE: angleFromTarget = targetObject->GetRelativeAngle(bot) ← Angle FROM B toward A closePos = targetObject->GetNearPoint(bot, ..., 11yd, angleFromTarget) ← Point near B RESULT: A (Bot) closePos B (Target) o___________________________________|------->o 128+ yards 11 yards Bot moves to closePos (11 yards from TARGET!), arrives at correct position. Next update: Distance check passes, bot uses item. SUCCESS! ``` ### Observable Behavior ``` [Update 1] Distance: 139.9yd → Issued movement command to position near target [Update 2] Distance: 100.0yd → Bot traveling (distance decreasing!) [Update 3] Distance: 60.0yd → Bot traveling [Update 4] Distance: 15.0yd → Bot arrived at closePos [Update 5] Distance: 15.0yd → Within safe range [11-30yd], using item! ``` ## Side-by-Side Code Comparison ### BEFORE (Broken) ```cpp else if (currentDistance > maxUseDistance) { TC_LOG_ERROR("...", "MOVING CLOSER"); // Misleading log // Get angle from BOT toward target float angleFromBot = bot->GetRelativeAngle(targetObject); Position closePos; // Calculate point near BOT at safe distance bot->GetNearPoint(bot, closePos.m_positionX, closePos.m_positionY, closePos.m_positionZ, safeDistance, angleFromBot); TC_LOG_ERROR("...", "Moving CLOSER to safe position ({}, {}, {}) at distance {}yd", closePos.GetPositionX(), closePos.GetPositionY(), closePos.GetPositionZ(), safeDistance); BotMovementUtil::MoveToPosition(bot, closePos); return; } ``` **Problem**: Creates position near **bot**, not near **target**! ### AFTER (Fixed) ```cpp else if (currentDistance > maxUseDistance) { TC_LOG_ERROR("...", "MOVING TOWARD TARGET"); // Accurate log // CRITICAL FIX: Calculate position FROM TARGET toward bot at safe distance // This ensures bot moves TOWARD target, not toward own position float angleFromTarget = targetObject->GetRelativeAngle(bot); Position closePos; // Calculate point near TARGET at safe distance targetObject->GetNearPoint(bot, closePos.m_positionX, closePos.m_positionY, closePos.m_positionZ, safeDistance, angleFromTarget); TC_LOG_ERROR("...", "Moving TOWARD target to safe position ({}, {}, {}) at distance {}yd from target", closePos.GetPositionX(), closePos.GetPositionY(), closePos.GetPositionZ(), safeDistance); BotMovementUtil::MoveToPosition(bot, closePos); return; } ``` **Solution**: Creates position near **target**, exactly where bot needs to be! ## API Reference ### GetRelativeAngle() Function ```cpp float WorldObject::GetRelativeAngle(WorldObject const* obj) const ``` **Returns**: Angle FROM `this` object TO `obj` (in radians) **Examples**: ```cpp float angle1 = bot->GetRelativeAngle(target); // Returns: Angle FROM bot TO target // Use case: Finding direction to face target from bot's perspective float angle2 = target->GetRelativeAngle(bot); // Returns: Angle FROM target TO bot // Use case: Finding direction from target toward bot ``` ### GetNearPoint() Function ```cpp void WorldObject::GetNearPoint(WorldObject* searcher, float& x, float& y, float& z, float distance, float angle) ``` **Creates**: A position at `distance` yards from `this` object at the given `angle` **Examples**: ```cpp Position pos1; bot->GetNearPoint(bot, pos1.m_positionX, pos1.m_positionY, pos1.m_positionZ, 10.0f, angle); // Creates: Position 10 yards from BOT at angle Position pos2; target->GetNearPoint(bot, pos2.m_positionX, pos2.m_positionY, pos2.m_positionZ, 10.0f, angle); // Creates: Position 10 yards from TARGET at angle ``` ## Geometric Explanation ### Scenario ``` Bot at coordinates: (100, 100) Target at coordinates: (200, 100) Distance between them: 100 yards Safe distance needed: 11 yards ``` ### Broken Calculation (Old Code) ``` Step 1: angleFromBot = bot->GetRelativeAngle(target) = angle from (100,100) toward (200,100) = 0 degrees (pointing east) Step 2: closePos = bot->GetNearPoint(bot, ..., 11yd, 0°) = point 11 yards east of (100,100) = (111, 100) Step 3: Bot moves from (100,100) to (111,100) New distance to target: 89 yards (still too far!) Next update: Repeat same calculation, bot moves to (122,100) Result: Bot slowly crawls toward target but takes many updates ``` ### Fixed Calculation (New Code) ``` Step 1: angleFromTarget = target->GetRelativeAngle(bot) = angle from (200,100) toward (100,100) = 180 degrees (pointing west) Step 2: closePos = target->GetNearPoint(bot, ..., 11yd, 180°) = point 11 yards west of (200,100) = (189, 100) Step 3: Bot moves from (100,100) to (189,100) New distance to target: 11 yards (PERFECT!) Next update: Distance check passes, bot uses item immediately Result: Bot travels directly to correct position in one command ``` ## Edge Cases Handled ### Case 1: Bot Too Close (Already Working) ``` Bot at 5 yards from target (minSafeDistance = 11yd) Code correctly uses: angleToBot = targetObject->GetRelativeAngle(bot); safePos = targetObject->GetNearPoint(bot, ..., safeDistance, angleToBot); Result: Bot moves AWAY from target to 11 yards Status: ✅ Already correct (unchanged by this fix) ``` ### Case 2: Bot Too Far (NOW FIXED) ``` Bot at 139.9 yards from target (maxUseDistance = 30yd) Code NOW correctly uses: angleFromTarget = targetObject->GetRelativeAngle(bot); closePos = targetObject->GetNearPoint(bot, ..., safeDistance, angleFromTarget); Result: Bot moves TOWARD target to 11 yards Status: ✅ Fixed by this change ``` ### Case 3: Bot In Range (Already Working) ``` Bot at 15 yards from target (within [11-30yd] range) Code skips movement, proceeds to item usage: - Stop movement - Face target - Cast spell from quest item - Quest progress updates Status: ✅ Already correct (unchanged by this fix) ``` ## Testing Verification ### Log Pattern Before Fix (BROKEN) ``` 📏 UseQuestItemOnTarget: Bot distance to target=139.9yd (safe range: 11.0-30.0yd) ⚠️ UseQuestItemOnTarget: Bot TOO FAR from target (139.9yd > 30.0yd) - MOVING CLOSER 🏃 UseQuestItemOnTarget: Moving CLOSER to safe position (...) at distance 11.0yd [... wait one update ...] 📏 UseQuestItemOnTarget: Bot distance to target=139.9yd (safe range: 11.0-30.0yd) ← SAME DISTANCE! ⚠️ UseQuestItemOnTarget: Bot TOO FAR from target (139.9yd > 30.0yd) - MOVING CLOSER 🏃 UseQuestItemOnTarget: Moving CLOSER to safe position (...) at distance 11.0yd [... infinite loop, quest never completes ...] ``` ### Log Pattern After Fix (WORKING) ``` 📏 UseQuestItemOnTarget: Bot distance to target=139.9yd (safe range: 11.0-30.0yd) ⚠️ UseQuestItemOnTarget: Bot TOO FAR from target (139.9yd > 30.0yd) - MOVING TOWARD TARGET 🏃 UseQuestItemOnTarget: Moving TOWARD target to safe position (...) at distance 11.0yd from target [... bot travels toward target ...] 📏 UseQuestItemOnTarget: Bot distance to target=15.0yd (safe range: 11.0-30.0yd) ✅ UseQuestItemOnTarget: Bot in safe range (15.0yd), health 100.0%, preparing to use item 🛑 UseQuestItemOnTarget: Bot stopped moving 👁️ UseQuestItemOnTarget: Bot now facing target 33737 (type: Creature) 🎯 UseQuestItemOnTarget: Casting spell 62678 on Creature ✅ Quest objective completed: 1/8 ``` ## Why This Bug Existed ### Root Cause Analysis 1. **Similar Variable Names**: `angleFromBot` vs `angleToBot` - easy to confuse 2. **Dual Context**: Code handles both "too close" and "too far" scenarios 3. **"Too Close" Was Correct**: The working code was implemented first 4. **Copy-Paste Error**: "Too far" code likely copied but not fully adapted 5. **Testing Gap**: Tests may have focused on short-distance scenarios ### Why It Wasn't Caught Earlier - Logs showed movement commands being issued (✓) - Logs showed calculated positions (✓) - BUT: No log showed distance change over time (✗) - Manual testing at close range worked fine (✓) - Long-distance testing revealed the issue (✓✓✓) ## Prevention Strategies ### Code Review Checklist - [ ] When using GetNearPoint(), verify reference object is correct - [ ] When using GetRelativeAngle(), verify FROM/TO direction is correct - [ ] Add distance delta logs: "Distance changed from X to Y" - [ ] Test both "too close" and "too far" scenarios - [ ] Test with extreme distances (100+ yards) ### Variable Naming Convention ```cpp // RECOMMENDED PATTERN: float angleFromTarget = target->GetRelativeAngle(bot); // FROM target TO bot Position posNearTarget = target->GetNearPoint(...); // Position NEAR target float angleFromBot = bot->GetRelativeAngle(target); // FROM bot TO target Position posNearBot = bot->GetNearPoint(...); // Position NEAR bot ``` --- **Date**: 2025-10-27 **Status**: ✅ DEPLOYED **Impact**: ALL creature trigger quests now work correctly