So pretty much whenever I first go into my in-game shop everything is normal until I click out of it then come back then everything I buy then doubles and then again and again. I have no clue why, I will put my whole code in here. Am I missing something? Please help, much appreciated.
ReplicatedStorage.Remotes.UIRemotes.UI_BoardStart.OnClientEvent:Connect(function(TeamName)
local Tycoon = Workspace:WaitForChild("Tycoon").Tycoons:WaitForChild(TeamName)
local Board = Tycoon.PurchasedObjects.Office.Whiteboard
local BoardCam = Board.BoardCamera
local PlayerName = LocalPlayer.Name
local Owner = Tycoon.TycoonInfo.Owner
if Owner.Value.Name == PlayerName then
Camera.CameraType = Enum.CameraType.Scriptable
--// Some Presets
MainFrame.TeamName.Text = LocalPlayer.ValuesGame.TeamName.Value
--// Labels
MainFrame.Exit.MouseButton1Click:Connect(function(plr)
ClickUI:Play()
MainFrame.Visible = false
Camera.CameraType = Enum.CameraType.Custom
Camera.CameraSubject = LocalPlayer.Character.Humanoid
end)
MainFrame.PassButton.MouseButton1Click:Connect(function(plr) -- PASS PURCHASE ATTRIBUTES SCREEN
ClickUI:Play()
MainFrame.PassPurchase.Visible = true
end)
MainFrame.PassPurchase.Purchase.MouseButton1Click:Connect(function(plr)
if LocalPlayer.ValuesGame.Team.PassGame.Value >= 10 then
print("Pass Game Maxed Out")
MainFrame.PassPurchase.PurchaseLabel.Text = "Your pass attributes are maxed out!"
task.wait(3)
MainFrame.PassPurchase.PurchaseLabel.Text = "Purchase 1 Pass Attribute For ".. CurrentPassCost .. " Cash?"
else
if LocalPlayer.leaderstats.Cash.Value <= CurrentPassCost then
ErrorUI:Play()
MainFrame.PassPurchase.PurchaseLabel.Text = "You cannot afford an attribute!"
task.wait(3)
MainFrame.PassPurchase.PurchaseLabel.Text = "Purchase 1 Pass Attribute For ".. CurrentPassCost .. " Cash?"
else
ReplicatedStorage.Remotes.Tycoon_Function_Remotes.White_Board.PurchasePassAttribute:FireServer(CurrentPassCost,TeamName)
print("" ..LocalPlayer.Name.. " Purchased an attribute for ".. CurrentPassCost .. "")
MainFrame.PassPurchase.Visible = false
SoundService.PurchaseCompleted:Play()
-- MainFrame.PassPurchase.Visible = false
end
end
end)
MainFrame.PassPurchase.Decline.MouseButton1Click:Connect(function(plr)
ClickUI:Play()
MainFrame.PassPurchase.Visible = false
end)
--===
MainFrame.RunButton.MouseButton1Click:Connect(function(plr) -- PASS PURCHASE ATTRIBUTES SCREEN
ClickUI:Play()
MainFrame.RunPurchase.Visible = true
end)
MainFrame.RunPurchase.Purchase.MouseButton1Click:Connect(function(plr)
if LocalPlayer.ValuesGame.Team.RunGame.Value >= 10 then
print("Pass Game Maxed Out")
MainFrame.RunPurchase.PurchaseLabel.Text = "Your run attributes are maxed out!"
task.wait(3)
MainFrame.RunPurchase.PurchaseLabel.Text = "Purchase 1 Run Attribute For ".. CurrentPassCost .. " Cash?"
else
if LocalPlayer.leaderstats.Cash.Value <= CurrentPassCost then
ErrorUI:Play()
MainFrame.RunPurchase.PurchaseLabel.Text = "You cannot afford an attribute!"
task.wait(3)
MainFrame.RunPurchase.PurchaseLabel.Text = "Purchase 1 Run Attribute For ".. CurrentPassCost .. " Cash?"
else
ReplicatedStorage.Remotes.Tycoon_Function_Remotes.White_Board.PurchaseRunAttribute:FireServer(CurrentPassCost,TeamName)
print("" ..LocalPlayer.Name.. " Purchased an attribute for ".. CurrentPassCost .. "")
MainFrame.RunPurchase.Visible = false
SoundService.PurchaseCompleted:Play()
-- MainFrame.PassPurchase.Visible = false
end
end
end)
MainFrame.RunPurchase.Decline.MouseButton1Click:Connect(function(plr)
ClickUI:Play()
MainFrame.RunPurchase.Visible = false
end)
--//
local CamTweenBoard = TweenService:Create(Camera,TweenInfo.new(
1,
Enum.EasingStyle.Quad,
Enum.EasingDirection.In),
{
CFrame = BoardCam.CFrame
})
SoundService.Chalk:Play()
CamTweenBoard:Play()
CamTweenBoard.Completed:Wait()
MainFrame.Visible = true
end
end)
You are binding all your UI events every time UI_BoardStart.OnClientEvent is triggered. Every time this event is triggered, you will have another set duplicate of UI events.
You would have to assign all the event connections (RBXScriptConnection) into accessible variables or some shared table and disconnect them when you no longer need them to trigger.
However, it is likely a better approach to simply connect your UI events once and instead use some shared state to allow/disallow the events to have any effect.
What is the purpose of the UI_BoardStart RemoteEvent? When and why is it triggered by the server?
When the player buys something from the client side using the shop, it then sends a remote event to the server to take their cash (leaderstats) using this code in serverscript service (teamname is the name of the players tycoon which is also the name of the players folder where the money is stored in the server)
ReplicatedStorage.Remotes.Tycoon_Function_Remotes.White_Board.PurchasePassAttribute.OnServerEvent:Connect(function(plr, CurrentPassCost, TeamName)
if plr.leaderstats.Cash.Value <= CurrentPassCost then
-- Player Doesn't Have Enough Cash
print("player doesn't have enough cash")
ReplicatedStorage.Remotes.Tycoon_Function_Remotes.White_Board.PurchaseNo:FireClient(plr)
else
local tcnInfo = Workspace:WaitForChild("Tycoon").Tycoons:FindFirstChild(TeamName):WaitForChild("TycoonInfo")
local cash = game.ServerStorage:WaitForChild("PlayerCash"):FindFirstChild(tcnInfo.Owner.Value.Name)
cash.Value -= CurrentPassCost
plr.ValuesGame.Team.PassGame.Value += 1
ReplicatedStorage.Remotes.Tycoon_Function_Remotes.White_Board.PurchasePassAttribute:FireClient(plr)
--print("" ..plr.Name.. " Purchased an attribute for ".. CurrentPassCost .. "")
end
end)
ReplicatedStorage.Remotes.Tycoon_Function_Remotes.White_Board.PurchaseRunAttribute.OnServerEvent:Connect(function(plr, CurrentPassCost, TeamName)
if plr.leaderstats.Cash.Value <= CurrentPassCost then
-- Player Doesn't Have Enough Cash
print("player doesn't have enough cash")
ReplicatedStorage.Remotes.Tycoon_Function_Remotes.White_Board.PurchaseNo1:FireClient(plr)
else
local tcnInfo = Workspace:WaitForChild("Tycoon").Tycoons:FindFirstChild(TeamName):WaitForChild("TycoonInfo")
local cash = game.ServerStorage:WaitForChild("PlayerCash"):FindFirstChild(tcnInfo.Owner.Value.Name)
cash.Value -= CurrentPassCost
plr.ValuesGame.Team.RunGame.Value += 1
ReplicatedStorage.Remotes.Tycoon_Function_Remotes.White_Board.PurchaseRunAttribute:FireClient(plr)
--print("" ..plr.Name.. " Purchased an attribute for ".. CurrentPassCost .. "")
end
end)
this is to determine the players tycoon which the players cash is set up in serverstorage and then subtracts that amount from their leaderstats which is how I set up the tycoon aspect of the game.
I use teamname from the proximity prompt to bring it over to the client for the most simple way under my knowledge of coding so far, must be an easier way, im trying to figure out how to make it so these don’t double which with what you said before is pretty self explanatory. But currently I don’t know how to fix it.
(edit)
teamname has no significant changes to the shop other than bringing the value of the purchase to the server to take the players cash.
When you connect to an event (RBXScriptSignal), using the :Connect() method, it returns a RBXScriptConnection. This instance has the method :Disconnect() which can be used to remove the function bound to the event.
local part = Instance.new("Part", workspace)
local partTouchedSignal = part.Touched:Connect(function()
print("Part touched")
end)
task.wait(30)
partTouchedSignal:Disconnect() --After 30 seconds, "Part touched" will no longer print even when the Part is touched.
Although this is a bit unorthodox, this approach could technically be used to connect your UI events (after the RemoteEvent is triggered) and disconnect them (after the shop is closed).