• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua push and pull spells for TFS 1.3

Icaraii

Well-Known Member
Joined
Jan 5, 2020
Messages
469
Solutions
1
Reaction score
58
Hey guys,

I've being looking for a push and pull spell for a while now, and can't seem to find working for TFS 1.3, can somebody help?

The push spell consist in push the target (single target or area of effect target) 4 sqm away, checking interferences in the way and if any interference is found in the way, the target will be push as farder as possible.

The pull spell consist in pulling the target (single target or area of effect target) 4 sqm closer, checking interferences in the way and if any interference is found in the way, the target will be pulled as closer as possible.

And a third spell, that is basically the 2 one but has a variation: Player cast spell and for the next 10 seconds, any monsters that hit him from 3 sqm plus, will be pulled to him, checking interferences in the way and if any interference is found in the way, the target will be pulled as closer as possible.

And a fourth spell, that is basically the 1 one but has a variation: Player cast spell and for the next 10 seconds, any monsters that hit him, will be pushed 3 sqm away from him, checking interferences in the way and if any interference is found in the way, the target will be pushed as far as possible.

I know it seems a lot, but is basically the same spell with 4 variations
 
Solution
Nice, pretty simple to edit, thanks
Here's my attempt at the divine caldera.

The main problem with the skill is that you have to manually iterate through the circle to do it properly, instead of automatically grabbing the tiles.

It's a giant pain the in butt. lol

Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HOLYDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYAREA)
combat:setArea(createCombatArea(AREA_CIRCLE3X3))

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 5) + 25
    local max = (level / 5) + (magicLevel * 6.2) + 45
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

local pushArea...
Ironically the push/pull part of the spell is easy and I can do it.. but the spell part I cannot.
Do you have a base spell for me to work from?
 
Ironically the push/pull part of the spell is easy and I can do it.. but the spell part I cannot.
Do you have a base spell for me to work from?
Can you do it based in the exori frigo spell?

Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEATTACK)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLICE)

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 1.4) + 8
    local max = (level / 5) + (magicLevel * 2.2) + 14
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onCastSpell(creature, variant)
    return combat:execute(creature, variant)
end
 
Can you do it based in the exori frigo spell?

Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEATTACK)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLICE)

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 1.4) + 8
    local max = (level / 5) + (magicLevel * 2.2) + 14
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onCastSpell(creature, variant)
    return combat:execute(creature, variant)
end
Probably, but it's a single target skill as apposed to an area skill. xD

Actually.. maybe that doesn't matter.

I just need to make the push/pull function I guess. 🤔

I'll see what I come up with.
 
For the area one, maybe base on exevo mas san

Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HOLYDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYAREA)
combat:setArea(createCombatArea(AREA_CIRCLE3X3))


function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 5) + 25
    local max = (level / 5) + (magicLevel * 6.2) + 45
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onCastSpell(creature, variant)
    return combat:execute(creature, variant)
end
 
Well, here's exori frigo.

Just install the two functions

Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEATTACK)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLICE)

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 1.4) + 8
    local max = (level / 5) + (magicLevel * 2.2) + 14
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onCastSpell(creature, variant)
    local target = creature:getTarget()
    if target then
        pullTarget(creature:getId(), target:getId(), 1, true)
    else
        local position = creature:getPosition()
        position:getNextPosition(creature:getDirection())
        local tile = Tile(position) 
        target = Creature(tile:getTopCreature())
        if target then
            pullTarget(creature:getId(), target:getId(), 1, true)
        end
    end
    return combat:execute(creature, variant)
end
 
It work flawless, but lets say I want to pull or push the target 3 sqm instead of 1, how do I do that? Is it possible?
 
It work flawless, but lets say I want to pull or push the target 3 sqm instead of 1, how do I do that? Is it possible?
Lua:
-- pushTarget(creatureId, creatureId, 1+, true/false)
function pushTarget(creatureId, targetId, amount, dynamic) -- dynamic means it'll look for extra squares

The 1+ in the function description is the amount of times it'll push the target.

So if you change 1 to 3, it'll attempt to push/pull them 3 times.
Lua:
pullTarget(creature:getId(), target:getId(), 1, true) -- 1 pull
pullTarget(creature:getId(), target:getId(), 3, true) -- 3 pull
 
Lua:
-- pushTarget(creatureId, creatureId, 1+, true/false)
function pushTarget(creatureId, targetId, amount, dynamic) -- dynamic means it'll look for extra squares

The 1+ in the function description is the amount of times it'll push the target.

So if you change 1 to 3, it'll attempt to push/pull them 3 times.
Nice, pretty simple to edit, thanks
 
Add this under local target = creature:getTarget() to make sure you cannot use this on training monks.

Lua:
    local names = {"Training Monk", "Batman"}
    if table.contains(names, target:getName()) then
        return true
    end
 
Last edited:
Nice, pretty simple to edit, thanks
Here's my attempt at the divine caldera.

