Tool Won't Re-Equip After Deleting from Hotbar Slot

Hello everyone,
I’m currently working on an inventory system for my Roblox game, but I’ve encountered a frustrating issue related to re-equipping tools after using a delete button in the hotbar.

  • The tool system allows players to equip tools by clicking on hotbar slots or pressing the corresponding keys (e.g., the ‘1’ key). However, after deleting a tool from a hotbar slot and attempting to reassign and equip the same tool, it fails to appear in the character’s hands. The system still detects the tool’s name, and the RemoteEvent fires correctly, but the tool doesn’t get cloned or equipped.

Edit: I’ve added a video below to illustrate the issue further

This is the LocalScript responsible for handling player interactions with the hotbar:

--<Variables>--
local players = game:GetService("Players")
local player = players.LocalPlayer
local Inventory_Gui = script.Parent
local inventoryFrame = Inventory_Gui:WaitForChild("inventoryFrame")
local scrollingFrame = inventoryFrame.ScrollingFrame
local itemTemp = scrollingFrame.ItemTemp
local hotbarFrame = Inventory_Gui:WaitForChild("hotbarFrame")

--<Services>--
local replicatedStorage = game:GetService("ReplicatedStorage")
local ReceiveInventoryData_RF = replicatedStorage:WaitForChild("Remotes").ReceiveInventoryData
local EquipToolRE = replicatedStorage:WaitForChild("Remotes").EquipTool
local contextActionService = game:GetService("ContextActionService")
local userIputService = game:GetService("UserInputService")


local StarterGui = game:GetService("StarterGui")
StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)

local KeyBinds = {
	[1] = Enum.KeyCode.One,
	[2] = Enum.KeyCode.Two,
	[3] = Enum.KeyCode.Three,
	[4] = Enum.KeyCode.Four,
	[5] = Enum.KeyCode.Five,
	[6] = Enum.KeyCode.Six,
	[7] = Enum.KeyCode.Seven,
	[8] = Enum.KeyCode.Eight,
	[9] = Enum.KeyCode.Nine
}

local function SetUpHotbar(slot)
	local slotValue = slot:FindFirstChildOfClass("StringValue")
	local deleteItem = slot:FindFirstChildOfClass("TextButton")
	local slotIndex = tonumber(slot.Name)

	if not slotValue then
		warn("Slot missing StringValue: " .. slot.Name)
		return
	end
	
	if not deleteItem then
		warn("Slot missing delete button: " .. slot.Name)
		return
	end

	--<Button clicked>--
	local function onButtonClick()
		if slotValue.Value and slotValue.Value ~= "" then
			EquipToolRE:FireServer(slotValue.Value)

			print("Hotbar slot clicked! Item: " .. slotValue.Value .. " in " .. slot.Name)
		else
			print("Hotbar slot clicked, but no item is assigned!")
		end
	end
	
	slot.MouseButton1Click:Connect(onButtonClick)
	
	--<Keys (1-9) pressed>--
	userIputService.InputBegan:Connect(function(input, gameProcessedEvent)
		if gameProcessedEvent then
			return
		end

		if input.KeyCode == KeyBinds[slotIndex] then
			if slotValue.Value and slotValue.Value ~= "" then
				EquipToolRE:FireServer(slotValue.Value)
				
				print("Hotbar slot clicked! Item: " .. slotValue.Value .. " in " .. slot.Name)
			else
				print("Hotbar slot clicked, but no item is assigned!")
			end
		end
	end)

	--<Delete button clicked>--
	deleteItem.MouseButton1Click:Connect(function()
		if player.Character:FindFirstChildOfClass("Tool") then
			return
		end
		slotValue.Value = ""
		print("Delete button clicked for hotbar slot: " .. slot.Name)
	end)
end


local function MoveToHotbar(itemName)
	for _, slot in pairs(hotbarFrame:GetChildren()) do
		local slotValue = slot:FindFirstChildOfClass("StringValue")
		if slotValue and slotValue.Value == itemName then
			print("Item '" .. itemName .. "' is already in the hotbar!")
			return 
		end
	end
	
	for _, slot in pairs(hotbarFrame:GetChildren()) do
		local slotValue = slot:FindFirstChildOfClass("StringValue")
		if slotValue and (slotValue.Value == nil or slotValue.Value == "") then
			slotValue.Value = itemName
			print("Item '" .. itemName .. "' added to hotbar slot: " .. slot.Name)
			SetUpHotbar(slot)
			return
		end
	end
