Add resource lost information to enemy damage breakdown (#8594)

This commit is contained in:
Edvinas-Smita
2025-04-09 21:00:25 +03:00
committed by GitHub
parent ec17d59ed8
commit 7492bd057c

View File

@@ -134,7 +134,8 @@ function calcs.takenHitFromDamage(rawDamage, damageType, actor)
local takenFlat = output[damageConvertedType.."takenFlat"]
if convertPercent > 0 or takenFlat ~= 0 then
local convertedDamage = rawDamage * convertPercent / 100
local reducedDamage = round(m_max(convertedDamage * damageMitigationMultiplierForType(convertedDamage, damageConvertedType) + takenFlat, 0) * output[damageConvertedType .."AfterReductionTakenHitMulti"]) * (1 - output["VaalArcticArmourMitigation"])
local vaalArctic = m_min(-modDB:Sum("MORE", nil, "VaalArcticArmourMitigation") / 100, 1)
local reducedDamage = round(m_max(convertedDamage * damageMitigationMultiplierForType(convertedDamage, damageConvertedType) + takenFlat, 0) * output[damageConvertedType .."AfterReductionTakenHitMulti"]) * (1 - vaalArctic)
receivedDamageSum = receivedDamageSum + reducedDamage
damages[damageConvertedType] = (reducedDamage > 0 or convertPercent > 0) and reducedDamage or nil
end
@@ -169,7 +170,7 @@ function calcs.reducePoolsByDamage(poolTable, damageTable, actor)
alliesTakenBeforeYou["frostShield"] = { remaining = output.FrostShieldLife, percent = output.FrostShieldDamageMitigation / 100 }
end
if output.TotalSpectreLife then
alliesTakenBeforeYou["specters"] = { remaining = output.TotalSpectreLife, percent = output.SpectreAllyDamageMitigation / 100 }
alliesTakenBeforeYou["spectres"] = { remaining = output.TotalSpectreLife, percent = output.SpectreAllyDamageMitigation / 100 }
end
if output.TotalTotemLife then
alliesTakenBeforeYou["totems"] = { remaining = output.TotalTotemLife, percent = output.TotemAllyDamageMitigation / 100 }
@@ -214,121 +215,141 @@ function calcs.reducePoolsByDamage(poolTable, damageTable, actor)
local LifeLossLostOverTime = poolTbl.LifeLossLostOverTime or 0
local LifeBelowHalfLossLostOverTime = poolTbl.LifeBelowHalfLossLostOverTime or 0
local overkillDamage = 0
local resourcesLostToTypeDamage = { Physical = { }, Lightning = { }, Cold = { }, Fire = { }, Chaos = { } }
local MoMPoolRemaining = m_huge
local esPoolRemaining = m_huge
for damageType, damage in pairs(damageTable) do
local damageRemainder = damage
for _, allyValues in pairs(alliesTakenBeforeYou) do
if not allyValues.damageType or allyValues.damageType == damageType then
if allyValues.remaining > 0 then
local tempDamage = m_min(damageRemainder * allyValues.percent, allyValues.remaining)
allyValues.remaining = m_floor(allyValues.remaining - tempDamage)
damageRemainder = damageRemainder - tempDamage
for _, damageType in ipairs(dmgTypeList) do
local damageRemainder = damageTable[damageType]
if damageRemainder then
for ally, allyValues in pairs(alliesTakenBeforeYou) do
if not allyValues.damageType or allyValues.damageType == damageType then
if allyValues.remaining > 0 then
local tempDamage = m_min(damageRemainder * allyValues.percent, allyValues.remaining)
allyValues.remaining = m_floor(allyValues.remaining - tempDamage)
damageRemainder = damageRemainder - tempDamage
resourcesLostToTypeDamage[damageType][ally] = tempDamage >= 1 and tempDamage or nil
end
end
end
end
-- frost shield / soul link / other taken before you does not count as you taking damage
damageTakenThatCanBeRecouped[damageType] = (damageTakenThatCanBeRecouped[damageType] or 0) + damageRemainder
if aegis[damageType] > 0 then
local tempDamage = m_min(damageRemainder, aegis[damageType])
aegis[damageType] = aegis[damageType] - tempDamage
damageRemainder = damageRemainder - tempDamage
end
if isElemental[damageType] and aegis.sharedElemental > 0 then
local tempDamage = m_min(damageRemainder, aegis.sharedElemental)
aegis.sharedElemental = aegis.sharedElemental - tempDamage
damageRemainder = damageRemainder - tempDamage
end
if aegis.shared > 0 then
local tempDamage = m_min(damageRemainder, aegis.shared)
aegis.shared = aegis.shared - tempDamage
damageRemainder = damageRemainder - tempDamage
end
if guard[damageType] > 0 then
local tempDamage = m_min(damageRemainder * output[damageType.."GuardAbsorbRate"] / 100, guard[damageType])
guard[damageType] = m_floor(guard[damageType] - tempDamage)
damageRemainder = damageRemainder - tempDamage
end
if guard.shared > 0 then
local tempDamage = m_min(damageRemainder * output.sharedGuardAbsorbRate / 100, guard.shared)
guard.shared = m_floor(guard.shared - tempDamage)
damageRemainder = damageRemainder - tempDamage
end
if ward > 0 then
local tempDamage = m_min(damageRemainder * (1 - (modDB:Sum("BASE", nil, "WardBypass") or 0) / 100), ward)
ward = ward - tempDamage
damageRemainder = damageRemainder - tempDamage
end
local esBypass = output[damageType.."EnergyShieldBypass"] / 100 or 0
local lifeHitPool = calcLifeHitPoolWithLossPrevention(life, output.Life, output.preventedLifeLoss, lifeLossBelowHalfPrevented)
local MoMEffect = m_min(output.sharedMindOverMatter + output[damageType.."MindOverMatter"], 100) / 100
local MoMPool = MoMEffect < 1 and m_min(lifeHitPool / (1 - MoMEffect) - lifeHitPool, mana) or mana
local lifePlusMoMHitPool = lifeHitPool + MoMPool
if energyShield > 0 and not modDB:Flag(nil, "EnergyShieldProtectsMana") and esBypass < 1 then
local esPool = esBypass > 0 and m_min(lifePlusMoMHitPool / esBypass - lifePlusMoMHitPool, energyShield) or energyShield
local tempDamage = m_min(damageRemainder * (1 - esBypass), esPool)
esPoolRemaining = m_min(esPoolRemaining, esPool - tempDamage)
energyShield = energyShield - tempDamage
damageRemainder = damageRemainder - tempDamage
elseif esBypass == 1 then
esPoolRemaining = 0
end
if MoMEffect > 0 and mana > 0 then
local MoMDamage = damageRemainder * MoMEffect
if modDB:Flag(nil, "EnergyShieldProtectsMana") and energyShield > 0 and esBypass < 1 then
local MoMEBPool = esBypass > 0 and m_min(MoMPool / esBypass - MoMPool, energyShield) or energyShield
local tempDamage = m_min(MoMDamage * (1 - esBypass), MoMEBPool)
esPoolRemaining = m_min(esPoolRemaining, MoMEBPool - tempDamage)
-- frost shield / soul link / other taken before you does not count as you taking damage
damageTakenThatCanBeRecouped[damageType] = (damageTakenThatCanBeRecouped[damageType] or 0) + damageRemainder
if aegis[damageType] > 0 then
local tempDamage = m_min(damageRemainder, aegis[damageType])
aegis[damageType] = aegis[damageType] - tempDamage
damageRemainder = damageRemainder - tempDamage
resourcesLostToTypeDamage[damageType].aegis = tempDamage >= 1 and tempDamage or nil
end
if isElemental[damageType] and aegis.sharedElemental > 0 then
local tempDamage = m_min(damageRemainder, aegis.sharedElemental)
aegis.sharedElemental = aegis.sharedElemental - tempDamage
damageRemainder = damageRemainder - tempDamage
resourcesLostToTypeDamage[damageType].sharedElementalAegis = tempDamage >= 1 and tempDamage or nil
end
if aegis.shared > 0 then
local tempDamage = m_min(damageRemainder, aegis.shared)
aegis.shared = aegis.shared - tempDamage
damageRemainder = damageRemainder - tempDamage
resourcesLostToTypeDamage[damageType].sharedAegis = tempDamage >= 1 and tempDamage or nil
end
if guard[damageType] > 0 then
local tempDamage = m_min(damageRemainder * output[damageType.."GuardAbsorbRate"] / 100, guard[damageType])
guard[damageType] = m_floor(guard[damageType] - tempDamage)
damageRemainder = damageRemainder - tempDamage
resourcesLostToTypeDamage[damageType].guard = tempDamage >= 1 and tempDamage or nil
end
if guard.shared > 0 then
local tempDamage = m_min(damageRemainder * output.sharedGuardAbsorbRate / 100, guard.shared)
guard.shared = m_floor(guard.shared - tempDamage)
damageRemainder = damageRemainder - tempDamage
resourcesLostToTypeDamage[damageType].sharedGuard = tempDamage >= 1 and tempDamage or nil
end
if ward > 0 then
local tempDamage = m_min(damageRemainder * (1 - (modDB:Sum("BASE", nil, "WardBypass") or 0) / 100), ward)
ward = ward - tempDamage
damageRemainder = damageRemainder - tempDamage
resourcesLostToTypeDamage[damageType].ward = tempDamage >= 1 and tempDamage or nil
end
local esBypass = output[damageType.."EnergyShieldBypass"] / 100 or 0
local lifeHitPool = calcLifeHitPoolWithLossPrevention(life, output.Life, output.preventedLifeLoss, lifeLossBelowHalfPrevented)
local MoMEffect = m_min(output.sharedMindOverMatter + output[damageType.."MindOverMatter"], 100) / 100
local MoMPool = MoMEffect < 1 and m_min(lifeHitPool / (1 - MoMEffect) - lifeHitPool, mana) or mana
local lifePlusMoMHitPool = lifeHitPool + MoMPool
if energyShield > 0 and not modDB:Flag(nil, "EnergyShieldProtectsMana") and esBypass < 1 then
local esPool = esBypass > 0 and m_min(lifePlusMoMHitPool / esBypass - lifePlusMoMHitPool, energyShield) or energyShield
local tempDamage = m_min(damageRemainder * (1 - esBypass), esPool)
esPoolRemaining = m_min(esPoolRemaining, esPool - tempDamage)
energyShield = energyShield - tempDamage
damageRemainder = damageRemainder - tempDamage
MoMDamage = MoMDamage - tempDamage
resourcesLostToTypeDamage[damageType].energyShield = tempDamage >= 1 and tempDamage or nil
elseif esBypass == 1 then
esPoolRemaining = 0
end
local tempDamage = m_min(MoMDamage, MoMPool)
MoMPoolRemaining = m_min(MoMPoolRemaining, MoMPool - tempDamage)
mana = mana - tempDamage
damageRemainder = damageRemainder - tempDamage
else
MoMPoolRemaining = 0
end
if output.preventedLifeLossTotal > 0 then
local halfLife = output.Life * 0.5
local lifeOverHalfLife = m_max(life - halfLife, 0)
local preventPercent = output.preventedLifeLoss / 100
local poolAboveLow = lifeOverHalfLife / (1 - preventPercent)
local preventBelowHalfPercent = lifeLossBelowHalfPrevented / 100
local damageThatLifeCanStillTake = poolAboveLow + m_max(m_min(life, halfLife), 0) / (1 - preventBelowHalfPercent) / (1 - output.preventedLifeLoss / 100)
if damageThatLifeCanStillTake < damageRemainder then
overkillDamage = overkillDamage + damageRemainder - damageThatLifeCanStillTake
damageRemainder = damageThatLifeCanStillTake
end
if output.preventedLifeLossBelowHalf ~= 0 then
local damageToSplit = m_min(damageRemainder, poolAboveLow)
local lostLife = damageToSplit * (1 - preventPercent)
local preventedLoss = damageToSplit * preventPercent
damageRemainder = damageRemainder - damageToSplit
LifeLossLostOverTime = LifeLossLostOverTime + preventedLoss
life = life - lostLife
if life <= halfLife then
local unspecificallyLowLifePreventedDamage = damageRemainder * preventPercent
LifeLossLostOverTime = LifeLossLostOverTime + unspecificallyLowLifePreventedDamage
damageRemainder = damageRemainder - unspecificallyLowLifePreventedDamage
local specificallyLowLifePreventedDamage = damageRemainder * preventBelowHalfPercent
LifeBelowHalfLossLostOverTime = LifeBelowHalfLossLostOverTime + specificallyLowLifePreventedDamage
damageRemainder = damageRemainder - specificallyLowLifePreventedDamage
if MoMEffect > 0 and mana > 0 then
local MoMDamage = damageRemainder * MoMEffect
if modDB:Flag(nil, "EnergyShieldProtectsMana") and energyShield > 0 and esBypass < 1 then
local MoMEBPool = esBypass > 0 and m_min(MoMPool / esBypass - MoMPool, energyShield) or energyShield
local tempDamage = m_min(MoMDamage * (1 - esBypass), MoMEBPool)
esPoolRemaining = m_min(esPoolRemaining, MoMEBPool - tempDamage)
energyShield = energyShield - tempDamage
damageRemainder = damageRemainder - tempDamage
MoMDamage = MoMDamage - tempDamage
resourcesLostToTypeDamage[damageType].energyShield = tempDamage >= 1 and tempDamage or nil
end
else
local tempDamage = damageRemainder * output.preventedLifeLoss / 100
LifeLossLostOverTime = LifeLossLostOverTime + tempDamage
local tempDamage = m_min(MoMDamage, MoMPool)
MoMPoolRemaining = m_min(MoMPoolRemaining, MoMPool - tempDamage)
mana = mana - tempDamage
damageRemainder = damageRemainder - tempDamage
resourcesLostToTypeDamage[damageType].mana = tempDamage >= 1 and tempDamage or nil
else
MoMPoolRemaining = 0
end
if output.preventedLifeLossTotal > 0 then
local halfLife = output.Life * 0.5
local lifeOverHalfLife = m_max(life - halfLife, 0)
local preventPercent = output.preventedLifeLoss / 100
local poolAboveLow = lifeOverHalfLife / (1 - preventPercent)
local preventBelowHalfPercent = lifeLossBelowHalfPrevented / 100
local damageThatLifeCanStillTake = poolAboveLow + m_max(m_min(life, halfLife), 0) / (1 - preventBelowHalfPercent) / (1 - output.preventedLifeLoss / 100)
if damageThatLifeCanStillTake < damageRemainder then
overkillDamage = overkillDamage + damageRemainder - damageThatLifeCanStillTake
damageRemainder = damageThatLifeCanStillTake
end
if output.preventedLifeLossBelowHalf ~= 0 then
local damageToSplit = m_min(damageRemainder, poolAboveLow)
local lostLife = damageToSplit * (1 - preventPercent)
local preventedLoss = damageToSplit * preventPercent
damageRemainder = damageRemainder - damageToSplit
LifeLossLostOverTime = LifeLossLostOverTime + preventedLoss
life = life - lostLife
resourcesLostToTypeDamage[damageType].life = lostLife
resourcesLostToTypeDamage[damageType].lifeLossPrevented = preventedLoss
if life <= halfLife then
local unspecificallyLowLifePreventedDamage = damageRemainder * preventPercent
LifeLossLostOverTime = LifeLossLostOverTime + unspecificallyLowLifePreventedDamage
damageRemainder = damageRemainder - unspecificallyLowLifePreventedDamage
local specificallyLowLifePreventedDamage = damageRemainder * preventBelowHalfPercent
LifeBelowHalfLossLostOverTime = LifeBelowHalfLossLostOverTime + specificallyLowLifePreventedDamage
damageRemainder = damageRemainder - specificallyLowLifePreventedDamage
resourcesLostToTypeDamage[damageType].lifeLossPrevented = resourcesLostToTypeDamage[damageType].lifeLossPrevented + unspecificallyLowLifePreventedDamage + specificallyLowLifePreventedDamage
end
resourcesLostToTypeDamage[damageType].lifeLossPrevented = resourcesLostToTypeDamage[damageType].lifeLossPrevented >= 1 and resourcesLostToTypeDamage[damageType].lifeLossPrevented or nil
else
local tempDamage = damageRemainder * output.preventedLifeLoss / 100
LifeLossLostOverTime = LifeLossLostOverTime + tempDamage
damageRemainder = damageRemainder - tempDamage
resourcesLostToTypeDamage[damageType].lifeLossPrevented = tempDamage >= 1 and tempDamage or nil
end
end
if life > 0 then
local tempDamage = m_min(damageRemainder, life)
life = life - tempDamage
damageRemainder = damageRemainder - tempDamage
resourcesLostToTypeDamage[damageType].life = (resourcesLostToTypeDamage[damageType].life or 0) + (tempDamage > 0 and tempDamage or 0)
end
overkillDamage = overkillDamage + damageRemainder
resourcesLostToTypeDamage[damageType].overkill = damageRemainder >= 1 and damageRemainder or nil
end
if life > 0 then
local tempDamage = m_min(damageRemainder, life)
life = life - tempDamage
damageRemainder = damageRemainder - tempDamage
end
overkillDamage = overkillDamage + damageRemainder
end
local hitPoolRemaining = calcLifeHitPoolWithLossPrevention(life, output.Life, output.preventedLifeLoss, lifeLossBelowHalfPrevented) +
(MoMPoolRemaining ~= m_huge and MoMPoolRemaining or 0) + (esPoolRemaining ~= m_huge and esPoolRemaining or 0)
@@ -345,10 +366,76 @@ function calcs.reducePoolsByDamage(poolTable, damageTable, actor)
LifeLossLostOverTime = m_ceil(LifeLossLostOverTime),
LifeBelowHalfLossLostOverTime = m_ceil(LifeBelowHalfLossLostOverTime),
OverkillDamage = m_ceil(overkillDamage),
hitPoolRemaining = m_floor(hitPoolRemaining)
hitPoolRemaining = m_floor(hitPoolRemaining),
resourcesLostToTypeDamage = resourcesLostToTypeDamage
}
end
---Inserts breakdown of resources drained by a hit
---@param breakdownTable table table to insert items to
---@param poolsRemaining table remaining pools after running reducePoolsByDamage on damage to beak down
---@param output table must already contain things like guard, aegis, ally life...
---@return table breakdownTable with drained resource list
local function incomingDamageBreakdown(breakdownTable, poolsRemaining, output)
--region Breakdown inserts
if output.FrostShieldLife and output.FrostShieldLife > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Frost Shield Life ^7(%d remaining)", output.FrostShieldLife - poolsRemaining.AlliesTakenBeforeYou["frostShield"].remaining, poolsRemaining.AlliesTakenBeforeYou["frostShield"].remaining))
end
if output.TotalSpectreLife and output.TotalSpectreLife > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Total Spectre Life ^7(%d remaining)", output.TotalSpectreLife - poolsRemaining.AlliesTakenBeforeYou["spectres"].remaining, poolsRemaining.AlliesTakenBeforeYou["spectres"].remaining))
end
if output.TotalTotemLife and output.TotalTotemLife > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Total Totem Life ^7(%d remaining)", output.TotalTotemLife - poolsRemaining.AlliesTakenBeforeYou["totems"].remaining, poolsRemaining.AlliesTakenBeforeYou["totems"].remaining))
end
if output.TotalVaalRejuvenationTotemLife and output.TotalVaalRejuvenationTotemLife > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Total Vaal Rejuvenation Totem Life ^7(%d remaining)", output.TotalVaalRejuvenationTotemLife - poolsRemaining.AlliesTakenBeforeYou["vaalRejuvenationTotems"].remaining, poolsRemaining.AlliesTakenBeforeYou["vaalRejuvenationTotems"].remaining))
end
if output.TotalRadianceSentinelLife and output.TotalRadianceSentinelLife > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Total Sentinel of Radiance Life ^7(%d remaining)", output.TotalRadianceSentinelLife - poolsRemaining.AlliesTakenBeforeYou["radianceSentinel"].remaining, poolsRemaining.AlliesTakenBeforeYou["radianceSentinel"].remaining))
end
if output.AlliedEnergyShield and output.AlliedEnergyShield > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Total Allied Energy shield ^7(%d remaining)", output.AlliedEnergyShield - poolsRemaining.AlliesTakenBeforeYou["soulLink"].remaining, poolsRemaining.AlliesTakenBeforeYou["soulLink"].remaining))
end
for _, damageType in ipairs(dmgTypeList) do
if poolsRemaining.resourcesLostToTypeDamage[damageType].aegis then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."%s Aegis charge ^7(%d remaining)", poolsRemaining.resourcesLostToTypeDamage[damageType].aegis, damageType, poolsRemaining.Aegis[damageType]))
end
end
if output.sharedElementalAegis and output.sharedElementalAegis ~= poolsRemaining.Aegis.sharedElemental then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Elemental Aegis charge ^7(%d remaining)", output.sharedElementalAegis - poolsRemaining.Aegis.sharedElemental, poolsRemaining.Aegis.sharedElemental))
end
if output.sharedAegis and output.sharedAegis > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Shared Aegis charge ^7(%d remaining)", output.sharedAegis - poolsRemaining.Aegis.shared, poolsRemaining.Aegis.shared))
end
for _, damageType in ipairs(dmgTypeList) do
if poolsRemaining.resourcesLostToTypeDamage[damageType].guard then
t_insert(breakdownTable, s_format("\n\t%d "..colorCodes.SCOURGE.."%s Guard charge ^7(%d remaining)", poolsRemaining.resourcesLostToTypeDamage[damageType].guard, damageType, poolsRemaining.Guard[damageType]))
end
end
if output.sharedGuardAbsorb and output.sharedGuardAbsorb > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.SCOURGE.."Shared Guard charge ^7(%d remaining)", output.sharedGuardAbsorb - poolsRemaining.Guard.shared, poolsRemaining.Guard.shared))
end
if output.Ward and output.Ward > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.WARD.."Ward", output.Ward))
end
if output.EnergyShieldRecoveryCap ~= poolsRemaining.EnergyShield and output.EnergyShieldRecoveryCap and output.EnergyShieldRecoveryCap > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.ES.."Energy Shield ^7(%d remaining)", output.EnergyShieldRecoveryCap - poolsRemaining.EnergyShield, poolsRemaining.EnergyShield))
end
if output.ManaUnreserved ~= poolsRemaining.Mana and output.ManaUnreserved and output.ManaUnreserved > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.MANA.."Mana ^7(%d remaining)", output.ManaUnreserved - poolsRemaining.Mana, poolsRemaining.Mana))
end
if poolsRemaining.LifeLossLostOverTime + poolsRemaining.LifeBelowHalfLossLostOverTime > 0 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.LIFE.."Life ^7Loss Prevented", poolsRemaining.LifeLossLostOverTime + poolsRemaining.LifeBelowHalfLossLostOverTime))
end
t_insert(breakdownTable, s_format("\t%d "..colorCodes.LIFE.."Life ^7(%d remaining)", output.LifeRecoverable - poolsRemaining.Life, poolsRemaining.Life))
if poolsRemaining.OverkillDamage >= 1 then
t_insert(breakdownTable, s_format("\t%d "..colorCodes.NEGATIVE.."Overkill damage", poolsRemaining.OverkillDamage))
end
--endregion
return breakdownTable
end
-- Performs all ingame and related defensive calculations
function calcs.defence(env, actor)
local modDB = actor.modDB
@@ -1905,18 +1992,6 @@ function calcs.buildDefenceEstimations(env, actor)
if takenMult ~= 1 or takenFlat ~= 0 or spellSuppressMult ~= 1 or impaleDamage ~= 0 then
t_insert(breakdown[damageType.."TakenHitMult"], s_format("= %.3f", output[damageType.."TakenHitMult"]))
end
breakdown[damageType.."TakenHit"] = {
s_format("Final %s Damage taken:", damageType),
s_format("%.1f incoming damage", damage),
s_format("x %.3f damage mult", output[damageType.."TakenHitMult"]),
s_format("= %.1f", output[damageType.."TakenHit"]),
}
t_insert(breakdown["totalTakenHit"].rowList, {
type = s_format("%s", damageType),
incoming = s_format("%.1f incoming damage", damage),
mult = s_format("x %.3f damage mult", output[damageType.."TakenHitMult"] ),
value = s_format("%d", output[damageType.."TakenHit"]),
})
if output.AnyTakenReflect then
breakdown[damageType.."TakenReflectMult"] = {
s_format("Resistance: %.3f", 1 - resist / 100),
@@ -2299,7 +2374,7 @@ function calcs.buildDefenceEstimations(env, actor)
}
end
-- from specters
-- from spectres
output["SpectreAllyDamageMitigation"] = modDB:Sum("BASE", nil, "takenFromSpectresBeforeYou")
if output["SpectreAllyDamageMitigation"] ~= 0 then
output["TotalSpectreLife"] = modDB:Sum("BASE", nil, "TotalSpectreLife")
@@ -2411,7 +2486,7 @@ function calcs.buildDefenceEstimations(env, actor)
alliesTakenBeforeYou["frostShield"] = { remaining = output.FrostShieldLife, percent = output.FrostShieldDamageMitigation / 100 }
end
if output.TotalSpectreLife then
alliesTakenBeforeYou["specters"] = { remaining = output.TotalSpectreLife, percent = output.SpectreAllyDamageMitigation / 100 }
alliesTakenBeforeYou["spectres"] = { remaining = output.TotalSpectreLife, percent = output.SpectreAllyDamageMitigation / 100 }
end
if output.TotalTotemLife then
alliesTakenBeforeYou["totems"] = { remaining = output.TotalTotemLife, percent = output.TotemAllyDamageMitigation / 100 }
@@ -3103,65 +3178,9 @@ function calcs.buildDefenceEstimations(env, actor)
t_insert(breakdown[maxHitCurType], s_format("/ %.2f ^8(modifiers to enemy damage)", enemyDamageMult))
end
t_insert(breakdown[maxHitCurType], s_format("= %.0f ^8maximum survivable enemy damage%s", finalMaxHit, useConversionSmoothing and " (approximate)" or ""))
local poolsRemaining = calcs.reducePoolsByDamage(nil, takenDamages, actor)
t_insert(breakdown[maxHitCurType], s_format("^8Such a hit would drain the following:"))
if output.FrostShieldLife and output.FrostShieldLife > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.GEM.."Frost Shield Life ^7(%d remaining)", output.FrostShieldLife - poolsRemaining.AlliesTakenBeforeYou["frostShield"].remaining, poolsRemaining.AlliesTakenBeforeYou["frostShield"].remaining))
end
if output.TotalSpectreLife and output.TotalSpectreLife > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.GEM.."Total Spectre Life ^7(%d remaining)", output.TotalSpectreLife - poolsRemaining.AlliesTakenBeforeYou["specters"].remaining, poolsRemaining.AlliesTakenBeforeYou["specters"].remaining))
end
if output.TotalTotemLife and output.TotalTotemLife > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.GEM.."Total Totem Life ^7(%d remaining)", output.TotalTotemLife - poolsRemaining.AlliesTakenBeforeYou["totems"].remaining, poolsRemaining.AlliesTakenBeforeYou["totems"].remaining))
end
if output.TotalVaalRejuvenationTotemLife and output.TotalVaalRejuvenationTotemLife > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.GEM.."Total Vaal Rejuvenation Totem Life ^7(%d remaining)", output.TotalVaalRejuvenationTotemLife - poolsRemaining.AlliesTakenBeforeYou["vaalRejuvenationTotems"].remaining, poolsRemaining.AlliesTakenBeforeYou["vaalRejuvenationTotems"].remaining))
end
if output.TotalRadianceSentinelLife and output.TotalRadianceSentinelLife > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.GEM.."Total Sentinel of Radiance Life ^7(%d remaining)", output.TotalRadianceSentinelLife - poolsRemaining.AlliesTakenBeforeYou["radianceSentinel"].remaining, poolsRemaining.AlliesTakenBeforeYou["radianceSentinel"].remaining))
end
if output.AlliedEnergyShield and output.AlliedEnergyShield > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.GEM.."Total Allied Energy shield ^7(%d remaining)", output.AlliedEnergyShield - poolsRemaining.AlliesTakenBeforeYou["soulLink"].remaining, poolsRemaining.AlliesTakenBeforeYou["soulLink"].remaining))
end
if output.sharedAegis and output.sharedAegis > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.GEM.."Shared Aegis charge ^7(%d remaining)", output.sharedAegis - poolsRemaining.Aegis.shared, poolsRemaining.Aegis.shared))
end
local receivedElemental = false
for takenType in pairs(takenDamages) do
receivedElemental = receivedElemental or isElemental[takenType]
if output[takenType.."Aegis"] and output[takenType.."Aegis"] > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.GEM.."%s Aegis charge ^7(%d remaining)", output[takenType.."Aegis"] - poolsRemaining.Aegis[takenType], takenType, poolsRemaining.Aegis[takenType]))
end
end
if receivedElemental and output.sharedElementalAegis and output.sharedElementalAegis > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.GEM.."Elemental Aegis charge ^7(%d remaining)", output.sharedElementalAegis - poolsRemaining.Aegis.sharedElemental, poolsRemaining.Aegis.sharedElemental))
end
if output.sharedGuardAbsorb and output.sharedGuardAbsorb > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.SCOURGE.."Shared Guard charge ^7(%d remaining)", output.sharedGuardAbsorb - poolsRemaining.Guard.shared, poolsRemaining.Guard.shared))
end
for takenType in pairs(takenDamages) do
if output[takenType.."GuardAbsorb"] and output[takenType.."GuardAbsorb"] > 0 then
t_insert(breakdown[maxHitCurType], s_format("\n\t%d "..colorCodes.SCOURGE.."%s Guard charge ^7(%d remaining)", output[takenType.."GuardAbsorb"] - poolsRemaining.Guard[takenType], takenType, poolsRemaining.Guard[takenType]))
end
end
if output.Ward and output.Ward > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.WARD.."Ward", output.Ward))
end
if output.EnergyShieldRecoveryCap ~= poolsRemaining.EnergyShield and output.EnergyShieldRecoveryCap and output.EnergyShieldRecoveryCap > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.ES.."Energy Shield ^7(%d remaining)", output.EnergyShieldRecoveryCap - poolsRemaining.EnergyShield, poolsRemaining.EnergyShield))
end
if output.ManaUnreserved ~= poolsRemaining.Mana and output.ManaUnreserved and output.ManaUnreserved > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.MANA.."Mana ^7(%d remaining)", output.ManaUnreserved - poolsRemaining.Mana, poolsRemaining.Mana))
end
if poolsRemaining.LifeLossLostOverTime + poolsRemaining.LifeBelowHalfLossLostOverTime > 0 then
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.LIFE.."Life ^7Loss Prevented", poolsRemaining.LifeLossLostOverTime + poolsRemaining.LifeBelowHalfLossLostOverTime))
end
t_insert(breakdown[maxHitCurType], s_format("\t%d "..colorCodes.LIFE.."Life ^7(%d remaining)", output.LifeRecoverable - poolsRemaining.Life, poolsRemaining.Life))
if poolsRemaining.OverkillDamage >= 1 then
t_insert(breakdown[maxHitCurType], s_format("\t%d Overkill damage", poolsRemaining.OverkillDamage))
end
t_insert(breakdown[maxHitCurType], "^8Such a hit would drain the following resources:")
breakdown[maxHitCurType] = incomingDamageBreakdown(breakdown[maxHitCurType], calcs.reducePoolsByDamage(nil, takenDamages, actor), output)
end
end
@@ -3595,4 +3614,106 @@ function calcs.buildDefenceEstimations(env, actor)
end
end
end
--region Add breakdown to enemy incoming damage
if breakdown then
local takenHit = { }
for _, damageType in ipairs(dmgTypeList) do
takenHit[damageType] = output[damageType.."TakenHit"] > 0 and output[damageType.."TakenHit"] or nil
t_insert(breakdown["totalTakenHit"].rowList, {
type = s_format("%s", damageType),
incoming = s_format("%.1f incoming damage", output[damageType.."TakenDamage"]),
mult = s_format("x %.3f damage mult", output[damageType.."TakenHitMult"] ),
value = s_format("%d", m_ceil(output[damageType.."TakenHit"])),
})
end
local poolsRemaining = calcs.reducePoolsByDamage(nil, takenHit, actor)
t_insert(breakdown["totalTakenHit"], "Such a hit would drain the following resources:")
breakdown["totalTakenHit"] = incomingDamageBreakdown(breakdown["totalTakenHit"], poolsRemaining, output)
for _, damageType in ipairs(dmgTypeList) do
local breakdownTable = {}
local resourcesLost = poolsRemaining.resourcesLostToTypeDamage[damageType]
local resourcesLostSum = 0
t_insert(breakdownTable, s_format("Final %s Damage taken:", damageType))
t_insert(breakdownTable, s_format("%.1f incoming damage", output[damageType.."TakenDamage"]))
t_insert(breakdownTable, s_format("x %.3f damage mult", output[damageType.."TakenHitMult"]))
t_insert(breakdownTable, s_format("= %.1f", output[damageType.."TakenHit"]))
t_insert(breakdownTable, "This part of the hit drains the following resources:")
if resourcesLost.frostShield then
resourcesLostSum = resourcesLostSum + resourcesLost.frostShield
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Frost Shield Life", resourcesLost.frostShield))
end
if resourcesLost.spectres then
resourcesLostSum = resourcesLostSum + resourcesLost.spectres
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Total Spectre Life", resourcesLost.spectres))
end
if resourcesLost.totems then
resourcesLostSum = resourcesLostSum + resourcesLost.totems
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Total Totem Life", resourcesLost.totems))
end
if resourcesLost.vaalRejuvenationTotems then
resourcesLostSum = resourcesLostSum + resourcesLost.vaalRejuvenationTotems
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Total Vaal Rejuvenation Totem Life", resourcesLost.vaalRejuvenationTotems))
end
if resourcesLost.radianceSentinel then
resourcesLostSum = resourcesLostSum + resourcesLost.radianceSentinel
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Total Sentinel of Radiance Life", resourcesLost.radianceSentinel))
end
if resourcesLost.soulLink then
resourcesLostSum = resourcesLostSum + resourcesLost.soulLink
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Total Allied Energy shield", resourcesLost.soulLink))
end
if resourcesLost.aegis then
resourcesLostSum = resourcesLostSum + resourcesLost.aegis
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."%s Aegis charge", resourcesLost.aegis, damageType))
end
if resourcesLost.sharedElementalAegis then
resourcesLostSum = resourcesLostSum + resourcesLost.sharedElementalAegis
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Elemental Aegis charge", resourcesLost.sharedElementalAegis))
end
if resourcesLost.sharedAegis then
resourcesLostSum = resourcesLostSum + resourcesLost.sharedAegis
t_insert(breakdownTable, s_format("\t%d "..colorCodes.GEM.."Shared Aegis charge", resourcesLost.sharedAegis))
end
if resourcesLost.guard then
resourcesLostSum = resourcesLostSum + resourcesLost.guard
t_insert(breakdownTable, s_format("\n\t%d "..colorCodes.SCOURGE.."%s Guard charge", resourcesLost.guard, damageType))
end
if resourcesLost.sharedGuard then
resourcesLostSum = resourcesLostSum + resourcesLost.sharedGuard
t_insert(breakdownTable, s_format("\t%d "..colorCodes.SCOURGE.."Shared Guard charge", resourcesLost.sharedGuard))
end
if resourcesLost.ward then
resourcesLostSum = resourcesLostSum + resourcesLost.ward
t_insert(breakdownTable, s_format("\t%d "..colorCodes.WARD.."Ward", resourcesLost.ward))
end
if resourcesLost.energyShield then
resourcesLostSum = resourcesLostSum + resourcesLost.energyShield
t_insert(breakdownTable, s_format("\t%d "..colorCodes.ES.."Energy Shield", resourcesLost.energyShield))
end
if resourcesLost.mana then
resourcesLostSum = resourcesLostSum + resourcesLost.mana
t_insert(breakdownTable, s_format("\t%d "..colorCodes.MANA.."Mana", resourcesLost.mana))
end
if resourcesLost.lifeLossPrevented and resourcesLost.lifeLossPrevented > 0 then
resourcesLostSum = resourcesLostSum + resourcesLost.lifeLossPrevented
t_insert(breakdownTable, s_format("\t%d "..colorCodes.LIFE.."Life ^7Loss Prevented", resourcesLost.lifeLossPrevented))
end
if resourcesLost.life and resourcesLost.life > 0 then
resourcesLostSum = resourcesLostSum + resourcesLost.life
t_insert(breakdownTable, s_format("\t%d "..colorCodes.LIFE.."Life", resourcesLost.life))
end
if resourcesLost.overkill then
resourcesLostSum = resourcesLostSum + resourcesLost.overkill
t_insert(breakdownTable, s_format("\t%d "..colorCodes.NEGATIVE.."Overkill damage", resourcesLost.overkill))
end
t_insert(breakdownTable, s_format("\t^8(%d total)", resourcesLostSum))
breakdown[damageType.."TakenHit"] = breakdownTable
end
end
--endregion
end