From 7d7edbd961a65dc0a568cc956dce7b58956b2440 Mon Sep 17 00:00:00 2001 From: ThePenguinMan96 Date: Wed, 23 Jul 2025 11:26:55 -0700 Subject: [PATCH 1/3] Warlock Soul Shard/Soulstone ID conversion Hello everyone, I'm still working on fixing issue #1439 , and I have a theory - it could be because the clients that are having the issue are not english, and the code currently checks for strings "soul shard" and "soulstone". This PR converts the check over to the item IDs, so it should work regardless of what client is being used. I tested it myself with the english client and there is functionally no difference than before - but I hope it solves the issue #1439 for the non-english clients and community. --- src/strategy/warlock/WarlockTriggers.cpp | 32 ++++++++++++++++++++++++ src/strategy/warlock/WarlockTriggers.h | 6 ++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/strategy/warlock/WarlockTriggers.cpp b/src/strategy/warlock/WarlockTriggers.cpp index 7f414f2e..e0493e20 100644 --- a/src/strategy/warlock/WarlockTriggers.cpp +++ b/src/strategy/warlock/WarlockTriggers.cpp @@ -7,6 +7,32 @@ #include "GenericTriggers.h" #include "Playerbots.h" +static const uint32 SOUL_SHARD_ITEM_ID = 6265; + +uint32 GetSoulShardCount(Player* bot) +{ + return bot->GetItemCount(SOUL_SHARD_ITEM_ID, false); // false = only bags +} + +// List of all Soulstone item IDs +static const std::vector soulstoneItemIds = { + 5232, // Minor Soulstone + 16892, // Lesser Soulstone + 16893, // Soulstone + 16895, // Greater Soulstone + 16896, // Major Soulstone + 22116, // Master Soulstone + 36895 // Demonic Soulstone +}; + +uint32 GetSoulstoneCount(Player* bot) +{ + uint32 count = 0; + for (uint32 id : soulstoneItemIds) + count += bot->GetItemCount(id, false); // false = only bags + return count; +} + bool SpellstoneTrigger::IsActive() { return BuffTrigger::IsActive() && AI_VALUE2(uint32, "item count", getName()) > 0; } bool FirestoneTrigger::IsActive() { return BuffTrigger::IsActive() && AI_VALUE2(uint32, "item count", getName()) > 0; } @@ -16,6 +42,12 @@ bool WarlockConjuredItemTrigger::IsActive() return ItemCountTrigger::IsActive() && AI_VALUE2(uint32, "item count", "soul shard") > 0; } +bool OutOfSoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot()) == 0; } + +bool TooManySoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot()) >= 6; } + +bool HasSoulstoneTrigger::IsActive() { return GetSoulstoneCount(botAI->GetBot()) == 0; } + // Checks if the target marked with the moon icon can be banished bool BanishTrigger::IsActive() { diff --git a/src/strategy/warlock/WarlockTriggers.h b/src/strategy/warlock/WarlockTriggers.h index ca85a999..3a448973 100644 --- a/src/strategy/warlock/WarlockTriggers.h +++ b/src/strategy/warlock/WarlockTriggers.h @@ -34,14 +34,14 @@ class OutOfSoulShardsTrigger : public Trigger { public: OutOfSoulShardsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soul shard", 2) {} - bool IsActive() override { return AI_VALUE2(uint32, "item count", "soul shard") == 0; } + bool IsActive() override; }; 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; } + bool IsActive() override; }; class FirestoneTrigger : public BuffTrigger @@ -62,7 +62,7 @@ class HasSoulstoneTrigger : public Trigger { public: HasSoulstoneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soulstone") {} - bool IsActive() override { return AI_VALUE2(uint32, "item count", "soulstone") == 0; } + bool IsActive() override; }; class SoulstoneTrigger : public Trigger From 5ac6e8751cbfd0241f8a296b6d742b28d3006a39 Mon Sep 17 00:00:00 2001 From: ThePenguinMan96 Date: Wed, 23 Jul 2025 12:45:02 -0700 Subject: [PATCH 2/3] Bagspace checks This commit is adding checks to the createsoulshard and createsoulstone actions, to check and see if there is enough bagspace to create an item. --- src/strategy/warlock/WarlockActions.cpp | 44 ++++++++++++++++++++++++- src/strategy/warlock/WarlockActions.h | 1 + 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/strategy/warlock/WarlockActions.cpp b/src/strategy/warlock/WarlockActions.cpp index c57a21c2..69f1f335 100644 --- a/src/strategy/warlock/WarlockActions.cpp +++ b/src/strategy/warlock/WarlockActions.cpp @@ -145,9 +145,51 @@ bool CreateSoulShardAction::isUseful() uint32 currentShards = bot->GetItemCount(ITEM_SOUL_SHARD, false); // false = only bags const uint32 SHARD_CAP = 6; // adjust as needed - return currentShards < SHARD_CAP; + // Only allow if under cap AND there is space for a new shard + ItemPosCountVec dest; + uint32 count = 1; + bool hasSpace = (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_SOUL_SHARD, count) == EQUIP_ERR_OK); + + return (currentShards < SHARD_CAP) && hasSpace; } +bool CastCreateSoulstoneAction::isUseful() +{ + Player* bot = botAI->GetBot(); + if (!bot) + return false; + + // List of all Soulstone item IDs + static const std::vector soulstoneIds = { + 5232, // Minor Soulstone + 16892, // Lesser Soulstone + 16893, // Soulstone + 16895, // Greater Soulstone + 16896, // Major Soulstone + 22116, // Master Soulstone + 36895 // Demonic Soulstone + }; + + // Check if the bot already has any soulstone + uint32 currentSoulstones = 0; + for (uint32 id : soulstoneIds) + currentSoulstones += bot->GetItemCount(id, false); // false = only bags + + // Allow only if the bot has no soulstone AND there is space for one + ItemPosCountVec dest; + uint32 count = 1; + bool hasSpace = false; + for (uint32 id : soulstoneIds) + { + if (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count) == EQUIP_ERR_OK) + { + hasSpace = true; + break; + } + } + + return (currentSoulstones == 0) && hasSpace; +} bool DestroySoulShardAction::Execute(Event event) { diff --git a/src/strategy/warlock/WarlockActions.h b/src/strategy/warlock/WarlockActions.h index 69530775..b3b7a3e2 100644 --- a/src/strategy/warlock/WarlockActions.h +++ b/src/strategy/warlock/WarlockActions.h @@ -84,6 +84,7 @@ class CastCreateSoulstoneAction : public CastBuffSpellAction { public: CastCreateSoulstoneAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "create soulstone") {} + bool isUseful() override; }; class UseSoulstoneSelfAction : public UseSpellItemAction From a33bb3b51effd0e311c71e17981b747eab9b9458 Mon Sep 17 00:00:00 2001 From: ThePenguinMan96 Date: Fri, 25 Jul 2025 14:02:20 -0700 Subject: [PATCH 3/3] Changes requested Updating based on changes requested for commit --- src/strategy/warlock/WarlockActions.cpp | 25 ++++++++----------- .../warlock/WarlockAiObjectContext.cpp | 4 +-- src/strategy/warlock/WarlockTriggers.cpp | 2 +- src/strategy/warlock/WarlockTriggers.h | 4 +-- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/strategy/warlock/WarlockActions.cpp b/src/strategy/warlock/WarlockActions.cpp index 69f1f335..b3b57871 100644 --- a/src/strategy/warlock/WarlockActions.cpp +++ b/src/strategy/warlock/WarlockActions.cpp @@ -171,24 +171,21 @@ bool CastCreateSoulstoneAction::isUseful() }; // Check if the bot already has any soulstone - uint32 currentSoulstones = 0; - for (uint32 id : soulstoneIds) - currentSoulstones += bot->GetItemCount(id, false); // false = only bags - - // Allow only if the bot has no soulstone AND there is space for one - ItemPosCountVec dest; - uint32 count = 1; - bool hasSpace = false; for (uint32 id : soulstoneIds) { - if (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count) == EQUIP_ERR_OK) - { - hasSpace = true; - break; - } + if (bot->GetItemCount(id, false) > 0) + return false; // Already has a soulstone } - return (currentSoulstones == 0) && hasSpace; + // Only need to check one soulstone type for bag space (usually the highest-tier) + ItemPosCountVec dest; + uint32 count = 1; + // Use the last in the list (highest tier) + uint32 soulstoneToCreate = soulstoneIds.back(); + + bool hasSpace = (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, soulstoneToCreate, count) == EQUIP_ERR_OK); + + return hasSpace; } bool DestroySoulShardAction::Execute(Event event) diff --git a/src/strategy/warlock/WarlockAiObjectContext.cpp b/src/strategy/warlock/WarlockAiObjectContext.cpp index 155ded9f..840ee8cd 100644 --- a/src/strategy/warlock/WarlockAiObjectContext.cpp +++ b/src/strategy/warlock/WarlockAiObjectContext.cpp @@ -137,7 +137,7 @@ public: creators["no healthstone"] = &WarlockTriggerFactoryInternal::HasHealthstone; creators["no firestone"] = &WarlockTriggerFactoryInternal::HasFirestone; creators["no spellstone"] = &WarlockTriggerFactoryInternal::HasSpellstone; - creators["no soulstone"] = &WarlockTriggerFactoryInternal::HasSoulstone; + creators["no soulstone"] = &WarlockTriggerFactoryInternal::OutOfSoulstone; creators["firestone"] = &WarlockTriggerFactoryInternal::firestone; creators["spellstone"] = &WarlockTriggerFactoryInternal::spellstone; creators["soulstone"] = &WarlockTriggerFactoryInternal::soulstone; @@ -181,7 +181,7 @@ private: 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); } - static Trigger* HasSoulstone(PlayerbotAI* botAI) { return new HasSoulstoneTrigger(botAI); } + static Trigger* OutOfSoulstone(PlayerbotAI* botAI) { return new OutOfSoulstoneTrigger(botAI); } static Trigger* firestone(PlayerbotAI* botAI) { return new FirestoneTrigger(botAI); } static Trigger* spellstone(PlayerbotAI* botAI) { return new SpellstoneTrigger(botAI); } static Trigger* soulstone(PlayerbotAI* botAI) { return new SoulstoneTrigger(botAI); } diff --git a/src/strategy/warlock/WarlockTriggers.cpp b/src/strategy/warlock/WarlockTriggers.cpp index e0493e20..b9794935 100644 --- a/src/strategy/warlock/WarlockTriggers.cpp +++ b/src/strategy/warlock/WarlockTriggers.cpp @@ -46,7 +46,7 @@ bool OutOfSoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot bool TooManySoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot()) >= 6; } -bool HasSoulstoneTrigger::IsActive() { return GetSoulstoneCount(botAI->GetBot()) == 0; } +bool OutOfSoulstoneTrigger::IsActive() { return GetSoulstoneCount(botAI->GetBot()) == 0; } // Checks if the target marked with the moon icon can be banished bool BanishTrigger::IsActive() diff --git a/src/strategy/warlock/WarlockTriggers.h b/src/strategy/warlock/WarlockTriggers.h index 3a448973..e5ce9ad1 100644 --- a/src/strategy/warlock/WarlockTriggers.h +++ b/src/strategy/warlock/WarlockTriggers.h @@ -58,10 +58,10 @@ public: bool IsActive() override; }; -class HasSoulstoneTrigger : public Trigger +class OutOfSoulstoneTrigger : public Trigger { public: - HasSoulstoneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soulstone") {} + OutOfSoulstoneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soulstone") {} bool IsActive() override; };