Skip to content

Commit 5b595e2

Browse files
authored
Merge b6af515 into b5d14f3
2 parents b5d14f3 + b6af515 commit 5b595e2

8 files changed

Lines changed: 70 additions & 1 deletion

File tree

src/game/Object/Player.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7492,6 +7492,10 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
74927492
sOutdoorPvPMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId);
74937493
sOutdoorPvPMgr.HandlePlayerEnterZone(this, newZone);
74947494

7495+
#ifdef ENABLE_PLAYERBOTS
7496+
sRandomPlayerbotMgr.OnPlayerZoneChange(this, newZone);
7497+
#endif
7498+
74957499
SendInitWorldStates(newZone); // only if really enters to new zone, not just area change, works strange...
74967500

74977501
if (sWorld.getConfig(CONFIG_BOOL_WEATHER))

src/modules/Bots/playerbot/PlayerbotAI.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,15 @@ void PlayerbotAI::UpdateAI(uint32 elapsed)
305305
return;
306306
}
307307

308+
if (sPlayerbotAIConfig.randomBotActiveZoneOnly &&
309+
!bot->GetGroup() && sRandomPlayerbotMgr.IsRandomBot(bot) &&
310+
botOutgoingPacketHandlers.IsEmpty() &&
311+
!sRandomPlayerbotMgr.HasRealPlayerInZone(bot->GetZoneId()))
312+
{
313+
SetNextCheckDelay(5000);
314+
return;
315+
}
316+
308317
if (nextAICheckDelay > sPlayerbotAIConfig.globalCoolDown &&
309318
bot->IsNonMeleeSpellCasted(true, true, false) &&
310319
*GetAiObjectContext()->GetValue<bool>("invalid target", "current target"))

src/modules/Bots/playerbot/PlayerbotAI.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ class PacketHandlingHelper
8282
void AddHandler(uint16 opcode, string handler);
8383
void Handle(ExternalEventHelper &helper);
8484
void AddPacket(const WorldPacket& packet);
85+
bool IsEmpty()
86+
{
87+
return queue.size() == 0;
88+
}
8589

8690
private:
8791
map<uint16, string> handlers;

src/modules/Bots/playerbot/PlayerbotAIConfig.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ PlayerbotAIConfig::PlayerbotAIConfig()
6464
randomBotJoinLfg(false),
6565
randomBotLoginAtStartup(false),
6666
randomBotKeepGroups(false),
67+
randomBotActiveZoneOnly(false),
6768
randomBotTeleLevel(0),
6869
logInGroupOnly(false),
6970
logValuesPerTick(false),
@@ -190,6 +191,7 @@ bool PlayerbotAIConfig::Initialize()
190191
randomBotMaxLevel = config.GetIntDefault("AiPlayerbot.RandomBotMaxLevel", 255);
191192
randomBotLoginAtStartup = config.GetBoolDefault("AiPlayerbot.RandomBotLoginAtStartup", true);
192193
randomBotKeepGroups = config.GetBoolDefault("AiPlayerbot.RandomBotKeepGroups", false);
194+
randomBotActiveZoneOnly = config.GetBoolDefault("AiPlayerbot.RandomBotActiveZoneOnly", false);
193195
randomBotTeleLevel = config.GetIntDefault("AiPlayerbot.RandomBotTeleLevel", 3);
194196

195197
randomChangeMultiplier = config.GetFloatDefault("AiPlayerbot.RandomChangeMultiplier", 1.0);

src/modules/Bots/playerbot/PlayerbotAIConfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class PlayerbotAIConfig
6969
bool randomBotJoinLfg; ///< Indicates if random bots should join Looking For Group.
7070
bool randomBotLoginAtStartup; ///< Indicates if random bots should login at startup.
7171
bool randomBotKeepGroups; ///< Indicates if random bots should preserve groups across restarts.
72+
bool randomBotActiveZoneOnly; ///< If true, ungrouped random bots only tick when a real player is in their zone.
7273
uint32 randomBotTeleLevel; ///< The teleport level for random bots.
7374
bool logInGroupOnly, logValuesPerTick;
7475
bool fleeingEnabled; ///< Indicates if fleeing is enabled for bots.

