How can I make 2 seperate leaderboards work?

Hello. I have 2 leaderboardHandler scripts for 2 IntValues and it seems that the leaderboards save the same value to the player as if there’s only 1 IntValue. It also seems that it doesn’t save the stats properly because whenever a player on the leaderboard is present in-game the leaderboard reads the proper IntValue. Also players seem to be getting assigned random numbers out of thin air. Any help with this? Should I just make 1 script instead? This method of having 2 seperate leaderboard scripts worked for me before because I’ve had 2 seperate datastores, could having 1 datastore be the issue?

LEADERBOARD1 SCRIPT:

local DataStoreService = game:GetService("DataStoreService")
local BricksLeaderboard = DataStoreService:GetOrderedDataStore("SaveSystem")

local function updateLeaderboard()
	local success, errorMessage = pcall(function()
		local Data = BricksLeaderboard:GetSortedAsync(false, 10)
		local BricksPage = Data:GetCurrentPage()
		for Rank, data in ipairs(BricksPage) do
			local userName = game.Players:GetNameFromUserIdAsync(tonumber(data.key))
			local Name = userName
			local Bricks = data.value
			local isOnLeaderboard = false
			for i, v in pairs(game.Workspace.GlobalLeaderboard.LeaderboardGUI.Holder:GetChildren()) do
				if v.Username.Text == Name then
					isOnLeaderboard = true
					break
				end
			end
			
			if Bricks > 0 and isOnLeaderboard == false then
				local newLbFrame = game.ReplicatedStorage:WaitForChild("LeaderboardFrame"):Clone()
				newLbFrame.Username.Text = Name
				newLbFrame.Bricks.Text = Bricks
				newLbFrame.Rank.Text = "#"..Rank
				newLbFrame.Position = UDim2.new(0,0, newLbFrame.Position.Y.Scale + (0.1 * #game.Workspace.GlobalLeaderboard.LeaderboardGUI.Holder:GetChildren()), 0)
				newLbFrame.Parent = game.Workspace.GlobalLeaderboard.LeaderboardGUI.Holder
			end
		end
	end)
	
	if not success then
	end
end

while true do
	for _, player in pairs(game.Players:GetChildren()) do
		BricksLeaderboard:SetAsync(player.UserId, player.leaderstats.Bricks.Value)
	end
	
	for _, frame in pairs(game.Workspace.GlobalLeaderboard.LeaderboardGUI.Holder:GetChildren()) do
		frame:Destroy()
	end
	
	updateLeaderboard()
	
	wait(120)
end

LEADERBOARD2 SCRIPT:

local DataStoreService = game:GetService("DataStoreService")
local DeathsLeaderboard = DataStoreService:GetOrderedDataStore("SaveSystem")

local function updateLeaderboard()
	local success, errorMessage = pcall(function()
			local Data = DeathsLeaderboard:GetSortedAsync(false, 10)
		local DeathsPage = Data:GetCurrentPage()
		for Rank, data in ipairs(DeathsPage) do
			local userName = game.Players:GetNameFromUserIdAsync(tonumber(data.key))
			local Name = userName
			local Deaths = data.value
			local isOnLeaderboard = false
			for i, v in pairs(game.Workspace.GlobalLeaderboard2.LeaderboardGUI2.Holder2:GetChildren()) do
				if v.Username2.Text == Name then
					isOnLeaderboard = true
					break
				end
			end
			
			if Deaths > 0 and isOnLeaderboard == false then
				local newLbFrame = game.ReplicatedStorage:WaitForChild("LeaderboardFrame2"):Clone()
				newLbFrame.Username2.Text = Name
				newLbFrame.Deaths.Text = Deaths
				newLbFrame.Rank2.Text = "#"..Rank
				newLbFrame.Position = UDim2.new(0,0, newLbFrame.Position.Y.Scale + (0.1 * #game.Workspace.GlobalLeaderboard2.LeaderboardGUI2.Holder2:GetChildren()), 0)
				newLbFrame.Parent = game.Workspace.GlobalLeaderboard2.LeaderboardGUI2.Holder2
			end
		end
	end)
	
	if not success then
	end
end

while true do
	for _, player in pairs(game.Players:GetChildren()) do
		DeathsLeaderboard:SetAsync(player.UserId, player.leaderstats.Deaths.Value)
	end
	
	for _, frame in pairs(game.Workspace.GlobalLeaderboard2.LeaderboardGUI2.Holder2:GetChildren()) do
		frame:Destroy()
	end
	
	updateLeaderboard()
	
	wait(120)
end

DATASTORE SCRIPT:

local datastore = game:GetService("DataStoreService")
local options = Instance.new("DataStoreOptions")
options.AllScopes = true
local ds = datastore:GetDataStore("SaveSystem")
local prefix = "Player_"
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

local function saveFunction() -- save function for making the thing work with coroutine cuz it requires a function booo 🌮🌮🌮🌮
	local playerData = ds:GetAsync(prefix .. tostring(game.Player.UserId)) 
	if playerData then
		game.Player.leaderstats.Bricks.Value = playerData[1] or 0
		game.Player.leaderstats.Deaths.Value = playerData[2] or 0
		game.Player.LotteryFolder.LotteryWins.Value = playerData[3] or 0
	else 
		ds:SetAsync(prefix .. tostring(game.Player.UserId), {
			game.Players.leaderstats.Bricks.Value,
			game.Players.leaderstats.Deaths.Value,
			game.Players.LotteryFolder.LotteryWins.Value
		})
	end
end


game.Players.PlayerAdded:Connect(function(player) -- once player joins, assign stats
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	
	local BrickCount = Instance.new("Folder")
	BrickCount.Name = "BrickCount"
	BrickCount.Parent = player
	
	local LotteryFolder = Instance.new("Folder")
	LotteryFolder.Name = "LotteryFolder"
	LotteryFolder.Parent = player
	
	local BrickCountValue = Instance.new("IntValue")
	BrickCountValue.Name = "BrickCountValue"
	BrickCountValue.Parent = BrickCount
	
	local LotteryWins = Instance.new("IntValue")
	LotteryWins.Name = "LotteryWins"
	LotteryWins.Parent = LotteryFolder
	
	local bricks = Instance.new("IntValue")
	bricks.Name = "Bricks"
	bricks.Parent = leaderstats
	
	local deaths = Instance.new("IntValue")
	deaths.Name = "Deaths"
	deaths.Parent = leaderstats
	
	player.CharacterAdded:Connect(function(character)
		local humanoid = character:WaitForChild("Humanoid")
		humanoid.Died:Connect(function()
			deaths.Value = deaths.Value + 1
		end)
	end)
	
	local playerData = ds:GetAsync(prefix .. tostring(player.UserId)) -- THIS THING IS FOR SAVING STATS DONT TOUCH THIS LIKE EVER
	if playerData then
		bricks.Value = playerData[1] or 0
		deaths.Value = playerData[2] or 0
		LotteryWins.Value = playerData[3] or 0
	else 
		ds:SetAsync(prefix .. tostring(player.UserId), {
			bricks.Value,
			deaths.Value,
			LotteryWins.Value
		})
	end
end)

game.Players.PlayerRemoving:Connect(function(player) -- on player leaving, save stats
	ds:SetAsync(prefix .. tostring(player.UserId), {
		player.leaderstats.Bricks.Value,
		player.leaderstats.Deaths.Value,
		player.LotteryFolder.LotteryWins.Value
	})
end)

game:BindToClose(function() -- on server shutdown, save data
	if not RunService:IsStudio() and #Players:GetPlayers() > 1 then
		for _, player in ipairs(Players:GetPlayers()) do
			coroutine.wrap(saveFunction)(player)
		end
	end
end)
1 Like

I think I might be extremely wrong on this since I don’t mess with OrderedDataStores much, but here’s what I think is happening.

In each of the scripts, when you loop through all the top 10 saved players, you get their value by writing data.value. However, when you save the data, you’re saving it as a table of three values.

This might be incorrect, but I think if you put data.value[1] or data.value[2] instead of data.value, it might work.

nevermind i just realized the datastore script uses a regular datastore and not an ordered datastore

edit: This time I think I actually found the issue. You’re overwriting the same datastore each time the leaderboards save, so when the scripts access the data it gets all funky.