TimeTrials Rework

ORIGINAL SCRIPT AND CREDIT FOUND HERE!

This script now requires QB-Core and CW-Performance.
Preview on Live Server

DISCLAIMER: I am a self taught dev, still learning. Code may be a POS but I’m workin on it haha.

0.8.5 July 21st

  • Small whitelist fixes
  • Code/Comment cleanup
  • Added vehicle_names.lua to fix cars showing NULL in scores
  • Added another track, more planned.
  • Any vehicle spawned through TimeTrials will now delete itself after the player exits to prevent vehicle spam.

0.8.0 Update July 13th

  • Implementation of basic framework detection for QB-Core added, standalone should work but is untested. Plan on having ESX and OX done for 0.9
  • Tweaked cancel timer settings
  • Fixed scoreboard not updating when entering new vehicle
  • Performance Improvement
  • Car Whitelisting with optional spawning for whitelisted cars
  • Many more options in config and tracks.lua
  • code cleanup

0.7.0 Update: posted on June 20th 2025

New features:

  • Countdown Timer (If you run out of time it cancels the time-trial.)
  • Fuelpump Placement (For the RP servers, should help for custom ymaps)
  • More Config Options (Blip settings, initial countdown time, countdown multiplyer, HUD Colors, &More)
  • Slight HUD refresh (all on screen timers and score displays converted from Seconds to Minutes:Seconds)
  • Car class whitelist. Allow/Disallow certain car classes. (Please check tracks.lua for setting classes)
  • Class based high scores, only see scores from same car class
  • Payout for completion, high score, and time remaining bonus
  • Debug for server console when a TT is completed along with the payout description
  • First pass of github version check

Possible future options:

  • Switch from json scores to db using oxmysql
  • Item based nui menu for scores, if we use oxmysql we could get all scores by vehicle and more fun stuff
  • config switch in tracks.lua for drift version of track, with custom function checks for devs to add, will probably setup for EasyDrift by default. And a check for IsInDriftMode or DriftHandling… something of that nature.

Preview:
→ 0.8 Youtube Preview Link ←





Link:
Github Download

5 Likes

Would be nice to get a video of the updates you’ve made. Interesting to see this oldie revived!

IMO the best way to run something like this is to access from an item or something like radial menu. I find the phone based stuff way to cumbersome, and not as organic as just using something on the spot to start a race.

Would recommend you work on this for QBox, a lot more you can do with ox_lib and Qbx_core.

1 Like

I’ll post a preview once I get done adding some more to it. Finishing up a few things in the next few days on it.

1 Like

bro can u share with me how could you learn it so easily like I’m lost in this environment and there are no tutorials on YouTube and qbcore documentation are very bad

Update just posted, video uploading now. It doesn’t seem like much but getting the timeout timer added in will now make the payout system possible as people can’t abuse length between checkpoints.

