From 9a0dc9a723f80f427275d23b1f0462c5ab452d65 Mon Sep 17 00:00:00 2001
From: Michael Serajnik <m@mser.at>
Date: Fri, 10 Nov 2023 13:38:51 +0100
Subject: [PATCH] Add partybot pull command.

---
 src/game/Chat/Chat.cpp               |  1 +
 src/game/Chat/Chat.h                 |  1 +
 src/game/PlayerBots/PlayerBotMgr.cpp | 59 ++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/src/game/Chat/Chat.cpp b/src/game/Chat/Chat.cpp
index 49b4d1f7830..a033ab77e5e 100644
--- a/src/game/Chat/Chat.cpp
+++ b/src/game/Chat/Chat.cpp
@@ -99,6 +99,7 @@ ChatCommand * ChatHandler::getCommandTable()
         { "setrole",    SEC_ADMINISTRATOR,      false, &ChatHandler::HandlePartyBotSetRoleCommand,     "", nullptr },
         { "attackstart",SEC_ADMINISTRATOR,      false, &ChatHandler::HandlePartyBotAttackStartCommand, "", nullptr },
         { "attackstop", SEC_ADMINISTRATOR,      false, &ChatHandler::HandlePartyBotAttackStopCommand,  "", nullptr },
+        { "pull",       SEC_ADMINISTRATOR,      false, &ChatHandler::HandlePartyBotPullCommand,        "", nullptr },
         { "aoe",        SEC_ADMINISTRATOR,      false, &ChatHandler::HandlePartyBotAoECommand,         "", nullptr },
         { "ccmark",     SEC_ADMINISTRATOR,      false, &ChatHandler::HandlePartyBotControlMarkCommand, "", nullptr },
         { "focusmark",  SEC_ADMINISTRATOR,      false, &ChatHandler::HandlePartyBotFocusMarkCommand,   "", nullptr },
diff --git a/src/game/Chat/Chat.h b/src/game/Chat/Chat.h
index 03dd59c37de..c70a271bd3b 100644
--- a/src/game/Chat/Chat.h
+++ b/src/game/Chat/Chat.h
@@ -263,6 +263,7 @@ class ChatHandler
         bool HandlePartyBotSetRoleCommand(char * args);
         bool HandlePartyBotAttackStartCommand(char * args);
         bool HandlePartyBotAttackStopCommand(char * args);
+        bool HandlePartyBotPullCommand(char * args);
         bool HandlePartyBotAoECommand(char * args);
         bool HandlePartyBotControlMarkCommand(char * args);
         bool HandlePartyBotFocusMarkCommand(char * args);
diff --git a/src/game/PlayerBots/PlayerBotMgr.cpp b/src/game/PlayerBots/PlayerBotMgr.cpp
index c5b30a430a2..1fcd11bc122 100644
--- a/src/game/PlayerBots/PlayerBotMgr.cpp
+++ b/src/game/PlayerBots/PlayerBotMgr.cpp
@@ -1610,6 +1610,65 @@ bool ChatHandler::HandlePartyBotUnpauseCommand(char* args)
     return HandlePartyBotPauseHelper(args, false);
 }
 
+bool ChatHandler::HandlePartyBotPullCommand(char* args)
+{
+    Player* pPlayer = GetSession()->GetPlayer();
+    Unit* pTarget = GetSelectedUnit();
+    if (!pTarget || (pTarget == pPlayer))
+    {
+        SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE);
+        SetSentErrorMessage(true);
+        return false;
+    }
+    
+    Group* pGroup = pPlayer->GetGroup();
+    if (!pGroup)
+    {
+        SendSysMessage("You are not in a group.");
+        SetSentErrorMessage(true);
+        return false;
+    }
+
+    bool back = false;
+    uint32 duration = 0;
+    if (char* arg1 = ExtractArg(&args))
+    {
+        duration = atoi(arg1);
+    }
+
+    if (!duration)
+        duration = 10 * IN_MILLISECONDS;
+
+    for (GroupReference* itr = pGroup->GetFirstMember(); itr != nullptr; itr = itr->next())
+    {
+        if (Player* pMember = itr->getSource())
+        {
+            if (pMember == pPlayer)
+                continue;
+
+            if (pMember->AI())
+            {
+                if (PartyBotAI* pAI = dynamic_cast<PartyBotAI*>(pMember->AI()))
+                {
+                    if (pAI->m_role == ROLE_MELEE_DPS || pAI->m_role == ROLE_RANGE_DPS)
+                    {
+                        HandlePartyBotPauseApplyHelper(pMember, duration);
+                        continue;
+                    }
+                    else if (pAI->m_role == ROLE_TANK)
+                    {
+                        if (pMember->IsValidAttackTarget(pTarget))
+                            pAI->AttackStart(pTarget);
+                    }
+                }
+            }
+        }
+    }
+    
+    PSendSysMessage("Tank party bots are pulling %s, DPS party bots are paused for %d seconds.", pTarget->GetName(), (duration / IN_MILLISECONDS));
+    return true;
+}
+
 bool ChatHandler::HandlePartyBotUnequipCommand(char* args)
 {
     Player* pTarget = GetSelectedPlayer();