The main problem with the skill is that you have to manually iterate through the circle to do it properly, instead of automatically grabbing the tiles.

It's a giant pain the in butt. lol

Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HOLYDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYAREA)
combat:setArea(createCombatArea(AREA_CIRCLE3X3))

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 5) + 25
    local max = (level / 5) + (magicLevel * 6.2) + 45
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

local pushArea = {
    {0, -3, -3}, {0, -2, -3}, {1, -1, -3}, {1,  0, -3}, {1,  1, -3}, {0,  2, -3}, {0,  3, -3}, -- {layer, x, y} -- x and y are counted from epicentre
    {0, -3, -2}, {1, -2, -2}, {2, -1, -2}, {2,  0, -2}, {2,  1, -2}, {1,  2, -2}, {0,  3, -2},
    {1, -3, -1}, {2, -2, -1}, {3, -1, -1}, {3,  0, -1}, {3,  1, -1}, {2,  2, -1}, {1,  3, -1},
    {1, -3,  0}, {2, -2,  0}, {3, -1,  0}, {0,  0,  0}, {3,  1,  0}, {2,  2,  0}, {1,  3,  0}, -- this is a re-creation of AREA_CIRCLE3X3
    {1, -3,  1}, {2, -2,  1}, {3, -1,  1}, {3,  0,  1}, {3,  1,  1}, {2,  2,  1}, {1,  3,  1},
    {0, -3,  2}, {1, -2,  2}, {2, -1,  2}, {2,  0,  2}, {2,  1,  2}, {1,  2,  2}, {0,  3,  2},
    {0, -3,  3}, {0, -2,  3}, {1, -1,  3}, {1,  0,  3}, {1,  1,  3}, {0,  2,  3}, {0,  3,  3},
}

--[[

-- Pull area is the opposite of push, the layers need to start close, then go outwards.
local pullArea = {
    {0, -3, -3}, {0, -2, -3}, {3, -1, -3}, {3,  0, -3}, {3,  1, -3}, {0,  2, -3}, {0,  3, -3},
    {0, -3, -2}, {3, -2, -2}, {2, -1, -2}, {2,  0, -2}, {2,  1, -2}, {3,  2, -2}, {0,  3, -2},
    {3, -3, -1}, {2, -2, -1}, {1, -1, -1}, {1,  0, -1}, {1,  1, -1}, {2,  2, -1}, {3,  3, -1},
    {3, -3,  0}, {2, -2,  0}, {1, -1,  0}, {0,  0,  0}, {1,  1,  0}, {2,  2,  0}, {3,  3,  0},
    {3, -3,  1}, {2, -2,  1}, {1, -1,  1}, {1,  0,  1}, {1,  1,  1}, {2,  2,  1}, {3,  3,  1},
    {0, -3,  2}, {3, -2,  2}, {2, -1,  2}, {2,  0,  2}, {2,  1,  2}, {3,  2,  2}, {0,  3,  2},
    {0, -3,  3}, {0, -2,  3}, {3, -1,  3}, {3,  0,  3}, {3,  1,  3}, {0,  2,  3}, {0,  3,  3},
}

]]--

function onCastSpell(creature, variant)
    local castPosition = creature:getPosition()
    local pushPosition
    for n = 1, 3 do -- how many 'layers' in the pushArea (need to find manually from above table)
        for i = 1, #pushArea do
            if pushArea[i][1] == n then
                pushPosition = Position(castPosition.x + pushArea[i][2], castPosition.y + pushArea[i][3], castPosition.z)
                local tile = Tile(pushPosition)
                if tile and tile:getCreatureCount() > 0 then
                    creatures = tile:getCreatures()
                    for _, target in ipairs(creatures) do
                        pushTarget(creature:getId(), target:getId(), 3, true)
                    end
                end
            end
        end
    end
    return combat:execute(creature, variant)
end
Post automatically merged:

This is basically what it looks like, before we add the x, y stuff.
Lua:
local pushArea = {
    0, 0, 1, 1, 1, 0, 0,
    0, 1, 2, 2, 2, 1, 0,
    1, 2, 3, 3, 3, 2, 1,
    1, 2, 3, 0, 3, 2, 1,
    1, 2, 3, 3, 3, 2, 1,
    0, 1, 2, 2, 2, 1, 0,
    0, 0, 1, 1, 1, 0, 0,
}
 
Last edited:
Solution
Here's my attempt at the divine caldera.

The main problem with the skill is that you have to manually iterate through the circle to do it properly, instead of automatically grabbing the tiles.

It's a giant pain the in butt. lol

Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HOLYDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYAREA)
combat:setArea(createCombatArea(AREA_CIRCLE3X3))

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 5) + 25
    local max = (level / 5) + (magicLevel * 6.2) + 45
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

