Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/game/Object/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7492,6 +7492,10 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
sOutdoorPvPMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId);
sOutdoorPvPMgr.HandlePlayerEnterZone(this, newZone);

#ifdef ENABLE_PLAYERBOTS
sRandomPlayerbotMgr.OnPlayerZoneChange(this, newZone);
#endif

SendInitWorldStates(newZone); // only if really enters to new zone, not just area change, works strange...

if (sWorld.getConfig(CONFIG_BOOL_WEATHER))
Expand Down
7 changes: 7 additions & 0 deletions src/modules/Bots/playerbot/PlayerbotAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,13 @@ void PlayerbotAI::UpdateAI(uint32 elapsed)
return;
}

if (sPlayerbotAIConfig.randomBotActiveZoneOnly && !bot->GetGroup() && sRandomPlayerbotMgr.IsRandomBot(bot) &&
!sRandomPlayerbotMgr.HasRealPlayerInZone(bot->GetZoneId()))
{
SetNextCheckDelay(5000);
return;
}

if (nextAICheckDelay > sPlayerbotAIConfig.globalCoolDown &&
bot->IsNonMeleeSpellCasted(true, true, false) &&
*GetAiObjectContext()->GetValue<bool>("invalid target", "current target"))
Expand Down
2 changes: 2 additions & 0 deletions src/modules/Bots/playerbot/PlayerbotAIConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ PlayerbotAIConfig::PlayerbotAIConfig()
randomBotJoinLfg(false),
randomBotLoginAtStartup(false),
randomBotKeepGroups(false),
randomBotActiveZoneOnly(false),
randomBotTeleLevel(0),
logInGroupOnly(false),
logValuesPerTick(false),
Expand Down Expand Up @@ -190,6 +191,7 @@ bool PlayerbotAIConfig::Initialize()
randomBotMaxLevel = config.GetIntDefault("AiPlayerbot.RandomBotMaxLevel", 255);
randomBotLoginAtStartup = config.GetBoolDefault("AiPlayerbot.RandomBotLoginAtStartup", true);
randomBotKeepGroups = config.GetBoolDefault("AiPlayerbot.RandomBotKeepGroups", false);
randomBotActiveZoneOnly = config.GetBoolDefault("AiPlayerbot.RandomBotActiveZoneOnly", false);
randomBotTeleLevel = config.GetIntDefault("AiPlayerbot.RandomBotTeleLevel", 3);

randomChangeMultiplier = config.GetFloatDefault("AiPlayerbot.RandomChangeMultiplier", 1.0);
Expand Down
1 change: 1 addition & 0 deletions src/modules/Bots/playerbot/PlayerbotAIConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class PlayerbotAIConfig
bool randomBotJoinLfg; ///< Indicates if random bots should join Looking For Group.
bool randomBotLoginAtStartup; ///< Indicates if random bots should login at startup.
bool randomBotKeepGroups; ///< Indicates if random bots should preserve groups across restarts.
bool randomBotActiveZoneOnly; ///< If true, ungrouped random bots only tick when a real player is in their zone.
uint32 randomBotTeleLevel; ///< The teleport level for random bots.
bool logInGroupOnly, logValuesPerTick;
bool fleeingEnabled; ///< Indicates if fleeing is enabled for bots.
Expand Down
38 changes: 38 additions & 0 deletions src/modules/Bots/playerbot/RandomPlayerbotMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,16 @@ void RandomPlayerbotMgr::OnPlayerLogout(Player* player)
{
players.erase(i);
}

uint32 zone = player->GetZoneId();
std::unordered_map<uint32, uint32>::iterator zi = m_playerZoneCounts.find(zone);
if (zi != m_playerZoneCounts.end())
{
if (zi->second <= 1)
m_playerZoneCounts.erase(zi);
else
zi->second--;
}
}
}

Expand Down Expand Up @@ -1042,7 +1052,35 @@ void RandomPlayerbotMgr::OnPlayerLogin(Player* player)
{
players.push_back(player);
sLog.outDebug("Including non-random bot player %s into random bot update", player->GetName());
m_playerZoneCounts[player->GetZoneId()]++;
}
}

void RandomPlayerbotMgr::OnPlayerZoneChange(Player* player, uint32 newZone)
{
if (player->GetPlayerbotAI())
return;

uint32 oldZone = player->GetZoneId();
if (oldZone == newZone)
return;

std::unordered_map<uint32, uint32>::iterator zi = m_playerZoneCounts.find(oldZone);
if (zi != m_playerZoneCounts.end())
{
if (zi->second <= 1)
m_playerZoneCounts.erase(zi);
else
zi->second--;
}

m_playerZoneCounts[newZone]++;
}

bool RandomPlayerbotMgr::HasRealPlayerInZone(uint32 zoneId) const
{
std::unordered_map<uint32, uint32>::const_iterator zi = m_playerZoneCounts.find(zoneId);
return zi != m_playerZoneCounts.end() && zi->second > 0;
}

Player* RandomPlayerbotMgr::GetRandomPlayer()
Expand Down
5 changes: 5 additions & 0 deletions src/modules/Bots/playerbot/RandomPlayerbotMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "PlayerbotAIBase.h"
#include "PlayerbotMgr.h"
#include <set>
#include <unordered_map>

class WorldPacket;
class Player;
Expand Down Expand Up @@ -99,6 +100,9 @@ class RandomPlayerbotMgr : public PlayerbotHolder
*/
void OnPlayerLogin(Player* player);

void OnPlayerZoneChange(Player* player, uint32 newZone);
bool HasRealPlayerInZone(uint32 zoneId) const;

/**
* @brief Gets a random player.
* @return Pointer to the random player.
Expand Down Expand Up @@ -235,6 +239,7 @@ class RandomPlayerbotMgr : public PlayerbotHolder
set<uint32> m_groupedBots; ///< Cached set of bot GUIDs currently in a group, refreshed each update cycle.
std::map<uint32, AreaCreatureStats> m_areaCreatureStatsMap;
std::map<std::pair<uint32, uint32>, uint32> m_cellToAreaCache;
std::unordered_map<uint32, uint32> m_playerZoneCounts; ///< zone_id -> real player count, for O(1) bot tick gating.
};

#define sRandomPlayerbotMgr MaNGOS::Singleton<RandomPlayerbotMgr>::Instance()
Expand Down
4 changes: 4 additions & 0 deletions src/modules/Bots/playerbot/aiplayerbot.conf.dist.in
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ AiPlayerbot.RandomBotTeleLevel = 3
# Preserve bot group assignments across server restarts
#AiPlayerbot.RandomBotKeepGroups = 0

# Only tick ungrouped random bots when a real player is in their zone.
# Reduces CPU load on empty zones at the cost of bots being frozen there.
#AiPlayerbot.RandomBotActiveZoneOnly = 0

# How far random bots are teleported after death
#AiPlayerbot.RandomBotTeleportDistance = 1000

Expand Down
Loading