From 47080d37ec649153193a88dde086404a879e2041 Mon Sep 17 00:00:00 2001 From: Lucas Karsten Date: Fri, 13 Nov 2026 08:56:27 -0300 Subject: [PATCH 1/2] Fix Flamewood's Avenging Flame ignoring the supported skill's totem limit Avenging Flame is cast by the totems of the skill Flamewood supports, but its ActiveTotemLimit was summed from its own mod list. Skill-specific limits (e.g. +N Searing Bond totems from Foulborn The Searing Touch or gem quality) were lost, so "per maximum number of Summoned Totems" and "per Summoned Totem" mods scaled from the wrong count. Use the trigger source's cached limit. --- spec/System/TestTriggers_spec.lua | 21 +++++++++++++++++++++ src/Modules/CalcOffence.lua | 10 +++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/spec/System/TestTriggers_spec.lua b/spec/System/TestTriggers_spec.lua index 72f9ec6e4aa..38d2461fa59 100644 --- a/spec/System/TestTriggers_spec.lua +++ b/spec/System/TestTriggers_spec.lua @@ -1639,4 +1639,25 @@ describe("TestTriggers", function() assert.is_falsy(build.calcsTab.mainEnv.player.mainSkill.skillFlags.weapon1Attack) assert.is_true(build.calcsTab.mainEnv.player.mainSkill.skillFlags.weapon2Attack) end) + + it("Avenging Flame uses the totem limit of the Flamewood-supported skill", function() + build.configTab.input.customMods = "+4 to maximum number of Summoned Searing Bond Totems\nSkills used by Totems have 10% more Area of Effect per maximum number of Summoned Totems" + build.configTab:BuildModList() + build.skillsTab:PasteSocketGroup("Searing Bond 20/0 1\nFlamewood 20/0 1\n") + runCallback("OnFrame") + + local sourceLimit = build.calcsTab.mainOutput.ActiveTotemLimit + + local mainSocketGroup = build.skillsTab.socketGroupList[build.mainSocketGroup] + mainSocketGroup.mainActiveSkill = 2 + build.modFlag = true + build.buildFlag = true + runCallback("OnFrame") + + assert.are.equals("Avenging Flame", build.calcsTab.mainEnv.player.mainSkill.activeEffect.grantedEffect.name) + assert.True(sourceLimit >= 5) + assert.are.equals(sourceLimit, build.calcsTab.mainOutput.ActiveTotemLimit) + assert.are.equals(sourceLimit, build.calcsTab.mainOutput.TotemsSummoned) + assert.are.equals(round(1 + 0.1 * sourceLimit, 2), round(build.calcsTab.mainOutput.AreaOfEffectMod, 2)) + end) end) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 76f6d5ca25e..ee172ff5296 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -1183,6 +1183,14 @@ function calcs.offence(env, actor, activeSkill) end if skillFlags.totem then output.ActiveTotemLimit = skillModList:Sum("BASE", skillCfg, "ActiveTotemLimit", "ActiveBallistaLimit") + -- Skills granted by a support and triggered by totems (e.g. Flamewood's Avenging Flame) are cast by the supported skill's totems + if activeSkill.skillTypes[SkillType.SkillGrantedBySupport] and skillData.triggerSourceUUID then + local sourceCache = GlobalCache.cachedData[env.mode][skillData.triggerSourceUUID] + local sourceLimit = sourceCache and sourceCache.Env.player.output.ActiveTotemLimit + if sourceLimit then + output.ActiveTotemLimit = sourceLimit + end + end end if skillFlags.area or skillData.radius or (skillFlags.mine and activeSkill.skillTypes[SkillType.Aura]) then calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, output, breakdown) @@ -4478,7 +4486,7 @@ function calcs.offence(env, actor, activeSkill) --assume skills with no cast, attack, or cooldown time are single cast bleedStacks = bleedStacks * globalOutput.BleedDuration * (globalOutput.HitSpeed or globalOutput.Speed) end - local activeTotems = env.modDB:Override(nil, "TotemsSummoned") or skillModList:Sum("BASE", skillCfg, "ActiveTotemLimit", "ActiveBallistaLimit") + local activeTotems = env.modDB:Override(nil, "TotemsSummoned") or output.ActiveTotemLimit or skillModList:Sum("BASE", skillCfg, "ActiveTotemLimit", "ActiveBallistaLimit") if skillFlags.totem then bleedStacks = bleedStacks * activeTotems end From bce207d7215b386bffcffde5225dde421941aa15 Mon Sep 17 00:00:00 2001 From: Lucas Karsten Date: Fri, 13 Nov 2026 09:42:40 -0300 Subject: [PATCH 2/2] Keep per Summoned Totem defences when Avenging Flame is the main skill CalcPerform takes the totem count for "per Summoned Totem" mods from the main skill's mod list before triggers run. With Avenging Flame selected it lost the supported skill's limit, so e.g. Ritual of Awakening regeneration or armour per totem dropped. Use the totem skill in the same socket group. --- spec/System/TestTriggers_spec.lua | 19 +++++++++++++++++++ src/Modules/CalcPerform.lua | 7 ++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/spec/System/TestTriggers_spec.lua b/spec/System/TestTriggers_spec.lua index 38d2461fa59..a2d61e4e26d 100644 --- a/spec/System/TestTriggers_spec.lua +++ b/spec/System/TestTriggers_spec.lua @@ -1660,4 +1660,23 @@ describe("TestTriggers", function() assert.are.equals(sourceLimit, build.calcsTab.mainOutput.TotemsSummoned) assert.are.equals(round(1 + 0.1 * sourceLimit, 2), round(build.calcsTab.mainOutput.AreaOfEffectMod, 2)) end) + + it("per Summoned Totem defences do not change when Avenging Flame is the main skill", function() + build.configTab.input.customMods = "+4 to maximum number of Summoned Searing Bond Totems\n+300 Armour per Summoned Totem" + build.configTab:BuildModList() + build.skillsTab:PasteSocketGroup("Searing Bond 20/0 1\nFlamewood 20/0 1\n") + runCallback("OnFrame") + + local sourceArmour = build.calcsTab.mainOutput.Armour + + local mainSocketGroup = build.skillsTab.socketGroupList[build.mainSocketGroup] + mainSocketGroup.mainActiveSkill = 2 + build.modFlag = true + build.buildFlag = true + runCallback("OnFrame") + + assert.are.equals("Avenging Flame", build.calcsTab.mainEnv.player.mainSkill.activeEffect.grantedEffect.name) + assert.True(sourceArmour >= 300 * 5) + assert.are.equals(sourceArmour, build.calcsTab.mainOutput.Armour) + end) end) diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index d683aab3ce3..58f4bf0b25a 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -1368,7 +1368,12 @@ function calcs.perform(env, skipEHP) enemyDB.multipliers["BrandsAttached"] = m_max(attached, enemyDB.multipliers["BrandsAttached"] or 0) end if activeSkill.skillFlags.totem then - local limit = env.player.mainSkill.skillModList:Sum("BASE", env.player.mainSkill.skillCfg, "ActiveTotemLimit", "ActiveBallistaLimit" ) + local limitSkill = env.player.mainSkill + -- A support-granted totem skill (e.g. Flamewood's Avenging Flame) is cast by the totems of the skill it supports + if limitSkill.skillTypes[SkillType.SkillGrantedBySupport] and activeSkill ~= limitSkill and activeSkill.socketGroup == limitSkill.socketGroup then + limitSkill = activeSkill + end + local limit = limitSkill.skillModList:Sum("BASE", limitSkill.skillCfg, "ActiveTotemLimit", "ActiveBallistaLimit" ) output.ActiveTotemLimit = m_max(limit, output.ActiveTotemLimit or 0) output.TotemsSummoned = modDB:Override(nil, "TotemsSummoned") or output.ActiveTotemLimit enemyDB.multipliers["TotemsSummoned"] = m_max(output.TotemsSummoned or 0, enemyDB.multipliers["TotemsSummoned"] or 0)