Janky Dex/Catalog Save/Detect System in my Find the Game


wait(.2)
local Players = game:GetService("Players")
local BadgeService = game:GetService("BadgeService")

local badges = {
	{id = 825470753469894, name = "Nuala", texture = "rbxassetid://18940489185"},
	{id = 3993436032447000, name = "Sunflower Nuala", texture = "rbxassetid://18944802036"},
	{id = 2794494538841400, name = "Beach Ball Nuala", texture = "rbxassetid://80222689551657"},
	{id = 2143889494944777, name = "Nualawood", texture = "rbxassetid://18946833131"},
	{id = 4176424032128923, name = "Giant Nuala", texture = "rbxassetid://103876632520199"},
	{id = 3182012389732672, name = "Hydrant Nuala", texture = "rbxassetid://100487757734727"},
	{id = 1101050386441915, name = "Sailor Nuala", texture = "rbxassetid://91109574359405"},
	{id = 661002574639906, name = "Sand Castle Nuala", texture = "rbxassetid://124947880599175"},
	{id = 473377285836462, name = "Nuala Miner", texture = "rbxassetid://128743420133652"},
	{id = 3762525486484396, name = "Nuala in a Car", texture = "rbxassetid://95427629249900"},
	{id = 340050098656158, name = "Golden Nuala", texture = "rbxassetid://126138662021056"},
	{id = 2160660132301528, name = "Nualafruit", texture = "rbxassetid://77055838031866"},
	{id = 1063303013099351, name = "Fossilized Nuala", texture = "rbxassetid://79465460318986"},
	{id = 270485295814570, name = "Orange Cat Nuala", texture = "rbxassetid://73816275866374"},
	{id = 755827457568771, name = "One with the Trees Nuala", texture = "rbxassetid://71257673798622"},
	--medium
	{id = 1420164253190837, name = "Squirrel Nuala", texture = "rbxassetid://113482393948846"},
	{id = 4358658733723848, name = "Sunala", texture = "rbxassetid://93600606095858"},
	{id = 3402913698605796, name = "Darkness Nuala", texture = "rbxassetid://112489906966646"},
	{id = 1738741922042695, name = "Soaked Nuala", texture = "rbxassetid://114570479911453"},
	{id = 3008797889549368, name = "Pet Nuala", texture = "rbxassetid://112869458098664"},
	{id = 1832432256834839, name = "Stuckala", texture = "rbxassetid://84250092672774"},
	{id = 2970196169244497, name = "Spider Nuala", texture = "rbxassetid://80339252884121"},
	{id = 4072019634641547, name = "Rooted Nuala", texture = "rbxassetid://96008593268327"},
	{id = 192741430310577, name = "Blurry Nuala", texture = "rbxassetid://113493534989565"},
	--hard
	{id = 204729745518514, name = "Sorta Secret Nuala", texture = "rbxassetid://70639536016768"},
	{id = 2203150997366991, name = "CEO Nuala", texture = "rbxassetid://79820069482902"},
	{id = 727546042646471, name = "Sparkling Water Nuala", texture = "rbxassetid://108536789846216"},
	{id = 3962196304428070, name = "Blue Cheese Nuala", texture = "rbxassetid://73818890487547"},
	{id = 2434531127950952, name = "Shiny Holo Nuala Card", texture = "rbxassetid://110793207823615"},
	{id = 175513168695701, name = "Inverted Nuala", texture = "rbxassetid://132450627819203"},
	{id = 1713165856656032, name = "Nuala Popsicle", texture = "rbxassetid://77270470518850"},
	{id = 533709723862086, name = "Geode Nuala", texture = "rbxassetid://126554522594528"},
	--intense
	{id = 454847409910032, name = "Secret Nuala", texture = "rbxassetid://96152411579165"},
	{id = 996134040535768, name = "Clockwork Nuala", texture = "rbxassetid://113871798097662"},
	{id = 454847409910032, name = "Glitchala", texture = "rbxassetid://118536585617465"},
	{id = 1731114169300166, name = "All Seeing Nuala", texture = "rbxassetid://137052549280413"},
	{id = 2036934203903108, name = "Shattered Nuala", texture = "rbxassetid://95519084437532"},
	{id = 4476419490344865, name = "Getting Over Nuala", texture = "rbxassetid://73186683114218"},
	{id = 1148612316112491, name = "Perspective Nuala", texture = "rbxassetid://110993534956541"},
	{id = 4417167326052753, name = "Evil Sunflower Nuala", texture = "rbxassetid://84628998129290"},
	{id = 2043023404572736, name = "Enchanted Nuala", texture = "rbxassetid://93246288392901"},
	{id = 3987020990443036, name = "MyDala", texture = "rbxassetid://82763103723814"},
	{id = 2953722112281299, name = "Nualoss", texture = "rbxassetid://72832102492468"},
	--insane
	{id = 40126125060604, name = "Painting Nuala", texture = "rbxassetid://82542755960424"},
	{id = 2322113928663430, name = "Nuala Tome", texture = "rbxassetid://105171665819956"},
	{id = 862720075315443, name = "There is no Nuala", texture = "rbxassetid://103116132463469"},
	{id = 2444506894085935, name = "Transparency Grid Nuala", texture = "rbxassetid://126548735691996"},
	{id = 3360273555884087, name = "Nuala of the Highest Lair", texture = "rbxassetid://18983536706"},
	{id = 3400104666010003, name = "WeirdCala", texture = "rbxassetid://127502625460014"},
	{id = 4187874656078620, name = "Very Secret Nuala", texture = "rbxassetid://99422042744585"},
	{id = 4351712341478131, name = "Nuala Sundae", texture = "rbxassetid://120606036215366"},
	{id = 149872491772465, name = "Missing Nuala", texture = "rbxassetid://130712649243760"},
	{id = 2989237371775314, name = "Error Nuala", texture = "rbxassetid://77765934507270"},
	{id = 4298685936848608, name = "NoClipala", texture = "rbxassetid://83885949305070"},
	{id = 1480730204551845, name = "Amazeing Nuala", texture = "rbxassetid://116736515402482"},
	--extreme
	{id = 3820190767963370, name = "Trolla", texture = "rbxassetid://118260270782448"},
	{id = 248692490906882, name = "Skinwalker Nuala", texture = "rbxassetid://77030405433033"},
	{id = 4065174263016170, name = "Recollectionala", texture = "rbxassetid://102689282022489"},
	{id = 1375269726864897, name = "Corrupted Nuala", texture = "rbxassetid://107120486096645"},
	{id = 3221419613951887, name = "Distorted Nuala", texture = "rbxassetid://104523945828252"},
	{id = 2381729989399521, name = "Anualag Horror", texture = "rbxassetid://76334306387556"},
	{id = 2407518871994148, name = "Nuala Constellation", texture = "rbxassetid://120362717482625"},
	{id = 4488432287139738, name = "Super Secret Nuala", texture = "rbxassetid://70980098280356"},
	--scardeycat
	{id = 2953722112281299, name = "Nuala Over Zero", texture = "rbxassetid://80461440223428"},
	{id = 4241551891661502, name = "Internet Nuala", texture = "rbxassetid://"},
	{id = 2629260279024232, name = "The Nuala is Lava", texture = "rbxassetid://135228501157252"},
	{id = 2488018575890184, name = "Nuala of the Upside Down", texture = "rbxassetid://112448225990430"},
	{id = 947573328526532, name = "Insanely Secret Nuala", texture = "rbxassetid://76411513054539"},
	{id = 2293209590453508, name = "Nualas in Time", texture = "http://www.roblox.com/asset/?id=139010281450474"},
	--catastrophic
	{id = 1491544040784761, name = "Nuala RNG", texture = "rbxassetid://120562327467124"},
	{id = 1199522669258002, name = "Black Hole Nuala", texture = "rbxassetid://77810750404723"},
	{id = 2909418844436231, name = "Badger Nuala", texture = "rbxassetid://18983578620"},
	{id = 3431167427759979, name = "Truly Trolling Nuala", texture = "rbxassetid://133523563740746"},
	--hairrowing
	{id = 1805495013054783, name = "Difficulty Chart Nuala", texture = "rbxassetid://111085992573816"},
	{id = 1314449722405156, name = "Badger Nuala 2: The Badgering", texture = "rbxassetid://92588827580523"},
	--meowciless


	
	




	-- More badges as needed,
	-- ...
}

