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

TFS 1.X+ Help with this script: Treasure Action.

Udun

Well-Known Member
Joined
Jan 5, 2012
Messages
192
Solutions
1
Reaction score
67
Hi guys! I'm having problems with this script. TFS 1.2, Tibia 10.98
Should do this:
The player use a shovel (or any item of your election) and you can make a hole in any ground (grass, desert, snow etc.) could be a custom "hole" item, and you can hide items inside like a depot, then after a X time the hole will decay to the gound that was before and the char can back later and take the buried stuff, it means, all the grounds of the server could be a potential depot or a place to hide things (lootbags, weapons, corpses, gp, etc) without need to go to the dp

Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)
  if isInArray({4526}, itemEx.itemid) then -- object ground ID that triggers the action
    local player = Player(cid)
    local storageKey = "holeStorage_" .. itemEx.uid
    if player:getStorageValue(storageKey) ~= 1 then
      -- create a new container and put it inside the hole
      local container = player:getPlayerSlotItem(2594) -- container ID
      if not container then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "There's not enough room for more items.")
        return true
      end
      for i = 1, container:getCapacity() do
        container:addItem(10) -- add the ammount if slots inside the container
      end
      doTransformItem(itemEx.uid, 8249) -- hole ID
      doTileAddItem(fromPosition, container:getId(), 1, container) -- puts container inside the hole
      player:setStorageValue(storageKey, container:getId()) -- storage ID of cointainer in the container chatacter system
      addEvent(function()
        -- Recover the objects in the container and eliminate it
        local holeContainer = Container(player:getStorageValue(storageKey))
        if holeContainer then
          for _, item in ipairs(holeContainer:getItems()) do
            player:addItemEx(item, false) -- Add the objects to the character
          end
          holeContainer:remove()
        end
        -- Return the hole to a normal gound item and eliminates the storage
        doTransformItem(itemEx.uid, 4526) -- original ground ID
        local holeItems = getTileItemsByType(fromPosition, ITEM_TYPE_HOLE)
        for i = 1, #holeItems do
          local item = holeItems[i]
          doSendMagicEffect(item:getPosition(), CONST_ME_POFF) -- effect when hole dissapear
          item:remove()
        end
        player:setStorageValue(storageKey, -1)
      end, 10000) -- Milisenconds "10000 = 10 seconds to the hole gets closed
      return true
    else
      player:sendTextMessage(MESSAGE_STATUS_SMALL, "You already have created a hole here. Use the shovel again to recover your objects.")
    end
  end
  return true
end

Thanks alot!
 
Last edited:
Hi guys! I'm having problems with this script. TFS 1.2, Tibia 10.98
Should do this:
The player use a shovel (or any item of your election) and you can make a hole in any ground (grass, desert, snow etc.) could be a custom "hole" item, and you can hide items inside like a depot, then after a X time the hole will decay to the gound that was before and the char can back later and take the buried stuff, it means, all the grounds of the server could be a potential depot or a place to hide things (lootbags, weapons, corpses, gp, etc) without need to go to the dp
Ok, there are couple things wrong with your script.

I'll start with the major issue with your addEvent - it will cause your server to crash, because you are passing a player and item references, while these could have been already removed from the game.

Here, corrected version
Lua:
    local playerId = player:getId()
    addEvent(function()
        local player = Player(playerId)
        if not player then
            return
        end

        -- Recover the objects in the container and remove it
        local holeContainer = Container(player:getStorageValue(storageKey))
        if holeContainer then
            for _, item in ipairs(holeContainer:getItems()) do
                -- You need to find the tile again (using position?) because the item might have been removed
                -- player:addItemEx(item, false) -- Add the objects to the character
            end
            holeContainer:remove()
        end

        -- FIXME doTransformItem(itemEx.uid, 4526) -- original ground ID4

        local holeItems = getTileItemsByType(fromPosition, ITEM_TYPE_HOLE)
        for i = 1, #holeItems do
            local item = holeItems[i]
            item:getPosition():sendMagixEffect(CONST_ME_POFF) -- effect when hole dissapear
            item:remove()
        end

        player:setStorageValue(storageKey, -1)
    end, 10 * 1000)

Second of all, by default, you can only use numerical storage keys, while you are trying to check a string one.
Third of all, As Bjarne Stroustrup suggests himself, you should first handle the corner cases.
This way you can get rid of the nesting, which makes your code very hard to read.

A cool simple watch

