Skip to content

Commit d770618

Browse files
authored
Enemy damaging ailments (#6814)
* add support for enemy damaging ailments fix merge conflict * include recoup and taken over time in ComprehensiveNetLifeRegen * fix spelling
1 parent 819c620 commit d770618

File tree

4 files changed

+163
-58
lines changed

4 files changed

+163
-58
lines changed

src/Data/ModCache.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7576,7 +7576,7 @@ c["Critical Strike Chance is 30% for Hits with this Weapon"]={{[1]={[1]={type="C
75767576
c["Critical Strike Chance is increased by Lightning Resistance"]={{[1]={flags=0,keywordFlags=0,name="CritChanceIncreasedByLightningRes",type="FLAG",value=true}},nil}
75777577
c["Critical Strike Chance is increased by Overcapped Lightning Resistance"]={{[1]={flags=0,keywordFlags=0,name="CritChanceIncreasedByOvercappedLightningRes",type="FLAG",value=true}},nil}
75787578
c["Critical Strikes Penetrate 10% of Enemy Elemental Resistances while affected by Zealotry"]={{[1]={[1]={type="Condition",var="CriticalStrike"},[2]={type="Condition",var="AffectedByZealotry"},flags=0,keywordFlags=0,name="ElementalPenetration",type="BASE",value=10}},nil}
7579-
c["Critical Strikes against you do not inherently inflict Elemental Ailments"]={nil,"Critical Strikes do not inherently inflict Elemental Ailments "}
7579+
c["Critical Strikes against you do not inherently inflict Elemental Ailments"]={{[1]={flags=0,keywordFlags=0,name="CritsOnYouDontAlwaysApplyElementalAilments",type="FLAG",value=true}},nil}
75807580
c["Critical Strikes deal no Damage"]={{[1]={[1]={type="Condition",var="CriticalStrike"},flags=0,keywordFlags=0,name="Damage",type="MORE",value=-100}},nil}
75817581
c["Critical Strikes do not always Freeze"]={{[1]={flags=0,keywordFlags=0,name="CritsDontAlwaysFreeze",type="FLAG",value=true}},nil}
75827582
c["Critical Strikes do not deal extra Damage"]={{[1]={flags=0,keywordFlags=0,name="NoCritMultiplier",type="FLAG",value=true}},nil}

src/Data/ModMap.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ return {
156156
type = "check",
157157
tooltipLines = { "All Monster Damage from Hits always Ignites" },
158158
apply = function(val, mapModEffect, modList, enemyModList)
159+
enemyModList:NewMod("IgniteChance", "BASE", 100, "Map mod Conflagrating")
160+
enemyModList:NewMod("AllDamageIgnites", "FLAG", true, "Map mod Conflagrating")
159161
end
160162
},
161163
["Impaling"] = {
@@ -171,6 +173,7 @@ return {
171173
tooltipLines = { "Monsters have a %d%% chance to Ignite, Freeze and Shock on Hit" },
172174
values = { 0, 15, 20 },
173175
apply = function(val, mapModEffect, values, modList, enemyModList)
176+
enemyModList:NewMod("ElementalAilmentChance", "BASE", values[val] * mapModEffect, "Map mod Empowered")
174177
end
175178
},
176179
["Overlord's"] = {
@@ -351,6 +354,7 @@ return {
351354
type = "check",
352355
tooltipLines = { "Monsters Poison on Hit" },
353356
apply = function(val, mapModEffect, modList, enemyModList)
357+
enemyModList:NewMod("PoisonChance", "BASE", 100, "Map mod of Venom")
354358
end
355359
},
356360
["of Deadliness"] = {
@@ -413,6 +417,8 @@ return {
413417
{ val = "Profane", label = "Enemy Phys As Chaos Monsters deal to extra Physical Damage Inflict Withered for seconds on Hit Profane" },
414418
{ val = "Fleet", label = "Enemy Inc Speed to increased Monster Movement Attack Cast".."Fleet" },
415419
{ val = "Impaling", label = "Enemy Impale Monsters have chance to with Attacks Impaling" },
420+
{ val = "Conflagrating", label = "Hits always Ignites All Monster Damage from Conflagrating" },
421+
{ val = "Empowered", label = "Elemental Ailments on Hit Monsters have chance to cause Empowered" },
416422
{ val = "Overlord's", label = "Boss Inc Damage / Speed Unique deals increased has Attack and Cast".."Overlord's" },
417423
},
418424
Suffix = {
@@ -430,6 +436,7 @@ return {
430436
{ val = "of Fatigue", label = "Less Cooldown Recovery Players have Rate".."of Fatigue" },
431437
{ val = "of Doubt", label = "Reduced Aura Effect Players have Non-Curse Auras from Skills".."of Doubt" },
432438
{ val = "of Imprecision", label = "Less Accuracy Players have Rating".."of Imprecision" },
439+
{ val = "of Venom", label = "Poison On Hit Monsters of Venom" },
433440
{ val = "of Deadliness", label = "Enemy Critical Strike Monsters have to increased Chance Monster Multiplier".."of Deadliness" },
434441
},
435442
}

src/Modules/CalcDefence.lua

Lines changed: 154 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,7 @@ function calcs.buildDefenceEstimations(env, actor)
14491449
}
14501450
end
14511451
local enemyCritChance = enemyDB:Flag(nil, "NeverCrit") and 0 or enemyDB:Flag(nil, "AlwaysCrit") and 100 or (m_max(m_min((modDB:Override(nil, "enemyCritChance") or env.configInput["enemyCritChance"] or env.configPlaceholder["enemyCritChance"] or 0) * (1 + modDB:Sum("INC", nil, "EnemyCritChance") / 100 + enemyDB:Sum("INC", nil, "CritChance") / 100) * (1 - output["ConfiguredEvadeChance"] / 100), 100), 0))
1452+
output["EnemyCritChance"] = enemyCritChance
14521453
local enemyCritDamage = m_max((env.configInput["enemyCritDamage"] or env.configPlaceholder["enemyCritDamage"] or 0) + enemyDB:Sum("BASE", nil, "CritMultiplier"), 0)
14531454
output["EnemyCritEffect"] = 1 + enemyCritChance / 100 * (enemyCritDamage / 100) * (1 - output.CritExtraDamageReduction / 100)
14541455
local enemyCfg = {keywordFlags = bit.bnot(KeywordFlag.MatchAll)} -- Match all keywordFlags parameter for enemy min-max damage mods
@@ -3243,63 +3244,147 @@ function calcs.buildDefenceEstimations(env, actor)
32433244
}
32443245
end
32453246
end
3246-
local enemyDotChance = 0 -- this is for future use for calculating ignite/bleed/poison etc
3247-
if damageCategoryConfig == "DamageOverTime" or enemyDotChance > 0 then
3247+
local enemyCritAilmentEffect = 1 + output.EnemyCritChance / 100 * 0.5 * (1 - output.CritExtraDamageReduction / 100)
3248+
-- this is just used so that ailments don't always showup if the enemy has no other way of applying the ailment and they have a low crit chance
3249+
local enemyCritThreshold = 10.1
3250+
local enemyBleedChance = 0
3251+
local enemyIgniteChance = 0
3252+
if output.SelfIgniteEffect ~= 0 and output.IgniteAvoidChance < 100 and output.SelfIgniteDuration ~= 0 and damageCategoryConfig ~= "DamageOverTime" then
3253+
enemyIgniteChance = enemyDB:Sum("BASE", nil, "IgniteChance", "ElementalAilmentChance")
3254+
local enemyCritAilmentChance = (not modDB:Flag(nil, "CritsOnYouDontAlwaysApplyElementalAilments")) and ((output.EnemyCritChance > enemyCritThreshold or enemyIgniteChance > 0) and output.EnemyCritChance or 0) or 0
3255+
enemyIgniteChance = (enemyCritAilmentChance + (1 - enemyCritAilmentChance / 100) * enemyIgniteChance) * (1 - output.IgniteAvoidChance / 100)
3256+
end
3257+
local enemyPoisonChance = 0
3258+
if output.SelfPoisonEffect ~= 0 and output.PoisonAvoidChance < 100 and output.SelfPoisonDuration ~= 0 and damageCategoryConfig ~= "DamageOverTime" then
3259+
enemyPoisonChance = enemyDB:Sum("BASE", nil, "PoisonChance") * (1 - output.PoisonAvoidChance / 100)
3260+
end
3261+
if damageCategoryConfig == "DamageOverTime" or (enemyIgniteChance + enemyPoisonChance + enemyBleedChance) > 0 then
32483262
output.TotalDegen = output.TotalBuildDegen or 0
3249-
for _, damageType in ipairs(dmgTypeList) do
3250-
local source = "Config"
3251-
local baseVal = tonumber(env.configInput["enemy"..damageType.."Damage"])
3252-
if baseVal == nil then
3253-
source = "Default"
3254-
baseVal = tonumber(env.configPlaceholder["enemy"..damageType.."Damage"]) or 0
3255-
end
3256-
if baseVal > 0 then
3257-
for damageConvertedType, convertPercent in pairs(actor.damageOverTimeShiftTable[damageType]) do
3258-
if convertPercent > 0 then
3259-
local total = baseVal * (convertPercent / 100) * output[damageConvertedType.."TakenDotMult"]
3260-
output[damageConvertedType.."EnemyDegen"] = (output[damageConvertedType.."EnemyDegen"] or 0) + total
3261-
output.TotalDegen = output.TotalDegen + total
3262-
if breakdown then
3263-
breakdown.TotalDegen = breakdown.TotalDegen or {
3264-
rowList = { },
3265-
colList = {
3266-
{ label = "Source", key = "source" },
3267-
{ label = "Base Type", key = "type" },
3268-
{ label = "Final Type", key = "type2" },
3269-
{ label = "Base", key = "base" },
3270-
{ label = "Taken As Percent", key = "conv" },
3271-
{ label = "Multiplier", key = "mult" },
3272-
{ label = "Total", key = "total" },
3263+
if damageCategoryConfig == "DamageOverTime" then
3264+
for _, damageType in ipairs(dmgTypeList) do
3265+
local source = "Config"
3266+
local baseVal = tonumber(env.configInput["enemy"..damageType.."Damage"])
3267+
if baseVal == nil then
3268+
source = "Default"
3269+
baseVal = tonumber(env.configPlaceholder["enemy"..damageType.."Damage"]) or 0
3270+
end
3271+
if baseVal > 0 then
3272+
for damageConvertedType, convertPercent in pairs(actor.damageOverTimeShiftTable[damageType]) do
3273+
if convertPercent > 0 then
3274+
local total = baseVal * (convertPercent / 100) * output[damageConvertedType.."TakenDotMult"]
3275+
output[damageConvertedType.."EnemyDegen"] = (output[damageConvertedType.."EnemyDegen"] or 0) + total
3276+
output.TotalDegen = output.TotalDegen + total
3277+
if breakdown then
3278+
breakdown.TotalDegen = breakdown.TotalDegen or {
3279+
rowList = { },
3280+
colList = {
3281+
{ label = "Source", key = "source" },
3282+
{ label = "Base Type", key = "type" },
3283+
{ label = "Final Type", key = "type2" },
3284+
{ label = "Base", key = "base" },
3285+
{ label = "Taken As Percent", key = "conv" },
3286+
{ label = "Multiplier", key = "mult" },
3287+
{ label = "Total", key = "total" },
3288+
}
32733289
}
3274-
}
3275-
t_insert(breakdown.TotalDegen.rowList, {
3276-
source = source,
3277-
type = damageType,
3278-
type2 = damageConvertedType,
3279-
base = s_format("%.1f", baseVal),
3280-
conv = s_format("x %.2f%%", convertPercent),
3281-
mult = s_format("x %.2f", output[damageConvertedType.."TakenDotMult"]),
3282-
total = s_format("%.1f", total),
3283-
})
3284-
breakdown[damageConvertedType.."EnemyDegen"] = breakdown[damageConvertedType.."EnemyDegen"] or {
3285-
rowList = { },
3286-
colList = {
3287-
{ label = "Source", key = "source" },
3288-
{ label = "Base Type", key = "type" },
3289-
{ label = "Base", key = "base" },
3290-
{ label = "Taken As Percent", key = "conv" },
3291-
{ label = "Multiplier", key = "mult" },
3292-
{ label = "Total", key = "total" },
3290+
t_insert(breakdown.TotalDegen.rowList, {
3291+
source = source,
3292+
type = damageType,
3293+
type2 = damageConvertedType,
3294+
base = s_format("%.1f", baseVal),
3295+
conv = s_format("x %.2f%%", convertPercent),
3296+
mult = s_format("x %.2f", output[damageConvertedType.."TakenDotMult"]),
3297+
total = s_format("%.1f", total),
3298+
})
3299+
breakdown[damageConvertedType.."EnemyDegen"] = breakdown[damageConvertedType.."EnemyDegen"] or {
3300+
rowList = { },
3301+
colList = {
3302+
{ label = "Source", key = "source" },
3303+
{ label = "Base Type", key = "type" },
3304+
{ label = "Base", key = "base" },
3305+
{ label = "Taken As Percent", key = "conv" },
3306+
{ label = "Multiplier", key = "mult" },
3307+
{ label = "Total", key = "total" },
3308+
}
32933309
}
3294-
}
3295-
t_insert(breakdown[damageConvertedType.."EnemyDegen"].rowList, {
3296-
source = source,
3297-
type = damageType,
3298-
base = s_format("%.1f", baseVal),
3299-
conv = s_format("x %.2f%%", convertPercent),
3300-
mult = s_format("x %.2f", output[damageConvertedType.."TakenDotMult"]),
3301-
total = s_format("%.1f", total),
3302-
})
3310+
t_insert(breakdown[damageConvertedType.."EnemyDegen"].rowList, {
3311+
source = source,
3312+
type = damageType,
3313+
base = s_format("%.1f", baseVal),
3314+
conv = s_format("x %.2f%%", convertPercent),
3315+
mult = s_format("x %.2f", output[damageConvertedType.."TakenDotMult"]),
3316+
total = s_format("%.1f", total),
3317+
})
3318+
end
3319+
end
3320+
end
3321+
end
3322+
end
3323+
elseif (enemyIgniteChance + enemyPoisonChance + enemyBleedChance) > 0 then
3324+
local ailmentList = {}
3325+
if enemyBleedChance > 0 then
3326+
ailmentList["Bleed"] = { damageType = "Physical", sourceTypes = { "Physical" } }
3327+
end
3328+
if enemyIgniteChance > 0 then
3329+
ailmentList["Ignite"] = { damageType = "Fire", sourceTypes = enemyDB:Flag(nil, "AllDamageIgnites") and dmgTypeList or { "Fire" } }
3330+
end
3331+
if enemyPoisonChance > 0 then
3332+
ailmentList["Poison"] = { damageType = "Chaos", sourceTypes = { "Physical", "Chaos" } }
3333+
end
3334+
for source, ailment in pairs(ailmentList) do
3335+
local baseVal = 0
3336+
for _, damageType in ipairs(ailment.sourceTypes) do
3337+
baseVal = baseVal + output[damageType.."TakenDamage"]
3338+
end
3339+
baseVal = baseVal * data.misc[source.."PercentBase"] * (enemyCritAilmentEffect / output["EnemyCritEffect"]) * output["Self"..source.."Effect"] / 100
3340+
if baseVal > 0 then
3341+
for damageConvertedType, convertPercent in pairs(actor.damageOverTimeShiftTable[ailment.damageType]) do
3342+
if convertPercent > 0 then
3343+
local total = baseVal * (convertPercent / 100) * output[damageConvertedType.."TakenDotMult"]
3344+
output[damageConvertedType.."EnemyDegen"] = (output[damageConvertedType.."EnemyDegen"] or 0) + total
3345+
output.TotalDegen = output.TotalDegen + total
3346+
if breakdown then
3347+
breakdown.TotalDegen = breakdown.TotalDegen or {
3348+
rowList = { },
3349+
colList = {
3350+
{ label = "Source", key = "source" },
3351+
{ label = "Base Type", key = "type" },
3352+
{ label = "Final Type", key = "type2" },
3353+
{ label = "Base", key = "base" },
3354+
{ label = "Taken As Percent", key = "conv" },
3355+
{ label = "Multiplier", key = "mult" },
3356+
{ label = "Total", key = "total" },
3357+
}
3358+
}
3359+
t_insert(breakdown.TotalDegen.rowList, {
3360+
source = source,
3361+
type = ailment.damageType,
3362+
type2 = damageConvertedType,
3363+
base = s_format("%.1f", baseVal),
3364+
conv = s_format("x %.2f%%", convertPercent),
3365+
mult = s_format("x %.2f", output[damageConvertedType.."TakenDotMult"]),
3366+
total = s_format("%.1f", total),
3367+
})
3368+
breakdown[damageConvertedType.."EnemyDegen"] = breakdown[damageConvertedType.."EnemyDegen"] or {
3369+
rowList = { },
3370+
colList = {
3371+
{ label = "Source", key = "source" },
3372+
{ label = "Base Type", key = "type" },
3373+
{ label = "Base", key = "base" },
3374+
{ label = "Taken As Percent", key = "conv" },
3375+
{ label = "Multiplier", key = "mult" },
3376+
{ label = "Total", key = "total" },
3377+
}
3378+
}
3379+
t_insert(breakdown[damageConvertedType.."EnemyDegen"].rowList, {
3380+
source = source,
3381+
type = ailment.damageType,
3382+
base = s_format("%.1f", baseVal),
3383+
conv = s_format("x %.2f%%", convertPercent),
3384+
mult = s_format("x %.2f", output[damageConvertedType.."TakenDotMult"]),
3385+
total = s_format("%.1f", total),
3386+
})
3387+
end
33033388
end
33043389
end
33053390
end
@@ -3379,18 +3464,30 @@ function calcs.buildDefenceEstimations(env, actor)
33793464
end
33803465
end
33813466
end
3382-
output.ComprehensiveNetLifeRegen = output.ComprehensiveNetLifeRegen - totalLifeDegen
3383-
output.ComprehensiveNetManaRegen = output.ComprehensiveNetManaRegen - totalManaDegen
3384-
output.ComprehensiveNetEnergyShieldRegen = output.ComprehensiveNetEnergyShieldRegen - totalEnergyShieldDegen
3467+
output.ComprehensiveNetLifeRegen = output.ComprehensiveNetLifeRegen + (output.LifeRecoupRecoveryAvg or 0) - totalLifeDegen - (output.LifeLossLostAvg or 0)
3468+
output.ComprehensiveNetManaRegen = output.ComprehensiveNetManaRegen + (output.ManaRecoupRecoveryAvg or 0) - totalManaDegen
3469+
output.ComprehensiveNetEnergyShieldRegen = output.ComprehensiveNetEnergyShieldRegen + (output.EnergyShieldRecoupRecoveryAvg or 0) - totalEnergyShieldDegen
33853470
output.ComprehensiveTotalNetRegen = output.ComprehensiveNetLifeRegen + output.ComprehensiveNetManaRegen + output.ComprehensiveNetEnergyShieldRegen
33863471
if breakdown then
33873472
t_insert(breakdown.ComprehensiveNetLifeRegen, s_format("%.1f ^8(total life regen)", output.LifeRegenRecovery))
3473+
if (output.LifeRecoupRecoveryAvg or 0) ~= 0 then
3474+
t_insert(breakdown.ComprehensiveNetLifeRegen, s_format("+ %.1f ^8(average life recoup)", (output.LifeRecoupRecoveryAvg or 0)))
3475+
end
33883476
t_insert(breakdown.ComprehensiveNetLifeRegen, s_format("- %.1f ^8(total life degen)", totalLifeDegen))
3477+
if (output.LifeLossLostAvg or 0) ~= 0 then
3478+
t_insert(breakdown.ComprehensiveNetLifeRegen, s_format("- %.1f ^8(average life lost over time)", (output.LifeLossLostAvg or 0)))
3479+
end
33893480
t_insert(breakdown.ComprehensiveNetLifeRegen, s_format("= %.1f", output.ComprehensiveNetLifeRegen))
33903481
t_insert(breakdown.ComprehensiveNetManaRegen, s_format("%.1f ^8(total mana regen)", output.ManaRegenRecovery))
3482+
if (output.ManaRecoupRecoveryAvg or 0) ~= 0 then
3483+
t_insert(breakdown.ComprehensiveNetManaRegen, s_format("+ %.1f ^8(average mana recoup)", (output.ManaRecoupRecoveryAvg or 0)))
3484+
end
33913485
t_insert(breakdown.ComprehensiveNetManaRegen, s_format("- %.1f ^8(total mana degen)", totalManaDegen))
33923486
t_insert(breakdown.ComprehensiveNetManaRegen, s_format("= %.1f", output.ComprehensiveNetManaRegen))
33933487
t_insert(breakdown.ComprehensiveNetEnergyShieldRegen, s_format("%.1f ^8(total energy shield regen)", output.EnergyShieldRegenRecovery))
3488+
if (output.EnergyShieldRecoupRecoveryAvg or 0) ~= 0 then
3489+
t_insert(breakdown.ComprehensiveNetEnergyShieldRegen, s_format("+ %.1f ^8(average energy shield recoup)", (output.EnergyShieldRecoupRecoveryAvg or 0)))
3490+
end
33943491
t_insert(breakdown.ComprehensiveNetEnergyShieldRegen, s_format("- %.1f ^8(total energy shield degen)", totalEnergyShieldDegen))
33953492
t_insert(breakdown.ComprehensiveNetEnergyShieldRegen, s_format("= %.1f", output.ComprehensiveNetEnergyShieldRegen))
33963493
breakdown.ComprehensiveTotalNetRegen = {

src/Modules/ModParser.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4228,6 +4228,7 @@ local specialModList = {
42284228
["immun[ei]t?y? to chill"] = { flag("ChillImmune"), },
42294229
["cannot be ignited"] = { flag("IgniteImmune"), },
42304230
["immun[ei]t?y? to ignite"] = { flag("IgniteImmune"), },
4231+
["critical strikes against you do not inherently inflict elemental ailments"] = { flag("CritsOnYouDontAlwaysApplyElementalAilments"), },
42314232
["cannot be ignited while at maximum endurance charges"] = { flag("IgniteImmune", {type = "StatThreshold", stat = "EnduranceCharges", thresholdStat = "EnduranceChargesMax" }, { type = "GlobalEffect", effectType = "Global", unscalable = true }), },
42324233
["grants immunity to ignite for (%d+) seconds if used while ignited"] = { flag("IgniteImmune", { type = "Condition", var = "UsingFlask" }), },
42334234
["grants immunity to bleeding for (%d+) seconds if used while bleeding"] = { flag("BleedImmune", { type = "Condition", var = "UsingFlask" }) },

0 commit comments

Comments
 (0)