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

Solved Want to correctly loop addevent

Apollos

Dude who does stuff
Joined
Apr 22, 2009
Messages
834
Solutions
123
Reaction score
675
Location
United States
[TFS 1.1]
Here's a party healing script I edited, it's working but I want to loop the addevent instead of calling it over and over. Seen some threads on how you have to loop a certain way, so how would you loop in this script.

LUA:
local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_AGGRESSIVE, 0)

local condition = createConditionObject(CONDITION_REGENERATION)
setConditionParam(condition, CONDITION_PARAM_SUBID, 1)
setConditionParam(condition, CONDITION_PARAM_BUFF_SPELL, 1)
setConditionParam(condition, CONDITION_PARAM_TICKS, 2 * 10 * 1000)
setConditionParam(condition, CONDITION_PARAM_HEALTHGAIN, 200)
setConditionParam(condition, CONDITION_PARAM_HEALTHTICKS, 2000)

local function sendEffect(cid, pid)
    doSendMagicEffect(getCreaturePosition(pid), CONST_ME_BUBBLES)
    doSendMagicEffect(getCreaturePosition(cid), CONST_ME_BUBBLES)
end

local baseMana = 120
function onCastSpell(cid, var)
    local pos = getCreaturePosition(cid)

    local membersList = getPartyMembers(cid)
    if(membersList == nil or type(membersList) ~= 'table' or #membersList <= 1) then
        doPlayerSendCancel(cid, "No party members in range.")
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    local affectedList = {}
    for _, pid in ipairs(membersList) do
        if(getDistanceBetween(getCreaturePosition(pid), pos) <= 36) then
            table.insert(affectedList, pid)
        end
    end

    local tmp = #affectedList
    if(tmp <= 1) then
        doPlayerSendCancel(cid, "No party members in range.")
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    local mana = math.ceil((0.9 ^ (tmp - 1) * baseMana) * tmp)
    if(getPlayerMana(cid) < mana) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTENOUGHMANA)
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    if(doCombat(cid, combat, var) ~= true) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTPOSSIBLE)
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    doPlayerAddMana(cid, -(mana - baseMana), FALSE)
    doPlayerAddManaSpent(cid, (mana - baseMana))
    for _, pid in ipairs(affectedList) do
        doAddCondition(pid, condition)
        doAddCondition(cid, condition)
        addEvent(sendEffect, 2000, cid.uid, pid)
        addEvent(sendEffect, 4000, cid.uid, pid)
        addEvent(sendEffect, 6000, cid.uid, pid)
        addEvent(sendEffect, 8000, cid.uid, pid)
    return true
    end
end
 
Solution
i'd still prefer calling the function each time it's needed rather than adding x events to the queue, incase an object becomes null before time of execution
aka if you use addEvent in loops with cid and the player logged out or something, the cid changes/becomes invalid
so once it executes and the cid is invalid you'll get errors, and will still continue because there's nothing to stop it unless you check if cid is valid inside the function (but if you do that you might as well just recall the function each time rather than using a loop)

lets say you have 10 events to send a magic effect to player X
if you use a loop, you add 10 events to the queue to send that effect at different times
if player X logs out, the 10 events will still...
Yeah, that works great. Thanks man, but what exactly does the i=2,8,2 mean?

from here
"That loop will execute something for each value of var from exp1 to exp2, using exp3 as the step to increment var. This third expression is optional; when absent, Lua assumes one as the step value. "
 
from here
"That loop will execute something for each value of var from exp1 to exp2, using exp3 as the step to increment var. This third expression is optional; when absent, Lua assumes one as the step value. "
Is this still a problem in the more recent version? I can't seem to get this type of way to work.
Lua - Use addEvent properly with loops
 
Last edited:
Ended up doing it like this, hopefully I'm not messing anything up with putting in the cid.uid but it was the only way to get it to work.
LUA:
_CONT = {}
function continue(delay, n, ...)
    local func = debug.getinfo(2).func
    if(not _CONT[func]) then
        _CONT[func] = true
        addEvent(repeatContinue, delay, func, delay, n, ...)
    end
