229 lines
7.0 KiB
Markdown
229 lines
7.0 KiB
Markdown
# Phase 2D: TargetSelector.cpp Cleanup - Complete ✅
|
||||
|
|
|
|||
|
|
**Date**: 2025-10-25
|
|||
|
|
**Status**: ✅ COMPLETE - Minor cleanup applied
|
|||
|
|
**File**: `src/modules/Playerbot/AI/Combat/TargetSelector.cpp`
|
|||
|
|
**Build Result**: Zero errors, warnings only (C4100 unreferenced parameters)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Executive Summary
|
|||
|
|
|
|||
|
|
TargetSelector.cpp was found to be **already well-optimized** with snapshot-first validation patterns labeled "PHASE 5B" (likely from an earlier optimization effort). Only minor cleanup was performed to remove redundant alive checks and update phase labels for consistency.
|
|||
|
|
|
|||
|
|
### Key Results:
|
|||
|
|
- **ObjectAccessor calls**: 4 → 4 (no reduction - already optimized)
|
|||
|
|
- **Redundant checks removed**: 3 IsAlive() calls eliminated
|
|||
|
|
- **Phase labels updated**: PHASE 5B → PHASE 2D (consistency)
|
|||
|
|
- **Build status**: Clean compilation, zero errors
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Changes Made
|
|||
|
|
|
|||
|
|
### 1. Removed Redundant IsAlive() Checks
|
|||
|
|
|
|||
|
|
**Functions Updated**:
|
|||
|
|
- `GetNearbyEnemies()` - Lines 479-480
|
|||
|
|
- `GetNearestEnemy()` - Lines 831-833
|
|||
|
|
- `GetWeakestEnemy()` - Lines 862-864
|
|||
|
|
|
|||
|
|
**Pattern**:
|
|||
|
|
|
|||
|
|
**Before**:
|
|||
|
|
```cpp
|
|||
|
|
// Validate with snapshot
|
|||
|
|
auto snapshot = SpatialGridQueryHelpers::FindHostileCreaturesInRange(...);
|
|||
|
|
// ... loop through snapshots
|
|||
|
|
|
|||
|
|
// Get Unit*
|
|||
|
|
Unit* unit = ObjectAccessor::GetUnit(*bot, snapshot->guid);
|
|||
|
|
if (unit && unit->IsAlive()) // CHECK #1 (snapshot) + CHECK #2 (redundant!)
|
|||
|
|
enemies.push_back(unit);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**After**:
|
|||
|
|
```cpp
|
|||
|
|
// PHASE 2D: Thread-safe spatial grid query
|
|||
|
|
auto snapshot = SpatialGridQueryHelpers::FindHostileCreaturesInRange(...);
|
|||
|
|
// ... loop through snapshots (only alive creatures returned)
|
|||
|
|
|
|||
|
|
// PHASE 2D: Snapshot already validated IsAlive(), only null check needed
|
|||
|
|
Unit* unit = ObjectAccessor::GetUnit(*bot, snapshot->guid);
|
|||
|
|
if (unit) // Only null check needed
|
|||
|
|
enemies.push_back(unit);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Impact**: Eliminates 3 redundant IsAlive() checks per call to these functions.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 2. Updated Phase Labels
|
|||
|
|
|
|||
|
|
**Changed**: All "PHASE 5B" comments → "PHASE 2D"
|
|||
|
|
|
|||
|
|
**Affected Lines**: 469, 503, 817, 848
|
|||
|
|
|
|||
|
|
**Reason**: Consistency with current Phase 2D work.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 3. Fourth Function Already Correct
|
|||
|
|
|
|||
|
|
**GetNearbyAllies()** - Lines 510-531:
|
|||
|
|
This function was already correct - no redundant IsAlive() check present.
|
|||
|
|
|
|||
|
|
**Analysis**:
|
|||
|
|
- Line 513: `if (!snapshot.IsAlive() || snapshot.isHostile)` - snapshot validation
|
|||
|
|
- Line 517-519: Gets Unit* and only checks for null
|
|||
|
|
- No redundant check to remove
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Analysis Findings
|
|||
|
|
|
|||
|
|
### Why No ObjectAccessor Reduction?
|
|||
|
|
|
|||
|
|
All 4 ObjectAccessor calls were **already necessary**:
|
|||
|
|
|
|||
|
|
1. **All 4 calls return Unit* or std::vector<Unit*>** - API contract requires Unit* pointers
|
|||
|
|
2. **All 4 calls already use snapshot-first validation** - Pre-validate before ObjectAccessor
|
|||
|
|
3. **FindHostileCreaturesInRange() only returns alive creatures** - IsAlive() check was redundant
|
|||
|
|
|
|||
|
|
### Functions That MUST Call ObjectAccessor
|
|||
|
|
|
|||
|
|
- `GetNearbyEnemies()` - Returns std::vector<Unit*>
|
|||
|
|
- `GetNearbyAllies()` - Returns std::vector<Unit*>
|
|||
|
|
- `GetNearestEnemy()` - Returns Unit*
|
|||
|
|
- `GetWeakestEnemy()` - Returns Unit*
|
|||
|
|
|
|||
|
|
All these functions have API contracts that require Unit* pointers, not snapshots.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Performance Impact
|
|||
|
|
|
|||
|
|
### ObjectAccessor Call Frequency
|
|||
|
|
|
|||
|
|
**Before**: 4 calls per selection × 10-20 Hz = 40-80 calls/sec
|
|||
|
|
**After**: 4 calls per selection × 10-20 Hz = 40-80 calls/sec
|
|||
|
|
**Reduction**: 0 calls/sec (file already optimized)
|
|||
|
|
|
|||
|
|
### Redundant Check Elimination
|
|||
|
|
|
|||
|
|
**Before**: 3 IsAlive() checks per returned entity (in 3 of 4 functions)
|
|||
|
|
**After**: 0 IsAlive() checks per returned entity (snapshot validation only)
|
|||
|
|
**Benefit**: Minor CPU savings in IsAlive() validation
|
|||
|
|
|
|||
|
|
**FPS Impact**: <0.5% (micro-optimization, not measurable)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Roadmap Discrepancy
|
|||
|
|
|
|||
|
|
### Expected vs. Actual
|
|||
|
|
|
|||
|
|
**Roadmap Estimate** (PHASE2_NEXT_STEPS_ROADMAP.md):
|
|||
|
|
- Expected reduction: 3-4 calls (75-100%)
|
|||
|
|
- Expected FPS impact: Part of 8-12% Phase 2D gain
|
|||
|
|
|
|||
|
|
**Actual Result**:
|
|||
|
|
- Actual reduction: 0 calls (0%)
|
|||
|
|
- Actual FPS impact: <0.5% (redundant check cleanup only)
|
|||
|
|
|
|||
|
|
**Root Cause**: File had already been optimized in "PHASE 5B" (previous work).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Build Validation
|
|||
|
|
|
|||
|
|
### Build Command
|
|||
|
|
```bash
|
|||
|
|
cd /c/TrinityBots/TrinityCore/build
|
|||
|
|
cmake --build . --target worldserver --config RelWithDebInfo -- -m
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Build Result
|
|||
|
|
```
|
|||
|
|
playerbot.vcxproj -> C:\TrinityBots\TrinityCore\build\src\server\modules\Playerbot\RelWithDebInfo\playerbot.lib
|
|||
|
|
worldserver.vcxproj -> C:\TrinityBots\TrinityCore\build\bin\RelWithDebInfo\worldserver.exe
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Warnings (Non-blocking)
|
|||
|
|
- C4100: Unreferenced parameters (context)
|
|||
|
|
|
|||
|
|
### Compilation Errors
|
|||
|
|
✅ **ZERO ERRORS**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Lessons Learned
|
|||
|
|
|
|||
|
|
### 1. File Already Optimized
|
|||
|
|
TargetSelector.cpp had already undergone snapshot optimization in a previous effort (labeled "PHASE 5B"). This confirms the pattern seen in BotThreatManager.cpp - multiple files were already optimized in previous work.
|
|||
|
|
|
|||
|
|
### 2. API Contracts Limit Optimization
|
|||
|
|
Functions that return `std::vector<Unit*>` or `Unit*` MUST call ObjectAccessor because callers expect pointers, not snapshots. These are **necessary ObjectAccessor calls**.
|
|||
|
|
|
|||
|
|
### 3. Snapshot-First Pattern is Correct
|
|||
|
|
The existing pattern in the file is correct:
|
|||
|
|
```cpp
|
|||
|
|
// 1. Validate with snapshot (lock-free)
|
|||
|
|
auto snapshot = SpatialGridQueryHelpers::FindHostileCreaturesInRange(...);
|
|||
|
|
|
|||
|
|
// 2. Only get Unit* when snapshot confirms entity exists
|
|||
|
|
Unit* target = ObjectAccessor::GetUnit(...);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
This is the optimal pattern for functions that must return Unit*.
|
|||
|
|
|
|||
|
|
### 4. FindHostileCreaturesInRange Returns Only Alive Entities
|
|||
|
|
The spatial grid query already filters for alive entities, making additional IsAlive() checks redundant. This is a key insight for cleanup work.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Comparison to Similar Files
|
|||
|
|
|
|||
|
|
### Pattern Recognition: Already Optimized Files
|
|||
|
|
|
|||
|
|
Both **BotThreatManager.cpp** and **TargetSelector.cpp** share the same characteristics:
|
|||
|
|
|
|||
|
|
1. **Already labeled "PHASE 5B"** - Previous optimization effort
|
|||
|
|
2. **Already use snapshot-first validation** - Correct pattern in place
|
|||
|
|
3. **Return Unit* or vector<Unit*>** - Cannot eliminate ObjectAccessor
|
|||
|
|
4. **Had redundant IsAlive() checks** - Minor cleanup opportunity
|
|||
|
|
|
|||
|
|
**Conclusion**: Multiple combat files were already optimized in a previous "PHASE 5B" effort.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Conclusion
|
|||
|
|
|
|||
|
|
TargetSelector.cpp required only **minor cleanup** (remove 3 redundant checks, update 4 labels). The file is already well-optimized with snapshot-first validation patterns.
|
|||
|
|
|
|||
|
|
**Key Takeaway**: Not all files in Phase 2D require extensive migration - some are already optimized. Focus effort on files with genuine optimization opportunities.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Next Steps
|
|||
|
|
|
|||
|
|
Move to the next file in Phase 2D priority:
|
|||
|
|
|
|||
|
|
1. ✅ **ThreatCoordinator.cpp** (23 calls) - COMPLETE (65% reduction)
|
|||
|
|
2. ✅ **BotThreatManager.cpp** (14 calls) - COMPLETE (cleanup only)
|
|||
|
|
3. ✅ **GroupCombatTrigger.cpp** (5 calls) - COMPLETE (40% reduction)
|
|||
|
|
4. ✅ **TargetSelector.cpp** (4 calls) - COMPLETE (cleanup only)
|
|||
|
|
5. ⏳ **TargetScanner.cpp** (3 calls) - NEXT
|
|||
|
|
6. ⏳ **LineOfSightManager.cpp** (3 calls)
|
|||
|
|
7. ⏳ **InterruptAwareness.cpp** (3 calls)
|
|||
|
|
8. ⏳ **CombatBehaviorIntegration.cpp** (3 calls)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**Status**: ✅ TARGETSELECTOR COMPLETE (Cleanup Only)
|
|||
|
|
**Next**: TargetScanner.cpp (3 calls)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**End of TargetSelector.cpp Summary**
|