Awarding badges upon reaching certain leaderstat value

I have a script which will award badges based on how much time you have spent in the game. It all works perfectly, except for one issue: it spams these requests in the console and eventually gives me too many requests errors. I was wondering if there was anything I could do to prevent these additional requests and just award the badge the one time then leave it.

My leaderstats script:

local bs = game:GetService("BadgeService")

local function onPlayerJoin(player)
	local leaderstats = Instance.new('Folder')
	leaderstats.Name = 'leaderstats'
	leaderstats.Parent = player

	local time_ = Instance.new('IntValue')
	time_.Name = 'Time'
	time_.Value = 0
	time_.Parent = leaderstats
	
	local joins = Instance.new('IntValue')
	joins.Name = 'Joins'
	joins.Value = 1
	joins.Parent = leaderstats
	--------------------------------The area of issue-------------------------------------
	--Time Badges
	time_.Changed:Connect(function(newVal)
		--10 Minutes
		if newVal >= 600 then
			bs:AwardBadge(player.UserId, 2124923890)
		end
		--30 Minutes
		if newVal >= 1800 then
			bs:AwardBadge(player.UserId, 2124923891)
		end
		--1 Hour
		if newVal >= 3600 then
			bs:AwardBadge(player.UserId, 2124923892)
		end
		--2 Hours
		if newVal >= 7200 then
			bs:AwardBadge(player.UserId, 2124923893)
		end
	end)
end

game.Players.PlayerAdded:Connect(onPlayerJoin)

My issue:

2 Likes

also to note: once I finish the script I will have 25 of these if statements inside of it. 25 badges for 25 different times.

1 Like

If you want it to look more clean without the insane load of if statements:
Put them into a table and “label” each badge.

2124923890 will be “600”
2124923891 will be “1800”

Then you can loop through the table and give the badge to the player if the timer reaches the desired value for each level and so on.

Different ways to go about this as well if you want but thats the basic jist.
The reason you’re getting those error messages is because its trying to give the same badge that it already gave, the if statement is basically checking every single second if:

The player got, 600, 1800, 3600, 7200, etc.
If it matches (which it will if lets say the player got 1800), then they will get both 600 and 1800.

Various ways to go about resolving this as well, check if the player has the badge before giving the badge, make the newVal check its exactly that time (been 1 and a half years since I’ve messed with some roblox stuff so I can’t guarantee that method will work without issues so instead just check if they have the badge)

Weird route would be to create a value to specifically track which badges they got in a numerical way by setting the value to be the value of the badge gotten, which is a roundabout way of just saying to check what badges they’ve gotten already.

2 Likes
local bs = game:GetService("BadgeService")

local function onPlayerJoin(player)
	local leaderstats = Instance.new('Folder')
	leaderstats.Name = 'leaderstats'
	leaderstats.Parent = player

	local time_ = Instance.new('IntValue')
	time_.Name = 'Time'
	time_.Value = 0
	time_.Parent = leaderstats

	local joins = Instance.new('IntValue')
	joins.Name = 'Joins'
	joins.Value = 1
	joins.Parent = leaderstats
	--------------------------------The area of issue-------------------------------------
	--Time Badges
	time_.Changed:Connect(function(newVal)
		--10 Minutes
		if newVal >= 600 then
			if not bs:UserHasBadgeAsync(player.UserId, 2124923890) then
				bs:AwardBadge(player.UserId, 2124923890)
			end
		end
		--30 Minutes
		if newVal >= 1800 then
			if not bs:UserHasBadgeAsync(player.UserId, 2124923891) then
				bs:AwardBadge(player.UserId, 2124923891)
			end
		end
		--1 Hour
		if newVal >= 3600 then
			if not bs:UserHasBadgeAsync(player.UserId, 2124923892) then
				bs:AwardBadge(player.UserId, 2124923892)
			end
		end
		--2 Hours
		if newVal >= 7200 then
			if not bs:UserHasBadgeAsync(player.UserId, 2124923893) then
				bs:AwardBadge(player.UserId, 2124923893)
			end
		end
	end)
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
2 Likes

I have tried this previously and it does work for a moment, then after about 30 seconds being in the game i start getting “too many requests” errors. and they flood the console.

I’ve never been the best at tables and dont know much about them, but i will attempt to learn and try to get this to work. thank you!

I see this is a timer stat which is likely changing every second, in that case just perform the badge checking/awarding every minute for each player.

local bs = game:GetService("BadgeService")

local players = {}

local function onPlayerJoin(player)
	local leaderstats = Instance.new('Folder')
	leaderstats.Name = 'leaderstats'
	leaderstats.Parent = player

	local time_ = Instance.new('IntValue')
	time_.Name = 'Time'
	time_.Value = 0
	time_.Parent = leaderstats

	local joins = Instance.new('IntValue')
	joins.Name = 'Joins'
	joins.Value = 1
	joins.Parent = leaderstats
	--------------------------------The area of issue-------------------------------------
	--Time Badges
	time_.Changed:Connect(function(newVal)
		if newVal % 60 == 0 then --Checks if the amount of seconds corresponds to a value in minutes with 0 seconds remaining.
			if newVal >= 600 then
				if not bs:UserHasBadgeAsync(player.UserId, 2124923890) then
					bs:AwardBadge(player.UserId, 2124923890)
				end
			end
			--30 Minutes
			if newVal >= 1800 then
				if not bs:UserHasBadgeAsync(player.UserId, 2124923891) then
					bs:AwardBadge(player.UserId, 2124923891)
				end
			end
			--1 Hour
			if newVal >= 3600 then
				if not bs:UserHasBadgeAsync(player.UserId, 2124923892) then
					bs:AwardBadge(player.UserId, 2124923892)
				end
			end
			--2 Hours
			if newVal >= 7200 then
				if not bs:UserHasBadgeAsync(player.UserId, 2124923893) then
					bs:AwardBadge(player.UserId, 2124923893)
				end
			end
		end
	end)
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
local bs = game:GetService("BadgeService")

