function RaceModule.SetRacers(z,a)for z=1,#a,1 do addRacer(a[z])end end function RaceModule.RegisterCheckpoint(z,a)if not checkpoints[a]then local z=Checkpoint.new(a,RaceModule)numCheckpoints=numCheckpoints+1 checkpoints[a]=z end end function RaceModule.PlayerCrossedCheckpoint(d,a,z)local m=racers[a]if not m or m.FinishedRace then return end local Q=m.CurrentLap CheckpointEvent:FireClient(a,{{"\099\104\101\099\107\112\111\105\110\116\072\105\116";z.CollisionBody}})if not m:HasStartedLap(Q)then m:StartLap(Q)onLapStartedEvent:Fire(a,Q)end if m:HasStartedLap(Q)then local d=z:SetPlayerPassed(a,Q)if not d then onCheckpointPassedEvent:Fire(z.CollisionBody)end end if hasPlayerFinishedLap(a,Q)then local z=m:FinishLap(Q)onLapFinishedEvent:Fire(a,Q,z)if Q==numLaps then if not winner then winner=a end m.FinishedRace=true onRaceFinishedEvent:Fire(winner)else wait()CheckpointEvent:FireClient(a,{{"\110\101\119\076\097\112"}})m.CurrentLap=m.CurrentLap+1 end end end function RaceModule.Start(z,a)if debugEnabled then print("\082\065\067\069\077\079\068\085\076\069\058 \083\116\097\114\116\105\110\103 \114\097\099\101")end winner=nil assert(numCheckpoints>0,"\078\111 \099\104\101\099\107\112\111\105\110\116\115 \114\101\103\105\115\116\101\114\101\100")assert(startCheckpoint,"\083\116\097\114\116 \067\104\101\099\107\112\111\105\110\116 \110\111\116 \115\101\116")assert(finishCheckpoint,"\070\105\110\105\115\104 \067\104\101\099\107\112\111\105\110\116 \110\111\116 \115\101\116")if debugEnabled then print("\082\065\067\069\077\079\068\085\076\069\058 \067\104\101\099\107\105\110\103 \105\102 \112\108\097\121\101\114\115 \115\101\116")end if#racers==0 then RaceModule:SetRacers(a)end for a,z in pairs(checkpoints)do z:Reset()end onRaceStartedEvent:Fire()local d=false local m m=RaceModule.RaceFinished:connect(function()d=true racers={}m:disconnect()end)spawn(function()wait(raceDuration)if not d then onRaceFinishedEvent:Fire(winner)end end)end

function RaceModule:SetRacers(racerList)
	for i = 1, #racerList do
		addRacer(racerList[i])
	end
end -- RaceModule:SetRacers()

function RaceModule:RegisterCheckpoint(checkpoint)
	if not checkpoints[checkpoint] then
		local newCheckpoint = Checkpoint.new(checkpoint, RaceModule)
		numCheckpoints = numCheckpoints + 1
		checkpoints[checkpoint] = newCheckpoint
	end
end -- RaceModule:RegisterCheckpoint()

function RaceModule:PlayerCrossedCheckpoint(player, checkpoint)
	local racer = racers[player]	
	
	if not racer or racer.FinishedRace then return end
	local currentLap = racer.CurrentLap

	CheckpointEvent:FireClient(player, {{"checkpointHit", checkpoint.CollisionBody}})
	
	if not racer:HasStartedLap(currentLap) then
		racer:StartLap(currentLap)
		onLapStartedEvent:Fire(player, currentLap)
	end
	
	if racer:HasStartedLap(currentLap) then
		local alreadyPassed = checkpoint:SetPlayerPassed(player, currentLap)
		if not alreadyPassed then		
			onCheckpointPassedEvent:Fire(checkpoint.CollisionBody)
		end
	end
	
	if hasPlayerFinishedLap(player, currentLap) then
		local lapTime = racer:FinishLap(currentLap)
		onLapFinishedEvent:Fire(player, currentLap, lapTime)
		if currentLap == numLaps then
			if not winner then
				winner = player
			end
			racer.FinishedRace = true
			onRaceFinishedEvent:Fire(winner)
		else
			wait() -- Let the last checkpoint temporarily change to hit color
			
			CheckpointEvent:FireClient(player, {{"newLap"}})
			
			racer.CurrentLap = racer.CurrentLap + 1
		end
	end
end -- RaceModule:PlayerCrossedCheckpoint()

function RaceModule:Start(activePlayers)
	if debugEnabled then print("RACEMODULE: Starting race") end	
	
	winner = nil
	
	assert(numCheckpoints > 0, "No checkpoints registered")
	assert(startCheckpoint, "Start Checkpoint not set")
	assert(finishCheckpoint, "Finish Checkpoint not set")
	
	if debugEnabled then print("RACEMODULE: Checking if players set") end
	if #racers == 0 then
		RaceModule:SetRacers(activePlayers)
	end	
	
	for _, checkpoint in pairs(checkpoints) do
		checkpoint:Reset()
	end

	onRaceStartedEvent:Fire()
	
	local raceOver = false
	local finishedConnection
	finishedConnection = RaceModule.RaceFinished:connect(function()
		raceOver = true
		racers = {}
		finishedConnection:disconnect()
	end)
	spawn(function()
		wait(raceDuration)
		if not raceOver then
			onRaceFinishedEvent:Fire(winner)
		end
	end)
end -- RaceModule:Start()