Files
ThordekkCore/docs/PHASE5_CLASSAI_INTEGRATION_GUIDE.md
T
2026-01-20 21:29:54 -03:00

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:

  1. Add includes (ActionPriorityQueue.h, BehaviorTree.h, BotAI.h)
  2. Get BotAI via this->GetBot()->GetBotAI()
  3. Register spells in ActionPriorityQueue with:
    • Appropriate priority (EMERGENCY → OPTIONAL)
    • Correct category (DAMAGE_SINGLE, DEFENSIVE, etc.)
    • Conditional logic (procs, health thresholds, etc.)
  4. Create behavior tree with:
    • Execute phase handling
    • Cooldown usage
    • Standard rotation
    • Filler spells
  5. 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

  1. ✅ Update Arms Warrior (example provided above)
  2. ⏳ Update Fury Warrior (similar pattern)
  3. ⏳ Update Protection Warrior (add defensive priorities)
  4. ⏳ 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!