local totalBadges = #badges

-- Function to retry badge checks
local function safeUserHasBadgeAsync(userId, badgeId, retryCount)
	retryCount = retryCount or 0
	print("Checking if user " .. userId .. " has badge " .. badgeId)
	local success, result = pcall(function()
		return BadgeService:UserHasBadgeAsync(userId, badgeId)
	end)

	if success then
		print("Badge check succeeded for user " .. userId .. " and badge " .. badgeId)
		return result
	else
		if retryCount < 3 then
			wait(1) -- Wait a bit before retrying
			print("Badge check failed for user " .. userId .. " and badge " .. badgeId .. ". Retrying...")
			return safeUserHasBadgeAsync(userId, badgeId, retryCount + 1)
		else
			print("Failed to check badge " .. badgeId .. " for user " .. userId)
			return false
		end
	end
end

-- Function to update badge position inside the ScrollFrame
local function updateBadgePositionAndSize(dexImage, positionIndex)
	local badgesPerRow = 5
	local badgeSize = UDim2.new(0.1, 0, 0.1, 0)
	local spacing = UDim2.new(0.05, 0, 0.05, 0)

	local baseOffsetX = UDim2.new(.1, 0, 0, 0)
	local baseOffsetY = UDim2.new(0, 0, 0.1, 0)

	local row = math.floor((positionIndex - 1) / badgesPerRow)
	local column = (positionIndex - 1) % badgesPerRow

	if dexImage then
		dexImage.Position = UDim2.new(column * (badgeSize.X.Scale + spacing.X.Scale), 0, row * (badgeSize.Y.Scale + spacing.Y.Scale), 0) + baseOffsetX + baseOffsetY
	else
		warn("dexImage is nil for badge at index: " .. tostring(positionIndex))
	end
