Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for pseudo recoup like divine shield and juggernaut #6833

Merged
merged 2 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/Data/ModCache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1896,9 +1896,8 @@ c["1.5% of Lightning Damage is Leeched as Energy Shield while affected by Wrath"
c["1.5% of Lightning Damage is Leeched as Mana while affected by Wrath"]={{[1]={[1]={type="Condition",var="AffectedByWrath"},flags=0,keywordFlags=0,name="LightningDamageManaLeech",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 @@ -4126,8 +4125,7 @@ c["3% more Spell Damage per Power Charge"]={{[1]={[1]={type="Multiplier",var="Po
c["3% of Attack Damage leeched as Life against Bleeding Enemies"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="Bleeding"},flags=1,keywordFlags=0,name="DamageLifeLeech",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 @@ -1141,6 +1141,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 @@ -2497,14 +2527,16 @@ function calcs.buildDefenceEstimations(env, actor)
if output["anyRecoup"] > 0 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 @@ -2515,8 +2547,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 @@ -2546,8 +2589,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 @@ -1384,6 +1384,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 @@ -1444,6 +1450,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 @@ -2136,7 +2148,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 @@ -2148,15 +2160,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 @@ -2168,7 +2180,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 @@ -3880,6 +3880,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
Loading