#need to iterate through multiple subtables in a very annoying and complicated way

1 messages · Page 1 of 1 (latest)

drifting hazel
#

I have no clue how to explain this but ill do my best. i have a list filled with subtables that go like this {Instance, Name, Amount}, and all of those are set into a single table. i need to iterate through these and only select the first instance of every subtable, so if i had {Slot, "Potion", 1}, {Slot, "Potion", 1}, {Slot, "Potion", 1}, {Slot, "Potion", 1}, {Slot, "Potion", 2}, {Slot, "Potion", 2}, {Slot, "Potion", 2}, {Slot, "Potion", 2}, it would only select the first {Slot, "Potion", 1} and {Slot, "Potion", 2} and then send those two subclasses to a seperate table. PLEASE GOD HELP ME I CANT FIGURE THIS OUT FOR THE LIFE OF ME

local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local function findFirstByName(targetName, tbl)
    for i, subtable in ipairs(tbl) do
        if subtable.name then
            return subtable
        end
    end
    return nil
end

local InventoryHolder = script.Parent:WaitForChild("InventoryHolder")
local InventorySlots = InventoryHolder:WaitForChild("InventorySlots")
local slots = {}
local items = {}

local itemsFolder = ReplicatedStorage:WaitForChild("Items")
local potion = itemsFolder:WaitForChild("Potion")

-- {Instance, ItemType, Amount, SlotSize}
-- 6, 12, 13, 14

ReplicatedStorage:WaitForChild("UpdateInventory").OnClientEvent:Connect(function(inventory)
    
    -- SET UP SLOT TABLE
    for i, label in InventorySlots:GetChildren() do
        if label:IsA("TextButton") then
            table.insert(slots, {label, name = nil, amount = nil})
        end
    end
    
    for i, slot in slots do
        slot["name"] = inventory[i]["name"]
        slot["amount"] = inventory[i]["amount"]
        
        if slot["name"] == "" then -- if slot is empty dont do anything
            slot[1].Text = i
        elseif slot["name"] ~= "" and slot["name"] then
            
            slot[1].Text = slot["name"]


            
        end
        
        
        slot[1].MouseButton1Click:Connect(function()
            if slot["amount"] then
                print(slot["amount"])
                
                
            end
        end)
        
    end
    
    
    
    -- SPAWN ITEMS INTO INVENTORY
    
    -- PRINT
    print("Slots:", slots)
    print("Inventory:", inventory)
    print("Items:", items)
    
    
end)
tender fable
#

have you considered making it into a set instead of repeating them

#

that would be far more performant in both speed and memory and would make your situation much simpler

#

The item is the key and the number of that item is the value, for example

drifting hazel
tender fable
#

tables

drifting hazel
#

ive never used sets

tender fable
#

well for your situation you would only need some kind of an identifier for a particular item to use as a key

#

And then you would increment the value related to that key when gaining an item of that type

#

adding new items does not take any shifting because you are using a table's hashmap properties when using non-numeric keys such as tables

drifting hazel
#

this is the end goal of what im trying to accomplish, so amount value in the id of a specific item you have in your inventory so duplicates would be 1, 2, 3 but then seperate items would be a different set of numbers.

#

each subtable is the location of each part on the table

tender fable
#

if you're just looking for a way to map a matrix onto another matrix, you really could just use buffers

drifting hazel
#

ive got no clue what a buffer is let me look at documentation rq

tender fable
#

you have a 6x6 grid, which means the buffer would be 36 in length

you would calculate the offset in the buffer as (grid y) * 6 + (grid x) % 6 and include any offset related to centering the item on your cursor

from there you would just need to check if any of the slots overlap (are already set to 1, for example) and cancel if they do, or add one to each if they don't

drifting hazel
#

alright it seems i am officially 100% lost for the first time since i started scripting i have no clue what im looking at

#

oh nvm

tender fable
#

you could also make the amount of bytes up to 8 times smaller but that is a bit of a hassle imo

drifting hazel
#

