From a76290a149530011ed28534bf9da022f27507627 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 29 Oct 2023 00:16:31 +0800 Subject: [PATCH] better shaman totem strategy --- src/strategy/actions/GenericSpellActions.cpp | 6 ++-- src/strategy/shaman/CasterShamanStrategy.cpp | 7 ++-- src/strategy/shaman/HealShamanStrategy.cpp | 6 ++-- src/strategy/shaman/MeleeShamanStrategy.cpp | 25 ++++++++++--- src/strategy/shaman/ShamanActions.cpp | 11 ++++-- src/strategy/shaman/ShamanActions.h | 36 ++++++++++++++----- src/strategy/shaman/ShamanAiObjectContext.cpp | 7 +++- src/strategy/shaman/ShamanTriggers.cpp | 6 ++++ src/strategy/shaman/ShamanTriggers.h | 17 +++++++-- src/strategy/shaman/TotemsShamanStrategy.cpp | 19 +++++++--- 10 files changed, 108 insertions(+), 32 deletions(-) diff --git a/src/strategy/actions/GenericSpellActions.cpp b/src/strategy/actions/GenericSpellActions.cpp index c5223882..7309ee7f 100644 --- a/src/strategy/actions/GenericSpellActions.cpp +++ b/src/strategy/actions/GenericSpellActions.cpp @@ -118,9 +118,9 @@ bool CastSpellAction::isUseful() CastMeleeSpellAction::CastMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell) { range = ATTACK_DISTANCE; - Unit* target = AI_VALUE(Unit*, "current target"); - if (target) - range = bot->GetMeleeRange(target); + // Unit* target = AI_VALUE(Unit*, "current target"); + // if (target) + // range = bot->GetMeleeRange(target); // range = target->GetCombinedCombatReach(); } diff --git a/src/strategy/shaman/CasterShamanStrategy.cpp b/src/strategy/shaman/CasterShamanStrategy.cpp index 6455dee3..bdb773c6 100644 --- a/src/strategy/shaman/CasterShamanStrategy.cpp +++ b/src/strategy/shaman/CasterShamanStrategy.cpp @@ -39,7 +39,8 @@ CasterShamanStrategy::CasterShamanStrategy(PlayerbotAI* botAI) : GenericShamanSt NextAction** CasterShamanStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("lava burst", ACTION_DEFAULT + 0.1f), + new NextAction("lava burst", ACTION_DEFAULT + 0.2f), + new NextAction("thunderstorm", ACTION_DEFAULT + 0.1f), new NextAction("lightning bolt", ACTION_DEFAULT), NULL); } @@ -55,7 +56,9 @@ void CasterShamanStrategy::InitTriggers(std::vector& triggers) // triggers.push_back(new TriggerNode("frost shock snare", NextAction::array(0, new NextAction("frost shock", 21.0f), nullptr))); triggers.push_back(new TriggerNode( "no fire totem", - NextAction::array(0, new NextAction("totem of wrath", 15.0f), NULL))); + NextAction::array(0, + // new NextAction("fire elemental totem", 16.0f), + new NextAction("totem of wrath", 15.0f), NULL))); triggers.push_back(new TriggerNode("enemy too close for spell", NextAction::array(0, new NextAction("flee", ACTION_HIGH), nullptr))); } diff --git a/src/strategy/shaman/HealShamanStrategy.cpp b/src/strategy/shaman/HealShamanStrategy.cpp index ed5ecad7..4deda015 100644 --- a/src/strategy/shaman/HealShamanStrategy.cpp +++ b/src/strategy/shaman/HealShamanStrategy.cpp @@ -81,9 +81,9 @@ void HealShamanStrategy::InitTriggers(std::vector& triggers) "party member cleanse spirit curse", NextAction::array(0, new NextAction("cleanse spirit curse on party", ACTION_DISPEL + 2), NULL))); - triggers.push_back(new TriggerNode( - "no fire totem", - NextAction::array(0, new NextAction("fire elemental totem", 11.0f), new NextAction("flametongue totem", 10.0f), NULL))); + // triggers.push_back(new TriggerNode( + // "no fire totem", + // NextAction::array(0, new NextAction("flametongue totem", 10.0f), NULL))); triggers.push_back(new TriggerNode( "no water totem", diff --git a/src/strategy/shaman/MeleeShamanStrategy.cpp b/src/strategy/shaman/MeleeShamanStrategy.cpp index 54db4dac..fff1d05c 100644 --- a/src/strategy/shaman/MeleeShamanStrategy.cpp +++ b/src/strategy/shaman/MeleeShamanStrategy.cpp @@ -50,9 +50,10 @@ MeleeShamanStrategy::MeleeShamanStrategy(PlayerbotAI* botAI) : GenericShamanStra NextAction** MeleeShamanStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("stormstrike", ACTION_DEFAULT + 0.4f), - new NextAction("earth shock", ACTION_DEFAULT + 0.3f), - new NextAction("fire nova", ACTION_DEFAULT + 0.2f), + new NextAction("stormstrike", ACTION_DEFAULT + 0.5f), + new NextAction("earth shock", ACTION_DEFAULT + 0.4f), + new NextAction("feral spirit", ACTION_DEFAULT + 0.3f), + new NextAction("fire nova", ACTION_DEFAULT + 0.2f), new NextAction("lava lash", ACTION_DEFAULT + 0.1f), new NextAction("melee", ACTION_DEFAULT), NULL); @@ -72,9 +73,23 @@ void MeleeShamanStrategy::InitTriggers(std::vector& triggers) // triggers.push_back(new TriggerNode("enemy too close for melee", NextAction::array(0, new NextAction("move out of enemy contact", ACTION_NORMAL + 8), nullptr))); triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("strength of earth totem", ACTION_LIGHT_HEAL), 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( "no fire totem", - NextAction::array(0, new NextAction("reach melee", 23.0f), new NextAction("magma totem", 22.0f), nullptr))); + NextAction::array(0, + new NextAction("reach melee", 23.0f), + new NextAction("magma totem", 22.0f), nullptr))); + + triggers.push_back(new TriggerNode("fire elemental totem", + NextAction::array(0, + new NextAction("reach melee", 33.0f), + new NextAction("fire elemental totem", 32.0f), + nullptr))); + + triggers.push_back(new TriggerNode( + "no air totem", + NextAction::array(0, new NextAction("windfury totem", 20.0f), nullptr))); + triggers.push_back(new TriggerNode( "medium mana", NextAction::array(0, new NextAction("shamanistic rage", 23.0f), nullptr))); @@ -83,6 +98,6 @@ void MeleeShamanStrategy::InitTriggers(std::vector& triggers) void MeleeAoeShamanStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("magma totem", NextAction::array(0, new NextAction("magma totem", 26.0f), nullptr))); + // triggers.push_back(new TriggerNode("magma totem", NextAction::array(0, new NextAction("magma totem", 26.0f), nullptr))); triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("fire nova", 25.0f), nullptr))); } diff --git a/src/strategy/shaman/ShamanActions.cpp b/src/strategy/shaman/ShamanActions.cpp index c8ede56d..e4e0fca2 100644 --- a/src/strategy/shaman/ShamanActions.cpp +++ b/src/strategy/shaman/ShamanActions.cpp @@ -7,7 +7,14 @@ bool CastTotemAction::isUseful() { - return CastBuffSpellAction::isUseful() && !AI_VALUE2(bool, "has totem", name); + if (needLifeTime > 0.1f) { + Unit* target = AI_VALUE(Unit*, "current target"); + float dps = AI_VALUE(float, "expected group dps"); + if (target->GetHealth() / dps < needLifeTime) { + return false; + } + } + return CastBuffSpellAction::isUseful() && !AI_VALUE2(bool, "has totem", name) && !botAI->HasAura(buff, bot); } bool CastManaSpringTotemAction::isUseful() @@ -27,7 +34,7 @@ bool CastSearingTotemAction::isUseful() bool CastMagmaTotemAction::isUseful() { - return CastMeleeSpellAction::isUseful() && !AI_VALUE2(bool, "has totem", name); + return CastTotemAction::isUseful() && !AI_VALUE2(bool, "has totem", name); } bool CastCleansingTotemAction::isUseful() diff --git a/src/strategy/shaman/ShamanActions.h b/src/strategy/shaman/ShamanActions.h index be21e676..3f7cb9f6 100644 --- a/src/strategy/shaman/ShamanActions.h +++ b/src/strategy/shaman/ShamanActions.h @@ -5,7 +5,9 @@ #ifndef _PLAYERBOT_SHAMANACTIONS_H #define _PLAYERBOT_SHAMANACTIONS_H +#include "Define.h" #include "GenericSpellActions.h" +#include "Playerbots.h" #include "SharedDefines.h" class PlayerbotAI; @@ -109,9 +111,19 @@ class CastWindfuryWeaponAction : public CastEnchantItemAction class CastTotemAction : public CastBuffSpellAction { public: - CastTotemAction(PlayerbotAI* botAI, std::string const spell) : CastBuffSpellAction(botAI, spell) { } + CastTotemAction(PlayerbotAI* botAI, std::string const spell, std::string const buffName = "", float needLifeTime = 8.0f) + : CastBuffSpellAction(botAI, spell), needLifeTime(needLifeTime) { + if (buffName == "") { + buff = spell; + } else { + buff = buffName; + } + } bool isUseful() override; + protected: + float needLifeTime; + std::string buff; }; class CastStoneskinTotemAction : public CastTotemAction @@ -129,13 +141,13 @@ class CastEarthbindTotemAction : public CastTotemAction class CastStrengthOfEarthTotemAction : public CastTotemAction { public: - CastStrengthOfEarthTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "strength of earth totem") { } + CastStrengthOfEarthTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "strength of earth totem", "strength of earth", 20.0f) { } }; class CastManaSpringTotemAction : public CastTotemAction { public: - CastManaSpringTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "mana spring totem") { } + CastManaSpringTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "mana spring totem", "mana spring", 20.0f) { } bool isUseful() override; }; @@ -164,7 +176,7 @@ class CastCleansingTotemAction : public CastTotemAction class CastFlametongueTotemAction : public CastTotemAction { public: - CastFlametongueTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "flametongue totem") { } + CastFlametongueTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "flametongue totem", "", 20.0f) { } bool isUseful() override; }; @@ -184,16 +196,16 @@ class CastGraceOfAirTotemAction : public CastTotemAction class CastSearingTotemAction : public CastTotemAction { public: - CastSearingTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "searing totem") { } + CastSearingTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "searing totem", "", 0.0f) { } std::string const GetTargetName() override { return "self target"; } bool isUseful() override; }; -class CastMagmaTotemAction : public CastMeleeSpellAction +class CastMagmaTotemAction : public CastTotemAction { public: - CastMagmaTotemAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "magma totem") { } + CastMagmaTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "magma totem", "", 0.0f) { } std::string const GetTargetName() override { return "self target"; } bool isUseful() override; @@ -392,7 +404,7 @@ class CastTotemOfWrathAction : public CastTotemAction class CastFireElementalTotemAction : public CastTotemAction { public: - CastFireElementalTotemAction(PlayerbotAI* ai) : CastTotemAction(ai, "fire elemental totem") {} + CastFireElementalTotemAction(PlayerbotAI* ai) : CastTotemAction(ai, "fire elemental totem", "", 0.0f) {} virtual std::string const GetTargetName() override { return "self target"; } virtual bool isUseful() override { return CastTotemAction::isUseful(); } }; @@ -400,7 +412,7 @@ class CastFireElementalTotemAction : public CastTotemAction class CastWrathOfAirTotemAction : public CastTotemAction { public: - CastWrathOfAirTotemAction(PlayerbotAI* ai) : CastTotemAction(ai, "wrath of air totem") {} + CastWrathOfAirTotemAction(PlayerbotAI* ai) : CastTotemAction(ai, "wrath of air totem", "wrath of air totem") {} }; class CastShamanisticRageAction : public CastBuffSpellAction @@ -408,4 +420,10 @@ class CastShamanisticRageAction : public CastBuffSpellAction public: CastShamanisticRageAction(PlayerbotAI* ai) : CastBuffSpellAction(ai, "shamanistic rage") {} }; + +class CastFeralSpiritAction : public CastSpellAction +{ + public: + CastFeralSpiritAction(PlayerbotAI* ai) : CastSpellAction(ai, "feral spirit") {} +}; #endif diff --git a/src/strategy/shaman/ShamanAiObjectContext.cpp b/src/strategy/shaman/ShamanAiObjectContext.cpp index 234f5bb3..c40f4957 100644 --- a/src/strategy/shaman/ShamanAiObjectContext.cpp +++ b/src/strategy/shaman/ShamanAiObjectContext.cpp @@ -74,6 +74,7 @@ class ShamanATriggerFactoryInternal : public NamedObjectContext creators["mana spring totem"] = &ShamanATriggerFactoryInternal::mana_spring_totem; creators["flametongue totem"] = &ShamanATriggerFactoryInternal::flametongue_totem; creators["strength of earth totem"] = &ShamanATriggerFactoryInternal::strength_of_earth_totem; + creators["fire elemental totem"] = &ShamanATriggerFactoryInternal::fire_elemental_totem; creators["magma totem"] = &ShamanATriggerFactoryInternal::magma_totem; creators["searing totem"] = &ShamanATriggerFactoryInternal::searing_totem; creators["wind shear"] = &ShamanATriggerFactoryInternal::wind_shear; @@ -102,6 +103,7 @@ class ShamanATriggerFactoryInternal : public NamedObjectContext creators["party member cure disease"] = &ShamanATriggerFactoryInternal::party_member_cure_disease; creators["no fire totem"] = &ShamanATriggerFactoryInternal::no_fire_totem; creators["no water totem"] = &ShamanATriggerFactoryInternal::no_water_totem; + creators["no air totem"] = &ShamanATriggerFactoryInternal::no_air_totem; creators["earth shield on main tank"] = &ShamanATriggerFactoryInternal::earth_shield_on_main_tank; creators["maelstrom weapon"] = &ShamanATriggerFactoryInternal::maelstrom_weapon; creators["flame shock"] = &ShamanATriggerFactoryInternal::flame_shock; @@ -127,6 +129,7 @@ class ShamanATriggerFactoryInternal : public NamedObjectContext static Trigger* mana_spring_totem(PlayerbotAI* botAI) { return new ManaSpringTotemTrigger(botAI); } static Trigger* flametongue_totem(PlayerbotAI* botAI) { return new FlametongueTotemTrigger(botAI); } static Trigger* strength_of_earth_totem(PlayerbotAI* botAI) { return new StrengthOfEarthTotemTrigger(botAI); } + static Trigger* fire_elemental_totem(PlayerbotAI* botAI) { return new FireElementalTotemTrigger(botAI); } static Trigger* magma_totem(PlayerbotAI* botAI) { return new MagmaTotemTrigger(botAI); } static Trigger* searing_totem(PlayerbotAI* botAI) { return new SearingTotemTrigger(botAI); } static Trigger* wind_shear(PlayerbotAI* botAI) { return new WindShearInterruptSpellTrigger(botAI); } @@ -143,6 +146,7 @@ class ShamanATriggerFactoryInternal : public NamedObjectContext static Trigger* party_member_cure_disease(PlayerbotAI* botAI) { return new PartyMemberCureDiseaseTrigger(botAI); } static Trigger* no_fire_totem(PlayerbotAI* ai) { return new NoFireTotemTrigger(ai); } static Trigger* no_water_totem(PlayerbotAI* ai) { return new NoWaterTotemTrigger(ai); } + static Trigger* no_air_totem(PlayerbotAI* ai) { return new NoAirTotemTrigger(ai); } static Trigger* earth_shield_on_main_tank(PlayerbotAI* ai) { return new EarthShieldOnMainTankTrigger(ai); } static Trigger* flame_shock(PlayerbotAI* ai) { return new FlameShockTrigger(ai); } static Trigger* wrath_of_air_totem(PlayerbotAI* ai) { return new WrathOfAirTotemTrigger(ai); } @@ -210,9 +214,9 @@ class ShamanAiObjectContextInternal : public NamedObjectContext creators["earth shield on main tank"] = &ShamanAiObjectContextInternal::earth_shield_on_main_tank; creators["fire elemental totem"] = &ShamanAiObjectContextInternal::fire_elemental_totem; creators["totem of wrath"] = &ShamanAiObjectContextInternal::totem_of_wrath; - creators["fire elemental totem"] = &ShamanAiObjectContextInternal::fire_elemental_totem; creators["wrath of air totem"] = &ShamanAiObjectContextInternal::wrath_of_air_totem; creators["shamanistic rage"] = &ShamanAiObjectContextInternal::shamanistic_rage; + creators["feral spirit"] = &ShamanAiObjectContextInternal::feral_spirit; } private: @@ -275,6 +279,7 @@ class ShamanAiObjectContextInternal : public NamedObjectContext static Action* fire_elemental_totem(PlayerbotAI* ai) { return new CastFireElementalTotemAction(ai); } static Action* wrath_of_air_totem(PlayerbotAI* ai) { return new CastWrathOfAirTotemAction(ai); } static Action* shamanistic_rage(PlayerbotAI* ai) { return new CastShamanisticRageAction(ai); } + static Action* feral_spirit(PlayerbotAI* ai) { return new CastFeralSpiritAction(ai); } }; diff --git a/src/strategy/shaman/ShamanTriggers.cpp b/src/strategy/shaman/ShamanTriggers.cpp index 684360f5..459b9bc6 100644 --- a/src/strategy/shaman/ShamanTriggers.cpp +++ b/src/strategy/shaman/ShamanTriggers.cpp @@ -84,4 +84,10 @@ bool NoWaterTotemTrigger::IsActive() !AI_VALUE2(bool, "has totem", "cleansing totem") && !AI_VALUE2(bool, "has totem", "mana spring totem") && !AI_VALUE2(bool, "has totem", "healing stream totem"); +} + +bool NoAirTotemTrigger::IsActive() +{ + return !AI_VALUE2(bool, "has totem", "wrath of air totem") && + !AI_VALUE2(bool, "has totem", "windfury totem"); } \ No newline at end of file diff --git a/src/strategy/shaman/ShamanTriggers.h b/src/strategy/shaman/ShamanTriggers.h index 4dae65e0..54395b4b 100644 --- a/src/strategy/shaman/ShamanTriggers.h +++ b/src/strategy/shaman/ShamanTriggers.h @@ -65,6 +65,12 @@ class StrengthOfEarthTotemTrigger : public TotemTrigger StrengthOfEarthTotemTrigger(PlayerbotAI* botAI) : TotemTrigger(botAI, "strength of earth totem") { } }; +class FireElementalTotemTrigger : public BoostTrigger +{ + public: + FireElementalTotemTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "fire elemental totem") { } +}; + class MagmaTotemTrigger : public TotemTrigger { public: @@ -234,13 +240,13 @@ class PartyMemberCureDiseaseTrigger : public PartyMemberNeedCureTrigger class NoFireTotemTrigger : public Trigger { public: NoFireTotemTrigger(PlayerbotAI* ai) : Trigger(ai, "no fire totem") {} - virtual bool IsActive() override; + bool IsActive() override; }; class NoWaterTotemTrigger : public Trigger { public: NoWaterTotemTrigger(PlayerbotAI* ai) : Trigger(ai, "no water totem") {} - virtual bool IsActive() override; + bool IsActive() override; }; class EarthShieldOnMainTankTrigger : public BuffOnMainTankTrigger @@ -259,4 +265,11 @@ class WrathOfAirTotemTrigger : public TotemTrigger public: WrathOfAirTotemTrigger(PlayerbotAI* ai) : TotemTrigger(ai, "wrath of air totem") {} }; + +class NoAirTotemTrigger : public TotemTrigger +{ + public: + NoAirTotemTrigger(PlayerbotAI* ai) : TotemTrigger(ai, "no air totem") {} + bool IsActive() override; +}; #endif diff --git a/src/strategy/shaman/TotemsShamanStrategy.cpp b/src/strategy/shaman/TotemsShamanStrategy.cpp index fabfa8cd..4c9a34aa 100644 --- a/src/strategy/shaman/TotemsShamanStrategy.cpp +++ b/src/strategy/shaman/TotemsShamanStrategy.cpp @@ -13,19 +13,28 @@ void TotemsShamanStrategy::InitTriggers(std::vector& triggers) { GenericShamanStrategy::InitTriggers(triggers); + triggers.push_back(new TriggerNode("fire elemental totem", NextAction::array(0, new NextAction("fire elemental totem", 32.0f), nullptr))); + triggers.push_back(new TriggerNode( - "wrath of air totem", + "no air totem", NextAction::array(0, new NextAction("wrath of air totem", 8.0f), NULL))); triggers.push_back(new TriggerNode( "no water totem", - NextAction::array(0, new NextAction("mana spring totem", 7.0f), NULL))); + NextAction::array(0, + new NextAction("mana spring totem", 7.0f), + new NextAction("healing stream totem", 6.0f), + nullptr))); + + triggers.push_back(new TriggerNode( + "no fire totem", + NextAction::array(0, + new NextAction("flametongue totem", 7.0f), + new NextAction("searing totem", 6.0f), + nullptr))); triggers.push_back(new TriggerNode( "strength of earth totem", NextAction::array(0, new NextAction("strength of earth totem", 6.0f), NULL))); - triggers.push_back(new TriggerNode( - "no fire totem", - NextAction::array(0, new NextAction("flametongue totem", 5.0f), NULL))); }