From 0d02fdbf73b6f04d393a60727253ed398f4f46a7 Mon Sep 17 00:00:00 2001 From: LocalIdentity Date: Sun, 30 Aug 2026 10:39:14 +0000 Subject: [PATCH 1/2] Apply changes from https://github.com/PathOfBuildingCommunity/PathOfBuilding/pull/10268 --- src/Data/SkillStatMap.lua | 2 +- src/Modules/CalcBreakdown.lua | 5 ++- src/Modules/CalcOffence.lua | 57 +++++++++++++++++++-------------- src/Modules/CalcOffence.lua.rej | 20 ++++++++++++ 4 files changed, 58 insertions(+), 26 deletions(-) create mode 100644 src/Modules/CalcOffence.lua.rej diff --git a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua index 9219bae6d3..6e1b7cc086 100644 --- a/src/Data/SkillStatMap.lua +++ b/src/Data/SkillStatMap.lua @@ -654,7 +654,7 @@ return function(mod, flag, skill) mod("AreaOfEffect", "MORE", nil, 0, 0, { type = "Condition", var = "CastOnFrostbolt" }), }, ["active_skill_area_of_effect_radius_+%_final"] = { - mod("AreaOfEffect", "MORE", nil), + mod("AreaOfEffectRadius", "MORE", nil), }, ["active_skill_area_of_effect_+%_final"] = { mod("AreaOfEffect", "MORE", nil), diff --git a/src/Modules/CalcBreakdown.lua b/src/Modules/CalcBreakdown.lua index eabb0d2bc6..e5b079eb6c 100644 --- a/src/Modules/CalcBreakdown.lua +++ b/src/Modules/CalcBreakdown.lua @@ -95,12 +95,15 @@ return function(modDB, output, actor) }) end - function breakdown.area(base, areaMod, total, incBreakpoint, moreBreakpoint, redBreakpoint, lessBreakpoint, label) + function breakdown.area(base, areaMod, total, incBreakpoint, moreBreakpoint, redBreakpoint, lessBreakpoint, label, radiusMod) local out = {} t_insert(out, label) if base ~= total then t_insert(out, s_format("%.1fm ^8(base radius)", base / 10)) t_insert(out, s_format("x %.2f ^8(square root of area of effect modifier)", m_floor(100 * m_sqrt(areaMod)) / 100)) + if radiusMod and radiusMod ~= 1 then + t_insert(out, s_format("x %.2f ^8(final radius modifier)", radiusMod)) + end t_insert(out, s_format("= %.1fm", total / 10)) end if incBreakpoint and moreBreakpoint and redBreakpoint and lessBreakpoint then diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 40425570cc..e0713e1485 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -159,9 +159,13 @@ end ---Calculates skill radius ---@param baseRadius number ---@param areaMod number +---@param radiusMod number|nil ---@return number -local function calcRadius(baseRadius, areaMod) - return m_floor(baseRadius * m_floor(100 * m_sqrt(areaMod)) / 100) +local function calcRadius(baseRadius, areaMod, radiusMod) + local radiusPercent = m_floor(100 * m_sqrt(areaMod)) + -- Final radius modifiers apply after Area of Effect has been converted to radius. + radiusPercent = m_floor(radiusPercent * (radiusMod or 1)) + return m_floor(baseRadius * radiusPercent / 100) end ---Calculates the tertiary radius for Molten Strike, correctly handling the deadzone. @@ -180,30 +184,31 @@ end ---@param baseRadius number ---@param incArea number @Additive modifier ---@param moreArea number @Multiplicative modifier +---@param radiusMod number|nil @Final radius modifier ---@return number, number, number, number @Next breakpoint: increased, more; Previous breakpoint: reduced, less -local function calcRadiusBreakpoints(baseRadius, incArea, moreArea) - local radius = calcRadius(baseRadius, round(round(incArea * moreArea, 10), 2)) +local function calcRadiusBreakpoints(baseRadius, incArea, moreArea, radiusMod) + local radius = calcRadius(baseRadius, calcAreaMod(incArea, moreArea), radiusMod) local incAreaBreakpoint, redAreaBreakpoint, moreAreaBreakpoint, lessAreaBreakpoint if radius > 0 then incAreaBreakpoint = 0 repeat incAreaBreakpoint = incAreaBreakpoint + 1 - local newRadius = calcRadius(baseRadius, round(round((incArea + incAreaBreakpoint / 100) * moreArea, 10), 2)) + local newRadius = calcRadius(baseRadius, calcAreaMod(incArea + incAreaBreakpoint / 100, moreArea), radiusMod) until (newRadius > radius) redAreaBreakpoint = 0 repeat redAreaBreakpoint = redAreaBreakpoint + 1 - local newRadius = calcRadius(baseRadius, round(round((incArea - redAreaBreakpoint / 100) * moreArea, 10), 2)) + local newRadius = calcRadius(baseRadius, calcAreaMod(incArea - redAreaBreakpoint / 100, moreArea), radiusMod) until (newRadius < radius) moreAreaBreakpoint = 0 repeat moreAreaBreakpoint = moreAreaBreakpoint + 1 - local newRadius = calcRadius(baseRadius, round(round(incArea * moreArea * (1 + moreAreaBreakpoint / 100), 10), 2)) + local newRadius = calcRadius(baseRadius, calcAreaMod(incArea, moreArea * (1 + moreAreaBreakpoint / 100)), radiusMod) until (newRadius > radius) lessAreaBreakpoint = 0 repeat lessAreaBreakpoint = lessAreaBreakpoint + 1 - local newRadius = calcRadius(baseRadius, round(round(incArea * moreArea * (1 - lessAreaBreakpoint / 100), 10), 2)) + local newRadius = calcRadius(baseRadius, calcAreaMod(incArea, moreArea * (1 - lessAreaBreakpoint / 100)), radiusMod) until (newRadius < radius) end return incAreaBreakpoint, moreAreaBreakpoint, redAreaBreakpoint, lessAreaBreakpoint @@ -425,7 +430,8 @@ function calcs.offence(env, actor, activeSkill) local function calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, output, breakdown) local incArea, moreArea = calcLib.mods(skillModList, skillCfg, "AreaOfEffect", "AreaOfEffectPrimary") - output.AreaOfEffectMod = round(round(incArea * moreArea, 10), 2) + output.AreaOfEffectMod = calcAreaMod(incArea, moreArea) + local radiusMod = calcLib.mod(skillModList, skillCfg, "AreaOfEffectRadius") if skillData.radiusIsWeaponRange then local range = 0 if skillFlags.weapon1Attack then @@ -439,29 +445,29 @@ function calcs.offence(env, actor, activeSkill) if skillData.radius then skillFlags.area = true local baseRadius = skillData.radius + (skillData.radiusExtra or 0) + skillModList:Sum("BASE", skillCfg, "AreaOfEffect") - output.AreaOfEffectRadius = calcRadius(baseRadius, output.AreaOfEffectMod) + output.AreaOfEffectRadius = calcRadius(baseRadius, output.AreaOfEffectMod, radiusMod) output.AreaOfEffectRadiusMetres = output.AreaOfEffectRadius / 10 if breakdown then - local incAreaBreakpoint, moreAreaBreakpoint, redAreaBreakpoint, lessAreaBreakpoint = calcRadiusBreakpoints(baseRadius, incArea, moreArea) - breakdown.AreaOfEffectRadius = breakdown.area(baseRadius, output.AreaOfEffectMod, output.AreaOfEffectRadius, incAreaBreakpoint, moreAreaBreakpoint, redAreaBreakpoint, lessAreaBreakpoint, skillData.radiusLabel) + local incAreaBreakpoint, moreAreaBreakpoint, redAreaBreakpoint, lessAreaBreakpoint = calcRadiusBreakpoints(baseRadius, incArea, moreArea, radiusMod) + breakdown.AreaOfEffectRadius = breakdown.area(baseRadius, output.AreaOfEffectMod, output.AreaOfEffectRadius, incAreaBreakpoint, moreAreaBreakpoint, redAreaBreakpoint, lessAreaBreakpoint, skillData.radiusLabel, radiusMod) end if skillData.radiusSecondary then local incAreaSecondary, moreAreaSecondary = calcLib.mods(skillModList, skillCfg, "AreaOfEffect", "AreaOfEffectSecondary") - output.AreaOfEffectModSecondary = round(round(incAreaSecondary * moreAreaSecondary, 10), 2) + output.AreaOfEffectModSecondary = calcAreaMod(incAreaSecondary, moreAreaSecondary) baseRadius = skillData.radiusSecondary + (skillData.radiusExtra or 0) - output.AreaOfEffectRadiusSecondary = calcRadius(baseRadius, output.AreaOfEffectModSecondary) + output.AreaOfEffectRadiusSecondary = calcRadius(baseRadius, output.AreaOfEffectModSecondary, radiusMod) output.AreaOfEffectRadiusSecondaryMetres = output.AreaOfEffectRadiusSecondary / 10 if breakdown then local incAreaBreakpointSecondary, moreAreaBreakpointSecondary, redAreaBreakpointSecondary, lessAreaBreakpointSecondary if not skillData.projectileSpeedAppliesToMSAreaOfEffect then - incAreaBreakpointSecondary, moreAreaBreakpointSecondary, redAreaBreakpointSecondary, lessAreaBreakpointSecondary = calcRadiusBreakpoints(baseRadius, incAreaSecondary, moreAreaSecondary) + incAreaBreakpointSecondary, moreAreaBreakpointSecondary, redAreaBreakpointSecondary, lessAreaBreakpointSecondary = calcRadiusBreakpoints(baseRadius, incAreaSecondary, moreAreaSecondary, radiusMod) end - breakdown.AreaOfEffectRadiusSecondary = breakdown.area(baseRadius, output.AreaOfEffectModSecondary, output.AreaOfEffectRadiusSecondary, incAreaBreakpointSecondary, moreAreaBreakpointSecondary, redAreaBreakpointSecondary, lessAreaBreakpointSecondary, skillData.radiusSecondaryLabel) + breakdown.AreaOfEffectRadiusSecondary = breakdown.area(baseRadius, output.AreaOfEffectModSecondary, output.AreaOfEffectRadiusSecondary, incAreaBreakpointSecondary, moreAreaBreakpointSecondary, redAreaBreakpointSecondary, lessAreaBreakpointSecondary, skillData.radiusSecondaryLabel, radiusMod) end end if skillData.radiusTertiary then local incAreaTertiary, moreAreaTertiary = calcLib.mods(skillModList, skillCfg, "AreaOfEffect", "AreaOfEffectTertiary") - output.AreaOfEffectModTertiary = round(round(incAreaTertiary * moreAreaTertiary, 10), 2) + output.AreaOfEffectModTertiary = calcAreaMod(incAreaTertiary, moreAreaTertiary) baseRadius = skillData.radiusTertiary + (skillData.radiusExtra or 0) if skillData.projectileSpeedAppliesToMSAreaOfEffect then local incSpeedTertiary, moreSpeedTertiary = calcLib.mods(skillModList, skillCfg, "ProjectileSpeed") @@ -487,7 +493,7 @@ function calcs.offence(env, actor, activeSkill) local radiusForBaseRadius = {} local radiiOccurrences = {} for adjustedBaseRadius, occurrenceCount in pairs(baseRadiiOccurrences) do - local radiusForDeviation = calcRadius(adjustedBaseRadius, output.AreaOfEffectModTertiary) + local radiusForDeviation = calcRadius(adjustedBaseRadius, output.AreaOfEffectModTertiary, radiusMod) radiusForBaseRadius[adjustedBaseRadius] = radiusForDeviation sumOfRandomRadii = sumOfRandomRadii + radiusForDeviation * occurrenceCount radiiOccurrences[radiusForDeviation] = (radiiOccurrences[radiusForDeviation] or 0) + occurrenceCount @@ -499,6 +505,9 @@ function calcs.offence(env, actor, activeSkill) local incAreaBreakpointTertiary, moreAreaBreakpointTertiary, redAreaBreakpointTertiary, lessAreaBreakpointTertiary = m_huge, m_huge, m_huge, m_huge t_insert(out, skillData.radiusTertiaryLabel) t_insert(out, s_format("R ^8(base radius)^7 x %.2f ^8(square root of area of effect modifier)", m_floor(100 * m_sqrt(output.AreaOfEffectModTertiary)) / 100)) + if radiusMod ~= 1 then + t_insert(out, s_format("x %.2f ^8(final radius modifier)", radiusMod)) + end local baseRadii = {} for adjustedBaseRadius in pairs(baseRadiiOccurrences) do t_insert(baseRadii, adjustedBaseRadius) @@ -506,7 +515,7 @@ function calcs.offence(env, actor, activeSkill) table.sort(baseRadii, function(a,b) return a < b end) for _, adjustedBaseRadius in ipairs(baseRadii) do t_insert(out, s_format("%.1f%% ^8chance of^7 %.1fm ^8base radius resulting in^7 %.1fm ^8final radius", baseRadiiOccurrences[adjustedBaseRadius] / marginWidth * 100, adjustedBaseRadius / 10, radiusForBaseRadius[adjustedBaseRadius] / 10)) - local incAreaBreakpointTertiaryIntermediate, moreAreaBreakpointTertiaryIntermediate, redAreaBreakpointTertiaryIntermediate, lessAreaBreakpointTertiaryIntermediate = calcRadiusBreakpoints(adjustedBaseRadius, incAreaTertiary, moreAreaTertiary) + local incAreaBreakpointTertiaryIntermediate, moreAreaBreakpointTertiaryIntermediate, redAreaBreakpointTertiaryIntermediate, lessAreaBreakpointTertiaryIntermediate = calcRadiusBreakpoints(adjustedBaseRadius, incAreaTertiary, moreAreaTertiary, radiusMod) incAreaBreakpointTertiary = m_min(incAreaBreakpointTertiary, incAreaBreakpointTertiaryIntermediate) moreAreaBreakpointTertiary = m_min(moreAreaBreakpointTertiary, moreAreaBreakpointTertiaryIntermediate) redAreaBreakpointTertiary = m_min(redAreaBreakpointTertiary, redAreaBreakpointTertiaryIntermediate) @@ -518,10 +527,10 @@ function calcs.offence(env, actor, activeSkill) breakdown.AreaOfEffectRadiusTertiary = out end else - output.AreaOfEffectRadiusTertiary = calcRadius(baseRadius, output.AreaOfEffectModTertiary) + output.AreaOfEffectRadiusTertiary = calcRadius(baseRadius, output.AreaOfEffectModTertiary, radiusMod) if breakdown then - local incAreaBreakpointTertiary, moreAreaBreakpointTertiary, redAreaBreakpointTertiary, lessAreaBreakpointTertiary = calcRadiusBreakpoints(baseRadius, incAreaTertiary, moreAreaTertiary) - breakdown.AreaOfEffectRadiusTertiary = breakdown.area(baseRadius, output.AreaOfEffectModTertiary, output.AreaOfEffectRadiusTertiary, incAreaBreakpointTertiary, moreAreaBreakpointTertiary, redAreaBreakpointTertiary, lessAreaBreakpointTertiary, skillData.radiusTertiaryLabel) + local incAreaBreakpointTertiary, moreAreaBreakpointTertiary, redAreaBreakpointTertiary, lessAreaBreakpointTertiary = calcRadiusBreakpoints(baseRadius, incAreaTertiary, moreAreaTertiary, radiusMod) + breakdown.AreaOfEffectRadiusTertiary = breakdown.area(baseRadius, output.AreaOfEffectModTertiary, output.AreaOfEffectRadiusTertiary, incAreaBreakpointTertiary, moreAreaBreakpointTertiary, redAreaBreakpointTertiary, lessAreaBreakpointTertiary, skillData.radiusTertiaryLabel, radiusMod) end end output.AreaOfEffectRadiusTertiaryMetres = output.AreaOfEffectRadiusTertiary / 10 @@ -1652,7 +1661,7 @@ function calcs.offence(env, actor, activeSkill) end end local incArea, moreArea = calcLib.mods(skillModList, skillCfg, "TrapTriggerAreaOfEffect") - local areaMod = round(round(incArea * moreArea, 10), 2) + local areaMod = calcAreaMod(incArea, moreArea) output.TrapTriggerRadius = calcRadius(data.misc.TrapTriggerRadiusBase, areaMod) output.TrapTriggerRadiusMetre = output.TrapTriggerRadius / 10 if breakdown then @@ -1753,7 +1762,7 @@ function calcs.offence(env, actor, activeSkill) end local incArea, moreArea = calcLib.mods(skillModList, skillCfg, "MineDetonationAreaOfEffect") - local areaMod = round(round(incArea * moreArea, 10), 2) + local areaMod = calcAreaMod(incArea, moreArea) output.MineDetonationRadius = calcRadius(data.misc.MineDetonationRadiusBase, areaMod) output.MineDetonationRadiusMetre = output.MineDetonationRadius / 10 if breakdown then diff --git a/src/Modules/CalcOffence.lua.rej b/src/Modules/CalcOffence.lua.rej new file mode 100644 index 0000000000..9d14312090 --- /dev/null +++ b/src/Modules/CalcOffence.lua.rej @@ -0,0 +1,20 @@ +diff a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua (rejected hunks) +@@ -149,6 +149,18 @@ local function calcAilmentSourceDamage(activeSkill, output, cfg, breakdown, dama + return min * convMult, max * convMult + end + ++---Calculates the area percentage after the client integer rounding stages. ++---@param incArea number @Additive modifier ++---@param moreArea number @Multiplicative modifier ++---@return number ++local function calcAreaMod(incArea, moreArea) ++ local baseAreaPercent = roundSymmetric(incArea * 100) ++ local finalAreaPercent = roundSymmetric(m_max(0, moreArea) * 100) ++ local areaPercent = baseAreaPercent * finalAreaPercent / 100 ++ areaPercent = areaPercent >= 0 and m_floor(areaPercent) or m_ceil(areaPercent) ++ return m_max(0, areaPercent) / 100 ++end ++ + ---Calculates skill radius + ---@param baseRadius number + ---@param areaMod number From 076bccbf2b67502d8639b1fb6d19256d78a437aa Mon Sep 17 00:00:00 2001 From: LocalIdentity Date: Sun, 30 Aug 2026 23:24:03 +1000 Subject: [PATCH 2/2] Fix port --- src/Modules/CalcOffence.lua | 12 ++++++++++++ src/Modules/CalcOffence.lua.rej | 20 -------------------- 2 files changed, 12 insertions(+), 20 deletions(-) delete mode 100644 src/Modules/CalcOffence.lua.rej diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index e0713e1485..b71fe46c3f 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -156,6 +156,18 @@ local function calcDamage(activeSkill, output, cfg, breakdown, damageType, typeF round(summedMax * inc * more * moreMaxDamage + addMax) end +---Calculates the area percentage after the client integer rounding stages. +---@param incArea number @Additive modifier +---@param moreArea number @Multiplicative modifier +---@return number +local function calcAreaMod(incArea, moreArea) + local baseAreaPercent = roundSymmetric(incArea * 100) + local finalAreaPercent = roundSymmetric(m_max(0, moreArea) * 100) + local areaPercent = baseAreaPercent * finalAreaPercent / 100 + areaPercent = areaPercent >= 0 and m_floor(areaPercent) or m_ceil(areaPercent) + return m_max(0, areaPercent) / 100 +end + ---Calculates skill radius ---@param baseRadius number ---@param areaMod number diff --git a/src/Modules/CalcOffence.lua.rej b/src/Modules/CalcOffence.lua.rej deleted file mode 100644 index 9d14312090..0000000000 --- a/src/Modules/CalcOffence.lua.rej +++ /dev/null @@ -1,20 +0,0 @@ -diff a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua (rejected hunks) -@@ -149,6 +149,18 @@ local function calcAilmentSourceDamage(activeSkill, output, cfg, breakdown, dama - return min * convMult, max * convMult - end - -+---Calculates the area percentage after the client integer rounding stages. -+---@param incArea number @Additive modifier -+---@param moreArea number @Multiplicative modifier -+---@return number -+local function calcAreaMod(incArea, moreArea) -+ local baseAreaPercent = roundSymmetric(incArea * 100) -+ local finalAreaPercent = roundSymmetric(m_max(0, moreArea) * 100) -+ local areaPercent = baseAreaPercent * finalAreaPercent / 100 -+ areaPercent = areaPercent >= 0 and m_floor(areaPercent) or m_ceil(areaPercent) -+ return m_max(0, areaPercent) / 100 -+end -+ - ---Calculates skill radius - ---@param baseRadius number - ---@param areaMod number