• 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!

Spell [TFS 1.X] Magic Missile

Leo32

Getting back into it...
Joined
Sep 21, 2007
Messages
987
Solutions
14
Reaction score
532
Naturally scaling strike spell.
Start with 2 missiles, gain an extra missile every 20 magic levels.

i6RAXoK.gif


Inspired by this post:

I suggest making its mana costs around 30-50 depending on your exp/skillrates.
Each missile does about half the damage of a strike spell, so once you get to 4-5 missiles its starts to be competitive with mana efficiency.

magic missile.lua
Lua:
-- Minimum amount of magic missiles
local minMissiles = 2

local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE)

local function arcaneDamage(player, var, target, missileEffectpos, animationroll)
    local player = Player(player)
    local creature = Creature(target)
    if player and creature then
        local level = player:getLevel()
        local magiclevel = player:getMagicLevel()
        local min = (level / 5) + (magiclevel * 0.2) + 5
        local max = (level / 5) + (magiclevel * 0.8) + 12
        combat:setFormula(COMBAT_FORMULA_LEVELMAGIC, 0, -min, 0, -max)
        Position(missileEffectpos):sendDistanceEffect(creature:getPosition(), CONST_ANI_ENERGYBALL)
        if animationroll == 1 then
            creature:getPosition():sendMagicEffect(CONST_ME_PURPLEENERGY)
        end
        combat:execute(player, var)
    end
    return true
end

local function arcaneBolt(player, var, target, count)
    local player = Player(player)
    local creature = Creature(target)
    if player and creature then
        local playerpos = player:getPosition()
        local creaturepos = creature:getPosition()
        local missileEffectpos = Position(playerpos)
        local differencey = playerpos.y - creaturepos.y -- positive = N, negative = S
        local differencex = playerpos.x - creaturepos.x -- positive = W, negative = E
        local ymodifier = 0
        local xmodifier = 0
        local animationroll = 0
        -- Cycle between each side of player depending if missile is even or odd
        if count % 2 == 0 then -- even
            if differencey > 0 then -- Target it to the N
                xmodifier = xmodifier + 1
                if math.random(1,2) == 2 then
                    ymodifier = ymodifier - 1
                end
            elseif differencey < 0 then -- Target is to the S
                xmodifier = xmodifier - 1
                if differencey < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    ymodifier = ymodifier + 1
                end
            end
            if differencex < 0 then -- Target is to the E
                ymodifier = ymodifier + 1
                if differencex < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    xmodifier = xmodifier + 1
                end
            elseif differencex > 0 then -- Target is to the W
                ymodifier = ymodifier - 1
                if math.random(1,2) == 2 then
                    xmodifier = xmodifier - 1
                end
            end
        else -- odd
            animationroll = 1
            if differencey > 0 then -- Target it to the N
                xmodifier = xmodifier - 1
                if math.random(1,2) == 2 then
                    ymodifier = ymodifier - 1
                end
            elseif differencey < 0 then -- Target is to the S
                xmodifier = xmodifier + 1
                if differencey < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    ymodifier = ymodifier + 1
                end
            end
            if differencex < 0 then -- Target is to the E
                ymodifier = ymodifier - 1
                if differencex < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    xmodifier = xmodifier + 1
                end
            elseif differencex > 0 then -- Target is to the W
                ymodifier = ymodifier + 1
                if math.random(1,2) == 2 then
                    xmodifier = xmodifier - 1
                end
            end
        end
        missileEffectpos.x = missileEffectpos.x + xmodifier
        missileEffectpos.y = missileEffectpos.y + ymodifier
        Position(playerpos):sendDistanceEffect(missileEffectpos, CONST_ANI_ENERGYBALL)
        addEvent(arcaneDamage, 150, player.uid, var, creature.uid, missileEffectpos, animationroll)
    end
    return true
end

function onCastSpell(player, var)
    local magiclevel = player:getMagicLevel()
    local target = player:getTarget()
    local missileCount = minMissiles + math.floor(magiclevel / 20) -- extra missile every 20 magic levels
    local count = 1
    for i = 1, missileCount do
        addEvent(arcaneBolt, 150 * (i - 1), player.uid, var, target.uid, count)
        count = count + 1
    end
    return true
end
 
