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.
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)