GUI not refreshing to show owned badge

Okay, so I’ve been working on a “Find the badges” game for a few weeks now, and I have just created a system that shows which of the badges you have found, by darkening the frames of the ones you haven’t collected.


As you can see here, it seems to work fine. The problem is that upon collecting a new badge, the index does not refresh, meaning it will still show as if I haven’t found the guy until I rejoin the game.

I would very much prefer not to force my players to rejoin the game every time they collect a new badge, so I’ve been trying to find a way to have the index “refresh” itself after collecting a badge, but I’m not quite sure how to go about it. Here’s the GUIs script that basically makes the index function.

local Players = game:GetService("Players")
local localplayer = Players.LocalPlayer
local CoreGui = game:GetService("StarterGui")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local dexgrid = game.Players.LocalPlayer:WaitForChild("PlayerGui"):WaitForChild("Dex"):WaitForChild("Dex"):WaitForChild("Dex")
local DetailedInfo = game.Players.LocalPlayer:WaitForChild("PlayerGui"):WaitForChild("Dex"):WaitForChild("Dex"):WaitForChild("DetailedInfo")
local OpenMenu = game.Players.LocalPlayer:WaitForChild("PlayerGui"):WaitForChild("Dex"):WaitForChild("Open")
local AwardBadge = game.ReplicatedStorage:WaitForChild("AwardBadge")
local open = false
local ReggieInfo = require(ReplicatedStorage.GuyInfo)
local badgeService = game:GetService("BadgeService")

templateitem = dexgrid.Reggie
for i, v in pairs(ReggieInfo) do
	local copy = templateitem:Clone()
	copy.Name = i
	copy.LayoutOrder = v[1]
	copy.Parent = dexgrid
	copy.Title.Text = v[2]
	copy.ImageButton.Image = v[3]
	if v[6] == "easy" then
		copy.DifficultyColor.BackgroundColor3 = Color3.fromRGB(75, 151, 75)
	elseif v[6] == "medium" then
		copy.DifficultyColor.BackgroundColor3 = Color3.fromRGB(200, 168, 51)
	elseif v[6] == "hard" then
		copy.DifficultyColor.BackgroundColor3 = Color3.fromRGB(200, 50, 50)
	elseif v[6] == "intense" then
		copy.DifficultyColor.BackgroundColor3 = Color3.fromRGB(9, 9, 9)
	elseif v[6] == "insane" then
		copy.DifficultyColor.BackgroundColor3 = Color3.fromRGB(31, 31, 172)
	elseif v[6] == "extreme" then
		copy.DifficultyColor.BackgroundColor3 = Color3.fromRGB(60, 141, 207)
	elseif v[6] == "TERRIFYING" then
		copy.DifficultyColor.BackgroundColor3 = Color3.fromRGB(62, 255, 255)
	elseif v[6] == "MINDBOGGLING" then
		copy.DifficultyColor.Image2.Image = 'rbxassetid://10491646858'
	elseif v[6] == "101" then
		copy.DifficultyColor.Image2.Image = 'rbxassetid://15695434986'
	end
	
	local userHasBadge = nil 
	success, err = pcall(function()
		userHasBadge = badgeService:UserHasBadgeAsync(game.Players.LocalPlayer.UserId, v[9])
	end)

	if userHasBadge then
		copy.ImageButton.BackgroundTransparency = 0
		copy.ImageButton.ImageTransparency = 0
		copy.ImageButton.MouseButton1Click:Connect(function()
			DetailedInfo.Description.Text = v[4]
			end)
	else
		copy.ImageButton.BackgroundTransparency = 0.9
		copy.ImageButton.ImageTransparency = 0.7
		copy.ImageButton.MouseButton1Click:Connect(function()
			DetailedInfo.Description.Text = "find this guy to unlock his description!"
			end)
	end
	
	
	
	
	copy.ImageButton.MouseButton1Click:Connect(function()
		DetailedInfo.KotName.Text = v[2]
		DetailedInfo.ImageFrame.ImageLabel.Image = v[3]
		DetailedInfo.Description.Text = v[4]
		DetailedInfo.Hint.Text = "hint: " .. v[5]
		DetailedInfo.DifficultyName.Text = v[6]
		DetailedInfo.MadeBy.Text = "made by @" .. v[7]
		DetailedInfo.Area.Text = v[8]
		if v[8] == "spawn" then
			DetailedInfo.Area.BackgroundColor3 = Color3.fromRGB(75, 151, 75)
		elseif v[8] == "arcade" then
			DetailedInfo.Area.BackgroundColor3 = Color3.fromRGB(109, 60, 150)
		elseif v[8] == "mixed" then
			DetailedInfo.Area.BackgroundColor3 = Color3.fromRGB(27, 42, 53)
		elseif v[8] == "anywhere" then
			DetailedInfo.Area.BackgroundColor3 = Color3.fromRGB(27, 42, 53)
		elseif v[8] == "offgame" then
			DetailedInfo.Area.BackgroundColor3 = Color3.fromRGB(27, 42, 53)
		end
		DetailedInfo.Visible = true
		dexgrid.Visible = false
		if v[6] == "easy" then
			DetailedInfo.DifficultyName.BackgroundColor3 = Color3.fromRGB(75, 151, 75)
		elseif v[6] == "medium" then
			DetailedInfo.DifficultyName.BackgroundColor3 = Color3.fromRGB(200, 168, 51)
		elseif v[6] == "hard" then
			DetailedInfo.DifficultyName.BackgroundColor3 = Color3.fromRGB(200, 50, 50)
		elseif v[6] == "intense" then
			DetailedInfo.DifficultyName.BackgroundColor3 = Color3.fromRGB(9, 9, 9)
		elseif v[6] == "insane" then
			DetailedInfo.DifficultyName.BackgroundColor3 = Color3.fromRGB(31, 31, 172)
		elseif v[6] == "extreme" then
			DetailedInfo.DifficultyName.BackgroundColor3 = Color3.fromRGB(60, 141, 207)
		elseif v[6] == "TERRIFYING" then
			DetailedInfo.DifficultyName.BackgroundColor3 = Color3.fromRGB(62, 255, 255)
		end
	end)
	
	local debounce = false
	
	workspace:WaitForChild("Badges (Guys)"):WaitForChild(i).Touched:Connect(function(itemThatTouchedPart)
		local playerCheck = Players:GetPlayerFromCharacter(itemThatTouchedPart.Parent) 
		if playerCheck and playerCheck == localplayer then
			if debounce == false then
				debounce = true

				CoreGui:SetCore("SendNotification", {
					Title = v[2];
					Text = "you've already found this guy";
					Icon = v[3];
					Duration = 3;
				})
				AwardBadge:FireServer(v[9])
				wait(0.001)
				local userHasBadge = nil 
				success, err = pcall(function()
					userHasBadge = badgeService:UserHasBadgeAsync(game.Players.LocalPlayer.UserId, v[9])
				end)

				wait(5)
				debounce = false
			end
		end
	end)
	
