Skip to content

Commit cfb33e3

Browse files
github-actions[bot]LocalIdentityLocalIdentity
authored
[pob2-port] Fix calculation of inverted Resistances when having a source of Penetration (#9898)
* Apply changes from PathOfBuildingCommunity/PathOfBuilding-PoE2#2177 * Fix merge --------- Co-authored-by: LocalIdentity <LocalIdentity@users.noreply.github.com> Co-authored-by: LocalIdentity <localidentity2@gmail.com>
1 parent 51da967 commit cfb33e3

3 files changed

Lines changed: 42 additions & 21 deletions

File tree

spec/System/TestSkills_spec.lua

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,22 @@ describe("TestAttacks", function()
150150

151151
assert.True(preAdrenalineMaxStages < build.calcsTab.mainEnv.player.activeSkillList[1].skillModList:Sum("BASE", nil, "Multiplier:BlightMaxStages"))
152152
end)
153+
154+
it("averages inverted elemental resistance after penetration", function()
155+
build.skillsTab:PasteSocketGroup("Fireball 20/0 1")
156+
build.configTab.input.enemyIsBoss = "None"
157+
build.configTab.input.enemyFireResist = 50
158+
build.configTab.input.customMods = "Hits have 50% chance to treat Enemy Monster Elemental Resistance values as inverted\nDamage Penetrates 50% of Enemy Fire Resistance"
159+
build.configTab:BuildModList()
160+
runCallback("OnFrame")
161+
162+
-- Unlike PoE 2, PoE 1 penetration can lower resistance below zero:
163+
-- 50% of hits use 0% resistance and 50% use -100% resistance.
164+
assert.are.equals(1.5, build.calcsTab.calcsOutput.FireEffMult)
165+
local breakdownText = table.concat(build.calcsTab.calcsEnv.player.breakdown.FireEffMult, "\n")
166+
assert.is_truthy(breakdownText:match("inverted hit"))
167+
assert.is_truthy(breakdownText:match("weighted average"))
168+
end)
153169
it("Test cost efficiency modifiers", function()
154170
-- Test Mana Cost Efficiency
155171
build.skillsTab:PasteSocketGroup("Ball Lightning 1/0 1\n")
@@ -212,4 +228,4 @@ describe("TestAttacks", function()
212228
local finalCost = build.calcsTab.mainOutput.ManaCost
213229
assert.are.equals(7, round(finalCost))
214230
end)
215-
end)
231+
end)

