From c8fbdc13f723a76b65685ac502ffd4365a97e920 Mon Sep 17 00:00:00 2001 From: WinterSolstice8 <60417494+wintersolstice8@users.noreply.github.com> Date: Tue, 14 Apr 2026 13:01:16 -0600 Subject: [PATCH 1/2] [lua] Move melee spike ratio out to a function --- scripts/globals/combat/physical_utilities.lua | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/scripts/globals/combat/physical_utilities.lua b/scripts/globals/combat/physical_utilities.lua index eb541a1a47c..b371a05418b 100644 --- a/scripts/globals/combat/physical_utilities.lua +++ b/scripts/globals/combat/physical_utilities.lua @@ -518,6 +518,37 @@ xi.combat.physical.wRatioCapOthers = function(wRatio, pDifFinalCap) return pDifLowerCap, pDifUpperCap end +---@param isPC boolean +---@param wRatio number +---@return number +local function getSpikeRatio(isPC, wRatio) + if isPC then + -- https://www.bg-wiki.com/ffxi/PDIF#Average_Melee_pDIF(qRatio) + -- This is also known as "pDIF spike" + if wRatio > 0.5 and wRatio < 1.5 then -- 0.5 and 1.5 are 0% chance + local sRatio = (0.5 - math.abs(wRatio - 1)) * 1.2 + + return utils.clamp(sRatio, 0, 1 / 3) -- 1/3 (one-third), not 0.33 + end + else + -- https://www.ffxiah.com/forum/topic/58479/monster-pdif-curves-and-other-info/#3751498 + -- This is also known as "pDIF spike" + local sRatio = 0 + + if wRatio > 0.0 and wRatio < 0.75 then + sRatio = -5 / 9 + (10 / 9) * wRatio + elseif wRatio <= 1.3 then + sRatio = 0.3 + else + sRatio = 5 / 3 - (270 / 256) * wRatio + end + + return utils.clamp(sRatio, 0, 0.3) + end + + return 0 +end + -- WARNING: This function is used in src/utils/battleutils.cpp "GetDamageRatio" function. -- If you update this parameters, update them there aswell. ---@param actor CBaseEntity @@ -614,16 +645,10 @@ xi.combat.physical.calculateMeleePDIF = function(actor, target, weaponType, wsAt if actor:isPC() then pDifFinalCap = (xi.combat.physical.pDifWeaponCapTable[weaponType] + damageLimitPlus) * damageLimitPercent + (isCritical and 1 or 0) - -- https://www.bg-wiki.com/ffxi/PDIF#Average_Melee_pDIF(qRatio) - -- This is also known as "pDIF spike" - if wRatio > 0.5 and wRatio < 1.5 then -- 0.5 and 1.5 are 0% chance - local sRatio = (0.5 - math.abs(wRatio - 1)) * 1.2 - - sRatio = utils.clamp(sRatio, 0, 1 / 3) -- 1/3 (one-third), not 0.33 + local sRatio = getSpikeRatio(true, wRatio) - if math.random(1, 10000) / 10000 <= sRatio then - return 1.0 - end + if math.random(1, 10000) / 10000 <= sRatio then + return 1.0 end pDifLowerCap, pDifUpperCap = xi.combat.physical.wRatioCapPC(wRatio, pDifFinalCap) @@ -635,19 +660,7 @@ xi.combat.physical.calculateMeleePDIF = function(actor, target, weaponType, wsAt local critBonus = (applyLevelCorrection and isCritical) and 1 or 0 pDifFinalCap = (basePDIF + damageLimitPlus) * damageLimitPercent + critBonus - -- https://www.ffxiah.com/forum/topic/58479/monster-pdif-curves-and-other-info/#3751498 - -- This is also known as "pDIF spike" - local sRatio = 0 - - if wRatio > 0.0 and wRatio < 0.75 then - sRatio = -5 / 9 + (10 / 9) * wRatio - elseif wRatio <= 1.3 then - sRatio = 0.3 - else - sRatio = 5 / 3 - (270 / 256) * wRatio - end - - sRatio = utils.clamp(sRatio, 0, 0.3) + local sRatio = getSpikeRatio(false, wRatio) if math.random(1, 10000) / 10000 <= sRatio then return 1.0 From cad7d51cb6545b275bd75b8a70bc6c0ccf0bc1cc Mon Sep 17 00:00:00 2001 From: WinterSolstice8 <60417494+wintersolstice8@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:26:35 -0600 Subject: [PATCH 2/2] [lua] Implement high/low pdif rolls for melee --- scripts/globals/combat/physical_utilities.lua | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/scripts/globals/combat/physical_utilities.lua b/scripts/globals/combat/physical_utilities.lua index b371a05418b..6cb9bd3cb7f 100644 --- a/scripts/globals/combat/physical_utilities.lua +++ b/scripts/globals/combat/physical_utilities.lua @@ -671,10 +671,18 @@ xi.combat.physical.calculateMeleePDIF = function(actor, target, weaponType, wsAt -- Apply level correction to UL/LL -- https://www.ffxiah.com/forum/topic/57989/post-2016-level-correction-testing/ - pDifLowerCap = pDifLowerCap + levelDifFactor - pDifUpperCap = pDifUpperCap + levelDifFactor + -- Dice roll the 50/50 chance to select two different bounds. Mote has not yet implemented the spike by the time of this post so his ratio is not 50/50 rate. + -- His model at the time and implemented spike, so the (0.0, 0.5) bounds also looks different + -- https://www.bluegartr.com/threads/108161-pDif-and-damage?p=5007487&viewfull=1#post5007487 + local upperMax = math.random(0, 1) == 0 and 0.5 or 0 + local upperBound = math.max(pDifUpperCap + levelDifFactor, upperMax) + local lowerbound = math.max(pDifLowerCap + levelDifFactor, 0) + + if upperBound == 0 then + return 0 + end - pDif = math.random(pDifLowerCap * 1000, pDifUpperCap * 1000) / 1000 + pDif = math.random(lowerbound * 1000, upperBound * 1000) / 1000 ---------------------------------------- -- Step 4: Melee random factor. @@ -821,6 +829,9 @@ xi.combat.physical.calculateRangedPDIF = function(actor, target, weaponType, wsA pDif = math.random(pDifLowerCap * 1000, pDifUpperCap * 1000) / 1000 + -- do not go negative, rolls below zero (proportionally) need to be rolled + pDif = math.max(pDif, 0) + ---------------------------------------- -- Step 4: Ranged critical factor. Bypasses caps. ----------------------------------------