mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-26 15:06:22 +00:00
[HOT FIX] MS build issues regarding folder / command lenght usage or rc.exe (#2038)
This commit is contained in:
446
src/Ai/Class/Warlock/Action/WarlockActions.cpp
Normal file
446
src/Ai/Class/Warlock/Action/WarlockActions.cpp
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "WarlockActions.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Event.h"
|
||||
#include "Item.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Playerbots.h"
|
||||
#include "ServerFacade.h"
|
||||
#include "Unit.h"
|
||||
#include "Timer.h"
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
|
||||
const int ITEM_SOUL_SHARD = 6265;
|
||||
|
||||
// Checks if the bot has less than 26 soul shards, and if so, allows casting Drain Soul
|
||||
bool CastDrainSoulAction::isUseful() { return AI_VALUE2(uint32, "item count", "soul shard") < 26; }
|
||||
|
||||
// Checks if the bot's health is above a certain threshold, and if so, allows casting Life Tap
|
||||
bool CastLifeTapAction::isUseful() { return AI_VALUE2(uint8, "health", "self target") > sPlayerbotAIConfig->lowHealth; }
|
||||
|
||||
// Checks if the target marked with the moon icon can be banished
|
||||
bool CastBanishOnCcAction::isPossible()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
// Only possible on elementals or demons
|
||||
uint32 creatureType = target->GetCreatureType();
|
||||
if (creatureType != CREATURE_TYPE_DEMON && creatureType != CREATURE_TYPE_ELEMENTAL)
|
||||
return false;
|
||||
|
||||
// Use base class to check spell available, range, etc
|
||||
return CastCrowdControlSpellAction::isPossible();
|
||||
}
|
||||
|
||||
// Checks if the target marked with the moon icon can be feared
|
||||
bool CastFearOnCcAction::isPossible()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
// Fear cannot be cast on mechanical or undead creatures
|
||||
uint32 creatureType = target->GetCreatureType();
|
||||
if (creatureType == CREATURE_TYPE_MECHANICAL || creatureType == CREATURE_TYPE_UNDEAD)
|
||||
return false;
|
||||
|
||||
// Use base class to check spell available, range, etc
|
||||
return CastCrowdControlSpellAction::isPossible();
|
||||
}
|
||||
|
||||
// Checks if the enemies are close enough to use Shadowflame
|
||||
bool CastShadowflameAction::isUseful()
|
||||
{
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (!target)
|
||||
return false;
|
||||
bool facingTarget = AI_VALUE2(bool, "facing", "current target");
|
||||
bool targetClose = bot->IsWithinCombatRange(target, 7.0f); // 7 yard cone
|
||||
return facingTarget && targetClose;
|
||||
}
|
||||
|
||||
// Checks if the bot knows Seed of Corruption, and prevents the use of Rain of Fire if it does
|
||||
bool CastRainOfFireAction::isUseful()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (!target)
|
||||
return false;
|
||||
if (bot->HasSpell(27243) || bot->HasSpell(47835) || bot->HasSpell(47836)) // Seed of Corruption spell IDs
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks if the enemies are close enough to use Hellfire
|
||||
bool CastHellfireAction::isUseful()
|
||||
{
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
return bot->IsWithinCombatRange(target, 5.0f); // 5 yard AoE radius
|
||||
}
|
||||
|
||||
// Checks if the "meta melee aoe" strategy is active, OR if the bot is in melee range of the target
|
||||
bool CastImmolationAuraAction::isUseful()
|
||||
{
|
||||
if (botAI->HasStrategy("meta melee", BOT_STATE_COMBAT))
|
||||
return true;
|
||||
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
if (!bot->HasAura(47241)) // 47241 is Metamorphosis spell ID (WotLK)
|
||||
return false;
|
||||
|
||||
return bot->IsWithinCombatRange(target, 5.0f); // 5 yard AoE radius
|
||||
}
|
||||
|
||||
// Checks if the "warlock tank" strategy is active, and if so, prevents the use of Soulshatter
|
||||
bool CastSoulshatterAction::isUseful()
|
||||
{
|
||||
if (botAI->HasStrategy("tank", BOT_STATE_COMBAT))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks if the bot has enough bag space to create a soul shard, then does so
|
||||
bool CreateSoulShardAction::Execute(Event event)
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
if (!bot)
|
||||
return false;
|
||||
|
||||
ItemPosCountVec dest;
|
||||
uint32 count = 1;
|
||||
if (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_SOUL_SHARD, count) == EQUIP_ERR_OK)
|
||||
{
|
||||
bot->StoreNewItem(dest, ITEM_SOUL_SHARD, true, Item::GenerateItemRandomPropertyId(ITEM_SOUL_SHARD));
|
||||
SQLTransaction<CharacterDatabaseConnection> trans = CharacterDatabase.BeginTransaction();
|
||||
bot->SaveInventoryAndGoldToDB(trans);
|
||||
CharacterDatabase.CommitTransaction(trans);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checks if the bot has less than 6 soul shards, allowing the creation of a new one
|
||||
bool CreateSoulShardAction::isUseful()
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
if (!bot)
|
||||
return false;
|
||||
|
||||
uint32 currentShards = bot->GetItemCount(ITEM_SOUL_SHARD, false); // false = only bags
|
||||
const uint32 SHARD_CAP = 6; // adjust as needed
|
||||
|
||||
// Only allow if under cap AND there is space for a new shard
|
||||
ItemPosCountVec dest;
|
||||
uint32 count = 1;
|
||||
bool hasSpace = (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_SOUL_SHARD, count) == EQUIP_ERR_OK);
|
||||
|
||||
return (currentShards < SHARD_CAP) && hasSpace;
|
||||
}
|
||||
|
||||
bool CastCreateSoulstoneAction::isUseful()
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
if (!bot)
|
||||
return false;
|
||||
|
||||
// List of all Soulstone item IDs
|
||||
static const std::vector<uint32> soulstoneIds = {
|
||||
5232, // Minor Soulstone
|
||||
16892, // Lesser Soulstone
|
||||
16893, // Soulstone
|
||||
16895, // Greater Soulstone
|
||||
16896, // Major Soulstone
|
||||
22116, // Master Soulstone
|
||||
36895 // Demonic Soulstone
|
||||
};
|
||||
|
||||
// Check if the bot already has any soulstone
|
||||
for (uint32 id : soulstoneIds)
|
||||
{
|
||||
if (bot->GetItemCount(id, false) > 0)
|
||||
return false; // Already has a soulstone
|
||||
}
|
||||
|
||||
// Only need to check one soulstone type for bag space (usually the highest-tier)
|
||||
ItemPosCountVec dest;
|
||||
uint32 count = 1;
|
||||
// Use the last in the list (highest tier)
|
||||
uint32 soulstoneToCreate = soulstoneIds.back();
|
||||
|
||||
bool hasSpace = (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, soulstoneToCreate, count) == EQUIP_ERR_OK);
|
||||
|
||||
return hasSpace;
|
||||
}
|
||||
|
||||
bool DestroySoulShardAction::Execute(Event event)
|
||||
{
|
||||
// Look for the first soul shard in any bag and destroy it
|
||||
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
{
|
||||
if (Bag* pBag = (Bag*)bot->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
{
|
||||
for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
||||
{
|
||||
if (Item* pItem = pBag->GetItemByPos(j))
|
||||
{
|
||||
if (pItem->GetTemplate()->ItemId == ITEM_SOUL_SHARD)
|
||||
{
|
||||
bot->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
|
||||
return true; // Only destroy one!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Also check main inventory slots (not in bags)
|
||||
for (int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i)
|
||||
{
|
||||
if (Item* pItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
{
|
||||
if (pItem->GetTemplate()->ItemId == ITEM_SOUL_SHARD)
|
||||
{
|
||||
bot->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checks if the target has a soulstone aura
|
||||
static bool HasSoulstoneAura(Unit* unit)
|
||||
{
|
||||
static const std::vector<uint32> soulstoneAuraIds = {20707, 20762, 20763, 20764, 20765, 27239, 47883};
|
||||
for (uint32 spellId : soulstoneAuraIds)
|
||||
if (unit->HasAura(spellId))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use the soulstone item on the bot itself with nc strategy "ss self"
|
||||
bool UseSoulstoneSelfAction::Execute(Event event)
|
||||
{
|
||||
std::vector<Item*> items = AI_VALUE2(std::vector<Item*>, "inventory items", "soulstone");
|
||||
if (items.empty())
|
||||
return false;
|
||||
|
||||
if (HasSoulstoneAura(bot))
|
||||
return false;
|
||||
|
||||
bot->SetSelection(bot->GetGUID());
|
||||
return UseItem(items[0], ObjectGuid::Empty, nullptr, bot);
|
||||
}
|
||||
|
||||
// Reservation map for soulstone targets (GUID -> reservation expiry in ms)
|
||||
static std::unordered_map<ObjectGuid, uint32> soulstoneReservations;
|
||||
static std::mutex soulstoneReservationsMutex;
|
||||
|
||||
// Helper to clean up expired reservations
|
||||
void CleanupSoulstoneReservations()
|
||||
{
|
||||
uint32 now = getMSTime();
|
||||
std::lock_guard<std::mutex> lock(soulstoneReservationsMutex);
|
||||
for (auto it = soulstoneReservations.begin(); it != soulstoneReservations.end();)
|
||||
{
|
||||
if (it->second <= now)
|
||||
it = soulstoneReservations.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the soulstone item on the bot's master with nc strategy "ss master"
|
||||
bool UseSoulstoneMasterAction::Execute(Event event)
|
||||
{
|
||||
CleanupSoulstoneReservations();
|
||||
|
||||
std::vector<Item*> items = AI_VALUE2(std::vector<Item*>, "inventory items", "soulstone");
|
||||
if (items.empty())
|
||||
return false;
|
||||
|
||||
Player* master = botAI->GetMaster();
|
||||
if (!master || HasSoulstoneAura(master))
|
||||
return false;
|
||||
|
||||
uint32 now = getMSTime();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(soulstoneReservationsMutex);
|
||||
if (soulstoneReservations.count(master->GetGUID()) && soulstoneReservations[master->GetGUID()] > now)
|
||||
return false; // Already being soulstoned
|
||||
|
||||
soulstoneReservations[master->GetGUID()] = now + 2500; // Reserve for 2.5 seconds
|
||||
}
|
||||
|
||||
float distance = sServerFacade->GetDistance2d(bot, master);
|
||||
if (distance >= 30.0f)
|
||||
return false;
|
||||
|
||||
if (!bot->IsWithinLOSInMap(master))
|
||||
return false;
|
||||
|
||||
bot->SetSelection(master->GetGUID());
|
||||
return UseItem(items[0], ObjectGuid::Empty, nullptr, master);
|
||||
}
|
||||
|
||||
// Use the soulstone item on a tank in the group with nc strategy "ss tank"
|
||||
bool UseSoulstoneTankAction::Execute(Event event)
|
||||
{
|
||||
CleanupSoulstoneReservations();
|
||||
|
||||
std::vector<Item*> items = AI_VALUE2(std::vector<Item*>, "inventory items", "soulstone");
|
||||
if (items.empty())
|
||||
return false;
|
||||
|
||||
Player* chosenTank = nullptr;
|
||||
Group* group = bot->GetGroup();
|
||||
uint32 now = getMSTime();
|
||||
|
||||
// First: Try to soulstone the main tank
|
||||
if (group)
|
||||
{
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
{
|
||||
Player* member = gref->GetSource();
|
||||
if (member && member->IsAlive() && botAI->IsTank(member) && botAI->IsMainTank(member) &&
|
||||
!HasSoulstoneAura(member))
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(soulstoneReservationsMutex);
|
||||
if (soulstoneReservations.count(member->GetGUID()) && soulstoneReservations[member->GetGUID()] > now)
|
||||
continue; // Already being soulstoned
|
||||
|
||||
float distance = sServerFacade->GetDistance2d(bot, member);
|
||||
if (distance < 30.0f && bot->IsWithinLOSInMap(member))
|
||||
{
|
||||
chosenTank = member;
|
||||
soulstoneReservations[chosenTank->GetGUID()] = now + 2500; // Reserve for 2.5 seconds
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no main tank found, soulstone another tank
|
||||
if (!chosenTank)
|
||||
{
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
{
|
||||
Player* member = gref->GetSource();
|
||||
if (member && member->IsAlive() && botAI->IsTank(member) && !HasSoulstoneAura(member))
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(soulstoneReservationsMutex);
|
||||
if (soulstoneReservations.count(member->GetGUID()) &&
|
||||
soulstoneReservations[member->GetGUID()] > now)
|
||||
continue; // Already being soulstoned
|
||||
|
||||
float distance = sServerFacade->GetDistance2d(bot, member);
|
||||
if (distance < 30.0f && bot->IsWithinLOSInMap(member))
|
||||
{
|
||||
chosenTank = member;
|
||||
soulstoneReservations[chosenTank->GetGUID()] = now + 2500; // Reserve for 2.5 seconds
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!chosenTank)
|
||||
return false;
|
||||
|
||||
bot->SetSelection(chosenTank->GetGUID());
|
||||
return UseItem(items[0], ObjectGuid::Empty, nullptr, chosenTank);
|
||||
}
|
||||
|
||||
// Use the soulstone item on a healer in the group with nc strategy "ss healer"
|
||||
bool UseSoulstoneHealerAction::Execute(Event event)
|
||||
{
|
||||
CleanupSoulstoneReservations();
|
||||
|
||||
std::vector<Item*> items = AI_VALUE2(std::vector<Item*>, "inventory items", "soulstone");
|
||||
if (items.empty())
|
||||
return false;
|
||||
|
||||
Player* healer = nullptr;
|
||||
Group* group = bot->GetGroup();
|
||||
uint32 now = getMSTime();
|
||||
if (group)
|
||||
{
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
{
|
||||
Player* member = gref->GetSource();
|
||||
if (member && member->IsAlive() && botAI->IsHeal(member) && !HasSoulstoneAura(member))
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(soulstoneReservationsMutex);
|
||||
if (soulstoneReservations.count(member->GetGUID()) &&
|
||||
soulstoneReservations[member->GetGUID()] > now)
|
||||
continue; // Already being soulstoned
|
||||
|
||||
float distance = sServerFacade->GetDistance2d(bot, member);
|
||||
if (distance < 30.0f && bot->IsWithinLOSInMap(member))
|
||||
{
|
||||
healer = member;
|
||||
soulstoneReservations[healer->GetGUID()] = now + 2500; // Reserve for 2.5 seconds
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!healer)
|
||||
return false;
|
||||
|
||||
bot->SetSelection(healer->GetGUID());
|
||||
return UseItem(items[0], ObjectGuid::Empty, nullptr, healer);
|
||||
}
|
||||
|
||||
const std::vector<uint32> CastCreateFirestoneAction::firestoneSpellIds = {
|
||||
60220, // Create Firestone (Rank 7)
|
||||
27250, // Rank 5
|
||||
17953, // Rank 4
|
||||
17952, // Rank 3
|
||||
17951, // Rank 2
|
||||
6366 // Rank 1
|
||||
};
|
||||
|
||||
CastCreateFirestoneAction::CastCreateFirestoneAction(PlayerbotAI* botAI)
|
||||
: CastBuffSpellAction(botAI, "create firestone")
|
||||
{
|
||||
}
|
||||
|
||||
bool CastCreateFirestoneAction::Execute(Event event)
|
||||
{
|
||||
for (uint32 spellId : firestoneSpellIds)
|
||||
{
|
||||
if (bot->HasSpell(spellId))
|
||||
return botAI->CastSpell(spellId, bot);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CastCreateFirestoneAction::isUseful()
|
||||
{
|
||||
for (uint32 spellId : firestoneSpellIds)
|
||||
{
|
||||
if (bot->HasSpell(spellId))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
529
src/Ai/Class/Warlock/Action/WarlockActions.h
Normal file
529
src/Ai/Class/Warlock/Action/WarlockActions.h
Normal file
@@ -0,0 +1,529 @@
|
||||
/*
|
||||
* 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_WARLOCKACTIONS_H
|
||||
#define _PLAYERBOT_WARLOCKACTIONS_H
|
||||
|
||||
#include "GenericSpellActions.h"
|
||||
#include "UseItemAction.h"
|
||||
#include "InventoryAction.h"
|
||||
#include "Action.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
class Unit;
|
||||
|
||||
// Buff and Out of Combat Spells
|
||||
|
||||
class CastDemonSkinAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastDemonSkinAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "demon skin") {}
|
||||
};
|
||||
|
||||
class CastDemonArmorAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastDemonArmorAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "demon armor") {}
|
||||
};
|
||||
|
||||
class CastFelArmorAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastFelArmorAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "fel armor") {}
|
||||
};
|
||||
|
||||
class CastSoulLinkAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastSoulLinkAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "soul link", false, 5000) {}
|
||||
std::string const GetTargetName() override { return "pet target"; }
|
||||
};
|
||||
|
||||
class CreateSoulShardAction : public Action
|
||||
{
|
||||
public:
|
||||
CreateSoulShardAction(PlayerbotAI* botAI) : Action(botAI, "create soul shard") {}
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class DestroySoulShardAction : public InventoryAction
|
||||
{
|
||||
public:
|
||||
DestroySoulShardAction(PlayerbotAI* botAI) : InventoryAction(botAI, "destroy soul shard") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class CastCreateHealthstoneAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCreateHealthstoneAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "create healthstone") {}
|
||||
};
|
||||
|
||||
class CastCreateFirestoneAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCreateFirestoneAction(PlayerbotAI* botAI);
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
|
||||
private:
|
||||
static const std::vector<uint32> firestoneSpellIds;
|
||||
};
|
||||
|
||||
class CastCreateSpellstoneAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCreateSpellstoneAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "create spellstone") {}
|
||||
};
|
||||
|
||||
class CastCreateSoulstoneAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCreateSoulstoneAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "create soulstone") {}
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class UseSoulstoneSelfAction : public UseSpellItemAction
|
||||
{
|
||||
public:
|
||||
UseSoulstoneSelfAction(PlayerbotAI* botAI) : UseSpellItemAction(botAI, "soulstone") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class UseSoulstoneMasterAction : public UseSpellItemAction
|
||||
{
|
||||
public:
|
||||
UseSoulstoneMasterAction(PlayerbotAI* botAI) : UseSpellItemAction(botAI, "soulstone") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class UseSoulstoneTankAction : public UseSpellItemAction
|
||||
{
|
||||
public:
|
||||
UseSoulstoneTankAction(PlayerbotAI* botAI) : UseSpellItemAction(botAI, "soulstone") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class UseSoulstoneHealerAction : public UseSpellItemAction
|
||||
{
|
||||
public:
|
||||
UseSoulstoneHealerAction(PlayerbotAI* botAI) : UseSpellItemAction(botAI, "soulstone") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
// Summoning Spells
|
||||
|
||||
class CastSummonVoidwalkerAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastSummonVoidwalkerAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "summon voidwalker") {}
|
||||
};
|
||||
|
||||
class CastSummonFelguardAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastSummonFelguardAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "summon felguard") {}
|
||||
};
|
||||
|
||||
class CastSummonFelhunterAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastSummonFelhunterAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "summon felhunter") {}
|
||||
};
|
||||
|
||||
class CastSummonImpAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastSummonImpAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "summon imp") {}
|
||||
};
|
||||
|
||||
class CastSummonSuccubusAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastSummonSuccubusAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "summon succubus") {}
|
||||
};
|
||||
class CastFelDominationAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastFelDominationAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "fel domination") {}
|
||||
};
|
||||
|
||||
// CC and Pet Spells
|
||||
|
||||
class CastBanishOnCcAction : public CastCrowdControlSpellAction
|
||||
{
|
||||
public:
|
||||
CastBanishOnCcAction(PlayerbotAI* botAI) : CastCrowdControlSpellAction(botAI, "banish") {}
|
||||
bool isPossible() override;
|
||||
};
|
||||
|
||||
class CastFearOnCcAction : public CastCrowdControlSpellAction
|
||||
{
|
||||
public:
|
||||
CastFearOnCcAction(PlayerbotAI* botAI) : CastCrowdControlSpellAction(botAI, "fear") {}
|
||||
bool isPossible() override;
|
||||
};
|
||||
|
||||
class CastSpellLockAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastSpellLockAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "spell lock") {}
|
||||
};
|
||||
|
||||
class CastDevourMagicPurgeAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastDevourMagicPurgeAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "devour magic") {}
|
||||
|
||||
std::string const GetTargetName() override { return "current target"; }
|
||||
};
|
||||
|
||||
class CastDevourMagicCleanseAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastDevourMagicCleanseAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "devour magic cleanse") {}
|
||||
std::string const getName() override { return "cleanse magic on party"; }
|
||||
};
|
||||
|
||||
// Utility Spells
|
||||
|
||||
class CastShadowWardAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastShadowWardAction(PlayerbotAI* ai) : CastBuffSpellAction(ai, "shadow ward") {}
|
||||
};
|
||||
|
||||
class CastSoulshatterAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastSoulshatterAction(PlayerbotAI* ai) : CastSpellAction(ai, "soulshatter") {}
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class CastLifeTapAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastLifeTapAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "life tap") {}
|
||||
|
||||
std::string const GetTargetName() override { return "self target"; }
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class DemonChargeAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
DemonChargeAction(PlayerbotAI* ai) : CastSpellAction(ai, "demon charge") {}
|
||||
};
|
||||
|
||||
// Cooldown Spells
|
||||
|
||||
class CastMetamorphosisAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastMetamorphosisAction(PlayerbotAI* ai) : CastBuffSpellAction(ai, "metamorphosis") {}
|
||||
};
|
||||
|
||||
class CastDemonicEmpowermentAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastDemonicEmpowermentAction(PlayerbotAI* ai) : CastBuffSpellAction(ai, "demonic empowerment") {}
|
||||
std::string const GetTargetName() override { return "pet target"; }
|
||||
};
|
||||
|
||||
// DoT/Curse Spells
|
||||
|
||||
class CastCorruptionAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCorruptionAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "corruption", true) {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check and prevent casting if Seed of Corruption is present
|
||||
return CastAuraSpellAction::isUseful() && !botAI->HasAura("seed of corruption", GetTarget(), false, true);
|
||||
}
|
||||
};
|
||||
|
||||
class CastCorruptionOnAttackerAction : public CastDebuffSpellOnAttackerAction
|
||||
{
|
||||
public:
|
||||
CastCorruptionOnAttackerAction(PlayerbotAI* botAI) : CastDebuffSpellOnAttackerAction(botAI, "corruption", true) {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check and prevent casting if Seed of Corruption is present
|
||||
return CastAuraSpellAction::isUseful() && !botAI->HasAura("seed of corruption", GetTarget(), false, true);
|
||||
}
|
||||
};
|
||||
|
||||
class CastImmolateAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastImmolateAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "immolate", true) {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
class CastImmolateOnAttackerAction : public CastDebuffSpellOnAttackerAction
|
||||
{
|
||||
public:
|
||||
CastImmolateOnAttackerAction(PlayerbotAI* botAI) : CastDebuffSpellOnAttackerAction(botAI, "immolate", true) {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
class CastUnstableAfflictionAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastUnstableAfflictionAction(PlayerbotAI* ai) : CastDebuffSpellAction(ai, "unstable affliction", true) {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
class CastUnstableAfflictionOnAttackerAction : public CastDebuffSpellOnAttackerAction
|
||||
{
|
||||
public:
|
||||
CastUnstableAfflictionOnAttackerAction(PlayerbotAI* ai)
|
||||
: CastDebuffSpellOnAttackerAction(ai, "unstable affliction", true)
|
||||
{
|
||||
}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
class CastCurseOfAgonyAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCurseOfAgonyAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "curse of agony", true) {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
class CastCurseOfAgonyOnAttackerAction : public CastDebuffSpellOnAttackerAction
|
||||
{
|
||||
public:
|
||||
CastCurseOfAgonyOnAttackerAction(PlayerbotAI* botAI)
|
||||
: CastDebuffSpellOnAttackerAction(botAI, "curse of agony", true)
|
||||
{
|
||||
}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
class CastCurseOfTheElementsAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCurseOfTheElementsAction(PlayerbotAI* ai) : CastDebuffSpellAction(ai, "curse of the elements", true) {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
class CastCurseOfDoomAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCurseOfDoomAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "curse of doom", true, 0) {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
class CastCurseOfExhaustionAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCurseOfExhaustionAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "curse of exhaustion") {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
class CastCurseOfTonguesAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCurseOfTonguesAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "curse of tongues") {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
class CastCurseOfWeaknessAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCurseOfWeaknessAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "curse of weakness") {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
};
|
||||
|
||||
// Damage Spells
|
||||
|
||||
class CastShadowBoltAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastShadowBoltAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "shadow bolt") {}
|
||||
};
|
||||
|
||||
class CastDrainSoulAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastDrainSoulAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "drain soul") {}
|
||||
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class CastDrainManaAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastDrainManaAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "drain mana") {}
|
||||
};
|
||||
|
||||
class CastDrainLifeAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastDrainLifeAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "drain life") {}
|
||||
};
|
||||
|
||||
class CastConflagrateAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastConflagrateAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "conflagrate") {}
|
||||
};
|
||||
|
||||
class CastIncinerateAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastIncinerateAction(PlayerbotAI* ai) : CastSpellAction(ai, "incinerate") {}
|
||||
};
|
||||
|
||||
class CastHauntAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastHauntAction(PlayerbotAI* ai) : CastSpellAction(ai, "haunt") {}
|
||||
};
|
||||
|
||||
class CastSoulFireAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastSoulFireAction(PlayerbotAI* ai) : CastSpellAction(ai, "soul fire") {}
|
||||
};
|
||||
|
||||
class CastShadowburnAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastShadowburnAction(PlayerbotAI* ai) : CastSpellAction(ai, "shadowburn") {}
|
||||
};
|
||||
|
||||
class CastChaosBoltAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastChaosBoltAction(PlayerbotAI* ai) : CastSpellAction(ai, "chaos bolt") {}
|
||||
};
|
||||
|
||||
class CastSearingPainAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastSearingPainAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "searing pain") {}
|
||||
};
|
||||
|
||||
// AoE Spells
|
||||
|
||||
class CastSeedOfCorruptionAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastSeedOfCorruptionAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "seed of corruption", true, 0) {}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
|
||||
};
|
||||
|
||||
class CastSeedOfCorruptionOnAttackerAction : public CastDebuffSpellOnAttackerAction
|
||||
{
|
||||
public:
|
||||
CastSeedOfCorruptionOnAttackerAction(PlayerbotAI* botAI)
|
||||
: CastDebuffSpellOnAttackerAction(botAI, "seed of corruption", true, 0)
|
||||
{
|
||||
}
|
||||
bool isUseful() override
|
||||
{
|
||||
// Bypass TTL check
|
||||
return CastAuraSpellAction::isUseful();
|
||||
}
|
||||
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
|
||||
};
|
||||
|
||||
class CastRainOfFireAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastRainOfFireAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "rain of fire") {}
|
||||
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class CastHellfireAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastHellfireAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "hellfire") {}
|
||||
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class CastShadowflameAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastShadowflameAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "shadowflame") {}
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class CastShadowfuryAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastShadowfuryAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "shadowfury") {}
|
||||
};
|
||||
|
||||
class CastImmolationAuraAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastImmolationAuraAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "immolation aura") {}
|
||||
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class ShadowCleaveAction : public CastMeleeSpellAction
|
||||
{
|
||||
public:
|
||||
ShadowCleaveAction(PlayerbotAI* ai) : CastMeleeSpellAction(ai, "shadow cleave") {}
|
||||
};
|
||||
#endif
|
||||
153
src/Ai/Class/Warlock/Strategy/AfflictionWarlockStrategy.cpp
Normal file
153
src/Ai/Class/Warlock/Strategy/AfflictionWarlockStrategy.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "AfflictionWarlockStrategy.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
// ===== Action Node Factory =====
|
||||
class AfflictionWarlockStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
public:
|
||||
AfflictionWarlockStrategyActionNodeFactory()
|
||||
{
|
||||
creators["corruption"] = &corruption;
|
||||
creators["corruption on attacker"] = &corruption;
|
||||
creators["unstable affliction"] = &unstable_affliction;
|
||||
creators["unstable affliction on attacker"] = &unstable_affliction;
|
||||
creators["haunt"] = &haunt;
|
||||
creators["shadow bolt"] = &shadow_bolt;
|
||||
creators["drain soul"] = &drain_soul;
|
||||
creators["life tap"] = &life_tap;
|
||||
creators["shadowflame"] = &shadowflame;
|
||||
creators["seed of corruption on attacker"] = &seed_of_corruption;
|
||||
creators["seed of corruption"] = &seed_of_corruption;
|
||||
creators["rain of fire"] = &rain_of_fire;
|
||||
}
|
||||
|
||||
private:
|
||||
static ActionNode* corruption(PlayerbotAI*) { return new ActionNode("corruption", {}, {}, {}); }
|
||||
static ActionNode* corruption_on_attacker(PlayerbotAI*) { return new ActionNode("corruption on attacker", {}, {}, {}); }
|
||||
static ActionNode* unstable_affliction(PlayerbotAI*) { return new ActionNode("unstable affliction", {}, {}, {}); }
|
||||
static ActionNode* unstable_affliction_on_attacker(PlayerbotAI*) { return new ActionNode("unstable affliction on attacker", {}, {}, {}); }
|
||||
static ActionNode* haunt(PlayerbotAI*) { return new ActionNode("haunt", {}, {}, {}); }
|
||||
static ActionNode* shadow_bolt(PlayerbotAI*) { return new ActionNode("shadow bolt", {}, {}, {}); }
|
||||
static ActionNode* drain_soul(PlayerbotAI*) { return new ActionNode("drain soul", {}, {}, {}); }
|
||||
static ActionNode* life_tap(PlayerbotAI*) { return new ActionNode("life tap", {}, {}, {}); }
|
||||
static ActionNode* shadowflame(PlayerbotAI*) { return new ActionNode("shadowflame", {}, {}, {}); }
|
||||
static ActionNode* seed_of_corruption_on_attacker(PlayerbotAI*) { return new ActionNode("seed of corruption on attacker", {}, {}, {}); }
|
||||
static ActionNode* seed_of_corruption(PlayerbotAI*) { return new ActionNode("seed of corruption", {}, {}, {}); }
|
||||
static ActionNode* rain_of_fire(PlayerbotAI*) { return new ActionNode("rain of fire", {}, {}, {}); }
|
||||
};
|
||||
|
||||
// ===== Single Target Strategy =====
|
||||
AfflictionWarlockStrategy::AfflictionWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrategy(botAI)
|
||||
{
|
||||
actionNodeFactories.Add(new AfflictionWarlockStrategyActionNodeFactory());
|
||||
}
|
||||
|
||||
// ===== Default Actions =====
|
||||
std::vector<NextAction> AfflictionWarlockStrategy::getDefaultActions()
|
||||
{
|
||||
return {
|
||||
NextAction("corruption", 5.5f),
|
||||
NextAction("unstable affliction", 5.4f),
|
||||
NextAction("haunt", 5.3f),
|
||||
NextAction("shadow bolt", 5.2f),
|
||||
NextAction("shoot", 5.0f)
|
||||
};
|
||||
}
|
||||
|
||||
// ===== Trigger Initialization ===
|
||||
void AfflictionWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
GenericWarlockStrategy::InitTriggers(triggers);
|
||||
|
||||
// Main DoT triggers for high uptime
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"corruption on attacker",
|
||||
{
|
||||
NextAction("corruption on attacker", 19.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"unstable affliction on attacker",
|
||||
{
|
||||
NextAction("unstable affliction on attacker", 19.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"corruption",
|
||||
{
|
||||
NextAction("corruption", 18.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"unstable affliction",
|
||||
{
|
||||
NextAction("unstable affliction", 17.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"haunt",
|
||||
{
|
||||
NextAction("haunt", 16.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Drain Soul as execute if target is low HP // Shadow Trance for free casts
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"shadow trance",
|
||||
{
|
||||
NextAction("shadow bolt", 16.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"target critical health",
|
||||
{
|
||||
NextAction("drain soul", 15.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Life Tap glyph buff, and Life Tap as filler
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"life tap glyph buff",
|
||||
{
|
||||
NextAction("life tap", 29.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"life tap",
|
||||
{
|
||||
NextAction("life tap", 5.1f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"enemy too close for spell",
|
||||
{
|
||||
NextAction("flee", 39.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
24
src/Ai/Class/Warlock/Strategy/AfflictionWarlockStrategy.h
Normal file
24
src/Ai/Class/Warlock/Strategy/AfflictionWarlockStrategy.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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_AFFLICTIONWARLOCKSTRATEGY_H
|
||||
#define _PLAYERBOT_AFFLICTIONWARLOCKSTRATEGY_H
|
||||
|
||||
#include "GenericWarlockStrategy.h"
|
||||
#include "CombatStrategy.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class AfflictionWarlockStrategy : public GenericWarlockStrategy
|
||||
{
|
||||
public:
|
||||
AfflictionWarlockStrategy(PlayerbotAI* botAI);
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "affli"; }
|
||||
std::vector<NextAction> getDefaultActions() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
189
src/Ai/Class/Warlock/Strategy/DemonologyWarlockStrategy.cpp
Normal file
189
src/Ai/Class/Warlock/Strategy/DemonologyWarlockStrategy.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "DemonologyWarlockStrategy.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
// ===== Action Node Factory =====
|
||||
class DemonologyWarlockStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
public:
|
||||
DemonologyWarlockStrategyActionNodeFactory()
|
||||
{
|
||||
creators["metamorphosis"] = &metamorphosis;
|
||||
creators["demonic empowerment"] = &demonic_empowerment;
|
||||
creators["corruption"] = &corruption;
|
||||
creators["corruption on attacker"] = &corruption_on_attacker;
|
||||
creators["immolate"] = &immolate;
|
||||
creators["immolate on attacker"] = &immolate_on_attacker;
|
||||
creators["incinerate"] = &incinerate;
|
||||
creators["soul fire"] = &soul_fire;
|
||||
creators["shadow bolt"] = &shadow_bolt;
|
||||
creators["life tap"] = &life_tap;
|
||||
creators["immolation aura"] = &immolation_aura;
|
||||
creators["shadowflame"] = &shadowflame;
|
||||
creators["seed of corruption on attacker"] = &seed_of_corruption_on_attacker;
|
||||
creators["seed of corruption"] = &seed_of_corruption;
|
||||
creators["rain of fire"] = &rain_of_fire;
|
||||
creators["demon charge"] = &demon_charge;
|
||||
}
|
||||
|
||||
private:
|
||||
static ActionNode* metamorphosis(PlayerbotAI*) { return new ActionNode("metamorphosis", {}, {}, {}); }
|
||||
static ActionNode* demonic_empowerment(PlayerbotAI*) { return new ActionNode("demonic empowerment", {}, {}, {}); }
|
||||
static ActionNode* corruption(PlayerbotAI*) { return new ActionNode("corruption", {}, {}, {}); }
|
||||
static ActionNode* corruption_on_attacker(PlayerbotAI*) { return new ActionNode("corruption on attacker", {}, {}, {}); }
|
||||
static ActionNode* immolate(PlayerbotAI*) { return new ActionNode("immolate", {}, {}, {}); }
|
||||
static ActionNode* immolate_on_attacker(PlayerbotAI*) { return new ActionNode("immolate on attacker", {}, {}, {}); }
|
||||
static ActionNode* incinerate(PlayerbotAI*) { return new ActionNode("incinerate", {}, {}, {}); }
|
||||
static ActionNode* soul_fire(PlayerbotAI*) { return new ActionNode("soul fire", {}, {}, {}); }
|
||||
static ActionNode* shadow_bolt(PlayerbotAI*) { return new ActionNode("shadow bolt", {}, {}, {}); }
|
||||
static ActionNode* life_tap(PlayerbotAI*) { return new ActionNode("life tap", {}, {}, {}); }
|
||||
static ActionNode* immolation_aura(PlayerbotAI*) { return new ActionNode("immolation aura", {}, {}, {}); }
|
||||
static ActionNode* shadowflame(PlayerbotAI*) { return new ActionNode("shadowflame", {}, {}, {}); }
|
||||
static ActionNode* seed_of_corruption_on_attacker(PlayerbotAI*) { return new ActionNode("seed of corruption on attacker", {}, {}, {}); }
|
||||
static ActionNode* seed_of_corruption(PlayerbotAI*) { return new ActionNode("seed of corruption", {}, {}, {}); }
|
||||
static ActionNode* rain_of_fire(PlayerbotAI*) { return new ActionNode("rain of fire", {}, {}, {}); }
|
||||
static ActionNode* demon_charge(PlayerbotAI*) { return new ActionNode("demon charge", {}, {}, {}); }
|
||||
};
|
||||
|
||||
// ===== Single Target Strategy =====
|
||||
DemonologyWarlockStrategy::DemonologyWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrategy(botAI)
|
||||
{
|
||||
actionNodeFactories.Add(new DemonologyWarlockStrategyActionNodeFactory());
|
||||
}
|
||||
|
||||
// ===== Default Actions =====
|
||||
std::vector<NextAction> DemonologyWarlockStrategy::getDefaultActions()
|
||||
{
|
||||
return {
|
||||
NextAction("corruption", 5.5f),
|
||||
NextAction("immolate", 5.4f),
|
||||
NextAction("shadow bolt", 5.3f),
|
||||
NextAction("incinerate", 5.2f),
|
||||
NextAction("shoot", 5.0f) };
|
||||
}
|
||||
|
||||
// ===== Trigger Initialization ===
|
||||
void DemonologyWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
GenericWarlockStrategy::InitTriggers(triggers);
|
||||
|
||||
// High priority cooldowns
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"metamorphosis",
|
||||
{
|
||||
NextAction("metamorphosis", 28.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"demonic empowerment",
|
||||
{
|
||||
NextAction("demonic empowerment", 28.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Main DoT triggers for high uptime
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"corruption on attacker",
|
||||
{
|
||||
NextAction("corruption on attacker", 19.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"immolate on attacker",
|
||||
{
|
||||
NextAction("immolate on attacker", 19.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"corruption",
|
||||
{
|
||||
NextAction("corruption", 18.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"immolate",
|
||||
{
|
||||
NextAction("immolate", 17.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Procs
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"decimation",
|
||||
{
|
||||
NextAction("soul fire", 17.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"molten core",
|
||||
{
|
||||
NextAction("incinerate", 16.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Life Tap glyph buff, and Life Tap as filler
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"life tap glyph buff",
|
||||
{
|
||||
NextAction("life tap", 29.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"life tap",
|
||||
{
|
||||
NextAction("life tap", 5.1f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"meta melee flee check",
|
||||
{
|
||||
NextAction("flee", 39.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Combat strategy to run to melee for Immolation Aura
|
||||
// Enabled by default for the Demonology spec
|
||||
// To enable, type "co +meta melee"
|
||||
// To disable, type "co -meta melee"
|
||||
MetaMeleeAoeStrategy::MetaMeleeAoeStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {}
|
||||
|
||||
void MetaMeleeAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"immolation aura active",
|
||||
{
|
||||
NextAction("reach melee", 25.5f),
|
||||
NextAction("demon charge", 25.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
32
src/Ai/Class/Warlock/Strategy/DemonologyWarlockStrategy.h
Normal file
32
src/Ai/Class/Warlock/Strategy/DemonologyWarlockStrategy.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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_DEMONOLOGYWARLOCKSTRATEGY_H
|
||||
#define _PLAYERBOT_DEMONOLOGYWARLOCKSTRATEGY_H
|
||||
|
||||
#include "GenericWarlockStrategy.h"
|
||||
#include "CombatStrategy.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class DemonologyWarlockStrategy : public GenericWarlockStrategy
|
||||
{
|
||||
public:
|
||||
DemonologyWarlockStrategy(PlayerbotAI* botAI);
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "demo"; }
|
||||
std::vector<NextAction> getDefaultActions() override;
|
||||
};
|
||||
|
||||
class MetaMeleeAoeStrategy : public CombatStrategy
|
||||
{
|
||||
public:
|
||||
MetaMeleeAoeStrategy(PlayerbotAI* botAI);
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "meta melee"; }
|
||||
};
|
||||
#endif
|
||||
153
src/Ai/Class/Warlock/Strategy/DestructionWarlockStrategy.cpp
Normal file
153
src/Ai/Class/Warlock/Strategy/DestructionWarlockStrategy.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "DestructionWarlockStrategy.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
// ===== Action Node Factory =====
|
||||
class DestructionWarlockStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
public:
|
||||
DestructionWarlockStrategyActionNodeFactory()
|
||||
{
|
||||
creators["immolate"] = &immolate;
|
||||
creators["conflagrate"] = &conflagrate;
|
||||
creators["chaos bolt"] = &chaos_bolt;
|
||||
creators["incinerate"] = &incinerate;
|
||||
creators["corruption"] = &corruption;
|
||||
creators["corruption on attacker"] = &corruption_on_attacker;
|
||||
creators["shadow bolt"] = &shadow_bolt;
|
||||
creators["shadowburn"] = &shadowburn;
|
||||
creators["life tap"] = &life_tap;
|
||||
creators["shadowfury"] = &shadowfury;
|
||||
creators["shadowflame"] = &shadowflame;
|
||||
creators["seed of corruption"] = &seed_of_corruption;
|
||||
creators["seed of corruption on attacker"] = &seed_of_corruption;
|
||||
creators["rain of fire"] = &rain_of_fire;
|
||||
}
|
||||
|
||||
private:
|
||||
static ActionNode* immolate(PlayerbotAI*) { return new ActionNode("immolate", {}, {}, {}); }
|
||||
static ActionNode* conflagrate(PlayerbotAI*) { return new ActionNode("conflagrate", {}, {}, {}); }
|
||||
static ActionNode* chaos_bolt(PlayerbotAI*) { return new ActionNode("chaos bolt", {}, {}, {}); }
|
||||
static ActionNode* incinerate(PlayerbotAI*) { return new ActionNode("incinerate", {}, {}, {}); }
|
||||
static ActionNode* corruption(PlayerbotAI*) { return new ActionNode("corruption", {}, {}, {}); }
|
||||
static ActionNode* corruption_on_attacker(PlayerbotAI*) { return new ActionNode("corruption on attacker", {}, {}, {}); }
|
||||
static ActionNode* shadow_bolt(PlayerbotAI*) { return new ActionNode("shadow bolt", {}, {}, {}); }
|
||||
static ActionNode* shadowburn(PlayerbotAI*) { return new ActionNode("shadowburn", {}, {}, {}); }
|
||||
static ActionNode* life_tap(PlayerbotAI*) { return new ActionNode("life tap", {}, {}, {}); }
|
||||
static ActionNode* shadowfury(PlayerbotAI*) { return new ActionNode("shadowfury", {}, {}, {}); }
|
||||
static ActionNode* shadowflame(PlayerbotAI*) { return new ActionNode("shadowflame", {}, {}, {}); }
|
||||
static ActionNode* seed_of_corruption(PlayerbotAI*) { return new ActionNode("seed of corruption", {}, {}, {}); }
|
||||
static ActionNode* seed_of_corruption_on_attacker(PlayerbotAI*) { return new ActionNode("seed of corruption on attacker", {}, {}, {}); }
|
||||
static ActionNode* rain_of_fire(PlayerbotAI*) { return new ActionNode("rain of fire", {}, {}, {}); }
|
||||
};
|
||||
|
||||
// ===== Single Target Strategy =====
|
||||
DestructionWarlockStrategy::DestructionWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrategy(botAI)
|
||||
{
|
||||
actionNodeFactories.Add(new DestructionWarlockStrategyActionNodeFactory());
|
||||
}
|
||||
|
||||
// ===== Default Actions =====
|
||||
std::vector<NextAction> DestructionWarlockStrategy::getDefaultActions()
|
||||
{
|
||||
return {
|
||||
NextAction("immolate", 5.9f),
|
||||
NextAction("conflagrate", 5.8f),
|
||||
NextAction("chaos bolt", 5.7f),
|
||||
NextAction("incinerate", 5.6f),
|
||||
NextAction("corruption", 5.3f), // Note: Corruption and Shadow Bolt won't be used after the character learns Incinerate at level 64
|
||||
NextAction("shadow bolt", 5.2f),
|
||||
NextAction("shoot", 5.0f)
|
||||
};
|
||||
}
|
||||
|
||||
// ===== Trigger Initialization ===
|
||||
void DestructionWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
GenericWarlockStrategy::InitTriggers(triggers);
|
||||
|
||||
// Main DoT triggers for high uptime + high priority cooldowns
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"immolate",
|
||||
{
|
||||
NextAction("immolate", 20.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"conflagrate",
|
||||
{
|
||||
NextAction("conflagrate", 19.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"chaos bolt",
|
||||
{
|
||||
NextAction("chaos bolt", 19.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Note: Corruption won't be used after the character learns Incinerate at level 64
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"corruption on attacker",
|
||||
{
|
||||
NextAction("corruption on attacker", 5.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"corruption",
|
||||
{
|
||||
NextAction("corruption", 5.4f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Shadowburn as execute if target is low HP
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"target critical health",
|
||||
{
|
||||
NextAction("shadowburn", 18.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Life Tap glyph buff, and Life Tap as filler
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"life tap glyph buff",
|
||||
{
|
||||
NextAction("life tap", 29.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"life tap",
|
||||
{
|
||||
NextAction("life tap", 5.1f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"enemy too close for spell",
|
||||
{
|
||||
NextAction("flee", 39.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
24
src/Ai/Class/Warlock/Strategy/DestructionWarlockStrategy.h
Normal file
24
src/Ai/Class/Warlock/Strategy/DestructionWarlockStrategy.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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_DESTRUCTIONWARLOCKSTRATEGY_H
|
||||
#define _PLAYERBOT_DESTRUCTIONWARLOCKSTRATEGY_H
|
||||
|
||||
#include "GenericWarlockStrategy.h"
|
||||
#include "CombatStrategy.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class DestructionWarlockStrategy : public GenericWarlockStrategy
|
||||
{
|
||||
public:
|
||||
DestructionWarlockStrategy(PlayerbotAI* botAI);
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "destro"; }
|
||||
std::vector<NextAction> getDefaultActions() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "GenericWarlockNonCombatStrategy.h"
|
||||
#include "AiFactory.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
class GenericWarlockNonCombatStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
public:
|
||||
GenericWarlockNonCombatStrategyActionNodeFactory()
|
||||
{
|
||||
creators["fel armor"] = &fel_armor;
|
||||
creators["demon armor"] = &demon_armor;
|
||||
creators["summon voidwalker"] = &summon_voidwalker;
|
||||
creators["summon felguard"] = &summon_felguard;
|
||||
creators["summon succubus"] = &summon_succubus;
|
||||
creators["summon felhunter"] = &summon_felhunter;
|
||||
}
|
||||
|
||||
// Pet skills are setup in pass-through fashion, so if one fails, it attempts to cast the next one
|
||||
// The order goes Felguard -> Felhunter -> Succubus -> Voidwalker -> Imp
|
||||
// Pets are summoned based on the non-combat strategy you have active, the warlock's level, and if they have a soul shard available
|
||||
|
||||
private:
|
||||
static ActionNode* fel_armor([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("fel armor",
|
||||
/*P*/ {},
|
||||
/*A*/ { NextAction("demon armor") },
|
||||
/*C*/ {});
|
||||
}
|
||||
|
||||
static ActionNode* demon_armor([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("demon armor",
|
||||
/*P*/ {},
|
||||
/*A*/ { NextAction("demon skin") },
|
||||
/*C*/ {});
|
||||
}
|
||||
static ActionNode* summon_voidwalker([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("summon voidwalker",
|
||||
/*P*/ {},
|
||||
/*A*/ { NextAction("summon imp") },
|
||||
/*C*/ {});
|
||||
}
|
||||
static ActionNode* summon_succubus([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("summon succubus",
|
||||
/*P*/ {},
|
||||
/*A*/ { NextAction("summon voidwalker") },
|
||||
/*C*/ {});
|
||||
}
|
||||
static ActionNode* summon_felhunter([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("summon felhunter",
|
||||
/*P*/ {},
|
||||
/*A*/ { NextAction("summon succubus") },
|
||||
/*C*/ {});
|
||||
}
|
||||
static ActionNode* summon_felguard([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("summon felguard",
|
||||
/*P*/ {},
|
||||
/*A*/ { NextAction("summon felhunter") },
|
||||
/*C*/ {});
|
||||
}
|
||||
};
|
||||
|
||||
GenericWarlockNonCombatStrategy::GenericWarlockNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI)
|
||||
{
|
||||
actionNodeFactories.Add(new GenericWarlockNonCombatStrategyActionNodeFactory());
|
||||
}
|
||||
|
||||
void GenericWarlockNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
NonCombatStrategy::InitTriggers(triggers);
|
||||
triggers.push_back(new TriggerNode("has pet", { NextAction("toggle pet spell", 60.0f) }));
|
||||
triggers.push_back(new TriggerNode("new pet", { NextAction("set pet stance", 60.0f) }));
|
||||
triggers.push_back(new TriggerNode("no pet", { NextAction("fel domination", 30.0f) }));
|
||||
triggers.push_back(new TriggerNode("no soul shard", { NextAction("create soul shard", 60.0f) }));
|
||||
triggers.push_back(new TriggerNode("too many soul shards", { NextAction("destroy soul shard", 60.0f) }));
|
||||
triggers.push_back(new TriggerNode("soul link", { NextAction("soul link", 28.0f) }));
|
||||
triggers.push_back(new TriggerNode("demon armor", { NextAction("fel armor", 27.0f) }));
|
||||
triggers.push_back(new TriggerNode("no healthstone", { NextAction("create healthstone", 26.0f) }));
|
||||
triggers.push_back(new TriggerNode("no soulstone", { NextAction("create soulstone", 25.0f) }));
|
||||
triggers.push_back(new TriggerNode("life tap", { NextAction("life tap", 23.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for summoning a Imp
|
||||
// Enabled by default for the Destruction spec
|
||||
// To enable, type "nc +imp"
|
||||
// To disable, type "nc -imp"
|
||||
SummonImpStrategy::SummonImpStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void SummonImpStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", { NextAction("summon imp", 29.0f) }));
|
||||
triggers.push_back(new TriggerNode("wrong pet", { NextAction("summon imp", 29.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for summoning a Voidwalker
|
||||
// Disabled by default
|
||||
// To enable, type "nc +voidwalker"
|
||||
// To disable, type "nc -voidwalker"
|
||||
SummonVoidwalkerStrategy::SummonVoidwalkerStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void SummonVoidwalkerStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", { NextAction("summon voidwalker", 29.0f) }));
|
||||
triggers.push_back(new TriggerNode("wrong pet", { NextAction("summon voidwalker", 29.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for summoning a Succubus
|
||||
// Disabled by default
|
||||
// To enable, type "nc +succubus"
|
||||
// To disable, type "nc -succubus"
|
||||
SummonSuccubusStrategy::SummonSuccubusStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void SummonSuccubusStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", { NextAction("summon succubus", 29.0f) }));
|
||||
triggers.push_back(new TriggerNode("wrong pet", { NextAction("summon succubus", 29.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for summoning a Felhunter
|
||||
// Enabled by default for the Affliction spec
|
||||
// To enable, type "nc +felhunter"
|
||||
// To disable, type "nc -felhunter"
|
||||
SummonFelhunterStrategy::SummonFelhunterStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void SummonFelhunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", { NextAction("summon felhunter", 29.0f) }));
|
||||
triggers.push_back(new TriggerNode("wrong pet", { NextAction("summon felhunter", 29.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for summoning a Felguard
|
||||
// Enabled by default for the Demonology spec
|
||||
// To enable, type "nc +felguard"
|
||||
// To disable, type "nc -felguard"
|
||||
SummonFelguardStrategy::SummonFelguardStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void SummonFelguardStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", { NextAction("summon felguard", 29.0f) }));
|
||||
triggers.push_back(new TriggerNode("wrong pet", { NextAction("summon felguard", 29.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for selecting themselves to receive soulstone
|
||||
// Disabled by default
|
||||
// To enable, type "nc +ss self"
|
||||
// To disable, type "nc -ss self"
|
||||
SoulstoneSelfStrategy::SoulstoneSelfStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void SoulstoneSelfStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("soulstone", { NextAction("soulstone self", 24.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for selecting the master to receive soulstone
|
||||
// Disabled by default
|
||||
// To enable, type "nc +ss master"
|
||||
// To disable, type "nc -ss master"
|
||||
SoulstoneMasterStrategy::SoulstoneMasterStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void SoulstoneMasterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("soulstone", { NextAction("soulstone master", 24.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for selecting tanks to receive soulstone
|
||||
// Disabled by default
|
||||
// To enable, type "nc +ss tank"
|
||||
// To disable, type "nc -ss tank"
|
||||
SoulstoneTankStrategy::SoulstoneTankStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void SoulstoneTankStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("soulstone", { NextAction("soulstone tank", 24.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for selecting healers to receive soulstone
|
||||
// Disabled by default
|
||||
// To enable, type "nc +ss healer"
|
||||
// To disable, type "nc -ss healer"
|
||||
SoulstoneHealerStrategy::SoulstoneHealerStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void SoulstoneHealerStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("soulstone", { NextAction("soulstone healer", 24.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for using Spellstone
|
||||
// Enabled by default for Affliction and Demonology specs
|
||||
// To enable, type "nc +spellstone"
|
||||
// To disable, type "nc -spellstone"
|
||||
UseSpellstoneStrategy::UseSpellstoneStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void UseSpellstoneStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no spellstone", { NextAction("create spellstone", 24.0f) }));
|
||||
triggers.push_back(new TriggerNode("spellstone", { NextAction("spellstone", 24.0f) }));
|
||||
}
|
||||
|
||||
// Non-combat strategy for using Firestone
|
||||
// Enabled by default for the Destruction spec
|
||||
// To enable, type "nc +firestone"
|
||||
// To disable, type "nc -firestone"
|
||||
UseFirestoneStrategy::UseFirestoneStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
|
||||
void UseFirestoneStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no firestone", { NextAction("create firestone", 24.0f) }));
|
||||
triggers.push_back(new TriggerNode("firestone", { NextAction("firestone", 24.0f) }));
|
||||
}
|
||||
132
src/Ai/Class/Warlock/Strategy/GenericWarlockNonCombatStrategy.h
Normal file
132
src/Ai/Class/Warlock/Strategy/GenericWarlockNonCombatStrategy.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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_GENERICWARLOCKNONCOMBATSTRATEGY_H
|
||||
#define _PLAYERBOT_GENERICWARLOCKNONCOMBATSTRATEGY_H
|
||||
|
||||
#include "NonCombatStrategy.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class GenericWarlockNonCombatStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
GenericWarlockNonCombatStrategy(PlayerbotAI* botAI);
|
||||
|
||||
std::string const getName() override { return "nc"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SummonImpStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SummonImpStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "imp"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SummonVoidwalkerStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SummonVoidwalkerStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "voidwalker"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SummonSuccubusStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SummonSuccubusStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "succubus"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SummonFelhunterStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SummonFelhunterStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "felhunter"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SummonFelguardStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SummonFelguardStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "felguard"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SoulstoneSelfStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SoulstoneSelfStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "ss self"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SoulstoneMasterStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SoulstoneMasterStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "ss master"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SoulstoneTankStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SoulstoneTankStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "ss tank"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SoulstoneHealerStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SoulstoneHealerStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "ss healer"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class UseSpellstoneStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
UseSpellstoneStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "spellstone"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class UseFirestoneStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
UseFirestoneStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "firestone"; }
|
||||
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
261
src/Ai/Class/Warlock/Strategy/GenericWarlockStrategy.cpp
Normal file
261
src/Ai/Class/Warlock/Strategy/GenericWarlockStrategy.cpp
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "GenericWarlockStrategy.h"
|
||||
#include "Strategy.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
class GenericWarlockStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
public:
|
||||
GenericWarlockStrategyActionNodeFactory()
|
||||
{
|
||||
creators["banish on cc"] = &banish_on_cc;
|
||||
creators["fear on cc"] = &fear_on_cc;
|
||||
creators["spell lock"] = &spell_lock;
|
||||
creators["devour magic purge"] = &devour_magic_purge;
|
||||
creators["devour magic cleanse"] = &devour_magic_cleanse;
|
||||
}
|
||||
|
||||
private:
|
||||
static ActionNode* banish_on_cc(PlayerbotAI*) { return new ActionNode("banish on cc", {}, {}, {}); }
|
||||
static ActionNode* fear_on_cc(PlayerbotAI*) { return new ActionNode("fear on cc", {}, {}, {}); }
|
||||
static ActionNode* spell_lock(PlayerbotAI*) { return new ActionNode("spell lock", {}, {}, {}); }
|
||||
static ActionNode* devour_magic_purge(PlayerbotAI*) { return new ActionNode("devour magic purge", {}, {}, {}); }
|
||||
static ActionNode* devour_magic_cleanse(PlayerbotAI*) { return new ActionNode("devour magic cleanse", {}, {}, {}); }
|
||||
};
|
||||
|
||||
GenericWarlockStrategy::GenericWarlockStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI)
|
||||
{
|
||||
actionNodeFactories.Add(new GenericWarlockStrategyActionNodeFactory());
|
||||
}
|
||||
|
||||
std::vector<NextAction> GenericWarlockStrategy::getDefaultActions()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void GenericWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
CombatStrategy::InitTriggers(triggers);
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"low mana",
|
||||
{
|
||||
NextAction("life tap", 95.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"medium threat",
|
||||
{
|
||||
NextAction("soulshatter", 55.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"spell lock",
|
||||
{
|
||||
NextAction("spell lock", 40.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"no soul shard",
|
||||
{
|
||||
NextAction("create soul shard", 60.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"too many soul shards",
|
||||
{
|
||||
NextAction("destroy soul shard", 60.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"devour magic purge",
|
||||
{
|
||||
NextAction("devour magic purge", 50.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"devour magic cleanse",
|
||||
{
|
||||
NextAction("devour magic cleanse", 50.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// ===== AoE Strategy, 3+ enemies =====
|
||||
|
||||
void AoEWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"medium aoe",
|
||||
{
|
||||
NextAction("immolation aura", 26.0f),
|
||||
NextAction("shadowfury", 23.0f),
|
||||
NextAction("shadowflame", 22.5f),
|
||||
NextAction("seed of corruption on attacker", 22.0f),
|
||||
NextAction("seed of corruption", 21.5f),
|
||||
NextAction("rain of fire", 21.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("rain of fire channel check",
|
||||
{
|
||||
NextAction("cancel channel", 21.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void WarlockBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
// Placeholder for future boost triggers
|
||||
}
|
||||
|
||||
void WarlockPetStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
// Placeholder for future pet triggers
|
||||
}
|
||||
|
||||
void WarlockCcStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"banish",
|
||||
{
|
||||
NextAction("banish on cc", 33.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"fear",
|
||||
{
|
||||
NextAction("fear on cc", 32.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Combat strategy for using Curse of Agony
|
||||
// Enabled by default for the Affliction spec
|
||||
// To enable, type "co +curse of agony"
|
||||
// To disable, type "co -curse of agony"
|
||||
void WarlockCurseOfAgonyStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"curse of agony on attacker",
|
||||
{
|
||||
NextAction("curse of agony on attacker", 18.5f)
|
||||
}
|
||||
)
|
||||
);
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"curse of agony",
|
||||
{
|
||||
NextAction("curse of agony", 17.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Combat strategy for using Curse of the Elements
|
||||
// Enabled by default for the Destruction spec
|
||||
// To enable, type "co +curse of elements"
|
||||
// To disable, type "co -curse of elements"
|
||||
void WarlockCurseOfTheElementsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"curse of the elements",
|
||||
{
|
||||
NextAction("curse of the elements", 29.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Combat strategy for using Curse of Doom
|
||||
// Disabled by default
|
||||
// To enable, type "co +curse of doom"
|
||||
// To disable, type "co -curse of doom"
|
||||
void WarlockCurseOfDoomStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"curse of doom",
|
||||
{
|
||||
NextAction("curse of doom", 29.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Combat strategy for using Curse of Exhaustion
|
||||
// Disabled by default
|
||||
// To enable, type "co +curse of exhaustion"
|
||||
// To disable, type "co -curse of exhaustion"
|
||||
void WarlockCurseOfExhaustionStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"curse of exhaustion",
|
||||
{
|
||||
NextAction("curse of exhaustion", 29.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Combat strategy for using Curse of Tongues
|
||||
// Disabled by default
|
||||
// To enable, type "co +curse of tongues"
|
||||
// To disable, type "co -curse of tongues"
|
||||
void WarlockCurseOfTonguesStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"curse of tongues",
|
||||
{
|
||||
NextAction("curse of tongues", 29.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Combat strategy for using Curse of Weakness
|
||||
// Disabled by default
|
||||
// To enable, type "co +curse of weakness"
|
||||
// To disable, type "co -curse of weakness"
|
||||
void WarlockCurseOfWeaknessStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode(
|
||||
"curse of weakness",
|
||||
{
|
||||
NextAction("curse of weakness", 29.0f)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
114
src/Ai/Class/Warlock/Strategy/GenericWarlockStrategy.h
Normal file
114
src/Ai/Class/Warlock/Strategy/GenericWarlockStrategy.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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_GENERICWARLOCKSTRATEGY_H
|
||||
#define _PLAYERBOT_GENERICWARLOCKSTRATEGY_H
|
||||
|
||||
#include "CombatStrategy.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class GenericWarlockStrategy : public CombatStrategy
|
||||
{
|
||||
public:
|
||||
GenericWarlockStrategy(PlayerbotAI* botAI);
|
||||
|
||||
std::string const getName() override { return "warlock"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::vector<NextAction> getDefaultActions() override;
|
||||
uint32 GetType() const override { return CombatStrategy::GetType() | STRATEGY_TYPE_RANGED | STRATEGY_TYPE_DPS; }
|
||||
};
|
||||
|
||||
class AoEWarlockStrategy : public CombatStrategy
|
||||
{
|
||||
public:
|
||||
AoEWarlockStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {}
|
||||
|
||||
std::string const getName() override { return "aoe"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class WarlockBoostStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
WarlockBoostStrategy(PlayerbotAI* botAI) : Strategy(botAI){};
|
||||
|
||||
std::string const getName() override { return "boost"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class WarlockPetStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
WarlockPetStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
std::string const getName() override { return "pet"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class WarlockCcStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
WarlockCcStrategy(PlayerbotAI* botAI) : Strategy(botAI){};
|
||||
|
||||
std::string const getName() override { return "cc"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class WarlockCurseOfAgonyStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
WarlockCurseOfAgonyStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
std::string const getName() override { return "curse of agony"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class WarlockCurseOfTheElementsStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
WarlockCurseOfTheElementsStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
std::string const getName() override { return "curse of elements"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class WarlockCurseOfDoomStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
WarlockCurseOfDoomStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
std::string const getName() override { return "curse of doom"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class WarlockCurseOfExhaustionStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
WarlockCurseOfExhaustionStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
std::string const getName() override { return "curse of exhaustion"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class WarlockCurseOfTonguesStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
WarlockCurseOfTonguesStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
std::string const getName() override { return "curse of tongues"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class WarlockCurseOfWeaknessStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
WarlockCurseOfWeaknessStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
std::string const getName() override { return "curse of weakness"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
47
src/Ai/Class/Warlock/Strategy/TankWarlockStrategy.cpp
Normal file
47
src/Ai/Class/Warlock/Strategy/TankWarlockStrategy.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "TankWarlockStrategy.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
// Combat strategy for a Warlock Tank, for certain bosses like Twin Emperors
|
||||
// Priority is set to spam Searing Pain and use Shadow Ward on CD
|
||||
// Disabled by default
|
||||
// To enable, type "co +tank"
|
||||
// To disable, type "co -tank"
|
||||
|
||||
// ===== Action Node Factory =====
|
||||
class TankWarlockStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
public:
|
||||
TankWarlockStrategyActionNodeFactory()
|
||||
{
|
||||
creators["shadow ward"] = &shadow_ward;
|
||||
creators["searing pain"] = &searing_pain;
|
||||
}
|
||||
|
||||
private:
|
||||
static ActionNode* shadow_ward(PlayerbotAI*) { return new ActionNode("shadow ward", {}, {}, {}); }
|
||||
static ActionNode* searing_pain(PlayerbotAI*) { return new ActionNode("searing pain", {}, {}, {}); }
|
||||
};
|
||||
|
||||
// ===== Warlock Tank Combat Strategy =====
|
||||
TankWarlockStrategy::TankWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrategy(botAI)
|
||||
{
|
||||
actionNodeFactories.Add(new TankWarlockStrategyActionNodeFactory());
|
||||
}
|
||||
|
||||
std::vector<NextAction> TankWarlockStrategy::getDefaultActions()
|
||||
{
|
||||
// Shadow Ward is the highest priority, Searing Pain next.
|
||||
return {
|
||||
NextAction("shadow ward", 27.5f),
|
||||
NextAction("searing pain", 27.0f)
|
||||
};
|
||||
}
|
||||
|
||||
void TankWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
}
|
||||
23
src/Ai/Class/Warlock/Strategy/TankWarlockStrategy.h
Normal file
23
src/Ai/Class/Warlock/Strategy/TankWarlockStrategy.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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_TANKWARLOCKSTRATEGY_H
|
||||
#define _PLAYERBOT_TANKWARLOCKSTRATEGY_H
|
||||
|
||||
#include "GenericWarlockStrategy.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class TankWarlockStrategy : public GenericWarlockStrategy
|
||||
{
|
||||
public:
|
||||
TankWarlockStrategy(PlayerbotAI* botAI);
|
||||
|
||||
std::string const getName() override { return "tank"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::vector<NextAction> getDefaultActions() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
265
src/Ai/Class/Warlock/Trigger/WarlockTriggers.cpp
Normal file
265
src/Ai/Class/Warlock/Trigger/WarlockTriggers.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "WarlockTriggers.h"
|
||||
#include "GenericTriggers.h"
|
||||
#include "Playerbots.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Player.h"
|
||||
|
||||
static const uint32 SOUL_SHARD_ITEM_ID = 6265;
|
||||
|
||||
uint32 GetSoulShardCount(Player* bot)
|
||||
{
|
||||
return bot->GetItemCount(SOUL_SHARD_ITEM_ID, false); // false = only bags
|
||||
}
|
||||
|
||||
// List of all Soulstone item IDs
|
||||
static const std::vector<uint32> soulstoneItemIds = {
|
||||
5232, // Minor Soulstone
|
||||
16892, // Lesser Soulstone
|
||||
16893, // Soulstone
|
||||
16895, // Greater Soulstone
|
||||
16896, // Major Soulstone
|
||||
22116, // Master Soulstone
|
||||
36895 // Demonic Soulstone
|
||||
};
|
||||
|
||||
uint32 GetSoulstoneCount(Player* bot)
|
||||
{
|
||||
uint32 count = 0;
|
||||
for (uint32 id : soulstoneItemIds)
|
||||
count += bot->GetItemCount(id, false); // false = only bags
|
||||
return count;
|
||||
}
|
||||
|
||||
bool SpellstoneTrigger::IsActive() { return BuffTrigger::IsActive() && AI_VALUE2(uint32, "item count", getName()) > 0; }
|
||||
|
||||
bool FirestoneTrigger::IsActive() { return BuffTrigger::IsActive() && AI_VALUE2(uint32, "item count", getName()) > 0; }
|
||||
|
||||
bool WarlockConjuredItemTrigger::IsActive()
|
||||
{
|
||||
return ItemCountTrigger::IsActive() && AI_VALUE2(uint32, "item count", "soul shard") > 0;
|
||||
}
|
||||
|
||||
bool OutOfSoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot()) == 0; }
|
||||
|
||||
bool TooManySoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot()) >= 26; }
|
||||
|
||||
bool OutOfSoulstoneTrigger::IsActive() { return GetSoulstoneCount(botAI->GetBot()) == 0; }
|
||||
|
||||
// Checks if the target marked with the moon icon can be banished
|
||||
bool BanishTrigger::IsActive()
|
||||
{
|
||||
Unit* ccTarget = context->GetValue<Unit*>("cc target", "banish")->Get();
|
||||
Unit* moonTarget = context->GetValue<Unit*>("rti cc target")->Get();
|
||||
return ccTarget && moonTarget && ccTarget == moonTarget && HasCcTargetTrigger::IsActive();
|
||||
}
|
||||
|
||||
// Checks if the target marked with the moon icon can be feared
|
||||
bool FearTrigger::IsActive()
|
||||
{
|
||||
Unit* ccTarget = context->GetValue<Unit*>("cc target", "fear")->Get();
|
||||
Unit* moonTarget = context->GetValue<Unit*>("rti cc target")->Get();
|
||||
return ccTarget && moonTarget && ccTarget == moonTarget && HasCcTargetTrigger::IsActive();
|
||||
}
|
||||
|
||||
bool DemonArmorTrigger::IsActive()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
return !botAI->HasAura("demon skin", target) && !botAI->HasAura("demon armor", target) &&
|
||||
!botAI->HasAura("fel armor", target);
|
||||
}
|
||||
|
||||
bool SoulLinkTrigger::IsActive()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
return !botAI->HasAura("soul link", target);
|
||||
}
|
||||
|
||||
bool DemonicEmpowermentTrigger::IsActive()
|
||||
{
|
||||
Pet* pet = bot->GetPet();
|
||||
if (!pet)
|
||||
return false;
|
||||
return !botAI->HasAura("demonic empowerment", pet);
|
||||
}
|
||||
|
||||
bool DecimationTrigger::IsActive()
|
||||
{
|
||||
Aura* aura = botAI->GetAura(getName(), GetTarget(), false, true);
|
||||
return aura && aura->GetDuration() > 3000;
|
||||
}
|
||||
|
||||
// Checks if the bot's mana is below 85% and health is above a low health threshold
|
||||
bool LifeTapTrigger::IsActive()
|
||||
{
|
||||
if (AI_VALUE2(uint8, "health", "self target") <= sPlayerbotAIConfig->lowHealth)
|
||||
return false;
|
||||
|
||||
if (!AI_VALUE2(bool, "has mana", "self target"))
|
||||
return false;
|
||||
if (AI_VALUE2(uint8, "mana", "self target") >= 85)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks if the Life Tap Glyph buff is active
|
||||
bool LifeTapGlyphBuffTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->HasAura(63320, bot))
|
||||
return false;
|
||||
|
||||
return BuffTrigger::IsActive();
|
||||
}
|
||||
|
||||
// Checks if the target has a conflicting debuff that is equal to Curse of the Elements
|
||||
bool CurseOfTheElementsTrigger::IsActive()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (!target || !target->IsAlive() || !target->IsInWorld())
|
||||
return false;
|
||||
|
||||
// List of all spell IDs for Ebon Plague, Earth and Moon, and Curse of the Elements
|
||||
static const uint32 CurseOfTheElementsExclusiveDebuffs[] = {// Ebon Plague
|
||||
51735, 51734, 51726,
|
||||
// Earth and Moon
|
||||
48511, 48513, 48514,
|
||||
// Curse of the Elements
|
||||
1490, 11721, 11722, 27228, 47865};
|
||||
|
||||
// Check if target has any of the exclusive debuffs
|
||||
for (uint32 spellId : CurseOfTheElementsExclusiveDebuffs)
|
||||
{
|
||||
if (target->HasAura(spellId))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use default BuffTrigger logic for the rest (only trigger if debuff is missing or expiring)
|
||||
return BuffTrigger::IsActive();
|
||||
}
|
||||
|
||||
// Checks if the target has a conflicting debuff that is equal to Curse of Weakness
|
||||
bool CurseOfWeaknessTrigger::IsActive()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (!target || !target->IsAlive() || !target->IsInWorld())
|
||||
return false;
|
||||
// List of all spell IDs for Curse of Weakness, Demoralizing Roar, Demoralizing Shout, and Vindication
|
||||
static const uint32 CurseOfWeaknessExclusiveDebuffs[] = {// Curse of Weakness
|
||||
702, 1108, 6205, 7646, 11707, 11708, 27224, 30909, 50511,
|
||||
// Demoralizing Roar
|
||||
99, 1735, 9490, 9747, 9898, 26998, 48559, 48560,
|
||||
// Demoralizing Shout
|
||||
1160, 6190, 11554, 11555, 11556, 25202, 25203, 47437,
|
||||
// Vindication
|
||||
67, 26017};
|
||||
|
||||
// Check if target has any of the exclusive debuffs
|
||||
for (uint32 spellId : CurseOfWeaknessExclusiveDebuffs)
|
||||
{
|
||||
if (target->HasAura(spellId))
|
||||
return false;
|
||||
}
|
||||
// Use default BuffTrigger logic for the rest (only trigger if debuff is missing or expiring)
|
||||
return BuffTrigger::IsActive();
|
||||
}
|
||||
|
||||
struct WarlockPetDef
|
||||
{
|
||||
const char* strategy; // The strategy string as recognized by the AI (e.g., "imp", "voidwalker", etc.)
|
||||
uint32 spellId; // The spell ID required to summon this pet
|
||||
uint32 npcEntry; // The NPC entry ID for the summoned pet creature
|
||||
};
|
||||
|
||||
// Static array with all relevant Warlock pets and their data
|
||||
static const WarlockPetDef pets[] = {{"imp", 688, 416},
|
||||
{"voidwalker", 697, 1860},
|
||||
{"succubus", 712, 1863},
|
||||
{"felhunter", 691, 417},
|
||||
{"felguard", 30146, 17252}};
|
||||
|
||||
bool WrongPetTrigger::IsActive()
|
||||
{
|
||||
// Retrieve the bot player and its current pet (if any)
|
||||
Player* bot = botAI->GetBot();
|
||||
Pet* pet = bot->GetPet();
|
||||
|
||||
// Step 1: Count how many pet strategies are currently enabled for this bot.
|
||||
// While doing so, also remember which pet strategy is the only enabled one (if that's the case).
|
||||
int enabledCount = 0;
|
||||
const WarlockPetDef* enabledPet =
|
||||
nullptr; // Pointer to the pet definition of the enabled strategy, if only one is enabled
|
||||
for (const WarlockPetDef& pd : pets)
|
||||
{
|
||||
if (botAI->HasStrategy(pd.strategy, BOT_STATE_NON_COMBAT))
|
||||
{
|
||||
enabledCount++;
|
||||
enabledPet = &pd; // Save the pointer to last enabled pet
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: If not exactly one pet strategy is enabled, we should not trigger.
|
||||
// This prevents ambiguous or conflicting situations.
|
||||
if (enabledCount != 1)
|
||||
return false;
|
||||
|
||||
// Step 3: If there is no pet, do not trigger.
|
||||
if (!pet)
|
||||
return false;
|
||||
|
||||
// Step 4: At this point, we know only one pet strategy is enabled.
|
||||
// We check if the currently summoned pet matches the enabled strategy.
|
||||
bool correctPet = false;
|
||||
if (pet)
|
||||
{
|
||||
CreatureTemplate const* ct = pet->GetCreatureTemplate();
|
||||
// Check if the pet's NPC entry matches the expected one for the enabled strategy
|
||||
if (ct && ct->Entry == enabledPet->npcEntry)
|
||||
correctPet = true;
|
||||
}
|
||||
|
||||
// Step 5: If the correct pet is already summoned, the trigger should not activate.
|
||||
if (correctPet)
|
||||
return false;
|
||||
|
||||
// Step 6: Finally, check if the bot actually knows the spell to summon the desired pet.
|
||||
// If so, the trigger is active (bot should summon the correct pet).
|
||||
if (bot->HasSpell(enabledPet->spellId))
|
||||
return true;
|
||||
|
||||
// Step 7: If we get here, the bot doesn't know the spell required to support the active pet strategy
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::set<uint32> RainOfFireChannelCheckTrigger::RAIN_OF_FIRE_SPELL_IDS = {
|
||||
5740, // Rain of Fire Rank 1
|
||||
6219, // Rain of Fire Rank 2
|
||||
11677, // Rain of Fire Rank 3
|
||||
11678, // Rain of Fire Rank 4
|
||||
27212, // Rain of Fire Rank 5
|
||||
47819, // Rain of Fire Rank 6
|
||||
47820 // Rain of Fire Rank 7
|
||||
};
|
||||
|
||||
bool RainOfFireChannelCheckTrigger::IsActive()
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
|
||||
// Check if the bot is channeling a spell
|
||||
if (Spell* spell = bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
{
|
||||
// Only trigger if the spell being channeled is Rain of Fire
|
||||
if (RAIN_OF_FIRE_SPELL_IDS.count(spell->m_spellInfo->Id))
|
||||
{
|
||||
uint8 attackerCount = AI_VALUE(uint8, "attacker count");
|
||||
return attackerCount < minEnemies;
|
||||
}
|
||||
}
|
||||
|
||||
// Not channeling Rain of Fire
|
||||
return false;
|
||||
}
|
||||
351
src/Ai/Class/Warlock/Trigger/WarlockTriggers.h
Normal file
351
src/Ai/Class/Warlock/Trigger/WarlockTriggers.h
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* 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_WARLOCKTRIGGERS_H
|
||||
#define _PLAYERBOT_WARLOCKTRIGGERS_H
|
||||
|
||||
#include "GenericTriggers.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Playerbots.h"
|
||||
#include "CureTriggers.h"
|
||||
#include "Trigger.h"
|
||||
#include <set>
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
// Buff and Out of Combat Triggers
|
||||
|
||||
class DemonArmorTrigger : public BuffTrigger
|
||||
{
|
||||
public:
|
||||
DemonArmorTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "demon armor") {}
|
||||
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class SoulLinkTrigger : public BuffTrigger
|
||||
{
|
||||
public:
|
||||
SoulLinkTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "soul link") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class OutOfSoulShardsTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
OutOfSoulShardsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soul shard", 2) {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class TooManySoulShardsTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
TooManySoulShardsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "too many soul shards") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class FirestoneTrigger : public BuffTrigger
|
||||
{
|
||||
public:
|
||||
FirestoneTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "firestone") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class SpellstoneTrigger : public BuffTrigger
|
||||
{
|
||||
public:
|
||||
SpellstoneTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "spellstone") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class OutOfSoulstoneTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
OutOfSoulstoneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soulstone") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class SoulstoneTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
SoulstoneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "soulstone") {}
|
||||
|
||||
bool IsActive() override
|
||||
{
|
||||
static const std::vector<uint32> soulstoneSpellIds = {20707, 20762, 20763, 20764, 20765, 27239, 47883};
|
||||
|
||||
if (AI_VALUE2(uint32, "item count", "soulstone") == 0)
|
||||
return false;
|
||||
|
||||
for (uint32 spellId : soulstoneSpellIds)
|
||||
{
|
||||
if (!bot->HasSpellCooldown(spellId))
|
||||
return true; // Ready to use
|
||||
}
|
||||
|
||||
return false; // All are on cooldown
|
||||
}
|
||||
};
|
||||
|
||||
class WarlockConjuredItemTrigger : public ItemCountTrigger
|
||||
{
|
||||
public:
|
||||
WarlockConjuredItemTrigger(PlayerbotAI* botAI, std::string const item) : ItemCountTrigger(botAI, item, 1) {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class HasSpellstoneTrigger : public WarlockConjuredItemTrigger
|
||||
{
|
||||
public:
|
||||
HasSpellstoneTrigger(PlayerbotAI* botAI) : WarlockConjuredItemTrigger(botAI, "spellstone") {}
|
||||
};
|
||||
|
||||
class HasFirestoneTrigger : public WarlockConjuredItemTrigger
|
||||
{
|
||||
public:
|
||||
HasFirestoneTrigger(PlayerbotAI* botAI) : WarlockConjuredItemTrigger(botAI, "firestone") {}
|
||||
};
|
||||
|
||||
class HasHealthstoneTrigger : public WarlockConjuredItemTrigger
|
||||
{
|
||||
public:
|
||||
HasHealthstoneTrigger(PlayerbotAI* botAI) : WarlockConjuredItemTrigger(botAI, "healthstone") {}
|
||||
};
|
||||
|
||||
class WrongPetTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
WrongPetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "wrong pet") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
// CC and Pet Triggers
|
||||
|
||||
class BanishTrigger : public HasCcTargetTrigger
|
||||
{
|
||||
public:
|
||||
BanishTrigger(PlayerbotAI* botAI) : HasCcTargetTrigger(botAI, "banish") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class FearTrigger : public HasCcTargetTrigger
|
||||
{
|
||||
public:
|
||||
FearTrigger(PlayerbotAI* botAI) : HasCcTargetTrigger(botAI, "fear") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class SpellLockInterruptSpellTrigger : public InterruptSpellTrigger
|
||||
{
|
||||
public:
|
||||
SpellLockInterruptSpellTrigger(PlayerbotAI* botAI) : InterruptSpellTrigger(botAI, "spell lock") {}
|
||||
};
|
||||
|
||||
class DevourMagicPurgeTrigger : public TargetAuraDispelTrigger
|
||||
{
|
||||
public:
|
||||
DevourMagicPurgeTrigger(PlayerbotAI* botAI) : TargetAuraDispelTrigger(botAI, "devour magic", DISPEL_MAGIC) {}
|
||||
};
|
||||
|
||||
class DevourMagicCleanseTrigger : public PartyMemberNeedCureTrigger
|
||||
{
|
||||
public:
|
||||
DevourMagicCleanseTrigger(PlayerbotAI* botAI) : PartyMemberNeedCureTrigger(botAI, "devour magic", DISPEL_MAGIC) {}
|
||||
};
|
||||
|
||||
// DoT/Curse Triggers
|
||||
|
||||
class CorruptionTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
CorruptionTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "corruption", 1, true, 0.5f) {}
|
||||
bool IsActive() override
|
||||
{
|
||||
return BuffTrigger::IsActive() && !botAI->HasAura("seed of corruption", GetTarget(), false, true);
|
||||
}
|
||||
};
|
||||
|
||||
class CorruptionOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
{
|
||||
public:
|
||||
CorruptionOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, "corruption", true) {}
|
||||
bool IsActive() override
|
||||
{
|
||||
return BuffTrigger::IsActive() && !botAI->HasAura("seed of corruption", GetTarget(), false, true);
|
||||
}
|
||||
};
|
||||
|
||||
class ImmolateTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
ImmolateTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "immolate", 1, true, 0.5f) {}
|
||||
bool IsActive() override { return BuffTrigger::IsActive(); }
|
||||
};
|
||||
|
||||
class ImmolateOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
{
|
||||
public:
|
||||
ImmolateOnAttackerTrigger(PlayerbotAI* ai) : DebuffOnAttackerTrigger(ai, "immolate", true) {}
|
||||
bool IsActive() override { return BuffTrigger::IsActive(); }
|
||||
};
|
||||
|
||||
class UnstableAfflictionTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
UnstableAfflictionTrigger(PlayerbotAI* ai) : DebuffTrigger(ai, "unstable affliction", 1, true, 0.5f) {}
|
||||
bool IsActive() override { return BuffTrigger::IsActive(); }
|
||||
};
|
||||
|
||||
class UnstableAfflictionOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
{
|
||||
public:
|
||||
UnstableAfflictionOnAttackerTrigger(PlayerbotAI* ai) : DebuffOnAttackerTrigger(ai, "unstable affliction", true) {}
|
||||
bool IsActive() override { return BuffTrigger::IsActive(); }
|
||||
};
|
||||
|
||||
class HauntTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
HauntTrigger(PlayerbotAI* ai) : DebuffTrigger(ai, "haunt", 1, true, 0) {}
|
||||
};
|
||||
|
||||
class CurseOfAgonyTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
CurseOfAgonyTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "curse of agony", 1, true, 0.5f) {}
|
||||
bool IsActive() override { return BuffTrigger::IsActive(); }
|
||||
};
|
||||
|
||||
class CurseOfAgonyOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
{
|
||||
public:
|
||||
CurseOfAgonyOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, "curse of agony", true) {}
|
||||
bool IsActive() override { return BuffTrigger::IsActive(); }
|
||||
};
|
||||
|
||||
class CurseOfTheElementsTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
CurseOfTheElementsTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "curse of the elements", 1, true, 0.5f) {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class CurseOfDoomTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
CurseOfDoomTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "curse of doom", 1, true, 0.5f) {}
|
||||
bool IsActive() override { return BuffTrigger::IsActive(); }
|
||||
};
|
||||
|
||||
class CurseOfExhaustionTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
CurseOfExhaustionTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "curse of exhaustion", 1, true, 0.5f) {}
|
||||
bool IsActive() override { return BuffTrigger::IsActive(); }
|
||||
};
|
||||
|
||||
class CurseOfTonguesTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
CurseOfTonguesTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "curse of tongues", 1, true, 0.5f) {}
|
||||
bool IsActive() override { return BuffTrigger::IsActive(); }
|
||||
};
|
||||
|
||||
class CurseOfWeaknessTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
CurseOfWeaknessTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "curse of weakness", 1, true, 0.5f) {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
// Proc/Cooldown Triggers
|
||||
|
||||
class LifeTapTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
LifeTapTrigger(PlayerbotAI* ai) : Trigger(ai, "life tap") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class LifeTapGlyphBuffTrigger : public BuffTrigger
|
||||
{
|
||||
public:
|
||||
LifeTapGlyphBuffTrigger(PlayerbotAI* ai) : BuffTrigger(ai, "life tap") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class MetamorphosisTrigger : public BoostTrigger
|
||||
{
|
||||
public:
|
||||
MetamorphosisTrigger(PlayerbotAI* ai) : BoostTrigger(ai, "metamorphosis") {}
|
||||
};
|
||||
|
||||
class DemonicEmpowermentTrigger : public BuffTrigger
|
||||
{
|
||||
public:
|
||||
DemonicEmpowermentTrigger(PlayerbotAI* ai) : BuffTrigger(ai, "demonic empowerment") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class ImmolationAuraActiveTrigger : public HasAuraTrigger
|
||||
{
|
||||
public:
|
||||
ImmolationAuraActiveTrigger(PlayerbotAI* ai) : HasAuraTrigger(ai, "immolation aura") {}
|
||||
};
|
||||
|
||||
class ShadowTranceTrigger : public HasAuraTrigger
|
||||
{
|
||||
public:
|
||||
ShadowTranceTrigger(PlayerbotAI* botAI) : HasAuraTrigger(botAI, "shadow trance") {}
|
||||
};
|
||||
|
||||
class BacklashTrigger : public HasAuraTrigger
|
||||
{
|
||||
public:
|
||||
BacklashTrigger(PlayerbotAI* botAI) : HasAuraTrigger(botAI, "backlash") {}
|
||||
};
|
||||
|
||||
class DecimationTrigger : public HasAuraTrigger
|
||||
{
|
||||
public:
|
||||
DecimationTrigger(PlayerbotAI* ai) : HasAuraTrigger(ai, "decimation") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class MoltenCoreTrigger : public HasAuraTrigger
|
||||
{
|
||||
public:
|
||||
MoltenCoreTrigger(PlayerbotAI* ai) : HasAuraTrigger(ai, "molten core") {}
|
||||
};
|
||||
|
||||
class MetamorphosisNotActiveTrigger : public HasNoAuraTrigger
|
||||
{
|
||||
public:
|
||||
MetamorphosisNotActiveTrigger(PlayerbotAI* ai) : HasNoAuraTrigger(ai, "metamorphosis") {}
|
||||
};
|
||||
|
||||
class MetaMeleeEnemyTooCloseForSpellTrigger : public TwoTriggers
|
||||
{
|
||||
public:
|
||||
MetaMeleeEnemyTooCloseForSpellTrigger(PlayerbotAI* ai)
|
||||
: TwoTriggers(ai, "enemy too close for spell", "metamorphosis not active") {}
|
||||
};
|
||||
|
||||
class RainOfFireChannelCheckTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
RainOfFireChannelCheckTrigger(PlayerbotAI* botAI, uint32 minEnemies = 2)
|
||||
: Trigger(botAI, "rain of fire channel check"), minEnemies(minEnemies)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsActive() override;
|
||||
|
||||
protected:
|
||||
uint32 minEnemies;
|
||||
static const std::set<uint32> RAIN_OF_FIRE_SPELL_IDS;
|
||||
};
|
||||
|
||||
#endif
|
||||
419
src/Ai/Class/Warlock/WarlockAiObjectContext.cpp
Normal file
419
src/Ai/Class/Warlock/WarlockAiObjectContext.cpp
Normal file
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "WarlockAiObjectContext.h"
|
||||
|
||||
#include "AfflictionWarlockStrategy.h"
|
||||
#include "DemonologyWarlockStrategy.h"
|
||||
#include "DestructionWarlockStrategy.h"
|
||||
#include "GenericTriggers.h"
|
||||
#include "GenericWarlockNonCombatStrategy.h"
|
||||
#include "NamedObjectContext.h"
|
||||
#include "Playerbots.h"
|
||||
#include "PullStrategy.h"
|
||||
#include "Strategy.h"
|
||||
#include "TankWarlockStrategy.h"
|
||||
#include "UseItemAction.h"
|
||||
#include "WarlockActions.h"
|
||||
#include "WarlockTriggers.h"
|
||||
|
||||
class WarlockStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
{
|
||||
public:
|
||||
WarlockStrategyFactoryInternal()
|
||||
{
|
||||
creators["nc"] = &WarlockStrategyFactoryInternal::nc;
|
||||
creators["pull"] = &WarlockStrategyFactoryInternal::pull;
|
||||
creators["boost"] = &WarlockStrategyFactoryInternal::boost;
|
||||
creators["cc"] = &WarlockStrategyFactoryInternal::cc;
|
||||
creators["pet"] = &WarlockStrategyFactoryInternal::pet;
|
||||
creators["meta melee"] = &WarlockStrategyFactoryInternal::meta_melee_aoe;
|
||||
creators["tank"] = &WarlockStrategyFactoryInternal::tank;
|
||||
creators["aoe"] = &WarlockStrategyFactoryInternal::aoe;
|
||||
}
|
||||
|
||||
private:
|
||||
static Strategy* nc(PlayerbotAI* botAI) { return new GenericWarlockNonCombatStrategy(botAI); }
|
||||
static Strategy* pull(PlayerbotAI* botAI) { return new PullStrategy(botAI, "shoot"); }
|
||||
static Strategy* boost(PlayerbotAI* botAI) { return new WarlockBoostStrategy(botAI); }
|
||||
static Strategy* cc(PlayerbotAI* botAI) { return new WarlockCcStrategy(botAI); }
|
||||
static Strategy* pet(PlayerbotAI* botAI) { return new WarlockPetStrategy(botAI); }
|
||||
static Strategy* meta_melee_aoe(PlayerbotAI* botAI) { return new MetaMeleeAoeStrategy(botAI); }
|
||||
static Strategy* tank(PlayerbotAI* botAI) { return new TankWarlockStrategy(botAI); }
|
||||
static Strategy* aoe(PlayerbotAI* botAI) { return new AoEWarlockStrategy(botAI); }
|
||||
};
|
||||
|
||||
class WarlockCombatStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
{
|
||||
public:
|
||||
WarlockCombatStrategyFactoryInternal() : NamedObjectContext<Strategy>(false, true)
|
||||
{
|
||||
creators["affli"] = &WarlockCombatStrategyFactoryInternal::affliction;
|
||||
creators["demo"] = &WarlockCombatStrategyFactoryInternal::demonology;
|
||||
creators["destro"] = &WarlockCombatStrategyFactoryInternal::destruction;
|
||||
}
|
||||
|
||||
private:
|
||||
static Strategy* affliction(PlayerbotAI* botAI) { return new AfflictionWarlockStrategy(botAI); }
|
||||
static Strategy* demonology(PlayerbotAI* botAI) { return new DemonologyWarlockStrategy(botAI); }
|
||||
static Strategy* destruction(PlayerbotAI* botAI) { return new DestructionWarlockStrategy(botAI); }
|
||||
};
|
||||
|
||||
class WarlockPetStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
{
|
||||
public:
|
||||
WarlockPetStrategyFactoryInternal() : NamedObjectContext<Strategy>(false, true)
|
||||
{
|
||||
creators["imp"] = &WarlockPetStrategyFactoryInternal::imp;
|
||||
creators["voidwalker"] = &WarlockPetStrategyFactoryInternal::voidwalker;
|
||||
creators["succubus"] = &WarlockPetStrategyFactoryInternal::succubus;
|
||||
creators["felhunter"] = &WarlockPetStrategyFactoryInternal::felhunter;
|
||||
creators["felguard"] = &WarlockPetStrategyFactoryInternal::felguard;
|
||||
}
|
||||
|
||||
private:
|
||||
static Strategy* imp(PlayerbotAI* ai) { return new SummonImpStrategy(ai); }
|
||||
static Strategy* voidwalker(PlayerbotAI* ai) { return new SummonVoidwalkerStrategy(ai); }
|
||||
static Strategy* succubus(PlayerbotAI* ai) { return new SummonSuccubusStrategy(ai); }
|
||||
static Strategy* felhunter(PlayerbotAI* ai) { return new SummonFelhunterStrategy(ai); }
|
||||
static Strategy* felguard(PlayerbotAI* ai) { return new SummonFelguardStrategy(ai); }
|
||||
};
|
||||
|
||||
class WarlockSoulstoneStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
{
|
||||
public:
|
||||
WarlockSoulstoneStrategyFactoryInternal() : NamedObjectContext<Strategy>(false, true)
|
||||
{
|
||||
creators["ss self"] = &WarlockSoulstoneStrategyFactoryInternal::soulstone_self;
|
||||
creators["ss master"] = &WarlockSoulstoneStrategyFactoryInternal::soulstone_master;
|
||||
creators["ss tank"] = &WarlockSoulstoneStrategyFactoryInternal::soulstone_tank;
|
||||
creators["ss healer"] = &WarlockSoulstoneStrategyFactoryInternal::soulstone_healer;
|
||||
}
|
||||
|
||||
private:
|
||||
static Strategy* soulstone_self(PlayerbotAI* ai) { return new SoulstoneSelfStrategy(ai); }
|
||||
static Strategy* soulstone_master(PlayerbotAI* ai) { return new SoulstoneMasterStrategy(ai); }
|
||||
static Strategy* soulstone_tank(PlayerbotAI* ai) { return new SoulstoneTankStrategy(ai); }
|
||||
static Strategy* soulstone_healer(PlayerbotAI* ai) { return new SoulstoneHealerStrategy(ai); }
|
||||
};
|
||||
|
||||
class WarlockCurseStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
{
|
||||
public:
|
||||
WarlockCurseStrategyFactoryInternal() : NamedObjectContext<Strategy>(false, true)
|
||||
{
|
||||
creators["curse of agony"] = &WarlockCurseStrategyFactoryInternal::curse_of_agony;
|
||||
creators["curse of elements"] = &WarlockCurseStrategyFactoryInternal::curse_of_elements;
|
||||
creators["curse of doom"] = &WarlockCurseStrategyFactoryInternal::curse_of_doom;
|
||||
creators["curse of exhaustion"] = &WarlockCurseStrategyFactoryInternal::curse_of_exhaustion;
|
||||
creators["curse of tongues"] = &WarlockCurseStrategyFactoryInternal::curse_of_tongues;
|
||||
creators["curse of weakness"] = &WarlockCurseStrategyFactoryInternal::curse_of_weakness;
|
||||
}
|
||||
|
||||
private:
|
||||
static Strategy* curse_of_agony(PlayerbotAI* botAI) { return new WarlockCurseOfAgonyStrategy(botAI); }
|
||||
static Strategy* curse_of_elements(PlayerbotAI* botAI) { return new WarlockCurseOfTheElementsStrategy(botAI); }
|
||||
static Strategy* curse_of_doom(PlayerbotAI* botAI) { return new WarlockCurseOfDoomStrategy(botAI); }
|
||||
static Strategy* curse_of_exhaustion(PlayerbotAI* botAI) { return new WarlockCurseOfExhaustionStrategy(botAI); }
|
||||
static Strategy* curse_of_tongues(PlayerbotAI* botAI) { return new WarlockCurseOfTonguesStrategy(botAI); }
|
||||
static Strategy* curse_of_weakness(PlayerbotAI* botAI) { return new WarlockCurseOfWeaknessStrategy(botAI); }
|
||||
};
|
||||
|
||||
class WarlockWeaponStoneStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
{
|
||||
public:
|
||||
WarlockWeaponStoneStrategyFactoryInternal() : NamedObjectContext<Strategy>(false, true)
|
||||
{
|
||||
creators["firestone"] = &WarlockWeaponStoneStrategyFactoryInternal::firestone;
|
||||
creators["spellstone"] = &WarlockWeaponStoneStrategyFactoryInternal::spellstone;
|
||||
}
|
||||
|
||||
private:
|
||||
static Strategy* firestone(PlayerbotAI* ai) { return new UseFirestoneStrategy(ai); }
|
||||
static Strategy* spellstone(PlayerbotAI* ai) { return new UseSpellstoneStrategy(ai); }
|
||||
};
|
||||
|
||||
class WarlockTriggerFactoryInternal : public NamedObjectContext<Trigger>
|
||||
{
|
||||
public:
|
||||
WarlockTriggerFactoryInternal()
|
||||
{
|
||||
creators["shadow trance"] = &WarlockTriggerFactoryInternal::shadow_trance;
|
||||
creators["demon armor"] = &WarlockTriggerFactoryInternal::demon_armor;
|
||||
creators["soul link"] = &WarlockTriggerFactoryInternal::soul_link;
|
||||
creators["no soul shard"] = &WarlockTriggerFactoryInternal::no_soul_shard;
|
||||
creators["too many soul shards"] = &WarlockTriggerFactoryInternal::too_many_soul_shards;
|
||||
creators["no healthstone"] = &WarlockTriggerFactoryInternal::HasHealthstone;
|
||||
creators["no firestone"] = &WarlockTriggerFactoryInternal::HasFirestone;
|
||||
creators["no spellstone"] = &WarlockTriggerFactoryInternal::HasSpellstone;
|
||||
creators["no soulstone"] = &WarlockTriggerFactoryInternal::OutOfSoulstone;
|
||||
creators["firestone"] = &WarlockTriggerFactoryInternal::firestone;
|
||||
creators["spellstone"] = &WarlockTriggerFactoryInternal::spellstone;
|
||||
creators["soulstone"] = &WarlockTriggerFactoryInternal::soulstone;
|
||||
creators["banish"] = &WarlockTriggerFactoryInternal::banish;
|
||||
creators["fear"] = &WarlockTriggerFactoryInternal::fear;
|
||||
creators["spell lock"] = &WarlockTriggerFactoryInternal::spell_lock;
|
||||
creators["devour magic purge"] = &WarlockTriggerFactoryInternal::devour_magic_purge;
|
||||
creators["devour magic cleanse"] = &WarlockTriggerFactoryInternal::devour_magic_cleanse;
|
||||
creators["backlash"] = &WarlockTriggerFactoryInternal::backlash;
|
||||
creators["corruption"] = &WarlockTriggerFactoryInternal::corruption;
|
||||
creators["corruption on attacker"] = &WarlockTriggerFactoryInternal::corruption_on_attacker;
|
||||
creators["immolate"] = &WarlockTriggerFactoryInternal::immolate;
|
||||
creators["immolate on attacker"] = &WarlockTriggerFactoryInternal::immolate_on_attacker;
|
||||
creators["unstable affliction"] = &WarlockTriggerFactoryInternal::unstable_affliction;
|
||||
creators["unstable affliction on attacker"] = &WarlockTriggerFactoryInternal::unstable_affliction_on_attacker;
|
||||
creators["haunt"] = &WarlockTriggerFactoryInternal::haunt;
|
||||
creators["decimation"] = &WarlockTriggerFactoryInternal::decimation;
|
||||
creators["life tap"] = &WarlockTriggerFactoryInternal::life_tap;
|
||||
creators["life tap glyph buff"] = &WarlockTriggerFactoryInternal::life_tap_glyph_buff;
|
||||
creators["molten core"] = &WarlockTriggerFactoryInternal::molten_core;
|
||||
creators["metamorphosis"] = &WarlockTriggerFactoryInternal::metamorphosis;
|
||||
creators["demonic empowerment"] = &WarlockTriggerFactoryInternal::demonic_empowerment;
|
||||
creators["immolation aura active"] = &WarlockTriggerFactoryInternal::immolation_aura_active;
|
||||
creators["metamorphosis not active"] = &WarlockTriggerFactoryInternal::metamorphosis_not_active;
|
||||
creators["meta melee flee check"] = &WarlockTriggerFactoryInternal::meta_melee_flee_check;
|
||||
creators["curse of agony"] = &WarlockTriggerFactoryInternal::curse_of_agony;
|
||||
creators["curse of agony on attacker"] = &WarlockTriggerFactoryInternal::curse_of_agony_on_attacker;
|
||||
creators["curse of the elements"] = &WarlockTriggerFactoryInternal::curse_of_the_elements;
|
||||
creators["curse of doom"] = &WarlockTriggerFactoryInternal::curse_of_doom;
|
||||
creators["curse of exhaustion"] = &WarlockTriggerFactoryInternal::curse_of_exhaustion;
|
||||
creators["curse of tongues"] = &WarlockTriggerFactoryInternal::curse_of_tongues;
|
||||
creators["curse of weakness"] = &WarlockTriggerFactoryInternal::curse_of_weakness;
|
||||
creators["wrong pet"] = &WarlockTriggerFactoryInternal::wrong_pet;
|
||||
creators["rain of fire channel check"] = &WarlockTriggerFactoryInternal::rain_of_fire_channel_check;
|
||||
}
|
||||
|
||||
private:
|
||||
static Trigger* shadow_trance(PlayerbotAI* botAI) { return new ShadowTranceTrigger(botAI); }
|
||||
static Trigger* demon_armor(PlayerbotAI* botAI) { return new DemonArmorTrigger(botAI); }
|
||||
static Trigger* soul_link(PlayerbotAI* botAI) { return new SoulLinkTrigger(botAI); }
|
||||
static Trigger* no_soul_shard(PlayerbotAI* botAI) { return new OutOfSoulShardsTrigger(botAI); }
|
||||
static Trigger* too_many_soul_shards(PlayerbotAI* botAI) { return new TooManySoulShardsTrigger(botAI); }
|
||||
static Trigger* HasHealthstone(PlayerbotAI* botAI) { return new HasHealthstoneTrigger(botAI); }
|
||||
static Trigger* HasFirestone(PlayerbotAI* botAI) { return new HasFirestoneTrigger(botAI); }
|
||||
static Trigger* HasSpellstone(PlayerbotAI* botAI) { return new HasSpellstoneTrigger(botAI); }
|
||||
static Trigger* OutOfSoulstone(PlayerbotAI* botAI) { return new OutOfSoulstoneTrigger(botAI); }
|
||||
static Trigger* firestone(PlayerbotAI* botAI) { return new FirestoneTrigger(botAI); }
|
||||
static Trigger* spellstone(PlayerbotAI* botAI) { return new SpellstoneTrigger(botAI); }
|
||||
static Trigger* soulstone(PlayerbotAI* botAI) { return new SoulstoneTrigger(botAI); }
|
||||
static Trigger* corruption(PlayerbotAI* botAI) { return new CorruptionTrigger(botAI); }
|
||||
static Trigger* corruption_on_attacker(PlayerbotAI* botAI) { return new CorruptionOnAttackerTrigger(botAI); }
|
||||
static Trigger* banish(PlayerbotAI* botAI) { return new BanishTrigger(botAI); }
|
||||
static Trigger* fear(PlayerbotAI* botAI) { return new FearTrigger(botAI); }
|
||||
static Trigger* spell_lock(PlayerbotAI* botAI) { return new SpellLockInterruptSpellTrigger(botAI); }
|
||||
static Trigger* devour_magic_purge(PlayerbotAI* botAI) { return new DevourMagicPurgeTrigger(botAI); }
|
||||
static Trigger* devour_magic_cleanse(PlayerbotAI* botAI) { return new DevourMagicCleanseTrigger(botAI); }
|
||||
static Trigger* backlash(PlayerbotAI* botAI) { return new BacklashTrigger(botAI); }
|
||||
static Trigger* immolate(PlayerbotAI* botAI) { return new ImmolateTrigger(botAI); }
|
||||
static Trigger* immolate_on_attacker(PlayerbotAI* ai) { return new ImmolateOnAttackerTrigger(ai); }
|
||||
static Trigger* unstable_affliction(PlayerbotAI* ai) { return new UnstableAfflictionTrigger(ai); }
|
||||
static Trigger* unstable_affliction_on_attacker(PlayerbotAI* ai) { return new UnstableAfflictionOnAttackerTrigger(ai); }
|
||||
static Trigger* haunt(PlayerbotAI* ai) { return new HauntTrigger(ai); }
|
||||
static Trigger* decimation(PlayerbotAI* ai) { return new DecimationTrigger(ai); }
|
||||
static Trigger* life_tap(PlayerbotAI* ai) { return new LifeTapTrigger(ai); }
|
||||
static Trigger* life_tap_glyph_buff(PlayerbotAI* ai) { return new LifeTapGlyphBuffTrigger(ai); }
|
||||
static Trigger* molten_core(PlayerbotAI* ai) { return new MoltenCoreTrigger(ai); }
|
||||
static Trigger* metamorphosis(PlayerbotAI* ai) { return new MetamorphosisTrigger(ai); }
|
||||
static Trigger* demonic_empowerment(PlayerbotAI* ai) { return new DemonicEmpowermentTrigger(ai); }
|
||||
static Trigger* immolation_aura_active(PlayerbotAI* ai) { return new ImmolationAuraActiveTrigger(ai); }
|
||||
static Trigger* metamorphosis_not_active(PlayerbotAI* ai) { return new MetamorphosisNotActiveTrigger(ai); }
|
||||
static Trigger* meta_melee_flee_check(PlayerbotAI* ai) { return new MetaMeleeEnemyTooCloseForSpellTrigger(ai); }
|
||||
static Trigger* curse_of_agony(PlayerbotAI* botAI) { return new CurseOfAgonyTrigger(botAI); }
|
||||
static Trigger* curse_of_agony_on_attacker(PlayerbotAI* botAI) { return new CurseOfAgonyOnAttackerTrigger(botAI); }
|
||||
static Trigger* curse_of_the_elements(PlayerbotAI* ai) { return new CurseOfTheElementsTrigger(ai); }
|
||||
static Trigger* curse_of_doom(PlayerbotAI* ai) { return new CurseOfDoomTrigger(ai); }
|
||||
static Trigger* curse_of_exhaustion(PlayerbotAI* ai) { return new CurseOfExhaustionTrigger(ai); }
|
||||
static Trigger* curse_of_tongues(PlayerbotAI* ai) { return new CurseOfTonguesTrigger(ai); }
|
||||
static Trigger* curse_of_weakness(PlayerbotAI* ai) { return new CurseOfWeaknessTrigger(ai); }
|
||||
static Trigger* wrong_pet(PlayerbotAI* ai) { return new WrongPetTrigger(ai); }
|
||||
static Trigger* rain_of_fire_channel_check(PlayerbotAI* ai) { return new RainOfFireChannelCheckTrigger(ai); }
|
||||
};
|
||||
|
||||
class WarlockAiObjectContextInternal : public NamedObjectContext<Action>
|
||||
{
|
||||
public:
|
||||
WarlockAiObjectContextInternal()
|
||||
{
|
||||
creators["fel armor"] = &WarlockAiObjectContextInternal::fel_armor;
|
||||
creators["demon armor"] = &WarlockAiObjectContextInternal::demon_armor;
|
||||
creators["demon skin"] = &WarlockAiObjectContextInternal::demon_skin;
|
||||
creators["soul link"] = &WarlockAiObjectContextInternal::soul_link;
|
||||
creators["create soul shard"] = &WarlockAiObjectContextInternal::create_soul_shard;
|
||||
creators["destroy soul shard"] = &WarlockAiObjectContextInternal::destroy_soul_shard;
|
||||
creators["create healthstone"] = &WarlockAiObjectContextInternal::create_healthstone;
|
||||
creators["create firestone"] = &WarlockAiObjectContextInternal::create_firestone;
|
||||
creators["create spellstone"] = &WarlockAiObjectContextInternal::create_spellstone;
|
||||
creators["create soulstone"] = &WarlockAiObjectContextInternal::create_soulstone;
|
||||
creators["firestone"] = &WarlockAiObjectContextInternal::firestone;
|
||||
creators["spellstone"] = &WarlockAiObjectContextInternal::spellstone;
|
||||
creators["soulstone self"] = &WarlockAiObjectContextInternal::soulstone_self;
|
||||
creators["soulstone master"] = &WarlockAiObjectContextInternal::soulstone_master;
|
||||
creators["soulstone tank"] = &WarlockAiObjectContextInternal::soulstone_tank;
|
||||
creators["soulstone healer"] = &WarlockAiObjectContextInternal::soulstone_healer;
|
||||
creators["summon voidwalker"] = &WarlockAiObjectContextInternal::summon_voidwalker;
|
||||
creators["summon felguard"] = &WarlockAiObjectContextInternal::summon_felguard;
|
||||
creators["summon felhunter"] = &WarlockAiObjectContextInternal::summon_felhunter;
|
||||
creators["summon succubus"] = &WarlockAiObjectContextInternal::summon_succubus;
|
||||
creators["summon imp"] = &WarlockAiObjectContextInternal::summon_imp;
|
||||
creators["fel domination"] = &WarlockAiObjectContextInternal::fel_domination;
|
||||
creators["immolate"] = &WarlockAiObjectContextInternal::immolate;
|
||||
creators["immolate on attacker"] = &WarlockAiObjectContextInternal::immolate_on_attacker;
|
||||
creators["corruption"] = &WarlockAiObjectContextInternal::corruption;
|
||||
creators["corruption on attacker"] = &WarlockAiObjectContextInternal::corruption_on_attacker;
|
||||
creators["shadow bolt"] = &WarlockAiObjectContextInternal::shadow_bolt;
|
||||
creators["drain soul"] = &WarlockAiObjectContextInternal::drain_soul;
|
||||
creators["drain mana"] = &WarlockAiObjectContextInternal::drain_mana;
|
||||
creators["drain life"] = &WarlockAiObjectContextInternal::drain_life;
|
||||
creators["banish on cc"] = &WarlockAiObjectContextInternal::banish_on_cc;
|
||||
creators["fear on cc"] = &WarlockAiObjectContextInternal::fear_on_cc;
|
||||
creators["spell lock"] = &WarlockAiObjectContextInternal::spell_lock;
|
||||
creators["devour magic purge"] = &WarlockAiObjectContextInternal::devour_magic_purge;
|
||||
creators["devour magic cleanse"] = &WarlockAiObjectContextInternal::devour_magic_cleanse;
|
||||
creators["seed of corruption"] = &WarlockAiObjectContextInternal::seed_of_corruption;
|
||||
creators["seed of corruption on attacker"] = &WarlockAiObjectContextInternal::seed_of_corruption_on_attacker;
|
||||
creators["rain of fire"] = &WarlockAiObjectContextInternal::rain_of_fire;
|
||||
creators["hellfire"] = &WarlockAiObjectContextInternal::hellfire;
|
||||
creators["shadowfury"] = &WarlockAiObjectContextInternal::shadowfury;
|
||||
creators["life tap"] = &WarlockAiObjectContextInternal::life_tap;
|
||||
creators["incinerate"] = &WarlockAiObjectContextInternal::incinerate;
|
||||
creators["conflagrate"] = &WarlockAiObjectContextInternal::conflagrate;
|
||||
creators["unstable affliction"] = &WarlockAiObjectContextInternal::unstable_affliction;
|
||||
creators["unstable affliction on attacker"] = &WarlockAiObjectContextInternal::unstable_affliction_on_attacker;
|
||||
creators["haunt"] = &WarlockAiObjectContextInternal::haunt;
|
||||
creators["demonic empowerment"] = &WarlockAiObjectContextInternal::demonic_empowerment;
|
||||
creators["metamorphosis"] = &WarlockAiObjectContextInternal::metamorphosis;
|
||||
creators["soul fire"] = &WarlockAiObjectContextInternal::soul_fire;
|
||||
creators["incinerate"] = &WarlockAiObjectContextInternal::incinerate;
|
||||
creators["demon charge"] = &WarlockAiObjectContextInternal::demon_charge;
|
||||
creators["shadow cleave"] = &WarlockAiObjectContextInternal::shadow_cleave;
|
||||
creators["shadowburn"] = &WarlockAiObjectContextInternal::shadowburn;
|
||||
creators["shadowflame"] = &WarlockAiObjectContextInternal::shadowflame;
|
||||
creators["immolation aura"] = &WarlockAiObjectContextInternal::immolation_aura;
|
||||
creators["chaos bolt"] = &WarlockAiObjectContextInternal::chaos_bolt;
|
||||
creators["soulshatter"] = &WarlockAiObjectContextInternal::soulshatter;
|
||||
creators["searing pain"] = WarlockAiObjectContextInternal::searing_pain;
|
||||
creators["shadow ward"] = &WarlockAiObjectContextInternal::shadow_ward;
|
||||
creators["curse of agony"] = &WarlockAiObjectContextInternal::curse_of_agony;
|
||||
creators["curse of agony on attacker"] = &WarlockAiObjectContextInternal::curse_of_agony_on_attacker;
|
||||
creators["curse of the elements"] = &WarlockAiObjectContextInternal::curse_of_the_elements;
|
||||
creators["curse of doom"] = &WarlockAiObjectContextInternal::curse_of_doom;
|
||||
creators["curse of exhaustion"] = &WarlockAiObjectContextInternal::curse_of_exhaustion;
|
||||
creators["curse of tongues"] = &WarlockAiObjectContextInternal::curse_of_tongues;
|
||||
creators["curse of weakness"] = &WarlockAiObjectContextInternal::curse_of_weakness;
|
||||
}
|
||||
|
||||
private:
|
||||
static Action* conflagrate(PlayerbotAI* botAI) { return new CastConflagrateAction(botAI); }
|
||||
static Action* incinerate(PlayerbotAI* botAI) { return new CastIncinerateAction(botAI); }
|
||||
static Action* immolate(PlayerbotAI* botAI) { return new CastImmolateAction(botAI); }
|
||||
static Action* immolate_on_attacker(PlayerbotAI* botAI) { return new CastImmolateOnAttackerAction(botAI); }
|
||||
static Action* fel_armor(PlayerbotAI* botAI) { return new CastFelArmorAction(botAI); }
|
||||
static Action* demon_armor(PlayerbotAI* botAI) { return new CastDemonArmorAction(botAI); }
|
||||
static Action* demon_skin(PlayerbotAI* botAI) { return new CastDemonSkinAction(botAI); }
|
||||
static Action* soul_link(PlayerbotAI* botAI) { return new CastSoulLinkAction(botAI); }
|
||||
static Action* create_soul_shard(PlayerbotAI* botAI) { return new CreateSoulShardAction(botAI); }
|
||||
static Action* destroy_soul_shard(PlayerbotAI* botAI) { return new DestroySoulShardAction(botAI); }
|
||||
static Action* create_healthstone(PlayerbotAI* botAI) { return new CastCreateHealthstoneAction(botAI); }
|
||||
static Action* create_firestone(PlayerbotAI* botAI) { return new CastCreateFirestoneAction(botAI); }
|
||||
static Action* create_spellstone(PlayerbotAI* botAI) { return new CastCreateSpellstoneAction(botAI); }
|
||||
static Action* create_soulstone(PlayerbotAI* botAI) { return new CastCreateSoulstoneAction(botAI); }
|
||||
static Action* firestone(PlayerbotAI* botAI) { return new UseSpellItemAction(botAI, "firestone", true); }
|
||||
static Action* spellstone(PlayerbotAI* botAI) { return new UseSpellItemAction(botAI, "spellstone", true); }
|
||||
static Action* soulstone_self(PlayerbotAI* botAI) { return new UseSoulstoneSelfAction(botAI); }
|
||||
static Action* soulstone_master(PlayerbotAI* botAI) { return new UseSoulstoneMasterAction(botAI); }
|
||||
static Action* soulstone_tank(PlayerbotAI* botAI) { return new UseSoulstoneTankAction(botAI); }
|
||||
static Action* soulstone_healer(PlayerbotAI* botAI) { return new UseSoulstoneHealerAction(botAI); }
|
||||
static Action* summon_voidwalker(PlayerbotAI* botAI) { return new CastSummonVoidwalkerAction(botAI); }
|
||||
static Action* summon_felguard(PlayerbotAI* botAI) { return new CastSummonFelguardAction(botAI); }
|
||||
static Action* summon_felhunter(PlayerbotAI* botAI) { return new CastSummonFelhunterAction(botAI); }
|
||||
static Action* summon_imp(PlayerbotAI* botAI) { return new CastSummonImpAction(botAI); }
|
||||
static Action* summon_succubus(PlayerbotAI* botAI) { return new CastSummonSuccubusAction(botAI); }
|
||||
static Action* fel_domination(PlayerbotAI* botAI) { return new CastFelDominationAction(botAI); }
|
||||
static Action* corruption(PlayerbotAI* botAI) { return new CastCorruptionAction(botAI); }
|
||||
static Action* corruption_on_attacker(PlayerbotAI* botAI) { return new CastCorruptionOnAttackerAction(botAI); }
|
||||
static Action* shadow_bolt(PlayerbotAI* botAI) { return new CastShadowBoltAction(botAI); }
|
||||
static Action* drain_soul(PlayerbotAI* botAI) { return new CastDrainSoulAction(botAI); }
|
||||
static Action* drain_mana(PlayerbotAI* botAI) { return new CastDrainManaAction(botAI); }
|
||||
static Action* drain_life(PlayerbotAI* botAI) { return new CastDrainLifeAction(botAI); }
|
||||
static Action* banish_on_cc(PlayerbotAI* botAI) { return new CastBanishOnCcAction(botAI); }
|
||||
static Action* fear_on_cc(PlayerbotAI* botAI) { return new CastFearOnCcAction(botAI); }
|
||||
static Action* spell_lock(PlayerbotAI* botAI) { return new CastSpellLockAction(botAI); }
|
||||
static Action* devour_magic_purge(PlayerbotAI* botAI) { return new CastDevourMagicPurgeAction(botAI); }
|
||||
static Action* devour_magic_cleanse(PlayerbotAI* botAI) { return new CastDevourMagicCleanseAction(botAI); }
|
||||
static Action* seed_of_corruption(PlayerbotAI* botAI) { return new CastSeedOfCorruptionAction(botAI); }
|
||||
static Action* seed_of_corruption_on_attacker(PlayerbotAI* botAI) { return new CastSeedOfCorruptionOnAttackerAction(botAI); }
|
||||
static Action* rain_of_fire(PlayerbotAI* botAI) { return new CastRainOfFireAction(botAI); }
|
||||
static Action* hellfire(PlayerbotAI* botAI) { return new CastHellfireAction(botAI); }
|
||||
static Action* shadowfury(PlayerbotAI* botAI) { return new CastShadowfuryAction(botAI); }
|
||||
static Action* life_tap(PlayerbotAI* botAI) { return new CastLifeTapAction(botAI); }
|
||||
static Action* unstable_affliction(PlayerbotAI* ai) { return new CastUnstableAfflictionAction(ai); }
|
||||
static Action* unstable_affliction_on_attacker(PlayerbotAI* ai) { return new CastUnstableAfflictionOnAttackerAction(ai); }
|
||||
static Action* haunt(PlayerbotAI* ai) { return new CastHauntAction(ai); }
|
||||
static Action* demonic_empowerment(PlayerbotAI* ai) { return new CastDemonicEmpowermentAction(ai); }
|
||||
static Action* metamorphosis(PlayerbotAI* ai) { return new CastMetamorphosisAction(ai); }
|
||||
static Action* soul_fire(PlayerbotAI* ai) { return new CastSoulFireAction(ai); }
|
||||
static Action* demon_charge(PlayerbotAI* ai) { return new DemonChargeAction(ai); }
|
||||
static Action* shadow_cleave(PlayerbotAI* ai) { return new ShadowCleaveAction(ai); }
|
||||
static Action* shadowburn(PlayerbotAI* ai) { return new CastShadowburnAction(ai); }
|
||||
static Action* shadowflame(PlayerbotAI* botAI) { return new CastShadowflameAction(botAI); }
|
||||
static Action* immolation_aura(PlayerbotAI* botAI) { return new CastImmolationAuraAction(botAI); }
|
||||
static Action* chaos_bolt(PlayerbotAI* botAI) { return new CastChaosBoltAction(botAI); }
|
||||
static Action* soulshatter(PlayerbotAI* botAI) { return new CastSoulshatterAction(botAI); }
|
||||
static Action* searing_pain(PlayerbotAI* botAI) { return new CastSearingPainAction(botAI); }
|
||||
static Action* shadow_ward(PlayerbotAI* botAI) { return new CastShadowWardAction(botAI); }
|
||||
static Action* curse_of_agony(PlayerbotAI* botAI) { return new CastCurseOfAgonyAction(botAI); }
|
||||
static Action* curse_of_agony_on_attacker(PlayerbotAI* botAI) { return new CastCurseOfAgonyOnAttackerAction(botAI); }
|
||||
static Action* curse_of_the_elements(PlayerbotAI* ai) { return new CastCurseOfTheElementsAction(ai); }
|
||||
static Action* curse_of_doom(PlayerbotAI* ai) { return new CastCurseOfDoomAction(ai); }
|
||||
static Action* curse_of_exhaustion(PlayerbotAI* ai) { return new CastCurseOfExhaustionAction(ai); }
|
||||
static Action* curse_of_tongues(PlayerbotAI* ai) { return new CastCurseOfTonguesAction(ai); }
|
||||
static Action* curse_of_weakness(PlayerbotAI* ai) { return new CastCurseOfWeaknessAction(ai); }
|
||||
};
|
||||
|
||||
SharedNamedObjectContextList<Strategy> WarlockAiObjectContext::sharedStrategyContexts;
|
||||
SharedNamedObjectContextList<Action> WarlockAiObjectContext::sharedActionContexts;
|
||||
SharedNamedObjectContextList<Trigger> WarlockAiObjectContext::sharedTriggerContexts;
|
||||
SharedNamedObjectContextList<UntypedValue> WarlockAiObjectContext::sharedValueContexts;
|
||||
|
||||
WarlockAiObjectContext::WarlockAiObjectContext(PlayerbotAI* botAI)
|
||||
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts)
|
||||
{
|
||||
}
|
||||
|
||||
void WarlockAiObjectContext::BuildSharedContexts()
|
||||
{
|
||||
BuildSharedStrategyContexts(sharedStrategyContexts);
|
||||
BuildSharedActionContexts(sharedActionContexts);
|
||||
BuildSharedTriggerContexts(sharedTriggerContexts);
|
||||
BuildSharedValueContexts(sharedValueContexts);
|
||||
}
|
||||
|
||||
void WarlockAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
|
||||
{
|
||||
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
|
||||
strategyContexts.Add(new WarlockStrategyFactoryInternal());
|
||||
strategyContexts.Add(new WarlockCombatStrategyFactoryInternal());
|
||||
strategyContexts.Add(new WarlockPetStrategyFactoryInternal());
|
||||
strategyContexts.Add(new WarlockSoulstoneStrategyFactoryInternal());
|
||||
strategyContexts.Add(new WarlockCurseStrategyFactoryInternal());
|
||||
strategyContexts.Add(new WarlockWeaponStoneStrategyFactoryInternal());
|
||||
}
|
||||
|
||||
void WarlockAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
|
||||
{
|
||||
AiObjectContext::BuildSharedActionContexts(actionContexts);
|
||||
actionContexts.Add(new WarlockAiObjectContextInternal());
|
||||
}
|
||||
|
||||
void WarlockAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
|
||||
{
|
||||
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
|
||||
triggerContexts.Add(new WarlockTriggerFactoryInternal());
|
||||
}
|
||||
|
||||
void WarlockAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
|
||||
{
|
||||
AiObjectContext::BuildSharedValueContexts(valueContexts);
|
||||
}
|
||||
30
src/Ai/Class/Warlock/WarlockAiObjectContext.h
Normal file
30
src/Ai/Class/Warlock/WarlockAiObjectContext.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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_WARLOCKAIOBJECTCONTEXT_H
|
||||
#define _PLAYERBOT_WARLOCKAIOBJECTCONTEXT_H
|
||||
|
||||
#include "AiObjectContext.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class WarlockAiObjectContext : public AiObjectContext
|
||||
{
|
||||
public:
|
||||
WarlockAiObjectContext(PlayerbotAI* botAI);
|
||||
|
||||
static void BuildSharedContexts();
|
||||
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
|
||||
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
|
||||
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
|
||||
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
|
||||
|
||||
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
|
||||
static SharedNamedObjectContextList<Action> sharedActionContexts;
|
||||
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
|
||||
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user