So I have a local script that has a function, and inside of that function there is a for, i loop which is:
for i, tower in pairs(towers) do
Inside of that, I have a function for when a gui button is activated:
newButton.Activated:Connect(function()
Inside of that function, I have some more lines a ways down that says:
buyButton.Activated:Connect(function()
interactItem(tower.Name)
print("Interacted")
end)
So, the newButton.Activated function opens a gui with a buyButton in it, which is where the buyButton is located. However, whenever I go to test, and I click the buyButton, this shows in my output:
As you can see, the function keeps calling multiple times and each time it’s called it increases by 1. I’m not exactly sure how to fix this or what is causing the issue. I’m guessing it’s probably because of the for i, loop, but I want to make sure before I mess around and ruin my script.
In case this has anything to do with it, in a server script I have the interactItem function being called (which is inside of the buyButton.Activated function, so the interactItem function calls when the buyButton is activated). Here is the interactItem function being called:
ReplicatedStorage.InteractItem.OnServerInvoke = function(player, itemName)
there is a for, i loop … Inside of that, I have a function
it sounds like your events are inside of the for loop which would be the reason it’ll fire multiple times
could you paste the code normally instead of breaking it up so we can see it properly
function updateItems()
limit.Text = #playerData.SelectedTowers .. "/5"
for i, tower in pairs(towers) do
local df = gui.Container:FindFirstChild("DisplayFrame")
local buyButton = df:FindFirstChild("BuyButton")
local buyPrompt = df:FindFirstChild("BuyPrompt")
local sf = df:FindFirstChild("StatsFrame")
local oldButton = itemsFrame:FindFirstChild(tower.Name)
if oldButton then
oldButton:Destroy()
end
local newButton = itemsFrame.TemplateButton:Clone()
newButton.Name = tower.Name
newButton.TowerName.Text = tower.Name
newButton.Image = tower.ImageAsset
newButton.Visible = true
newButton.LayoutOrder = tower.Price
newButton.Parent = itemsFrame
local status = getItemStatus(tower.Name)
if status == "For Sale" then
newButton.Status.Text = "$" .. comma(tower.Price)
elseif status == "Equipped" then
newButton.Status.Text = "✅ Equipped"
newButton.Status.TextColor3 = Color3.new(0,0,0)
newButton.BackgroundColor3 = Color3.new(0,0,0)
else
newButton.Status.Text = ""
end
newButton.Activated:Connect(function()
local towerObject = towerFolder:FindFirstChild(tower.Name):Clone()
local viewportFrame = gui.Container.DisplayFrame.ViewportFrame
local worldModel = viewportFrame.WorldModel
local dfStatus = getItemStatus(tower.Name)
if dfStatus == "For Sale" then
buyButton.Text = "$" .. comma(tower.Price)
buyButton.TextColor3 = Color3.new(0, 0.666667, 0)
buyPrompt.Visible = true
elseif dfStatus == "Equipped" then
buyButton.Text = "Owned"
buyButton.TextColor3 = Color3.new(0.784314, 0.784314, 0.784314)
buyButton.BackgroundColor3 = Color3.new(0,0,0)
buyPrompt.Visible = false
else
buyButton.Text = "✅ Equipped"
buyButton.TextColor3 = Color3.new(0.666667, 1, 1)
buyButton.BackgroundColor3 = Color3.new(0,0,0)
buyPrompt.Visible = false
end
df:FindFirstChild("Name").Text = tower.Name
df:FindFirstChild("GoldPrice").Text = "$" .. towerFolder:FindFirstChild(tower.Name).Config.Price.Value
sf.CooldownFrame:FindFirstChild("Title").Text = towerFolder:FindFirstChild(tower.Name).Config.Cooldown.Value
sf.DamageFrame:FindFirstChild("Title").Text = towerFolder:FindFirstChild(tower.Name).Config.Damage.Value
sf.RangeFrame:FindFirstChild("Title").Text = towerFolder:FindFirstChild(tower.Name).Config.Range.Value
worldModel:ClearAllChildren()
towerObject.Parent = worldModel
local Camera = Instance.new("Camera")
Camera.Parent = viewportFrame
viewportFrame.CurrentCamera = Camera
Camera.CFrame = CFrame.new(towerObject.PrimaryPart.Position + towerObject.PrimaryPart.CFrame.LookVector * 3.5, towerObject.PrimaryPart.Position)
Camera.CFrame = towerObject.PrimaryPart.CFrame * CFrame.Angles(0, math.rad(-195), 0) * CFrame.new(0,0,3.5)
local outline = ReplicatedStorage.Misc:FindFirstChild("TowerOutline"):Clone()
outline.Parent = towerObject
playAnimation(towerObject, "Idle")
buyButton.Activated:Connect(function()
interactItem(tower.Name)
print("Interacted")
end)
end)
end
end
That’s the whole function, by the way I know that’s the reason it fires multiple times, but I can’t figure out an alternative to the code I have to fix it.
you need to take your events out of the for loop
function updateItems()
limit.Text = #playerData.SelectedTowers .. "/5"
for i, tower in pairs(towers) do
local df = gui.Container:FindFirstChild("DisplayFrame")
local buyButton = df:FindFirstChild("BuyButton")
local buyPrompt = df:FindFirstChild("BuyPrompt")
local sf = df:FindFirstChild("StatsFrame")
local oldButton = itemsFrame:FindFirstChild(tower.Name)
if oldButton then
oldButton:Destroy()
end
local newButton = itemsFrame.TemplateButton:Clone()
newButton.Name = tower.Name
newButton.TowerName.Text = tower.Name
newButton.Image = tower.ImageAsset
newButton.Visible = true
newButton.LayoutOrder = tower.Price
newButton.Parent = itemsFrame
local status = getItemStatus(tower.Name)
if status == "For Sale" then
newButton.Status.Text = "$" .. comma(tower.Price)
elseif status == "Equipped" then
newButton.Status.Text = "✅ Equipped"
newButton.Status.TextColor3 = Color3.new(0,0,0)
newButton.BackgroundColor3 = Color3.new(0,0,0)
else
newButton.Status.Text = ""
end
end
newButton.Activated:Connect(function()
local towerObject = towerFolder:FindFirstChild(tower.Name):Clone()
local viewportFrame = gui.Container.DisplayFrame.ViewportFrame
local worldModel = viewportFrame.WorldModel
local dfStatus = getItemStatus(tower.Name)
if dfStatus == "For Sale" then
buyButton.Text = "$" .. comma(tower.Price)
buyButton.TextColor3 = Color3.new(0, 0.666667, 0)
buyPrompt.Visible = true
elseif dfStatus == "Equipped" then
buyButton.Text = "Owned"
buyButton.TextColor3 = Color3.new(0.784314, 0.784314, 0.784314)
buyButton.BackgroundColor3 = Color3.new(0,0,0)
buyPrompt.Visible = false
else
buyButton.Text = "✅ Equipped"
buyButton.TextColor3 = Color3.new(0.666667, 1, 1)
buyButton.BackgroundColor3 = Color3.new(0,0,0)
buyPrompt.Visible = false
end
df:FindFirstChild("Name").Text = tower.Name
df:FindFirstChild("GoldPrice").Text = "$" .. towerFolder:FindFirstChild(tower.Name).Config.Price.Value
sf.CooldownFrame:FindFirstChild("Title").Text = towerFolder:FindFirstChild(tower.Name).Config.Cooldown.Value
sf.DamageFrame:FindFirstChild("Title").Text = towerFolder:FindFirstChild(tower.Name).Config.Damage.Value
sf.RangeFrame:FindFirstChild("Title").Text = towerFolder:FindFirstChild(tower.Name).Config.Range.Value
worldModel:ClearAllChildren()
towerObject.Parent = worldModel
local Camera = Instance.new("Camera")
Camera.Parent = viewportFrame
viewportFrame.CurrentCamera = Camera
Camera.CFrame = CFrame.new(towerObject.PrimaryPart.Position + towerObject.PrimaryPart.CFrame.LookVector * 3.5, towerObject.PrimaryPart.Position)
Camera.CFrame = towerObject.PrimaryPart.CFrame * CFrame.Angles(0, math.rad(-195), 0) * CFrame.new(0,0,3.5)
local outline = ReplicatedStorage.Misc:FindFirstChild("TowerOutline"):Clone()
outline.Parent = towerObject
playAnimation(towerObject, "Idle")
end)
buyButton.Activated:Connect(function()
interactItem(tower.Name)
print("Interacted")
end)
end
So, what would I do to call the cloned newButton? Also without the for loop how am I supposed to call the tower etc.?
you’re right i realized you’re making new buttons
how many times are you calling `updateItems’ function
I call it twice. Once when the shop is opened, which is what all of this is in, and once when the interactItem function is called:
local function interactItem(itemName)
local data = interactItemFunc:InvokeServer(itemName)
if data then
playerData = data
updateItems()
end
end
I was looking at the GuiButton Documentation and i think you should use .MouseButton1Click
instead of .Activated, as it will only play once, but even if that doesn’t work then you should try replacing the :Connect() with :Once().