Last edited:
I love how your spells change with ml, not only the formula, but the extra missiles, or extra targets, etc
Keep the good work <3
 
nice job bro!, but i get this error when i use this spell with no target

Lua Script Error: [Spell Interface]
data/spells/scripts/attack/magic_missile.lua:eek:nCastSpell
data/spells/scripts/attack/magic_missile.lua:100: attempt to index local 'target' (a nil value)
stack traceback:
[C]: in function '__index'
data/spells/scripts/attack/magic_missile.lua:100: in function <data/spells/scripts/attack/magic_missile.lua:94>
 
Wasnt made with that in mind.
 
Lua:
-- Minimum amount of magic missiles
local minMissiles = 2

local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE)

local function arcaneDamage(player, var, target, missileEffectpos, animationroll)
    local player = Player(player)
    local creature = Creature(target)
    if player and creature then
        local level = player:getLevel()
        local magiclevel = player:getMagicLevel()
        local min = (level / 5) + (magiclevel * 0.2) + 5
        local max = (level / 5) + (magiclevel * 0.8) + 12
        combat:setFormula(COMBAT_FORMULA_LEVELMAGIC, 0, -min, 0, -max)
        Position(missileEffectpos):sendDistanceEffect(creature:getPosition(), CONST_ANI_ENERGYBALL)
        if animationroll == 1 then
            creature:getPosition():sendMagicEffect(CONST_ME_PURPLEENERGY)
        end
        combat:execute(player, var)
    end
    return true
end

local function arcaneBolt(player, var, target, count)
    local player = Player(player)
    local creature = Creature(target)
    if player and creature then
        local playerpos = player:getPosition()
        local creaturepos = creature:getPosition()
        local missileEffectpos = Position(playerpos)
        local differencey = playerpos.y - creaturepos.y -- positive = N, negative = S
        local differencex = playerpos.x - creaturepos.x -- positive = W, negative = E
        local ymodifier = 0
        local xmodifier = 0
        local animationroll = 0
        -- Cycle between each side of player depending if missile is even or odd
        if count % 2 == 0 then -- even
            if differencey > 0 then -- Target it to the N
                xmodifier = xmodifier + 1
                if math.random(1,2) == 2 then
                    ymodifier = ymodifier - 1
                end
            elseif differencey < 0 then -- Target is to the S
                xmodifier = xmodifier - 1
                if differencey < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    ymodifier = ymodifier + 1
                end
            end
            if differencex < 0 then -- Target is to the E
                ymodifier = ymodifier + 1
                if differencex < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    xmodifier = xmodifier + 1
                end
            elseif differencex > 0 then -- Target is to the W
                ymodifier = ymodifier - 1
                if math.random(1,2) == 2 then
                    xmodifier = xmodifier - 1
                end
            end
        else -- odd
            animationroll = 1
            if differencey > 0 then -- Target it to the N
                xmodifier = xmodifier - 1
                if math.random(1,2) == 2 then
                    ymodifier = ymodifier - 1
                end
            elseif differencey < 0 then -- Target is to the S
                xmodifier = xmodifier + 1
                if differencey < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    ymodifier = ymodifier + 1
                end
            end
            if differencex < 0 then -- Target is to the E
                ymodifier = ymodifier - 1
                if differencex < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    xmodifier = xmodifier + 1
                end
            elseif differencex > 0 then -- Target is to the W
                ymodifier = ymodifier + 1
                if math.random(1,2) == 2 then
                    xmodifier = xmodifier - 1
                end
            end
        end
        missileEffectpos.x = missileEffectpos.x + xmodifier
        missileEffectpos.y = missileEffectpos.y + ymodifier
        Position(playerpos):sendDistanceEffect(missileEffectpos, CONST_ANI_ENERGYBALL)
        addEvent(arcaneDamage, 150, player.uid, var, creature.uid, missileEffectpos, animationroll)
    end
    return true
end

function onCastSpell(player, var)
    local magiclevel = player:getMagicLevel()
    local target = player:getTarget()
    local missileCount = minMissiles + math.floor(magiclevel / 20) -- extra missile every 20 magic levels
    local count = 1
    if target then
        for i = 1, missileCount do
            addEvent(arcaneBolt, 150 * (i - 1), player.uid, var, target.uid, count)
            count = count + 1
        end
    end
    return true