would my original problem be any easier using these

tender fable
#

"easier" depends on if you're comfortable with what is essentially an array (buffer)

#

it is concise and makes for a very small memory footprint in datastores, but if you do prefer to use tables then ..

drifting hazel
#

i dont know how using essentially the same thing but with less data would make problem solving it easier

tender fable
#

the way you are doing it now is with tables as slots, right

drifting hazel
#

yes

#

i can show you the grid rq

#

this is what it looks like in testing with that code up there

#

i havent made them movable in this one yet

tender fable
#

if you use a buffer, you can effectively avoid using tables at all and instead use a sort of bit mask (numerical value, by the way) for every item (which you would have to store per item)

drifting hazel
#

this is like the resident evil inventory btw idk if i got that across

tender fable
#

You want to be able to find it to drag it with your mouse, is that right

#

why would you need to sort

drifting hazel
#

yes but it would also drag the rest of those grids around them

tender fable
#

right

drifting hazel
tender fable
#

you shouldn't need to iterate either if you can just index it a certain way

#

which you can do by its (unique, btw) bitmask

drifting hazel
#

so i can just select a certain point in the data based on where the person clicks on the grid?

#

and the data would correspond to the selected item

#

lemme learn more about these rq

drifting hazel
#

i feel like im just going to have the same problem here where i cant get the specific slot that i want

tender fable
#

This is basically what I am suggesting:

Consider your grid as a matrix of 0s and 1s

This is an empty grid of 4x2
{
0,0,0,0,
0,0,0,0
}

if you were to drop an item of dimensions 2, 1 on the position (x=0,y=1) in the grid, it would look like this
{
0,0,0,0,
1,1,0,0
}

