mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 23:49:25 +02:00
<!--
Thank you for contributing to mod-playerbots, please make sure that
you...
1. Submit your PR to the test-staging branch, not master.
2. Read the guidelines below before submitting.
3. Don't delete parts of this template.
DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND
PREDICTABILITY over behavioral realism.
Every action and decision executes PER BOT AND PER TRIGGER. Small
increases in logic complexity scale
poorly across thousands of bots and negatively affect all. We prioritize
a stable system over a smarter
one. Bots don't need to behave perfectly; believable behavior is the
goal, not human simulation.
Default behavior must be cheap in processing; expensive behavior must be
opt-in.
Before submitting, make sure your changes aligns with these principles.
-->
## Pull Request Description
<!-- Describe what this change does and why it is needed -->
Clean up a bunch of additional unused variable warnings.
## Feature Evaluation
<!--
If your PR is very minimal (comment typo, wrong ID reference, etc), and
it is very obvious it will not have
any impact on performance, you may skip these question. If necessary, a
maintainer may ask you for them later.
-->
<!-- Please answer the following: -->
- Describe the **minimum logic** required to achieve the intended
behavior.
- Describe the **processing cost** when this logic executes across many
bots.
## How to Test the Changes
<!--
- Step-by-step instructions to test the change.
- Any required setup (e.g. multiple players, number of bots, specific
configuration).
- Expected behavior and how to verify it.
-->
## Impact Assessment
<!-- As a generic test, before and after measure of pmon (playerbot pmon
tick) can help you here. -->
- Does this change increase per-bot/per-tick processing or risk scaling
poorly with thousands of bots?
- - [x] No, not at all
- - [ ] Minimal impact (**explain below**)
- - [ ] Moderate impact (**explain below**)
- Does this change modify default bot behavior?
- - [x] No
- - [ ] Yes (**explain why**)
- Does this change add new decision branches or increase maintenance
complexity?
- - [x] No
- - [ ] Yes (**explain below**)
## Messages to Translate
<!--
Bot messages have to be translatable, but you don't need to do the
translations here. You only need to make sure
the message is in a translatable format, and list in the table the
message_key and the default English message.
Search for GetBotTextOrDefault in the codebase for examples.
-->
- Does this change add bot messages to translate?
- - [x] No
- - [ ] Yes (**list messages in the table**)
| Message key | Default message |
| --------------- | ------------------ |
| | |
| | |
## AI Assistance
<!--
AI assistance is allowed, but all submitted code must be fully
understood, reviewed, and owned by the contributor.
We expect contributors to be honest about what they do and do not
understand.
-->
- Was AI assistance used while working on this change?
- - [ ] No
- - [x] Yes (**explain below**)
<!--
If yes, please specify:
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code
generation).
- Which parts of the change were influenced or generated, and whether it
was thoroughly reviewed.
-->
Claude reviewed the warnings log from a build and suggested a series of
changes. I focused just on these warnings for now. Every line was
reviewed. Some sections need to be reviewed by author for intent.
## Final Checklist
- - [x] Stability is not compromised.
- - [x] Performance impact is understood, tested, and acceptable.
- - [x] Added logic complexity is justified and explained.
- - [x] Documentation updated if needed (Conf comments, WiKi commands).
## Notes for Reviewers
<!-- Anything else that's helpful to review or test your pull request.
-->
545 lines
19 KiB
C++
545 lines
19 KiB
C++
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "Playerbots.h"
|
|
|
|
#include "BattlefieldScript.h"
|
|
#include "Channel.h"
|
|
#include "Config.h"
|
|
#include "DatabaseEnv.h"
|
|
#include "DatabaseLoader.h"
|
|
#include "GuildTaskMgr.h"
|
|
#include "PlayerScript.h"
|
|
#include "PlayerbotAIConfig.h"
|
|
#include "PlayerbotGuildMgr.h"
|
|
#include "PlayerbotSpellRepository.h"
|
|
#include "PlayerbotWorldThreadProcessor.h"
|
|
#include "RandomPlayerbotMgr.h"
|
|
#include "ScriptMgr.h"
|
|
#include "PlayerbotCommandScript.h"
|
|
#include "cmath"
|
|
#include "BattleGroundTactics.h"
|
|
|
|
class PlayerbotsDatabaseScript : public DatabaseScript
|
|
{
|
|
public:
|
|
PlayerbotsDatabaseScript() : DatabaseScript("PlayerbotsDatabaseScript") {}
|
|
|
|
bool OnDatabasesLoading() override
|
|
{
|
|
DatabaseLoader playerbotLoader("server.playerbots");
|
|
playerbotLoader.SetUpdateFlags(sConfigMgr->GetOption<bool>("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<std::string>();
|
|
}
|
|
|
|
if (revision.empty())
|
|
revision = "Unknown Playerbots Database Revision";
|
|
}
|
|
};
|
|
|
|
class PlayerbotsPlayerScript : public PlayerScript
|
|
{
|
|
public:
|
|
PlayerbotsPlayerScript() : PlayerScript("PlayerbotsPlayerScript", {
|
|
PLAYERHOOK_ON_LOGIN,
|
|
PLAYERHOOK_ON_AFTER_UPDATE,
|
|
PLAYERHOOK_ON_BEFORE_CRITERIA_PROGRESS,
|
|
PLAYERHOOK_ON_BEFORE_ACHI_COMPLETE,
|
|
PLAYERHOOK_CAN_PLAYER_USE_PRIVATE_CHAT,
|
|
PLAYERHOOK_CAN_PLAYER_USE_GROUP_CHAT,
|
|
PLAYERHOOK_CAN_PLAYER_USE_GUILD_CHAT,
|
|
PLAYERHOOK_CAN_PLAYER_USE_CHANNEL_CHAT,
|
|
PLAYERHOOK_ON_GIVE_EXP,
|
|
PLAYERHOOK_ON_BEFORE_TELEPORT
|
|
}) {}
|
|
|
|
void OnPlayerLogin(Player* player) override
|
|
{
|
|
if (!player->GetSession()->IsBot())
|
|
{
|
|
PlayerbotsMgr::instance().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/mod-playerbots/mod-playerbots|r");
|
|
}
|
|
|
|
if (sPlayerbotAIConfig.enabled || sPlayerbotAIConfig.randomBotAutologin)
|
|
{
|
|
std::string maxAllowedBotCount = std::to_string(sRandomPlayerbotMgr.GetMaxAllowedBotCount());
|
|
|
|
ChatHandler(player->GetSession()).SendSysMessage(
|
|
"|cff00ff00Playerbots:|r The server is configured with " + maxAllowedBotCount + " bots.");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool OnPlayerBeforeTeleport(Player* /*player*/, uint32 /*mapid*/, float /*x*/, float /*y*/, float /*z*/,
|
|
float /*orientation*/, uint32 /*options*/, Unit* /*target*/) override
|
|
{
|
|
/* for now commmented out until proven its actually required
|
|
* havent seen any proof CleanVisibilityReferences() is needed
|
|
|
|
// If the player is not safe to touch, do nothing
|
|
if (!player)
|
|
return true;
|
|
|
|
// If same map or not in world do nothing
|
|
if (!player->IsInWorld() || player->GetMapId() == mapid)
|
|
return true;
|
|
|
|
// If real player do nothing
|
|
PlayerbotAI* ai = GET_PLAYERBOT_AI(player);
|
|
if (!ai || ai->IsRealPlayer())
|
|
return true;
|
|
|
|
// Cross-map bot teleport: defer visibility reference cleanup.
|
|
// CleanVisibilityReferences() erases this bot's GUID from other objects' visibility containers.
|
|
// This is intentionally done via the event queue (instead of directly here) because erasing
|
|
// from other players' visibility maps inside the teleport call stack can hit unsafe re-entrancy
|
|
// or iterator invalidation while visibility updates are in progress
|
|
ObjectGuid guid = player->GetGUID();
|
|
player->m_Events.AddEventAtOffset(
|
|
[guid, mapid]()
|
|
{
|
|
// do nothing, if the player is not safe to touch
|
|
Player* p = ObjectAccessor::FindPlayer(guid);
|
|
if (!p || !p->IsInWorld() || p->IsDuringRemoveFromWorld())
|
|
return;
|
|
|
|
// do nothing if we are already on the target map
|
|
if (p->GetMapId() == mapid)
|
|
return;
|
|
|
|
p->GetObjectVisibilityContainer().CleanVisibilityReferences();
|
|
},
|
|
Milliseconds(0));
|
|
|
|
*/
|
|
|
|
return true;
|
|
}
|
|
|
|
void OnPlayerAfterUpdate(Player* player, uint32 diff) override
|
|
{
|
|
PlayerbotAI* const botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player);
|
|
|
|
if (botAI != nullptr)
|
|
{
|
|
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)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
PlayerbotAI* const botAI = PlayerbotsMgr::instance().GetPlayerbotAI(receiver);
|
|
|
|
if (botAI == nullptr)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
botAI->HandleCommand(type, msg, player);
|
|
|
|
// hotfix; otherwise the server will crash when whispering logout
|
|
// https://github.com/mod-playerbots/mod-playerbots/pull/1838
|
|
// TODO: find the root cause and solve it. (does not happen in party chat)
|
|
if (msg == "logout")
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Group* group) override
|
|
{
|
|
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
|
{
|
|
Player* const member = itr->GetSource();
|
|
|
|
if (member == nullptr)
|
|
continue;
|
|
|
|
PlayerbotAI* const botAI = PlayerbotsMgr::instance().GetPlayerbotAI(member);
|
|
|
|
if (botAI == nullptr)
|
|
continue;
|
|
|
|
botAI->HandleCommand(type, msg, player);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Guild* /*guild*/) override
|
|
{
|
|
if (type != CHAT_MSG_GUILD)
|
|
return true;
|
|
|
|
PlayerbotMgr* playerbotMgr = PlayerbotsMgr::instance().GetPlayerbotMgr(player);
|
|
|
|
if (playerbotMgr == nullptr)
|
|
return true;
|
|
|
|
for (PlayerBotMap::const_iterator it = playerbotMgr->GetPlayerBotsBegin(); it != playerbotMgr->GetPlayerBotsEnd(); ++it)
|
|
{
|
|
Player* const bot = it->second;
|
|
|
|
if (bot == nullptr)
|
|
continue;
|
|
|
|
if (bot->GetGuildId() != player->GetGuildId())
|
|
continue;
|
|
|
|
PlayerbotsMgr::instance().GetPlayerbotAI(bot)->HandleCommand(type, msg, player);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Channel* channel) override
|
|
{
|
|
PlayerbotMgr* const playerbotMgr = PlayerbotsMgr::instance().GetPlayerbotMgr(player);
|
|
|
|
if (playerbotMgr != nullptr && channel->GetFlags() & 0x18)
|
|
playerbotMgr->HandleCommand(type, msg);
|
|
|
|
sRandomPlayerbotMgr.HandleCommand(type, msg, player);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* achievement) override
|
|
{
|
|
if ((sRandomPlayerbotMgr.IsRandomBot(player) || sRandomPlayerbotMgr.IsAddclassBot(player)) &&
|
|
(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void OnPlayerGiveXP(Player* player, uint32& amount, Unit* /*victim*/, uint8 /*xpSource*/) override
|
|
{
|
|
// early return
|
|
if (sPlayerbotAIConfig.randomBotXPRate == 1.0 || !player)
|
|
return;
|
|
|
|
// no XP multiplier, when player is no bot.
|
|
if (!player->GetSession()->IsBot() || !sRandomPlayerbotMgr.IsRandomBot(player))
|
|
return;
|
|
|
|
// no XP multiplier, when bot is in a group with a real player.
|
|
if (Group* group = player->GetGroup())
|
|
{
|
|
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
|
{
|
|
Player* member = gref->GetSource();
|
|
if (!member)
|
|
continue;
|
|
|
|
if (!member->GetSession()->IsBot())
|
|
return;
|
|
}
|
|
}
|
|
|
|
// otherwise apply bot XP multiplier.
|
|
amount = static_cast<uint32>(std::round(static_cast<float>(amount) * sPlayerbotAIConfig.randomBotXPRate));
|
|
}
|
|
};
|
|
|
|
class PlayerbotsMiscScript : public MiscScript
|
|
{
|
|
public:
|
|
PlayerbotsMiscScript() : MiscScript("PlayerbotsMiscScript", {MISCHOOK_ON_DESTRUCT_PLAYER}) {}
|
|
|
|
void OnDestructPlayer(Player* player) override
|
|
{
|
|
PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player);
|
|
|
|
if (botAI != nullptr)
|
|
delete botAI;
|
|
|
|
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
|
delete playerbotMgr;
|
|
}
|
|
};
|
|
|
|
class PlayerbotsServerScript : public ServerScript
|
|
{
|
|
public:
|
|
PlayerbotsServerScript() : ServerScript("PlayerbotsServerScript", {
|
|
SERVERHOOK_CAN_PACKET_RECEIVE
|
|
}) {}
|
|
|
|
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", {
|
|
WORLDHOOK_ON_BEFORE_WORLD_INITIALIZED,
|
|
WORLDHOOK_ON_UPDATE
|
|
}) {}
|
|
|
|
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/mod-playerbots/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", " ");
|
|
|
|
PlayerbotSpellRepository::Instance().Initialize();
|
|
|
|
LOG_INFO("server.loading", "Playerbots World Thread Processor initialized");
|
|
}
|
|
|
|
void OnUpdate(uint32 diff) override
|
|
{
|
|
PlayerbotWorldThreadProcessor::instance().Update(diff);
|
|
sRandomPlayerbotMgr.UpdateAI(diff); // World thread only
|
|
}
|
|
};
|
|
|
|
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 && !PlayerbotsMgr::instance().GetPlayerbotAI(player)))
|
|
{
|
|
nonBotFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return nonBotFound;
|
|
}
|
|
|
|
void OnPlayerbotCheckKillTask(Player* player, Unit* victim) override
|
|
{
|
|
if (player)
|
|
GuildTaskMgr::instance().CheckKillTask(player, victim);
|
|
}
|
|
|
|
void OnPlayerbotCheckPetitionAccount(Player* player, bool& found) override
|
|
{
|
|
if (!found)
|
|
return;
|
|
|
|
if (PlayerbotsMgr::instance().GetPlayerbotAI(player) != nullptr)
|
|
found = false;
|
|
}
|
|
|
|
bool OnPlayerbotCheckUpdatesToSend(Player* player) override
|
|
{
|
|
PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player);
|
|
|
|
if (botAI == nullptr)
|
|
return true;
|
|
|
|
return botAI->IsRealPlayer();
|
|
}
|
|
|
|
void OnPlayerbotPacketSent(Player* player, WorldPacket const* packet) override
|
|
{
|
|
if (player == nullptr)
|
|
return;
|
|
|
|
PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player);
|
|
|
|
if (botAI != nullptr)
|
|
botAI->HandleBotOutgoingPacket(*packet);
|
|
|
|
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
|
playerbotMgr->HandleMasterOutgoingPacket(*packet);
|
|
}
|
|
|
|
void OnPlayerbotUpdate(uint32 /*diff*/) override
|
|
{
|
|
sRandomPlayerbotMgr.UpdateSessions(); // Per-bot updates only
|
|
}
|
|
|
|
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 = PlayerbotsMgr::instance().GetPlayerbotAI(player);
|
|
|
|
if (botAI == nullptr || botAI->IsRealPlayer())
|
|
{
|
|
playerbotMgr->LogoutAllBots();
|
|
}
|
|
}
|
|
|
|
sRandomPlayerbotMgr.OnPlayerLogout(player);
|
|
}
|
|
|
|
void OnPlayerbotLogoutBots() override
|
|
{
|
|
LOG_INFO("playerbots", "Logging out all bots...");
|
|
sRandomPlayerbotMgr.LogoutAllBots();
|
|
}
|
|
};
|
|
|
|
class PlayerBotsBGScript : public BGScript
|
|
{
|
|
public:
|
|
PlayerBotsBGScript() : BGScript("PlayerBotsBGScript") {}
|
|
|
|
void OnBattlegroundStart(Battleground* bg) override
|
|
{
|
|
BGStrategyData data;
|
|
|
|
switch (bg->GetBgTypeID())
|
|
{
|
|
case BATTLEGROUND_WS:
|
|
data.allianceStrategy = urand(0, WS_STRATEGY_MAX - 1);
|
|
data.hordeStrategy = urand(0, WS_STRATEGY_MAX - 1);
|
|
break;
|
|
case BATTLEGROUND_AB:
|
|
data.allianceStrategy = urand(0, AB_STRATEGY_MAX - 1);
|
|
data.hordeStrategy = urand(0, AB_STRATEGY_MAX - 1);
|
|
break;
|
|
case BATTLEGROUND_AV:
|
|
data.allianceStrategy = urand(0, AV_STRATEGY_MAX - 1);
|
|
data.hordeStrategy = urand(0, AV_STRATEGY_MAX - 1);
|
|
break;
|
|
case BATTLEGROUND_EY:
|
|
data.allianceStrategy = urand(0, EY_STRATEGY_MAX - 1);
|
|
data.hordeStrategy = urand(0, EY_STRATEGY_MAX - 1);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
bgStrategies[bg->GetInstanceID()] = data;
|
|
}
|
|
|
|
void OnBattlegroundEnd(Battleground* bg, TeamId /*winnerTeam*/) override { bgStrategies.erase(bg->GetInstanceID()); }
|
|
};
|
|
|
|
// Workaround for missing InitEnabledHooksIfNeeded for new BattlefieldScript in ScriptMgr
|
|
class PlayerbotsBattlefieldScript : public BattlefieldScript
|
|
{
|
|
public:
|
|
PlayerbotsBattlefieldScript() : BattlefieldScript("PlayerbotsBattlefieldScript") { }
|
|
};
|
|
|
|
void AddPlayerbotsSecureLoginScripts();
|
|
|
|
void AddSC_TempestKeepBotScripts();
|
|
|
|
void AddPlayerbotsScripts()
|
|
{
|
|
new PlayerbotsBattlefieldScript();
|
|
new PlayerbotsDatabaseScript();
|
|
new PlayerbotsPlayerScript();
|
|
new PlayerbotsMiscScript();
|
|
new PlayerbotsServerScript();
|
|
new PlayerbotsWorldScript();
|
|
new PlayerbotsScript();
|
|
new PlayerBotsBGScript();
|
|
AddPlayerbotsSecureLoginScripts();
|
|
AddPlayerbotsCommandscripts();
|
|
PlayerBotsGuildValidationScript();
|
|
AddSC_TempestKeepBotScripts();
|
|
}
|