• 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!
  • 2026 staff recruitment is open! Check it out and consider applying!

Lua Spells and Animations

Aeronx

Intermediate OT User
Joined
Dec 17, 2015
Messages
746
Solutions
9
Reaction score
125
Hello everyone!

Im doing some testing and trying to learn a bit here, so maybe you can help me out, thank you in advance.

Here's the code:
Code:
 local function sendEffc(cid)
    local cid = Player(cid)
    r1 = cid:getPosition()
    a1 = Position(r1.x, r1.y - 3, r1.z)
    a2 = Position(r1.x + 1, r1.y - 3, r1.z)
    a3 = Position(r1.x + 2, r1.y - 2, r1.z)
    a4 = Position(r1.x + 3, r1.y - 1, r1.z)
    a5 = Position(r1.x + 3, r1.y, r1.z)
    a6 = Position(r1.x + 3, r1.y + 1, r1.z)
    a7 = Position(r1.x + 2, r1.y + 2, r1.z)
    a8 = Position(r1.x + 1, r1.y + 3, r1.z)
    a9 = Position(r1.x, r1.y + 3, r1.z)
    a10 = Position(r1.x - 1, r1.y + 3, r1.z)
    a11 = Position(r1.x - 2, r1.y + 2, r1.z)
    a12 = Position(r1.x - 3, r1.y + 1, r1.z)
    a13 = Position(r1.x - 3, r1.y, r1.z)
    a14 = Position(r1.x - 3, r1.y - 1, r1.z)
    a15 = Position(r1.x - 2, r1.y - 2, r1.z)
    a16 = Position(r1.x - 1, r1.y - 3, r1.z)

    a1:sendDistanceEffect(a2, CONST_ANI_FIRE)
    a2:sendDistanceEffect(a3, CONST_ANI_FIRE)
    a3:sendDistanceEffect(a4, CONST_ANI_FIRE)
    a4:sendDistanceEffect(a5, CONST_ANI_FIRE)
    a5:sendDistanceEffect(a6, CONST_ANI_FIRE)
    a6:sendDistanceEffect(a7, CONST_ANI_FIRE)
    a7:sendDistanceEffect(a8, CONST_ANI_FIRE)
    a8:sendDistanceEffect(a9, CONST_ANI_FIRE)
    a9:sendDistanceEffect(a10, CONST_ANI_FIRE)
    a10:sendDistanceEffect(a11, CONST_ANI_FIRE)
    a11:sendDistanceEffect(a12, CONST_ANI_FIRE)
    a12:sendDistanceEffect(a13, CONST_ANI_FIRE)
    a13:sendDistanceEffect(a14, CONST_ANI_FIRE)
    a14:sendDistanceEffect(a15, CONST_ANI_FIRE)
    a15:sendDistanceEffect(a16, CONST_ANI_FIRE)
    a16:sendDistanceEffect(a1, CONST_ANI_FIRE)

    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a1, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a2, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a3, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a4, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a5, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a6, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a7, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a8, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a9, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a10, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a11, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a12, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a13, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a14, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a15, {1}, 10, 20, CONST_ANI_FIRE)
    doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, a16, {1}, 10, 20, CONST_ANI_FIRE)

end
local times = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}
function onCastSpell(creature, variant)
    for i = 1, #times do
    addEvent(sendEffc, times[i] * 150, creature.uid)
    end
   return true
end

First of all this spell onCast creates a ring of fire and damages all creatures on it.

-How can i optimize the code? It looks waaay too repetitive.
-How can i add delay between sendDistanceEffects? and apply the same delay to damage?

Thank you for your time.
 
Solution
X
My bad! working perfectly! Thank you all!

Actually learned something today! Thanks for your time!


--Edit:

After doing some testing i got this:
(Because there was an obvious exploit, you could use it throgh walls!)

