local function c(c)if not activePlayer then return end local k=1 if#c>=1 then k=c[1]end inRace=true if k and _numLaps==0 then _numLaps=k numCheckpoints=numCheckpoints*_numLaps end for c,k in ipairs(checkpointList)do local A=k:FindFirstChild("\067\104\101\099\107\112\111\105\110\116")A.Color=NOT_HIT_COLOR local o=k:FindFirstChild("\082\105\110\103")if o then o.Color=NOT_HIT_COLOR end end if not ArrowGuide then ArrowGuide=require(script:WaitForChild("\065\114\114\111\119\071\117\105\100\101"))end arrow=ArrowGuide.new(checkpointList)end local function k(c)if not(activePlayer and inRace)then return end local k=false if#c>=1 then k=c[1]else return end local A=k.Parent local o=A:FindFirstChild("\072\105\116")if not o then o=Instance.new("\066\111\111\108\086\097\108\117\101")o.Name="\072\105\116"o.Parent=A o.Value=true else return end k.Color=HIT_COLOR local b=k.Parent:FindFirstChild("\082\105\110\103")if b then b.Color=HIT_COLOR end local N=checkpointParticle:Clone()local w=player.Character or player.CharacterAdded:wait()N.CFrame=w.PrimaryPart.CFrame N.Parent=w.PrimaryPart local P=N:GetChildren()for c,k in pairs(P)do if k:IsA("\080\097\114\116\105\099\108\101\069\109\105\116\116\101\114")then k:Emit(10)end end spawn(function()wait(PARTICLE_DURATION)N:Destroy()end)checkpointSound.Parent=k checkpointSound:Play()numCheckpointsHit=numCheckpointsHit+1 CheckpointCount.Text=tostring(numCheckpointsHit)..("\047"..tostring(numCheckpoints))end local function A()if not(activePlayer and inRace)then return end for c,k in ipairs(checkpointList)do local A=k:FindFirstChild("\067\104\101\099\107\112\111\105\110\116")local o=k:FindFirstChild("\072\105\116")if o then o:Destroy()end A.Color=NOT_HIT_COLOR local b=k:FindFirstChild("\082\105\110\103")if b then b.Color=NOT_HIT_COLOR end end end local function o()inRace=false numCheckpointsHit=0 for c,k in ipairs(checkpointList)do local A=k:FindFirstChild("\067\104\101\099\107\112\111\105\110\116")local o=k:FindFirstChild("\072\105\116")if o then o:Destroy()end A.Color=HIT_COLOR local b=k:FindFirstChild("\082\105\110\103")if b then b.Color=HIT_COLOR end end arrow:Destroy()CheckpointCount.Text=tostring(numCheckpointsHit)..("\047"..tostring(numCheckpoints))end local function b(c)local k=false if#c>=1 then k=c[1]else return end activePlayer=k if not k and inRace then inRace=false o()end if not k then local c=player.PlayerGui local k=c:FindFirstChild("\084\111\112\066\097\114")k.Enabled=false end end local function N()RaceFinishedSound:Play()end local function w(w)for w,P in pairs(w)do if P[1]=="\115\101\116\117\112"then table.remove(P,1)c(P)elseif P[1]=="\099\104\101\099\107\112\111\105\110\116\072\105\116"then table.remove(P,1)k(P)elseif P[1]=="\110\101\119\076\097\112"then A()elseif P[1]=="\114\101\115\101\116"then o()elseif P[1]=="\115\101\116\065\099\116\105\118\101"then table.remove(P,1)b(P)elseif P[1]=="\114\097\099\101\070\105\110\105\115\104\101\100"then table.remove(P,1)N()end end end

local function setupCheckpoints(args)
	if not (activePlayer) then return end
		
	local numLaps = 1
	if #args >= 1 then
		numLaps = args[1]
	end

	-- Player is in race
	inRace = true
	
	-- Set the number of laps in the race and use it to calc the total number
	-- of checkpoints
	if (numLaps and _numLaps == 0) then
		_numLaps = numLaps
		numCheckpoints = numCheckpoints * _numLaps
	end
	
	-- Set up checkpoints (color as not hit)
	for _, checkpoint in ipairs(checkpointList) do
		local checkpointCollisionBody = checkpoint:FindFirstChild("Checkpoint")
		
		-- Set color of checkpoint
		checkpointCollisionBody.Color = NOT_HIT_COLOR
		
		-- Set color of checkpoint ring if one exists
		local ring = checkpoint:FindFirstChild("Ring")
		if ring then
			ring.Color = NOT_HIT_COLOR
		end
	end
	
	if not ArrowGuide then
		ArrowGuide = require(script:WaitForChild("ArrowGuide"))
	end
	arrow = ArrowGuide.new(checkpointList)
end -- setupCheckpoints()

