How to make a simple global leaderboard

That’s the entire point of it being a global leaderboard. Please explain what you mean?

1 Like

Ignore what I wrote I just realised how it works lol sorry for bothering you.

1 Like

I realized that the issue I was having was with

I printed b.Value and it came as nil.
How do I make it the actual value?

Whole script
local sg = script.Parent
local sample = script:WaitForChild("Sample")
local sf = sg:WaitForChild("ScrollingFrame")
local ui = sf:WaitForChild("UI")

local dataStoreService = game:GetService("DataStoreService")
local dataStore = dataStoreService:GetOrderedDataStore("Leaderboard")

wait(5)
while true do
	for i,plr in pairs(game.Players:GetPlayers()) do
		if plr.UserId>0 then
            local w = plr.leaderstats.Highscore.Value
			if w then
				pcall(function()
					dataStore:UpdateAsync(plr.UserId,function(oldVal)
						return tonumber(w)
					end)
				end)
			end
		end
	end    
	local smallestFirst = false
    local numberToShow = 10
    local minValue = 1
    local maxValue = 10e30
    local pages = dataStore:GetSortedAsync(smallestFirst, numberToShow, minValue, maxValue)
    local top = pages:GetCurrentPage()
	local data = {}
	for a,b in ipairs(top) do
		local userid = b.key
		local highscore = b.value
		local username = "[Failed To Load]"
		local s,e = pcall(function()
		 username = game.Players:GetNameFromUserIdAsync(userid)
		end)
		if not s then
		   warn("Error getting name for "..userid..". Error: "..e)
		end
		local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
		table.insert(data,{username,highscore,image})
	end
	ui.Parent = script
	sf:ClearAllChildren()
	ui.Parent = sf
	for number,d in pairs(data) do
		local name = d[1]
		local val = d[2]
		local image = d[3]
		local color = Color3.new(1,1,1)
		if number == 1 then
			color = Color3.new(1,1,0)
		elseif number == 2 then
			color = Color3.new(0.9,0.9,0.9)
		elseif number == 3 then
			color = Color3.fromRGB(166, 112, 0)
		end
		local new = sample:Clone()
		new.Name = name
        new.LayoutOrder = number
		new.Image.Image = image
		new.Image.Place.Text = number
		new.Image.Place.TextColor3 = color
		new.PName.Text = name
		new.Value.Text = val
		new.Value.TextColor3 = color
		new.PName.TextColor3 = color
		new.Parent = sf
	end
	wait()
	sf.CanvasSize = UDim2.new(0,0,0,ui.AbsoluteContentSize.Y)
        wait(120)
end

That’s weird. b.value should never be nil, regardless if data is stored are not. Make sure you are using b.value and not b.Value.

Could you show the code you’re using to print the value?

In your example,
isn’t

The same as 931*1000 (= 931000)
How is it

?

Lol I was using b.Value it worked when I changed it.

I have another question, will it work the same if I change the wait(120) to:

for i = 120,1,-1 do
    updateTimer.Text = "Updating in "..i.." seconds"
    wait(1)
end

Just so it tells the player when it will update?

1 Like

Yes, as long as the total wait is long enough. Experiment around with it, depending on the game lower intervals can work. However, I tend to suggest keeping it above 2 minutes because saving a player’s data should be more important than updating the leaderboard.

1 Like

I clarified the example to make it clearer, there are two solutions, one which just floors the value, and one which saves a few decimal places by storing the decimal places as an integer. The original example didn’t have a separation between the two, which I can see why that would be confusing.

1 Like

I have another problem. @ThatTimothy


It displays the info of the top 3 people but after that it only shows the image of the other players and nothing else.
local sg = script.Parent --Surface GUI
local sample = script:WaitForChild(“Sample”) --Our Sample frame
local sf = sg:WaitForChild(“ScrollingFrame”) --The scrolling frame
local ui = sf:WaitForChild(“UI”) --The UI list layout

local dataStoreService = game:GetService("DataStoreService")
--The data store service
local dataStore = dataStoreService:GetOrderedDataStore("TotalTime")
--Get the data store with key "Leaderboard"
--Want to make different leaderboards?
--Change this key to a different string ("Leaderboard2", ect.), and you can have multiple leaderboards!