Trying to avoid this problem got this:
Code:
local positions = {
    {0, -3},
    {1, -3},
    {2, -2},
    {3, -1},
    {3,  0},
    {3,  1},
    {2,  2},
    {1,  3},
    {0,  3},
    {-1, 3},
    {-2, 2},
    {-3, 1},
    {-3, 0},
    {-3, -1},
    {-2, -2},
    {-1, -3}
}
local function sendEffc(cid, max_iterations, iterations)
    local x = (max_iterations - iterations) + 1
    if x > 16 then
        repeat
            x = x - 16
        until x <= 16
    end
    local y = x + 1
    if y > 16 then
        y = 1...
Updated:
Same effect straight line from south to north.
Maybe you copied it before I was able to update.
I'll just paste below.
LUA:
local positions = {
    {0, -3},
    {1, -3},
    {2, -2},
    {3, -1},
    {3,  0},
    {3,  1},
    {2,  2},
    {1,  3},
    {0,  3},
    {-1, 3},
    {-2, 2},
    {-3, 1},
    {-3, 0},
    {-3, 1},
    {-2, 2},
    {-1, 3}
}

local function sendEffc(cid, cid_x, cid_y, cid_z, count)
    local x = count
    if x > 16 then
        repeat
            x = x - 16
        until x <= 16
    end
    local y = x + 1
    if y > 16 then
        y = 1
    end
    local pid = Player(cid)
    local pos = Position(cid_x + positions[x][1], cid_y + positions[x][2], cid_z)
    local pos2 = Position(cid_x + positions[y][1], cid_y + positions[y][2], cid_z)
    pos:sendDistanceEffect(pos2, CONST_ANI_FIRE)
    doAreaCombatHealth(pid, COMBAT_FIREDAMAGE, pos, {1}, 10, 20, CONST_ANI_FIRE)
    count = count - 1
    if count > 0 then
        addEvent(sendEffc, 150, cid, cid_x, cid_y, cid_z, count)
    end
end

function onCastSpell(creature, variant)
    local times_to_run = 2
    local cid = Player(creature.uid)
    local cid_p = cid:getPosition()
    addEvent(sendEffc, 150, creature.uid, cid_p.x, cid_p.y, cid_p.z, times_to_run * 16)
    return true
end
 
Whaaaat? HAHAHAHA epic xD
uggh. lmao

try this
LUA:
local positions = {
    {0, -3},
    {1, -3},
    {2, -2},
    {3, -1},
    {3,  0},
    {3,  1},
    {2,  2},
    {1,  3},
    {0,  3},
    {-1, 3},
    {-2, 2},
    {-3, 1},
    {-3, 0},
    {-3, 1},
    {-2, 2},
    {-1, 3}
}

local function sendEffc(cid, cid_x, cid_y, cid_z, n, count)
    local x = ((count - n) + 1)
    if x > 16 then
        repeat
            x = x - 16
        until x <= 16
    end
    local y = x + 1
    if y > 16 then
        y = 1
    end
    local pid = Player(cid)
    local pos = Position(cid_x + positions[x][1], cid_y + positions[x][2], cid_z)
    local pos2 = Position(cid_x + positions[y][1], cid_y + positions[y][2], cid_z)
    pos:sendDistanceEffect(pos2, CONST_ANI_FIRE)
    doAreaCombatHealth(pid, COMBAT_FIREDAMAGE, pos, {1}, 10, 20, CONST_ANI_FIRE)
    n = n - 1
    if n > 0 then
        addEvent(sendEffc, 150, cid, cid_x, cid_y, cid_z, n, count)
    end
end

function onCastSpell(creature, variant)
    local times_to_run = 2
    local cid = Player(creature.uid)
    local cid_p = cid:getPosition()
    addEvent(sendEffc, 150, creature.uid, cid_p.x, cid_p.y, cid_p.z, times_to_run * 16, times_to_run * 16)
    return true
end
 
