⭐ Check out our Tebex store for some cheap scripts ⭐
📷 Images & Video 📺
If you are updating make sure to check Updating for relevant SQL updates
Note: ESX requires ox_lib and ox_target
Note: For ESX make sure to change out moneyTypes to corresponding versions in the config (ESX uses "money" instead of "cash" for example)
Features:
- Create tracks
- Host races
- Automated Races
- Time Trial Bounties
- Built in Crypto system
- Buy-Ins and automated splits
- Phasing/Ghosting
- Reversed tracks
- Participation payouts
- Elmination races
- Racing user system with customizeable auth
- ELO system for ranked racing
- Crew system with rankings
- Elmination Races
- Advanced leaderboards
- Customizeable checkpoints
- Race positions
- Curated tracks (mark tracks as verified good)
- Split times
- Translateable
- Track Sharing
- Optional default tracks
- Forced first person mode
- Vehicle Performance Class limits
Do note, this script has TWO systems for participation money. Make sure to check the readme and read the comments regarding these and how to use them.
As of update posted on 1st July -23, racer names are unique. The max limit is by default 3 but can be set individually. If you want to remove names from DB without openign it up, an admin can use
/remracename <racerName>
As of update posted on 26th August -23 we will no longer support qb-menu usage.
As of update posted on 7th August -24 phasing/ghosting no longer has a transperancy, this might make it look different from videos you've seen
⭐ Check out our Tebex store for some cheap scripts ⭐
At the bottom left corner there's a cog wheel. Clicking this brings up the options menu (more stuff to come). But here you can toggle using the GPS route and the style of it.
Our idea with this feature is to allow admins to flag a track as "DONE". The track can no longer be edited. Additional features of curated tracks might be only allowing participation money to be paid out on those tracks, for example.
The key to this script working is making tracks that works well. If you're trying to do 200 checkpoint style races with checkpoints randomly thrown around the map, this is not the script for you. There is a max checkpoint variable in the config that will warn users when they reached the level. Some PCs might struggle with different lower/higher amounts tho, so keep that in mind.
- Avoid placing checkpoints on/under/near bridges/overpasses.
- GTA GPS can't handle opposite-directions on roads: Place checkpoints on the correct side of the road
- Intersections can be tricky for the GPS. We advice to not put checkpoints in the middle of them, but before or after, in the correct lane.
- Alleys can cause issues. Use with caution.
- The script spawns 2 entities + 1 emitter for EVERY checkpoint. If you have 100 checkpoints that might just crash peoples games.
You can grab the checkpoints from either My Tracks tab in game, by using the copy button or directly from the database entry and then pasting to something like https://pastebin.com/ There's an import function (if enabled in config) in the Create Track tab to import via paste.
Hop into the CW Discord and share some tracks in the racingapp-tracks channel!
The script offers automated races. You can set these up in the config (Config.AutomatedRaces
, Config.AutomatedOptions
). If any of these are commented out/removed the automation will not start.
The Automation will, at random, try to grab one of the tracks from the Config.AutomatedRaces
table at the interval of what you set in Config.AutomatedOptions.timeBetweenRaces
, by default this is 20 minutes. The races start after 5 minutes of popping up.
As of 16th November 2024 the script has cuztomizeable time trial bounties that players can collect. These are defined in the config in Config.Bounties
and Config.BountiesOptiones
. The config has most things explained in comments, but a bounty is defined like this example:
{
trackId = 'CW-4267', -- TrackId. Found in your tracks in racingapp or in DB
maxClass = 'B', -- Max Class
reversed = false, -- reversed track or not
timeToBeat = 130000, -- time you have to beat in milliseconds
extraTime = 5000, -- max time (in milliseconds) that can be added ontop of timeToBeat when generated
price = 500, -- Price money
sprint = true, -- require race to be a sprint to claim bounty
rankRequired = 2, -- Rank required to claim
},
These are randomized upon server start (~5 seconds after script start/restart). You can modify how many of these are added in the Bounties Options. If your auth type has the handleBounties
auth you should be able to re-roll the bounties from the bounties menu.
RacingApp has a built in crypto system tied to the racing user. To use this you can set your payment methods to 'racingcrypto'
and it will use the custom Racing Crypto System instead of your core payment system. The crypto is tied to a racinguser, so make sure you have a way to buy one of those with normal money if you don't want to have racing masters handle your users.
The system allows for buying, selling and transfering. There's a fee for selling (can be customized).
Want to use the Racing Crypto from other script? Check out Adding Racing Crypto To Other Scripts
The script offers user management now. We've moved away from the basic/master fob and instead users are saved in the database. To swap your user, open the racingapp and press the cog-icon to open the settings. To create users you can either buy a user account from a trader/laptop (if this is enabled in the config) or have someone create one for you.
The tiers are racer < creator < master < god and are defined as follows:
racer = {
join = true, -- join races
records = true, -- see records
setup = true, -- setup races
create = false, -- create races
control = false, -- control users
controlAll = false, -- control all users
}
...
join means you can join races
records means you can access records
setup means you can set up races
create means you can create tracks
control means you can manage users you create
controllAll allows you to control all users, and also permanently delete users
Basically, any racer name/user created by another player will be tied to them. So if person X buys an account from player Y, player Y can also revoke player Xs account via the in game menus, as long as player Y has a user with the control authorization.
The easiest way. Just use the Racing GPS that's included in the script.
If you want to open racingapp from another script you can use the exports
Client side:
exports['cw-racingapp']:openRacingApp()
Server side:
exports['cw-racingapp']:openRacingApp(source)
ALL EXPORTS ARE SERVER SIDE ONLY!
You'll need to know the name of the race user you want to check for here. Swap out 'RacerName' for whatever name you want to use
local racerName = 'This Is Just An Example String You Have To Change This'
local cryptoAmount = exports['cw-racingapp']:getRacerCrypto(racerName)
print(racerName, 'has ', cryptoAmount)
local racerName = 'This Is Just An Example String You Have To Change This'
local hasEnough = exports['cw-racingapp']:hasEnoughCrypto(racerName, 20)
print(racerName, 'has 20 or more crypto:', hasEnough )
local racerName = 'This Is Just An Example String You Have To Change This'
local success = exports['cw-racingapp']:addRacerCrypto(racerName, 20)
print('successfully gave', racerName, ' 20 crypto: ', success)
local racerName = 'This Is Just An Example String You Have To Change This'
local success = exports['cw-racingapp']:removeCrypto(racerName, 20)
print('successfully charged', racerName, ' 20 crypto: ', success)
This one is usefull if you want to get all users for a player so you can list them in other scripts
-- With CitizenID
local citizenId = 'ThisIsJustAnExampleStringYouHaveToChangeThis123'
local result = exports['cw-racingapp']:getRacingUsersByCitizenId(citizenId)
print('All racing users belonging to citizenid', citizenId, json.encode(result, {indent=true}) )
-- with Source
-- OBVIOUSLY YOU NEED TO HAVE A DEFINED SOURCE IN THIS ONE!!
local result = exports['cw-racingapp']:getRacingUsersBySrc(source)
print('All racing users belonging to source', source, json.encode(result, {indent=true}) )
Older Videos
Update to track editor:
Images
Track Setup
Leaderboards
Track Creation
You can create tracks from both using an in-game editor or copy/paste a set of checkpoints.
Manage Tracks
Manage Crew
Handle your race users
Settings
- Download ZIP
- Update or insert the database tables. These are found in the
cw-racingapp.sql
andcw-racingcrews.sql
files- Optionally also run
default_tracks.sql
if you want to add the default tracks
- Optionally also run
- Adjust values in the
config.lua
file to your liking (Hot tip: GO OVER THIS FILE BEFORE REPORTING ISSUES) - Add the item to your
qb-core/shared/items.lua
(If you use another inventory/core you obviously might need to change this part)
['racing_gps'] = {['name'] = 'racing_gps', ['label'] = 'Racing GPS', ['weight'] = 500, ['type'] = 'item', ['image'] = 'racing_gps.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['description'] = 'Wroom wroom.'},
- Add the item image to your inventory image folder
- If you're not using QBOX then comment out
'@qbx_core/modules/playerdata.lua'
in fxmanifest - Open the game and give yourself the item. When you open the app for the first time you'll be prompted to create a user. The first user to be created will be a
god
user, after that the rest will beracer
type of whatever you set it to in the config. Optionally you can create a god user with the command (see below)
You only need both this resource and cw-performance.
Use the command createracinguser
to do this. For example:
/createracinguser god 1 IReadTheReadme
This will create a god account for the user with serverID 1 (probably you if you're on your dev server) called IReadTheReadme.
Spawn the item racing_gps
normally and use it.
Some users have reported this not working and throwing an error. It seems this is related to Core issues. The order of the input might differ for some cores for some reason. The server side printout should help you determine the order. Just type it in according to that instead.
RacingApp does not come with a phone app, but maybe you want to create one! Now, including everything from racingapp would be insanity, but at least you can join, leave and setup race via exports now! So you can create your own Phone App an just use these exports to get some of the basic features out of Racingapp.
This will get all the existing tracks for you to display
local tracks = exports['cw-racingapp']:getAvailableTracks()
print(json.encode(tracks, {indent=true})) -- This will be the data returned. Do what you will with it
This will get all the posted races for you to display
local races = exports['cw-racingapp']:getAvailableRaces()
print(json.encode(races, {indent=true})) -- This will be the data returned. Do what you will with it
local success = exports['cw-racingapp']:joinRace(raceId)
Where raceId
is replaced by the id of a race you want to join (same id as track id)
local success = exports['cw-racingapp']:leaveRace(raceId)
Where raceId
is replaced by the id of a race you want to join (same id as track id)
local setupData = {
track = 'TR-IMADETHISUP', -- Track Id. Same as the ID of the track in DB or what you fetched earlier.
laps = 2, -- number, amount of laps. 0 = sprint,
maxClass = nil, -- nil or a class, if you want to limit vehicle class with cw-performance,
ghostingOn = false, -- true of false, if ghosting should be on or not
ghostingTime = 0, -- number, how long ghosting stays on. zero for entire race
buyIn = 0, -- number, cost to enter race,
ranked = false,-- true or false, if you want ranked or not
reversed = false, -- true or false, if you want the race to be reversed
participationMoney = 0, -- Money users get for just being there (this is normally an admin setup thing)
participationCurrency = 'cash', -- Money type of users get for just being there (this is normally an admin setup thing)
firstPerson = false, -- true or false, if you want to force first person
}
local success = exports['cw-racingapp']:attemptSetupRace(setupData)
RacingApp is built in VUE, this means you can't just edit the files directly. This requires some more know-how than just developing with basic html/js. You can find out more information in this Boilerplate Repo.
If you're updating from a previous version these might be for you
You need to update one of your database tables. Run this:
ALTER TABLE racer_names
ADD COLUMN auth TEXT DEFAULT 'racer',
ADD COLUMN createdby TEXT,
ADD COLUMN revoked TINYINT DEFAULT 0;
You also need to change out the old GPS/fob items to the new one, see setup section. You might also want to read up on the new system, see User Management section.
See setup section for instructions on how to build a dist
- Make sure to run the sql in
cw-racingcrews.sql
- Run this in your Database to update your
racer_names
:
ALTER TABLE racer_names
ADD COLUMN ranking INT(11) NULL DEFAULT '0';
A new column was added. If you're updating you can run this script to add it to your database
ALTER TABLE `race_tracks`
ADD COLUMN `metadata` TEXT NULL DEFAULT NULL COLLATE 'utf8_general_ci' AFTER `checkpoints`;
Two new columns were added to the race user table. You can run this to update an existing table
ALTER TABLE `racer_names`
ADD COLUMN `crew` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
ADD COLUMN `active` INT(11) NOT NULL DEFAULT '0';
This WILL break your crews, so to fix this, after you've run the above, you can run this:
note: This is for QBOX/QB, not sure if the table names are the same for ESX so make sure to check that
UPDATE racer_names rn
JOIN players p ON JSON_UNQUOTE(JSON_EXTRACT(p.metadata, '$.selectedRacerName')) = rn.racername
SET rn.crew = JSON_UNQUOTE(JSON_EXTRACT(p.metadata, '$.selectedCrew'))
WHERE JSON_UNQUOTE(JSON_EXTRACT(p.metadata, '$.selectedCrew')) IS NOT NULL;
I messed some stuff up initial and used charId instead of stateId cause I'm 🥔 fix by running this:
UPDATE racer_names
SET citizenid = (
SELECT stateId
FROM characters
WHERE characters.charId = racer_names.citizenid
);
Added a built in crypto system (Sorry Renewed Users)
ALTER TABLE racer_names
ADD COLUMN crypto INT DEFAULT 0 NOT NULL;
Drops the race_tracks
table. Use this if you're uninstalling (warning: all tracks and records will be gone)
@JELLYHITAM | Quantum Roleplay Indonesia
@Rithvikk05 | HTRP
@MisterCookie1234 |
-
ItsANoBrainer for QB-Racing, which this is was once upton a time based on
-
Detroit__Tony for ESX conversion