From a611a44059c917807382653eeac2c8c05dc8ec10 Mon Sep 17 00:00:00 2001 From: Umeboshi Date: Fri, 10 Apr 2026 19:37:48 -0700 Subject: [PATCH] [core][lua] Correct base TP returns for mobs. --- scripts/globals/combat/tp.lua | 12 +++++++++- src/map/utils/battleutils.cpp | 41 ++++++++++------------------------- src/map/utils/battleutils.h | 2 +- 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/scripts/globals/combat/tp.lua b/scripts/globals/combat/tp.lua index 648279ce955..911dcbab6ee 100644 --- a/scripts/globals/combat/tp.lua +++ b/scripts/globals/combat/tp.lua @@ -7,10 +7,14 @@ xi.combat.tp = xi.combat.tp or {} -- "Local" functions only used here. ----------------------------------- +-- USED IN CORE (If you add/remove function params, they must be mirrored in core) -- https://www.bg-wiki.com/ffxi/Tactical_Points -- Gainee is the target who is going to gain the TP. -- For instance, if a player attacks a mob, the mob uses the mob formula when gaining TP from the returned hit. -- This appears to be a measure to not buff mobs when players were buffed with the new TP gain formula. +--- @params gainee CBaseEntity +--- @params delay integer +--- @return integer xi.combat.tp.calculateTPReturn = function(gainee, delay) local tpReturn = 0 @@ -152,7 +156,13 @@ xi.combat.tp.getSingleRangedHitTPReturn = function(actor) return math.floor(xi.combat.tp.calculateTPReturn(actor, delay) * storeTPModifier) end +-- This function calculates how much TP a target(The defender) will gain upon being hit by a physical attack. -- TODO: does Ikishoten factor into this as a bonus to baseTPGain if it procs on the hit? Needs verification. +--- @params actor CBaseEntity +--- @params target CBaseEntity +--- @params totalDamage integer +--- @params delay integer +--- @return integer xi.combat.tp.calculateTPGainOnPhysicalDamage = function(actor, target, totalDamage, delay) if not actor or not target then return 0 @@ -168,7 +178,7 @@ xi.combat.tp.calculateTPGainOnPhysicalDamage = function(actor, target, totalDama -- TODO: does dAGI penalty work against/for Trusts/Pets? Nothing is documented for this. Currently assuming mob only. local attackOutput = xi.combat.tp.getModifiedDelayAndCanZanshin(actor, delay) - local baseTPGain = xi.combat.tp.calculateTPReturn(target, attackOutput.modifiedDelay) + local baseTPGain = xi.combat.tp.calculateTPReturn(actor, attackOutput.modifiedDelay) local dAGI = actor:getStat(xi.mod.AGI) - target:getStat(xi.mod.AGI) local inhibitTPModifier = (100 - target:getMod(xi.mod.INHIBIT_TP)) / 100 -- no known cap: https://www.bg-wiki.com/ffxi/Monster_TP_gain#Inhibit_TP local dAGIModifier = utils.clamp(200 - (dAGI + 30) / 200, 0.5, 1) -- 50% reduction at +70 dAGI: https://www.bg-wiki.com/ffxi/Monster_TP_gain diff --git a/src/map/utils/battleutils.cpp b/src/map/utils/battleutils.cpp index 1a197abc27e..4b18637d6ec 100644 --- a/src/map/utils/battleutils.cpp +++ b/src/map/utils/battleutils.cpp @@ -1770,34 +1770,17 @@ float GetRangedDamageRatio(CBattleEntity* PAttacker, CBattleEntity* PDefender, b return pDIF; } -int16 CalculateBaseTP(int32 delay) +int16 CalculateBaseTP(CBattleEntity* PEntity, int32 delay) { - int16 x = 1; - if (delay <= 180) - { - x = (int16)(61 + ((delay - 180) * 63.0f) / 360); - } - else if (delay <= 540) - { - x = (int16)(61 + ((delay - 180) * 88.0f) / 360); - } - else if (delay <= 630) - { - x = (int16)(149 + ((delay - 540) * 20.0f) / 360); - } - else if (delay <= 720) - { - x = (int16)(154 + ((delay - 630) * 28.0f) / 360); - } - else if (delay <= 900) - { - x = (int16)(161 + ((delay - 720) * 24.0f) / 360); - } - else + int16 baseTPReturn = 0; + + auto calculateBaseTPGainFunc = lua["xi"]["combat"]["tp"]["calculateTPReturn"]; + if (calculateBaseTPGainFunc.valid()) { - x = (int16)(173 + ((delay - 900) * 28.0f) / 360); + baseTPReturn = calculateBaseTPGainFunc(PEntity, delay); } - return x; + + return baseTPReturn; } bool TryInterruptSpell(CBattleEntity* PAttacker, CBattleEntity* PDefender, CSpell* PSpell) @@ -2179,7 +2162,7 @@ int32 TakePhysicalDamage(CBattleEntity* PAttacker, CBattleEntity* PDefender, PHY { int32 delay = PAttacker->GetRangedWeaponDelay(true); - baseTp = CalculateBaseTP(delay * 120 / 1000); + baseTp = CalculateBaseTP(PAttacker, delay * 120 / 1000); } else { @@ -2199,7 +2182,7 @@ int32 TakePhysicalDamage(CBattleEntity* PAttacker, CBattleEntity* PDefender, PHY ratio = 2.0f; } - baseTp = CalculateBaseTP(delay * 60.0f / 1000.0f / ratio); + baseTp = CalculateBaseTP(PAttacker, delay * 60.0f / 1000.0f / ratio); } if (giveTPtoAttacker) @@ -2367,7 +2350,7 @@ int32 TakeWeaponskillDamage(CBattleEntity* PAttacker, CBattleEntity* PDefender, if (isRanged) { int32 delay = PAttacker->GetRangedWeaponDelay(true); - baseTp = CalculateBaseTP((delay * 120) / 1000); + baseTp = CalculateBaseTP(PAttacker, (delay * 120) / 1000); } else { @@ -2388,7 +2371,7 @@ int32 TakeWeaponskillDamage(CBattleEntity* PAttacker, CBattleEntity* PDefender, ratio = 2.0f; } - baseTp = CalculateBaseTP(delay * 60 / 1000 / ratio); + baseTp = CalculateBaseTP(PAttacker, delay * 60 / 1000 / ratio); } // add tp to attacker diff --git a/src/map/utils/battleutils.h b/src/map/utils/battleutils.h index 917e63349ce..09b11b98e81 100644 --- a/src/map/utils/battleutils.h +++ b/src/map/utils/battleutils.h @@ -177,7 +177,7 @@ int32 GetEnmityModDamage(int16 level); int32 GetEnmityModCure(int16 level); bool isValidSelfTargetWeaponskill(int wsid); bool CanUseWeaponskill(CCharEntity* PChar, CWeaponSkill* PSkill); -int16 CalculateBaseTP(int32 delay); +int16 CalculateBaseTP(CBattleEntity* PEntity, int32 delay); void GenerateCureEnmity(CBattleEntity* PSource, CBattleEntity* PTarget, int32 amount, int32 fixedCE = 0, int32 fixedVE = 0); void GenerateInRangeEnmity(CBattleEntity* PSource, int32 CE, int32 VE); void handleKillshotEnmity(CBattleEntity* PAttacker, CBattleEntity* PTarget);