Files
ThordekkCore/.claude/IMMEDIATE_IMPLEMENTATION_TASKS.md
T
2026-01-20 21:24:33 -03:00

17 KiB

Immediate Implementation Tasks - Day 1 Critical Path

Objective: Deliver testable group functionality within 8 hours Priority: CRITICAL - Foundation for all testing

Hour-by-Hour Implementation Plan

Hours 1-2: Foundation Setup & Group Invitation Handler

Agent Assignments

  • Primary: wow-bot-behavior-designer
  • Support: trinity-integration-tester
  • Validation: test-automation-engineer

Critical Tasks

Hour 1: Project Setup

# Create implementation directory structure
mkdir -p src/modules/Playerbot/Group/Implementation
mkdir -p src/modules/Playerbot/Tests/Group
mkdir -p src/modules/Playerbot/Movement/Advanced

Create GroupInvitationHandler.h

#ifndef GROUP_INVITATION_HANDLER_H
#define GROUP_INVITATION_HANDLER_H

#include "Player.h"
#include "Group.h"
#include "WorldSession.h"

namespace Playerbot {

class TC_GAME_API GroupInvitationHandler
{
public:
    explicit GroupInvitationHandler(Player* bot);
    ~GroupInvitationHandler() = default;

    // Core invitation handling
    bool ShouldAcceptInvitation(Player* inviter) const;
    void HandleInvitation(WorldPacket& packet);
    void AcceptInvitation(ObjectGuid inviterGuid);
    void DeclineInvitation(ObjectGuid inviterGuid);

    // State management
    bool IsWaitingForInvitation() const { return _waitingForInvite; }
    void SetAutoAcceptInvitations(bool accept) { _autoAccept = accept; }

private:
    Player* _bot;
    ObjectGuid _pendingInviter;
    bool _waitingForInvite{false};
    bool _autoAccept{true};
    uint32 _lastInviteTime{0};

    // Helper methods
    bool IsValidInviter(Player* inviter) const;
    bool CanJoinGroup(Group* group) const;
    void LogInvitationEvent(std::string const& event, Player* inviter) const;
};

} // namespace Playerbot

#endif // GROUP_INVITATION_HANDLER_H

Hour 2: GroupInvitationHandler.cpp Implementation

#include "GroupInvitationHandler.h"
#include "BotSession.h"
#include "Log.h"
#include "GameTime.h"
#include "Group.h"
#include "GroupMgr.h"
#include "Opcodes.h"

namespace Playerbot {

GroupInvitationHandler::GroupInvitationHandler(Player* bot) : _bot(bot)
{
    if (!_bot)
    {
        TC_LOG_ERROR("playerbot.group", "GroupInvitationHandler created with null bot");
        return;
    }

    TC_LOG_DEBUG("playerbot.group", "GroupInvitationHandler created for bot {}",
                 _bot->GetName());
}

bool GroupInvitationHandler::ShouldAcceptInvitation(Player* inviter) const
{
    if (!_autoAccept || !inviter)
        return false;

    // Check if inviter is valid
    if (!IsValidInviter(inviter))
        return false;

    // Check cooldown (prevent spam)
    if (GameTime::GetGameTimeMS() - _lastInviteTime < 5000) // 5 second cooldown
        return false;

    // Check if we can join the group
    Group* inviterGroup = inviter->GetGroup();
    if (!CanJoinGroup(inviterGroup))
        return false;

    return true;
}

void GroupInvitationHandler::HandleInvitation(WorldPacket& packet)
{
    ObjectGuid inviterGuid;
    packet >> inviterGuid;

    Player* inviter = ObjectAccessor::FindConnectedPlayer(inviterGuid);
    if (!inviter)
    {
        TC_LOG_DEBUG("playerbot.group", "Bot {} received invitation from offline player",
                     _bot->GetName());
        return;
    }

    LogInvitationEvent("Received invitation", inviter);

    if (ShouldAcceptInvitation(inviter))
    {
        AcceptInvitation(inviterGuid);
    }
    else
    {
        DeclineInvitation(inviterGuid);
    }
}

void GroupInvitationHandler::AcceptInvitation(ObjectGuid inviterGuid)
{
    Player* inviter = ObjectAccessor::FindConnectedPlayer(inviterGuid);
    if (!inviter)
        return;

    // Send accept packet
    WorldPacket data(CMSG_GROUP_ACCEPT, 0);
    _bot->GetSession()->HandleGroupAcceptOpcode(data);

    _lastInviteTime = GameTime::GetGameTimeMS();
    _pendingInviter = inviterGuid;

    LogInvitationEvent("Accepted invitation", inviter);

    TC_LOG_INFO("playerbot.group", "Bot {} accepted group invitation from {}",
                _bot->GetName(), inviter->GetName());
}

bool GroupInvitationHandler::IsValidInviter(Player* inviter) const
{
    if (!inviter)
        return false;

    // Don't accept invitations from other bots (prevent bot loops)
    if (inviter->GetSession()->IsBot())
        return false;

    // Check if inviter is in same map
    if (inviter->GetMapId() != _bot->GetMapId())
        return false;

    // Check distance (within reasonable range)
    float distance = inviter->GetDistance(_bot);
    if (distance > 1000.0f) // 1000 yards maximum
        return false;

    return true;
}

bool GroupInvitationHandler::CanJoinGroup(Group* group) const
{
    if (!group)
        return true; // Can join new group

    // Check group size
    if (group->GetMembersCount() >= GROUP_MAX_SIZE)
        return false;

    // Check if already in a group
    if (_bot->GetGroup())
        return false;

    return true;
}

void GroupInvitationHandler::LogInvitationEvent(std::string const& event, Player* inviter) const
{
    TC_LOG_DEBUG("playerbot.group", "Bot {} - {}: inviter={}, map={}, distance={:.1f}",
                 _bot->GetName(), event, inviter->GetName(),
                 inviter->GetMapId(), inviter->GetDistance(_bot));
}

} // namespace Playerbot