end

This way the error is gone, but you wont get a heads up like no target selected.
 
better than cipsoft IMO

i'm thankful for old cipsoft for bring tibia to life and despise the current one for ruin something so good.
BloodStone is prime example of the potential of OTclient and the possibilities.


Thanks buddy, I'm building up a spell system for my ot from scratch.
Plan is to post everything useful I create here for others to use (cause lets be honest who knows if my OT will ever see the light of day).

awesome missile man! keep it up
and even if its take few years, im sure your IT will see daylight!
and be very loved by a community that you will create.

best wish i can give you.
hope you never see another bug in your code! and everything will go smooth for you!
 
Wasnt made with that in mind.
i know... the problem just was the flood in the console with this error, but i have solved it.. thx
Post automatically merged:

Lua:
-- Minimum amount of magic missiles
local minMissiles = 2

local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE)

local function arcaneDamage(player, var, target, missileEffectpos, animationroll)
    local player = Player(player)
    local creature = Creature(target)
    if player and creature then
        local level = player:getLevel()
        local magiclevel = player:getMagicLevel()
        local min = (level / 5) + (magiclevel * 0.2) + 5
        local max = (level / 5) + (magiclevel * 0.8) + 12
        combat:setFormula(COMBAT_FORMULA_LEVELMAGIC, 0, -min, 0, -max)
        Position(missileEffectpos):sendDistanceEffect(creature:getPosition(), CONST_ANI_ENERGYBALL)
        if animationroll == 1 then
            creature:getPosition():sendMagicEffect(CONST_ME_PURPLEENERGY)
        end
        combat:execute(player, var)
    end
    return true
end

local function arcaneBolt(player, var, target, count)
    local player = Player(player)
    local creature = Creature(target)
    if player and creature then
        local playerpos = player:getPosition()
        local creaturepos = creature:getPosition()
        local missileEffectpos = Position(playerpos)
        local differencey = playerpos.y - creaturepos.y -- positive = N, negative = S
        local differencex = playerpos.x - creaturepos.x -- positive = W, negative = E
        local ymodifier = 0
        local xmodifier = 0
        local animationroll = 0
        -- Cycle between each side of player depending if missile is even or odd
        if count % 2 == 0 then -- even
            if differencey > 0 then -- Target it to the N
                xmodifier = xmodifier + 1
                if math.random(1,2) == 2 then
                    ymodifier = ymodifier - 1
                end
            elseif differencey < 0 then -- Target is to the S
                xmodifier = xmodifier - 1
                if differencey < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    ymodifier = ymodifier + 1
                end
            end
            if differencex < 0 then -- Target is to the E
                ymodifier = ymodifier + 1
                if differencex < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    xmodifier = xmodifier + 1
                end
            elseif differencex > 0 then -- Target is to the W
                ymodifier = ymodifier - 1
                if math.random(1,2) == 2 then
                    xmodifier = xmodifier - 1
                end
            end
        else -- odd
            animationroll = 1
            if differencey > 0 then -- Target it to the N
                xmodifier = xmodifier - 1
                if math.random(1,2) == 2 then
                    ymodifier = ymodifier - 1
                end
            elseif differencey < 0 then -- Target is to the S
                xmodifier = xmodifier + 1
                if differencey < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    ymodifier = ymodifier + 1
                end
            end
            if differencex < 0 then -- Target is to the E
                ymodifier = ymodifier - 1
                if differencex < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    xmodifier = xmodifier + 1
                end
            elseif differencex > 0 then -- Target is to the W
                ymodifier = ymodifier + 1
                if math.random(1,2) == 2 then
                    xmodifier = xmodifier - 1
                end
            end
        end
        missileEffectpos.x = missileEffectpos.x + xmodifier
        missileEffectpos.y = missileEffectpos.y + ymodifier
        Position(playerpos):sendDistanceEffect(missileEffectpos, CONST_ANI_ENERGYBALL)
        addEvent(arcaneDamage, 150, player.uid, var, creature.uid, missileEffectpos, animationroll)
    end
    return true
end

