diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 40271940..d10f950c 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -43,6 +43,7 @@ #include "PlayerbotAIConfig.h" #include "PlayerbotDbStore.h" #include "PlayerbotMgr.h" +#include "PlayerbotGuildMgr.h" #include "Playerbots.h" #include "PointMovementGenerator.h" #include "PositionValue.h" @@ -5862,26 +5863,12 @@ bool PlayerbotAI::CanMove() return bot->GetMotionMaster()->GetCurrentMovementGeneratorType() != FLIGHT_MOTION_TYPE; } -bool PlayerbotAI::IsRealGuild(uint32 guildId) -{ - Guild* guild = sGuildMgr->GetGuildById(guildId); - if (!guild) - { - return false; - } - uint32 leaderAccount = sCharacterCache->GetCharacterAccountIdByGuid(guild->GetLeaderGUID()); - if (!leaderAccount) - return false; - - return !(sPlayerbotAIConfig->IsInRandomAccountList(leaderAccount)); -} - bool PlayerbotAI::IsInRealGuild() { if (!bot->GetGuildId()) return false; - return IsRealGuild(bot->GetGuildId()); + return sPlayerbotGuildMgr->IsRealGuild(bot->GetGuildId()); } void PlayerbotAI::QueueChatResponse(const ChatQueuedReply chatReply) { chatReplies.push_back(std::move(chatReply)); } diff --git a/src/PlayerbotAI.h b/src/PlayerbotAI.h index 602b18d2..c8f5f230 100644 --- a/src/PlayerbotAI.h +++ b/src/PlayerbotAI.h @@ -579,7 +579,6 @@ public: void ResetJumpDestination() { jumpDestination = Position(); } bool CanMove(); - static bool IsRealGuild(uint32 guildId); bool IsInRealGuild(); static std::vector dispel_whitelist; bool EqualLowercaseName(std::string s1, std::string s2); diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 1b47c196..d8a8b0b4 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -10,6 +10,7 @@ #include "PlayerbotDungeonSuggestionMgr.h" #include "PlayerbotFactory.h" #include "Playerbots.h" +#include "PlayerbotGuildMgr.h" #include "RandomItemMgr.h" #include "RandomPlayerbotFactory.h" #include "RandomPlayerbotMgr.h" @@ -666,6 +667,7 @@ bool PlayerbotAIConfig::Initialize() sRandomPlayerbotMgr->Init(); } + sPlayerbotGuildMgr->Init(); sRandomItemMgr->Init(); sRandomItemMgr->InitAfterAhBot(); sPlayerbotTextMgr->LoadBotTexts(); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 5013e412..fb112fc9 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -273,7 +273,6 @@ public: bool deleteRandomBotAccounts; uint32 randomBotGuildCount, randomBotGuildSizeMax; bool deleteRandomBotGuilds; - std::vector randomBotGuilds; std::vector pvpProhibitedZoneIds; std::vector pvpProhibitedAreaIds; bool fastReactInBG; diff --git a/src/PlayerbotGuildMgr.cpp b/src/PlayerbotGuildMgr.cpp new file mode 100644 index 00000000..98d71dab --- /dev/null +++ b/src/PlayerbotGuildMgr.cpp @@ -0,0 +1,322 @@ +#include "PlayerbotGuildMgr.h" +#include "Player.h" +#include "PlayerbotAIConfig.h" +#include "DatabaseEnv.h" +#include "Guild.h" +#include "GuildMgr.h" +#include "RandomPlayerbotMgr.h" +#include "ScriptMgr.h" + +PlayerbotGuildMgr::PlayerbotGuildMgr(){} + +void PlayerbotGuildMgr::Init() +{ + _guildCache.clear(); + if (sPlayerbotAIConfig->deleteRandomBotGuilds) + DeleteBotGuilds(); + + LoadGuildNames(); + ValidateGuildCache(); +} + +bool PlayerbotGuildMgr::CreateGuild(Player* player, std::string guildName) +{ + Guild* guild = new Guild(); + if (!guild->Create(player, guildName)) + { + LOG_ERROR("playerbots", "Error creating guild [ {} ] with leader [ {} ]", guildName, + player->GetName()); + delete guild; + return false; + } + sGuildMgr->AddGuild(guild); + + LOG_DEBUG("playerbots", "Guild created: id={} name='{}'", guild->GetId(), guildName); + SetGuildEmblem(guild->GetId()); + + GuildCache entry; + entry.name = guildName; + entry.memberCount = 1; + entry.status = 1; + entry.maxMembers = sPlayerbotAIConfig->randomBotGuildSizeMax; + entry.faction = player->GetTeamId(); + + _guildCache[guild->GetId()] = entry; + return true; +} + +bool PlayerbotGuildMgr::SetGuildEmblem(uint32 guildId) +{ + Guild* guild = sGuildMgr->GetGuildById(guildId); + if (!guild) + return false; + + // create random emblem + uint32 st, cl, br, bc, bg; + bg = urand(0, 51); + bc = urand(0, 17); + cl = urand(0, 17); + br = urand(0, 7); + st = urand(0, 180); + + LOG_DEBUG("playerbots", + "[TABARD] new guild id={} random -> style={}, color={}, borderStyle={}, borderColor={}, bgColor={}", + guild->GetId(), st, cl, br, bc, bg); + + // populate guild table with a random tabard design + CharacterDatabase.Execute( + "UPDATE guild SET EmblemStyle={}, EmblemColor={}, BorderStyle={}, BorderColor={}, BackgroundColor={} " + "WHERE guildid={}", + st, cl, br, bc, bg, guild->GetId()); + LOG_DEBUG("playerbots", "[TABARD] UPDATE done for guild id={}", guild->GetId()); + + // Immediate reading for log + if (QueryResult qr = CharacterDatabase.Query( + "SELECT EmblemStyle,EmblemColor,BorderStyle,BorderColor,BackgroundColor FROM guild WHERE guildid={}", + guild->GetId())) + { + Field* f = qr->Fetch(); + LOG_DEBUG("playerbots", + "[TABARD] DB check guild id={} => style={}, color={}, borderStyle={}, borderColor={}, bgColor={}", + guild->GetId(), f[0].Get(), f[1].Get(), f[2].Get(), f[3].Get(), f[4].Get()); + } + return true; +} + +std::string PlayerbotGuildMgr::AssignToGuild(Player* player) +{ + if (!player) + return ""; + + uint8_t playerFaction = player->GetTeamId(); + std::vector partiallyfilledguilds; + partiallyfilledguilds.reserve(_guildCache.size()); + + for (auto& keyValue : _guildCache) + { + GuildCache& cached = keyValue.second; + if (cached.status == 1 && cached.faction == playerFaction) + partiallyfilledguilds.push_back(&cached); + } + + if (!partiallyfilledguilds.empty()) + { + size_t idx = static_cast(urand(0, static_cast(partiallyfilledguilds.size()) - 1)); + return (partiallyfilledguilds[idx]->name); + } + + size_t count = std::count_if( + _guildCache.begin(), _guildCache.end(), + [](const std::pair& pair) + { + return !pair.second.hasRealPlayer; + } + ); + + if (count < sPlayerbotAIConfig->randomBotGuildCount) + { + for (auto& key : _shuffled_guild_keys) + { + if (_guildNames[key]) + { + LOG_INFO("playerbots","Assigning player [{}] to guild [{}]", player->GetName(), key); + return key; + } + } + LOG_ERROR("playerbots","No available guild names left."); + } + return ""; +} + +void PlayerbotGuildMgr::OnGuildUpdate(Guild* guild) +{ + auto it = _guildCache.find(guild->GetId()); + if (it == _guildCache.end()) + return; + + GuildCache& entry = it->second; + entry.memberCount = guild->GetMemberCount(); + if (entry.memberCount < entry.maxMembers) + entry.status = 1; + else if (entry.memberCount >= entry.maxMembers) + entry.status = 2; // Full + std::string guildName = guild->GetName(); + for (auto& it : _guildNames) + { + if (it.first == guildName) + { + it.second = false; + break; + } + } +} + +void PlayerbotGuildMgr::ResetGuildCache() +{ + for (auto it = _guildCache.begin(); it != _guildCache.end();) + { + GuildCache& cached = it->second; + cached.memberCount = 0; + cached.faction = 2; + cached.status = 0; + } +} + +void PlayerbotGuildMgr::LoadGuildNames() +{ + LOG_INFO("playerbots", "Loading guild names from playerbots_guild_names..."); + + QueryResult result = CharacterDatabase.Query("SELECT name_id, name FROM playerbots_guild_names"); + + if (!result) + { + LOG_ERROR("playerbots", "No entries found in playerbots_guild_names. List is empty."); + return; + } + + do + { + Field* fields = result->Fetch(); + _guildNames[fields[1].Get()] = true; + } while (result->NextRow()); + + for (auto& pair : _guildNames) + _shuffled_guild_keys.push_back(pair.first); + + std::random_device rd; + std::mt19937 g(rd()); + + std::shuffle(_shuffled_guild_keys.begin(), _shuffled_guild_keys.end(), g); + LOG_INFO("playerbots", "Loaded {} guild entries from playerbots_guild_names table.", _guildNames.size()); +} + +void PlayerbotGuildMgr::ValidateGuildCache() +{ + QueryResult result = CharacterDatabase.Query("SELECT guildid, name FROM guild"); + if (!result) + { + LOG_ERROR("playerbots", "No guilds found in database, resetting guild cache"); + ResetGuildCache(); + return; + } + + std::unordered_map dbGuilds; + do + { + Field* fields = result->Fetch(); + uint32 guildId = fields[0].Get(); + std::string guildName = fields[1].Get(); + dbGuilds[guildId] = guildName; + } while (result->NextRow()); + + for (auto it = dbGuilds.begin(); it != dbGuilds.end(); it++) + { + uint32 guildId = it->first; + GuildCache cache; + cache.name = it->second; + cache.maxMembers = sPlayerbotAIConfig->randomBotGuildSizeMax; + + Guild* guild = sGuildMgr ->GetGuildById(guildId); + if (!guild) + continue; + + cache.memberCount = guild->GetMemberCount(); + ObjectGuid leaderGuid = guild->GetLeaderGUID(); + CharacterCacheEntry const* leaderEntry = sCharacterCache->GetCharacterCacheByGuid(leaderGuid); + uint32 leaderAccount = leaderEntry->AccountId; + cache.hasRealPlayer = !(sPlayerbotAIConfig->IsInRandomAccountList(leaderAccount)); + cache.faction = Player::TeamIdForRace(leaderEntry->Race); + if (cache.memberCount == 0) + cache.status = 0; // empty + else if (cache.memberCount < cache.maxMembers) + cache.status = 1; // partially filled + else + cache.status = 2; // full + + _guildCache.insert_or_assign(guildId, cache); + for (auto& it : _guildNames) + { + if (it.first == cache.name) + { + it.second = false; + break; + } + } + } +} + +void PlayerbotGuildMgr::DeleteBotGuilds() +{ + LOG_INFO("playerbots", "Deleting random bot guilds..."); + std::vector randomBots; + + PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BOT); + stmt->SetData(0, "add"); + if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt)) + { + do + { + Field* fields = result->Fetch(); + uint32 bot = fields[0].Get(); + randomBots.push_back(bot); + } while (result->NextRow()); + } + + for (std::vector::iterator i = randomBots.begin(); i != randomBots.end(); ++i) + { + if (Guild* guild = sGuildMgr->GetGuildByLeader(ObjectGuid::Create(*i))) + guild->Disband(); + } + LOG_INFO("playerbots", "Random bot guilds deleted"); +} + +bool PlayerbotGuildMgr::IsRealGuild(Player* bot) +{ + if (!bot) + return false; + uint32 guildId = bot->GetGuildId(); + if (!guildId) + return false; + + return IsRealGuild(guildId); +} + +bool PlayerbotGuildMgr::IsRealGuild(uint32 guildId) +{ + if (!guildId) + return false; + + auto it = _guildCache.find(guildId); + if (it == _guildCache.end()) + return false; + + return it->second.hasRealPlayer; +} + +class BotGuildCacheWorldScript : public WorldScript +{ + public: + + BotGuildCacheWorldScript() : WorldScript("BotGuildCacheWorldScript"), _validateTimer(0){} + + void OnUpdate(uint32 diff) override + { + _validateTimer += diff; + + if (_validateTimer >= _validateInterval) // Validate every hour + { + _validateTimer = 0; + sPlayerbotGuildMgr->ValidateGuildCache(); + LOG_INFO("playerbots", "Scheduled guild cache validation"); + } + } + + private: + uint32 _validateInterval = HOUR*IN_MILLISECONDS; + uint32 _validateTimer; +}; + +void PlayerBotsGuildValidationScript() +{ + new BotGuildCacheWorldScript(); +} \ No newline at end of file diff --git a/src/PlayerbotGuildMgr.h b/src/PlayerbotGuildMgr.h new file mode 100644 index 00000000..0df0df73 --- /dev/null +++ b/src/PlayerbotGuildMgr.h @@ -0,0 +1,52 @@ +#ifndef _PLAYERBOT_PLAYERBOTGUILDMGR_H +#define _PLAYERBOT_PLAYERBOTGUILDMGR_H + +#include "Guild.h" +#include "Player.h" +#include "PlayerbotAI.h" + +class PlayerbotAI; + +class PlayerbotGuildMgr +{ +public: + static PlayerbotGuildMgr* instance() + { + static PlayerbotGuildMgr instance; + return &instance; + } + + void Init(); + std::string AssignToGuild(Player* player); + void LoadGuildNames(); + void ValidateGuildCache(); + void ResetGuildCache(); + bool CreateGuild(Player* player, std::string guildName); + void OnGuildUpdate (Guild* guild); + bool SetGuildEmblem(uint32 guildId); + void DeleteBotGuilds(); + bool IsRealGuild(uint32 guildId); + bool IsRealGuild(Player* bot); + +private: + PlayerbotGuildMgr(); + std::unordered_map _guildNames; + + struct GuildCache + { + std::string name; + uint8 status; + uint32 maxMembers = 0; + uint32 memberCount = 0; + uint8 faction = 0; + bool hasRealPlayer = false; + }; + std::unordered_map _guildCache; + std::vector _shuffled_guild_keys; +}; + +void PlayerBotsGuildValidationScript(); + +#define sPlayerbotGuildMgr PlayerbotGuildMgr::instance() + +#endif \ No newline at end of file diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index 13a6acff..ae3d4e1b 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -32,6 +32,7 @@ #include "PlayerbotSecurity.h" #include "PlayerbotWorldThreadProcessor.h" #include "Playerbots.h" +#include "PlayerbotGuildMgr.h" #include "RandomPlayerbotMgr.h" #include "SharedDefines.h" #include "WorldSession.h" @@ -1193,7 +1194,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg if (ObjectAccessor::FindConnectedPlayer(guid)) continue; uint32 guildId = sCharacterCache->GetCharacterGuildIdByGuid(guid); - if (guildId && PlayerbotAI::IsRealGuild(guildId)) + if (guildId && sPlayerbotGuildMgr->IsRealGuild(guildId)) continue; AddPlayerBot(guid, master->GetSession()->GetAccountId()); messages.push_back("Add class " + std::string(charname)); diff --git a/src/Playerbots.cpp b/src/Playerbots.cpp index e69c46bd..97e72e42 100644 --- a/src/Playerbots.cpp +++ b/src/Playerbots.cpp @@ -25,6 +25,7 @@ #include "Metric.h" #include "PlayerScript.h" #include "PlayerbotAIConfig.h" +#include "PlayerbotGuildMgr.h" #include "PlayerbotSpellCache.h" #include "PlayerbotWorldThreadProcessor.h" #include "RandomPlayerbotMgr.h" @@ -514,6 +515,6 @@ void AddPlayerbotsScripts() new PlayerbotsScript(); new PlayerBotsBGScript(); AddPlayerbotsSecureLoginScripts(); - AddSC_playerbots_commandscript(); + PlayerBotsGuildValidationScript(); } diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index 4be2d0ed..5a4672f5 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -11,6 +11,7 @@ #include "GuildMgr.h" #include "PlayerbotFactory.h" #include "Playerbots.h" +#include "PlayerbotGuildMgr.h" #include "ScriptMgr.h" #include "SharedDefines.h" #include "SocialMgr.h" @@ -754,187 +755,6 @@ void RandomPlayerbotFactory::CreateRandomBots() sPlayerbotAIConfig->randomBotAccounts.size(), totalRandomBotChars); } -void RandomPlayerbotFactory::CreateRandomGuilds() -{ - std::vector randomBots; - - PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BOT); - stmt->SetData(0, "add"); - if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt)) - { - do - { - Field* fields = result->Fetch(); - uint32 bot = fields[0].Get(); - randomBots.push_back(bot); - } while (result->NextRow()); - } - - if (sPlayerbotAIConfig->deleteRandomBotGuilds) - { - LOG_INFO("playerbots", "Deleting random bot guilds..."); - for (std::vector::iterator i = randomBots.begin(); i != randomBots.end(); ++i) - { - if (Guild* guild = sGuildMgr->GetGuildByLeader(ObjectGuid::Create(*i))) - guild->Disband(); - } - - LOG_INFO("playerbots", "Random bot guilds deleted"); - } - - 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; - sPlayerbotAIConfig->randomBotGuilds.clear(); - sPlayerbotAIConfig->randomBotGuilds.shrink_to_fit(); // avoids accumulating old capacity - - if (!botAccounts.empty()) - { - 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")) - { - do - { - Field* f = res->Fetch(); - const uint32 guildId = f[0].Get(); - const uint32 accountId = f[1].Get(); - - // Determine if guild leader's account is a bot account. - if (botAccounts.find(accountId) != botAccounts.end()) - { - ++guildNumber; - sPlayerbotAIConfig->randomBotGuilds.push_back(guildId); - } - } while (res->NextRow()); - } - } - - LOG_INFO("playerbots", "{}/{} random bot guilds exist in guild table",guildNumber, sPlayerbotAIConfig->randomBotGuildCount); - if (guildNumber >= sPlayerbotAIConfig->randomBotGuildCount) - { - LOG_DEBUG("playerbots", "No new random guilds required"); - return; - } - - // We list the available leaders (online bots, not in guilds) - GuidVector availableLeaders; - availableLeaders.reserve(randomBots.size()); // limit reallocs - for (const uint32 botLowGuid : randomBots) - { - ObjectGuid leader = ObjectGuid::Create(botLowGuid); - if (sGuildMgr->GetGuildByLeader(leader)) - { - // already GuildLeader -> ignored - continue; - } - else - { - if (Player* player = ObjectAccessor::FindPlayer(leader)) - { - if (!player->GetGuildId()) - availableLeaders.push_back(leader); - } - } - } - LOG_DEBUG("playerbots", "{} available leaders for new guilds found", availableLeaders.size()); - - // Create up to randomBotGuildCount by counting only EFFECTIVE creations - uint32 createdThisRun = 0; - for (; guildNumber < sPlayerbotAIConfig->randomBotGuildCount; /* ++guildNumber -> done only if creation */) - { - std::string const guildName = CreateRandomGuildName(); - if (guildName.empty()) - break; // no more names available in playerbots_guild_names - - if (sGuildMgr->GetGuildByName(guildName)) - continue; // name already taken, skip - - if (availableLeaders.empty()) - { - LOG_ERROR("playerbots", "No leaders for random guilds available"); - break; // no more leaders: we can no longer progress without distorting the counter - } - - uint32 index = urand(0, availableLeaders.size() - 1); - ObjectGuid leader = availableLeaders[index]; - availableLeaders.erase(availableLeaders.begin() + index); // Removes the chosen leader to avoid re-selecting it repeatedly - - Player* player = ObjectAccessor::FindPlayer(leader); - if (!player) - { - LOG_ERROR("playerbots", "ObjectAccessor Cannot find player to set leader for guild {} . Skipped...", - guildName.c_str()); - // we will try with other leaders in the next round (guildNumber is not incremented) - continue; - } - - if (player->GetGuildId()) - { - // leader already in guild -> we don't advance the counter, we move on to the next one - continue; - } - - LOG_DEBUG("playerbots", "Creating guild name='{}' leader='{}'...", guildName.c_str(), player->GetName().c_str()); - - Guild* guild = new Guild(); - if (!guild->Create(player, guildName)) - { - LOG_ERROR("playerbots", "Error creating guild [ {} ] with leader [ {} ]", guildName.c_str(), - player->GetName().c_str()); - delete guild; - continue; - } - - sGuildMgr->AddGuild(guild); - - LOG_DEBUG("playerbots", "Guild created: id={} name='{}'", guild->GetId(), guildName.c_str()); - - // create random emblem - uint32 st, cl, br, bc, bg; - bg = urand(0, 51); - bc = urand(0, 17); - cl = urand(0, 17); - br = urand(0, 7); - st = urand(0, 180); - - LOG_DEBUG("playerbots", - "[TABARD] new guild id={} random -> style={}, color={}, borderStyle={}, borderColor={}, bgColor={}", - guild->GetId(), st, cl, br, bc, bg); - - // populate guild table with a random tabard design - CharacterDatabase.Execute( - "UPDATE guild SET EmblemStyle={}, EmblemColor={}, BorderStyle={}, BorderColor={}, BackgroundColor={} " - "WHERE guildid={}", - st, cl, br, bc, bg, guild->GetId()); - LOG_DEBUG("playerbots", "[TABARD] UPDATE done for guild id={}", guild->GetId()); - - // Immediate reading for log - if (QueryResult qr = CharacterDatabase.Query( - "SELECT EmblemStyle,EmblemColor,BorderStyle,BorderColor,BackgroundColor FROM guild WHERE guildid={}", - guild->GetId())) - { - Field* f = qr->Fetch(); - LOG_DEBUG("playerbots", - "[TABARD] DB check guild id={} => style={}, color={}, borderStyle={}, borderColor={}, bgColor={}", - guild->GetId(), f[0].Get(), f[1].Get(), f[2].Get(), f[3].Get(), f[4].Get()); - } - - sPlayerbotAIConfig->randomBotGuilds.push_back(guild->GetId()); - // The guild is only counted if it is actually created - ++guildNumber; - ++createdThisRun; - } - - // Shows the true total and how many were created during this run - LOG_INFO("playerbots", "{} random bot guilds created this run)", createdThisRun); -} - std::string const RandomPlayerbotFactory::CreateRandomGuildName() { std::string guildName = ""; diff --git a/src/RandomPlayerbotFactory.h b/src/RandomPlayerbotFactory.h index d6c19e45..92f2c9f3 100644 --- a/src/RandomPlayerbotFactory.h +++ b/src/RandomPlayerbotFactory.h @@ -51,7 +51,6 @@ public: Player* CreateRandomBot(WorldSession* session, uint8 cls, std::unordered_map>& names); static void CreateRandomBots(); - static void CreateRandomGuilds(); static void CreateRandomArenaTeams(ArenaType slot, uint32 count); static std::string const CreateRandomGuildName(); static uint32 CalculateTotalAccountCount(); diff --git a/src/factory/PlayerbotFactory.cpp b/src/factory/PlayerbotFactory.cpp index 50a216c9..ef320eba 100644 --- a/src/factory/PlayerbotFactory.cpp +++ b/src/factory/PlayerbotFactory.cpp @@ -30,6 +30,7 @@ #include "PlayerbotAI.h" #include "PlayerbotAIConfig.h" #include "PlayerbotDbStore.h" +#include "PlayerbotGuildMgr.h" #include "Playerbots.h" #include "QuestDef.h" #include "RandomItemMgr.h" @@ -3965,45 +3966,33 @@ void PlayerbotFactory::InitInventoryEquip() void PlayerbotFactory::InitGuild() { if (bot->GetGuildId()) - return; - - // bot->SaveToDB(false, false); - - // add guild tabard - if (bot->GetGuildId() && !bot->HasItemCount(5976, 1)) - StoreItem(5976, 1); - - if (sPlayerbotAIConfig->randomBotGuilds.empty()) - RandomPlayerbotFactory::CreateRandomGuilds(); - - std::vector guilds; - for (std::vector::iterator i = sPlayerbotAIConfig->randomBotGuilds.begin(); - i != sPlayerbotAIConfig->randomBotGuilds.end(); ++i) - guilds.push_back(*i); - - if (guilds.empty()) { - LOG_ERROR("playerbots", "No random guilds available"); + if (!bot->HasItemCount(5976, 1) && bot->GetLevel() > 9) + StoreItem(5976, 1); return; } - int index = urand(0, guilds.size() - 1); - uint32 guildId = guilds[index]; - Guild* guild = sGuildMgr->GetGuildById(guildId); + std::string guildName = sPlayerbotGuildMgr->AssignToGuild(bot); + if (guildName.empty()) + return; + + Guild* guild = sGuildMgr->GetGuildByName(guildName); if (!guild) { - LOG_ERROR("playerbots", "Invalid guild {}", guildId); + if (!sPlayerbotGuildMgr->CreateGuild(bot, guildName)) + LOG_ERROR("playerbots","Failed to create guild {} for bot {}", guildName, bot->GetName()); return; } - - if (guild->GetMemberSize() < urand(10, sPlayerbotAIConfig->randomBotGuildSizeMax)) - guild->AddMember(bot->GetGUID(), urand(GR_OFFICER, GR_INITIATE)); - + else + { + if (guild->AddMember(bot->GetGUID(),urand(GR_OFFICER, GR_INITIATE))) + sPlayerbotGuildMgr->OnGuildUpdate(guild); + else + LOG_ERROR("playerbots","Bot {} failed to join guild {}.", bot->GetName(), guildName); + } // add guild tabard if (bot->GetGuildId() && bot->GetLevel() > 9 && urand(0, 4) && !bot->HasItemCount(5976, 1)) StoreItem(5976, 1); - - // bot->SaveToDB(false, false); } void PlayerbotFactory::InitImmersive()