From 7d50ceef3daebef32075085ed88d7293d7b857ce Mon Sep 17 00:00:00 2001 From: Iain Donnelly Date: Wed, 1 Oct 2025 16:39:48 +0100 Subject: [PATCH 1/7] Update RandomPlayerbotFactory.cpp Added a query to count the number of guilds straight from the DB, then filter out player guilds. (instead of relying on accessing guilds from a list of random bots and adding them up) This needs some formatting / tidying once I make sure we are counting guilds properly. --- src/RandomPlayerbotFactory.cpp | 41 ++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index cf5fdc91..b5d74b8d 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -875,15 +875,52 @@ void RandomPlayerbotFactory::CreateRandomGuilds() LOG_INFO("playerbots", "Random bot guilds deleted"); } + // Check how many randomBot guilds are in the guild table in the characterDB uint32 guildNumber = 0; + QueryResult guildTableResults = CharacterDatabase.Query("SELECT guildid, leaderguid FROM guid"); + if (guildTableResults) + { + do + { + Field* fields = guildTableResults->Fetch(); + uint32 guildID = fields[0].Get(); + uint32 leaderGuid = fields[1].Get(); + + // check the accountID of the guild leader against the list of randomBot accounts to determine if this is a player guild or a bot guild + QueryResult charactersTableResults = CharacterDatabase.Query("SELECT account FROM characters WHERE guid = ({})", leaderGuid); + if (charactersTableResults) + { + Field* fields2 = charactersTableResults->Fetch(); + uint32 accountID = fields2[0].Get(); + + if(std::find(sPlayerbotAIConfig->randomBotAccounts.begin(),sPlayerbotAIConfig->randomBotAccounts.end(), accountID) != sPlayerbotAIConfig->randomBotAccounts.end()) + { + guildNumber++; + sPlayerbotAIConfig->randomBotGuilds.push_back(guildID); + } + } + } while (guildTableResults->NextRow()); + } + GuidVector availableLeaders; for (std::vector::iterator i = randomBots.begin(); i != randomBots.end(); ++i) { ObjectGuid leader = ObjectGuid::Create(*i); if (Guild* guild = sGuildMgr->GetGuildByLeader(leader)) { - ++guildNumber; - sPlayerbotAIConfig->randomBotGuilds.push_back(guild->GetId()); + uint32 guildID = guild->GetId(); + if(std::find(sPlayerbotAIConfig->randomBotGuilds.begin(), sPlayerbotAIConfig->randomBotGuilds.end(), guildID) !=sPlayerbotAIConfig->randomBotGuilds.end()) + { + // this randombot guild has already been counted, the leader is not availble + } + else + { + // somehow we missed this guild when checking the guild table + // THIS SHOULDN'T RUN. + // THIS ENTIRE FIND() IS A WASTE OF RESOURCES (in theory) + ++guildNumber; + sPlayerbotAIConfig->randomBotGuilds.push_back(guildID); + } } else { From 8a68de4476fef4aa0c00d97e5c6a855ffc445276 Mon Sep 17 00:00:00 2001 From: Iain Donnelly Date: Wed, 1 Oct 2025 17:36:00 +0100 Subject: [PATCH 2/7] Update RandomPlayerbotFactory.cpp Fixed a typo --- src/RandomPlayerbotFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index b5d74b8d..c28b9587 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -877,7 +877,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds() // Check how many randomBot guilds are in the guild table in the characterDB uint32 guildNumber = 0; - QueryResult guildTableResults = CharacterDatabase.Query("SELECT guildid, leaderguid FROM guid"); + QueryResult guildTableResults = CharacterDatabase.Query("SELECT guildid, leaderguid FROM guild"); if (guildTableResults) { do @@ -887,7 +887,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds() uint32 leaderGuid = fields[1].Get(); // check the accountID of the guild leader against the list of randomBot accounts to determine if this is a player guild or a bot guild - QueryResult charactersTableResults = CharacterDatabase.Query("SELECT account FROM characters WHERE guid = ({})", leaderGuid); + QueryResult charactersTableResults = CharacterDatabase.Query("SELECT account FROM characters WHERE guid = {}", leaderGuid); if (charactersTableResults) { Field* fields2 = charactersTableResults->Fetch(); From 444be2994e184eff444bdb5334cf2b63dc824aca Mon Sep 17 00:00:00 2001 From: Iain Donnelly Date: Wed, 1 Oct 2025 23:20:48 +0100 Subject: [PATCH 3/7] v2 Neatened some things up, removed obsolete code, added a break out of the loop if an empty guild name (none available) is returned from the playerbots_guild_names table. --- src/RandomPlayerbotFactory.cpp | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index c28b9587..49d32b0c 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -902,25 +902,14 @@ void RandomPlayerbotFactory::CreateRandomGuilds() } while (guildTableResults->NextRow()); } + // Get a list of bots that are logged in and available to lead new guilds GuidVector availableLeaders; for (std::vector::iterator i = randomBots.begin(); i != randomBots.end(); ++i) { ObjectGuid leader = ObjectGuid::Create(*i); if (Guild* guild = sGuildMgr->GetGuildByLeader(leader)) { - uint32 guildID = guild->GetId(); - if(std::find(sPlayerbotAIConfig->randomBotGuilds.begin(), sPlayerbotAIConfig->randomBotGuilds.end(), guildID) !=sPlayerbotAIConfig->randomBotGuilds.end()) - { - // this randombot guild has already been counted, the leader is not availble - } - else - { - // somehow we missed this guild when checking the guild table - // THIS SHOULDN'T RUN. - // THIS ENTIRE FIND() IS A WASTE OF RESOURCES (in theory) - ++guildNumber; - sPlayerbotAIConfig->randomBotGuilds.push_back(guildID); - } + // Bot is already a GM } else { @@ -929,6 +918,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds() availableLeaders.push_back(leader); } } + LOG_INFO("playerbots", "randomBotGuilds - {} available leaders for new guilds found", availableLeaders.size()); // Create up to randomBotGuildCount by counting only EFFECTIVE creations uint32 createdThisRun = 0; @@ -936,10 +926,10 @@ void RandomPlayerbotFactory::CreateRandomGuilds() { std::string const guildName = CreateRandomGuildName(); if (guildName.empty()) - continue; + break; // no more names available in playerbots_guild_names if (sGuildMgr->GetGuildByName(guildName)) - continue; + continue; // name already taken, skip if (availableLeaders.empty()) { From 24f841f7284a24b5a2ef32423847f029aa5af4a0 Mon Sep 17 00:00:00 2001 From: Iain Donnelly Date: Wed, 1 Oct 2025 23:35:08 +0100 Subject: [PATCH 4/7] Verbose logging. Should now be able to see guild count values as the server inits --- src/RandomPlayerbotFactory.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index 49d32b0c..4b375c11 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -902,6 +902,18 @@ void RandomPlayerbotFactory::CreateRandomGuilds() } while (guildTableResults->NextRow()); } + // Is it worth continuing? + LOG_INFO("playerbots", "{}/{} random bot guilds exist in guild table)", guildNumber, sPlayerbotAIConfig->randomBotGuildCount); + if (guildNumber >= sPlayerbotAIConfig->randomBotGuildCount) + { + LOG_INFO("playerbots", "No new random guilds required"); + return; + } + else + { + LOG_INFO("playerbots", "Creating {} new random guilds...", sPlayerbotAIConfig->randomBotGuildCount - guildNumber); + } + // Get a list of bots that are logged in and available to lead new guilds GuidVector availableLeaders; for (std::vector::iterator i = randomBots.begin(); i != randomBots.end(); ++i) @@ -918,7 +930,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds() availableLeaders.push_back(leader); } } - LOG_INFO("playerbots", "randomBotGuilds - {} available leaders for new guilds found", availableLeaders.size()); + LOG_INFO("playerbots", "{} available leaders for new guilds found", availableLeaders.size()); // Create up to randomBotGuildCount by counting only EFFECTIVE creations uint32 createdThisRun = 0; @@ -1008,8 +1020,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds() } // Shows the true total and how many were created during this run - LOG_INFO("playerbots", "{} random bot guilds available (created this run: {})", - uint32(sPlayerbotAIConfig->randomBotGuilds.size()), createdThisRun); + LOG_INFO("playerbots", "{} random bot guilds created this run)", createdThisRun); } std::string const RandomPlayerbotFactory::CreateRandomGuildName() From 0e4c759e7f2b9951dda811960ff72b03765a5f93 Mon Sep 17 00:00:00 2001 From: Iain Donnelly Date: Thu, 2 Oct 2025 14:37:47 +0100 Subject: [PATCH 5/7] Wishmaster update Optimised, better use of DB Query, avoids reallocations. Nice. --- src/RandomPlayerbotFactory.cpp | 69 ++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index 4b375c11..bed18d6c 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -875,59 +875,64 @@ void RandomPlayerbotFactory::CreateRandomGuilds() LOG_INFO("playerbots", "Random bot guilds deleted"); } - // Check how many randomBot guilds are in the guild table in the characterDB + std::unordered_set botAccounts; + botAccounts.reserve(sPlayerbotAIConfig->randomBotAccounts.size()); + for (uint32 acc : sPlayerbotAIConfig->randomBotAccounts) + botAccounts.insert(acc); + + // Recount bot guilds directly from the database (does not depend on connected bots) uint32 guildNumber = 0; - QueryResult guildTableResults = CharacterDatabase.Query("SELECT guildid, leaderguid FROM guild"); - if (guildTableResults) + sPlayerbotAIConfig->randomBotGuilds.clear(); + sPlayerbotAIConfig->randomBotGuilds.shrink_to_fit(); // avoids accumulating old capacity + + if (!botAccounts.empty()) { - do + if (QueryResult res = CharacterDatabase.Query( + // We only retrieve what is necessary (guildid, leader account) + "SELECT g.guildid, c.account " + "FROM guild g JOIN characters c ON g.leaderguid = c.guid")) { - Field* fields = guildTableResults->Fetch(); - uint32 guildID = fields[0].Get(); - uint32 leaderGuid = fields[1].Get(); - - // check the accountID of the guild leader against the list of randomBot accounts to determine if this is a player guild or a bot guild - QueryResult charactersTableResults = CharacterDatabase.Query("SELECT account FROM characters WHERE guid = {}", leaderGuid); - if (charactersTableResults) + do { - Field* fields2 = charactersTableResults->Fetch(); - uint32 accountID = fields2[0].Get(); + Field* f = res->Fetch(); + const uint32 guildId = f[0].Get(); + const uint32 accountId = f[1].Get(); - if(std::find(sPlayerbotAIConfig->randomBotAccounts.begin(),sPlayerbotAIConfig->randomBotAccounts.end(), accountID) != sPlayerbotAIConfig->randomBotAccounts.end()) + // Boss considered 'bot' if his account is in botAccounts + if (botAccounts.find(accountId) != botAccounts.end()) { - guildNumber++; - sPlayerbotAIConfig->randomBotGuilds.push_back(guildID); + ++guildNumber; + sPlayerbotAIConfig->randomBotGuilds.push_back(guildId); } - } - } while (guildTableResults->NextRow()); + } while (res->NextRow()); + } } - // Is it worth continuing? - LOG_INFO("playerbots", "{}/{} random bot guilds exist in guild table)", guildNumber, sPlayerbotAIConfig->randomBotGuildCount); + LOG_INFO("playerbots", "{}/{} random bot guilds exist in guild table",guildNumber, sPlayerbotAIConfig->randomBotGuildCount); if (guildNumber >= sPlayerbotAIConfig->randomBotGuildCount) { LOG_INFO("playerbots", "No new random guilds required"); return; } - else - { - LOG_INFO("playerbots", "Creating {} new random guilds...", sPlayerbotAIConfig->randomBotGuildCount - guildNumber); - } - // Get a list of bots that are logged in and available to lead new guilds + // We list the available leaders (online bots, not in guilds) GuidVector availableLeaders; - for (std::vector::iterator i = randomBots.begin(); i != randomBots.end(); ++i) + availableLeaders.reserve(randomBots.size()); // limit reallocs + for (const uint32 botLowGuid : randomBots) { - ObjectGuid leader = ObjectGuid::Create(*i); - if (Guild* guild = sGuildMgr->GetGuildByLeader(leader)) + ObjectGuid leader = ObjectGuid::Create(botLowGuid); + if (sGuildMgr->GetGuildByLeader(leader)) { - // Bot is already a GM + // already GuildLeader -> ignored + continue; } else { - Player* player = ObjectAccessor::FindPlayer(leader); - if (player && !player->GetGuildId()) - availableLeaders.push_back(leader); + if (Player* player = ObjectAccessor::FindPlayer(leader)) + { + if (!player->GetGuildId()) + availableLeaders.push_back(leader); + } } } LOG_INFO("playerbots", "{} available leaders for new guilds found", availableLeaders.size()); From 3f050a4a77371a3564e601fe592ee7be0f822927 Mon Sep 17 00:00:00 2001 From: Iain Donnelly Date: Tue, 7 Oct 2025 22:46:19 +0100 Subject: [PATCH 6/7] Change LOG_INFO to LOG_DEBUG --- src/RandomPlayerbotFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index bed18d6c..48531b96 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -911,7 +911,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds() LOG_INFO("playerbots", "{}/{} random bot guilds exist in guild table",guildNumber, sPlayerbotAIConfig->randomBotGuildCount); if (guildNumber >= sPlayerbotAIConfig->randomBotGuildCount) { - LOG_INFO("playerbots", "No new random guilds required"); + LOG_DEBUG("playerbots", "No new random guilds required"); return; } @@ -935,7 +935,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds() } } } - LOG_INFO("playerbots", "{} available leaders for new guilds found", availableLeaders.size()); + LOG_DEBUG("playerbots", "{} available leaders for new guilds found", availableLeaders.size()); // Create up to randomBotGuildCount by counting only EFFECTIVE creations uint32 createdThisRun = 0; From 1d19dea9746bc7fb26db56dd9af0232c832e7be0 Mon Sep 17 00:00:00 2001 From: Iain Donnelly Date: Wed, 22 Oct 2025 23:53:42 +0100 Subject: [PATCH 7/7] Update RandomPlayerbotFactory.cpp --- src/RandomPlayerbotFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index 48531b96..ceed748d 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -898,7 +898,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds() const uint32 guildId = f[0].Get(); const uint32 accountId = f[1].Get(); - // Boss considered 'bot' if his account is in botAccounts + // Determine if guild leader's account is a bot account. if (botAccounts.find(accountId) != botAccounts.end()) { ++guildNumber;