diff --git a/src/factory/PlayerbotFactory.cpp b/src/factory/PlayerbotFactory.cpp index 2fe6cdfa..02e47b21 100644 --- a/src/factory/PlayerbotFactory.cpp +++ b/src/factory/PlayerbotFactory.cpp @@ -3255,7 +3255,7 @@ void PlayerbotFactory::InitReagents() items.push_back({17030, 40}); // Ankh break; case CLASS_WARLOCK: - items.push_back({6265, 20}); // shard + items.push_back({6265, 5}); // shard break; case CLASS_PRIEST: if (level >= 48 && level < 60) diff --git a/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp b/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp index 88423d90..1e2b89af 100644 --- a/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp +++ b/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp @@ -80,7 +80,8 @@ void GenericWarlockNonCombatStrategy::InitTriggers(std::vector& tr NonCombatStrategy::InitTriggers(triggers); triggers.push_back(new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 60.0f), nullptr))); triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("fel domination", 30.0f), nullptr))); - triggers.push_back(new TriggerNode("no soul shard", NextAction::array(0, new NextAction("create soul shard", 29.5f), nullptr))); + triggers.push_back(new TriggerNode("no soul shard", NextAction::array(0, new NextAction("create soul shard", 60.0f), nullptr))); + triggers.push_back(new TriggerNode("too many soul shards", NextAction::array(0, new NextAction("destroy soul shard", 60.0f), nullptr))); triggers.push_back(new TriggerNode("soul link", NextAction::array(0, new NextAction("soul link", 28.0f), nullptr))); triggers.push_back(new TriggerNode("demon armor", NextAction::array(0, new NextAction("fel armor", 27.0f), nullptr))); triggers.push_back(new TriggerNode("no healthstone", NextAction::array(0, new NextAction("create healthstone", 26.0f), nullptr))); diff --git a/src/strategy/warlock/GenericWarlockStrategy.cpp b/src/strategy/warlock/GenericWarlockStrategy.cpp index 1eb5bdbb..9ad266d4 100644 --- a/src/strategy/warlock/GenericWarlockStrategy.cpp +++ b/src/strategy/warlock/GenericWarlockStrategy.cpp @@ -42,6 +42,7 @@ void GenericWarlockStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode("medium threat", NextAction::array(0, new NextAction("soulshatter", 55.0f), nullptr))); triggers.push_back(new TriggerNode("spell lock", NextAction::array(0, new NextAction("spell lock", 40.0f), nullptr))); triggers.push_back(new TriggerNode("no soul shard", NextAction::array(0, new NextAction("create soul shard", 60.0f), nullptr))); + triggers.push_back(new TriggerNode("too many soul shards", NextAction::array(0, new NextAction("destroy soul shard", 60.0f), nullptr))); triggers.push_back(new TriggerNode("devour magic purge", NextAction::array(0, new NextAction("devour magic purge", 50.0f), nullptr))); triggers.push_back(new TriggerNode("devour magic cleanse", NextAction::array(0, new NextAction("devour magic cleanse", 50.0f), nullptr))); } diff --git a/src/strategy/warlock/WarlockActions.cpp b/src/strategy/warlock/WarlockActions.cpp index 50cb9e83..433adfed 100644 --- a/src/strategy/warlock/WarlockActions.cpp +++ b/src/strategy/warlock/WarlockActions.cpp @@ -135,6 +135,43 @@ bool CreateSoulShardAction::Execute(Event event) return false; } + +bool DestroySoulShardAction::Execute(Event event) +{ + static const uint32 SOUL_SHARD_ID = 6265; + // Look for the first soul shard in any bag and destroy it + for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + if (Bag* pBag = (Bag*)bot->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + { + for (uint32 j = 0; j < pBag->GetBagSize(); ++j) + { + if (Item* pItem = pBag->GetItemByPos(j)) + { + if (pItem->GetTemplate()->ItemId == SOUL_SHARD_ID) + { + bot->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); + return true; // Only destroy one! + } + } + } + } + } + // Also check main inventory slots (not in bags) + for (int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) + { + if (Item* pItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + { + if (pItem->GetTemplate()->ItemId == SOUL_SHARD_ID) + { + bot->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); + return true; + } + } + } + return false; +} + // Checks if the target has a soulstone aura static bool HasSoulstoneAura(Unit* unit) { @@ -322,3 +359,37 @@ bool UseSoulstoneHealerAction::Execute(Event event) bot->SetSelection(healer->GetGUID()); return UseItem(items[0], ObjectGuid::Empty, nullptr, healer); } + +const std::vector CastCreateFirestoneAction::firestoneSpellIds = { + 60220, // Create Firestone (Rank 7) + 27250, // Rank 5 + 17953, // Rank 4 + 17952, // Rank 3 + 17951, // Rank 2 + 6366 // Rank 1 +}; + +CastCreateFirestoneAction::CastCreateFirestoneAction(PlayerbotAI* botAI) + : CastBuffSpellAction(botAI, "create firestone") +{ +} + +bool CastCreateFirestoneAction::Execute(Event event) +{ + for (uint32 spellId : firestoneSpellIds) + { + if (bot->HasSpell(spellId)) + return botAI->CastSpell(spellId, bot); + } + return false; +} + +bool CastCreateFirestoneAction::isUseful() +{ + for (uint32 spellId : firestoneSpellIds) + { + if (bot->HasSpell(spellId)) + return true; + } + return false; +} diff --git a/src/strategy/warlock/WarlockActions.h b/src/strategy/warlock/WarlockActions.h index d87358f7..dbf069a8 100644 --- a/src/strategy/warlock/WarlockActions.h +++ b/src/strategy/warlock/WarlockActions.h @@ -8,6 +8,7 @@ #include "GenericSpellActions.h" #include "UseItemAction.h" +#include "InventoryAction.h" #include "Action.h" class PlayerbotAI; @@ -47,6 +48,14 @@ public: bool Execute(Event event) override; }; +class DestroySoulShardAction : public InventoryAction +{ +public: + DestroySoulShardAction(PlayerbotAI* botAI) : InventoryAction(botAI, "destroy soul shard") {} + + bool Execute(Event event) override; +}; + class CastCreateHealthstoneAction : public CastBuffSpellAction { public: @@ -56,7 +65,12 @@ public: class CastCreateFirestoneAction : public CastBuffSpellAction { public: - CastCreateFirestoneAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "create firestone") {} + CastCreateFirestoneAction(PlayerbotAI* botAI); + bool Execute(Event event) override; + bool isUseful() override; + +private: + static const std::vector firestoneSpellIds; }; class CastCreateSpellstoneAction : public CastBuffSpellAction diff --git a/src/strategy/warlock/WarlockAiObjectContext.cpp b/src/strategy/warlock/WarlockAiObjectContext.cpp index 1fe4bf1e..fa1e895d 100644 --- a/src/strategy/warlock/WarlockAiObjectContext.cpp +++ b/src/strategy/warlock/WarlockAiObjectContext.cpp @@ -138,6 +138,7 @@ public: creators["demon armor"] = &WarlockTriggerFactoryInternal::demon_armor; creators["soul link"] = &WarlockTriggerFactoryInternal::soul_link; creators["no soul shard"] = &WarlockTriggerFactoryInternal::no_soul_shard; + creators["too many soul shards"] = &WarlockTriggerFactoryInternal::too_many_soul_shards; creators["no healthstone"] = &WarlockTriggerFactoryInternal::HasHealthstone; creators["no firestone"] = &WarlockTriggerFactoryInternal::HasFirestone; creators["no spellstone"] = &WarlockTriggerFactoryInternal::HasSpellstone; @@ -181,6 +182,7 @@ private: static Trigger* demon_armor(PlayerbotAI* botAI) { return new DemonArmorTrigger(botAI); } static Trigger* soul_link(PlayerbotAI* botAI) { return new SoulLinkTrigger(botAI); } static Trigger* no_soul_shard(PlayerbotAI* botAI) { return new OutOfSoulShardsTrigger(botAI); } + static Trigger* too_many_soul_shards(PlayerbotAI* botAI) { return new TooManySoulShardsTrigger(botAI); } static Trigger* HasHealthstone(PlayerbotAI* botAI) { return new HasHealthstoneTrigger(botAI); } static Trigger* HasFirestone(PlayerbotAI* botAI) { return new HasFirestoneTrigger(botAI); } static Trigger* HasSpellstone(PlayerbotAI* botAI) { return new HasSpellstoneTrigger(botAI); } @@ -229,6 +231,7 @@ public: creators["demon skin"] = &WarlockAiObjectContextInternal::demon_skin; creators["soul link"] = &WarlockAiObjectContextInternal::soul_link; creators["create soul shard"] = &WarlockAiObjectContextInternal::create_soul_shard; + creators["destroy soul shard"] = &WarlockAiObjectContextInternal::destroy_soul_shard; creators["create healthstone"] = &WarlockAiObjectContextInternal::create_healthstone; creators["create firestone"] = &WarlockAiObjectContextInternal::create_firestone; creators["create spellstone"] = &WarlockAiObjectContextInternal::create_spellstone; @@ -301,6 +304,7 @@ private: static Action* demon_skin(PlayerbotAI* botAI) { return new CastDemonSkinAction(botAI); } static Action* soul_link(PlayerbotAI* botAI) { return new CastSoulLinkAction(botAI); } static Action* create_soul_shard(PlayerbotAI* botAI) { return new CreateSoulShardAction(botAI); } + static Action* destroy_soul_shard(PlayerbotAI* botAI) { return new DestroySoulShardAction(botAI); } static Action* create_healthstone(PlayerbotAI* botAI) { return new CastCreateHealthstoneAction(botAI); } static Action* create_firestone(PlayerbotAI* botAI) { return new CastCreateFirestoneAction(botAI); } static Action* create_spellstone(PlayerbotAI* botAI) { return new CastCreateSpellstoneAction(botAI); } diff --git a/src/strategy/warlock/WarlockTriggers.h b/src/strategy/warlock/WarlockTriggers.h index 04de574a..4dedc218 100644 --- a/src/strategy/warlock/WarlockTriggers.h +++ b/src/strategy/warlock/WarlockTriggers.h @@ -37,6 +37,13 @@ public: bool IsActive() override { return AI_VALUE2(uint32, "item count", "soul shard") == 0; } }; +class TooManySoulShardsTrigger : public Trigger +{ +public: + TooManySoulShardsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "too many soul shards") {} + bool IsActive() override { return AI_VALUE2(uint32, "item count", "soul shard") >= 6; } +}; + class FirestoneTrigger : public BuffTrigger { public: