Problem with custom inventory equipping and unequipping

Hey everyone!

I’ve been scripting a custom inventory system in which the items are string values where the name of the value is the name of the item and the value is a UUID string created with GenerateGUID.
These values are inside of a folder parented to the player, and the inventory script loops through that folder and creates a button for each of those items.
For the equipping and unequipping part I have some GUI “slots” and when a button is clicked it gets parented to one of those slots and a remote event is fired so the actual welding of the weapon and armor models can happen.
So far so good! Until I encountered a problem, what if I need to delete one of those items? So, to handle that I created another frame with an equip/unequip button and a delete one, changed my script so that the remote event was fired when the equip/unequip button is pressed and not the item one and it works, but I have created some sort of bug where, the first time that I equip/unequip something it behaves as it should, but afterwards it looks like the buttons “think” they are all the same one and start equipping/unequipping everything that was already in the slots.
I’m sure I’m overlooking an if statement I should be making or something I should be adding somewhere, but I’m in need of some outside input on the logic I created here.

robloxapp-20220407-1253126.wmv (560.1 KB)

The Inventory Local Script

local EquipWeaponRemote = game.ReplicatedStorage:WaitForChild("GameRemotes"):WaitForChild("EquipWeapon")
local EquipArmorRemote = game.ReplicatedStorage:WaitForChild("GameRemotes"):WaitForChild("EquipArmor")
local InHandRemote = game.ReplicatedStorage:WaitForChild("GameRemotes"):WaitForChild("InHand")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UnequipWeaponRemote = ReplicatedStorage:WaitForChild("GameRemotes"):WaitForChild("UnequipWeapon")
local UnequipArmorRemote = ReplicatedStorage:WaitForChild("GameRemotes"):WaitForChild("UnequipArmor")
local weapons = ReplicatedStorage:WaitForChild("ItemsInfo"):WaitForChild("WeaponInfo")
local player = game.Players.LocalPlayer
local character = player.Character
local playerInventory = player:WaitForChild("Inventory")
local equippedItems = player:WaitForChild("Info")
local equippedWeapon = equippedItems:WaitForChild("Weapon")
local equippedArmor = equippedItems:WaitForChild("Armor")
local inHandBool = player:WaitForChild("Bools"):WaitForChild("InHand")
local aftersenditem = ReplicatedStorage:WaitForChild("GameRemotes"):WaitForChild("AfterSendItem")
game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack,false)


local items = {}
local buttons = {}

function searchInventory()
	for i,v in pairs(playerInventory:GetChildren()) do
		if v:isA("StringValue") then 
			table.insert(items,v) 
		end
	end
end

function searchEquipped()
	for i,v in pairs(equippedItems:GetChildren()) do 
		if v:isA("StringValue") then 
		end
	end
end


function addInventoryBtn (item)
	local itemType = ReplicatedStorage.ItemsInfo.WeaponInfo[item.Name].ItemType.Value
	local itemHover = script.Parent.Parent.ItemHover
	local button = script.SlotTemplate:Clone()
	local listitem = {item.Name, item.Value}
	button.LayoutOrder = 1
	button.Name = item.Name
	button.Value.Value = item.Name .. "::" .. item.Value
	button.Image = "rbxassetid://"..ReplicatedStorage.ItemsInfo.WeaponInfo[item.Name].ItemPicture.Value
	button.Parent = script.Parent.ScrollingFrame 
	table.insert(buttons, button)
	button.MouseButton1Click:Connect(function()
		if itemHover.Visible == false then
			itemHover.Visible = true
			itemHover.NameText.Text = item.Name
			if itemType == "Weapon" then
				itemHover.Stats.Text = "Damage:" .. ReplicatedStorage.ItemsInfo.WeaponInfo[item.Name].Damage.Value
				if button.Value.Value == equippedWeapon.Value then
					itemHover.EquipBtn.Text = "Unequip"
					itemHover.EquipBtn.MouseButton1Click:Connect(function()
						if itemHover.EquipBtn.Text == "Unequip" and button.Value.Value == equippedWeapon.Value then
						UnequipWeaponRemote:FireServer(listitem)
							itemHover.Visible = false
							end
					end)
				elseif button.Value.Value ~= equippedWeapon.Value then
					itemHover.EquipBtn.Text = "Equip"
					itemHover.EquipBtn.MouseButton1Click:Connect(function()
						if itemHover.EquipBtn.Text == "Equip" and equippedWeapon.Value == "" then
						EquipWeaponRemote:FireServer(listitem) 
							itemHover.Visible = false
							end
					end)
				end
			elseif itemType == "Armor" then
				itemHover.Stats.Text = "Health: " .. ReplicatedStorage.ItemsInfo.WeaponInfo[item.Name].HP.Value .."\nDefense:" .. ReplicatedStorage.ItemsInfo.WeaponInfo[item.Name].Defense.Value
				if button.Value.Value == equippedArmor.Value then
					itemHover.EquipBtn.Text = "Unequip"
					itemHover.EquipBtn.MouseButton1Click:Connect(function()
						if itemHover.EquipBtn.Text == "Unequip" and button.Value.Value == equippedArmor.Value then
						UnequipArmorRemote:FireServer(listitem)
							itemHover.Visible = false
							end
					end)
				elseif button.Value.Value ~= equippedArmor.Value then
					itemHover.EquipBtn.Text = "Equip"
					itemHover.EquipBtn.MouseButton1Click:Connect(function()
						if itemHover.EquipBtn.Text == "Equip" and equippedArmor.Value == "" then
						EquipArmorRemote:FireServer(listitem) 
							itemHover.Visible = false
							end
					end)
				end
			end
		else
			itemHover.Visible = false
		end
	end)