local function checkpointHit(args)	
	if not (activePlayer and inRace) then return end
	
	local checkpointCollisionBody = false
	if #args >= 1 then
		checkpointCollisionBody = args[1]
	else
		return
	end
	
	local parent = checkpointCollisionBody.Parent
	
	-- Mark checkpoint as hit
	local hit = parent:FindFirstChild("Hit")
	if not (hit) then
		hit = Instance.new("BoolValue")
		hit.Name = "Hit"
		hit.Parent = parent
		hit.Value = true
	else
		-- Checkpoint already hit
		return
	end
	
	-- Set color of checkpoint
	checkpointCollisionBody.Color = HIT_COLOR
		
	-- Set color of checkpoint ring if one exists
	local ring = checkpointCollisionBody.Parent:FindFirstChild("Ring")
	if ring then
		ring.Color = HIT_COLOR
	end
	
	-- Create particle effect
	local particle = checkpointParticle:Clone()
	local character = player.Character or player.CharacterAdded:wait()
	particle.CFrame = character.PrimaryPart.CFrame
	particle.Parent = character.PrimaryPart

	--particle.CFrame = checkpointCollisionBody.CFrame
	--particle.Parent = checkpointCollisionBody

	local emitterChildren = particle:GetChildren()
	
	for _, child in pairs(emitterChildren) do 
		-- If the child is a particle, then cause it to emit
		if child:IsA("ParticleEmitter") then
			child:Emit(10) 
		end
	end

	-- Destroy particle after PARTICLE_DURATION seconds
	spawn(function() wait(PARTICLE_DURATION) particle:Destroy() end)
	
	-- Play checkpoint sound
	checkpointSound.Parent = checkpointCollisionBody
	checkpointSound:Play()
	
	-- Increment checkpoints hit count
	numCheckpointsHit = numCheckpointsHit + 1
	
	-- Display checkpoint count
	CheckpointCount.Text = tostring(numCheckpointsHit).."/"..tostring(numCheckpoints)
end -- checkpointHit()

local function newLap()
	if not (activePlayer and inRace) then return end
	
	-- Set up checkpoints (color as not hit)
	for _, checkpoint in ipairs(checkpointList) do
		local checkpointCollisionBody = checkpoint:FindFirstChild("Checkpoint")
		
		-- Delete hit BoolValue
		local hit = checkpoint:FindFirstChild("Hit")
		if hit then
			hit:Destroy()
		end
		
		-- Set color of checkpoint
		checkpointCollisionBody.Color = NOT_HIT_COLOR
		
		-- Set color of checkpoint ring if one exists
		local ring = checkpoint:FindFirstChild("Ring")
		if ring then
			ring.Color = NOT_HIT_COLOR
		end
	end
end -- newLap()

local function resetCheckpoints()
	inRace = false
	numCheckpointsHit = 0
	
		-- Set up checkpoints (color as not hit)
	for _, checkpoint in ipairs(checkpointList) do
		local checkpointCollisionBody = checkpoint:FindFirstChild("Checkpoint")
		
		-- Delete hit BoolValue
		local hit = checkpoint:FindFirstChild("Hit")
		if hit then
			hit:Destroy()
		end
		
		-- Set color of checkpoint
		checkpointCollisionBody.Color = HIT_COLOR
		
		-- Set color of checkpoint ring if one exists
		local ring = checkpoint:FindFirstChild("Ring")
		if ring then
			ring.Color = HIT_COLOR
		end
	end
	
	arrow:Destroy()
	
	-- Display checkpoint count
	CheckpointCount.Text = tostring(numCheckpointsHit).."/"..tostring(numCheckpoints)
end -- resetCheckpoints()

local function setActive(args)
	local active = false
	if #args >= 1 then
		active = args[1]
	else
		return
	end

	activePlayer = active
	
	-- No longer in current race if no longer active
	if (not active and inRace) then
		inRace = false
		resetCheckpoints()
	end

	if not active then
		-- Hide racing GUIs
		local PlayerGui = player.PlayerGui
		local TopBar = PlayerGui:FindFirstChild("TopBar")
		TopBar.Enabled = false
	end
end -- setActive()

local function raceFinished()
	RaceFinishedSound:Play()
end

local function checkpointEvent(args)
	for _, arg in pairs(args) do
		if arg[1] == "setup" then
			table.remove(arg, 1)
			setupCheckpoints(arg)
		elseif arg[1] == "checkpointHit" then
			table.remove(arg, 1)
			checkpointHit(arg)
		elseif arg[1] == "newLap" then
			newLap()
		elseif arg[1] == "reset" then
			resetCheckpoints()
		elseif arg[1] == "setActive" then
			table.remove(arg, 1)
			setActive(arg)
		elseif arg[1] == "raceFinished" then
			table.remove(arg, 1)
			raceFinished()
		end
	end
end -- checkpointEvent()