Badge not awarding for top 20 spots on Global Leaderboard

I’ve been struggling with this for a few days… I am trying to get my script to award a badge to a player for being in the top 20 spots of the global leaderboard. It prints the rankings, but nothing else… no errors either. I also have the right badge id there, but I didn’t put it in for this example. I know the error is the main line in the Award function and has specifically to do with the part where I put badgelist[player.UserId]

Here is the server script:

local players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local DataStoreService = game:GetService("DataStoreService")
local Data = DataStoreService:GetOrderedDataStore("MyOrderedDataStore")
local badgeService = game:GetService("BadgeService")
local badgeId = 0  -- This is just zero for this example

local isAscending = true
local pageSize = 20
local minValue = 1
local maxValue = 10e30
local pages = Data:GetSortedAsync(isAscending, pageSize, minValue, maxValue)
local topTwenty = pages:GetCurrentPage()

local data = {}

while true do
	for a,b in ipairs(topTwenty) do
		local user = b.key
		local points = (math.floor((b.value / 1000000000000000) * 1000)) / 1000
		local username = "[Failed To Load]"
		local s,e = pcall(function()
			username = user
		end)
		if not s then
			warn("Error getting name for "..user..". Error: "..e)
		end

		table.insert(data,{username,points})
	end 

	for rank, d in pairs(data) do
		local name = d[1]
		local points = d[2]
		Id = tonumber(name)
		badgelist = {
			[Id] = {}
		}
		ranknew = rank
		print(Id .. " is ranked #" .. rank)
	end 

	local function Award(player)
		local player = players.LocalPlayer
		if player and badgelist[player.UserId] and ranknew <= 20 and not badgeService:UserHasBadgeAsync(player.UserId, badgeId) then
			badgeService:AwardBadge(player.UserId, badgeId)
			print("awarded badge")
		end
	end

	Award()
	wait(60)
end

Thanks for your help!

The problem here is that you are attempting to reference LocalPlayer on the server’s side, which is nil. This results in the award function conditional not continuing since the variable “player” technically does not exist.

Since the script is server-sided, you could loop through the players and run the award function for each player.

1 Like

I will give that a try and circle back. Is my badgelist variable set up correctly?

When setting something in BadgeList, you are completely resetting the table by setting it as {data}. All you technically have to do is have it be an empty table local variable at the start of the while loop and setting values of it by using BadgeList[Id] = value

Current script:

local players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local DataStoreService = game:GetService("DataStoreService")
local Data = DataStoreService:GetOrderedDataStore("MyOrderedDataStore")
local badgeService = game:GetService("BadgeService")
local badgeId = 0

local isAscending = true
local pageSize = 20
local minValue = 1
local maxValue = 10e30
local pages = Data:GetSortedAsync(isAscending, pageSize, minValue, maxValue)
local topTwenty = pages:GetCurrentPage()

local data = {}

while true do
	for a,b in ipairs(topTwenty) do
		local user = b.key
		local points = (math.floor((b.value / 1000000000000000) * 1000)) / 1000
		local username = "[Failed To Load]"
		local s,e = pcall(function()
			username = user
		end)
		if not s then
			warn("Error getting name for "..user..". Error: "..e)
		end

		table.insert(data,{username,points})
	end 

	for rank, d in pairs(data) do
		local name = d[1]
		local points = d[2]
		Id = tonumber(name)
		ranknew = rank
		print(Id .. " is ranked #" .. rank)
	end 

	local function Award(player)
		if player and player.UserId == Id and ranknew <= 20 and not badgeService:UserHasBadgeAsync(player.UserId, badgeId) then
			badgeService:AwardBadge(player.UserId, badgeId)
			print("awarded badge")
		end
	end
	
	players.PlayerAdded:Connect(function(player)
			for _,v in ipairs(players:GetChildren()) do
				Award(v)
			end
	end)
	
	wait(60)
end

I don’t know if I set this up correctly, but it still doesn’t produce errors or the final print.

So it prints all except the “awarded badge”