[RELEASE] Pringus Simple Race Script

Am i just dumb AF or can this not do more than one race ? :face_with_raised_eyebrow:

can u share your player life script ?

So i made it so i can set up multiple races now.
My only problem is to get the timer to display the time in Minutes:Seconds.Milliseconds

Here are 2 ways of freezing the people at the start of the race

This one completelely freezes them until the countdown is over:

    Citizen.CreateThread(function()
        local time = 0
        function setcountdown(x)
          time = GetGameTimer() + x*1000
        end
        function getcountdown()
          return math.floor((time-GetGameTimer())/1000)
        end
        setcountdown(6)
        while getcountdown() > 0 do
            Citizen.Wait(1)
			FreezeEntityPosition(GetVehiclePedIsUsing(GetPlayerPed(-1)), true)  -- freeze player
            DrawHudText(getcountdown(), {255,191,0,255},0.5,0.4,4.0,4.0)
        end
            TriggerEvent("fs_race:BeginRaceCarbonDownhill")
			FreezeEntityPosition(GetVehiclePedIsUsing(GetPlayerPed(-1)), false) -- unfreeze player
    end)
end)

This one makes the player unable to move, but not 100% freezed, so he can do a burnout while countdown is running:

    Citizen.CreateThread(function()
        local time = 0
        function setcountdown(x)
          time = GetGameTimer() + x*1000
        end
        function getcountdown()
          return math.floor((time-GetGameTimer())/1000)
        end
        setcountdown(6)
        while getcountdown() > 0 do
            Citizen.Wait(1)
			FreezeEntityPosition(GetVehiclePedIsUsing(GetPlayerPed(-1)), true)  -- freeze player
            DrawHudText(getcountdown(), {255,191,0,255},0.5,0.4,4.0,4.0)
			FreezeEntityPosition(GetVehiclePedIsUsing(GetPlayerPed(-1)), false) -- unfreeze player
        end
            TriggerEvent("fs_race:BeginRaceCarbonDownhill")
    end)