Integration with BotAI

// Add to BotAI.h
#include "Group/GroupInvitationHandler.h"

class BotAI {
private:
    std::unique_ptr<GroupInvitationHandler> _groupHandler;

public:
    GroupInvitationHandler* GetGroupHandler() const { return _groupHandler.get(); }
};

// Add to BotAI.cpp constructor
BotAI::BotAI(Player* bot) : _bot(bot) {
    // ... existing code ...

    // Initialize group handler
    _groupHandler = std::make_unique<GroupInvitationHandler>(bot);
}

Hours 3-4: Basic Following Behavior

Agent Assignments

  • Primary: wow-bot-behavior-designer
  • Support: cpp-architecture-optimizer

Implementation Tasks

Create LeaderFollowBehavior.h

#ifndef LEADER_FOLLOW_BEHAVIOR_H
#define LEADER_FOLLOW_BEHAVIOR_H

#include "Strategy.h"
#include "Position.h"
#include "Player.h"
#include "Group.h"

namespace Playerbot {

enum class FollowState : uint8 {
    INACTIVE,       // Not following anyone
    FOLLOWING,      // Actively following leader
    POSITIONING,    // Moving to correct formation position
    TELEPORTING     // Teleporting to leader (large distance)
};

enum class FormationRole : uint8 {
    TANK_LEFT,      // Front-left of leader
    TANK_RIGHT,     // Front-right of leader
    DPS_LEFT,       // Left flank
    DPS_RIGHT,      // Right flank
    DPS_REAR,       // Behind leader
    HEALER_CENTER,  // Center-rear
    HEALER_FAR      // Far-rear position
};

class TC_GAME_API LeaderFollowBehavior : public Strategy
{
public:
    explicit LeaderFollowBehavior();

    // Strategy interface
    void InitializeActions() override;
    void InitializeTriggers() override;
    void InitializeValues() override;
    StrategyRelevance CalculateRelevance(BotAI* ai) const override;

    // Follow behavior methods
    void UpdateFollowBehavior(BotAI* ai, uint32 diff);
    Position CalculateFollowPosition(Player* leader, FormationRole role);
    bool ShouldTeleportToLeader(Player* bot, Player* leader);

    // State management
    FollowState GetFollowState() const { return _followState; }
    void SetFollowTarget(Player* leader);
    Player* GetFollowTarget() const;

private:
    FollowState _followState{FollowState::INACTIVE};
    ObjectGuid _followTargetGuid;
    Position _lastFollowPosition;
    uint32 _lastPositionUpdate{0};
    FormationRole _assignedRole{FormationRole::DPS_REAR};

    // Helper methods
    FormationRole DetermineFormationRole(Player* bot);
    bool IsInCorrectPosition(Player* bot, Position targetPos);
    void InitiateMovement(Player* bot, Position destination);
    void HandleTeleportation(Player* bot, Player* leader);
};

} // namespace Playerbot

#endif // LEADER_FOLLOW_BEHAVIOR_H

Key Implementation Functions:

Position LeaderFollowBehavior::CalculateFollowPosition(Player* leader, FormationRole role)
{
    Position leaderPos = leader->GetPosition();
    float offset = 8.0f; // Base follow distance

    switch (role)
    {
        case FormationRole::TANK_LEFT:
            return {leaderPos.GetPositionX() - offset, leaderPos.GetPositionY() + offset,
                   leaderPos.GetPositionZ(), leaderPos.GetOrientation()};
        case FormationRole::TANK_RIGHT:
            return {leaderPos.GetPositionX() + offset, leaderPos.GetPositionY() + offset,
                   leaderPos.GetPositionZ(), leaderPos.GetOrientation()};
        case FormationRole::DPS_LEFT:
            return {leaderPos.GetPositionX() - offset, leaderPos.GetPositionY(),
                   leaderPos.GetPositionZ(), leaderPos.GetOrientation()};
        case FormationRole::DPS_RIGHT:
            return {leaderPos.GetPositionX() + offset, leaderPos.GetPositionY(),
                   leaderPos.GetPositionZ(), leaderPos.GetOrientation()};
        case FormationRole::DPS_REAR:
            return {leaderPos.GetPositionX(), leaderPos.GetPositionY() - offset,
                   leaderPos.GetPositionZ(), leaderPos.GetOrientation()};
        case FormationRole::HEALER_CENTER:
            return {leaderPos.GetPositionX(), leaderPos.GetPositionY() - offset * 1.5f,
                   leaderPos.GetPositionZ(), leaderPos.GetOrientation()};
        case FormationRole::HEALER_FAR:
            return {leaderPos.GetPositionX(), leaderPos.GetPositionY() - offset * 2.0f,
                   leaderPos.GetPositionZ(), leaderPos.GetOrientation()};
    }

    return leaderPos; // Fallback
}

Hours 5-6: Combat Engagement & Target Assistance

Agent Assignments

  • Primary: wow-mechanics-expert
  • Support: trinity-integration-tester

Implementation Tasks

Create GroupCombatTrigger.h

#ifndef GROUP_COMBAT_TRIGGER_H
#define GROUP_COMBAT_TRIGGER_H

#include "Trigger.h"
#include "Player.h"
#include "Unit.h"

namespace Playerbot {

class TC_GAME_API GroupCombatTrigger : public Trigger
{
public:
    GroupCombatTrigger() : Trigger("group_combat") {}

    bool IsActive(BotAI* ai) override;
    std::string GetActionName() override { return "engage_group_combat"; }

private:
    bool IsGroupInCombat(Group* group);
    bool ShouldEngageCombat(Player* bot, Group* group);
    Unit* GetGroupTarget(Group* group);
};

class TC_GAME_API TargetAssistAction : public Action
{
public:
    TargetAssistAction() : Action("engage_group_combat") {}

    ActionResult Execute(BotAI* ai, ActionContext const& context) override;
    bool IsPossible(BotAI* ai) const override;

private:
    Unit* GetLeaderTarget(Player* leader);
    bool IsValidAssistTarget(Unit* target, Player* bot);
};

} // namespace Playerbot

#endif // GROUP_COMBAT_TRIGGER_H

Core Combat Logic:

ActionResult TargetAssistAction::Execute(BotAI* ai, ActionContext const& context)
{
    Player* bot = ai->GetBot();
    Group* group = bot->GetGroup();

    if (!group)
        return ActionResult::FAILED;

    // Get group leader
    Player* leader = ObjectAccessor::FindConnectedPlayer(group->GetLeaderGUID());
    if (!leader)
        return ActionResult::FAILED;

    // Get leader's target
    Unit* leaderTarget = GetLeaderTarget(leader);
    if (!leaderTarget || !IsValidAssistTarget(leaderTarget, bot))
        return ActionResult::FAILED;

    // Set bot's target to leader's target
    bot->SetTarget(leaderTarget->GetGUID());

    // Engage combat if not already in combat
    if (!bot->IsInCombat())
    {
        bot->Attack(leaderTarget, true);
    }

    TC_LOG_DEBUG("playerbot.combat", "Bot {} assisting leader {} against target {}",
                 bot->GetName(), leader->GetName(), leaderTarget->GetName());

    return ActionResult::SUCCESS;
}

Hours 7-8: Integration Testing & Validation

Agent Assignments

  • Primary: test-automation-engineer
  • Support: trinity-integration-tester, resource-monitor-limiter

Critical Validation Tasks

Create GroupFunctionalityTests.cpp

#include "GroupFunctionalityTests.h"
#include "BotSession.h"
#include "Player.h"
#include "Group.h"