src/Modules/CalcBreakdown.lua

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,20 +108,25 @@ function breakdown.area(base, areaMod, total, incBreakpoint, moreBreakpoint, red
108108
return out
109109
end
110110

111-
function breakdown.effMult(damageType, resist, pen, taken, mult, takenMore, sourceRes, useRes, invertChance)
111+
function breakdown.effMult(damageType, resist, pen, taken, mult, takenMore, sourceRes, useRes, invertChance, effectiveResist)
112112
local out = { }
113113
local resistForm = (damageType == "Physical") and "physical damage reduction" or "resistance"
114114
local resistLabel = resistForm
115+
effectiveResist = effectiveResist or resist - pen
115116

116-
if invertChance and invertChance ~= 0 then
117-
resistLabel = "average inverted "..resistForm
118-
end
119117
if sourceRes and sourceRes ~= damageType then
120118
t_insert(out, s_format("Enemy %s: %d%% ^8(%s)", resistLabel, resist, sourceRes))
121119
elseif resist ~= 0 then
122120
t_insert(out, s_format("Enemy %s: %d%%", resistLabel, resist))
123121
end
124-
if pen ~= 0 or not useRes then
122+
if invertChance and invertChance ~= 0 and useRes then
123+
local normalResist = resist - pen
124+
local invertedResist = -resist - pen
125+
t_insert(out, "Effective resistance:")
126+
t_insert(out, s_format("%g%% ^8(non-inverted hit after penetration)", normalResist))
127+
t_insert(out, s_format("%g%% ^8(inverted hit after penetration)", invertedResist))
128+
t_insert(out, s_format("= %g%% ^8(weighted average from %.0f%% inversion chance)", effectiveResist, invertChance * 100))
129+
elseif pen ~= 0 or not useRes then
125130
t_insert(out, "Effective resistance:")
126131
t_insert(out, s_format("%d%% ^8(resistance)", resist))
127132
if pen < 0 then
@@ -139,7 +144,7 @@ function breakdown.effMult(damageType, resist, pen, taken, mult, takenMore, sour
139144
if useRes then
140145
breakdown.multiChain(out, {
141146
label = "Effective DPS modifier:",
142-
{ "%.2f ^8(%s)", 1 - (resist - pen) / 100, resistForm },
147+
{ "%.2f ^8(%s)", 1 - effectiveResist / 100, resistForm },
143148
{ "%.2f ^8(increased/reduced damage taken)", 1 + taken / 100 },
144149
{ "%.2f ^8(more/less damage taken)", takenMore },
145150
total = s_format("= %.3f", mult),

src/Modules/CalcOffence.lua

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3367,14 +3367,8 @@ function calcs.offence(env, actor, activeSkill)
33673367
end
33683368
end
33693369
local invertChanceEle = m_max(m_min(skillModList:Sum("CHANCE", cfg, "HitsInvertEleResChance"), 1), 0)
3370-
if isElemental[damageType] and invertChanceEle > 0 then
3371-
-- resist = (1 - invertChanceEle) * resist + invertChanceEle * (-1 * resist)
3372-
resist = resist - 2 * invertChanceEle * resist
3373-
end
33743370
local invertChanceChaos = m_max(m_min(skillModList:Sum("CHANCE", cfg, "HitsInvertChaosResChance"), 1), 0)
3375-
if damageType == "Chaos" and invertChanceChaos > 0 then
3376-
resist = resist - 2 * invertChanceChaos * resist
3377-
end
3371+
local invertChance = (isElemental[damageType] and invertChanceEle) or (damageType == "Chaos" and invertChanceChaos) or 0
33783372
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)
33793373
if skillFlags.projectile then
33803374
takenInc = takenInc + enemyDB:Sum("INC", nil, "ProjectileDamageTaken")
@@ -3388,24 +3382,30 @@ function calcs.offence(env, actor, activeSkill)
33883382
local effMult = (1 + takenInc / 100) * takenMore
33893383
local useResChance = useThisResist(damageType)
33903384
local useRes = useResChance > 0
3385+
local effectiveResist = resist
33913386
if skillModList:Flag(cfg, isElemental[damageType] and "CannotElePenIgnore" or nil) then
3392-
effMult = effMult * (1 - resist / 100)
3387+
effectiveResist = invertChance > 0 and (resist - 2 * invertChance * resist) or resist
3388+
effMult = effMult * (1 - effectiveResist / 100)
33933389
elseif useRes then
3394-
effMult = effMult * (1 - ((resist - pen) * useResChance) / 100)
3390+
if invertChance > 0 then
3391+
effectiveResist = ((resist - pen) * (1 - invertChance) + (-resist - pen) * invertChance) * useResChance
3392+
else
3393+
effectiveResist = (resist - pen) * useResChance
3394+
end
3395+
effMult = effMult * (1 - effectiveResist / 100)
33953396
end
33963397
damageTypeHitMin = damageTypeHitMin * effMult
33973398
damageTypeHitMax = damageTypeHitMax * effMult
33983399
damageTypeHitAvg = damageTypeHitAvg * effMult
33993400
if env.mode == "CALCS" then
34003401
output[damageType.."EffMult"] = effMult
34013402
end
3402-
local invertChance = (isElemental[damageType] and invertChanceEle) or (damageType == "Chaos" and invertChanceChaos) or 0
3403-
if pass == 2 and breakdown and (effMult ~= 1 or sourceRes ~= damageType) and skillModList:Flag(cfg, isElemental[damageType] and "CannotElePenIgnore" or nil) then
3403+
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
34043404
t_insert(breakdown[damageType], s_format("x %.3f ^8(effective DPS modifier)", effMult))
3405-
breakdown[damageType.."EffMult"] = breakdown.effMult(damageType, resist, 0, takenInc, effMult, takenMore, sourceRes, useRes, invertChance)
3406-
elseif pass == 2 and breakdown and (effMult ~= 1 or sourceRes ~= damageType) then
3405+
breakdown[damageType.."EffMult"] = breakdown.effMult(damageType, resist, 0, takenInc, effMult, takenMore, sourceRes, useRes, invertChance, effectiveResist)
3406+
elseif pass == 2 and breakdown and (effMult ~= 1 or sourceRes ~= damageType or invertChance > 0) then
34073407
t_insert(breakdown[damageType], s_format("x %.3f ^8(effective DPS modifier)", effMult))
3408-
breakdown[damageType.."EffMult"] = breakdown.effMult(damageType, resist, pen, takenInc, effMult, takenMore, sourceRes, useRes, invertChance)
3408+
breakdown[damageType.."EffMult"] = breakdown.effMult(damageType, resist, pen, takenInc, effMult, takenMore, sourceRes, useRes, invertChance, effectiveResist)
34093409
end
34103410
end
34113411
if pass == 2 and breakdown then

0 commit comments

Comments
 (0)