From 27609b295150f6cd5e43e8d52abea228d1f02d9c Mon Sep 17 00:00:00 2001 From: Trifall Date: Wed, 22 Jul 2026 03:18:24 -0400 Subject: [PATCH 1/2] Include projectile sequence damage mod in Kinetic Fusillade ailment damage calculations --- .../TestKineticFusilladePoison_spec.lua | 76 +++++++++++++++++++ src/Data/Skills/act_int.lua | 6 +- src/Export/Skills/act_int.txt | 4 +- 3 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 spec/System/TestKineticFusilladePoison_spec.lua diff --git a/spec/System/TestKineticFusilladePoison_spec.lua b/spec/System/TestKineticFusilladePoison_spec.lua new file mode 100644 index 00000000000..0f25574cccc --- /dev/null +++ b/spec/System/TestKineticFusilladePoison_spec.lua @@ -0,0 +1,76 @@ +describe("Kinetic Fusillade poison damage", function() + local poisonMods = "Adds 1000 to 1000 Fire Damage to Attacks\n100% chance to Poison on Hit\nAll Damage from Hits can Poison" + + local function recalculate() + build.modFlag = true + build.buildFlag = true + runCallback("OnFrame") + end + + local function setupBuild(skillName) + newBuild() + build.itemsTab:CreateDisplayItemFromRaw([[Elemental Wand + Imbued Wand + Crafted: true + Prefix: None + Prefix: None + Prefix: None + Suffix: None + Suffix: None + Suffix: None + Quality: 0 + Sockets: B-B-B + LevelReq: 59 + Implicits: 0]]) + build.itemsTab:AddDisplayItem() + build.skillsTab:PasteSocketGroup((skillName or "Kinetic Fusillade") .. " 20/20 1\nGreater Multiple Projectiles 20/0 1\n") + build.configTab.input.customMods = poisonMods + build.configTab:BuildModList() + runCallback("OnFrame") + end + + it("applies sequential projectile damage to poison", function() + setupBuild() + + local socketGroup = build.skillsTab.socketGroupList[build.mainSocketGroup] + local srcInstance = socketGroup.displaySkillList[socketGroup.mainActiveSkill].activeEffect.srcInstance + local allProjectilesPoisonDPS = build.calcsTab.mainOutput.MainHand.PoisonDPS + assert.are.equals(5, build.calcsTab.mainOutput.ProjectileCount) + assert.are.equals(24, build.calcsTab.mainOutput.KineticFusilladeAvgMoreMult) + + srcInstance.skillPart = 2 + recalculate() + local oneProjectilePoisonDPS = build.calcsTab.mainOutput.MainHand.PoisonDPS + + assert.are.near(1.24, allProjectilesPoisonDPS / oneProjectilePoisonDPS, 0.001) + end) + + it("applies sequential projectile damage to poison with Detonation", function() + setupBuild("Kinetic Fusillade of Detonation") + + local socketGroup = build.skillsTab.socketGroupList[build.mainSocketGroup] + local srcInstance = socketGroup.displaySkillList[socketGroup.mainActiveSkill].activeEffect.srcInstance + local allProjectilesPoisonDPS = build.calcsTab.mainOutput.MainHand.PoisonDPS + assert.are.equals(8, build.calcsTab.mainOutput.ProjectileCount) + assert.are.equals(56, build.calcsTab.mainOutput.KineticFusilladeAvgMoreMult) + + srcInstance.skillPart = 2 + recalculate() + local oneProjectilePoisonDPS = build.calcsTab.mainOutput.MainHand.PoisonDPS + + assert.are.near(1.56, allProjectilesPoisonDPS / oneProjectilePoisonDPS, 0.001) + end) + + it("does not apply generic projectile damage to poison", function() + setupBuild() + local poisonDPS = build.calcsTab.mainOutput.MainHand.PoisonDPS + local averageHit = build.calcsTab.mainOutput.MainHand.AverageHit + + build.configTab.input.customMods = poisonMods .. "\n100% increased Projectile Damage" + build.configTab:BuildModList() + recalculate() + + assert.are.equals(poisonDPS, build.calcsTab.mainOutput.MainHand.PoisonDPS) + assert.is_true(averageHit < build.calcsTab.mainOutput.MainHand.AverageHit) + end) +end) diff --git a/src/Data/Skills/act_int.lua b/src/Data/Skills/act_int.lua index 4fecc8f91ec..d1ac01ba0ab 100644 --- a/src/Data/Skills/act_int.lua +++ b/src/Data/Skills/act_int.lua @@ -11017,7 +11017,7 @@ skills["KineticFusillade"] = { -- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n -- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2 local avgMoreMult = moreDamagePerProj * (output.ProjectileCount - 1) / 2 - activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusillade", ModFlag.Hit) + activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusillade", 0, bit.bor(KeywordFlag.Hit, KeywordFlag.Ailment)) -- Store the average multiplier for display output.KineticFusilladeAvgMoreMult = avgMoreMult @@ -11235,7 +11235,7 @@ skills["KineticFusilladeAltX"] = { -- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n -- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2 local avgMoreMult = moreDamagePerProj * (output.ProjectileCount - 1) / 2 - activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusilladeAltX", ModFlag.Hit) + activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusilladeAltX", 0, bit.bor(KeywordFlag.Hit, KeywordFlag.Ailment)) -- Store the average multiplier for display output.KineticFusilladeAvgMoreMult = avgMoreMult @@ -21371,4 +21371,4 @@ skills["Zealotry"] = { [39] = { 19, 53, 33, cooldown = 1.2, levelRequirement = 99, manaReservationPercent = 50, storedUses = 1, statInterpolation = { 1, 1, 1, }, }, [40] = { 20, 54, 34, cooldown = 1.2, levelRequirement = 100, manaReservationPercent = 50, storedUses = 1, statInterpolation = { 1, 1, 1, }, }, }, -} \ No newline at end of file +} diff --git a/src/Export/Skills/act_int.txt b/src/Export/Skills/act_int.txt index 4c746132496..e593c3c899a 100644 --- a/src/Export/Skills/act_int.txt +++ b/src/Export/Skills/act_int.txt @@ -2299,7 +2299,7 @@ local skills, mod, flag, skill = ... -- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n -- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2 local avgMoreMult = moreDamagePerProj * (output.ProjectileCount - 1) / 2 - activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusillade", ModFlag.Hit) + activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusillade", 0, bit.bor(KeywordFlag.Hit, KeywordFlag.Ailment)) -- Store the average multiplier for display output.KineticFusilladeAvgMoreMult = avgMoreMult @@ -2441,7 +2441,7 @@ local skills, mod, flag, skill = ... -- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n -- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2 local avgMoreMult = moreDamagePerProj * (output.ProjectileCount - 1) / 2 - activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusilladeAltX", ModFlag.Hit) + activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusilladeAltX", 0, bit.bor(KeywordFlag.Hit, KeywordFlag.Ailment)) -- Store the average multiplier for display output.KineticFusilladeAvgMoreMult = avgMoreMult From d6e7c3b03b1fa56a8992a8a4cdc6f7f0bdc2cd70 Mon Sep 17 00:00:00 2001 From: LocalIdentity Date: Fri, 24 Jul 2026 03:59:19 +1000 Subject: [PATCH 2/2] Simple fix No need for a test --- .../TestKineticFusilladePoison_spec.lua | 76 ------------------- src/Data/Skills/act_int.lua | 6 +- src/Export/Skills/act_int.txt | 4 +- 3 files changed, 5 insertions(+), 81 deletions(-) delete mode 100644 spec/System/TestKineticFusilladePoison_spec.lua diff --git a/spec/System/TestKineticFusilladePoison_spec.lua b/spec/System/TestKineticFusilladePoison_spec.lua deleted file mode 100644 index 0f25574cccc..00000000000 --- a/spec/System/TestKineticFusilladePoison_spec.lua +++ /dev/null @@ -1,76 +0,0 @@ -describe("Kinetic Fusillade poison damage", function() - local poisonMods = "Adds 1000 to 1000 Fire Damage to Attacks\n100% chance to Poison on Hit\nAll Damage from Hits can Poison" - - local function recalculate() - build.modFlag = true - build.buildFlag = true - runCallback("OnFrame") - end - - local function setupBuild(skillName) - newBuild() - build.itemsTab:CreateDisplayItemFromRaw([[Elemental Wand - Imbued Wand - Crafted: true - Prefix: None - Prefix: None - Prefix: None - Suffix: None - Suffix: None - Suffix: None - Quality: 0 - Sockets: B-B-B - LevelReq: 59 - Implicits: 0]]) - build.itemsTab:AddDisplayItem() - build.skillsTab:PasteSocketGroup((skillName or "Kinetic Fusillade") .. " 20/20 1\nGreater Multiple Projectiles 20/0 1\n") - build.configTab.input.customMods = poisonMods - build.configTab:BuildModList() - runCallback("OnFrame") - end - - it("applies sequential projectile damage to poison", function() - setupBuild() - - local socketGroup = build.skillsTab.socketGroupList[build.mainSocketGroup] - local srcInstance = socketGroup.displaySkillList[socketGroup.mainActiveSkill].activeEffect.srcInstance - local allProjectilesPoisonDPS = build.calcsTab.mainOutput.MainHand.PoisonDPS - assert.are.equals(5, build.calcsTab.mainOutput.ProjectileCount) - assert.are.equals(24, build.calcsTab.mainOutput.KineticFusilladeAvgMoreMult) - - srcInstance.skillPart = 2 - recalculate() - local oneProjectilePoisonDPS = build.calcsTab.mainOutput.MainHand.PoisonDPS - - assert.are.near(1.24, allProjectilesPoisonDPS / oneProjectilePoisonDPS, 0.001) - end) - - it("applies sequential projectile damage to poison with Detonation", function() - setupBuild("Kinetic Fusillade of Detonation") - - local socketGroup = build.skillsTab.socketGroupList[build.mainSocketGroup] - local srcInstance = socketGroup.displaySkillList[socketGroup.mainActiveSkill].activeEffect.srcInstance - local allProjectilesPoisonDPS = build.calcsTab.mainOutput.MainHand.PoisonDPS - assert.are.equals(8, build.calcsTab.mainOutput.ProjectileCount) - assert.are.equals(56, build.calcsTab.mainOutput.KineticFusilladeAvgMoreMult) - - srcInstance.skillPart = 2 - recalculate() - local oneProjectilePoisonDPS = build.calcsTab.mainOutput.MainHand.PoisonDPS - - assert.are.near(1.56, allProjectilesPoisonDPS / oneProjectilePoisonDPS, 0.001) - end) - - it("does not apply generic projectile damage to poison", function() - setupBuild() - local poisonDPS = build.calcsTab.mainOutput.MainHand.PoisonDPS - local averageHit = build.calcsTab.mainOutput.MainHand.AverageHit - - build.configTab.input.customMods = poisonMods .. "\n100% increased Projectile Damage" - build.configTab:BuildModList() - recalculate() - - assert.are.equals(poisonDPS, build.calcsTab.mainOutput.MainHand.PoisonDPS) - assert.is_true(averageHit < build.calcsTab.mainOutput.MainHand.AverageHit) - end) -end) diff --git a/src/Data/Skills/act_int.lua b/src/Data/Skills/act_int.lua index d1ac01ba0ab..f0eea0e70ee 100644 --- a/src/Data/Skills/act_int.lua +++ b/src/Data/Skills/act_int.lua @@ -11017,7 +11017,7 @@ skills["KineticFusillade"] = { -- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n -- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2 local avgMoreMult = moreDamagePerProj * (output.ProjectileCount - 1) / 2 - activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusillade", 0, bit.bor(KeywordFlag.Hit, KeywordFlag.Ailment)) + activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusillade") -- Store the average multiplier for display output.KineticFusilladeAvgMoreMult = avgMoreMult @@ -11235,7 +11235,7 @@ skills["KineticFusilladeAltX"] = { -- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n -- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2 local avgMoreMult = moreDamagePerProj * (output.ProjectileCount - 1) / 2 - activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusilladeAltX", 0, bit.bor(KeywordFlag.Hit, KeywordFlag.Ailment)) + activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusilladeAltX") -- Store the average multiplier for display output.KineticFusilladeAvgMoreMult = avgMoreMult @@ -21371,4 +21371,4 @@ skills["Zealotry"] = { [39] = { 19, 53, 33, cooldown = 1.2, levelRequirement = 99, manaReservationPercent = 50, storedUses = 1, statInterpolation = { 1, 1, 1, }, }, [40] = { 20, 54, 34, cooldown = 1.2, levelRequirement = 100, manaReservationPercent = 50, storedUses = 1, statInterpolation = { 1, 1, 1, }, }, }, -} +} \ No newline at end of file diff --git a/src/Export/Skills/act_int.txt b/src/Export/Skills/act_int.txt index e593c3c899a..556c41b7e79 100644 --- a/src/Export/Skills/act_int.txt +++ b/src/Export/Skills/act_int.txt @@ -2299,7 +2299,7 @@ local skills, mod, flag, skill = ... -- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n -- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2 local avgMoreMult = moreDamagePerProj * (output.ProjectileCount - 1) / 2 - activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusillade", 0, bit.bor(KeywordFlag.Hit, KeywordFlag.Ailment)) + activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusillade") -- Store the average multiplier for display output.KineticFusilladeAvgMoreMult = avgMoreMult @@ -2441,7 +2441,7 @@ local skills, mod, flag, skill = ... -- Average multiplier: sum of (0, X, 2X, 3X, ..., (n-1)X) / n -- This equals: X * (0 + 1 + 2 + ... + (n-1)) / n = X * n(n-1)/2 / n = X * (n-1)/2 local avgMoreMult = moreDamagePerProj * (output.ProjectileCount - 1) / 2 - activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusilladeAltX", 0, bit.bor(KeywordFlag.Hit, KeywordFlag.Ailment)) + activeSkill.skillModList:NewMod("Damage", "MORE", avgMoreMult, "Skill:KineticFusilladeAltX") -- Store the average multiplier for display output.KineticFusilladeAvgMoreMult = avgMoreMult