Commands#
Taxi Job registers no chat or console commands, on purpose. Everything a driver does starts at the dispatcher, and everything an admin changes lives in config/config.lua. If you want a command — or a radial menu, a laptop prop or a phone shortcut — to open the job panel, call the export from a resource of your own:
-- any client script of your own
RegisterCommand('taxi', function()
exports['qs-taxijob']:openTaxiMenu()
end, false)The panel opens wherever the player is; the camera only cuts to the dispatcher when they are standing within a few metres of him. Giving players the job is your framework's own command:
Command | From | Description |
|---|---|---|
| ESX, QBCore, Qbox | Gives player |
<id> is the player's server id — the number next to their name in the player list.
Client Exports and Events#
For opening the job from your own scripts, and showing a message in its style.
Opening the job panel
-- client side
exports['qs-taxijob']:openTaxiMenu()
-- or from the server, for one player
TriggerClientEvent('qs-taxijob:openTaxiMenu', source)There is deliberately no export that opens the statistics or the guide on their own. Both are views inside the panel, and opening one alone would capture the cursor with nothing on screen — open the panel instead.
Showing a notification in the job's style
-- from the server; type is 'success', 'error', 'warning' or 'info'
TriggerClientEvent('qs-taxijob:sendNotification', source, 'notify', 'success', 'Your cab has been serviced')It follows Config.DefaultNotifications, so it lands in your own notification resource when that is what the job uses.
Server Exports#
How another resource reads or drives Taxi Job — a scoreboard counting drivers, a jail script ending a shift, a dispatch that only pages drivers who are free, the phone app booking a ride.
Who is working
local count = exports['qs-taxijob']:getOnDutyCount() -- drivers on duty
local onDuty = exports['qs-taxijob']:isPlayerOnDuty(source) -- true / false
local drivers = exports['qs-taxijob']:getOnDutyDrivers() -- { serverId, ... }
local onShift = exports['qs-taxijob']:isPlayerOnShift(source) -- clocked on, with a cab
local busy = exports['qs-taxijob']:IsPlayerOnMission(source) -- a fare in progress right nowExport | Answers |
|---|---|
| The duty flag: raised when a shift starts, cleared when it ends. What a scoreboard wants. |
| Whether the server has a shift on file for the player. |
| Whether the player has paid work in progress — an NPC fare that has been called, or an accepted player fare. A driver waiting at the rank is on shift but not on a mission, and a passenger never is. |
Ending a shift
-- e.g. from a jail script, the moment the driver is taken off the road
local ended = exports['qs-taxijob']:cancelShift(source) -- false when they had no shiftThe driver's client cleans up exactly as if they had clocked off — the cab, the blips, the meter and the uniform — and any player fare they were carrying is refunded to the passenger. A server id passed as a string is accepted too.
Drivers and ratings
local drivers = exports['qs-taxijob']:getAllTaxiPlayers()
-- { { id = 12, name = 'Ana López', onDuty = true }, ... }
local rated = exports['qs-taxijob']:getAllTaxiPlayersWithRatings()
-- { { id = 12, name = 'Ana López', onDuty = true,
-- rating = { average = 4.6, count = 31, trips = 88 } }, ... }
local rating = exports['qs-taxijob']:getDriverRating(driverId)
-- { average = 4.6, count = 31, trips = 88 }, or { average = 0, count = 0 }
local ok = exports['qs-taxijob']:addDriverRating(driverId, 5) -- 1 to 5, saved immediatelyBoth lists include every online player with a taxi job, on duty or not, and names follow Config.PlayerNameSource. addDriverRating goes on the same reputation the cab's own star ratings use.
Phone rides
local ok, reason = exports['qs-taxijob']:requestRideFromPhone(passengerId, driverId)
-- reason: 'invalid', 'driver_offline' or 'driver_busy'
local accepted = exports['qs-taxijob']:respondToPhoneRide(driverId, passengerId)A request notifies the driver through qs-smartphone and fires qs-taxijob-phone:phoneRideRequest on their client with the passenger's id and name. A driver holds one request at a time; one left unanswered for two minutes expires, so the driver can be asked again.
Server Events#
For reacting to the job from another server script:
AddEventHandler('qs-taxijob:multiplayerRideEnded', function(driverId, passengerId)
-- a player fare reached its destination and the driver has been paid
end)Listen with AddEventHandler, not RegisterNetEvent. It is fired on the server only, and registering it as a net event would let any client fire your handler with ids of its choosing.
About Payments#
No event or export pays a driver for a fare. Pickups, drop-offs, prices, the on-time bonus and the police roll are all decided inside the resource, and money moves only after the server has checked the driver is where the fare says. The events older versions used for that — qs-taxijob:getPayment, qs-taxijob:passengerStartsRide and qs-taxijob:checkPlayerMoney — no longer exist; see Updating.



