/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "Playerbots.h" #include "Channel.h" #include "Config.h" #include "DatabaseEnv.h" #include "DatabaseLoader.h" #include "GuildTaskMgr.h" #include "Metric.h" #include "RandomPlayerbotMgr.h" #include "ScriptMgr.h" #include "cs_playerbots.h" #include "cmath" class PlayerbotsDatabaseScript : public DatabaseScript { public: PlayerbotsDatabaseScript() : DatabaseScript("PlayerbotsDatabaseScript") {} bool OnDatabasesLoading() override { DatabaseLoader playerbotLoader("server.playerbots"); playerbotLoader.SetUpdateFlags(sConfigMgr->GetOption("Playerbots.Updates.EnableDatabases", true) ? DatabaseLoader::DATABASE_PLAYERBOTS : 0); playerbotLoader.AddDatabase(PlayerbotsDatabase, "Playerbots"); return playerbotLoader.Load(); } void OnDatabasesKeepAlive() override { PlayerbotsDatabase.KeepAlive(); } void OnDatabasesClosing() override { PlayerbotsDatabase.Close(); } void OnDatabaseWarnAboutSyncQueries(bool apply) override { PlayerbotsDatabase.WarnAboutSyncQueries(apply); } void OnDatabaseSelectIndexLogout(Player* player, uint32& statementIndex, uint32& statementParam) override { statementIndex = CHAR_UPD_CHAR_OFFLINE; statementParam = player->GetGUID().GetCounter(); } void OnDatabaseGetDBRevision(std::string& revision) override { if (QueryResult resultPlayerbot = PlayerbotsDatabase.Query("SELECT date FROM version_db_playerbots ORDER BY date DESC LIMIT 1")) { Field* fields = resultPlayerbot->Fetch(); revision = fields[0].Get(); } if (revision.empty()) { revision = "Unknown Playerbots Database Revision"; } } }; class PlayerbotsPlayerScript : public PlayerScript { public: PlayerbotsPlayerScript() : PlayerScript("PlayerbotsPlayerScript") {} void OnPlayerLogin(Player* player) override { if (!player->GetSession()->IsBot()) { sPlayerbotsMgr->AddPlayerbotData(player, false); sRandomPlayerbotMgr->OnPlayerLogin(player); // Before modifying the following messages, please make sure it does not violate the AGPLv3.0 license // especially if you are distributing a repack or hosting a public server // e.g. you can replace the URL with your own repository, // but it should be publicly accessible and include all modifications you've made if (sPlayerbotAIConfig->enabled) { ChatHandler(player->GetSession()).SendSysMessage( "|cff00ff00This server runs with |cff00ccffmod-playerbots|r " "|cffcccccchttps://github.com/liyunfan1223/mod-playerbots|r"); } if (sPlayerbotAIConfig->enabled || sPlayerbotAIConfig->randomBotAutologin) { std::string roundedTime = std::to_string(std::ceil((sPlayerbotAIConfig->maxRandomBots * 0.11 / 60) * 10) / 10.0); roundedTime = roundedTime.substr(0, roundedTime.find('.') + 2); ChatHandler(player->GetSession()).SendSysMessage( "|cff00ff00Playerbots:|r bot initialization at server startup takes about '" + roundedTime + "' minutes."); } } } void OnPlayerAfterUpdate(Player* player, uint32 diff) override { if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) { botAI->UpdateAI(diff); } if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) { playerbotMgr->UpdateAI(diff); } } bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Player* receiver) override { if (type == CHAT_MSG_WHISPER) { if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(receiver)) { botAI->HandleCommand(type, msg, player); return false; } } return true; } void OnPlayerChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Group* group) override { for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) { if (Player* member = itr->GetSource()) { if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(member)) { botAI->HandleCommand(type, msg, player); } } } } void OnPlayerChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg) override { if (type == CHAT_MSG_GUILD) { if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) { for (PlayerBotMap::const_iterator it = playerbotMgr->GetPlayerBotsBegin(); it != playerbotMgr->GetPlayerBotsEnd(); ++it) { if (Player* const bot = it->second) { if (bot->GetGuildId() == player->GetGuildId()) { GET_PLAYERBOT_AI(bot)->HandleCommand(type, msg, player); } } } } } } void OnPlayerChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Channel* channel) override { if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) { if (channel->GetFlags() & 0x18) { playerbotMgr->HandleCommand(type, msg); } } sRandomPlayerbotMgr->HandleCommand(type, msg, player); } bool OnPlayerBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* /*criteria*/) override { if (sRandomPlayerbotMgr->IsRandomBot(player)) { return false; } return true; } bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* /*achievement*/) override { if (sRandomPlayerbotMgr->IsRandomBot(player)) { return false; } return true; } }; class PlayerbotsMiscScript : public MiscScript { public: PlayerbotsMiscScript() : MiscScript("PlayerbotsMiscScript", {MISCHOOK_ON_DESTRUCT_PLAYER}) {} void OnDestructPlayer(Player* player) override { if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) { delete botAI; } if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) { delete playerbotMgr; } } }; class PlayerbotsServerScript : public ServerScript { public: PlayerbotsServerScript() : ServerScript("PlayerbotsServerScript") {} void OnPacketReceived(WorldSession* session, WorldPacket const& packet) override { if (Player* player = session->GetPlayer()) if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) playerbotMgr->HandleMasterIncomingPacket(packet); } }; class PlayerbotsWorldScript : public WorldScript { public: PlayerbotsWorldScript() : WorldScript("PlayerbotsWorldScript") {} void OnBeforeWorldInitialized() override { // Before modifying the following messages, please make sure it does not violate the AGPLv3.0 license // especially if you are distributing a repack or hosting a public server // e.g. you can replace the URL with your own repository, // but it should be publicly accessible and include all modifications you've made LOG_INFO("server.loading", "============================================================"); LOG_INFO("server.loading", "|| ||"); LOG_INFO("server.loading", "|| AzerothCore Playerbots Module ||"); LOG_INFO("server.loading", "|| ||"); LOG_INFO("server.loading", "============================================================"); LOG_INFO("server.loading", "|| mod-playerbots is a community-driven open-source ||"); LOG_INFO("server.loading", "|| project based on AzerothCore, licensed under AGPLv3.0 ||"); LOG_INFO("server.loading", "============================================================"); LOG_INFO("server.loading", "|| https://github.com/liyunfan1223/mod-playerbots ||"); LOG_INFO("server.loading", "============================================================"); uint32 oldMSTime = getMSTime(); LOG_INFO("server.loading", " "); LOG_INFO("server.loading", "Load Playerbots Config..."); sPlayerbotAIConfig->Initialize(); LOG_INFO("server.loading", ">> Loaded playerbots config in {} ms", GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", " "); } }; class PlayerbotsScript : public PlayerbotScript { public: PlayerbotsScript() : PlayerbotScript("PlayerbotsScript") {} bool OnPlayerbotCheckLFGQueue(lfg::Lfg5Guids const& guidsList) override { bool nonBotFound = false; for (ObjectGuid const& guid : guidsList.guids) { Player* player = ObjectAccessor::FindPlayer(guid); if (guid.IsGroup() || (player && !GET_PLAYERBOT_AI(player))) { nonBotFound = true; break; } } return nonBotFound; } void OnPlayerbotCheckKillTask(Player* player, Unit* victim) override { if (player) sGuildTaskMgr->CheckKillTask(player, victim); } void OnPlayerbotCheckPetitionAccount(Player* player, bool& found) override { if (found && GET_PLAYERBOT_AI(player)) found = false; } bool OnPlayerbotCheckUpdatesToSend(Player* player) override { if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) return botAI->IsRealPlayer(); return true; } void OnPlayerbotPacketSent(Player* player, WorldPacket const* packet) override { if (!player) return; if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) { botAI->HandleBotOutgoingPacket(*packet); } if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) { playerbotMgr->HandleMasterOutgoingPacket(*packet); } } void OnPlayerbotUpdate(uint32 diff) override { sRandomPlayerbotMgr->UpdateAI(diff); sRandomPlayerbotMgr->UpdateSessions(); } void OnPlayerbotUpdateSessions(Player* player) override { if (player) if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) playerbotMgr->UpdateSessions(); } void OnPlayerbotLogout(Player* player) override { if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) { PlayerbotAI* botAI = GET_PLAYERBOT_AI(player); if (!botAI || botAI->IsRealPlayer()) { playerbotMgr->LogoutAllBots(); } } sRandomPlayerbotMgr->OnPlayerLogout(player); } void OnPlayerbotLogoutBots() override { sRandomPlayerbotMgr->LogoutAllBots(); } }; void AddPlayerbotsScripts() { new PlayerbotsDatabaseScript(); new PlayerbotsPlayerScript(); new PlayerbotsMiscScript(); new PlayerbotsServerScript(); new PlayerbotsWorldScript(); new PlayerbotsScript(); AddSC_playerbots_commandscript(); }