diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index a7d7c1d8..efa9d84a 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -2125,7 +2125,7 @@ bool PlayerbotAI::CanCastSpell(std::string const name, Unit* target, Item* itemT return CanCastSpell(aiObjectContext->GetValue("spell id", name)->Get(), target, true, itemTarget); } -bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, Item* itemTarget) +bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, Item* itemTarget, Item* castItem) { if (!spellid) { if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { @@ -2249,9 +2249,11 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, Spell* spell = new Spell(bot, spellInfo, TRIGGERED_NONE); spell->m_targets.SetUnitTarget(target); - - spell->m_CastItem = itemTarget ? itemTarget : aiObjectContext->GetValue("item for spell", spellid)->Get(); - spell->m_targets.SetItemTarget(spell->m_CastItem); + spell->m_CastItem = castItem; + if (itemTarget == nullptr) { + itemTarget = aiObjectContext->GetValue("item for spell", spellid)->Get();; + } + spell->m_targets.SetItemTarget(itemTarget); SpellCastResult result = spell->CheckCast(true); delete spell; diff --git a/src/PlayerbotAI.h b/src/PlayerbotAI.h index 7011f012..e515ab40 100644 --- a/src/PlayerbotAI.h +++ b/src/PlayerbotAI.h @@ -387,7 +387,7 @@ class PlayerbotAI : public PlayerbotAIBase virtual bool IsInterruptableSpellCasting(Unit* player, std::string const spell); virtual bool HasAuraToDispel(Unit* player, uint32 dispelType); - bool CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell = true, Item* itemTarget = nullptr); + bool CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell = true, Item* itemTarget = nullptr, Item* castItem = nullptr); bool CanCastSpell(uint32 spellid, GameObject* goTarget, uint8 effectMask, bool checkHasSpell = true); bool CanCastSpell(uint32 spellid, float x, float y, float z, uint8 effectMask, bool checkHasSpell = true, Item* itemTarget = nullptr); diff --git a/src/strategy/actions/UseItemAction.cpp b/src/strategy/actions/UseItemAction.cpp index 1c50c7c0..0c8b49f3 100644 --- a/src/strategy/actions/UseItemAction.cpp +++ b/src/strategy/actions/UseItemAction.cpp @@ -86,7 +86,7 @@ bool UseItemAction::UseItem(Item* item, ObjectGuid goGuid, Item* itemTarget, Uni if (item->GetTemplate()->Spells[i].SpellId > 0) { spellId = item->GetTemplate()->Spells[i].SpellId; - if (!botAI->CanCastSpell(spellId, bot, false, item)) { + if (!botAI->CanCastSpell(spellId, bot, false, itemTarget, item)) { return false; } } diff --git a/src/strategy/rogue/GenericRogueNonCombatStrategy.cpp b/src/strategy/rogue/GenericRogueNonCombatStrategy.cpp index 52c10ddc..74d95313 100644 --- a/src/strategy/rogue/GenericRogueNonCombatStrategy.cpp +++ b/src/strategy/rogue/GenericRogueNonCombatStrategy.cpp @@ -5,6 +5,29 @@ #include "GenericRogueNonCombatStrategy.h" #include "Playerbots.h" + +class GenericRogueNonCombatStrategyActionNodeFactory : public NamedObjectFactory +{ + public: + GenericRogueNonCombatStrategyActionNodeFactory() + { + creators["use deadly poison on off hand"] = &use_deadly_poison_on_off_hand; + } + + private: + static ActionNode* use_deadly_poison_on_off_hand(PlayerbotAI* botAI) + { + return new ActionNode ("use deadly poison on off hand", + /*P*/ nullptr, + /*A*/ NextAction::array(0, new NextAction("use instant poison on off hand"), nullptr), + /*C*/ nullptr); + } +}; + +GenericRogueNonCombatStrategy::GenericRogueNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) { + actionNodeFactories.Add(new GenericRogueNonCombatStrategyActionNodeFactory()); +} + void GenericRogueNonCombatStrategy::InitTriggers(std::vector& triggers) { NonCombatStrategy::InitTriggers(triggers); diff --git a/src/strategy/rogue/GenericRogueNonCombatStrategy.h b/src/strategy/rogue/GenericRogueNonCombatStrategy.h index 9a482419..a7d2a6c6 100644 --- a/src/strategy/rogue/GenericRogueNonCombatStrategy.h +++ b/src/strategy/rogue/GenericRogueNonCombatStrategy.h @@ -12,7 +12,7 @@ class PlayerbotAI; class GenericRogueNonCombatStrategy : public NonCombatStrategy { public: - GenericRogueNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) { } + GenericRogueNonCombatStrategy(PlayerbotAI* botAI); std::string const getName() override { return "nc"; } void InitTriggers(std::vector& triggers) override; diff --git a/src/strategy/rogue/RogueActions.cpp b/src/strategy/rogue/RogueActions.cpp index e0ece34c..18df897c 100644 --- a/src/strategy/rogue/RogueActions.cpp +++ b/src/strategy/rogue/RogueActions.cpp @@ -51,7 +51,7 @@ bool UseDeadlyPoisonAction::Execute(Event event) { std::vector items; std::string poison_name; for (std::string& suffix: poison_suffixs) { - poison_name = getName() + suffix; + poison_name = "Deadly Poison" + suffix; items = AI_VALUE2(std::vector, "inventory items", poison_name); if (!items.empty()) { break; @@ -70,7 +70,7 @@ bool UseDeadlyPoisonAction::isPossible() { std::vector items; std::string poison_name; for (std::string& suffix: poison_suffixs) { - poison_name = getName() + suffix; + poison_name = "Deadly Poison" + suffix; items = AI_VALUE2(std::vector, "inventory items", poison_name); if (!items.empty()) { break; @@ -84,7 +84,7 @@ bool UseInstantPoisonAction::Execute(Event event) { std::vector items; std::string poison_name; for (std::string& suffix: poison_suffixs) { - poison_name = getName() + suffix; + poison_name = "Instant Poison" + suffix; items = AI_VALUE2(std::vector, "inventory items", poison_name); if (!items.empty()) { break; @@ -102,11 +102,43 @@ bool UseInstantPoisonAction::isPossible() { std::vector items; std::string poison_name; for (std::string& suffix: poison_suffixs) { - poison_name = getName() + suffix; + poison_name = "Instant Poison" + suffix; items = AI_VALUE2(std::vector, "inventory items", poison_name); if (!items.empty()) { break; } } return !items.empty(); -} \ No newline at end of file +} + +bool UseInstantPoisonOffHandAction::Execute(Event event) { + std::vector poison_suffixs = {" IX", " VIII", " VII", " VI", " V", " IV", " III", " II", ""}; + std::vector items; + std::string poison_name; + for (std::string& suffix: poison_suffixs) { + poison_name = "Instant Poison" + suffix; + items = AI_VALUE2(std::vector, "inventory items", poison_name); + if (!items.empty()) { + break; + } + } + if (items.empty()) { + return false; + } + Item* const itemForSpell = bot->GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND ); + return UseItem(*items.begin(), ObjectGuid::Empty, itemForSpell); +} + +bool UseInstantPoisonOffHandAction::isPossible() { + std::vector poison_suffixs = {" IX", " VIII", " VII", " VI", " V", " IV", " III", " II", ""}; + std::vector items; + std::string poison_name; + for (std::string& suffix: poison_suffixs) { + poison_name = "Instant Poison" + suffix; + items = AI_VALUE2(std::vector, "inventory items", poison_name); + if (!items.empty()) { + break; + } + } + return !items.empty(); +} diff --git a/src/strategy/rogue/RogueActions.h b/src/strategy/rogue/RogueActions.h index 4ddff1ce..b6f34972 100644 --- a/src/strategy/rogue/RogueActions.h +++ b/src/strategy/rogue/RogueActions.h @@ -149,6 +149,14 @@ class UseInstantPoisonAction : public UseItemAction virtual bool isPossible() override; }; +class UseInstantPoisonOffHandAction : public UseItemAction +{ + public: + UseInstantPoisonOffHandAction(PlayerbotAI* ai) : UseItemAction(ai, "Instant Poison Off Hand") {} + virtual bool Execute(Event event) override; + virtual bool isPossible() override; +}; + class FanOfKnivesAction : public CastMeleeSpellAction { public: diff --git a/src/strategy/rogue/RogueAiObjectContext.cpp b/src/strategy/rogue/RogueAiObjectContext.cpp index cdb6792e..469ab00e 100644 --- a/src/strategy/rogue/RogueAiObjectContext.cpp +++ b/src/strategy/rogue/RogueAiObjectContext.cpp @@ -133,6 +133,7 @@ class RogueAiObjectContextInternal : public NamedObjectContext creators["tricks of the trade on main tank"] = &RogueAiObjectContextInternal::tricks_of_the_trade_on_main_tank; creators["use instant poison on main hand"] = &RogueAiObjectContextInternal::use_instant_poison; creators["use deadly poison on off hand"] = &RogueAiObjectContextInternal::use_deadly_poison; + creators["use instant poison on off hand"] = &RogueAiObjectContextInternal::use_instant_poison_off_hand; creators["fan of knives"] = &RogueAiObjectContextInternal::fan_of_knives; creators["killing spree"] = &RogueAiObjectContextInternal::killing_spree; } @@ -169,6 +170,7 @@ class RogueAiObjectContextInternal : public NamedObjectContext static Action* tricks_of_the_trade_on_main_tank(PlayerbotAI* ai) { return new CastTricksOfTheTradeOnMainTankAction(ai); } static Action* use_instant_poison(PlayerbotAI* ai) { return new UseInstantPoisonAction(ai); } static Action* use_deadly_poison(PlayerbotAI* ai) { return new UseDeadlyPoisonAction(ai); } + static Action* use_instant_poison_off_hand(PlayerbotAI* ai) { return new UseInstantPoisonOffHandAction(ai); } static Action* fan_of_knives(PlayerbotAI* ai) { return new FanOfKnivesAction(ai); } static Action* killing_spree(PlayerbotAI* ai) { return new CastKillingSpreeAction(ai); } };