As the title states, I am having trouble with leaderstats, but allow me to go into detail the problem I am facing.
What I am trying to achieve is a script that will increase an amount of points over time (For example, a player gains 1 point every second). I have managed to create a leaderstat system with a datastore (the datastore is necessary in this project), but am struggling with the increase of points over time.
Here is what I have so far:
Leaderstat and Datastore script (ServerScriptService)
local DataStoreService = game:GetService("DataStoreService")
local PointsStore = DataStoreService:GetDataStore("PointsStore")
game.Players.PlayerAdded:Connect(function(Player)
local SavedPoints = PointsStore:GetAsync(Player.UserId)
local Leaderstats = Instance.new("Folder", Player)
Leaderstats.Name = "leaderstats"
local PointsValue = Instance.new("IntValue", Leaderstats)
PointsValue.Name = "Points"
if SavedPoints ~= nil then
PointsValue.Value = SavedPoints
end
PointsValue.Changed:Connect(function(NewPoints)
PointsStore:SetAsync(Player.UserId, NewPoints)
end)
end)
Point Increase Script (Server Script Service) - This script doesn’t seem to be working.
game.Players.PlayerAdded:Connect(function(player)
while true do
player.leaderstats.Points.Value = player.leaderstats.Points.Value + 1
wait(1)
end
end)
The first script is working fine - it loads the leaderstats, and the datastore is working. The second script however isn’t working, and is not adding the points. I assume the solution is simple, however after searching around, there has been no success in finding a solution.
amount = 1
timedelay = 1
currencyName = "Points"
while true do
wait(timedelay)
for i,v in pairs(game.Players:GetPlayers) do
if v:FindFirstChild("leaderstats") then
v.leaderstats[currencyName].Value = v.leaderstats[currencyName].Value + 1
end
end
end
This is because the first script gets yielded when it accesses the datastore, so leaderstats isn’t made in time. The fix for this will be
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = player:WaitForChild("leaderstats") -- wait for leaderstats and store it in a variable
while true do
leaderstats.Points.Value += 1 -- compound operator, just increases value by 1
wait(1)
end
end)
local currency = "Points" -- your currency name that will increase
local delay = 1 -- delay in second for each time will increase
local amount = 1 -- The amount to be added each time
while true do
for i, player in pairs(game.Players:GetPlayers()) do
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats then
if leaderstats:FindFirstChild(currency) then
leaderstats[currency].Value += amount
end
end
end
wait(delay)
end
This is not good for 2 reasons, you should use UpdateAsync() and far more importantly, you shouldn’t be updating the datastore every second.
os.time() gives the world time in seconds
I would do something like this.
local prevTime = os.time()
function updatePoints()
local now = os.time()
for p, player in pairs(Players:GetPlayers()) do
player.leaderstats.Points.Value += now-prevTime
end
prevTime = now
end
When you want that to run is up to you. At the very least you need it to happen as people join and leave to keep the start time relevant to all current players.