end

function createInventory ()
	local playerInventoryLoaded = playerInventory:GetChildren()
	for i = 1, #playerInventoryLoaded do
		addInventoryBtn(playerInventoryLoaded[i])		
		handleWeaponEquip()
		handleArmorEquip()
	end
end

function handleWeaponEquip ()
	print("handleEquip", equippedWeapon.Value)
	if equippedWeapon.Value == "" then
		local weaponBtn = script.Parent.Parent.Char.Weapon
		if weaponBtn.Value.Value == "" then
			return
		end
		weaponBtn.Name = weaponBtn.Value.Value
		weaponBtn.Parent = script.Parent.ScrollingFrame
		weaponBtn = script.Parent.Parent.Char.placeholderWeapon
		weaponBtn.Name = "Weapon"
	else
		local weaponBtn = script.Parent.Parent.Char.Weapon
		for i,btn in pairs(script.Parent.ScrollingFrame:GetChildren()) do
			if btn:IsA("UIGridLayout") then
				continue
			end
			if btn.Value.Value == equippedWeapon.Value then
				btn.Parent = script.Parent.Parent.Char
				btn.Name = weaponBtn.Name
				btn.Position = weaponBtn.Position
				btn.Size = weaponBtn.Size
				weaponBtn.Name = "placeholderWeapon"
			end
		end
	end
end

function handleArmorEquip ()
	print("handleEquip", equippedArmor.Value)
	if equippedArmor.Value == "" then
		local armorBtn = script.Parent.Parent.Char.Armor
		if armorBtn.Value.Value == "" then
			return
		end
		armorBtn.Name = armorBtn.Value.Value
		armorBtn.Parent = script.Parent.ScrollingFrame
		armorBtn = script.Parent.Parent.Char.placeholderArmor
		armorBtn.Name = "Armor"
	else
		local armorBtn = script.Parent.Parent.Char.Armor
		for i,btn in pairs(script.Parent.ScrollingFrame:GetChildren()) do
			if btn:IsA("UIGridLayout") then
				continue
			end
			if btn.Value.Value == equippedArmor.Value then
				btn.Parent = script.Parent.Parent.Char
				btn.Name = armorBtn.Name
				btn.Position = armorBtn.Position
				btn.Size = armorBtn.Size
				armorBtn.Name = "placeholderArmor"
			end
		end
	end
end


function handleAdd (child)
	addInventoryBtn(child)	
end

function backpackRefresh()
	items = {}
	searchInventory()
end

items = {}
searchInventory()
createInventory()

equippedWeapon.Changed:Connect(handleWeaponEquip)
equippedArmor.Changed:Connect(handleArmorEquip)
aftersenditem.OnClientEvent:Connect(handleAdd)
player.Inventory.ChildAdded:connect(handleAdd)
player.Inventory.ChildRemoved:connect(backpackRefresh)

character.ChildAdded:connect(backpackRefresh)
character.ChildRemoved:connect(backpackRefresh)

The part in the Server Script that handles the equipping remotes

EquipWeaponRemote.OnServerEvent:Connect(function(Player, weapon_item)
	local info = Player:WaitForChild("Info")
		AddWeapon(Player, weapon_item)
end)

UnequipWeaponRemote.OnServerEvent:Connect(function(player, weapon_item)

	local info = player:WaitForChild("Info")
	info.Weapon.Value = ""
	player.Character:WaitForChild("Weapon"):Destroy()
end)

EquipArmorRemote.OnServerEvent:Connect(function(Player, armor_item)
	local info = Player:WaitForChild("Info")
	local playerStats = Player:WaitForChild("PlayerStats")
	local defense = playerStats:WaitForChild("Defense")
	local HP = playerStats:WaitForChild("Health")
	local itemDefense = ReplicatedStorage.ItemsInfo.WeaponInfo[armor_item[1]].Defense
	local itemHP = ReplicatedStorage.ItemsInfo.WeaponInfo[armor_item[1]].HP
	local character = Player.Character
	local humanoid = character.Humanoid

	info.Armor.Value = armor_item[1] .."::".. armor_item[2]

	HP.Value += itemHP.Value
	humanoid.MaxHealth = HP.Value

		defense.Value += itemDefense.Value


end)

UnequipArmorRemote.OnServerEvent:Connect(function(Player, armor_item)
	local info = Player:WaitForChild("Info")
	local playerStats = Player:WaitForChild("PlayerStats")
	local defense = playerStats:WaitForChild("Defense")
	local HP = playerStats:WaitForChild("Health")
	local itemDefense = ReplicatedStorage.ItemsInfo.WeaponInfo[armor_item[1]].Defense
	local itemHP = ReplicatedStorage.ItemsInfo.WeaponInfo[armor_item[1]].HP
	local character = Player.Character
	local humanoid = character.Humanoid

	info.Armor.Value = ""
 
	defense.Value -= itemDefense.Value
	HP.Value -= itemHP.Value
	humanoid.MaxHealth = HP.Value
	humanoid.Health = HP.Value

end)

I’m sorry for the long post and thank you for your time!

1 Like

you can use some sort of debounce, when youre equipping the item, set debounce to true. And vice versa

I’m sorry for the late reply, I wasn’t able to do anything yesterday.
I tried to add a debounce in different parts of the script but nothing seems to change, and then I tried adding a debounce for each type of item but no success there too, because somehow, after I unequip an item, all the buttons start to think they all are that item.

Okay, I found out what the problem is and how to solve it, I had to disconnect the function in the equipbtn MouseButton1Click!