end
function repeatContinue(func, delay, n, ...)
    if(n > 1) then
        func(...)
        addEvent(repeatContinue, delay, func, delay, n - 1, ...)
    else
        _CONT[func] = nil
    end
end
LUA:
local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_AGGRESSIVE, 0)

local condition = createConditionObject(CONDITION_REGENERATION)
setConditionParam(condition, CONDITION_PARAM_SUBID, 1)
setConditionParam(condition, CONDITION_PARAM_BUFF_SPELL, 1)
setConditionParam(condition, CONDITION_PARAM_TICKS, 2 * 5 * 1000)
setConditionParam(condition, CONDITION_PARAM_HEALTHGAIN, 200)
setConditionParam(condition, CONDITION_PARAM_HEALTHTICKS, 2000)

function sendEffect(cid, pid)
    if(not isCreature(cid)) then
        return
    end
 
    doSendMagicEffect(getCreaturePosition(pid), CONST_ME_BUBBLES)
    doSendMagicEffect(getCreaturePosition(cid), CONST_ME_BUBBLES)
    -- repeat 4 times (will only repeat 4 times because it count the current call as 1!) each second
    continue(2000, 6, cid, pid)
end

local baseMana = 120
function onCastSpell(cid, var)
    local pos = getCreaturePosition(cid)

    local membersList = getPartyMembers(cid)
    if(membersList == nil or type(membersList) ~= 'table' or #membersList <= 1) then
        doPlayerSendCancel(cid, "No party members in range.")
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    local affectedList = {}
    for _, pid in ipairs(membersList) do
        if(getDistanceBetween(getCreaturePosition(pid), pos) <= 36) then
            table.insert(affectedList, pid)
        end
    end

    local tmp = #affectedList
    if(tmp <= 1) then
        doPlayerSendCancel(cid, "No party members in range.")
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    local mana = math.ceil((0.9 ^ (tmp - 1) * baseMana) * tmp)
    if(getPlayerMana(cid) < mana) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTENOUGHMANA)
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    if(doCombat(cid, combat, var) ~= true) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTPOSSIBLE)
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    doPlayerAddMana(cid, -(mana - baseMana), FALSE)
    doPlayerAddManaSpent(cid, (mana - baseMana))
    for _, pid in ipairs(affectedList) do
        doAddCondition(pid, condition)
        doAddCondition(cid, condition)
        doSendMagicEffect(getCreaturePosition(cid), CONST_ME_MAGIC_BLUE)
        doSendMagicEffect(getCreaturePosition(pid), CONST_ME_MAGIC_BLUE)
        sendEffect(cid.uid, pid)
    return true
    end
end
 
i'd still prefer calling the function each time it's needed rather than adding x events to the queue, incase an object becomes null before time of execution
aka if you use addEvent in loops with cid and the player logged out or something, the cid changes/becomes invalid
so once it executes and the cid is invalid you'll get errors, and will still continue because there's nothing to stop it unless you check if cid is valid inside the function (but if you do that you might as well just recall the function each time rather than using a loop)

lets say you have 10 events to send a magic effect to player X
if you use a loop, you add 10 events to the queue to send that effect at different times
if player X logs out, the 10 events will still execute and you will get 10 errors, unless each time you use stopEvent inside the callback
if you use a function that re-calls itself, everything will stop once cid is invalid
lets say on effect 6 the player logs out, loop will execute 6-10 anyways, but the function that re-calls itself would execute 6 then stop rather than continuing
LUA:
function sendEffect(cid, i, max, delay)
    local player = Player(cid)
    -- check if player still exists with current cid
    if not player then
        return
    end
    player:getPosition():sendMagicEffect(CONST_ME_BUBBLES)
    if i < max then
        addEvent(sendEffect, delay, cid, i+1, max, delay) -- re-call the function in 2 seconds, add +1 to i variable
    end
end
then you can call this with
LUA:
sendEffect(cid, 1, 10, 2000) -- runs like a delayed loop (for i = 1, 10 do) with a 2000ms delay between each execution
 
Solution
Back
Top