Creating a summoning feature like Toilet Tower Defense, All Star Tower Defense(Im getting a glitch with my inventory)

So I want to make a summoning feature like Toilet Tower Defense, All Star Tower Defense with an inventory

The issue that Im getting is not being able to Unequip towers and also not being to Unequip towers Once I reach 5 towers because they keep Replacing Look at this video and output image for better details

I have tried multiple ways of fixing such as looking at other ways people make inventorys in the developer forum which failed and ended in more bugs, tryed to fix my logic a bit but Idk why it dosen’t go away… Im not asking for full scripts just tell me a way to solve this issue

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local items = {
	{Name = "Brute", Rarity = "Common", Percentage = 50},
	{Name = "Samurai", Rarity = "Rare", Percentage = 30},
	{Name = "Rocker", Rarity = "Epic", Percentage = 15},
	{Name = "Wizard", Rarity = "Epic", Percentage = 15},
	{Name = "Slinger", Rarity = "Legendary", Percentage = 5},
}

local gui = script.Parent
local inventoryMenu = gui.InventoryFrame
local openInventory = gui.InventoryOpen
local summonOne = gui.SummonButtonOne
local summonTen = gui.SummonButtonTen

local summonCost = 100 
local summonTenCost = 900
local cooldownTime = 1 

local templateButton = gui.InventoryFrame.ScrollingFrame.Template 
local equippedSlots = {} -- Table to store equipped towers
local cooldowns = {} -- Table to store cooldowns for each tower
local towerCounters = {} -- Table to store the count of each tower type

local function generateUniqueID(towerName)
	if not towerCounters[towerName] then
		towerCounters[towerName] = 1
	else
		towerCounters[towerName] = towerCounters[towerName] + 1
	end
	return towerName .. "_" .. towerCounters[towerName]
end

local function isTowerEquipped(uniqueTowerName)
	for _, equippedTower in ipairs(equippedSlots) do
		if equippedTower.Name == uniqueTowerName then
			return true
		end
	end
	return false
end

local function getEquippedTowerIndex(uniqueTowerName)
	for i, equippedTower in ipairs(equippedSlots) do
		if equippedTower.Name == uniqueTowerName then
			return i
		end
	end
	return nil
end



local function unequipTower(uniqueTowerName, currentTime)
	for i, equippedTower in ipairs(equippedSlots) do
		if equippedTower.Name == uniqueTowerName then
			table.remove(equippedSlots, i)
			print("Unequipped tower:", uniqueTowerName)

			local equippedSlot = gui.TowersInventory:FindFirstChild("TowerSlot" .. i)
			if equippedSlot then
				equippedSlot.Image = ""
				equippedSlot.Visible = false
			end

			cooldowns[uniqueTowerName] = currentTime
			return
		end
	end
end


