From cc6f6c2c3ae7f0e286bde1767d2cef0db69c8a98 Mon Sep 17 00:00:00 2001 From: kadeshar Date: Sat, 2 May 2026 21:19:37 +0200 Subject: [PATCH] Thorns reapply fix (#2338) ## Pull Request Description Allowed druid cast Thorns on target which already have Thorns on him to extend duration. Related with: #2290 ## How to Test the Changes 1. Invite 2 bot (one of them must be druid which can cast thorns) 2. Select second bot and use commad `cast thorns` 3. Wait until buff timer decrease 4. Use again same command 5. Druid should cast spell ## Impact Assessment - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [x] No, not at all - - [ ] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) - Does this change modify default bot behavior? - - [x] No - - [ ] Yes (**explain why**) - Does this change add new decision branches or increase maintenance complexity? - - [x] No - - [ ] Yes (**explain below**) ## AI Assistance Was AI assistance used while working on this change? - - [ ] No - - [x] Yes (**explain below**) To understand reason. ## Final Checklist - - [x] Stability is not compromised. - - [x] Performance impact is understood, tested, and acceptable. - - [x] Added logic complexity is justified and explained. - - [x] Any new bot dialogue lines are translated. - - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers --- src/Ai/Class/Druid/Action/DruidActions.cpp | 31 ++++++++++++++++++++++ src/Ai/Class/Druid/Action/DruidActions.h | 6 +++++ 2 files changed, 37 insertions(+) diff --git a/src/Ai/Class/Druid/Action/DruidActions.cpp b/src/Ai/Class/Druid/Action/DruidActions.cpp index 2eb809480..c01cc4342 100644 --- a/src/Ai/Class/Druid/Action/DruidActions.cpp +++ b/src/Ai/Class/Druid/Action/DruidActions.cpp @@ -11,6 +11,22 @@ #include "AoeValues.h" #include "TargetValue.h" +namespace +{ + bool PrepareThornsTarget(PlayerbotAI* botAI, Unit* target) + { + if (!target) + return false; + + Aura* existingThorns = botAI->GetAura("thorns", target, true); + if (!existingThorns) + return true; + + target->RemoveOwnedAura(existingThorns, AURA_REMOVE_BY_CANCEL); + return true; + } +} + std::vector CastAbolishPoisonAction::getAlternatives() { return NextAction::merge({ NextAction("cure poison") }, @@ -33,6 +49,21 @@ bool CastLifebloomOnMainTankAction::isUseful() return !lifebloom || lifebloom->GetStackAmount() < 3 || lifebloom->GetDuration() < 2000; } +bool CastThornsAction::Execute(Event event) +{ + return PrepareThornsTarget(botAI, GetTarget()) && CastBuffSpellAction::Execute(event); +} + +bool CastThornsOnPartyAction::Execute(Event event) +{ + return PrepareThornsTarget(botAI, GetTarget()) && BuffOnPartyAction::Execute(event); +} + +bool CastThornsOnMainTankAction::Execute(Event event) +{ + return PrepareThornsTarget(botAI, GetTarget()) && BuffOnMainTankAction::Execute(event); +} + Value* CastEntanglingRootsCcAction::GetTargetValue() { return context->GetValue("cc target", "entangling roots"); diff --git a/src/Ai/Class/Druid/Action/DruidActions.h b/src/Ai/Class/Druid/Action/DruidActions.h index 016c3dfc4..7e02a985f 100644 --- a/src/Ai/Class/Druid/Action/DruidActions.h +++ b/src/Ai/Class/Druid/Action/DruidActions.h @@ -114,18 +114,24 @@ class CastThornsAction : public CastBuffSpellAction { public: CastThornsAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "thorns") {} + + bool Execute(Event event) override; }; class CastThornsOnPartyAction : public BuffOnPartyAction { public: CastThornsOnPartyAction(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, "thorns") {} + + bool Execute(Event event) override; }; class CastThornsOnMainTankAction : public BuffOnMainTankAction { public: CastThornsOnMainTankAction(PlayerbotAI* botAI) : BuffOnMainTankAction(botAI, "thorns", false) {} + + bool Execute(Event event) override; }; class CastLifebloomOnMainTankAction : public BuffOnMainTankAction