From 79d3617e2cc1a5409bd9c0d2318b8896b804454e Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 22 Jul 2026 14:54:05 +0200 Subject: [PATCH 1/3] Add support for "Spirit Infusion" Occultist Ascendancy node --- src/Modules/CalcPerform.lua | 14 ++++++++++++++ src/Modules/Calcs.lua | 3 +++ src/Modules/ConfigOptions.lua | 3 +++ src/Modules/ModParser.lua | 1 + 4 files changed, 21 insertions(+) diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index 1fb88582c4c..1db2653e5f9 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -708,6 +708,15 @@ local function doActorMisc(env, actor) modDB:NewMod("Cost", "MORE", -effect, "Fanaticism", ModFlag.Cast) modDB:NewMod("AreaOfEffect", "INC", effect, "Fanaticism", ModFlag.Cast) end + if modDB:Flag(nil, "Condition:CanGainSpiritInfusion") then + -- storing tags in local var to avoid repetition + local globalEffectTag = { type = "GlobalEffect", effectType = "Buff", effectName = "Spirit Infusion", unscalable = true } + local multiplierTag = { type = "Multiplier", var = "SpiritInfusion"--[[ , limitVar = "SpiritInfusionsMax" ]] } + + modDB:NewMod("EnergyShieldRechargeFaster", "INC", 30 , "Spirit Infusion", multiplierTag, globalEffectTag) + modDB:NewMod("Damage", "MORE", 10 , "Spirit Infusion", nil, KeywordFlag.Spell, { type = "SkillType", skillType = SkillType.Channel }, multiplierTag, globalEffectTag) + modDB:NewMod("Cost", "MORE", 20 , "Spirit Infusion", nil, KeywordFlag.Spell, { type = "SkillType", skillType = SkillType.Channel }, multiplierTag, globalEffectTag) + end if modDB:Flag(nil, "UnholyMight") then local effect = 1 + modDB:Sum("INC", nil, "BuffEffectOnSelf") / 100 modDB:NewMod("PhysicalDamageConvertToChaos", "BASE", m_floor(100 * effect), "Unholy Might") @@ -957,6 +966,7 @@ local function doActorCharges(env, actor) output.AfflictionChargesMax = m_max(modDB:Flag(nil, "MaximumFrenzyChargesEqualsMaximumAfflictionCharges") and output.FrenzyChargesMax or 0, 0) output.BloodChargesMax = m_max(modDB:Sum("BASE", nil, "BloodChargesMax"), 0) output.SpiritChargesMax = m_max(modDB:Sum("BASE", nil, "SpiritChargesMax"), 0) + output.SpiritInfusionsMax = modDB:Sum("BASE", nil, "SpiritInfusionsMax") + (modDB:Flag(nil, "Condition:CanGainSpiritInfusion") and 5 or 0) -- Initialize Charges output.PowerCharges = 0 @@ -972,6 +982,7 @@ local function doActorCharges(env, actor) output.AfflictionCharges = 0 output.BloodCharges = 0 output.SpiritCharges = 0 + output.SpiritInfusions = 0 -- Conditionally over-write Charge values if modDB:Flag(nil, "MinimumFrenzyChargesIsMaximumFrenzyCharges") then @@ -1036,6 +1047,8 @@ local function doActorCharges(env, actor) end output.BloodCharges = m_min(modDB:Override(nil, "BloodCharges") or output.BloodChargesMax, output.BloodChargesMax) output.SpiritCharges = m_min(modDB:Override(nil, "SpiritCharges") or 0, output.SpiritChargesMax) + output.SpiritInfusions = m_min(modDB:Override(nil, "SpiritInfusion") or 0, output.SpiritInfusionsMax) + output.CrabBarriers = m_min(modDB:Override(nil, "CrabBarriers") or output.CrabBarriersMax, output.CrabBarriersMax) if modDB:Flag(nil, "HaveMaximumPowerCharges") then @@ -1069,6 +1082,7 @@ local function doActorCharges(env, actor) modDB.multipliers["AfflictionCharge"] = output.AfflictionCharges modDB.multipliers["BloodCharge"] = output.BloodCharges modDB.multipliers["SpiritCharge"] = output.SpiritCharges + modDB.multipliers["SpiritInfusion"] = output.SpiritInfusions end function calcs.actionSpeedMod(actor) diff --git a/src/Modules/Calcs.lua b/src/Modules/Calcs.lua index 871d53587f1..4bede0efd00 100644 --- a/src/Modules/Calcs.lua +++ b/src/Modules/Calcs.lua @@ -677,6 +677,9 @@ function calcs.buildOutput(build, mode) if build.calcsTab.mainEnv.multipliersUsed["SpiritCharge"] then t_insert(combatList, s_format("%d Spirit Charges", output.SpiritCharges)) end + if build.calcsTab.mainEnv.multipliersUsed["SpiritInfusion"] then + t_insert(combatList, s_format("%d Spirit Infusions", output.SpiritInfusions)) + end if env.player.mainSkill.baseSkillModList:Flag(nil, "Cruelty") then t_insert(combatList, "Cruelty") end diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index e77099db2db..3bc04390e30 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -1653,6 +1653,9 @@ Huge sets the radius to 11. { var = "buffFanaticism", type = "check", label = "Do you have Fanaticism?", ifFlag = "Condition:CanGainFanaticism", tooltip = "This will enable the Fanaticism buff itself. (Grants 75% more cast speed, reduced skill cost, and increased area of effect)", apply = function(val, modList, enemyModList) modList:NewMod("Condition:Fanaticism", "FLAG", true, "Config", { type = "Condition", var = "Combat" }, { type = "Condition", var = "CanGainFanaticism" }) end }, + { var = "overrideSpiritInfusion", type = "countAllowZero", label = "# of Spirit Infusion stacks:", ifFlag = "Condition:CanGainSpiritInfusion", tooltip = "Each stack of Spirit Infusion grants:\n30% faster start of Energy Shield Recharge, \nChannelling Spells deal 10% more Damage and \nChannelling Spells have 20% more Cost", apply = function(val, modList, enemyModList) + modList:NewMod("SpiritInfusion", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" } ) + end }, { var = "conditionHitsAlwaysStun", type = "check", label = "Do your hits always stun?", ifFlag = "Condition:maceMasteryStunCullSpecced", tooltip = "This enables the conditional culling strike from the mace mastery.", apply = function(val, modList, enemyModList) modList:NewMod("CullPercent", "MAX", 10, "Config", { type = "Condition", var = "Combat" }, {type = "Condition", var = "maceMasteryStunCullSpecced"}) end }, diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index bc4a0ccf005..5f6909b05b2 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -2873,6 +2873,7 @@ local specialModList = { ["every second, inflict withered on nearby enemies for (%d+) seconds"] = { flag("Condition:CanWither") }, ["nearby hindered enemies deal (%d+)%% reduced damage over time"] = function(num) return { mod("EnemyModifier", "LIST", { mod = mod("DamageOverTime", "INC", -num) }, { type = "ActorCondition", actor = "enemy", var = "Hindered" }) } end, ["nearby chilled enemies deal (%d+)%% reduced damage with hits"] = function(num) return { mod("EnemyModifier", "LIST", { mod = mod("Damage", "INC", -num) }, { type = "ActorCondition", actor = "enemy", var = "Chilled" }) } end, + ["gain spirit infusion every (%d+)%.?(%d?) seconds? while channelling a spell"] = function(_,_) return { flag("Condition:CanGainSpiritInfusion") } end, -- Pathfinder ["always poison on hit while using a flask"] = { mod("PoisonChance", "BASE", 100, { type = "Condition", var = "UsingFlask" }) }, ["poisons you inflict during any flask effect have (%d+)%% chance to deal (%d+)%% more damage"] = function(num, _, more) return { mod("Damage", "MORE", tonumber(more) * num / 100, nil, 0, KeywordFlag.Poison, { type = "Condition", var = "UsingFlask" }) } end, From e30832d476b7b49a6d6a7331373739d4575a7509 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 22 Jul 2026 15:03:50 +0200 Subject: [PATCH 2/3] Add more flexible mod pattern --- src/Modules/ModParser.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 5f6909b05b2..51a632b884d 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -2873,7 +2873,7 @@ local specialModList = { ["every second, inflict withered on nearby enemies for (%d+) seconds"] = { flag("Condition:CanWither") }, ["nearby hindered enemies deal (%d+)%% reduced damage over time"] = function(num) return { mod("EnemyModifier", "LIST", { mod = mod("DamageOverTime", "INC", -num) }, { type = "ActorCondition", actor = "enemy", var = "Hindered" }) } end, ["nearby chilled enemies deal (%d+)%% reduced damage with hits"] = function(num) return { mod("EnemyModifier", "LIST", { mod = mod("Damage", "INC", -num) }, { type = "ActorCondition", actor = "enemy", var = "Chilled" }) } end, - ["gain spirit infusion every (%d+)%.?(%d?) seconds? while channelling a spell"] = function(_,_) return { flag("Condition:CanGainSpiritInfusion") } end, + ["gain spirit infusion every ?(%d?)%.?(%d?) seconds? while channelling a spell"] = function(_,_) return { flag("Condition:CanGainSpiritInfusion") } end, -- Pathfinder ["always poison on hit while using a flask"] = { mod("PoisonChance", "BASE", 100, { type = "Condition", var = "UsingFlask" }) }, ["poisons you inflict during any flask effect have (%d+)%% chance to deal (%d+)%% more damage"] = function(num, _, more) return { mod("Damage", "MORE", tonumber(more) * num / 100, nil, 0, KeywordFlag.Poison, { type = "Condition", var = "UsingFlask" }) } end, From 92d33dd24034f6b5e44c62f3f7e23990b8fc8876 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 22 Jul 2026 15:05:52 +0200 Subject: [PATCH 3/3] Slightly rename and reposition config option It is now right below "Spirit Charges" which seemed fitting --- src/Modules/ConfigOptions.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index 3bc04390e30..f4a2ab33354 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -948,6 +948,9 @@ Huge sets the radius to 11. { var = "overrideSpiritCharges", type = "countAllowZero", label = "# of Spirit Charges:", ifMult = "SpiritCharge", apply = function(val, modList, enemyModList) modList:NewMod("SpiritCharges", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" }) end }, + { var = "overrideSpiritInfusion", type = "countAllowZero", label = "# of Spirit Infusions:", ifFlag = "Condition:CanGainSpiritInfusion", tooltip = "Each stack of Spirit Infusion grants:\n30% faster start of Energy Shield Recharge, \nChannelling Spells deal 10% more Damage and \nChannelling Spells have 20% more Cost", apply = function(val, modList, enemyModList) + modList:NewMod("SpiritInfusion", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" } ) + end }, { var = "minionsUsePowerCharges", type = "check", label = "Do your Minions use Power Charges?", ifFlag = "haveMinion", apply = function(val, modList, enemyModList) modList:NewMod("MinionModifier", "LIST", { mod = modLib.createMod("UsePowerCharges", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) }, "Config") end }, @@ -1653,9 +1656,6 @@ Huge sets the radius to 11. { var = "buffFanaticism", type = "check", label = "Do you have Fanaticism?", ifFlag = "Condition:CanGainFanaticism", tooltip = "This will enable the Fanaticism buff itself. (Grants 75% more cast speed, reduced skill cost, and increased area of effect)", apply = function(val, modList, enemyModList) modList:NewMod("Condition:Fanaticism", "FLAG", true, "Config", { type = "Condition", var = "Combat" }, { type = "Condition", var = "CanGainFanaticism" }) end }, - { var = "overrideSpiritInfusion", type = "countAllowZero", label = "# of Spirit Infusion stacks:", ifFlag = "Condition:CanGainSpiritInfusion", tooltip = "Each stack of Spirit Infusion grants:\n30% faster start of Energy Shield Recharge, \nChannelling Spells deal 10% more Damage and \nChannelling Spells have 20% more Cost", apply = function(val, modList, enemyModList) - modList:NewMod("SpiritInfusion", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" } ) - end }, { var = "conditionHitsAlwaysStun", type = "check", label = "Do your hits always stun?", ifFlag = "Condition:maceMasteryStunCullSpecced", tooltip = "This enables the conditional culling strike from the mace mastery.", apply = function(val, modList, enemyModList) modList:NewMod("CullPercent", "MAX", 10, "Config", { type = "Condition", var = "Combat" }, {type = "Condition", var = "maceMasteryStunCullSpecced"}) end },