Code:
x = 1, y = 2
x = 2, y = 3
x = 3, y = 4
x = 4, y = 5
x = 5, y = 6
x = 6, y = 7
x = 7, y = 8
x = 8, y = 9
x = 9, y = 10
x = 10, y = 11
x = 11, y = 12
x = 12, y = 13
x = 13, y = 14
x = 14, y = 15
x = 15, y = 16
x = 16, y = 1
x = 1, y = 2
x = 2, y = 3
x = 3, y = 4
x = 4, y = 5
x = 5, y = 6
x = 6, y = 7
x = 7, y = 8
x = 8, y = 9
x = 9, y = 10
x = 10, y = 11
x = 11, y = 12
x = 12, y = 13
x = 13, y = 14
x = 14, y = 15
x = 15, y = 16
x = 16, y = 1
 
Code:
x = 1, y = 2
x = 2, y = 3
x = 3, y = 4
x = 4, y = 5
x = 5, y = 6
x = 6, y = 7
x = 7, y = 8
x = 8, y = 9
x = 9, y = 10
x = 10, y = 11
x = 11, y = 12
x = 12, y = 13
x = 13, y = 14
x = 14, y = 15
x = 15, y = 16
x = 16, y = 1
x = 1, y = 2
x = 2, y = 3
x = 3, y = 4
x = 4, y = 5
x = 5, y = 6
x = 6, y = 7
x = 7, y = 8
x = 8, y = 9
x = 9, y = 10
x = 10, y = 11
x = 11, y = 12
x = 12, y = 13
x = 13, y = 14
x = 14, y = 15
x = 15, y = 16
x = 16, y = 1
update with below
Code:
local positions = {
   {0, -3},
   {1, -3},
   {2, -2},
   {3, -1},
   {3,  0},
   {3,  1},
   {2,  2},
   {1,  3},
   {0,  3},
   {-1, 3},
   {-2, 2},
   {-3, 1},
   {-3, 0},
   {-3, -1},
   {-2, -2},
   {-1, -3}
}
 
Haha! finally working perfect! :)
Sweet.
Here's the full code I suppose.
LUA:
local positions = {
    {0, -3},
    {1, -3},
    {2, -2},
    {3, -1},
    {3,  0},
    {3,  1},
    {2,  2},
    {1,  3},
    {0,  3},
    {-1, 3},
    {-2, 2},
    {-3, 1},
    {-3, 0},
    {-3, -1},
    {-2, -2},
    {-1, -3}
}

local function sendEffc(cid, cid_x, cid_y, cid_z, max_iterations, iterations)
    local x = (max_iterations - iterations) + 1
    if x > 16 then
        repeat
            x = x - 16
        until x <= 16
    end
    local y = x + 1
    if y > 16 then
        y = 1
    end
    local pos = Position(cid_x + positions[x][1], cid_y + positions[x][2], cid_z)
    local pos2 = Position(cid_x + positions[y][1], cid_y + positions[y][2], cid_z)
    pos:sendDistanceEffect(pos2, CONST_ANI_FIRE)
    local pid = Player(cid)
    doAreaCombatHealth(pid, COMBAT_FIREDAMAGE, pos, {1}, 10, 20, CONST_ANI_FIRE)
    iterations = iterations - 1
    if iterations > 0 then
        addEvent(sendEffc, 150, cid, cid_x, cid_y, cid_z, max_iterations, iterations)
    end
end

function onCastSpell(creature, variant)
    local times_to_run = 2 * #positions
    local cid = Player(creature.uid)
    local cid_p = cid:getPosition()
    addEvent(sendEffc, 150, creature.uid, cid_p.x, cid_p.y, cid_p.z, times_to_run, times_to_run)
    return true
end
 
Edit: Not working as intended.

If you move the spell doesnt follow. Its just a circle on the floor.
 
Edit: Not working as intended.

If you move the spell doesnt follow. Its just a circle on the floor.
A simple fix..
I had no idea you wanted it to follow the player.
LUA:
local positions = {
    {0, -3},
    {1, -3},
    {2, -2},
    {3, -1},
    {3,  0},
    {3,  1},
    {2,  2},
    {1,  3},
    {0,  3},
    {-1, 3},
    {-2, 2},
    {-3, 1},
    {-3, 0},
    {-3, -1},
    {-2, -2},
    {-1, -3}
}