namespace Playerbot {

class GroupFunctionalityTests : public TestSuite
{
public:
    void RunAllTests() override
    {
        TestGroupInvitationAcceptance();
        TestLeaderFollowingBasic();
        TestCombatEngagement();
        TestTargetAssistance();
        TestIntegrationScenario();
    }

private:
    void TestGroupInvitationAcceptance()
    {
        // Create test environment
        auto testPlayer = CreateTestPlayer("TestLeader");
        auto botPlayer = CreateTestBot("TestBot");

        // Send group invitation
        testPlayer->GetSession()->SendGroupInvite(botPlayer);

        // Wait for response (max 5 seconds)
        uint32 timeoutMs = 5000;
        uint32 elapsed = 0;

        while (elapsed < timeoutMs && !botPlayer->GetGroup())
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            elapsed += 100;
        }

        // Validate bot joined group
        ASSERT_TRUE(botPlayer->GetGroup() != nullptr);
        ASSERT_TRUE(botPlayer->GetGroup()->IsMember(botPlayer->GetGUID()));

        TC_LOG_INFO("test.group", "✅ Group invitation test PASSED");
    }

    void TestIntegrationScenario()
    {
        // Full workflow test: Invite → Follow → Combat → Target
        auto leader = CreateTestPlayer("Leader");
        auto bot1 = CreateTestBot("Bot1");
        auto bot2 = CreateTestBot("Bot2");

        // Step 1: Create group
        CreateTestGroup(leader, {bot1, bot2});

        // Step 2: Move leader, verify following
        MovePlayer(leader, Position(100, 100, 0, 0));
        std::this_thread::sleep_for(std::chrono::seconds(2));

        ASSERT_TRUE(IsNearPosition(bot1, leader->GetPosition(), 15.0f));
        ASSERT_TRUE(IsNearPosition(bot2, leader->GetPosition(), 15.0f));

        // Step 3: Engage combat, verify assistance
        auto enemy = CreateTestEnemy("TestEnemy");
        leader->Attack(enemy, true);
        std::this_thread::sleep_for(std::chrono::seconds(1));

        ASSERT_TRUE(bot1->GetVictim() == enemy);
        ASSERT_TRUE(bot2->GetVictim() == enemy);

        TC_LOG_INFO("test.group", "✅ Integration scenario test PASSED");
    }
};

} // namespace Playerbot

Performance Validation:

class PerformanceValidator
{
public:
    struct PerformanceMetrics
    {
        uint64 memoryUsageBytes{0};
        double cpuUsagePercent{0.0};
        uint32 responseTimeMs{0};
        uint32 packetsPerSecond{0};
    };

    PerformanceMetrics MeasureBotPerformance(Player* bot, uint32 durationMs)
    {
        PerformanceMetrics metrics;

        // Measure memory usage
        metrics.memoryUsageBytes = GetBotMemoryUsage(bot);

        // Measure CPU usage over time
        auto startTime = std::chrono::high_resolution_clock::now();
        auto startCpuTime = GetThreadCpuTime();

        std::this_thread::sleep_for(std::chrono::milliseconds(durationMs));

        auto endTime = std::chrono::high_resolution_clock::now();
        auto endCpuTime = GetThreadCpuTime();

        auto totalTime = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
        auto cpuTime = std::chrono::duration_cast<std::chrono::milliseconds>(endCpuTime - startCpuTime);

        metrics.cpuUsagePercent = (double)cpuTime.count() / totalTime.count() * 100.0;

        return metrics;
    }

    bool ValidatePerformanceTargets(PerformanceMetrics const& metrics)
    {
        bool memoryOk = metrics.memoryUsageBytes < (10 * 1024 * 1024); // <10MB
        bool cpuOk = metrics.cpuUsagePercent < 0.1; // <0.1% CPU
        bool responseOk = metrics.responseTimeMs < 500; // <500ms response

        return memoryOk && cpuOk && responseOk;
    }
};

Success Criteria Validation

End of Hour 8 Deliverables:

  • Group Invitation: 100% acceptance rate
  • Following: Bots maintain formation within 15 yards
  • Combat: Engagement within 3 seconds of leader
  • Target Assistance: Attack same target as leader
  • Performance: <10MB memory, <0.1% CPU per bot
  • Testing: All integration tests pass

Demo Scenario (Hour 8)

# Demonstration script
1. Create player character "TestLeader"
2. Spawn 4 bots via console commands
3. TestLeader invites all bots to group
4. Verify: All bots accept invitations automatically
5. TestLeader moves around zone
6. Verify: All bots follow in formation
7. TestLeader attacks training dummy
8. Verify: All bots engage same target
9. TestLeader switches targets
10. Verify: All bots switch targets immediately

Handoff Package

  • Complete source code for all components
  • Integration test suite functional
  • Performance benchmarks established
  • Documentation for Phase 2 development
  • Architecture ready for advanced combat features

This critical path delivers fully testable group functionality within 8 hours while establishing the foundation for all subsequent development phases.