18 KiB
Phase 5 Systems - ClassAI Integration Guide
Overview
The Phase 5 systems (ActionPriorityQueue, BehaviorTree, ActionScoringEngine) are currently not populated with actual spell data. Each ClassAI needs to be updated to register spells and create behavior trees.
Current Status: ❌ Systems are empty (infrastructure exists but no data) Required: ✅ Populate systems during spec initialization
Integration Points
1. ActionPriorityQueue - Spell Registration
Location: InitializeRotation() or constructor
Purpose: Register all spells with priorities and conditions
Pattern:
void InitializeArmsRotation()
{
BotAI* ai = this->GetBot()->GetBotAI();
if (!ai)
return;
auto* queue = ai->GetActionPriorityQueue();
if (!queue)
return;
// Register spells with priorities
queue->RegisterSpell(SPELL_EXECUTE,
SpellPriority::EMERGENCY,
SpellCategory::DAMAGE_SINGLE);
queue->RegisterSpell(SPELL_MORTAL_STRIKE,
SpellPriority::HIGH,
SpellCategory::DAMAGE_SINGLE);
queue->RegisterSpell(SPELL_COLOSSUS_SMASH,
SpellPriority::CRITICAL,
SpellCategory::OFFENSIVE);
// Add conditions
queue->AddCondition(SPELL_EXECUTE,
[](Player* bot, Unit* target) {
return target && target->GetHealthPct() < 20.0f;
},
"Target HP < 20%");
queue->AddCondition(SPELL_OVERPOWER,
[](Player* bot, Unit*) {
return bot->HasAura(SPELL_OVERPOWER_PROC);
},
"Overpower proc active");
}
2. BehaviorTree - Tree Creation
Location: InitializeRotation() or constructor
Purpose: Create hierarchical decision tree for combat flow
Pattern:
void InitializeArmsRotation()
{
using namespace bot::ai;
using namespace bot::ai::BehaviorTreeBuilder;
BotAI* ai = this->GetBot()->GetBotAI();
if (!ai)
return;
auto* tree = ai->GetBehaviorTree();
if (!tree)
return;
// Create Arms Warrior behavior tree
auto root = Selector("Arms Rotation", {
// Emergency Execute Phase
Sequence("Execute Phase", {
Condition("Target < 20% HP", [](Player* bot, Unit* target) {
return target && target->GetHealthPct() < 20.0f;
}),
Selector("Execute Priority", {
Action("Cast Execute", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_EXECUTE))
{
this->CastSpell(target, SPELL_EXECUTE);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
}),
Action("Cast Mortal Strike", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_MORTAL_STRIKE))
{
this->CastSpell(target, SPELL_MORTAL_STRIKE);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
})
})
}),
// Standard Rotation
Sequence("Standard Rotation", {
// Maintain Colossus Smash debuff
Selector("Maintain CS", {
Condition("CS Active", [this](Player* bot, Unit* target) {
return target && target->HasAura(SPELL_COLOSSUS_SMASH);
}),
Action("Cast Colossus Smash", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_COLOSSUS_SMASH))
{
this->CastSpell(target, SPELL_COLOSSUS_SMASH);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
})
}),
// Cast Mortal Strike
Action("Cast Mortal Strike", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_MORTAL_STRIKE))
{
this->CastSpell(target, SPELL_MORTAL_STRIKE);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
}),
// Cast Overpower with proc
Sequence("Overpower on Proc", {
Condition("Has Overpower Proc", [this](Player* bot, Unit*) {
return bot->HasAura(SPELL_OVERPOWER_PROC);
}),
Action("Cast Overpower", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_OVERPOWER))
{
this->CastSpell(target, SPELL_OVERPOWER);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
})
})
})
});
tree->SetRoot(root);
}
Complete Arms Warrior Integration Example
Here's the complete code to add to ArmsWarriorRefactored.h:
void InitializeArmsRotation()
{
using namespace bot::ai;
using namespace bot::ai::BehaviorTreeBuilder;
// Setup any Arms-specific initialization
_tacticalMasteryRage = 0;
// ========================================================================
// PHASE 5 INTEGRATION: ActionPriorityQueue
// ========================================================================
BotAI* ai = this->GetBot()->GetBotAI();
if (!ai)
return;
auto* queue = ai->GetActionPriorityQueue();
if (queue)
{
// Emergency spells
queue->RegisterSpell(SPELL_EXECUTE, SpellPriority::EMERGENCY, SpellCategory::DAMAGE_SINGLE);
queue->AddCondition(SPELL_EXECUTE,
[](Player* bot, Unit* target) {
return target && target->GetHealthPct() < 20.0f;
},
"Target HP < 20% (Execute range)");
// Critical cooldowns
queue->RegisterSpell(SPELL_COLOSSUS_SMASH, SpellPriority::CRITICAL, SpellCategory::OFFENSIVE);
queue->RegisterSpell(SPELL_BLADESTORM, SpellPriority::CRITICAL, SpellCategory::DAMAGE_AOE);
queue->RegisterSpell(SPELL_AVATAR, SpellPriority::CRITICAL, SpellCategory::OFFENSIVE);
// High priority core rotation
queue->RegisterSpell(SPELL_MORTAL_STRIKE, SpellPriority::HIGH, SpellCategory::DAMAGE_SINGLE);
queue->RegisterSpell(SPELL_OVERPOWER, SpellPriority::HIGH, SpellCategory::DAMAGE_SINGLE);
queue->AddCondition(SPELL_OVERPOWER,
[](Player* bot, Unit*) {
return bot->HasAura(SPELL_OVERPOWER_PROC);
},
"Overpower proc active");
// Medium priority
queue->RegisterSpell(SPELL_WHIRLWIND, SpellPriority::MEDIUM, SpellCategory::DAMAGE_AOE);
queue->AddCondition(SPELL_WHIRLWIND,
[](Player* bot, Unit* target) {
// Use Whirlwind for AoE situations
return bot->GetAttackersCount() >= 3;
},
"3+ targets (AoE)");
queue->RegisterSpell(SPELL_REND, SpellPriority::MEDIUM, SpellCategory::DAMAGE_SINGLE);
queue->AddCondition(SPELL_REND,
[](Player* bot, Unit* target) {
return target && !target->HasAura(SPELL_REND);
},
"Rend not active on target");
// Low priority fillers
queue->RegisterSpell(SPELL_HEROIC_STRIKE, SpellPriority::LOW, SpellCategory::DAMAGE_SINGLE);
queue->RegisterSpell(SPELL_CLEAVE, SpellPriority::LOW, SpellCategory::DAMAGE_AOE);
TC_LOG_INFO("module.playerbot", "⚔️ ARMS WARRIOR: Registered {} spells in ActionPriorityQueue",
queue->GetSpellCount());
}
// ========================================================================
// PHASE 5 INTEGRATION: BehaviorTree
// ========================================================================
auto* behaviorTree = ai->GetBehaviorTree();
if (behaviorTree)
{
auto root = Selector("Arms Warrior Combat", {
// ============================================================
// 1. EXECUTE PHASE (Target < 20% HP)
// ============================================================
Sequence("Execute Phase", {
Condition("Target < 20% HP", [](Player* bot, Unit* target) {
return target && target->GetHealthPct() < 20.0f;
}),
Selector("Execute Priority", {
Action("Cast Execute", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_EXECUTE))
{
this->CastSpell(target, SPELL_EXECUTE);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
}),
Action("Cast Mortal Strike (Execute Phase)", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_MORTAL_STRIKE))
{
this->CastSpell(target, SPELL_MORTAL_STRIKE);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
})
})
}),
// ============================================================
// 2. COOLDOWN USAGE (Boss fights, burst windows)
// ============================================================
Sequence("Use Major Cooldowns", {
Condition("Should use cooldowns", [](Player* bot, Unit* target) {
// Use cooldowns on bosses or when target has >500k HP
return target && (target->GetCreatureType() == CREATURE_TYPE_HUMANOID ||
target->GetMaxHealth() > 500000);
}),
Selector("Cooldown Priority", {
Action("Cast Avatar", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(bot, SPELL_AVATAR))
{
this->CastSpell(bot, SPELL_AVATAR);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
}),
Action("Cast Bladestorm", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(bot, SPELL_BLADESTORM))
{
this->CastSpell(bot, SPELL_BLADESTORM);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
})
})
}),
// ============================================================
// 3. STANDARD ROTATION
// ============================================================
Sequence("Standard Rotation", {
// Maintain Colossus Smash debuff
Selector("Maintain Colossus Smash", {
Condition("CS Active", [](Player* bot, Unit* target) {
return target && target->HasAura(SPELL_COLOSSUS_SMASH);
}),
Action("Cast Colossus Smash", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_COLOSSUS_SMASH))
{
this->CastSpell(target, SPELL_COLOSSUS_SMASH);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
})
}),
// Cast Mortal Strike on cooldown
Selector("Mortal Strike", {
Action("Cast Mortal Strike", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_MORTAL_STRIKE))
{
this->CastSpell(target, SPELL_MORTAL_STRIKE);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
})
}),
// Cast Overpower on proc
Sequence("Overpower on Proc", {
Condition("Has Overpower Proc", [](Player* bot, Unit*) {
return bot->HasAura(SPELL_OVERPOWER_PROC);
}),
Action("Cast Overpower", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_OVERPOWER))
{
this->CastSpell(target, SPELL_OVERPOWER);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
})
}),
// Filler spells
Selector("Filler", {
Action("Cast Whirlwind (AoE)", [this](Player* bot, Unit* target) {
if (bot->GetAttackersCount() >= 3 && this->CanCastSpell(target, SPELL_WHIRLWIND))
{
this->CastSpell(target, SPELL_WHIRLWIND);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
}),
Action("Cast Heroic Strike", [this](Player* bot, Unit* target) {
if (this->CanCastSpell(target, SPELL_HEROIC_STRIKE))
{
this->CastSpell(target, SPELL_HEROIC_STRIKE);
return NodeStatus::SUCCESS;
}
return NodeStatus::FAILURE;
})
})
})
});
behaviorTree->SetRoot(root);
TC_LOG_INFO("module.playerbot", "🌲 ARMS WARRIOR: BehaviorTree initialized with hierarchical combat flow");
}
}
Required Includes
Add these includes to the ClassAI header file:
#include "../Decision/ActionPriorityQueue.h"
#include "../Decision/BehaviorTree.h"
#include "../BotAI.h"
Integration Checklist for Each Class
✅ Required Steps:
- Add includes (ActionPriorityQueue.h, BehaviorTree.h, BotAI.h)
- Get BotAI via
this->GetBot()->GetBotAI() - Register spells in ActionPriorityQueue with:
- Appropriate priority (EMERGENCY → OPTIONAL)
- Correct category (DAMAGE_SINGLE, DEFENSIVE, etc.)
- Conditional logic (procs, health thresholds, etc.)
- Create behavior tree with:
- Execute phase handling
- Cooldown usage
- Standard rotation
- Filler spells
- Test that decisions are being made by DecisionFusion
⚠️ Important Notes:
- ActionScoringEngine will automatically score spells from ActionPriorityQueue
- DecisionFusion will collect votes from all 3 systems
- No changes needed to DecisionFusion itself - it already integrates
Classes Requiring Integration
| Class | Priority | Specs |
|---|---|---|
| Warrior | High | Arms, Fury, Protection |
| Paladin | High | Holy, Protection, Retribution |
| Priest | High | Discipline, Holy, Shadow |
| Mage | Medium | Arcane, Fire, Frost |
| Warlock | Medium | Affliction, Demonology, Destruction |
| Rogue | Medium | Assassination, Combat, Subtlety |
| Hunter | Medium | Beast Mastery, Marksmanship, Survival |
| Druid | Medium | Balance, Feral, Guardian, Restoration |
| Shaman | Medium | Elemental, Enhancement, Restoration |
| Death Knight | Low | Blood, Frost, Unholy |
| Monk | Low | Brewmaster, Mistweaver, Windwalker |
| Demon Hunter | Low | Havoc, Vengeance |
| Evoker | Low | Devastation, Preservation |
Performance Impact
Per-Spec Cost:
- ActionPriorityQueue registration: One-time ~0.1ms
- BehaviorTree creation: One-time ~0.2ms
- Runtime overhead: <0.1ms per decision
Total: ~0.3ms one-time initialization per bot
Testing Integration
After integration, verify:
# Run unit tests
cd build
ctest -R Phase5
# Enable debug logging in game
.playerbot debug fusion 1
.playerbot debug priority 1
.playerbot debug behavior 1
# Spawn test bot
.playerbot add <name>
# Check logs for:
# ⚔️ ARMS WARRIOR: Registered X spells in ActionPriorityQueue
# 🌲 ARMS WARRIOR: BehaviorTree initialized with hierarchical combat flow
Example Output (Expected)
INFO: ⚔️ ARMS WARRIOR: Registered 11 spells in ActionPriorityQueue
INFO: 🌲 ARMS WARRIOR: BehaviorTree initialized with hierarchical combat flow
INFO: 🎯 DECISION FUSION: Collecting votes for TestBot
DEBUG: DecisionFusion: Vote from ActionPriority - Mortal Strike (confidence: 0.8, urgency: 0.7)
DEBUG: DecisionFusion: Vote from BehaviorTree - Mortal Strike (confidence: 0.9, urgency: 0.8)
DEBUG: DecisionFusion: Vote from ActionScoring - Mortal Strike (score: 387.5, confidence: 0.77)
INFO: 🎯 DECISION FUSION: Recommended action 12294 (Mortal Strike) - 3 votes, confidence 0.85
Next Steps
- ✅ Update Arms Warrior (example provided above)
- ⏳ Update Fury Warrior (similar pattern)
- ⏳ Update Protection Warrior (add defensive priorities)
- ⏳ Update remaining 10 classes (39 total specs)
Questions?
- Review:
/home/user/TrinityCore/PHASE5_PHASE6_COMPLETION_SUMMARY.md - Unit Tests:
/home/user/TrinityCore/tests/Phase5/ - API Docs: Header files in
src/modules/Playerbot/AI/Decision/
Remember: The infrastructure is complete. Now we just need to populate it with spell data!