diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index 6af4e4e9..4d9aa06f 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -39,17 +39,16 @@ private: uint32 masterAccountId; PlayerbotHolder* playerbotHolder; public: - PlayerbotLoginQueryHolder(PlayerbotHolder* playerbotHolder, uint32 masterAccount, uint32 accountId, ObjectGuid guid, bool byAddClass) - : LoginQueryHolder(accountId, guid), masterAccountId(masterAccount), playerbotHolder(playerbotHolder), byAddClass(byAddClass) + PlayerbotLoginQueryHolder(PlayerbotHolder* playerbotHolder, uint32 masterAccount, uint32 accountId, ObjectGuid guid) + : LoginQueryHolder(accountId, guid), masterAccountId(masterAccount), playerbotHolder(playerbotHolder) { } uint32 GetMasterAccountId() const { return masterAccountId; } PlayerbotHolder* GetPlayerbotHolder() { return playerbotHolder; } - bool byAddClass; }; -void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId, bool byAddClass) +void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId) { // bot is loading if (botLoading.find(playerGuid) != botLoading.end()) @@ -71,12 +70,13 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId bool sameAccount = sPlayerbotAIConfig->allowAccountBots && accountId == masterAccountId; Guild* guild = masterPlayer ? sGuildMgr->GetGuildById(masterPlayer->GetGuildId()) : nullptr; bool sameGuild = sPlayerbotAIConfig->allowGuildBots && guild && guild->GetMember(playerGuid); + bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(playerGuid.GetCounter()); bool allowed = true; std::ostringstream out; std::string botName; sCharacterCache->GetCharacterNameByGuid(playerGuid, botName); - if (!isRndbot && !sameAccount && !sameGuild && !byAddClass) + if (!isRndbot && !sameAccount && !sameGuild && !addClassBot) { allowed = false; out << "Failure: You are not allowed to control bot " << botName.c_str(); @@ -106,7 +106,7 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId return; } std::shared_ptr holder = - std::make_shared(this, masterAccountId, accountId, playerGuid, byAddClass); + std::make_shared(this, masterAccountId, accountId, playerGuid); if (!holder->Initialize()) { return; @@ -131,7 +131,6 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder) { uint32 botAccountId = holder.GetAccountId(); - bool byAddClass = holder.byAddClass; // At login DBC locale should be what the server is set to use by default (as spells etc are hardcoded to ENUS this // allows channels to work as intended) WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, @@ -161,7 +160,7 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con } sRandomPlayerbotMgr->OnPlayerLogin(bot); - OnBotLogin(bot, byAddClass); + OnBotLogin(bot); botLoading.erase(holder.GetGuid()); } @@ -403,9 +402,7 @@ void PlayerbotHolder::DisablePlayerBot(ObjectGuid guid) void PlayerbotHolder::RemoveFromPlayerbotsMap(ObjectGuid guid) { - playerBots.erase(guid); - if (addClassBots.find(guid) != addClassBots.end()) - addClassBots.erase(guid); + playerBots.erase(guid); } Player* PlayerbotHolder::GetPlayerBot(ObjectGuid playerGuid) const @@ -421,7 +418,7 @@ Player* PlayerbotHolder::GetPlayerBot(ObjectGuid::LowType lowGuid) const return (it == playerBots.end()) ? 0 : it->second; } -void PlayerbotHolder::OnBotLogin(Player* const bot, bool byAddClass) +void PlayerbotHolder::OnBotLogin(Player* const bot) { // Prevent duplicate login if (playerBots.find(bot->GetGUID()) != playerBots.end()) @@ -431,9 +428,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot, bool byAddClass) sPlayerbotsMgr->AddPlayerbotData(bot, true); playerBots[bot->GetGUID()] = bot; - if (byAddClass) - addClassBots.insert(bot->GetGUID()); - + OnBotLoginInternal(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); @@ -482,10 +477,6 @@ void PlayerbotHolder::OnBotLogin(Player* const bot, bool byAddClass) if (!groupValid) { bot->RemoveFromGroup(); - // WorldPacket p; - // std::string const member = bot->GetName(); - // p << uint32(PARTY_OP_LEAVE) << member << uint32(0); - // bot->GetSession()->HandleGroupDisbandOpcode(p); } } @@ -557,7 +548,8 @@ void PlayerbotHolder::OnBotLogin(Player* const bot, bool byAddClass) } bot->SaveToDB(false, false); - if (byAddClass && master && isRandomAccount && master->GetLevel() < bot->GetLevel()) + bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(bot->GetGUID().GetCounter()); + if (addClassBot && master && isRandomAccount && master->GetLevel() < bot->GetLevel()) { // PlayerbotFactory factory(bot, master->GetLevel()); // factory.Randomize(false); @@ -673,21 +665,10 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje if (!bot) return "bot not found"; - bool addClassBot = true; - if (!isRandomAccount || isRandomBot) - { - addClassBot = false; - } - - if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster()) - { - PlayerbotMgr* masterMgr = GET_PLAYERBOT_MGR(master); - if (masterMgr && masterMgr->addClassBots.find(guid) == masterMgr->addClassBots.end()) - addClassBot = false; - } + bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(guid.GetCounter()); if (!addClassBot) - return "ERROR: You can not use this command on non-addclass random bot."; + return "ERROR: You can not use this command on non-addclass bot."; if (!admin) { @@ -1066,15 +1047,16 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg return messages; } uint8 teamId = master->GetTeamId(true); - std::vector &guidCache = sRandomPlayerbotMgr->addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)]; - for (size_t i = 0; i < guidCache.size(); i++) + const std::unordered_set &guidCache = sRandomPlayerbotMgr->addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)]; + for (const ObjectGuid &guid: guidCache) { - ObjectGuid guid = guidCache[i]; if (botLoading.find(guid) != botLoading.end()) continue; if (ObjectAccessor::FindConnectedPlayer(guid)) continue; - AddPlayerBot(guid, master->GetSession()->GetAccountId(), true); + if (sCharacterCache->GetCharacterGuildIdByGuid(guid)) + continue; + AddPlayerBot(guid, master->GetSession()->GetAccountId()); messages.push_back("Add class " + std::string(charname)); return messages; } diff --git a/src/PlayerbotMgr.h b/src/PlayerbotMgr.h index 9880a508..5c62c999 100644 --- a/src/PlayerbotMgr.h +++ b/src/PlayerbotMgr.h @@ -27,7 +27,7 @@ public: PlayerbotHolder(); virtual ~PlayerbotHolder(){}; - void AddPlayerBot(ObjectGuid guid, uint32 masterAccountId, bool byAddClass = false); + void AddPlayerBot(ObjectGuid guid, uint32 masterAccountId); void HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder); void LogoutPlayerBot(ObjectGuid guid); @@ -43,7 +43,7 @@ public: void HandleBotPackets(WorldSession* session); void LogoutAllBots(); - void OnBotLogin(Player* const bot, bool byAddClass = false); + void OnBotLogin(Player* const bot); std::vector HandlePlayerbotCommand(char const* args, Player* master = nullptr); std::string const ProcessBotCommand(std::string const cmd, ObjectGuid guid, ObjectGuid masterguid, bool admin, @@ -59,7 +59,6 @@ protected: virtual void OnBotLoginInternal(Player* const bot) = 0; PlayerBotMap playerBots; - std::unordered_set addClassBots; std::unordered_set botLoading; }; diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index 3c90c5cf..32e550b5 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -1709,37 +1709,34 @@ void RandomPlayerbotMgr::PrepareTeleportCache() void RandomPlayerbotMgr::PrepareAddclassCache() { - int32 maxAccountId = sPlayerbotAIConfig->randomBotAccounts.back(); - int32 minIdx = sPlayerbotAIConfig->randomBotAccounts.size() - 1 >= sPlayerbotAIConfig->addClassAccountPoolSize - ? sPlayerbotAIConfig->randomBotAccounts.size() - sPlayerbotAIConfig->addClassAccountPoolSize - : 0; - int32 minAccountId = sPlayerbotAIConfig->randomBotAccounts[minIdx]; - if (minAccountId < 0) - { - LOG_ERROR("playerbots", "No available account for add class!"); - } + /// @FIXME: Modifying RandomBotAccountCount may cause the original addclass bots to be converted into rndbots, + // which needs to be fixed by separating the two accounts in implementation + size_t poolSize = sPlayerbotAIConfig->addClassAccountPoolSize; + size_t start = sPlayerbotAIConfig->randomBotAccounts.size() > poolSize ? sPlayerbotAIConfig->randomBotAccounts.size() - poolSize : 0; int32 collected = 0; - for (uint8 claz = CLASS_WARRIOR; claz <= CLASS_DRUID; claz++) + for (size_t i = start; i < sPlayerbotAIConfig->randomBotAccounts.size(); i++) { - if (claz == 10) - continue; - QueryResult results = CharacterDatabase.Query( - "SELECT guid, race FROM characters " - "WHERE account >= {} AND account <= {} AND class = '{}' AND online = 0 AND " - "guid NOT IN ( SELECT guid FROM guild_member ) " - "ORDER BY account DESC", - minAccountId, maxAccountId, claz); - if (results) + for (uint8 claz = CLASS_WARRIOR; claz <= CLASS_DRUID; claz++) { - do + if (claz == 10) + continue; + QueryResult results = CharacterDatabase.Query( + "SELECT guid, race FROM characters " + "WHERE account = {} AND class = '{}' AND online = 0 " + "ORDER BY account DESC", + sPlayerbotAIConfig->randomBotAccounts[i], claz); + if (results) { - Field* fields = results->Fetch(); - ObjectGuid guid = ObjectGuid(HighGuid::Player, fields[0].Get()); - uint32 race = fields[1].Get(); - bool isAlliance = race == 1 || race == 3 || race == 4 || race == 7 || race == 11; - addclassCache[GetTeamClassIdx(isAlliance, claz)].push_back(guid); - collected++; - } while (results->NextRow()); + do + { + Field* fields = results->Fetch(); + ObjectGuid guid = ObjectGuid(HighGuid::Player, fields[0].Get()); + uint32 race = fields[1].Get(); + bool isAlliance = race == 1 || race == 3 || race == 4 || race == 7 || race == 11; + addclassCache[GetTeamClassIdx(isAlliance, claz)].insert(guid); + collected++; + } while (results->NextRow()); + } } } LOG_INFO("playerbots", ">> {} characters collected for addclass command.", collected); @@ -2113,6 +2110,22 @@ bool RandomPlayerbotMgr::IsRandomBot(ObjectGuid::LowType bot) return false; } +bool RandomPlayerbotMgr::IsAddclassBot(ObjectGuid::LowType bot) +{ + ObjectGuid guid = ObjectGuid::Create(bot); + for (uint8 claz = CLASS_WARRIOR; claz <= CLASS_DRUID; claz++) + { + if (claz == 10) + continue; + for (uint8 isAlliance = 0; isAlliance <= 1; isAlliance++) + { + if (addclassCache[GetTeamClassIdx(isAlliance, claz)].find(guid) != addclassCache[GetTeamClassIdx(isAlliance, claz)].end()) + return true; + } + } + return false; +} + void RandomPlayerbotMgr::GetBots() { if (!currentBots.empty()) diff --git a/src/RandomPlayerbotMgr.h b/src/RandomPlayerbotMgr.h index 8fa53fc9..4206a977 100644 --- a/src/RandomPlayerbotMgr.h +++ b/src/RandomPlayerbotMgr.h @@ -111,6 +111,7 @@ public: static bool HandlePlayerbotConsoleCommand(ChatHandler* handler, char const* args); bool IsRandomBot(Player* bot); bool IsRandomBot(ObjectGuid::LowType bot); + bool IsAddclassBot(ObjectGuid::LowType bot); void Randomize(Player* bot); void Clear(Player* bot); void RandomizeFirst(Player* bot); @@ -172,7 +173,7 @@ public: void PrepareAddclassCache(); void PrepareTeleportCache(); void Init(); - std::map> addclassCache; + std::map> addclassCache; std::map> locsPerLevelCache; std::map> allianceStarterPerLevelCache; std::map> hordeStarterPerLevelCache;