end

On the server side, I have the following ModuleScript to manage equipping tools:

local serverScriptService = game:GetService("ServerScriptService")
local replicatedStorage = game:GetService("ReplicatedStorage")
local toolModelsFolder = replicatedStorage:WaitForChild("ToolsModels")



local Equip_Tool_Manager = {}

function Equip_Tool_Manager.EquipTool(player: Player, toolName: string)
	local character = player.Character
	local humanoid = character:FindFirstChild("Humanoid")
	local toolmodel = toolModelsFolder:FindFirstChild(toolName)
	
	if not character then
		warn("EquipTool failed: Character not found for player " .. player.Name)
		return
	end
	
	if not humanoid then
		warn("EquipTool failed: Humanoid not found for player " .. player.Name)
		return
	end
	
	if not toolmodel then
		warn("EquipTool failed: Tool '" .. toolName .. "' does not exist")
		return
	end
	
	local characterExistingTool = character:FindFirstChildOfClass("Tool")
	if characterExistingTool then
		print("tool eliminated")
		characterExistingTool.Parent = player.Backpack
		characterExistingTool:Destroy()
		return
	end
	local tool = toolmodel:Clone()
	print("tool cloned")
	tool.Parent = character
end

return Equip_Tool_Manager

I suspect the issue might be related to how the tool is destroyed and re-cloned, but I cannot pinpoint the problem.

If anyone has encountered a similar issue or has insights into what could be going wrong, I would greatly appreciate your guidance!

1 Like

Try to add a task.wait(), this might help the tool to clone correctly.

local tool = toolmodel:Clone()
task.wait()
print("tool cloned")
tool.Parent = character

Thank you so much! I can’t believe it works because of the task.wait(). Now, every time I use the delete button to reassign the tool, it prints one extra number compared to the last time, but I think it might be due to the remote event.

  18:54:59.442   ▶ tool cloned (x5)  -  Server - Equip_Tool_Manager:38
  18:54:59.444   ▶ info sent (x5)  -  Server - MainServer:68

  18:58:54.600   ▶ tool cloned (x6)  -  Server - Equip_Tool_Manager:38
  18:58:54.602   ▶ info sent (x6)  -  Server - MainServer:68
1 Like

Is there a way to reset a remote event to avoid duplicates?

When I click on a slot in my hotbar to equip a tool, everything works fine initially. However, after reassigning tools multiple times, the events seem to duplicate, resulting in multiple logs in the console and unintended behavior.

The code is the same:

local function SetUpHotbar(slot)
	
	local slotValue = slot:FindFirstChildOfClass("StringValue")
	local deleteItem = slot:FindFirstChildOfClass("TextButton")
	local slotIndex = tonumber(slot.Name)

	if not slotValue then
		warn("Slot missing StringValue: " .. slot.Name)
		return
	end
	
	if not deleteItem then
		warn("Slot missing delete button: " .. slot.Name)
		return
	end

	--<Button clicked>--
	slot.MouseButton1Click:Connect(function()
		if slotValue.Value and slotValue.Value ~= "" then
			EquipToolRE:FireServer(slotValue.Value)
			print("Hotbar slot clicked! Item: " .. slotValue.Value .. " in " .. slot.Name)
		else
			print("Hotbar slot clicked, but no item is assigned!")
		end
	end)
	
	--<Keys (1-9) pressed>--
	userIputService.InputBegan:Connect(function(input, gameProcessedEvent)
		if gameProcessedEvent then
			return
		end

		if input.KeyCode == KeyBinds[slotIndex] then
			if slotValue.Value and slotValue.Value ~= "" then
				EquipToolRE:FireServer(slotValue.Value)
				
				print("Hotbar slot clicked! Item: " .. slotValue.Value .. " in " .. slot.Name)
			else
				print("Hotbar slot clicked, but no item is assigned!")
			end
		end
	end)

	--<Delete button clicked>--
	deleteItem.MouseButton1Click:Connect(function()
		if player.Character:FindFirstChildOfClass("Tool") then
			return
		end
		slotValue.Value = ""
		print("Delete button clicked for hotbar slot: " .. slot.Name)
	end)
