Upgrade script rewarding stats everytime player joins the game

I have this upgrades script, and it works as intended (player clicks button, gets stat if player has enough currency) however, when the player leaves and rejoins, it will add stats to the player (refer to video, notice how all stats that have been upgraded at least once will get their values added to when the player rejoins)
https://gyazo.com/eb810e077c889cd7d73d9722864491c0

I know it has something to with the playeradded event but I don’t know how to re format it to work properly

-- Speed
game.Players.PlayerAdded:Connect(function(plr)
	local function updateWalkSpeed()
		local character = plr.Character
		if character then
			local humanoid = character:FindFirstChildOfClass("Humanoid")
			local upgradesFolder = plr:FindFirstChild("Data") and plr.Data:FindFirstChild("Upgrades")

			if humanoid and upgradesFolder then
				local speedValue = upgradesFolder:WaitForChild("Speed").Value

				if speedValue == 0 then
					humanoid.WalkSpeed = 16
				else
					humanoid.WalkSpeed = 8 * speedValue
				end
			end
		end
	end

	plr.CharacterAdded:Connect(updateWalkSpeed)

	local upgradesFolder = plr:WaitForChild("Data"):WaitForChild("Upgrades")
	local speedValue = upgradesFolder:WaitForChild("Speed")
	speedValue:GetPropertyChangedSignal("Value"):Connect(updateWalkSpeed)
end)


--Button Cooldown
local function updateLabel(plr)
	local label = plr:WaitForChild("Data"):WaitForChild("PlayerData").ButtonCooldown -- change this
	local upgradeslabel = plr:WaitForChild("Data"):WaitForChild("Upgrades"):WaitForChild("Button Cooldown") -- change this

	local function update()
		local upgradesValue = tonumber(upgradeslabel.Value) or 0
		if upgradeslabel.Value == 0 then return end
		label.Value = label.Value - 0.05 -- * upgradesValue
	end

	update()
	upgradeslabel.Changed:Connect(update)
end

game.Players.PlayerAdded:Connect(function(plr)
	updateLabel(plr)
end)


--Rune Cooldown
local function updateRuneLabel(plr)
	local label = plr:WaitForChild("Data"):WaitForChild("PlayerData").RuneCooldown -- change this
	local upgradeslabel = plr:WaitForChild("Data"):WaitForChild("Upgrades"):WaitForChild("Rune Cooldown") -- change this

	local function updateRune()
		local upgradesValue = tonumber(upgradeslabel.Value) or 0
		if upgradeslabel.Value == 0 then return end
		label.Value = label.Value - 0.05 -- * upgradesValue
	end

	updateRune()
	upgradeslabel.Changed:Connect(updateRune)
end

game.Players.PlayerAdded:Connect(function(plr)
	updateRuneLabel(plr)
end)


--Luck
local function updateLuckLabel(plr)
	local label = plr:WaitForChild("Data"):WaitForChild("PlayerData").Luck -- change this
	local upgradeslabel = plr:WaitForChild("Data"):WaitForChild("Upgrades"):WaitForChild("Rune Luck") -- change this

	local function updateLuck()
		local upgradesValue = tonumber(upgradeslabel.Value) or 0
		if upgradeslabel.Value == 0 then return end
		label.Value = label.Value + 0.25 -- * upgradesValue
	end

	updateLuck()
	upgradeslabel.Changed:Connect(updateLuck)
end

game.Players.PlayerAdded:Connect(function(plr)
	updateLuckLabel(plr)
end)


--Bulk
local function updateBulkLabel(plr)
	local label = plr:WaitForChild("Data"):WaitForChild("PlayerData").Bulk -- change this
	local upgradeslabel = plr:WaitForChild("Data"):WaitForChild("Upgrades"):WaitForChild("Bulk") -- change this

	local function updateBulk()
		local upgradesValue = tonumber(upgradeslabel.Value) or 0
		if upgradeslabel.Value == 0 then return end
		label.Value = label.Value + 1 -- * upgradesValue
	end

	updateBulk()
	upgradeslabel.Changed:Connect(updateBulk)
end

game.Players.PlayerAdded:Connect(function(plr)
	updateBulkLabel(plr)
end)

You’re doing the same thing with every function. E.g in the above code you create the “updateLuck()” function then instantly run it. So every time a player joins its instantly running the “updateLuck()” function. I’m not sure your reasoning for doing that but simply just remove it for each update function you have.

1 Like

its there so it will update the label within the GUI to display the right amount of times the upgrade was done when the player joins

I’m assuming you have a local script that listens for the value to change → then updates the UI. You can just use that function/code when the script first runs:

E.g:

-- This is client sided (local script)

local MyLuckValue = -- path to your luck value
local function UpdateLabels()
	MyLuckTextLabel.Text = MyLuckValue.Value;	
end;

MyLuckValue.Changed:Connect(function() -- Runs when it changes 
	UpdateLabels()
end);

UpdateLabels() -- Run it instantly

this is the local script it is very confusing, I didn’t make it, so I might not be able to answer any questions you have about it

local repStorage = game:GetService("ReplicatedStorage")
local upgradeEvent = repStorage:WaitForChild("Upgrade")
local upgradeInfo = require(repStorage:WaitForChild("Modules"):WaitForChild("Upgrades"))
local clientFunc = require(repStorage:WaitForChild("Client Storage"):WaitForChild("ClientFunctions"))

local Modules = repStorage:WaitForChild("Modules")

local x = require(Modules.EternityNum)
local player = game.Players.LocalPlayer
local upgradeFolder1, upgradeFolder2 = player:WaitForChild("Data"):WaitForChild("Upgradable"), player:WaitForChild("Data"):WaitForChild("Upgrades")

local SuffixList = { "", "K", "M", "B", "T", "Qa","Qi","Sx","Sp","Oc","No","D","Ud","Dd","Td","QaD","QiD","SxD","SpD","OcD","NoD","Vgt","goog","Inf" }

local names = {"K", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", "Oc", "No", "Dd", "Ud", "Dd", "Td", "Qad", "Qid", 
	"Sxd", "Spd", "Ocd", "Nod", "Vg", "Uvg", "Dvg", "Tvg", "Qavg", "Qivg", "Sxvg", "Spvg", "Ocvg"}
local pows = {}
for i = 1, #names do table.insert(pows, 1000^i) end

local function formatNumber(x: number): string 
	local ab = math.abs(x)

	if ab < 1000 then return string.format("%.2f", ab) end 
	local p = math.min(math.floor(math.log10(ab)/3), #names)
	local num = math.floor(ab/pows[p]*100)/100
	return num*math.sign(x)..names[p]
end

_G.AbrevNum = function(value, idp, e)
	idp = ((not idp) and (value>=1000)) and 1 or (not idp) and 0 or idp
	local exp = math.floor(math.log(math.max(1, math.abs(value)), 1000))
	local suffix = SuffixList[1 + exp] or ("e+" .. exp)
	return ("%." .. idp .. "f%s"):format((math.floor(value * ((10 ^ idp) / (1000 ^ exp))) / (10 ^ idp)), suffix)
end



function output(text, Color, toFrame)

	toFrame = toFrame or script.Parent.Parent.Parent.Parent.Parent.ErrorText
	toFrame.Text = text or "Error: Unkown"
	toFrame.TextColor3 = Color or Color3.new(1, 0, 0)
	toFrame.Visible = true
	task.wait(2)
	toFrame.Visible = false
end

task.wait(2)
for _, frame in script.Parent:GetChildren() do
	if not frame:IsA("Frame") then continue end

	local statsValue = upgradeFolder1:FindFirstChild(frame.Name) or upgradeFolder2:FindFirstChild(frame.Name)
	local info = upgradeInfo.Upgrades[frame.Name]
	if not statsValue or not info then warn(frame, "was not found") continue end
	local function upd()
		frame.Progress.Text = ('%s/%s'):format(statsValue.Value, info.Max)
		local max = statsValue.Value >= info.Max
		local price = upgradeInfo.getPrice(frame.Name,statsValue.Value)
		frame.Price.Price.Text = max and "Max" or _G.AbrevNum(upgradeInfo.getPrice(frame.Name,statsValue.Value)).. " Tokens"
		frame.TextButton.BackgroundColor3 = max and Color3.new(1, 0, 0) or (x.le((player:WaitForChild("Data").Stats.Tokens.Value), price) and Color3.new(1, 0, 0) or Color3.new(0, 1, 0))

end
	upd()
	statsValue.Changed:Connect(upd)
	player:WaitForChild("Data").Stats.Tokens.Changed:Connect(upd) -- dasd

	frame.TextButton.Activated:Connect(function()
		local s, msg = upgradeEvent:InvokeServer(frame.Name)
		if not s then
			clientFunc.global_sounds.err:Play()
			output(msg, Color3.new(1,1,1))
		else
			clientFunc.global_sounds.success:Play()
		end
	end)
end

What you posted should already update the values when the player joins. Are you referencing the right folder?

You have 2 folder names:

Did you change the name of the upgrade folder?

the upgrades folder just stores how many of each upgrade the player has