end

-- Function to check badges and update ScrollFrame
local function checkBadges(player, scrollFrame, badgeCounterLabel, retries)
	wait(.2)
	retries = retries or 0
	print("Checking badges...")
	local badgeCount = 0 -- Track the number of badges found

	for index, badge in ipairs(badges) do
		print("Checking badge:", badge.name)
		local hasBadge = safeUserHasBadgeAsync(player.UserId, badge.id, retries)
		local dexImage = scrollFrame:FindFirstChild(badge.name)

		if dexImage then
			print("Found badge image:", badge.name)
			dexImage.Image = badge.texture
			updateBadgePositionAndSize(dexImage, index)

			if hasBadge then
				print("Badge is owned:", badge.name)
				dexImage.ImageTransparency = 0
				local textLabel = dexImage:FindFirstChildOfClass("TextLabel")
				if textLabel then
					textLabel.TextColor3 = Color3.new(0, 1, 0) -- Green for owned badges
				end
				badgeCount = badgeCount + 1 -- Increment the badge count
			else
				print("Badge is not owned:", badge.name)
				dexImage.ImageTransparency = 0.5
				local textLabel = dexImage:FindFirstChildOfClass("TextLabel")
				if textLabel then
					textLabel.TextColor3 = Color3.new(1, 1, 1) -- White for unowned badges
				end
			end
		else
			print("Badge image not found:", badge.name)
		end
	end

	print("Badge count:", badgeCount)
	-- Update the badge counter (X / Y format)
	if badgeCounterLabel then
		badgeCounterLabel.Text = "" .. badgeCount .. " / " .. totalBadges .. " Nualas"
	end
	if badgeCount >= 20 then
		print("20 badges have been found!")
		-- Add any action you want to perform here when 20 badges are found
	game.ReplicatedStorage:WaitForChild("taxi"):FireServer(player)

	end
end

-- Function called when player's character is added
local function onCharacterAdded(character)
	wait(2) -- Slight delay to ensure character is loaded
	print("Character added")
	local player = Players.LocalPlayer
	local playerGui = player:WaitForChild("PlayerGui")
	local screenGui = playerGui:FindFirstChild("ScreenGui")

	if not screenGui then
		warn("ScreenGui not found!")
		return
	end

	local dexFrame = screenGui:FindFirstChild("dexPage1")
	if not dexFrame then
		warn("dexPage1 frame not found!")
		return
	end

	local scrollFrame = dexFrame:FindFirstChild("ScrollFrame")
	if not scrollFrame then
		warn("ScrollFrame not found inside dexPage1!")
		return
	end

	-- Create a badge counter label if not already present
	local badgeCounterLabel = dexFrame.ScrollFrame:FindFirstChild("BadgeCounter")
	if not badgeCounterLabel then
		badgeCounterLabel = Instance.new("TextLabel")
		badgeCounterLabel.Name = "BadgeCounter"
		badgeCounterLabel.Size = UDim2.new(0.4, 0, 0.1, 0) -- Width is 40% of the parent frame, height is 10%
		badgeCounterLabel.Position = UDim2.new(0.25, 0, 0, 0) -- Center horizontally and place it at the top
		badgeCounterLabel.BackgroundTransparency = 1
		badgeCounterLabel.TextScaled = true
		badgeCounterLabel.TextColor3 = Color3.new(1, 1, 1) -- White text
		badgeCounterLabel.TextStrokeTransparency = 0.5 -- Optional: Adds a stroke to make text stand out
		badgeCounterLabel.Parent = dexFrame.ScrollFrame
	end

	-- Check badges and update ScrollFrame
	wait(.1)
	checkBadges(player, scrollFrame, badgeCounterLabel, 0)
end

-- Connect the Player.CharacterAdded event
local player = Players.LocalPlayer
player.CharacterAdded:Connect(onCharacterAdded)

-- Handle case where the player's character is already loaded
if player.Character then
	onCharacterAdded(player.Character)
end

I want to improve this save system. I’m 99% sure the issue is less to do with the code and more to do with BadgeService and BadgeDetection being overloaded. So, I can think of two possible routes to go with this…

1.Ssomehow make it so the badges aren’t overloaded, wether that be by scripting or some other magical method I don’t know about, without slowing it down too much. in other words, optimizing.

And 2… ugh… remake the entire badge system to use datastores instead of badge detection… fun.

So, if option 1 works, amazing. If option 2 is needed… Im willing to put in the work. But, for both, I’d like a little nudging in the right direction lol.

Why do you have wait(.2) at the start?

1 Like

it helped with the optimization… I think…

Maybe just… add a couple of waits in between some lines and see if that helps? If it doesnt, you will probably have to use datastores… Goodluck with that, i would recommend using gnomecode’s tutorial if your going the second option, helped me alot.

1 Like