From b6c1c9456721e6d61d6540681f3aa1b680753a5c Mon Sep 17 00:00:00 2001 From: Umeboshi Date: Thu, 27 Feb 2025 07:56:52 -0800 Subject: [PATCH] [core][lua] Hookup core parry checks to lua --- scripts/enum/mod.lua | 2 ++ scripts/globals/combat/physical_utilities.lua | 24 ++++++++++++++++--- src/map/entities/battleentity.cpp | 7 ------ src/map/modifier.h | 6 +++-- src/map/utils/attackutils.cpp | 21 ++++++++++++++-- 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/scripts/enum/mod.lua b/scripts/enum/mod.lua index a429fd0bde1..47ade73e93f 100644 --- a/scripts/enum/mod.lua +++ b/scripts/enum/mod.lua @@ -1025,6 +1025,8 @@ xi.mod = DESPAWN_TIME_REDUCTION = 1134, -- Reduction in seconds. 1 = 1 second less to despawn. + PARRY_HP_RECOVERY = 1135, -- Recover HP on successful parry. + -- IF YOU ADD ANY NEW MODIFIER HERE, ADD IT IN src/map/modifier.h ASWELL! -- The spares take care of finding the next ID to use so long as we don't forget to list IDs that have been freed up by refactoring. diff --git a/scripts/globals/combat/physical_utilities.lua b/scripts/globals/combat/physical_utilities.lua index 3d3d97c32d7..f2440f8bd50 100644 --- a/scripts/globals/combat/physical_utilities.lua +++ b/scripts/globals/combat/physical_utilities.lua @@ -707,7 +707,7 @@ xi.combat.physical.criticalRateFromFencer = function(actor) end -- Critical rate from Building Flourish. --- TODO: Study case were if we can attach modifiers to the effect itself, both this and the effect may need refactoring. +-- TODO: Study case where if we can attach modifiers to the effect itself, both this and the effect may need refactoring. xi.combat.physical.criticalRateFromFlourish = function(actor) local buildingFlourishBonus = 0 @@ -1031,9 +1031,17 @@ xi.combat.physical.isParried = function(defender, attacker) xi.combat.physical.calculateParryRate(defender, attacker) > math.random(1, 100) then parried = true + + -- https://www.bg-wiki.com/ffxi/Turms_Mittens + if + defender:getMod(xi.mod.PARRY_HP_RECOVERY) > 0 and + not defender:hasStatusEffect(xi.effect.CURSE_II) + then + local recoveryValue = defender:getMod(xi.mod.PARRY_HP_RECOVERY) + defender:addHP(recoveryValue) + end + if defender:isPC() then - -- TODO: implement Turms mod here (when that mod is added to LSB) - defender:trySkillUp(xi.skill.PARRY, attacker:getMainLvl()) -- handle tactical parry if defender:hasTrait(xi.trait.TACTICAL_PARRY) then defender:addTP(defender:getMod(xi.mod.TACTICAL_PARRY)) @@ -1041,6 +1049,16 @@ xi.combat.physical.isParried = function(defender, attacker) end end + -- Handle skill ups. + if defender:isPC() then + if + parried or -- We parried + not xi.settings.map.PARRY_OLD_SKILLUP_STYLE -- Old style skillup is not enabled + then + defender:trySkillUp(xi.skill.PARRY, attacker:getMainLvl()) + end + end + return parried end diff --git a/src/map/entities/battleentity.cpp b/src/map/entities/battleentity.cpp index eaa325c9b17..4feeb69c84e 100644 --- a/src/map/entities/battleentity.cpp +++ b/src/map/entities/battleentity.cpp @@ -2527,13 +2527,6 @@ bool CBattleEntity::OnAttack(CAttackState& state, action_t& action) } } - if (attack.IsParried() || !settings::get("map.PARRY_OLD_SKILLUP_STYLE")) - { - if (battleutils::GetParryRate(this, PTarget) > 0) - { - charutils::TrySkillUP((CCharEntity*)PTarget, SKILL_PARRY, GetMLevel()); - } - } if (!attack.IsCountered() && !attack.IsParried()) { charutils::TrySkillUP((CCharEntity*)PTarget, SKILL_EVASION, GetMLevel()); diff --git a/src/map/modifier.h b/src/map/modifier.h index fa7f58c08ba..7d23a17c039 100644 --- a/src/map/modifier.h +++ b/src/map/modifier.h @@ -1,4 +1,4 @@ -/* +/* =========================================================================== Copyright (c) 2010-2015 Darkstar Dev Teams This program is free software: you can redistribute it and/or modify @@ -1070,12 +1070,14 @@ enum class Mod DESPAWN_TIME_REDUCTION = 1134, // Reduction in seconds. 1 = 1 second less to despawn. + PARRY_HP_RECOVERY = 1135, // Recover HP on successful parry. + // IF YOU ADD ANY NEW MODIFIER HERE, ADD IT IN scripts/enum/mod.lua ASWELL! // The spares take care of finding the next ID to use so long as we don't forget to list IDs that have been freed up by refactoring. // 570 through 825 used by WS DMG mods these are not spares. // - // SPARE IDs: 1135 and onward + // SPARE IDs: 1136 and onward }; // temporary workaround for using enum class as unordered_map key until compilers support it diff --git a/src/map/utils/attackutils.cpp b/src/map/utils/attackutils.cpp index e429092fca7..9d0a796c347 100644 --- a/src/map/utils/attackutils.cpp +++ b/src/map/utils/attackutils.cpp @@ -24,6 +24,7 @@ #include "battleutils.h" #include "common/utils.h" #include "items/item_weapon.h" +#include "lua/luautils.h" #include "status_effect_container.h" namespace attackutils @@ -232,10 +233,26 @@ namespace attackutils bool IsParried(CBattleEntity* PAttacker, CBattleEntity* PDefender) { - if (facing(PDefender->loc.p, PAttacker->loc.p, 64)) + auto isParriedFunc = lua["xi"]["combat"]["physical"]["isParried"]; + + if (isParriedFunc.valid()) { - return (xirand::GetRandomNumber(100) < battleutils::GetParryRate(PAttacker, PDefender)); + try + { + bool result = isParriedFunc(PDefender, PAttacker); + return result; + } + catch (const sol::error& err) + { + ShowError("attackutils::IsParried(): %s", err.what()); + return false; + } + } + else + { + ShowError("attackutils::IsParried() failed to run Lua function"); } + return false; }