Custom Backpack Script

This is a custom tool bar which can only hold 2 tools, for some reason when you have 1 tool equipped, you can equip it and unequip it just fine, but if you equip 1 tool and switch to the other tool it just gets completely removed, how can i fix this?

local ToolCollection = require(script.ToolImages)
local UIS = game:GetService("UserInputService")

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local backpack = player.Backpack
local HipSlots = player:WaitForChild("HipSlots")

local ToolScreen = script.Parent.ToolScreen

local OpenSlots = {ToolScreen.Slot1, ToolScreen.Slot2}
local ClosedSlots = {}

local toolIdCounter = 0

local function sortSlots()
	table.sort(OpenSlots, function(a, b)
		return a.Name < b.Name
	end)
end

local function FindToolFromSlot(Slot)

	for i, tool in pairs(HipSlots:GetChildren()) do
		if tool:GetAttribute("ToolId") == Slot:GetAttribute("ToolUniqueId") then
			return tool
		end
	end

	for i, tool in pairs(character:GetChildren()) do
		if tool:IsA("Tool") and tool:GetAttribute("ToolId") == Slot:GetAttribute("ToolUniqueId") then
			return tool
		end
	end	

	for i, tool in pairs(backpack:GetChildren()) do
		if tool:GetAttribute("ToolId") == Slot:GetAttribute("ToolUniqueId") then
			return tool
		end
	end

end

local function UnequipEquippedTool()
	for _, tool in pairs(character:GetChildren()) do
		if tool:IsA("Tool") then
			tool.Parent = HipSlots
			break
		end
	end
end


UIS.InputBegan:Connect(function (input, processed)
	if Enum.KeyCode.One == input.KeyCode and processed == false then
		local Tool = FindToolFromSlot(ToolScreen.Slot1)
		print(Tool)
		if Tool and not Tool:IsA("Humanoid") then
			if Tool.Parent ~= character then
				UnequipEquippedTool()
				Tool.Parent = character
			else
				Tool.Parent = HipSlots
			end
		end
	elseif Enum.KeyCode.Two == input.KeyCode and processed == false then
		local Tool = FindToolFromSlot(ToolScreen.Slot2)
		print(Tool)
		if Tool and not Tool:IsA("Humanoid") then
			if Tool.Parent ~= character then
				UnequipEquippedTool()
				Tool.Parent = character
			else
				Tool.Parent = HipSlots
			end
		end
	end
end)

character.ChildAdded:Connect(function (child)
	if child:IsA("Tool") and not child:GetAttribute("ToolId") then
		if #OpenSlots > 0 then

			sortSlots()

			local Slot = OpenSlots[1]
			table.remove(OpenSlots, 1)
			table.insert(ClosedSlots, Slot)


			toolIdCounter += 1
			child:SetAttribute("ToolId", toolIdCounter)


			Slot.ToolImage.Image = ToolCollection[child.Name].Id
			Slot.ToolImage.Size = ToolCollection[child.Name].Size
			Slot.ToolImage.Position = ToolCollection[child.Name].Position
			Slot:SetAttribute("ToolUniqueId", toolIdCounter)
			Slot:SetAttribute("ToolName", child.Name)
			Slot.Visible = true

			local Tool = FindToolFromSlot(Slot)
			print(Tool)
		end
	end
end)

character.ChildRemoved:Connect(function (child)
	if child:IsA("Tool") then
		local uniqueId = child:GetAttribute("ToolId")
		for i, Slot in ipairs(ClosedSlots) do
			if Slot:GetAttribute("ToolUniqueId") == uniqueId then

				Slot:SetAttribute("ToolUniqueId", nil)
				Slot:SetAttribute("ToolName", nil)
				child:SetAttribute("ToolId")
				Slot.ToolImage.Image = ""
				Slot.ToolImage.Size = UDim2.new(0, 0, 0, 0)
				Slot.ToolImage.Position = UDim2.new(0, 0, 0, 0)

				table.insert(OpenSlots, Slot)
				table.remove(ClosedSlots, i)
				break
			end
		end
	end
end)


