• 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 doRemoveItem problem

Under Influence

Advanced OT User
Joined
Jul 27, 2009
Messages
152
Reaction score
167
Can some one explain to me why the console gives me: LuaScriptInterface::luaDoRemoveItem(). Item not found

This is a script to make a spell which the player leaves a blue flame and if he uses the same spell within 5 seconds he will be teleported to the flame that was left. Also is it possible to read the timeleft from addEvent, so I can show a message with the cooldown time left?

I am a LUA scripting newbie by the way

Code:
BLUE_FLAME = 1397
function onCastSpell(cid, var)
    local pos = getPlayerPosition(cid)
    local storage = getPlayerStorageValue(cid, BLUE_FLAME)
    local thyitem
 
    if storage > 0 then
        doSendMagicEffect(pos, 10)
   
        doTeleportThing(cid, getThingPos(storage))
        doRemoveItem(storage)
   
        setPlayerStorageValue(cid,BLUE_FLAME,0)
        doSendMagicEffect(getThingPos(storage), CONST_ME_MAGIC_GREEN)
   
    elseif storage == 0 then
        doSendMagicEffect(pos, CONST_ME_POFF)
        doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTPOSSIBLE)
    else
        thyitem = Game.createItem(BLUE_FLAME, 1, pos)
        setPlayerStorageValue(cid,BLUE_FLAME,thyitem)
   
        addEvent(onBackTeleportField, 5 * 1000, pos,cid)
    end
 
end


function onBackTeleportField(position,cid)
    local storage = getPlayerStorageValue(cid, BLUE_FLAME)
 
    if storage > 0 then
        doRemoveItem(storage)
    end
 
    setPlayerStorageValue(cid,BLUE_FLAME,-1)
end
 
Last edited:
Solution
spell script
Lua:
local BLUE_FLAME = 1397
local STORAGE_KEY = 77261

countdownEvents = countdownEvents or {}

function removeFlame(position)
    local tile = Tile(position)
    if tile then
        local flame = tile:getItemById(BLUE_FLAME)
        if flame then
            flame:remove()
        end
    end
end

function countdown(cid, position, i, j)
    local player = Player(cid)
    if not player then
        return
    end
    if i < j then
        local seconds = j - i
        player:sendCancelMessage(string.format("Time left: %s second%s", seconds, (seconds > 1 and "s" or "")))
        countdownEvents[cid] = {id = addEvent(countdown, 1000, cid, position, i+1, j), position = position}
    else
        removeFlame(position)...
Can some one explain to me why the console gives me: LuaScriptInterface::luaDoRemoveItem(). Item not found

This is a script to make a spell which the player leaves a blue flame and if he uses the same spell within 5 seconds he will be teleported to the flame that was left. Also is it possible to read the timeleft from addEvent, so I can show a message with the cooldown time left?

I am a LUA scripting newbie by the way

Code:
BLUE_FLAME = 1397
function onCastSpell(cid, var)
    local pos = getPlayerPosition(cid)
    local storage = getPlayerStorageValue(cid, BLUE_FLAME)
    local thyitem
 
    if storage > 0 then
        doSendMagicEffect(pos, 10)
 
        doTeleportThing(cid, getThingPos(storage))
        doRemoveItem(storage)
 
        setPlayerStorageValue(cid,BLUE_FLAME,0)
        doSendMagicEffect(getThingPos(storage), CONST_ME_MAGIC_GREEN)
 
    elseif storage == 0 then
        doSendMagicEffect(pos, CONST_ME_POFF)
        doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTPOSSIBLE)
    else
        thyitem = Game.createItem(BLUE_FLAME, 1, pos)
        setPlayerStorageValue(cid,BLUE_FLAME,thyitem)
 
        addEvent(onBackTeleportField, 5 * 1000, pos,cid)
    end
 
end


function onBackTeleportField(position,cid)
    local storage = getPlayerStorageValue(cid, BLUE_FLAME)
 
    if storage > 0 then
        doRemoveItem(storage)
    end
 
    setPlayerStorageValue(cid,BLUE_FLAME,-1)
end
Lua:
doRemoveItem(uid[, count])
getPlayerStorageValue(uid, key)
doPlayerSetStorageValue(uid, key, newValue)
Lua:
thyitem = Game.createItem(BLUE_FLAME, 1, pos)
setPlayerStorageValue(cid,BLUE_FLAME,thyitem)
Lua:
local storage = getPlayerStorageValue(cid, BLUE_FLAME)
doRemoveItem(storage)

The problem lies within how you are using player storage values.
I believe TFS 1.0+ allows you to create storages using strings, but I'm uncertain exactly how that translates when using game.createItem.
If I were to take a guess, it is probably taking the (UID) UniqueID number of the object that is being created and putting that into the player storage.
Thus, your problem.
When you are removing the item, you need to know the UID of the item at the moment you are trying to remove it.
UID's are constantly changing. They are not a static number.
Because of their erratic nature, you need to find the item you are looking for each and every time you want to manipulate it.
In your case you are using a UID that no longer exists, and attempting to remove it which provides you with the error 'item not found'.

One way to solve the problem is to track the position of the player, and then see if the 'blue flame' is still on that square when they are recasting the spell to return.
You'll want to attribute some special attribute to the flame, so that you can check and remove the flames of a specific player, in case multiple players use the spell on the same tile.

