Koja Scripts
FREE

Player settings

js.json: the defaults new players get, Discord, logo, key hints, and how the settings menu is built.

Player settings

Every player can restyle their own HUD from the settings menu (/settings). editable/shared/js.json decides what a player starts with before they change anything, adds your Discord link, logo and key hints, and describes the settings menu itself.

The file has three parts:

KeyWhat it holds
default_settingsWhat a new player's HUD looks like
uiServer branding: Discord, logo, key hints, built-in binds
options_settingsWhich options appear in the settings menu, grouped into windows

Where player choices are stored

A player's choices are saved in their own game client (the NUI browser storage), not on the server. They follow the player's PC, not their character, and survive server restarts and resource updates.

What a player sees is your default_settings with their own changes laid on top. So when you change a default, everybody who has not touched that particular option gets the new value; players who changed it keep theirs.

Two defaults come from config.lua instead and win over js.json:

SettingComes from
minimap.visibilityKOJA.HideMinimapOnFoot — true gives vehicle, false gives always
killfeed.enabled, killfeed.anyDistance, killfeed.distanceKOJA.Killfeed

default_settings

HUD, status and speedometer

editable/shared/js.json
"hud": { "visibility": true },
"status": {
    "visibility": true,
    "style": "default",
    "colors": { "health": "#ff4444", "shield": "#e2e2e2", "food": "#d8932b", "water": "#60b7ff",
                "stamina": "#8dd82b", "oxygen": "#4b7dad", "voice": "#ffb74d", "stress": "#ff6666" },
    "percent": { "health": { "value": 50, "action": "below", "visibility": true }, "...": {} },
    "enabled": { "health": true, "shield": true, "food": true, "water": true,
                 "stamina": true, "oxygen": true, "voice": true, "stress": true },
    "borderradius": 0.5,
    "scale": "1.5"
},
"carhud": {
    "visibility": true,
    "style": "gauge",
    "metertype": "kmh",
    "elements": { "gear": true, "fuel": true, "nitro": true, "seatbelt": true, "engine": true,
                  "rpm": false, "engineHealth": false, "lights": false, "indicators": false, "cruise": false }
}
SettingValuesWhat it does
hud.visibilitytrue / falseThe whole HUD
status.visibilitytrue / falseThe status bars
status.styledefault, circle, echo, minimal, hexagonStatus bar style
status.colors.<id>hex colourColour of each bar
status.enabled.<id>true / falseShow or hide a single bar
status.percent.<id>value, action, visibilityShow a bar only above or below a value — see below
status.borderradius0.01–1.5Corner rounding
status.scale"0.5", "1.5", "3"Small, Default, Big. A string, not a number
carhud.visibilitytrue / falseThe speedometer
carhud.stylegauge, default, compact, minimal, pvpSpeedometer style
carhud.metertypekmh, mphSpeed unit
carhud.elements.<id>true / falsegear, fuel, nitro, seatbelt, engine, rpm, engineHealth, lights, indicators, cruise

The status ids are health, shield (armour), food (hunger), water (thirst), stamina, oxygen, voice and stress.

Conditional bars. status.percent can hide a bar until it matters. "visibility": true — the default for every bar — means always show, and the rule is ignored. Set it to false and the rule applies: with "action": "below" and "value": 50 the bar shows only while it is under 50%, so hunger appears when the player gets hungry. "above" is the opposite, which suits oxygen and stress. In the menu this is Settings → STATUS → Status Percents Settings: Show, Show if over, Show if under.

Messages and information

editable/shared/js.json
"notify": { "visibility": true, "position": "top-right", "style": "default" },
"informations": {
    "visibility": true,
    "opacity": 1,
    "items": { "logo": false, "voice": true, "id": true, "time": true,
               "cash": true, "bank": true, "job": true, "discord": true }
},
"keybinds": { "visibility": true },
"compass": { "visibility": "always", "style": "bar" },
"weapon": { "visibility": false },
"minimap": { "visibility": "always" }
SettingValuesWhat it does
notify.visibilitytrue / falseNotifications
notify.positiontop-right, bottom-leftWhere they stack
notify.styledefault, minimalistic, modernNotification style
informations.visibilitytrue / falseThe information panel
informations.opacity0–1Its opacity
informations.items.<id>true / falselogo, voice, id, time, cash, bank, job, discord
keybinds.visibilitytrue / falseThe key hints list
compass.visibilityalways, vehicle, foot, neverWhen the compass shows
compass.stylebar, minimal, cardinalCompass style
weapon.visibilitytrue / falseWeapon and ammo panel
minimap.visibilityalways, vehicle, foot, neverOverridden by KOJA.HideMinimapOnFoot, see above

Watermark, PVP, warnings, killfeed, effects

