diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 496ea5d7..c3923270 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -655,7 +655,19 @@ AiPlayerbot.RandomBotJoinBG = 1 AiPlayerbot.RandomBotAutoJoinBG = 0 # Random bot arena team count -AiPlayerbot.RandomBotArenaTeamCount = 20 +# Teams are created when bots are initialized on server restart. +# You may need to first delete all arena teams, then reinitialize bots. +# Warning: Reinitializing bots completely resets them (command in game: .playerbots rndbot init) +# Bots only join one arena team to avoid queueing issues. Take that into account when increasing count. +# Default: 2v2: 10 (20 Bots), 3v3: 10 (30 bots), 5v5: 5 (25 bots). +AiPlayerbot.RandomBotArenaTeam2v2Count = 10 +AiPlayerbot.RandomBotArenaTeam3v3Count = 10 +AiPlayerbot.RandomBotArenaTeam5v5Count = 5 + +# Arena rating is randomized on team creation. +# Default: Max: 2000, Min: 1000. +AiPlayerbot.RandomBotArenaTeamMaxRating = 2000 +AiPlayerbot.RandomBotArenaTeamMinRating = 1000 # Delete all random bot arena teams AiPlayerbot.DeleteRandomBotArenaTeams = 0 diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 94765f34..3a75bc40 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -335,8 +335,12 @@ bool PlayerbotAIConfig::Initialize() randomBotGroupNearby = sConfigMgr->GetOption("AiPlayerbot.RandomBotGroupNearby", true); // arena - randomBotArenaTeamCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeamCount", 20); + randomBotArenaTeam2v2Count = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeam2v2Count", 10); + randomBotArenaTeam3v3Count = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeam3v3Count", 10); + randomBotArenaTeam5v5Count = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeam5v5Count", 5); deleteRandomBotArenaTeams = sConfigMgr->GetOption("AiPlayerbot.DeleteRandomBotArenaTeams", false); + randomBotArenaTeamMaxRating = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeamMaxRating", 2000); + randomBotArenaTeamMinRating = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeamMinRating", 1000); selfBotLevel = sConfigMgr->GetOption("AiPlayerbot.SelfBotLevel", 1); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index c008c051..986b1520 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -211,6 +211,11 @@ class PlayerbotAIConfig uint32 tweakValue; //Debugging config uint32 randomBotArenaTeamCount; + uint32 randomBotArenaTeamMaxRating; + uint32 randomBotArenaTeamMinRating; + uint32 randomBotArenaTeam2v2Count; + uint32 randomBotArenaTeam3v3Count; + uint32 randomBotArenaTeam5v5Count; bool deleteRandomBotArenaTeams; std::vector randomBotArenaTeams; diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 21409f18..249ada8a 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -5,6 +5,7 @@ #include "PlayerbotFactory.h" #include "AccountMgr.h" #include "AiFactory.h" +#include "ArenaTeam.h" #include "ArenaTeamMgr.h" #include "DBCStores.h" #include "DBCStructure.h" @@ -363,14 +364,14 @@ void PlayerbotFactory::Randomize(bool incremental) //if (pmo) // pmo->finish(); - // if (bot->GetLevel() >= 70) - // { - // pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas"); - // LOG_INFO("playerbots", "Initializing arena teams..."); - // InitArenaTeam(); - // if (pmo) - // pmo->finish(); - // } + if (bot->GetLevel() >= 70) + { + pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas"); + LOG_INFO("playerbots", "Initializing arena teams..."); + InitArenaTeam(); + if (pmo) + pmo->finish(); + } if (!incremental) { bot->RemovePet(nullptr, PET_SAVE_AS_CURRENT, true); @@ -3268,8 +3269,39 @@ void PlayerbotFactory::InitArenaTeam() if (!sPlayerbotAIConfig->IsInRandomAccountList(bot->GetSession()->GetAccountId())) return; + // Currently the teams are only remade after a server restart and if deleteRandomBotArenaTeams = 1 + // This is because randomBotArenaTeams is only empty on server restart. + // A manual reinitalization (.playerbots rndbot init) is also required after the teams have been deleted. if (sPlayerbotAIConfig->randomBotArenaTeams.empty()) - RandomPlayerbotFactory::CreateRandomArenaTeams(); + { + if (sPlayerbotAIConfig->deleteRandomBotArenaTeams) + { + LOG_INFO("playerbots", "Deleting random bot arena teams..."); + + for (auto it = sArenaTeamMgr->GetArenaTeams().begin(); it != sArenaTeamMgr->GetArenaTeams().end(); ++it) { + ArenaTeam* arenateam = it->second; + if (arenateam->GetCaptain() && arenateam->GetCaptain().IsPlayer()) + { + Player* bot = ObjectAccessor::FindPlayer(arenateam->GetCaptain()); + PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); + if (!botAI || botAI->IsRealPlayer()) + { + continue; + } + else + { + arenateam->Disband(nullptr); + } + } + } + + LOG_INFO("playerbots", "Random bot arena teams deleted"); + } + + RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_2v2, sPlayerbotAIConfig->randomBotArenaTeam2v2Count); + RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_3v3, sPlayerbotAIConfig->randomBotArenaTeam3v3Count); + RandomPlayerbotFactory::CreateRandomArenaTeams(ARENA_TYPE_5v5, sPlayerbotAIConfig->randomBotArenaTeam5v5Count); + } std::vector arenateams; for (std::vector::iterator i = sPlayerbotAIConfig->randomBotArenaTeams.begin(); i != sPlayerbotAIConfig->randomBotArenaTeams.end(); ++i) @@ -3281,28 +3313,47 @@ void PlayerbotFactory::InitArenaTeam() return; } - int index = urand(0, arenateams.size() - 1); - uint32 arenateamID = arenateams[index]; - ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamById(arenateamID); - if (!arenateam) + while (!arenateams.empty()) { - LOG_ERROR("playerbots", "Invalid arena team {}", arenateamID); - return; - } - - if (arenateam->GetMembersSize() < ((uint32)arenateam->GetType() * 2) && bot->GetLevel() >= 70) - { - ObjectGuid capt = arenateam->GetCaptain(); - Player* botcaptain = ObjectAccessor::FindPlayer(capt); - - if ((bot && bot->GetArenaTeamId(arenateam->GetSlot())) || sCharacterCache->GetCharacterArenaTeamIdByGuid(bot->GetGUID(), arenateam->GetSlot()) != 0) - return; - - if (botcaptain && botcaptain->GetTeamId() == bot->GetTeamId()) //need? + int index = urand(0, arenateams.size() - 1); + uint32 arenateamID = arenateams[index]; + ArenaTeam *arenateam = sArenaTeamMgr->GetArenaTeamById(arenateamID); + if (!arenateam) { - arenateam->AddMember(bot->GetGUID()); - arenateam->SaveToDB(); + LOG_ERROR("playerbots", "Invalid arena team {}", arenateamID); + arenateams.erase(arenateams.begin() + index); + continue; } + + if (arenateam->GetMembersSize() < ((uint32)arenateam->GetType()) && bot->GetLevel() >= 70) + { + ObjectGuid capt = arenateam->GetCaptain(); + Player* botcaptain = ObjectAccessor::FindPlayer(capt); + + // To avoid bots removing each other from groups when queueing, force them to only be in one team + for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot) + { + uint32 arenaTeamId = bot->GetArenaTeamId(arena_slot); + if (!arenaTeamId) + continue; + + ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(arenaTeamId); + if (team){ + if (sCharacterCache->GetCharacterArenaTeamIdByGuid(bot->GetGUID(), team->GetSlot()) != 0) + { + return; + } + return; + } + } + + if (botcaptain && botcaptain->GetTeamId() == bot->GetTeamId()) // need? + { + arenateam->AddMember(bot->GetGUID()); + arenateam->SaveToDB(); + } + } + arenateams.erase(arenateams.begin() + index); } bot->SaveToDB(false, false); diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index e1fec407..e17f1da8 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -618,7 +618,7 @@ std::string const RandomPlayerbotFactory::CreateRandomGuildName() return std::move(guildName); } -void RandomPlayerbotFactory::CreateRandomArenaTeams() +void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count) { std::vector randomBots; @@ -635,28 +635,12 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams() while (result->NextRow()); } - if (sPlayerbotAIConfig->deleteRandomBotArenaTeams) - { - LOG_INFO("playerbots", "Deleting random bot arena teams..."); - - for (std::vector::iterator i = randomBots.begin(); i != randomBots.end(); ++i) - { - ObjectGuid captain = ObjectGuid::Create(*i); - ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamByCaptain(captain); - if (arenateam) - //sObjectMgr->RemoveArenaTeam(arenateam->GetId()); - arenateam->Disband(nullptr); - } - - LOG_INFO("playerbots", "Random bot arena teams deleted"); - } - uint32 arenaTeamNumber = 0; GuidVector availableCaptains; for (std::vector::iterator i = randomBots.begin(); i != randomBots.end(); ++i) { ObjectGuid captain = ObjectGuid::Create(*i); - ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamByCaptain(captain); + ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamByCaptain(captain, type); if (arenateam) { ++arenaTeamNumber; @@ -671,7 +655,7 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams() } } - for (; arenaTeamNumber < sPlayerbotAIConfig->randomBotArenaTeamCount; ++arenaTeamNumber) + for (; arenaTeamNumber < count; ++arenaTeamNumber) { std::string const arenaTeamName = CreateRandomArenaTeamName(); if (arenaTeamName.empty()) @@ -698,29 +682,17 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams() continue; } - QueryResult results = CharacterDatabase.Query("SELECT `type` FROM playerbots_arena_team_names WHERE name = '{}'", arenaTeamName.c_str()); - if (!results) - { - LOG_ERROR("playerbots", "No valid types for arena teams"); - return; - } + // Below query no longer required as now user has control over the number of each type of arena team they want to create. + // Keeping commented for potential future reference. + // QueryResult results = CharacterDatabase.Query("SELECT `type` FROM playerbots_arena_team_names WHERE name = '{}'", arenaTeamName.c_str()); + // if (!results) + // { + // LOG_ERROR("playerbots", "No valid types for arena teams"); + // return; + // } - Field* fields = results->Fetch(); - uint8 slot = fields[0].Get(); - - ArenaType type; - switch (slot) - { - case 2: - type = ARENA_TYPE_2v2; - break; - case 3: - type = ARENA_TYPE_3v3; - break; - case 5: - type = ARENA_TYPE_5v5; - break; - } + // Field* fields = results->Fetch(); + // uint8 slot = fields[0].Get(); ArenaTeam* arenateam = new ArenaTeam(); if (!arenateam->Create(player->GetGUID(), type, arenaTeamName, 0, 0, 0, 0, 0)) @@ -732,7 +704,7 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams() arenateam->SetCaptain(player->GetGUID()); // set random rating - arenateam->SetRatingForAll(urand(1500, 2700)); + arenateam->SetRatingForAll(urand(sPlayerbotAIConfig->randomBotArenaTeamMinRating, sPlayerbotAIConfig->randomBotArenaTeamMaxRating)); // set random emblem uint32 backgroundColor = urand(0xFF000000, 0xFFFFFFFF); diff --git a/src/RandomPlayerbotFactory.h b/src/RandomPlayerbotFactory.h index d6a69eba..f022f013 100644 --- a/src/RandomPlayerbotFactory.h +++ b/src/RandomPlayerbotFactory.h @@ -10,10 +10,13 @@ #include #include #include +#include "DBCEnums.h" class Player; class WorldSession; +enum ArenaType : uint8; + class RandomPlayerbotFactory { public: @@ -23,7 +26,7 @@ class RandomPlayerbotFactory Player* CreateRandomBot(WorldSession* session, uint8 cls, std::unordered_map> names); static void CreateRandomBots(); static void CreateRandomGuilds(); - static void CreateRandomArenaTeams(); + static void CreateRandomArenaTeams(ArenaType slot, uint32 count); static std::string const CreateRandomGuildName(); private: