Inventory System Bug

Hi! So I have made an inventory system where you can equip multiple tools at once. The problem is, when two or more tools are equipped and all the texts say “unequip,” it takes two clicks of the button to finally change the text button’s text to equip. This is a big problem because the tool is still in the player’s inventory even though the button says to “equip.”
Picture of frame:

Here is the code I used for the inventory:

for i, tool in pairs(ownedTrails) do
		local item = script.InvItem:Clone()
		item.Image = tool:WaitForChild("Folder").ImageLabel.Image
		item.SelectButton.Text = "Equip"
		item.Title.Text = tool.Name
		item.Visible = true



		item.Parent = invFrame.ShopGUI.Tools






		item.SelectButton.MouseButton1Click:Connect(function()
			local price = tool.Price.Value
			local coins = player.leaderstats.Coins.Value
			if item == SelectedTrail then
				item.SelectButton.Text = "Equip"

				SelectedTrail = nil
			else
				if player.OwnedTools:FindFirstChild(tool.Name) or (price <= coins) then
					item.SelectButton.Text = "Unequip" 
				else
					item.SelectButton.Text = "Unequip"
				end
				

				SelectedTrail = item
			end

			TrailSelectedRE:FireServer(tool)
		end)
	end




end		

So to sum this post up in one question, how can I make the button stop requiring to clicks to finally change the text?

Since you have made it so that multiple tools can be equipped at once, the issue at hand is because you have a single variable that holds a reference to the current equipped item… See the issue? How will one variable to one item be able to handle concurrent equipped items?

3 Likes

I’d suggest changing SelectedTrail to a table, because with that you can insert multiple things and delete multiple things without having to change any already existing ones.

Im confused on how to change that variable into a table. When the button is clicked, it needs to send over that tools information. If I send it over in a table, won’t there be multiple options?

You could loop everything inside the table and get its information.

As @Synteuro stated, you wanted multiple parts equipped, is that right? Using a table would work out.

Do you mind linking a devhub post or youtube tutorial to lead me in the right direction? I’m having trouble figuring out how to do this.

I believe that I can help you if you show me the script where it sends over the information. From there, I can further help you.

So when the button is clicked, it triggers a remote event. Its connected through this script.

ToolSelectedRE.OnServerEvent:Connect(function(plr, tool)
	if not tool or typeof(tool) ~= "Instance" then return end -- we still want this here just in case

	local ownedTool = plr.OwnedTools:FindFirstChild(tool.Name)
	



	if not ownedTool then
		print(plr.Name," is buying the ",tool.Name," tool.")

		local price = tool.Price.Value
		local coins = plr.leaderstats.Coins

		if price <= coins.Value then
			coins.Value -= price

			local newTool = tool:Clone() do
				newTool.Parent = plr.OwnedTools



			end
		end
	elseif ownedTool then
		if plr.Backpack:FindFirstChild(tool.Name) == nil then
			print(plr.Name," equipped ",tool.Name," tool.")

			local new = tool:Clone()
			new.Parent = plr.Backpack

		elseif plr.Backpack:FindFirstChild(tool.Name) then
			print("triggered")

			local deleted = plr.Backpack:WaitForChild(tool.Name)
			deleted:Destroy()

		end
	end
end)

1 Like
ToolSelectedRE.OnServerEvent:Connect(function(plr, tools) -- tools is the table you're going to send
	if not tool or typeof(tool) ~= "Instance" then return end -- we still want this here just in case

    for _, tool in pairs(tools) do
		local ownedTool = plr.OwnedTools:FindFirstChild(tool.Name)
	
		if not ownedTool then
			print(plr.Name," is buying the ",tool.Name," tool.")
	
			local price = tool.Price.Value
			local coins = plr.leaderstats.Coins
	
			if price <= coins.Value then
				coins.Value -= price
	
				local newTool = tool:Clone() do
					newTool.Parent = plr.OwnedTools
				end
			end
		elseif ownedTool then
			if plr.Backpack:FindFirstChild(tool.Name) == nil then
				print(plr.Name," equipped ",tool.Name," tool.")
	
				local new = tool:Clone()
				new.Parent = plr.Backpack
			elseif plr.Backpack:FindFirstChild(tool.Name) then
				print("triggered")
	
				local deleted = plr.Backpack:WaitForChild(tool.Name)
				deleted:Destroy()
			end
	    end
    end
end)

Tell me if this works or not.

So, its acting even weirder now (i’ll try to explain the best I can). So instead of last time where when all 2 of the buttons said “unequip” and you would have to click each of them 2 times to work, you can now click one button just once to change back to “equip” but the other one will take two clicks. This has nothing to do with the frame, its whatever button says “unequip” last will take two clicks. Does that make sense?

Yeah, I think I understand. In the script you provided in post 1, did you do something like table.insert(SelectedTrail, VAL)?

DID YOU CHANGE IT TO**

1 Like

No, I have not changed it to a table yet. Should I?

1 Like

This is the full script:

function updateInventory()

	for i, child in pairs(invFrame.ShopGUI.Tools:GetChildren()) do
		if child:IsA("ImageLabel") then child:Destroy() end
	end


	local ownedTrails = ownedTrailsFolder:GetChildren()
	print(ownedTrails)

	table.sort(ownedTrails, function(a, b)
		return trailsFolder[a.Name].Price.Value < trailsFolder[b.Name].Price.Value or trailsFolder[a.Name].Price.Value == trailsFolder[b.Name].Price.Value and a.Name < b.Name
	end)


	for i, tool in pairs(ownedTrails) do
		local item = script.InvItem:Clone()
		item.Image = tool:WaitForChild("Folder").ImageLabel.Image
		item.SelectButton.Text = "Equip"
		item.Title.Text = tool.Name
		item.Visible = true



		item.Parent = invFrame.ShopGUI.Tools






		item.SelectButton.MouseButton1Click:Connect(function()
			local price = tool.Price.Value
			local coins = player.leaderstats.Coins.Value
			if item == SelectedTrail then
				item.SelectButton.Text = "Equip"

				SelectedTrail = nil
			else
				if player.OwnedTools:FindFirstChild(tool.Name) or (price <= coins) then
					item.SelectButton.Text = "Unequip" 
				else
					item.SelectButton.Text = "Unequip"
				end
				

				SelectedTrail = item
			end

			TrailSelectedRE:FireServer(tool)
		end)
	end




end		

I realize now I was missing some parts which could have made some variables confusing.

Before I give you the full script, I need to tell you about another problem.
You see the function where you click SelectButton? When updateInventory runs again, those functions are still there.

If we use a dictionary, we would be able to remove and disconnect this function.

also I changed everything to a table

local buttonDictionary = {}
local clonedToItem = {}

function updateInventory()
	for i, child in pairs(invFrame.ShopGUI.Tools:GetChildren()) do
		if child:IsA("ImageLabel") then
            child:Destroy() 
            buttonDictionary[child.SelectButton]:Disconnect() -- removing it
            buttonDictionary[child.SelectButton] = nil 
        end
	end

    for i, v in pairs(clonedToItem) do
       clonedToItem[i] = nil
    end

	local ownedTrails = ownedTrailsFolder:GetChildren()
	print(ownedTrails)

	table.sort(ownedTrails, function(a, b)
		return trailsFolder[a.Name].Price.Value < trailsFolder[b.Name].Price.Value or trailsFolder[a.Name].Price.Value == trailsFolder[b.Name].Price.Value and a.Name < b.Name
	end)

	for i, tool in pairs(ownedTrails) do
		local item = script.InvItem:Clone()
		item.Image = tool:WaitForChild("Folder").ImageLabel.Image
		item.SelectButton.Text = "Equip"
		item.Title.Text = tool.Name
		item.Visible = true

        clonedToItem[item] = tool

		item.Parent = invFrame.ShopGUI.Tools

		buttonDictionary[item.SelectButton] = item.SelectButton.MouseButton1Click:Connect(function() -- adding it
			local price = tool.Price.Value
			local coins = player.leaderstats.Coins.Value

			if item == SelectedTrail then
				item.SelectButton.Text = "Equip"

				table.remove(SelectedTrail, table.find(SelectedTrail, item))
			else
				if player.OwnedTools:FindFirstChild(tool.Name) or (price <= coins) then
					item.SelectButton.Text = "Unequip" 
				else
					item.SelectButton.Text = "Unequip"
				end
				

				table.insert(SelectedTrail, item)
			end

            local finalTable = {}

            for i, v in pairs(SelectedTrail) do
                table.insert(finalTable, clonedToItem[v])
            end

			TrailSelectedRE:FireServer(finalTable)
		end)
	end
end		

There is an error on this line right here because SelectedTrail doesn’t exist anymore. What should I change it to?

if item == SelectedTrail then

if table.find(SelectedTrail, item) then

I changed the script above to fit, also.

There is still a red line under “SelectedTrail.” Also, could you elaborate on the future issue and what this could cause?
Edit: I see what you mean about the problem, nevermind.

Im confused about the red line under SelectedTrail because I define it in my variables.

Where is this line? Also which script is it in