How Integrations Work#
Everything framework- or third-party-specific in Taxi Job sits in a few small files left open for editing — client/framework/, server/framework/, client/vehiclekeys/, client/clothing.lua and client/target.lua — and the rest of the script only ever calls those. Some layers are detected from what is running; the rest are a switch in config/config.lua.
Layer | Supported | Chosen by | Without it |
|---|---|---|---|
Framework | es_extended · qb-core · qbx_core | Auto | Required — the job does not load. |
Target | ox_target · qb-target |
| Press E beside the dispatcher. |
Vehicle keys | Eleven key systems | Auto | The cab is driven without keys being handed over. |
Fuel | Any resource with |
| The cab spawns with the game's default fuel. |
3D prompts | qs-textui | Auto | The game's own 3D text. |
Notifications | Built in, or any notify resource |
| — |
Dispatch | qs-dispatch, or any |
| Reported illegal stops alert nobody. |
Uniform | esx_skin + skinchanger · qb-clothing |
| Drivers keep their own clothes. |
Quests | qs-inventory | Auto | No taxi quests. |
Job money | qs-job-management | Auto | Fares are paid to the driver in cash. |
Phone | qs-smartphone and the Taxi Job phone app | Auto | No ride requests by phone. |
Every optional integration degrades quietly. A missing resource makes its feature stand down — nothing errors, and the rest of the job carries on.
Notifications and Prompts#
Notifications#
With Config.DefaultNotifications on, Taxi Job draws its own notifications, coloured by type and with a sound. Turn it off to send every message to your own notification resource instead, through SendTextMessage in config/config.lua:
Config.DefaultNotifications = false
-- type is 'info', 'success', 'warning' or 'error'
function SendTextMessage(msg, type)
exports['okokNotify']:Alert('Taxi', msg, 5000, type)
endThe shipped function fills in info, error and success one by one; a single call that passes the type straight through, like the one above, also covers the warnings about hard braking and queasy passengers.
Prompts#
The "press E" prompts at the dispatcher, the pickup, the stop and the drop-off are always the job's own, merged into one hint so two prompts never fight for the same corner. Config.DrawText3D = true replaces them with floating text over each point — drawn by qs-textui when it is running, and by the game's own text otherwise.
Discord Logs#
Shifts, payouts and experience can be posted to Discord as embeds. They are off by default — paste a webhook, switch them on and choose the events:
-- config/config.lua
Config.Webhooks = {
Enabled = true,
Url = 'https://discord.com/api/webhooks/...', -- the shared channel
Name = 'qs-taxijob',
Avatar = '',
Timestamp = true,
Events = {
MoneyPaid = 'https://discord.com/api/webhooks/...', -- a staff channel of its own
ExperienceGiven = true, -- the shared Url
MissionStarted = true,
MissionFinished = true,
MissionAbandoned = false, -- not sent
},
}Event | Posted when |
|---|---|
| A driver clocks on, with the cab they took out. |
| An NPC fare is handed in: what it paid — or that the payment was refused — the experience, whether it was illegal, and the streak. |
| A shift ends for any reason, with the fares driven and whether one was still in progress. |
| Money actually reaches a driver. A refused payment is never logged as paid. |
| Experience is granted, with the level before and after and the progress towards the next. |
Target#
With a target script switched on, the dispatcher gets a single Start working option instead of the key prompt. It opens the same panel whether the player is on shift or not — the panel decides whether to offer Start shift or Clock off.
Config.Target = true
Config.TargetScript = "ox" -- "ox" for ox_target, "qb" for qb-targetThe option is added in client/target.lua, which is open for editing if your target resource is called differently.
Vehicle Keys#
The key system is detected when the client loads, from the first of these it finds running. The cab's keys are handed over when it spawns and taken back when the shift ends:
qs-vehiclekeys · qb-vehiclekeys · qbx_vehiclekeys · wasabi_carlock · F_RealCarKeysSystem · fivecode_carkeys · glfp10_carkeys · mono_carkeys · ti_vehicleKeys · vehicles_keys · xd_locksystem
Run only one of them, and start it before qs-taxijob. On QBCore and Qbox the cab also fires vehiclekeys:client:SetOwner on spawn, which most QB key scripts listen for on their own.
Your own key system#
When none of the supported systems is running, the job uses client/vehiclekeys/none.lua, which does nothing. Fill it in to call your own resource:
-- client/vehiclekeys/none.lua
if Config.Vehiclekeys ~= 'none' then
return
end
function AddVehiclekeys(vehicle, plate)
exports['my_keys']:GiveKeys(plate)
end
function RemoveVehiclekeys(vehicle, plate)
exports['my_keys']:RemoveKeys(plate)
endEvery other file in that folder is a working example to copy from — qs-vehiclekeys.lua shows how to pass the model as well as the plate.
Fuel#
Config.Fuel = true
Config.FuelExport = exports['LegacyFuel'] -- any resource with a SetFuel(vehicle, level) exportThe tank is filled to 100 when the cab spawns. Any fuel script with a SetFuel(vehicle, level) export works — point Config.FuelExport at yours, for example exports['ps-fuel'] or exports['cdn-fuel'].
Police Dispatch#
When an illegal stop is reported, Config.DispatchExport is called on the driver's client. It is empty by default — fill it in with your dispatch resource:
Config.DispatchExport = function()
exports['qs-dispatch']:SuspiciousActivity()
endIt runs at the moment the driver is actually reported — after the hand-off scene — not when the offer is accepted, so the call reaches the police from where the deal happened.
The Driver Uniform#
With Config.Clothing on, drivers change into a uniform when they clock on and back into their own clothes when they clock off. The outfit is set at the top of client/clothing.lua, one table for male and one for female characters:
local playerClothing = {
male = {
["arms"] = 0,
["tshirt_1"] = 15, ["tshirt_2"] = 0,
["torso_1"] = 65, ["torso_2"] = 2,
["pants_1"] = 9, ["pants_2"] = 1,
["shoes_1"] = 12, ["shoes_2"] = 0,
-- helmet, chain, mask, bags, glasses, vest, watches, bracelets...
},
female = {
-- the same keys
},
}Framework | Applied with |
|---|---|
ESX |
|
QBCore / Qbox |
|
Running illenium-appearance on QBCore? Its reload line is already in client/clothing.lua, commented out beside the qb-clothing one. With Config.QuasarInventory on, qs-inventory is locked while the outfit changes.
Inventory and Quests#
With qs-inventory running, every driver is given three taxi quests when they log in:
Quest | Advances on |
|---|---|
Taxi Progress ( | Every level gained. |
Complete taxi rides ( | Every NPC fare handed in. |
Drive real passengers ( | Every player fare completed. |
The quests are defined in server/missions.lua, open for editing — titles, descriptions and rewards. Every call to the inventory is protected, so a quest resource that is still starting never costs a driver their fare.
Black money on QBCore and Qbox#
Illegal fares are paid as the black_money item on QBCore and Qbox. Stock QBCore ships markedbills instead, so add a black_money item to your inventory's item list. Until you do, illegal fares are refused with This item does not exist: black_money, and the console names the missing item once. On ESX they go to the black_money account.
Job Management#
With qs-job-management running, every legal fare and every player fare is paid into the taxi job's money there instead of the driver's pocket — the company earns, and pays its drivers through its own salaries. Illegal fares still go straight to the driver as black money. Nothing to configure: it is picked up as soon as the resource is running.
The Smartphone App#
The Taxi Job phone app for Quasar Smartphone lets players see who is driving and book a ride by phone. It uses the same records and the same server-side flow as the job itself: the driver gets a phone notification and an in-game request, a request no driver answers expires after two minutes, and ratings left through the app go on the same reputation as ratings left in the cab — a driver has one reputation, not two.
The exports the app relies on are listed in Commands and Exports, along with the duty exports a scoreboard reads.
Renamed Frameworks#
Everything the job asks of the framework — the job check, money, identifiers, names, spawning the cab — goes through client/framework/esx.lua or qb.lua and their twins in server/framework/. Running a renamed core?
Map the name
Add your resource to the
frameworkslist at the top ofconfig/config.lua, mapped to the framework it is based on:lua local frameworks = { ['es_extended'] = 'esx', ['qb-core'] = 'qb', ['qbx_core'] = 'qb', ['my-core'] = 'qb', -- your renamed core }Point the bridges at it
In the matching client and server framework files, change the export the core object is read from —
exports['qb-core']:GetCoreObject()orexports['es_extended']:getSharedObject()— to your resource's name.Restart
Restart the server — not only the resource — so the framework is detected from a clean start.
Languages#
Eleven translations ship in config/translations.lua: English (en), Spanish (es), Italian (it), French (fr), Portuguese (pt), German (de), Russian (ru), Turkish (tr), Dutch (nl), Simplified Chinese (cn) and Traditional Chinese (zh-tw). Pick one at the top of that file:
Config.Language = "es"English is the fallback for every key, so a line another language has not translated yet shows in English rather than as a raw key. To add a language, copy the en block, give it a new code and translate the text between the quotes. The currency symbol is the CURRENCY_TYPE key, placed before or after the amount by Config.CurrencyPosition.