end

Output:

  20:11:58.477  Item 'Wooden Axe' added to hotbar slot: 1  -  Client - Inventory_Manager:103
  20:12:02.543  Hotbar slot clicked! Item: Wooden Axe in 1  -  Client - Inventory_Manager:56
  20:12:02.559  tool cloned  -  Server - Equip_Tool_Manager:38
  20:12:09.826  Hotbar slot clicked! Item: Wooden Axe in 1  -  Client - Inventory_Manager:56
  20:12:13.826  Delete button clicked for hotbar slot: 1  -  Client - Inventory_Manager:85
--------------------------------------------------------------------------------------------------------------------------------
  20:12:16.309  Item 'Wooden Axe' added to hotbar slot: 1  -  Client - Inventory_Manager:103
  20:12:18.210   ▶ Hotbar slot clicked! Item: Wooden Axe in 1 (x2)  -  Client - Inventory_Manager:56
  20:12:18.226   ▶ tool cloned (x2)  -  Server - Equip_Tool_Manager:38
  20:12:19.958   ▶ Hotbar slot clicked! Item: Wooden Axe in 1 (x2)  -  Client - Inventory_Manager:56
  20:12:23.241   ▶ Delete button clicked for hotbar slot: 1 (x2)  -  Client - Inventory_Manager:85
-------------------------------------------------------------------------------------------------------------------------------
  20:12:25.144  Item 'Wooden Axe' added to hotbar slot: 1  -  Client - Inventory_Manager:103
  20:12:26.310   ▶ Hotbar slot clicked! Item: Wooden Axe in 1 (x3)  -  Client - Inventory_Manager:56
  20:12:26.325   ▶ tool cloned (x3)  -  Server - Equip_Tool_Manager:38
  20:12:28.375   ▶ Hotbar slot clicked! Item: Wooden Axe in 1 (x3)  -  Client - Inventory_Manager:56

How can I reset or clean up the events to prevent this duplication? Should I be handling the connections differently, or is there a more efficient way to manage the remote events and tool assignments?

Any help or insight is greatly appreciated!

Fixed!
Here’s the solution if anyone’s curious

local hotbarConnections = {}

local function SetUpHotbar(slot)

	if hotbarConnections[slot] then
		for _, connections in ipairs(hotbarConnections[slot]) do
			connections:Disconnect()
		end
		hotbarConnections[slot] = nil
	end

	local slotValue = slot:FindFirstChildOfClass("StringValue")
	local deleteItem = slot:FindFirstChildOfClass("TextButton")
	local slotIndex = tonumber(slot.Name)

	if not slotValue then
		warn("Slot missing StringValue: " .. slot.Name)
		return
	end

	if not deleteItem then
		warn("Slot missing delete button: " .. slot.Name)
		return
	end

	hotbarConnections[slot] = {}

	--<Button clicked>--
	table.insert(hotbarConnections[slot], slot.MouseButton1Click:Connect(function()
		if slotValue.Value and slotValue.Value ~= "" then
			EquipToolRE:FireServer(slotValue.Value)
			print("Hotbar slot clicked! Item: " .. slotValue.Value .. " in " .. slot.Name)
		else
			print("Hotbar slot clicked, but no item is assigned!")
		end
	end))

	--<Keys (1-9) pressed>--
	table.insert(hotbarConnections[slot], userIputService.InputBegan:Connect(function(input, gameProcessedEvent)
		if gameProcessedEvent then
			return
		end

		if input.KeyCode == KeyBinds[slotIndex] then
			if slotValue.Value and slotValue.Value ~= "" then
				EquipToolRE:FireServer(slotValue.Value)

				print("Hotbar slot clicked! Item: " .. slotValue.Value .. " in " .. slot.Name)
			else
				print("Hotbar slot clicked, but no item is assigned!")
			end
		end
	end))

	--<Delete button clicked>--
	table.insert(hotbarConnections[slot], deleteItem.MouseButton1Click:Connect(function()
		if player.Character:FindFirstChildOfClass("Tool") then
			return
		end
		slotValue.Value = ""
		print("Delete button clicked for hotbar slot: " .. slot.Name)
	end))
end