backpack.ChildAdded:Connect(function (child)
	if child:IsA("Tool") then
		if #OpenSlots > 0 then

			sortSlots()

			child.Parent = HipSlots

			local Slot = OpenSlots[1]
			table.remove(OpenSlots, 1)
			table.insert(ClosedSlots, Slot)


			toolIdCounter += 1


			Slot.ToolImage.Image = ToolCollection[child.Name].Id
			Slot.ToolImage.Size = ToolCollection[child.Name].Size
			Slot.ToolImage.Position = ToolCollection[child.Name].Position
			Slot.Visible = true
		end
	end
end)

HipSlots.ChildAdded:Connect(function (child)
	if child:IsA("Tool") then
		if #OpenSlots > 0 then

			sortSlots()

			child.Parent = HipSlots

			local Slot = OpenSlots[1]
			table.remove(OpenSlots, 1)
			table.insert(ClosedSlots, Slot)


			toolIdCounter += 1
			child:SetAttribute("ToolId", toolIdCounter)


			Slot.ToolImage.Image = ToolCollection[child.Name].Id
			Slot.ToolImage.Size = ToolCollection[child.Name].Size
			Slot.ToolImage.Position = ToolCollection[child.Name].Position
			Slot:SetAttribute("ToolUniqueId", toolIdCounter)
			Slot:SetAttribute("ToolName", child.Name)
			Slot.Visible = true
		end
	end
end)

Video Example:
robloxapp-20250317-1843096.wmv (1.7 MB)

1 Like

bumping this topic
bumping this topic

Can you upload a place file? Helps us to understand your setup without having to completely dissect every line

1 Like

Yep, here it is
---------------removed

child:SetAttribute(“ToolId”, nil) --missed the 2nd augment on this one

1 Like

This is not about the bug, but you can optimize the following part:

local KeyCodeList = {
	[Enum.KeyCode.One] = ToolScreen.Slot1,
	[Enum.KeyCode.Two] = ToolScreen.Slot2
}

UIS.InputBegan:Connect(function (Input, Processed)
	if KeyCodeList[Input.KeyCode] and not Processed then
		local Tool = FindToolFromSlot(KeyCodeList[Input.KeyCode])

		if Tool and Tool:IsA("Tool") and Tool.Parent == HipSlots then
			UnequipEquippedTool()
			Tool.Parent = character
		elseif Tool and Tool:IsA("Tool") and Tool.Parent == character then
			Tool.Parent = HipSlots
		end
	end
end)

As well as this one:

local function SetupNewTool(NewTool, Location)
	if NewTool:IsA("Tool") and #OpenSlots > 0 then
		sortSlots()
		
		local Slot = OpenSlots[1]
		table.remove(OpenSlots, 1)
		table.insert(ClosedSlots, Slot)
		
		toolIdCounter += 1
		Slot.ToolImage.Image = ToolCollection[NewTool.Name].Id
		Slot.ToolImage.Size = ToolCollection[NewTool.Name].Size
		Slot.ToolImage.Position = ToolCollection[NewTool.Name].Position
		
		if Location == "Backpack" then
			NewTool.Parent = HipSlots
		elseif Location == "HipSlots" then
			NewTool:SetAttribute("ToolId", toolIdCounter)
			Slot:SetAttribute("ToolUniqueId", toolIdCounter)
			Slot:SetAttribute("ToolName", NewTool.Name)
		end
		
		Slot.Visible = true
	end
end

backpack.ChildAdded:Connect(function(Child)
	SetupNewTool(Child, "Backpack")
end)

HipSlots.ChildAdded:Connect(function(Child)
	SetupNewTool(Child, "HipSlots")
end)
2 Likes

thanks for helping me out with this, I’m still trying to figure it out but im getting close to a fix

1 Like

thanks for the help guys! started fresh with a new script and got everything working 10x better!

