Data Saving Minute Leaderboard

So, I am trying to make a leaderboard for minutes that saves, but upon looking for tutorials they only teach you about how to make a data store with the ‘cash’ leader and not how to script a actual data saving minute leaderboard. If you could help me, I would greatly appreciate it.

1 Like

The tutorials shows you how to save a variable which is most common cash. You need to take that concept of saving a variable and make that variable track time in minutes I would assume.

But I have no idea how to ‘track time’ :frowning:

After you create the stats, do a while loop with the condition as wait(60) and inside it, increment minutes by one and save it. (I suggest DS2 tho…)

Just do a wait

local minutes = 0

while wait(60) do
minutes = minutes + 1
end
2 Likes
game.Players.ChildAdded:connect(function(Player)
	local Lead = Instance.new("IntValue",Player)
	Lead.Name = "leaderstats"
	local Cash = Instance.new("IntValue",Lead)
	Cash.Name = "Minutes Played"
	Cash.Value = 0
	 
	DataStore = game:GetService("DataStoreService"):GetDataStore("MinutesPlayed")
	local Key = Player.userId
	local Data = DataStore:GetAsync(Key)
	
	if Data then
		Cash.Value = Data
	end
end)

game.Players.ChildRemoved:connect(function(Player)
	local Key = Player.userId
	DataStore:SetAsync(Key,Player.leaderstats.Cash.Value)
end)

while wait(60) do
minutes = minutes + 1
end

Would that work

No, you need to move the loop inside the PlayerAdded event.

You will need to move the loop in to the PlayerAdded function so each individual player has their own counter and not a server shared one.

Here:

game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder", player)
leaderstats.Name = "leaderstats"

local Minutes = Instance.new("IntValue", leaderstats)
Minutes.Name = "Minutes"
Minutes.Value = 0

while true do
wait(60)
Minutes.Value = Minutes.Value + 1
end
end)
1 Like

Most of the other solutions here use wait(60), which is not a reliable solution. wait(60) can take much longer than a minute depending on what other scripts are running at the end of that period. Doing a tick-based approach is much simpler and more reliable. For example:

local datastore = game:GetService("DataStoreService"):GetService("MinutesPlayed")
-- since the datastore isn't based on the player, only the keys are,
-- there's no reason to define the datastore instead the PlayerAdded event

local joinTimes = {} -- store a table of when players joined

game:GetService("Players").PlayerAdded:Connect(function(player)

	local leaderstats = Instance.new("Folder", player)
	-- folders are meant for storing stuff, no need to use an intvalue
	leaderstats.Name = "leaderstats"

	local playTime = Instance.new("IntValue", leaderstats)
	playTime.Name = "Time Played"

	local key = player.UserId
	local success, data = pcall(datastore.GetAsync, datastore, key)
	-- make sure you handle errors properly, otherwise your code will break

	if success then -- if it worked,
		playTime.Value = data or 0 -- set it to whatever was saved (or 0 if nothing was saved)
		joinTimes[player] = {data or 0, tick()} -- keep track of when the player joined and what they had saved
	else
		warn(data) -- put the error in the console as a warning
		-- ... you can do better error handling here too
	end
end)

game:GetService("Players").PlayerRemoving:Connect(function(player)
	-- when a player leaves,
	local key = player.UserId
	local success, error = pcall(datastore.IncrementAsync, datastore, math.floor((tick() - joinTimes[player][2])/ 60))
	-- add onto the saved data the amount of time between when they joined and now in minutes

	if not success then -- if it errors,
		warn("UpdateAsync failed for", player, ":", error)
		-- retry or whatever error handling you want
	end
end)

game:GetService("RunService").Heartbeat:Connect(function()
	-- every frame, for every player, update their time played
	local now = tick()
	for player, times in pairs(joinTimes) do
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats and leaderstats:FindFirstChild("Time Played") then
			leaderstats["Time Played"].Value = times[1] + math.floor((now - times[2]) / 60)
			-- set their time played to what was saved + how long it's been since they've joined (in min)
		end
	end
end)

Edit: It’s not really simpler, I’m not sure what I was thinking.

8 Likes

Is there another way to do the math at the very bottom of the script? An error message about attempting to do arithmetic gets spammed in the output when I try it.