wait(5)
while true do
	--will add wait(120) at the end
	--loop that runs every 2 minutes
	for i,plr in pairs(game.Players:GetChildren()) do--Loop through players
		if plr.UserId>0 then--Prevent errors
			local w = plr.leaderstats["Time Played"].Value
			if w then
				pcall(function()
					--Wrap in a pcall so if Roblox is down, it won't error and break.
					dataStore:UpdateAsync(plr.UserId,function(oldVal)
						--Set new value
						return tonumber(w)
					end)
				end)
			end
		end
	end
	
	
	local smallestFirst = false--false = 2 before 1, true = 1 before 2
	local numberToShow = 100--Any number between 1-100, how many will be shown
	local minValue = 1--Any numbers lower than this will be excluded
	local maxValue = 10e30--(10^30), any numbers higher than this will be excluded
	local pages = dataStore:GetSortedAsync(smallestFirst, numberToShow, minValue, maxValue)
	--Get data
	local top = pages:GetCurrentPage()--Get the first page	
	
	local data = {}--Store new data
	for a,b in ipairs(top) do--Loop through data
		local userid = b.key--User id
		local points = b.value--Points
		local username = "[Failed To Load]"--If it fails, we let them know
		local s,e = pcall(function()
			username = game.Players:GetNameFromUserIdAsync(userid)--Get username
		end)
		if not s then--Something went wrong
			warn("Error getting name for "..userid..". Error: "..e)
		end
		local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
		--Make a image of them
		table.insert(data,{username,points,image})--Put new data in new table
	end
	
	ui.Parent = script
	sf:ClearAllChildren()--Remove old frames
	ui.Parent = sf
	for number,d in pairs(data) do--Loop through our new data
		local name = d[1]
		local val = d[2]
		local image = d[3]
		local color = Color3.new(1,1,1)--Default color
		if number == 1 then
			color = Color3.new(.8,.6,0)--1st place color
		elseif number == 2 then
			color = Color3.new(0.7,0.8,0.6)--2nd place color
		elseif number == 3 then
			color = Color3.fromRGB(166, 112, 0)--3rd place color
		end
		local new = sample:Clone()--Make a clone of the sample frame
		new.Name = name--Set name for better recognition and debugging
		new.LayoutOrder = number--UIListLayout uses this to sort in the correct order
		new.Image.Image = image--Set the image
		new.Image.Place.Text = number--Set the place
		new.Image.Place.TextColor3 = color--Set the place color (Gold = 1st)
		new.PName.Text = name--Set the username
		new.Value.Text = val--Set the amount of points
		new.Value.TextColor3 = color--Set the place color (Gold = 1st)
		new.PName.TextColor3 = color--Set the place color (Gold = 1st)
		new.Parent = sf--Parent to scrolling frame
	end
	wait()
	sf.CanvasSize = UDim2.new(0,0,0,ui.AbsoluteContentSize.Y)
	--Give enough room for the frames to sit in
	wait(120)
end--End the while loop

Here is the script.

1 Like

If you’re using the same code, you have to update it if you change the hierarchy of your text labels. Make sure you check the output for more information, as there likely is an error.

For an example of how you should setup the ui, see the OP. There is also a download and demo for more information.

1 Like

Are you talking about the variables?

the error is occurring here?

If you’ve changed the layout of the ui elements, then you have to modify the code to compensate for it.

If you dont understand what that means, you’ll want to use the copy provided in the demo that works and modify it from there.

If the text isn’t displaying, it’s either the same color as the background, or the script is referencing the wrong items. If it’s the later, you should see errors in your ouput.

I can’t help you much more with just an image. I’d need to know your object hierarchy as well.

Oh, here is the object hierarchy.
image
Thanks!

How do we make a leaderboard where it takes all of a client’s data and adds up

You would add up the data and save that. OrderedDataStores can only store numerical integers, so it’s up to you to figure out how to store what you want to sort as a integer.

1 Like

How could I make this work with DataStore2? Is it possible to have it work with DataStore2?
(DataStore2)

Thank you so much - I see this will be a great help!

DataStore2 is for regular datastores - not ordered ones. So no, not directly. However, what you could do, is also save the same data you want to sort to the ordered data store. This does mean that the data will be in two places at once, but it’s the only way to handle ordered data stores as they only accept numbers.

1 Like

Yes, just make it grab the value from DataStore2 when saving the value to the Ordered Data Store and you should be fine.

1 Like

Hi! Whenever I use the monthly part, it gives me this error:

  Error getting name for Y:2021 M:4donations 610735452. Error: Unable to cast string to int64  -  Server - Script:103
  14:32:28.801  Unable to cast string to int64  -  Server - Script:105
  14:32:28.801  Stack Begin  -  Studio
  14:32:28.801  Script 'Workspace.Donation.SurfaceGui.Script', Line 105  -  Studio - Script:105
  14:32:28.802  Stack End  -  Studio

I’ve tried a few things but couldn’t get it to work. The problem is that the DataStore key isn’t just the playerId, it’s the playerId along with the month, but I can’t figure out how to make it so it’s monthly and have the code be able to refrence the playerID.

Any help is appreciated!