local pushArea = {
    {0, -3, -3}, {0, -2, -3}, {1, -1, -3}, {1,  0, -3}, {1,  1, -3}, {0,  2, -3}, {0,  3, -3}, -- {layer, x, y} -- x and y are counted from epicentre
    {0, -3, -2}, {1, -2, -2}, {2, -1, -2}, {2,  0, -2}, {2,  1, -2}, {1,  2, -2}, {0,  3, -2},
    {1, -3, -1}, {2, -2, -1}, {3, -1, -1}, {3,  0, -1}, {3,  1, -1}, {2,  2, -1}, {1,  3, -1},
    {1, -3,  0}, {2, -2,  0}, {3, -1,  0}, {0,  0,  0}, {3,  1,  0}, {2,  2,  0}, {1,  3,  0}, -- this is a re-creation of AREA_CIRCLE3X3
    {1, -3,  1}, {2, -2,  1}, {3, -1,  1}, {3,  0,  1}, {3,  1,  1}, {2,  2,  1}, {1,  3,  1},
    {0, -3,  2}, {1, -2,  2}, {2, -1,  2}, {2,  0,  2}, {2,  1,  2}, {1,  2,  2}, {0,  3,  2},
    {0, -3,  3}, {0, -2,  3}, {1, -1,  3}, {1,  0,  3}, {1,  1,  3}, {0,  2,  3}, {0,  3,  3},
}

--[[

-- Pull area is the opposite of push, the layers need to start close, then go outwards.
local pullArea = {
    {0, -3, -3}, {0, -2, -3}, {3, -1, -3}, {3,  0, -3}, {3,  1, -3}, {0,  2, -3}, {0,  3, -3},
    {0, -3, -2}, {3, -2, -2}, {2, -1, -2}, {2,  0, -2}, {2,  1, -2}, {3,  2, -2}, {0,  3, -2},
    {3, -3, -1}, {2, -2, -1}, {1, -1, -1}, {1,  0, -1}, {1,  1, -1}, {2,  2, -1}, {3,  3, -1},
    {3, -3,  0}, {2, -2,  0}, {1, -1,  0}, {0,  0,  0}, {1,  1,  0}, {2,  2,  0}, {3,  3,  0},
    {3, -3,  1}, {2, -2,  1}, {1, -1,  1}, {1,  0,  1}, {1,  1,  1}, {2,  2,  1}, {3,  3,  1},
    {0, -3,  2}, {3, -2,  2}, {2, -1,  2}, {2,  0,  2}, {2,  1,  2}, {3,  2,  2}, {0,  3,  2},
    {0, -3,  3}, {0, -2,  3}, {3, -1,  3}, {3,  0,  3}, {3,  1,  3}, {0,  2,  3}, {0,  3,  3},
}

]]--

function onCastSpell(creature, variant)
    local castPosition = creature:getPosition()
    local pushPosition
    for n = 1, 3 do -- how many 'layers' in the pushArea (need to find manually from above table)
        for i = 1, #pushArea do
            if pushArea[i][1] == n then
                pushPosition = Position(castPosition.x + pushArea[i][2], castPosition.y + pushArea[i][3], castPosition.z)
                local tile = Tile(pushPosition)
                if tile then
                    creatures = tile:getCreatures()
                    if #creatures > 0 then
                        for _, target in ipairs(creatures) do
                            pushTarget(creature:getId(), target:getId(), 3, true)
                        end
                    end
                end
            end
        end
    end
    return combat:execute(creature, variant)
end
Post automatically merged:

This is basically what it looks like, before we add the x, y stuff.
Lua:
local pushArea = {
    0, 0, 1, 1, 1, 0, 0,
    0, 1, 2, 2, 2, 1, 0,
    1, 2, 3, 3, 3, 2, 1,
    1, 2, 3, 0, 3, 2, 1,
    1, 2, 3, 3, 3, 2, 1,
    0, 1, 2, 2, 2, 1, 0,
    0, 0, 1, 1, 1, 0, 0,
}
This one is not quite working. The effect doesn't appear if hit the monsters, it's not dealing damage and this error appear on TFS:
Lua Script Error: [Spell Interface]
data/spells/scripts/attack/pullarea.lua:eek:nCastSpell
data/spells/scripts/attack/pullarea.lua:49: attempt to get length of global 'creatures' (a nil value)
stack traceback:
[C]: in function '__len'
data/spells/scripts/attack/pullarea.lua:49: in function <data/spells/scripts/attack/pullarea.lua:39>

Lua Script Error: [Spell Interface]
data/spells/scripts/attack/pusharea.lua:eek:nCastSpell
data/spells/scripts/attack/pusharea.lua:49: attempt to get length of global 'creatures' (a nil value)
stack traceback:
[C]: in function '__len'
data/spells/scripts/attack/pusharea.lua:49: in function <data/spells/scripts/attack/pusharea.lua:39>
 
attempt to get length of global 'creatures' (a nil value)

try replacing:
Lua:
if #creatures > 0 then
with
Lua:
if creatures and #creatures > 0 then

edit:
or.. since it only needs to check if there are any creatures on the tile, you could do the following:
Lua:
if creatures then
 
Back
Top