Koja Scripts

Configuration

Every option in shared/config.lua of Koja Spawn Selector: opening, last location, anti combat log, map, live preview, sounds, housing, stats, the spawn definition and the editable files.

Configuration

Everything lives in shared/config.lua. Restart the resource after a change.

General

OptionDefaultWhat it does
Config.Locale'pl'Language, a file name from shared/locales/
Config.DebugfalsePrints selections, combat logs and failing checks to the console
Config.ServerName'KOJA ROLEPLAY'Shown in the panel header
Config.Themesee belowUI colours, see Theme / UI colours
Config.FallbackLegion SquareWhere a player spawns when no location is available

Theme / UI colours

shared/config.lua
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
}
KeyDefaultWhat 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

shared/config.lua
Config.Open = {
    OnPlayerLoaded = true,
    Delay = 250,
    CanCancel = false,
    ShowLocked = true,
    RememberChoice = true,
}
Config.QbSpawnCompat = true
OptionWhat it does
OnPlayerLoadedESX: open on esx:playerLoaded. Skipped while Koja Multicharacter runs
Delayms to wait after esx:playerLoaded before opening
CanCancelDefault for ESC / the exit button. Every Open call can override it with canCancel. Never allowed while a restriction is active
ShowLockedtrue shows locked spots with their lock label, false hides them
RememberChoicePreselect the location the player picked last time
Config.QbSpawnCompatListen to the qb-spawn events from qb-multicharacter

Admin

shared/config.lua
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

shared/config.lua
Config.LastLocation = {
    Enabled = true,
    SaveInterval = 60,
    FrameworkFallback = true,
    IgnoreBuckets = true,
}
OptionWhat it does
EnabledShow "Last location" and save positions
SaveIntervalSeconds between saves of every spawned player (minimum 10). Positions are also saved on logout, disconnect and resource stop
FrameworkFallbackNo saved row yet: use users.position (ESX) or players.position (QBCore)
IgnoreBucketsDo 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

shared/config.lua
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

shared/config.lua
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,
}
OptionWhat it does
Enabledfalse = a plain fade and teleport
Height, TopFov, HoldTimeThe top-down shot: metres above the spot, field of view, how long it holds (ms)
DescendTimems of the descent to the street
ApproachDistance, ApproachHeightWhere the descent ends: metres behind and above the ped
SettleTime, FinalDistance, FinalHeightThe last move to an over-the-shoulder shot
BlendOutms of the blend into the gameplay camera
LoadTimeoutLongest wait (ms) for collision and streaming at the spot

Map

shared/config.lua
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' },
    },
}
OptionWhat it does
FocusDistanceCamera distance in metres when a location is selected
OnlineDetailUp close, stream the sharper zoom 7 tiles from the Rockstar map CDN. Offline the shipped zoom 6 tiles are used
ShowWorldTime of day, weather, rain and snow on the map
BlipImageUrlWhere blip icons come from, %s = the blip name
GameBlipsGame blips shown on the map: sprite id = blip image name
shared/config.lua
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

shared/config.lua
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

shared/config.lua
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

shared/config.lua
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

shared/config.lua
Config.Stats = { Enabled = true, KeepDays = 90 }

Categories

shared/config.lua
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:

Spawn definition
{
    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 = {},
}
FieldRequiredDescription
idYesUnique string or number. last is reserved for the last location
labelYesName in the list and on the map
coordsYesvec4, vec3 or { x, y, z, w } (also h / heading)
descriptionNoSecond line
categoryNoCategory id, default city
iconNoOverrides the category icon
blipNoGTA blip image name, used instead of the icon
imageNoPicture for the card. Without one, the card shows the live preview or the map. Photos taken in the editor are used automatically
jobsNo'police', { 'police', 'sheriff' } or { police = minGrade }
onDutyNoThe job must be on duty
gangsNoSame format as jobs, QBCore gangs
aceNoACE permission the player needs
lockedLabelNoText when locked. Default: "Police only" from the job label
hideLockedNoHide instead of showing it locked
vehicleNoModel name, or { model, plate, props, fuel, keys }: spawn in the driver seat
cinematicNoTurns the camera flight on or off for this spot
orderNoOrder inside its category
dataNoAnything. You get it back in onSpawn and the events

Editable files

client/editable.lua

FunctionCalled 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

FunctionWhat 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