diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index e7233c2a..624cce51 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -1203,15 +1203,16 @@ AiPlayerbot.PremadeSpecLink.2.5.80 = -1532013022-05230250203331322133201321 # AiPlayerbot.PremadeSpecName.3.0 = bm pve -AiPlayerbot.PremadeSpecGlyph.3.0 = 42912,43350,42902,43351,43338,45732 -AiPlayerbot.PremadeSpecLink.3.0.60 = 51200201505112243110531051 -AiPlayerbot.PremadeSpecLink.3.0.80 = 51200201505112243120531251-025305101 +AiPlayerbot.PremadeSpecGlyph.3.0 = 42912,43350,42902,43351,43338,42914 +AiPlayerbot.PremadeSpecLink.3.0.40 = 512002015051122301 +AiPlayerbot.PremadeSpecLink.3.0.60 = 51200201505112233110531151 +AiPlayerbot.PremadeSpecLink.3.0.80 = 51200201505112243130531351-005305101 AiPlayerbot.PremadeSpecName.3.1 = mm pve -AiPlayerbot.PremadeSpecGlyph.3.1 = 42912,43350,42914,43351,43338,45732 -AiPlayerbot.PremadeSpecLink.3.1.60 = -025315101030013233125031051 -AiPlayerbot.PremadeSpecLink.3.1.80 = 502-025335101030013233135031351-5000002 +AiPlayerbot.PremadeSpecGlyph.3.1 = 42912,43350,45625,43351,43338,42914 +AiPlayerbot.PremadeSpecLink.3.1.60 = -035305101030013233115031151 +AiPlayerbot.PremadeSpecLink.3.1.80 = 502-035305101230013233135031351-5000002 AiPlayerbot.PremadeSpecName.3.2 = surv pve -AiPlayerbot.PremadeSpecGlyph.3.2 = 42912,43350,45731,43351,43338,45732 +AiPlayerbot.PremadeSpecGlyph.3.2 = 45733,43350,45731,43351,43338,45732 AiPlayerbot.PremadeSpecLink.3.2.60 = --5000032500033330502135201311 AiPlayerbot.PremadeSpecLink.3.2.80 = -005305101-5000032500033330532135301321 AiPlayerbot.PremadeSpecName.3.3 = bm pvp diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index b6693095..08cdc9a3 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -367,12 +367,14 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa } break; case CLASS_HUNTER: - engine->addStrategiesNoInit("dps", "aoe", "bdps", "dps assist", nullptr); - engine->addStrategy("dps debuff", false); - // if (tab == HUNTER_TAB_SURVIVAL) - // { - // engine->addStrategy("trap weave", false); - // } + if (tab == 0) // Beast Mastery + engine->addStrategiesNoInit("bm", "bm aoe", nullptr); + else if (tab == 1) // Marksmanship + engine->addStrategiesNoInit("mm", "mm aoe", nullptr); + else if (tab == 2) // Survival + engine->addStrategiesNoInit("surv", "surv aoe", "trap weave", nullptr); + + engine->addStrategiesNoInit("cc", "dps assist", nullptr); break; case CLASS_ROGUE: if (tab == ROGUE_TAB_ASSASSINATION || tab == ROGUE_TAB_SUBTLETY) diff --git a/src/strategy/hunter/BeastMasteryHunterStrategy.cpp b/src/strategy/hunter/BeastMasteryHunterStrategy.cpp new file mode 100644 index 00000000..787f95b4 --- /dev/null +++ b/src/strategy/hunter/BeastMasteryHunterStrategy.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016+ AzerothCore , 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 "BeastMasteryHunterStrategy.h" +#include "Playerbots.h" + +// ===== Action Node Factory ===== +class BeastMasteryHunterStrategyActionNodeFactory : public NamedObjectFactory +{ +public: + BeastMasteryHunterStrategyActionNodeFactory() + { + creators["auto shot"] = &auto_shot; + creators["kill command"] = &kill_command; + creators["kill shot"] = &kill_shot; + creators["viper sting"] = &viper_sting; + creators["serpent sting"] = serpent_sting; + creators["aimed shot"] = &aimed_shot; + creators["arcane shot"] = &arcane_shot; + creators["steady shot"] = &steady_shot; + creators["multi-shot"] = &multi_shot; + creators["volley"] = &volley; + } + +private: + static ActionNode* auto_shot(PlayerbotAI*) { return new ActionNode("auto shot", nullptr, nullptr, nullptr); } + static ActionNode* kill_command(PlayerbotAI*) { return new ActionNode("kill command", nullptr, nullptr, nullptr); } + static ActionNode* kill_shot(PlayerbotAI*) { return new ActionNode("kill shot", nullptr, nullptr, nullptr); } + static ActionNode* viper_sting(PlayerbotAI*) { return new ActionNode("viper sting", nullptr, nullptr, nullptr); } + static ActionNode* serpent_sting(PlayerbotAI*) { return new ActionNode("serpent sting", nullptr, nullptr, nullptr); } + static ActionNode* aimed_shot(PlayerbotAI*) { return new ActionNode("aimed shot", nullptr, nullptr, nullptr); } + static ActionNode* arcane_shot(PlayerbotAI*) { return new ActionNode("arcane shot", nullptr, nullptr, nullptr); } + static ActionNode* steady_shot(PlayerbotAI*) { return new ActionNode("steady shot", nullptr, nullptr, nullptr); } + static ActionNode* multi_shot(PlayerbotAI*) { return new ActionNode("multi shot", nullptr, nullptr, nullptr); } + static ActionNode* volley(PlayerbotAI*) { return new ActionNode("volley", nullptr, nullptr, nullptr); } +}; + +// ===== Single Target Strategy ===== +BeastMasteryHunterStrategy::BeastMasteryHunterStrategy(PlayerbotAI* botAI) : GenericHunterStrategy(botAI) +{ + actionNodeFactories.Add(new BeastMasteryHunterStrategyActionNodeFactory()); +} + +// ===== Default Actions ===== +NextAction** BeastMasteryHunterStrategy::getDefaultActions() +{ + return NextAction::array(0, new NextAction("bestial wrath", 19.0f), + new NextAction("kill command", 5.7f), + new NextAction("kill shot", 5.6f), + new NextAction("serpent sting", 5.5f), + new NextAction("aimed shot", 5.4f), + new NextAction("arcane shot", 5.3f), + new NextAction("steady shot", 5.2f), + new NextAction("auto shot", 5.1f), nullptr); +} + +// ===== Trigger Initialization === +void BeastMasteryHunterStrategy::InitTriggers(std::vector& triggers) +{ + GenericHunterStrategy::InitTriggers(triggers); + triggers.push_back(new TriggerNode("intimidation", NextAction::array(0, new NextAction("intimidation", 40.0f), nullptr))); + triggers.push_back(new TriggerNode("kill command", NextAction::array(0, new NextAction("kill command", 18.5f), nullptr))); + triggers.push_back(new TriggerNode("target critical health", NextAction::array(0, new NextAction("kill shot", 18.0f), nullptr))); + triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 17.5f), nullptr))); + triggers.push_back(new TriggerNode("no stings", NextAction::array(0, new NextAction("serpent sting", 17.0f), nullptr))); + triggers.push_back(new TriggerNode("serpent sting on attacker", NextAction::array(0, new NextAction("serpent sting on attacker", 16.5f), nullptr))); +} + +// ===== AoE Strategy, 2/3+ enemies ===== +BeastMasteryHunterAoeStrategy::BeastMasteryHunterAoeStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {} + +void BeastMasteryHunterAoeStrategy::InitTriggers(std::vector& triggers) +{ + triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("volley", 22.0f), nullptr))); + triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("multi-shot", 21.0f), nullptr))); +} diff --git a/src/strategy/hunter/BeastMasteryHunterStrategy.h b/src/strategy/hunter/BeastMasteryHunterStrategy.h new file mode 100644 index 00000000..78e99214 --- /dev/null +++ b/src/strategy/hunter/BeastMasteryHunterStrategy.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2016+ AzerothCore , 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. + */ + +#ifndef _PLAYERBOT_BEASTMASTERYHUNTERSTRATEGY_H +#define _PLAYERBOT_BEASTMASTERYHUNTERSTRATEGY_H + +#include "GenericHunterStrategy.h" +#include "CombatStrategy.h" + +class PlayerbotAI; + +class BeastMasteryHunterStrategy : public GenericHunterStrategy +{ +public: + BeastMasteryHunterStrategy(PlayerbotAI* botAI); + + void InitTriggers(std::vector& triggers) override; + std::string const getName() override { return "bm"; } + NextAction** getDefaultActions() override; +}; + +class BeastMasteryHunterAoeStrategy : public CombatStrategy +{ +public: + BeastMasteryHunterAoeStrategy(PlayerbotAI* botAI); + + void InitTriggers(std::vector& triggers) override; + std::string const getName() override { return "bm aoe"; } +}; +#endif diff --git a/src/strategy/hunter/DpsHunterStrategy.cpp b/src/strategy/hunter/DpsHunterStrategy.cpp deleted file mode 100644 index b8709378..00000000 --- a/src/strategy/hunter/DpsHunterStrategy.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2016+ AzerothCore , 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 "DpsHunterStrategy.h" - -#include "Playerbots.h" - -class DpsHunterStrategyActionNodeFactory : public NamedObjectFactory -{ -public: - DpsHunterStrategyActionNodeFactory() - { - creators["aimed shot"] = &aimed_shot; - creators["steady shot"] = &steady_shot; - } - -private: - static ActionNode* aimed_shot([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode("aimed shot", - /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("multi-shot"), nullptr), - /*C*/ nullptr); - } - static ActionNode* steady_shot([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode("steady shot", - /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("arcane shot"), nullptr), - /*C*/ nullptr); - } -}; - -DpsHunterStrategy::DpsHunterStrategy(PlayerbotAI* botAI) : GenericHunterStrategy(botAI) -{ - actionNodeFactories.Add(new DpsHunterStrategyActionNodeFactory()); -} - -NextAction** DpsHunterStrategy::getDefaultActions() -{ - return NextAction::array( - 0, - new NextAction("explosive shot", ACTION_HIGH + 1.0f), - new NextAction("kill shot", ACTION_DEFAULT + 0.8f), - new NextAction("chimera shot", ACTION_DEFAULT + 0.6f), - new NextAction("aimed shot", ACTION_DEFAULT + 0.5f), - new NextAction("silencing shot", ACTION_DEFAULT + 0.4f), - new NextAction("kill command", ACTION_DEFAULT + 0.3f), - // new NextAction("arcane shot", ACTION_DEFAULT + 0.2f), - new NextAction("steady shot", ACTION_DEFAULT + 0.1f), - new NextAction("auto shot", ACTION_DEFAULT), nullptr); -} - -void DpsHunterStrategy::InitTriggers(std::vector& triggers) -{ - GenericHunterStrategy::InitTriggers(triggers); - - triggers.push_back( - new TriggerNode("black arrow", NextAction::array(0, new NextAction("black arrow", 19.0f), nullptr))); - triggers.push_back( - new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 23.0f), nullptr))); - triggers.push_back( - new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 31.0f), nullptr))); - triggers.push_back(new TriggerNode("concussive shot on snare target", - NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr))); - // triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("call pet", 21.0f), NULL))); - // triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend - // pet", 21.0f), NULL))); - triggers.push_back( - new TriggerNode("has aggro", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr))); -} - -void DpsAoeHunterStrategy::InitTriggers(std::vector& triggers) -{ - triggers.push_back( - new TriggerNode("light aoe", NextAction::array(0, new NextAction("multi-shot", 20.0f), nullptr))); - triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("volley", 21.0f), nullptr))); - triggers.push_back( - new TriggerNode("serpent sting on attacker", - NextAction::array(0, new NextAction("serpent sting on attacker", 17.0f), nullptr))); -} - -void DpsHunterDebuffStrategy::InitTriggers(std::vector& triggers) -{ - triggers.push_back( - new TriggerNode("no stings", NextAction::array(0, new NextAction("serpent sting", 18.0f), nullptr))); -} diff --git a/src/strategy/hunter/DpsHunterStrategy.h b/src/strategy/hunter/DpsHunterStrategy.h deleted file mode 100644 index 2cf8707c..00000000 --- a/src/strategy/hunter/DpsHunterStrategy.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2016+ AzerothCore , 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. - */ - -#ifndef _PLAYERBOT_DPSHUNTERSTRATEGY_H -#define _PLAYERBOT_DPSHUNTERSTRATEGY_H - -#include "GenericHunterStrategy.h" - -class PlayerbotAI; - -class DpsHunterStrategy : public GenericHunterStrategy -{ -public: - DpsHunterStrategy(PlayerbotAI* botAI); - - void InitTriggers(std::vector& triggers) override; - std::string const getName() override { return "dps"; } - NextAction** getDefaultActions() override; -}; - -class DpsAoeHunterStrategy : public CombatStrategy -{ -public: - DpsAoeHunterStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {} - - void InitTriggers(std::vector& triggers) override; - std::string const getName() override { return "aoe"; } -}; - -class DpsHunterDebuffStrategy : public CombatStrategy -{ -public: - DpsHunterDebuffStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {} - - void InitTriggers(std::vector& triggers) override; - std::string const getName() override { return "dps debuff"; } -}; - -#endif diff --git a/src/strategy/hunter/GenericHunterStrategy.cpp b/src/strategy/hunter/GenericHunterStrategy.cpp index 9e32b4ee..4c4763f9 100644 --- a/src/strategy/hunter/GenericHunterStrategy.cpp +++ b/src/strategy/hunter/GenericHunterStrategy.cpp @@ -16,6 +16,7 @@ public: creators["rapid fire"] = &rapid_fire; creators["boost"] = &rapid_fire; creators["aspect of the pack"] = &aspect_of_the_pack; + creators["aspect of the dragonhawk"] = &aspect_of_the_dragonhawk; creators["feign death"] = &feign_death; creators["wing clip"] = &wing_clip; creators["mongoose bite"] = &mongoose_bite; @@ -40,6 +41,14 @@ private: /*C*/ nullptr); } + static ActionNode* aspect_of_the_dragonhawk([[maybe_unused]] PlayerbotAI* botAI) + { + return new ActionNode("aspect of the dragonhawk", + /*P*/ nullptr, + /*A*/ NextAction::array(0, new NextAction("aspect of the hawk"), nullptr), + /*C*/ nullptr); + } + static ActionNode* feign_death([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode("feign death", @@ -80,7 +89,6 @@ private: /*A*/ NextAction::array(0, new NextAction("immolation trap"), nullptr), /*C*/ nullptr); } - }; GenericHunterStrategy::GenericHunterStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) @@ -92,58 +100,48 @@ void GenericHunterStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("enemy within melee", - NextAction::array(0, - new NextAction("explosive trap", ACTION_MOVE + 7), - new NextAction("mongoose bite", ACTION_HIGH + 2), - new NextAction("wing clip", ACTION_HIGH + 1), - nullptr))); - triggers.push_back( - new TriggerNode("medium threat", NextAction::array(0, new NextAction("feign death", 35.0f), nullptr))); - triggers.push_back(new TriggerNode("hunters pet medium health", - NextAction::array(0, new NextAction("mend pet", ACTION_HIGH + 2), nullptr))); - triggers.push_back(new TriggerNode("no ammo", - NextAction::array(0, new NextAction("equip upgrades", ACTION_HIGH + 9), nullptr))); - triggers.push_back(new TriggerNode("aspect of the viper", - NextAction::array(0, new NextAction("aspect of the viper", ACTION_HIGH), NULL))); - triggers.push_back(new TriggerNode("enemy too close for auto shot", - NextAction::array(0, - new NextAction("disengage", ACTION_MOVE + 5), - new NextAction("flee", ACTION_MOVE + 4), - nullptr))); - triggers.push_back( - new TriggerNode("low tank threat", - NextAction::array(0, new NextAction("misdirection on main tank", ACTION_HIGH + 7), NULL))); - triggers.push_back( - new TriggerNode("low health", NextAction::array(0, new NextAction("deterrence", ACTION_HIGH + 5), nullptr))); - - triggers.push_back(new TriggerNode("tranquilizing shot enrage", - NextAction::array(0, new NextAction("tranquilizing shot", 61.0f), NULL))); - triggers.push_back(new TriggerNode("tranquilizing shot magic", - NextAction::array(0, new NextAction("tranquilizing shot", 61.0f), NULL))); -} + // Mark/Ammo/Mana Triggers + triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("equip upgrades", 30.0f), nullptr))); + triggers.push_back(new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 29.5f), nullptr))); + triggers.push_back(new TriggerNode("rapid fire", NextAction::array(0, new NextAction("rapid fire", 29.0f), nullptr))); + triggers.push_back(new TriggerNode("aspect of the viper", NextAction::array(0, new NextAction("aspect of the viper", 28.0f), NULL))); + triggers.push_back(new TriggerNode("aspect of the hawk", NextAction::array(0, new NextAction("aspect of the dragonhawk", 27.5f), nullptr))); -NextAction** HunterBoostStrategy::getDefaultActions() -{ - return NextAction::array(0, new NextAction("bestial wrath", 15.0f), nullptr); + // Aggro/Threat/Defensive Triggers + triggers.push_back(new TriggerNode("has aggro", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr))); + triggers.push_back(new TriggerNode("low tank threat", NextAction::array(0, new NextAction("misdirection on main tank", 27.0f), NULL))); + triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("deterrence", 35.0f), nullptr))); + triggers.push_back(new TriggerNode("concussive shot on snare target", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr))); + triggers.push_back(new TriggerNode("medium threat", NextAction::array(0, new NextAction("feign death", 35.0f), nullptr))); + triggers.push_back(new TriggerNode("hunters pet medium health", NextAction::array(0, new NextAction("mend pet", 22.0f), nullptr))); + triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", 21.0f), nullptr))); + + // Dispel Triggers + triggers.push_back(new TriggerNode("tranquilizing shot enrage", NextAction::array(0, new NextAction("tranquilizing shot", 61.0f), NULL))); + triggers.push_back(new TriggerNode("tranquilizing shot magic", NextAction::array(0, new NextAction("tranquilizing shot", 61.0f), NULL))); + + // Ranged-based Triggers + triggers.push_back(new TriggerNode("enemy within melee", NextAction::array(0, + new NextAction("explosive trap", 37.0f), + new NextAction("mongoose bite", 22.0f), + new NextAction("wing clip", 21.0f), nullptr))); + + triggers.push_back(new TriggerNode("enemy too close for auto shot", NextAction::array(0, + new NextAction("disengage", 35.0f), + new NextAction("flee", 34.0f), nullptr))); } void HunterBoostStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back( - new TriggerNode("rapid fire", NextAction::array(0, new NextAction("rapid fire", 16.0f), nullptr))); } void HunterCcStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "scare beast", NextAction::array(0, new NextAction("scare beast on cc", ACTION_HIGH + 3), nullptr))); - triggers.push_back(new TriggerNode( - "freezing trap", NextAction::array(0, new NextAction("freezing trap on cc", ACTION_HIGH + 3), nullptr))); + triggers.push_back(new TriggerNode("scare beast", NextAction::array(0, new NextAction("scare beast on cc", 23.0f), nullptr))); + triggers.push_back(new TriggerNode("freezing trap", NextAction::array(0, new NextAction("freezing trap on cc", 23.0f), nullptr))); } void HunterTrapWeaveStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode( - "immolation trap no cd", NextAction::array(0, new NextAction("reach melee", ACTION_HIGH + 3), nullptr))); + triggers.push_back(new TriggerNode("immolation trap no cd", NextAction::array(0, new NextAction("reach melee", 23.0f), nullptr))); } diff --git a/src/strategy/hunter/GenericHunterStrategy.h b/src/strategy/hunter/GenericHunterStrategy.h index 52148eed..ea4f2b9c 100644 --- a/src/strategy/hunter/GenericHunterStrategy.h +++ b/src/strategy/hunter/GenericHunterStrategy.h @@ -27,7 +27,6 @@ public: HunterBoostStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} std::string const getName() override { return "boost"; } - NextAction** getDefaultActions() override; void InitTriggers(std::vector& triggers) override; }; diff --git a/src/strategy/hunter/HunterActions.cpp b/src/strategy/hunter/HunterActions.cpp index 074a9bbd..b0351cf6 100644 --- a/src/strategy/hunter/HunterActions.cpp +++ b/src/strategy/hunter/HunterActions.cpp @@ -10,11 +10,10 @@ #include "PlayerbotAI.h" #include "Playerbots.h" -bool CastHuntersMarkAction::isUseful() { return CastDebuffSpellAction::isUseful(); } - bool CastViperStingAction::isUseful() { - return AI_VALUE2(uint8, "mana", "self target") < 50 && AI_VALUE2(uint8, "mana", "current target") >= 30; + return CastAuraSpellAction::isUseful() && AI_VALUE2(uint8, "mana", "self target") < 50 && + AI_VALUE2(uint8, "mana", "current target") >= 30; } bool CastAspectOfTheCheetahAction::isUseful() @@ -22,6 +21,42 @@ bool CastAspectOfTheCheetahAction::isUseful() return !botAI->HasAnyAuraOf(GetTarget(), "aspect of the cheetah", "aspect of the pack", nullptr); } +bool CastAspectOfTheHawkAction::isUseful() +{ + Unit* target = GetTarget(); + if (!target) + return false; + if (bot->HasSpell(61846) || bot->HasSpell(61847)) // Aspect of the Dragonhawk spell IDs + return false; + return true; +} + +bool CastArcaneShotAction::isUseful() +{ + Unit* target = GetTarget(); + if (!target) + return false; + if (bot->HasSpell(53301) || bot->HasSpell(60051) || bot->HasSpell(60052) || bot->HasSpell(60053)) // Explosive Shot spell IDs + return false; + + // Armor Penetration rating check - will not cast Arcane Shot above 435 ArP + int32 armorPenRating = bot->GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_ARMOR_PENETRATION); + if (armorPenRating > 435) + return false; + + return true; +} + +bool CastImmolationTrapAction::isUseful() +{ + Unit* target = GetTarget(); + if (!target) + return false; + if (bot->HasSpell(13813) || bot->HasSpell(14316) || bot->HasSpell(14317) || bot->HasSpell(27025) || bot->HasSpell(49066) || bot->HasSpell(49067)) // Explosive Trap spell IDs + return false; + return true; +} + Value* CastFreezingTrap::GetTargetValue() { return context->GetValue("cc target", "freezing trap"); } bool FeedPetAction::Execute(Event event) @@ -62,7 +97,6 @@ bool CastDisengageAction::isUseful() return !botAI->HasStrategy("trap weave", BOT_STATE_COMBAT); } - Value* CastScareBeastCcAction::GetTargetValue() { return context->GetValue("cc target", "scare beast"); } bool CastScareBeastCcAction::Execute(Event event) { return botAI->CastSpell("scare beast", GetTarget()); } diff --git a/src/strategy/hunter/HunterActions.h b/src/strategy/hunter/HunterActions.h index d8618c42..752577c5 100644 --- a/src/strategy/hunter/HunterActions.h +++ b/src/strategy/hunter/HunterActions.h @@ -9,107 +9,24 @@ #include "AiObject.h" #include "Event.h" #include "GenericSpellActions.h" +#include "Unit.h" class PlayerbotAI; class Unit; -// BEGIN_RANGED_SPELL_ACTION(CastHuntersMarkAction, "hunter's mark") -// END_SPELL_ACTION() +// Buff and Out of Combat Spells -class CastHuntersMarkAction : public CastDebuffSpellAction +class CastTrueshotAuraAction : public CastBuffSpellAction { public: - CastHuntersMarkAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "hunter's mark") {} - bool isUseful() override; -}; -class CastAutoShotAction : public CastSpellAction -{ -public: - CastAutoShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "auto shot") {} - ActionThreatType getThreatType() override { return ActionThreatType::None; } - bool isUseful() override; -}; - -BEGIN_RANGED_SPELL_ACTION(CastArcaneShotAction, "arcane shot") -END_SPELL_ACTION() - -class CastExplosiveShotAction : public CastDebuffSpellAction -{ -public: - CastExplosiveShotAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {} -}; - -BEGIN_RANGED_SPELL_ACTION(CastAimedShotAction, "aimed shot") -END_SPELL_ACTION() - -BEGIN_RANGED_SPELL_ACTION(CastChimeraShotAction, "chimera shot") -END_SPELL_ACTION() - -class CastConcussiveShotAction : public CastSnareSpellAction -{ -public: - CastConcussiveShotAction(PlayerbotAI* botAI) : CastSnareSpellAction(botAI, "concussive shot") {} -}; - -BEGIN_RANGED_SPELL_ACTION(CastDistractingShotAction, "distracting shot") -END_SPELL_ACTION() - -BEGIN_RANGED_SPELL_ACTION(CastMultiShotAction, "multi-shot") -END_SPELL_ACTION() - -BEGIN_RANGED_SPELL_ACTION(CastVolleyAction, "volley") -ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } -END_SPELL_ACTION() - -DEBUFF_CHECKISOWNER_ACTION(CastSerpentStingAction, "serpent sting"); - -BEGIN_RANGED_SPELL_ACTION(CastWyvernStingAction, "wyvern sting") -END_SPELL_ACTION() - -BEGIN_RANGED_SPELL_ACTION(CastViperStingAction, "viper sting") -bool isUseful() override; -END_SPELL_ACTION() - -BEGIN_RANGED_SPELL_ACTION(CastScorpidStingAction, "scorpid sting") -END_SPELL_ACTION() - -BEGIN_RANGED_SPELL_ACTION(CastSteadyShotAction, "steady shot") -END_SPELL_ACTION() - -BEGIN_RANGED_SPELL_ACTION(CastKillShotAction, "kill shot") -END_SPELL_ACTION() - -BEGIN_RANGED_SPELL_ACTION(CastSilencingShotAction, "silencing shot") -END_SPELL_ACTION() - -BEGIN_RANGED_SPELL_ACTION(CastTranquilizingShotAction, "tranquilizing shot") -END_SPELL_ACTION() - -class CastDisengageAction : public CastSpellAction -{ -public: - CastDisengageAction(PlayerbotAI* botAI): CastSpellAction(botAI, "disengage") {} - - bool Execute(Event event) override; - bool isUseful() override; -}; - -class CastImmolationTrapAction : public CastSpellAction -{ -public: - CastImmolationTrapAction(PlayerbotAI* botAI): CastSpellAction(botAI, "immolation trap") {} -}; - -class CastExplosiveTrapAction : public CastSpellAction -{ -public: - CastExplosiveTrapAction(PlayerbotAI* botAI): CastSpellAction(botAI, "explosive trap") {} + CastTrueshotAuraAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "trueshot aura") {} }; class CastAspectOfTheHawkAction : public CastBuffSpellAction { public: CastAspectOfTheHawkAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "aspect of the hawk") {} + bool isUseful() override; }; class CastAspectOfTheMonkeyAction : public CastBuffSpellAction @@ -150,45 +67,7 @@ public: CastAspectOfTheViperAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "aspect of the viper") {} }; -class CastCallPetAction : public CastBuffSpellAction -{ -public: - CastCallPetAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "call pet") {} -}; - -class CastMendPetAction : public CastAuraSpellAction -{ -public: - CastMendPetAction(PlayerbotAI* botAI) : CastAuraSpellAction(botAI, "mend pet") {} - - std::string const GetTargetName() override { return "pet target"; } -}; - -class CastKillCommandAction : public CastAuraSpellAction -{ -public: - CastKillCommandAction(PlayerbotAI* botAI) : CastAuraSpellAction(botAI, "kill command") {} - - std::string const GetTargetName() override { return "pet target"; } -}; - -class CastRevivePetAction : public CastBuffSpellAction -{ -public: - CastRevivePetAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "revive pet") {} -}; - -class CastTrueshotAuraAction : public CastBuffSpellAction -{ -public: - CastTrueshotAuraAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "trueshot aura") {} -}; - -class CastFeignDeathAction : public CastBuffSpellAction -{ -public: - CastFeignDeathAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "feign death") {} -}; +// Cooldown Spells class CastRapidFireAction : public CastBuffSpellAction { @@ -208,10 +87,30 @@ public: CastReadinessAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "readiness") {} }; -class CastBlackArrow : public CastDebuffSpellAction +class CastDisengageAction : public CastSpellAction { public: - CastBlackArrow(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "black arrow", true) {} + CastDisengageAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "disengage") {} + + bool Execute(Event event) override; + bool isUseful() override; +}; + +// CC Spells + +class CastScareBeastAction : public CastSpellAction +{ +public: + CastScareBeastAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "scare beast") {} +}; + +class CastScareBeastCcAction : public CastSpellAction +{ +public: + CastScareBeastCcAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "scare beast on cc") {} + + Value* GetTargetValue() override; + bool Execute(Event event) override; }; class CastFreezingTrap : public CastDebuffSpellAction @@ -222,6 +121,297 @@ public: Value* GetTargetValue() override; }; +class CastWyvernStingAction : public CastDebuffSpellAction +{ +public: + CastWyvernStingAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "wyvern sting", true) {} +}; + +class CastSilencingShotAction : public CastSpellAction +{ +public: + CastSilencingShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "silencing shot") {} +}; + +class CastConcussiveShotAction : public CastSnareSpellAction +{ +public: + CastConcussiveShotAction(PlayerbotAI* botAI) : CastSnareSpellAction(botAI, "concussive shot") {} +}; + +class CastIntimidationAction : public CastBuffSpellAction +{ +public: + CastIntimidationAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "intimidation", false, 5000) {} + std::string const GetTargetName() override { return "pet target"; } +}; + +// Threat Spells + +class CastDistractingShotAction : public CastSpellAction +{ +public: + CastDistractingShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "distracting shot") {} +}; + +class CastMisdirectionOnMainTankAction : public BuffOnMainTankAction +{ +public: + CastMisdirectionOnMainTankAction(PlayerbotAI* ai) : BuffOnMainTankAction(ai, "misdirection", true) {} +}; + +class CastFeignDeathAction : public CastBuffSpellAction +{ +public: + CastFeignDeathAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "feign death") {} +}; + +// Pet Spells + +class FeedPetAction : public Action +{ +public: + FeedPetAction(PlayerbotAI* botAI) : Action(botAI, "feed pet") {} + + bool Execute(Event event) override; +}; + +class CastCallPetAction : public CastBuffSpellAction +{ +public: + CastCallPetAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "call pet") {} +}; + +class CastMendPetAction : public CastAuraSpellAction +{ +public: + CastMendPetAction(PlayerbotAI* botAI) : CastAuraSpellAction(botAI, "mend pet") {} + std::string const GetTargetName() override { return "pet target"; } +}; + +class CastRevivePetAction : public CastBuffSpellAction +{ +public: + CastRevivePetAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "revive pet") {} +}; + +class CastKillCommandAction : public CastBuffSpellAction +{ +public: + CastKillCommandAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "kill command", false, 5000) {} + std::string const GetTargetName() override { return "pet target"; } +}; + +class CastBestialWrathAction : public CastBuffSpellAction +{ +public: + CastBestialWrathAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "bestial wrath", false, 5000) {} + std::string const GetTargetName() override { return "pet target"; } +}; + +// Direct Damage Spells + +class CastAutoShotAction : public CastSpellAction +{ +public: + CastAutoShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "auto shot") {} + ActionThreatType getThreatType() override { return ActionThreatType::None; } + bool isUseful() override; +}; + +class CastArcaneShotAction : public CastSpellAction +{ +public: + CastArcaneShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "arcane shot") {} + bool isUseful() override; +}; + +class CastAimedShotAction : public CastSpellAction +{ +public: + CastAimedShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "aimed shot") {} +}; + +class CastChimeraShotAction : public CastSpellAction +{ +public: + CastChimeraShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "chimera shot") {} +}; + +class CastSteadyShotAction : public CastSpellAction +{ +public: + CastSteadyShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "steady shot") {} +}; + +class CastKillShotAction : public CastSpellAction +{ +public: + CastKillShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "kill shot") {} +}; + +// DoT/Debuff Spells + +class CastHuntersMarkAction : public CastDebuffSpellAction +{ +public: + CastHuntersMarkAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "hunter's mark") {} + bool isUseful() override + { + // Bypass TTL check + return CastAuraSpellAction::isUseful(); + } +}; + +class CastTranquilizingShotAction : public CastSpellAction +{ +public: + CastTranquilizingShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "tranquilizing shot") {} +}; + +class CastViperStingAction : public CastDebuffSpellAction +{ +public: + CastViperStingAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "viper sting", true) {} + bool isUseful() override; +}; + +class CastSerpentStingAction : public CastDebuffSpellAction +{ +public: + CastSerpentStingAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "serpent sting", true) {} + bool isUseful() override + { + // Bypass TTL check + return CastAuraSpellAction::isUseful(); + } +}; + +class CastScorpidStingAction : public CastDebuffSpellAction +{ +public: + CastScorpidStingAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "scorpid sting", true) {} + bool isUseful() override + { + // Bypass TTL check + return CastAuraSpellAction::isUseful(); + } +}; + +class CastSerpentStingOnAttackerAction : public CastDebuffSpellOnAttackerAction +{ +public: + CastSerpentStingOnAttackerAction(PlayerbotAI* botAI) : CastDebuffSpellOnAttackerAction(botAI, "serpent sting", true) {} + bool isUseful() override + { + // Bypass TTL check + return CastAuraSpellAction::isUseful(); + } +}; + +class CastImmolationTrapAction : public CastSpellAction +{ +public: + CastImmolationTrapAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "immolation trap") {} + bool isUseful() override; +}; + +class CastExplosiveTrapAction : public CastSpellAction +{ +public: + CastExplosiveTrapAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "explosive trap") {} +}; + +class CastBlackArrow : public CastDebuffSpellAction +{ +public: + CastBlackArrow(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "black arrow", true) {} + bool isUseful() override + { + if (botAI->HasStrategy("trap weave", BOT_STATE_COMBAT)) + return false; + // Bypass TTL check + return CastAuraSpellAction::isUseful(); + } +}; + +class CastExplosiveShotAction : public CastDebuffSpellAction +{ +public: + CastExplosiveShotAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {} + bool isUseful() override + { + // Bypass TTL check + return CastAuraSpellAction::isUseful(); + } +}; + +// Rank 4 +class CastExplosiveShotRank4Action : public CastDebuffSpellAction +{ +public: + CastExplosiveShotRank4Action(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {} + + bool Execute(Event event) override { return botAI->CastSpell(60053, GetTarget()); } + bool isUseful() override + { + Unit* target = GetTarget(); + if (!target) + return false; + return !target->HasAura(60053); + } +}; + +// Rank 3 +class CastExplosiveShotRank3Action : public CastDebuffSpellAction +{ +public: + CastExplosiveShotRank3Action(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {} + + bool Execute(Event event) override { return botAI->CastSpell(60052, GetTarget()); } + bool isUseful() override + { + Unit* target = GetTarget(); + if (!target) + return false; + return !target->HasAura(60052); + } +}; + +// Rank 2 +class CastExplosiveShotRank2Action : public CastDebuffSpellAction +{ +public: + CastExplosiveShotRank2Action(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {} + + bool Execute(Event event) override { return botAI->CastSpell(60051, GetTarget()); } + bool isUseful() override + { + Unit* target = GetTarget(); + if (!target) + return false; + return !target->HasAura(60051); + } +}; + +// Rank 1 +class CastExplosiveShotRank1Action : public CastDebuffSpellAction +{ +public: + CastExplosiveShotRank1Action(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {} + + bool Execute(Event event) override { return botAI->CastSpell(53301, GetTarget()); } + bool isUseful() override + { + Unit* target = GetTarget(); + if (!target) + return false; + return !target->HasAura(53301); + } +}; + +// Melee Spells + class CastWingClipAction : public CastSpellAction { public: @@ -243,47 +433,19 @@ public: CastMongooseBiteAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "mongoose bite") {} }; -class CastSerpentStingOnAttackerAction : public CastDebuffSpellOnAttackerAction +// AoE Spells + +class CastMultiShotAction : public CastSpellAction { public: - CastSerpentStingOnAttackerAction(PlayerbotAI* botAI) : CastDebuffSpellOnAttackerAction(botAI, "serpent sting", true) - { - } + CastMultiShotAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "multi-shot") {} }; -class FeedPetAction : public Action +class CastVolleyAction : public CastSpellAction { public: - FeedPetAction(PlayerbotAI* botAI) : Action(botAI, "feed pet") {} - - bool Execute(Event event) override; + CastVolleyAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "volley") {} + ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } }; -class CastBestialWrathAction : public CastBuffSpellAction -{ -public: - CastBestialWrathAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "bestial wrath") {} - std::string const GetTargetName() override { return "pet target"; } -}; - -class CastScareBeastAction : public CastSpellAction -{ -public: - CastScareBeastAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "scare beast") {} -}; - -class CastScareBeastCcAction : public CastSpellAction -{ -public: - CastScareBeastCcAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "scare beast on cc") {} - - Value* GetTargetValue() override; - bool Execute(Event event) override; -}; - -class CastMisdirectionOnMainTankAction : public BuffOnMainTankAction -{ -public: - CastMisdirectionOnMainTankAction(PlayerbotAI* ai) : BuffOnMainTankAction(ai, "misdirection", true) {} -}; #endif diff --git a/src/strategy/hunter/HunterAiObjectContext.cpp b/src/strategy/hunter/HunterAiObjectContext.cpp index 9b89b651..35c94813 100644 --- a/src/strategy/hunter/HunterAiObjectContext.cpp +++ b/src/strategy/hunter/HunterAiObjectContext.cpp @@ -4,9 +4,11 @@ */ #include "HunterAiObjectContext.h" - -#include "DpsHunterStrategy.h" +#include "BeastMasteryHunterStrategy.h" +#include "MarksmanshipHunterStrategy.h" +#include "SurvivalHunterStrategy.h" #include "GenericHunterNonCombatStrategy.h" +#include "GenericHunterStrategy.h" #include "HunterActions.h" #include "HunterBuffStrategies.h" #include "HunterTriggers.h" @@ -18,25 +20,31 @@ class HunterStrategyFactoryInternal : public NamedObjectContext public: HunterStrategyFactoryInternal() { - creators["dps"] = &HunterStrategyFactoryInternal::dps; creators["nc"] = &HunterStrategyFactoryInternal::nc; - creators["aoe"] = &HunterStrategyFactoryInternal::aoe; - creators["dps debuff"] = &HunterStrategyFactoryInternal::dps_debuff; creators["boost"] = &HunterStrategyFactoryInternal::boost; creators["pet"] = &HunterStrategyFactoryInternal::pet; creators["cc"] = &HunterStrategyFactoryInternal::cc; creators["trap weave"] = &HunterStrategyFactoryInternal::trap_weave; + creators["bm"] = &HunterStrategyFactoryInternal::beast_mastery; + creators["mm"] = &HunterStrategyFactoryInternal::marksmanship; + creators["surv"] = &HunterStrategyFactoryInternal::survival; + creators["bm aoe"] = &HunterStrategyFactoryInternal::beast_mastery_aoe; + creators["mm aoe"] = &HunterStrategyFactoryInternal::marksmanship_aoe; + creators["surv aoe"] = &HunterStrategyFactoryInternal::survival_aoe; } private: - static Strategy* aoe(PlayerbotAI* botAI) { return new DpsAoeHunterStrategy(botAI); } - static Strategy* dps(PlayerbotAI* botAI) { return new DpsHunterStrategy(botAI); } static Strategy* nc(PlayerbotAI* botAI) { return new GenericHunterNonCombatStrategy(botAI); } - static Strategy* dps_debuff(PlayerbotAI* botAI) { return new DpsHunterDebuffStrategy(botAI); } static Strategy* boost(PlayerbotAI* botAI) { return new HunterBoostStrategy(botAI); } static Strategy* pet(PlayerbotAI* botAI) { return new HunterPetStrategy(botAI); } static Strategy* cc(PlayerbotAI* botAI) { return new HunterCcStrategy(botAI); } static Strategy* trap_weave(PlayerbotAI* botAI) { return new HunterTrapWeaveStrategy(botAI); } + static Strategy* beast_mastery(PlayerbotAI* botAI) { return new BeastMasteryHunterStrategy(botAI); } + static Strategy* marksmanship(PlayerbotAI* botAI) { return new MarksmanshipHunterStrategy(botAI); } + static Strategy* survival(PlayerbotAI* botAI) { return new SurvivalHunterStrategy(botAI); } + static Strategy* beast_mastery_aoe(PlayerbotAI* botAI) { return new BeastMasteryHunterAoeStrategy(botAI); } + static Strategy* marksmanship_aoe(PlayerbotAI* botAI) { return new MarksmanshipHunterAoeStrategy(botAI); } + static Strategy* survival_aoe(PlayerbotAI* botAI) { return new SurvivalHunterAoeStrategy(botAI); } }; class HunterBuffStrategyFactoryInternal : public NamedObjectContext @@ -91,15 +99,17 @@ public: creators["tranquilizing shot enrage"] = &HunterTriggerFactoryInternal::remove_enrage; creators["tranquilizing shot magic"] = &HunterTriggerFactoryInternal::remove_magic; creators["immolation trap no cd"] = &HunterTriggerFactoryInternal::immolation_trap_no_cd; + creators["kill command"] = &HunterTriggerFactoryInternal::kill_command; + creators["explosive shot"] = &HunterTriggerFactoryInternal::explosive_shot; + creators["lock and load"] = &HunterTriggerFactoryInternal::lock_and_load; + creators["silencing shot"] = &HunterTriggerFactoryInternal::silencing_shot; + creators["intimidation"] = &HunterTriggerFactoryInternal::intimidation; } private: static Trigger* auto_shot(PlayerbotAI* botAI) { return new AutoShotTrigger(botAI); } static Trigger* scare_beast(PlayerbotAI* botAI) { return new ScareBeastTrigger(botAI); } - static Trigger* concussive_shot_on_snare_target(PlayerbotAI* botAI) - { - return new ConsussiveShotSnareTrigger(botAI); - } + static Trigger* concussive_shot_on_snare_target(PlayerbotAI* botAI) { return new ConsussiveShotSnareTrigger(botAI); } static Trigger* pet_not_happy(PlayerbotAI* botAI) { return new HunterPetNotHappy(botAI); } static Trigger* serpent_sting_on_attacker(PlayerbotAI* botAI) { return new SerpentStingOnAttackerTrigger(botAI); } static Trigger* trueshot_aura(PlayerbotAI* botAI) { return new TrueshotAuraTrigger(botAI); } @@ -126,6 +136,11 @@ private: static Trigger* remove_enrage(PlayerbotAI* ai) { return new TargetRemoveEnrageTrigger(ai); } static Trigger* remove_magic(PlayerbotAI* ai) { return new TargetRemoveMagicTrigger(ai); } static Trigger* immolation_trap_no_cd(PlayerbotAI* ai) { return new ImmolationTrapNoCdTrigger(ai); } + static Trigger* kill_command(PlayerbotAI* botAI) { return new KillCommandTrigger(botAI); } + static Trigger* explosive_shot(PlayerbotAI* botAI) { return new ExplosiveShotTrigger(botAI); } + static Trigger* lock_and_load(PlayerbotAI* botAI) { return new LockAndLoadTrigger(botAI); } + static Trigger* silencing_shot(PlayerbotAI* botAI) { return new SilencingShotTrigger(botAI); } + static Trigger* intimidation(PlayerbotAI* botAI) { return new IntimidationTrigger(botAI); } }; class HunterAiObjectContextInternal : public NamedObjectContext @@ -183,6 +198,11 @@ public: creators["disengage"] = &HunterAiObjectContextInternal::disengage; creators["immolation trap"] = &HunterAiObjectContextInternal::immolation_trap; creators["explosive trap"] = &HunterAiObjectContextInternal::explosive_trap; + creators["explosive shot rank 4"] = &HunterAiObjectContextInternal::explosive_shot_rank_4; + creators["explosive shot rank 3"] = &HunterAiObjectContextInternal::explosive_shot_rank_3; + creators["explosive shot rank 2"] = &HunterAiObjectContextInternal::explosive_shot_rank_2; + creators["explosive shot rank 1"] = &HunterAiObjectContextInternal::explosive_shot_rank_1; + creators["intimidation"] = &HunterAiObjectContextInternal::intimidation; } private: @@ -235,6 +255,11 @@ private: static Action* disengage(PlayerbotAI* ai) { return new CastDisengageAction(ai); } static Action* immolation_trap(PlayerbotAI* ai) { return new CastImmolationTrapAction(ai); } static Action* explosive_trap(PlayerbotAI* ai) { return new CastExplosiveTrapAction(ai); } + static Action* explosive_shot_rank_4(PlayerbotAI* ai) { return new CastExplosiveShotRank4Action(ai); } + static Action* explosive_shot_rank_3(PlayerbotAI* ai) { return new CastExplosiveShotRank3Action(ai); } + static Action* explosive_shot_rank_2(PlayerbotAI* ai) { return new CastExplosiveShotRank2Action(ai); } + static Action* explosive_shot_rank_1(PlayerbotAI* ai) { return new CastExplosiveShotRank1Action(ai); } + static Action* intimidation(PlayerbotAI* ai) { return new CastIntimidationAction(ai); } }; HunterAiObjectContext::HunterAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) diff --git a/src/strategy/hunter/HunterTriggers.cpp b/src/strategy/hunter/HunterTriggers.cpp index 4d0c26c2..6a79b7eb 100644 --- a/src/strategy/hunter/HunterTriggers.cpp +++ b/src/strategy/hunter/HunterTriggers.cpp @@ -4,7 +4,6 @@ */ #include "HunterTriggers.h" - #include "GenericSpellActions.h" #include "GenericTriggers.h" #include "HunterActions.h" @@ -14,12 +13,19 @@ #include "ServerFacade.h" #include "SharedDefines.h" +bool KillCommandTrigger::IsActive() +{ + Unit* target = GetTarget(); + return !botAI->HasAura("kill command", target); +} + bool BlackArrowTrigger::IsActive() { if (botAI->HasStrategy("trap weave", BOT_STATE_COMBAT)) return false; return DebuffTrigger::IsActive(); + return BuffTrigger::IsActive(); } bool HunterAspectOfTheHawkTrigger::IsActive() @@ -35,6 +41,7 @@ bool HunterNoStingsActiveTrigger::IsActive() Unit* target = AI_VALUE(Unit*, "current target"); return DebuffTrigger::IsActive() && target && !botAI->HasAura("serpent sting", target, false, true) && !botAI->HasAura("scorpid sting", target, false, true) && !botAI->HasAura("viper sting", target, false, true); + return BuffTrigger::IsActive(); } bool HuntersPetDeadTrigger::IsActive() @@ -130,4 +137,5 @@ bool SerpentStingOnAttackerTrigger::IsActive() } return !botAI->HasAura("scorpid sting", target, false, true) && !botAI->HasAura("viper sting", target, false, true); -} \ No newline at end of file + return BuffTrigger::IsActive(); +} diff --git a/src/strategy/hunter/HunterTriggers.h b/src/strategy/hunter/HunterTriggers.h index d0d4db9c..c0d18ddc 100644 --- a/src/strategy/hunter/HunterTriggers.h +++ b/src/strategy/hunter/HunterTriggers.h @@ -9,23 +9,11 @@ #include "CureTriggers.h" #include "GenericTriggers.h" #include "Trigger.h" +#include "PlayerbotAI.h" class PlayerbotAI; -class HunterNoStingsActiveTrigger : public DebuffTrigger -{ -public: - HunterNoStingsActiveTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "no stings") {} - bool IsActive() override; -}; - -class AutoShotTrigger : public Trigger -{ -public: - AutoShotTrigger(PlayerbotAI* botAI) : Trigger(botAI, "auto shot") {} - - bool IsActive() override; -}; +// Buff and Out of Combat Triggers class HunterAspectOfTheMonkeyTrigger : public BuffTrigger { @@ -50,7 +38,6 @@ class HunterAspectOfTheViperTrigger : public BuffTrigger { public: HunterAspectOfTheViperTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "aspect of the viper") {} - bool IsActive() override; }; @@ -58,44 +45,9 @@ class HunterAspectOfThePackTrigger : public BuffTrigger { public: HunterAspectOfThePackTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "aspect of the pack") {} - bool IsActive() override; }; -BEGIN_TRIGGER(HuntersPetDeadTrigger, Trigger) -END_TRIGGER() - -BEGIN_TRIGGER(HuntersPetLowHealthTrigger, Trigger) -END_TRIGGER() - -BEGIN_TRIGGER(HuntersPetMediumHealthTrigger, Trigger) -END_TRIGGER() - -class BlackArrowTrigger : public DebuffTrigger -{ -public: - BlackArrowTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "black arrow", 1, true) {} - bool IsActive() override; -}; - -class HuntersMarkTrigger : public DebuffTrigger -{ -public: - HuntersMarkTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "hunter's mark", 1, false, 25.0f) {} -}; - -class FreezingTrapTrigger : public HasCcTargetTrigger -{ -public: - FreezingTrapTrigger(PlayerbotAI* botAI) : HasCcTargetTrigger(botAI, "freezing trap") {} -}; - -class RapidFireTrigger : public BoostTrigger -{ -public: - RapidFireTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "rapid fire") {} -}; - class TrueshotAuraTrigger : public BuffTrigger { public: @@ -109,28 +61,6 @@ public: bool IsActive() override; }; -class SerpentStingOnAttackerTrigger : public DebuffOnAttackerTrigger -{ -public: - SerpentStingOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, "serpent sting", true) {} - bool IsActive() override; -}; - -BEGIN_TRIGGER(HunterPetNotHappy, Trigger) -END_TRIGGER() - -class ConsussiveShotSnareTrigger : public SnareTargetTrigger -{ -public: - ConsussiveShotSnareTrigger(PlayerbotAI* botAI) : SnareTargetTrigger(botAI, "concussive shot") {} -}; - -class ScareBeastTrigger : public HasCcTargetTrigger -{ -public: - ScareBeastTrigger(PlayerbotAI* botAI) : HasCcTargetTrigger(botAI, "scare beast") {} -}; - class HunterLowAmmoTrigger : public AmmoCountTrigger { public: @@ -153,6 +83,115 @@ public: bool IsActive() override; }; +// Cooldown Triggers + +class RapidFireTrigger : public BoostTrigger +{ +public: + RapidFireTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "rapid fire") {} +}; + +class BestialWrathTrigger : public BuffTrigger +{ +public: + BestialWrathTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "bestial wrath") {} +}; + +class IntimidationTrigger : public BuffTrigger +{ +public: + IntimidationTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "intimidation") {} +}; + +class KillCommandTrigger : public BuffTrigger +{ +public: + KillCommandTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "kill command") {} + bool IsActive() override; +}; + +class LockAndLoadTrigger : public BuffTrigger +{ +public: + LockAndLoadTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "lock and load") {} + + bool IsActive() override + { + return botAI->HasAura("lock and load", botAI->GetBot()); + } +}; + +// CC Triggers + +class FreezingTrapTrigger : public HasCcTargetTrigger +{ +public: + FreezingTrapTrigger(PlayerbotAI* botAI) : HasCcTargetTrigger(botAI, "freezing trap") {} +}; + +class ConsussiveShotSnareTrigger : public SnareTargetTrigger +{ +public: + ConsussiveShotSnareTrigger(PlayerbotAI* botAI) : SnareTargetTrigger(botAI, "concussive shot") {} +}; + +class ScareBeastTrigger : public HasCcTargetTrigger +{ +public: + ScareBeastTrigger(PlayerbotAI* botAI) : HasCcTargetTrigger(botAI, "scare beast") {} +}; + +class SilencingShotTrigger : public InterruptSpellTrigger +{ +public: + SilencingShotTrigger(PlayerbotAI* botAI) : InterruptSpellTrigger(botAI, "silencing shot") {} +}; + +// DoT/Debuff Triggers + +class HuntersMarkTrigger : public DebuffTrigger +{ +public: + HuntersMarkTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "hunter's mark", 1, true, 0.5f) {} + bool IsActive() override { return BuffTrigger::IsActive(); } +}; + +class ExplosiveShotTrigger : public DebuffTrigger +{ +public: + ExplosiveShotTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "explosive shot", 1, true) {} + bool IsActive() override { return BuffTrigger::IsActive(); } +}; + +class BlackArrowTrigger : public DebuffTrigger +{ +public: + BlackArrowTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "black arrow", 1, true) {} + bool IsActive() override; +}; + +class HunterNoStingsActiveTrigger : public DebuffTrigger +{ +public: + HunterNoStingsActiveTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "no stings") {} + bool IsActive() override; +}; + +class SerpentStingOnAttackerTrigger : public DebuffOnAttackerTrigger +{ +public: + SerpentStingOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, "serpent sting", true) {} + bool IsActive() override; +}; + +// Damage/Combat Triggers + +class AutoShotTrigger : public Trigger +{ +public: + AutoShotTrigger(PlayerbotAI* botAI) : Trigger(botAI, "auto shot") {} +}; + class SwitchToRangedTrigger : public Trigger { public: @@ -193,4 +232,16 @@ public: ImmolationTrapNoCdTrigger(PlayerbotAI* ai) : SpellNoCooldownTrigger(ai, "immolation trap") {} }; +BEGIN_TRIGGER(HuntersPetDeadTrigger, Trigger) +END_TRIGGER() + +BEGIN_TRIGGER(HuntersPetLowHealthTrigger, Trigger) +END_TRIGGER() + +BEGIN_TRIGGER(HuntersPetMediumHealthTrigger, Trigger) +END_TRIGGER() + +BEGIN_TRIGGER(HunterPetNotHappy, Trigger) +END_TRIGGER() + #endif diff --git a/src/strategy/hunter/MarksmanshipHunterStrategy.cpp b/src/strategy/hunter/MarksmanshipHunterStrategy.cpp new file mode 100644 index 00000000..f9619656 --- /dev/null +++ b/src/strategy/hunter/MarksmanshipHunterStrategy.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2016+ AzerothCore , 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 "MarksmanshipHunterStrategy.h" +#include "Playerbots.h" + +// ===== Action Node Factory ===== +class MarksmanshipHunterStrategyActionNodeFactory : public NamedObjectFactory +{ +public: + MarksmanshipHunterStrategyActionNodeFactory() + { + creators["auto shot"] = &auto_shot; + creators["silencing shot"] = &silencing_shot; + creators["kill command"] = &kill_command; + creators["kill shot"] = &kill_shot; + creators["viper sting"] = &viper_sting; + creators["serpent sting"] = serpent_sting; + creators["chimera shot"] = &chimera_shot; + creators["aimed shot"] = &aimed_shot; + creators["arcane shot"] = &arcane_shot; + creators["steady shot"] = &steady_shot; + creators["multi-shot"] = &multi_shot; + creators["volley"] = &volley; + } + +private: + static ActionNode* auto_shot(PlayerbotAI*) { return new ActionNode("auto shot", nullptr, nullptr, nullptr); } + static ActionNode* silencing_shot(PlayerbotAI*) { return new ActionNode("silencing shot", nullptr, nullptr, nullptr); } + static ActionNode* kill_command(PlayerbotAI*) { return new ActionNode("kill command", nullptr, nullptr, nullptr); } + static ActionNode* kill_shot(PlayerbotAI*) { return new ActionNode("kill shot", nullptr, nullptr, nullptr); } + static ActionNode* viper_sting(PlayerbotAI*) { return new ActionNode("viper sting", nullptr, nullptr, nullptr); } + static ActionNode* serpent_sting(PlayerbotAI*) { return new ActionNode("serpent sting", nullptr, nullptr, nullptr); } + static ActionNode* chimera_shot(PlayerbotAI*) { return new ActionNode("chimera shot", nullptr, nullptr, nullptr); } + static ActionNode* aimed_shot(PlayerbotAI*) { return new ActionNode("aimed shot", nullptr, nullptr, nullptr); } + static ActionNode* arcane_shot(PlayerbotAI*) { return new ActionNode("arcane shot", nullptr, nullptr, nullptr); } + static ActionNode* steady_shot(PlayerbotAI*) { return new ActionNode("steady shot", nullptr, nullptr, nullptr); } + static ActionNode* multi_shot(PlayerbotAI*) { return new ActionNode("multi shot", nullptr, nullptr, nullptr); } + static ActionNode* volley(PlayerbotAI*) { return new ActionNode("volley", nullptr, nullptr, nullptr); } +}; + +// ===== Single Target Strategy ===== +MarksmanshipHunterStrategy::MarksmanshipHunterStrategy(PlayerbotAI* botAI) : GenericHunterStrategy(botAI) +{ + actionNodeFactories.Add(new MarksmanshipHunterStrategyActionNodeFactory()); +} + +// ===== Default Actions ===== +NextAction** MarksmanshipHunterStrategy::getDefaultActions() +{ + return NextAction::array(0, + new NextAction("kill command", 5.8f), + new NextAction("kill shot", 5.7f), + new NextAction("serpent sting", 5.6f), + new NextAction("chimera shot", 5.5f), + new NextAction("aimed shot", 5.4f), + new NextAction("arcane shot", 5.3f), + new NextAction("steady shot", 5.2f), + new NextAction("auto shot", 5.1f), nullptr); +} + +// ===== Trigger Initialization === +void MarksmanshipHunterStrategy::InitTriggers(std::vector& triggers) +{ + GenericHunterStrategy::InitTriggers(triggers); + triggers.push_back(new TriggerNode("silencing shot", NextAction::array(0, new NextAction("silencing shot", 40.0f), nullptr))); + triggers.push_back(new TriggerNode("kill command", NextAction::array(0, new NextAction("kill command", 18.5f), nullptr))); + triggers.push_back(new TriggerNode("target critical health", NextAction::array(0, new NextAction("kill shot", 18.0f), nullptr))); + triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 17.5f), nullptr))); + triggers.push_back(new TriggerNode("no stings", NextAction::array(0, new NextAction("serpent sting", 17.0f), nullptr))); + triggers.push_back(new TriggerNode("serpent sting on attacker", NextAction::array(0, new NextAction("serpent sting on attacker", 16.5f), nullptr))); +} + +// ===== AoE Strategy, 2/3+ enemies ===== +MarksmanshipHunterAoeStrategy::MarksmanshipHunterAoeStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {} + +void MarksmanshipHunterAoeStrategy::InitTriggers(std::vector& triggers) +{ + triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("volley", 22.0f), nullptr))); + triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("multi-shot", 21.0f), nullptr))); +} diff --git a/src/strategy/hunter/MarksmanshipHunterStrategy.h b/src/strategy/hunter/MarksmanshipHunterStrategy.h new file mode 100644 index 00000000..83a24cef --- /dev/null +++ b/src/strategy/hunter/MarksmanshipHunterStrategy.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2016+ AzerothCore , 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. + */ + +#ifndef _PLAYERBOT_MARKSMANSHIPHUNTERSTRATEGY_H +#define _PLAYERBOT_MARKSMANSHIPHUNTERSTRATEGY_H + +#include "GenericHunterStrategy.h" +#include "CombatStrategy.h" + +class PlayerbotAI; + +class MarksmanshipHunterStrategy : public GenericHunterStrategy +{ +public: + MarksmanshipHunterStrategy(PlayerbotAI* botAI); + + void InitTriggers(std::vector& triggers) override; + std::string const getName() override { return "mm"; } + NextAction** getDefaultActions() override; +}; + +class MarksmanshipHunterAoeStrategy : public CombatStrategy +{ +public: + MarksmanshipHunterAoeStrategy(PlayerbotAI* botAI); + + void InitTriggers(std::vector& triggers) override; + std::string const getName() override { return "mm aoe"; } +}; +#endif diff --git a/src/strategy/hunter/SurvivalHunterStrategy.cpp b/src/strategy/hunter/SurvivalHunterStrategy.cpp new file mode 100644 index 00000000..475db2dd --- /dev/null +++ b/src/strategy/hunter/SurvivalHunterStrategy.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2016+ AzerothCore , 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 "SurvivalHunterStrategy.h" +#include "Playerbots.h" + +// ===== Action Node Factory ===== +class SurvivalHunterStrategyActionNodeFactory : public NamedObjectFactory +{ +public: + SurvivalHunterStrategyActionNodeFactory() + { + creators["auto shot"] = &auto_shot; + creators["kill command"] = &kill_command; + creators["kill shot"] = &kill_shot; + creators["explosive shot"] = &explosive_shot; + creators["black arrow"] = &black_arrow; + creators["viper sting"] = &viper_sting; + creators["serpent sting"] = serpent_sting; + creators["aimed shot"] = &aimed_shot; + creators["arcane shot"] = &arcane_shot; + creators["steady shot"] = &steady_shot; + creators["multi-shot"] = &multi_shot; + creators["volley"] = &volley; + } + +private: + static ActionNode* auto_shot(PlayerbotAI*) { return new ActionNode("auto shot", nullptr, nullptr, nullptr); } + static ActionNode* kill_command(PlayerbotAI*) { return new ActionNode("kill command", nullptr, nullptr, nullptr); } + static ActionNode* kill_shot(PlayerbotAI*) { return new ActionNode("kill shot", nullptr, nullptr, nullptr); } + static ActionNode* explosive_shot(PlayerbotAI*) { return new ActionNode("explosive shot", nullptr, nullptr, nullptr); } + static ActionNode* black_arrow(PlayerbotAI*) { return new ActionNode("black arrow", nullptr, nullptr, nullptr); } + static ActionNode* viper_sting(PlayerbotAI*) { return new ActionNode("viper sting", nullptr, nullptr, nullptr); } + static ActionNode* serpent_sting(PlayerbotAI*) { return new ActionNode("serpent sting", nullptr, nullptr, nullptr); } + static ActionNode* aimed_shot(PlayerbotAI*) { return new ActionNode("aimed shot", nullptr, nullptr, nullptr); } + static ActionNode* arcane_shot(PlayerbotAI*) { return new ActionNode("arcane shot", nullptr, nullptr, nullptr); } + static ActionNode* steady_shot(PlayerbotAI*) { return new ActionNode("steady shot", nullptr, nullptr, nullptr); } + static ActionNode* multi_shot(PlayerbotAI*) { return new ActionNode("multi shot", nullptr, nullptr, nullptr); } + static ActionNode* volley(PlayerbotAI*) { return new ActionNode("volley", nullptr, nullptr, nullptr); } +}; + +// ===== Single Target Strategy ===== +SurvivalHunterStrategy::SurvivalHunterStrategy(PlayerbotAI* botAI) : GenericHunterStrategy(botAI) +{ + actionNodeFactories.Add(new SurvivalHunterStrategyActionNodeFactory()); +} + +// ===== Default Actions ===== +NextAction** SurvivalHunterStrategy::getDefaultActions() +{ + return NextAction::array(0, + new NextAction("kill command", 5.9f), + new NextAction("kill shot", 5.8f), + new NextAction("explosive shot", 5.7f), + new NextAction("black arrow", 5.6f), + new NextAction("serpent sting", 5.5f), + new NextAction("aimed shot", 5.4f), + new NextAction("arcane shot", 5.3f), + new NextAction("steady shot", 5.2f), + new NextAction("auto shot", 5.1f), nullptr); +} + +// ===== Trigger Initialization === +void SurvivalHunterStrategy::InitTriggers(std::vector& triggers) +{ + GenericHunterStrategy::InitTriggers(triggers); + + triggers.push_back(new TriggerNode("lock and load", NextAction::array(0, new NextAction("explosive shot rank 4", 28.0f), nullptr))); + triggers.push_back(new TriggerNode("lock and load", NextAction::array(0, new NextAction("explosive shot rank 3", 27.5f), nullptr))); + triggers.push_back(new TriggerNode("lock and load", NextAction::array(0, new NextAction("explosive shot rank 2", 27.0f), nullptr))); + triggers.push_back(new TriggerNode("lock and load", NextAction::array(0, new NextAction("explosive shot rank 1", 26.5f), nullptr))); + + triggers.push_back(new TriggerNode("kill command", NextAction::array(0, new NextAction("kill command", 18.5f), nullptr))); + triggers.push_back(new TriggerNode("target critical health", NextAction::array(0, new NextAction("kill shot", 18.0f), nullptr))); + triggers.push_back(new TriggerNode("explosive shot", NextAction::array(0, new NextAction("explosive shot", 17.5f), nullptr))); + triggers.push_back(new TriggerNode("black arrow", NextAction::array(0, new NextAction("black arrow", 16.5f), nullptr))); + triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 16.0f), nullptr))); + triggers.push_back(new TriggerNode("no stings", NextAction::array(0, new NextAction("serpent sting", 15.5f), nullptr))); + triggers.push_back(new TriggerNode("serpent sting on attacker", NextAction::array(0, new NextAction("serpent sting on attacker", 15.0f), nullptr))); +} + +// ===== AoE Strategy, 2/3+ enemies ===== +SurvivalHunterAoeStrategy::SurvivalHunterAoeStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {} + +void SurvivalHunterAoeStrategy::InitTriggers(std::vector& triggers) +{ + triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("volley", 22.0f), nullptr))); + triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("multi-shot", 21.0f), nullptr))); +} diff --git a/src/strategy/hunter/SurvivalHunterStrategy.h b/src/strategy/hunter/SurvivalHunterStrategy.h new file mode 100644 index 00000000..73eadb06 --- /dev/null +++ b/src/strategy/hunter/SurvivalHunterStrategy.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2016+ AzerothCore , 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. + */ + +#ifndef _PLAYERBOT_SURVIVALHUNTERSTRATEGY_H +#define _PLAYERBOT_SURVIVALHUNTERSTRATEGY_H + +#include "GenericHunterStrategy.h" +#include "CombatStrategy.h" + +class PlayerbotAI; + +class SurvivalHunterStrategy : public GenericHunterStrategy +{ +public: + SurvivalHunterStrategy(PlayerbotAI* botAI); + + void InitTriggers(std::vector& triggers) override; + std::string const getName() override { return "surv"; } + NextAction** getDefaultActions() override; +}; + +class SurvivalHunterAoeStrategy : public CombatStrategy +{ +public: + SurvivalHunterAoeStrategy(PlayerbotAI* botAI); + + void InitTriggers(std::vector& triggers) override; + std::string const getName() override { return "surv aoe"; } +}; +#endif