function onCastSpell(player, var)
    local magiclevel = player:getMagicLevel()
    local target = player:getTarget()
    local missileCount = minMissiles + math.floor(magiclevel / 20) -- extra missile every 20 magic levels
    local count = 1
    if target then
        for i = 1, missileCount do
            addEvent(arcaneBolt, 150 * (i - 1), player.uid, var, target.uid, count)
            count = count + 1
        end
    end
    return true
end

This way the error is gone, but you wont get a heads up like no target selected.
cool! thank you man,

i made a small change, and now it works very nice


Lua:
-- Minimum amount of magic missiles
local minMissiles = 2

local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE)

local function arcaneDamage(player, var, target, missileEffectpos, animationroll)
    local player = Player(player)
    local creature = Creature(target)
    if player and creature then
        local level = player:getLevel()
        local magiclevel = player:getMagicLevel()
        local min = (level / 5) + (magiclevel * 0.2) + 5
        local max = (level / 5) + (magiclevel * 0.8) + 12
        combat:setFormula(COMBAT_FORMULA_LEVELMAGIC, 0, -min, 0, -max)
        Position(missileEffectpos):sendDistanceEffect(creature:getPosition(), CONST_ANI_ENERGYBALL)
        if animationroll == 1 then
            creature:getPosition():sendMagicEffect(CONST_ME_PURPLEENERGY)
        end
        combat:execute(player, var)
    end

    return true
end

local function arcaneBolt(player, var, target, count)
    local player = Player(player)
    local creature = Creature(target)
    if player and creature then
        local playerpos = player:getPosition()
        local creaturepos = creature:getPosition()
        local missileEffectpos = Position(playerpos)
        local differencey = playerpos.y - creaturepos.y -- positive = N, negative = S
        local differencex = playerpos.x - creaturepos.x -- positive = W, negative = E
        local ymodifier = 0
        local xmodifier = 0
        local animationroll = 0
        -- Cycle between each side of player depending if missile is even or odd
        if count % 2 == 0 then -- even
            if differencey > 0 then -- Target it to the N
                xmodifier = xmodifier + 1
                if math.random(1,2) == 2 then
                    ymodifier = ymodifier - 1
                end
            elseif differencey < 0 then -- Target is to the S
                xmodifier = xmodifier - 1
                if differencey < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    ymodifier = ymodifier + 1
                end
            end
            if differencex < 0 then -- Target is to the E
                ymodifier = ymodifier + 1
                if differencex < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    xmodifier = xmodifier + 1
                end
            elseif differencex > 0 then -- Target is to the W
                ymodifier = ymodifier - 1
                if math.random(1,2) == 2 then
                    xmodifier = xmodifier - 1
                end
            end
        else -- odd
            animationroll = 1
            if differencey > 0 then -- Target it to the N
                xmodifier = xmodifier - 1
                if math.random(1,2) == 2 then
                    ymodifier = ymodifier - 1
                end
            elseif differencey < 0 then -- Target is to the S
                xmodifier = xmodifier + 1
                if differencey < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    ymodifier = ymodifier + 1
                end
            end
            if differencex < 0 then -- Target is to the E
                ymodifier = ymodifier - 1
                if differencex < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    xmodifier = xmodifier + 1
                end
            elseif differencex > 0 then -- Target is to the W
                ymodifier = ymodifier + 1
                if math.random(1,2) == 2 then
                    xmodifier = xmodifier - 1
                end
            end
        end
        missileEffectpos.x = missileEffectpos.x + xmodifier
        missileEffectpos.y = missileEffectpos.y + ymodifier
        Position(playerpos):sendDistanceEffect(missileEffectpos, CONST_ANI_ENERGYBALL)
        addEvent(arcaneDamage, 150, player.uid, var, creature.uid, missileEffectpos, animationroll)
    end
    return true
end

function onCastSpell(player, var)
    local magiclevel = player:getMagicLevel()
    local target = player:getTarget()
    local missileCount = minMissiles + math.floor(magiclevel / 20) -- extra missile every 20 magic levels
    local count = 1
    if target then
        for i = 1, missileCount do
            addEvent(arcaneBolt, 150 * (i - 1), player.uid, var, target.uid, count)
            count = count + 1
        end
    else
     player:sendTextMessage(MESSAGE_STATUS_SMALL, "You need to select a target.")
  
    return false
    end
    return true
end
 