local function createInventoryButton(item, index)
	local button = templateButton:Clone()
	button.Name = item.Name
	button.Image = item:WaitForChild("Config").Image.Texture
	button.Parent = gui.InventoryFrame.ScrollingFrame
	button.Visible = true

	button.MouseButton1Click:Connect(function()
		local currentTime = tick()
		local towerName = item.Name

		if cooldowns[towerName] and currentTime - cooldowns[towerName] < cooldownTime then
			print("Tower is on cooldown.")
			return
		end

		local uniqueTowerName = generateUniqueID(towerName)

		if isTowerEquipped(uniqueTowerName) then
			unequipTower(uniqueTowerName, currentTime)
			return
		end

		if #equippedSlots >= 5 then
			warn("Cannot equip more than 5 towers.")
			return
		end

		-- Check if a tower with the same base name is already equipped
		local baseTowerName = towerName
		for _, equippedTower in ipairs(equippedSlots) do
			if equippedTower.Name:match("^" .. baseTowerName .. "_") then
				-- Replace the existing tower with the new one
				equippedTower.Name = uniqueTowerName
				equippedTower.Image = button.Image
				print("Replaced tower:", uniqueTowerName)

				-- Update the corresponding slot in TowersInventory
				local equippedSlot = gui.TowersInventory:FindFirstChild("TowerSlot" .. "_")
				if equippedSlot then
					equippedSlot.Image = button.Image
				end

				-- Set cooldown for the tower
				cooldowns[towerName] = currentTime
				return
			end
		end

		-- Equip the tower
		local newTower = {Name = uniqueTowerName, Image = button.Image}
		table.insert(equippedSlots, newTower)
		print("Equipped tower:", uniqueTowerName)

		-- Assign tower to the corresponding empty slot in TowersInventory
		local equippedSlot = gui.TowersInventory:FindFirstChild("TowerSlot" .. #equippedSlots)
		if equippedSlot then
			equippedSlot.Image = button.Image
			equippedSlot.Visible = true
		end

		-- Set cooldown for the tower
		cooldowns[towerName] = currentTime
	end)
end

openInventory.MouseButton1Up:Connect(function()
	-- Clear existing inventory buttons
	for _, button in ipairs(gui.InventoryFrame.ScrollingFrame:GetChildren()) do
		if button:IsA("ImageButton") then
			button:Destroy()
		end
	end

	-- Populate inventory buttons
	local playerInventory = Players.LocalPlayer:WaitForChild("PlayerData"):WaitForChild("Inventory")
	for index, item in ipairs(playerInventory:GetChildren()) do
		if item:IsA("Model") then
			createInventoryButton(item, index)
		end
	end

	inventoryMenu.Visible = not inventoryMenu.Visible
end)

local function canSummonOnce(playerGold)
	return playerGold >= summonCost
end

local function deductGold(playerGold)
	return playerGold - summonCost
end

local function summonOnce()
	local playerGold = Players.LocalPlayer:WaitForChild("leaderstats").Money.Value

	if not canSummonOnce(playerGold) then
		warn("Not enough gold to summon once.")
		return
	end

	playerGold = deductGold(playerGold)
	Players.LocalPlayer:WaitForChild("leaderstats").Money.Value = playerGold

	if playerGold < 0 then
		playerGold = 0
		Players.LocalPlayer:WaitForChild("leaderstats").Money.Value = playerGold
		warn("Player's gold went below 0. Set to 0.")
	end

	local totalPercentage = 0
	for _, item in ipairs(items) do
		totalPercentage = totalPercentage + item.Percentage
	end

	local randomNumber = math.random(1, totalPercentage)
	local selectedTower
	local accumulatedPercentage = 0
	for _, item in ipairs(items) do
		accumulatedPercentage = accumulatedPercentage + item.Percentage
		if randomNumber <= accumulatedPercentage then
			selectedTower = item
			break
		end
	end

	if not selectedTower then
		warn("Failed to select tower.")
		return
	end

	local towerModel = ReplicatedStorage.Items[selectedTower.Rarity]:FindFirstChild(selectedTower.Name)
	if not towerModel then
		warn("Tower model not found.")
		return
	end

	local playerInventory = Players.LocalPlayer:WaitForChild("PlayerData"):WaitForChild("Inventory")
	local existingTower = playerInventory:FindFirstChild(selectedTower.Name) -- Check if tower already exists
	local newTower
	if existingTower then
		newTower = existingTower:Clone()
	else
		newTower = towerModel:Clone()
	end

	newTower.Name = generateUniqueID(selectedTower.Name) -- Assign the unique name
	newTower.Parent = playerInventory

	createInventoryButton(newTower, #playerInventory:GetChildren())
end

summonOne.MouseButton1Up:Connect(summonOnce)

local function summonTens()
	local playerGold = Players.LocalPlayer:WaitForChild("leaderstats").Money.Value

	if not canSummonOnce(playerGold) then
		warn("Not enough gold to summon ten times.")
		return
	end

	playerGold -= summonTenCost
	Players.LocalPlayer:WaitForChild("leaderstats").Money.Value = playerGold

	for i = 1, 10 do
		if playerGold < 0 then
			playerGold = 0
			break
		end

		Players.LocalPlayer:WaitForChild("leaderstats").Money.Value = playerGold

		local totalPercentage = 0
		for _, item in ipairs(items) do
			totalPercentage = totalPercentage + item.Percentage
		end

		local randomNumber = math.random(1, totalPercentage)
		local selectedTower
		local accumulatedPercentage = 0
		for _, item in ipairs(items) do
			accumulatedPercentage = accumulatedPercentage + item.Percentage
			if randomNumber <= accumulatedPercentage then
				selectedTower = item
				break
			end
		end

		if not selectedTower then
			warn("Failed to select tower.")
			return
		end

		local towerModel = ReplicatedStorage.Items[selectedTower.Rarity]:FindFirstChild(selectedTower.Name)
		if not towerModel then
			warn("Tower model not found.")
			return
		end

		local playerInventory = Players.LocalPlayer:WaitForChild("PlayerData"):WaitForChild("Inventory")
		local existingTower = playerInventory:FindFirstChild(selectedTower.Name) -- Check if tower already exists
		local newTower
		if existingTower then
			newTower = existingTower:Clone()
		else
			newTower = towerModel:Clone()
		end

		newTower.Name = generateUniqueID(selectedTower.Name) -- Assign the unique name
		newTower.Parent = playerInventory

		createInventoryButton(newTower, #playerInventory:GetChildren())
	end

	print("Summoned ten times. Player's remaining gold:", playerGold)
end

summonTen.MouseButton1Up:Connect(summonTens)

Thx for any help

add a counter to when its >4 it wont allow any adding of more towers, it should fix it, and let me know what it outputs with this fix.

1 Like

so hello, I wanted to ask where exactly should I add the counter? I’ve added it into unequipTower but it dosen’t seem to do anything
the output is the same

same script, thats easiest and best, do something like:

local amount = 0
toweradded:Connect(Function() amount += 1
end)
towerremoved:Connect(Function() amount -= 1
end)
If amount < 5 then
    --put code here for adding another!
else
    print("to much towers!")
end
2 Likes

alright this seems to work but I still cannot Unequip towers before or after reaching 5 towers because it is constantly refreshing/replacing the tower name making it unable to unequip


this is the output

local towerAdded = Instance.new("BindableEvent")
local towerRemoved = Instance.new("BindableEvent")

local function createInventoryButton(item, index)
	local button = templateButton:Clone()
	button.Name = item.Name
	button.Image = item:WaitForChild("Config").Image.Texture
	button.Parent = gui.InventoryFrame.ScrollingFrame
	button.Visible = true

	button.MouseButton1Click:Connect(function()
		local currentTime = tick()
		local towerName = item.Name

		if cooldowns[towerName] and currentTime - cooldowns[towerName] < cooldownTime then
			print("Tower is on cooldown.")
			return
		end

		local uniqueTowerName = generateUniqueID(towerName)

		if isTowerEquipped(uniqueTowerName) then
			unequipTower(uniqueTowerName, currentTime)
			return
		end


		if #equippedSlots >= 5 then
			warn("Cannot equip more than 5 towers.")
			return
		end

		-- Check if a tower with the same base name is already equipped
		local baseTowerName = towerName
		for _, equippedTower in ipairs(equippedSlots) do
			if equippedTower.Name:match("^" .. baseTowerName .. "_") then
				-- Replace the existing tower with the new one
				equippedTower.Name = uniqueTowerName
				equippedTower.Image = button.Image
				print("Replaced tower:", uniqueTowerName)

				-- Update the corresponding slot in TowersInventory
				local equippedSlot = gui.TowersInventory:FindFirstChild("TowerSlot" .. "_")
				if equippedSlot then
					equippedSlot.Image = button.Image
				end

				-- Set cooldown for the tower
				cooldowns[towerName] = currentTime
				return
			end
		end

		local amount = 0
		towerAdded.Event:Connect(function() amount += 1 towerAdded:Fire()
		end)
		
		towerRemoved.Event:Connect(function() amount -= 1 towerRemoved:Fire()

		end)

		if amount < 5 then
			local newTower = {Name = uniqueTowerName, Image = button.Image}
			table.insert(equippedSlots, newTower)
			print("Equipped tower:", uniqueTowerName)

		elseif amount >= 1 and towerName == uniqueTowerName then
			unequipTower()
		else
			print("to much towers!")
		end

		-- Assign tower to the corresponding empty slot in TowersInventory
		local equippedSlot = gui.TowersInventory:FindFirstChild("TowerSlot" .. #equippedSlots)
		if equippedSlot then
			equippedSlot.Image = button.Image
			equippedSlot.Visible = true
		end

		-- Set cooldown for the tower
		cooldowns[towerName] = currentTime
	end)
end

this is where I’ve made the change, also I had to use a event in order to be able to use the Connect:(function()

if I didn’t it wouldn’t allow me to, if u got any more ideas as to how I could make this work It would help, I also tried some other stuff before events but it was just not equiping at all