mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
warlock and dk strategy port
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "AiFactory.h"
|
||||
#include "BattlegroundMgr.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Playerbots.h"
|
||||
#include "Engine.h"
|
||||
#include "Group.h"
|
||||
@@ -346,10 +347,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
||||
engine->addStrategies("dps", "threat", "dps assist", "aoe", "close", "behind", "stealth", nullptr);
|
||||
break;
|
||||
case CLASS_WARLOCK:
|
||||
if (player->getLevel() > 19)
|
||||
engine->addStrategy("dps debuff");
|
||||
|
||||
engine->addStrategies("dps assist", "dps", "aoe", "ranged", "pet", "threat", nullptr);
|
||||
engine->addStrategies("dps assist", "dps", "dps debuff", "aoe", "ranged", "threat", nullptr);
|
||||
break;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
if (tab == 0)
|
||||
@@ -518,7 +516,14 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
|
||||
nonCombatEngine->addStrategy("dps assist");
|
||||
break;
|
||||
case CLASS_WARLOCK:
|
||||
nonCombatEngine->addStrategies("pet", "dps assist", nullptr);
|
||||
if (tab == WARLOCK_TAB_AFFLICATION) {
|
||||
nonCombatEngine->addStrategies("bmana", nullptr);
|
||||
} else if (tab == WARLOCK_TAB_DEMONOLOGY) {
|
||||
nonCombatEngine->addStrategies("bdps", nullptr);
|
||||
} else if (tab == WARLOCK_TAB_DESTRUCTION) {
|
||||
nonCombatEngine->addStrategies("bhealth", nullptr);
|
||||
}
|
||||
nonCombatEngine->addStrategies("dps assist", nullptr);
|
||||
break;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
if (tab == 0)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "PlayerbotMgr.h"
|
||||
#include "PositionValue.h"
|
||||
#include "ServerFacade.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "SocialMgr.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "UpdateTime.h"
|
||||
@@ -1680,6 +1681,57 @@ bool PlayerbotAI::HasAura(uint32 spellId, Unit const* unit)
|
||||
return false;
|
||||
}
|
||||
|
||||
Aura* PlayerbotAI::GetAura(std::string const name, Unit* unit, bool checkIsOwner, bool checkDuration, int checkStack)
|
||||
{
|
||||
if (!unit)
|
||||
return nullptr;
|
||||
|
||||
std::wstring wnamepart;
|
||||
if (!Utf8toWStr(name, wnamepart))
|
||||
return nullptr;
|
||||
|
||||
wstrToLower(wnamepart);
|
||||
|
||||
for (uint32 auraType = SPELL_AURA_BIND_SIGHT; auraType < TOTAL_AURAS; auraType++)
|
||||
{
|
||||
Unit::AuraEffectList const& auras = unit->GetAuraEffectsByType((AuraType)auraType);
|
||||
if (auras.empty())
|
||||
continue;
|
||||
|
||||
for (AuraEffect const* aurEff : auras)
|
||||
{
|
||||
SpellInfo const* spellInfo = aurEff->GetSpellInfo();
|
||||
|
||||
std::string const auraName = spellInfo->SpellName[0];
|
||||
if (auraName.empty() || auraName.length() != wnamepart.length() || !Utf8FitTo(auraName, wnamepart))
|
||||
continue;
|
||||
|
||||
if (IsRealAura(bot, aurEff, unit))
|
||||
{
|
||||
if (checkIsOwner && aurEff) {
|
||||
if (aurEff->GetCasterGUID() != bot->GetGUID())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checkDuration && aurEff) {
|
||||
if (aurEff->GetBase()->GetDuration() == -1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkStack != -1 && aurEff) {
|
||||
if (aurEff->GetBase()->GetStackAmount() < checkStack) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return aurEff->GetBase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool PlayerbotAI::HasAnyAuraOf(Unit* player, ...)
|
||||
{
|
||||
if (!player)
|
||||
@@ -1711,15 +1763,30 @@ bool PlayerbotAI::CanCastSpell(std::string const name, Unit* target, Item* itemT
|
||||
|
||||
bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, Item* itemTarget)
|
||||
{
|
||||
if (!spellid)
|
||||
if (!spellid) {
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
LOG_DEBUG("playerbots", "Can cast spell failed. No spellid. - spellid: {}, bot name: {}",
|
||||
spellid, bot->GetName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bot->HasUnitState(UNIT_STATE_LOST_CONTROL))
|
||||
if (bot->HasUnitState(UNIT_STATE_LOST_CONTROL)) {
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
LOG_DEBUG("playerbots", "Can cast spell failed. Unit state lost control. - spellid: {}, bot name: {}",
|
||||
spellid, bot->GetName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!target)
|
||||
target = bot;
|
||||
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup())
|
||||
LOG_DEBUG("playerbots", "Can cast spell? - target name: {}, spellid: {}, bot name: {}",
|
||||
target->GetName(), spellid, bot->GetName());
|
||||
|
||||
if (Pet* pet = bot->GetPet())
|
||||
if (pet->HasSpell(spellid))
|
||||
return true;
|
||||
@@ -1741,8 +1808,13 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell,
|
||||
}
|
||||
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid);
|
||||
if (!spellInfo)
|
||||
if (!spellInfo) {
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
LOG_DEBUG("playerbots", "Can cast spell failed. No spellInfo. - target name: {}, spellid: {}, bot name: {}",
|
||||
target->GetName(), spellid, bot->GetName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 CastingTime = !spellInfo->IsChanneled() ? spellInfo->CalcCastTime(bot) : spellInfo->GetDuration();
|
||||
if (CastingTime && bot->isMoving()) {
|
||||
@@ -1762,15 +1834,15 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell,
|
||||
// if (!positiveSpell && bot->IsFriendlyTo(target))
|
||||
// return false;
|
||||
|
||||
bool damage = false;
|
||||
for (uint8 i = EFFECT_0; i <= EFFECT_2; i++)
|
||||
{
|
||||
if (spellInfo->Effects[i].Effect == SPELL_EFFECT_SCHOOL_DAMAGE)
|
||||
{
|
||||
damage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// bool damage = false;
|
||||
// for (uint8 i = EFFECT_0; i <= EFFECT_2; i++)
|
||||
// {
|
||||
// if (spellInfo->Effects[i].Effect == SPELL_EFFECT_SCHOOL_DAMAGE)
|
||||
// {
|
||||
// damage = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (target->IsImmunedToSpell(spellInfo)) {
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
@@ -1780,19 +1852,19 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!damage)
|
||||
{
|
||||
for (uint8 i = EFFECT_0; i <= EFFECT_2; i++)
|
||||
{
|
||||
if (target->IsImmunedToSpellEffect(spellInfo, i)) {
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
LOG_DEBUG("playerbots", "target is immuned to spell effect - target name: {}, spellid: {}, bot name: {}",
|
||||
target->GetName(), spellid, bot->GetName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (!damage)
|
||||
// {
|
||||
// for (uint8 i = EFFECT_0; i <= EFFECT_2; i++)
|
||||
// {
|
||||
// if (target->IsImmunedToSpellEffect(spellInfo, i)) {
|
||||
// if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
// LOG_DEBUG("playerbots", "target is immuned to spell effect - target name: {}, spellid: {}, bot name: {}",
|
||||
// target->GetName(), spellid, bot->GetName());
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (bot != target && sServerFacade->GetDistance2d(bot, target) > sPlayerbotAIConfig->sightDistance) {
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
@@ -2050,7 +2122,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
|
||||
bot->GetTradeData()->SetSpell(spellId);
|
||||
delete spell;
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
LOG_DEBUG("playerbots", "Spell cast no item - target name: {}, spellid: {}, bot name: {}}",
|
||||
LOG_DEBUG("playerbots", "Spell cast no item - target name: {}, spellid: {}, bot name: {}",
|
||||
target->GetName(), spellId, bot->GetName());
|
||||
}
|
||||
return true;
|
||||
@@ -2111,8 +2183,15 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
|
||||
// if (spellSuccess != SPELL_CAST_OK)
|
||||
// return false;
|
||||
|
||||
spell->prepare(&targets);
|
||||
SpellCastResult result = spell->prepare(&targets);
|
||||
|
||||
if (result != SPELL_CAST_OK) {
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
LOG_DEBUG("playerbots", "Spell cast failed. - target name: {}, spellid: {}, bot name: {}, result: {}",
|
||||
target->GetName(), spellId, bot->GetName(), result);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// if (spellInfo->Effects[0].Effect == SPELL_EFFECT_OPEN_LOCK || spellInfo->Effects[0].Effect == SPELL_EFFECT_SKINNING)
|
||||
// {
|
||||
// LootObject loot = *aiObjectContext->GetValue<LootObject>("loot target");
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "PlayerbotAIBase.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "PlayerbotSecurity.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "PlayerbotTextMgr.h"
|
||||
|
||||
@@ -376,6 +377,7 @@ class PlayerbotAI : public PlayerbotAIBase
|
||||
bool CanCastSpell(uint32 spellid, float x, float y, float z, uint8 effectMask, bool checkHasSpell = true, Item* itemTarget = nullptr);
|
||||
|
||||
bool HasAura(uint32 spellId, Unit const* player);
|
||||
Aura* GetAura(std::string const spellName, Unit* unit, bool checkIsOwner = false, bool checkDuration = false, int checkStack = -1);
|
||||
bool CastSpell(uint32 spellId, Unit* target, Item* itemTarget = nullptr);
|
||||
bool CastSpell(uint32 spellId, float x, float y, float z, Item* itemTarget = nullptr);
|
||||
bool canDispel(SpellInfo const* spellInfo, uint32 dispelType);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "CharacterCache.h"
|
||||
#include "CharacterPackets.h"
|
||||
#include "Common.h"
|
||||
#include "ObjectAccessor.h"
|
||||
@@ -776,10 +777,12 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
|
||||
|
||||
if (!charname)
|
||||
{
|
||||
Player* tPlayer = ObjectAccessor::FindConnectedPlayer(master->GetTarget());
|
||||
if (tPlayer) {
|
||||
charname = new char[tPlayer->GetName().size() + 1];
|
||||
strcpy(charname, tPlayer->GetName().c_str());
|
||||
std::string name;
|
||||
bool isPlayer = sCharacterCache->GetCharacterNameByGuid(master->GetTarget(), name);
|
||||
// Player* tPlayer = ObjectAccessor::FindConnectedPlayer(master->GetTarget());
|
||||
if (isPlayer) {
|
||||
charname = new char[name.size() + 1];
|
||||
strcpy(charname, name.c_str());
|
||||
} else {
|
||||
messages.push_back("usage: list/reload/tweak/self or add/init/remove PLAYERNAME");
|
||||
return messages;
|
||||
|
||||
@@ -62,14 +62,23 @@ bool CastSpellAction::Execute(Event event)
|
||||
|
||||
bool CastSpellAction::isPossible()
|
||||
{
|
||||
if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true))
|
||||
if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true)) {
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
LOG_DEBUG("playerbots", "Can cast spell failed. Vehicle. - bot name: {}",
|
||||
bot->GetName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (spell == "mount" && !bot->IsMounted() && !bot->IsInCombat())
|
||||
return true;
|
||||
|
||||
if (spell == "mount" && bot->IsInCombat())
|
||||
{
|
||||
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
|
||||
LOG_DEBUG("playerbots", "Can cast spell failed. Mount. - bot name: {}",
|
||||
bot->GetName());
|
||||
}
|
||||
bot->Dismount();
|
||||
return false;
|
||||
}
|
||||
@@ -118,7 +127,7 @@ CastMeleeSpellAction::CastMeleeSpellAction(PlayerbotAI* botAI, std::string const
|
||||
|
||||
bool CastAuraSpellAction::isUseful()
|
||||
{
|
||||
return GetTarget() && (GetTarget() != nullptr) && (GetTarget() != nullptr) && CastSpellAction::isUseful() && !botAI->HasAura(spell, GetTarget(), true, isOwner);
|
||||
return GetTarget() && (GetTarget() != nullptr) && CastSpellAction::isUseful() && !botAI->HasAura(spell, GetTarget(), false, isOwner);
|
||||
}
|
||||
|
||||
CastEnchantItemAction::CastEnchantItemAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell)
|
||||
|
||||
@@ -222,6 +222,12 @@ std::vector<Item*> InventoryAction::parseItems(std::string const text, IterateIt
|
||||
FindFoodVisitor visitor(bot, 59, text == "conjured drink" || text == "conjured water");
|
||||
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
|
||||
found.insert(visitor.GetResult().begin(), visitor.GetResult().end());
|
||||
|
||||
if (found.empty()) {
|
||||
FindFoodVisitor visitor(bot, 11);
|
||||
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
|
||||
found.insert(visitor.GetResult().begin(), visitor.GetResult().end());
|
||||
}
|
||||
}
|
||||
|
||||
if (text == "mana potion")
|
||||
|
||||
@@ -254,9 +254,8 @@ bool UseItemAction::UseItem(Item* item, ObjectGuid goGuid, Item* itemTarget, Uni
|
||||
if (bot->IsInCombat())
|
||||
return false;
|
||||
|
||||
bot->SetStandState(UNIT_STAND_STATE_SIT);
|
||||
// bot->SetStandState(UNIT_STAND_STATE_SIT);
|
||||
botAI->InterruptSpell();
|
||||
|
||||
float hp = bot->GetHealthPct();
|
||||
float mp = bot->GetPower(POWER_MANA) * 100.0f / bot->GetMaxPower(POWER_MANA);
|
||||
float p = 0.f;
|
||||
@@ -272,17 +271,18 @@ bool UseItemAction::UseItem(Item* item, ObjectGuid goGuid, Item* itemTarget, Uni
|
||||
}
|
||||
else if (isFood)
|
||||
{
|
||||
p = hp;
|
||||
p = std::min(hp, mp);
|
||||
TellConsumableUse(item, "Eating", p);
|
||||
}
|
||||
|
||||
if (!bot->IsInCombat() && !bot->InBattleground())
|
||||
botAI->SetNextCheckDelay(27000.0f * (100 - p) / 100.0f);
|
||||
botAI->SetNextCheckDelay(std::max(10000.0f, 27000.0f * (100 - p) / 100.0f));
|
||||
|
||||
if (!bot->IsInCombat() && bot->InBattleground())
|
||||
botAI->SetNextCheckDelay(20000.0f * (100 - p) / 100.0f);
|
||||
botAI->SetNextCheckDelay(std::max(10000.0f,20000.0f * (100 - p) / 100.0f));
|
||||
|
||||
//botAI->SetNextCheckDelay(27000.0f * (100 - p) / 100.0f);
|
||||
// botAI->SetNextCheckDelay(20000);
|
||||
bot->GetSession()->HandleUseItemOpcode(packet);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -30,6 +30,7 @@ class BloodDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
//creators["hysteria"] = &hysteria;
|
||||
//creators["dancing weapon"] = &dancing_weapon;
|
||||
//creators["dark command"] = &dark_command;
|
||||
creators["taunt spell"] = &dark_command;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -37,7 +38,7 @@ class BloodDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
return new ActionNode("rune strike",
|
||||
/*P*/ NextAction::array(0, new NextAction("frost presence"), nullptr),
|
||||
/*A*/ NextAction::array(0, new NextAction("death coil"), nullptr),
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
@@ -56,6 +57,13 @@ class BloodDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
static ActionNode* dark_command([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("dark command",
|
||||
/*P*/ NextAction::array(0, new NextAction("frost presence"), NULL),
|
||||
/*A*/ NextAction::array(0, new NextAction("death grip"), NULL),
|
||||
/*C*/ NULL);
|
||||
}
|
||||
};
|
||||
|
||||
BloodDKStrategy::BloodDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
|
||||
@@ -65,8 +73,15 @@ BloodDKStrategy::BloodDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
|
||||
|
||||
NextAction** BloodDKStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("melee", ACTION_NORMAL + 2), new NextAction("heart strike", ACTION_NORMAL + 5),
|
||||
new NextAction("death strike", ACTION_NORMAL + 4), new NextAction("rune strike", ACTION_NORMAL + 3), nullptr);
|
||||
return NextAction::array(0,
|
||||
new NextAction("rune strike", ACTION_NORMAL + 7),
|
||||
new NextAction("heart strike", ACTION_NORMAL + 6),
|
||||
new NextAction("icy touch", ACTION_NORMAL + 5),
|
||||
new NextAction("death coil", ACTION_NORMAL + 4),
|
||||
new NextAction("plague strike", ACTION_NORMAL + 3),
|
||||
new NextAction("blood strike", ACTION_NORMAL + 2),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
NULL);
|
||||
}
|
||||
|
||||
void BloodDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
*/
|
||||
|
||||
#include "DKActions.h"
|
||||
#include "Duration.h"
|
||||
#include "GenericSpellActions.h"
|
||||
#include "Playerbots.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
|
||||
NextAction** CastDeathchillAction::getPrerequisites()
|
||||
{
|
||||
@@ -29,3 +33,15 @@ NextAction** CastBloodMeleeSpellAction::getPrerequisites()
|
||||
{
|
||||
return NextAction::merge(NextAction::array(0, new NextAction("blood presence"), nullptr), CastMeleeSpellAction::getPrerequisites());
|
||||
}
|
||||
|
||||
bool CastRaiseDeadAction::Execute(Event event)
|
||||
{
|
||||
bool result = CastBuffSpellAction::Execute(event);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
uint32 spellId = AI_VALUE2(uint32, "spell id", spell);
|
||||
// const SpellInfo *spellInfo = sSpellMgr->GetSpellInfo(spellId);
|
||||
bot->AddSpellCooldown(spellId, 0, 3 * 60 * 1000);
|
||||
return true;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef _PLAYERBOT_DKACTIONS_H
|
||||
#define _PLAYERBOT_DKACTIONS_H
|
||||
|
||||
#include "Event.h"
|
||||
#include "GenericSpellActions.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
@@ -80,16 +81,30 @@ class CastRuneStrikeAction : public CastMeleeSpellAction
|
||||
};
|
||||
|
||||
//debuff
|
||||
BEGIN_DEBUFF_ACTION(CastPestilenceAction, "pestilence")
|
||||
END_SPELL_ACTION()
|
||||
// BEGIN_DEBUFF_ACTION(CastPestilenceAction, "pestilence")
|
||||
// END_SPELL_ACTION()
|
||||
|
||||
class CastPestilenceAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastPestilenceAction(PlayerbotAI* ai) : CastSpellAction(ai, "pestilence") {}
|
||||
ActionThreatType getThreatType() override { return ActionThreatType::None; }
|
||||
};
|
||||
|
||||
|
||||
//debuff
|
||||
BEGIN_DEBUFF_ACTION(CastHowlingBlastAction, "howling blast")
|
||||
END_SPELL_ACTION()
|
||||
|
||||
//debuff it
|
||||
BEGIN_DEBUFF_ACTION(CastIcyTouchAction, "icy touch")
|
||||
END_SPELL_ACTION()
|
||||
// BEGIN_DEBUFF_ACTION(CastIcyTouchAction, "icy touch")
|
||||
// END_SPELL_ACTION()
|
||||
|
||||
class CastIcyTouchAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastIcyTouchAction(PlayerbotAI* ai) : CastSpellAction(ai, "icy touch") {}
|
||||
};
|
||||
|
||||
class CastIcyTouchOnAttackerAction : public CastDebuffSpellOnAttackerAction
|
||||
{
|
||||
@@ -189,13 +204,13 @@ class CastDeathStrikeAction : public CastMeleeSpellAction
|
||||
class CastScourgeStrikeAction : public CastMeleeSpellAction
|
||||
{
|
||||
public:
|
||||
CastScourgeStrikeAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "scorgue strike") { }
|
||||
CastScourgeStrikeAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "scourge strike") { }
|
||||
};
|
||||
|
||||
class CastDeathCoilAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastDeathCoilAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "death coill") { }
|
||||
CastDeathCoilAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "death coil") { }
|
||||
};
|
||||
|
||||
class CastBloodBoilAction : public CastBuffSpellAction
|
||||
@@ -262,6 +277,7 @@ class CastRaiseDeadAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastRaiseDeadAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "raise dead") { }
|
||||
virtual bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class CastKillingMachineAction : public CastBuffSpellAction
|
||||
|
||||
@@ -4,9 +4,24 @@
|
||||
|
||||
#include "DKTriggers.h"
|
||||
#include "Playerbots.h"
|
||||
#include "SharedDefines.h"
|
||||
#include <string>
|
||||
|
||||
bool DKPresenceTrigger::IsActive()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
return !botAI->HasAura("blood presence", target) && !botAI->HasAura("unholy presence", target) && !botAI->HasAura("frost presence", target);
|
||||
}
|
||||
|
||||
bool PestilenceTrigger::IsActive() {
|
||||
if (!SpellTrigger::IsActive()) {
|
||||
return false;
|
||||
}
|
||||
Aura *blood_plague = botAI->GetAura("blood plague", GetTarget(), true, true);
|
||||
Aura *frost_fever = botAI->GetAura("frost fever", GetTarget(), true, true);
|
||||
if ((blood_plague && blood_plague->GetDuration() <= 5000) ||
|
||||
(frost_fever && frost_fever->GetDuration() <= 5000)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -12,19 +12,19 @@ class PlayerbotAI;
|
||||
BUFF_TRIGGER(HornOfWinterTrigger, "horn of winter");
|
||||
BUFF_TRIGGER(BoneShieldTrigger, "bone shield");
|
||||
BUFF_TRIGGER(ImprovedIcyTalonsTrigger, "improved icy talons");
|
||||
DEBUFF_CHECKISOWNER_TRIGGER(PlagueStrikeDebuffTrigger, "plague strike");
|
||||
DEBUFF_CHECKISOWNER_TRIGGER(IcyTouchDebuffTrigger, "icy touch");
|
||||
DEBUFF_CHECKISOWNER_TRIGGER(PlagueStrikeDebuffTrigger, "blood plague");
|
||||
DEBUFF_CHECKISOWNER_TRIGGER(IcyTouchDebuffTrigger, "frost fever");
|
||||
|
||||
class PlagueStrikeDebuffOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
{
|
||||
public:
|
||||
PlagueStrikeDebuffOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, "plague strike", true) { }
|
||||
PlagueStrikeDebuffOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, "blood plague", true) { }
|
||||
};
|
||||
|
||||
class IcyTouchDebuffOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
{
|
||||
public:
|
||||
IcyTouchDebuffOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, "icy touch", true) { }
|
||||
IcyTouchDebuffOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, "frost fever", true) { }
|
||||
};
|
||||
|
||||
class DKPresenceTrigger : public BuffTrigger
|
||||
@@ -63,6 +63,7 @@ class PestilenceTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
PestilenceTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "pestilence") { }
|
||||
virtual bool IsActive() override;
|
||||
};
|
||||
|
||||
class BloodStrikeTrigger : public DebuffTrigger
|
||||
|
||||
@@ -34,7 +34,7 @@ class FrostDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
return new ActionNode("obliterate",
|
||||
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
|
||||
/*A*/ NextAction::array(0, new NextAction("frost strike"), nullptr),
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class FrostDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
return new ActionNode("howling blast",
|
||||
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
|
||||
/*A*/ NextAction::array(0, new NextAction("icy touch"), nullptr),
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
};
|
||||
@@ -70,7 +70,13 @@ FrostDKStrategy::FrostDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
|
||||
|
||||
NextAction** FrostDKStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("melee", ACTION_NORMAL), new NextAction("frost strike", ACTION_NORMAL + 5), new NextAction("obliterate", ACTION_NORMAL + 4), nullptr);
|
||||
return NextAction::array(0,
|
||||
new NextAction("obliterate", ACTION_NORMAL + 5),
|
||||
new NextAction("frost strike", ACTION_NORMAL + 4),
|
||||
// new NextAction("death strike", ACTION_NORMAL + 3),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
void FrostDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
@@ -78,6 +84,7 @@ void FrostDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
GenericDKStrategy::InitTriggers(triggers);
|
||||
|
||||
triggers.push_back(new TriggerNode("empower weapon", NextAction::array(0, new NextAction("empower weapon", ACTION_NORMAL + 4), nullptr)));
|
||||
triggers.push_back(new TriggerNode("pestilence", NextAction::array(0, new NextAction("pestilence", ACTION_HIGH + 9), NULL)));
|
||||
}
|
||||
|
||||
void FrostDKAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -54,7 +54,7 @@ class GenericDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
return new ActionNode("death coil",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ NextAction::array(0, new NextAction("death strike"), nullptr),
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class GenericDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
return new ActionNode("heart strike",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ NextAction::array(0, new NextAction("blood strike"), nullptr),
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
@@ -158,21 +158,20 @@ void GenericDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
MeleeCombatStrategy::InitTriggers(triggers);
|
||||
|
||||
triggers.push_back(new TriggerNode("high aoe", NextAction::array(0, new NextAction("anti magic shell", ACTION_NORMAL + 3), nullptr)));
|
||||
triggers.push_back(new TriggerNode("death coil", NextAction::array(0, new NextAction("death coil", ACTION_NORMAL + 3), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("death coil", NextAction::array(0, new NextAction("death coil", ACTION_NORMAL + 3), nullptr)));
|
||||
triggers.push_back(new TriggerNode("critical aoe heal", NextAction::array(0, new NextAction("anti magic zone", ACTION_EMERGENCY + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("raise dead", ACTION_NORMAL + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode("mind freeze", NextAction::array(0, new NextAction("mind freeze", ACTION_HIGH + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("bone shield", NextAction::array(0, new NextAction("bone shield", ACTION_NORMAL + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("horn of winter", NextAction::array(0, new NextAction("horn of winter", ACTION_NORMAL + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("mind freeze on enemy healer", NextAction::array(0, new NextAction("mind freeze on enemy healer", ACTION_HIGH + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("icy touch", ACTION_NORMAL + 9),
|
||||
new NextAction("death grip", ACTION_NORMAL + 9), new NextAction("reach melee", ACTION_NORMAL + 8), nullptr)));
|
||||
triggers.push_back(new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), nullptr)));
|
||||
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("icebound fortitude", ACTION_HIGH + 5), new NextAction("rune tap", ACTION_HIGH + 4), nullptr)));
|
||||
triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("rune tap", ACTION_NORMAL + 4), new NextAction("death strike", ACTION_NORMAL + 3), nullptr)));
|
||||
triggers.push_back(new TriggerNode("icy touch on attacker", NextAction::array(0, new NextAction("icy touch", ACTION_HIGH + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("icy touch", NextAction::array(0, new NextAction("icy touch", ACTION_HIGH + 1), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("icy touch on attacker", NextAction::array(0, new NextAction("icy touch on attacker", ACTION_HIGH + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("plague strike", NextAction::array(0, new NextAction("plague strike", ACTION_HIGH + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("plague strike on attacker", NextAction::array(0, new NextAction("plague strike", ACTION_HIGH + 1), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("plague strike on attacker", NextAction::array(0, new NextAction("plague strike on attacker", ACTION_HIGH + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("high aoe", NextAction::array(0, new NextAction("unholy blight", ACTION_NORMAL + 6), new NextAction("death and decay", ACTION_NORMAL + 5),
|
||||
new NextAction("pestilence", ACTION_NORMAL + 4), new NextAction("blood boil", ACTION_NORMAL + 3), nullptr)));
|
||||
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("death and decay", ACTION_NORMAL + 5),
|
||||
|
||||
@@ -33,7 +33,7 @@ class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
static ActionNode* death_strike([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("death strike",
|
||||
/*P*/ NextAction::array(0, new NextAction("unholy pressence"), nullptr),
|
||||
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
static ActionNode* corpse_explosion([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("corpse explosion",
|
||||
/*P*/ NextAction::array(0, new NextAction("unholy pressence"), nullptr),
|
||||
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
@@ -49,15 +49,22 @@ class UnholyDKStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
static ActionNode* scourge_strike([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("scourge strike",
|
||||
/*P*/ NextAction::array(0, new NextAction("unholy pressence"), nullptr),
|
||||
/*A*/ NextAction::array(0, new NextAction("death strike"), nullptr),
|
||||
/*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr),
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
NextAction** UnholyDKStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("melee", ACTION_NORMAL), new NextAction("scourge strike" , ACTION_NORMAL + 3), nullptr);
|
||||
return NextAction::array(0,
|
||||
new NextAction("scourge strike", ACTION_NORMAL + 6),
|
||||
new NextAction("blood strike", ACTION_NORMAL + 5),
|
||||
new NextAction("death coil", ACTION_NORMAL + 4),
|
||||
new NextAction("plague strike", ACTION_NORMAL + 3),
|
||||
new NextAction("icy touch", ACTION_NORMAL + 2),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
NULL);
|
||||
}
|
||||
|
||||
void UnholyDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
|
||||
#include "GenericTriggers.h"
|
||||
#include "BattlegroundWS.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "Playerbots.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include <string>
|
||||
|
||||
bool LowManaTrigger::IsActive()
|
||||
{
|
||||
@@ -18,7 +22,20 @@ bool MediumManaTrigger::IsActive()
|
||||
|
||||
bool NoPetTrigger::IsActive()
|
||||
{
|
||||
return (!AI_VALUE(Unit*, "pet target")) && (!bot->GetGuardianPet()) && (!bot->GetFirstControlled()) && (!AI_VALUE2(bool, "mounted", "self target"));
|
||||
// Guardian* gp = bot->GetGuardianPet();
|
||||
// bot->getpet
|
||||
// if (gp) {
|
||||
// bot->Yell("Guardian name: " + gp->GetName(), LANG_UNIVERSAL);
|
||||
// }
|
||||
// Minion* minion = bot->GetFirstMinion();
|
||||
// if (minion) {
|
||||
// bot->Yell("has minion: " + minion->GetName(), LANG_UNIVERSAL);
|
||||
// }
|
||||
return (bot->GetMinionGUID().IsEmpty()) &&
|
||||
(!AI_VALUE(Unit*, "pet target")) &&
|
||||
(!bot->GetGuardianPet()) &&
|
||||
(!bot->GetFirstControlled()) &&
|
||||
(!AI_VALUE2(bool, "mounted", "self target"));
|
||||
}
|
||||
|
||||
bool HasPetTrigger::IsActive() {
|
||||
@@ -193,7 +210,7 @@ bool TargetInSightTrigger::IsActive()
|
||||
|
||||
bool DebuffTrigger::IsActive()
|
||||
{
|
||||
return BuffTrigger::IsActive() && AI_VALUE2(uint8, "health", GetTargetName()) > 15;
|
||||
return BuffTrigger::IsActive() && AI_VALUE2(uint8, "health", GetTargetName()) > life_bound;
|
||||
}
|
||||
|
||||
bool SpellTrigger::IsActive()
|
||||
@@ -331,7 +348,7 @@ bool AttackerCountTrigger::IsActive()
|
||||
|
||||
bool HasAuraTrigger::IsActive()
|
||||
{
|
||||
return botAI->HasAura(getName(), GetTarget());
|
||||
return botAI->HasAura(getName(), GetTarget(), false, false, -1, true);
|
||||
}
|
||||
|
||||
bool TimerTrigger::IsActive()
|
||||
|
||||
@@ -306,10 +306,12 @@ class TargetInSightTrigger : public Trigger
|
||||
class DebuffTrigger : public BuffTrigger
|
||||
{
|
||||
public:
|
||||
DebuffTrigger(PlayerbotAI* botAI, std::string const spell, int32 checkInterval = 1, bool checkIsOwner = false) : BuffTrigger(botAI, spell, checkInterval, checkIsOwner) { }
|
||||
DebuffTrigger(PlayerbotAI* botAI, std::string const spell, int32 checkInterval = 1, bool checkIsOwner = false, float life_bound = 0.25) : BuffTrigger(botAI, spell, checkInterval, checkIsOwner), life_bound(life_bound) { }
|
||||
|
||||
std::string const GetTargetName() override { return "current target"; }
|
||||
bool IsActive() override;
|
||||
protected:
|
||||
float life_bound;
|
||||
};
|
||||
|
||||
class DebuffOnAttackerTrigger : public DebuffTrigger
|
||||
|
||||
@@ -11,6 +11,8 @@ class DpsWarlockStrategyActionNodeFactory : public NamedObjectFactory<ActionNode
|
||||
DpsWarlockStrategyActionNodeFactory()
|
||||
{
|
||||
creators["shadow bolt"] = &shadow_bolt;
|
||||
creators["unstable affliction"] = &unstable_affliction;
|
||||
creators["unstable affliction on attacker"] = &unstable_affliction_on_attacker;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -21,6 +23,20 @@ class DpsWarlockStrategyActionNodeFactory : public NamedObjectFactory<ActionNode
|
||||
/*A*/ NextAction::array(0, new NextAction("shoot"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
static ActionNode* unstable_affliction(PlayerbotAI* ai)
|
||||
{
|
||||
return new ActionNode ("unstable affliction",
|
||||
/*P*/ NULL,
|
||||
/*A*/ NextAction::array(0, new NextAction("immolate"), NULL),
|
||||
/*C*/ NULL);
|
||||
}
|
||||
static ActionNode* unstable_affliction_on_attacker(PlayerbotAI* ai)
|
||||
{
|
||||
return new ActionNode ("unstable affliction on attacker",
|
||||
/*P*/ NULL,
|
||||
/*A*/ NextAction::array(0, new NextAction("immolate on attacker"), NULL),
|
||||
/*C*/ NULL);
|
||||
}
|
||||
};
|
||||
|
||||
DpsWarlockStrategy::DpsWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrategy(botAI)
|
||||
@@ -30,7 +46,11 @@ DpsWarlockStrategy::DpsWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrat
|
||||
|
||||
NextAction** DpsWarlockStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("incinirate", 10.0f), new NextAction("shadow bolt", 10.0f), nullptr);
|
||||
return NextAction::array(0,
|
||||
new NextAction("haunt", 14.0f),
|
||||
new NextAction("demonic empowerment", 13.0f),
|
||||
new NextAction("shadow bolt", 10.0f),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void DpsWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
@@ -38,19 +58,39 @@ void DpsWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
GenericWarlockStrategy::InitTriggers(triggers);
|
||||
|
||||
triggers.push_back(new TriggerNode("backlash", NextAction::array(0, new NextAction("shadow bolt", 20.0f), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"haunt",
|
||||
NextAction::array(0, new NextAction("haunt", 26.0f), NULL)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"shadow trance",
|
||||
NextAction::array(0, new NextAction("shadow bolt", 15.0f), NULL)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"backlash",
|
||||
NextAction::array(0, new NextAction("shadow bolt", 15.0f), NULL)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"molten core",
|
||||
NextAction::array(0, new NextAction("incinerate", 15.0f), NULL)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"decimation",
|
||||
NextAction::array(0, new NextAction("soul fire", 16.0f), NULL)));
|
||||
}
|
||||
|
||||
void DpsAoeWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("rain of fire", 37.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("corruption on attacker", NextAction::array(0, new NextAction("corruption on attacker", 27.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("curse of agony on attacker", NextAction::array(0, new NextAction("curse of agony on attacker", 28.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("siphon life on attacker", NextAction::array(0, new NextAction("siphon life on attacker", 29.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("curse of agony on attacker", NextAction::array(0, new NextAction("curse of agony on attacker", 28.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("unstable affliction on attacker", NextAction::array(0, new NextAction("unstable affliction on attacker", 22.0f), NULL)));
|
||||
}
|
||||
|
||||
void DpsWarlockDebuffStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("corruption", NextAction::array(0, new NextAction("corruption", 22.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("curse of agony", NextAction::array(0, new NextAction("curse of agony", 21.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("siphon life", NextAction::array(0, new NextAction("siphon life", 23.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("curse of agony", NextAction::array(0, new NextAction("curse of agony", 20.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("unstable affliction", NextAction::array(0, new NextAction("unstable affliction", 21.0f), NULL)));
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ class GenericWarlockNonCombatStrategyActionNodeFactory : public NamedObjectFacto
|
||||
creators["summon voidwalker"] = &summon_voidwalker;
|
||||
creators["summon felguard"] = &summon_felguard;
|
||||
creators["summon succubus"] = &summon_succubus;
|
||||
creators["summon felhunter"] = &summon_felhunter;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -57,6 +58,14 @@ class GenericWarlockNonCombatStrategyActionNodeFactory : public NamedObjectFacto
|
||||
/*A*/ NextAction::array(0, new NextAction("summon voidwalker"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
static ActionNode* summon_felhunter([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("summon felhunter",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ NextAction::array(0, new NextAction("summon imp"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
GenericWarlockNonCombatStrategy::GenericWarlockNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI)
|
||||
@@ -69,12 +78,38 @@ void GenericWarlockNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& tr
|
||||
NonCombatStrategy::InitTriggers(triggers);
|
||||
|
||||
triggers.push_back(new TriggerNode("demon armor", NextAction::array(0, new NextAction("fel armor", 21.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
|
||||
}
|
||||
|
||||
void WarlockPetStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felguard", 60.0f), nullptr)));
|
||||
// TODO Warlock pets
|
||||
|
||||
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
|
||||
}
|
||||
|
||||
SummonImpStrategy::SummonImpStrategy(PlayerbotAI* ai): NonCombatStrategy(ai) {}
|
||||
|
||||
void SummonImpStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode(
|
||||
"no pet",
|
||||
NextAction::array(0, new NextAction("summon imp", 11.0f), NULL)));
|
||||
}
|
||||
|
||||
SummonFelguardStrategy::SummonFelguardStrategy(PlayerbotAI* ai): NonCombatStrategy(ai) {}
|
||||
|
||||
void SummonFelguardStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode(
|
||||
"no pet",
|
||||
NextAction::array(0, new NextAction("summon felguard", 11.0f), NULL)));
|
||||
}
|
||||
|
||||
SummonFelhunterStrategy::SummonFelhunterStrategy(PlayerbotAI* ai): NonCombatStrategy(ai) {}
|
||||
|
||||
void SummonFelhunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode(
|
||||
"no pet",
|
||||
NextAction::array(0, new NextAction("summon felhunter", 11.0f), NULL)));
|
||||
}
|
||||
@@ -27,4 +27,31 @@ class WarlockPetStrategy : public Strategy
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SummonImpStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SummonImpStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "bhealth"; }
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SummonFelguardStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SummonFelguardStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "bdps"; }
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
class SummonFelhunterStrategy : public NonCombatStrategy
|
||||
{
|
||||
public:
|
||||
SummonFelhunterStrategy(PlayerbotAI* ai);
|
||||
virtual std::string const getName() override { return "bmana"; }
|
||||
public:
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,11 +45,12 @@ void GenericWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
CombatStrategy::InitTriggers(triggers);
|
||||
|
||||
triggers.push_back(new TriggerNode("shadow trance", NextAction::array(0, new NextAction("shadow bolt", 20.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("drain life", 40.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("medium mana", NextAction::array(0, new NextAction("life tap", ACTION_EMERGENCY + 5), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("shadow trance", NextAction::array(0, new NextAction("shadow bolt", 20.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("drain life", 40.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("life tap", ACTION_EMERGENCY + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode("target critical health", NextAction::array(0, new NextAction("drain soul", 30.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("immolate", NextAction::array(0, new NextAction("immolate", 13.0f), new NextAction("conflagrate", 13.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("immolate", NextAction::array(0, new NextAction("immolate", 13.0f), new NextAction("conflagrate", 13.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("enemy too close for spell", NextAction::array(0, new NextAction("flee", 49.0f), NULL)));
|
||||
}
|
||||
|
||||
void WarlockBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -13,6 +13,7 @@ class GenericWarlockStrategyActionNodeFactory : public NamedObjectFactory<Action
|
||||
creators["summon voidwalker"] = &summon_voidwalker;
|
||||
creators["summon felguard"] = &summon_felguard;
|
||||
creators["summon succubus"] = &summon_succubus;
|
||||
creators["summon felhunter"] = &summon_felhunter;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -39,6 +40,14 @@ class GenericWarlockStrategyActionNodeFactory : public NamedObjectFactory<Action
|
||||
/*A*/ NextAction::array(0, new NextAction("summon voidwalker"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
static ActionNode* summon_felhunter([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("summon felhunter",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ NextAction::array(0, new NextAction("summon imp"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
TankWarlockStrategy::TankWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrategy(botAI)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
bool CastDrainSoulAction::isUseful()
|
||||
{
|
||||
return AI_VALUE2(uint32, "item count", "soul shard") < uint32(AI_VALUE(uint8, "bag space") * 0.2);
|
||||
return AI_VALUE2(uint32, "item count", "soul shard") < 10;
|
||||
}
|
||||
|
||||
Value<Unit*>* CastBanishAction::GetTargetValue()
|
||||
|
||||
@@ -93,6 +93,12 @@ class CastSummonFelguardAction : public CastBuffSpellAction
|
||||
CastSummonFelguardAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "summon felguard") { }
|
||||
};
|
||||
|
||||
class CastSummonFelhunterAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastSummonFelhunterAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "summon felhunter") { }
|
||||
};
|
||||
|
||||
class CastSummonImpAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
@@ -218,4 +224,45 @@ class CastSiphonLifeOnAttackerAction : public CastDebuffSpellOnAttackerAction
|
||||
CastSiphonLifeOnAttackerAction(PlayerbotAI* botAI) : CastDebuffSpellOnAttackerAction(botAI, "siphon life") { }
|
||||
};
|
||||
|
||||
class CastUnstableAfflictionAction: public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastUnstableAfflictionAction(PlayerbotAI* ai) : CastDebuffSpellAction(ai, "unstable affliction", true) {}
|
||||
};
|
||||
|
||||
class CastHauntAction: public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastHauntAction(PlayerbotAI* ai) : CastSpellAction(ai, "haunt") {}
|
||||
};
|
||||
|
||||
class CastDemonicEmpowermentAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastDemonicEmpowermentAction(PlayerbotAI* ai) : CastBuffSpellAction(ai, "demonic empowerment") {}
|
||||
};
|
||||
|
||||
class CastMetamorphosisAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastMetamorphosisAction(PlayerbotAI* ai) : CastBuffSpellAction(ai, "metamorphosis") {}
|
||||
};
|
||||
|
||||
class CastUnstableAfflictionOnAttackerAction : public CastDebuffSpellOnAttackerAction
|
||||
{
|
||||
public:
|
||||
CastUnstableAfflictionOnAttackerAction(PlayerbotAI* ai) : CastDebuffSpellOnAttackerAction(ai, "unstable affliction", true) {}
|
||||
};
|
||||
|
||||
class CastSoulFireAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastSoulFireAction(PlayerbotAI* ai) : CastSpellAction(ai, "soul fire") {}
|
||||
};
|
||||
|
||||
class CastIncinerateAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastIncinerateAction(PlayerbotAI* ai) : CastSpellAction(ai, "incinerate") {}
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "WarlockAiObjectContext.h"
|
||||
#include "DpsWarlockStrategy.h"
|
||||
#include "GenericWarlockNonCombatStrategy.h"
|
||||
#include "Strategy.h"
|
||||
#include "TankWarlockStrategy.h"
|
||||
#include "WarlockActions.h"
|
||||
#include "WarlockTriggers.h"
|
||||
@@ -51,6 +52,21 @@ class WarlockCombatStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
static Strategy* dps(PlayerbotAI* botAI) { return new DpsWarlockStrategy(botAI); }
|
||||
};
|
||||
|
||||
class NonCombatBuffStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
{
|
||||
public:
|
||||
NonCombatBuffStrategyFactoryInternal() : NamedObjectContext<Strategy>(false, true)
|
||||
{
|
||||
creators["bdps"] = &NonCombatBuffStrategyFactoryInternal::felguard;
|
||||
creators["bmana"] = &NonCombatBuffStrategyFactoryInternal::felhunter;
|
||||
creators["bhealth"] = &NonCombatBuffStrategyFactoryInternal::imp;
|
||||
}
|
||||
private:
|
||||
static Strategy* imp(PlayerbotAI* ai) { return new SummonImpStrategy(ai); }
|
||||
static Strategy* felhunter(PlayerbotAI* ai) { return new SummonFelhunterStrategy(ai); }
|
||||
static Strategy* felguard(PlayerbotAI* ai) { return new SummonFelguardStrategy(ai); }
|
||||
};
|
||||
|
||||
class WarlockTriggerFactoryInternal : public NamedObjectContext<Trigger>
|
||||
{
|
||||
public:
|
||||
@@ -73,6 +89,15 @@ class WarlockTriggerFactoryInternal : public NamedObjectContext<Trigger>
|
||||
creators["amplify curse"] = &WarlockTriggerFactoryInternal::amplify_curse;
|
||||
creators["siphon life"] = &WarlockTriggerFactoryInternal::siphon_life;
|
||||
creators["siphon life on attacker"] = &WarlockTriggerFactoryInternal::siphon_life_on_attacker;
|
||||
|
||||
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["molten core"] = &WarlockTriggerFactoryInternal::molten_core;
|
||||
creators["metamorphosis"] = &WarlockTriggerFactoryInternal::metamorphosis;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -93,6 +118,13 @@ class WarlockTriggerFactoryInternal : public NamedObjectContext<Trigger>
|
||||
static Trigger* backlash(PlayerbotAI* botAI) { return new BacklashTrigger(botAI); }
|
||||
static Trigger* fear(PlayerbotAI* botAI) { return new FearTrigger(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* molten_core(PlayerbotAI* ai) { return new MoltenCoreTrigger(ai); }
|
||||
static Trigger* metamorphosis(PlayerbotAI* ai) { return new MetamorphosisTrigger(ai); }
|
||||
};
|
||||
|
||||
class WarlockAiObjectContextInternal : public NamedObjectContext<Action>
|
||||
@@ -109,6 +141,7 @@ class WarlockAiObjectContextInternal : public NamedObjectContext<Action>
|
||||
creators["spellstone"] = &WarlockAiObjectContextInternal::spellstone;
|
||||
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["immolate"] = &WarlockAiObjectContextInternal::immolate;
|
||||
@@ -133,6 +166,14 @@ class WarlockAiObjectContextInternal : public NamedObjectContext<Action>
|
||||
creators["incinirate"] = &WarlockAiObjectContextInternal::incinirate;
|
||||
creators["conflagrate"] = &WarlockAiObjectContextInternal::conflagrate;
|
||||
creators["amplify curse"] = &WarlockAiObjectContextInternal::amplify_curse;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -153,6 +194,7 @@ class WarlockAiObjectContextInternal : public NamedObjectContext<Action>
|
||||
static Action* spellstone(PlayerbotAI* botAI) { return new UseSpellItemAction(botAI, "spellstone", true); }
|
||||
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* corruption(PlayerbotAI* botAI) { return new CastCorruptionAction(botAI); }
|
||||
static Action* corruption_on_attacker(PlayerbotAI* botAI) { return new CastCorruptionOnAttackerAction(botAI); }
|
||||
static Action* siphon_life(PlayerbotAI* botAI) { return new CastSiphonLifeAction(botAI); }
|
||||
@@ -169,12 +211,20 @@ class WarlockAiObjectContextInternal : public NamedObjectContext<Action>
|
||||
static Action* rain_of_fire(PlayerbotAI* botAI) { return new CastRainOfFireAction(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* incinerate(PlayerbotAI* ai) { return new CastIncinerateAction(ai); }
|
||||
};
|
||||
|
||||
WarlockAiObjectContext::WarlockAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI)
|
||||
{
|
||||
strategyContexts.Add(new WarlockStrategyFactoryInternal());
|
||||
strategyContexts.Add(new WarlockCombatStrategyFactoryInternal());
|
||||
strategyContexts.Add(new NonCombatBuffStrategyFactoryInternal());
|
||||
actionContexts.Add(new WarlockAiObjectContextInternal());
|
||||
triggerContexts.Add(new WarlockTriggerFactoryInternal());
|
||||
}
|
||||
|
||||
@@ -20,3 +20,25 @@ bool WarlockConjuredItemTrigger::IsActive()
|
||||
{
|
||||
return ItemCountTrigger::IsActive() && AI_VALUE2(uint32, "item count", "soul shard") > 0;
|
||||
}
|
||||
|
||||
bool ImmolateOnAttackerTrigger::IsActive()
|
||||
{
|
||||
return DebuffOnAttackerTrigger::IsActive() &&
|
||||
// !botAI->HasAura("immolate", GetTarget(), false, true) &&
|
||||
!botAI->HasAura("unstable affliction", GetTarget(), false, true);
|
||||
}
|
||||
|
||||
bool UnstableAfflictionTrigger::IsActive()
|
||||
{
|
||||
return DebuffTrigger::IsActive() &&
|
||||
!botAI->HasAura("immolate", GetTarget(), false, true);
|
||||
// !botAI->HasAura("unstable affliction", GetTarget(), false, true);
|
||||
}
|
||||
|
||||
bool UnstableAfflictionOnAttackerTrigger::IsActive()
|
||||
{
|
||||
return DebuffOnAttackerTrigger::IsActive() &&
|
||||
!botAI->HasAura("immolate", GetTarget(), false, true);
|
||||
// !botAI->HasAura("unstable affliction", GetTarget(), false, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ DEBUFF_CHECKISOWNER_TRIGGER(SiphonLifeTrigger, "siphon life");
|
||||
class CorruptionOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
{
|
||||
public:
|
||||
CorruptionOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, "corruption") { }
|
||||
CorruptionOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, "corruption", true) { }
|
||||
};
|
||||
|
||||
class CastCurseOfAgonyOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
@@ -49,6 +49,13 @@ class SiphonLifeOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
|
||||
DEBUFF_CHECKISOWNER_TRIGGER(ImmolateTrigger, "immolate");
|
||||
|
||||
class ImmolateOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
{
|
||||
public:
|
||||
ImmolateOnAttackerTrigger(PlayerbotAI* ai) : DebuffOnAttackerTrigger(ai, "immolate") {}
|
||||
virtual bool IsActive();
|
||||
};
|
||||
|
||||
class ShadowTranceTrigger : public HasAuraTrigger
|
||||
{
|
||||
public:
|
||||
@@ -105,4 +112,41 @@ class AmplifyCurseTrigger : public BuffTrigger
|
||||
AmplifyCurseTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "amplify curse") { }
|
||||
};
|
||||
|
||||
class UnstableAfflictionTrigger : public DebuffTrigger // SpellTrigger
|
||||
{
|
||||
public:
|
||||
UnstableAfflictionTrigger(PlayerbotAI* ai) : DebuffTrigger(ai, "unstable affliction", 1, true) {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class UnstableAfflictionOnAttackerTrigger : public DebuffOnAttackerTrigger
|
||||
{
|
||||
public:
|
||||
UnstableAfflictionOnAttackerTrigger(PlayerbotAI* ai) : DebuffOnAttackerTrigger(ai, "unstable affliction", true) {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class HauntTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
HauntTrigger(PlayerbotAI* ai) : DebuffTrigger(ai, "haunt", 1, true, 0) {}
|
||||
};
|
||||
|
||||
class DecimationTrigger : public HasAuraTrigger
|
||||
{
|
||||
public:
|
||||
DecimationTrigger(PlayerbotAI* ai) : HasAuraTrigger(ai, "decimation") {}
|
||||
};
|
||||
|
||||
class MoltenCoreTrigger : public HasAuraTrigger
|
||||
{
|
||||
public:
|
||||
MoltenCoreTrigger(PlayerbotAI* ai) : HasAuraTrigger(ai, "molten core") {}
|
||||
};
|
||||
|
||||
class MetamorphosisTrigger : public BoostTrigger
|
||||
{
|
||||
public:
|
||||
MetamorphosisTrigger(PlayerbotAI* ai) : BoostTrigger(ai, "metamorphosis") {}
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user