Server-owner guide: installation, configuration, payment system, and hooks.
| Author | Rox Development |
|---|---|
| Resource name | rd-taxi |
| Version | 2.0 |
| Framework support | Standalone, QBCore, QBox, ESX |
| Dependency | PolyZone |
| License | Script unlocked - UI locked ($3.99 add-on to unlock) |
RD Taxi is an AI-driven taxi service. Players walk to a stop, call a driver, ride to a waypoint, and pay a fare, with a set of realism systems layered on top:
RD Taxi does not require a specific framework. Payment is entirely optional and wired up by you - see Payment System.
.lua file in RD Taxi v2 is open and editable out of the box - nothing is escrowed. The only locked part is the NUI (the taxi selection UI - html/). If you want that unlocked too, it's available as a small $3.99 add-on (covers the extra development effort) on our store.rd-taxi in server.cfg.rd-taxi folder into your resources directory.ensure rd-taxi to server.cfg, after PolyZone.config.lua and set your Config.TaxiStops coordinates and Config.TaxiDrivers to match your map and roleplay needs.RD_TAXI_HOOKS.OnChargePlayer / OnRefundPlayer inside custom_functions.lua - see Payment System.config.lua and custom_functions.lua are the two files you're actually meant to change day to day. All script files are listed in escrow_ignore inside fxmanifest.lua; only the NUI files under html/ stay locked unless purchased separately.Config.TaxiStops. A marker and optional floating label appear.en_route and the driver heads to the player.Config.EntryTimeoutAfterArrival seconds to board.Config.WaypointTimeout seconds.delivering. The fare is charged here if Config.PaymentTiming = "on_confirm".Config.PaymentTiming = "on_arrival".Config.ExitTimeout seconds. The driver returns to its assigned stop and resumes duty.At any stage the ride can be interrupted - the player can cancel, disconnect, die, get badly hurt, or draw a weapon - and every one of these safely releases the taxi back to available instead of leaving it stuck.
config.lua)| Setting | Description |
|---|---|
Config.Framework | "qbcore", "qbox", "esx", or "standalone". Informational only - the core ride logic doesn't branch on it, it's there for your own hooks. |
Config.PaymentEnabled | Master on/off switch for the payment system. |
Config.TaxiFare | Flat fare charged per ride. |
Config.PaymentTiming | "on_confirm" or "on_arrival" - see Ride Flow. |
| Setting | Description |
|---|---|
Config.TaxiBlipSprite / Color / Scale | Static blip shown at each taxi stop. |
Config.StopMarker | The 3D marker and floating label drawn at each stop - type, color, scale, draw distance, label distance, and so on. |
Config.MovingTaxiBlipSprite / Color / Scale | Blip shown while a taxi is actively coming to, or carrying, a player. |
Config.ShowBlipWhenEnRoute / ShowBlipWhenDelivering / ShowBlipWhenReturning | Toggle the moving blip per ride phase. |
Stop names are auto-detected at runtime with GetNameOfZone / GetLabelText (e.g. "Downtown" → "Downtown Taxi Stop" via Config.AutoLabelSuffix). Set a manual label on a Config.TaxiStops entry only if you want to override the auto-detected name.
Config.V2)The main block controlling realistic driving behavior. Set Config.V2.Enabled = false to fall back to simpler, non-realistic driving.
| Field | Purpose |
|---|---|
VehicleProtectionMode | "protected" - taxis can't be damaged or griefed. "realistic" - taxis can take damage. |
EnablePullOverPark / EnableDestinationPark | Whether the taxi pulls to the curb for pickup / drop-off instead of stopping mid-road. |
EnableIdleWander | Available taxis cruise near their stop instead of sitting frozen. |
EnableIndicators / EnableHazards | Turn signals and hazard lights during the relevant moments. |
EnableDriverSpeech / EnableDriverLookAtPlayer | Driver voice lines and head-tracking toward the player. |
EnableCrashRecovery | Auto-recovery for flipped, stuck, or airborne taxis - see Crash / Stuck Recovery. |
Speeds.{Pickup, Trip, Return, Wander} | Max driving speed (m/s) per phase. |
Distances.* | Tuning for when the taxi switches into pulling-over behavior, and how precisely it stops. |
Recovery.* | Tuning for the stuck / flip / airborne detector. |
Dispatch.* | Quick Call settings - see Quick Call Dispatch. |
Cancel.* | Cancel window and cancel fee - see Cancel System. |
Arrival.* | Curbside-arrival tuning - how far from intersections, and search radius. |
| Setting | Description |
|---|---|
Config.WaypointTimeout | Seconds to pick a destination after boarding, before being kicked. |
Config.EntryTimeoutAfterArrival | Seconds to board after the taxi arrives, before the dispatch auto-cancels. |
Config.MaxTrollDistance | Distance in meters beyond which wandering away from an incoming taxi can cancel the pickup. |
Config.CooldownAfterKick | Cooldown after being kicked from a taxi before another can be called. |
Config.ExitTimeout | Seconds to exit after arriving at the destination. |
Config.ReservedTimeout | Seconds a taxi stays reserved for a player before the reservation expires server-side. |
Config.TaxiStops - each entry defines a name, coords, PolyZone size, heading, and spawnCoords (where the taxi parks for that stop).
Config.TaxiDrivers - each entry defines a driver's id, name, pedModel, vehicleModel, image, color, assignedStop (must match a stop's name), and driving personality (ability, aggressiveness).
assignedStop matches the stop a player is standing at will be offered to them. This keeps dispatch distances sane and stops drivers being summoned from across the map.Config.VoiceLines)Controls the in-cabin dialogue system - greetings, idle chatter, weather/night-aware lines, phone call / radio / smoking reactions, regular-customer greetings, ringtone, and volume levels. Most owners only need Enabled and the volume fields; see the inline comments in config.lua for every option.
Config.GunDetection)FirearmWeapons and MeleeWeapons are explicit weapon-name lists - edit them to add or remove specific weapons for your server. An explicit list, rather than "any weapon," avoids false positives from flashlights, cameras, parachutes, fire extinguishers, and similar props. Full behavior is covered in Gun Detection.
Payment is entirely optional and handled through the OnChargePlayer / OnRefundPlayer hooks in custom_functions.lua. This is what makes RD Taxi framework-agnostic - wire the two functions to whatever economy your server uses (QBCore, ESX, a custom bank script, or nothing at all if Config.PaymentEnabled = false).
function RD_TAXI_HOOKS.OnChargePlayer(ctx)
local ok, msg = exports['your-economy']:RemoveMoney(ctx.source, ctx.amount, "rd-taxi-" .. ctx.reason)
if ok then
return { success = true }
end
return { success = false, message = msg or "You don't have enough money!" }
end
Returning { success = false } cancels the ride and shows your message to the player. OnRefundPlayer doesn't need a pass/fail - a fire-and-forget call is fine either way.
/taxicancel lets a player manually cancel an active ride, registered directly in client.lua. It only works when Config.V2.Cancel.EnableCancelCommand is true.
Rides can be cancelled within a configurable window (Config.V2.Cancel), optionally with a fee. Cancelling always safely releases the taxi back to available rather than leaving it in a broken state.
| Field | Description |
|---|---|
EnableCancelCommand | Allow /taxicancel during a ride. |
CancelWindowMs | Cancelling is only allowed within this many milliseconds of confirming the destination. |
CancelFeeEnabled / CancelFeeAmount | Whether cancelling charges a fee, and how much. |
A taxi dispatched to one player is reserved server-side for Config.ReservedTimeout seconds. This stops other players jumping into a taxi that's already on its way to someone else, keeping the ride flow consistent and preventing griefing during pickup.
Controlled by Config.GunDetection:
GunDetection = {
Enabled = true,
ExitTimeoutMs = 5000,
IncludeMelee = true,
FirearmWeapons = { ... },
MeleeWeapons = { ... }
}
If a passenger draws a weapon from the configured lists during a ride, the driver:
ExitTimeoutMs to get out.RD_TAXI_HOOKS.OnGunDetected - wire your own police-dispatch resource here) and gets out of the car himself rather than sitting there.on_confirm timing was used), and the taxi resumes normal duty automatically.If the passenger leaves as soon as they're warned, the driver skips straight to resuming duty.
Detection checks whether the weapon is actually drawn in the passenger's hand, not just equipped in an inventory slot, so a holstered weapon never falsely triggers this.
Controlled by Config.BleedingDetection:
BleedingDetection = {
Enabled = true,
HealthThreshold = 0.25,
ResponseTimeoutMs = 8000,
Hospital = { label = "...", coords = vector3(...) },
PoliceDepartment = { label = "...", coords = vector3(...) }
}
When a player confirms a destination below HealthThreshold of their max health, the driver notices and offers a choice instead of just driving to the original waypoint: hospital, police station, or keep the original destination. If the player doesn't respond within ResponseTimeoutMs, the driver keeps driving to the original destination.
HealthThreshold lower than Config.VoiceLines.HurtHealthThreshold, otherwise the driver will offer a redirect on every ride where it would normally just comment on the player being hurt.Controlled by Config.V2.Recovery, active only when Config.V2.EnableCrashRecovery = true:
Recovery = {
CheckIntervalMs = 2500,
UpsideDownSeconds = 8,
InAirSeconds = 10,
StuckSeconds = 25,
StuckMinMoveMeters = 3.0
}
Every active taxi is monitored for three failure states: flipped upside down, stuck in the air, or not making meaningful progress (StuckMinMoveMeters) while its engine is running. If any state persists past its threshold, the taxi is teleported back to its assigned stop and freed for the next dispatch. Any onboard passenger is notified and their blip cleared.
Lets a player request the closest available taxi without walking to a stop. Controlled by Config.V2.Dispatch:
| Field | Description |
|---|---|
EnableQuickCall | Shows a Quick Call option in the taxi UI that dispatches the closest free taxi to the player. |
ClosestUpdateMs | How often taxi positions refresh for closest-dispatch calculations. |
ClosestMaxDistance | If greater than 0, Quick Call only dispatches a taxi within this distance. 0 means unlimited. |
custom_functions.lua)This file customizes behavior without touching the core resource. It's excluded from escrow specifically so it stays editable.
| Hook | Fires when | Notes |
|---|---|---|
OnCancelRequested(ctx) | A manual cancel is requested, before default logic runs. | Good spot for logging, or to deny a cancel outright. |
OnCancelled(ctx) | After default cancel logic completes. | |
OnDeathCancel(ctx) | A ride is cancelled because the passenger died. | Return { handled = true } to fully override - if you do, you're responsible for freeing/returning the taxi. |
OnGunDetected(ctx) | The driver spots a weapon and starts the escalation sequence. | Wire your police-dispatch resource here. Return value is unused - RD Taxi's own reaction always runs. |
OnChargePlayer(ctx) | A fare, cancel fee, or gun-related charge is due. | See Payment System. |
OnRefundPlayer(ctx) | A fare or fee needs refunding. | See Payment System. |
Common ctx fields (best-effort - not every field is present on every hook):
source -- number, player source
taxiId -- number
phase -- string: "en_route" | "delivering" | "returning" | "available" | etc.
reason -- string: "player_dead" | "player_dropped" | "manual_cancel" | "pickup_cancel" | etc.
pickupStopKey -- string|nil
amount -- number (payment hooks only)
Config.TaxiStops with a unique name, PolyZone coords / size / heading, and spawnCoords - a vector4, where the 4th component is the spawn heading.Config.TaxiDrivers with a unique id, driver and vehicle details, and set assignedStop to the name from step 1.Stop labels are auto-detected from the game world - no need to set one manually unless you want to override the name FiveM detects for that location.
| Symptom | Likely cause |
|---|---|
| Taxi never moves after being dispatched | Usually a vehicle network-ownership issue. Make sure NetworkRequestControlOfEntity runs before drive tasks are issued. |
| Driver frozen after confirming a destination, or after a mid-ride cancel | Same network-ownership issue as above. |
| "You moved too far away" fires immediately on a fresh call | Make sure players are only offered taxis assigned to the stop they're standing at - calling across the map will always struggle to beat Config.MaxTrollDistance. |
| Payment never charges on a standalone server | Payment should fire based on Config.PaymentEnabled alone. Make sure nothing in client.lua / server.lua is excluding Config.Framework == "standalone". |
| Taxi stuck indefinitely with no self-recovery | Check Config.V2.EnableCrashRecovery is true and Config.V2.Recovery values aren't set unreasonably high. |
| No taxis shown at a stop | Confirm at least one driver's assignedStop exactly matches that stop's name. |
rd-taxi/
├── fxmanifest.lua
├── config.lua -- server owner: all tuning lives here
├── custom_functions.lua -- server owner: hooks for payment, cancel, gun-detect, death
├── client/
│ ├── client.lua -- ride flow, driving tasks, voice lines, recovery, gun detection, /taxicancel
│ └── zones.lua -- PolyZone stop zones, markers, blips, label resolution
├── server/
│ └── server.lua -- dispatch, status, payment triggers, cancel handling, hooks
└── html/
├── index.html / style.css / script.js -- taxi selection UI (NUI) - locked unless purchased separately
├── images/
└── sounds/
config.lua and custom_functions.lua are the files intended for regular editing by server owners. Every other .lua file is unlocked and readable too - only the html/ UI files are locked by default.
Documentation created by Rox Development - RD Taxi v2.