local badges = {["tenMinuteBadge"] = {}, ["thirtyMinuteBadge"] = {}, ["oneHourBadge"] = {}, ["twoHoursBadge"] = {}}

local function onPlayerJoin(player)
	local leaderstats = Instance.new('Folder')
	leaderstats.Name = 'leaderstats'
	leaderstats.Parent = player

	local time_ = Instance.new('IntValue')
	time_.Name = 'Time'
	time_.Value = 0
	time_.Parent = leaderstats

	local joins = Instance.new('IntValue')
	joins.Name = 'Joins'
	joins.Value = 1
	joins.Parent = leaderstats
	--------------------------------The area of issue-------------------------------------
	--Time Badges
	time_.Changed:Connect(function(newVal)
		if newVal % 60 == 0 then --Checks if the amount of seconds corresponds to a value in minutes with 0 seconds remaining.
			if newVal >= 600 then
				if not table.find(badges["tenMinuteBadge"], player) then
					if bs:UserHasBadgeAsync(player.UserId, 2124923890) then
						table.insert(badges["tenMinuteBadge"], player)
					else
						bs:AwardBadge(player.UserId, 2124923890)
					end
				end
			end
			--30 Minutes
			if newVal >= 1800 then
				if not table.find(badges["thirtyMinuteBadge"], player) then
					if bs:UserHasBadgeAsync(player.UserId, 2124923891) then
						table.insert(badges["thirtyMinuteBadge"], player)
					else
						bs:AwardBadge(player.UserId, 2124923891)
					end
				end
			end
			--1 Hour
			if newVal >= 3600 then
				if not table.find(badges["oneHourBadge"], player) then
					if bs:UserHasBadgeAsync(player.UserId, 2124923892) then
						table.insert(badges["oneHourBadge"], player)
					else
						bs:AwardBadge(player.UserId, 2124923892)
					end
				end
			end
			--2 Hours
			if newVal >= 7200 then
				if not table.find(badges["twoHoursBadge"], player) then
					if bs:UserHasBadgeAsync(player.UserId, 2124923893) then
						table.insert(badges["twoHoursBadge"], player)
					else
						bs:AwardBadge(player.UserId, 2124923893)
					end
				end
			end
		end
	end)
end

local function onPlayerRemoving(player)
	if table.find(badges["tenMinuteBadge"], player) then
		table.remove(badges["tenMinuteBadge"], table.find(badges["tenMinuteBadge"], player))
	end
	
	if table.find(badges["thirtyMinuteBadge"], player) then
		table.remove(badges["thirtyMinuteBadge"], table.find(badges["thirtyMinuteBadge"], player))
	end
	
	if table.find(badges["oneHourBadge"], player) then
		table.remove(badges["oneHourBadge"], table.find(badges["oneHourBadge"], player))
	end
	
	if table.find(badges["twoHoursBadge"], player) then
		table.remove(badges["twoHoursBadge"], table.find(badges["twoHoursBadge"], player))
	end
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerRemoving)

To improve on that idea with arrays.

local bs = game:GetService("BadgeService")

local badges = {["tenMinuteBadge"] = {}, ["thirtyMinuteBadge"] = {}, ["oneHourBadge"] = {}, ["twoHoursBadge"] = {}}

local function onPlayerJoin(player)
	local leaderstats = Instance.new('Folder')
	leaderstats.Name = 'leaderstats'
	leaderstats.Parent = player

	local time_ = Instance.new('IntValue')
	time_.Name = 'Time'
	time_.Value = 0
	time_.Parent = leaderstats

	local joins = Instance.new('IntValue')
	joins.Name = 'Joins'
	joins.Value = 1
	joins.Parent = leaderstats
	--------------------------------The area of issue-------------------------------------
	--Time Badges
	time_.Changed:Connect(function(newVal)
		if newVal % 60 == 0 then --Checks if the amount of seconds corresponds to a value in minutes with 0 seconds remaining.
			if newVal >= 600 then
				if not badges["tenMinuteBadge"][player] then
					if bs:UserHasBadgeAsync(player.UserId, 2124923890) then
						badges["tenMinuteBadge"][player] = true
					else
						bs:AwardBadge(player.UserId, 2124923890)
					end
				end
			end
			--30 Minutes
			if newVal >= 1800 then
				if not badges["thirtyMinuteBadge"][player] then
					if bs:UserHasBadgeAsync(player.UserId, 2124923891) then
						badges["thirtyMinuteBadge"][player] = true
					else
						bs:AwardBadge(player.UserId, 2124923891)
					end
				end
			end
			--1 Hour
			if newVal >= 3600 then
				if not badges["oneHourBadge"][player] then
					if bs:UserHasBadgeAsync(player.UserId, 2124923892) then
						badges["oneHourBadge"][player] = true
					else
						bs:AwardBadge(player.UserId, 2124923892)
					end
				end
			end
			--2 Hours
			if newVal >= 7200 then
				if not badges["twoHoursBadge"][player] then
					if bs:UserHasBadgeAsync(player.UserId, 2124923893) then
						badges["twoHoursBadge"][player] = true
					else
						bs:AwardBadge(player.UserId, 2124923893)
					end
				end
			end
		end
	end)
end

local function onPlayerRemoving(player)
	badges["tenMinuteBadge"][player] = nil
	badges["thirtyMinuteBadge"][player] = nil
	badges["oneHourBadge"][player] = nil
	badges["twoHoursBadge"][player] = nil
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerRemoving)

Dictionaries are likely more performant for this use-case.