Text not updating to the current saved data upon respawn/reloading into game

I my game I have a stat system where a user can increase their Attack, Special and Defence stats by using points they get when they level up.
The points a user has and the level they are get saved however when I leave the game and come back the text says they are 0 even though they are not. The only way the text updates to the correct level/how many points a user has in only when I get another point from leveling up and use it on one of the stats. I’m not sure how to make the text show the current points/stat level a player is.

I left the game and the points show 0 and level for Attack shows 1 when it should be level 2 and 1 point.

I had to get another point to use it on Attack which should already say Level 2 but only says level 1. When I use the point on Attack it then goes from Level 1 to level 3.
After I get and use the point

below are some of the scripts I have been using. I’m fairly new to scripting so have been using resources like the forums, youtube and the roblox / AI assistant. Also this was a already created stat system I just make it more of my own in how I wanted it to look/be.

Scripts:

Local Script in StatsButton

local ReplicatedStorage = game:GetService("ReplicatedStorage")  
local remoteEvent = ReplicatedStorage:WaitForChild("LeveledUp")
local remoteFunction = ReplicatedStorage:WaitForChild("IncreaseStats")
local savePointsEvent = ReplicatedStorage:WaitForChild("SavePoints")  -- Correct event name

local button = script.Parent
local statsFrame = button.Parent:WaitForChild("StatsFrame")  -- Ensure StatsFrame exists
local player = game.Players.LocalPlayer
local points = statsFrame:WaitForChild("Points")  -- Ensure Points label exists

-- Show stats frame when the Stats button is clicked
button.MouseButton1Down:Connect(function()
	statsFrame.Visible = true
end)

-- Hide stats frame when the Close button is clicked
local close = statsFrame:FindFirstChild("Close")  -- Ensure Close button exists
if close then
	close.MouseButton1Down:Connect(function()
		statsFrame.Visible = false
	end)
else
	warn("Close button not found in StatsFrame!")  -- Debugging line if Close button is missing
end

-- Update the points display when the player levels up
local function onLeveledUp()
	points.Text = "Points: " .. player.Points.Value  -- Update points from player's Points
end

-- Connect the leveled-up event to update the points label
remoteEvent.OnClientEvent:Connect(onLeveledUp)

-- Handle stat increases for each Plus button
for _, plusButton in pairs(statsFrame.PlusFolder:GetChildren()) do
	plusButton.MouseButton1Down:Connect(function()
		if player.Points.Value > 0 then  -- Check if there are points to spend
			-- Call the server to increase the corresponding stat
			local pointsValue, statValue = remoteFunction:InvokeServer(plusButton.Name)

			-- Update points display after stat change
			if pointsValue then
				points.Text = "Points: " .. pointsValue
			end

			-- Update the stat level display
			local levelFolder = statsFrame.LevelFolder
			local levelLabel = levelFolder:FindFirstChild(plusButton.Name)
			if levelLabel then
				levelLabel.Text = "Lv." .. statValue
			end

			-- Save the updated points value to the server
			local successSavePoints, errorMessage = pcall(function()
				savePointsEvent:FireServer(player.Points.Value)
			end)

			-- Log an error if saving points fails
			if not successSavePoints then
				warn("Failed to save points:", errorMessage)
			end
		else
			print("Not enough points to increase", plusButton.Name)
		end
	end)
end

ServerScript:

local DataStoreService = game:GetService("DataStoreService")
local pointsDataStore = DataStoreService:GetDataStore("PlayerPointsDataStore")
local statsDataStore = DataStoreService:GetDataStore("PlayerStatsDataStore")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local loadStatsEvent = ReplicatedStorage:WaitForChild("LoadStats")  -- RemoteEvent to notify client

