mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-02-02 10:23:47 +00:00
Compare commits
3 Commits
b16789fa54
...
83c6977de5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83c6977de5 | ||
|
|
686fe513b2 | ||
|
|
61402e83a1 |
@@ -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"
|
||||
@@ -1503,9 +1504,6 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
|
||||
case 532:
|
||||
strategyName = "karazhan"; // Karazhan
|
||||
break;
|
||||
case 533:
|
||||
strategyName = "naxx"; // Naxxramas
|
||||
break;
|
||||
case 544:
|
||||
strategyName = "magtheridon"; // Magtheridon's Lair
|
||||
break;
|
||||
@@ -5865,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)); }
|
||||
|
||||
@@ -579,7 +579,6 @@ public:
|
||||
void ResetJumpDestination() { jumpDestination = Position(); }
|
||||
|
||||
bool CanMove();
|
||||
static bool IsRealGuild(uint32 guildId);
|
||||
bool IsInRealGuild();
|
||||
static std::vector<std::string> dispel_whitelist;
|
||||
bool EqualLowercaseName(std::string s1, std::string s2);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -273,7 +273,6 @@ public:
|
||||
bool deleteRandomBotAccounts;
|
||||
uint32 randomBotGuildCount, randomBotGuildSizeMax;
|
||||
bool deleteRandomBotGuilds;
|
||||
std::vector<uint32> randomBotGuilds;
|
||||
std::vector<uint32> pvpProhibitedZoneIds;
|
||||
std::vector<uint32> pvpProhibitedAreaIds;
|
||||
bool fastReactInBG;
|
||||
|
||||
322
src/PlayerbotGuildMgr.cpp
Normal file
322
src/PlayerbotGuildMgr.cpp
Normal file
@@ -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<uint8>(), f[1].Get<uint8>(), f[2].Get<uint8>(), f[3].Get<uint8>(), f[4].Get<uint8>());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string PlayerbotGuildMgr::AssignToGuild(Player* player)
|
||||
{
|
||||
if (!player)
|
||||
return "";
|
||||
|
||||
uint8_t playerFaction = player->GetTeamId();
|
||||
std::vector<GuildCache*> 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<size_t>(urand(0, static_cast<int>(partiallyfilledguilds.size()) - 1));
|
||||
return (partiallyfilledguilds[idx]->name);
|
||||
}
|
||||
|
||||
size_t count = std::count_if(
|
||||
_guildCache.begin(), _guildCache.end(),
|
||||
[](const std::pair<const uint32, GuildCache>& 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<std::string>()] = 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<uint32, std::string> dbGuilds;
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint32 guildId = fields[0].Get<uint32>();
|
||||
std::string guildName = fields[1].Get<std::string>();
|
||||
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<uint32> 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<uint32>();
|
||||
randomBots.push_back(bot);
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
for (std::vector<uint32>::iterator i = randomBots.begin(); i != randomBots.end(); ++i)
|
||||
{
|
||||
if (Guild* guild = sGuildMgr->GetGuildByLeader(ObjectGuid::Create<HighGuid::Player>(*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();
|
||||
}
|
||||
52
src/PlayerbotGuildMgr.h
Normal file
52
src/PlayerbotGuildMgr.h
Normal file
@@ -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<std::string, bool> _guildNames;
|
||||
|
||||
struct GuildCache
|
||||
{
|
||||
std::string name;
|
||||
uint8 status;
|
||||
uint32 maxMembers = 0;
|
||||
uint32 memberCount = 0;
|
||||
uint8 faction = 0;
|
||||
bool hasRealPlayer = false;
|
||||
};
|
||||
std::unordered_map<uint32 , GuildCache> _guildCache;
|
||||
std::vector<std::string> _shuffled_guild_keys;
|
||||
};
|
||||
|
||||
void PlayerBotsGuildValidationScript();
|
||||
|
||||
#define sPlayerbotGuildMgr PlayerbotGuildMgr::instance()
|
||||
|
||||
#endif
|
||||
@@ -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<std::string> 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));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<uint32> 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<uint32>();
|
||||
randomBots.push_back(bot);
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->deleteRandomBotGuilds)
|
||||
{
|
||||
LOG_INFO("playerbots", "Deleting random bot guilds...");
|
||||
for (std::vector<uint32>::iterator i = randomBots.begin(); i != randomBots.end(); ++i)
|
||||
{
|
||||
if (Guild* guild = sGuildMgr->GetGuildByLeader(ObjectGuid::Create<HighGuid::Player>(*i)))
|
||||
guild->Disband();
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "Random bot guilds deleted");
|
||||
}
|
||||
|
||||
std::unordered_set<uint32> 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<uint32>();
|
||||
const uint32 accountId = f[1].Get<uint32>();
|
||||
|
||||
// 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<HighGuid::Player>(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<uint8>(), f[1].Get<uint8>(), f[2].Get<uint8>(), f[3].Get<uint8>(), f[4].Get<uint8>());
|
||||
}
|
||||
|
||||
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 = "";
|
||||
|
||||
@@ -51,7 +51,6 @@ public:
|
||||
|
||||
Player* CreateRandomBot(WorldSession* session, uint8 cls, std::unordered_map<NameRaceAndGender, std::vector<std::string>>& names);
|
||||
static void CreateRandomBots();
|
||||
static void CreateRandomGuilds();
|
||||
static void CreateRandomArenaTeams(ArenaType slot, uint32 count);
|
||||
static std::string const CreateRandomGuildName();
|
||||
static uint32 CalculateTotalAccountCount();
|
||||
|
||||
@@ -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<uint32> guilds;
|
||||
for (std::vector<uint32>::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()
|
||||
|
||||
@@ -43,8 +43,6 @@
|
||||
#include "raids/magtheridon/RaidMagtheridonTriggerContext.h"
|
||||
#include "raids/gruulslair/RaidGruulsLairActionContext.h"
|
||||
#include "raids/gruulslair/RaidGruulsLairTriggerContext.h"
|
||||
#include "raids/naxxramas/RaidNaxxActionContext.h"
|
||||
#include "raids/naxxramas/RaidNaxxTriggerContext.h"
|
||||
#include "raids/eyeofeternity/RaidEoEActionContext.h"
|
||||
#include "raids/eyeofeternity/RaidEoETriggerContext.h"
|
||||
#include "raids/vaultofarchavon/RaidVoAActionContext.h"
|
||||
@@ -117,7 +115,6 @@ void AiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Act
|
||||
actionContexts.Add(new RaidKarazhanActionContext());
|
||||
actionContexts.Add(new RaidMagtheridonActionContext());
|
||||
actionContexts.Add(new RaidGruulsLairActionContext());
|
||||
actionContexts.Add(new RaidNaxxActionContext());
|
||||
actionContexts.Add(new RaidOsActionContext());
|
||||
actionContexts.Add(new RaidEoEActionContext());
|
||||
actionContexts.Add(new RaidVoAActionContext());
|
||||
@@ -152,7 +149,6 @@ void AiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Tr
|
||||
triggerContexts.Add(new RaidKarazhanTriggerContext());
|
||||
triggerContexts.Add(new RaidMagtheridonTriggerContext());
|
||||
triggerContexts.Add(new RaidGruulsLairTriggerContext());
|
||||
triggerContexts.Add(new RaidNaxxTriggerContext());
|
||||
triggerContexts.Add(new RaidOsTriggerContext());
|
||||
triggerContexts.Add(new RaidEoETriggerContext());
|
||||
triggerContexts.Add(new RaidVoATriggerContext());
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
#include "OutfitAction.h"
|
||||
#include "PositionAction.h"
|
||||
#include "DropQuestAction.h"
|
||||
#include "RaidNaxxActions.h"
|
||||
#include "RandomBotUpdateAction.h"
|
||||
#include "ReachTargetActions.h"
|
||||
#include "ReleaseSpiritAction.h"
|
||||
|
||||
@@ -185,7 +185,6 @@ public:
|
||||
creators["guild remove"] = &ChatActionContext::guild_remove;
|
||||
creators["guild leave"] = &ChatActionContext::guild_leave;
|
||||
creators["rtsc"] = &ChatActionContext::rtsc;
|
||||
creators["naxx chat shortcut"] = &ChatActionContext::naxx_chat_shortcut;
|
||||
creators["bwl chat shortcut"] = &ChatActionContext::bwl_chat_shortcut;
|
||||
creators["tell estimated dps"] = &ChatActionContext::tell_estimated_dps;
|
||||
creators["join"] = &ChatActionContext::join;
|
||||
@@ -298,7 +297,6 @@ private:
|
||||
static Action* guild_remove(PlayerbotAI* botAI) { return new GuildRemoveAction(botAI); }
|
||||
static Action* guild_leave(PlayerbotAI* botAI) { return new GuildLeaveAction(botAI); }
|
||||
static Action* rtsc(PlayerbotAI* botAI) { return new RTSCAction(botAI); }
|
||||
static Action* naxx_chat_shortcut(PlayerbotAI* ai) { return new NaxxChatShortcutAction(ai); }
|
||||
static Action* bwl_chat_shortcut(PlayerbotAI* ai) { return new BwlChatShortcutAction(ai); }
|
||||
static Action* tell_estimated_dps(PlayerbotAI* ai) { return new TellEstimatedDpsAction(ai); }
|
||||
static Action* join(PlayerbotAI* ai) { return new JoinGroupAction(ai); }
|
||||
|
||||
@@ -241,20 +241,6 @@ bool MaxDpsChatShortcutAction::Execute(Event event)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NaxxChatShortcutAction::Execute(Event event)
|
||||
{
|
||||
Player* master = GetMaster();
|
||||
if (!master)
|
||||
return false;
|
||||
|
||||
botAI->Reset();
|
||||
botAI->ChangeStrategy("+naxx", BOT_STATE_NON_COMBAT);
|
||||
botAI->ChangeStrategy("+naxx", BOT_STATE_COMBAT);
|
||||
botAI->TellMasterNoFacing("Add Naxx Strategies!");
|
||||
// bot->Say("Add Naxx Strategies!", LANG_UNIVERSAL);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BwlChatShortcutAction::Execute(Event event)
|
||||
{
|
||||
Player* master = GetMaster();
|
||||
|
||||
@@ -85,13 +85,6 @@ public:
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NaxxChatShortcutAction : public Action
|
||||
{
|
||||
public:
|
||||
NaxxChatShortcutAction(PlayerbotAI* ai) : Action(ai, "naxx chat shortcut") {}
|
||||
virtual bool Execute(Event event);
|
||||
};
|
||||
|
||||
class BwlChatShortcutAction : public Action
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -84,8 +84,6 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
||||
new TriggerNode("target", NextAction::array(0, new NextAction("tell target", relevance), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("ready", NextAction::array(0, new NextAction("ready check", relevance), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("naxx", NextAction::array(0, new NextAction("naxx chat shortcut", relevance), NULL)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("bwl", NextAction::array(0, new NextAction("bwl chat shortcut", relevance), NULL)));
|
||||
triggers.push_back(
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "RaidKarazhanStrategy.h"
|
||||
#include "RaidMagtheridonStrategy.h"
|
||||
#include "RaidGruulsLairStrategy.h"
|
||||
#include "RaidNaxxStrategy.h"
|
||||
#include "RaidOsStrategy.h"
|
||||
#include "RaidEoEStrategy.h"
|
||||
#include "RaidVoAStrategy.h"
|
||||
@@ -27,7 +26,6 @@ public:
|
||||
creators["karazhan"] = &RaidStrategyContext::karazhan;
|
||||
creators["magtheridon"] = &RaidStrategyContext::magtheridon;
|
||||
creators["gruulslair"] = &RaidStrategyContext::gruulslair;
|
||||
creators["naxx"] = &RaidStrategyContext::naxx;
|
||||
creators["wotlk-os"] = &RaidStrategyContext::wotlk_os;
|
||||
creators["wotlk-eoe"] = &RaidStrategyContext::wotlk_eoe;
|
||||
creators["voa"] = &RaidStrategyContext::voa;
|
||||
@@ -43,7 +41,6 @@ private:
|
||||
static Strategy* karazhan(PlayerbotAI* botAI) { return new RaidKarazhanStrategy(botAI); }
|
||||
static Strategy* magtheridon(PlayerbotAI* botAI) { return new RaidMagtheridonStrategy(botAI); }
|
||||
static Strategy* gruulslair(PlayerbotAI* botAI) { return new RaidGruulsLairStrategy(botAI); }
|
||||
static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); }
|
||||
static Strategy* wotlk_os(PlayerbotAI* botAI) { return new RaidOsStrategy(botAI); }
|
||||
static Strategy* wotlk_eoe(PlayerbotAI* botAI) { return new RaidEoEStrategy(botAI); }
|
||||
static Strategy* voa(PlayerbotAI* botAI) { return new RaidVoAStrategy(botAI); }
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
// /*
|
||||
// * Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||
// and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||
// */
|
||||
|
||||
#ifndef _PLAYERBOT_RAIDNAXXACTIONCONTEXT_H
|
||||
#define _PLAYERBOT_RAIDNAXXACTIONCONTEXT_H
|
||||
|
||||
#include "Action.h"
|
||||
#include "NamedObjectContext.h"
|
||||
#include "RaidNaxxActions.h"
|
||||
|
||||
class RaidNaxxActionContext : public NamedObjectContext<Action>
|
||||
{
|
||||
public:
|
||||
RaidNaxxActionContext()
|
||||
{
|
||||
creators["grobbulus go behind the boss"] = &RaidNaxxActionContext::go_behind_the_boss;
|
||||
creators["rotate grobbulus"] = &RaidNaxxActionContext::rotate_grobbulus;
|
||||
creators["grobbulus move center"] = &RaidNaxxActionContext::grobbulus_move_center;
|
||||
|
||||
creators["heigan dance melee"] = &RaidNaxxActionContext::heigan_dance_melee;
|
||||
creators["heigan dance ranged"] = &RaidNaxxActionContext::heigan_dance_ranged;
|
||||
creators["thaddius attack nearest pet"] = &RaidNaxxActionContext::thaddius_attack_nearest_pet;
|
||||
// creators["thaddius melee to place"] = &RaidNaxxActionContext::thaddius_tank_to_place;
|
||||
// creators["thaddius ranged to place"] = &RaidNaxxActionContext::thaddius_ranged_to_place;
|
||||
creators["thaddius move to platform"] = &RaidNaxxActionContext::thaddius_move_to_platform;
|
||||
creators["thaddius move polarity"] = &RaidNaxxActionContext::thaddius_move_polarity;
|
||||
|
||||
creators["razuvious use obedience crystal"] = &RaidNaxxActionContext::razuvious_use_obedience_crystal;
|
||||
creators["razuvious target"] = &RaidNaxxActionContext::razuvious_target;
|
||||
|
||||
creators["horseman attract alternatively"] = &RaidNaxxActionContext::horseman_attract_alternatively;
|
||||
creators["horseman attack in order"] = &RaidNaxxActionContext::horseman_attack_in_order;
|
||||
|
||||
creators["sapphiron ground position"] = &RaidNaxxActionContext::sapphiron_ground_position;
|
||||
creators["sapphiron flight position"] = &RaidNaxxActionContext::sapphiron_flight_position;
|
||||
|
||||
creators["kel'thuzad choose target"] = &RaidNaxxActionContext::kelthuzad_choose_target;
|
||||
creators["kel'thuzad position"] = &RaidNaxxActionContext::kelthuzad_position;
|
||||
|
||||
creators["anub'rekhan choose target"] = &RaidNaxxActionContext::anubrekhan_choose_target;
|
||||
creators["anub'rekhan position"] = &RaidNaxxActionContext::anubrekhan_position;
|
||||
|
||||
creators["gluth choose target"] = &RaidNaxxActionContext::gluth_choose_target;
|
||||
creators["gluth position"] = &RaidNaxxActionContext::gluth_position;
|
||||
creators["gluth slowdown"] = &RaidNaxxActionContext::gluth_slowdown;
|
||||
|
||||
creators["loatheb position"] = &RaidNaxxActionContext::loatheb_position;
|
||||
creators["loatheb choose target"] = &RaidNaxxActionContext::loatheb_choose_target;
|
||||
}
|
||||
|
||||
private:
|
||||
static Action* go_behind_the_boss(PlayerbotAI* ai) { return new GrobbulusGoBehindAction(ai); }
|
||||
static Action* rotate_grobbulus(PlayerbotAI* ai) { return new GrobbulusRotateAction(ai); }
|
||||
static Action* grobbulus_move_center(PlayerbotAI* ai) { return new GrobblulusMoveCenterAction(ai); }
|
||||
static Action* heigan_dance_melee(PlayerbotAI* ai) { return new HeiganDanceMeleeAction(ai); }
|
||||
static Action* heigan_dance_ranged(PlayerbotAI* ai) { return new HeiganDanceRangedAction(ai); }
|
||||
static Action* thaddius_attack_nearest_pet(PlayerbotAI* ai) { return new ThaddiusAttackNearestPetAction(ai); }
|
||||
// static Action* thaddius_tank_to_place(PlayerbotAI* ai) { return new ThaddiusMeleeToPlaceAction(ai); }
|
||||
// static Action* thaddius_ranged_to_place(PlayerbotAI* ai) { return new ThaddiusRangedToPlaceAction(ai); }
|
||||
static Action* thaddius_move_to_platform(PlayerbotAI* ai) { return new ThaddiusMoveToPlatformAction(ai); }
|
||||
static Action* thaddius_move_polarity(PlayerbotAI* ai) { return new ThaddiusMovePolarityAction(ai); }
|
||||
static Action* razuvious_target(PlayerbotAI* ai) { return new RazuviousTargetAction(ai); }
|
||||
static Action* razuvious_use_obedience_crystal(PlayerbotAI* ai)
|
||||
{
|
||||
return new RazuviousUseObedienceCrystalAction(ai);
|
||||
}
|
||||
static Action* horseman_attract_alternatively(PlayerbotAI* ai)
|
||||
{
|
||||
return new HorsemanAttractAlternativelyAction(ai);
|
||||
}
|
||||
static Action* horseman_attack_in_order(PlayerbotAI* ai) { return new HorsemanAttactInOrderAction(ai); }
|
||||
// static Action* sapphiron_ground_main_tank_position(PlayerbotAI* ai) { return new
|
||||
// SapphironGroundMainTankPositionAction(ai); }
|
||||
static Action* sapphiron_ground_position(PlayerbotAI* ai) { return new SapphironGroundPositionAction(ai); }
|
||||
static Action* sapphiron_flight_position(PlayerbotAI* ai) { return new SapphironFlightPositionAction(ai); }
|
||||
// static Action* sapphiron_avoid_chill(PlayerbotAI* ai) { return new SapphironAvoidChillAction(ai); }
|
||||
static Action* kelthuzad_choose_target(PlayerbotAI* ai) { return new KelthuzadChooseTargetAction(ai); }
|
||||
static Action* kelthuzad_position(PlayerbotAI* ai) { return new KelthuzadPositionAction(ai); }
|
||||
static Action* anubrekhan_choose_target(PlayerbotAI* ai) { return new AnubrekhanChooseTargetAction(ai); }
|
||||
static Action* anubrekhan_position(PlayerbotAI* ai) { return new AnubrekhanPositionAction(ai); }
|
||||
static Action* gluth_choose_target(PlayerbotAI* ai) { return new GluthChooseTargetAction(ai); }
|
||||
static Action* gluth_position(PlayerbotAI* ai) { return new GluthPositionAction(ai); }
|
||||
static Action* gluth_slowdown(PlayerbotAI* ai) { return new GluthSlowdownAction(ai); }
|
||||
static Action* loatheb_position(PlayerbotAI* ai) { return new LoathebPositionAction(ai); }
|
||||
static Action* loatheb_choose_target(PlayerbotAI* ai) { return new LoathebChooseTargetAction(ai); }
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,324 +0,0 @@
|
||||
#ifndef _PLAYERBOT_RAIDNAXXACTIONS_H
|
||||
#define _PLAYERBOT_RAIDNAXXACTIONS_H
|
||||
|
||||
#include "Action.h"
|
||||
#include "AttackAction.h"
|
||||
#include "GenericActions.h"
|
||||
#include "MovementActions.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Playerbots.h"
|
||||
#include "RaidNaxxBossHelper.h"
|
||||
#include "RaidNaxxScripts.h"
|
||||
|
||||
// just for test
|
||||
// class TryToGetBossAIAction : public Action
|
||||
// {
|
||||
// public:
|
||||
// TryToGetBossAIAction(PlayerbotAI* ai) : Action(ai, "try to get boss ai") {}
|
||||
|
||||
// public:
|
||||
// virtual bool Execute(Event event);
|
||||
// };
|
||||
|
||||
class GrobbulusGoBehindAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
GrobbulusGoBehindAction(PlayerbotAI* ai, float distance = 24.0f, float delta_angle = M_PI / 8)
|
||||
: MovementAction(ai, "grobbulus go behind")
|
||||
{
|
||||
this->distance = distance;
|
||||
this->delta_angle = delta_angle;
|
||||
}
|
||||
virtual bool Execute(Event event);
|
||||
|
||||
protected:
|
||||
float distance, delta_angle;
|
||||
};
|
||||
|
||||
class GrobbulusRotateAction : public RotateAroundTheCenterPointAction
|
||||
{
|
||||
public:
|
||||
GrobbulusRotateAction(PlayerbotAI* botAI)
|
||||
: RotateAroundTheCenterPointAction(botAI, "rotate grobbulus", 3281.23f, -3310.38f, 35.0f, 8, true, M_PI)
|
||||
{
|
||||
}
|
||||
virtual bool isUseful() override
|
||||
{
|
||||
return RotateAroundTheCenterPointAction::isUseful() && botAI->IsMainTank(bot) &&
|
||||
AI_VALUE2(bool, "has aggro", "boss target");
|
||||
}
|
||||
uint32 GetCurrWaypoint() override;
|
||||
};
|
||||
|
||||
class GrobblulusMoveCenterAction : public MoveInsideAction
|
||||
{
|
||||
public:
|
||||
GrobblulusMoveCenterAction(PlayerbotAI* ai) : MoveInsideAction(ai, 3281.23f, -3310.38f, 5.0f) {}
|
||||
};
|
||||
|
||||
class HeiganDanceAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
HeiganDanceAction(PlayerbotAI* ai) : MovementAction(ai, "heigan dance")
|
||||
{
|
||||
this->prev_phase = 0;
|
||||
this->prev_erupt = 0;
|
||||
this->prev_timer = 0;
|
||||
ResetSafe();
|
||||
waypoints.push_back(std::make_pair(2794.88f, -3668.12f));
|
||||
waypoints.push_back(std::make_pair(2775.49f, -3674.43f));
|
||||
waypoints.push_back(std::make_pair(2762.30f, -3684.59f));
|
||||
waypoints.push_back(std::make_pair(2755.99f, -3703.96f));
|
||||
}
|
||||
|
||||
protected:
|
||||
bool CalculateSafe();
|
||||
void ResetSafe()
|
||||
{
|
||||
curr_safe = 0;
|
||||
curr_dir = 1;
|
||||
}
|
||||
void NextSafe()
|
||||
{
|
||||
curr_safe += curr_dir;
|
||||
if (curr_safe == 3 || curr_safe == 0)
|
||||
{
|
||||
curr_dir = -curr_dir;
|
||||
}
|
||||
}
|
||||
uint32 prev_phase, prev_erupt, prev_timer;
|
||||
uint32 curr_safe, curr_dir;
|
||||
std::vector<std::pair<float, float>> waypoints;
|
||||
};
|
||||
|
||||
class HeiganDanceMeleeAction : public HeiganDanceAction
|
||||
{
|
||||
public:
|
||||
HeiganDanceMeleeAction(PlayerbotAI* ai) : HeiganDanceAction(ai) {}
|
||||
virtual bool Execute(Event event);
|
||||
};
|
||||
|
||||
class HeiganDanceRangedAction : public HeiganDanceAction
|
||||
{
|
||||
public:
|
||||
HeiganDanceRangedAction(PlayerbotAI* ai) : HeiganDanceAction(ai) { platform = std::make_pair(2794.26f, -3706.67f); }
|
||||
virtual bool Execute(Event event);
|
||||
|
||||
protected:
|
||||
std::pair<float, float> platform;
|
||||
};
|
||||
|
||||
class ThaddiusAttackNearestPetAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
ThaddiusAttackNearestPetAction(PlayerbotAI* ai) : AttackAction(ai, "thaddius attack nearest pet"), helper(ai) {}
|
||||
virtual bool Execute(Event event);
|
||||
virtual bool isUseful();
|
||||
|
||||
private:
|
||||
ThaddiusBossHelper helper;
|
||||
};
|
||||
|
||||
// class ThaddiusMeleeToPlaceAction : public MovementAction
|
||||
// {
|
||||
// public:
|
||||
// ThaddiusMeleeToPlaceAction(PlayerbotAI* ai) : MovementAction(ai, "thaddius melee to place") {}
|
||||
// virtual bool Execute(Event event);
|
||||
// virtual bool isUseful();
|
||||
// };
|
||||
|
||||
// class ThaddiusRangedToPlaceAction : public MovementAction
|
||||
// {
|
||||
// public:
|
||||
// ThaddiusRangedToPlaceAction(PlayerbotAI* ai) : MovementAction(ai, "thaddius ranged to place") {}
|
||||
// virtual bool Execute(Event event);
|
||||
// virtual bool isUseful();
|
||||
// };
|
||||
|
||||
class ThaddiusMoveToPlatformAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
ThaddiusMoveToPlatformAction(PlayerbotAI* ai) : MovementAction(ai, "thaddius move to platform") {}
|
||||
virtual bool Execute(Event event);
|
||||
virtual bool isUseful();
|
||||
};
|
||||
|
||||
class ThaddiusMovePolarityAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
ThaddiusMovePolarityAction(PlayerbotAI* ai) : MovementAction(ai, "thaddius move polarity") {}
|
||||
virtual bool Execute(Event event);
|
||||
virtual bool isUseful();
|
||||
};
|
||||
|
||||
class RazuviousUseObedienceCrystalAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
RazuviousUseObedienceCrystalAction(PlayerbotAI* ai)
|
||||
: MovementAction(ai, "razuvious use obedience crystal"), helper(ai)
|
||||
{
|
||||
}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
private:
|
||||
RazuviousBossHelper helper;
|
||||
};
|
||||
|
||||
class RazuviousTargetAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
RazuviousTargetAction(PlayerbotAI* ai) : AttackAction(ai, "razuvious target"), helper(ai) {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
private:
|
||||
RazuviousBossHelper helper;
|
||||
};
|
||||
|
||||
class HorsemanAttractAlternativelyAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
HorsemanAttractAlternativelyAction(PlayerbotAI* ai) : AttackAction(ai, "horseman attract alternatively"), helper(ai)
|
||||
{
|
||||
}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
protected:
|
||||
FourhorsemanBossHelper helper;
|
||||
};
|
||||
|
||||
class HorsemanAttactInOrderAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
HorsemanAttactInOrderAction(PlayerbotAI* ai) : AttackAction(ai, "horseman attact in order"), helper(ai) {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
protected:
|
||||
FourhorsemanBossHelper helper;
|
||||
};
|
||||
|
||||
// class SapphironGroundMainTankPositionAction : public MovementAction
|
||||
// {
|
||||
// public:
|
||||
// SapphironGroundMainTankPositionAction(PlayerbotAI* ai) : MovementAction(ai, "sapphiron ground main tank
|
||||
// position") {} virtual bool Execute(Event event);
|
||||
// };
|
||||
|
||||
class SapphironGroundPositionAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
SapphironGroundPositionAction(PlayerbotAI* ai) : MovementAction(ai, "sapphiron ground position"), helper(ai) {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
protected:
|
||||
SapphironBossHelper helper;
|
||||
};
|
||||
|
||||
class SapphironFlightPositionAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
SapphironFlightPositionAction(PlayerbotAI* ai) : MovementAction(ai, "sapphiron flight position"), helper(ai) {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
protected:
|
||||
SapphironBossHelper helper;
|
||||
bool MoveToNearestIcebolt();
|
||||
};
|
||||
|
||||
// class SapphironAvoidChillAction : public MovementAction
|
||||
// {
|
||||
// public:
|
||||
// SapphironAvoidChillAction(PlayerbotAI* ai) : MovementAction(ai, "sapphiron avoid chill") {}
|
||||
// virtual bool Execute(Event event);
|
||||
// };
|
||||
|
||||
class KelthuzadChooseTargetAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
KelthuzadChooseTargetAction(PlayerbotAI* ai) : AttackAction(ai, "kel'thuzad choose target"), helper(ai) {}
|
||||
virtual bool Execute(Event event);
|
||||
|
||||
private:
|
||||
KelthuzadBossHelper helper;
|
||||
};
|
||||
|
||||
class KelthuzadPositionAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KelthuzadPositionAction(PlayerbotAI* ai) : MovementAction(ai, "kel'thuzad position"), helper(ai) {}
|
||||
virtual bool Execute(Event event);
|
||||
|
||||
private:
|
||||
KelthuzadBossHelper helper;
|
||||
};
|
||||
|
||||
class AnubrekhanChooseTargetAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
AnubrekhanChooseTargetAction(PlayerbotAI* ai) : AttackAction(ai, "anub'rekhan choose target") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class AnubrekhanPositionAction : public RotateAroundTheCenterPointAction
|
||||
{
|
||||
public:
|
||||
AnubrekhanPositionAction(PlayerbotAI* ai)
|
||||
: RotateAroundTheCenterPointAction(ai, "anub'rekhan position", 3272.49f, -3476.27f, 45.0f, 16)
|
||||
{
|
||||
}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class GluthChooseTargetAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
GluthChooseTargetAction(PlayerbotAI* ai) : AttackAction(ai, "gluth choose target"), helper(ai) {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
private:
|
||||
GluthBossHelper helper;
|
||||
};
|
||||
|
||||
class GluthPositionAction : public RotateAroundTheCenterPointAction
|
||||
{
|
||||
public:
|
||||
GluthPositionAction(PlayerbotAI* ai)
|
||||
: RotateAroundTheCenterPointAction(ai, "gluth position", 3293.61f, -3149.01f, 12.0f, 12), helper(ai)
|
||||
{
|
||||
}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
private:
|
||||
GluthBossHelper helper;
|
||||
};
|
||||
|
||||
class GluthSlowdownAction : public Action
|
||||
{
|
||||
public:
|
||||
GluthSlowdownAction(PlayerbotAI* ai) : Action(ai, "gluth slowdown"), helper(ai) {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
private:
|
||||
GluthBossHelper helper;
|
||||
};
|
||||
|
||||
class LoathebPositionAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
LoathebPositionAction(PlayerbotAI* ai) : MovementAction(ai, "loatheb position"), helper(ai) {}
|
||||
virtual bool Execute(Event event);
|
||||
|
||||
private:
|
||||
LoathebBossHelper helper;
|
||||
};
|
||||
|
||||
class LoathebChooseTargetAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
LoathebChooseTargetAction(PlayerbotAI* ai) : AttackAction(ai, "loatheb choose target"), helper(ai) {}
|
||||
virtual bool Execute(Event event);
|
||||
|
||||
private:
|
||||
LoathebBossHelper helper;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,419 +0,0 @@
|
||||
#ifndef _PLAYERBOT_RAIDNAXXBOSSHELPER_H
|
||||
#define _PLAYERBOT_RAIDNAXXBOSSHELPER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "AiObject.h"
|
||||
#include "AiObjectContext.h"
|
||||
#include "EventMap.h"
|
||||
#include "Log.h"
|
||||
#include "NamedObjectContext.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Playerbots.h"
|
||||
#include "RaidNaxxScripts.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SharedDefines.h"
|
||||
|
||||
const uint32 NAXX_MAP_ID = 533;
|
||||
|
||||
template <class BossAiType>
|
||||
class GenericBossHelper : public AiObject
|
||||
{
|
||||
public:
|
||||
GenericBossHelper(PlayerbotAI* botAI, std::string name) : AiObject(botAI), _name(name) {}
|
||||
virtual bool UpdateBossAI()
|
||||
{
|
||||
if (!bot->IsInCombat())
|
||||
{
|
||||
_unit = nullptr;
|
||||
}
|
||||
if (_unit && (!_unit->IsInWorld() || !_unit->IsAlive()))
|
||||
{
|
||||
_unit = nullptr;
|
||||
}
|
||||
if (!_unit)
|
||||
{
|
||||
_unit = AI_VALUE2(Unit*, "find target", _name);
|
||||
if (!_unit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_target = _unit->ToCreature();
|
||||
if (!_target)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_ai = dynamic_cast<BossAiType*>(_target->GetAI());
|
||||
if (!_ai)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_event_map = &_ai->events;
|
||||
if (!_event_map)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!_event_map)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_timer = _event_map->GetTimer();
|
||||
return true;
|
||||
}
|
||||
virtual void Reset()
|
||||
{
|
||||
_unit = nullptr;
|
||||
_target = nullptr;
|
||||
_ai = nullptr;
|
||||
_event_map = nullptr;
|
||||
_timer = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
Unit* _unit = nullptr;
|
||||
Creature* _target = nullptr;
|
||||
BossAiType* _ai = nullptr;
|
||||
EventMap* _event_map = nullptr;
|
||||
uint32 _timer = 0;
|
||||
};
|
||||
|
||||
class KelthuzadBossHelper : public GenericBossHelper<Kelthuzad::boss_kelthuzad::boss_kelthuzadAI>
|
||||
{
|
||||
public:
|
||||
KelthuzadBossHelper(PlayerbotAI* botAI) : GenericBossHelper(botAI, "kel'thuzad") {}
|
||||
const std::pair<float, float> center = {3716.19f, -5106.58f};
|
||||
const std::pair<float, float> tank_pos = {3709.19f, -5104.86f};
|
||||
const std::pair<float, float> assist_tank_pos = {3746.05f, -5112.74f};
|
||||
bool IsPhaseOne() { return _event_map->GetNextEventTime(Kelthuzad::EVENT_PHASE_2) != 0; }
|
||||
bool IsPhaseTwo() { return !IsPhaseOne(); }
|
||||
Unit* GetAnyShadowFissure()
|
||||
{
|
||||
Unit* shadow_fissure = nullptr;
|
||||
GuidVector units = *context->GetValue<GuidVector>("nearest triggers");
|
||||
for (auto i = units.begin(); i != units.end(); i++)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(*i);
|
||||
if (!unit)
|
||||
continue;
|
||||
if (botAI->EqualLowercaseName(unit->GetName(), "shadow fissure"))
|
||||
{
|
||||
shadow_fissure = unit;
|
||||
}
|
||||
}
|
||||
return shadow_fissure;
|
||||
}
|
||||
};
|
||||
|
||||
class RazuviousBossHelper : public GenericBossHelper<Razuvious::boss_razuvious::boss_razuviousAI>
|
||||
{
|
||||
public:
|
||||
RazuviousBossHelper(PlayerbotAI* botAI) : GenericBossHelper(botAI, "instructor razuvious") {}
|
||||
};
|
||||
|
||||
class SapphironBossHelper : public GenericBossHelper<Sapphiron::boss_sapphiron::boss_sapphironAI>
|
||||
{
|
||||
public:
|
||||
const std::pair<float, float> mainTankPos = {3512.07f, -5274.06f};
|
||||
const std::pair<float, float> center = {3517.31f, -5253.74f};
|
||||
const float GENERIC_HEIGHT = 137.29f;
|
||||
SapphironBossHelper(PlayerbotAI* botAI) : GenericBossHelper(botAI, "sapphiron") {}
|
||||
bool UpdateBossAI() override
|
||||
{
|
||||
if (!GenericBossHelper::UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint32 nextEventGround = _event_map->GetNextEventTime(Sapphiron::EVENT_GROUND);
|
||||
if (nextEventGround && nextEventGround != lastEventGround)
|
||||
lastEventGround = nextEventGround;
|
||||
return true;
|
||||
}
|
||||
bool IsPhaseGround() { return _target->GetReactState() == REACT_AGGRESSIVE; }
|
||||
bool IsPhaseFlight() { return !IsPhaseGround(); }
|
||||
bool JustLanded()
|
||||
{
|
||||
return (_event_map->GetNextEventTime(Sapphiron::EVENT_FLIGHT_START) - _timer) >=
|
||||
EVENT_FLIGHT_INTERVAL - POSITION_TIME_AFTER_LANDED;
|
||||
}
|
||||
bool WaitForExplosion() { return _event_map->GetNextEventTime(Sapphiron::EVENT_FLIGHT_SPELL_EXPLOSION); }
|
||||
bool FindPosToAvoidChill(std::vector<float>& dest)
|
||||
{
|
||||
Aura* aura = botAI->GetAura("chill", bot);
|
||||
if (!aura)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DynamicObject* dyn_obj = aura->GetDynobjOwner();
|
||||
if (!dyn_obj)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Unit* currentTarget = AI_VALUE(Unit*, "current target");
|
||||
float angle = 0;
|
||||
uint32 index = botAI->GetGroupSlotIndex(bot);
|
||||
if (currentTarget)
|
||||
{
|
||||
if (botAI->IsRanged(bot))
|
||||
{
|
||||
if (bot->GetExactDist2d(currentTarget) <= 45.0f)
|
||||
{
|
||||
angle = bot->GetAngle(dyn_obj) - M_PI + (rand_norm() - 0.5) * M_PI / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index % 2 == 0)
|
||||
{
|
||||
angle = bot->GetAngle(currentTarget) + M_PI / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = bot->GetAngle(currentTarget) - M_PI / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index % 3 == 0)
|
||||
{
|
||||
angle = bot->GetAngle(currentTarget);
|
||||
}
|
||||
else if (index % 3 == 1)
|
||||
{
|
||||
angle = bot->GetAngle(currentTarget) + M_PI / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = bot->GetAngle(currentTarget) - M_PI / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = bot->GetAngle(dyn_obj) - M_PI + (rand_norm() - 0.5) * M_PI / 2;
|
||||
}
|
||||
dest = {bot->GetPositionX() + cos(angle) * 5.0f, bot->GetPositionY() + sin(angle) * 5.0f, bot->GetPositionZ()};
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint32 POSITION_TIME_AFTER_LANDED = 5000;
|
||||
const uint32 EVENT_FLIGHT_INTERVAL = 45000;
|
||||
uint32 lastEventGround = 0;
|
||||
};
|
||||
|
||||
class GluthBossHelper : public GenericBossHelper<Gluth::boss_gluth::boss_gluthAI>
|
||||
{
|
||||
public:
|
||||
const std::pair<float, float> mainTankPos25 = {3331.48f, -3109.06f};
|
||||
const std::pair<float, float> mainTankPos10 = {3278.29f, -3162.06f};
|
||||
const std::pair<float, float> beforeDecimatePos = {3267.34f, -3175.68f};
|
||||
const std::pair<float, float> leftSlowDownPos = {3290.68f, -3141.65f};
|
||||
const std::pair<float, float> rightSlowDownPos = {3300.78f, -3151.98f};
|
||||
const std::pair<float, float> rangedPos = {3301.45f, -3139.29f};
|
||||
const std::pair<float, float> healPos = {3303.09f, -3135.24f};
|
||||
|
||||
const float decimatedZombiePct = 10.0f;
|
||||
GluthBossHelper(PlayerbotAI* botAI) : GenericBossHelper(botAI, "gluth") {}
|
||||
bool BeforeDecimate()
|
||||
{
|
||||
uint32 decimate = _event_map->GetNextEventTime(Gluth::EVENT_DECIMATE);
|
||||
return decimate && decimate - _timer <= 3000;
|
||||
}
|
||||
bool JustStartCombat() { return _timer < 10000; }
|
||||
};
|
||||
|
||||
class LoathebBossHelper : public GenericBossHelper<Loatheb::boss_loatheb::boss_loathebAI>
|
||||
{
|
||||
public:
|
||||
const std::pair<float, float> mainTankPos = {2877.57f, -3967.00f};
|
||||
const std::pair<float, float> rangePos = {2896.96f, -3980.61f};
|
||||
LoathebBossHelper(PlayerbotAI* botAI) : GenericBossHelper(botAI, "loatheb") {}
|
||||
};
|
||||
|
||||
class FourhorsemanBossHelper : public GenericBossHelper<FourHorsemen::boss_four_horsemen::boss_four_horsemenAI>
|
||||
{
|
||||
public:
|
||||
const float posZ = 241.27f;
|
||||
const std::pair<float, float> attractPos[2] = {{2502.03f, -2910.90f},
|
||||
{2484.61f, -2947.07f}}; // left (sir zeliek), right (lady blaumeux)
|
||||
FourhorsemanBossHelper(PlayerbotAI* botAI) : GenericBossHelper(botAI, "sir zeliek") {}
|
||||
bool UpdateBossAI() override
|
||||
{
|
||||
if (!GenericBossHelper::UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!bot->IsInCombat())
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
sir = _unit;
|
||||
lady = AI_VALUE2(Unit*, "find target", "lady blaumeux");
|
||||
if (!lady)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
ladyAI = dynamic_cast<FourHorsemen::boss_four_horsemen::boss_four_horsemenAI*>(lady->GetAI());
|
||||
if (!ladyAI)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
ladyEvent = &ladyAI->events;
|
||||
const uint32 voidZone = ladyEvent->GetNextEventTime(FourHorsemen::EVENT_SECONDARY_SPELL);
|
||||
if (voidZone && lastEventVoidZone != voidZone)
|
||||
{
|
||||
voidZoneCounter++;
|
||||
voidZoneCounter %= 8;
|
||||
lastEventVoidZone = voidZone;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void Reset() override
|
||||
{
|
||||
GenericBossHelper::Reset();
|
||||
sir = nullptr;
|
||||
lady = nullptr;
|
||||
ladyAI = nullptr;
|
||||
ladyEvent = nullptr;
|
||||
lastEventVoidZone = 0;
|
||||
voidZoneCounter = 0;
|
||||
posToGo = 0;
|
||||
}
|
||||
bool IsAttracter(Player* bot)
|
||||
{
|
||||
Difficulty diff = bot->GetRaidDifficulty();
|
||||
if (diff == RAID_DIFFICULTY_25MAN_NORMAL)
|
||||
{
|
||||
return botAI->IsRangedDpsAssistantOfIndex(bot, 0) || botAI->IsHealAssistantOfIndex(bot, 0) ||
|
||||
botAI->IsHealAssistantOfIndex(bot, 1) || botAI->IsHealAssistantOfIndex(bot, 2);
|
||||
}
|
||||
return botAI->IsRangedDpsAssistantOfIndex(bot, 0) || botAI->IsHealAssistantOfIndex(bot, 0);
|
||||
}
|
||||
void CalculatePosToGo(Player* bot)
|
||||
{
|
||||
bool raid25 = bot->GetRaidDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL;
|
||||
if (!lady)
|
||||
{
|
||||
posToGo = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Interval: 24s - 15s - 15s - ...
|
||||
posToGo = !(_timer <= 9000 || ((_timer - 9000) / 67500) % 2 == 0);
|
||||
if (botAI->IsRangedDpsAssistantOfIndex(bot, 0) || (raid25 && botAI->IsHealAssistantOfIndex(bot, 1)))
|
||||
{
|
||||
posToGo = 1 - posToGo;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::pair<float, float> CurrentAttractPos()
|
||||
{
|
||||
float posX = attractPos[posToGo].first, posY = attractPos[posToGo].second;
|
||||
if (posToGo == 1)
|
||||
{
|
||||
float offset_x;
|
||||
float offset_y;
|
||||
if (voidZoneCounter < 4)
|
||||
{
|
||||
offset_x = voidZoneCounter * (-4.5f);
|
||||
offset_y = voidZoneCounter * (4.5f);
|
||||
}
|
||||
if (voidZoneCounter >= 4)
|
||||
{
|
||||
offset_x = (7 - voidZoneCounter) * (-4.5f);
|
||||
offset_y = (7 - voidZoneCounter) * (4.5f);
|
||||
offset_x += 4.5f;
|
||||
offset_y += 4.5f;
|
||||
}
|
||||
posX += offset_x;
|
||||
posY += offset_y;
|
||||
}
|
||||
return {posX, posY};
|
||||
}
|
||||
Unit* CurrentAttackTarget()
|
||||
{
|
||||
if (posToGo == 0)
|
||||
{
|
||||
return sir;
|
||||
}
|
||||
return lady;
|
||||
}
|
||||
|
||||
protected:
|
||||
Unit* sir = nullptr;
|
||||
Unit* lady = nullptr;
|
||||
FourHorsemen::boss_four_horsemen::boss_four_horsemenAI* ladyAI = nullptr;
|
||||
EventMap* ladyEvent = nullptr;
|
||||
uint32 lastEventVoidZone = 0;
|
||||
uint32 voidZoneCounter = 0;
|
||||
int posToGo = 0;
|
||||
};
|
||||
class ThaddiusBossHelper : public GenericBossHelper<Thaddius::boss_thaddius::boss_thaddiusAI>
|
||||
{
|
||||
public:
|
||||
const std::pair<float, float> tankPosFeugen = {3522.94f, -3002.60f};
|
||||
const std::pair<float, float> tankPosStalagg = {3436.14f, -2919.98f};
|
||||
const std::pair<float, float> rangedPosFeugen = {3500.45f, -2997.92f};
|
||||
const std::pair<float, float> rangedPosStalagg = {3441.01f, -2942.04f};
|
||||
const float tankPosZ = 312.61f;
|
||||
ThaddiusBossHelper(PlayerbotAI* botAI) : GenericBossHelper(botAI, "thaddius") {}
|
||||
bool UpdateBossAI() override
|
||||
{
|
||||
if (!GenericBossHelper::UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
feugen = AI_VALUE2(Unit*, "find target", "feugen");
|
||||
stalagg = AI_VALUE2(Unit*, "find target", "stalagg");
|
||||
return true;
|
||||
}
|
||||
bool IsPhasePet() { return (feugen && feugen->IsAlive()) || (stalagg && stalagg->IsAlive()); }
|
||||
bool IsPhaseTransition()
|
||||
{
|
||||
if (IsPhasePet())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _unit->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
bool IsPhaseThaddius() { return !IsPhasePet() && !IsPhaseTransition(); }
|
||||
Unit* GetNearestPet()
|
||||
{
|
||||
Unit* unit = nullptr;
|
||||
if (feugen && feugen->IsAlive())
|
||||
{
|
||||
unit = feugen;
|
||||
}
|
||||
if (stalagg && stalagg->IsAlive() && (!feugen || bot->GetDistance(stalagg) < bot->GetDistance(feugen)))
|
||||
{
|
||||
unit = stalagg;
|
||||
}
|
||||
return unit;
|
||||
}
|
||||
std::pair<float, float> PetPhaseGetPosForTank()
|
||||
{
|
||||
if (GetNearestPet() == feugen)
|
||||
{
|
||||
return tankPosFeugen;
|
||||
}
|
||||
return tankPosStalagg;
|
||||
}
|
||||
std::pair<float, float> PetPhaseGetPosForRanged()
|
||||
{
|
||||
if (GetNearestPet() == feugen)
|
||||
{
|
||||
return rangedPosFeugen;
|
||||
}
|
||||
return rangedPosStalagg;
|
||||
}
|
||||
|
||||
protected:
|
||||
Unit* feugen = nullptr;
|
||||
Unit* stalagg = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,325 +0,0 @@
|
||||
#include "RaidNaxxMultipliers.h"
|
||||
|
||||
#include "ChooseTargetActions.h"
|
||||
#include "DKActions.h"
|
||||
#include "DruidActions.h"
|
||||
#include "DruidBearActions.h"
|
||||
#include "FollowActions.h"
|
||||
#include "GenericActions.h"
|
||||
#include "GenericSpellActions.h"
|
||||
#include "HunterActions.h"
|
||||
#include "MageActions.h"
|
||||
#include "MovementActions.h"
|
||||
#include "PaladinActions.h"
|
||||
#include "PriestActions.h"
|
||||
#include "RaidNaxxActions.h"
|
||||
#include "ReachTargetActions.h"
|
||||
#include "RogueActions.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ShamanActions.h"
|
||||
#include "UseMeetingStoneAction.h"
|
||||
#include "WarriorActions.h"
|
||||
|
||||
float GrobbulusMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "grobbulus");
|
||||
if (!boss)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
if (dynamic_cast<AvoidAoeAction*>(action) || dynamic_cast<CombatFormationMoveAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float HeiganDanceMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "heigan the unclean");
|
||||
if (!boss)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
auto* boss_ai = dynamic_cast<Heigan::boss_heigan::boss_heiganAI*>(boss->GetAI());
|
||||
if (!boss_ai || boss_ai->events.Empty())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
EventMap* eventMap = &boss_ai->events;
|
||||
uint32 curr_phase = boss_ai->currentPhase;
|
||||
uint32 curr_dance = eventMap->GetNextEventTime(4);
|
||||
uint32 curr_timer = eventMap->GetTimer();
|
||||
uint32 curr_erupt = eventMap->GetNextEventTime(3);
|
||||
if (dynamic_cast<CombatFormationMoveAction*>(action) ||
|
||||
dynamic_cast<CastDisengageAction*>(action) ||
|
||||
dynamic_cast<CastBlinkBackAction*>(action) )
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
if (curr_phase != 1 && (int32)curr_dance - curr_timer >= 3000)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
if (dynamic_cast<HeiganDanceAction*>(action) || dynamic_cast<CurePartyMemberAction*>(action))
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
if (dynamic_cast<CastSpellAction*>(action) && !dynamic_cast<CastMeleeSpellAction*>(action))
|
||||
{
|
||||
CastSpellAction* spellAction = dynamic_cast<CastSpellAction*>(action);
|
||||
uint32 spellId = AI_VALUE2(uint32, "spell id", spellAction->getSpell());
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
|
||||
if (!spellInfo)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
uint32 castTime = spellInfo->CalcCastTime();
|
||||
if (castTime == 0 && !spellInfo->IsChanneled())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float LoathebGenericMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "loatheb");
|
||||
if (!boss)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
context->GetValue<bool>("neglect threat")->Set(true);
|
||||
if (botAI->GetState() == BOT_STATE_COMBAT &&
|
||||
(dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action) ||
|
||||
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) || dynamic_cast<FleeAction*>(action) ||
|
||||
dynamic_cast<CombatFormationMoveAction*>(action)))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
if (!dynamic_cast<CastHealingSpellAction*>(action))
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
Aura* aura = botAI->GetAura("necrotic aura", bot);
|
||||
if (!aura || aura->GetDuration() <= 1500)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float ThaddiusGenericMultiplier::GetValue(Action* action)
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
if (dynamic_cast<CombatFormationMoveAction*>(action))
|
||||
return 0.0f;
|
||||
// pet phase
|
||||
if (helper.IsPhasePet() &&
|
||||
(dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action) ||
|
||||
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
|
||||
dynamic_cast<ReachPartyMemberToHealAction*>(action) || dynamic_cast<BuffOnMainTankAction*>(action)))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
// die at the same time
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
Unit* feugen = AI_VALUE2(Unit*, "find target", "feugen");
|
||||
Unit* stalagg = AI_VALUE2(Unit*, "find target", "stalagg");
|
||||
if (helper.IsPhasePet() && target && feugen && stalagg && target->GetHealthPct() <= 40 &&
|
||||
(feugen->GetHealthPct() >= target->GetHealthPct() + 3 || stalagg->GetHealthPct() >= target->GetHealthPct() + 3))
|
||||
{
|
||||
if (dynamic_cast<CastSpellAction*>(action) && !dynamic_cast<CastHealingSpellAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
// magnetic pull
|
||||
// uint32 curr_timer = eventMap->GetTimer();
|
||||
// // if (curr_phase == 2 && bot->GetPositionZ() > 312.5f && dynamic_cast<MovementAction*>(action))
|
||||
// {
|
||||
// if (curr_phase == 2 && (curr_timer % 20000 >= 18000 || curr_timer % 20000 <= 2000) &&
|
||||
// dynamic_cast<MovementAction*>(action))
|
||||
// {
|
||||
// // MotionMaster *mm = bot->GetMotionMaster();
|
||||
// // mm->Clear();
|
||||
// return 0.0f;
|
||||
// }
|
||||
// thaddius phase
|
||||
// if (curr_phase == 8 && dynamic_cast<FleeAction*>(action))
|
||||
// {
|
||||
// return 0.0f;
|
||||
// }
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float SapphironGenericMultiplier::GetValue(Action* action)
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
if (dynamic_cast<FollowAction*>(action) || dynamic_cast<CastDeathGripAction*>(action) ||
|
||||
dynamic_cast<CombatFormationMoveAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float InstructorRazuviousGenericMultiplier::GetValue(Action* action)
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
context->GetValue<bool>("neglect threat")->Set(true);
|
||||
if (botAI->GetState() == BOT_STATE_COMBAT &&
|
||||
(dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action) ||
|
||||
dynamic_cast<CastTauntAction*>(action) || dynamic_cast<CastDarkCommandAction*>(action) ||
|
||||
dynamic_cast<CastHandOfReckoningAction*>(action) || dynamic_cast<CastGrowlAction*>(action)))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float KelthuzadGenericMultiplier::GetValue(Action* action)
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
if ((dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action) ||
|
||||
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) || dynamic_cast<FollowAction*>(action) ||
|
||||
dynamic_cast<FleeAction*>(action)))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
if (helper.IsPhaseOne())
|
||||
{
|
||||
if (dynamic_cast<CastTotemAction*>(action) || dynamic_cast<CastShadowfiendAction*>(action) ||
|
||||
dynamic_cast<CastRaiseDeadAction*>(action) || dynamic_cast<CastFeignDeathAction*>(action) ||
|
||||
dynamic_cast<CastInvisibilityAction*>(action) || dynamic_cast<CastVanishAction*>(action) ||
|
||||
dynamic_cast<PetAttackAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
if (helper.IsPhaseTwo())
|
||||
{
|
||||
if (dynamic_cast<CastBlizzardAction*>(action) || dynamic_cast<CastFrostNovaAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float AnubrekhanGenericMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "anub'rekhan");
|
||||
if (!boss)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
if (
|
||||
// (dynamic_cast<DpsAssistAction*>(action) ||
|
||||
// dynamic_cast<DpsAssistAction*>(action) ||
|
||||
// dynamic_cast<TankAssistAction*>(action) ||
|
||||
dynamic_cast<FollowAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
// BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI());
|
||||
// EventMap* eventMap = boss_ai->GetEvents();
|
||||
// uint32 curr_phase = eventMap->GetPhaseMask();
|
||||
if (botAI->HasAura("locust swarm", boss))
|
||||
{
|
||||
if (dynamic_cast<FleeAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float FourhorsemanGenericMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "sir zeliek");
|
||||
if (!boss)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
context->GetValue<bool>("neglect threat")->Set(true);
|
||||
if ((dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action)))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// float GothikGenericMultiplier::GetValue(Action* action)
|
||||
// {
|
||||
// Unit* boss = AI_VALUE2(Unit*, "find target", "gothik the harvester");
|
||||
// if (!boss)
|
||||
// {
|
||||
// return 1.0f;
|
||||
// }
|
||||
// BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI());
|
||||
// EventMap* eventMap = boss_botAI->GetEvents();
|
||||
// uint32 curr_phase = eventMap->GetPhaseMask();
|
||||
// if (curr_phase == 1 && (dynamic_cast<FollowAction*>(action)))
|
||||
// {
|
||||
// return 0.0f;
|
||||
// }
|
||||
// if (curr_phase == 1 && (dynamic_cast<AttackAction*>(action)))
|
||||
// {
|
||||
// Unit* target = action->GetTarget();
|
||||
// if (target == boss)
|
||||
// {
|
||||
// return 0.0f;
|
||||
// }
|
||||
// }
|
||||
// return 1.0f;
|
||||
// }
|
||||
|
||||
float GluthGenericMultiplier::GetValue(Action* action)
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
if ((dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action) ||
|
||||
dynamic_cast<FleeAction*>(action) || dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
|
||||
dynamic_cast<CastStarfallAction*>(action)))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (botAI->IsMainTank(bot))
|
||||
{
|
||||
Aura* aura = botAI->GetAura("mortal wound", bot, false, true);
|
||||
if (aura && aura->GetStackAmount() >= 5)
|
||||
{
|
||||
if (dynamic_cast<CastTauntAction*>(action) || dynamic_cast<CastDarkCommandAction*>(action) ||
|
||||
dynamic_cast<CastHandOfReckoningAction*>(action) || dynamic_cast<CastGrowlAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dynamic_cast<PetAttackAction*>(action))
|
||||
{
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (target && target->GetEntry() == Gluth::NPC_ZOMBIE_CHOW)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
|
||||
#ifndef _PLAYERRBOT_RAIDNAXXMULTIPLIERS_H_
|
||||
#define _PLAYERRBOT_RAIDNAXXMULTIPLIERS_H_
|
||||
|
||||
#include "Multiplier.h"
|
||||
#include "raids/naxxramas/RaidNaxxBossHelper.h"
|
||||
|
||||
class GrobbulusMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
GrobbulusMultiplier(PlayerbotAI* ai) : Multiplier(ai, "grobbulus") {}
|
||||
|
||||
public:
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
class HeiganDanceMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
HeiganDanceMultiplier(PlayerbotAI* ai) : Multiplier(ai, "helgan dance") {}
|
||||
|
||||
public:
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class LoathebGenericMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
LoathebGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "loatheb generic") {}
|
||||
|
||||
public:
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class ThaddiusGenericMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
ThaddiusGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "thaddius generic"), helper(ai) {}
|
||||
|
||||
public:
|
||||
virtual float GetValue(Action* action);
|
||||
|
||||
private:
|
||||
ThaddiusBossHelper helper;
|
||||
};
|
||||
|
||||
class SapphironGenericMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
SapphironGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "sapphiron generic"), helper(ai) {}
|
||||
|
||||
virtual float GetValue(Action* action);
|
||||
|
||||
private:
|
||||
SapphironBossHelper helper;
|
||||
};
|
||||
|
||||
class InstructorRazuviousGenericMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
InstructorRazuviousGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "instructor razuvious generic"), helper(ai)
|
||||
{
|
||||
}
|
||||
virtual float GetValue(Action* action);
|
||||
|
||||
private:
|
||||
RazuviousBossHelper helper;
|
||||
};
|
||||
|
||||
class KelthuzadGenericMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
KelthuzadGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "kelthuzad generic"), helper(ai) {}
|
||||
virtual float GetValue(Action* action);
|
||||
|
||||
private:
|
||||
KelthuzadBossHelper helper;
|
||||
};
|
||||
|
||||
class AnubrekhanGenericMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
AnubrekhanGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "anubrekhan generic") {}
|
||||
|
||||
public:
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class FourhorsemanGenericMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
FourhorsemanGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "fourhorseman generic") {}
|
||||
|
||||
public:
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
// class GothikGenericMultiplier : public Multiplier
|
||||
// {
|
||||
// public:
|
||||
// GothikGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "gothik generic") {}
|
||||
|
||||
// public:
|
||||
// virtual float GetValue(Action* action);
|
||||
// };
|
||||
|
||||
class GluthGenericMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
GluthGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "gluth generic"), helper(ai) {}
|
||||
float GetValue(Action* action) override;
|
||||
|
||||
private:
|
||||
GluthBossHelper helper;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
#ifndef _PLAYERBOT_RAIDNAXXSCRIPTS_H
|
||||
#define _PLAYERBOT_RAIDNAXXSCRIPTS_H
|
||||
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_faerlina.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_gluth.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_gothik.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_grobbulus.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_heigan.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_loatheb.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_maexxna.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_noth.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_patchwerk.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_razuvious.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_sapphiron.h"
|
||||
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_thaddius.h"
|
||||
|
||||
#endif
|
||||
@@ -1,105 +0,0 @@
|
||||
#include "RaidNaxxStrategy.h"
|
||||
|
||||
#include "RaidNaxxMultipliers.h"
|
||||
|
||||
void RaidNaxxStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
// Grobbulus
|
||||
triggers.push_back(new TriggerNode(
|
||||
"mutating injection",
|
||||
NextAction::array(0, new NextAction("grobbulus go behind the boss", ACTION_RAID + 2), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("mutating injection removed",
|
||||
NextAction::array(0, new NextAction("grobbulus move center", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"grobbulus cloud", NextAction::array(0, new NextAction("rotate grobbulus", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
// Heigan the Unclean
|
||||
triggers.push_back(new TriggerNode(
|
||||
"heigan melee", NextAction::array(0, new NextAction("heigan dance melee", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"heigan ranged", NextAction::array(0, new NextAction("heigan dance ranged", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
// Kel'Thuzad
|
||||
triggers.push_back(new TriggerNode(
|
||||
"kel'thuzad", NextAction::array(0, new NextAction("kel'thuzad position", ACTION_RAID + 2),
|
||||
new NextAction("kel'thuzad choose target", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
// Anub'Rekhan
|
||||
triggers.push_back(new TriggerNode(
|
||||
"anub'rekhan", NextAction::array(0, new NextAction("anub'rekhan position", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
// Thaddius
|
||||
triggers.push_back(
|
||||
new TriggerNode("thaddius phase pet",
|
||||
NextAction::array(0, new NextAction("thaddius attack nearest pet", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("thaddius phase pet lose aggro",
|
||||
NextAction::array(0, new NextAction("taunt spell", ACTION_RAID + 2), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("thaddius phase transition",
|
||||
NextAction::array(0, new NextAction("thaddius move to platform", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("thaddius phase thaddius",
|
||||
NextAction::array(0, new NextAction("thaddius move polarity", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
// Instructor Razuvious
|
||||
triggers.push_back(new TriggerNode(
|
||||
"razuvious tank",
|
||||
NextAction::array(0, new NextAction("razuvious use obedience crystal", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"razuvious nontank", NextAction::array(0, new NextAction("razuvious target", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
// four horseman
|
||||
triggers.push_back(new TriggerNode(
|
||||
"horseman attractors",
|
||||
NextAction::array(0, new NextAction("horseman attract alternatively", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("horseman except attractors",
|
||||
NextAction::array(0, new NextAction("horseman attack in order", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
// sapphiron
|
||||
triggers.push_back(
|
||||
new TriggerNode("sapphiron ground",
|
||||
NextAction::array(0, new NextAction("sapphiron ground position", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("sapphiron flight",
|
||||
NextAction::array(0, new NextAction("sapphiron flight position", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
// Gluth
|
||||
triggers.push_back(
|
||||
new TriggerNode("gluth", NextAction::array(0, new NextAction("gluth choose target", ACTION_RAID + 1),
|
||||
new NextAction("gluth position", ACTION_RAID + 1),
|
||||
new NextAction("gluth slowdown", ACTION_RAID), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("gluth main tank mortal wound",
|
||||
NextAction::array(0, new NextAction("taunt spell", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
// Loatheb
|
||||
triggers.push_back(new TriggerNode(
|
||||
"loatheb", NextAction::array(0, new NextAction("loatheb position", ACTION_RAID + 1),
|
||||
new NextAction("loatheb choose target", ACTION_RAID + 1), nullptr)));
|
||||
}
|
||||
|
||||
void RaidNaxxStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
||||
{
|
||||
multipliers.push_back(new GrobbulusMultiplier(botAI));
|
||||
multipliers.push_back(new HeiganDanceMultiplier(botAI));
|
||||
multipliers.push_back(new LoathebGenericMultiplier(botAI));
|
||||
multipliers.push_back(new ThaddiusGenericMultiplier(botAI));
|
||||
multipliers.push_back(new SapphironGenericMultiplier(botAI));
|
||||
multipliers.push_back(new InstructorRazuviousGenericMultiplier(botAI));
|
||||
multipliers.push_back(new KelthuzadGenericMultiplier(botAI));
|
||||
multipliers.push_back(new AnubrekhanGenericMultiplier(botAI));
|
||||
multipliers.push_back(new FourhorsemanGenericMultiplier(botAI));
|
||||
// multipliers.push_back(new GothikGenericMultiplier(botAI));
|
||||
multipliers.push_back(new GluthGenericMultiplier(botAI));
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
#ifndef _PLAYERBOT_RAIDNAXXSTRATEGY_H
|
||||
#define _PLAYERBOT_RAIDNAXXSTRATEGY_H
|
||||
|
||||
#include "AiObjectContext.h"
|
||||
#include "Multiplier.h"
|
||||
#include "RaidNaxxScripts.h"
|
||||
#include "Strategy.h"
|
||||
|
||||
class RaidNaxxStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
RaidNaxxStrategy(PlayerbotAI* ai) : Strategy(ai) {}
|
||||
virtual std::string const getName() override { return "naxx"; }
|
||||
virtual void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
virtual void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,74 +0,0 @@
|
||||
// /*
|
||||
// * Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||
// and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||
// */
|
||||
|
||||
#ifndef _PLAYERBOT_RAIDNAXXTRIGGERCONTEXT_H
|
||||
#define _PLAYERBOT_RAIDNAXXTRIGGERCONTEXT_H
|
||||
|
||||
#include "AiObjectContext.h"
|
||||
#include "NamedObjectContext.h"
|
||||
#include "RaidNaxxTriggers.h"
|
||||
|
||||
class RaidNaxxTriggerContext : public NamedObjectContext<Trigger>
|
||||
{
|
||||
public:
|
||||
RaidNaxxTriggerContext()
|
||||
{
|
||||
creators["mutating injection"] = &RaidNaxxTriggerContext::mutating_injection;
|
||||
creators["mutating injection removed"] = &RaidNaxxTriggerContext::mutating_injection_removed;
|
||||
creators["grobbulus cloud"] = &RaidNaxxTriggerContext::grobbulus_cloud;
|
||||
creators["heigan melee"] = &RaidNaxxTriggerContext::heigan_melee;
|
||||
creators["heigan ranged"] = &RaidNaxxTriggerContext::heigan_ranged;
|
||||
|
||||
creators["thaddius phase pet"] = &RaidNaxxTriggerContext::thaddius_phase_pet;
|
||||
creators["thaddius phase pet lose aggro"] = &RaidNaxxTriggerContext::thaddius_phase_pet_lose_aggro;
|
||||
creators["thaddius phase transition"] = &RaidNaxxTriggerContext::thaddius_phase_transition;
|
||||
creators["thaddius phase thaddius"] = &RaidNaxxTriggerContext::thaddius_phase_thaddius;
|
||||
|
||||
creators["razuvious tank"] = &RaidNaxxTriggerContext::razuvious_tank;
|
||||
creators["razuvious nontank"] = &RaidNaxxTriggerContext::razuvious_nontank;
|
||||
|
||||
creators["horseman attractors"] = &RaidNaxxTriggerContext::horseman_attractors;
|
||||
creators["horseman except attractors"] = &RaidNaxxTriggerContext::horseman_except_attractors;
|
||||
|
||||
creators["sapphiron ground"] = &RaidNaxxTriggerContext::sapphiron_ground;
|
||||
creators["sapphiron flight"] = &RaidNaxxTriggerContext::sapphiron_flight;
|
||||
|
||||
creators["kel'thuzad"] = &RaidNaxxTriggerContext::kelthuzad;
|
||||
|
||||
creators["anub'rekhan"] = &RaidNaxxTriggerContext::anubrekhan;
|
||||
|
||||
creators["gluth"] = &RaidNaxxTriggerContext::gluth;
|
||||
creators["gluth main tank mortal wound"] = &RaidNaxxTriggerContext::gluth_main_tank_mortal_wound;
|
||||
|
||||
creators["loatheb"] = &RaidNaxxTriggerContext::loatheb;
|
||||
}
|
||||
|
||||
private:
|
||||
static Trigger* mutating_injection(PlayerbotAI* ai) { return new MutatingInjectionTrigger(ai); }
|
||||
static Trigger* mutating_injection_removed(PlayerbotAI* ai) { return new MutatingInjectionRemovedTrigger(ai); }
|
||||
static Trigger* grobbulus_cloud(PlayerbotAI* ai) { return new GrobbulusCloudTrigger(ai); }
|
||||
static Trigger* heigan_melee(PlayerbotAI* ai) { return new HeiganMeleeTrigger(ai); }
|
||||
static Trigger* heigan_ranged(PlayerbotAI* ai) { return new HeiganRangedTrigger(ai); }
|
||||
|
||||
static Trigger* thaddius_phase_pet(PlayerbotAI* ai) { return new ThaddiusPhasePetTrigger(ai); }
|
||||
static Trigger* thaddius_phase_pet_lose_aggro(PlayerbotAI* ai) { return new ThaddiusPhasePetLoseAggroTrigger(ai); }
|
||||
static Trigger* thaddius_phase_transition(PlayerbotAI* ai) { return new ThaddiusPhaseTransitionTrigger(ai); }
|
||||
static Trigger* thaddius_phase_thaddius(PlayerbotAI* ai) { return new ThaddiusPhaseThaddiusTrigger(ai); }
|
||||
static Trigger* razuvious_tank(PlayerbotAI* ai) { return new RazuviousTankTrigger(ai); }
|
||||
static Trigger* razuvious_nontank(PlayerbotAI* ai) { return new RazuviousNontankTrigger(ai); }
|
||||
|
||||
static Trigger* horseman_attractors(PlayerbotAI* ai) { return new HorsemanAttractorsTrigger(ai); }
|
||||
static Trigger* horseman_except_attractors(PlayerbotAI* ai) { return new HorsemanExceptAttractorsTrigger(ai); }
|
||||
|
||||
static Trigger* sapphiron_ground(PlayerbotAI* ai) { return new SapphironGroundTrigger(ai); }
|
||||
static Trigger* sapphiron_flight(PlayerbotAI* ai) { return new SapphironFlightTrigger(ai); }
|
||||
static Trigger* kelthuzad(PlayerbotAI* ai) { return new KelthuzadTrigger(ai); }
|
||||
static Trigger* anubrekhan(PlayerbotAI* ai) { return new AnubrekhanTrigger(ai); }
|
||||
static Trigger* gluth(PlayerbotAI* ai) { return new GluthTrigger(ai); }
|
||||
static Trigger* gluth_main_tank_mortal_wound(PlayerbotAI* ai) { return new GluthMainTankMortalWoundTrigger(ai); }
|
||||
static Trigger* loatheb(PlayerbotAI* ai) { return new LoathebTrigger(ai); }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,210 +0,0 @@
|
||||
#include "RaidNaxxTriggers.h"
|
||||
|
||||
#include "EventMap.h"
|
||||
#include "Playerbots.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Trigger.h"
|
||||
|
||||
bool AuraRemovedTrigger::IsActive()
|
||||
{
|
||||
bool check = botAI->HasAura(name, bot, false, false, -1, true);
|
||||
bool ret = false;
|
||||
if (prev_check && !check)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
prev_check = check;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MutatingInjectionRemovedTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "grobbulus");
|
||||
if (!boss)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return HasNoAuraTrigger::IsActive() && botAI->GetState() == BOT_STATE_COMBAT && botAI->IsRanged(bot);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool BossEventTrigger<T>::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE(Unit*, "boss target");
|
||||
if (!boss || boss->GetEntry() != boss_entry)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
T* ai = dynamic_cast<T*>(boss->GetAI());
|
||||
EventMap* eventMap = &ai->events;
|
||||
if (!eventMap)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const uint32 event_time = eventMap->GetNextEventTime(event_id);
|
||||
if (event_time != last_event_time)
|
||||
{
|
||||
last_event_time = event_time;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GrobbulusCloudTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE(Unit*, "boss target");
|
||||
if (!boss || boss->GetEntry() != boss_entry)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!botAI->IsMainTank(bot))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// bot->Yell("has aggro on " + boss->GetName() + " : " + to_string(AI_VALUE2(bool, "has aggro", "boss target")),
|
||||
// LANG_UNIVERSAL);
|
||||
return AI_VALUE2(bool, "has aggro", "boss target");
|
||||
}
|
||||
|
||||
bool HeiganMeleeTrigger::IsActive()
|
||||
{
|
||||
Unit* heigan = AI_VALUE2(Unit*, "find target", "heigan the unclean");
|
||||
if (!heigan)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !botAI->IsRanged(bot);
|
||||
}
|
||||
|
||||
bool HeiganRangedTrigger::IsActive()
|
||||
{
|
||||
Unit* heigan = AI_VALUE2(Unit*, "find target", "heigan the unclean");
|
||||
if (!heigan)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return botAI->IsRanged(bot);
|
||||
}
|
||||
|
||||
bool RazuviousTankTrigger::IsActive()
|
||||
{
|
||||
Difficulty diff = bot->GetRaidDifficulty();
|
||||
if (diff == RAID_DIFFICULTY_10MAN_NORMAL)
|
||||
{
|
||||
return helper.UpdateBossAI() && botAI->IsTank(bot);
|
||||
}
|
||||
return helper.UpdateBossAI() && bot->getClass() == CLASS_PRIEST;
|
||||
}
|
||||
|
||||
bool RazuviousNontankTrigger::IsActive()
|
||||
{
|
||||
Difficulty diff = bot->GetRaidDifficulty();
|
||||
if (diff == RAID_DIFFICULTY_10MAN_NORMAL)
|
||||
{
|
||||
return helper.UpdateBossAI() && !(botAI->IsTank(bot));
|
||||
}
|
||||
return helper.UpdateBossAI() && !(bot->getClass() == CLASS_PRIEST);
|
||||
}
|
||||
|
||||
bool HorsemanAttractorsTrigger::IsActive()
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return helper.IsAttracter(bot);
|
||||
}
|
||||
|
||||
bool HorsemanExceptAttractorsTrigger::IsActive()
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !helper.IsAttracter(bot);
|
||||
}
|
||||
|
||||
bool SapphironGroundTrigger::IsActive()
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return helper.IsPhaseGround();
|
||||
}
|
||||
|
||||
bool SapphironFlightTrigger::IsActive()
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return helper.IsPhaseFlight();
|
||||
}
|
||||
|
||||
bool GluthTrigger::IsActive() { return helper.UpdateBossAI(); }
|
||||
|
||||
bool GluthMainTankMortalWoundTrigger::IsActive()
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!botAI->IsAssistTankOfIndex(bot, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Unit* mt = AI_VALUE(Unit*, "main tank");
|
||||
if (!mt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Aura* aura = botAI->GetAura("mortal wound", mt, false, true);
|
||||
if (!aura || aura->GetStackAmount() < 5)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KelthuzadTrigger::IsActive() { return helper.UpdateBossAI(); }
|
||||
|
||||
bool AnubrekhanTrigger::IsActive() {
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "anub'rekhan");
|
||||
if (!boss)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoathebTrigger::IsActive() { return helper.UpdateBossAI(); }
|
||||
|
||||
bool ThaddiusPhasePetTrigger::IsActive()
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return helper.IsPhasePet();
|
||||
}
|
||||
|
||||
bool ThaddiusPhaseTransitionTrigger::IsActive()
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return helper.IsPhaseTransition();
|
||||
}
|
||||
|
||||
bool ThaddiusPhaseThaddiusTrigger::IsActive()
|
||||
{
|
||||
if (!helper.UpdateBossAI())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return helper.IsPhaseThaddius();
|
||||
}
|
||||
|
||||
template bool BossEventTrigger<Grobbulus::boss_grobbulus::boss_grobbulusAI>::IsActive();
|
||||
@@ -1,223 +0,0 @@
|
||||
|
||||
#ifndef _PLAYERBOT_RAIDNAXXTRIGGERS_H
|
||||
#define _PLAYERBOT_RAIDNAXXTRIGGERS_H
|
||||
|
||||
#include "EventMap.h"
|
||||
#include "GenericTriggers.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "RaidNaxxBossHelper.h"
|
||||
#include "RaidNaxxScripts.h"
|
||||
#include "Trigger.h"
|
||||
|
||||
class MutatingInjectionTrigger : public HasAuraTrigger
|
||||
{
|
||||
public:
|
||||
MutatingInjectionTrigger(PlayerbotAI* ai) : HasAuraTrigger(ai, "mutating injection", 1) {}
|
||||
};
|
||||
|
||||
class AuraRemovedTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
AuraRemovedTrigger(PlayerbotAI* botAI, std::string name) : Trigger(botAI, name, 1) { this->prev_check = false; }
|
||||
virtual bool IsActive() override;
|
||||
|
||||
protected:
|
||||
bool prev_check;
|
||||
};
|
||||
|
||||
class MutatingInjectionRemovedTrigger : public HasNoAuraTrigger
|
||||
{
|
||||
public:
|
||||
MutatingInjectionRemovedTrigger(PlayerbotAI* ai) : HasNoAuraTrigger(ai, "mutating injection") {}
|
||||
virtual bool IsActive();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class BossEventTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
BossEventTrigger(PlayerbotAI* ai, uint32 boss_entry, uint32 event_id, std::string name = "boss event")
|
||||
: Trigger(ai, name, 1)
|
||||
{
|
||||
this->boss_entry = boss_entry;
|
||||
this->event_id = event_id;
|
||||
this->last_event_time = -1;
|
||||
}
|
||||
virtual bool IsActive();
|
||||
|
||||
protected:
|
||||
uint32 boss_entry, event_id, last_event_time;
|
||||
};
|
||||
|
||||
class GrobbulusCloudTrigger : public BossEventTrigger<Grobbulus::boss_grobbulus::boss_grobbulusAI>
|
||||
{
|
||||
public:
|
||||
GrobbulusCloudTrigger(PlayerbotAI* ai) : BossEventTrigger(ai, 15931, 2, "grobbulus cloud event") {}
|
||||
virtual bool IsActive();
|
||||
};
|
||||
|
||||
class HeiganMeleeTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
HeiganMeleeTrigger(PlayerbotAI* ai) : Trigger(ai, "heigan melee") {}
|
||||
virtual bool IsActive();
|
||||
};
|
||||
|
||||
class HeiganRangedTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
HeiganRangedTrigger(PlayerbotAI* ai) : Trigger(ai, "heigan ranged") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class RazuviousTankTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
RazuviousTankTrigger(PlayerbotAI* ai) : Trigger(ai, "instructor razuvious tank"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
RazuviousBossHelper helper;
|
||||
};
|
||||
|
||||
class RazuviousNontankTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
RazuviousNontankTrigger(PlayerbotAI* ai) : Trigger(ai, "instructor razuvious non-tank"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
RazuviousBossHelper helper;
|
||||
};
|
||||
|
||||
class KelthuzadTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KelthuzadTrigger(PlayerbotAI* ai) : Trigger(ai, "kel'thuzad trigger"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
KelthuzadBossHelper helper;
|
||||
};
|
||||
|
||||
class AnubrekhanTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
AnubrekhanTrigger(PlayerbotAI* ai) : Trigger(ai, "anub'rekhan") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class ThaddiusPhasePetTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
ThaddiusPhasePetTrigger(PlayerbotAI* ai) : Trigger(ai, "thaddius phase pet"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
ThaddiusBossHelper helper;
|
||||
};
|
||||
|
||||
class ThaddiusPhasePetLoseAggroTrigger : public ThaddiusPhasePetTrigger
|
||||
{
|
||||
public:
|
||||
ThaddiusPhasePetLoseAggroTrigger(PlayerbotAI* ai) : ThaddiusPhasePetTrigger(ai) {}
|
||||
virtual bool IsActive()
|
||||
{
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
return ThaddiusPhasePetTrigger::IsActive() && botAI->IsTank(bot) && target && target->GetVictim() != bot;
|
||||
}
|
||||
};
|
||||
|
||||
class ThaddiusPhaseTransitionTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
ThaddiusPhaseTransitionTrigger(PlayerbotAI* ai) : Trigger(ai, "thaddius phase transition"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
ThaddiusBossHelper helper;
|
||||
};
|
||||
|
||||
class ThaddiusPhaseThaddiusTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
ThaddiusPhaseThaddiusTrigger(PlayerbotAI* ai) : Trigger(ai, "thaddius phase thaddius"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
ThaddiusBossHelper helper;
|
||||
};
|
||||
|
||||
class HorsemanAttractorsTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
HorsemanAttractorsTrigger(PlayerbotAI* ai) : Trigger(ai, "fourhorsemen attractors"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
FourhorsemanBossHelper helper;
|
||||
};
|
||||
|
||||
class HorsemanExceptAttractorsTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
HorsemanExceptAttractorsTrigger(PlayerbotAI* ai) : Trigger(ai, "fourhorsemen except attractors"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
FourhorsemanBossHelper helper;
|
||||
};
|
||||
|
||||
class SapphironGroundTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
SapphironGroundTrigger(PlayerbotAI* ai) : Trigger(ai, "sapphiron ground"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
SapphironBossHelper helper;
|
||||
};
|
||||
|
||||
class SapphironFlightTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
SapphironFlightTrigger(PlayerbotAI* ai) : Trigger(ai, "sapphiron flight"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
SapphironBossHelper helper;
|
||||
};
|
||||
|
||||
class GluthTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
GluthTrigger(PlayerbotAI* ai) : Trigger(ai, "gluth trigger"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
GluthBossHelper helper;
|
||||
};
|
||||
|
||||
class GluthMainTankMortalWoundTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
GluthMainTankMortalWoundTrigger(PlayerbotAI* ai) : Trigger(ai, "gluth main tank mortal wound trigger"), helper(ai)
|
||||
{
|
||||
}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
GluthBossHelper helper;
|
||||
};
|
||||
|
||||
class LoathebTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
LoathebTrigger(PlayerbotAI* ai) : Trigger(ai, "loatheb"), helper(ai) {}
|
||||
bool IsActive() override;
|
||||
|
||||
private:
|
||||
LoathebBossHelper helper;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -126,7 +126,6 @@ public:
|
||||
creators["guild leave"] = &ChatTriggerContext::guild_leave;
|
||||
creators["rtsc"] = &ChatTriggerContext::rtsc;
|
||||
creators["drink"] = &ChatTriggerContext::drink;
|
||||
// creators["naxx"] = &ChatTriggerContext::naxx;
|
||||
// creators["bwl"] = &ChatTriggerContext::bwl;
|
||||
creators["dps"] = &ChatTriggerContext::dps;
|
||||
creators["disperse"] = &ChatTriggerContext::disperse;
|
||||
@@ -244,7 +243,6 @@ private:
|
||||
static Trigger* guild_leave(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "guild leave"); }
|
||||
static Trigger* rtsc(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "rtsc"); }
|
||||
static Trigger* drink(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "drink"); }
|
||||
// static Trigger* naxx(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "naxx"); }
|
||||
// static Trigger* bwl(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "bwl"); }
|
||||
static Trigger* dps(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "dps"); }
|
||||
static Trigger* disperse(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "disperse"); }
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "NewRpgStrategy.h"
|
||||
#include "NewRpgTriggers.h"
|
||||
#include "PvpTriggers.h"
|
||||
#include "RaidNaxxTriggers.h"
|
||||
#include "RpgTriggers.h"
|
||||
#include "RtiTriggers.h"
|
||||
#include "StuckTriggers.h"
|
||||
|
||||
Reference in New Issue
Block a user