Configuration
Everything lives in shared/config.lua. Restart the resource after a change.
General
| Option | Default | What it does |
|---|---|---|
Config.Locale | 'pl' | Language, a file name from shared/locales/ |
Config.Debug | false | Prints selections, combat logs and failing checks to the console |
Config.ServerName | 'KOJA ROLEPLAY' | Shown in the panel header |
Config.Theme | see below | UI colours, see Theme / UI colours |
Config.Fallback | Legion Square | Where a player spawns when no location is available |
Theme / UI colours
Config.Theme = {
accent = '#FF9B00', -- primary colour: buttons, selected spawn, map pins and route
background = '#121212', -- base colour of the panels (tinted warm by the UI)
text = '#F1ECE6', -- main text colour (muted text and borders follow it)
success = '#9BE22D', -- positive states: free / available
danger = '#FF5A4F', -- negative states: errors, locked, live view
}| Key | Default | What it colours |
|---|---|---|
accent | '#FF9B00' | The primary colour: buttons, the selected spawn, the map pins and the route |
background | '#121212' | The base colour of the panels. The UI tints it warm, like Koja Appearance |
text | '#F1ECE6' | The main text colour. Muted text and borders follow it |
success | '#9BE22D' | Positive states: free, available |
danger | '#FF5A4F' | Negative states: errors, locked spots, the live view |
Colours are hex only, #RGB or #RRGGBB. They are applied as CSS variables when the UI opens, so you do not need to rebuild the UI. Restart the resource after changing them.
An invalid colour is ignored and the default from the table is used instead.
Opening
Config.Open = {
OnPlayerLoaded = true,
Delay = 250,
CanCancel = false,
ShowLocked = true,
RememberChoice = true,
}
Config.QbSpawnCompat = true| Option | What it does |
|---|---|
OnPlayerLoaded | ESX: open on esx:playerLoaded. Skipped while Koja Multicharacter runs |
Delay | ms to wait after esx:playerLoaded before opening |
CanCancel | Default for ESC / the exit button. Every Open call can override it with canCancel. Never allowed while a restriction is active |
ShowLocked | true shows locked spots with their lock label, false hides them |
RememberChoice | Preselect the location the player picked last time |
Config.QbSpawnCompat | Listen to the qb-spawn events from qb-multicharacter |
Admin
Config.Command = { Enabled = true, Name = 'spawnselector', Editor = 'spawneditor', Event = 'spawnevent' }
Config.Admin = { Groups = { 'admin', 'superadmin', 'god' }, Ace = 'command' }The check goes through KOJA.Server.IsAdmin; change it in ServerEditable.IsAdmin. See Admin tools.
Last location
Config.LastLocation = {
Enabled = true,
SaveInterval = 60,
FrameworkFallback = true,
IgnoreBuckets = true,
}| Option | What it does |
|---|---|
Enabled | Show "Last location" and save positions |
SaveInterval | Seconds between saves of every spawned player (minimum 10). Positions are also saved on logout, disconnect and resource stop |
FrameworkFallback | No saved row yet: use users.position (ESX) or players.position (QBCore) |
IgnoreBuckets | Do not save players in a routing bucket other than 0 (interiors, instances) |
Anti combat log, death and jail
Config.AntiCombatLog, Config.Death and Config.Jail are explained with the API on Anti combat log & restrictions.
New characters
Config.NewCharacter = {
UseSelector = false,
Spawns = {
{ id = 'start_airport', label = 'Los Santos International', description = 'Arrivals', category = 'start', coords = vec4(-1037.74, -2737.89, 20.17, 327.9) },
},
}UseSelector = false leaves new ESX characters to your character creator. When a new character opens the selector (isNew = true), only these spawns are listed.
Camera flight
Config.Cinematic = {
Enabled = true,
Height = 650.0,
TopFov = 45.0,
HoldTime = 900,
DescendTime = 3200,
ApproachDistance = 22.0,
ApproachHeight = 14.0,
SettleTime = 1800,
FinalDistance = 3.4,
FinalHeight = 0.85,
BlendOut = 1100,
LoadTimeout = 6000,
}| Option | What it does |
|---|---|
Enabled | false = a plain fade and teleport |
Height, TopFov, HoldTime | The top-down shot: metres above the spot, field of view, how long it holds (ms) |
DescendTime | ms of the descent to the street |
ApproachDistance, ApproachHeight | Where the descent ends: metres behind and above the ped |
SettleTime, FinalDistance, FinalHeight | The last move to an over-the-shoulder shot |
BlendOut | ms of the blend into the gameplay camera |
LoadTimeout | Longest wait (ms) for collision and streaming at the spot |
Map
Config.Map = {
FocusDistance = 2600,
OnlineDetail = true,
ShowWorld = true,
BlipImageUrl = 'https://docs.fivem.net/blips/%s.png',
GameBlips = {
Enabled = true,
Sprites = { [60] = 'radar_police_station', [61] = 'radar_hospital' },
},
}| Option | What it does |
|---|---|
FocusDistance | Camera distance in metres when a location is selected |
OnlineDetail | Up close, stream the sharper zoom 7 tiles from the Rockstar map CDN. Offline the shipped zoom 6 tiles are used |
ShowWorld | Time of day, weather, rain and snow on the map |
BlipImageUrl | Where blip icons come from, %s = the blip name |
GameBlips | Game blips shown on the map: sprite id = blip image name |
Config.Roads = { enabled = true, file = 'data/roads.json', cellSize = 150.0, maxSnapRings = 12, zWeight = 0.5, speedFactor = { [0] = 0.6, 0.9, 1.15, 1.45 }, maxExpansions = 20000, cacheSize = 64 }The road graph for the route line. enabled = false turns the route off; the other values are the koja-dispatch router settings.
Live preview
Config.LivePreview = { Enabled = true, Distance = 9.0, Height = 3.2, Fov = 45.0, Orbit = 6.0 }The camera circling the selected spot in the card: metres behind, metres up, field of view and degrees per second.
Sounds
Config.Sound = { Enabled = true, Volume = 0.45, Ambient = true, Music = nil }Music takes any URL the NUI can play (https://... or nui://your-resource/music.mp3) and replaces the synthesised ambient.
Housing
Config.Housing = {
['qb-houses'] = 'auto',
['qs-housing'] = 'auto',
['ps-housing'] = 'auto',
['esx_property'] = 'auto',
['nolag_properties'] = 'auto',
['bcs_housing'] = 'auto',
}'auto' lists owned properties when that resource is started, true always tries, false turns the provider off.
Stats
Config.Stats = { Enabled = true, KeepDays = 90 }Categories
Config.Categories = {
{ id = 'event', icon = 'star', order = 0 },
{ id = 'last', icon = 'footprints', order = 1 },
{ id = 'start', icon = 'plane', order = 2 },
{ id = 'property', icon = 'home', order = 3 },
{ id = 'job', icon = 'briefcase', order = 4 },
{ id = 'gang', icon = 'skull', order = 5 },
{ id = 'city', icon = 'map-pin', order = 6 },
}The label comes from the locale key category_<id>, or set label yourself. Other resources can add categories with RegisterCategory.
Icons: anchor, briefcase, building, car, footprints, home, hospital, lock, map-pin, mountain, plane, shield, skull, star, tent, trees, waves. Unknown names show a map pin.
Spawns
Config.Spawns is the list everyone can see. A spawn is a table:
{
id = 'mrpd',
label = 'Mission Row',
description = 'Police Department',
category = 'job',
coords = vec4(428.23, -984.28, 29.76, 3.5),
icon = 'shield',
blip = 'radar_police_station',
image = 'https://example.com/mrpd.webp',
jobs = { police = 0, sheriff = 2 },
onDuty = false,
gangs = { ballas = 0 },
ace = 'group.vip',
lockedLabel = 'VIP only',
hideLocked = false,
vehicle = { model = 'police', plate = 'LSPD01', fuel = 100 },
cinematic = true,
order = 0,
data = {},
}| Field | Required | Description |
|---|---|---|
id | Yes | Unique string or number. last is reserved for the last location |
label | Yes | Name in the list and on the map |
coords | Yes | vec4, vec3 or { x, y, z, w } (also h / heading) |
description | No | Second line |
category | No | Category id, default city |
icon | No | Overrides the category icon |
blip | No | GTA blip image name, used instead of the icon |
image | No | Picture for the card. Without one, the card shows the live preview or the map. Photos taken in the editor are used automatically |
jobs | No | 'police', { 'police', 'sheriff' } or { police = minGrade } |
onDuty | No | The job must be on duty |
gangs | No | Same format as jobs, QBCore gangs |
ace | No | ACE permission the player needs |
lockedLabel | No | Text when locked. Default: "Police only" from the job label |
hideLocked | No | Hide instead of showing it locked |
vehicle | No | Model name, or { model, plate, props, fuel, keys }: spawn in the driver seat |
cinematic | No | Turns the camera flight on or off for this spot |
order | No | Order inside its category |
data | No | Anything. You get it back in onSpawn and the events |
Editable files
client/editable.lua
| Function | Called when |
|---|---|
ClientEditable.Notify(desc, type) | The selector shows a message |
ClientEditable.OnOpen(options) | The map opens. Hide your HUD here |
ClientEditable.OnClose(spawn, options) | The map closes (spawn is nil when cancelled). Show your HUD again |
ClientEditable.OnSpawned(spawn, options) | The player landed |
ClientEditable.OnVehicleSpawned(vehicle, data) | A spawn vehicle was created |
ClientEditable.CanOpen(options) | Return false to block opening |
server/editable.lua
| Function | What it does |
|---|---|
ServerEditable.GetJob(source) | Job used for locks: { name, label, grade, onDuty } |
ServerEditable.GetGang(source) | Gang used for locks (QBCore by default) |
ServerEditable.CanAccess(source, spawn, job) | Return false, 'Reason' to lock a spot |
ServerEditable.GetSpawns(source, identifier) | Return extra spawns for this player |
ServerEditable.IsAdmin(source) | Who can use the admin commands and tabs |
ServerEditable.IsDead(source) | Dead right now (QB metadata by default) |
ServerEditable.IsDeadOnLogin(source, identifier) | Dead when the selector opens (QB metadata, ESX users.is_dead) |
ServerEditable.IsJailed(source, identifier) | In jail (QB injail, ESX users.jail_time / users.jail) |
ServerEditable.OnCombatLog(identifier, record) | A player left during combat |
ServerEditable.OnSpawned(source, spawn, isNew) | The player landed |