local QBCore = exports['qb-core']:GetCoreObject() local Countdown = 10 local ToFarCountdown = 10 local FinishedUITimeout = false local RaceData = { InCreator = false, InRace = false, ClosestCheckpoint = 0, } local CreatorData = { RaceName = nil, Checkpoints = {}, TireDistance = 3.0, ConfirmDelete = false, } local CurrentRaceData = { RaceId = nil, RaceName = nil, Checkpoints = {}, Started = false, CurrentCheckpoint = nil, TotalLaps = 0, Lap = 0, } -- Handlers AddEventHandler('onResourceStop', function(resource) if resource == GetCurrentResourceName() then for k, _ in pairs(CreatorData.Checkpoints) do if CreatorData.Checkpoints[k].pileleft ~= nil then local coords = CreatorData.Checkpoints[k].offset.right local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CreatorData.Checkpoints[k].pileright = nil end if CreatorData.Checkpoints[k].pileright ~= nil then local coords = CreatorData.Checkpoints[k].offset.right local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CreatorData.Checkpoints[k].pileright = nil end end for k, _ in pairs(CurrentRaceData.Checkpoints) do if CurrentRaceData.Checkpoints[k] ~= nil then if CurrentRaceData.Checkpoints[k].pileleft ~= nil then local coords = CurrentRaceData.Checkpoints[k].offset.right local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CurrentRaceData.Checkpoints[k].pileright = nil end if CurrentRaceData.Checkpoints[k].pileright ~= nil then local coords = CurrentRaceData.Checkpoints[k].offset.right local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CurrentRaceData.Checkpoints[k].pileright = nil end end end end end) -- Functions local function DrawText3Ds(x, y, z, text) SetTextScale(0.35, 0.35) SetTextFont(4) SetTextProportional(1) SetTextColour(255, 255, 255, 215) BeginTextCommandDisplayText("STRING") SetTextCentre(true) AddTextComponentSubstringPlayerName(text) SetDrawOrigin(x,y,z, 0) EndTextCommandDisplayText(0.0, 0.0) local factor = (string.len(text)) / 370 DrawRect(0.0, 0.0+0.0125, 0.017+ factor, 0.03, 0, 0, 0, 75) ClearDrawOrigin() end local function GetClosestCheckpoint() local pos = GetEntityCoords(PlayerPedId(), true) local current = nil local dist = nil for id, _ in pairs(CreatorData.Checkpoints) do if current ~= nil then if #(pos - vector3(CreatorData.Checkpoints[id].coords.x, CreatorData.Checkpoints[id].coords.y, CreatorData.Checkpoints[id].coords.z)) < dist then current = id dist = #(pos - vector3(CreatorData.Checkpoints[id].coords.x, CreatorData.Checkpoints[id].coords.y, CreatorData.Checkpoints[id].coords.z)) end else dist = #(pos - vector3(CreatorData.Checkpoints[id].coords.x, CreatorData.Checkpoints[id].coords.y, CreatorData.Checkpoints[id].coords.z)) current = id end end RaceData.ClosestCheckpoint = current end local function CreatorUI() CreateThread(function() while true do if RaceData.InCreator then SendNUIMessage({ action = "Update", type = "creator", data = CreatorData, racedata = RaceData, active = true, }) else SendNUIMessage({ action = "Update", type = "creator", data = CreatorData, racedata = RaceData, active = false, }) break end Wait(200) end end) end local function DeleteCheckpoint() local NewCheckpoints = {} if RaceData.ClosestCheckpoint ~= 0 then if CreatorData.Checkpoints[RaceData.ClosestCheckpoint] ~= nil then if CreatorData.Checkpoints[RaceData.ClosestCheckpoint].blip ~= nil then RemoveBlip(CreatorData.Checkpoints[RaceData.ClosestCheckpoint].blip) CreatorData.Checkpoints[RaceData.ClosestCheckpoint].blip = nil end if CreatorData.Checkpoints[RaceData.ClosestCheckpoint].pileleft ~= nil then local coords = CreatorData.Checkpoints[RaceData.ClosestCheckpoint].offset.left local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CreatorData.Checkpoints[RaceData.ClosestCheckpoint].pileleft = nil end if CreatorData.Checkpoints[RaceData.ClosestCheckpoint].pileright ~= nil then local coords = CreatorData.Checkpoints[RaceData.ClosestCheckpoint].offset.right local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CreatorData.Checkpoints[RaceData.ClosestCheckpoint].pileright = nil end for id, data in pairs(CreatorData.Checkpoints) do if id ~= RaceData.ClosestCheckpoint then NewCheckpoints[#NewCheckpoints+1] = data end end CreatorData.Checkpoints = NewCheckpoints else QBCore.Functions.Notify('You cant go to fast', 'error') end else QBCore.Functions.Notify('You cant go too fast', 'error') end end local function SaveRace() local RaceDistance = 0 for k, v in pairs(CreatorData.Checkpoints) do if k + 1 <= #CreatorData.Checkpoints then local checkpointdistance = #(vector3(v.coords.x, v.coords.y, v.coords.z) - vector3(CreatorData.Checkpoints[k + 1].coords.x, CreatorData.Checkpoints[k + 1].coords.y, CreatorData.Checkpoints[k + 1].coords.z)) RaceDistance = RaceDistance + checkpointdistance end end CreatorData.RaceDistance = RaceDistance TriggerServerEvent('qb-lapraces:server:SaveRace', CreatorData) QBCore.Functions.Notify('Race: '..CreatorData.RaceName..' is saved!', 'success') for id,_ in pairs(CreatorData.Checkpoints) do if CreatorData.Checkpoints[id].blip ~= nil then RemoveBlip(CreatorData.Checkpoints[id].blip) CreatorData.Checkpoints[id].blip = nil end if CreatorData.Checkpoints[id] ~= nil then if CreatorData.Checkpoints[id].pileleft ~= nil then local coords = CreatorData.Checkpoints[id].offset.left local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CreatorData.Checkpoints[id].pileleft = nil end if CreatorData.Checkpoints[id].pileright ~= nil then local coords = CreatorData.Checkpoints[id].offset.right local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CreatorData.Checkpoints[id].pileright = nil end end end RaceData.InCreator = false CreatorData.RaceName = nil CreatorData.Checkpoints = {} end local function AddCheckpoint() local PlayerPed = PlayerPedId() local PlayerPos = GetEntityCoords(PlayerPed) local PlayerVeh = GetVehiclePedIsIn(PlayerPed) local Offset = { left = { x = (GetOffsetFromEntityInWorldCoords(PlayerVeh, -CreatorData.TireDistance, 0.0, 0.0)).x, y = (GetOffsetFromEntityInWorldCoords(PlayerVeh, -CreatorData.TireDistance, 0.0, 0.0)).y, z = (GetOffsetFromEntityInWorldCoords(PlayerVeh, -CreatorData.TireDistance, 0.0, 0.0)).z, }, right = { x = (GetOffsetFromEntityInWorldCoords(PlayerVeh, CreatorData.TireDistance, 0.0, 0.0)).x, y = (GetOffsetFromEntityInWorldCoords(PlayerVeh, CreatorData.TireDistance, 0.0, 0.0)).y, z = (GetOffsetFromEntityInWorldCoords(PlayerVeh, CreatorData.TireDistance, 0.0, 0.0)).z, } } CreatorData.Checkpoints[#CreatorData.Checkpoints+1] = { coords = { x = PlayerPos.x, y = PlayerPos.y, z = PlayerPos.z, }, offset = Offset, } for id, CheckpointData in pairs(CreatorData.Checkpoints) do if CheckpointData.blip ~= nil then RemoveBlip(CheckpointData.blip) end CheckpointData.blip = AddBlipForCoord(CheckpointData.coords.x, CheckpointData.coords.y, CheckpointData.coords.z) SetBlipSprite(CheckpointData.blip, 1) SetBlipDisplay(CheckpointData.blip, 4) SetBlipScale(CheckpointData.blip, 0.8) SetBlipAsShortRange(CheckpointData.blip, true) SetBlipColour(CheckpointData.blip, 26) ShowNumberOnBlip(CheckpointData.blip, id) SetBlipShowCone(CheckpointData.blip, false) BeginTextCommandSetBlipName("STRING") AddTextComponentSubstringPlayerName("Checkpoint: "..id) EndTextCommandSetBlipName(CheckpointData.blip) end end local function CreatorLoop() CreateThread(function() while RaceData.InCreator do local PlayerPed = PlayerPedId() local PlayerVeh = GetVehiclePedIsIn(PlayerPed) if PlayerVeh ~= 0 then if IsControlJustPressed(0, 161) or IsDisabledControlJustPressed(0, 161) then AddCheckpoint() end if IsControlJustPressed(0, 162) or IsDisabledControlJustPressed(0, 162) then if CreatorData.Checkpoints ~= nil and next(CreatorData.Checkpoints) ~= nil then DeleteCheckpoint() else QBCore.Functions.Notify('You have not placed any checkpoints yet..', 'error') end end if IsControlJustPressed(0, 311) or IsDisabledControlJustPressed(0, 311) then if CreatorData.Checkpoints ~= nil and #CreatorData.Checkpoints >= 2 then SaveRace() else QBCore.Functions.Notify('You must have at least 10 checkpoints', 'error') end end if IsControlJustPressed(0, 40) or IsDisabledControlJustPressed(0, 40) then if CreatorData.TireDistance + 1.0 ~= 16.0 then CreatorData.TireDistance = CreatorData.TireDistance + 1.0 else QBCore.Functions.Notify('You can not go higher than 15') end end if IsControlJustPressed(0, 39) or IsDisabledControlJustPressed(0, 39) then if CreatorData.TireDistance - 1.0 ~= 1.0 then CreatorData.TireDistance = CreatorData.TireDistance - 1.0 else QBCore.Functions.Notify('You cannot go lower than 2') end end else local coords = GetEntityCoords(PlayerPedId()) DrawText3Ds(coords.x, coords.y, coords.z, 'You must be in a vehicle') end if IsControlJustPressed(0, 163) or IsDisabledControlJustPressed(0, 163) then if not CreatorData.ConfirmDelete then CreatorData.ConfirmDelete = true QBCore.Functions.Notify('Press [9] again to confirm', 'error', 5000) else for _, CheckpointData in pairs(CreatorData.Checkpoints) do if CheckpointData.blip ~= nil then RemoveBlip(CheckpointData.blip) end end for id,_ in pairs(CreatorData.Checkpoints) do if CreatorData.Checkpoints[id].pileleft ~= nil then local coords = CreatorData.Checkpoints[id].offset.left local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 8.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CreatorData.Checkpoints[id].pileleft = nil end if CreatorData.Checkpoints[id].pileright ~= nil then local coords = CreatorData.Checkpoints[id].offset.right local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 8.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CreatorData.Checkpoints[id].pileright = nil end end RaceData.InCreator = false CreatorData.RaceName = nil CreatorData.Checkpoints = {} QBCore.Functions.Notify('Race-editor canceled!', 'error') CreatorData.ConfirmDelete = false end end Wait(3) end end) end local function RaceUI() CreateThread(function() while true do if CurrentRaceData.Checkpoints ~= nil and next(CurrentRaceData.Checkpoints) ~= nil then if CurrentRaceData.Started then CurrentRaceData.RaceTime = CurrentRaceData.RaceTime + 1 CurrentRaceData.TotalTime = CurrentRaceData.TotalTime + 1 end SendNUIMessage({ action = "Update", type = "race", data = { CurrentCheckpoint = CurrentRaceData.CurrentCheckpoint, TotalCheckpoints = #CurrentRaceData.Checkpoints, TotalLaps = CurrentRaceData.TotalLaps, CurrentLap = CurrentRaceData.Lap, RaceStarted = CurrentRaceData.Started, RaceName = CurrentRaceData.RaceName, Time = CurrentRaceData.RaceTime, TotalTime = CurrentRaceData.TotalTime, BestLap = CurrentRaceData.BestLap, }, racedata = RaceData, active = true, }) else if not FinishedUITimeout then FinishedUITimeout = true SetTimeout(10000, function() FinishedUITimeout = false SendNUIMessage({ action = "Update", type = "race", data = {}, racedata = RaceData, active = false, }) end) end break end Wait(12) end end) end local function SetupRace(sRaceData, Laps) RaceData.RaceId = sRaceData.RaceId CurrentRaceData = { RaceId = sRaceData.RaceId, Creator = sRaceData.Creator, RaceName = sRaceData.RaceName, Checkpoints = sRaceData.Checkpoints, Started = false, CurrentCheckpoint = 1, TotalLaps = Laps, Lap = 1, RaceTime = 0, TotalTime = 0, BestLap = 0, Racers = {} } for k, v in pairs(CurrentRaceData.Checkpoints) do ClearAreaOfObjects(v.offset.left.x, v.offset.left.y, v.offset.left.z, 50.0, 0) CurrentRaceData.Checkpoints[k].pileleft = CreateObject(`prop_offroad_tyres02`, v.offset.left.x, v.offset.left.y, v.offset.left.z, 0, 0, 0) PlaceObjectOnGroundProperly(CurrentRaceData.Checkpoints[k].pileleft) FreezeEntityPosition(CurrentRaceData.Checkpoints[k].pileleft, 1) SetEntityAsMissionEntity(CurrentRaceData.Checkpoints[k].pileleft, 1, 1) ClearAreaOfObjects(v.offset.right.x, v.offset.right.y, v.offset.right.z, 50.0, 0) CurrentRaceData.Checkpoints[k].pileright = CreateObject(`prop_offroad_tyres02`, v.offset.right.x, v.offset.right.y, v.offset.right.z, 0, 0, 0) PlaceObjectOnGroundProperly(CurrentRaceData.Checkpoints[k].pileright) FreezeEntityPosition(CurrentRaceData.Checkpoints[k].pileright, 1) SetEntityAsMissionEntity(CurrentRaceData.Checkpoints[k].pileright, 1, 1) CurrentRaceData.Checkpoints[k].blip = AddBlipForCoord(v.coords.x, v.coords.y, v.coords.z) SetBlipSprite(CurrentRaceData.Checkpoints[k].blip, 1) SetBlipDisplay(CurrentRaceData.Checkpoints[k].blip, 4) SetBlipScale(CurrentRaceData.Checkpoints[k].blip, 0.6) SetBlipAsShortRange(CurrentRaceData.Checkpoints[k].blip, true) SetBlipColour(CurrentRaceData.Checkpoints[k].blip, 26) ShowNumberOnBlip(CurrentRaceData.Checkpoints[k].blip, k) BeginTextCommandSetBlipName("STRING") AddTextComponentSubstringPlayerName("Checkpoint: "..k) EndTextCommandSetBlipName(CurrentRaceData.Checkpoints[k].blip) end RaceUI() end local function showNonLoopParticle(dict, particleName, coords, scale) RequestNamedPtfxAsset(dict) while not HasNamedPtfxAssetLoaded(dict) do Wait(0) end UseParticleFxAssetNextCall(dict) local particleHandle = StartParticleFxLoopedAtCoord(particleName, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, scale, false, false, false) SetParticleFxLoopedColour(particleHandle, 0, 255, 0 ,0) return particleHandle end local function DoPilePfx() if CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint] ~= nil then local Timeout = 500 local Size = 2.0 local left = showNonLoopParticle('core', 'ent_sht_flame', CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint].offset.left, Size) local right = showNonLoopParticle('core', 'ent_sht_flame', CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint].offset.right, Size) SetTimeout(Timeout, function() StopParticleFxLooped(left, false) StopParticleFxLooped(right, false) end) end end local function SetupPiles() for k, v in pairs(CreatorData.Checkpoints) do if CreatorData.Checkpoints[k].pileleft == nil then ClearAreaOfObjects(v.offset.left.x, v.offset.left.y, v.offset.left.z, 50.0, 0) CreatorData.Checkpoints[k].pileleft = CreateObject(`prop_offroad_tyres02`, v.offset.left.x, v.offset.left.y, v.offset.left.z, 0, 0, 0) PlaceObjectOnGroundProperly(CreatorData.Checkpoints[k].pileleft) FreezeEntityPosition(CreatorData.Checkpoints[k].pileleft, 1) SetEntityAsMissionEntity(CreatorData.Checkpoints[k].pileleft, 1, 1) end if CreatorData.Checkpoints[k].pileright == nil then ClearAreaOfObjects(v.offset.right.x, v.offset.right.y, v.offset.right.z, 50.0, 0) CreatorData.Checkpoints[k].pileright = CreateObject(`prop_offroad_tyres02`, v.offset.right.x, v.offset.right.y, v.offset.right.z, 0, 0, 0) PlaceObjectOnGroundProperly(CreatorData.Checkpoints[k].pileright) FreezeEntityPosition(CreatorData.Checkpoints[k].pileleft, 1) SetEntityAsMissionEntity(CreatorData.Checkpoints[k].pileleft, 1, 1) end end end local function GetMaxDistance(OffsetCoords) local Distance = #(vector3(OffsetCoords.left.x, OffsetCoords.left.y, OffsetCoords.left.z) - vector3(OffsetCoords.right.x, OffsetCoords.right.y, OffsetCoords.right.z)) local Retval = 7.5 if Distance > 20.0 then Retval = 12.5 end return Retval end local function SecondsToClock(seconds) seconds = tonumber(seconds) local retval if seconds <= 0 then retval = "00:00:00"; else local hours = string.format("%02.f", math.floor(seconds/3600)); local mins = string.format("%02.f", math.floor(seconds/60 - (hours*60))); local secs = string.format("%02.f", math.floor(seconds - hours*3600 - mins *60)); retval = hours..":"..mins..":"..secs end return retval end local function FinishRace() TriggerServerEvent('qb-lapraces:server:FinishPlayer', CurrentRaceData, CurrentRaceData.TotalTime, CurrentRaceData.TotalLaps, CurrentRaceData.BestLap) if CurrentRaceData.BestLap ~= 0 then QBCore.Functions.Notify('Race finished in '..SecondsToClock(CurrentRaceData.TotalTime)..', with the best lap: '..SecondsToClock(CurrentRaceData.BestLap)) else QBCore.Functions.Notify('Race finished in '..SecondsToClock(CurrentRaceData.TotalTime)) end for k, _ in pairs(CurrentRaceData.Checkpoints) do if CurrentRaceData.Checkpoints[k].blip ~= nil then RemoveBlip(CurrentRaceData.Checkpoints[k].blip) CurrentRaceData.Checkpoints[k].blip = nil end if CurrentRaceData.Checkpoints[k].pileleft ~= nil then local coords = CurrentRaceData.Checkpoints[k].offset.left local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CurrentRaceData.Checkpoints[k].pileleft = nil end if CurrentRaceData.Checkpoints[k].pileright ~= nil then local coords = CurrentRaceData.Checkpoints[k].offset.right local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CurrentRaceData.Checkpoints[k].pileright = nil end end CurrentRaceData.RaceName = nil CurrentRaceData.Checkpoints = {} CurrentRaceData.Started = false CurrentRaceData.CurrentCheckpoint = 0 CurrentRaceData.TotalLaps = 0 CurrentRaceData.Lap = 0 CurrentRaceData.RaceTime = 0 CurrentRaceData.TotalTime = 0 CurrentRaceData.BestLap = 0 CurrentRaceData.RaceId = nil RaceData.InRace = false end local function Info() local PlayerPed = PlayerPedId() local plyVeh = GetVehiclePedIsIn(PlayerPed, false) local IsDriver = GetPedInVehicleSeat(plyVeh, -1) == PlayerPed local returnValue = plyVeh ~= 0 and plyVeh ~= nil and IsDriver return returnValue, plyVeh end local function IsInRace() local retval = false if RaceData.InRace then retval = true end return retval end local function IsInEditor() local retval = false if RaceData.InCreator then retval = true end return retval end exports('IsInEditor', IsInEditor) exports('IsInRace', IsInRace) -- Events RegisterNetEvent('qb-lapraces:client:StartRaceEditor', function(RaceName) if not RaceData.InCreator then CreatorData.RaceName = RaceName RaceData.InCreator = true CreatorUI() CreatorLoop() else QBCore.Functions.Notify('You are already making a race.', 'error') end end) RegisterNetEvent('qb-lapraces:client:UpdateRaceRacerData', function(RaceId, aRaceData) if (CurrentRaceData.RaceId ~= nil) and CurrentRaceData.RaceId == RaceId then CurrentRaceData.Racers = aRaceData.Racers end end) RegisterNetEvent('qb-lapraces:client:JoinRace', function(Data, Laps) if not RaceData.InRace then RaceData.InRace = true SetupRace(Data, Laps) TriggerServerEvent('qb-lapraces:server:UpdateRaceState', CurrentRaceData.RaceId, false, true) else QBCore.Functions.Notify('Youre already in a race..', 'error') end end) RegisterNetEvent('qb-lapraces:client:LeaveRace', function(_) QBCore.Functions.Notify('You have completed the race!') for k, _ in pairs(CurrentRaceData.Checkpoints) do if CurrentRaceData.Checkpoints[k].blip ~= nil then RemoveBlip(CurrentRaceData.Checkpoints[k].blip) CurrentRaceData.Checkpoints[k].blip = nil end if CurrentRaceData.Checkpoints[k].pileleft ~= nil then local coords = CurrentRaceData.Checkpoints[k].offset.left local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CurrentRaceData.Checkpoints[k].pileleft = nil end if CurrentRaceData.Checkpoints[k].pileright ~= nil then local coords = CurrentRaceData.Checkpoints[k].offset.right local Obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, `prop_offroad_tyres02`, 0, 0, 0) DeleteObject(Obj) ClearAreaOfObjects(coords.x, coords.y, coords.z, 50.0, 0) CurrentRaceData.Checkpoints[k].pileright = nil end end CurrentRaceData.RaceName = nil CurrentRaceData.Checkpoints = {} CurrentRaceData.Started = false CurrentRaceData.CurrentCheckpoint = 0 CurrentRaceData.TotalLaps = 0 CurrentRaceData.Lap = 0 CurrentRaceData.RaceTime = 0 CurrentRaceData.TotalTime = 0 CurrentRaceData.BestLap = 0 CurrentRaceData.RaceId = nil RaceData.InRace = false FreezeEntityPosition(GetVehiclePedIsIn(PlayerPedId(), false), false) end) RegisterNetEvent('qb-lapraces:client:RaceCountdown', function() TriggerServerEvent('qb-lapraces:server:UpdateRaceState', CurrentRaceData.RaceId, true, false) if CurrentRaceData.RaceId ~= nil then while Countdown ~= 0 do if CurrentRaceData.RaceName ~= nil then if Countdown == 10 then QBCore.Functions.Notify('The race will start in 10 seconds', 'error', 2500) PlaySound(-1, "slow", "SHORT_PLAYER_SWITCH_SOUND_SET", 0, 0, 1) elseif Countdown <= 5 then QBCore.Functions.Notify(Countdown, 'error', 500) PlaySound(-1, "slow", "SHORT_PLAYER_SWITCH_SOUND_SET", 0, 0, 1) end Countdown = Countdown - 1 FreezeEntityPosition(GetVehiclePedIsIn(PlayerPedId(), true), true) else break end Wait(1000) end if CurrentRaceData.RaceName ~= nil then SetNewWaypoint(CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].coords.x, CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].coords.y) QBCore.Functions.Notify('GO!', 'success', 1000) SetBlipScale(CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].blip, 1.0) FreezeEntityPosition(GetVehiclePedIsIn(PlayerPedId(), true), false) DoPilePfx() CurrentRaceData.Started = true Countdown = 10 else FreezeEntityPosition(GetVehiclePedIsIn(PlayerPedId(), true), false) Countdown = 10 end else QBCore.Functions.Notify('You are not currently in a race..', 'error') end end) RegisterNetEvent('qb-lapraces:client:PlayerFinishs', function(RaceId, Place, FinisherData) if CurrentRaceData.RaceId ~= nil then if CurrentRaceData.RaceId == RaceId then QBCore.Functions.Notify(FinisherData.PlayerData.charinfo.firstname..' is finished on spot: '..Place, 'error', 3500) end end end) RegisterNetEvent('qb-lapraces:client:WaitingDistanceCheck', function() Wait(1000) CreateThread(function() while true do if not CurrentRaceData.Started then local ped = PlayerPedId() local pos = GetEntityCoords(ped) if CurrentRaceData.Checkpoints[1] ~= nil then local cpcoords = CurrentRaceData.Checkpoints[1].coords local dist = #(pos - vector3(cpcoords.x, cpcoords.y, cpcoords.z)) if dist > 115.0 then if ToFarCountdown ~= 0 then ToFarCountdown = ToFarCountdown - 1 QBCore.Functions.Notify('Go back to the start or you will be kicked from the race: '..ToFarCountdown..'s', 'error', 500) else TriggerServerEvent('qb-lapraces:server:LeaveRace', CurrentRaceData) ToFarCountdown = 10 break end Wait(1000) else if ToFarCountdown ~= 10 then ToFarCountdown = 10 end end end else break end Wait(3) end end) end) -- Threads CreateThread(function() while true do if RaceData.InCreator then local PlayerPed = PlayerPedId() local PlayerVeh = GetVehiclePedIsIn(PlayerPed) if PlayerVeh ~= 0 then local Offset = { left = { x = (GetOffsetFromEntityInWorldCoords(PlayerVeh, -CreatorData.TireDistance, 0.0, 0.0)).x, y = (GetOffsetFromEntityInWorldCoords(PlayerVeh, -CreatorData.TireDistance, 0.0, 0.0)).y, z = (GetOffsetFromEntityInWorldCoords(PlayerVeh, -CreatorData.TireDistance, 0.0, 0.0)).z, }, right = { x = (GetOffsetFromEntityInWorldCoords(PlayerVeh, CreatorData.TireDistance, 0.0, 0.0)).x, y = (GetOffsetFromEntityInWorldCoords(PlayerVeh, CreatorData.TireDistance, 0.0, 0.0)).y, z = (GetOffsetFromEntityInWorldCoords(PlayerVeh, CreatorData.TireDistance, 0.0, 0.0)).z, } } DrawText3Ds(Offset.left.x, Offset.left.y, Offset.left.z, 'Checkpoint L') DrawText3Ds(Offset.right.x, Offset.right.y, Offset.right.z, 'Checkpoint R') end end Wait(3) end end) CreateThread(function() while true do local ped = PlayerPedId() local pos = GetEntityCoords(ped) if CurrentRaceData.RaceName ~= nil then if CurrentRaceData.Started then local cp if CurrentRaceData.CurrentCheckpoint + 1 > #CurrentRaceData.Checkpoints then cp = 1 else cp = CurrentRaceData.CurrentCheckpoint + 1 end local data = CurrentRaceData.Checkpoints[cp] local CheckpointDistance = #(pos - vector3(data.coords.x, data.coords.y, data.coords.z)) local MaxDistance = GetMaxDistance(CurrentRaceData.Checkpoints[cp].offset) if CheckpointDistance < MaxDistance then if CurrentRaceData.TotalLaps == 0 then if CurrentRaceData.CurrentCheckpoint + 1 < #CurrentRaceData.Checkpoints then CurrentRaceData.CurrentCheckpoint = CurrentRaceData.CurrentCheckpoint + 1 SetNewWaypoint(CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].coords.x, CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].coords.y) TriggerServerEvent('qb-lapraces:server:UpdateRacerData', CurrentRaceData.RaceId, CurrentRaceData.CurrentCheckpoint, CurrentRaceData.Lap, false) DoPilePfx() PlaySound(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0, 0, 1) SetBlipScale(CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint].blip, 0.6) SetBlipScale(CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].blip, 1.0) else DoPilePfx() PlaySound(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0, 0, 1) CurrentRaceData.CurrentCheckpoint = CurrentRaceData.CurrentCheckpoint + 1 TriggerServerEvent('qb-lapraces:server:UpdateRacerData', CurrentRaceData.RaceId, CurrentRaceData.CurrentCheckpoint, CurrentRaceData.Lap, true) FinishRace() end else if CurrentRaceData.CurrentCheckpoint + 1 > #CurrentRaceData.Checkpoints then if CurrentRaceData.Lap + 1 > CurrentRaceData.TotalLaps then DoPilePfx() PlaySound(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0, 0, 1) CurrentRaceData.CurrentCheckpoint = CurrentRaceData.CurrentCheckpoint + 1 TriggerServerEvent('qb-lapraces:server:UpdateRacerData', CurrentRaceData.RaceId, CurrentRaceData.CurrentCheckpoint, CurrentRaceData.Lap, true) FinishRace() else DoPilePfx() PlaySound(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0, 0, 1) if CurrentRaceData.RaceTime < CurrentRaceData.BestLap then CurrentRaceData.BestLap = CurrentRaceData.RaceTime elseif CurrentRaceData.BestLap == 0 then CurrentRaceData.BestLap = CurrentRaceData.RaceTime end CurrentRaceData.RaceTime = 0 CurrentRaceData.Lap = CurrentRaceData.Lap + 1 CurrentRaceData.CurrentCheckpoint = 1 SetNewWaypoint(CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].coords.x, CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].coords.y) TriggerServerEvent('qb-lapraces:server:UpdateRacerData', CurrentRaceData.RaceId, CurrentRaceData.CurrentCheckpoint, CurrentRaceData.Lap, false) end else CurrentRaceData.CurrentCheckpoint = CurrentRaceData.CurrentCheckpoint + 1 if CurrentRaceData.CurrentCheckpoint ~= #CurrentRaceData.Checkpoints then SetNewWaypoint(CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].coords.x, CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].coords.y) TriggerServerEvent('qb-lapraces:server:UpdateRacerData', CurrentRaceData.RaceId, CurrentRaceData.CurrentCheckpoint, CurrentRaceData.Lap, false) SetBlipScale(CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint].blip, 0.6) SetBlipScale(CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint + 1].blip, 1.0) else SetNewWaypoint(CurrentRaceData.Checkpoints[1].coords.x, CurrentRaceData.Checkpoints[1].coords.y) TriggerServerEvent('qb-lapraces:server:UpdateRacerData', CurrentRaceData.RaceId, CurrentRaceData.CurrentCheckpoint, CurrentRaceData.Lap, false) SetBlipScale(CurrentRaceData.Checkpoints[#CurrentRaceData.Checkpoints].blip, 0.6) SetBlipScale(CurrentRaceData.Checkpoints[1].blip, 1.0) end DoPilePfx() PlaySound(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0, 0, 1) end end end else local data = CurrentRaceData.Checkpoints[CurrentRaceData.CurrentCheckpoint] -- DrawText3Ds(data.coords.x, data.coords.y, data.coords.z, 'Ga hier staan') DrawMarker(4, data.coords.x, data.coords.y, data.coords.z + 1.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.9, 1.5, 1.5, 255, 255, 255, 255, 0, 1, 0, 0, 0, 0, 0) end else Wait(1000) end Wait(3) end end) CreateThread(function() while true do if RaceData.InCreator then GetClosestCheckpoint() SetupPiles() end Wait(1000) end end) CreateThread(function() while true do local Driver, plyVeh = Info() if Driver then if GetVehicleCurrentGear(plyVeh) < 3 and GetVehicleCurrentRpm(plyVeh) == 1.0 and math.ceil(GetEntitySpeed(plyVeh) * 2.236936) > 50 then while GetVehicleCurrentRpm(plyVeh) > 0.6 do SetVehicleCurrentRpm(plyVeh, 0.3) Wait(1) end Wait(800) end end Wait(500) end end)