From b96de60c1ba962c2ae0e4942bf3f1c23230ca2d0 Mon Sep 17 00:00:00 2001 From: Mickael Cagnion Date: Fri, 2 Oct 2026 01:22:18 +0200 Subject: [PATCH] Fix EHP falling with life gained on block when defences increase The per-hit "missing life/mana before enemy hit" recovery for Defiance of Destiny checked its value by truthiness, but the value is a modDB sum and is 0 for every other build. Since 0 is truthy in Lua, the block ran on every iteration and clamped Life back to its maximum, discarding the life gained on block that the EHP speed-up had just credited for the batched hits. Lowering damage taken could then enlarge the batch, discard more gains and reduce the number of hits survived, so more resistance or life gave less EHP (issue 9446). Only apply the recovery when the value is non-zero, as the nearby LifeWhenHit checks already do. Defiance of Destiny keeps its behaviour. --- spec/System/TestDefence_spec.lua | 28 ++++++++++++++++++++++++++++ src/Modules/CalcDefence.lua | 4 ++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/spec/System/TestDefence_spec.lua b/spec/System/TestDefence_spec.lua index e6addf68c3b..3ebccc38332 100644 --- a/spec/System/TestDefence_spec.lua +++ b/spec/System/TestDefence_spec.lua @@ -1723,4 +1723,32 @@ describe("TestDefence", function() assertClose(block.EffectiveBlockChance, 10) assert.is_true(block.TotalEHP > base.TotalEHP) end) + + it("does not lower EHP with life gained on block when resistance increases", function() + local function calcEHP(coldResist) + newBuild() + build.configTab.input.enemyDamageType = "Melee" + build.configTab.input.enemyPhysicalDamage = "0" + build.configTab.input.enemyFireDamage = "0" + build.configTab.input.enemyColdDamage = "600" + build.configTab.input.enemyLightningDamage = "0" + build.configTab.input.enemyChaosDamage = "0" + build.configTab.input.customMods = [[ + +1000 to maximum Life + +75% chance to Block Attack Damage + +100 Life gained when you Block + ]] .. "+" .. coldResist .. "% to Cold Resistance\n" + build.configTab:BuildModList() + runCallback("OnFrame") + return build.calcsTab.calcsOutput.TotalEHP + end + + local lowerResistEHP = calcEHP(30) + local higherResistEHP = calcEHP(33) + + newBuild() + + assert.is_true(higherResistEHP >= lowerResistEHP, + string.format("EHP fell from %.1f to %.1f", lowerResistEHP, higherResistEHP)) + end) end) diff --git a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua index bc768a077ac..0817faa1c6f 100644 --- a/src/Modules/CalcDefence.lua +++ b/src/Modules/CalcDefence.lua @@ -2702,10 +2702,10 @@ function calcs.buildDefenceEstimations(env, actor) poolTable.EnergyShield = m_min(poolTable.EnergyShield + DamageIn.EnergyShieldWhenHit * (gainMult - 1), gainMult * output.EnergyShieldRecoveryCap) end end - if DamageIn.MissingLifeBeforeEnemyHit and poolTable.Life > 0 then + if (DamageIn.MissingLifeBeforeEnemyHit or 0) ~= 0 and poolTable.Life > 0 then poolTable.Life = m_min(poolTable.Life + DamageIn.MissingLifeBeforeEnemyHit * ((output.LifeUnreserved or 0) - poolTable.Life) / 100, output.LifeRecoverable or 0) end - if DamageIn.MissingManaBeforeEnemyHit and poolTable.Mana > 0 then + if (DamageIn.MissingManaBeforeEnemyHit or 0) ~= 0 and poolTable.Mana > 0 then poolTable.Mana = m_min(poolTable.Mana + DamageIn.MissingManaBeforeEnemyHit * ((output.ManaUnreserved or 0) - poolTable.Mana) / 100, output.ManaUnreserved or 0) end poolTable = calcs.reducePoolsByDamage(poolTable, Damage, actor)