game.Players.PlayerAdded:Connect(function(player)
	-- Try loading player data
	local success, points = pcall(function()
		return pointsDataStore:GetAsync(player.UserId)
	end)

	if success and points then
		player:SetAttribute("Points", points)
	else
		-- Default to 0 if no data is found
		player:SetAttribute("Points", 0)
	end

	-- Load saved stats for the player
	local success, stats = pcall(function()
		return statsDataStore:GetAsync(player.UserId)
	end)

	if success and stats then
		for statName, statValue in pairs(stats) do
			local stat = player:FindFirstChild(statName)
			if stat then
				stat.Value = statValue
			end
		end
	else
		-- Default to 1 for all stats if no data is found
		for _, stat in pairs({"Attack", "Defence", "Special"}) do
			local statValue = Instance.new("IntValue")
			statValue.Name = stat
			statValue.Value = 1  -- Set default value to 1 for each stat
			statValue.Parent = player
		end
	end

	-- Notify the client to update UI with loaded data
	loadStatsEvent:FireClient(player)
end)

game.Players.PlayerRemoving:Connect(function(player)
	-- Save player points
	local success, errorMessage = pcall(function()
		pointsDataStore:SetAsync(player.UserId, player:GetAttribute("Points"))
	end)

	if not success then
		warn("Failed to save points:", errorMessage)
	end

	-- Save player stats
	local stats = {}
	for _, stat in pairs({"Attack", "Defence", "Special"}) do
		local statValue = player:FindFirstChild(stat)
		if statValue then
			stats[stat] = statValue.Value
		end
	end

	local success, errorMessage = pcall(function()
		statsDataStore:SetAsync(player.UserId, stats)
	end)

	if not success then
		warn("Failed to save stats:", errorMessage)
	end
end)

I also have this Server Script in which what is related to the Folders in the StatGUI that was the original code that came with this stat system I just added it to what I have already created for my leaderboard system so not sure if it should be included in there or not.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService("DataStoreService")
local coinsDataStore = DataStoreService:GetDataStore("PlayerCoinsDataStore")
local expLevelDataStore = DataStoreService:GetDataStore("PlayerExpLevelDataStore")
local remoteEvent = ReplicatedStorage:WaitForChild("LeveledUp")
local remoteFunction = ReplicatedStorage:WaitForChild("IncreaseStats")
local savePointsEvent = ReplicatedStorage:WaitForChild("SavePoints") -- Using the correct SavePoints event

-- Function to update points label on the client side
local function updatePointsLabel(player, pointsValue)
	remoteEvent:FireClient(player, pointsValue) -- Update points label on the client
end

-- Handle stat increase when the client invokes the remote function
local function increaseStats(player, button)
	if player.Points.Value > 0 then -- Ensure player has points to spend
		player.Points.Value -= 1
		local pointsValue = player.Points.Value
		local stat = player.StatsFolder:FindFirstChild(button)
		if stat then
			stat.Value += 1
			local statValue = stat.Value
			updatePointsLabel(player, pointsValue) -- Call to update points after stat increase
			return pointsValue, statValue
		end
	end
	warn("Invalid stat button or insufficient points for", player.Name)
	return player.Points.Value, nil
end

-- Bind the "increaseStats" function to the remote function's "OnServerInvoke" callback
remoteFunction.OnServerInvoke = increaseStats