local function sendEffc(cid, max_iterations, iterations)
    local x = (max_iterations - iterations) + 1
    if x > 16 then
        repeat
            x = x - 16
        until x <= 16
    end
    local y = x + 1
    if y > 16 then
        y = 1
    end
    local pid = Player(cid)
    local pid_p = pid:getPosition()
    local pos = Position(pid_p.x + positions[x][1], pid_p.y + positions[x][2], pid_p.z)
    local pos2 = Position(pid_p.x + positions[y][1], pid_p.y + positions[y][2], pid_p.z)
    pos:sendDistanceEffect(pos2, CONST_ANI_FIRE)
    doAreaCombatHealth(pid, COMBAT_FIREDAMAGE, pos, {1}, 10, 20, CONST_ANI_FIRE)
    iterations = iterations - 1
    if iterations > 0 then
        addEvent(sendEffc, 150, cid, max_iterations, iterations)
    end
end

function onCastSpell(creature, variant)
    local times_to_run = 2 * #positions
    addEvent(sendEffc, 150, creature.uid, times_to_run, times_to_run)
    return true
end
 
My bad! working perfectly! Thank you all!

Actually learned something today! Thanks for your time!


--Edit:

After doing some testing i got this:
(Because there was an obvious exploit, you could use it throgh walls!)

Trying to avoid this problem got this:
Code:
local positions = {
    {0, -3},
    {1, -3},
    {2, -2},
    {3, -1},
    {3,  0},
    {3,  1},
    {2,  2},
    {1,  3},
    {0,  3},
    {-1, 3},
    {-2, 2},
    {-3, 1},
    {-3, 0},
    {-3, -1},
    {-2, -2},
    {-1, -3}
}
local function sendEffc(cid, max_iterations, iterations)
    local x = (max_iterations - iterations) + 1
    if x > 16 then
        repeat
            x = x - 16
        until x <= 16
    end
    local y = x + 1
    if y > 16 then
        y = 1
    end
    local pid = Player(cid)
    local pid_p = pid:getPosition()
    local pos = Position(pid_p.x + positions[x][1], pid_p.y + positions[x][2], pid_p.z)
    local pos2 = Position(pid_p.x + positions[y][1], pid_p.y + positions[y][2], pid_p.z)
    if Tile(pos):hasFlag(TILESTATE_PROTECTIONZONE) then
            return false
        end
    local tile = Tile(pos)
    if not (tile:hasProperty(CONST_PROP_BLOCKPROJECTILE) or tile:hasFlag(TILESTATE_FLOORCHANGE) or tile:hasFlag(TILESTATE_TELEPORT) or tile:hasFlag(TILESTATE_PROTECTIONZONE)) then
    pos:sendDistanceEffect(pos2, CONST_ANI_FIRE)
    doAreaCombatHealth(pid, COMBAT_FIREDAMAGE, pos, {1}, 10, 20, CONST_ANI_FIRE)
    iterations = iterations - 1
    if iterations > 0 then
        addEvent(sendEffc, 100, cid, max_iterations, iterations)
    end
    end
end
function onCastSpell(creature, variant)
    local times_to_run = 10 * #positions
    addEvent(sendEffc, 100, creature.uid, times_to_run, times_to_run)
    return true
end

This does half the trick, the problem is when it encounters a pz zone, blockprojectile, etc, the spell stops, instead of continuing to the next tile. Fixes?
 
Last edited:
My bad! working perfectly! Thank you all!

Actually learned something today! Thanks for your time!


--Edit:

After doing some testing i got this:
(Because there was an obvious exploit, you could use it throgh walls!)

