Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Inventory System issue with dropping item when not in Hotbar or Slot, how shall I fix this?

so I am making an inventory system for a game and yeah I know this is downright spaghetti code but I currently have the problem where when I drop the object without being in a slot or Hotbar it goes to the slot to the last one when it should go to the first one available I have a for loop in place on line 71 but that doesn't work. Anyway of flipping it around? The script is a Localscript and is located within an ImageButton

GIf to show what I mean by "drop": https://gyazo.com/041c291b5d6c3436870ebfd20d9cc439

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

local gui = script.Parent

local dragging
local dragInput
local dragStart
local startPos
local startLoc = gui.Position
local inHotbar = false
local inSlot = true

local x 
local y

local newSlot
local oldSlot

local function update(input)
	local delta = input.Position - dragStart
	if not inHotbar then
		if startPos.X.Offset + delta.X > 0 and startPos.Y.Offset + delta.Y > 0 then
			gui.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
		elseif startPos.X.Offset + delta.X > 0 then
			gui.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, 0)
		elseif startPos.Y.Offset + delta.Y > 0 then
			gui.Position = UDim2.new(startPos.X.Scale, 0, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
		end
	else
		gui.Parent.HoldsItem.Value = false
		gui.Parent = gui.Parent.Parent.Parent.Handler
		inHotbar = false
	end
end

gui.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		if not inHotbar and inSlot then
			x = getPos(tonumber(gui.Parent.Name), "x")
			y = getPos(tonumber(gui.Parent.Name), "y")
			oldSlot = gui.Parent
			gui.Parent = gui.Parent.Parent
			gui.Position = UDim2.new(0, x, 0, y)
			dragStart = input.Position
			startPos = gui.Position
			gui.ZIndex = 3
		end
		dragging = true
	end
end)

gui.MouseButton1Up:Connect(function(input)
	dragging = false
	gui.ZIndex = 2
	snap()
end)

gui.InputChanged:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
		dragInput = input
	end
end)

function snap(input)
	if not inHotbar then
		local HB = checkIfInHotbar(input)
		if HB == false then
			local S = checkIfInSlot(input, false)
			if S == false then
				for i,v in ipairs(gui.Parent:GetChildren()) do
					if v:IsA("Frame") then
						if #v:GetChildren() <= 2 then
							gui.Parent = v
							gui.Position = UDim2.new(0,0,0,0)
						end
					end
				end
			elseif S == true then
				newSlot = checkIfInSlot(input, true)
				newSlot.Sample.Parent = oldSlot
				gui.Parent = newSlot
				gui.Position = UDim2.new(0,0,0,0)
			else
				gui.Parent = gui.Parent[S.Name]
				gui.Position = UDim2.new(0,0,0,0)
			end
			
		else
			gui.Parent = script.Parent.Parent.Parent.Hotbar[HB.Name]
			gui.Position = UDim2.new(0,0,0,0)
			inHotbar = true
			gui.Parent.HoldsItem.Value = true
		end
	end
end

UserInputService.InputChanged:Connect(function(input)
	if input == dragInput and dragging then
		update(input)
	end
end)

function checkIfInHotbar(input)
	local Hotbar = gui.Parent.Parent.Hotbar:GetChildren()
	for i,HB in pairs(Hotbar) do
		if HB.MouseOver.Value then
			if HB.HoldsItem.Value then
				return false
			end
			return HB
		end
	end
	return false
end

function checkIfInSlot(input, special)
	local Slot = gui.Parent.Parent.Handler:GetChildren()
	for i,S in pairs(Slot) do
		if S:IsA("Frame") then
			if S.MouseOver.Value then
				if #S:GetChildren() == 3 then
					if special then
						return S
					end
					return false
				end
				return S
			end
		end
	end
	return false
end

function resetHoldsItem()
	local Hotbar = game:GetService("Players").LocalPlayer.PlayerGui.Inventory.Frame.Frame.Hotbar:GetChildren()
	for i,HB in pairs(Hotbar) do
		HB.HoldsItem.Value = false
	end
end

function getPos(i, type)
	if i <= 5 then
		if type == "x" then
			return ((i-1)*100)+(8.5*i)
		elseif type == "y" then
			return 5
		end
	elseif i > 5 and i <= 10 then
		if type == "x" then
			return ((i-6)*100)+(8.5*(i-5))
		elseif type == "y" then
			return 110
		end
	elseif i > 10 and i <= 15 then
		if type == "x" then 
			return ((i-11)*100)+(8.5*(i-10))
		elseif type == "y" then
			return 215
		end
	elseif i > 15 and i <= 20 then
		if type == "x" then 
			return ((i-16)*100)+(8.5*(i-15))
		elseif type == "y" then
			return 320
		end
	end
end

1 answer

The way I fixed this was by changing the code on line 71 as it was a hot mess to the following:

local available = {}
				for i,v in next, gui.Parent:GetChildren() do
					if v:IsA("Frame") and #v:GetChildren() <= 2 then
						available[#available+1] = v
					end
				end
					gui.Parent = available[1]
					gui.Position = UDim2.new(0,0,0,0)
					
					table.remove(available, 1)

This discussion is preserved as it was. New answers, comments, and votes are closed.