From f3405c86ec691d70e2ab55cbb1a1d187a2323f93 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:51:54 +0200 Subject: [PATCH 01/11] Add mod parsing for Parried Debuff Magnitude --- src/Data/ModCache.lua | 14 +++++--------- src/Modules/ModParser.lua | 1 + 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 524bfaca78..97a4a4660f 100644 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -1161,7 +1161,7 @@ c["10% increased Movement Speed"]={{[1]={flags=0,keywordFlags=0,name="MovementSp c["10% increased Movement Speed when on Full Life"]={{[1]={[1]={type="Condition",var="FullLife"},flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=10}},nil} c["10% increased Movement Speed while Sprinting"]={{[1]={[1]={type="Condition",var="Sprinting"},flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=10}},nil} c["10% increased Movement Speed while Surrounded"]={{[1]={[1]={type="Condition",var="Surrounded"},flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=10}},nil} -c["10% increased Parried Debuff Magnitude"]={{}," Parried Debuff Magnitude "} +c["10% increased Parried Debuff Magnitude"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffMagnitude",type="INC",value=10}},nil} c["10% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=10}},nil} c["10% increased Pin duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=10}}," Pin "} c["10% increased Poison Duration"]={{[1]={flags=0,keywordFlags=0,name="EnemyPoisonDuration",type="INC",value=10}},nil} @@ -1604,9 +1604,7 @@ c["15% increased Melee Damage with Hits at Close Range"]={{[1]={[1]={type="Condi c["15% increased Minion Duration"]={{[1]={[1]={skillType=77,type="SkillType"},flags=0,keywordFlags=0,name="Duration",type="INC",value=15}},nil} c["15% increased Movement Speed"]={{[1]={flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=15}},nil} c["15% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=15}}," Parried Debuff "} -c["15% increased Parried Debuff Magnitude"]={{}," Parried Debuff Magnitude "} -c["15% increased Parried Debuff Magnitude 20% increased Parry Hit Area of Effect"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=15}}," Parried Debuff Magnitude 20% increasedHit "} -c["15% increased Parried Debuff Magnitude Cannot be Critically Hit while Parrying"]={{}," Parried Debuff Magnitude Cannot be Critically Hit while Parrying "} +c["15% increased Parried Debuff Magnitude"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffMagnitude",type="INC",value=15}},nil} c["15% increased Parry Hit Area of Effect"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=15}},"Hit "} c["15% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=15}},nil} c["15% increased Pin Buildup"]={{[1]={flags=0,keywordFlags=0,name="EnemyPinBuildup",type="INC",value=15}},nil} @@ -2264,7 +2262,7 @@ c["25% increased Melee Damage"]={{[1]={flags=256,keywordFlags=0,name="Damage",ty c["25% increased Minion Duration"]={{[1]={[1]={skillType=77,type="SkillType"},flags=0,keywordFlags=0,name="Duration",type="INC",value=25}},nil} c["25% increased Movement Speed"]={{[1]={flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=25}},nil} c["25% increased Movement Speed while affected by an Ailment"]={{[1]={[1]={type="Condition",varList={[1]="Bleeding",[2]="Poisoned",[3]="Ignited",[4]="Chilled",[5]="Frozen",[6]="Shocked",[7]="Electrocuted"}},flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=25}},nil} -c["25% increased Parried Debuff Magnitude"]={{}," Parried Debuff Magnitude "} +c["25% increased Parried Debuff Magnitude"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffMagnitude",type="INC",value=25}},nil} c["25% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=25}},nil} c["25% increased Presence Area of Effect"]={{[1]={flags=0,keywordFlags=0,name="PresenceArea",type="INC",value=25}},nil} c["25% increased Projectile Speed"]={{[1]={flags=0,keywordFlags=0,name="ProjectileSpeed",type="INC",value=25}},nil} @@ -3033,7 +3031,7 @@ c["50% increased Melee Damage against Heavy Stunned enemies"]={{[1]={[1]={actor= c["50% increased Melee Damage against Immobilised Enemies"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="Immobilised"},flags=256,keywordFlags=0,name="Damage",type="INC",value=50}},nil} c["50% increased Minion Damage while you have at least two different active Offerings"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="Damage",type="INC",value=50}}}}," while you have at least two different active Offerings "} c["50% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=50}}," Parried Debuff "} -c["50% increased Parried Debuff Magnitude"]={{}," Parried Debuff Magnitude "} +c["50% increased Parried Debuff Magnitude"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffMagnitude",type="INC",value=50}},nil} c["50% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=50}},nil} c["50% increased Rarity of Items found"]={{[1]={flags=0,keywordFlags=0,name="LootRarity",type="INC",value=50}},nil} c["50% increased Rarity of Items found when on Low Life"]={{[1]={[1]={type="Condition",var="LowLife"},flags=0,keywordFlags=0,name="LootRarity",type="INC",value=50}},nil} @@ -3159,9 +3157,7 @@ c["6% increased Mana Regeneration Rate"]={{[1]={flags=0,keywordFlags=0,name="Man c["6% increased Minion Duration"]={{[1]={[1]={skillType=77,type="SkillType"},flags=0,keywordFlags=0,name="Duration",type="INC",value=6}},nil} c["6% increased Movement Speed if you've successfully Parried Recently"]={{[1]={[1]={type="Condition",var="ParriedRecently"},flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=6}},nil} c["6% increased Movement Speed while you have an active Charm"]={{[1]={[1]={type="Condition",var="UsingCharm"},flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=6}},nil} -c["6% increased Parried Debuff Magnitude"]={{}," Parried Debuff Magnitude "} -c["6% increased Parried Debuff Magnitude 8% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=6}}," Parried Debuff Magnitude 8% increased Parried Debuff "} -c["6% increased Parried Debuff Magnitude 8% increased Parry Hit Area of Effect"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=6}}," Parried Debuff Magnitude 8% increasedHit "} +c["6% increased Parried Debuff Magnitude"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffMagnitude",type="INC",value=6}},nil} c["6% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=6}},nil} c["6% increased Power Charge Duration"]={{[1]={flags=0,keywordFlags=0,name="PowerChargesDuration",type="INC",value=6}},nil} c["6% increased Reservation Efficiency of Herald Skills"]={{[1]={[1]={skillType=52,type="SkillType"},flags=0,keywordFlags=0,name="ReservationEfficiency",type="INC",value=6}},nil} diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 301db66c28..b05ac04f51 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -503,6 +503,7 @@ local modNameList = { ["maximum fortification"] = "MaximumFortification", ["fortification"] = "MinimumFortification", ["maximum valour"] = "MaximumValour", + ["parried debuff magnitude"] = "ParryDebuffMagnitude", -- Charges ["maximum power charge"] = "PowerChargesMax", ["maximum power charges"] = "PowerChargesMax", From 1b760a1f91ec91b54229cf7ecb6f9f55176058e7 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:00:21 +0200 Subject: [PATCH 02/11] Add specific debuff magnitude processing Adds processing of "Magnitude" modifiers, in addition to existing checks for generif "DebuffEffect" and skill-specific "Magnitude" modifiers --- src/Modules/CalcPerform.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index 5e80d8abb7..c5aa0d4c6d 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -2257,7 +2257,8 @@ function calcs.perform(env, skipEHP) end end if buff.type == "Debuff" then - local inc = skillModList:Sum("INC", skillCfg, "DebuffEffect") + local specificInc = skillModList:Sum("INC", skillCfg, buff.name:gsub(" ", "").."Magnitude") or 0 -- non-skill increases specific to that debuff type + local inc = skillModList:Sum("INC", skillCfg, "DebuffEffect") + specificInc local more = skillModList:More(skillCfg, "DebuffEffect") * calcLib.mod(skillModList, skillCfg, "Magnitude") mult = (1 + inc / 100) * more end From 64274cd71777d06acbefdcb97e3d419839d40443 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:03:18 +0200 Subject: [PATCH 03/11] Change processing of Parry debuff stats - Moved the process of Debuff to `skillStatMap` as "Refutation" introduced new ways to gain access to parry debuff - Changed the mod details slightly to enable better debuff processing --- src/Data/SkillStatMap.lua | 4 ++++ src/Data/Skills/other.lua | 5 ----- src/Export/Skills/other.txt | 5 ----- src/Modules/ConfigOptions.lua | 2 +- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua index dc93877d50..e4e5de0f5f 100644 --- a/src/Data/SkillStatMap.lua +++ b/src/Data/SkillStatMap.lua @@ -2783,6 +2783,10 @@ return { ["frost_wall_maximum_life"] = { mod("IceCrystalLifeBase", "BASE", nil), }, +-- Parry +["base_parry_buff_damage_taken_+%_final_to_apply"] = { + mod("DamageTaken", "MORE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Debuff", effectName = "Parry Debuff", effectCond = "ParryActive" }, { type = "Condition", var = "Effective" }), +}, -- Other ["triggered_skill_damage_+%"] = { mod("TriggeredDamage", "INC", nil, 0, 0, { type = "SkillType", skillType = SkillType.Triggered }), diff --git a/src/Data/Skills/other.lua b/src/Data/Skills/other.lua index 09905431e9..8d006d9623 100644 --- a/src/Data/Skills/other.lua +++ b/src/Data/Skills/other.lua @@ -11664,11 +11664,6 @@ skills["ParryPlayer"] = { label = "Parry", incrementalEffectiveness = 0.054999999701977, statDescriptionScope = "parry", - statMap = { - ["base_parry_buff_damage_taken_+%_final_to_apply"] = { - mod("DamageTaken", "MORE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Debuff", effectName = "Parry" }, { type = "Condition", var = "ParryActive" }), - }, - }, baseFlags = { attack = true, melee = true, diff --git a/src/Export/Skills/other.txt b/src/Export/Skills/other.txt index fcae5dc63f..821348f6a6 100644 --- a/src/Export/Skills/other.txt +++ b/src/Export/Skills/other.txt @@ -763,11 +763,6 @@ statMap = { #skill ParryPlayer #set ParryPlayer #flags attack melee duration shieldAttack area -statMap = { - ["base_parry_buff_damage_taken_+%_final_to_apply"] = { - mod("DamageTaken", "MORE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Debuff", effectName = "Parry" }, { type = "Condition", var = "ParryActive" }), - }, -}, #baseMod skill("debuff", true) #mods #skillEnd diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index c1b133a63c..8d6cd45cbd 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -483,7 +483,7 @@ local configSettings = { end }, { label = "Parry:", ifSkill = "Parry" }, { var = "parryActive", type = "check", label = "Enemy has Parry Debuff", ifSkill = "Parry", tooltip = "The Parry debuff grants:\n\tEnemies take 50% more Attack Damage", apply = function(val, modList, enemyModList) - enemyModList:NewMod("Condition:ParryActive", "FLAG", true, "Config") + modList:NewMod("Condition:ParryActive", "FLAG", true, "Config") end }, { label = "Plague Bearer:", ifSkill = "Plague Bearer"}, { var = "plagueBearerState", type = "list", label = "State:", ifSkill = "Plague Bearer", list = {{val="INC",label="Incubating"},{val="INF",label="Infecting"}}, apply = function(val, modList, enemyModList) From 14c16647a40c24a10f84062da993f7c94955ece8 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:07:56 +0200 Subject: [PATCH 04/11] Add stats for Parry duration and range Parry duration hasn't been processed at all yet, and mods affecting Parry range currently false apply to the weapon range used for the Parry attack, rather than blocking distance --- src/Data/SkillStatMap.lua | 4 ++++ src/Data/Skills/other.lua | 8 ++++++++ src/Export/Skills/other.txt | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua index e4e5de0f5f..02f519f375 100644 --- a/src/Data/SkillStatMap.lua +++ b/src/Data/SkillStatMap.lua @@ -2787,6 +2787,10 @@ return { ["base_parry_buff_damage_taken_+%_final_to_apply"] = { mod("DamageTaken", "MORE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Debuff", effectName = "Parry Debuff", effectCond = "ParryActive" }, { type = "Condition", var = "Effective" }), }, +["base_parry_duration_ms"] = { + skill("ParryDuration", nil), + div = 1000, +}, -- Other ["triggered_skill_damage_+%"] = { mod("TriggeredDamage", "INC", nil, 0, 0, { type = "SkillType", skillType = SkillType.Triggered }), diff --git a/src/Data/Skills/other.lua b/src/Data/Skills/other.lua index 8d006d9623..9ddd9325ea 100644 --- a/src/Data/Skills/other.lua +++ b/src/Data/Skills/other.lua @@ -11671,6 +11671,14 @@ skills["ParryPlayer"] = { shieldAttack = true, area = true, }, + statMap = { + ["base_maximum_active_block_distance_for_non_projectiles"] = { + skill("ParryBaseDistanceNonProj", nil), + }, + ["base_maximum_active_block_distance_for_projectiles"] = { + skill("ParryBaseDistanceProj", nil) + }, + }, baseMods = { skill("debuff", true), }, diff --git a/src/Export/Skills/other.txt b/src/Export/Skills/other.txt index 821348f6a6..01e4fae5a8 100644 --- a/src/Export/Skills/other.txt +++ b/src/Export/Skills/other.txt @@ -763,6 +763,14 @@ statMap = { #skill ParryPlayer #set ParryPlayer #flags attack melee duration shieldAttack area +statMap = { + ["base_maximum_active_block_distance_for_non_projectiles"] = { + skill("ParryBaseDistanceNonProj", nil), + }, + ["base_maximum_active_block_distance_for_projectiles"] = { + skill("ParryBaseDistanceProj", nil) + }, +}, #baseMod skill("debuff", true) #mods #skillEnd From 37d3fdbbad213d489e0949da74ca6ebac441ed98 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:09:59 +0200 Subject: [PATCH 05/11] Separate buff expiry function from skill duration Makes it easier to reuse in other contexts. No functional change otherwise --- src/Modules/CalcOffence.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index f17362af38..601a1abec4 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -358,6 +358,11 @@ local function calcWarcryCastTime(skillModList, skillCfg, skillData, actor) return warcryCastTime end +--- Calculates effect of buff/debuff expiration rate on actors +local function calcBuffExpirationMult(actorDB, cfg) + return 1 / m_max(data.misc.BuffExpirationSlowCap, calcLib.mod(actorDB, cfg, "BuffExpireFaster")) +end + function calcSkillDuration(skillModList, skillCfg, skillData, env, enemyDB) local durationMod = calcLib.mod(skillModList, skillCfg, "Duration", "PrimaryDuration", "DamagingAilmentDuration", skillData.mineDurationAppliesToSkill and "MineDuration" or nil) durationMod = m_max(durationMod, 0) @@ -365,7 +370,7 @@ function calcSkillDuration(skillModList, skillCfg, skillData, env, enemyDB) local duration = durationBase * durationMod local debuffDurationMult = 1 if env.mode_effective then - debuffDurationMult = 1 / m_max(data.misc.BuffExpirationSlowCap, calcLib.mod(enemyDB, skillCfg, "BuffExpireFaster")) + debuffDurationMult = calcBuffExpirationMult(enemyDB, skillCfg) end if skillData.debuff then duration = duration * debuffDurationMult From a5f8c9fcac8f7fdde877467e54d93aa944098f5b Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:11:58 +0200 Subject: [PATCH 06/11] Enable parry debuff recognition for "Refutation" --- src/Data/Skills/other.lua | 3 +++ src/Export/Skills/other.txt | 1 + 2 files changed, 4 insertions(+) diff --git a/src/Data/Skills/other.lua b/src/Data/Skills/other.lua index 9ddd9325ea..57acc551a5 100644 --- a/src/Data/Skills/other.lua +++ b/src/Data/Skills/other.lua @@ -12639,6 +12639,9 @@ skills["RefutationPlayer"] = { statDescriptionScope = "refutation", baseFlags = { }, + baseMods = { + skill("debuff", true), + }, constantStats = { { "base_skill_effect_duration", 4000 }, { "movement_speed_+%_final_while_performing_action", -70 }, diff --git a/src/Export/Skills/other.txt b/src/Export/Skills/other.txt index 01e4fae5a8..b1f300e7e1 100644 --- a/src/Export/Skills/other.txt +++ b/src/Export/Skills/other.txt @@ -851,6 +851,7 @@ statMap = { #skill RefutationPlayer #set RefutationPlayer #flags +#baseMod skill("debuff", true) #mods #skillEnd From 31fdf5aaac5ec629545686578584e8e9a906aaa3 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:12:20 +0200 Subject: [PATCH 07/11] Add support for Parry Debuff Duration & Range mods Includes: - Parsing of mods - Calculation and adding to `output` - Breakdowns for each stat in CalcsSections --- src/Data/ModCache.lua | 22 +++++++++---------- src/Data/SkillStatMap.lua | 2 +- src/Data/Skills/other.lua | 4 ++-- src/Export/Skills/other.txt | 4 ++-- src/Modules/CalcOffence.lua | 42 ++++++++++++++++++++++++++++++++++++ src/Modules/CalcSections.lua | 14 ++++++++++++ src/Modules/ModParser.lua | 3 ++- 7 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 97a4a4660f..7c3336b501 100644 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -1297,7 +1297,7 @@ c["100% increased Ignite Magnitude"]={{[1]={flags=0,keywordFlags=8388608,name="A c["100% increased Magnitude of Abyssal Wasting you inflict"]={{}," Magnitude of Abyssal Wasting you inflict "} c["100% increased Magnitude of Abyssal Wasting you inflict Abyssal Wasting you inflict has Infinite Duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=100}}," Magnitude of Abyssal Wasting you inflict Abyssal Wasting you inflict has Infinite "} c["100% increased Mana Regeneration Rate"]={{[1]={flags=0,keywordFlags=0,name="ManaRegen",type="INC",value=100}},nil} -c["100% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=100}}," Parried Debuff "} +c["100% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffDuration",type="INC",value=100}},nil} c["100% increased Parry Damage"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="Damage",type="INC",value=100}},nil} c["100% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=100}},nil} c["100% increased Spell Damage"]={{[1]={flags=2,keywordFlags=0,name="Damage",type="INC",value=100}},nil} @@ -1603,7 +1603,7 @@ c["15% increased Melee Damage if you've dealt a Projectile Attack Hit in the pas c["15% increased Melee Damage with Hits at Close Range"]={{[1]={[1]={type="Condition",var="AtCloseRange"},flags=256,keywordFlags=262144,name="Damage",type="INC",value=15}},nil} c["15% increased Minion Duration"]={{[1]={[1]={skillType=77,type="SkillType"},flags=0,keywordFlags=0,name="Duration",type="INC",value=15}},nil} c["15% increased Movement Speed"]={{[1]={flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=15}},nil} -c["15% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=15}}," Parried Debuff "} +c["15% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffDuration",type="INC",value=15}},nil} c["15% increased Parried Debuff Magnitude"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffMagnitude",type="INC",value=15}},nil} c["15% increased Parry Hit Area of Effect"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=15}},"Hit "} c["15% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=15}},nil} @@ -1801,7 +1801,7 @@ c["2% increased Mana Recovery rate per 10 Tribute"]={{[1]={[1]={actor="parent",d c["2% increased Maximum Life per socketed Grand Spectrum"]={{[1]={[1]={type="Multiplier",var="GrandSpectrum"},flags=0,keywordFlags=0,name="Life",type="INC",value=2}},nil} c["2% increased Movement Speed"]={{[1]={flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=2}},nil} c["2% increased Movement Speed while Sprinting"]={{[1]={[1]={type="Condition",var="Sprinting"},flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=2}},nil} -c["2% increased Parried Debuff Duration per 10 Tribute"]={{[1]={[1]={actor="parent",div=10,stat="Tribute",type="PerStat"},flags=0,keywordFlags=0,name="Duration",type="INC",value=2}}," Parried Debuff "} +c["2% increased Parried Debuff Duration per 10 Tribute"]={{[1]={[1]={actor="parent",div=10,stat="Tribute",type="PerStat"},flags=0,keywordFlags=0,name="ParryDebuffDuration",type="INC",value=2}},nil} c["2% increased Reservation Efficiency of Skills per Idol in your Equipment"]={{[1]={flags=0,keywordFlags=0,name="ReservationEfficiency",type="INC",value=2}}," per Idol in your Equipment "} c["2% increased Reservation Efficiency of Skills per Idol in your Equipment -4% to all Elemental Resistances per non-Idol Augment in your Equipment"]={{[1]={flags=0,keywordFlags=0,name="ReservationEfficiency",type="INC",value=2}}," per Idol in your Equipment -4% to all Elemental Resistances per non-Idol Augment in your Equipment "} c["2% increased Skill Speed"]={{[1]={flags=0,keywordFlags=0,name="Speed",type="INC",value=2},[2]={flags=0,keywordFlags=0,name="WarcrySpeed",type="INC",value=2},[3]={flags=0,keywordFlags=0,name="TotemPlacementSpeed",type="INC",value=2}},nil} @@ -1985,10 +1985,10 @@ c["20% increased Minion Duration"]={{[1]={[1]={skillType=77,type="SkillType"},fl c["20% increased Movement Speed"]={{[1]={flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=20}},nil} c["20% increased Movement Speed while affected by an Ailment"]={{[1]={[1]={type="Condition",varList={[1]="Bleeding",[2]="Poisoned",[3]="Ignited",[4]="Chilled",[5]="Frozen",[6]="Shocked",[7]="Electrocuted"}},flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=20}},nil} c["20% increased Movement Speed while an enemy with an Open Weakness is in your Presence"]={{[1]={[1]={type="Condition",var="OpenWeaknessEnemyPresence"},flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=20}},nil} -c["20% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=20}}," Parried Debuff "} +c["20% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffDuration",type="INC",value=20}},nil} c["20% increased Parry Damage"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="Damage",type="INC",value=20}},nil} c["20% increased Parry Hit Area of Effect"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=20}},"Hit "} -c["20% increased Parry Range"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="WeaponRange",type="INC",value=20}},nil} +c["20% increased Parry Range"]={{[1]={flags=0,keywordFlags=0,name="ParryRangeNonProj",type="INC",value=20},[2]={flags=0,keywordFlags=0,name="ParryRangeProj",type="INC",value=20}},nil} c["20% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=20}},nil} c["20% increased Physical Damage with Bows"]={{[1]={flags=131076,keywordFlags=0,name="PhysicalDamage",type="INC",value=20}},nil} c["20% increased Pin Buildup"]={{[1]={flags=0,keywordFlags=0,name="EnemyPinBuildup",type="INC",value=20}},nil} @@ -2019,7 +2019,7 @@ c["20% increased Stun buildup if you have Shapeshifted to an Animal form Recentl c["20% increased Thorns damage"]={{[1]={flags=32,keywordFlags=0,name="Damage",type="INC",value=20}},nil} c["20% increased Totem Damage"]={{[1]={flags=0,keywordFlags=16384,name="Damage",type="INC",value=20}},nil} c["20% increased Totem Life"]={{[1]={flags=0,keywordFlags=0,name="TotemLife",type="INC",value=20}},nil} -c["20% increased Totem Placement range"]={{[1]={flags=0,keywordFlags=16384,name="WeaponRange",type="INC",value=20}}," Placement "} +c["20% increased Totem Placement range"]={{}," Placement range "} c["20% increased Totem Placement speed"]={{[1]={flags=0,keywordFlags=0,name="TotemPlacementSpeed",type="INC",value=20}},nil} c["20% increased Tribute"]={{[1]={flags=0,keywordFlags=0,name="Tribute",type="INC",value=20}},nil} c["20% increased Warcry Speed"]={{[1]={flags=0,keywordFlags=4,name="WarcrySpeed",type="INC",value=20}},nil} @@ -2517,9 +2517,9 @@ c["30% increased Mana Regeneration Rate while moving"]={{[1]={[1]={type="Conditi c["30% increased Melee Damage if you've dealt a Projectile Attack Hit in the past eight seconds"]={{[1]={[1]={type="Condition",var="HitProjectileRecently"},flags=256,keywordFlags=0,name="Damage",type="INC",value=30}},nil} c["30% increased Melee Damage when on Full Life"]={{[1]={[1]={type="Condition",var="FullLife"},flags=256,keywordFlags=0,name="Damage",type="INC",value=30}},nil} c["30% increased Movement Speed"]={{[1]={flags=0,keywordFlags=0,name="MovementSpeed",type="INC",value=30}},nil} -c["30% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=30}}," Parried Debuff "} +c["30% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffDuration",type="INC",value=30}},nil} c["30% increased Parry Damage"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="Damage",type="INC",value=30}},nil} -c["30% increased Parry Range"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="WeaponRange",type="INC",value=30}},nil} +c["30% increased Parry Range"]={{[1]={flags=0,keywordFlags=0,name="ParryRangeNonProj",type="INC",value=30},[2]={flags=0,keywordFlags=0,name="ParryRangeProj",type="INC",value=30}},nil} c["30% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=30}},nil} c["30% increased Physical Damage while Shapeshifted"]={{[1]={[1]={type="Condition",var="Shapeshifted"},flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=30}},nil} c["30% increased Pin Buildup"]={{[1]={flags=0,keywordFlags=0,name="EnemyPinBuildup",type="INC",value=30}},nil} @@ -3030,7 +3030,7 @@ c["50% increased Mana Regeneration Rate while stationary"]={{[1]={[1]={type="Con c["50% increased Melee Damage against Heavy Stunned enemies"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="HeavyStunned"},flags=256,keywordFlags=0,name="Damage",type="INC",value=50}},nil} c["50% increased Melee Damage against Immobilised Enemies"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="Immobilised"},flags=256,keywordFlags=0,name="Damage",type="INC",value=50}},nil} c["50% increased Minion Damage while you have at least two different active Offerings"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={flags=0,keywordFlags=0,name="Damage",type="INC",value=50}}}}," while you have at least two different active Offerings "} -c["50% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=50}}," Parried Debuff "} +c["50% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffDuration",type="INC",value=50}},nil} c["50% increased Parried Debuff Magnitude"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffMagnitude",type="INC",value=50}},nil} c["50% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=50}},nil} c["50% increased Rarity of Items found"]={{[1]={flags=0,keywordFlags=0,name="LootRarity",type="INC",value=50}},nil} @@ -3045,7 +3045,7 @@ c["50% increased Strength Requirement"]={{[1]={flags=0,keywordFlags=0,name="StrR c["50% increased Stun Threshold while Channelling"]={{[1]={[1]={type="Condition",var="Channelling"},flags=0,keywordFlags=0,name="StunThreshold",type="INC",value=50}},nil} c["50% increased Surrounded Area of Effect"]={{[1]={flags=0,keywordFlags=0,name="SurroundedArea",type="INC",value=50}},nil} c["50% increased Thorns damage if you've consumed an Endurance Charge Recently"]={{[1]={[1]={limit=1,type="Multiplier",var="RemovableEnduranceCharge"},flags=32,keywordFlags=0,name="Damage",type="INC",value=50}},nil} -c["50% increased Totem Placement range"]={{[1]={flags=0,keywordFlags=16384,name="WeaponRange",type="INC",value=50}}," Placement "} +c["50% increased Totem Placement range"]={{}," Placement range "} c["50% increased amount of Mana Leeched"]={{[1]={flags=0,keywordFlags=0,name="MaxManaLeechRate",type="INC",value=50}},nil} c["50% increased effect of Incision"]={{[1]={flags=0,keywordFlags=0,name="IncisionEffect",type="INC",value=50}},nil} c["50% increased effect of Small Passive Skills"]={{[1]={flags=0,keywordFlags=0,name="SmallPassiveSkillEffect",type="INC",value=50}},nil} @@ -3338,7 +3338,7 @@ c["8% increased Mana Regeneration Rate"]={{[1]={flags=0,keywordFlags=0,name="Man c["8% increased Melee Attack Speed"]={{[1]={flags=257,keywordFlags=0,name="Speed",type="INC",value=8}},nil} c["8% increased Melee Damage"]={{[1]={flags=256,keywordFlags=0,name="Damage",type="INC",value=8}},nil} c["8% increased Minion Duration"]={{[1]={[1]={skillType=77,type="SkillType"},flags=0,keywordFlags=0,name="Duration",type="INC",value=8}},nil} -c["8% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=8}}," Parried Debuff "} +c["8% increased Parried Debuff Duration"]={{[1]={flags=0,keywordFlags=0,name="ParryDebuffDuration",type="INC",value=8}},nil} c["8% increased Parry Hit Area of Effect"]={{[1]={[1]={includeTransfigured=true,skillName="Parry",type="SkillName"},flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=8}},"Hit "} c["8% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=8}},nil} c["8% increased Power Charge Duration"]={{[1]={flags=0,keywordFlags=0,name="PowerChargesDuration",type="INC",value=8}},nil} diff --git a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua index 02f519f375..5a1ba715f1 100644 --- a/src/Data/SkillStatMap.lua +++ b/src/Data/SkillStatMap.lua @@ -2788,7 +2788,7 @@ return { mod("DamageTaken", "MORE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Debuff", effectName = "Parry Debuff", effectCond = "ParryActive" }, { type = "Condition", var = "Effective" }), }, ["base_parry_duration_ms"] = { - skill("ParryDuration", nil), + skill("parryDebuffDuration", nil), div = 1000, }, -- Other diff --git a/src/Data/Skills/other.lua b/src/Data/Skills/other.lua index 57acc551a5..e5a6add1bf 100644 --- a/src/Data/Skills/other.lua +++ b/src/Data/Skills/other.lua @@ -11673,10 +11673,10 @@ skills["ParryPlayer"] = { }, statMap = { ["base_maximum_active_block_distance_for_non_projectiles"] = { - skill("ParryBaseDistanceNonProj", nil), + skill("parryRangeNonProj", nil), }, ["base_maximum_active_block_distance_for_projectiles"] = { - skill("ParryBaseDistanceProj", nil) + skill("parryRangeProj", nil) }, }, baseMods = { diff --git a/src/Export/Skills/other.txt b/src/Export/Skills/other.txt index b1f300e7e1..42d451535b 100644 --- a/src/Export/Skills/other.txt +++ b/src/Export/Skills/other.txt @@ -765,10 +765,10 @@ statMap = { #flags attack melee duration shieldAttack area statMap = { ["base_maximum_active_block_distance_for_non_projectiles"] = { - skill("ParryBaseDistanceNonProj", nil), + skill("parryRangeNonProj", nil), }, ["base_maximum_active_block_distance_for_projectiles"] = { - skill("ParryBaseDistanceProj", nil) + skill("parryRangeProj", nil) }, }, #baseMod skill("debuff", true) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 601a1abec4..bb3a8c3489 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -6126,6 +6126,48 @@ function calcs.offence(env, actor, activeSkill) if skillFlags.monsterExplode then output.CombinedAvgToMonsterLife = output.CombinedAvg / monsterLife * 100 end + -- Parry non-damage stats + if skillData.parryDebuffDuration and skillData.parryDebuffDuration > 0 then + local expirationMult = calcBuffExpirationMult(enemyDB, skillCfg) + --skillModList:NewMod("ParryDebuffDuration", "BASE", skillData.parryDebuffDuration, "Base value from skill") + output.ParryDebuffDuration = skillData.parryDebuffDuration * calcLib.mod(skillModList, skillCfg, "ParryDebuffDuration") * (expirationMult or 0) + if breakdown then + breakdown.ParryDebuffDuration = { + s_format("Duration of parry debuff on enemy:\n"), + s_format(""), + s_format("%.2fs ^8(base duration)", skillData.parryDebuffDuration), + s_format("x %.2f ^8(modifier)", calcLib.mod(skillModList, skillCfg, "ParryDebuffDuration")), + } + if expirationMult and expirationMult ~= 1 then + t_insert(breakdown.ParryDebuffDuration, s_format("x %.2f ^8(buff expiration multiplier)", expirationMult)) + end + t_insert(breakdown.ParryDebuffDuration, s_format("= %.2fs", output.ParryDebuffDuration)) + end + end + if skillData.parryRangeNonProj or skillData.parryRangeProj then + output.ParryRangeNonProj = (skillData.parryRangeNonProj or 0) * calcLib.mod(skillModList, skillCfg, "ParryRangeNonProj") + output.ParryRangeProj = (skillData.parryRangeProj or 0) * calcLib.mod(skillModList, skillCfg, "ParryRangeProj") + if breakdown then + if output.ParryRangeNonProj > 0 then + breakdown.ParryRangeNonProj = { + s_format("Max Parry distance vs. non-projectiles:"), + s_format(""), + s_format("%.1f m ^8(base parry range for non-projectiles)", skillData.parryRangeNonProj), + s_format("x %.1f ^8(modifier)", calcLib.mod(skillModList, skillCfg, "ParryRangeNonProj")), + s_format("= %.1f m", output.ParryRangeNonProj), + } + end + if output.ParryRangeProj > 0 then + breakdown.ParryRangeProj = { + s_format("Max Parry distance vs. projectiles:\n"), + s_format(""), + s_format("%.1f m ^8(base parry range for projectiles)", skillData.parryRangeProj), + s_format("x %.1f ^8(modifier)", calcLib.mod(skillModList, skillCfg, "ParryRangeProj")), + s_format("= %.1f m", output.ParryRangeProj), + } + end + end + end if skillFlags.impale then local mainHandImpaleDPS, offHandImpaleDPS if skillFlags.attack and skillData.doubleHitsWhenDualWielding and skillFlags.bothWeaponAttack then diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index 1792e3e71b..1005c360e8 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -850,6 +850,20 @@ return { { breakdown = "SealGainTime" }, { modName = "SealGainFrequency", cfg = "skill" }, }, }, + -- Parry + { label = "Parry Duration", haveOutput = "ParryDebuffDuration", { format = "{2:output:ParryDebuffDuration}s", + { breakdown = "ParryDebuffDuration" }, + { label = "Player modifiers", modName = "ParryDebuffDuration", cfg = "skill" }, + { label = "Enemy modifiers", modName = "BuffExpireFaster", enemy = true }, + }, }, + { label = "Parry Range", haveOutput = "ParryRangeNonProj", { format = "{1:output:ParryRangeNonProj}m", + { breakdown = "ParryRangeNonProj" }, + { label = "Range modifiers", modName = "ParryRangeNonProj", cfg = "skill" }, + }, }, + { label = "Parry Range Proj", haveOutput = "ParryRangeProj", { format = "{1:output:ParryRangeProj}m", + { breakdown = "ParryRangeProj" }, + { label = "Range modifiers", modName = "ParryRangeProj", cfg = "skill" }, + }, }, -- Mines { label = "Active Mine Limit", flag = "mine", { format = "{0:output:ActiveMineLimit}", { modName = "ActiveMineLimit", cfg = "skill" }, }, }, { label = "Mine Throw Rate", flag = "mine", { format = "{2:output:MineLayingSpeed}", diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index b05ac04f51..89b5633f69 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -504,6 +504,8 @@ local modNameList = { ["fortification"] = "MinimumFortification", ["maximum valour"] = "MaximumValour", ["parried debuff magnitude"] = "ParryDebuffMagnitude", + ["parried debuff duration"] = "ParryDebuffDuration", + ["parry range"] = { "ParryRangeNonProj", "ParryRangeProj" }, -- Charges ["maximum power charge"] = "PowerChargesMax", ["maximum power charges"] = "PowerChargesMax", @@ -663,7 +665,6 @@ local modNameList = { ["cooldown recovery rate"] = "CooldownRecovery", ["cooldown use"] = "AdditionalCooldownUses", ["cooldown uses"] = "AdditionalCooldownUses", - ["range"] = "WeaponRange", ["weapon range"] = "WeaponRange", ["metres to weapon range"] = "WeaponRangeMetre", ["metre to weapon range"] = "WeaponRangeMetre", From c723366c1a91a8d3d99c48d2eb65f7c00de861ea Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:42:44 +0200 Subject: [PATCH 08/11] Add breakdown for parry debuff magnitude Also slight changes to calculation approach in `CalcPerform` as it previously didn't account for debuff effect being multiplicative --- src/Data/SkillStatMap.lua | 1 + src/Modules/CalcOffence.lua | 24 +++++++++++++++++++++++- src/Modules/CalcPerform.lua | 7 ++++--- src/Modules/CalcSections.lua | 5 +++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua index 5a1ba715f1..b09b476812 100644 --- a/src/Data/SkillStatMap.lua +++ b/src/Data/SkillStatMap.lua @@ -2786,6 +2786,7 @@ return { -- Parry ["base_parry_buff_damage_taken_+%_final_to_apply"] = { mod("DamageTaken", "MORE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Debuff", effectName = "Parry Debuff", effectCond = "ParryActive" }, { type = "Condition", var = "Effective" }), + skill("parryDebuffBaseMagnitude", nil), }, ["base_parry_duration_ms"] = { skill("parryDebuffDuration", nil), diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index bb3a8c3489..90b86a29b8 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -6126,7 +6126,29 @@ function calcs.offence(env, actor, activeSkill) if skillFlags.monsterExplode then output.CombinedAvgToMonsterLife = output.CombinedAvg / monsterLife * 100 end - -- Parry non-damage stats + -- Parry Stats + -- NOTE: This section is mainly for skill-specific breakdowns. Actual application of damage modifier is handled in `CalcPerform` + local parryDebuffMagnitudeMod = calcLib.mod(skillModList, skillCfg, "ParryDebuffMagnitude") + if skillData.parryDebuffBaseMagnitude and parryDebuffMagnitudeMod and parryDebuffMagnitudeMod ~= 1 then + output.ParryDebuffMagnitudeMod = parryDebuffMagnitudeMod + if breakdown then + local inc = skillModList:Sum("INC", skillCfg, "ParryDebuffMagnitude") + local more = skillModList:More(skillCfg, "ParryDebuffMagnitude") * calcLib.mod(skillModList, skillCfg, "DebuffEffect") + breakdown.ParryDebuffMagnitudeMod = { + s_format("Modifiers to Parry Debuff Magnitude:"), + s_format(""), + s_format("x %.2f ^8(increased magnitude)", 1 + inc / 100), + s_format("x %.2f ^8(more magnitude)", more + 1), + s_format("= %.2f", parryDebuffMagnitudeMod), + s_format(""), + s_format("Resulting Parry Debuff Magnitude:"), + s_format("%.2f%% more damage taken ^8(base magnitude)", skillData.parryDebuffBaseMagnitude), + s_format("x %.2f", parryDebuffMagnitudeMod), + s_format("= %.2f%% more damage taken", skillData.parryDebuffBaseMagnitude * parryDebuffMagnitudeMod), + s_format("^8Note: Only the highest Parry Debuff magnitude will be counted"), + } + end + end if skillData.parryDebuffDuration and skillData.parryDebuffDuration > 0 then local expirationMult = calcBuffExpirationMult(enemyDB, skillCfg) --skillModList:NewMod("ParryDebuffDuration", "BASE", skillData.parryDebuffDuration, "Base value from skill") diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index c5aa0d4c6d..9a46240e26 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -2257,9 +2257,10 @@ function calcs.perform(env, skipEHP) end end if buff.type == "Debuff" then - local specificInc = skillModList:Sum("INC", skillCfg, buff.name:gsub(" ", "").."Magnitude") or 0 -- non-skill increases specific to that debuff type - local inc = skillModList:Sum("INC", skillCfg, "DebuffEffect") + specificInc - local more = skillModList:More(skillCfg, "DebuffEffect") * calcLib.mod(skillModList, skillCfg, "Magnitude") + local specificDebuffMult = calcLib.mod(skillModList, skillCfg, buff.name:gsub(" ", "").."Magnitude") -- non-skill mods specific to that debuff type + local skillMagnitudeMult = calcLib.mod(skillModList, skillCfg, "Magnitude") + local inc = skillModList:Sum("INC", skillCfg, "DebuffEffect") + local more = skillModList:More(skillCfg, "DebuffEffect") * skillMagnitudeMult * specificDebuffMult mult = (1 + inc / 100) * more end srcList:ScaleAddList(buff.modList, mult * stackCount) diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index 1005c360e8..aac448a6cd 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -851,6 +851,11 @@ return { { modName = "SealGainFrequency", cfg = "skill" }, }, }, -- Parry + { label = "Parry Effect Mod", haveOutput = "ParryDebuffMagnitudeMod", { format = "x {2:output:ParryDebuffMagnitudeMod}", + { breakdown = "ParryDebuffMagnitudeMod" }, + { label = "Parry Magnitude", modName = "ParryDebuffMagnitude", cfg = "skill" }, + { label = "Debuff Effect", modName = "DebuffEffect", cfg = "skill" }, + }, }, { label = "Parry Duration", haveOutput = "ParryDebuffDuration", { format = "{2:output:ParryDebuffDuration}s", { breakdown = "ParryDebuffDuration" }, { label = "Player modifiers", modName = "ParryDebuffDuration", cfg = "skill" }, From 3178addca07fc67b0b606dcb5cbc012fa1af9cf4 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Thu, 4 Jun 2026 10:49:37 +0200 Subject: [PATCH 09/11] Make parry config option available for other skills --- src/Data/SkillStatMap.lua | 1 + src/Modules/ConfigOptions.lua | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua index b09b476812..09086b5830 100644 --- a/src/Data/SkillStatMap.lua +++ b/src/Data/SkillStatMap.lua @@ -2787,6 +2787,7 @@ return { ["base_parry_buff_damage_taken_+%_final_to_apply"] = { mod("DamageTaken", "MORE", nil, ModFlag.Attack, 0, { type = "GlobalEffect", effectType = "Debuff", effectName = "Parry Debuff", effectCond = "ParryActive" }, { type = "Condition", var = "Effective" }), skill("parryDebuffBaseMagnitude", nil), + flag("CanParry"), }, ["base_parry_duration_ms"] = { skill("parryDebuffDuration", nil), diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index 8d6cd45cbd..d97ccb1d52 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -481,8 +481,8 @@ local configSettings = { modList:NewMod("Multiplier:StoicismSeconds", "BASE", m_min(m_max(val, 0), 20), "Config") modList:NewMod("Multiplier:StoicismCap", "BASE", 20, "Config") end }, - { label = "Parry:", ifSkill = "Parry" }, - { var = "parryActive", type = "check", label = "Enemy has Parry Debuff", ifSkill = "Parry", tooltip = "The Parry debuff grants:\n\tEnemies take 50% more Attack Damage", apply = function(val, modList, enemyModList) + { label = "Parry:", ifFlag = "CanParry" }, + { var = "parryActive", type = "check", label = "Enemy has Parry Debuff", ifFlag = "CanParry", tooltip = "The Parry debuff grants:\n\tEnemies take 50% more Attack Damage", apply = function(val, modList, enemyModList) modList:NewMod("Condition:ParryActive", "FLAG", true, "Config") end }, { label = "Plague Bearer:", ifSkill = "Plague Bearer"}, From 0cf1286beceed5f0ee8dd9e382adbdfd3cb2fc05 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Thu, 4 Jun 2026 12:09:39 +0200 Subject: [PATCH 10/11] Fix config option not appearing for other skills --- src/Modules/CalcPerform.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index 9a46240e26..2a52666184 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -2374,6 +2374,9 @@ function calcs.perform(env, skipEHP) if activeSkill.skillModList:Flag(nil, "ApplyCriticalWeakness") then modDB:NewMod("ApplyCriticalWeakness", "FLAG", true) end + if activeSkill.skillModList:Flag(nil, "CanParry") then + modDB:NewMod("CanParry", "FLAG", true) + end --Handle combustion if enemyDB:Flag(nil, "Condition:Ignited") and (activeSkill.skillTypes[SkillType.Damage] or activeSkill.skillTypes[SkillType.Attack]) and not appliedCombustion then for _, support in ipairs(activeSkill.supportList) do From 558d43bed8225c51531160f42aea7ebce8cc0d2c Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Thu, 4 Jun 2026 14:19:35 +0200 Subject: [PATCH 11/11] Add parry test to `TestSkills_spec.lua` Automatically tests: - parry debuff increases damage when active - parry magnitude further increases damage - parry debuff does not affect spell damage NOTE: that last one will have to be adjusted once we support the mod that changes parry to apply to spell damage instead, but I guess that's what the test is for... --- spec/System/TestSkills_spec.lua | 52 +++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/spec/System/TestSkills_spec.lua b/spec/System/TestSkills_spec.lua index 6b9d590ec9..a8d7108981 100644 --- a/spec/System/TestSkills_spec.lua +++ b/spec/System/TestSkills_spec.lua @@ -987,4 +987,56 @@ describe("TestSkills", function() local expectedAverageEffect = 1 + (build.calcsTab.calcsOutput.MaxAncestralEmpowermentCombinedDamageEffect - 1) * build.calcsTab.calcsOutput.AncestralEmpowermentCombinedUptimeRatio / 100 assert.are.equals(round(expectedAverageEffect, 4), round(build.calcsTab.calcsOutput.AvgAncestralEmpowermentCombinedDamageEffect, 4)) end) + + it("calculates effects of parry debuff correctly", function() + build.itemsTab:CreateDisplayItemFromRaw([[ + Generic EV Shield + Desert Buckler + Evasion: 230 + Quality: 20 + LevelReq: 80 + ]]) + build.itemsTab:AddDisplayItem() + runCallback("OnFrame") + build.skillsTab:PasteSocketGroup("Parry 20/0 1") + runCallback("OnFrame") + build.configTab:BuildModList() + runCallback("OnFrame") + build.calcsTab:BuildOutput() + runCallback("OnFrame") + + -- Test general debuff + local preParryDmg = build.calcsTab.mainOutput.AverageDamage + build.configTab.configSets[1].input.parryActive = true + build.configTab:BuildModList() + build.calcsTab:BuildOutput() + runCallback("OnFrame") + local postParryDmg = build.calcsTab.mainOutput.AverageDamage + assert.True(postParryDmg > preParryDmg, "Damage should be higher with Parry active") + + -- Test Magnitude + build.configTab.input.customMods = "50% increased parried debuff magnitude" + build.configTab:BuildModList() + runCallback("OnFrame") + build.calcsTab:BuildOutput() + runCallback("OnFrame") + local incMagnitudeDmg = build.calcsTab.mainOutput.AverageDamage + assert.True(incMagnitudeDmg > postParryDmg, "Damage should be higher with increased parried debuff magnitude") + + -- Test effect on spells + build.skillsTab:PasteSocketGroup("Bone Cage 20/0 1") + runCallback("OnFrame") + selectActiveSkillById(build.skillsTab.socketGroupList[#build.skillsTab.socketGroupList], "BoneCagePlayer") + runCallback("OnFrame") + build.calcsTab:BuildOutput() + runCallback("OnFrame") + local withParrySpellDmg = build.calcsTab.mainOutput.AverageDamage + build.configTab.configSets[1].input.parryActive = false + build.configTab:BuildModList() + runCallback("OnFrame") + build.calcsTab:BuildOutput() + runCallback("OnFrame") + local noParrySpellDmg = build.calcsTab.mainOutput.AverageDamage + assert.equals(withParrySpellDmg, noParrySpellDmg, "Parry should not affect spell damage") + end) end)