warlock and dk strategy port

This commit is contained in:
Yunfan Li
2023-06-03 14:01:20 +08:00
parent a44b310c0a
commit 0f483047e5
27 changed files with 562 additions and 88 deletions

View File

@@ -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)

View File

@@ -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");

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)

View File

@@ -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")

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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),

View File

@@ -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)

View File

@@ -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()

View File

@@ -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

View File

@@ -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)));
}

View File

@@ -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)));
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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()

View File

@@ -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

View File

@@ -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());
}

View File

@@ -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);
}

View File

@@ -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