Touched to get badge

help, What I hope is that when the player touches Part1, player will have 5 seconds to touch Part2, after which the player will receive the badge if the player leaves or dies, it will be cancelled, and the player should touch Part1 again.

3 Likes

Character Is Not Valid Of UserId Instead Character.Parent.UserId
or to get a player you need game.Players:FindFirstChildOfClass("Player")
and you can get a userid player.UserId

Both parts need to detect .Touched. When the first part is hit, the script should store this information in a table, so that the function called when the second part is touched may know whether the player is eligible to be awarded a badge.

Adding to what @ahmetygci34 said, Player is an object that represents a player in game and is a member of the Players service. Character is a model in workspace players actually move around. Player.Character is a reference to this object.

BadgeService performs web requests, so the calls, although hardly, can be exhausted. They might also fail. pcall makes sure the code is safe.

I added comments to explain what each part does. The script is tested but please let me know if you find a bug.

Code
local Players = game:GetService("Players")
local BadgeService = game:GetService("BadgeService")

local part1 = workspace.Part1
local part2 = workspace.Part2

local BADGE_ID = 2607888591101161
local ALLOWED_TIME_BETWEEN_TOUCHES = 5 -- seconds

-- badgeOwners keeps track of all players in game
-- that own the badge as an array, e.g. {Player1, Player2, ...}
local badgeOwners = {}
-- lastPart1TouchTime stores the last time player has touched
-- Part1 in form of a dictionary, e.g. {[Player1] = time, ...}
local lastPart1TouchTime = {}

-- When Part1 is touched, lastPart1TouchTime is updated
part1.Touched:Connect(function(hit)
	local player = Players:GetPlayerFromCharacter(hit.Parent)
	
	if player then
		lastPart1TouchTime[player] = os.time()
	end
end)

-- When Part2 is touched, the badge is awared if eligible
part2.Touched:Connect(function(hit)
	local player = Players:GetPlayerFromCharacter(hit.Parent)
	
	if player then
		-- Has it been more than ALLOWED_TIME_BETWEEN_TOUCHES seconds
		-- since the touch of Part1? Return
		if (os.time() - (lastPart1TouchTime[player] or 0)) > ALLOWED_TIME_BETWEEN_TOUCHES then
			print("Not eligible")
			return
		end
		
		-- Does the player already have the badge? Return
		if table.find(badgeOwners, player) then
			print("Already owns the badge")
			return
		end
		
		-- Attempt to award the badge. The request may occasionally fail
		local success, result = pcall(function()
			BadgeService:AwardBadge(player.UserId, BADGE_ID)
		end)
		
		-- Successfully awared badge places the player among
		-- the badge owners
		if success then
			table.insert(badgeOwners, player)
			print("Awarded the badge")
		else
			print("Failed to award the badge")
		end
	end
end)

-- When the player joins the game, check whether they
-- have the badge with a couple of retries
Players.PlayerAdded:Connect(function(player)
	local success, result
	local retries = 0
	repeat
		success, result = pcall(function()
			BadgeService:UserHasBadgeAsync(player.UserId, BADGE_ID)
		end)
		retries += 1
	until success or retries == 3
	
	if success == true and result == true then
		table.insert(badgeOwners, player)
	end
end)

-- Once the player leaves, clear them from both tables
Players.PlayerRemoving:Connect(function(player)
	lastPart1TouchTime[player] = nil
	table.remove(badgeOwners, table.find(badgeOwners, player))
end)
3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.