# Group Event System - BotAI Integration Guide **Purpose**: This guide explains how to integrate the Group Event System with BotAI when it becomes available. --- ## ๐Ÿ“‹ Prerequisites Before integrating, ensure: - โœ… Group Event System is compiled (GroupEventBus, GroupStateMachine, GroupEventHandler, PlayerbotGroupScript) - โœ… BotAI class exists with Update() method - โœ… Bots are managed by BotSpawner or similar lifecycle manager --- ## ๐Ÿ”ง Integration Steps ### Step 1: Subscribe to Group Events (BotAI Constructor) Add event subscriptions in `BotAI::BotAI()` constructor: ```cpp // In BotAI.cpp constructor #include "Group/GroupEventBus.h" BotAI::BotAI(Player* bot) : _bot(bot) { // ... existing initialization ... // Subscribe to group events auto eventBus = Playerbot::GroupEventBus::instance(); // Subscribe to member join/leave events eventBus->Subscribe(_bot->GetGUID(), Playerbot::GroupEventType::MEMBER_JOINED, [this](Playerbot::GroupEvent const& event) { OnGroupMemberJoined(event); }); eventBus->Subscribe(_bot->GetGUID(), Playerbot::GroupEventType::MEMBER_LEFT, [this](Playerbot::GroupEvent const& event) { OnGroupMemberLeft(event); }); // Subscribe to leader change events eventBus->Subscribe(_bot->GetGUID(), Playerbot::GroupEventType::LEADER_CHANGED, [this](Playerbot::GroupEvent const& event) { OnGroupLeaderChanged(event); }); // Subscribe to loot method changes eventBus->Subscribe(_bot->GetGUID(), Playerbot::GroupEventType::LOOT_METHOD_CHANGED, [this](Playerbot::GroupEvent const& event) { OnLootMethodChanged(event); }); // Subscribe to raid conversion eventBus->Subscribe(_bot->GetGUID(), Playerbot::GroupEventType::RAID_CONVERTED, [this](Playerbot::GroupEvent const& event) { OnRaidConverted(event); }); // Subscribe to difficulty changes eventBus->Subscribe(_bot->GetGUID(), Playerbot::GroupEventType::DIFFICULTY_CHANGED, [this](Playerbot::GroupEvent const& event) { OnDifficultyChanged(event); }); // Add more subscriptions as needed... } ``` ### Step 2: Unsubscribe on Destruction (BotAI Destructor) ```cpp // In BotAI.cpp destructor BotAI::~BotAI() { // Unsubscribe from all events Playerbot::GroupEventBus::instance()->UnsubscribeAll(_bot->GetGUID()); // ... existing cleanup ... } ``` ### Step 3: Enable Per-Bot Group Polling (BotAI::Update) ```cpp // In BotAI::Update() #include "Group/PlayerbotGroupScript.h" void BotAI::Update(uint32 diff) { // ... existing update logic ... // Poll group state changes (if bot is in a group) if (Group* group = _bot->GetGroup()) { Playerbot::PlayerbotGroupScript::PollGroupStateChanges(group, diff); } // ... rest of update logic ... } ``` ### Step 4: Implement Event Handler Methods Add handler methods to BotAI class: ```cpp // In BotAI.h class BotAI { private: // Group event handlers void OnGroupMemberJoined(Playerbot::GroupEvent const& event); void OnGroupMemberLeft(Playerbot::GroupEvent const& event); void OnGroupLeaderChanged(Playerbot::GroupEvent const& event); void OnLootMethodChanged(Playerbot::GroupEvent const& event); void OnRaidConverted(Playerbot::GroupEvent const& event); void OnDifficultyChanged(Playerbot::GroupEvent const& event); // Add more as needed... }; // In BotAI.cpp void BotAI::OnGroupMemberJoined(Playerbot::GroupEvent const& event) { TC_LOG_DEBUG("bot.ai", "BotAI: Group member joined - Group: {}, Member: {}", event.groupGuid.ToString(), event.targetGuid.ToString()); // Example: Update formation when new member joins if (_combatCoordinator) _combatCoordinator->UpdateFormation(); } void BotAI::OnGroupMemberLeft(Playerbot::GroupEvent const& event) { TC_LOG_DEBUG("bot.ai", "BotAI: Group member left - Group: {}, Member: {}", event.groupGuid.ToString(), event.targetGuid.ToString()); // Example: Adjust tactics when member leaves if (_combatCoordinator) _combatCoordinator->RecalculateGroupComposition(); } void BotAI::OnGroupLeaderChanged(Playerbot::GroupEvent const& event) { TC_LOG_INFO("bot.ai", "BotAI: Group leader changed - New leader: {}", event.targetGuid.ToString()); // Example: Update assist target if leader changed if (event.targetGuid == _bot->GetGUID()) { // Bot is now the leader TC_LOG_INFO("bot.ai", "BotAI: Bot {} is now group leader", _bot->GetName()); } } void BotAI::OnLootMethodChanged(Playerbot::GroupEvent const& event) { TC_LOG_DEBUG("bot.ai", "BotAI: Loot method changed - Method: {}", event.data1); // Example: Adjust looting behavior based on loot method // data1 contains the new LootMethod value } void BotAI::OnRaidConverted(Playerbot::GroupEvent const& event) { bool isRaid = (event.data1 != 0); TC_LOG_INFO("bot.ai", "BotAI: Group converted to {} - Group: {}", isRaid ? "RAID" : "PARTY", event.groupGuid.ToString()); // Example: Switch to raid formations if converted to raid if (isRaid && _combatCoordinator) _combatCoordinator->SwitchToRaidFormation(); } void BotAI::OnDifficultyChanged(Playerbot::GroupEvent const& event) { TC_LOG_DEBUG("bot.ai", "BotAI: Difficulty changed - Difficulty: {}", event.data1); // Example: Adjust AI aggressiveness based on difficulty // data1 contains the new difficulty ID } ``` --- ## ๐ŸŽฏ Event Types and Data ### Available Events (via hooks + polling) | Event Type | Trigger | data1 | data2 | targetGuid | Description | |-----------|---------|-------|-------|------------|-------------| | MEMBER_JOINED | OnAddMember hook | - | - | Member GUID | New member joined group | | MEMBER_LEFT | OnRemoveMember hook | RemoveMethod | - | Member GUID | Member left group | | LEADER_CHANGED | OnChangeLeader hook | - | - | New leader GUID | Leadership changed | | GROUP_DISBANDED | OnDisband hook | - | - | - | Group disbanded | | LOOT_METHOD_CHANGED | Polling | LootMethod | - | - | Loot method changed | | LOOT_THRESHOLD_CHANGED | Polling | ItemQualities | - | - | Loot threshold changed | | MASTER_LOOTER_CHANGED | Polling | - | - | Master looter GUID | Master looter changed | | DIFFICULTY_CHANGED | Polling | Difficulty ID | - | - | Instance difficulty changed | | RAID_CONVERTED | Polling | 1=raid, 0=party | - | - | Party/raid conversion | | SUBGROUP_CHANGED | Polling | New subgroup | - | Member GUID | Member subgroup changed | ### Unavailable Events (TrinityCore limitations) - โŒ TARGET_ICON_CHANGED (no Group::GetTargetIcon() accessor) - โŒ READY_CHECK_* (no Group::IsReadyCheckActive() accessor) **Workaround**: Implement packet sniffing for SMSG_RAID_TARGET_UPDATE and SMSG_READY_CHECK packets --- ## ๐Ÿ“Š Performance Considerations ### Polling Overhead - **Per-bot polling**: ~200 CPU cycles per poll - **Poll interval**: 100-500ms recommended (configurable in BotAI::Update) - **500 bots**: ~0.03% CPU @ 3GHz with 100ms polling ### Memory Usage - **GroupState cache**: ~150 bytes per group - **Event queue**: ~64 bytes per queued event - **Total**: <10MB for 500 bot groups ### Optimization Tips 1. **Poll only when in group**: Check `_bot->GetGroup()` before polling 2. **Adjust poll interval**: Use higher interval (500ms) for idle bots 3. **Batch event processing**: GroupEventBus processes events in batches 4. **Unsubscribe unused events**: Only subscribe to events you actually use --- ## ๐Ÿงช Testing the Integration ### Test 1: Member Join/Leave ```cpp // Create test scenario Bot1->InvitePlayerToGroup(Bot2); Bot2->AcceptGroupInvite(); // Verify: OnGroupMemberJoined() called for both bots Bot2->LeaveGroup(); // Verify: OnGroupMemberLeft() called for Bot1 ``` ### Test 2: Loot Method Change ```cpp Group* group = Bot1->GetGroup(); group->SetLootMethod(LootMethod::MASTER_LOOT); // Wait for next poll cycle (100ms) // Verify: OnLootMethodChanged() called for all group bots ``` ### Test 3: Raid Conversion ```cpp Group* group = Bot1->GetGroup(); for (int i = 0; i < 5; i++) group->AddMember(TestBot[i]); group->ConvertToRaid(); // Verify: OnRaidConverted() called with data1 = 1 ``` --- ## ๐Ÿ” Debugging ### Enable Debug Logging ```cpp // In worldserver.conf Logger.Group = 4, Console Server # Enable group event logging Logger.BotAI = 4, Console Server # Enable bot AI logging ``` ### Event Bus Statistics ```cpp // Get event statistics auto stats = Playerbot::GroupEventBus::instance()->GetStatistics(); TC_LOG_INFO("bot.ai", "Event Bus Stats:\n" " Total Published: {}\n" " Total Delivered: {}\n" " Pending: {}\n" " Avg Process Time: {} ฮผs", stats.totalPublished, stats.totalDelivered, stats.pendingCount, stats.avgProcessTimeUs); ``` ### Dump Event Queue ```cpp // Dump pending events for debugging Playerbot::GroupEventBus::instance()->DumpEventQueue(); ``` --- ## โœ… Integration Checklist Before deploying, verify: - [ ] BotAI subscribes to events in constructor - [ ] BotAI unsubscribes in destructor - [ ] BotAI::Update() calls PollGroupStateChanges() - [ ] All event handlers implemented - [ ] Event handlers update bot behavior appropriately - [ ] Performance testing with 100+ bots - [ ] Memory leak testing (no leaked subscriptions) - [ ] Event delivery tested for all event types --- ## ๐Ÿš€ Advanced Usage ### Custom Event Priorities ```cpp // Publish custom high-priority event Playerbot::GroupEvent event; event.type = Playerbot::GroupEventType::MEMBER_JOINED; event.priority = Playerbot::EventPriority::CRITICAL; // Process immediately event.groupGuid = group->GetGUID(); event.targetGuid = newMember->GetGUID(); Playerbot::GroupEventBus::instance()->PublishEvent(event); ``` ### Event Filtering ```cpp // Subscribe with filter predicate eventBus->Subscribe(_bot->GetGUID(), Playerbot::GroupEventType::MEMBER_JOINED, [this](Playerbot::GroupEvent const& event) { // Only handle if this is MY group if (event.groupGuid == _bot->GetGroup()->GetGUID()) OnGroupMemberJoined(event); }); ``` ### Batch Event Processing ```cpp // Process multiple events at once std::vector events; eventBus->GetPendingEvents(_bot->GetGUID(), events, 10); // Get up to 10 events for (auto const& event : events) { switch (event.type) { case Playerbot::GroupEventType::MEMBER_JOINED: OnGroupMemberJoined(event); break; // ... handle other events ... } } ``` --- ## ๐Ÿ“š Related Documentation - **GROUP_EVENT_SYSTEM_STATUS.md** - System implementation status - **Group/GroupEventBus.h** - Event bus API documentation - **Group/GroupStateMachine.h** - State machine documentation - **Group/GroupEventHandler.h** - Event handler implementations - **Group/PlayerbotGroupScript.h** - TrinityCore integration