From a1cb9dea05dff6aa92ac192ea944ecdcaf6d83f0 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Wed, 14 Aug 2024 18:18:01 +0800 Subject: [PATCH] Improve class spell and use trinket --- src/factory/StatsCollector.cpp | 12 +- src/factory/StatsWeightCalculator.cpp | 14 ++- src/strategy/actions/ActionContext.h | 6 + src/strategy/actions/GenericActions.cpp | 6 +- src/strategy/actions/GenericSpellActions.cpp | 113 +++++++++++++++--- src/strategy/actions/GenericSpellActions.h | 34 +++++- src/strategy/actions/ListSpellsAction.cpp | 5 +- src/strategy/deathknight/DKActions.h | 9 +- src/strategy/druid/DruidActions.h | 4 +- src/strategy/druid/DruidAiObjectContext.cpp | 4 +- src/strategy/druid/DruidBearActions.h | 4 +- src/strategy/druid/FeralDruidStrategy.cpp | 2 +- src/strategy/druid/GenericDruidStrategy.cpp | 3 + src/strategy/generic/RacialsStrategy.cpp | 20 ++-- src/strategy/hunter/DpsHunterStrategy.cpp | 15 ++- src/strategy/hunter/GenericHunterStrategy.cpp | 3 + src/strategy/hunter/HunterActions.h | 13 +- src/strategy/hunter/HunterAiObjectContext.cpp | 2 + src/strategy/paladin/DpsPaladinStrategy.cpp | 4 +- .../paladin/GenericPaladinStrategy.cpp | 4 +- src/strategy/paladin/PaladinActions.cpp | 7 -- src/strategy/paladin/PaladinActions.h | 11 +- .../paladin/PaladinAiObjectContext.cpp | 2 - src/strategy/paladin/TankPaladinStrategy.cpp | 4 +- src/strategy/priest/GenericPriestStrategy.cpp | 5 +- src/strategy/priest/HolyPriestStrategy.cpp | 4 +- src/strategy/priest/PriestActions.h | 7 ++ src/strategy/priest/PriestAiObjectContext.cpp | 2 + src/strategy/priest/PriestTriggers.h | 2 +- src/strategy/priest/ShadowPriestStrategy.cpp | 6 +- .../rogue/AssassinationRogueStrategy.cpp | 7 +- src/strategy/rogue/DpsRogueStrategy.cpp | 10 +- src/strategy/rogue/RogueActions.h | 6 + src/strategy/rogue/RogueAiObjectContext.cpp | 4 + src/strategy/rogue/RogueComboActions.h | 20 ++-- src/strategy/rogue/RogueTriggers.h | 7 ++ src/strategy/shaman/ShamanActions.cpp | 20 +++- src/strategy/shaman/ShamanActions.h | 5 +- src/strategy/triggers/GenericTriggers.cpp | 18 ++- src/strategy/triggers/GenericTriggers.h | 15 +++ src/strategy/triggers/HealthTriggers.h | 10 +- src/strategy/triggers/TriggerContext.h | 3 + src/strategy/values/AttackerCountValues.cpp | 9 +- .../values/AttackerWithoutAuraTargetValue.cpp | 2 +- src/strategy/values/PartyMemberToHeal.cpp | 2 + src/strategy/values/PartyMemberValue.cpp | 3 +- src/strategy/warrior/WarriorActions.h | 17 ++- 47 files changed, 377 insertions(+), 108 deletions(-) diff --git a/src/factory/StatsCollector.cpp b/src/factory/StatsCollector.cpp index 70965177..322e4742 100644 --- a/src/factory/StatsCollector.cpp +++ b/src/factory/StatsCollector.cpp @@ -225,7 +225,10 @@ bool StatsCollector::SpecialSpellFilter(uint32 spellId) { if (type_ != CollectorType::SPELL_HEAL) stats[STATS_TYPE_CRIT] += 50; return true; - break; + case 59620: + if (type_ == CollectorType::MELEE) + stats[STATS_TYPE_ATTACK_POWER] += 120; + return true; case 67702: // Death's Verdict stats[STATS_TYPE_ATTACK_POWER] += 225; return true; @@ -493,6 +496,13 @@ void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float mu case SPELL_AURA_MOD_INCREASE_HEALTH: stats[STATS_TYPE_STAMINA] += val * multiplier / 15; break; + case SPELL_AURA_SCHOOL_ABSORB: + { + int32 schoolType = effectInfo.MiscValue; + if (schoolType & SPELL_SCHOOL_MASK_NORMAL) + stats[STATS_TYPE_STAMINA] += val * multiplier / 15; + break; + } case SPELL_AURA_MOD_ATTACK_POWER: stats[STATS_TYPE_ATTACK_POWER] += val * multiplier; break; diff --git a/src/factory/StatsWeightCalculator.cpp b/src/factory/StatsWeightCalculator.cpp index 19dd85a0..9ee2b487 100644 --- a/src/factory/StatsWeightCalculator.cpp +++ b/src/factory/StatsWeightCalculator.cpp @@ -9,6 +9,7 @@ #include "AiFactory.h" #include "DBCStores.h" +#include "ItemTemplate.h" #include "ObjectMgr.h" #include "PlayerbotAI.h" #include "SharedDefines.h" @@ -231,7 +232,8 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player) stats_weights_[STATS_TYPE_EXPERTISE] += 2.0f; stats_weights_[STATS_TYPE_MELEE_DPS] += 5.2f; } - else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE || + else if (cls == CLASS_WARLOCK || + cls == CLASS_MAGE || (cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW) || // shadow (cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ELEMENTAL) || // element (cls == CLASS_DRUID && tab == DRUID_TAB_BALANCE)) // balance @@ -454,6 +456,16 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto) { weight_ *= 0.1; } + if (cls == CLASS_ROGUE && player_->HasAura(13964) + && (proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE)) + { + weight_ *= 1.1; + } + if (cls == CLASS_WARRIOR && player_->HasAura(12785) + && (proto->SubClass == ITEM_SUBCLASS_WEAPON_THROWN || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2)) + { + weight_ *= 1.1; + } } } diff --git a/src/strategy/actions/ActionContext.h b/src/strategy/actions/ActionContext.h index 3f0cf4e1..724c35f2 100644 --- a/src/strategy/actions/ActionContext.h +++ b/src/strategy/actions/ActionContext.h @@ -154,6 +154,9 @@ public: creators["give water"] = &ActionContext::give_water; creators["mount"] = &ActionContext::mount; creators["war stomp"] = &ActionContext::war_stomp; + creators["blood fury"] = &ActionContext::blood_fury; + creators["berserking"] = &ActionContext::berserking; + creators["use trinket"] = &ActionContext::use_trinket; creators["auto talents"] = &ActionContext::auto_talents; creators["auto learn spell"] = &ActionContext::auto_learn_spell; creators["auto share quest"] = &ActionContext::auto_share_quest; @@ -324,6 +327,9 @@ private: static Action* try_emergency(PlayerbotAI* botAI) { return new TryEmergencyAction(botAI); } static Action* mount(PlayerbotAI* botAI) { return new CastSpellAction(botAI, "mount"); } static Action* war_stomp(PlayerbotAI* botAI) { return new CastWarStompAction(botAI); } + static Action* blood_fury(PlayerbotAI* botAI) { return new CastBloodFuryAction(botAI); } + static Action* berserking(PlayerbotAI* botAI) { return new CastBerserkingAction(botAI); } + static Action* use_trinket(PlayerbotAI* botAI) { return new UseTrinketAction(botAI); } static Action* auto_talents(PlayerbotAI* botAI) { return new AutoSetTalentsAction(botAI); } static Action* auto_learn_spell(PlayerbotAI* botAI) { return new AutoLearnSpellAction(botAI); } static Action* auto_share_quest(PlayerbotAI* ai) { return new AutoShareQuestAction(ai); } diff --git a/src/strategy/actions/GenericActions.cpp b/src/strategy/actions/GenericActions.cpp index be75370a..84997212 100644 --- a/src/strategy/actions/GenericActions.cpp +++ b/src/strategy/actions/GenericActions.cpp @@ -36,9 +36,9 @@ bool TogglePetSpellAutoCastAction::Execute(Event event) continue; bool shouldApply = true; - // imp's spell, felhunte's intelligence, ghoul's leap, cat stealth + // imp's spell, felhunte's intelligence, cat stealth if (spellId == 4511 || spellId == 1742 || spellId == 54424 || spellId == 57564 || spellId == 57565 || - spellId == 57566 || spellId == 57567 || spellId == 47482 || spellId == 24450) + spellId == 57566 || spellId == 57567 || spellId == 24450) { shouldApply = false; } @@ -72,7 +72,7 @@ bool PetAttackAction::Execute(Event event) { return false; } - // pet->SetReactState(REACT_DEFENSIVE); + pet->SetReactState(REACT_PASSIVE); pet->ClearUnitState(UNIT_STATE_FOLLOW); pet->AttackStop(); pet->SetTarget(target->GetGUID()); diff --git a/src/strategy/actions/GenericSpellActions.cpp b/src/strategy/actions/GenericSpellActions.cpp index 3e4b2147..05938358 100644 --- a/src/strategy/actions/GenericSpellActions.cpp +++ b/src/strategy/actions/GenericSpellActions.cpp @@ -6,8 +6,13 @@ #include "GenericSpellActions.h" #include "Event.h" +#include "ItemTemplate.h" +#include "ObjectDefines.h" +#include "Opcodes.h" +#include "Player.h" #include "Playerbots.h" #include "ServerFacade.h" +#include "WorldPacket.h" CastSpellAction::CastSpellAction(PlayerbotAI* botAI, std::string const spell) : Action(botAI, spell), range(botAI->GetRange("spell")), spell(spell) @@ -124,11 +129,35 @@ 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); +} - // range = target->GetCombinedCombatReach(); +bool CastMeleeSpellAction::isUseful() +{ + Unit* target = GetTarget(); + if (!target) + return false; + + if (!bot->IsWithinMeleeRange(target)) + return false; + + return CastSpellAction::isUseful(); +} + +CastMeleeDebuffSpellAction::CastMeleeDebuffSpellAction(PlayerbotAI* botAI, std::string const spell, bool isOwner, float needLifeTime) : CastDebuffSpellAction(botAI, spell, isOwner, needLifeTime) +{ + range = ATTACK_DISTANCE; +} + +bool CastMeleeDebuffSpellAction::isUseful() +{ + Unit* target = GetTarget(); + if (!target) + return false; + + if (!bot->IsWithinMeleeRange(target)) + return false; + + return CastDebuffSpellAction::isUseful(); } bool CastAuraSpellAction::isUseful() @@ -209,17 +238,7 @@ CastShootAction::CastShootAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "s NextAction** CastSpellAction::getPrerequisites() { - if (spell == "mount") - return nullptr; - - if (range > botAI->GetRange("spell")) - return nullptr; - else if (range > ATTACK_DISTANCE) - return NextAction::merge(NextAction::array(0, new NextAction("reach spell"), nullptr), - Action::getPrerequisites()); - else - return NextAction::merge(NextAction::array(0, new NextAction("reach melee"), nullptr), - Action::getPrerequisites()); + return nullptr; } Value* CastDebuffSpellOnAttackerAction::GetTargetValue() @@ -271,6 +290,70 @@ bool CastVehicleSpellAction::Execute(Event event) return botAI->CastVehicleSpell(spellId, GetTarget()); } +bool UseTrinketAction::Execute(Event event) +{ + Item* trinket1 = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_TRINKET1); + + if (trinket1 && UseTrinket(trinket1)) + return true; + + Item* trinket2 = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_TRINKET2); + + if (trinket2 && UseTrinket(trinket2)) + return true; + + return false; +} + +bool UseTrinketAction::UseTrinket(Item* item) +{ + if (bot->CanUseItem(item) != EQUIP_ERR_OK) + return false; + + if (bot->IsNonMeleeSpellCast(true)) + return false; + + uint8 bagIndex = item->GetBagSlot(); + uint8 slot = item->GetSlot(); + uint8 spell_index = 0; + uint8 cast_count = 1; + ObjectGuid item_guid = item->GetGUID(); + uint32 glyphIndex = 0; + uint8 castFlags = 0; + uint32 targetFlag = TARGET_FLAG_NONE; + uint32 spellId = 0; + for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + { + if (item->GetTemplate()->Spells[i].SpellId > 0 && item->GetTemplate()->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE) + { + spellId = item->GetTemplate()->Spells[i].SpellId; + if (!botAI->CanCastSpell(spellId, bot, false)) + { + return false; + } + break; + } + } + if (!spellId) + return false; + WorldPacket packet(CMSG_USE_ITEM); + packet << bagIndex << slot << cast_count << spellId << item_guid << glyphIndex << castFlags; + + Unit* target = AI_VALUE(Unit*, "current target"); + if (target) + { + targetFlag = TARGET_FLAG_UNIT; + packet << targetFlag << target->GetGUID().WriteAsPacked(); + } + else + { + targetFlag = TARGET_FLAG_NONE; + packet << targetFlag << bot->GetPackGUID(); + } + bot->GetSession()->HandleUseItemOpcode(packet); + return true; +} + Value* BuffOnMainTankAction::GetTargetValue() { return context->GetValue("main tank", spell); } bool CastDebuffSpellAction::isUseful() diff --git a/src/strategy/actions/GenericSpellActions.h b/src/strategy/actions/GenericSpellActions.h index 773f3ac0..b9870011 100644 --- a/src/strategy/actions/GenericSpellActions.h +++ b/src/strategy/actions/GenericSpellActions.h @@ -9,6 +9,7 @@ #include "Action.h" #include "PlayerbotAI.h" #include "PlayerbotAIConfig.h" +#include "UseItemAction.h" #include "Value.h" class PlayerbotAI; @@ -52,6 +53,7 @@ class CastMeleeSpellAction : public CastSpellAction { public: CastMeleeSpellAction(PlayerbotAI* botAI, std::string const spell); + bool isUseful() override; }; class CastDebuffSpellAction : public CastAuraSpellAction @@ -67,6 +69,13 @@ private: float needLifeTime; }; +class CastMeleeDebuffSpellAction : public CastDebuffSpellAction +{ +public: + CastMeleeDebuffSpellAction(PlayerbotAI* botAI, std::string const spell, bool isOwner = false, float needLifeTime = 8.0f); + bool isUseful() override; +}; + class CastDebuffSpellOnAttackerAction : public CastDebuffSpellAction { public: @@ -245,10 +254,31 @@ public: CastManaTapAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "mana tap") {} }; -class CastWarStompAction : public CastSpellAction +class CastWarStompAction : public CastMeleeSpellAction { public: - CastWarStompAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "war stomp") {} + CastWarStompAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "war stomp") {} +}; + +class CastBloodFuryAction : public CastBuffSpellAction +{ +public: + CastBloodFuryAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "blood fury") {} +}; + +class CastBerserkingAction : public CastBuffSpellAction +{ +public: + CastBerserkingAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "berserking") {} +}; + +class UseTrinketAction : public Action +{ +public: + UseTrinketAction(PlayerbotAI* botAI) : Action(botAI, "use trinket") {} + bool Execute(Event event) override; +protected: + bool UseTrinket(Item* trinket); }; class CastSpellOnEnemyHealerAction : public CastSpellAction diff --git a/src/strategy/actions/ListSpellsAction.cpp b/src/strategy/actions/ListSpellsAction.cpp index 82e786a0..652d22b7 100644 --- a/src/strategy/actions/ListSpellsAction.cpp +++ b/src/strategy/actions/ListSpellsAction.cpp @@ -143,7 +143,10 @@ std::vector> ListSpellsAction::GetSpellList(std:: SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); if (!spellInfo) continue; - + + if (spellInfo->IsPassive()) + continue; + SkillLineAbilityEntry const* skillLine = skillSpells[itr->first]; if (skill != SKILL_NONE && (!skillLine || skillLine->SkillLine != skill)) continue; diff --git a/src/strategy/deathknight/DKActions.h b/src/strategy/deathknight/DKActions.h index 9d35de2c..2fe9c708 100644 --- a/src/strategy/deathknight/DKActions.h +++ b/src/strategy/deathknight/DKActions.h @@ -110,11 +110,11 @@ public: CastIcyTouchAction(PlayerbotAI* ai) : CastSpellAction(ai, "icy touch") {} }; -class CastIcyTouchOnAttackerAction : public CastDebuffSpellOnMeleeAttackerAction +class CastIcyTouchOnAttackerAction : public CastDebuffSpellOnAttackerAction { public: CastIcyTouchOnAttackerAction(PlayerbotAI* botAI) - : CastDebuffSpellOnMeleeAttackerAction(botAI, "icy touch", true, .0f) + : CastDebuffSpellOnAttackerAction(botAI, "icy touch", true, .0f) { } }; @@ -232,16 +232,17 @@ public: CastDeathCoilAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "death coil") {} }; -class CastBloodBoilAction : public CastSpellAction +class CastBloodBoilAction : public CastMeleeSpellAction { public: - CastBloodBoilAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "blood boil") {} + CastBloodBoilAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "blood boil") {} }; class CastDeathAndDecayAction : public CastSpellAction { public: CastDeathAndDecayAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "death and decay") {} + ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } }; class CastHornOfWinterAction : public CastSpellAction diff --git a/src/strategy/druid/DruidActions.h b/src/strategy/druid/DruidActions.h index f73a6864..749ba3ea 100644 --- a/src/strategy/druid/DruidActions.h +++ b/src/strategy/druid/DruidActions.h @@ -234,10 +234,10 @@ public: NextAction** getAlternatives() override; }; -class CastBarskinAction : public CastBuffSpellAction +class CastBarkskinAction : public CastBuffSpellAction { public: - CastBarskinAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "barskin") {} + CastBarkskinAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "barkskin") {} }; class CastInnervateAction : public CastSpellAction diff --git a/src/strategy/druid/DruidAiObjectContext.cpp b/src/strategy/druid/DruidAiObjectContext.cpp index 1a938842..b1181ae2 100644 --- a/src/strategy/druid/DruidAiObjectContext.cpp +++ b/src/strategy/druid/DruidAiObjectContext.cpp @@ -198,7 +198,7 @@ public: creators["healing touch on party"] = &DruidAiObjectContextInternal::healing_touch_on_party; creators["rebirth"] = &DruidAiObjectContextInternal::rebirth; creators["revive"] = &DruidAiObjectContextInternal::revive; - creators["barskin"] = &DruidAiObjectContextInternal::barskin; + creators["barkskin"] = &DruidAiObjectContextInternal::barkskin; creators["lacerate"] = &DruidAiObjectContextInternal::lacerate; creators["hurricane"] = &DruidAiObjectContextInternal::hurricane; creators["innervate"] = &DruidAiObjectContextInternal::innervate; @@ -281,7 +281,7 @@ private: static Action* healing_touch_on_party(PlayerbotAI* botAI) { return new CastHealingTouchOnPartyAction(botAI); } static Action* rebirth(PlayerbotAI* botAI) { return new CastRebirthAction(botAI); } static Action* revive(PlayerbotAI* botAI) { return new CastReviveAction(botAI); } - static Action* barskin(PlayerbotAI* botAI) { return new CastBarskinAction(botAI); } + static Action* barkskin(PlayerbotAI* botAI) { return new CastBarkskinAction(botAI); } static Action* lacerate(PlayerbotAI* botAI) { return new CastLacerateAction(botAI); } static Action* hurricane(PlayerbotAI* botAI) { return new CastHurricaneAction(botAI); } static Action* innervate(PlayerbotAI* botAI) { return new CastInnervateAction(botAI); } diff --git a/src/strategy/druid/DruidBearActions.h b/src/strategy/druid/DruidBearActions.h index 8377bdd1..e83821bb 100644 --- a/src/strategy/druid/DruidBearActions.h +++ b/src/strategy/druid/DruidBearActions.h @@ -43,10 +43,10 @@ public: CastSwipeAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "swipe") {} }; -class CastDemoralizingRoarAction : public CastDebuffSpellAction +class CastDemoralizingRoarAction : public CastMeleeDebuffSpellAction { public: - CastDemoralizingRoarAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "demoralizing roar") {} + CastDemoralizingRoarAction(PlayerbotAI* botAI) : CastMeleeDebuffSpellAction(botAI, "demoralizing roar") {} }; class CastMangleBearAction : public CastMeleeSpellAction diff --git a/src/strategy/druid/FeralDruidStrategy.cpp b/src/strategy/druid/FeralDruidStrategy.cpp index c00e4620..ed4b030b 100644 --- a/src/strategy/druid/FeralDruidStrategy.cpp +++ b/src/strategy/druid/FeralDruidStrategy.cpp @@ -27,7 +27,7 @@ private: { return new ActionNode("survival instincts", /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("barskin"), nullptr), + /*A*/ NextAction::array(0, new NextAction("barkskin"), nullptr), /*C*/ nullptr); } diff --git a/src/strategy/druid/GenericDruidStrategy.cpp b/src/strategy/druid/GenericDruidStrategy.cpp index 5d820c36..c44668f7 100644 --- a/src/strategy/druid/GenericDruidStrategy.cpp +++ b/src/strategy/druid/GenericDruidStrategy.cpp @@ -106,6 +106,9 @@ void GenericDruidStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); + triggers.push_back( + new TriggerNode("low health", NextAction::array(0, new NextAction("barkskin", ACTION_HIGH + 7), 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))); diff --git a/src/strategy/generic/RacialsStrategy.cpp b/src/strategy/generic/RacialsStrategy.cpp index 4b17bdf9..7762abca 100644 --- a/src/strategy/generic/RacialsStrategy.cpp +++ b/src/strategy/generic/RacialsStrategy.cpp @@ -25,14 +25,18 @@ private: void RacialsStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("low health", NextAction::array(0, new NextAction("lifeblood", 71.0f), nullptr))); - // triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("war stomp", 71.0f), - // nullptr))); - /*triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("war stomp", 71.0f), - * nullptr)));*/ - /*triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("arcane torrent", - ACTION_EMERGENCY + 6), nullptr))); triggers.push_back(new TriggerNode("medium mana", NextAction::array(0, new - NextAction("mana tap", ACTION_EMERGENCY + 6), nullptr)));*/ + new TriggerNode("low health", NextAction::array(0, new NextAction("lifeblood", ACTION_NORMAL + 5), nullptr))); + triggers.push_back( + new TriggerNode("medium aoe", NextAction::array(0, new NextAction("war stomp", ACTION_NORMAL + 5), nullptr))); + triggers.push_back(new TriggerNode( + "low mana", NextAction::array(0, new NextAction("arcane torrent", ACTION_NORMAL + 5), nullptr))); + + triggers.push_back(new TriggerNode( + "generic boost", NextAction::array(0, new NextAction("blood fury", ACTION_NORMAL + 5), + new NextAction("berserking", ACTION_NORMAL + 5), + new NextAction("use trinket", ACTION_NORMAL + 4), + nullptr))); + } RacialsStrategy::RacialsStrategy(PlayerbotAI* botAI) : Strategy(botAI) diff --git a/src/strategy/hunter/DpsHunterStrategy.cpp b/src/strategy/hunter/DpsHunterStrategy.cpp index 684622a3..325f3b93 100644 --- a/src/strategy/hunter/DpsHunterStrategy.cpp +++ b/src/strategy/hunter/DpsHunterStrategy.cpp @@ -10,7 +10,11 @@ class DpsHunterStrategyActionNodeFactory : public NamedObjectFactory { public: - DpsHunterStrategyActionNodeFactory() { creators["aimed shot"] = &aimed_shot; } + DpsHunterStrategyActionNodeFactory() + { + creators["aimed shot"] = &aimed_shot; + creators["steady shot"] = &steady_shot; + } private: static ActionNode* aimed_shot([[maybe_unused]] PlayerbotAI* botAI) @@ -20,6 +24,13 @@ private: /*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) @@ -32,7 +43,7 @@ NextAction** DpsHunterStrategy::getDefaultActions() return NextAction::array( 0, new NextAction("kill shot", ACTION_DEFAULT + 0.6f), new NextAction("chimera shot", ACTION_DEFAULT + 0.5f), new NextAction("explosive shot", ACTION_DEFAULT + 0.4f), new NextAction("aimed shot", ACTION_DEFAULT + 0.3f), - new NextAction("arcane shot", ACTION_DEFAULT + 0.2f), new NextAction("steady shot", ACTION_DEFAULT + 0.1f), + /*new NextAction("arcane shot", ACTION_DEFAULT + 0.2f),*/ new NextAction("steady shot", ACTION_DEFAULT + 0.1f), new NextAction("auto shot", ACTION_DEFAULT), nullptr); // return NextAction::array(0, new NextAction("explosive shot", 11.0f), new NextAction("auto shot", 10.0f), new // NextAction("auto attack", 9.0f), nullptr); diff --git a/src/strategy/hunter/GenericHunterStrategy.cpp b/src/strategy/hunter/GenericHunterStrategy.cpp index 7c621b2a..e59df4cd 100644 --- a/src/strategy/hunter/GenericHunterStrategy.cpp +++ b/src/strategy/hunter/GenericHunterStrategy.cpp @@ -97,6 +97,9 @@ void GenericHunterStrategy::InitTriggers(std::vector& triggers) triggers.push_back( new TriggerNode("misdirection on main tank", 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", diff --git a/src/strategy/hunter/HunterActions.h b/src/strategy/hunter/HunterActions.h index ef95eb15..868905c6 100644 --- a/src/strategy/hunter/HunterActions.h +++ b/src/strategy/hunter/HunterActions.h @@ -32,8 +32,11 @@ public: BEGIN_RANGED_SPELL_ACTION(CastArcaneShotAction, "arcane shot") END_SPELL_ACTION() -BEGIN_RANGED_SPELL_ACTION(CastExplosiveShotAction, "explosive 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() @@ -160,6 +163,12 @@ public: CastRapidFireAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "rapid fire") {} }; +class CastDeterrenceAction : public CastBuffSpellAction +{ +public: + CastDeterrenceAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "deterrence") {} +}; + class CastReadinessAction : public CastBuffSpellAction { public: diff --git a/src/strategy/hunter/HunterAiObjectContext.cpp b/src/strategy/hunter/HunterAiObjectContext.cpp index 588888a9..32548aad 100644 --- a/src/strategy/hunter/HunterAiObjectContext.cpp +++ b/src/strategy/hunter/HunterAiObjectContext.cpp @@ -149,6 +149,7 @@ public: creators["freezing trap"] = &HunterAiObjectContextInternal::freezing_trap; creators["rapid fire"] = &HunterAiObjectContextInternal::rapid_fire; creators["boost"] = &HunterAiObjectContextInternal::rapid_fire; + creators["deterrence"] = &HunterAiObjectContextInternal::deterrence; creators["readiness"] = &HunterAiObjectContextInternal::readiness; creators["aspect of the hawk"] = &HunterAiObjectContextInternal::aspect_of_the_hawk; creators["aspect of the monkey"] = &HunterAiObjectContextInternal::aspect_of_the_monkey; @@ -200,6 +201,7 @@ private: static Action* black_arrow(PlayerbotAI* botAI) { return new CastBlackArrow(botAI); } static Action* freezing_trap(PlayerbotAI* botAI) { return new CastFreezingTrap(botAI); } static Action* rapid_fire(PlayerbotAI* botAI) { return new CastRapidFireAction(botAI); } + static Action* deterrence(PlayerbotAI* botAI) { return new CastDeterrenceAction(botAI); } static Action* readiness(PlayerbotAI* botAI) { return new CastReadinessAction(botAI); } static Action* aspect_of_the_hawk(PlayerbotAI* botAI) { return new CastAspectOfTheHawkAction(botAI); } static Action* aspect_of_the_monkey(PlayerbotAI* botAI) { return new CastAspectOfTheMonkeyAction(botAI); } diff --git a/src/strategy/paladin/DpsPaladinStrategy.cpp b/src/strategy/paladin/DpsPaladinStrategy.cpp index e3ecf5c2..da74b42d 100644 --- a/src/strategy/paladin/DpsPaladinStrategy.cpp +++ b/src/strategy/paladin/DpsPaladinStrategy.cpp @@ -85,7 +85,7 @@ NextAction** DpsPaladinStrategy::getDefaultActions() return NextAction::array(0, new NextAction("crusader strike", ACTION_DEFAULT + 0.4f), new NextAction("judgement of wisdom", ACTION_DEFAULT + 0.3f), new NextAction("divine storm", ACTION_DEFAULT + 0.2f), - new NextAction("melee consecration", ACTION_DEFAULT + 0.1f), + new NextAction("consecration", ACTION_DEFAULT + 0.1f), new NextAction("melee", ACTION_DEFAULT), NULL); } @@ -112,7 +112,7 @@ void DpsPaladinStrategy::InitTriggers(std::vector& triggers) // triggers.push_back(new TriggerNode("repentance", NextAction::array(0, new NextAction("repentance", // ACTION_INTERRUPT + 2), nullptr))); triggers.push_back(new TriggerNode( - "medium aoe", NextAction::array(0, new NextAction("melee consecration", ACTION_HIGH + 3), nullptr))); + "medium aoe", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 3), nullptr))); triggers.push_back( new TriggerNode("art of war", NextAction::array(0, new NextAction("exorcism", ACTION_HIGH + 2), nullptr))); triggers.push_back(new TriggerNode("target critical health", diff --git a/src/strategy/paladin/GenericPaladinStrategy.cpp b/src/strategy/paladin/GenericPaladinStrategy.cpp index 68d5bc84..676a6159 100644 --- a/src/strategy/paladin/GenericPaladinStrategy.cpp +++ b/src/strategy/paladin/GenericPaladinStrategy.cpp @@ -17,8 +17,8 @@ void GenericPaladinStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - // triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("divine shield", - // ACTION_CRITICAL_HEAL + 2), new NextAction("holy light", ACTION_CRITICAL_HEAL + 2), nullptr))); + triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("divine shield", + ACTION_HIGH + 5), nullptr))); triggers.push_back( new TriggerNode("hammer of justice interrupt", NextAction::array(0, new NextAction("hammer of justice", ACTION_INTERRUPT), nullptr))); diff --git a/src/strategy/paladin/PaladinActions.cpp b/src/strategy/paladin/PaladinActions.cpp index 402d4a56..1b5e46c0 100644 --- a/src/strategy/paladin/PaladinActions.cpp +++ b/src/strategy/paladin/PaladinActions.cpp @@ -153,13 +153,6 @@ Unit* CastRighteousDefenseAction::GetTarget() return current_target->GetVictim(); } -bool CastMeleeConsecrationAction::isUseful() -{ - Unit* target = GetTarget(); - // float dis = distance + CONTACT_DISTANCE; - return target && bot->IsWithinMeleeRange(target); // sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, - // "distance", GetTargetName()), distance); -} bool CastDivineSacrificeAction::isUseful() { diff --git a/src/strategy/paladin/PaladinActions.h b/src/strategy/paladin/PaladinActions.h index 826c82e2..17fe052b 100644 --- a/src/strategy/paladin/PaladinActions.h +++ b/src/strategy/paladin/PaladinActions.h @@ -44,13 +44,6 @@ SPELL_ACTION(CastHolyShockAction, "holy shock"); // consecration MELEE_ACTION(CastConsecrationAction, "consecration"); -class CastMeleeConsecrationAction : public CastSpellAction -{ -public: - CastMeleeConsecrationAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "consecration") {} - bool isUseful() override; -}; - // repentance SNARE_ACTION(CastRepentanceSnareAction, "repentance"); DEBUFF_ACTION(CastRepentanceAction, "repentance"); @@ -67,10 +60,10 @@ BUFF_ACTION(CastDivineFavorAction, "divine favor"); // fury BUFF_ACTION(CastRighteousFuryAction, "righteous fury"); -class CastDivineStormAction : public CastBuffSpellAction +class CastDivineStormAction : public CastMeleeSpellAction { public: - CastDivineStormAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "divine storm") {} + CastDivineStormAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "divine storm") {} }; class CastCrusaderStrikeAction : public CastMeleeSpellAction diff --git a/src/strategy/paladin/PaladinAiObjectContext.cpp b/src/strategy/paladin/PaladinAiObjectContext.cpp index 770069a1..094e2fb7 100644 --- a/src/strategy/paladin/PaladinAiObjectContext.cpp +++ b/src/strategy/paladin/PaladinAiObjectContext.cpp @@ -232,7 +232,6 @@ public: creators["concentration aura"] = &PaladinAiObjectContextInternal::concentration_aura; creators["holy wrath"] = &PaladinAiObjectContextInternal::holy_wrath; creators["consecration"] = &PaladinAiObjectContextInternal::consecration; - creators["melee consecration"] = &PaladinAiObjectContextInternal::melee_consecration; creators["cleanse disease"] = &PaladinAiObjectContextInternal::cleanse_disease; creators["cleanse poison"] = &PaladinAiObjectContextInternal::cleanse_poison; creators["cleanse magic"] = &PaladinAiObjectContextInternal::cleanse_magic; @@ -331,7 +330,6 @@ private: static Action* concentration_aura(PlayerbotAI* botAI) { return new CastConcentrationAuraAction(botAI); } static Action* holy_wrath(PlayerbotAI* botAI) { return new CastHolyWrathAction(botAI); } static Action* consecration(PlayerbotAI* botAI) { return new CastConsecrationAction(botAI); } - static Action* melee_consecration(PlayerbotAI* botAI) { return new CastMeleeConsecrationAction(botAI); } static Action* cleanse_poison(PlayerbotAI* botAI) { return new CastCleansePoisonAction(botAI); } static Action* cleanse_disease(PlayerbotAI* botAI) { return new CastCleanseDiseaseAction(botAI); } static Action* cleanse_magic(PlayerbotAI* botAI) { return new CastCleanseMagicAction(botAI); } diff --git a/src/strategy/paladin/TankPaladinStrategy.cpp b/src/strategy/paladin/TankPaladinStrategy.cpp index 517a639a..649fe21e 100644 --- a/src/strategy/paladin/TankPaladinStrategy.cpp +++ b/src/strategy/paladin/TankPaladinStrategy.cpp @@ -82,7 +82,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode( "light aoe", NextAction::array(0, new NextAction("avenger's shield", ACTION_HIGH + 5), nullptr))); triggers.push_back( - new TriggerNode("medium aoe", NextAction::array(0, new NextAction("melee consecration", ACTION_HIGH + 7), + new TriggerNode("medium aoe", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 7), new NextAction("avenger's shield", ACTION_HIGH + 6), nullptr))); // triggers.push_back(new TriggerNode("avenger's shield", NextAction::array(0, new NextAction("avenger's shield", // ACTION_HIGH + 7), nullptr))); @@ -107,7 +107,7 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) new TriggerNode("medium group heal occasion", NextAction::array(0, new NextAction("divine sacrifice", ACTION_HIGH + 5), nullptr))); triggers.push_back(new TriggerNode( - "enough mana", NextAction::array(0, new NextAction("melee consecration", ACTION_HIGH + 4), nullptr))); + "enough mana", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 4), nullptr))); triggers.push_back(new TriggerNode("not facing target", NextAction::array(0, new NextAction("set facing", ACTION_NORMAL + 7), nullptr))); triggers.push_back(new TriggerNode( diff --git a/src/strategy/priest/GenericPriestStrategy.cpp b/src/strategy/priest/GenericPriestStrategy.cpp index b087c79e..8ef2c3ae 100644 --- a/src/strategy/priest/GenericPriestStrategy.cpp +++ b/src/strategy/priest/GenericPriestStrategy.cpp @@ -31,8 +31,9 @@ void GenericPriestStrategy::InitTriggers(std::vector& triggers) // NextAction("inner focus", 42.0f), nullptr))); triggers.push_back(new TriggerNode("medium mana", // NextAction::array(0, new NextAction("symbol of hope", ACTION_EMERGENCY), nullptr))); triggers.push_back(new // TriggerNode("low mana", NextAction::array(0, new NextAction("consume magic", 10.0f), nullptr))); - // triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("desperate prayer", - // ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new + triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("desperate prayer", + ACTION_HIGH + 5), nullptr))); + // triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new // NextAction("elune's grace", ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("chastise", // NextAction::array(0, new NextAction("chastise", ACTION_INTERRUPT), nullptr))); triggers.push_back(new TriggerNode( diff --git a/src/strategy/priest/HolyPriestStrategy.cpp b/src/strategy/priest/HolyPriestStrategy.cpp index decae30d..40f34a28 100644 --- a/src/strategy/priest/HolyPriestStrategy.cpp +++ b/src/strategy/priest/HolyPriestStrategy.cpp @@ -73,7 +73,9 @@ void HolyHealPriestStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode( "party member critical health", - NextAction::array(0, new NextAction("power word: shield on party", ACTION_CRITICAL_HEAL + 5), + NextAction::array(0, + new NextAction("guardian spirit on party", ACTION_CRITICAL_HEAL + 6), + new NextAction("power word: shield on party", ACTION_CRITICAL_HEAL + 5), new NextAction("flash heal on party", ACTION_CRITICAL_HEAL + 3), new NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 2), NULL))); diff --git a/src/strategy/priest/PriestActions.h b/src/strategy/priest/PriestActions.h index e7a95937..468694c8 100644 --- a/src/strategy/priest/PriestActions.h +++ b/src/strategy/priest/PriestActions.h @@ -173,4 +173,11 @@ public: CastMindSearAction(PlayerbotAI* ai) : CastSpellAction(ai, "mind sear") {} ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } }; + +class CastGuardianSpiritOnPartyAction : public HealPartyMemberAction +{ +public: + CastGuardianSpiritOnPartyAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "guardian spirit", 40.0f, HealingManaEfficiency::MEDIUM) {} +}; + #endif diff --git a/src/strategy/priest/PriestAiObjectContext.cpp b/src/strategy/priest/PriestAiObjectContext.cpp index d48d1109..0df50eec 100644 --- a/src/strategy/priest/PriestAiObjectContext.cpp +++ b/src/strategy/priest/PriestAiObjectContext.cpp @@ -234,6 +234,7 @@ public: creators["hymn of hope"] = &PriestAiObjectContextInternal::hymn_of_hope; creators["divine hymn"] = &PriestAiObjectContextInternal::divine_hymn; creators["mind sear"] = &PriestAiObjectContextInternal::mind_sear; + creators["guardian spirit on party"] = &PriestAiObjectContextInternal::guardian_spirit_on_party; } private: @@ -339,6 +340,7 @@ private: static Action* hymn_of_hope(PlayerbotAI* ai) { return new CastHymnOfHopeAction(ai); } static Action* divine_hymn(PlayerbotAI* ai) { return new CastDivineHymnAction(ai); } static Action* mind_sear(PlayerbotAI* ai) { return new CastMindSearAction(ai); } + static Action* guardian_spirit_on_party(PlayerbotAI* ai) { return new CastGuardianSpiritOnPartyAction(ai); } }; PriestAiObjectContext::PriestAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) diff --git a/src/strategy/priest/PriestTriggers.h b/src/strategy/priest/PriestTriggers.h index fbfeeb57..f4eab6da 100644 --- a/src/strategy/priest/PriestTriggers.h +++ b/src/strategy/priest/PriestTriggers.h @@ -23,7 +23,7 @@ CURE_TRIGGER(CureDiseaseTrigger, "cure disease", DISPEL_DISEASE); CURE_PARTY_TRIGGER(PartyMemberCureDiseaseTrigger, "cure disease", DISPEL_DISEASE); BUFF_TRIGGER_A(InnerFireTrigger, "inner fire"); BUFF_TRIGGER_A(ShadowformTrigger, "shadowform"); -BUFF_TRIGGER(PowerInfusionTrigger, "power infusion"); +BOOST_TRIGGER(PowerInfusionTrigger, "power infusion"); BUFF_TRIGGER(InnerFocusTrigger, "inner focus"); BUFF_TRIGGER(ShadowProtectionTrigger, "shadow protection"); BUFF_PARTY_TRIGGER(ShadowProtectionOnPartyTrigger, "shadow protection"); diff --git a/src/strategy/priest/ShadowPriestStrategy.cpp b/src/strategy/priest/ShadowPriestStrategy.cpp index 474ce4db..e2433c7d 100644 --- a/src/strategy/priest/ShadowPriestStrategy.cpp +++ b/src/strategy/priest/ShadowPriestStrategy.cpp @@ -29,8 +29,10 @@ void ShadowPriestStrategy::InitTriggers(std::vector& triggers) // ACTION_MOVE + 9), nullptr))); triggers.push_back( new TriggerNode("shadowform", NextAction::array(0, new NextAction("shadowform", ACTION_HIGH), nullptr))); - // triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("dispersion", ACTION_EMERGENCY - // + 5), nullptr))); + triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("dispersion", ACTION_HIGH + + 5), nullptr))); + triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("dispersion", ACTION_HIGH + + 5), nullptr))); triggers.push_back( new TriggerNode("vampiric embrace", NextAction::array(0, new NextAction("vampiric embrace", 16.0f), nullptr))); triggers.push_back( diff --git a/src/strategy/rogue/AssassinationRogueStrategy.cpp b/src/strategy/rogue/AssassinationRogueStrategy.cpp index c0eafa69..380ac292 100644 --- a/src/strategy/rogue/AssassinationRogueStrategy.cpp +++ b/src/strategy/rogue/AssassinationRogueStrategy.cpp @@ -66,8 +66,11 @@ void AssassinationRogueStrategy::InitTriggers(std::vector& trigger new TriggerNode("medium threat", NextAction::array(0, new NextAction("vanish", ACTION_HIGH), NULL))); triggers.push_back( - new TriggerNode("low health", NextAction::array(0, new NextAction("evasion", ACTION_EMERGENCY), - new NextAction("feint", ACTION_EMERGENCY), NULL))); + new TriggerNode("low health", NextAction::array(0, new NextAction("evasion", ACTION_HIGH + 9), + new NextAction("feint", ACTION_HIGH + 8), nullptr))); + + triggers.push_back( + new TriggerNode("critical health", NextAction::array(0, new NextAction("cloak of shadows", ACTION_HIGH + 7), nullptr))); triggers.push_back( new TriggerNode("kick", NextAction::array(0, new NextAction("kick", ACTION_INTERRUPT + 2), NULL))); diff --git a/src/strategy/rogue/DpsRogueStrategy.cpp b/src/strategy/rogue/DpsRogueStrategy.cpp index f3b2ab1c..6fc450b9 100644 --- a/src/strategy/rogue/DpsRogueStrategy.cpp +++ b/src/strategy/rogue/DpsRogueStrategy.cpp @@ -108,8 +108,11 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) new TriggerNode("medium threat", NextAction::array(0, new NextAction("vanish", ACTION_HIGH), nullptr))); triggers.push_back( - new TriggerNode("low health", NextAction::array(0, new NextAction("evasion", ACTION_EMERGENCY), - new NextAction("feint", ACTION_EMERGENCY), nullptr))); + new TriggerNode("low health", NextAction::array(0, new NextAction("evasion", ACTION_HIGH + 9), + new NextAction("feint", ACTION_HIGH + 8), nullptr))); + + triggers.push_back( + new TriggerNode("critical health", NextAction::array(0, new NextAction("cloak of shadows", ACTION_HIGH + 7), nullptr))); triggers.push_back( new TriggerNode("kick", NextAction::array(0, new NextAction("kick", ACTION_INTERRUPT + 2), nullptr))); @@ -125,6 +128,9 @@ void DpsRogueStrategy::InitTriggers(std::vector& triggers) triggers.push_back( new TriggerNode("light aoe", NextAction::array(0, new NextAction("blade flurry", ACTION_HIGH + 3), nullptr))); + triggers.push_back( + new TriggerNode("blade flurry", NextAction::array(0, new NextAction("blade flurry", ACTION_HIGH + 2), nullptr))); + triggers.push_back(new TriggerNode( "enemy out of melee", NextAction::array(0, new NextAction("stealth", ACTION_NORMAL + 9), new NextAction("sprint", ACTION_NORMAL + 8), diff --git a/src/strategy/rogue/RogueActions.h b/src/strategy/rogue/RogueActions.h index f68fb676..35d846ea 100644 --- a/src/strategy/rogue/RogueActions.h +++ b/src/strategy/rogue/RogueActions.h @@ -17,6 +17,12 @@ public: CastEvasionAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "evasion") {} }; +class CastCloakOfShadowsAction : public CastBuffSpellAction +{ +public: + CastCloakOfShadowsAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "cloak of shadows") {} +}; + class CastHungerForBloodAction : public CastBuffSpellAction { public: diff --git a/src/strategy/rogue/RogueAiObjectContext.cpp b/src/strategy/rogue/RogueAiObjectContext.cpp index e4f88909..355c8953 100644 --- a/src/strategy/rogue/RogueAiObjectContext.cpp +++ b/src/strategy/rogue/RogueAiObjectContext.cpp @@ -76,12 +76,14 @@ public: creators["off hand weapon no enchant"] = &RogueTriggerFactoryInternal::off_hand_weapon_no_enchant; creators["tricks of the trade on main tank"] = &RogueTriggerFactoryInternal::tricks_of_the_trade_on_main_tank; creators["adrenaline rush"] = &RogueTriggerFactoryInternal::adrenaline_rush; + creators["blade fury"] = &RogueTriggerFactoryInternal::blade_fury; creators["target with combo points almost dead"] = &RogueTriggerFactoryInternal::target_with_combo_points_almost_dead; } private: static Trigger* adrenaline_rush(PlayerbotAI* botAI) { return new AdrenalineRushTrigger(botAI); } + static Trigger* blade_fury(PlayerbotAI* botAI) { return new BladeFuryTrigger(botAI); } static Trigger* kick(PlayerbotAI* botAI) { return new KickInterruptSpellTrigger(botAI); } static Trigger* rupture(PlayerbotAI* botAI) { return new RuptureTrigger(botAI); } static Trigger* slice_and_dice(PlayerbotAI* botAI) { return new SliceAndDiceTrigger(botAI); } @@ -122,6 +124,7 @@ public: creators["eviscerate"] = &RogueAiObjectContextInternal::eviscerate; creators["vanish"] = &RogueAiObjectContextInternal::vanish; creators["evasion"] = &RogueAiObjectContextInternal::evasion; + creators["cloak of shadows"] = &RogueAiObjectContextInternal::cloak_of_shadows; creators["kick"] = &RogueAiObjectContextInternal::kick; creators["feint"] = &RogueAiObjectContextInternal::feint; creators["backstab"] = &RogueAiObjectContextInternal::backstab; @@ -161,6 +164,7 @@ private: static Action* eviscerate(PlayerbotAI* botAI) { return new CastEviscerateAction(botAI); } static Action* vanish(PlayerbotAI* botAI) { return new CastVanishAction(botAI); } static Action* evasion(PlayerbotAI* botAI) { return new CastEvasionAction(botAI); } + static Action* cloak_of_shadows(PlayerbotAI* botAI) { return new CastCloakOfShadowsAction(botAI); } static Action* kick(PlayerbotAI* botAI) { return new CastKickAction(botAI); } static Action* feint(PlayerbotAI* botAI) { return new CastFeintAction(botAI); } static Action* backstab(PlayerbotAI* botAI) { return new CastBackstabAction(botAI); } diff --git a/src/strategy/rogue/RogueComboActions.h b/src/strategy/rogue/RogueComboActions.h index 171d0b7d..e5ebc5a8 100644 --- a/src/strategy/rogue/RogueComboActions.h +++ b/src/strategy/rogue/RogueComboActions.h @@ -18,34 +18,34 @@ public: bool isUseful() override; }; -class CastSinisterStrikeAction : public CastComboAction +class CastSinisterStrikeAction : public CastSpellAction { public: - CastSinisterStrikeAction(PlayerbotAI* botAI) : CastComboAction(botAI, "sinister strike") {} + CastSinisterStrikeAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "sinister strike") {} }; -class CastMutilateAction : public CastComboAction +class CastMutilateAction : public CastSpellAction { public: - CastMutilateAction(PlayerbotAI* botAI) : CastComboAction(botAI, "mutilate") {} + CastMutilateAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "mutilate") {} }; -class CastRiposteAction : public CastComboAction +class CastRiposteAction : public CastSpellAction { public: - CastRiposteAction(PlayerbotAI* botAI) : CastComboAction(botAI, "riposte") {} + CastRiposteAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "riposte") {} }; -class CastGougeAction : public CastComboAction +class CastGougeAction : public CastSpellAction { public: - CastGougeAction(PlayerbotAI* botAI) : CastComboAction(botAI, "gouge") {} + CastGougeAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "gouge") {} }; -class CastBackstabAction : public CastComboAction +class CastBackstabAction : public CastSpellAction { public: - CastBackstabAction(PlayerbotAI* botAI) : CastComboAction(botAI, "backstab") {} + CastBackstabAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "backstab") {} }; #endif diff --git a/src/strategy/rogue/RogueTriggers.h b/src/strategy/rogue/RogueTriggers.h index 30ca4105..467bd9fc 100644 --- a/src/strategy/rogue/RogueTriggers.h +++ b/src/strategy/rogue/RogueTriggers.h @@ -36,6 +36,13 @@ public: // bool isPossible(); }; +class BladeFuryTrigger : public BoostTrigger +{ +public: + BladeFuryTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "blade fury") {} +}; + + class RuptureTrigger : public DebuffTrigger { public: diff --git a/src/strategy/shaman/ShamanActions.cpp b/src/strategy/shaman/ShamanActions.cpp index ee6e3bea..7394c320 100644 --- a/src/strategy/shaman/ShamanActions.cpp +++ b/src/strategy/shaman/ShamanActions.cpp @@ -6,6 +6,7 @@ #include "ShamanActions.h" #include "Playerbots.h" +#include "Totem.h" bool CastTotemAction::isUseful() { @@ -41,7 +42,24 @@ bool CastSearingTotemAction::isUseful() return CastTotemAction::isUseful() && !AI_VALUE2(bool, "has totem", "flametongue totem"); } -bool CastMagmaTotemAction::isUseful() { return CastTotemAction::isUseful() && !AI_VALUE2(bool, "has totem", name); } +bool CastMagmaTotemAction::isUseful() { + Unit* target = AI_VALUE(Unit*, "current target"); + if (!target || !bot->IsWithinMeleeRange(target)) + return false; + + return CastTotemAction::isUseful() && !AI_VALUE2(bool, "has totem", name); +} + +bool CastFireNovaAction::isUseful() { + Creature* fireTotem = bot->GetMap()->GetCreature(bot->m_SummonSlot[1]); + if (!fireTotem) + return false; + + if (bot->GetDistance(fireTotem) > 8.0f) + return false; + + return CastMeleeSpellAction::isUseful(); +} bool CastCleansingTotemAction::isUseful() { diff --git a/src/strategy/shaman/ShamanActions.h b/src/strategy/shaman/ShamanActions.h index 0356a144..2568cd11 100644 --- a/src/strategy/shaman/ShamanActions.h +++ b/src/strategy/shaman/ShamanActions.h @@ -231,10 +231,11 @@ public: bool isUseful() override; }; -class CastFireNovaAction : public CastSpellAction +class CastFireNovaAction : public CastMeleeSpellAction { public: - CastFireNovaAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "fire nova") {} + CastFireNovaAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "fire nova") {} + bool isUseful() override; }; class CastWindShearAction : public CastSpellAction diff --git a/src/strategy/triggers/GenericTriggers.cpp b/src/strategy/triggers/GenericTriggers.cpp index 49617449..c1f80eb7 100644 --- a/src/strategy/triggers/GenericTriggers.cpp +++ b/src/strategy/triggers/GenericTriggers.cpp @@ -308,7 +308,23 @@ std::string const TwoTriggers::getName() return name; } -bool BoostTrigger::IsActive() { return BuffTrigger::IsActive() && AI_VALUE(uint8, "balance") <= balance; } +bool BoostTrigger::IsActive() +{ + if (!BuffTrigger::IsActive()) + return false; + Unit* target = AI_VALUE(Unit*, "current target"); + if (target && target->ToPlayer()) + return true; + return AI_VALUE(uint8, "balance") <= balance; +} + +bool GenericBoostTrigger::IsActive() +{ + Unit* target = AI_VALUE(Unit*, "current target"); + if (target && target->ToPlayer()) + return true; + return AI_VALUE(uint8, "balance") <= balance; +} bool ItemCountTrigger::IsActive() { return AI_VALUE2(uint32, "item count", item) < count; } diff --git a/src/strategy/triggers/GenericTriggers.h b/src/strategy/triggers/GenericTriggers.h index 2410f674..35a49e3f 100644 --- a/src/strategy/triggers/GenericTriggers.h +++ b/src/strategy/triggers/GenericTriggers.h @@ -409,6 +409,21 @@ protected: float balance; }; +class GenericBoostTrigger : public Trigger +{ +public: + GenericBoostTrigger(PlayerbotAI* botAI, float balance = 50.f) + : Trigger(botAI, "generic boost", 1), balance(balance) + { + } + + bool IsActive() override; + +protected: + float balance; +}; + + class RandomTrigger : public Trigger { public: diff --git a/src/strategy/triggers/HealthTriggers.h b/src/strategy/triggers/HealthTriggers.h index 88739fef..d9f3253c 100644 --- a/src/strategy/triggers/HealthTriggers.h +++ b/src/strategy/triggers/HealthTriggers.h @@ -48,7 +48,7 @@ class LowHealthTrigger : public HealthInRangeTrigger { public: LowHealthTrigger(PlayerbotAI* botAI, std::string const name = "low health", - float value = sPlayerbotAIConfig->lowHealth, float minValue = sPlayerbotAIConfig->criticalHealth) + float value = sPlayerbotAIConfig->lowHealth, float minValue = 0) : HealthInRangeTrigger(botAI, name, value, minValue) { } @@ -69,7 +69,7 @@ class MediumHealthTrigger : public LowHealthTrigger { public: MediumHealthTrigger(PlayerbotAI* botAI) - : LowHealthTrigger(botAI, "medium health", sPlayerbotAIConfig->mediumHealth, sPlayerbotAIConfig->lowHealth) + : LowHealthTrigger(botAI, "medium health", sPlayerbotAIConfig->mediumHealth, 0) { } }; @@ -89,7 +89,7 @@ class PartyMemberLowHealthTrigger : public HealthInRangeTrigger public: PartyMemberLowHealthTrigger(PlayerbotAI* botAI, std::string const name = "party member low health", float value = sPlayerbotAIConfig->lowHealth, - float minValue = sPlayerbotAIConfig->criticalHealth) + float minValue = 0) : HealthInRangeTrigger(botAI, name, value, minValue) { } @@ -111,7 +111,7 @@ class PartyMemberMediumHealthTrigger : public PartyMemberLowHealthTrigger public: PartyMemberMediumHealthTrigger(PlayerbotAI* botAI) : PartyMemberLowHealthTrigger(botAI, "party member medium health", sPlayerbotAIConfig->mediumHealth, - sPlayerbotAIConfig->lowHealth) + 0) { } }; @@ -121,7 +121,7 @@ class PartyMemberAlmostFullHealthTrigger : public PartyMemberLowHealthTrigger public: PartyMemberAlmostFullHealthTrigger(PlayerbotAI* botAI) : PartyMemberLowHealthTrigger(botAI, "party member almost full health", sPlayerbotAIConfig->almostFullHealth, - sPlayerbotAIConfig->mediumHealth) + 0) { } }; diff --git a/src/strategy/triggers/TriggerContext.h b/src/strategy/triggers/TriggerContext.h index a10d9ca7..788b7743 100644 --- a/src/strategy/triggers/TriggerContext.h +++ b/src/strategy/triggers/TriggerContext.h @@ -53,6 +53,8 @@ public: creators["party member medium health"] = &TriggerContext::PartyMemberMediumHealth; creators["party member almost full health"] = &TriggerContext::PartyMemberAlmostFullHealth; + creators["generic boost"] = &TriggerContext::generic_boost; + creators["protect party member"] = &TriggerContext::protect_party_member; creators["light rage available"] = &TriggerContext::LightRageAvailable; @@ -318,6 +320,7 @@ private: { return new PartyMemberAlmostFullHealthTrigger(botAI); } + static Trigger* generic_boost(PlayerbotAI* botAI) { return new GenericBoostTrigger(botAI); } static Trigger* PartyMemberCriticalHealth(PlayerbotAI* botAI) { return new PartyMemberCriticalHealthTrigger(botAI); diff --git a/src/strategy/values/AttackerCountValues.cpp b/src/strategy/values/AttackerCountValues.cpp index 9cc82a37..59de8995 100644 --- a/src/strategy/values/AttackerCountValues.cpp +++ b/src/strategy/values/AttackerCountValues.cpp @@ -66,8 +66,13 @@ uint8 BalancePercentValue::Calculate() playerLevel += player->GetLevel(); } + uint32 memberCount = group->GetMembersCount(); + playerLevel /= memberCount; + if (memberCount <= 10) + playerLevel *= memberCount; + else + playerLevel *= 10; } - GuidVector v = context->GetValue("attackers")->Get(); for (ObjectGuid const guid : v) { @@ -89,7 +94,7 @@ uint8 BalancePercentValue::Calculate() level *= 3; break; case CREATURE_ELITE_WORLDBOSS: - level *= 50; + level *= 30; break; } diff --git a/src/strategy/values/AttackerWithoutAuraTargetValue.cpp b/src/strategy/values/AttackerWithoutAuraTargetValue.cpp index a9fcd5c4..a3945e64 100644 --- a/src/strategy/values/AttackerWithoutAuraTargetValue.cpp +++ b/src/strategy/values/AttackerWithoutAuraTargetValue.cpp @@ -19,7 +19,7 @@ Unit* AttackerWithoutAuraTargetValue::Calculate() if (!unit || !unit->IsAlive()) continue; - if (bot->GetDistance(unit) > botAI->GetRange(range)) + if (!bot->IsWithinCombatRange(unit, botAI->GetRange(range))) continue; if (unit->GetHealth() < max_health) diff --git a/src/strategy/values/PartyMemberToHeal.cpp b/src/strategy/values/PartyMemberToHeal.cpp index e16d63d0..3fb0b45d 100644 --- a/src/strategy/values/PartyMemberToHeal.cpp +++ b/src/strategy/values/PartyMemberToHeal.cpp @@ -41,6 +41,8 @@ Unit* PartyMemberToHeal::Calculate() for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) { Player* player = gref->GetSource(); + if (player->IsGameMaster()) + continue; if (player && player->IsAlive()) { uint8 health = player->GetHealthPct(); diff --git a/src/strategy/values/PartyMemberValue.cpp b/src/strategy/values/PartyMemberValue.cpp index 023eeefd..48ae772a 100644 --- a/src/strategy/values/PartyMemberValue.cpp +++ b/src/strategy/values/PartyMemberValue.cpp @@ -103,7 +103,8 @@ bool PartyMemberValue::Check(Unit* player) { // return player && player != bot && player->GetMapId() == bot->GetMapId() && bot->IsWithinDistInMap(player, // sPlayerbotAIConfig->sightDistance, false); - return player && player->GetMapId() == bot->GetMapId() && + bool isGM = player->ToPlayer() && player->ToPlayer()->IsGameMaster(); + return player && player->GetMapId() == bot->GetMapId() && !isGM && bot->GetDistance(player) < sPlayerbotAIConfig->spellDistance * 2 && bot->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); } diff --git a/src/strategy/warrior/WarriorActions.h b/src/strategy/warrior/WarriorActions.h index d571b67e..05505da0 100644 --- a/src/strategy/warrior/WarriorActions.h +++ b/src/strategy/warrior/WarriorActions.h @@ -20,14 +20,21 @@ BUFF_ACTION(CastBerserkerStanceAction, "berserker stance"); // shouts BUFF_ACTION(CastBattleShoutAction, "battle shout"); MELEE_ACTION_U(CastBattleShoutTauntAction, "battle shout", CastSpellAction::isUseful()); // useful to rebuff -DEBUFF_ACTION_R(CastDemoralizingShoutAction, "demoralizing shout", 8.0f); // low range debuff -class CastDemoralizingShoutWithoutLifeTimeCheckAction : public CastDebuffSpellAction +// DEBUFF_ACTION_R(CastDemoralizingShoutAction, "demoralizing shout", 8.0f); // low range debuff + +class CastDemoralizingShoutAction : public CastMeleeDebuffSpellAction +{ +public: + CastDemoralizingShoutAction(PlayerbotAI* botAI) + : CastMeleeDebuffSpellAction(botAI, "demoralizing shout") {} +}; + +class CastDemoralizingShoutWithoutLifeTimeCheckAction : public CastMeleeDebuffSpellAction { public: CastDemoralizingShoutWithoutLifeTimeCheckAction(PlayerbotAI* botAI) - : CastDebuffSpellAction(botAI, "demoralizing shout", false, 0.0f) + : CastMeleeDebuffSpellAction(botAI, "demoralizing shout", false, 0.0f) { - range = 8.0f; } }; @@ -63,7 +70,7 @@ DEBUFF_ACTION(CastShatteringThrowAction, "shattering throw"); MELEE_ACTION(CastMortalStrikeAction, "mortal strike"); BUFF_ACTION(CastSweepingStrikesAction, "sweeping strikes"); // arms talents 3.3.5 -BUFF_ACTION(CastBladestormAction, "bladestorm"); +MELEE_ACTION(CastBladestormAction, "bladestorm"); // fury MELEE_ACTION(CastCleaveAction, "cleave");