Koja Scripts

Configuration

Every option of Koja Multicharacter in shared/config.lua: slots, identity, scene, cutscenes, seasons, audio, arrival, trash, CK, approval, party, spawn, relog and admin.

Configuration

All options live in shared/config.lua, spawn points in shared/spawns.lua and webhooks in server/config.lua.

General

KeyDefaultDescription
Config.DebugfalseConsole logs
Config.Locale'en'en or pl. Add your own file in locales/
Config.ServerName'KOJA ROLEPLAY'Shown in the top bar
Config.LogonilImage URL for the top bar
Config.Currency'$'Money prefix
Config.ShowMoneytrueShows cash and bank on the character card
Config.Themesee belowUI colours and corners, see Theme / UI colours

Theme / UI colours

shared/config.lua
Config.Theme = {
    accent = '#FF9B00',     -- primary colour: buttons, highlights, selected slot, sliders
    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 / online
    danger = '#FF5A4F',     -- negative states: delete, errors, unavailable
    corners = 'rounded',    -- 'rounded' (chamfered) or 'sharp'
}
KeyDefaultWhat it colours
accent'#FF9B00'The primary colour: buttons, highlights, the selected slot and sliders
background'#121212'The base colour of the panels. The UI tints it warm
text'#F1ECE6'The main text colour. Muted text and borders follow it
success'#9BE22D'Positive states: free, available, online
danger'#FF5A4F'Negative states: delete, errors, unavailable
corners'rounded''rounded' (chamfered corners) or 'sharp'

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. Any corners value other than 'sharp' gives 'rounded'.

Slots

shared/config.lua
Config.Slots = {
    Default = 3,
    Max = 8,
    ShowLocked = true,
    ShopUrl = nil,
    ImportEsxSlots = true,
    Tiers = {
        { ace = 'koja.multicharacter.slots.vip', slots = 5 },
        { ace = 'koja.multicharacter.slots.staff', slots = 8 },
    },
    DiscordRoles = {},
}
KeyDescription
DefaultSlots for every player
MaxHow many slots the UI shows. Extra ones are drawn as locked
ShowLockedShow locked slots up to Max
ShopUrlLink shown on locked slots, for example your Tebex
ImportEsxSlotsReads multicharacter_slots from the old esx_multicharacter when the player has no own override
Tiers{ ace, slots }. The highest matching tier wins. Overrides from /charslots win over tiers
DiscordRoles['role id'] = slots. Needs kmc_discord_token and kmc_discord_guild in server.cfg; the bot must be a member of the guild. Roles are cached for 10 minutes

Identity

KeyDefaultDescription
MinNameLength / MaxNameLength2 / 16Length of first and last name
CapitalizetrueUpper-cases the first letter
MinAge / MaxAge18 / 90Allowed age
Height, MinHeight, MaxHeight, DefaultHeighttrue, 150, 210, 178Height field in cm
Nationality, Nationalitiestrue, 20 entriesNationality field. An empty list turns it into free text
Backstory.Enabled / Required / MaxLengthtrue / false / 600Backstory field
UniqueNamestrueRejects a first and last name that already exists
BlacklistedNamesadmin, staff, ...Rejected names (first, last or full, case-insensitive)
EsxDateFormat'DD/MM/YYYY'Format of users.dateofbirth on ESX: DD/MM/YYYY, MM/DD/YYYY or YYYY-MM-DD

Names allow letters (including accented and Cyrillic), spaces, apostrophes and hyphens.

Delete, trash, CK and presets

KeyDefaultDescription
Config.Delete.EnabledtruePlayers can delete their characters
Config.Delete.ConfirmNametruePlayers must type the full name to delete
Config.Trash.Days7Days a deleted character stays restorable. 0 = delete is permanent
Config.Trash.PurgeInterval600Seconds between purge runs
Config.CK.AllowDeletetruePlayers can delete a dead (memorial) character
Config.CK.ReasonRequiredtrueStaff must give a reason for a CK
Config.Presets.EnabledtrueAppearance presets
Config.Presets.Max6Presets per account

Approval and name changes

KeyDefaultDescription
Config.Approval.EnabledfalseNew characters wait for staff approval before the first spawn
Config.Approval.NotifyStafftrueOnline staff get a notification
Config.NameChange.EnabledtruePlayers can request a new name from the character card
Config.NameChange.ReasonRequired / MaxReasontrue / 300Reason field
Config.NameChange.ShowDeniedDays7How long a denied request stays visible

set kmc_webhook_approval "https://discord.com/api/webhooks/..." posts new characters waiting for approval.

Appearance

KeyDefaultDescription
Resource'auto'Tries koja-appearance / illenium-appearance, fivem-appearance, then qb-clothing and esx_skin. Or set a resource name
AllowPedChangefalseNew characters can pick any ped model in the editor
ForceSavetrueThe editor reopens until the player saves
Menuall trueEditor sections for new characters: headBlend, faceFeatures, headOverlays, components, props, tattoos

Scene

KeyDefaultDescription
RandomtrueRandom location each time, otherwise the first one
LineupfalseAll characters stand next to each other and the camera slides between them
LineupSpacing1.15Distance between characters in the line-up
Hour, Weather19, 'EXTRASUNNY'Default time and weather. A location can override them
CameraDistance, MinDistance, MaxDistance, Height, Side, LookHeight, Fov, Interp (ms)
Scenarios5 scenariosRandom idle scenarios for the preview characters
LocationsVinewood Hills, Michael's House{ label, ped = vec4(...), hour?, weather? }. ped is where the character stands, the camera is placed in front of it
AutoFrametrueSnaps the character to the ground and turns it in 45° steps when a wall blocks the camera or the walk path

Opening shot

