#Inventory system

1 messages · Page 1 of 1 (latest)

cerulean blade
#

I have spent around 10 hours debugging an inventory system, specifically the drag and drop. If anybody could tell me where the problem is, that would be very much appreciated.

Problem: Drag and drop, nothing happening when I drag

Code below ⬇️

lofty steppeBOT
#

studio** You are now Level 24! **studio

cerulean blade
#

Entire code ⬇️

#

Intended behaviour when dragging: Just move the item name and data from the original slot to the target slot

cloud sail
#

Too much work to download that ngl just send it in different parts

cloud sail
#

Idk just send full code in different parts

cerulean blade
#
-- Services
local Players            = game:GetService("Players")
local UserInputService   = game:GetService("UserInputService")
local ReplicatedStorage  = game:GetService("ReplicatedStorage")

-- Remote events
local RE_Equip = ReplicatedStorage:WaitForChild("RequestEquip")

-- Player & character
local player = Players.LocalPlayer
player.CharacterAdded:Wait()
local backpack = player:WaitForChild("Backpack")

-- Get GUIs
local screenGui       = player:WaitForChild("PlayerGui"):WaitForChild("InventoryUI")
local inventoryFrame  = screenGui:WaitForChild("InventoryFrame")
local hotbarContainer = screenGui:WaitForChild("HotbarContainer")
local scrollingFrame  = inventoryFrame:WaitForChild("Container")

local hotbarSlotTemplate    = hotbarContainer:WaitForChild("HotbarSlotTemplate")
local inventorySlotTemplate = scrollingFrame:WaitForChild("InventorySlotTemplate")
local maxHotbarSlots, maxInventorySlots = 5, 25

hotbarSlotTemplate.Visible    = false
inventorySlotTemplate.Visible = false

local lastDropUIIndex = nil

local dragging
local dragData = {}  

local hotbarSlots, inventorySlots = {}, {}
for i = 1, maxHotbarSlots do
    local slot = hotbarSlotTemplate:Clone()
    slot.SlotNumber.Text = i
    slot.Visible         = true
    slot.Parent          = hotbarContainer
    hotbarSlots[i]       = slot
end
for i = 1, maxInventorySlots do
    local slot = inventorySlotTemplate:Clone()
    slot.Visible       = true
    slot.Parent        = scrollingFrame
    inventorySlots[i]  = slot
end

local hotbarTools   = {}  
local inventoryOrder = {}
local uiInventory = {}
#
local function buildStackList()
    local stacks = {}
    for _, container in ipairs({ backpack, player.Character }) do
        for _, tool in ipairs(container:GetChildren()) do
            if tool:IsA("Tool") then
                local name = tool.Name
                if not stacks[name] then
                    stacks[name] = { name = name, tool = tool, count = 1 }
                else
                    stacks[name].count += 1
                end
            end
        end
    end

    local t = {}
    for _, data in pairs(stacks) do
        table.insert(t, { name = data.name, tool = data.tool })
    end
    table.sort(t, function(a, b)
        return a.name < b.name
    end)
    return t
end

local function makeGhost(slotFrame)
    
    local ghost = slotFrame:Clone()
    
    local absSize = slotFrame.AbsoluteSize
    ghost.Size        = UDim2.fromOffset(absSize.X, absSize.Y)
    ghost.AnchorPoint = Vector2.new(0, 0)
    
    ghost.BackgroundTransparency = 0.5
    ghost.Active = false
    
    ghost.ZIndex = 100
    ghost.Parent = screenGui
    return ghost
end

local function isOverSlot(x, y, slot)
    local pos, size = slot.AbsolutePosition, slot.AbsoluteSize
    return x >= pos.X and x <= pos.X + size.X
        and y >= pos.Y and y <= pos.Y + size.Y
end

do
    local initial = buildStackList()
    for _, entry in ipairs(initial) do
        table.insert(inventoryOrder, entry)
    end