Here, slightly refactored version to get you going.
Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition)
    if not table.contains({ 4526 }, itemEx.itemid) then -- object ground ID that triggers the action
        return true
    end

    local player = Player(cid)

    local storageKey = "holeStorage_" .. itemEx.uid
    if player:getStorageValue(storageKey) == 1 then
        player:sendTextMessage(MESSAGE_STATUS_SMALL,
            "You already have created a hole here. Use the shovel again to recover your objects.")
        return true
    end

    -- create a new container and put it inside the hole
    local container = player:getPlayerSlotItem(2594) -- container ID
    if not container then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "There's not enough room for more items.")
        return true
    end

    -- add the ammount if slots inside the container
    for _ = 1, container:getCapacity() do
        container:addItem(10)
    end

    itemEx:transform(8249)
    player:setStorageValue(storageKey, container:getId())

    -- Are you are trying to fit the container inside the same container?
    -- doTileAddItem(fromPosition, container:getId(), 1, container) -- puts container inside the hole

    local playerId = player:getId()
    addEvent(function()
        local player = Player(playerId)
        if not player then
            return
        end

        -- Recover the objects in the container and remove it
        local holeContainer = Container(player:getStorageValue(storageKey))
        if holeContainer then
            for _, item in ipairs(holeContainer:getItems()) do
                -- You need to find the tile again because the item might have been removed
                -- player:addItemEx(item, false) -- Add the objects to the character
            end
            holeContainer:remove()
        end

        -- FIXME doTransformItem(itemEx.uid, 4526) -- original ground ID

        local holeItems = getTileItemsByType(fromPosition, ITEM_TYPE_HOLE)
        for i = 1, #holeItems do
            local item = holeItems[i]
            item:getPosition():sendMagixEffect(CONST_ME_POFF) -- effect when hole dissapear
            item:remove()
        end

        player:setStorageValue(storageKey, -1)
    end, 10 * 1000)

    return true
end
This obviously is not working, but will be a good start.

To actually achieve your goal of hiding items in tiles, you will need to create a table of positions (keys) and containers (values), to which you'll be moving the items.
Then, upon user action, you'll need to check the table and either create the container, populate it with your items, or move the items out of the container, remove it and clear the key.

Good luck
 
Last edited:
Ok, there are couple things wrong with your script.

I'll start with the major issue with your addEvent - it will cause your server to crash, because you are passing a player and item references, while these could have been already removed from the game.

Here, corrected version
Lua:
    local playerId = player:getId()
    addEvent(function()
        local player = Player(playerId)
        if not player then
            return
        end

        -- Recover the objects in the container and remove it
        local holeContainer = Container(player:getStorageValue(storageKey))
        if holeContainer then
            for _, item in ipairs(holeContainer:getItems()) do
                player:addItemEx(item, false) -- Add the objects to the character
            end
            holeContainer:remove()
        end

        -- FIXME doTransformItem(itemEx.uid, 4526) -- original ground ID
        -- You need to find the tile again (using position?) because the item might have been removed

        local holeItems = getTileItemsByType(fromPosition, ITEM_TYPE_HOLE)
        for i = 1, #holeItems do
            local item = holeItems[i]
            item:getPosition():sendMagixEffect(CONST_ME_POFF) -- effect when hole dissapear
            item:remove()
        end

        player:setStorageValue(storageKey, -1)
    end, 10 * 1000)

Second of all, by default, you can only use numerical storage keys, while you are trying to check a string one.
Third of all, As Bjarne Stroustrup suggests himself, you should first handle the corner cases.
This way you can get rid of the nesting, which makes your code very hard to read.

A cool simple watch

Here, slightly refactored version to get you going.
Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition)
    if not table.contains({ 4526 }, itemEx.itemid) then -- object ground ID that triggers the action
        return true
    end

    local player = Player(cid)

    local storageKey = "holeStorage_" .. itemEx.uid
    if player:getStorageValue(storageKey) == 1 then
        player:sendTextMessage(MESSAGE_STATUS_SMALL,
            "You already have created a hole here. Use the shovel again to recover your objects.")
        return true
    end

    -- create a new container and put it inside the hole
    local container = player:getPlayerSlotItem(2594) -- container ID
    if not container then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "There's not enough room for more items.")
        return true
    end

    -- add the ammount if slots inside the container
    for _ = 1, container:getCapacity() do
        container:addItem(10)
    end

    itemEx:transform(8249)
    player:setStorageValue(storageKey, container:getId())

    -- Are you are trying to fit the container inside the same container?
    -- doTileAddItem(fromPosition, container:getId(), 1, container) -- puts container inside the hole

    local playerId = player:getId()
    addEvent(function()
        local player = Player(playerId)
        if not player then
            return
        end

        -- Recover the objects in the container and remove it
        local holeContainer = Container(player:getStorageValue(storageKey))
        if holeContainer then
            for _, item in ipairs(holeContainer:getItems()) do
                player:addItemEx(item, false) -- Add the objects to the character
            end
            holeContainer:remove()
        end

        -- FIXME doTransformItem(itemEx.uid, 4526) -- original ground ID
        -- You need to find the tile again because the item might have been removed

        local holeItems = getTileItemsByType(fromPosition, ITEM_TYPE_HOLE)
        for i = 1, #holeItems do
            local item = holeItems[i]
            item:getPosition():sendMagixEffect(CONST_ME_POFF) -- effect when hole dissapear
            item:remove()
        end

        player:setStorageValue(storageKey, -1)
    end, 10 * 1000)

    return true
end
This obviously is not working, but will be a good start.

To actually achieve your goal of hiding items in tiles, you will need to create a table of positions (keys) and containers (values), to which you'll be moving the items.
Then, upon user action, you'll need to check the table and either create the container, populate it with your items, or move the items out of the container, remove it and clear the key.

Good luck
Thanks alot for your answer. I think this system would be very cool to implement in general on the ot community. I've been chasing it for long time. Sadly I'm very noob in coding. Can't make it work.
 
Back
Top