Auto calculate RandomBotAccountCount by default (#964)

* Remove RandomBotAccountCount requirement

* Remove RandomBotAccountCount

* Remove randomBotAccountCount

* Remove randomBotAccountCount

* Update playerbots.conf.dist

* Style

* Set RotationPoolSize to 20 to work with the bot amount defaults

* Update PlayerbotAIConfig.cpp: Sync with default config

* Set +1 where appropriate

* Acc patch (#73)

* Account for TBC
* Still made it possible to change manually if desired

* uint32 randomBotAccountCount;

* Update Playerbots.cpp
This commit is contained in:
SaW
2025-02-14 15:03:53 +01:00
committed by GitHub
parent c2caf3c564
commit 4793644a15
3 changed files with 896 additions and 891 deletions

View File

@@ -81,14 +81,16 @@ AiPlayerbot.Enabled = 1
# Enable random bot system # Enable random bot system
AiPlayerbot.RandomBotAutologin = 1 AiPlayerbot.RandomBotAutologin = 1
# Random bot account
# Please ensure that RandomBotAccountCount is greater than (MaxRandomBots / 10 + AddClassAccountPoolSize)
AiPlayerbot.RandomBotAccountCount = 200
# Random bot count # Random bot count
AiPlayerbot.MinRandomBots = 50 AiPlayerbot.MinRandomBots = 50
AiPlayerbot.MaxRandomBots = 50 AiPlayerbot.MaxRandomBots = 50
# Random bot accounts
# If you are not using any expansion at all, you may have to set this manually, then
# please ensure that RandomBotAccountCount is at least greater than (MaxRandomBots / 10 + AddClassAccountPoolSize)
# default: 0 - Automatic
AiPlayerbot.RandomBotAccountCount = 0
# Delete all random bot accounts (reset randombots) # Delete all random bot accounts (reset randombots)
AiPlayerbot.DeleteRandomBotAccounts = 0 AiPlayerbot.DeleteRandomBotAccounts = 0
@@ -115,7 +117,6 @@ AiPlayerbot.MaxAddedBots = 40
AiPlayerbot.AddClassCommand = 1 AiPlayerbot.AddClassCommand = 1
# Set the addclass command account pool size # Set the addclass command account pool size
# Addclass command uses a subset of accounts from RandomBotAccountCount
AiPlayerbot.AddClassAccountPoolSize = 50 AiPlayerbot.AddClassAccountPoolSize = 50
# Bot group invitation permission level (0 = GM only, 1 = accept based on level, 2 = always accept) # Bot group invitation permission level (0 = GM only, 1 = accept based on level, 2 = always accept)
@@ -506,8 +507,8 @@ AiPlayerbot.RandomBotAccountPrefix = "rndbot"
# default: 0 (disable, the online bots are fixed) # default: 0 (disable, the online bots are fixed)
AiPlayerbot.EnableRotation = 0 AiPlayerbot.EnableRotation = 0
# Bots pool size for rotation (should be less than RandomBotAccountCount * 10) # Bots pool size for rotation (should be less than MaxRandomBots)
AiPlayerbot.RotationPoolSize = 500 AiPlayerbot.RotationPoolSize = 20
AiPlayerbot.RandomBotMinLevel = 1 AiPlayerbot.RandomBotMinLevel = 1
AiPlayerbot.RandomBotMaxLevel = 80 AiPlayerbot.RandomBotMaxLevel = 80

View File

@@ -155,7 +155,7 @@ bool PlayerbotAIConfig::Initialize()
botAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.BotAutologin", false); botAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.BotAutologin", false);
randomBotAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutologin", true); randomBotAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutologin", true);
minRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBots", 50); minRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBots", 50);
maxRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBots", 200); maxRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBots", 50);
randomBotUpdateInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotUpdateInterval", 20); randomBotUpdateInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotUpdateInterval", 20);
randomBotCountChangeMinInterval = randomBotCountChangeMinInterval =
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE); sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE);
@@ -434,7 +434,7 @@ bool PlayerbotAIConfig::Initialize()
} }
randomBotAccountPrefix = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotAccountPrefix", "rndbot"); randomBotAccountPrefix = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotAccountPrefix", "rndbot");
randomBotAccountCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAccountCount", 200); randomBotAccountCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAccountCount", 0);
deleteRandomBotAccounts = sConfigMgr->GetOption<bool>("AiPlayerbot.DeleteRandomBotAccounts", false); deleteRandomBotAccounts = sConfigMgr->GetOption<bool>("AiPlayerbot.DeleteRandomBotAccounts", false);
randomBotGuildCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotGuildCount", 20); randomBotGuildCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotGuildCount", 20);
deleteRandomBotGuilds = sConfigMgr->GetOption<bool>("AiPlayerbot.DeleteRandomBotGuilds", false); deleteRandomBotGuilds = sConfigMgr->GetOption<bool>("AiPlayerbot.DeleteRandomBotGuilds", false);
@@ -505,7 +505,7 @@ bool PlayerbotAIConfig::Initialize()
limitGearExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitGearExpansion", 1); limitGearExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitGearExpansion", 1);
randombotStartingLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandombotStartingLevel", 5); randombotStartingLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandombotStartingLevel", 5);
enableRotation = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableRotation", false); enableRotation = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableRotation", false);
rotationPoolSize = sConfigMgr->GetOption<int32>("AiPlayerbot.RotationPoolSize", 500); rotationPoolSize = sConfigMgr->GetOption<int32>("AiPlayerbot.RotationPoolSize", 20);
gearscorecheck = sConfigMgr->GetOption<bool>("AiPlayerbot.GearScoreCheck", false); gearscorecheck = sConfigMgr->GetOption<bool>("AiPlayerbot.GearScoreCheck", false);
randomBotPreQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.PreQuests", true); randomBotPreQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.PreQuests", true);

