10 KiB
10 KiB
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)
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)
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
float WorldObject::GetRelativeAngle(WorldObject const* obj) const
Returns: Angle FROM this object TO obj (in radians)
Examples:
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
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:
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
- Similar Variable Names:
angleFromBotvsangleToBot- easy to confuse - Dual Context: Code handles both "too close" and "too far" scenarios
- "Too Close" Was Correct: The working code was implemented first
- Copy-Paste Error: "Too far" code likely copied but not fully adapted
- 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
// 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