landsandboat/scripts/combat/action_additional_effect_status.lua

230 lines
9.2 KiB
Lua

-----------------------------------
-- Global file for additional effects (Status Effects)
-----------------------------------
xi = xi or {}
xi.combat = xi.combat or {}
xi.combat.action = xi.combat.action or {}
-----------------------------------
local defaultsTable =
{
[xi.effect.AMNESIA ] = { xi.subEffect.AMNESIA, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.ATTACK_DOWN ] = { xi.subEffect.ATTACK_DOWN, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.BIND ] = { xi.subEffect.DARKNESS_DAMAGE, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.BLINDNESS ] = { xi.subEffect.BLIND, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.CURSE_I ] = { xi.subEffect.CURSE, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.DEFENSE_DOWN ] = { xi.subEffect.DEFENSE_DOWN, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.EVASION_DOWN ] = { xi.subEffect.EVASION_DOWN, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.KO ] = { xi.subEffect.DEATH, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.MUTE ] = { xi.subEffect.SILENCE, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.NONE ] = { xi.subEffect.DARKNESS_DAMAGE, xi.msg.basic.ADD_EFFECT_DISPEL },
[xi.effect.PARALYSIS ] = { xi.subEffect.PARALYSIS, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.PETRIFICATION] = { xi.subEffect.PETRIFY, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.PLAGUE ] = { xi.subEffect.PLAGUE, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.POISON ] = { xi.subEffect.POISON, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.SILENCE ] = { xi.subEffect.SILENCE, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.SLEEP_I ] = { xi.subEffect.SLEEP, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.SLOW ] = { xi.subEffect.SLOW, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.STUN ] = { xi.subEffect.STUN, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.TERROR ] = { xi.subEffect.PARALYSIS, xi.msg.basic.ADD_EFFECT_STATUS },
[xi.effect.WEIGHT ] = { xi.subEffect.ATTACK_DOWN, xi.msg.basic.ADD_EFFECT_STATUS },
}
-----------------------------------
-- Local functions to ensure defaults are set.
-----------------------------------
local function validateParameters(actor, target, fedData)
local params = {}
-- Additional effect target.
params.aeTarget = fedData.aeTarget or target -- Default to the current attack target.
-- Chance.
params.chance = fedData.chance or 100 -- Default: Always proc.
-- Source is ranged attack or melee? Skip en-spell check if so.
params.isRanged = fedData.isRanged or false -- Assume melee.
-- Status effect application parameters.
params.effectId = fedData.effectId or xi.effect.NONE
params.power = fedData.power or 0
params.tick = fedData.tick or 0
params.duration = fedData.duration or 120
params.subType = fedData.subType or 0
params.subPower = fedData.subPower or 0
params.tier = fedData.tier or 0
params.resistRate = fedData.resistRate or 0
-- Action properties.
params.magicalElement = fedData.magicalElement or xi.data.statusEffect.getAssociatedElement(params.effectId, xi.element.NONE)
params.actorStat = fedData.actorStat or 0
params.targetStat = fedData.targetStat or params.actorStat
params.skillRank = fedData.skillRank or xi.skillRank.A_PLUS
params.bonusMacc = fedData.bonusMacc or 0
-- Optional behavior.
params.resetEmnity = fedData.resetEmnity or false -- Currently unused. For future use.
params.absorbEffect = fedData.absorbEffect or false
-- Animations and messaging.
params.animation = fedData.animation or (defaultsTable[params.effectId][1] or 0)
params.message = fedData.message or (defaultsTable[params.effectId][2] or 0)
return params
end
local function hasEnspell(actor)
local enspellTable =
{
[ 1] = xi.effect.ENFIRE,
[ 2] = xi.effect.ENFIRE_II,
[ 3] = xi.effect.ENBLIZZARD,
[ 4] = xi.effect.ENBLIZZARD_II,
[ 5] = xi.effect.ENAERO,
[ 6] = xi.effect.ENAERO_II,
[ 7] = xi.effect.ENSTONE,
[ 8] = xi.effect.ENSTONE_II,
[ 9] = xi.effect.ENTHUNDER,
[10] = xi.effect.ENTHUNDER_II,
[11] = xi.effect.ENWATER,
[12] = xi.effect.ENWATER_II,
[13] = xi.effect.ENLIGHT,
[14] = xi.effect.ENDARK,
}
for i = 1, #enspellTable do
if actor:hasStatusEffect(enspellTable[i]) then
return true
end
end
return false
end
-----------------------------------
-- Global functions called from "emtity.onAdditionalEffect()"
-----------------------------------
xi.combat.action.executeAddEffectEnhancement = function(actor, target, fedData)
local params = validateParameters(actor, target, fedData)
-- Early return: En-spell overrides innate/weapon additional effects, except ranged attacks.
if not params.isRanged and hasEnspell(actor) then
return 0, 0, 0
end
-- Early return: Incorrect effect ID.
if params.effectId == xi.effect.NONE then
return 0, 0, 0
end
-- Early return: No proc.
if math.randomInt(1, 100) > params.chance then
return 0, 0, 0
end
-- Early return: Target has an status effect that invalidates current (Outright incompatible or higher tier).
if xi.data.statusEffect.isEffectNullified(params.aeTarget, params.effectId, params.tier) then
return 0, 0, 0
end
-- Apply effect.
if params.aeTarget:addStatusEffect(params.effectId, { power = params.power, duration = params.duration, origin = actor, tick = params.tick, subType = params.subType, subPower = params.subPower, tier = params.tier }) then
return params.animation, params.message, params.effectId
end
return 0, 0, 0
end
xi.combat.action.executeAddEffectEnfeeblement = function(actor, target, fedData)
local params = validateParameters(actor, target, fedData)
-- Early return: En-spell overrides innate/weapon additional effects, except ranged attacks.
if not params.isRanged and hasEnspell(actor) then
return 0, 0, 0
end
-- Early return: Incorrect effect ID.
if params.effectId == xi.effect.NONE then
return 0, 0, 0
end
-- Early return: No proc.
if math.randomInt(1, 100) > params.chance then
return 0, 0, 0
end
-- Early return: Target is immune.
if xi.data.statusEffect.isTargetImmune(params.aeTarget, params.effectId, params.magicalElement) then
return 0, 0, 0
end
-- Early return: Target triggers resist trait.
if xi.data.statusEffect.isTargetResistant(actor, params.aeTarget, params.effectId) then
return 0, 0, 0
end
-- Early return: Target has an status effect that invalidates current (Outright incompatible or higher tier).
if xi.data.statusEffect.isEffectNullified(params.aeTarget, params.effectId, params.tier) then
return 0, 0, 0
end
-- Early return: Resist rate too high.
local resistanceRate = xi.combat.magicHitRate.calculateResistRate(actor, params.aeTarget, params)
if not xi.data.statusEffect.isResistRateSuccessfull(params.effectId, resistanceRate, params.resistRate) then
return 0, 0, 0
end
-- Calculate duration.
local totalDuration = math.floor(params.duration * resistanceRate)
-- Apply effect.
if params.aeTarget:addStatusEffect(params.effectId, { power = params.power, duration = totalDuration, origin = actor, tick = params.tick, subType = params.subType, subPower = params.subPower, tier = params.tier }) then
return params.animation, params.message, params.effectId
end
return 0, 0, 0
end
xi.combat.action.executeAddEffectDispel = function(actor, target, fedData)
local params = validateParameters(actor, target, fedData)
-- Early return: En-spell overrides innate/weapon additional effects, except ranged attacks.
if not params.isRanged and hasEnspell(actor) then
return 0, 0, 0
end
-- Early return: Incorrect effect ID.
if params.effectId ~= xi.effect.NONE then
return 0, 0, 0
end
-- Early return: No proc.
if math.randomInt(1, 100) > params.chance then
return 0, 0, 0
end
-- Early return: No dispelable effect.
if not params.aeTarget:hasStatusEffectByFlag(xi.effectFlag.DISPELABLE) then
return 0, 0, 0
end
-- Early return: Resist rate too high.
local resistanceRate = xi.combat.magicHitRate.calculateResistRate(actor, params.aeTarget, params)
if not xi.data.statusEffect.isResistRateSuccessfull(params.effectId, resistanceRate, params.resistRate) then
return 0, 0, 0
end
-- Attampt to dispel or steal an status effect.
local dispelledEffect = 0
if params.absorbEffect then
dispelledEffect = actor:stealStatusEffect(params.aeTarget, xi.effectFlag.DISPELABLE, true)
else
dispelledEffect = params.aeTarget:dispelStatusEffect(xi.effectFlag.DISPELABLE)
end
if dispelledEffect == 0 then
return 0, 0, 0
end
return params.animation, params.message, dispelledEffect
end