View File

@@ -3,24 +3,24 @@
* and/or modify it under version 2 of the License, or (at your option), any later version. * and/or modify it under version 2 of the License, or (at your option), any later version.
*/ */
#include "RandomPlayerbotFactory.h" #include "RandomPlayerbotFactory.h"
#include "AccountMgr.h" #include "AccountMgr.h"
#include "ArenaTeamMgr.h" #include "ArenaTeamMgr.h"
#include "DatabaseEnv.h" #include "DatabaseEnv.h"
#include "GuildMgr.h" #include "GuildMgr.h"
#include "PlayerbotFactory.h" #include "PlayerbotFactory.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "SocialMgr.h" #include "SocialMgr.h"
#include "Timer.h" #include "Timer.h"
std::map<uint8, std::vector<uint8>> RandomPlayerbotFactory::availableRaces; std::map<uint8, std::vector<uint8>> RandomPlayerbotFactory::availableRaces;
constexpr RandomPlayerbotFactory::NameRaceAndGender RandomPlayerbotFactory::CombineRaceAndGender(uint8 gender, constexpr RandomPlayerbotFactory::NameRaceAndGender RandomPlayerbotFactory::CombineRaceAndGender(uint8 gender,
uint8 race) uint8 race)
{ {
switch (race) switch (race)
{ {
case RACE_HUMAN: case RACE_HUMAN:
@@ -47,10 +47,10 @@ constexpr RandomPlayerbotFactory::NameRaceAndGender RandomPlayerbotFactory::Comb
LOG_ERROR("playerbots", "The race with ID %d does not have a naming category", race); LOG_ERROR("playerbots", "The race with ID %d does not have a naming category", race);
return static_cast<NameRaceAndGender>(static_cast<uint8>(NameRaceAndGender::GenericMale) + gender); return static_cast<NameRaceAndGender>(static_cast<uint8>(NameRaceAndGender::GenericMale) + gender);
} }
} }
RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(accountId) RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(accountId)
{ {
uint32 const expansion = sWorld->getIntConfig(CONFIG_EXPANSION); uint32 const expansion = sWorld->getIntConfig(CONFIG_EXPANSION);
availableRaces[CLASS_WARRIOR].push_back(RACE_HUMAN); availableRaces[CLASS_WARRIOR].push_back(RACE_HUMAN);
@@ -151,10 +151,10 @@ RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(acc
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_GNOME); availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_GNOME);
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_DWARF); availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_DWARF);
} }
} }
Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls, std::unordered_map<NameRaceAndGender, std::vector<std::string>>& nameCache) Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls, std::unordered_map<NameRaceAndGender, std::vector<std::string>>& nameCache)
{ {
LOG_DEBUG("playerbots", "Creating new random bot for class {}", cls); LOG_DEBUG("playerbots", "Creating new random bot for class {}", cls);
uint8 gender = rand() % 2 ? GENDER_MALE : GENDER_FEMALE; uint8 gender = rand() % 2 ? GENDER_MALE : GENDER_FEMALE;
@@ -259,10 +259,10 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls
name.c_str(), race, cls); name.c_str(), race, cls);
return player; return player;
} }
std::string const RandomPlayerbotFactory::CreateRandomBotName(NameRaceAndGender raceAndGender) std::string const RandomPlayerbotFactory::CreateRandomBotName(NameRaceAndGender raceAndGender)
{ {
std::string botName = ""; std::string botName = "";
int tries = 3; int tries = 3;
while (--tries) while (--tries)
@@ -391,17 +391,21 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(NameRaceAndGender
LOG_ERROR("playerbots", "Random name generation failed."); LOG_ERROR("playerbots", "Random name generation failed.");
botName.clear(); botName.clear();
return std::move(botName); return std::move(botName);
} }
void RandomPlayerbotFactory::CreateRandomBots() void RandomPlayerbotFactory::CreateRandomBots()
{ {
bool isWOTLK = sWorld->getIntConfig(CONFIG_EXPANSION) == EXPANSION_WRATH_OF_THE_LICH_KING;
/* multi-thread here is meaningless? since the async db operations */ /* multi-thread here is meaningless? since the async db operations */
if (sPlayerbotAIConfig->deleteRandomBotAccounts) if (sPlayerbotAIConfig->deleteRandomBotAccounts)
{ {
std::vector<uint32> botAccounts; std::vector<uint32> botAccounts;
std::vector<uint32> botFriends; std::vector<uint32> botFriends;
uint32 totalAccountCount = (sPlayerbotAIConfig->randomBotAccountCount != 0) ? sPlayerbotAIConfig->randomBotAccountCount
: (isWOTLK ? (sPlayerbotAIConfig->maxRandomBots / 10) : (sPlayerbotAIConfig->maxRandomBots / 9))
+ sPlayerbotAIConfig->addClassAccountPoolSize + 1;
for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber) for (uint32 accountNumber = 0; accountNumber < totalAccountCount; ++accountNumber)
{ {
std::ostringstream out; std::ostringstream out;
out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber; out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber;
@@ -440,11 +444,13 @@ void RandomPlayerbotFactory::CreateRandomBots()
LOG_INFO("playerbots", "Creating random bot accounts..."); LOG_INFO("playerbots", "Creating random bot accounts...");
std::unordered_map<NameRaceAndGender, std::vector<std::string>> nameCache; std::unordered_map<NameRaceAndGender, std::vector<std::string>> nameCache;
uint32 totalAccCount = sPlayerbotAIConfig->randomBotAccountCount;
std::vector<std::future<void>> account_creations; std::vector<std::future<void>> account_creations;
int account_creation = 0; int account_creation = 0;
uint32 totalAccountCount = (sPlayerbotAIConfig->randomBotAccountCount != 0) ? sPlayerbotAIConfig->randomBotAccountCount
: (isWOTLK ? (sPlayerbotAIConfig->maxRandomBots / 10) : (sPlayerbotAIConfig->maxRandomBots / 9))
+ sPlayerbotAIConfig->addClassAccountPoolSize + 1;
for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber) for (uint32 accountNumber = 0; accountNumber < totalAccountCount; ++accountNumber)
{ {
std::ostringstream out; std::ostringstream out;
out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber; out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber;
@@ -488,13 +494,12 @@ void RandomPlayerbotFactory::CreateRandomBots()
LOG_INFO("playerbots", "Creating random bot characters..."); LOG_INFO("playerbots", "Creating random bot characters...");
uint32 totalRandomBotChars = 0; uint32 totalRandomBotChars = 0;
uint32 totalCharCount = sPlayerbotAIConfig->randomBotAccountCount * 10;
std::vector<std::pair<Player*, uint32>> playerBots; std::vector<std::pair<Player*, uint32>> playerBots;
std::vector<WorldSession*> sessionBots; std::vector<WorldSession*> sessionBots;
int bot_creation = 0; int bot_creation = 0;
bool nameCached = false; bool nameCached = false;
for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber) for (uint32 accountNumber = 0; accountNumber < totalAccountCount; ++accountNumber)
{ {
std::ostringstream out; std::ostringstream out;
out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber; out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber;
@@ -546,8 +551,7 @@ void RandomPlayerbotFactory::CreateRandomBots()
} while (result->NextRow()); } while (result->NextRow());
} }
LOG_DEBUG("playerbots", "Creating random bot characters for account: [{}/{}]", accountNumber + 1, LOG_DEBUG("playerbots", "Creating random bot characters for account: [{}/{}]", accountNumber + 1, totalAccountCount);
sPlayerbotAIConfig->randomBotAccountCount);
RandomPlayerbotFactory factory(accountId); RandomPlayerbotFactory factory(accountId);
WorldSession* session = new WorldSession(accountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, WorldSession* session = new WorldSession(accountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING,
@@ -608,10 +612,10 @@ void RandomPlayerbotFactory::CreateRandomBots()
LOG_INFO("server.loading", ">> {} random bot accounts with {} characters available", LOG_INFO("server.loading", ">> {} random bot accounts with {} characters available",
sPlayerbotAIConfig->randomBotAccounts.size(), totalRandomBotChars); sPlayerbotAIConfig->randomBotAccounts.size(), totalRandomBotChars);
} }
void RandomPlayerbotFactory::CreateRandomGuilds() void RandomPlayerbotFactory::CreateRandomGuilds()
{ {
std::vector<uint32> randomBots; std::vector<uint32> randomBots;
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BOT); PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BOT);
@@ -709,10 +713,10 @@ void RandomPlayerbotFactory::CreateRandomGuilds()
} }
LOG_INFO("playerbots", "{} random bot guilds available", guildNumber); LOG_INFO("playerbots", "{} random bot guilds available", guildNumber);
} }
std::string const RandomPlayerbotFactory::CreateRandomGuildName() std::string const RandomPlayerbotFactory::CreateRandomGuildName()
{ {
std::string guildName = ""; std::string guildName = "";
QueryResult result = CharacterDatabase.Query("SELECT MAX(name_id) FROM playerbots_guild_names"); QueryResult result = CharacterDatabase.Query("SELECT MAX(name_id) FROM playerbots_guild_names");
@@ -740,10 +744,10 @@ std::string const RandomPlayerbotFactory::CreateRandomGuildName()
guildName = fields[0].Get<std::string>(); guildName = fields[0].Get<std::string>();
return std::move(guildName); return std::move(guildName);
} }
void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count) void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count)
{ {
std::vector<uint32> randomBots; std::vector<uint32> randomBots;
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BOT); PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BOT);
@@ -851,10 +855,10 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count
} }
LOG_INFO("playerbots", "{} random bot {}vs{} arena teams available", arenaTeamNumber, type, type); LOG_INFO("playerbots", "{} random bot {}vs{} arena teams available", arenaTeamNumber, type, type);
} }
std::string const RandomPlayerbotFactory::CreateRandomArenaTeamName() std::string const RandomPlayerbotFactory::CreateRandomArenaTeamName()
{ {
std::string arenaTeamName = ""; std::string arenaTeamName = "";
QueryResult result = CharacterDatabase.Query("SELECT MAX(name_id) FROM playerbots_arena_team_names"); QueryResult result = CharacterDatabase.Query("SELECT MAX(name_id) FROM playerbots_arena_team_names");
@@ -883,4 +887,4 @@ std::string const RandomPlayerbotFactory::CreateRandomArenaTeamName()
arenaTeamName = fields[0].Get<std::string>(); arenaTeamName = fields[0].Get<std::string>();
return std::move(arenaTeamName); return std::move(arenaTeamName);
} }