From e48e2517d17d2c40d4fdfd71ce5e4c80d014f229 Mon Sep 17 00:00:00 2001 From: Von Kieffer Date: Wed, 4 Nov 2026 09:56:42 -0600 Subject: [PATCH] Support Witchhunter's No Mercy "Deal up to 40% more Damage to Enemies based on their missing Concentration" didn't parse. It now scales linearly with a new Config option, "Enemy's missing Concentration %" (0-100, shown when the build has No Mercy): 50% missing gives 20% more Damage, 100% gives the full 40%. Co-Authored-By: Claude Opus 5.5 --- spec/System/TestNoMercy_spec.lua | 41 ++++++++++++++++++++++++++++++++ src/Data/ModCache.lua | 2 +- src/Modules/ConfigOptions.lua | 3 +++ src/Modules/ModParser.lua | 3 +++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 spec/System/TestNoMercy_spec.lua diff --git a/spec/System/TestNoMercy_spec.lua b/spec/System/TestNoMercy_spec.lua new file mode 100644 index 0000000000..357f27125d --- /dev/null +++ b/spec/System/TestNoMercy_spec.lua @@ -0,0 +1,41 @@ +describe("TestNoMercy", function() + before_each(function() + newBuild() + end) + + teardown(function() + -- newBuild() takes care of resetting everything in setup() + end) + + local function dpsWith(missing) + build.configTab.input.customMods = "Deal up to 40% more Damage to Enemies based on their missing Concentration" + build.configTab.input.multiplierEnemyMissingConcentration = missing + build.configTab:BuildModList() + runCallback("OnFrame") + return build.calcsTab.mainOutput.TotalDPS + end + + it("parses the No Mercy node", function() + local node = build.spec.nodes[46535] + assert.is_not_nil(node) + local mod = node.mods[1].list[1] + assert.is_nil(node.mods[1].extra) + assert.are.equals("Damage", mod.name) + assert.are.equals("MORE", mod.type) + assert.are.equals("EnemyMissingConcentrationPercent", mod[1].var) + end) + + it("scales with the enemy's missing Concentration", function() + build.skillsTab:PasteSocketGroup("Fireball 20/0 1") + local base = dpsWith(0) + assert.True(base > 0) + assert.is_true(math.abs(dpsWith(50) - base * 1.2) < 0.01) + assert.is_true(math.abs(dpsWith(100) - base * 1.4) < 0.01) + end) + + it("caps at 100% missing Concentration", function() + build.skillsTab:PasteSocketGroup("Fireball 20/0 1") + local base = dpsWith(0) + assert.is_true(math.abs(dpsWith(250) - base * 1.4) < 0.01) + end) +end) diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 50484e61c0..de5c8742c7 100644 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -7156,7 +7156,7 @@ c["Deal no Non-Elemental Damage"]={{[1]={flags=0,keywordFlags=0,name="DealNoPhys c["Deal no Non-Fire Damage"]={{[1]={flags=0,keywordFlags=0,name="DealNoPhysical",type="FLAG",value=true},[2]={flags=0,keywordFlags=0,name="DealNoLightning",type="FLAG",value=true},[3]={flags=0,keywordFlags=0,name="DealNoCold",type="FLAG",value=true},[4]={flags=0,keywordFlags=0,name="DealNoChaos",type="FLAG",value=true}},nil} c["Deal no Non-Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="DealNoLightning",type="FLAG",value=true},[2]={flags=0,keywordFlags=0,name="DealNoCold",type="FLAG",value=true},[3]={flags=0,keywordFlags=0,name="DealNoFire",type="FLAG",value=true},[4]={flags=0,keywordFlags=0,name="DealNoChaos",type="FLAG",value=true}},nil} c["Deal no Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="DealNoPhysical",type="FLAG",value=true}},nil} -c["Deal up to 40% more Damage to Enemies based on their missing Concentration"]={nil,"up to 40% more Damage to Enemies based on their missing Concentration "} +c["Deal up to 40% more Damage to Enemies based on their missing Concentration"]={{[1]={[1]={limit=100,type="Multiplier",var="EnemyMissingConcentrationPercent"},flags=0,keywordFlags=0,name="Damage",type="MORE",value=0.4}},nil} c["Deal your Thorns Damage to Enemies you Stun with Melee Attacks"]={nil,"your Thorns Damage to Enemies you Stun with Melee Attacks "} c["Deal your Thorns Damage to Enemies you Stun with Melee Attacks 35 to 53 Physical Thorns damage"]={{[1]={flags=256,keywordFlags=0,name="PhysicalMin",type="BASE",value=35},[2]={flags=256,keywordFlags=0,name="PhysicalMax",type="BASE",value=53}},"your to Enemies you Stun "} c["Deal your Thorns damage to enemies you Critically Hit with Melee Attacks"]={nil,"your Thorns damage to enemies you Critically Hit with Melee Attacks "} diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index 9033f6a152..d2c071d07a 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -1678,6 +1678,9 @@ Huge sets the radius to 11. { var = "conditionBleedAggravated", type = "check", label = "Is the Bleed Aggravated?", ifMod = "BleedChance", tooltip = "Bleeding deals an extra 100% damage while the target is moving, or if the Bleeding is Aggravated", apply = function(val, modList, enemyModList) enemyModList:NewMod("Condition:BleedAggravated", "FLAG", true, "Config", { type = "Condition", var = "Effective" }) end }, + { var = "multiplierEnemyMissingConcentration", type = "count", label = "Enemy's missing Concentration %:", ifMult = "EnemyMissingConcentrationPercent", tooltip = "How much of the enemy's maximum Concentration you have broken (0-100), for Witchhunter's No Mercy.", apply = function(val, modList, enemyModList) + modList:NewMod("Multiplier:EnemyMissingConcentrationPercent", "BASE", m_min(m_max(val, 0), 100), "Config", { type = "Condition", var = "Effective" }) + end }, { var = "conditionEnemyFullLife", type = "check", label = "Is the enemy on Full ^xE05030Life?", ifEnemyCond = "FullLife", apply = function(val, modList, enemyModList) enemyModList:NewMod("Condition:FullLife", "FLAG", true, "Config", { type = "Condition", var = "Effective" }) end }, diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index ff8a00f8fa..f94cd5cb14 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -3311,6 +3311,9 @@ local specialModList = { mod("ExtraSkill", "LIST", { skillId = "SorceryWardPlayer", level = 1 }), }, ["sorcery ward's barrier can also take physical and chaos damage from hits"] = { flag("Condition:CeremonialAblution") }, + ["deal up to (%d+)%% more damage to enemies based on their missing concentration"] = function(num) return { + mod("Damage", "MORE", num / 100, { type = "Multiplier", var = "EnemyMissingConcentrationPercent", limit = 100 }), + } end, -- Warrior - Smith of Kitava ["body armour grants armour also applies to (%a+) damage taken from hits"] = function(_, dmgType) return { mod("ArmourAppliesTo"..firstToUpper(dmgType).."DamageTaken", "BASE", 100, { type = "ItemCondition", itemSlot = "Body Armour", rarityCond = "NORMAL" })