Skip to content

Commit

Permalink
Add support for pseudo recoup like divine shield and juggernaut (#6833)
Browse files Browse the repository at this point in the history
* Add support for pseudo recoup like divine shield and juggernaut

* fix spelling
  • Loading branch information
Regisle authored Aug 14, 2024
1 parent bf9f84c commit 2257923
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 11 deletions.
6 changes: 2 additions & 4 deletions src/Data/ModCache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1981,9 +1981,8 @@ c["1.5% of Lightning Damage is Leeched as Mana while affected by Wrath"]={{[1]={
c["1.5% of Physical Attack Damage Leeched as Life"]={{[1]={flags=1,keywordFlags=0,name="PhysicalDamageLifeLeech",type="BASE",value=1.5}},nil}
c["1.5% of Physical Attack Damage Leeched as Mana"]={{[1]={flags=1,keywordFlags=0,name="PhysicalDamageManaLeech",type="BASE",value=1.5}},nil}
c["1.5% of Physical Damage prevented from Hits in the past"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="BASE",value=1.5}}," prevented from Hits in the past "}
c["1.5% of Physical Damage prevented from Hits in the past 10 seconds is Regenerated as Life per second"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="BASE",value=1.5}}," prevented from Hits in the past 10 seconds is Regenerated as Life per second "}
c["1.5% of Physical Damage prevented from Hits in the past 10 seconds is Regenerated as Life per second"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamageMitigatedLifePseudoRecoup",type="BASE",value=15},[2]={flags=0,keywordFlags=0,name="PhysicalDamageMitigatedLifePseudoRecoupDuration",type="BASE",value="10"}},nil}
c["1.6% of Physical Attack Damage Leeched as Life"]={{[1]={flags=1,keywordFlags=0,name="PhysicalDamageLifeLeech",type="BASE",value=1.6}},nil}
c["10 seconds is Regenerated as Life per second"]={{[1]={flags=0,keywordFlags=0,name="Life",type="BASE",value=10}}," seconds is Regenerated as per second "}
c["10% Chance for Traps to Trigger an additional time"]={{}," to Trigger an additional time "}
c["10% Chance to Block Attack Damage"]={{[1]={flags=0,keywordFlags=0,name="BlockChance",type="BASE",value=10}},nil}
c["10% Chance to Block Attack Damage during Effect"]={{[1]={[1]={type="Condition",var="UsingFlask"},flags=0,keywordFlags=0,name="BlockChance",type="BASE",value=10}},nil}
Expand Down Expand Up @@ -4291,8 +4290,7 @@ c["3% of Damage from Hits is taken from your nearest Totem's Life before you"]={
c["3% of Damage is taken from Mana before Life"]={{[1]={flags=0,keywordFlags=0,name="DamageTakenFromManaBeforeLife",type="BASE",value=3}},nil}
c["3% of Life Regenerated per Second if you've dealt a Critical Strike in the past 8 seconds"]={{[1]={[1]={type="Condition",var="CritInPast8Sec"},flags=0,keywordFlags=0,name="LifeRegenPercent",type="BASE",value=3}},nil}
c["3% of Physical Attack Damage Leeched as Life"]={{[1]={flags=1,keywordFlags=0,name="PhysicalDamageLifeLeech",type="BASE",value=3}},nil}
c["3% of Physical Damage prevented from Hits Recently is Regenerated as Energy Shield per second"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="BASE",value=3}}," prevented from Hits Recently is Regenerated as Energy Shield per second "}
c["3% of Physical Damage prevented from Hits Recently is Regenerated as Energy Shield per second Limited to 1 Keystone Tattoo"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="BASE",value=3}}," prevented from Hits Recently is Regenerated as Energy Shield per second Limited to 1 Keystone Tattoo "}
c["3% of Physical Damage prevented from Hits Recently is Regenerated as Energy Shield per second"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamageMitigatedEnergyShieldPseudoRecoup",type="BASE",value=12}},nil}
c["3% reduced Attack and Cast Speed per Frenzy Charge"]={{[1]={[1]={type="Multiplier",var="FrenzyCharge"},flags=0,keywordFlags=0,name="Speed",type="INC",value=-3}},nil}
c["3% reduced Cost of Skills"]={{[1]={flags=0,keywordFlags=0,name="Cost",type="INC",value=-3}},nil}
c["3% reduced Mana Cost of Skills"]={{[1]={flags=0,keywordFlags=0,name="ManaCost",type="INC",value=-3}},nil}
Expand Down
65 changes: 62 additions & 3 deletions src/Modules/CalcDefence.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,36 @@ function calcs.defence(env, actor)
end
end
end

-- pseudo recoup (eg %physical damage prevented from hits regenerated)
for _, resource in ipairs(recoupTypeList) do
if not modDB:Flag(nil, "No"..resource.."Regen") and not modDB:Flag(nil, "CannotGain"..resource) then
local PhysicalDamageMitigatedPseudoRecoup = modDB:Sum("BASE", nil, "PhysicalDamageMitigated"..resource.."PseudoRecoup")
if PhysicalDamageMitigatedPseudoRecoup > 0 then
output["PhysicalDamageMitigated"..resource.."PseudoRecoupDuration"] = modDB:Sum("BASE", nil, "PhysicalDamageMitigated"..resource.."PseudoRecoupDuration")
if output["PhysicalDamageMitigated"..resource.."PseudoRecoupDuration"] == 0 then
output["PhysicalDamageMitigated"..resource.."PseudoRecoupDuration"] = 4
end
local inc = modDB:Sum("INC", nil, resource.."Regen")
local more = modDB:More(nil, resource.."Regen")
output["PhysicalDamageMitigated"..resource.."PseudoRecoup"] = PhysicalDamageMitigatedPseudoRecoup * (1 + inc/100) * more * output[resource.."RecoveryRateMod"]
output["anyRecoup"] = output["anyRecoup"] + output["PhysicalDamageMitigated"..resource.."PseudoRecoup"]
if breakdown then
breakdown["PhysicalDamageMitigated"..resource.."PseudoRecoup"] = { }
if output[resource.."RecoveryRateMod"] ~= 1 or inc ~= 0 or more ~= 1 then
t_insert(breakdown["PhysicalDamageMitigated"..resource.."PseudoRecoup"], s_format("%d%% ^8(base)", PhysicalDamageMitigatedPseudoRecoup))
if inc ~= 0 or more ~= 1 then
t_insert(breakdown["PhysicalDamageMitigated"..resource.."PseudoRecoup"], s_format("* %.2f ^8(regeneration rate modifier)", (1 + inc/100) * more))
end
if output[resource.."RecoveryRateMod"] ~= 1 then
t_insert(breakdown["PhysicalDamageMitigated"..resource.."PseudoRecoup"], s_format("* %.2f ^8(recovery rate modifier)", output[resource.."RecoveryRateMod"]))
end
end
t_insert(breakdown["PhysicalDamageMitigated"..resource.."PseudoRecoup"], s_format("= %.1f%% over %d seconds", output["PhysicalDamageMitigated"..resource.."PseudoRecoup"], output["PhysicalDamageMitigated"..resource.."PseudoRecoupDuration"]))
end
end
end
end
end

-- Ward recharge
Expand Down Expand Up @@ -2666,14 +2696,16 @@ function calcs.buildDefenceEstimations(env, actor)
if output["anyRecoup"] > 0 and damageCategoryConfig ~= "DamageOverTime" then
local totalDamage = 0
local totalElementalDamage = 0
local totalPhysicalDamageMitigated = output["NumberOfMitigatedDamagingHits"] * (output.PhysicalTakenDamage - output.PhysicalTakenHit)
local extraPseudoRecoup = {}
for _, damageType in ipairs(dmgTypeList) do
totalDamage = totalDamage + output[damageType.."PoolLost"]
if isElemental[damageType] then
totalElementalDamage = totalElementalDamage + output[damageType.."PoolLost"]
end
end
local recoupTypeList = {"Life", "Mana", "EnergyShield"}
for _, recoupType in ipairs(recoupTypeList) do
for i, recoupType in ipairs(recoupTypeList) do
local recoupTime = (modDB:Flag(nil, "3Second"..recoupType.."Recoup") or modDB:Flag(nil, "3SecondRecoup")) and 3 or 4
output["Total"..recoupType.."RecoupRecovery"] = (output[recoupType.."Recoup"] or 0) / 100 * totalDamage
if (output["Elemental"..recoupType.."Recoup"] or 0) > 0 and totalElementalDamage > 0 then
Expand All @@ -2684,8 +2716,19 @@ function calcs.buildDefenceEstimations(env, actor)
output["Total"..recoupType.."RecoupRecovery"] = output["Total"..recoupType.."RecoupRecovery"] + output[damageType..recoupType.."Recoup"] / 100 * output[damageType.."PoolLost"]
end
end
output[recoupType.."RecoupRecoveryMax"] = output["Total"..recoupType.."RecoupRecovery"] / recoupTime
output[recoupType.."RecoupRecoveryAvg"] = output["Total"..recoupType.."RecoupRecovery"] / (output["EHPsurvivalTime"] + recoupTime)
output["Total"..recoupType.."PseudoRecoup"] = (output["PhysicalDamageMitigated"..recoupType.."PseudoRecoup"] or 0) / 100 * totalPhysicalDamageMitigated
local PseudoRecoupDuration = (output["PhysicalDamageMitigated"..recoupType.."PseudoRecoupDuration"] or 4)
-- Pious Path
if output["Total"..recoupType.."PseudoRecoup"] ~= 0 then
for j=i+1,#recoupTypeList do
if modDB:Flag(nil, recoupType.."RegenerationRecovers"..recoupTypeList[j]) and not modDB:Flag(nil, "UnaffectedBy"..recoupTypeList[j].."Regen") and not modDB:Flag(nil, "No"..recoupTypeList[j].."Regen") and not modDB:Flag(nil, "CannotGain"..recoupTypeList[j]) then
extraPseudoRecoup[recoupTypeList[j]] = { output["Total"..recoupType.."PseudoRecoup"] * output[recoupTypeList[j].."RecoveryRateMod"] / output[recoupType.."RecoveryRateMod"], PseudoRecoupDuration }
end
end
end
output["Total"..recoupType.."PseudoRecoup"] = ((not modDB:Flag(nil, "UnaffectedBy"..recoupType.."Regen")) and output["Total"..recoupType.."PseudoRecoup"] or 0)
output[recoupType.."RecoupRecoveryMax"] = output["Total"..recoupType.."RecoupRecovery"] / recoupTime + output["Total"..recoupType.."PseudoRecoup"] / PseudoRecoupDuration + (extraPseudoRecoup[recoupType] and (extraPseudoRecoup[recoupType][1] / extraPseudoRecoup[recoupType][2]) or 0)
output[recoupType.."RecoupRecoveryAvg"] = output["Total"..recoupType.."RecoupRecovery"] / (output["EHPsurvivalTime"] + recoupTime) + output["Total"..recoupType.."PseudoRecoup"] / (output["EHPsurvivalTime"] + PseudoRecoupDuration) + (extraPseudoRecoup[recoupType] and (extraPseudoRecoup[recoupType][1] / (output["EHPsurvivalTime"] + extraPseudoRecoup[recoupType][2])) or 0)
if breakdown then
local multipleTypes = 0
breakdown[recoupType.."RecoupRecoveryMax"] = { }
Expand Down Expand Up @@ -2715,8 +2758,24 @@ function calcs.buildDefenceEstimations(env, actor)
t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("= %d ^8(total damage recoup amount)", output["Total"..recoupType.."RecoupRecovery"]))
breakdown[recoupType.."RecoupRecoveryAvg"] = copyTable(breakdown[recoupType.."RecoupRecoveryMax"])
t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("/ %.2f ^8(over %d seconds)", recoupTime, recoupTime))
if output["Total"..recoupType.."PseudoRecoup"] > 0 then
t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("+ %.2f ^8(total damage mitigated pseudo recoup amount)", output["Total"..recoupType.."PseudoRecoup"]))
t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("/ %.2f ^8(over %d seconds)", PseudoRecoupDuration, PseudoRecoupDuration))
end
if extraPseudoRecoup[recoupType] then
t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("+ %.2f ^8(total damage mitigated pseudo recoup amount)", extraPseudoRecoup[recoupType][1]))
t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("/ %.2f ^8(over %d seconds)", extraPseudoRecoup[recoupType][2], extraPseudoRecoup[recoupType][2]))
end
t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("= %.2f per second ^8", output[recoupType.."RecoupRecoveryMax"]))
t_insert(breakdown[recoupType.."RecoupRecoveryAvg"], s_format("/ %.2f ^8(total time of the recoup (survival time + %d seconds))", (output["EHPsurvivalTime"] + recoupTime), recoupTime))
if output["Total"..recoupType.."PseudoRecoup"] > 0 then
t_insert(breakdown[recoupType.."RecoupRecoveryAvg"], s_format("+ %.2f ^8(total damage mitigated pseudo recoup amount)", output["Total"..recoupType.."PseudoRecoup"]))
t_insert(breakdown[recoupType.."RecoupRecoveryAvg"], s_format("/ %.2f ^8(total time of the recoup (survival time + %d seconds)", (output["EHPsurvivalTime"] + PseudoRecoupDuration), PseudoRecoupDuration))
end
if extraPseudoRecoup[recoupType] then
t_insert(breakdown[recoupType.."RecoupRecoveryAvg"], s_format("+ %.2f ^8(total damage mitigated pseudo recoup amount)", extraPseudoRecoup[recoupType][1]))
t_insert(breakdown[recoupType.."RecoupRecoveryAvg"], s_format("/ %.2f ^8(total time of the recoup (survival time + %d seconds)", (output["EHPsurvivalTime"] + extraPseudoRecoup[recoupType][2]), extraPseudoRecoup[recoupType][2]))
end
t_insert(breakdown[recoupType.."RecoupRecoveryAvg"], s_format("= %.2f per second ^8", output[recoupType.."RecoupRecoveryAvg"]))
end
end
Expand Down
20 changes: 16 additions & 4 deletions src/Modules/CalcSections.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,12 @@ return {
{ label = "Recovery modifiers", modName = "LifeRecoveryRate" },
{ label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } },
}, },
{ label = "Dmg. Mit. Regen", haveOutput = "PhysicalDamageMitigatedLifePseudoRecoup", { format = "{1:output:PhysicalDamageMitigatedLifePseudoRecoup}%", { breakdown = "PhysicalDamageMitigatedLifePseudoRecoup" },
{ label = "Sources", modName = "PhysicalDamageMitigatedLifePseudoRecoup" },
{ label = "Increased Life Regeneration Rate", modName = { "LifeRegen" }, modType = "INC" },
{ label = "More Life Regeneration Rate", modName = { "LifeRegen" }, modType = "MORE" },
{ label = "Recovery modifiers", modName = "LifeRecoveryRate" },
}, },
} }
} },
{ 1, "Mana", 2, colorCodes.MANA, {{ defaultCollapsed = false, label = "Mana", data = {
Expand Down Expand Up @@ -1461,6 +1467,12 @@ return {
{ label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" },
{ label = "FasterRecoup", modName = "3SecondRecoup" },
}, },
{ label = "Dmg. Mit. Regen", haveOutput = "PhysicalDamageMitigatedEnergyShieldPseudoRecoup", { format = "{1:output:PhysicalDamageMitigatedEnergyShieldPseudoRecoup}%", { breakdown = "PhysicalDamageMitigatedEnergyShieldPseudoRecoup" },
{ label = "Sources", modName = "PhysicalDamageMitigatedEnergyShieldPseudoRecoup" },
{ label = "Increased Energy Shield Regeneration Rate", modName = { "EnergyShieldRegen" }, modType = "INC" },
{ label = "More Energy Shield Regeneration Rate", modName = { "EnergyShieldRegen" }, modType = "MORE" },
{ label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" },
}, },
} }
} },
{ 1, "Ward", 2, colorCodes.WARD, {{ defaultCollapsed = false, label = "Ward", data = {
Expand Down Expand Up @@ -2175,7 +2187,7 @@ return {
{ label = "Recoup Max.", haveOutput = "anyRecoup",
{ format = "{0:output:LifeRecoupRecoveryMax}",
{ breakdown = "LifeRecoupRecoveryMax" },
{ label = "Sources", modName = { "LifeRecoup", "PhysicalLifeRecoup", "LightningLifeRecoup", "ColdLifeRecoup", "FireLifeRecoup", "ChaosLifeRecoup" } },
{ label = "Sources", modName = { "LifeRecoup", "PhysicalLifeRecoup", "LightningLifeRecoup", "ColdLifeRecoup", "FireLifeRecoup", "ChaosLifeRecoup", "PhysicalDamageMitigatedLifePseudoRecoup" } },
{ label = "Recovery modifiers", modName = "LifeRecoveryRate" },
{ label = "Faster Recoup", modName = "3SecondRecoup" },
},
Expand All @@ -2187,15 +2199,15 @@ return {
},
{ format = "{0:output:EnergyShieldRecoupRecoveryMax}",
{ breakdown = "EnergyShieldRecoupRecoveryMax" },
{ label = "Sources", modName = { "EnergyShieldRecoup", "ElementalEnergyShieldRecoup" } },
{ label = "Sources", modName = { "EnergyShieldRecoup", "ElementalEnergyShieldRecoup", "PhysicalDamageMitigatedEnergyShieldPseudoRecoup" } },
{ label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" },
{ label = "Faster Recoup", modName = "3SecondRecoup" },
},
},
{ label = "Recoup Avg.", haveOutput = "anyRecoup",
{ format = "{0:output:LifeRecoupRecoveryAvg}",
{ breakdown = "LifeRecoupRecoveryAvg" },
{ label = "Sources", modName = { "LifeRecoup", "PhysicalLifeRecoup", "LightningLifeRecoup", "ColdLifeRecoup", "FireLifeRecoup", "ChaosLifeRecoup" } },
{ label = "Sources", modName = { "LifeRecoup", "PhysicalLifeRecoup", "LightningLifeRecoup", "ColdLifeRecoup", "FireLifeRecoup", "ChaosLifeRecoup", "PhysicalDamageMitigatedLifePseudoRecoup" } },
{ label = "Recovery modifiers", modName = "LifeRecoveryRate" },
{ label = "Faster Recoup", modName = "3SecondRecoup" },
},
Expand All @@ -2207,7 +2219,7 @@ return {
},
{ format = "{0:output:EnergyShieldRecoupRecoveryAvg}",
{ breakdown = "EnergyShieldRecoupRecoveryAvg" },
{ label = "Sources", modName = { "EnergyShieldRecoup", "ElementalEnergyShieldRecoup" } },
{ label = "Sources", modName = { "EnergyShieldRecoup", "ElementalEnergyShieldRecoup", "PhysicalDamageMitigatedEnergyShieldPseudoRecoup" } },
{ label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" },
{ label = "Faster Recoup", modName = "3SecondRecoup" },
},
Expand Down
5 changes: 5 additions & 0 deletions src/Modules/ModParser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4141,6 +4141,11 @@ local specialModList = {
["(%d+)%% of damage taken while affected by clarity recouped as mana"] = function(num) return { mod("ManaRecoup", "BASE", num, { type = "Condition", var = "AffectedByClarity" }) } end,
["recoup effects instead occur over 3 seconds"] = { flag("3SecondRecoup") },
["life recoup effects instead occur over 3 seconds"] = { flag("3SecondLifeRecoup") },
["([%d%.]+)%% of physical damage prevented from hits in the past (%d+) seconds is regenerated as life per second"] = function(num, _, duration) return {
mod("PhysicalDamageMitigatedLifePseudoRecoup", "BASE", num * duration),
mod("PhysicalDamageMitigatedLifePseudoRecoupDuration", "BASE", duration),
} end,
["([%d%.]+)%% of physical damage prevented from hits recently is regenerated as energy shield per second"] = function(num) return { mod("PhysicalDamageMitigatedEnergyShieldPseudoRecoup", "BASE", num * 4) } end,
["cannot leech or regenerate mana"] = { flag("NoManaRegen"), flag("CannotLeechMana") },
["right ring slot: you cannot regenerate mana" ] = { flag("NoManaRegen", { type = "SlotNumber", num = 2 }) },
["y?o?u? ?cannot recharge energy shield"] = { flag("NoEnergyShieldRecharge") },
Expand Down

0 comments on commit 2257923

Please sign in to comment.