end
#
local function refreshSlots()

    
    local stackCounts = {} 
    for _, container in ipairs({ backpack, player.Character }) do
        for _, tool in ipairs(container:GetChildren()) do
            if tool:IsA("Tool") then
                local name = tool.Name
                if not stackCounts[name] then
                    stackCounts[name] = { count = 1, prototype = tool }
                else
                    stackCounts[name].count += 1
                end
            end
        end
    end

    for i = 1, maxHotbarSlots do
        local slot = hotbarSlots[i]
        slot.ItemName.Text      = ""
        slot.StackLabel.Text    = ""
        local tool = hotbarTools[i]
        if tool then
            
            local name = tool.Name
            local data = stackCounts[name]
            if data then
                slot.ItemName.Text   = name
                slot.StackLabel.Text = (data.count > 1) and ("x "..data.count) or ""
                stackCounts[name] = nil
            else
                hotbarTools[i] = nil
            end
        else
#
else
            
            for _, entry in ipairs(inventoryOrder) do
                if stackCounts[entry.name] and not table.find(hotbarTools, entry.tool) then
                    hotbarTools[i]       = entry.tool
                    slot.ItemName.Text   = entry.name
                    local count = stackCounts[entry.name].count
                    slot.StackLabel.Text = (count > 1) and ("x "..count) or ""
                    stackCounts[entry.name] = nil
                    break
                end
            end
        end
    end

    
    local filtered, map = {}, {}
    for orderIdx, entry in ipairs(inventoryOrder) do
        if not table.find(hotbarTools, entry.tool) then
            table.insert(filtered, entry)
            map[#filtered] = orderIdx
        end
    end

    visibleInventory = {}
    for _, entry in ipairs(inventoryOrder) do
        if not table.find(hotbarTools, entry.tool) then
            table.insert(visibleInventory, entry)
        end
    end

    
    for uiIdx = 1, maxInventorySlots do
        local slot   = inventorySlots[uiIdx]
        local entry  = visibleInventory[uiIdx]

        if entry then
            
            local count = stackCounts[entry.name].count
            slot.ItemName.Text   = entry.name
            slot.StackLabel.Text = (count > 1) and ("x "..count) or ""
            slot:SetAttribute("hasEntry",  true)
            
            -- Making the slot red (for testing) (Not making it red)
            if uiIdx == lastDropUIIndex then
                slot.BackgroundColor3 = Color3.fromRGB(255, 0, 0)
            else
                
                slot.BackgroundColor3 = Color3.fromRGB( 50,  50, 50)  
            end
        else
            slot.ItemName.Text   = ""
            slot.StackLabel.Text = ""
            slot:SetAttribute("hasEntry",  false)
        end
        
        slot:SetAttribute("uiIdx", uiIdx)
    end
end
#
refreshSlots()
UserInputService.InputBegan:Connect(function(input, gameProcessed)
    if not gameProcessed and input.KeyCode == Enum.KeyCode.B then
        inventoryFrame.Visible = not inventoryFrame.Visible
    end
end)
for _, event in ipairs({ backpack.ChildAdded, backpack.ChildRemoved,
    player.Character.ChildAdded, player.Character.ChildRemoved }) do
    event:Connect(function() task.wait(); refreshSlots() end)
end


local function toggleEquip(slotIndex)
    local tool = hotbarTools[slotIndex]
    if not tool then return end

    RE_Equip:FireServer(tool)
    
    task.delay(0.1, refreshSlots)
end


local SlotsContainer = scrollingFrame 


local function GetSlotUnderMouse()
    local mousePos = UserInputService:GetMouseLocation()
    local guiInset = game:GetService("GuiService"):GetGuiInset() 
    local adjustedPos = mousePos - guiInset

    for _, slot in ipairs(SlotsContainer:GetChildren()) do
        if slot:IsA("GuiObject") then
            local pos = slot.AbsolutePosition
            local size = slot.AbsoluteSize

            local within =
                adjustedPos.X >= pos.X and adjustedPos.X <= pos.X + size.X and
                adjustedPos.Y >= pos.Y and adjustedPos.Y <= pos.Y + size.Y

            if within then
                print(slot.Name)
                slot.BackgroundColor3 = Color3.new(255, 0, 0)
                return slot
            end
        end
    end

    return nil
end
#
local function onSlotInput(slotFrame, containerType, slotIndex)

    
    local function getFilteredInventory()
        local filtered, map = {}, {}
        for orderIdx, entry in ipairs(inventoryOrder) do
            
            if not table.find(hotbarTools, entry.tool) then
                table.insert(filtered, entry)
                map[#filtered] = orderIdx
            end
        end
        return filtered, map
    end

    slotFrame.InputBegan:Connect(function(input)
        if input.UserInputType ~= Enum.UserInputType.MouseButton1 then
            return
        end

        local filteredStart, mapStart = getFilteredInventory()

        if containerType == "inventory" then
            -- exit if empty slot
            if not slotFrame:GetAttribute("hasEntry") then
                print("Empty slot")
                return
            end

            
            dragData.originContainer = "inventory"
            dragData.originUIIndex   = slotIndex
            dragData.entry           = visibleInventory[slotIndex]
            dragData.tool            = dragData.entry.tool
        end


        local startPos    = UserInputService:GetMouseLocation()
        local dragging    = false
        local moveConn, stateConn

        
        moveConn = UserInputService.InputChanged:Connect(function(rbxInput)
            if rbxInput.UserInputType ~= Enum.UserInputType.MouseMovement then
                return
            end
#
local curPos = UserInputService:GetMouseLocation()
            if not dragging and (curPos - startPos).Magnitude > 5 then
                dragging = true

                
                local filtered, map = getFilteredInventory()
                dragData.originContainer = containerType

                if containerType == "inventory" then
                    
                    local invEntry = filteredStart[slotIndex]
                    dragData.entry           = invEntry
                    dragData.tool            = invEntry.tool
                    dragData.originOrderIndex = mapStart[slotIndex]
                else
                    
                    local tool = hotbarTools[slotIndex]
                    if not tool then
                        
                        moveConn:Disconnect()
                        stateConn:Disconnect()
                        return
                    end
                    dragData.tool      = tool
                    dragData.entry     = { name = tool.Name, tool = tool }
                    dragData.originIndex = slotIndex
                end

                dragData.ghostFrame = makeGhost(slotFrame)
            end

            if dragging and dragData.ghostFrame then
                
                dragData.ghostFrame.Position = UDim2.fromOffset(curPos.X, curPos.Y)
            end
        end)
#

fuck

#

discord won't let me send anymore

cerulean blade
#

oh

#

or I can send it on pastebin

terse hazel
#

ask gpt ya hurr

cerulean blade
cerulean blade
terse hazel
#

lol

#

mine said ts

cerulean blade
terse hazel
#

im too lazy to read the code tbh so idk if gpt is being ahh

terse hazel
cerulean blade
cloud sail
#

Yeah this shit do not make sense to me I’m too low level

#

Add prints and find what it’s doing and not doing

hidden ember
hidden ember
cerulean blade
#

hi srry for the late response

cerulean blade
#
stateConn = input:GetPropertyChangedSignal("UserInputState"):Connect(function()
            print("HI")
#

it's printing HI when I drop onto a slot

cerulean blade
cerulean blade
#

Bump

hidden ember
cerulean blade
#

I'll do that later

#

I just need to implement dragging and dropping so that I can complete my inventory system

hidden ember
#

i'd put the breakpoint on that print

cerulean blade
#

But it's just not swapping slot items when dragging and dropping

hidden ember
#

maybe i missed it but i can't spot any a,b=b,a or a temporary variable used in swapping

#

there's a bunch of these that kind-of look like swapping elseif dragData.originContainer == "inventory" and targetContainer == "inventory" then

#

but it's using table.remove then table.insert from the same table? much weird

#

oh there's a swap hotbarTools[dragData.originIndex], hotbarTools[targetIndex] =hotbarTools[targetIndex], hotbarTools[dragData.originIndex]

#

bruh this nesting is so bad

cerulean blade
#

I know 😭

hidden ember
#

you doing really weird things to this table ```lua
local function getFilteredInventory()
local filtered, map = {}, {}
for orderIdx, entry in ipairs(inventoryOrder) do

        if not table.find(hotbarTools, entry.tool) then
            table.insert(filtered, entry)
            map[#filtered] = orderIdx
        end
    end
    return filtered, map
end```
#

poor thing local inventoryOrder = {}

hidden ember
#

your nesting too stronk to properly trace this, breakpoint is your best bet

#

as you step through the code keep watch of the watch variables tab and find where the swap code is getting skipped over then check why

#

then just go from there 👍

cerulean blade
#

Alright will try that, thank you