diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 5d445cab..37e1ad89 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -509,13 +509,6 @@ AiPlayerbot.RandomBotRandomPassword = 0 # Accounts to create for random bots AiPlayerbot.RandomBotAccountPrefix = "rndbot" -# Enable/Disable rotation of bots (randomly select a bot from the bots pool to go online and rotate them periodically) -# default: 0 (disable, the online bots are fixed) -AiPlayerbot.EnableRotation = 0 - -# Bots pool size for rotation (should be higher than MaxRandomBots) -AiPlayerbot.RotationPoolSize = 100 - AiPlayerbot.RandomBotMinLevel = 1 AiPlayerbot.RandomBotMaxLevel = 80 @@ -529,6 +522,16 @@ AiPlayerbot.PreQuests = 0 # Enable LFG for random bots AiPlayerbot.RandomBotJoinLfg = 1 +# Enable/Disable periodic online - offline to mimic the real-world scenario where not all players are online simultaneously +# When enabled, bots are randomly selected to go online or offline periodically from a larger set +# Default: 0 (disabled, the set of online bots remains fixed) +AiPlayerbot.EnablePeriodicOnlineOffline = 0 + +# Defines the ratio between the total number of bots (including offline ones) and the number of bots currently online (MaxRandomBots) +# This setting must greater than 1.0 and only applies when EnablePeriodicOnlineOffline +# Default: 2.0 (total number of bots is twice the number of MaxRandomBots) +AiPlayerbot.PeriodicOnlineOfflineRatio = 2.0 + # Percentage ratio of alliance and horde AiPlayerbot.RandomBotAllianceRatio = 50 AiPlayerbot.RandomBotHordeRatio = 50 @@ -877,7 +880,7 @@ AiPlayerbot.MinRandomBotReviveTime = 60 AiPlayerbot.MaxRandomBotReviveTime = 300 AiPlayerbot.MinRandomBotTeleportInterval = 3600 AiPlayerbot.MaxRandomBotTeleportInterval = 18000 -AiPlayerbot.RandomBotInWorldWithRotationDisabled = 31104000 +AiPlayerbot.PermanantlyInWorldTime = 31104000 # # diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 2eb0bcfa..71fd8d62 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -173,8 +173,8 @@ bool PlayerbotAIConfig::Initialize() maxRandomBotReviveTime = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotReviveTime", 5 * MINUTE); minRandomBotTeleportInterval = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotTeleportInterval", 1 * HOUR); maxRandomBotTeleportInterval = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotTeleportInterval", 5 * HOUR); - randomBotInWorldWithRotationDisabled = - sConfigMgr->GetOption("AiPlayerbot.RandomBotInWorldWithRotationDisabled", 1 * YEAR); + permanantlyInWorldTime = + sConfigMgr->GetOption("AiPlayerbot.PermanantlyInWorldTime", 1 * YEAR); randomBotTeleportDistance = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleportDistance", 100); randomBotsPerInterval = sConfigMgr->GetOption("AiPlayerbot.RandomBotsPerInterval", 60); minRandomBotsPriceChangeInterval = @@ -504,8 +504,8 @@ bool PlayerbotAIConfig::Initialize() limitEnchantExpansion = sConfigMgr->GetOption("AiPlayerbot.LimitEnchantExpansion", 1); limitGearExpansion = sConfigMgr->GetOption("AiPlayerbot.LimitGearExpansion", 1); randombotStartingLevel = sConfigMgr->GetOption("AiPlayerbot.RandombotStartingLevel", 5); - enableRotation = sConfigMgr->GetOption("AiPlayerbot.EnableRotation", false); - rotationPoolSize = sConfigMgr->GetOption("AiPlayerbot.RotationPoolSize", 100); + enablePeriodicOnlineOffline = sConfigMgr->GetOption("AiPlayerbot.EnablePeriodicOnlineOffline", false); + periodicOnlineOfflineRatio = sConfigMgr->GetOption("AiPlayerbot.PeriodicOnlineOfflineRatio", 2.0); gearscorecheck = sConfigMgr->GetOption("AiPlayerbot.GearScoreCheck", false); randomBotPreQuests = sConfigMgr->GetOption("AiPlayerbot.PreQuests", true); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index eced5535..f13178d3 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -95,7 +95,7 @@ public: uint32 minRandomBotChangeStrategyTime, maxRandomBotChangeStrategyTime; uint32 minRandomBotReviveTime, maxRandomBotReviveTime; uint32 minRandomBotTeleportInterval, maxRandomBotTeleportInterval; - uint32 randomBotInWorldWithRotationDisabled; + uint32 permanantlyInWorldTime; uint32 minRandomBotPvpTime, maxRandomBotPvpTime; uint32 randomBotsPerInterval; uint32 minRandomBotsPriceChangeInterval, maxRandomBotsPriceChangeInterval; @@ -235,8 +235,8 @@ public: uint32 limitEnchantExpansion; uint32 limitGearExpansion; uint32 randombotStartingLevel; - bool enableRotation; - uint32 rotationPoolSize; + bool enablePeriodicOnlineOffline; + float periodicOnlineOfflineRatio; bool gearscorecheck; bool randomBotPreQuests; diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index 3b6d9d1c..7142d93b 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -411,19 +411,45 @@ uint32 RandomPlayerbotFactory::CalculateTotalAccountCount() bool isWOTLK = sWorld->getIntConfig(CONFIG_EXPANSION) == EXPANSION_WRATH_OF_THE_LICH_KING; // Determine divisor based on WOTLK condition - int divisor = isWOTLK ? 10 : 9; + int divisor = CalculateAvailableCharsPerAccount(); - // Calculate max bots or rotation pool size - int maxBotsOrRotation = std::max( - sPlayerbotAIConfig->maxRandomBots, - sPlayerbotAIConfig->enableRotation ? sPlayerbotAIConfig->rotationPoolSize : 0 - ); + // Calculate max bots + int maxBots = sPlayerbotAIConfig->maxRandomBots; + // Take perodic online - offline into account + if (sPlayerbotAIConfig->enablePeriodicOnlineOffline) + { + maxBots *= sPlayerbotAIConfig->periodicOnlineOfflineRatio; + } // Calculate base accounts, add class account pool size, and add 1 as a fixed offset - uint32 baseAccounts = maxBotsOrRotation / divisor; + uint32 baseAccounts = maxBots / divisor; return baseAccounts + sPlayerbotAIConfig->addClassAccountPoolSize + 1; } +uint32 RandomPlayerbotFactory::CalculateAvailableCharsPerAccount() +{ + bool noDK = sPlayerbotAIConfig->disableDeathKnightLogin || sWorld->getIntConfig(CONFIG_EXPANSION) != EXPANSION_WRATH_OF_THE_LICH_KING; + + uint32 availableChars = noDK ? 9 : 10; + + uint32 hordeRatio = sPlayerbotAIConfig->randomBotHordeRatio; + uint32 allianceRatio = sPlayerbotAIConfig->randomBotAllianceRatio; + + // horde : alliance = 50 : 50 -> 0% + // horde : alliance = 0 : 50 -> 50% + // horde : alliance = 10 : 50 -> 40% + float unavailableRatio = static_cast((std::max(hordeRatio, allianceRatio) - std::min(hordeRatio, allianceRatio))) / + (std::max(hordeRatio, allianceRatio) * 2); + + if (unavailableRatio != 0) + { + // conservative floor to ensure enough chars (may result in more accounts than needed) + availableChars = availableChars - availableChars * unavailableRatio; + } + + return availableChars; +} + void RandomPlayerbotFactory::CreateRandomBots() { /* multi-thread here is meaningless? since the async db operations */ diff --git a/src/RandomPlayerbotFactory.h b/src/RandomPlayerbotFactory.h index a863c735..94e51537 100644 --- a/src/RandomPlayerbotFactory.h +++ b/src/RandomPlayerbotFactory.h @@ -54,13 +54,14 @@ public: static void CreateRandomGuilds(); static void CreateRandomArenaTeams(ArenaType slot, uint32 count); static std::string const CreateRandomGuildName(); + static uint32 CalculateTotalAccountCount(); + static uint32 CalculateAvailableCharsPerAccount(); private: std::string const CreateRandomBotName(NameRaceAndGender raceAndGender); static std::string const CreateRandomArenaTeamName(); uint32 accountId; - static uint32 CalculateTotalAccountCount(); static std::map> availableRaces; }; diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index 32e550b5..fd8e3fa4 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -47,6 +47,7 @@ #include "Unit.h" #include "UpdateTime.h" #include "World.h" +#include "RandomPlayerbotFactory.h" void PrintStatsThread() { sRandomPlayerbotMgr->PrintStats(); } @@ -464,18 +465,25 @@ uint32 RandomPlayerbotMgr::AddRandomBots() maxAllowedBotCount -= currentBots.size(); maxAllowedBotCount = std::min(sPlayerbotAIConfig->randomBotsPerInterval, maxAllowedBotCount); - uint32 allowedAllianceCount = maxAllowedBotCount * (sPlayerbotAIConfig->randomBotAllianceRatio) / (sPlayerbotAIConfig->randomBotAllianceRatio + sPlayerbotAIConfig->randomBotHordeRatio); + uint32 allowedAllianceCount = maxAllowedBotCount * (sPlayerbotAIConfig->randomBotAllianceRatio) / + (sPlayerbotAIConfig->randomBotAllianceRatio + sPlayerbotAIConfig->randomBotHordeRatio); uint32 allowedHordeCount = maxAllowedBotCount - allowedAllianceCount; for (std::vector::iterator i = sPlayerbotAIConfig->randomBotAccounts.begin(); i != sPlayerbotAIConfig->randomBotAccounts.end(); i++) { uint32 accountId = *i; - if (sPlayerbotAIConfig->enableRotation) + if (sPlayerbotAIConfig->enablePeriodicOnlineOffline) { - uint32 limit = std::min((uint32)sPlayerbotAIConfig->randomBotAccounts.size(), - sPlayerbotAIConfig->rotationPoolSize / 10 + 1); - uint32 index = urand(0, limit); + // minus addclass bots account + int32 baseAccount = RandomPlayerbotFactory::CalculateTotalAccountCount() - sPlayerbotAIConfig->addClassAccountPoolSize; + + if (baseAccount <= 0 || baseAccount > sPlayerbotAIConfig->randomBotAccounts.size()) + { + LOG_ERROR("playerbots", "Account calculation error with PeriodicOnlineOffline"); + return 0; + } + uint32 index = urand(0, baseAccount - 1); accountId = sPlayerbotAIConfig->randomBotAccounts[index]; } CharacterDatabasePreparedStatement* stmt = @@ -535,10 +543,10 @@ uint32 RandomPlayerbotMgr::AddRandomBots() for (uint32& guid : guids) { - uint32 add_time = sPlayerbotAIConfig->enableRotation + uint32 add_time = sPlayerbotAIConfig->enablePeriodicOnlineOffline ? urand(sPlayerbotAIConfig->minRandomBotInWorldTime, sPlayerbotAIConfig->maxRandomBotInWorldTime) - : sPlayerbotAIConfig->randomBotInWorldWithRotationDisabled; + : sPlayerbotAIConfig->permanantlyInWorldTime; SetEventValue(guid, "add", 1, add_time); SetEventValue(guid, "logout", 0, 0);