The error occurs on line 45 when the player finishes the race. I think it has to do with introducing the player through the function from line 179 in the racers table
Do I have to create another function when the player finishes the race and remove him from the table?
local RaceModule = {}
local Checkpoint = require(script.Checkpoint)
local Racer = require(script.Racer)
-- Local variable defaults
local startCheckpoint = nil
local finishCheckpoint = nil
local numLaps = 3
local autoStart = true
local raceDuration = 180
local intermissionDuration = 15
local debugEnabled = false
-- Other local variables
local numCheckpoints = 0
local checkpoints = {}
local racers = {}
local winner = nil
-- Private functions
local function getCheckpointFromPart(part)
for _, checkpoint in pairs(checkpoints) do
if checkpoint.CollisionBody == part then
return checkpoint
end
end
return nil
end
local function hasPlayerFinishedLap(player, lap)
for _, checkpoint in pairs(checkpoints) do
if checkpoint:PlayerLapPassed(player, lap) ~= lap then
return false
end
end
return true
end
local function addRacer(player)
racers[player] = Racer.new()
end
local function checkAllFinished()
for _, racer in pairs(racers) do
if not racer:hasFinishedLap(numLaps) then
return false
end
end
return true
end
-- Getters/Setters
function RaceModule:SetStartCheckpoint(checkpoint)
startCheckpoint = getCheckpointFromPart(checkpoint)
end
function RaceModule:GetStartCheckpoint()
return startCheckpoint
end
function RaceModule:SetFinishCheckpoint(checkpoint)
finishCheckpoint = getCheckpointFromPart(checkpoint)
end
function RaceModule:GetFinishCheckpoint()
return finishCheckpoint
end
function RaceModule:SetNumLaps(number)
numLaps = number
end
function RaceModule:GetNumLaps()
return numLaps
end
function RaceModule:SetAutoStart(autostart)
autoStart = autostart
end
function RaceModule:GetAutoStart()
return autoStart
end
function RaceModule:SetRaceDuration(duration)
raceDuration = duration
end
function RaceModule:GetRaceDuration()
return raceDuration
end
function RaceModule:SetIntermissionDuration(duration)
intermissionDuration = duration
end
function RaceModule:GetIntermissionDuration()
return intermissionDuration
end
function RaceModule:SetDebugEnabled(enabled)
debugEnabled = enabled
end
function RaceModule:GetDebugEnabled()
return debugEnabled
end
-- Events
local onRaceStartedEvent = Instance.new("BindableEvent")
RaceModule.RaceStarted = onRaceStartedEvent.Event
local onRaceFinishedEvent = Instance.new("BindableEvent")
RaceModule.RaceFinished = onRaceFinishedEvent.Event
local onLapStartedEvent = Instance.new("BindableEvent")
RaceModule.LapStarted = onLapStartedEvent.Event
local onLapFinishedEvent = Instance.new("BindableEvent")
RaceModule.LapFinished = onLapFinishedEvent.Event
local onIntermissionStartedEvent = Instance.new("BindableEvent")
RaceModule.IntermissionStarted = onIntermissionStartedEvent.Event
local onCheckpointPassedEvent = Instance.new("BindableEvent")
RaceModule.CheckpointPassed = onCheckpointPassedEvent.Event
-- Public functions
function RaceModule:SetRacers(racerList)
for i = 1, #racerList do
addRacer(racerList[i])
end
end
function RaceModule:RegisterCheckpoint(checkpoint)
if not checkpoints[checkpoint] then
local newCheckpoint = Checkpoint.new(checkpoint, RaceModule)
numCheckpoints = numCheckpoints + 1
checkpoints[checkpoint] = newCheckpoint
end
end
function RaceModule:PlayerCrossedCheckpoint(player, checkpoint)
local racer = racers[player]
if not racer or racer.FinishedRace then return end
local currentLap = racer.CurrentLap
if checkpoint == startCheckpoint and 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 checkpoint == finishCheckpoint and 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
if checkAllFinished() then
onRaceFinishedEvent:Fire(winner)
end
else
racer.CurrentLap = racer.CurrentLap + 1
end
end
end
workspace.Part.ProximityPrompt.Triggered:Connect(function(player)
table.insert(racers,player)
print(table.unpack(racers))
end)
function RaceModule:Start()
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
print("problema")
print("aicea ii problema")
RaceModule:SetRacers(racers)
print(table.unpack(racers))
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
-- Autostart code
spawn(function()
wait(5)
repeat
onIntermissionStartedEvent:Fire()
wait(intermissionDuration)
RaceModule:Start()
RaceModule.RaceFinished:wait()
until autoStart == false
end)
return RaceModule
Race module
local Lap = {}
Lap.__index = Lap
function Lap.new()
local newLap = {}
setmetatable(newLap, Lap)
newLap.Started = true
newLap.StartTime = tick()
newLap.LapTime = 0
newLap.Finished = false
return newLap
end
local Racer = {}
Racer.__index = Racer
function Racer.new()
local newRacer = {}
setmetatable(newRacer, Racer)
newRacer.CurrentLap = 1
newRacer.Laps = {}
newRacer.FinishedRace = false
return newRacer
end
function Racer:StartLap(lapNumber)
self.Laps[lapNumber] = Lap.new()
end
function Racer:FinishLap(lapNumber)
local lap = self.Laps[lapNumber]
lap.LapTime = tick() - lap.StartTime
lap.Finished = true
return lap.LapTime
end
function Racer:HasStartedLap(lapNumber)
if lapNumber <= #self.Laps then
return self.Laps[lapNumber].Started
end
return false
end
function Racer:HasFinishedLap(lapNumber)
if lapNumber <= #self.Laps then
return self.Laps[lapNumber].Finished
end
return false
end
return Racer
Checkpoint
local Checkpoint = {}
Checkpoint.__index = Checkpoint
function Checkpoint.new(collisionBody, manager)
assert(collisionBody, "Trying to set partless checkpoint")
local newCheckpoint = {CollisionBody = collisionBody, Manager = manager}
setmetatable(newCheckpoint, Checkpoint)
newCheckpoint.PlayersTouched = {}
newCheckpoint.CollisionBody.Touched:connect(function(otherPart)
if otherPart and otherPart.Parent then
local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
if player then
newCheckpoint.Manager:PlayerCrossedCheckpoint(player, newCheckpoint)
end
end
end)
newCheckpoint.CollisionConnection = nil
return newCheckpoint
end
function Checkpoint:Reset()
self.PlayersTouched = {}
end
function Checkpoint:SetPlayerPassed(player, lapNumber)
local alreadyPassed = (self.PlayersTouched[player] == lapNumber)
self.PlayersTouched[player] = lapNumber
return alreadyPassed
end
function Checkpoint:PlayerLapPassed(player)
return self.PlayersTouched[player]
end
return Checkpoint