full script for future reference and anybody that wants it.

local UIS = game:GetService("UserInputService")

local ToolDetailCollection = require(script:WaitForChild("ToolImages"))

local plr = game.Players.LocalPlayer
local backpack = plr.Backpack
local char = plr.Character or plr.CharacterAdded:Wait()

local ToolScreen = script.Parent:WaitForChild("ToolScreen")

local OpenSlots = {ToolScreen.Slot1, ToolScreen.Slot2}

local Keybinds = {
	[Enum.KeyCode.One] = ToolScreen.Slot1,
	[Enum.KeyCode.Two] = ToolScreen.Slot2
}

local function Sort()
	table.sort(OpenSlots, function (a,b)
		return a.Name < b.Name
	end)
end

local function SetSlot(slot, tool)
	slot.ToolImage.Image = ToolDetailCollection[tool.Name].Id
	slot.ToolImage.Size = ToolDetailCollection[tool.Name].Size
	slot.ToolImage.Position = ToolDetailCollection[tool.Name].Position
	print(table.find(OpenSlots,slot))
	table.remove(OpenSlots, table.find(OpenSlots, slot))
	Sort()
end

local function RemoveSlot(slot)
	slot.ToolImage.Image = ""
	slot.ToolImage.Size = UDim2.new(0,0,0,0)
	slot.ToolImage.Position = UDim2.new(0,0,0,0)
	table.insert(OpenSlots, slot)
	Sort()
end

local function FindSlotFromTool(tool)
	for i, slotGui in pairs(ToolScreen:GetChildren()) do
		if slotGui:IsA("Frame") and slotGui.Name == tool:GetAttribute("Slot") and slotGui ~= nil then
			return slotGui
		end
	end
end

local function FindToolFromSlot(Slot)
	
	for i, tool in pairs(plr.Backpack:GetChildren()) do
		if tool:GetAttribute("Slot") == Slot.Name then
			return tool
		end
	end
	
	for i, tool in pairs(char:GetChildren()) do
		if tool:GetAttribute("Slot") == Slot.Name then
			return tool
		end
	end
end

UIS.InputBegan:Connect(function (input, processed)
	if Keybinds[input.KeyCode] and not processed then
		local tool = FindToolFromSlot(Keybinds[input.KeyCode])
		if tool then
			if tool.Parent == char then
				tool.Parent = plr.Backpack
				Keybinds[input.KeyCode].BackgroundColor3 = Color3.fromRGB(186, 186, 186)
			elseif tool.Parent == plr.Backpack then
				local toolInChar = char:FindFirstChildWhichIsA("Tool")
				
				if toolInChar then
					toolInChar.Parent = plr.Backpack
				end
				tool.Parent = char
				Keybinds[input.KeyCode].BackgroundColor3 = Color3.fromRGB(255, 255, 255)
			end
		end
	end
end)

char.ChildAdded:Connect(function (child)
	if child:IsA("Tool") and child:GetAttribute("Slot") == nil then
		if #OpenSlots > 0 then

			local slot = OpenSlots[1]

			child:SetAttribute("Slot", slot.Name)

			slot.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
			SetSlot(slot, child)
		end
	elseif child:IsA("Tool") then
		
		local slot = FindSlotFromTool(child)
		slot.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
			
	end
end)

char.ChildRemoved:Connect(function (child)
	if child:IsA("Tool") and child.Parent ~= plr.Backpack then

		local slot = FindSlotFromTool(child)

		if slot then
			child:SetAttribute("Slot", nil)
			slot.BackgroundColor3 = Color3.fromRGB(186, 186, 186)
			RemoveSlot(slot)
		end
		

	elseif child:IsA("Tool") and child.Parent == plr.Backpack then
		local slot = FindSlotFromTool(child)
		slot.BackgroundColor3 = Color3.fromRGB(186, 186, 186)
	end
end)
1 Like

Nice! A rewrite can do wonders sometimes :relieved:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.