New features:

  • Countdown Timer (If you run out of time it cancels the time-trial.)
  • Fuelpump Placement (For the RP servers, should help for custom ymaps
  • More Config Options (Blip settings, initial countdown time, countdown multiplier)
  • Slight HUD refresh (all on screen timers and score displays converted from Seconds to Minutes:Seconds)

Next I plan on focusing on the framework implementation and payout function. I don’t have to really worry about keeping up on a standalone version as we have the old script, so this will be more and more QB-core dependent going on in the future. The payout function should go quick then I can start adding the optional item based features, and Config settings to fix modded vehicles showing as NULL

Still welcome to any ideas or feature requests you all have.

The Codeium extension for VS Code helped me a lot along the way. I learn best by doing so being able to just ask how to do it, being shown, and given an example really helped. It’s been a great AI tool!

It’d be cool if it’s possible to add anti-cheat features. Like my server has a handling editor but if this script forces the player to use the server default handling that’ll be nice.

I’ll look into it! Thank you for the suggestion!

1 Like

This is such an amazing script! Keep it up :slight_smile:

Also… I just came up with an idea tho, if I can pick which vehicle categories can do which races according to vehicles.lua in qb-core, that would be wonderful. For example, vanilla sports and muscles can do some races but for other races, they are restricted, and only custom categories that I made in vehicles.lua can do them.

I apologize for asking you too many things…lol

1 Like

U can do that with a whitelisting/blacklist system, basically whitelisting certain cars for each track like this
tracks.lua

        title = "LookOutPoint [RACE]",
        isEnabled = true,
        showWaypoints = false,
        trialBlacklist = true,
        blacklistVehicles = {
            [GetHashKey("anubis")] = true,
            [GetHashKey("a33maxima")] = true,
            [GetHashKey("c63hr")] = true,
            [GetHashKey("dc2")] = true,
            [GetHashKey("e46")] = true,
            [GetHashKey("evo9")] = true,
            [GetHashKey("m6coupe")] = true,
            [GetHashKey("mansrs6")] = true,
            [GetHashKey("priustaxi")] = true,
            [GetHashKey("r34g")] = true,
            [GetHashKey("r35")] = true,
            [GetHashKey("rs4avant")] = true,
            [GetHashKey("s30")] = true,
            [GetHashKey("z4alchemist")] = true,
            [GetHashKey("z32")] = true,
            [GetHashKey("jester3")] = true,
            
        },
        money = 220,
        exp = 220,

client.lua

                if GetDistanceBetweenCoords( race.start.x, race.start.y, race.start.z, 
                 GetEntityCoords(player)) < START_PROMPT_DISTANCE  then
                    helpMessage("Press ~INPUT_CONTEXT~ to Race!")
                    if (IsControlJustReleased(1, 51)) then
                        local player = GetPlayerPed(-1)
                        local pVeh = GetVehiclePedIsIn(player, false)
                            if race.trialBlacklist then
                            local pVehModel = GetEntityModel(pVeh)
                                if race.blacklistVehicles[pVehModel] == false
                                then
                        -- Set race index, clear scores and trigger event to start the race
                                raceState.index = index
                                raceState.scores = nil
                                raceState.getTime = index
                                TriggerEvent("raceCountdown")

                                else
                                    TriggerEvent('chat:addMessage', {
                                        color = {255,0,0},
                                        multiline = true,
                                        args = {"Car not allowed!"}
                                
                                    })
                                    end
                                end
                                if  not race.trialBlacklist then
                                        raceState.index = index
                                        raceState.getTime = index
                                        TriggerEvent("raceCountdown")
                            break
                        end

i have it setup as a blacklist but you could just change if race.blacklistVehicles[pVehModel] == false then to if race.blacklistVehicles[pVehModel] == true and it´ll act like a whitelist, then rename it if you want
only annoyance with this is that you´ll have to manually whitelist the cars for each track, theres better ways but thats the way I have it setup and I thought it might help you out

1 Like

no leaderboars show any ideas?

It lists the top 10 fastest times, player, and vehicle used above each starting zone.

i did run for the first time but it dint show and dint create the json file

I love this script, really cool you picked it up and make it qb-core friendly. all seems to work great i just not getting the top ten times to show. i think it not saves the times, i keep getting fastest track while i know there was a faster time.

it might be missing the scores.txt file as something changed and it no longer creates it if it’s not there. Let me get everything set back up and look into it.

Dev server has been purchased which will turn into a showcase server for the mod now that I will be working on this again. Thanks for waiting while I took a much needed break from development. My last bender was 6 months straight of dayz server development with over 170 server mod change-logs and 75 hours of DayZ Tools time logged… I’m hoping this time around I don’t dive into the deep end but take it slowly with a weekend here and a weekend there. I already have the fivem server setup with the resources I want… If you do check out the preview server, it’s setup as a racing server, I’ll update everything here once I get a good sized TimeTrials update ready to push.

Those that have used my version of the resource and have any idea’s now is the time to share them. :slight_smile: I hope everyone enjoys the summer and gets outdoors with some friends!! Had a good few games of disc golf myself recently with some buddies and brews.

1 Like

Fix for the scores not showing up listed below, or the next big update will fix it.

Find the following on line 18 - 44 of timetrials_sv.lua

-- Save scores to JSON file
function saveScores(scores)
    local file = io.open(scoreFileName, "w+")
    if file then
        local contents = json.encode(scores)
        file:write(contents)
        io.close( file )
        return true
    else
        return false
    end
end

-- Load scores from JSON file
function getScores()
    local contents = ""
    local myTable = {}
    local file = io.open(scoreFileName, "r")
    if file then
        -- read all contents of file into a string
        local contents = file:read("*a")
        myTable = json.decode(contents);
        io.close( file )
        return myTable
    end
    return {}
end

and replace it with the following

-- Save scores to JSON file
function saveScores(scores)
    local contents = json.encode(scores)

    SaveResourceFile(GetCurrentResourceName(), scoreFileName, contents, -1)
end

-- Load scores from JSON file
function getScores()
    local contents = ""
    local myTable = {}
    local contents = LoadResourceFile(GetCurrentResourceName(), scoreFileName)
		

    if contents then
        myTable = json.decode(contents)
				return myTable
    end
end
1 Like

Thank you man, will try this out asap.
i am happy you pick this project up again, but not gonna lie, i have no idea what you cold do more lol, maybe a reset option, but that is all i can think about right now, just love the script and be able to have some cool time trials for my players

Small update to 0.6.0 for fixes and feature update.

Update to 0.7.0

This version requires a clean install.

More config options, more implementation of class based high scores, checkpoint style slightly reworked.

More to come…

1 Like