end
templateitem:Destroy()

DetailedInfo.TextButton.MouseButton1Click:Connect(function()
	dexgrid.Visible = true
	DetailedInfo.Visible = false
end)

OpenMenu.MouseButton1Click:Connect(function()
	open = not open
	if open == false then
		dexgrid.Parent.Visible = false
	else
		dexgrid.Parent.Visible = true
	end
end)

Any ideas or help would be appreciated!

This section specifically is the badge checking system:

	if userHasBadge then
		copy.ImageButton.BackgroundTransparency = 0
		copy.ImageButton.ImageTransparency = 0
		copy.ImageButton.MouseButton1Click:Connect(function()
			DetailedInfo.Description.Text = v[4]
			end)
	else
		copy.ImageButton.BackgroundTransparency = 0.9
		copy.ImageButton.ImageTransparency = 0.7
		copy.ImageButton.MouseButton1Click:Connect(function()
			DetailedInfo.Description.Text = "find this guy to unlock his description!"
			end)
	end

Have you tried runservice yet? There’s probably a faster way, but runservice will definetly do the job.

How would I go about using runservice in a case like this?

You could set up a Heartbeat loop, and then copy whatever code you use to check if someone has a badge or not into the loop.
Keep in mind this is the “slow” way, and there’s probably a faster way out there that I have no clue about. So if someone has a faster way, by all means take theirs.
In the meantime,

local rs = game:GetService(“RunService”)
rs.Heartbeat:Connect(function(deltaTime)
if userHasBadge then
copy.ImageButton.BackgroundTransparency = 0
copy.ImageButton.ImageTransparency = 0
copy.ImageButton.MouseButton1Click:Connect(function()
DetailedInfo.Description.Text = v[4]
end)
else
copy.ImageButton.BackgroundTransparency = 0.9
copy.ImageButton.ImageTransparency = 0.7
copy.ImageButton.MouseButton1Click:Connect(function()
DetailedInfo.Description.Text = “find this guy to unlock his description!”
end)
end
end)

This doesn’t seem to be working. Have I implemented it correctly?

	local userHasBadge = nil 
	success, err = pcall(function()
		userHasBadge = badgeService:UserHasBadgeAsync(game.Players.LocalPlayer.UserId, v[9])
	end)
	
	local rs = game:GetService("RunService")
	rs.Heartbeat:Connect(function(deltaTime)
		if userHasBadge then
			copy.ImageButton.MouseButton1Click:Connect(function()
				DetailedInfo.Description.Text = v[4]
			end)
			copy.ImageButton.BackgroundTransparency = 0
			copy.ImageButton.ImageTransparency = 0
		else
			copy.ImageButton.MouseButton1Click:Connect(function()
				DetailedInfo.Description.Text = "Find this guy to unlock his description"
			end)
			copy.ImageButton.BackgroundTransparency = 0.9
			copy.ImageButton.ImageTransparency = 0.7
		end
	end)

What you should do is cache all owned badges when the player first joins, send the list owned badge list to the client, then fire a BadgeAwarded remote event everytime you award a badge.
Best way to go about it.

You should make it a module script so you can use and adapt it for any other games you want to create.