Skip to content

Commit 96c9665

Browse files
LocalIdentityLocalIdentity
andauthored
Fix calculation of inverted Resistances when having a source of Pen (#2177)
The calculation for inverted res was handled incorrectly where it was applying an average reduction to the resistance value and then we were applying pen on top of that We now calculated the average res based on the chance to invert and the impact of pen Co-authored-by: LocalIdentity <localidentity2@gmail.com>
1 parent 57b6daa commit 96c9665

3 files changed

Lines changed: 46 additions & 17 deletions

File tree

spec/System/TestSkills_spec.lua

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,20 @@ describe("TestSkills", function()
798798
assert.True(build.calcsTab.mainEnv.enemyDB:Sum("BASE", nil, "FireResist") < fireResistWithoutPotentExposure)
799799
end)
800800

801+
it("averages inverted elemental resistance after penetration", function()
802+
build.skillsTab:PasteSocketGroup("Fireball 20/0 1")
803+
build.configTab.input.enemyIsBoss = "None"
804+
build.configTab.input.enemyFireResist = 50
805+
build.configTab.input.customMods = "Hits have 50% chance to treat Enemy Monster Elemental Resistance values as inverted\nDamage Penetrates 50% of Enemy Fire Resistance"
806+
build.configTab:BuildModList()
807+
runCallback("OnFrame")
808+
809+
assert.are.equals(1.25, build.calcsTab.calcsOutput.FireEffMult)
810+
local breakdownText = table.concat(build.calcsTab.calcsEnv.player.breakdown.FireEffMult, "\n")
811+
assert.truthy(breakdownText:match("inverted hit"))
812+
assert.truthy(breakdownText:match("weighted average"))
813+
end)
814+
801815
it("Test granted skills with exposure stats make exposure configurable", function()
802816
build.skillsTab:PasteSocketGroup("Fireball 20/0 1")
803817
local spec = build.spec

src/Modules/CalcBreakdown.lua

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,20 +110,29 @@ function breakdown.area(base, areaMod, total, incBreakpoint, moreBreakpoint, red
110110
return out
111111
end
112112

113-
function breakdown.effMult(damageType, resist, pen, taken, mult, takenMore, sourceRes, useRes, invertChance, minPen)
113+
function breakdown.effMult(damageType, resist, pen, taken, mult, takenMore, sourceRes, useRes, invertChance, minPen, effectiveResist)
114114
local out = { }
115115
local resistForm = (damageType == "Physical") and "physical damage reduction" or "resistance"
116116
local resistLabel = resistForm
117-
118-
if invertChance and invertChance ~= 0 then
119-
resistLabel = "average inverted "..resistForm
117+
minPen = minPen or 0
118+
local calcPenResist = function(resist)
119+
return resist > minPen and m_max(resist - pen, minPen) or resist
120120
end
121+
effectiveResist = effectiveResist or calcPenResist(resist)
122+
121123
if sourceRes and sourceRes ~= damageType then
122124
t_insert(out, s_format("Enemy %s: %d%% ^8(%s)", resistLabel, resist, sourceRes))
123125
elseif resist ~= 0 then
124126
t_insert(out, s_format("Enemy %s: %d%%", resistLabel, resist))
125127
end
126-
if pen ~= 0 or not useRes then
128+
if invertChance and invertChance ~= 0 and useRes then
129+
local normalResist = calcPenResist(resist)
130+
local invertedResist = calcPenResist(-resist)
131+
t_insert(out, "Effective resistance:")
132+
t_insert(out, s_format("%g%% ^8(non-inverted hit after penetration)", normalResist))
133+
t_insert(out, s_format("%g%% ^8(inverted hit after penetration)", invertedResist))
134+
t_insert(out, s_format("= %g%% ^8(weighted average from %.0f%% inversion chance)", effectiveResist, invertChance * 100))
135+
elseif pen ~= 0 or not useRes then
127136
t_insert(out, "Effective resistance:")
128137
t_insert(out, s_format("%d%% ^8(resistance)", resist))
129138
if pen < 0 then
@@ -145,7 +154,7 @@ function breakdown.effMult(damageType, resist, pen, taken, mult, takenMore, sour
145154
if useRes then
146155
breakdown.multiChain(out, {
147156
label = "Effective DPS modifier:",
148-
{ "%.2f ^8(%s)", 1 - (math.max(resist - pen,0)) / 100, resistForm },
157+
{ "%.2f ^8(%s)", 1 - effectiveResist / 100, resistForm },
149158
{ "%.2f ^8(increased/reduced damage taken)", 1 + taken / 100 },
150159
{ "%.2f ^8(more/less damage taken)", takenMore },
151160
total = s_format("= %.3f", mult),

src/Modules/CalcOffence.lua

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4157,11 +4157,7 @@ function calcs.offence(env, actor, activeSkill)
41574157
end
41584158
end
41594159

4160-
local invertChance = m_max(m_min(skillModList:Sum("CHANCE", cfg, "HitsInvertEleResChance"), 1), 0)
4161-
if isElemental[damageType] and invertChance > 0 then
4162-
-- resist = (1 - invertChance) * resist + invertChance * (-1 * resist)
4163-
resist = resist - 2 * invertChance * resist
4164-
end
4160+
local invertChance = isElemental[damageType] and m_max(m_min(skillModList:Sum("CHANCE", cfg, "HitsInvertEleResChance"), 1), 0) or 0
41654161
sourceRes = env.modDB:Flag(nil, "Enemy"..sourceRes.."ResistEqualToYours") and "Your "..sourceRes.." Resistance" or (env.partyMembers.modDB:Flag(nil, "Enemy"..sourceRes.."ResistEqualToYours") and "Party Member "..sourceRes.." Resistance" or sourceRes)
41664162
if skillFlags.projectile then
41674163
takenInc = takenInc + enemyDB:Sum("INC", nil, "ProjectileDamageTaken")
@@ -4174,23 +4170,33 @@ function calcs.offence(env, actor, activeSkill)
41744170
end
41754171
local effMult = (1 + takenInc / 100) * takenMore
41764172
local useRes = useThisResist(damageType)
4173+
local effectiveResist = resist
4174+
local calcPenResist = function(resist)
4175+
return resist > minPen and m_max(resist - pen, minPen) or resist
4176+
end
41774177
if skillModList:Flag(cfg, isElemental[damageType] and "CannotElePenIgnore" or nil) then
4178-
effMult = effMult * (1 - resist / 100)
4178+
effectiveResist = (isElemental[damageType] and invertChance > 0) and (resist - 2 * invertChance * resist) or resist
4179+
effMult = effMult * (1 - effectiveResist / 100)
41794180
elseif useRes then
4180-
effMult = effMult * (1 - (resist > minPen and m_max(resist - pen, minPen) or resist) / 100)
4181+
if isElemental[damageType] and invertChance > 0 then
4182+
effectiveResist = calcPenResist(resist) * (1 - invertChance) + calcPenResist(-resist) * invertChance
4183+
else
4184+
effectiveResist = calcPenResist(resist)
4185+
end
4186+
effMult = effMult * (1 - effectiveResist / 100)
41814187
end
41824188
damageTypeHitMin = damageTypeHitMin * effMult
41834189
damageTypeHitMax = damageTypeHitMax * effMult
41844190
damageTypeHitAvg = damageTypeHitAvg * effMult
41854191
if env.mode == "CALCS" then
41864192
output[damageType.."EffMult"] = effMult
41874193
end
4188-
if pass == 2 and breakdown and (effMult ~= 1 or sourceRes ~= damageType) and skillModList:Flag(cfg, isElemental[damageType] and "CannotElePenIgnore" or nil) then
4194+
if pass == 2 and breakdown and (effMult ~= 1 or sourceRes ~= damageType or invertChance > 0) and skillModList:Flag(cfg, isElemental[damageType] and "CannotElePenIgnore" or nil) then
41894195
t_insert(breakdown[damageType], s_format("x %.3f ^8(effective DPS modifier)", effMult))
4190-
breakdown[damageType.."EffMult"] = breakdown.effMult(damageType, resist, 0, takenInc, effMult, takenMore, sourceRes, useRes, invertChance, minPen)
4191-
elseif pass == 2 and breakdown and (effMult ~= 1 or (resist - pen) < minPen or sourceRes ~= damageType) then
4196+
breakdown[damageType.."EffMult"] = breakdown.effMult(damageType, resist, 0, takenInc, effMult, takenMore, sourceRes, useRes, invertChance, minPen, effectiveResist)
4197+
elseif pass == 2 and breakdown and (effMult ~= 1 or (resist - pen) < minPen or sourceRes ~= damageType or invertChance > 0) then
41924198
t_insert(breakdown[damageType], s_format("x %.3f ^8(effective DPS modifier)", effMult))
4193-
breakdown[damageType.."EffMult"] = breakdown.effMult(damageType, resist, pen, takenInc, effMult, takenMore, sourceRes, useRes, invertChance, minPen)
4199+
breakdown[damageType.."EffMult"] = breakdown.effMult(damageType, resist, pen, takenInc, effMult, takenMore, sourceRes, useRes, invertChance, minPen, effectiveResist)
41944200
end
41954201
end
41964202
if pass == 2 and breakdown then

0 commit comments

Comments
 (0)