From ca0dafd67b0e97e52edc12016de22a03c50c6219 Mon Sep 17 00:00:00 2001 From: Spargel Date: Sun, 21 Sep 2025 21:17:53 -0500 Subject: [PATCH 1/8] Fix SetTotemAction Add isUseful and check array size instead of pointer size --- src/strategy/shaman/ShamanActions.cpp | 28 +++++++++++++++++-- src/strategy/shaman/ShamanActions.h | 40 ++++++++++++++------------- 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/src/strategy/shaman/ShamanActions.cpp b/src/strategy/shaman/ShamanActions.cpp index dbb83a0c..5d5eff81 100644 --- a/src/strategy/shaman/ShamanActions.cpp +++ b/src/strategy/shaman/ShamanActions.cpp @@ -93,10 +93,8 @@ bool CastSpiritWalkAction::Execute(Event event) bool SetTotemAction::Execute(Event event) { - size_t spellIdsCount = sizeof(totemSpellIds) / sizeof(uint32); - uint32 totemSpell = 0; - for (int i = spellIdsCount - 1; i >= 0; --i) + for (int i = (int)totemSpellIdsCount - 1; i >= 0; --i) { if (bot->HasSpell(totemSpellIds[i])) { @@ -109,3 +107,27 @@ bool SetTotemAction::Execute(Event event) bot->addActionButton(actionButtonId, totemSpell, ACTION_BUTTON_SPELL); return true; } + +bool SetTotemAction::isUseful() +{ + Player* bot = botAI->GetBot(); + ActionButton const* button = bot->GetActionButton(actionButtonId); + if (!button || button->GetType() != ACTION_BUTTON_SPELL || button->GetAction() == 0) + return true; // No totem assigned + + // Find the highest rank the bot knows + uint32 highestKnown = 0; + for (int i = (int)totemSpellIdsCount - 1; i >= 0; --i) + { + if (bot->HasSpell(totemSpellIds[i])) + { + highestKnown = totemSpellIds[i]; + break; + } + } + if (!highestKnown) + return false; // Bot doesn't know any valid rank + + // Only consider the bar set if the highest rank is assigned + return button->GetAction() != highestKnown; +} diff --git a/src/strategy/shaman/ShamanActions.h b/src/strategy/shaman/ShamanActions.h index 4d64bb1d..a3d57102 100644 --- a/src/strategy/shaman/ShamanActions.h +++ b/src/strategy/shaman/ShamanActions.h @@ -531,12 +531,14 @@ public: class SetTotemAction : public Action { public: - SetTotemAction(PlayerbotAI* botAI, std::string const totemName, const uint32 totemSpellIds[], int actionButtonId) - : Action(botAI, "set " + totemName), totemSpellIds(totemSpellIds), actionButtonId(actionButtonId) + SetTotemAction(PlayerbotAI* botAI, std::string const totemName, const uint32 totemSpellIds[], size_t totemSpellIdsCount, int actionButtonId) + : Action(botAI, "set " + totemName), totemSpellIds(totemSpellIds), totemSpellIdsCount(totemSpellIdsCount), actionButtonId(actionButtonId) { } bool Execute(Event event) override; + bool isUseful() override; uint32 const* totemSpellIds; + size_t totemSpellIdsCount; int actionButtonId; }; @@ -544,119 +546,119 @@ class SetStrengthOfEarthTotemAction : public SetTotemAction { public: SetStrengthOfEarthTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "strength of earth totem", STRENGTH_OF_EARTH_TOTEM, TOTEM_BAR_SLOT_EARTH) {} + : SetTotemAction(ai, "strength of earth totem", STRENGTH_OF_EARTH_TOTEM, sizeof(STRENGTH_OF_EARTH_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_EARTH) {} }; class SetStoneskinTotemAction : public SetTotemAction { public: SetStoneskinTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "stoneskin totem", STONESKIN_TOTEM, TOTEM_BAR_SLOT_EARTH) {} + : SetTotemAction(ai, "stoneskin totem", STONESKIN_TOTEM, sizeof(STONESKIN_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_EARTH) {} }; class SetTremorTotemAction : public SetTotemAction { public: SetTremorTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "tremor totem", TREMOR_TOTEM, TOTEM_BAR_SLOT_EARTH) {} + : SetTotemAction(ai, "tremor totem", TREMOR_TOTEM, sizeof(TREMOR_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_EARTH) {} }; class SetEarthbindTotemAction : public SetTotemAction { public: SetEarthbindTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "earthbind totem", EARTHBIND_TOTEM, TOTEM_BAR_SLOT_EARTH) {} + : SetTotemAction(ai, "earthbind totem", EARTHBIND_TOTEM, sizeof(EARTHBIND_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_EARTH) {} }; class SetSearingTotemAction : public SetTotemAction { public: SetSearingTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "searing totem", SEARING_TOTEM, TOTEM_BAR_SLOT_FIRE) {} + : SetTotemAction(ai, "searing totem", SEARING_TOTEM, sizeof(SEARING_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_FIRE) {} }; class SetMagmaTotemAction : public SetTotemAction { public: SetMagmaTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "magma totem", MAGMA_TOTEM, TOTEM_BAR_SLOT_FIRE) {} + : SetTotemAction(ai, "magma totem", MAGMA_TOTEM, sizeof(MAGMA_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_FIRE) {} }; class SetFlametongueTotemAction : public SetTotemAction { public: SetFlametongueTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "flametongue totem", FLAMETONGUE_TOTEM, TOTEM_BAR_SLOT_FIRE) {} + : SetTotemAction(ai, "flametongue totem", FLAMETONGUE_TOTEM, sizeof(FLAMETONGUE_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_FIRE) {} }; class SetTotemOfWrathAction : public SetTotemAction { public: SetTotemOfWrathAction(PlayerbotAI* ai) - : SetTotemAction(ai, "totem of wrath", TOTEM_OF_WRATH, TOTEM_BAR_SLOT_FIRE) {} + : SetTotemAction(ai, "totem of wrath", TOTEM_OF_WRATH, sizeof(TOTEM_OF_WRATH)/sizeof(uint32), TOTEM_BAR_SLOT_FIRE) {} }; class SetFrostResistanceTotemAction : public SetTotemAction { public: SetFrostResistanceTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "frost resistance totem", FROST_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_FIRE) {} + : SetTotemAction(ai, "frost resistance totem", FROST_RESISTANCE_TOTEM, sizeof(FROST_RESISTANCE_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_FIRE) {} }; class SetHealingStreamTotemAction : public SetTotemAction { public: SetHealingStreamTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "healing stream totem", HEALING_STREAM_TOTEM, TOTEM_BAR_SLOT_WATER) {} + : SetTotemAction(ai, "healing stream totem", HEALING_STREAM_TOTEM, sizeof(HEALING_STREAM_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_WATER) {} }; class SetManaSpringTotemAction : public SetTotemAction { public: SetManaSpringTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "mana spring totem", MANA_SPRING_TOTEM, TOTEM_BAR_SLOT_WATER) {} + : SetTotemAction(ai, "mana spring totem", MANA_SPRING_TOTEM, sizeof(MANA_SPRING_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_WATER) {} }; class SetCleansingTotemAction : public SetTotemAction { public: SetCleansingTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "cleansing totem", CLEANSING_TOTEM, TOTEM_BAR_SLOT_WATER) {} + : SetTotemAction(ai, "cleansing totem", CLEANSING_TOTEM, sizeof(CLEANSING_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_WATER) {} }; class SetFireResistanceTotemAction : public SetTotemAction { public: SetFireResistanceTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "fire resistance totem", FIRE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_WATER) {} + : SetTotemAction(ai, "fire resistance totem", FIRE_RESISTANCE_TOTEM, sizeof(FIRE_RESISTANCE_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_WATER) {} }; class SetWrathOfAirTotemAction : public SetTotemAction { public: SetWrathOfAirTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "wrath of air totem", WRATH_OF_AIR_TOTEM, TOTEM_BAR_SLOT_AIR) {} + : SetTotemAction(ai, "wrath of air totem", WRATH_OF_AIR_TOTEM, sizeof(WRATH_OF_AIR_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_AIR) {} }; class SetWindfuryTotemAction : public SetTotemAction { public: SetWindfuryTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "windfury totem", WINDFURY_TOTEM, TOTEM_BAR_SLOT_AIR) {} + : SetTotemAction(ai, "windfury totem", WINDFURY_TOTEM, sizeof(WINDFURY_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_AIR) {} }; class SetNatureResistanceTotemAction : public SetTotemAction { public: SetNatureResistanceTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "nature resistance totem", NATURE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_AIR) {} + : SetTotemAction(ai, "nature resistance totem", NATURE_RESISTANCE_TOTEM, sizeof(NATURE_RESISTANCE_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_AIR) {} }; class SetGroundingTotemAction : public SetTotemAction { public: SetGroundingTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "grounding totem", GROUNDING_TOTEM, TOTEM_BAR_SLOT_AIR) {} + : SetTotemAction(ai, "grounding totem", GROUNDING_TOTEM, sizeof(GROUNDING_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_AIR) {} }; #endif From f35e39e19c075cd998902d7d928e561814cfe722 Mon Sep 17 00:00:00 2001 From: Spargel Date: Mon, 22 Sep 2025 03:00:29 -0500 Subject: [PATCH 2/8] Removing unnecessary variable --- src/strategy/shaman/ShamanActions.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/strategy/shaman/ShamanActions.cpp b/src/strategy/shaman/ShamanActions.cpp index 5d5eff81..c1cacad9 100644 --- a/src/strategy/shaman/ShamanActions.cpp +++ b/src/strategy/shaman/ShamanActions.cpp @@ -116,18 +116,11 @@ bool SetTotemAction::isUseful() return true; // No totem assigned // Find the highest rank the bot knows - uint32 highestKnown = 0; for (int i = (int)totemSpellIdsCount - 1; i >= 0; --i) { if (bot->HasSpell(totemSpellIds[i])) - { - highestKnown = totemSpellIds[i]; - break; - } + return button->GetAction() != totemSpellIds[i]; } - if (!highestKnown) - return false; // Bot doesn't know any valid rank - - // Only consider the bar set if the highest rank is assigned - return button->GetAction() != highestKnown; + // Bot doesn't know any valid rank + return false; } From 01f0b71a172d5535a7d5755b897b19fbb4c76d16 Mon Sep 17 00:00:00 2001 From: kadeshar Date: Thu, 25 Sep 2025 20:31:42 +0200 Subject: [PATCH 3/8] - Code refactoring --- src/strategy/shaman/ShamanActions.cpp | 20 ++----------- src/strategy/shaman/ShamanActions.h | 40 ++++++++++++-------------- src/strategy/shaman/ShamanTriggers.cpp | 11 ++++--- 3 files changed, 28 insertions(+), 43 deletions(-) diff --git a/src/strategy/shaman/ShamanActions.cpp b/src/strategy/shaman/ShamanActions.cpp index c1cacad9..83e915da 100644 --- a/src/strategy/shaman/ShamanActions.cpp +++ b/src/strategy/shaman/ShamanActions.cpp @@ -93,8 +93,9 @@ bool CastSpiritWalkAction::Execute(Event event) bool SetTotemAction::Execute(Event event) { + size_t spellIdsCount = sizeof(totemSpellIds) / sizeof(uint32); uint32 totemSpell = 0; - for (int i = (int)totemSpellIdsCount - 1; i >= 0; --i) + for (int i = (int)spellIdsCount - 1; i >= 0; --i) { if (bot->HasSpell(totemSpellIds[i])) { @@ -107,20 +108,3 @@ bool SetTotemAction::Execute(Event event) bot->addActionButton(actionButtonId, totemSpell, ACTION_BUTTON_SPELL); return true; } - -bool SetTotemAction::isUseful() -{ - Player* bot = botAI->GetBot(); - ActionButton const* button = bot->GetActionButton(actionButtonId); - if (!button || button->GetType() != ACTION_BUTTON_SPELL || button->GetAction() == 0) - return true; // No totem assigned - - // Find the highest rank the bot knows - for (int i = (int)totemSpellIdsCount - 1; i >= 0; --i) - { - if (bot->HasSpell(totemSpellIds[i])) - return button->GetAction() != totemSpellIds[i]; - } - // Bot doesn't know any valid rank - return false; -} diff --git a/src/strategy/shaman/ShamanActions.h b/src/strategy/shaman/ShamanActions.h index a3d57102..4d64bb1d 100644 --- a/src/strategy/shaman/ShamanActions.h +++ b/src/strategy/shaman/ShamanActions.h @@ -531,14 +531,12 @@ public: class SetTotemAction : public Action { public: - SetTotemAction(PlayerbotAI* botAI, std::string const totemName, const uint32 totemSpellIds[], size_t totemSpellIdsCount, int actionButtonId) - : Action(botAI, "set " + totemName), totemSpellIds(totemSpellIds), totemSpellIdsCount(totemSpellIdsCount), actionButtonId(actionButtonId) + SetTotemAction(PlayerbotAI* botAI, std::string const totemName, const uint32 totemSpellIds[], int actionButtonId) + : Action(botAI, "set " + totemName), totemSpellIds(totemSpellIds), actionButtonId(actionButtonId) { } bool Execute(Event event) override; - bool isUseful() override; uint32 const* totemSpellIds; - size_t totemSpellIdsCount; int actionButtonId; }; @@ -546,119 +544,119 @@ class SetStrengthOfEarthTotemAction : public SetTotemAction { public: SetStrengthOfEarthTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "strength of earth totem", STRENGTH_OF_EARTH_TOTEM, sizeof(STRENGTH_OF_EARTH_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_EARTH) {} + : SetTotemAction(ai, "strength of earth totem", STRENGTH_OF_EARTH_TOTEM, TOTEM_BAR_SLOT_EARTH) {} }; class SetStoneskinTotemAction : public SetTotemAction { public: SetStoneskinTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "stoneskin totem", STONESKIN_TOTEM, sizeof(STONESKIN_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_EARTH) {} + : SetTotemAction(ai, "stoneskin totem", STONESKIN_TOTEM, TOTEM_BAR_SLOT_EARTH) {} }; class SetTremorTotemAction : public SetTotemAction { public: SetTremorTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "tremor totem", TREMOR_TOTEM, sizeof(TREMOR_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_EARTH) {} + : SetTotemAction(ai, "tremor totem", TREMOR_TOTEM, TOTEM_BAR_SLOT_EARTH) {} }; class SetEarthbindTotemAction : public SetTotemAction { public: SetEarthbindTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "earthbind totem", EARTHBIND_TOTEM, sizeof(EARTHBIND_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_EARTH) {} + : SetTotemAction(ai, "earthbind totem", EARTHBIND_TOTEM, TOTEM_BAR_SLOT_EARTH) {} }; class SetSearingTotemAction : public SetTotemAction { public: SetSearingTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "searing totem", SEARING_TOTEM, sizeof(SEARING_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_FIRE) {} + : SetTotemAction(ai, "searing totem", SEARING_TOTEM, TOTEM_BAR_SLOT_FIRE) {} }; class SetMagmaTotemAction : public SetTotemAction { public: SetMagmaTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "magma totem", MAGMA_TOTEM, sizeof(MAGMA_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_FIRE) {} + : SetTotemAction(ai, "magma totem", MAGMA_TOTEM, TOTEM_BAR_SLOT_FIRE) {} }; class SetFlametongueTotemAction : public SetTotemAction { public: SetFlametongueTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "flametongue totem", FLAMETONGUE_TOTEM, sizeof(FLAMETONGUE_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_FIRE) {} + : SetTotemAction(ai, "flametongue totem", FLAMETONGUE_TOTEM, TOTEM_BAR_SLOT_FIRE) {} }; class SetTotemOfWrathAction : public SetTotemAction { public: SetTotemOfWrathAction(PlayerbotAI* ai) - : SetTotemAction(ai, "totem of wrath", TOTEM_OF_WRATH, sizeof(TOTEM_OF_WRATH)/sizeof(uint32), TOTEM_BAR_SLOT_FIRE) {} + : SetTotemAction(ai, "totem of wrath", TOTEM_OF_WRATH, TOTEM_BAR_SLOT_FIRE) {} }; class SetFrostResistanceTotemAction : public SetTotemAction { public: SetFrostResistanceTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "frost resistance totem", FROST_RESISTANCE_TOTEM, sizeof(FROST_RESISTANCE_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_FIRE) {} + : SetTotemAction(ai, "frost resistance totem", FROST_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_FIRE) {} }; class SetHealingStreamTotemAction : public SetTotemAction { public: SetHealingStreamTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "healing stream totem", HEALING_STREAM_TOTEM, sizeof(HEALING_STREAM_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_WATER) {} + : SetTotemAction(ai, "healing stream totem", HEALING_STREAM_TOTEM, TOTEM_BAR_SLOT_WATER) {} }; class SetManaSpringTotemAction : public SetTotemAction { public: SetManaSpringTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "mana spring totem", MANA_SPRING_TOTEM, sizeof(MANA_SPRING_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_WATER) {} + : SetTotemAction(ai, "mana spring totem", MANA_SPRING_TOTEM, TOTEM_BAR_SLOT_WATER) {} }; class SetCleansingTotemAction : public SetTotemAction { public: SetCleansingTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "cleansing totem", CLEANSING_TOTEM, sizeof(CLEANSING_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_WATER) {} + : SetTotemAction(ai, "cleansing totem", CLEANSING_TOTEM, TOTEM_BAR_SLOT_WATER) {} }; class SetFireResistanceTotemAction : public SetTotemAction { public: SetFireResistanceTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "fire resistance totem", FIRE_RESISTANCE_TOTEM, sizeof(FIRE_RESISTANCE_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_WATER) {} + : SetTotemAction(ai, "fire resistance totem", FIRE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_WATER) {} }; class SetWrathOfAirTotemAction : public SetTotemAction { public: SetWrathOfAirTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "wrath of air totem", WRATH_OF_AIR_TOTEM, sizeof(WRATH_OF_AIR_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_AIR) {} + : SetTotemAction(ai, "wrath of air totem", WRATH_OF_AIR_TOTEM, TOTEM_BAR_SLOT_AIR) {} }; class SetWindfuryTotemAction : public SetTotemAction { public: SetWindfuryTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "windfury totem", WINDFURY_TOTEM, sizeof(WINDFURY_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_AIR) {} + : SetTotemAction(ai, "windfury totem", WINDFURY_TOTEM, TOTEM_BAR_SLOT_AIR) {} }; class SetNatureResistanceTotemAction : public SetTotemAction { public: SetNatureResistanceTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "nature resistance totem", NATURE_RESISTANCE_TOTEM, sizeof(NATURE_RESISTANCE_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_AIR) {} + : SetTotemAction(ai, "nature resistance totem", NATURE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_AIR) {} }; class SetGroundingTotemAction : public SetTotemAction { public: SetGroundingTotemAction(PlayerbotAI* ai) - : SetTotemAction(ai, "grounding totem", GROUNDING_TOTEM, sizeof(GROUNDING_TOTEM)/sizeof(uint32), TOTEM_BAR_SLOT_AIR) {} + : SetTotemAction(ai, "grounding totem", GROUNDING_TOTEM, TOTEM_BAR_SLOT_AIR) {} }; #endif diff --git a/src/strategy/shaman/ShamanTriggers.cpp b/src/strategy/shaman/ShamanTriggers.cpp index 35afbea1..225289e7 100644 --- a/src/strategy/shaman/ShamanTriggers.cpp +++ b/src/strategy/shaman/ShamanTriggers.cpp @@ -432,12 +432,15 @@ bool SetTotemTrigger::IsActive() return true; size_t totemSpellIdsCount = sizeof(totemSpellIds) / sizeof(uint32); - for (size_t i = 0; i < totemSpellIdsCount; ++i) + for (int i = (int)totemSpellIdsCount - 1; i >= 0; --i) + { - if (button->GetAction() == totemSpellIds[i]) + if (bot->HasSpell(totemSpellIds[i])) + { - return false; + return button->GetAction() != totemSpellIds[i]; } } - return true; + + return false; } From f23b2ea2f6e3a52d80e658ac45d141a3c3bfa0e7 Mon Sep 17 00:00:00 2001 From: Gonzalo Date: Sat, 27 Sep 2025 08:06:16 -0300 Subject: [PATCH 4/8] fix: Optimize DrinkAction to check mana in isUseful instead of Execute (#1666) * fix: Optimize DrinkAction to check mana in isUseful instead of Execute - Move HasManaValue check from Execute to isUseful for better performance - Prevents non-mana classes from executing drink actions unnecessarily - Improves AI efficiency by early filtering in isUseful method Addresses reviewer feedback about HasManaValue usage optimization * Update NonCombatActions.cpp --------- Co-authored-by: bash <31279994+hermensbas@users.noreply.github.com> --- src/strategy/actions/NonCombatActions.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/strategy/actions/NonCombatActions.cpp b/src/strategy/actions/NonCombatActions.cpp index d3c49dec..262e0f20 100644 --- a/src/strategy/actions/NonCombatActions.cpp +++ b/src/strategy/actions/NonCombatActions.cpp @@ -13,10 +13,6 @@ bool DrinkAction::Execute(Event event) if (bot->IsInCombat()) return false; - bool hasMana = AI_VALUE2(bool, "has mana", "self target"); - if (!hasMana) - return false; - if (botAI->HasCheat(BotCheatMask::food)) { // if (bot->IsNonMeleeSpellCast(true)) @@ -54,7 +50,14 @@ bool DrinkAction::Execute(Event event) return UseItemAction::Execute(event); } -bool DrinkAction::isUseful() { return UseItemAction::isUseful() && AI_VALUE2(uint8, "mana", "self target") < 100; } +bool DrinkAction::isUseful() +{ + // check class uses mana + if (!AI_VALUE2(bool, "has mana", "self target")) + return false; + + return UseItemAction::isUseful() && AI_VALUE2(uint8, "mana", "self target") < 100; +} bool DrinkAction::isPossible() { From f5a6194808f5b8c6029d6aa6ed7af8de405d6837 Mon Sep 17 00:00:00 2001 From: Crow Date: Sat, 27 Sep 2025 13:31:06 -0500 Subject: [PATCH 5/8] Fixed some comments in the config (#1668) --- conf/playerbots.conf.dist | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 4e76eb09..b4e715f9 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -519,7 +519,7 @@ AiPlayerbot.AutoGearScoreLimit = 0 # "taxi" (bots may use all flight paths, though they will not actually learn them) # "raid" (bots use cheats implemented into raid strategies) # To use multiple cheats, separate them by commas below (e.g., to enable all, use "gold,health,mana,power,raid,taxi") -# Default: taxi and raid are enabled +# Default: food, taxi, and raid are enabled AiPlayerbot.BotCheats = "food,taxi,raid" # @@ -1603,10 +1603,10 @@ AiPlayerbot.PremadeSpecLink.11.6.80 = 05320021--230033312031500531353013251 # # -# Applies a permanent buff to all bots simulating effects of spells, flasks, food, runes, etc. +# Applies automatically refreshing buffs to bots simulating effects of spells, flasks, food, runes, etc. # Requires sending the command "nc +worldbuff" in chat to a bot (or a group of bots) to enable # Each entry in the matrix should be formatted as follows: Entry:FactionID,ClassID,SpecID,MinimumLevel,MaximumLevel:SpellID1,SpellID2,etc.; -# Use 0 for any field to make it agnostic (e.g., 0 for FactionID means the entry will apply buffs to either faction) +# FactionID may be set to 0 for the entry to apply buffs to bots of either faction # The default entries create a cross-faction list of level 80 buffs for each implemented pve spec from the "Premade Specs" section # The default entries may be deleted or modified, and new custom entries may be added From 0547ce5cf7404097751df62a2d0c71d4c9d5d1e3 Mon Sep 17 00:00:00 2001 From: kadeshar Date: Sat, 27 Sep 2025 20:57:10 +0200 Subject: [PATCH 6/8] - Code optimalizations --- src/strategy/shaman/ShamanActions.cpp | 18 +++++++++++++----- src/strategy/shaman/ShamanTriggers.cpp | 15 ++++++++++----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/strategy/shaman/ShamanActions.cpp b/src/strategy/shaman/ShamanActions.cpp index 83e915da..42f3a8e9 100644 --- a/src/strategy/shaman/ShamanActions.cpp +++ b/src/strategy/shaman/ShamanActions.cpp @@ -93,18 +93,26 @@ bool CastSpiritWalkAction::Execute(Event event) bool SetTotemAction::Execute(Event event) { - size_t spellIdsCount = sizeof(totemSpellIds) / sizeof(uint32); + const size_t spellIdsCount = sizeof(totemSpellIds) / sizeof(uint32); + if (spellIdsCount == 0) + return false; // early return + uint32 totemSpell = 0; - for (int i = (int)spellIdsCount - 1; i >= 0; --i) + + // Iterate backwards due signed/unsigned int + for (size_t i = spellIdsCount; i-- > 0;) { - if (bot->HasSpell(totemSpellIds[i])) + const uint32 spellId = totemSpellIds[i]; + if (bot->HasSpell(spellId)) { - totemSpell = totemSpellIds[i]; + totemSpell = spellId; break; } } - if (!totemSpell) + + if (totemSpell == 0) return false; + bot->addActionButton(actionButtonId, totemSpell, ACTION_BUTTON_SPELL); return true; } diff --git a/src/strategy/shaman/ShamanTriggers.cpp b/src/strategy/shaman/ShamanTriggers.cpp index 225289e7..cdee870c 100644 --- a/src/strategy/shaman/ShamanTriggers.cpp +++ b/src/strategy/shaman/ShamanTriggers.cpp @@ -424,6 +424,7 @@ bool SetTotemTrigger::IsActive() { if (!bot->HasSpell(SPELL_CALL_OF_THE_ELEMENTS)) return false; + if (!bot->HasSpell(requiredSpellId)) return false; @@ -431,14 +432,18 @@ bool SetTotemTrigger::IsActive() if (!button || button->GetType() != ACTION_BUTTON_SPELL || button->GetAction() == 0) return true; - size_t totemSpellIdsCount = sizeof(totemSpellIds) / sizeof(uint32); - for (int i = (int)totemSpellIdsCount - 1; i >= 0; --i) - + const size_t totemSpellIdsCount = sizeof(totemSpellIds) / sizeof(uint32); + if (totemSpellIdsCount == 0) { - if (bot->HasSpell(totemSpellIds[i])) + return false; + } + for (int i = (int)totemSpellIdsCount - 1; i >= 0; --i) + { + const uint32 spellId = totemSpellIds[i]; + if (bot->HasSpell(spellId)) { - return button->GetAction() != totemSpellIds[i]; + return button->GetAction() != spellId; } } From 662e7f1b0b392df314cb1c52501f01c436ffddb7 Mon Sep 17 00:00:00 2001 From: bash <31279994+hermensbas@users.noreply.github.com> Date: Sat, 27 Sep 2025 23:00:24 +0200 Subject: [PATCH 7/8] Update ShamanActions.cpp --- src/strategy/shaman/ShamanActions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategy/shaman/ShamanActions.cpp b/src/strategy/shaman/ShamanActions.cpp index 42f3a8e9..d4d0f98a 100644 --- a/src/strategy/shaman/ShamanActions.cpp +++ b/src/strategy/shaman/ShamanActions.cpp @@ -99,7 +99,7 @@ bool SetTotemAction::Execute(Event event) uint32 totemSpell = 0; - // Iterate backwards due signed/unsigned int + // Iterate backwards to prioritize the highest-rank totem spell the bot knows for (size_t i = spellIdsCount; i-- > 0;) { const uint32 spellId = totemSpellIds[i]; From 23d9931f65418619ae450e37539f0414b5a13c4e Mon Sep 17 00:00:00 2001 From: avirar Date: Sun, 28 Sep 2025 08:01:24 +1000 Subject: [PATCH 8/8] Resolved crash in BGStatusAction (#1656) * Prevent race condition and server crash * Updated other direct packet handling lines to queue packets instead --- src/strategy/actions/BattleGroundJoinAction.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategy/actions/BattleGroundJoinAction.cpp b/src/strategy/actions/BattleGroundJoinAction.cpp index 1877a5f2..fda822ef 100644 --- a/src/strategy/actions/BattleGroundJoinAction.cpp +++ b/src/strategy/actions/BattleGroundJoinAction.cpp @@ -688,7 +688,7 @@ bool BGLeaveAction::Execute(Event event) WorldPacket packet(CMSG_BATTLEFIELD_PORT, 20); packet << type << unk2 << (uint32)_bgTypeId << unk << uint8(0); - bot->GetSession()->HandleBattleFieldPortOpcode(packet); + bot->GetSession()->QueuePacket(new WorldPacket(packet)); if (IsRandomBot) botAI->SetMaster(nullptr); @@ -917,7 +917,7 @@ bool BGStatusAction::Execute(Event event) WorldPacket packet(CMSG_BATTLEFIELD_PORT, 20); packet << type << unk2 << (uint32)_bgTypeId << unk << action; - bot->GetSession()->HandleBattleFieldPortOpcode(packet); + bot->GetSession()->QueuePacket(new WorldPacket(packet)); botAI->ResetStrategies(false); if (!bot->GetBattleground()) @@ -972,7 +972,7 @@ bool BGStatusAction::Execute(Event event) WorldPacket packet(CMSG_BATTLEFIELD_PORT, 20); action = 0; packet << type << unk2 << (uint32)_bgTypeId << unk << action; - bot->GetSession()->HandleBattleFieldPortOpcode(packet); + bot->GetSession()->QueuePacket(new WorldPacket(packet)); botAI->ResetStrategies(!IsRandomBot); botAI->GetAiObjectContext()->GetValue("bg type")->Set(0); @@ -1039,7 +1039,7 @@ bool BGStatusAction::Execute(Event event) WorldPacket packet(CMSG_BATTLEFIELD_PORT, 20); packet << type << unk2 << (uint32)_bgTypeId << unk << action; - bot->GetSession()->HandleBattleFieldPortOpcode(packet); + bot->GetSession()->QueuePacket(new WorldPacket(packet)); botAI->ResetStrategies(false); if (!bot->GetBattleground())