Because this is expressed as bits, you can use this mask as the index/key for your item in a table or array of appropriate size (you're better off with a table for this part or an array if you do base 2 logarithmic transformation). To look up your item from the table, you must first find where your cursor is in the grid and iterate like so:

0,0,0,0,
1,1,0,0 -- start here because your cursor is at x=1,y=1.

Index the table (with keys as masks, values as items) with the corresponding value 4 (because the bits up to this cursor are both 0s and the cursor's bit is 1, making 100 in binary which is 4) to see if it matches with a valid item (not nil). It doesn't, so we move one bit to the left.

0,0,0,0,
1,1,0,0 -- we are here now

We do the same thing as before, but since there is a value that matches 12 (binary is 1100, decimal is 12) in the table, we return the value which is a valid item.

#

I am very shit at improvising a lesson so if this doesn't work then I'm sorry

drifting hazel
#

yeah thats what i was thinking you were getting at

tender fable
#

come to think of it, you wouldn't need to worry about the other bits, just the one at the cursor and its offset, so it would be 8, not 12

that way it doesn't mess up if there are more than one item in there

just kidding because if there is a 2 by 2 and a 1 by 1 this doesn't work
0,1,1,0
1,1,1,0 -- selects the 1 by 1 on the bottom left instead of the 2 by 2

tender fable
drifting hazel
#

i was thinking of having it when you hover over a button it selects the corresponding offset in the buffer

ornate boneBOT
#

studio** You are now Level 9! **studio

drifting hazel
#

but then i still have the problem where i dont know where the item root is or where the spawn it

#

on the grid i mean

tender fable
#

Well in my example you just iterate, but if you wanted to store that somewhere it becomes a bit more complicated

#

idk how a button would work well there aside from existing as the starting place

drifting hazel
#

WAIT I HAD AN IDEA

drifting hazel
#

nevermind

terse sentinel
#

Did i get this right:
You have a table filled with objects.
Each object is represented by a table
Each object has a shape that can fill inventory.
You want to iterate through objects or iterate through the shape?

#

@drifting hazel

drifting hazel
#

YES YES YES

#

i can actually tell you understand

#

my problem is that i cant create an anchorpoint for the item object to spawn onto the inventory

#

well ive gotten this but now that ive done this i cant have multiple objects of the same type on the inventory and select them individually

#

potion1 is the anchorpoint btw

terse sentinel
#

I am struggling to read the code. Could you like edit your original message so that you add "lua"?
looks like this:
```lua
--your code in here
```

drifting hazel
#

oh ok

terse sentinel
#

Sorry about that 😅

drifting hazel
#

gimme a sec ill give the updated one

#
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

function collidesWith(gui1, gui2)
    local gui1_topLeft = gui1.AbsolutePosition
    local gui1_bottomRight = gui1_topLeft + gui1.AbsoluteSize

    local gui2_topLeft = gui2.AbsolutePosition
    local gui2_bottomRight = gui2_topLeft + gui2.AbsoluteSize

    return ((gui1_topLeft.x < gui2_bottomRight.x and gui1_bottomRight.x > gui2_topLeft.x) and (gui1_topLeft.y < gui2_bottomRight.y and gui1_bottomRight.y > gui2_topLeft.y))
end

local function findFirstByName(targetName, tbl)
    for i, subtable in ipairs(tbl) do
        if subtable.name then
            return subtable
        end
    end
    return nil
end

local InventoryHolder = script.Parent:WaitForChild("InventoryHolder")
local InventorySlots = InventoryHolder:WaitForChild("InventorySlots")
local slots = {}
local items = {}

local itemsFolder = ReplicatedStorage:WaitForChild("Items")
local potion = itemsFolder:WaitForChild("Potion")

-- {Instance, ItemType, Amount, SlotSize}
-- 6, 12, 13, 14

ReplicatedStorage:WaitForChild("UpdateInventory").OnClientEvent:Connect(function(inventory)
    
    -- SET UP SLOT TABLE
    for i, label in InventorySlots:GetChildren() do
        if label:IsA("TextButton") then
            table.insert(slots, {label, name = inventory[i - 1]["name"], amount = inventory[i - 1]["amount"]})
        end
    end
    
    for i, slot in ipairs(slots) do
        if slot.name then
            slot[1].Text = slot.name .. tostring(slot.amount)
        end
        
        if slot.amount == 1 then
            
            local item = potion:Clone()
            item.Parent = InventoryHolder
            
            local desiredAbsolutePosition = slot[1].AbsolutePosition -- some Vector2
            local relativePosition = desiredAbsolutePosition - item.Parent.AbsolutePosition
            item.Position = UDim2.fromOffset(relativePosition.X + 27, relativePosition.Y + 26)
            
        end
        
        
        slot[1].MouseButton1Click:Connect(function()
            if slot["name"] then
                print("yes")
            end
        end)
    end
    
    task.wait(1)
    -- PRINT
    print("Slots:", slots)
    print("Inventory:", inventory)
    
    
end)
#

there ya go

terse sentinel
#

thanks ill check

drifting hazel
#

im not really sure why the other guy was suggesting buffers, i think he thought i had a problem with the moving the item around part or actually just importing the location data onto the grid when i had already successfully done thta

terse sentinel
#

Also wondering, what is InventoryHolder, frame? and inventory slots is uigrid layout or smth? i do not know UI too well

#

Contrary to what you think i dont "get this" but i think i can figure out as soon as i know what youre trying and how your data is structured

drifting hazel
#

inventory holder is just to prevent ui weirdness and make it waaaay easier to position the item onto the grid, also ignore the disabled script it was from me testing

#

because absoluteposition is really weird

#

and then theres also a uigrid inside of the actual inventoryslots thing so i cant just clone the item into that

#

oh yeah this is also what the slots table looks like

#

or the actual template data

terse sentinel
#

I didnt quite understand this. Probably due to not knowing Items or potion, and it seems there are other scripts too that might influence when im testing.
but heres my thoughts how to structure things.
If you have a 6x6 grid, you can label them from top to right, downwards.
e.g.

1  2  3  4  5  6
7  8  9  10 11 12
``` and so on
Then each item can be something like this:
```lua
local items = {gridPosition, itemId, itemName, value, shape}
--Then you can just store one table for items, and one table for the actual grid
local grid = {items[index], displayName, displayValue}
--also having an "empty" template to fill the grid that also looks like this
{gridPosition, itemId, itemName, value, shape}

Then to store an item, you just store the index of the item, within the items table. So when you click a slot, it takes you to the correct item. If thats helpful.

If not and you wanna use your current method, and are struggling with not being able to use the same type, is to store a unique ID for each item just to make sure they dont match

#

shape could just be a table aswell with the relative positions compared to the root of the item
where you do -6 to put in slot one above, +6 to put down below, and -1 / +1 to put to the sides

drifting hazel
terse sentinel
#

In the grid, then e.g. slot 9,10,11,4 would be filled. Then clicking any of those gives you the same ItemIndex automatically. So no need to iterate

terse sentinel
#

Or like what you put them as

drifting hazel
#

what would the item[index] be in the grid table im confused on that

terse sentinel
#

sorry my bad, I shouldve just done itemIndex : Number

#

its the index of the item in the inventory

#

My point is keeping inventory and grid seperate, but relational

drifting hazel
#

so the items table would be more like {{}}

#

oops

terse sentinel
#

Yeah

drifting hazel
#

multiple subtables in that?

terse sentinel
#

assume one item withing items looks like this: {gridPosition, itemId, itemName, value, shape}

drifting hazel
#

ok yeah that makes more sense

terse sentinel
#

So yeah but its easier to think of them like objects

#

easier if you turn into set aswell i think. More "objecty"

drifting hazel
#

yes but now i still have the same problem of how do i clone the item onto the grid at the correct position

#

and then have it still fill out the spots on the grid that its on

terse sentinel
#

Are you able to get the grid slot number if you hover over it with your mouse? i assumed thats what the relativePosition did

drifting hazel
#

no relativeposition just puts the cloned item onto the grid

#

its a weird equation thing to fix absoluteposition in ui

terse sentinel
#

How are you able to place the slots then without their index?

drifting hazel
#

and then cloned the item to position 1

terse sentinel
#

like when you moved around in the video*
Cause if you can get the currentslot youre hovering over, then i know how to do the placement

terse sentinel
#

ill check wether i can get info from a slot

drifting hazel
#

the video where i move things around is a completely seperate script

#

im sorry i didnt mention that i forgot i sent it

terse sentinel
#

no problem. but ill try tell you if it makes sense

drifting hazel
#

in the moving one i cant put two items on the grid and i start with the item moving in my hand

terse sentinel
#

So when you first place an item, you have the shape in item table. If you get the currentslot you're hovering over, when filling, then you can do something like this:

local grid = {1,2,3....etc}
local items = {...}
local uniqueId
local function fillSlot(slotNumber, item, itemIndex)
  grid[slotNumber] = {
    ["ItemIndex"] = itemIndex,
    ["DisplayName"] = item.Name,
    ["DisplayValue"] = item.Value
    }
end
local function placeItem(currentSlot, item, itemIndex)
  local gridSlots = {}
  for _, offset in item.Shape do
    table.insert(gridSlots,currentSlot+offset)
  end
  for _, slot in gridSlots do
    fillSlot(slot, item, itemIndex)
  end
end
--i assume the server gives the items to the clients
getItem.OnClientEvent:connect(function(item)
  local newId = uniqueId()
  local currentSlot = mouseGetCurrentSlot()
  placeItem(currentSlot, item, newId)
end)

something like this in spirit. Sorry about delay, boss came for a short talk

drifting hazel
#

dont worry about the delay i can feel this getting closer to being solved

#

its like on the tip of my brain

#

i think this will help a lot though thanks

#

im gonna clear this script to get a fresh start and hopefully that will be it

terse sentinel
#

Wish you best of luck

drifting hazel
#

the only problem is that the offset is going to be different based on where you put it so i think i might have to learn some math shit with x and y axis on a matrix

drifting hazel