As for your second question.. it's unclear how you want to provide the information to the player.

If you script the blue flame to expire automatically after 5 seconds, and the player can recast the ability multiple times to return to the flame, then I'd simply add a storage to the player and show them the milliseconds they have left.
Lua:
os.mtime()

If you want it to automatically count down, I'd create a looping addEvent.
It's not going to be perfectly accurate down to the millisecond as the script itself requires time to complete, but over a short span of 5 seconds, it's going to be accurate enough for your purposes. (within 0-1 milliseconds I'd assume.)
Simple example of a looping addEvent.
Lua:
local function simple_loop(amount)
    print(amount)
    if amount > 0 then
        addEvent(simple_loop, 1000, amount - 1)
    end
end

function onCastSpell(cid, var)
    addEvent(simple_loop, 0, 5)
    return true
end

Side Note: on TFS 1.0+ bandying player data around inside of addEvents like you did in your above script is apparently dangerous and can crash servers, or so I've been told.
You'd have to ask someone smarter then myself to explain it to you as I simply can't grasp the reasoning behind the concept.
Just figured I'd pass on the advice.
 
spell script
Lua:
local BLUE_FLAME = 1397
local STORAGE_KEY = 77261

countdownEvents = countdownEvents or {}

function removeFlame(position)
    local tile = Tile(position)
    if tile then
        local flame = tile:getItemById(BLUE_FLAME)
        if flame then
            flame:remove()
        end
    end
end

function countdown(cid, position, i, j)
    local player = Player(cid)
    if not player then
        return
    end
    if i < j then
        local seconds = j - i
        player:sendCancelMessage(string.format("Time left: %s second%s", seconds, (seconds > 1 and "s" or "")))
        countdownEvents[cid] = {id = addEvent(countdown, 1000, cid, position, i+1, j), position = position}
    else
        removeFlame(position)
        player:teleportTo(position)
        player:setStorageValue(STORAGE_KEY, -1)
    end
end

function onCastSpell(creature, variant)
    local player = Player(creature)
    if not player then
        return false
    end
    local cid = player:getId()
    local position = player:getPosition()
    local storage = player:getStorageValue(STORAGE_KEY)
    if storage == -1 then
        Game.createItem(BLUE_FLAME, -1, position)
        countdown(cid, position, 1, 6)
        player:setStorageValue(STORAGE_KEY, 1)
    elseif storage == 1 then
        local event = countdownEvents[cid]
        if event then
            stopEvent(event.id)
            teleportBack(player, event.position)
        end
        player:setStorageValue(STORAGE_KEY, -1)
    end
    return true
end

logout.lua in creaturescripts
Lua:
function onLogout(player)
    local playerId = player:getId()
    if nextUseStaminaTime[playerId] then
        nextUseStaminaTime[playerId] = nil
    end
    local event = countdownEvents[playerId]
    if event then
        removeFlame(event.position)
        player:setStorageValue(77261, -1)
    end
    return true
end
 
Last edited:
Solution
xeraphus he won't learn if you do it for him and explain nothing. lol

Oh well. I'm out of here.
 
Thanks for the code, it really helped me understand how to do it, however the console was giving me errors, using that kind of definition, and I wanted to keep the state machine where the player can only use the spell again 5 seconds after the initial cast, showing the time left in case he uses on the spell before the 5 seconds.

This is a very nice spell to do some tricks in PVP and to do some kind of stairhopping :)

Final code:

Code:
local BLUE_FLAME = 1397
local STORAGE_KEY = 77261
countdownEvents = countdownEvents or {}

function removeFlame(position)

    local flame = getTileItemById(position, BLUE_FLAME)
    if flame then
        doRemoveItem(flame.uid)
    end
 
end

function countdown(cid, position, i)
    if not Player(cid) then
        return
    end
    if i > 0 then
        countdownEvents[cid] = {id = addEvent(countdown, 1000, cid, position, i-1), position = position,seconds=i}
    else
        if getPlayerStorageValue(cid,STORAGE_KEY) == 1 then
            removeFlame(position)
        end
        setPlayerStorageValue(cid,STORAGE_KEY,-1)
    end
end

function onCastSpell(cid, variant)
    if not Player(creature) then
        return false
    end

    local position = getPlayerPosition(cid)
    local storage = getPlayerStorageValue(cid,STORAGE_KEY)
 
    if storage == -1 then
        Game.createItem(BLUE_FLAME, 1, position)
        countdown(cid, position, 5)
        setPlayerStorageValue(cid,STORAGE_KEY,1)
    elseif storage == 0 then
        local event = countdownEvents[cid]
        if event then
            doSendMagicEffect(position, CONST_ME_POFF)
            doPlayerSendCancel(cid,string.format("Time left: %s second%s", event.seconds, (event.seconds > 1 and "s" or "")))
        end
     
        return false
    elseif storage == 1 then
        local event = countdownEvents[cid]
        if event then
            doSendMagicEffect(position, 10)
            doTeleportThing(cid,event.position)
            doSendMagicEffect(event.position, CONST_ME_MAGIC_GREEN)
            removeFlame(event.position)
            setPlayerStorageValue(cid,STORAGE_KEY,0)
        end
     
    end
 
    return true
end
 
Last edited:
Back
Top