From 76352471afda47fa7956ea0eeea8e3eb3e499fd2 Mon Sep 17 00:00:00 2001 From: Default global Date: Sun, 26 Jan 2025 21:54:10 -0800 Subject: [PATCH 1/2] Re-apply recoup upgrades from PR #376 , except for Petrified Blood removal --- src/Data/ModCache.lua | 4 +- src/Modules/CalcDefence.lua | 197 ++++++++++++++++++----------------- src/Modules/CalcSections.lua | 59 +++++------ src/Modules/ModParser.lua | 2 + 4 files changed, 134 insertions(+), 128 deletions(-) diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index ff1fe14290..8e382c8ed4 100755 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -1510,7 +1510,7 @@ c["25% increased chance to Shock"]={{[1]={flags=0,keywordFlags=0,name="EnemyShoc c["25% increased chance to inflict Ailments against Rare or Unique Enemies"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="RareOrUnique"},flags=0,keywordFlags=0,name="AilmentChance",type="INC",value=25}},nil} c["25% increased chance to inflict Ailments with Projectiles"]={{[1]={flags=1024,keywordFlags=0,name="AilmentChance",type="INC",value=25}},nil} c["25% increased maximum Energy Shield"]={{[1]={[1]={type="Global"},flags=0,keywordFlags=0,name="EnergyShield",type="INC",value=25}},nil} -c["25% increased speed of Recoup Effects"]={{[1]={flags=0,keywordFlags=0,name="LocalEffect",type="INC",value=25}}," speed of Recoup s "} +c["25% increased speed of Recoup Effects"]={{[1]={flags=0,keywordFlags=0,name="RecoupSpeed",type="INC",value=25}},nil} c["25% less Magnitude of Chill you inflict"]={{[1]={flags=0,keywordFlags=0,name="EnemyChillMagnitude",type="MORE",value=-25}},nil} c["25% more Melee Critical Hit Chance while Blinded"]={{[1]={[1]={type="Condition",var="Blinded"},[2]={neg=true,type="Condition",var="CannotBeBlinded"},flags=256,keywordFlags=0,name="CritChance",type="MORE",value=25}},nil} c["25% more Skill Speed while Off Hand is empty and you have"]={{[1]={[1]={type="Condition",var="OffHandIsEmpty"},flags=0,keywordFlags=0,name="Speed",type="MORE",value=25},[2]={[1]={type="Condition",var="OffHandIsEmpty"},flags=0,keywordFlags=0,name="WarcrySpeed",type="MORE",value=25}}," and you have "} @@ -2027,7 +2027,7 @@ c["50% of Cold and Lightning Damage taken as Fire Damage"]={{[1]={flags=0,keywor c["50% of Damage taken Recouped as Mana"]={{[1]={flags=0,keywordFlags=0,name="ManaRecoup",type="BASE",value=50}},nil} c["50% of Elemental Damage taken as Chaos Damage"]={{[1]={flags=0,keywordFlags=0,name="ElementalDamageTakenAsChaos",type="BASE",value=50}},nil} c["50% of Maximum Life Converted to Energy Shield"]={{[1]={flags=0,keywordFlags=0,name="LifeConvertToEnergyShield",type="BASE",value=50}},nil} -c["50% of Physical Damage prevented Recouped as Life"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="BASE",value=50}}," prevented Recouped as Life "} +c["50% of Physical Damage prevented Recouped as Life"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamageMitigatedLifeRecoup",type="BASE",value=50}},nil} c["50% of charges used by Charms granted to your Life Flasks"]={{[1]={[3]={type="Multiplier",var="AvgCharmChargesUsed"},flags=0,keywordFlags=0,name="FlaskChargesGained",type="MORE",value=0.5}},nil} c["50% of your Life Regeneration is granted to Allies in your Presence"]={{[1]={flags=0,keywordFlags=0,name="ExtraAura",type="LIST",value={mod={flags=0,keywordFlags=0,name="LifeRegen",type="BASE",value=50},onlyAllies=true}}}," your is granted to "} c["50% reduced Chill Duration on you"]={{[1]={flags=0,keywordFlags=0,name="SelfChillDuration",type="INC",value=-50}},nil} diff --git a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua index 72115a9511..d18a013a8e 100644 --- a/src/Modules/CalcDefence.lua +++ b/src/Modules/CalcDefence.lua @@ -567,6 +567,8 @@ function calcs.defence(env, actor) local condList = modDB.conditions + local effectiveRecoupTime = ((modDB:Flag(nil, "4SecondRecoup")) and 4 or 8) / (1 + modDB:Sum("INC", nil, "RecoupSpeed") / 100) + -- Action Speed output.ActionSpeedMod = calcs.actionSpeedMod(actor) @@ -1459,8 +1461,9 @@ function calcs.defence(env, actor) output.EnergyShieldRecharge = 0 end - -- recoup + -- recoup magnitude do + -- check if player *Recoup mods exist, apply *RecoveryRateMods output["anyRecoup"] = 0 local recoupTypeList = {"Life", "Mana", "EnergyShield"} for _, recoupType in ipairs(recoupTypeList) do @@ -1472,14 +1475,17 @@ function calcs.defence(env, actor) breakdown[recoupType.."Recoup"] = { s_format("%d%% ^8(base)", baseRecoup), s_format("* %.2f ^8(recovery rate modifier)", output[recoupType.."RecoveryRateMod"]), - s_format("= %.1f%% over %d seconds", output[recoupType.."Recoup"], (modDB:Flag(nil, "4Second"..recoupType.."Recoup") or modDB:Flag(nil, "4SecondRecoup")) and 4 or 8) + s_format("= %.1f%% over %.2f seconds", output[recoupType.."Recoup"], effectiveRecoupTime) } else - breakdown[recoupType.."Recoup"] = { s_format("%d%% over %d seconds", output[recoupType.."Recoup"], (modDB:Flag(nil, "4Second"..recoupType.."Recoup") or modDB:Flag(nil, "4SecondRecoup")) and 4 or 8) } + breakdown[recoupType.."Recoup"] = { + s_format("%d%% over %.2f seconds", output[recoupType.."Recoup"], effectiveRecoupTime) + } end end end + -- check for elemental -> ES recoup (in PoE2 this is Stormweaver Ascendancy: Heart of the Storm) local ElementalEnergyShieldRecoup = modDB:Sum("BASE", nil, "ElementalEnergyShieldRecoup") output.ElementalEnergyShieldRecoup = ElementalEnergyShieldRecoup * output.EnergyShieldRecoveryRateMod output["anyRecoup"] = output["anyRecoup"] + output.ElementalEnergyShieldRecoup @@ -1488,13 +1494,14 @@ function calcs.defence(env, actor) breakdown.ElementalEnergyShieldRecoup = { s_format("%d%% ^8(base)", ElementalEnergyShieldRecoup), s_format("* %.2f ^8(recovery rate modifier)", output.EnergyShieldRecoveryRateMod), - s_format("= %.1f%% over %d seconds", output.ElementalEnergyShieldRecoup, (modDB:Flag(nil, "4SecondEnergyShieldRecoup") or modDB:Flag(nil, "4SecondRecoup")) and 4 or 8) + s_format("= %.1f%% over %d seconds", output.ElementalEnergyShieldRecoup, effectiveRecoupTime) } else - breakdown.ElementalEnergyShieldRecoup = { s_format("%d%% over %d seconds", output.ElementalEnergyShieldRecoup, (modDB:Flag(nil, "4SecondEnergyShieldRecoup") or modDB:Flag(nil, "4SecondRecoup")) and 4 or 8) } + breakdown.ElementalEnergyShieldRecoup = { s_format("%d%% over %.2f seconds", output.ElementalEnergyShieldRecoup, effectiveRecoupTime) } end end + -- check for elemental life recoup effects, eg ColdLifeRecoup, apply LifeRecoveryRateMod for _, damageType in ipairs(dmgTypeList) do local LifeRecoup = modDB:Sum("BASE", nil, damageType.."LifeRecoup") output[damageType.."LifeRecoup"] = LifeRecoup * output.LifeRecoveryRateMod @@ -1504,39 +1511,28 @@ function calcs.defence(env, actor) breakdown[damageType.."LifeRecoup"] = { s_format("%d%% ^8(base)", LifeRecoup), s_format("* %.2f ^8(recovery rate modifier)", output.LifeRecoveryRateMod), - s_format("= %.1f%% over %d seconds", output[damageType.."LifeRecoup"], (modDB:Flag(nil, "4SecondLifeRecoup") or modDB:Flag(nil, "4SecondRecoup")) and 4 or 8) + s_format("= %.1f%% over %d seconds", output[damageType.."LifeRecoup"], effectiveRecoupTime) } else - breakdown[damageType.."LifeRecoup"] = { s_format("%d%% over %d seconds", output[damageType.."LifeRecoup"], (modDB:Flag(nil, "4SecondLifeRecoup") or modDB:Flag(nil, "4SecondRecoup")) and 4 or 8) } + breakdown[damageType.."LifeRecoup"] = { s_format("%d%% over %.2f seconds", output[damageType.."LifeRecoup"], effectiveRecoupTime) } end end end - -- pseudo recoup (eg %physical damage prevented from hits regenerated) + -- mitigation recoup (eg % physical damage prevented from hits recouped) for _, resource in ipairs(recoupTypeList) do + -- note: tested NoLifeRegen effect on mitigation recoup in PoE2 (using Titanrot Cataphract) on Jan 18 2025 + -- it does indeed block mitigation recoup - but not normal recoup... 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"] + -- phys prevented from hits recouped + local PhysicalDamageMitigatedRecoup = modDB:Sum("BASE", nil, "PhysicalDamageMitigated"..resource.."Recoup") + if PhysicalDamageMitigatedRecoup > 0 then + output["PhysicalDamageMitigated"..resource.."Recoup"] = PhysicalDamageMitigatedRecoup * output[resource.."RecoveryRateMod"] + output["anyRecoup"] = output["anyRecoup"] + output["PhysicalDamageMitigated"..resource.."Recoup"] 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"])) + breakdown["PhysicalDamageMitigated"..resource.."Recoup"] = { } + t_insert(breakdown["PhysicalDamageMitigated"..resource.."Recoup"], s_format("%d%% ^8(base)", PhysicalDamageMitigatedRecoup)) + t_insert(breakdown["PhysicalDamageMitigated"..resource.."Recoup"], s_format("= %.1f%% over %.2f seconds", output["PhysicalDamageMitigated"..resource.."Recoup"], effectiveRecoupTime)) end end end @@ -1697,7 +1693,8 @@ function calcs.buildDefenceEstimations(env, actor) local condList = modDB.conditions local damageCategoryConfig = env.configInput.enemyDamageType or "Average" - + local effectiveRecoupTime = ((modDB:Flag(nil, "4SecondRecoup")) and 4 or 8) / (1 + modDB:Sum("INC", nil, "RecoupSpeed") / 100) + -- chance to not be hit calculations if damageCategoryConfig ~= "DamageOverTime" then local worstOf = env.configInput.EHPUnluckyWorstOf or 1 @@ -2997,45 +2994,47 @@ function calcs.buildDefenceEstimations(env, actor) end end - -- recoup + -- recoup value and breakdown if output["anyRecoup"] > 0 and damageCategoryConfig ~= "DamageOverTime" then local totalDamage = 0 local totalElementalDamage = 0 local totalPhysicalDamageMitigated = output["NumberOfMitigatedDamagingHits"] * (output.PhysicalTakenDamage - output.PhysicalTakenHit) - local extraPseudoRecoup = {} + local recoupAvgTime = output["EHPSurvivalTime"] + effectiveRecoupTime + for _, damageType in ipairs(dmgTypeList) do totalDamage = totalDamage + output[damageType.."RecoupableDamageTaken"] if isElemental[damageType] then totalElementalDamage = totalElementalDamage + output[damageType.."RecoupableDamageTaken"] end end + local recoupTypeList = {"Life", "Mana", "EnergyShield"} for i, recoupType in ipairs(recoupTypeList) do - local recoupTime = (modDB:Flag(nil, "4Second"..recoupType.."Recoup") or modDB:Flag(nil, "4SecondRecoup")) and 4 or 8 output["Total"..recoupType.."RecoupRecovery"] = (output[recoupType.."Recoup"] or 0) / 100 * totalDamage if (output["Elemental"..recoupType.."Recoup"] or 0) > 0 and totalElementalDamage > 0 then output["Total"..recoupType.."RecoupRecovery"] = output["Total"..recoupType.."RecoupRecovery"] + output["Elemental"..recoupType.."Recoup"] / 100 * totalElementalDamage end + -- eg FireLifeRecoup for _, damageType in ipairs(dmgTypeList) do if (output[damageType..recoupType.."Recoup"] or 0) > 0 and output[damageType.."RecoupableDamageTaken"] > 0 then output["Total"..recoupType.."RecoupRecovery"] = output["Total"..recoupType.."RecoupRecovery"] + output[damageType..recoupType.."Recoup"] / 100 * output[damageType.."RecoupableDamageTaken"] end end - 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 + + output["Total"..recoupType.."Recoup"] = (output["PhysicalDamageMitigated"..recoupType.."Recoup"] or 0) / 100 * totalPhysicalDamageMitigated + + local totalRecoup = output["Total"..recoupType.."RecoupRecovery"] + if output["Total"..recoupType.."Recoup"] > 0 then + totalRecoup = totalRecoup + output["Total"..recoupType.."Recoup"] 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) + + output[recoupType.."RecoupRecoveryMax"] = totalRecoup / effectiveRecoupTime + output[recoupType.."RecoupRecoveryAvg"] = totalRecoup / recoupAvgTime + if breakdown then local multipleTypes = 0 + + -- standard recoup types breakdown[recoupType.."RecoupRecoveryMax"] = { } if (output[recoupType.."Recoup"] or 0) > 0 then t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("%d ^8(total damage taken during ehp calcs)", totalDamage)) @@ -3046,93 +3045,101 @@ function calcs.buildDefenceEstimations(env, actor) if multipleTypes > 0 then t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("")) end - t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("%s%d ^8(total elemental damage taken during ehp calcs)", multipleTypes > 0 and "+" or "", totalDamage)) + t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("%s%d ^8(total elemental damage taken during ehp calcs)", multipleTypes > 0 and "+" or "", totalElementalDamage)) t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("* %.2f ^8(percent of damage recouped)", output["Elemental"..recoupType.."Recoup"] / 100)) multipleTypes = multipleTypes + 1 end + for _, damageType in ipairs(dmgTypeList) do if (output[damageType..recoupType.."Recoup"] or 0) > 0 and output[damageType.."RecoupableDamageTaken"] > 0 then if multipleTypes > 0 then t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("")) end - t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("%s%d ^8(total %s damage taken during ehp calcs)", multipleTypes > 0 and "+" or "", totalDamage, damageType)) + t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("%s%d ^8(total %s damage taken during ehp calcs)", multipleTypes > 0 and "+" or "", output[damageType.."RecoupableDamageTaken"], damageType)) t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("* %.2f ^8(percent of damage recouped)", output[damageType..recoupType.."Recoup"] / 100)) multipleTypes = multipleTypes + 1 end end - 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])) + + if output["Total"..recoupType.."Recoup"] > 0 then + t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("")) + t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("+ %.2f ^8(total Physical damage mitigated)", totalPhysicalDamageMitigated)) + t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("* %.2f ^8(percent Physical mitigated as %s)", output["PhysicalDamageMitigated"..recoupType.."Recoup"] / 100, recoupType)) + t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("+ %.2f ^8(total damage mitigated recoup amount)", output["Total"..recoupType.."Recoup"])) end + t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("")) + t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("= %d ^8(total damage recoup amount)", totalRecoup)) + + breakdown[recoupType.."RecoupRecoveryAvg"] = copyTable(breakdown[recoupType.."RecoupRecoveryMax"]) + + t_insert(breakdown[recoupType.."RecoupRecoveryMax"], s_format("/ %.2f ^8(over %.2f seconds)", effectiveRecoupTime, effectiveRecoupTime)) 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 ^8(total time of the recoup (%.2f sec survival time + %.2f sec recoup))", + recoupAvgTime, + output["EHPSurvivalTime"], + effectiveRecoupTime + )) t_insert(breakdown[recoupType.."RecoupRecoveryAvg"], s_format("= %.2f per second ^8", output[recoupType.."RecoupRecoveryAvg"])) end end end - -- petrified blood "degen" + -- Grasping Wounds + Petrified Blood "degen" if output.preventedLifeLossTotal > 0 and (output["LifeLossLostOverTime"] and output["LifeBelowHalfLossLostOverTime"]) then + local preventedDegenDuration = 4 + local preventedAvgTime = output["EHPSurvivalTime"] + preventedDegenDuration local LifeLossBelowHalfLost = modDB:Sum("BASE", nil, "LifeLossBelowHalfLost") / 100 - output["LifeLossLostMax"] = (output["LifeLossLostOverTime"] + output["LifeBelowHalfLossLostOverTime"] * LifeLossBelowHalfLost) / 4 - output["LifeLossLostAvg"] = (output["LifeLossLostOverTime"] + output["LifeBelowHalfLossLostOverTime"] * LifeLossBelowHalfLost) / (output["EHPSurvivalTime"] + 4) + + output["LifeLossLostMax"] = (output["LifeLossLostOverTime"] + output["LifeBelowHalfLossLostOverTime"] * LifeLossBelowHalfLost) / preventedDegenDuration + output["LifeLossLostAvg"] = (output["LifeLossLostOverTime"] + output["LifeBelowHalfLossLostOverTime"] * LifeLossBelowHalfLost) / preventedAvgTime + if breakdown then breakdown["LifeLossLostMax"] = { } + breakdown["LifeLossLostAvg"] = { } + if output["LifeLossLostOverTime"] ~= 0 then - t_insert(breakdown["LifeLossLostMax"], s_format("( %d ^8(total damage prevented by Progenesis)", output["LifeLossLostOverTime"])) + t_insert(breakdown["LifeLossLostMax"], s_format("( %d ^8(total damage prevented by Grasping Wounds)", output["LifeLossLostOverTime"])) + t_insert(breakdown["LifeLossLostAvg"], s_format("( %d ^8(total damage prevented by Grasping Wounds)", output["LifeLossLostOverTime"])) end if output["LifeBelowHalfLossLostOverTime"] ~= 0 then t_insert(breakdown["LifeLossLostMax"], s_format("%s %d ^8(total damage prevented by petrified blood)", output["LifeLossLostOverTime"] ~= 0 and "+" or "(", output["LifeBelowHalfLossLostOverTime"])) t_insert(breakdown["LifeLossLostMax"], s_format("* %.2f ^8(percent of damage taken from petrified blood)", LifeLossBelowHalfLost)) - end - t_insert(breakdown["LifeLossLostMax"], s_format(") / %.2f ^8(over 4 seconds)", 4)) - t_insert(breakdown["LifeLossLostMax"], s_format("= %.2f per second", output["LifeLossLostMax"])) - breakdown["LifeLossLostAvg"] = { } - if output["LifeLossLostOverTime"] ~= 0 then - t_insert(breakdown["LifeLossLostAvg"], s_format("( %d ^8(total damage prevented by Progenesis)", output["LifeLossLostOverTime"])) - end - if output["LifeBelowHalfLossLostOverTime"] ~= 0 then t_insert(breakdown["LifeLossLostAvg"], s_format("%s %d ^8(total damage prevented by petrified blood)", output["LifeLossLostOverTime"] ~= 0 and "+" or "(", output["LifeBelowHalfLossLostOverTime"])) t_insert(breakdown["LifeLossLostAvg"], s_format("* %.2f ^8(percent of damage taken from petrified blood)", LifeLossBelowHalfLost)) end - t_insert(breakdown["LifeLossLostAvg"], s_format(") / %.2f ^8(total time of the degen (survival time + 4 seconds))", (output["EHPSurvivalTime"] + 4))) + + t_insert(breakdown["LifeLossLostMax"], s_format(") / %.2f ^8(over %d seconds)", preventedDegenDuration, preventedDegenDuration)) + t_insert(breakdown["LifeLossLostMax"], s_format("= %.2f per second", output["LifeLossLostMax"])) + + t_insert(breakdown["LifeLossLostAvg"], s_format( + ") / %.2f ^8(total time of the degen (%.2f survival time + %d seconds))", + preventedAvgTime, + output["EHPSurvivalTime"], + preventedDegenDuration + )) t_insert(breakdown["LifeLossLostAvg"], s_format("= %.2f per second", output["LifeLossLostAvg"])) end end - -- net recovery over time from enemy hits - if (output["LifeRecoupRecoveryAvg"] or 0) > 0 or output.preventedLifeLossTotal > 0 then + -- If there is life recoup and preventedLifeLoss (Grasping Wounds), add per second sum in Calcs breakdown + if (output["LifeRecoupRecoveryAvg"] or 0) > 0 and output.preventedLifeLossTotal > 0 then + output["showNetRecoup"] = true + output["netLifeRecoupAndLossLostOverTimeMax"] = (output["LifeRecoupRecoveryMax"] or 0) - (output["LifeLossLostMax"] or 0) output["netLifeRecoupAndLossLostOverTimeAvg"] = (output["LifeRecoupRecoveryAvg"] or 0) - (output["LifeLossLostAvg"] or 0) - if (output["LifeRecoupRecoveryAvg"] or 0) > 0 and output.preventedLifeLossTotal > 0 then - output["showNetRecoup"] = true - if breakdown then - breakdown["netLifeRecoupAndLossLostOverTimeMax"] = { - s_format("%.2f ^8(total life recouped per second)", output["LifeRecoupRecoveryMax"]), - s_format("- %.2f ^8(total life taken over time per second)", output["LifeLossLostMax"]), - s_format("= %.2f per second", output["netLifeRecoupAndLossLostOverTimeMax"]), - } - breakdown["netLifeRecoupAndLossLostOverTimeAvg"] = { - s_format("%.2f ^8(total life recouped per second)", output["LifeRecoupRecoveryAvg"]), - s_format("- %.2f ^8(total life taken over time per second)", output["LifeLossLostAvg"]), - s_format("= %.2f per second", output["netLifeRecoupAndLossLostOverTimeAvg"]), - } - end + if breakdown then + breakdown["netLifeRecoupAndLossLostOverTimeMax"] = { + s_format("%.2f ^8(total life recouped per second)", output["LifeRecoupRecoveryMax"]), + s_format("- %.2f ^8(total life taken over time per second)", output["LifeLossLostMax"]), + s_format("= %.2f per second", output["netLifeRecoupAndLossLostOverTimeMax"]), + } + breakdown["netLifeRecoupAndLossLostOverTimeAvg"] = { + s_format("%.2f ^8(total life recouped per second)", output["LifeRecoupRecoveryAvg"]), + s_format("- %.2f ^8(total life taken over time per second)", output["LifeLossLostAvg"]), + s_format("= %.2f per second", output["netLifeRecoupAndLossLostOverTimeAvg"]), + } end end diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index 82ed8e053b..bc4363d050 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -1422,38 +1422,37 @@ return { { label = "Recoup", haveOutput = "LifeRecoup", { format = "{1:output:LifeRecoup}%", { breakdown = "LifeRecoup" }, { label = "Sources", modName = "LifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, - { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, { label = "Phys Recoup", haveOutput = "PhysicalLifeRecoup", { format = "{1:output:PhysicalLifeRecoup}%", { breakdown = "PhysicalLifeRecoup" }, { label = "Sources", modName = "PhysicalLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, - { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, - { label = "Light Recoup", haveOutput = "LightningLifeRecoup", { format = "{1:output:LightningLifeRecoup}%", { breakdown = "LightningLifeRecoup" }, + { label = "Lightning Recoup", haveOutput = "LightningLifeRecoup", { format = "{1:output:LightningLifeRecoup}%", { breakdown = "LightningLifeRecoup" }, { label = "Sources", modName = "LightningLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, - { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, { label = "Cold Recoup", haveOutput = "ColdLifeRecoup", { format = "{1:output:ColdLifeRecoup}%", { breakdown = "ColdLifeRecoup" }, { label = "Sources", modName = "ColdLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, - { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, { label = "Fire Recoup", haveOutput = "FireLifeRecoup", { format = "{1:output:FireLifeRecoup}%", { breakdown = "FireLifeRecoup" }, { label = "Sources", modName = "FireLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, - { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, { label = "Chaos Recoup", haveOutput = "ChaosLifeRecoup", { format = "{1:output:ChaosLifeRecoup}%", { breakdown = "ChaosLifeRecoup" }, { label = "Sources", modName = "ChaosLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, - { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, - { 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 = "Mitigation Recoup", haveOutput = "PhysicalDamageMitigatedLifeRecoup", { format = "{1:output:PhysicalDamageMitigatedLifeRecoup}%", { breakdown = "PhysicalDamageMitigatedLifeRecoup" }, + { label = "Sources", modName = "PhysicalDamageMitigatedLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, } } } }, @@ -1477,7 +1476,7 @@ return { { label = "Recoup", haveOutput = "ManaRecoup", { format = "{1:output:ManaRecoup}%", { breakdown = "ManaRecoup" }, { label = "Sources", modName = "ManaRecoup" }, { label = "Recovery modifiers", modName = "ManaRecoveryRate" }, - { label = "FasterRecoup", modName = "3SecondRecoup" }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, } } } }, @@ -1521,17 +1520,15 @@ return { { label = "Recoup", haveOutput = "EnergyShieldRecoup", { format = "{1:output:EnergyShieldRecoup}%", { breakdown = "EnergyShieldRecoup" }, { label = "Sources", modName = "EnergyShieldRecoup" }, { label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" }, - { label = "FasterRecoup", modName = "3SecondRecoup" }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, { label = "Ele Recoup", haveOutput = "ElementalEnergyShieldRecoup", { format = "{1:output:ElementalEnergyShieldRecoup}%", { breakdown = "ElementalEnergyShieldRecoup" }, { label = "Sources", modName = "ElementalEnergyShieldRecoup" }, { label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" }, - { label = "FasterRecoup", modName = "3SecondRecoup" }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, - { 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 = "Mitigation Regen", haveOutput = "PhysicalDamageMitigatedEnergyShieldRecoup", { format = "{1:output:PhysicalDamageMitigatedEnergyShieldRecoup}%", { breakdown = "PhysicalDamageMitigatedEnergyShieldRecoup" }, + { label = "Sources", modName = "PhysicalDamageMitigatedEnergyShieldRecoup" }, { label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" }, }, }, } } @@ -2225,7 +2222,7 @@ return { { breakdown = "ChaosMaximumHitTaken" }, }, } -} }, { defaultCollapsed = true, label = "Recoup and Hit Taken Over Time", data = { +} }, { defaultCollapsed = true, label = "Net Recovery per Second", data = { colWidth = 190, extra = colorCodes.LIFE.."{0:output:netLifeRecoupAndLossLostOverTimeAvg}, "..colorCodes.MANA.."{0:output:ManaRecoupRecoveryAvg}, "..colorCodes.ES.."{0:output:EnergyShieldRecoupRecoveryAvg}", { @@ -2236,50 +2233,50 @@ return { { label = "Recoup Max.", haveOutput = "anyRecoup", { format = "{0:output:LifeRecoupRecoveryMax}", { breakdown = "LifeRecoupRecoveryMax" }, - { label = "Sources", modName = { "LifeRecoup", "PhysicalLifeRecoup", "LightningLifeRecoup", "ColdLifeRecoup", "FireLifeRecoup", "ChaosLifeRecoup", "PhysicalDamageMitigatedLifePseudoRecoup" } }, + { label = "Sources", modName = { "LifeRecoup", "PhysicalLifeRecoup", "LightningLifeRecoup", "ColdLifeRecoup", "FireLifeRecoup", "ChaosLifeRecoup", "PhysicalDamageMitigatedLifeRecoup" } }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, - { label = "Faster Recoup", modName = "3SecondRecoup" }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, { format = "{0:output:ManaRecoupRecoveryMax}", { breakdown = "ManaRecoupRecoveryMax" }, { label = "Sources", modName = "ManaRecoup" }, { label = "Recovery modifiers", modName = "ManaRecoveryRate" }, - { label = "Faster Recoup", modName = "3SecondRecoup" }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, { format = "{0:output:EnergyShieldRecoupRecoveryMax}", { breakdown = "EnergyShieldRecoupRecoveryMax" }, - { label = "Sources", modName = { "EnergyShieldRecoup", "ElementalEnergyShieldRecoup", "PhysicalDamageMitigatedEnergyShieldPseudoRecoup" } }, + { label = "Sources", modName = { "EnergyShieldRecoup", "ElementalEnergyShieldRecoup", "PhysicalDamageMitigatedEnergyShieldRecoup" } }, { label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" }, - { label = "Faster Recoup", modName = "3SecondRecoup" }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, { label = "Recoup Avg.", haveOutput = "anyRecoup", { format = "{0:output:LifeRecoupRecoveryAvg}", { breakdown = "LifeRecoupRecoveryAvg" }, - { label = "Sources", modName = { "LifeRecoup", "PhysicalLifeRecoup", "LightningLifeRecoup", "ColdLifeRecoup", "FireLifeRecoup", "ChaosLifeRecoup", "PhysicalDamageMitigatedLifePseudoRecoup" } }, + { label = "Sources", modName = { "LifeRecoup", "PhysicalLifeRecoup", "LightningLifeRecoup", "ColdLifeRecoup", "FireLifeRecoup", "ChaosLifeRecoup", "PhysicalDamageMitigatedLifeRecoup" } }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, - { label = "Faster Recoup", modName = "3SecondRecoup" }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, { format = "{0:output:ManaRecoupRecoveryAvg}", { breakdown = "ManaRecoupRecoveryAvg" }, { label = "Sources", modName = "ManaRecoup" }, { label = "Recovery modifiers", modName = "ManaRecoveryRate" }, - { label = "Faster Recoup", modName = "3SecondRecoup" }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, { format = "{0:output:EnergyShieldRecoupRecoveryAvg}", { breakdown = "EnergyShieldRecoupRecoveryAvg" }, - { label = "Sources", modName = { "EnergyShieldRecoup", "ElementalEnergyShieldRecoup", "PhysicalDamageMitigatedEnergyShieldPseudoRecoup" } }, + { label = "Sources", modName = { "EnergyShieldRecoup", "ElementalEnergyShieldRecoup", "PhysicalDamageMitigatedEnergyShieldRecoup" } }, { label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" }, - { label = "Faster Recoup", modName = "3SecondRecoup" }, + { label = "Recoup Speed", modName = { "4SecondRecoup", "RecoupSpeed" } }, }, }, - { label = "Hit Over Time Max.", haveOutput = "preventedLifeLossTotal", + { label = "Hit Over Time Max.", haveOutput = "preventedLifeLossTotal", color = colorCodes.LIFE, { format = "{0:output:LifeLossLostMax}", { breakdown = "LifeLossLostMax" }, { modName = { "LifeLossPrevented", "LifeLossBelowHalfPrevented", "LifeLossBelowHalfLost" } }, }, }, - { label = "Hit Over Time Avg.", haveOutput = "preventedLifeLossTotal", + { label = "Hit Over Time Avg.", haveOutput = "preventedLifeLossTotal", color = colorCodes.LIFE, { format = "{0:output:LifeLossLostAvg}", { breakdown = "LifeLossLostAvg" }, { modName = { "LifeLossPrevented", "LifeLossBelowHalfPrevented", "LifeLossBelowHalfLost" } }, diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index df9b2a3980..45e9fa01bb 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -377,6 +377,8 @@ local modNameList = { ["elemental damage taken recouped as energy shield"] = { "LightningEnergyShieldRecoup", "ColdEnergyShieldRecoup", "FireEnergyShieldRecoup" }, ["damage taken recouped as mana"] = "ManaRecoup", ["damage taken recouped as life, mana and energy shield"] = { "LifeRecoup", "EnergyShieldRecoup", "ManaRecoup" }, + ["speed of recoup effects"] = "RecoupSpeed", + ["physical damage prevented recouped as life"] = "PhysicalDamageMitigatedLifeRecoup", -- Stun/knockback modifiers ["stun recovery"] = "StunRecovery", ["stun and block recovery"] = "StunRecovery", From 379822e613743456e887be6dbc7810300bb83140 Mon Sep 17 00:00:00 2001 From: Default global Date: Sun, 26 Jan 2025 22:08:32 -0800 Subject: [PATCH 2/2] Fix missing net value in display --- src/Modules/CalcDefence.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua index d18a013a8e..32535e6c5d 100644 --- a/src/Modules/CalcDefence.lua +++ b/src/Modules/CalcDefence.lua @@ -3124,11 +3124,10 @@ function calcs.buildDefenceEstimations(env, actor) end -- If there is life recoup and preventedLifeLoss (Grasping Wounds), add per second sum in Calcs breakdown + output["netLifeRecoupAndLossLostOverTimeMax"] = (output["LifeRecoupRecoveryMax"] or 0) - (output["LifeLossLostMax"] or 0) + output["netLifeRecoupAndLossLostOverTimeAvg"] = (output["LifeRecoupRecoveryAvg"] or 0) - (output["LifeLossLostAvg"] or 0) if (output["LifeRecoupRecoveryAvg"] or 0) > 0 and output.preventedLifeLossTotal > 0 then output["showNetRecoup"] = true - - output["netLifeRecoupAndLossLostOverTimeMax"] = (output["LifeRecoupRecoveryMax"] or 0) - (output["LifeLossLostMax"] or 0) - output["netLifeRecoupAndLossLostOverTimeAvg"] = (output["LifeRecoupRecoveryAvg"] or 0) - (output["LifeLossLostAvg"] or 0) if breakdown then breakdown["netLifeRecoupAndLossLostOverTimeMax"] = { s_format("%.2f ^8(total life recouped per second)", output["LifeRecoupRecoveryMax"]),