• 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 get all items from container (and sub containers)

drakylucas

Intermediate OT User
Joined
Dec 15, 2015
Messages
235
Solutions
7
Reaction score
121
Hello guys!


I'm using otservbr repos (canary) (but it should be pretty similar to TFS master branch)

How can I get a list containing all items from specific container?

just explaining what I want to do:
I want that people can move some items from Store to Depot (and vice-versa) only, not allowing them to move the items to a backpack. This part is already ok:

I made a function:
Lua:
local function isMovingToDepot(toContainer)
    local currentContainer = toContainer
    if currentContainer:isContainer() then
        while currentContainer:getParent():isContainer() do
            currentContainer = currentContainer:getParent()
        end
        print(currentContainer:getName())
        return (string.find(currentContainer:getName(), "depot box") ~= nil)
    end
    return false
end

and I'm checking in player.lua event (onMoveItem):

Code:
local containerTo = self:getContainerById(toPosition.y-64)
    if (containerTo) then
        -- do not allow moving some store items out of depot/store
        if (isInArray(storeItemID, item:getId()) and not isMovingToDepot(containerTo) and not (containerTo:getId() == ITEM_STORE_INBOX)) then
            self:sendCancelMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM)
            return false
        end     
some more code
end


this part works, but the player can still move the store item inside a backpack in depot (which is ok), but then he is able to move this backpack from depot to the ground or to his backpack, and I'm trying to avoid that checking if the item he's moving contains a store item OR if the container he is moving contain a store item inside of it (this is the part I'm being struggle)


Code:
    -- Handle move items to the ground
    if toPosition.x ~= CONTAINER_POSITION then
        -- do not allow moving certain store items to the ground
        if (item:isContainer()) then
            -- I NEED TO EDIT HERE TO CHECK IF, INSIDE THAT CONTAINER (AND ALSO INSIDE ALL CONTAINERS INSIDE OF IT) THERE IS AN ITEM FROM StoreItemID table 
        end
        if (isInArray(storeItemID, item:getId())) then
            self:sendCancelMessage("You can not move this item to the ground.")
            return false
        end
        return true
    end


Thanks in advance!
Post automatically merged:

I could do it :)

in lib/core/table.lua I added that:
Code:
function TableConcat(t1,t2)
    for i=1,#t2 do
        t1[#t1+1] = t2[i]
    end
    return t1
end

and in lib/core/container.lua I made this recursive function:
Code:
function Container.getAllItemsInside(self)
    local itemList = {}
    if self:isContainer() then
        local size = self:getSize()
        for slot=0, size-1 do
            local item = self:getItem(slot)
            if (item) then
                if(item:isContainer()) then
                    itemList = TableConcat(itemList, item:getAllItemsInside())
                end
                itemList[#itemList+1] = item:getId()
            end
        end
    end
    return itemList
end

the output is like this:
{
[1] = 3043,
[2] = 2869,
[3] = 3031,
[4] = 238
}


Now the only part I'm pending is to check if any items from table storeItemID is present in the output of getAllItemsInside function created above :)
Post automatically merged:

Did the check this way:

Code:
    -- Handle move items to the ground
    if toPosition.x ~= CONTAINER_POSITION then
        -- do not allow moving certain store items to the ground
        if (item:isContainer()) then 
            local containerItems = item:getAllItemsInside()
            for i=1, #storeItemID do
                if(table.find(containerItems, storeItemID[i])) then
                    self:sendCancelMessage("You can not move this item to the ground. There are store items inside of it.")
                    return false
                end
            end
        end
        if (isInArray(storeItemID, item:getId())) then
            self:sendCancelMessage("You can not move this item to the ground.")
            return false
        end
        return true
    end


it's working now... but, is there any efficient way of doing this check? I mean, if the backpack has 10000 items, it would iterate over 10000 items every time the player tries to move that container.
 
Last edited:
You should look at TFS in the source files for their: container:getItems() function. Try to copy that because it includes a param for recursive (loop through everything) that makes this code really easy to create. You can see my release in the revscript system to look through all backpack items.
 
Back
Top