-- Load player data when they join
game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local cash = Instance.new("IntValue")
	cash.Name = "Cash"
	cash.Parent = leaderstats

	local level = Instance.new("IntValue")
	level.Name = "Level"
	level.Value = 1
	level.Parent = leaderstats

	local exp = Instance.new("IntValue")
	exp.Name = "EXP"
	exp.Value = 0
	exp.Parent = leaderstats

	local points = Instance.new("IntValue")
	points.Name = "Points"
	points.Value = 1
	points.Parent = player

	local statsFolder = Instance.new("Folder")
	statsFolder.Name = "StatsFolder"
	statsFolder.Parent = player

	local Attack = Instance.new("IntValue")
	Attack.Name = "Attack"
	Attack.Value = 1
	Attack.Parent = statsFolder

	local Special = Instance.new("IntValue")
	Special.Name = "Special"
	Special.Value = 1
	Special.Parent = statsFolder

	local Defence = Instance.new("IntValue")
	Defence.Name = "Defence"
	Defence.Value = 1
	Defence.Parent = statsFolder

	-- Load saved coins from the coins DataStore
	local success, coins = pcall(function()
		return coinsDataStore:GetAsync(player.UserId)
	end)
	if success and coins then
		cash.Value = coins
	else
		cash.Value = 0
	end

	-- Load saved EXP, Level, and Points from the new DataStore
	local successExpLevel, savedData = pcall(function()
		return expLevelDataStore:GetAsync(player.UserId)
	end)
	if successExpLevel and savedData then
		exp.Value = savedData.EXP or 0
		level.Value = savedData.Level or 1
		points.Value = savedData.Points or 1 -- Default to 1 if no saved data

		-- Load saved stats (Attack, Defence, Special)
		local savedStats = savedData.Stats or {}
		Attack.Value = savedStats.Attack or 1
		Defence.Value = savedStats.Defence or 1
		Special.Value = savedStats.Special or 1
	else
		exp.Value = 0
		level.Value = 1
		points.Value = 1
	end

	-- Add RequiredEXP in stats folder (for tracking)
	local stats = Instance.new("Folder")
	stats.Name = "stats"
	stats.Parent = player

	local requiredEXP = Instance.new("IntValue")
	requiredEXP.Name = "RequiredEXP"
	requiredEXP.Value = 500
	requiredEXP.Parent = stats

	exp.Changed:Connect(function()
		if exp.Value >= requiredEXP.Value then
			exp.Value -= requiredEXP.Value
			level.Value += 1
			requiredEXP.Value = 500 + (level.Value - 1) * 1
			points.Value += 1
			updatePointsLabel(player, points.Value) -- Update points after leveling up

			-- Save updated Points, Level, EXP, and Stats to DataStore
			local successSavePoints = pcall(function()
				expLevelDataStore:SetAsync(player.UserId, {
					EXP = exp.Value,
					Level = level.Value,
					Points = points.Value,
					Stats = {
						Attack = Attack.Value,
						Defence = Defence.Value,
						Special = Special.Value
					}
				})
			end)
			if not successSavePoints then
				warn("Failed to save points for player:", player.Name)
			end
		end
	end)

	-- Save player data when they leave
	game.Players.PlayerRemoving:Connect(function(player)
		local success, errorMessage = pcall(function()
			coinsDataStore:SetAsync(player.UserId, player.leaderstats.Cash.Value)
		end)
		if not success then
			warn("Failed to save coins for player:", player.Name, errorMessage)
		end

		local exp = player.leaderstats:FindFirstChild("EXP")
		local level = player.leaderstats:FindFirstChild("Level")
		local points = player:FindFirstChild("Points")

		if exp and level and points then
			local successExpLevel, errorMessage = pcall(function()
				expLevelDataStore:SetAsync(player.UserId, {
					EXP = exp.Value,
					Level = level.Value,
					Points = points.Value,
					Stats = {
						Attack = Attack.Value,
						Defence = Defence.Value,
						Special = Special.Value
					}
				})
			end)
			if not successExpLevel then
				warn("Failed to save EXP, Level, and Points for player:", player.Name, errorMessage)
			end
		end
	end)

	-- Award coins and XP when killing Troll Guard
	local function awardPlayer(player, coinsAwarded, expAwarded)
		if player and player:FindFirstChild("leaderstats") then
			local cash = player.leaderstats.Cash
			cash.Value += coinsAwarded

			local exp = player.leaderstats.EXP
			exp.Value += expAwarded
		end
	end

	-- Mobs behavior for awarding XP and coins
	local mobsFolder = game.Workspace:FindFirstChild("Mobs")
	if mobsFolder then
		for _, mob in pairs(mobsFolder:GetChildren()) do
			if mob.Name == "Troll Guard" then
				local humanoid = mob:FindFirstChildOfClass("Humanoid")
				if humanoid then
					humanoid.Died:Connect(function()
						local creatorTag = humanoid:FindFirstChild("creator")
						if creatorTag and creatorTag.Value then
							local player = creatorTag.Value
							awardPlayer(player, 0, 50) -- Award XP and Coins
						end
					end)
				end
			end
		end
	end
