From 53395b64ed5b2de95881cc59d676daaf1469065a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E4=BD=A9=E8=8C=B9?= Date: Thu, 23 Mar 2023 12:22:58 -0600 Subject: [PATCH] avoid AOE strategy (WIP) --- src/strategy/StrategyContext.h | 2 + src/strategy/generic/CombatStrategy.cpp | 58 +++++++++++++++++++++++ src/strategy/generic/CombatStrategy.h | 9 ++++ src/strategy/triggers/GenericTriggers.cpp | 5 ++ src/strategy/triggers/GenericTriggers.h | 8 ++++ src/strategy/triggers/TriggerContext.h | 4 ++ src/strategy/values/AoeValues.cpp | 32 +++++++++++++ src/strategy/values/AoeValues.h | 15 ++++++ src/strategy/values/ValueContext.h | 4 ++ 9 files changed, 137 insertions(+) diff --git a/src/strategy/StrategyContext.h b/src/strategy/StrategyContext.h index a11d4ccc..6d4af223 100644 --- a/src/strategy/StrategyContext.h +++ b/src/strategy/StrategyContext.h @@ -108,6 +108,7 @@ class StrategyContext : public NamedObjectContext creators["group"] = &StrategyContext::group; creators["guild"] = &StrategyContext::guild; creators["grind"] = &StrategyContext::grind; + creators["avoid aoe"] = &StrategyContext::avoid_aoe; } private: @@ -166,6 +167,7 @@ class StrategyContext : public NamedObjectContext static Strategy* group(PlayerbotAI* botAI) { return new GroupStrategy(botAI); } static Strategy* guild (PlayerbotAI* botAI) { return new GuildStrategy(botAI); } static Strategy* grind(PlayerbotAI* botAI) { return new GrindingStrategy(botAI); } + static Strategy* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeStrategy(botAI); } }; class MovementStrategyContext : public NamedObjectContext diff --git a/src/strategy/generic/CombatStrategy.cpp b/src/strategy/generic/CombatStrategy.cpp index b0bb4aa3..765621a6 100644 --- a/src/strategy/generic/CombatStrategy.cpp +++ b/src/strategy/generic/CombatStrategy.cpp @@ -14,3 +14,61 @@ void CombatStrategy::InitTriggers(std::vector &triggers) triggers.push_back(new TriggerNode("combat stuck", NextAction::array(0, new NextAction("reset", 1.0f), nullptr))); triggers.push_back(new TriggerNode("combat long stuck", NextAction::array(0, new NextAction("hearthstone", 0.9f), new NextAction("repop", 0.8f), nullptr))); } + + +AvoidAoeStrategy::AvoidAoeStrategy(PlayerbotAI* botAI) : Strategy(botAI) +{ +} + + +class AvoidAoeStrategyMultiplier : public Multiplier +{ +public: + AvoidAoeStrategyMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "run away on area debuff") {} + +public: + virtual float GetValue(Action* action); + +private: +}; + +float AvoidAoeStrategyMultiplier::GetValue(Action* action) +{ + if (!action) + return 1.0f; + + std::string name = action->getName(); + if (name == "follow" || name == "co" || name == "nc" || name == "drop target") + return 1.0f; + + uint32 spellId = AI_VALUE2(uint32, "spell id", name); + const SpellInfo* const pSpellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!pSpellInfo) return 1.0f; + + if (spellId && pSpellInfo->Targets & TARGET_FLAG_DEST_LOCATION) + return 1.0f; + else if (spellId && pSpellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION) + return 1.0f; + + uint32 castTime = pSpellInfo->CalcCastTime(); + + if (AI_VALUE2(bool, "has area debuff", "self target") && spellId && castTime > 0) + { + return 0.0f; + } + + return 1.0f; +} + + +void AvoidAoeStrategy::InitTriggers(std::vector& triggers) +{ + triggers.push_back(new TriggerNode( + "has area debuff", + NextAction::array(0, new NextAction("flee", ACTION_EMERGENCY + 5), NULL))); +} + +void AvoidAoeStrategy::InitMultipliers(std::vector& multipliers) +{ + multipliers.push_back(new AvoidAoeStrategyMultiplier(botAI)); +} \ No newline at end of file diff --git a/src/strategy/generic/CombatStrategy.h b/src/strategy/generic/CombatStrategy.h index ea966150..0ac9e3f3 100644 --- a/src/strategy/generic/CombatStrategy.h +++ b/src/strategy/generic/CombatStrategy.h @@ -18,4 +18,13 @@ class CombatStrategy : public Strategy uint32 GetType() const override { return STRATEGY_TYPE_COMBAT; } }; +class AvoidAoeStrategy : public Strategy +{ +public: + explicit AvoidAoeStrategy(PlayerbotAI* ai); + const std::string getName() override { return "avoid aoe"; } + void InitMultipliers(std::vector& multipliers) override; + void InitTriggers(std::vector& triggers) override; +}; + #endif diff --git a/src/strategy/triggers/GenericTriggers.cpp b/src/strategy/triggers/GenericTriggers.cpp index 68087ab6..9015b724 100644 --- a/src/strategy/triggers/GenericTriggers.cpp +++ b/src/strategy/triggers/GenericTriggers.cpp @@ -508,3 +508,8 @@ bool IsFallingFarTrigger::IsActive() { return bot->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR); } + +bool HasAreaDebuffTrigger::IsActive() +{ + return AI_VALUE2(bool, "has area debuff", "self target"); +} diff --git a/src/strategy/triggers/GenericTriggers.h b/src/strategy/triggers/GenericTriggers.h index 46d617a3..85e5d172 100644 --- a/src/strategy/triggers/GenericTriggers.h +++ b/src/strategy/triggers/GenericTriggers.h @@ -702,4 +702,12 @@ class IsFallingFarTrigger : public Trigger bool IsActive() override; }; + +class HasAreaDebuffTrigger : public Trigger { + public: + HasAreaDebuffTrigger(PlayerbotAI* botAI) : Trigger(botAI, "have area debuff") {} + + bool IsActive() override; +}; + #endif diff --git a/src/strategy/triggers/TriggerContext.h b/src/strategy/triggers/TriggerContext.h index 3577c69a..a762adb3 100644 --- a/src/strategy/triggers/TriggerContext.h +++ b/src/strategy/triggers/TriggerContext.h @@ -77,6 +77,9 @@ class TriggerContext : public NamedObjectContext creators["medium aoe"] = &TriggerContext::MediumAoe; creators["high aoe"] = &TriggerContext::HighAoe; + creators["has area debuff"] = &TriggerContext::HasAreaDebuff; + + creators["enemy out of melee"] = &TriggerContext::EnemyOutOfMelee; creators["enemy out of spell"] = &TriggerContext::EnemyOutOfSpell; creators["enemy too close for spell"] = &TriggerContext::enemy_too_close_for_spell; @@ -224,6 +227,7 @@ class TriggerContext : public NamedObjectContext static Trigger* LightAoe(PlayerbotAI* botAI) { return new LightAoeTrigger(botAI); } static Trigger* MediumAoe(PlayerbotAI* botAI) { return new MediumAoeTrigger(botAI); } static Trigger* HighAoe(PlayerbotAI* botAI) { return new HighAoeTrigger(botAI); } + static Trigger* HasAreaDebuff(PlayerbotAI* botAI) { return new HasAreaDebuffTrigger(botAI); } static Trigger* LoseAggro(PlayerbotAI* botAI) { return new LoseAggroTrigger(botAI); } static Trigger* HasAggro(PlayerbotAI* botAI) { return new HasAggroTrigger(botAI); } static Trigger* LowHealth(PlayerbotAI* botAI) { return new LowHealthTrigger(botAI); } diff --git a/src/strategy/values/AoeValues.cpp b/src/strategy/values/AoeValues.cpp index 875529e7..67f7d1e0 100644 --- a/src/strategy/values/AoeValues.cpp +++ b/src/strategy/values/AoeValues.cpp @@ -5,6 +5,7 @@ #include "AoeValues.h" #include "Playerbots.h" #include "ServerFacade.h" +#include "SpellAuraEffects.h" GuidVector FindMaxDensity(Player* bot) { @@ -85,3 +86,34 @@ uint8 AoeCountValue::Calculate() { return FindMaxDensity(bot).size(); } + +bool HasAreaDebuffValue::Calculate() +{ + for (uint32 auraType = SPELL_AURA_BIND_SIGHT; auraType < TOTAL_AURAS; auraType++) + { + Unit::AuraEffectList const& auras = botAI->GetBot()->GetAuraEffectsByType((AuraType)auraType); + + if (auras.empty()) + continue; + + for (AuraEffect const* aurEff : auras) + { + SpellInfo const* proto = aurEff->GetSpellInfo(); + + if (!proto) + continue; + + uint32 trigger_spell_id = proto->Effects[aurEff->GetEffIndex()].TriggerSpell; + if (trigger_spell_id == 29767) //Overload + { + return true; + } + else + { + return (!proto->IsPositive() && aurEff->IsPeriodic() && proto->HasAreaAuraEffect()); + } + } + } + + return false; +} \ No newline at end of file diff --git a/src/strategy/values/AoeValues.h b/src/strategy/values/AoeValues.h index c73c2514..04ca3f37 100644 --- a/src/strategy/values/AoeValues.h +++ b/src/strategy/values/AoeValues.h @@ -7,6 +7,7 @@ #include "Object.h" #include "Value.h" +#include "AiObjectContext.h" class PlayerbotAI; @@ -26,4 +27,18 @@ class AoeCountValue : public CalculatedValue uint8 Calculate() override; }; +class HasAreaDebuffValue : public BoolCalculatedValue, public Qualified +{ + public: + HasAreaDebuffValue(PlayerbotAI* botAI) : BoolCalculatedValue(botAI) {} + + Unit* GetTarget() + { + AiObjectContext* ctx = AiObject::context; + + return ctx->GetValue(qualifier)->Get(); + } + virtual bool Calculate(); +}; + #endif diff --git a/src/strategy/values/ValueContext.h b/src/strategy/values/ValueContext.h index 8e60813d..7d0c9080 100644 --- a/src/strategy/values/ValueContext.h +++ b/src/strategy/values/ValueContext.h @@ -283,6 +283,8 @@ class ValueContext : public NamedObjectContext creators["RTSC selected"] = &ValueContext::RTSC_selected; creators["RTSC next spell action"] = &ValueContext::RTSC_next_spell_action; creators["RTSC saved location"] = &ValueContext::RTSC_saved_location; + + creators["has area debuff"] = &ValueContext::has_area_debuff; } private: @@ -471,6 +473,8 @@ class ValueContext : public NamedObjectContext static UntypedValue* RTSC_selected(PlayerbotAI* botAI) { return new RTSCSelectedValue(botAI); } static UntypedValue* RTSC_next_spell_action(PlayerbotAI* botAI) { return new RTSCNextSpellActionValue(botAI); } static UntypedValue* RTSC_saved_location(PlayerbotAI* botAI) { return new RTSCSavedLocationValue(botAI); } + + static UntypedValue* has_area_debuff(PlayerbotAI* botAI) { return new HasAreaDebuffValue(botAI); } }; #endif