src/modules/Bots/playerbot/RandomPlayerbotMgr.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,16 @@ void RandomPlayerbotMgr::OnPlayerLogout(Player* player)
10041004
{
10051005
players.erase(i);
10061006
}
1007+
1008+
uint32 zone = player->GetZoneId();
1009+
std::unordered_map<uint32, uint32>::iterator zi = m_playerZoneCounts.find(zone);
1010+
if (zi != m_playerZoneCounts.end())
1011+
{
1012+
if (zi->second <= 1)
1013+
m_playerZoneCounts.erase(zi);
1014+
else
1015+
zi->second--;
1016+
}
10071017
}
10081018
}
10091019

@@ -1041,8 +1051,38 @@ void RandomPlayerbotMgr::OnPlayerLogin(Player* player)
10411051
if (!player->GetPlayerbotAI())
10421052
{
10431053
players.push_back(player);
1044-
sLog.outDebug("Including non-random bot player %s into random bot update", player->GetName());
1054+
// do not add to m_playerZoneCounts, as OnPlayerZoneChange is called anyway
1055+
}
1056+
}
1057+
1058+
void RandomPlayerbotMgr::OnPlayerZoneChange(Player* player, uint32 newZone)
1059+
{
1060+
if (player->GetPlayerbotAI() ||
1061+
player->GetSession()->GetRemoteAddress() == "bot")
1062+
{
1063+
// PlayerbotAI is not set before calling this on entry, so remote address chk
1064+
return;
10451065
}
1066+
1067+
uint32 oldZone = player->GetCachedZoneId();
1068+
if (oldZone == newZone)
1069+
return;
1070+
1071+
std::unordered_map<uint32, uint32>::iterator zi = m_playerZoneCounts.find(oldZone);
1072+
if (zi != m_playerZoneCounts.end())
1073+
{
1074+
if (zi->second <= 1)
1075+
m_playerZoneCounts.erase(zi);
1076+
else
1077+
zi->second--;
1078+
}
1079+
m_playerZoneCounts[newZone]++;
1080+
}
1081+
1082+
bool RandomPlayerbotMgr::HasRealPlayerInZone(uint32 zoneId) const
1083+
{
1084+
std::unordered_map<uint32, uint32>::const_iterator zi = m_playerZoneCounts.find(zoneId);
1085+
return zi != m_playerZoneCounts.end() && zi->second > 0;
10461086
}
10471087

10481088
Player* RandomPlayerbotMgr::GetRandomPlayer()

src/modules/Bots/playerbot/RandomPlayerbotMgr.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "PlayerbotAIBase.h"
66
#include "PlayerbotMgr.h"
77
#include <set>
8+
#include <unordered_map>
89

910
class WorldPacket;
1011
class Player;
@@ -99,6 +100,9 @@ class RandomPlayerbotMgr : public PlayerbotHolder
99100
*/
100101
void OnPlayerLogin(Player* player);
101102

103+
void OnPlayerZoneChange(Player* player, uint32 newZone);
104+
bool HasRealPlayerInZone(uint32 zoneId) const;
105+
102106
/**
103107
* @brief Gets a random player.
104108
* @return Pointer to the random player.
@@ -235,6 +239,7 @@ class RandomPlayerbotMgr : public PlayerbotHolder
235239
set<uint32> m_groupedBots; ///< Cached set of bot GUIDs currently in a group, refreshed each update cycle.
236240
std::map<uint32, AreaCreatureStats> m_areaCreatureStatsMap;
237241
std::map<std::pair<uint32, uint32>, uint32> m_cellToAreaCache;
242+
std::unordered_map<uint32, uint32> m_playerZoneCounts; ///< zone_id -> real player count, for O(1) bot tick gating.
238243
};
239244

240245
#define sRandomPlayerbotMgr MaNGOS::Singleton<RandomPlayerbotMgr>::Instance()

src/modules/Bots/playerbot/aiplayerbot.conf.dist.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ AiPlayerbot.RandomBotTeleLevel = 3
164164
# Preserve bot group assignments across server restarts
165165
#AiPlayerbot.RandomBotKeepGroups = 0
166166

167+
# Only tick ungrouped random bots when a real player is in their zone.
168+
# Reduces CPU load on empty zones at the cost of bots being frozen there.
169+
#AiPlayerbot.RandomBotActiveZoneOnly = 0
170+
167171
# How far random bots are teleported after death
168172
#AiPlayerbot.RandomBotTeleportDistance = 1000
169173

0 commit comments

Comments
 (0)