From d45a7dc5b838022d0078008324cfb731f86ece07 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 29 May 2023 23:03:21 +0800 Subject: [PATCH] fix party member dispel. --- src/PlayerbotAI.cpp | 4 +- src/strategy/actions/ActionContext.h | 4 + src/strategy/actions/ChatActionContext.h | 2 + src/strategy/actions/GenericActions.cpp | 27 ++++++ src/strategy/actions/GenericActions.h | 7 ++ src/strategy/actions/TellLosAction.cpp | 65 +++++++++++++ src/strategy/actions/TellLosAction.h | 7 ++ .../GenericDKNonCombatStrategy.cpp | 3 +- src/strategy/druid/DruidActions.h | 17 ++++ src/strategy/druid/DruidAiObjectContext.cpp | 6 ++ src/strategy/druid/DruidShapeshiftActions.cpp | 5 + src/strategy/druid/DruidShapeshiftActions.h | 1 + src/strategy/druid/DruidTriggers.cpp | 2 +- .../druid/GenericDruidNonCombatStrategy.cpp | 37 +++++--- src/strategy/druid/GenericDruidStrategy.cpp | 14 +-- src/strategy/druid/HealDruidStrategy.cpp | 60 ++++++++++-- .../generic/ChatCommandHandlerStrategy.cpp | 1 + .../hunter/GenericHunterNonCombatStrategy.cpp | 1 + src/strategy/triggers/ChatTriggerContext.h | 2 + src/strategy/triggers/CureTriggers.h | 2 +- src/strategy/triggers/GenericTriggers.cpp | 4 + src/strategy/triggers/GenericTriggers.h | 8 ++ src/strategy/triggers/HealthTriggers.cpp | 5 + src/strategy/triggers/HealthTriggers.h | 10 ++ src/strategy/triggers/TriggerContext.h | 4 + src/strategy/values/PartyMemberToHeal.cpp | 93 +++++++------------ src/strategy/values/PartyMemberValue.cpp | 14 ++- 27 files changed, 316 insertions(+), 89 deletions(-) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 3350f263..524384e8 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -2568,7 +2568,7 @@ bool PlayerbotAI::HasAuraToDispel(Unit* target, uint32 dispelType) continue; if (sPlayerbotAIConfig->dispelAuraDuration && aura->GetDuration() && aura->GetDuration() < (int32)sPlayerbotAIConfig->dispelAuraDuration) - return false; + continue; if (canDispel(spellInfo, dispelType)) return true; @@ -2946,7 +2946,7 @@ void PlayerbotAI::RemoveShapeshift() RemoveAura("swift flight form"); RemoveAura("aquatic form"); RemoveAura("ghost wolf"); - RemoveAura("tree of life"); + // RemoveAura("tree of life"); } uint32 PlayerbotAI::GetEquipGearScore(Player* player, bool withBags, bool withBank) diff --git a/src/strategy/actions/ActionContext.h b/src/strategy/actions/ActionContext.h index 7e89e23b..3e07f02e 100644 --- a/src/strategy/actions/ActionContext.h +++ b/src/strategy/actions/ActionContext.h @@ -219,6 +219,8 @@ class ActionContext : public NamedObjectContext creators["rpg trade useful"] = &ActionContext::rpg_trade_useful; creators["rpg duel"] = &ActionContext::rpg_duel; creators["rpg mount anim"] = &ActionContext::rpg_mount_anim; + + creators["toggle pet spell"] = &ActionContext::toggle_pet_spell; } private: @@ -378,6 +380,8 @@ class ActionContext : public NamedObjectContext static Action* rpg_trade_useful(PlayerbotAI* botAI) { return new RpgTradeUsefulAction(botAI); } static Action* rpg_duel(PlayerbotAI* botAI) { return new RpgDuelAction(botAI); } static Action* rpg_mount_anim(PlayerbotAI* botAI) { return new RpgMountAnimAction(botAI); } + + static Action* toggle_pet_spell(PlayerbotAI* ai) { return new TogglePetSpellAutoCastAction(ai); } }; #endif diff --git a/src/strategy/actions/ChatActionContext.h b/src/strategy/actions/ChatActionContext.h index b258dc84..3565483c 100644 --- a/src/strategy/actions/ChatActionContext.h +++ b/src/strategy/actions/ChatActionContext.h @@ -85,6 +85,7 @@ class ChatActionContext : public NamedObjectContext creators["reputation"] = &ChatActionContext::reputation; creators["log"] = &ChatActionContext::log; creators["los"] = &ChatActionContext::los; + creators["aura"] = &ChatActionContext::aura; creators["drop"] = &ChatActionContext::drop; creators["clean quest log"] = &ChatActionContext::clean_quest_log; creators["share"] = &ChatActionContext::share; @@ -238,6 +239,7 @@ class ChatActionContext : public NamedObjectContext static Action* reputation(PlayerbotAI* botAI) { return new TellReputationAction(botAI); } static Action* log(PlayerbotAI* botAI) { return new LogLevelAction(botAI); } static Action* los(PlayerbotAI* botAI) { return new TellLosAction(botAI); } + static Action* aura(PlayerbotAI* ai) { return new TellAuraAction(ai); } static Action* ll(PlayerbotAI* botAI) { return new LootStrategyAction(botAI); } static Action* ss(PlayerbotAI* botAI) { return new SkipSpellsListAction(botAI); } static Action* add_all_loot(PlayerbotAI* botAI) { return new AddAllLootAction(botAI); } diff --git a/src/strategy/actions/GenericActions.cpp b/src/strategy/actions/GenericActions.cpp index 5d34bf43..43da2703 100644 --- a/src/strategy/actions/GenericActions.cpp +++ b/src/strategy/actions/GenericActions.cpp @@ -13,3 +13,30 @@ bool MeleeAction::isUseful() return true; } + +bool TogglePetSpellAutoCastAction::Execute(Event event) { + Pet* pet = bot->GetPet(); + if (!pet) { + return false; + } + for (PetSpellMap::const_iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) + { + if(itr->second.state == PETSPELL_REMOVED) + continue; + + uint32 spellId = itr->first; + const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (spellInfo->IsPassive()) + continue; + + // imp's spell, felhunte's intelligence, ghoul's leap + if (spellId == 4511 || spellId == 1742 || + spellId == 54424 || spellId == 57564 || spellId == 57565 || spellId == 57566 || spellId == 57567 || + spellId == 47482) { + pet->ToggleAutocast(spellInfo, false); + } else { + pet->ToggleAutocast(spellInfo, true); + } + } + return true; +} \ No newline at end of file diff --git a/src/strategy/actions/GenericActions.h b/src/strategy/actions/GenericActions.h index 7c6b9936..66385008 100644 --- a/src/strategy/actions/GenericActions.h +++ b/src/strategy/actions/GenericActions.h @@ -18,4 +18,11 @@ class MeleeAction : public AttackAction bool isUseful() override; }; +class TogglePetSpellAutoCastAction: public Action +{ +public: + TogglePetSpellAutoCastAction(PlayerbotAI* ai): Action(ai, "toggle pet spell") {} + virtual bool Execute(Event event) override; +}; + #endif diff --git a/src/strategy/actions/TellLosAction.cpp b/src/strategy/actions/TellLosAction.cpp index 810913d3..461df0d9 100644 --- a/src/strategy/actions/TellLosAction.cpp +++ b/src/strategy/actions/TellLosAction.cpp @@ -61,3 +61,68 @@ void TellLosAction::ListGameObjects(std::string const title, GuidVector gos) botAI->TellMaster(chat->FormatGameobject(go)); } } + +bool TellAuraAction::Execute(Event event) +{ + botAI->TellMaster("--- Auras ---"); + sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "--- Auras ---"); + Unit::AuraApplicationMap& map = bot->GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator i = map.begin(); i != map.end(); ++i) + { + Aura * aura = i->second->GetBase(); + if (!aura) + continue; + + const std::string auraName = aura->GetSpellInfo()->SpellName[0]; + sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "Info of Aura - name: " + auraName); + AuraObjectType type = aura->GetType(); + WorldObject* owner = aura->GetOwner(); + std::string owner_name = owner ? owner->GetName() : "unknown"; + float distance = bot->GetDistance2d(owner); + Unit* caster = aura->GetCaster(); + std::string caster_name = caster ? caster->GetName() : "unknown"; + bool is_area = aura->IsArea(); + int32 duration = aura->GetDuration(); + const SpellInfo* spellInfo = aura->GetSpellInfo(); + int32 spellId = aura->GetSpellInfo()->Id; + bool isPositive = aura->GetSpellInfo()->IsPositive(); + sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "Info of Aura - name: " + auraName + + " caster: " + caster_name + + " type: " + std::to_string(type) + + " owner: " + owner_name + + " distance: " + std::to_string(distance) + + " isArea: " + std::to_string(is_area) + + " duration: " + std::to_string(duration) + + " spellId: " + std::to_string(spellId) + + " isPositive: " + std::to_string(isPositive)); + + botAI->TellMaster("Info of Aura - name: " + auraName + + " caster: " + caster_name + + " type: " + std::to_string(type) + + " owner: " + owner_name + + " distance: " + std::to_string(distance) + + " isArea: " + std::to_string(is_area) + + " duration: " + std::to_string(duration) + + " spellId: " + std::to_string(spellId) + + " isPositive: " + std::to_string(isPositive)); + + if (type == DYNOBJ_AURA_TYPE) { + DynamicObject* dyn_owner = aura->GetDynobjOwner(); + float radius = dyn_owner->GetRadius(); + int32 spellId = dyn_owner->GetSpellId(); + int32 duration = dyn_owner->GetDuration(); + sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, std::string("Info of DynamicObject -") + + " name: " + dyn_owner->GetName() + + " radius: " + std::to_string(radius) + + " spell id: " + std::to_string(spellId) + + " duration: " + std::to_string(duration)); + + botAI->TellMaster(std::string("Info of DynamicObject -") + + " name: " + dyn_owner->GetName() + + " radius: " + std::to_string(radius) + + " spell id: " + std::to_string(spellId) + + " duration: " + std::to_string(duration)); + } + } + return true; +} \ No newline at end of file diff --git a/src/strategy/actions/TellLosAction.h b/src/strategy/actions/TellLosAction.h index b506e502..5879fd85 100644 --- a/src/strategy/actions/TellLosAction.h +++ b/src/strategy/actions/TellLosAction.h @@ -21,4 +21,11 @@ class TellLosAction : public Action void ListGameObjects(std::string const title, GuidVector gos); }; +class TellAuraAction : public Action +{ + public: + TellAuraAction(PlayerbotAI* ai) : Action(ai, "aura") {} + + virtual bool Execute(Event event); +}; #endif diff --git a/src/strategy/deathknight/GenericDKNonCombatStrategy.cpp b/src/strategy/deathknight/GenericDKNonCombatStrategy.cpp index c0694a22..e648bec7 100644 --- a/src/strategy/deathknight/GenericDKNonCombatStrategy.cpp +++ b/src/strategy/deathknight/GenericDKNonCombatStrategy.cpp @@ -44,9 +44,10 @@ void GenericDKNonCombatStrategy::InitTriggers(std::vector& trigger triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("raise dead", ACTION_NORMAL + 1), nullptr))); triggers.push_back(new TriggerNode("horn of winter", NextAction::array(0, new NextAction("horn of winter", 21.0f), nullptr))); triggers.push_back(new TriggerNode("bone shield", NextAction::array(0, new NextAction("bone shield", 21.0f), nullptr))); + triggers.push_back(new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 11.0f), NULL))); } void DKBuffDpsStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("improved icy talons", NextAction::array(0, new NextAction("improved icy talons", 19.0f), nullptr))); + // triggers.push_back(new TriggerNode("improved icy talons", NextAction::array(0, new NextAction("improved icy talons", 19.0f), nullptr))); } diff --git a/src/strategy/druid/DruidActions.h b/src/strategy/druid/DruidActions.h index 9031f43b..372ebead 100644 --- a/src/strategy/druid/DruidActions.h +++ b/src/strategy/druid/DruidActions.h @@ -236,4 +236,21 @@ class CastNaturesSwiftnessAction : public CastBuffSpellAction CastNaturesSwiftnessAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "nature's swiftness") { } }; +class CastWildGrowthOnPartyAction : public HealPartyMemberAction +{ +public: + CastWildGrowthOnPartyAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "wild growth") {} +}; + +class CastPartySwiftmendAction : public HealPartyMemberAction +{ +public: + CastPartySwiftmendAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "swiftmend") {} +}; + +class CastPartyNourishAction : public HealPartyMemberAction +{ +public: + CastPartyNourishAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "nourish") {} +}; #endif diff --git a/src/strategy/druid/DruidAiObjectContext.cpp b/src/strategy/druid/DruidAiObjectContext.cpp index 8b1baf63..c53973e4 100644 --- a/src/strategy/druid/DruidAiObjectContext.cpp +++ b/src/strategy/druid/DruidAiObjectContext.cpp @@ -199,6 +199,9 @@ class DruidAiObjectContextInternal : public NamedObjectContext creators["shred"] = &DruidAiObjectContextInternal::shred; creators["ravage"] = &DruidAiObjectContextInternal::ravage; creators["pounce"] = &DruidAiObjectContextInternal::pounce; + creators["wild growth on party"] = &DruidAiObjectContextInternal::wild_growth_on_party; + creators["swiftmend on party"] = &DruidAiObjectContextInternal::swiftmend_on_party; + creators["nourish on party"] = &DruidAiObjectContextInternal::nourish_on_party; } private: @@ -270,6 +273,9 @@ class DruidAiObjectContextInternal : public NamedObjectContext static Action* prowl(PlayerbotAI* botAI) { return new CastProwlAction(botAI); } static Action* dash(PlayerbotAI* botAI) { return new CastDashAction(botAI); } static Action* shred(PlayerbotAI* botAI) { return new CastShredAction(botAI); } + static Action* wild_growth_on_party(PlayerbotAI* ai) { return new CastWildGrowthOnPartyAction(ai); } + static Action* swiftmend_on_party(PlayerbotAI *ai) { return new CastPartySwiftmendAction(ai); } + static Action* nourish_on_party(PlayerbotAI *ai) { return new CastPartyNourishAction(ai); } }; DruidAiObjectContext::DruidAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) diff --git a/src/strategy/druid/DruidShapeshiftActions.cpp b/src/strategy/druid/DruidShapeshiftActions.cpp index d5967ea1..ea4934bc 100644 --- a/src/strategy/druid/DruidShapeshiftActions.cpp +++ b/src/strategy/druid/DruidShapeshiftActions.cpp @@ -39,3 +39,8 @@ bool CastCasterFormAction::Execute(Event event) botAI->RemoveShapeshift(); return true; } + +bool CastTreeFormAction::isUseful() { + return GetTarget() && (GetTarget() != nullptr) && (GetTarget() != nullptr) && + CastSpellAction::isUseful() && !botAI->HasAura(33891, bot); +} \ No newline at end of file diff --git a/src/strategy/druid/DruidShapeshiftActions.h b/src/strategy/druid/DruidShapeshiftActions.h index d6231d00..49409a3d 100644 --- a/src/strategy/druid/DruidShapeshiftActions.h +++ b/src/strategy/druid/DruidShapeshiftActions.h @@ -36,6 +36,7 @@ class CastTreeFormAction : public CastBuffSpellAction { public: CastTreeFormAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "tree of life") { } + bool isUseful() override; }; class CastMoonkinFormAction : public CastBuffSpellAction diff --git a/src/strategy/druid/DruidTriggers.cpp b/src/strategy/druid/DruidTriggers.cpp index 2d851fca..137dfc37 100644 --- a/src/strategy/druid/DruidTriggers.cpp +++ b/src/strategy/druid/DruidTriggers.cpp @@ -42,7 +42,7 @@ bool BearFormTrigger::IsActive() bool TreeFormTrigger::IsActive() { - return !botAI->HasAura("tree of life", bot); + return !botAI->HasAura(33891, bot); } bool CatFormTrigger::IsActive() diff --git a/src/strategy/druid/GenericDruidNonCombatStrategy.cpp b/src/strategy/druid/GenericDruidNonCombatStrategy.cpp index 85461eb4..36e8c6d7 100644 --- a/src/strategy/druid/GenericDruidNonCombatStrategy.cpp +++ b/src/strategy/druid/GenericDruidNonCombatStrategy.cpp @@ -14,7 +14,7 @@ class GenericDruidNonCombatStrategyActionNodeFactory : public NamedObjectFactory creators["thorns on party"] = þs_on_party; creators["mark of the wild"] = &mark_of_the_wild; creators["mark of the wild on party"] = &mark_of_the_wild_on_party; - creators["innervate"] = &innervate; + // creators["innervate"] = &innervate; } private: @@ -50,13 +50,13 @@ class GenericDruidNonCombatStrategyActionNodeFactory : public NamedObjectFactory /*C*/ nullptr); } - static ActionNode* innervate([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode ("innervate", - /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("drink"), nullptr), - /*C*/ nullptr); - } + // static ActionNode* innervate([[maybe_unused]] PlayerbotAI* botAI) + // { + // return new ActionNode ("innervate", + // /*P*/ nullptr, + // /*A*/ NextAction::array(0, new NextAction("drink"), nullptr), + // /*C*/ nullptr); + // } }; GenericDruidNonCombatStrategy::GenericDruidNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) @@ -70,12 +70,27 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector& trig triggers.push_back(new TriggerNode("mark of the wild", NextAction::array(0, new NextAction("mark of the wild", 14.0f), nullptr))); triggers.push_back(new TriggerNode("thorns", NextAction::array(0, new NextAction("thorns", 12.0f), nullptr))); - triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", 21.0f), nullptr))); + // triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", 21.0f), nullptr))); triggers.push_back(new TriggerNode("party member cure poison", NextAction::array(0, new NextAction("abolish poison on party", 20.0f), nullptr))); triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("revive", 22.0f), nullptr))); - triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY + 5), nullptr))); - triggers.push_back(new TriggerNode("swimming", NextAction::array(0, new NextAction("aquatic form", 1.0f), nullptr))); + // triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY + 5), nullptr))); + // triggers.push_back(new TriggerNode("swimming", NextAction::array(0, new NextAction("aquatic form", 1.0f), nullptr))); triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr))); + + triggers.push_back(new TriggerNode("party member critical health", + NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5), + new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6), NULL))); + + triggers.push_back(new TriggerNode("party member low health", + NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3), + new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4), NULL))); + + triggers.push_back(new TriggerNode("party member medium health", + NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1), + new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), NULL))); + + triggers.push_back(new TriggerNode("party member almost full health", + NextAction::array(0, new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), NULL))); } GenericDruidBuffStrategy::GenericDruidBuffStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) diff --git a/src/strategy/druid/GenericDruidStrategy.cpp b/src/strategy/druid/GenericDruidStrategy.cpp index fab69091..b883fee9 100644 --- a/src/strategy/druid/GenericDruidStrategy.cpp +++ b/src/strategy/druid/GenericDruidStrategy.cpp @@ -104,17 +104,17 @@ void GenericDruidStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("regrowth", ACTION_MEDIUM_HEAL + 2), nullptr))); - triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1), nullptr))); - triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("regrowth", ACTION_CRITICAL_HEAL + 2), new NextAction("healing touch", ACTION_CRITICAL_HEAL + 2), nullptr))); - triggers.push_back(new TriggerNode("party member critical health", NextAction::array(0, new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 1), new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 1), nullptr))); - triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("rebirth", ACTION_HIGH + 1), nullptr))); - triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY + 5), nullptr))); + // triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("regrowth", ACTION_MEDIUM_HEAL + 2), nullptr))); + // triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1), nullptr))); + // triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("regrowth", ACTION_CRITICAL_HEAL + 2), new NextAction("healing touch", ACTION_CRITICAL_HEAL + 2), nullptr))); + // triggers.push_back(new TriggerNode("party member critical health", NextAction::array(0, new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 1), new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 1), nullptr))); + // triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("rebirth", ACTION_HIGH + 1), nullptr))); + // triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY + 5), nullptr))); } void DruidCureStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", ACTION_DISPEL + 2), nullptr))); + // triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", ACTION_DISPEL + 2), nullptr))); triggers.push_back(new TriggerNode("party member cure poison", NextAction::array(0, new NextAction("abolish poison on party", ACTION_DISPEL + 1), nullptr))); } diff --git a/src/strategy/druid/HealDruidStrategy.cpp b/src/strategy/druid/HealDruidStrategy.cpp index 1168b056..4ea3b6ba 100644 --- a/src/strategy/druid/HealDruidStrategy.cpp +++ b/src/strategy/druid/HealDruidStrategy.cpp @@ -22,10 +22,58 @@ void HealDruidStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode("enemy out of spell", NextAction::array(0, new NextAction("reach spell", ACTION_NORMAL + 9), nullptr))); triggers.push_back(new TriggerNode("tree form", NextAction::array(0, new NextAction("tree form", ACTION_HIGH + 1), nullptr))); - triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("regrowth", ACTION_MEDIUM_HEAL + 2), nullptr))); - triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0, new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1), nullptr))); - triggers.push_back(new TriggerNode("almost full health", NextAction::array(0, new NextAction("rejuvenation", ACTION_LIGHT_HEAL + 2), nullptr))); - triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 1), nullptr))); - triggers.push_back(new TriggerNode("medium aoe heal", NextAction::array(0, new NextAction("tranquility", ACTION_MEDIUM_HEAL + 3), nullptr))); - triggers.push_back(new TriggerNode("party member to heal out of spell range", NextAction::array(0, new NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 1), nullptr))); + triggers.push_back(new TriggerNode("party member to heal out of spell range", NextAction::array(0, new NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 9), nullptr))); + + // CRITICAL + triggers.push_back(new TriggerNode( + "party member critical health", + NextAction::array(0, + new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 3), + new NextAction("wild growth", ACTION_CRITICAL_HEAL + 2), + new NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1), + // new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 0), + NULL))); + + triggers.push_back(new TriggerNode( + "party member critical health", + NextAction::array(0, new NextAction("nature's swiftness", ACTION_CRITICAL_HEAL + 4), NULL))); + + triggers.push_back(new TriggerNode( + "group heal occasion", + NextAction::array(0, new NextAction("tranquility", ACTION_CRITICAL_HEAL + 5), NULL))); + + // LOW + triggers.push_back(new TriggerNode( + "party member low health", + NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 9), + new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 8), + new NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 7), + new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 6), + // new NextAction("healing touch on party", ACTION_MEDIUM_HEAL + 5), + NULL))); + + // MEDIUM + triggers.push_back(new TriggerNode( + "party member medium health", + NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 4), + new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3), + new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), + new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1), + NULL))); + + // almost full + triggers.push_back(new TriggerNode( + "party member almost full health", + NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3), + new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), + new NextAction("regrowth on party", ACTION_LIGHT_HEAL + 1), + NULL))); + + triggers.push_back(new TriggerNode( + "medium mana", + NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 5), NULL))); + + triggers.push_back(new TriggerNode( + "enemy too close for spell", + NextAction::array(0, new NextAction("flee", 49.0f), NULL))); } diff --git a/src/strategy/generic/ChatCommandHandlerStrategy.cpp b/src/strategy/generic/ChatCommandHandlerStrategy.cpp index ba23b38c..444d898b 100644 --- a/src/strategy/generic/ChatCommandHandlerStrategy.cpp +++ b/src/strategy/generic/ChatCommandHandlerStrategy.cpp @@ -70,6 +70,7 @@ ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : Pas supported.push_back("reputation"); supported.push_back("log"); supported.push_back("los"); + supported.push_back("aura"); supported.push_back("drop"); supported.push_back("share"); supported.push_back("ll"); diff --git a/src/strategy/hunter/GenericHunterNonCombatStrategy.cpp b/src/strategy/hunter/GenericHunterNonCombatStrategy.cpp index 1ee4bbe0..5e8eb6ef 100644 --- a/src/strategy/hunter/GenericHunterNonCombatStrategy.cpp +++ b/src/strategy/hunter/GenericHunterNonCombatStrategy.cpp @@ -52,6 +52,7 @@ void GenericHunterNonCombatStrategy::InitTriggers(std::vector& tri void HunterPetStrategy::InitTriggers(std::vector& triggers) { triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("call pet", 60.0f), nullptr))); + triggers.push_back(new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 60.0f), nullptr))); triggers.push_back(new TriggerNode("pet not happy", NextAction::array(0, new NextAction("feed pet", 60.0f), nullptr))); triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", 60.0f), nullptr))); triggers.push_back(new TriggerNode("hunters pet dead", NextAction::array(0, new NextAction("revive pet", 60.0f), nullptr))); diff --git a/src/strategy/triggers/ChatTriggerContext.h b/src/strategy/triggers/ChatTriggerContext.h index 89976efd..12c192f1 100644 --- a/src/strategy/triggers/ChatTriggerContext.h +++ b/src/strategy/triggers/ChatTriggerContext.h @@ -22,6 +22,7 @@ class ChatTriggerContext : public NamedObjectContext creators["reputation"] = &ChatTriggerContext::reputation; creators["log"] = &ChatTriggerContext::log; creators["los"] = &ChatTriggerContext::los; + creators["aura"] = &ChatTriggerContext::aura; creators["drop"] = &ChatTriggerContext::drop; creators["share"] = &ChatTriggerContext::share; creators["q"] = &ChatTriggerContext::q; @@ -187,6 +188,7 @@ class ChatTriggerContext : public NamedObjectContext static Trigger* reputation(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "reputation"); } static Trigger* log(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "log"); } static Trigger* los(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "los"); } + static Trigger* aura(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "aura"); } static Trigger* loot_all(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "add all loot"); } static Trigger* release(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "release"); } static Trigger* reset_ai(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "reset botAI"); } diff --git a/src/strategy/triggers/CureTriggers.h b/src/strategy/triggers/CureTriggers.h index 033968aa..5eab46de 100644 --- a/src/strategy/triggers/CureTriggers.h +++ b/src/strategy/triggers/CureTriggers.h @@ -13,7 +13,7 @@ class Unit; class NeedCureTrigger : public SpellTrigger { public: - NeedCureTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : SpellTrigger(botAI, spell, 5), dispelType(dispelType) { } + NeedCureTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : SpellTrigger(botAI, spell, 1), dispelType(dispelType) { } std::string const GetTargetName() override { return "self target"; } bool IsActive() override; diff --git a/src/strategy/triggers/GenericTriggers.cpp b/src/strategy/triggers/GenericTriggers.cpp index d1c2f822..25ddd2b2 100644 --- a/src/strategy/triggers/GenericTriggers.cpp +++ b/src/strategy/triggers/GenericTriggers.cpp @@ -21,6 +21,10 @@ bool NoPetTrigger::IsActive() return !AI_VALUE(Unit*, "pet target") && !AI_VALUE2(bool, "mounted", "self target"); } +bool HasPetTrigger::IsActive() { + return AI_VALUE(Unit*, "pet target") && !AI_VALUE2(bool, "mounted", "self target");; +} + bool HighManaTrigger::IsActive() { return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < 65; diff --git a/src/strategy/triggers/GenericTriggers.h b/src/strategy/triggers/GenericTriggers.h index 284c2cca..0ed7dc79 100644 --- a/src/strategy/triggers/GenericTriggers.h +++ b/src/strategy/triggers/GenericTriggers.h @@ -418,6 +418,14 @@ class NoPetTrigger : public Trigger bool IsActive() override; }; +class HasPetTrigger : public Trigger +{ +public: + HasPetTrigger(PlayerbotAI* ai) : Trigger(ai, "no pet", 5) {} + + virtual bool IsActive() override; +}; + class ItemCountTrigger : public Trigger { public: diff --git a/src/strategy/triggers/HealthTriggers.cpp b/src/strategy/triggers/HealthTriggers.cpp index 21102acc..9233c734 100644 --- a/src/strategy/triggers/HealthTriggers.cpp +++ b/src/strategy/triggers/HealthTriggers.cpp @@ -30,3 +30,8 @@ bool AoeHealTrigger::IsActive() return AI_VALUE2(uint8, "aoe heal", type) >= count; } +bool AoeInGroupTrigger::IsActive() +{ + Group *group = bot->GetGroup(); + return group && AI_VALUE2(uint8, "aoe heal", type) >= (group->GetMembersCount() * ratio); +} \ No newline at end of file diff --git a/src/strategy/triggers/HealthTriggers.h b/src/strategy/triggers/HealthTriggers.h index 7f523663..671ff8ec 100644 --- a/src/strategy/triggers/HealthTriggers.h +++ b/src/strategy/triggers/HealthTriggers.h @@ -132,4 +132,14 @@ class AoeHealTrigger : public Trigger std::string const type; }; +class AoeInGroupTrigger : public Trigger { + public: + AoeInGroupTrigger(PlayerbotAI* ai, std::string name, std::string type, float ratio) : + Trigger(ai, name), ratio(ratio), type(type) {} + virtual bool IsActive(); + protected: + float ratio; + std::string type; + }; + #endif diff --git a/src/strategy/triggers/TriggerContext.h b/src/strategy/triggers/TriggerContext.h index a762adb3..df0bdbc1 100644 --- a/src/strategy/triggers/TriggerContext.h +++ b/src/strategy/triggers/TriggerContext.h @@ -97,6 +97,7 @@ class TriggerContext : public NamedObjectContext creators["corpse near"] = &TriggerContext::corpse_near; creators["party member dead"] = &TriggerContext::PartyMemberDead; creators["no pet"] = &TriggerContext::no_pet; + creators["has pet"] = &TriggerContext::has_pet; creators["has attackers"] = &TriggerContext::has_attackers; creators["no possible targets"] = &TriggerContext::no_possible_targets; creators["possible adds"] = &TriggerContext::possible_adds; @@ -118,6 +119,7 @@ class TriggerContext : public NamedObjectContext creators["critical aoe heal"] = &TriggerContext::critical_aoe_heal; creators["low aoe heal"] = &TriggerContext::low_aoe_heal; creators["medium aoe heal"] = &TriggerContext::medium_aoe_heal; + creators["group heal occasion"] = &TriggerContext::group_heal_occasion; creators["invalid target"] = &TriggerContext::invalid_target; creators["lfg proposal active"] = &TriggerContext::lfg_proposal_active; @@ -210,6 +212,7 @@ class TriggerContext : public NamedObjectContext static Trigger* critical_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "critical aoe heal", "critical", 2); } static Trigger* low_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "low aoe heal", "low", 2); } static Trigger* medium_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "medium aoe heal", "medium", 2); } + static Trigger* group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.4); } static Trigger* target_changed(PlayerbotAI* botAI) { return new TargetChangedTrigger(botAI); } static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); } static Trigger* no_possible_targets(PlayerbotAI* botAI) { return new NoPossibleTargetsTrigger(botAI); } @@ -277,6 +280,7 @@ class TriggerContext : public NamedObjectContext static Trigger* PartyMemberCriticalHealth(PlayerbotAI* botAI) { return new PartyMemberCriticalHealthTrigger(botAI); } static Trigger* protect_party_member(PlayerbotAI* botAI) { return new ProtectPartyMemberTrigger(botAI); } static Trigger* no_pet(PlayerbotAI* botAI) { return new NoPetTrigger(botAI); } + static Trigger* has_pet(PlayerbotAI* botAI) { return new HasPetTrigger(botAI); } static Trigger* has_attackers(PlayerbotAI* botAI) { return new HasAttackersTrigger(botAI); } static Trigger* random_bot_update_trigger(PlayerbotAI* botAI) { return new RandomBotUpdateTrigger(botAI); } static Trigger* no_non_bot_players_around(PlayerbotAI* botAI) { return new NoNonBotPlayersAroundTrigger(botAI); } diff --git a/src/strategy/values/PartyMemberToHeal.cpp b/src/strategy/values/PartyMemberToHeal.cpp index 1ef0f6b3..b21f8089 100644 --- a/src/strategy/values/PartyMemberToHeal.cpp +++ b/src/strategy/values/PartyMemberToHeal.cpp @@ -29,77 +29,54 @@ inline bool compareByHealth(Unit const* u1, Unit const* u2) Unit* PartyMemberToHeal::Calculate() { - IsTargetOfHealingSpell predicate; - std::vector needHeals; - std::vector tankTargets; - if (bot->GetTarget()) - { - Unit* target = botAI->GetUnit(bot->GetTarget()); - if (target && target->IsFriendlyTo(bot) && target->HealthBelowPct(100)) - needHeals.push_back(target); - } + IsTargetOfHealingSpell predicate; Group* group = bot->GetGroup(); - if (!group && needHeals.empty()) - return nullptr; + if (!group) + return bot; - if (group) + bool isRaid = bot->GetGroup()->isRaidGroup(); + MinValueCalculator calc(100); + + for (GroupReference *gref = group->GetFirstMember(); gref; gref = gref->next()) { - for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) - { - Player* player = gref->GetSource(); - if (!Check(player) || !player->IsAlive()) - continue; - - // do not heal dueling members - if (player->duel && player->duel->Opponent) - continue; - + Player* player = gref->GetSource(); + if (player && Check(player) && player->IsAlive()) { uint8 health = player->GetHealthPct(); - if (health < sPlayerbotAIConfig->almostFullHealth || !IsTargetOfSpellCast(player, predicate)) - needHeals.push_back(player); - - if (botAI->IsTank(player) && bot->IsInSameRaidWith(player)) - tankTargets.push_back(player); - } - } - - if (needHeals.empty() && tankTargets.empty()) - return nullptr; - - if (needHeals.empty() && !tankTargets.empty()) - needHeals = tankTargets; - - std::sort(needHeals.begin(), needHeals.end(), compareByHealth); - - uint32 healerIndex = 0; - if (group) - { - for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) - { - Player* player = gref->GetSource(); - if (!player) continue; - if (player == bot) break; - if (botAI->IsHeal(player)) - { - float percent = (float)player->GetPower(POWER_MANA) / (float)player->GetMaxPower(POWER_MANA) * 100.0; - if (percent > sPlayerbotAIConfig->lowMana) - healerIndex++; + if (isRaid || health < sPlayerbotAIConfig->mediumHealth || !IsTargetOfSpellCast(player, predicate)) { + if (player->GetDistance2d(bot) > sPlayerbotAIConfig->spellDistance) { + calc.probe(health + 30, player); + } else { + calc.probe(health + player->GetDistance2d(bot) / 10, player); + } } } - } - else - healerIndex = 1; - healerIndex = healerIndex % needHeals.size(); - return needHeals[healerIndex]; + Pet* pet = player->GetPet(); + if (pet && Check(pet) && pet->IsAlive()) { + uint8 health = ((Unit*)pet)->GetHealthPct(); + if (isRaid || health < sPlayerbotAIConfig->mediumHealth) + calc.probe(health + 30, pet); + } + + Unit* charm = player->GetCharm(); + if (charm && Check(charm) && charm->IsAlive()) { + uint8 health = charm->GetHealthPct(); + if (isRaid || health < sPlayerbotAIConfig->mediumHealth) + calc.probe(health, charm); + } + } + return (Unit*)calc.param; } bool PartyMemberToHeal::Check(Unit* player) { - return player && player != bot && player->GetMapId() == bot->GetMapId() && player->IsInWorld() && - sServerFacade->GetDistance2d(bot, player) < (player->IsPlayer() && botAI->IsTank((Player*)player) ? 50.0f : 40.0f); + // return player && player != bot && player->GetMapId() == bot->GetMapId() && player->IsInWorld() && + // sServerFacade->GetDistance2d(bot, player) < (player->IsPlayer() && botAI->IsTank((Player*)player) ? 50.0f : 40.0f); + return player && player->GetMapId() == bot->GetMapId() && + bot->GetDistance(player) < sPlayerbotAIConfig->spellDistance * 2 && + bot->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); } Unit* PartyMemberToProtect::Calculate() diff --git a/src/strategy/values/PartyMemberValue.cpp b/src/strategy/values/PartyMemberValue.cpp index 5966b04e..a6bb9379 100644 --- a/src/strategy/values/PartyMemberValue.cpp +++ b/src/strategy/values/PartyMemberValue.cpp @@ -45,12 +45,19 @@ Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool ign } } } + } else { + std::vector vec; + vec.push_back(bot); + Unit* target = FindPartyMember(&vec, predicate); + if (target) + return target; + return NULL; } if (!ignoreOutOfGroup && !nearestPlayers.empty() && nearestPlayers.size() < 100) nearestGroupPlayers.insert(nearestGroupPlayers.end(), nearestPlayers.begin(), nearestPlayers.end()); - nearestPlayers.insert(nearestPlayers.end(), nearestGroupPlayers.begin(), nearestGroupPlayers.end()); + // nearestPlayers.insert(nearestP layers.end(), nearestGroupPlayers.begin(), nearestGroupPlayers.end()); std::vector healers; std::vector tanks; @@ -93,7 +100,10 @@ Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool ign bool PartyMemberValue::Check(Unit* player) { - return player && player != bot && player->GetMapId() == bot->GetMapId() && bot->IsWithinDistInMap(player, sPlayerbotAIConfig->sightDistance, false); + // return player && player != bot && player->GetMapId() == bot->GetMapId() && bot->IsWithinDistInMap(player, sPlayerbotAIConfig->sightDistance, false); + return player && player->GetMapId() == bot->GetMapId() && + bot->GetDistance(player) < sPlayerbotAIConfig->spellDistance * 2 && + bot->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); } bool PartyMemberValue::IsTargetOfSpellCast(Player* target, SpellEntryPredicate &predicate)