illarion-content/magic/arcane/delayedAttack.lua
brightrim 0b6913a335 fix
2026-01-10 16:33:01 +01:00

270 lines
8.5 KiB
Lua

--[[
Illarion Server
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
You should have received a copy of the GNU Affero General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
]]
local magicGFXSFX = require("magic.arcane.magicGFXSFX")
local targeting = require("magic.arcane.targeting")
local dealDamage = require("magic.arcane.dealMagicDamage")
local staticObjects = require("magic.arcane.staticObjects")
local stun = require("magic.arcane.stun")
local MSReduction = require("magic.arcane.manaStaminaReduction")
local illuminate = require("magic.arcane.illuminate")
local DoT = require("magic.arcane.magicDoT")
local runes = require("magic.arcane.runes")
local harvestFruit = require("magic.arcane.harvestFruit")
local movement = require("magic.arcane.movement")
local lifesteal = require("magic.arcane.lifesteal")
local snare = require("magic.arcane.snare")
local plantRoot = require("magic.arcane.plantRoot")
local stallMana = require("magic.arcane.stallMana")
local traps = require("magic.arcane.traps")
local information = require("magic.arcane.spirit.information")
local tutorials = require("magic.tutorials")
local dispel = require("magic.arcane.dispel")
local castingSpeed = require("magic.arcane.castingSpeed")
local M = {}
function M.getTarget(user, myEffect, lx, ly, tx, ty, tz)
local x
local y
if lx == tx and ly == ty then
return false
end
if ty > ly then
y = ly+1
elseif ty < ly then
y = ly-1
else
y = ly
end
if tx > lx then
x = lx+1
elseif tx < lx then
x = lx-1
else
x = lx
end
myEffect:addValue("lastX", x)
myEffect:addValue("lastY", y)
return position(x, y, tz)
end
local function refreshAndVerifyTargets(targets)
local verifiedTargets = {}
for index, target in pairs(targets.targets) do
local add = true
if isValidChar(target) then
for _, verifiedTarget in pairs(verifiedTargets) do
if target == verifiedTarget then --Target already exists in list, no duplicates
add = false
end
end
else
add = false
end
if add then
table.insert(verifiedTargets, target)
end
end
targets.targets = verifiedTargets
return targets
end
function M.spellEffects(user, targets, spell, element, ORL, level, castDuration, thePosition)
targets = refreshAndVerifyTargets(targets)
local SOLH = runes.checkSpellForRuneByName("SOLH", spell)
local OrlRune = runes.checkSpellForRuneByName("ORL", spell)
if not (SOLH and OrlRune) then
illuminate.CheckIfIlluminate(user, targets, spell)
DoT.dealMagicDoT(user, targets, spell, element, level, castDuration)
magicGFXSFX.getAdditionalUserGFXSFX(user, spell)
harvestFruit.checkIfHarvestFruit(user, targets, spell)
movement.applyMovementSpells(user, targets, spell, ORL)
lifesteal.instantLifeOrManaSteal(user, targets, spell, ORL, thePosition)
plantRoot.createEntanglingPlant(user, targets, spell, level)
dealDamage.applyMagicDamage(user, targets, spell, element, ORL, false, level, castDuration)
snare.applySnare(user, targets, spell, ORL, level)
stun.checkForStun(user, spell, targets)
MSReduction.checkForIncreaseStamina(user, targets, spell)
plantRoot.applyPlantRoot(user, targets, spell)
staticObjects.spawnStaticObjects(user, targets, spell, level)
stallMana.applyManaStalling(user, targets, spell)
information.invokeSpiritSpells(user, targets, spell)
dispel.dispel(spell, targets)
else --spell effect gets applied to trap instead
traps.createEarthTraps(user, targets, spell, level)
end
magicGFXSFX.getTargetGFXSFX(targets, spell, true)
if spell == 8 then
if tutorials.isTutorialNPCnearby(user) then
if user:getQuestProgress(237) == 6 then
user:setQuestProgress(237, 7)
end
end
end
end
function M.applyDelay(user, target, spell, ORL, level, startedInAttackMode)
local targetx = target.x
local targety = target.y
local targetz = target.z
local casterx = user.pos.x
local castery = user.pos.y
local startedInAttackModeValue = 0
if startedInAttackMode then
startedInAttackModeValue = 1
end
local foundEffect, myEffect = user.effects:find(7)
if not foundEffect then
myEffect = LongTimeEffect(7,5)
myEffect:addValue("lastX", casterx)
myEffect:addValue("lastY", castery)
myEffect:addValue("targetX", targetx)
myEffect:addValue("targetY", targety)
myEffect:addValue("targetZ", targetz)
myEffect:addValue("spell", spell)
myEffect:addValue("level", level)
myEffect:addValue("startedInAttackMode", startedInAttackModeValue)
if ORL then
myEffect:addValue("ORL", ORL)
end
user.effects:addEffect(myEffect)
else
myEffect:addValue("lastX", casterx)
myEffect:addValue("lastY", castery)
myEffect:addValue("targetX", targetx)
myEffect:addValue("targetY", targety)
myEffect:addValue("targetZ", targetz)
myEffect:addValue("spell", spell)
myEffect:addValue("level", level)
myEffect:addValue("startedInAttackMode", startedInAttackModeValue)
if ORL then
myEffect:addValue("ORL", ORL)
end
M.addEffect(myEffect, user)
end
end
function M.addEffect(myEffect, user)
end
local function nextPositionIntoTargets(nextPosition)
local targets = {positions = {nextPosition}, items = {}, targets = {}}
return targets
end
function M.callEffect(myEffect, user)
local foundSpell, spell = myEffect:findValue("spell")
if not foundSpell then
return
end
local foundLX, lx = myEffect:findValue("lastX")
local foundLY, ly = myEffect:findValue("lastY")
local foundTX, tx = myEffect:findValue("targetX")
local foundTY, ty = myEffect:findValue("targetY")
local foundTZ, tz = myEffect:findValue("targetZ")
local foundOrl, ORL = myEffect:findValue("ORL")
local foundStartedInAttackMode, startedInAttackMode = myEffect:findValue("startedInAttackMode")
if foundStartedInAttackMode and startedInAttackMode == 1 then
startedInAttackMode = true
else
startedInAttackMode = false
end
local foundLevel, level = myEffect:findValue("level")
if not foundLevel then
level = 0
end
local nextPosition
local castSpell = false
local positions = {}
local targetPosition
local targets
local RA = runes.checkSpellForRuneByName("RA", spell)
local CUN = runes.checkSpellForRuneByName("CUN", spell)
local SUL = runes.checkSpellForRuneByName("SUL", spell)
if not foundOrl then
ORL = false
end
if foundLX and foundLY and foundTX and foundTY and foundTZ then
targetPosition = position(tonumber(tx), tonumber(ty), tonumber(tz))
nextPosition = M.getTarget(user, myEffect, lx, ly, tx, ty, tz)
if nextPosition and world:isCharacterOnField(nextPosition) then
targetPosition = nextPosition
castSpell = true
end
if not nextPosition then
nextPosition = position(tx, ty, tz)
castSpell = true
end
table.insert(positions, {position = nextPosition})
end
local element
if foundSpell then
element = runes.fetchElement(spell)
end
local effectTargets = nextPositionIntoTargets(nextPosition)
if castSpell then
targets = targeting.getPositionsAndTargets(user, spell, targetPosition)
targets = targeting.addTargets(user, spell, targets, startedInAttackMode)
if (RA or CUN) and SUL then
targets = targeting.refreshTargets(targets)
end
local castDuration = castingSpeed.arcaneSpellCastSpeed(nil, spell, true)
M.spellEffects(user, targets, spell, element, ORL, level, castDuration, targetPosition)
return false
end
if foundSpell then
magicGFXSFX.getTargetGFXSFX(effectTargets, spell)
myEffect.nextCalled=5
end
return true
end
return M