end)```

Mind sharing your version with multiple races? I’d love to see how it’s done.

I changed multiple things now, so i thought of posting the whole thing.

  • Made it easier to set up, just replace the stuff in the How To and you’re done.
  • Added a sound to the countdown.
  • Removed the line TriggerEvent("fs_freemode:displayHelp", "Press ~INPUT_CONTEXT~ to Race!") since it didnt work for me and just produced lag while standing on the start marker.
  • 2 ways of freezing the player at the start, move 1 line to switch between them.
  • Timer Shows Minutes:Seconds.ms instead of Seconds.ms
  • Race is cancelled with F1, F2 and F3 and plays the “wasted” sound when cancelled.
    (on my server thats Menu, NoClip, and TP to Waypoint Key)
  • Checkpoint sound changed to just a slight beep.
  • Finish sound changed so smth more rewarding than “Wasted”.
-- Pringus race script (probably more accurately a time trial script) 
-- todo: add laps?
-- Edit by Meh

function LocalPed()
	return GetPlayerPed(-1)
end
 
--[[
	HOW TO:
	
	- Replace every TRACKNAME with the name of your track. No spaces! (eg. AkinaDownhill)
	- Replace every STARTX, STARTY and STARTZ with the coordinates of your start line
	- Replace every STARTHEADING with the heading the car should have when starting the race
	- Replace every LINE1 and LINE2 with the text you would like to have displayed above the start marker
	- Replace every TRACKNAMEDISPLAY to the name that the blip should have on the map, and that gets shown in chat when 
	  finishing the race. Spaces allowed. (eg. Akina - Downhill)
	- (optional) Make checkpoints
	- Make a finish line
	
		Shitty multi race support:
		Make a new resource, with a new timer.lua, and set up a new race.


	Add checkpoints using the formatting:
	CheckPoints[1] =  	{ x = 0.00, y = 0.00, z = 0.00, type = 5}
	Number in brackets is the number of the checkpoint (CheckPoints[1] would be the first 
	checkpoint in the race)
	Change the checkpoint type to determine whether or not it will be a checkpoint or
	the finish line. type = 5 for regular checkpoints, type = 9 for the finish.
]]

local CheckPoints = {}
CheckPoints[1] =  	{ x = example , y = example, z = example, type = 5} -- a checkpoint
CheckPoints[2] =  	{ x = example, y = example, z = example, type = 9} -- the finish line


----------------------------------------------------------------------------------------------------------------
-- Theoretically you dont have to edit any of the below because you can replace all the stuff in the "How to" --
----------------------------------------------------------------------------------------------------------------

local blips = {
    {title="TRACKNAMEDISPLAY", colour=4, id=315, x= STARTX, y= STARTY, z= STARTZ}
}


local IsRacingTRACKNAME = false 
local cP = 1
local cP2 = 2
local checkpoint
local blip
local startTime

Citizen.CreateThread(function()
    preRace()
end)

function preRace()
    while true do
        Citizen.Wait(0)
        if not IsRacingTRACKNAME then
            DrawMarker(1, STARTX, STARTY, STARTZ - 1.5, 0, 0, 0, 0, 0, 0, 3.0001, 3.0001, 1.5001, 250, 250, 250, 180, 0, 0, 0,0)

        if GetDistanceBetweenCoords( STARTX, STARTY, STARTZ, GetEntityCoords(LocalPed())) < 20.0 then
            	Draw3DText( STARTX, STARTY, STARTZ  -.500, "LINE1",4,0.3,0.2)
            	Draw3DText( STARTX, STARTY, STARTZ  -.900, "LINE2",4,0.3,0.2)
		end
		if GetDistanceBetweenCoords( STARTX, STARTY, STARTZ, GetEntityCoords(LocalPed())) < 2.0 then
				Draw3DText( STARTX, STARTY, STARTZ  -1.400, "Press E to start",4,0.15,0.1)
        end
        if GetDistanceBetweenCoords( STARTX, STARTY, STARTZ, GetEntityCoords(LocalPed())) < 2.0 then
            if (IsControlJustReleased(1, 38)) then
                if IsRacingTRACKNAME == false then
                    IsRacingTRACKNAME = true
                    TriggerEvent("cRace:TPALLTRACKNAME")
                else
                    return
                end
            end
        end
    end
end
end

RegisterNetEvent("cRace:TPALLTRACKNAME")
AddEventHandler("cRace:TPALLTRACKNAME", function()
    SetPedCoordsKeepVehicle(PlayerPedId(), STARTX, STARTY, STARTZ)
	PlaySoundFrontend(-1, "5s", "MP_MISSION_COUNTDOWN_SOUNDSET" )
    SetEntityHeading(PlayerPedId(), STARTHEADING)
    Citizen.CreateThread(function()
        local time = 0
        function setcountdown(x)
          time = GetGameTimer() + x*1000
        end
        function getcountdown()
          return math.floor((time-GetGameTimer())/1000)
        end
        setcountdown(5)  -- The Seconds that count down
        while getcountdown() > 0 do
            Citizen.Wait(1)
			FreezeEntityPosition(GetVehiclePedIsUsing(GetPlayerPed(-1)), true) 
            DrawHudText(getcountdown(), {255,191,0,255},0.48,0.4,4.0,4.0)
			FreezeEntityPosition(GetVehiclePedIsUsing(GetPlayerPed(-1)), false) -- move this one down 1 line to not have "burnout", but 100% freeze
        end
            TriggerEvent("fs_race:BeginRaceTRACKNAME")
    end)
end)

RegisterNetEvent("fs_race:BeginRaceTRACKNAME") --main loop
AddEventHandler("fs_race:BeginRaceTRACKNAME", function()
    startTime = GetGameTimer()
    Citizen.CreateThread(function()
        checkpoint = CreateCheckpoint(CheckPoints[cP].type, CheckPoints[cP].x,  CheckPoints[cP].y,  CheckPoints[cP].z + 2, CheckPoints[cP2].x, CheckPoints[cP2].y, CheckPoints[cP2].z, 8.0, 204, 204, 1, 100, 0)
        blip = AddBlipForCoord(CheckPoints[cP].x, CheckPoints[cP].y, CheckPoints[cP].z)          
        while IsRacingTRACKNAME do 	
            Citizen.Wait(5)
            SetVehicleDensityMultiplierThisFrame(0.0)
            SetPedDensityMultiplierThisFrame(0.0)
            SetRandomVehicleDensityMultiplierThisFrame(0.0)
            SetParkedVehicleDensityMultiplierThisFrame(0.0)
            SetScenarioPedDensityMultiplierThisFrame(0.0, 0.0)

            -- Comment these 3 out if you don't want HUD text:
			
            --DrawHudText(math.floor(GetDistanceBetweenCoords(CheckPoints[cP].x,  CheckPoints[cP].y,  CheckPoints[cP].z, GetEntityCoords(GetPlayerPed(-1)))) .. " meters", {249, 249, 249,255},0.0,0.75,1.0,1.0)
            DrawHudText(string.format("%i / %i", cP, tablelength(CheckPoints)), {249, 249, 249, 255},0.118,0.765,0.7,0.7)
            DrawHudText(formatTimer(startTime, GetGameTimer()), {240, 240, 240, 240}, 0.019,0.745,1.1,1.1)	
			
					--Cancelling the race when F1, F2 or F3 is pressed:
					if (IsControlJustReleased(1, 288) or IsDisabledControlJustReleased( 0, 288 )) then
                        PlaySoundFrontend(-1, "ScreenFlash", "WastedSounds")
                        DeleteCheckpoint(checkpoint)
                        RemoveBlip(blip)
                        IsRacingTRACKNAME = false
                        cP = 1
                        cP2 = 2
                        preRace()
                    end	
					if (IsControlJustReleased(1, 289) or IsDisabledControlJustReleased( 0, 289 )) then
                        PlaySoundFrontend(-1, "ScreenFlash", "WastedSounds")
                        DeleteCheckpoint(checkpoint)
                        RemoveBlip(blip)
                        IsRacingTRACKNAME = false
                        cP = 1
                        cP2 = 2
                        preRace()
                    end	
					if (IsControlJustReleased(1, 170) or IsDisabledControlJustReleased( 0, 170 )) then
                        PlaySoundFrontend(-1, "ScreenFlash", "WastedSounds")
                        DeleteCheckpoint(checkpoint)
                        RemoveBlip(blip)
                        IsRacingTRACKNAME = false
                        cP = 1
                        cP2 = 2
                        preRace()
                    end
					
                if GetDistanceBetweenCoords(CheckPoints[cP].x,  CheckPoints[cP].y,  CheckPoints[cP].z, GetEntityCoords(GetPlayerPed(-1))) < 6.0 then
                    if CheckPoints[cP].type == 5 then
                        DeleteCheckpoint(checkpoint)
                        RemoveBlip(blip)
                        PlaySoundFrontend(-1, "Beep_Red", "DLC_HEIST_HACKING_SNAKE_SOUNDS" )
                        cP = cP + 1
					if(CheckPoints[cP].type == 5) then
						cP2 = cP2+1
					end
                        checkpoint = CreateCheckpoint(CheckPoints[cP].type, CheckPoints[cP].x,  CheckPoints[cP].y,  CheckPoints[cP].z + 2, CheckPoints[cP2].x, CheckPoints[cP2].y, CheckPoints[cP2].z, 8.0, 204, 204, 1, 100, 0)
                        blip = AddBlipForCoord(CheckPoints[cP].x, CheckPoints[cP].y, CheckPoints[cP].z)
                    else
                        PlaySoundFrontend(-1, "CHECKPOINT_PERFECT", "HUD_MINI_GAME_SOUNDSET")
                        DeleteCheckpoint(checkpoint)
                        RemoveBlip(blip)
                        IsRacingTRACKNAME = false
                        cP = 1
                        cP2 = 2
                        TriggerEvent("chatMessage", "^1Race Timer^0", {0,0,0}, string.format("Finished ^1TRACKNAMEDISPLAY ^0with a time of ^1^_" .. formatTimer(startTime, GetGameTimer())))
                        preRace()
                    end
                    else
                end
            end
        end)
end)				
				
--utility funcs

function tablelength(T)
    local count = 0
    for _ in pairs(T) do 
    count = count + 1 end
    return count
end

function formatTimer(startTime, currTime)

	newTime = currTime - startTime

	local floor = math.floor

	local ms = floor(newTime % 1000)
	local hundredths = floor(ms / 10)
	local seconds = floor(newTime / 1000)
	local minutes = floor(seconds / 60);   seconds = floor(seconds % 60)
	formattedTime = string.format("%02d:%02d.%02d", minutes, seconds, hundredths)

	return formattedTime

end

function Draw3DText(x,y,z,textInput,fontId,scaleX,scaleY)
	local px,py,pz=table.unpack(GetGameplayCamCoords())
	local dist = GetDistanceBetweenCoords(px,py,pz, x,y,z, 1)
    
	local scale = (1/dist)*20
	local fov = (1/GetGameplayCamFov())*100
	local scale = scale*fov
    
	SetTextScale(scaleX*scale, scaleY*scale)
	SetTextFont(fontId)
	SetTextProportional(1)
	SetTextColour(255, 255, 255, 250)
	SetTextDropshadow(1, 1, 1, 1, 255)
	SetTextEdge(2, 0, 0, 0, 150)
	SetTextDropShadow()
	SetTextOutline()
	SetTextEntry("STRING")
	SetTextCentre(1)
	AddTextComponentString(textInput)
	SetDrawOrigin(x,y,z+2, 0)
	DrawText(0.0, 0.0)
	ClearDrawOrigin()
end

function DrawHudText(text,colour,coordsx,coordsy,scalex,scaley) --courtesy of driftcounter
    SetTextFont(4) -- 7 is the heavy GTA font
    SetTextProportional(7)
    SetTextScale(scalex, scaley)
    local colourr,colourg,colourb,coloura = table.unpack(colour)
    SetTextColour(colourr,colourg,colourb, coloura)
    SetTextDropshadow(0, 0, 0, 0, coloura)
    SetTextEdge(1, 0, 0, 0, coloura)
    SetTextDropShadow()
    SetTextOutline()
    SetTextEntry("STRING")
    AddTextComponentString(text)
    DrawText(coordsx,coordsy)
end

--create blip
Citizen.CreateThread(function()
    for _, info in pairs(blips) do
        info.blip = AddBlipForCoord(info.x, info.y, info.z)
        SetBlipSprite(info.blip, info.id)
        SetBlipDisplay(info.blip, 4)
        SetBlipScale(info.blip, 1.0)
        SetBlipColour(info.blip, info.colour)
        SetBlipAsShortRange(info.blip, true)
        BeginTextCommandSetBlipName("STRING")
        AddTextComponentString(info.title)
        EndTextCommandSetBlipName(info.blip)
    end
end)
4 Likes

could create a system to save the times of the players.

1 Like

yeah a thing of the style …:stuck_out_tongue:

server

RegisterServerEvent('esx_illegalrace:logs')
AddEventHandler('esx_illegalrace:logs', function(finaltime)

    local _source 		  = source
    local xPlayer         = ESX.GetPlayerFromId(source)
	local time 		= os.date("%d/%m/%y %X")
	local newFile	 = "illegalrace : " .. xPlayer.name .. " : have just made a time of " .. finaltime .. " secondes à la date du " .. time .. "\n"
	local file 	   = io.open('logs/illegalrace.txt', "a")

	file:write(newFile)
	file:flush()
	file:close()

end)

client

Citizen.CreateThread(function()
	while true do
		Citizen.Wait(0)
		if CurrentAction ~= nil then
			SetTextComponentFormat('STRING')
			AddTextComponentString(CurrentActionMsg)
      DisplayHelpTextFromStringLabel(0, 0, 1, -1)

      if CurrentAction == 'finish' then
        local playerPed = GetPlayerPed(-1)
        local vehicle = GetVehiclePedIsIn(playerPed,  false)
         finaltime = math.floor(Config.secondsRemaining *-1 )

        if IsPedInAnyVehicle(playerPed,  false) and RaceStarted then
          ESX.Game.DeleteVehicle(vehicle)
          illegalraceStartTimer       = false
          RaceStarted             = false 
          Config.secondsRemaining = 60
          ESX.ShowNotification(_U('yourtime') .. finaltime .. _U('seconde'))
          ESX.ShowNotification(_U('thanks'))
          TriggerServerEvent('esx_illegalrace:logs', finaltime)
        end
      end 
    end

    if illegalraceStartTimer and not RaceStarted then
      DrawTextCentre(_U('start') .. Config.secondsRemaining .. _U('seconde'))
    end	

	end
end)

You should release this as a standalone resource.

1 Like

Maybe soon, i have to revisit it and set up all timers on my server again, anyways, and will likely edit it again.

1 Like

what about race with more players?

1 Like