Trying to avoid this problem got this:
Code:
local positions = {
    {0, -3},
    {1, -3},
    {2, -2},
    {3, -1},
    {3,  0},
    {3,  1},
    {2,  2},
    {1,  3},
    {0,  3},
    {-1, 3},
    {-2, 2},
    {-3, 1},
    {-3, 0},
    {-3, -1},
    {-2, -2},
    {-1, -3}
}
local function sendEffc(cid, max_iterations, iterations)
    local x = (max_iterations - iterations) + 1
    if x > 16 then
        repeat
            x = x - 16
        until x <= 16
    end
    local y = x + 1
    if y > 16 then
        y = 1
    end
    local pid = Player(cid)
    local pid_p = pid:getPosition()
    local pos = Position(pid_p.x + positions[x][1], pid_p.y + positions[x][2], pid_p.z)
    local pos2 = Position(pid_p.x + positions[y][1], pid_p.y + positions[y][2], pid_p.z)
    if Tile(pos):hasFlag(TILESTATE_PROTECTIONZONE) then
            return false
        end
    local tile = Tile(pos)
    if not (tile:hasProperty(CONST_PROP_BLOCKPROJECTILE) or tile:hasFlag(TILESTATE_FLOORCHANGE) or tile:hasFlag(TILESTATE_TELEPORT) or tile:hasFlag(TILESTATE_PROTECTIONZONE)) then
    pos:sendDistanceEffect(pos2, CONST_ANI_FIRE)
    doAreaCombatHealth(pid, COMBAT_FIREDAMAGE, pos, {1}, 10, 20, CONST_ANI_FIRE)
    iterations = iterations - 1
    if iterations > 0 then
        addEvent(sendEffc, 100, cid, max_iterations, iterations)
    end
    end
end
function onCastSpell(creature, variant)
    local times_to_run = 10 * #positions
    addEvent(sendEffc, 100, creature.uid, times_to_run, times_to_run)
    return true
end

This does half the trick, the problem is when it encounters a pz zone, blockprojectile, etc, the spell stops, instead of continuing to the next tile. Fixes?
Just move the 'iterations' part above your checks.
LUA:
local positions = {
    {0, -3},
    {1, -3},
    {2, -2},
    {3, -1},
    {3,  0},
    {3,  1},
    {2,  2},
    {1,  3},
    {0,  3},
    {-1, 3},
    {-2, 2},
    {-3, 1},
    {-3, 0},
    {-3, -1},
    {-2, -2},
    {-1, -3}
}

local function sendEffc(cid, max_iterations, iterations)
    iterations = iterations - 1
    if iterations > 0 then
        addEvent(sendEffc, 100, cid, max_iterations, iterations)
    end
    local x = max_iterations - iterations
    if x > 16 then
        repeat
            x = x - 16
        until x <= 16
    end
    local y = x + 1
    if y > 16 then
        y = 1
    end
    local pid = Player(cid)
    local pid_p = pid:getPosition()
    local pos = Position(pid_p.x + positions[x][1], pid_p.y + positions[x][2], pid_p.z)
    local pos2 = Position(pid_p.x + positions[y][1], pid_p.y + positions[y][2], pid_p.z)
    if Tile(pos):hasFlag(TILESTATE_PROTECTIONZONE) then
        return false
    end
    local tile = Tile(pos)
    if not (tile:hasProperty(CONST_PROP_BLOCKPROJECTILE) or tile:hasFlag(TILESTATE_FLOORCHANGE) or tile:hasFlag(TILESTATE_TELEPORT) or tile:hasFlag(TILESTATE_PROTECTIONZONE)) then
        pos:sendDistanceEffect(pos2, CONST_ANI_FIRE)
        doAreaCombatHealth(pid, COMBAT_FIREDAMAGE, pos, {1}, 10, 20, CONST_ANI_FIRE)
    end
end

function onCastSpell(creature, variant)
    local times_to_run = 10 * #positions
    addEvent(sendEffc, 100, creature.uid, times_to_run, times_to_run)
    return true
end
 
Solution
Back
Top