From edef4911f6bb7295a7a6f29a9c1c98bf56f78ada Mon Sep 17 00:00:00 2001 From: Xaver-DaRed Date: Sun, 19 Apr 2026 23:37:12 +0200 Subject: [PATCH] Improve mobskill status effect handling and application --- scripts/actions/mobskills/spider_web.lua | 11 +- .../combat/action_mobskill_status_effect.lua | 121 ++++++++++++++---- 2 files changed, 101 insertions(+), 31 deletions(-) diff --git a/scripts/actions/mobskills/spider_web.lua b/scripts/actions/mobskills/spider_web.lua index 659f9d08ed6..351df54324f 100644 --- a/scripts/actions/mobskills/spider_web.lua +++ b/scripts/actions/mobskills/spider_web.lua @@ -10,17 +10,12 @@ mobskillObject.onMobSkillCheck = function(target, mob, skill) end mobskillObject.onMobWeaponSkill = function(mob, target, skill, action) - local effectparams = + local effectTable = { - effectId = xi.effect.SLOW, - power = 3000, - duration = 90, - tier = 8, -- https://wiki.ffo.jp/html/4125.html + [1] = { effectId = xi.effect.SLOW, power = 3000, duration = 90, tier = 8, }, } - xi.combat.action.executeMobskillStatusEffect(mob, target, skill, effectparams, true) - - return xi.effect.SLOW + return xi.combat.action.executeMobskillStatusEffect(mob, target, skill, effectTable, {}) end return mobskillObject diff --git a/scripts/globals/combat/action_mobskill_status_effect.lua b/scripts/globals/combat/action_mobskill_status_effect.lua index 1ed1dd0d26c..845aa278b83 100644 --- a/scripts/globals/combat/action_mobskill_status_effect.lua +++ b/scripts/globals/combat/action_mobskill_status_effect.lua @@ -9,6 +9,7 @@ xi.combat = xi.combat or {} xi.combat.action = xi.combat.action or {} ----------------------------------- +-- Define each step where the process can end. local step = { CANT_GAIN = 1, @@ -16,11 +17,12 @@ local step = RESIST_TRAIT_CHECK = 3, NULLIFY_CHECK = 4, RESIST_RATE_CHECK = 5, - APPLICATION_SUCCESS = 6, - APPLICATION_FAIL = 7, + APPLICATION_FAIL = 6, + APPLICATION_SUCCESS = 7, } -local function validateParameters(fedData) +-- Validate the parameters of an specific entry of the status effect table. +local function validateEffectParameters(fedData) local params = {} -- Status effect application parameters. @@ -42,44 +44,47 @@ local function validateParameters(fedData) return params end -local function handleReturn(skill, setMessage, message, processStep) - if not setMessage then - return - end +-- Validate the parameters of the skill messaging. +local function validateMessageParameters(fedData) + local params = {} - -- TODO: Handle message modifiers with mobskills. - -- if processStep == step.RESIST_TRAIT_CHECK then - -- skill:setModifier(xi.msg.actionModifier.RESIST) -- Resist! - -- end + -- Action messages per step. + params.messageBypass = fedData.messageBypass or false + params.messageCantGain = fedData.messageCantGain or xi.msg.basic.SKILL_NO_EFFECT + params.messageIsImmune = fedData.messageIsImmune or xi.msg.basic.SKILL_MISS + params.messageIsTraitResisted = fedData.messageIsTraitResisted or xi.msg.basic.SKILL_MISS + params.messageIsIncompatible = fedData.messageIsIncompatible or xi.msg.basic.SKILL_MISS + params.messageIsResisted = fedData.messageIsResisted or xi.msg.basic.SKILL_MISS + params.messageIsNotSuccessful = fedData.messageIsNotSuccessful or xi.msg.basic.SKILL_MISS + params.messageIsSuccessful = fedData.messageIsSuccessful or xi.msg.basic.SKILL_ENFEEB_IS - skill:setMsg(message) + return params end -xi.combat.action.executeMobskillStatusEffect = function(actor, target, skill, effectData, setMessage) - -- Ensure all data fed is valid and initialized. - local params = validateParameters(effectData) - +-- Handle (and apply) the action status effect. +local function handleStatusEffect(actor, target, params) + -- Check if can gain. if not target:canGainStatusEffect(params.effectId, params.power) then - return handleReturn(skill, setMessage, xi.msg.basic.SKILL_NO_EFFECT, step.CANT_GAIN) + return step.CANT_GAIN end -- Check immunity. if xi.data.statusEffect.isTargetImmune(target, params.effectId, params.element) then - return handleReturn(skill, setMessage, xi.msg.basic.SKILL_MISS, step.IMMUNE_CHECK) + return step.IMMUNE_CHECK -- Check resist traits. elseif xi.data.statusEffect.isTargetResistant(actor, target, params.effectId) then - return handleReturn(skill, setMessage, xi.msg.basic.SKILL_MISS, step.RESIST_TRAIT_CHECK) + return step.RESIST_TRAIT_CHECK -- Check effect incompatibilities. elseif xi.data.statusEffect.isEffectNullified(target, params.effectId, params.tier) then - return handleReturn(skill, setMessage, xi.msg.basic.SKILL_MISS, step.NULLIFY_CHECK) + return step.NULLIFY_CHECK end -- Calculate resist state. local resistanceRate = xi.combat.magicHitRate.calculateResistRate(actor, target, 0, 0, params.rank, params.element, params.stat, params.effectId, params.macc) if not xi.data.statusEffect.isResistRateSuccessfull(params.effectId, resistanceRate, params.resistRate) then - return handleReturn(skill, setMessage, xi.msg.basic.SKILL_MISS, step.RESIST_RATE_CHECK) + return step.RESIST_RATE_CHECK end -- Calculate duration. @@ -87,8 +92,78 @@ xi.combat.action.executeMobskillStatusEffect = function(actor, target, skill, ef -- Apply effect. if target:addStatusEffect(params.effectId, { power = params.power, duration = totalDuration, origin = actor, tick = params.tick, subType = params.subType, subPower = params.subPower, tier = params.tier }) then - return handleReturn(skill, setMessage, xi.msg.basic.SKILL_ENFEEB_IS, step.APPLICATION_SUCCESS) + return step.APPLICATION_SUCCESS end - return handleReturn(skill, setMessage, xi.msg.basic.SKILL_MISS, step.APPLICATION_FAIL) + return step.APPLICATION_FAIL +end + +-- Handle (set) the action message Id. +local function handleActionMessage(skill, bestResult, messageParams) + if messageParams.messageBypass then + return + end + + switch(bestResult): caseof + { + [step.CANT_GAIN] = function() + skill:setMsg(messageParams.messageCantGain) + end, + + [step.IMMUNE_CHECK] = function() + skill:setMsg(messageParams.messageIsImmune) + end, + + [step.RESIST_TRAIT_CHECK] = function() + skill:setMsg(messageParams.messageIsTraitResisted) + end, + + [step.NULLIFY_CHECK] = function() + skill:setMsg(messageParams.messageIsIncompatible) + end, + + [step.RESIST_RATE_CHECK] = function() + skill:setMsg(messageParams.messageIsResisted) + end, + + [step.APPLICATION_FAIL] = function() + skill:setMsg(messageParams.messageIsNotSuccessful) + end, + + [step.APPLICATION_SUCCESS] = function() + skill:setMsg(messageParams.messageIsSuccessful) + end, + } +end + +xi.combat.action.executeMobskillStatusEffect = function(actor, target, skill, effectData, messageData) + -- Cycle over all effects. Apply (or not) and save the result in a table. + local dTableEffectResults = {} + for i = 1, #effectData do + local effectParams = validateEffectParameters(effectData[i]) + local result = handleStatusEffect(actor, target, effectParams) + table.insert(dTableEffectResults, i, { effectParams.effectId, result }) + end + + -- Decide best effect outcome, for the message and the effect Id to return. + local bestResult = 0 + local bestIndex = 0 + + for j = 1, #dTableEffectResults do + local currentResult = dTableEffectResults[j][2] + if currentResult > bestResult then + bestResult = currentResult + bestIndex = j + end + end + + -- Fetch best effect Id. + local effectId = dTableEffectResults[bestIndex][1] + + -- Handle messaging. + local messageParams = validateMessageParameters(messageData) + handleActionMessage(skill, bestResult, messageParams) + + -- Return best effect Id. + return effectId end