editable/shared/js.json
"watermark": { "visibility": true, "style": "default", "font": "Poppins", "size": 0.95,
               "color": { "text": "#f2f2f5" } },
"pvp": { "enabled": false },
"warnings": { "lowHealth": true, "lowFuel": true, "sound": true,
              "healthThreshold": 20, "fuelThreshold": 15 },
"killfeed": { "enabled": false, "style": "default", "anyDistance": true, "distance": 100 },
"statuseffects": { "enabled": true }
SettingValuesWhat it does
watermark.visibilitytrue / falseOnly matters when KOJA.Watermark.Enabled is true
watermark.styledefault, line, bracketWatermark style
watermark.fontPoppins, Inter, Montserrat, Proxima, SF ProFont
watermark.size0.6–1.8Text size
watermark.color.texthex colourText colour
pvp.enabledtrue / falsePVP mode — see Features
warnings.lowHealth, warnings.lowFueltrue / falseLow health and low fuel warnings
warnings.healthThreshold, warnings.fuelThreshold5–50Percent at which each warning starts
warnings.soundtrue / falseBeep with the warnings
killfeed.styledefault, minimal, modernKillfeed style
statuseffects.enabledtrue / falseThe status effects row

Binds and layout

editable/shared/js.json
"customBinds": [],
"builtinBinds": [
    { "id": "engine", "key": "B", "command": "+toggle_engine" },
    { "id": "seatbelt", "key": "L", "command": "+toggle_seatbelt" },
    { "id": "cruise", "key": "T", "command": "+toggle_cruisemode" },
    { "id": "nitro", "key": "N", "command": "+toggle_nitro" },
    { "id": "vehicleMenu", "key": "U", "command": "koja_vehiclemenu" }
],
"layout": {
    "status": { "x": 0, "y": 0 },
    "minimap": { "x": 0, "y": 0, "scale": 1 }
}
  • customBinds — key-to-command binds every new player starts with, for example { "key": "F5", "command": "e sit" }. The command runs as if typed in chat, without the slash.
  • builtinBinds — the starting keys of the HUD's own actions. Keep these in line with the Key values in config.lua.
  • layout — starting offsets for each element, in percent of the screen width (x) and height (y). Players set these by dragging in Edit layout; you rarely need to touch them.

ui

editable/shared/js.json
"ui": {
    "discord": "discord.gg/hexelstore",
    "logo": "",
    "keybinds": {
        "position": "right",
        "hints": [
            { "key": "M", "label": "Main menu" },
            { "key": "F3", "label": "Reload voice" }
        ]
    },
    "activeBinds": [
        { "id": "engine", "key": "B", "command": "+toggle_engine",
          "label": "Engine", "description": "Toggle the vehicle engine" }
    ]
}
KeyWhat it does
discordInvite shown in the information panel. Empty string hides it.
logoURL of your server logo, shown at the top of the information panel when the player enables Server Logo. Use an https:// image link.
keybinds.positionright or left — which side of the screen the key hints sit on.
keybinds.hintsThe list of key hints. They are only labels: changing them does not bind anything. Put your server's real keys here.
activeBindsThe HUD's built-in actions as listed in Settings → BINDS, with the label and description players see.

options_settings

This part builds the settings menu. It has three categories — hud (shown as MAIN), status and carhud (SPEEDOMETER) — and each is a list of windows:

editable/shared/js.json
{
    "window": "notify",
    "icon": "fa-solid fa-bell",
    "title": "notify_settings.title",
    "description": "notify_settings.description",
    "color": "#ff6666",
    "settings": [
        {
            "type": "dropdown",
            "id": "notify.position",
            "title": "notify_settings.settings.position_title",
            "description": "notify_settings.settings.position_description",
            "options": [
                { "id": "top-right", "label": "notify_settings.options.position.top-right" },
                { "id": "bottom-left", "label": "notify_settings.options.position.bottom-left" }
            ]
        }
    ]
}
FieldMeaning
windowWindow id
iconA Font Awesome class
title, description, labelKeys into ui.settings of the locale file — see Translations
colorAccent colour of the window
settings[].idThe default_settings path the control changes, for example notify.position
settings[].typeswitch, dropdown, slider (with min and max), color (one picker per option), toggles (one switch per option) or percent (value, above/below, on/off)

What you can safely do here:

  • Remove a setting or a whole window, to stop players changing it. The default still applies.
  • Reorder windows and settings.
  • Remove options from a dropdown — for example offer only two speedometer styles.

What does not work: adding a setting whose id the UI does not read, or a dropdown value the component has no style for. New behaviour needs a change in web/src — see UI development.

Resetting a player

A player resets their own settings from the settings menu. There is no server-side reset, because the settings are not stored on the server.