shared/config.lua
Intro = {
    Enabled = true,
    Duration = 3200,
    Distance = 7.5,
    Side = 2.5,
    Height = 2.2,
},

The camera starts wide (Distance, Side and Height are added to the normal pose) and glides in over Duration ms.

Character switch cutscene

shared/config.lua
Transition = {
    Enabled = true,
    WalkDistance = 2.8,
    WalkSpeed = 1.0,
    ExitTime = 2600,
    CameraOut = 700,
    CameraIn = 1900,
    CameraWide = 1.2,
    CameraSwing = 1.1,
    CameraRise = 0.2,
    Gestures = {
        { dict = 'clothingshirt', anim = 'try_shirt_positive_d' },
        { dict = 'clothingtie', anim = 'try_tie_positive_a' },
        { dict = 'clothingspecs', anim = 'try_glasses_positive_a' },
        { dict = 'anim@mp_player_intupperthumbs_up', anim = 'idle_a' },
    },
},
KeyDescription
Enabledfalse swaps characters instantly
WalkDistance, WalkSpeedHow far and how fast the new character walks in
ExitTimeMs before the old character is removed
CameraOut, CameraInMs for the camera to swing out and back
CameraWide, CameraSwing, CameraRiseHow far the camera pulls back, moves sideways and rises during the swing
GesturesAnimations the new character plays on arrival, one picked at random. A missing animation is skipped

Scene per character

shared/config.lua
PerCharacter = {
    Enabled = true,
    Fade = 450,
    Jobs = {
        police = { label = 'Mission Row PD', ped = vec4(428.23, -984.28, 30.71, 3.5), hour = 21 },
        ambulance = { label = 'Pillbox Hospital', ped = vec4(298.6, -584.5, 43.26, 70.0), hour = 18 },
        mechanic = { label = 'Benny\'s', ped = vec4(-205.62, -1310.66, 31.29, 0.0), hour = 17 },
    },
    Gangs = {},
},

Single mode only; the line-up keeps one location. A sceneLocation hook (houses, motels) wins over Jobs and Gangs. Characters without a match use Locations. Fade is the fade time in ms when the scene moves.

Car in the scene

KeyDefaultDescription
Vehicle.EnabledtrueShows one of the character's owned vehicles behind them (owned_vehicles on ESX, player_vehicles on QB)
Vehicle.Pick'best''best' (class, then top speed) or 'first'
Vehicle.Candidates6How many owned vehicles are sent to the client to pick from
Vehicle.Back, Vehicle.Side3.4, 1.3Position behind the character in metres. Skipped when the spot is blocked

Seasons

KeyDescription
Seasons.EnabledSeasonal scenes
Seasons.ForceSeason name to force (for testing), nil = by date
Seasons.List{ name, from = 'MM-DD', to = 'MM-DD', weather, hour?, snow?, music?, props = { { model, offset = vec3(right, forward, up), heading } } }. Winter (12-01 to 01-06) and Halloween (10-20 to 11-03) ship by default

Audio

KeyDefaultDescription
Config.Audio.EnabledtrueAll sounds and music
Volume, MusicVolume0.6, 0.220..1
MusictrueDefault for players who never touched the music toggle
Sounds15 soundsSound name to file in web/build/sounds (false turns one off)
Tracksdefault, winter, halloweenMusic per season music key

Players mute sounds and music with the two buttons in the top bar. The choice is saved on their PC.

Arrival

KeyDescription
Config.Arrival.EnabledPlays the arrival cutscene on a new character's first spawn at NewCharacterSpawn
Mode'plane' or a name registered with RegisterArrival
SkippableSPACE / ENTER skips
PlaneModel, flight Heading, Length, StartHeight and EndHeight above the spawn, Duration ms, CameraBack, CameraHeight
WalkThe character walks Distance m to the spawn point over Duration ms. Camera CameraDistance in front, CameraHeight up

Party

KeyDefaultDescription
Config.Party.EnabledtrueParty button in the selection
MaxSize6Members per party
CodeLength5Length of the join code
SpawnDistance1.6Distance from the party member when spawning next to them

Spawn

KeyDefaultDescription
SelectortrueShow the spawn selector, otherwise spawn at the last location
UseKojaSpawnSelectortrueWhen koja-spawnselector is started, use its map instead of the built-in screen
NewCharacterSelectorfalseNew characters also pick a spawn, otherwise they go to NewCharacterSpawn
NewCharacterSpawnairportWhere new characters arrive
LastLocationtrueOffer the last location
AllowBacktrueBack button from the spawn selector to the characters
TriggerPlayerSpawnedfalseAlso fires the classic playerSpawned event
CameraSky camera Height, Back, Interp and Fov
Protection10 sEnabled, Duration (s), Ghost, Invincible, DisableFiring, Alpha

Spawn points in shared/spawns.lua use the same fields as the RegisterSpawn export.

Relog

KeyDefaultDescription
Enabled, Commandtrue, 'relog'The switch character command
Cooldown60Seconds after spawning before switching is allowed
CombatSeconds30Blocks switching for this long after damage was dealt or taken
BlockWhenDead, BlockInVehicletrue, trueExtra checks
Progress3000Progress bar length in ms. 0 is instant

Other

KeyDefaultDescription
Config.Bucket.Enabled / Offsettrue / 5000Private routing bucket (Offset + server id) while choosing
Config.Playtime.SaveInterval300Seconds between playtime saves
Config.StarterItemsphone, water, breadItems given to a new character on first spawn
Config.Esx.Prefix'char'ESX character prefix, char1:license
Config.Esx.AutoResizeColumnstrueWidens identifier / owner columns so the prefix fits
Config.AdminGroups, ACE and command names, see Commands