Last edited:
Hey, idk why but this spell give 0 dmg to monsters. 0 errors ;/ :(

@ Solved
 
Last edited:
i know... the problem just was the flood in the console with this error, but i have solved it.. thx
Post automatically merged:


cool! thank you man,

i made a small change, and now it works very nice


Lua:
-- Minimum amount of magic missiles
local minMissiles = 2

local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE)

local function arcaneDamage(player, var, target, missileEffectpos, animationroll)
    local player = Player(player)
    local creature = Creature(target)
    if player and creature then
        local level = player:getLevel()
        local magiclevel = player:getMagicLevel()
        local min = (level / 5) + (magiclevel * 0.2) + 5
        local max = (level / 5) + (magiclevel * 0.8) + 12
        combat:setFormula(COMBAT_FORMULA_LEVELMAGIC, 0, -min, 0, -max)
        Position(missileEffectpos):sendDistanceEffect(creature:getPosition(), CONST_ANI_ENERGYBALL)
        if animationroll == 1 then
            creature:getPosition():sendMagicEffect(CONST_ME_PURPLEENERGY)
        end
        combat:execute(player, var)
    end

    return true
end

local function arcaneBolt(player, var, target, count)
    local player = Player(player)
    local creature = Creature(target)
    if player and creature then
        local playerpos = player:getPosition()
        local creaturepos = creature:getPosition()
        local missileEffectpos = Position(playerpos)
        local differencey = playerpos.y - creaturepos.y -- positive = N, negative = S
        local differencex = playerpos.x - creaturepos.x -- positive = W, negative = E
        local ymodifier = 0
        local xmodifier = 0
        local animationroll = 0
        -- Cycle between each side of player depending if missile is even or odd
        if count % 2 == 0 then -- even
            if differencey > 0 then -- Target it to the N
                xmodifier = xmodifier + 1
                if math.random(1,2) == 2 then
                    ymodifier = ymodifier - 1
                end
            elseif differencey < 0 then -- Target is to the S
                xmodifier = xmodifier - 1
                if differencey < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    ymodifier = ymodifier + 1
                end
            end
            if differencex < 0 then -- Target is to the E
                ymodifier = ymodifier + 1
                if differencex < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    xmodifier = xmodifier + 1
                end
            elseif differencex > 0 then -- Target is to the W
                ymodifier = ymodifier - 1
                if math.random(1,2) == 2 then
                    xmodifier = xmodifier - 1
                end
            end
        else -- odd
            animationroll = 1
            if differencey > 0 then -- Target it to the N
                xmodifier = xmodifier - 1
                if math.random(1,2) == 2 then
                    ymodifier = ymodifier - 1
                end
            elseif differencey < 0 then -- Target is to the S
                xmodifier = xmodifier + 1
                if differencey < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    ymodifier = ymodifier + 1
                end
            end
            if differencex < 0 then -- Target is to the E
                ymodifier = ymodifier - 1
                if differencex < -1 or math.random(1,2) == 2 then -- Force if 1sqm away due to client perspective
                    xmodifier = xmodifier + 1
                end
            elseif differencex > 0 then -- Target is to the W
                ymodifier = ymodifier + 1
                if math.random(1,2) == 2 then
                    xmodifier = xmodifier - 1
                end
            end
        end
        missileEffectpos.x = missileEffectpos.x + xmodifier
        missileEffectpos.y = missileEffectpos.y + ymodifier
        Position(playerpos):sendDistanceEffect(missileEffectpos, CONST_ANI_ENERGYBALL)
        addEvent(arcaneDamage, 150, player.uid, var, creature.uid, missileEffectpos, animationroll)
    end
    return true
end

function onCastSpell(player, var)
    local magiclevel = player:getMagicLevel()
    local target = player:getTarget()
    local missileCount = minMissiles + math.floor(magiclevel / 20) -- extra missile every 20 magic levels
    local count = 1
    if target then
        for i = 1, missileCount do
            addEvent(arcaneBolt, 150 * (i - 1), player.uid, var, target.uid, count)
            count = count + 1
        end
    else
     player:sendTextMessage(MESSAGE_STATUS_SMALL, "You need to select a target.")
 
    return false
    end
    return true
end
Anybody Can help me with damage? It deal 0 damage. I was trying to solve it but i really dont know
 
Back
Top