end)

I would recommend moving everything from line 37 to line 64 to a function, then hook it up such that the event still runs the code, and also run the function once on initial runthrough of the script.

i.e.

local ReplicatedStorage = game:GetService("ReplicatedStorage")  
local remoteEvent = ReplicatedStorage:WaitForChild("LeveledUp")
local remoteFunction = ReplicatedStorage:WaitForChild("IncreaseStats")
local savePointsEvent = ReplicatedStorage:WaitForChild("SavePoints")  -- Correct event name
local button = script.Parent
local statsFrame = button.Parent:WaitForChild("StatsFrame")  -- Ensure StatsFrame exists
local player = game.Players.LocalPlayer
local points = statsFrame:WaitForChild("Points")  -- Ensure Points label exists
-- Show stats frame when the Stats button is clicked
button.MouseButton1Down:Connect(function()
	statsFrame.Visible = true
end)
-- Hide stats frame when the Close button is clicked
local close = statsFrame:FindFirstChild("Close")  -- Ensure Close button exists
if close then
	close.MouseButton1Down:Connect(function()
		statsFrame.Visible = false
	end)
else
	warn("Close button not found in StatsFrame!")  -- Debugging line if Close button is missing
end
-- Update the points display when the player levels up
local function onLeveledUp()
	points.Text = "Points: " .. player.Points.Value  -- Update points from player's Points
end
-- Connect the leveled-up event to update the points label
remoteEvent.OnClientEvent:Connect(onLeveledUp)
-- Handle stat increases for each Plus button


local function ButtonPressed()
	if player.Points.Value > 0 then  -- Check if there are points to spend
		-- Call the server to increase the corresponding stat
		local pointsValue, statValue = remoteFunction:InvokeServer(plusButton.Name)
		-- Update points display after stat change
		if pointsValue then
			points.Text = "Points: " .. pointsValue
		end
		-- Update the stat level display
		local levelFolder = statsFrame.LevelFolder
		local levelLabel = levelFolder:FindFirstChild(plusButton.Name)
		if levelLabel then
			levelLabel.Text = "Lv." .. statValue
		end
		-- Save the updated points value to the server
		local successSavePoints, errorMessage = pcall(function()
			savePointsEvent:FireServer(player.Points.Value)
		end)
		-- Log an error if saving points fails
		if not successSavePoints then
			warn("Failed to save points:", errorMessage)
		end
	else
		print("Not enough points to increase", plusButton.Name)
	end
end

for _, plusButton in pairs(statsFrame.PlusFolder:GetChildren()) do
	plusButton.MouseButton1Down:Connect(ButtonPressed)
end
ButtonPressed()
1 Like

You’re forgetting to forward the current GuiButton instance to the function. You’ll have to change your code to:

local function buttonPressed(button: GuiButton)
    -- ...
end
for _, button in buttons do
    buttonPressed(button)

    button.MouseButton1Click:Connect(function()
        buttonPressed(button)
    end)
end

This doesn’t do anything to help OP’s problem though. What OP needs to do is call onLeveledUp at the bottom of their script. Instead of connecting it to a RemoteEvent, they should connect it to IntValue.Changed:

onLeveledUp()

points.Changed:Connect(onLeveledUp)

This code works to consistently relay the current state of points.Value to the screen. The name “onLeveledUp” doesn’t sound very appropriate anymore, so it’s best to re–name the function to “updatePoints”.
@zoppezi

1 Like

Thank you so much! That seemed to work for me greatly and the points are getting updated accordingly. I am just working on the level part now being updated since it doesn’t update when I come back into the game. If I get a new point and add it to the level it will go from Level 0 to level 5 since it was saved at level 4 but not displaying as such. would I just do the same thing for the level as the points when I call onLeveledUp?

Yes. You would do the same thing

Do I need to create a variable for each of the levels in the level folder? I tried doing that and then calling the update at end but it doesn’t seem to work still. Points are working however whenever I click the button to increase a state ie Attack it goes from level 0 to level 8 when it should be displayed as level 7 then go to level 8.
Thanks for any help!