if not _Race then
Race={
Checkpoints={
};
Begin=0;
StartPos=nil;
};
_Race=true;
end
function Race:OnTimerTick()
if self.Started then
for i,v in pairs(self.Checkpoints) do
local pos=v.pos;
local racers=System.GetEntitiesInSphereByClass(pos,v.radius,\"Player\");
--printf(\"Checking checkpoint %d\",i);
for i,player in pairs(racers) do
if player.RaceID and player.RaceID==self.RcID then
if not player:IsOnVehicle() then
Msg:SendToTarget(player,\"You must be on vehicle!\");
else
local diff=v.Index - player.CPIDX;
if diff==1 then
if v.Index==#self.Checkpoints then
if not self.WonIDX then
Chat:SendToAll(nil,\"%s won the race with time %.2f s\",player:GetName(),_time-self.Begin);
self.WonIDX=2;
player.RaceID=nil;
else
Chat:SendToAll(nil,\"%s finished the race at #%d position with time %.2f s\",player:GetName(),self.WonIDX,_time-self.Begin);
player.RaceID=nil;
self.WonIDX=self.WonIDX+1;
end
else
Msg:SendToTarget(player,\"Checkpoint %d/%d, your time: %.2f s\",\"center\",v.Index,#self.Checkpoints,_time-self.Begin);
player.CPIDX=v.Index;
end
elseif diff>1 then
Msg:SendToTarget(player,\"You missed %d checkpoints!\",\"center\",diff-1);
end
end
end
end
end
end
end
function Race:AddCP(posi,radi)
radi=radi or 5;
local idx=#self.Checkpoints+1;
self.Checkpoints[#self.Checkpoints+1]={
pos=posi;
radius=radi;
Index=idx;
};
end
function Race:Clear()
self.Checkpoints={};
self.Started=false;
self.Exists=false;
end
function Race:Start()
self.WonIDX=nil;
self.Begin=_time;
self.Started=true;
end
function Race:Stop()
self.Started=false;
self.Exists=false;
end
function Race:Create(pos)
self.StartPos=pos;
end
function Race:Countdown()
self.RcID=math.random();
self.Exists=true;
for i=1,60 do
Script.SetTimer(i*1000,function()
if i==60 then
Msg:SendToAll(\"RACE STARTED!\",\"center\",i);
self:Start();
else
Msg:SendToAll(\"Race starting in %d seconds, write !joinrace to join!\",\"center\",60-i);
end
end);
end
end
AddChatCommand(\"crrace\",function(self,player)
Chat:SendToTarget(nil,player,\"Race successfuly created, !cdrace to countdown!\");
Race:Create(player:GetPos());
end,nil,{AdminOnly=true});
AddChatCommand(\"cdrace\",function(self,player)
Race.Started=false;
Chat:SendToTarget(nil,player,\"Successfuly launched countdown!\");
Race:Countdown();
end,nil,{AdminOnly=true});
AddChatCommand(\"startrace\",function(self,player)
Chat:SendToTarget(nil,player,\"Race successfuly started!\");
Race:Start();
end,nil,{AdminOnly=true});
AddChatCommand(\"stoprace\",function(self,player)
Chat:SendToTarget(nil,player,\"Race successfuly stopped!\");
Race:Stop();
end,nil,{AdminOnly=true});
AddChatCommand(\"clearrace\",function(self,player)
Chat:SendToTarget(nil,player,\"Race successfuly cleared!\");
Race:Clear();
end,nil,{AdminOnly=true});
AddChatCommand(\"addcp\",function(self,player)
Chat:SendToTarget(nil,player,\"Checkpoint %d successfuly added!\",#Race.Checkpoints+1);
Race:AddCP(player:GetPos(),5);
end,nil,{AdminOnly=true});
AddChatCommand(\"joinrace\",function(self,player)
if not Race.Exists then Chat:SendToTarget(nil,player,\"No race in progress!\"); return; end
if Race.Started then Chat:SendToTarget(nil,player,\"Race has already started!\"); return; end
Chat:SendToTarget(nil,player,\"Successfuly joined the race, use !leaverace to leave.\");
player.RaceID=Race.RcID;
player.CPIDX=0;
player.opos=player:GetPos();
TeleportPlayer(player,Race.StartPos);
end,nil);
AddChatCommand(\"leaverace\",function(self,player)
if not Race.Exists then Chat:SendToTarget(nil,player,\"No race in progress!\"); return; end
if not player.opos then Chat:SendToTarget(nil,player,\"You aren\'t on race!\"); return; end
Chat:SendToTarget(nil,player,\"Successfuly left the race!\");
player.RaceID=nil;
TeleportPlayer(player,player.opos);
player.opos=nil;
end,nil);
SafeWriting.FuncContainer:LoadPlugin(Race);
Checkpoints are virtual, it means that you have to spawn physical entity first with LevelDesigner, and then !Addcp.
Before you add any checkpoint, use !crrace on place, where you want players to be teleported to, when they write !Joinrace.
To start race-countdown, use !cdrace; to stop race, use !stoprace and to let race continue, !startrace.
To clear current race, use !clearrace and to leave the race, use !leaverace.❤️ 0