Configuration
Server defaults, custom siren packs, fleet-wide references, the render constants, and the data.json schema a vehicle developer needs to ship a configured car.
Vehicles are configured in game, in the Editor — LEDs, patterns, rules
and sirens are all set there, and Save writes them to one data.json at the resource
root, keyed by model name.
This page is the rest: the settings an operator sets once for the whole server, and what a vehicle developer needs to ship a car that arrives already configured.
Server defaults
An admin with tlib.admin saves their display settings as the server-wide fallback through
/tels → Set as Server Defaults. They become top-level keys in data.json, and a
player's own setting always wins.
| Setting | Default | Range | Description |
|---|---|---|---|
envQuality | 4 | 0 – 4 | Environmental lighting (OFF / Low / Medium / High / Smart) |
lightingQuality | 4 | 0 – 4 | LED render pipeline quality |
hudVisible | true | boolean | HUD visibility fallback |
hudLayout | — | string | Default HUD layout name |
autoCalib | false | boolean | Whether auto-calibration runs periodically for clients who opted in |
paRange | 25 | 10 – 100 | Default PA mic range, metres. A value outside the bounds is rejected with a console warning |
paPreset | "police" | enum | "police", "fire" or "clean". Anything else is rejected with a console warning |
Custom siren packs
tELS must know which audio bank each SoundSet belongs to before it can play it. It already knows its own pack, WM-ServerSirens and OISS. Every other pack needs a mapping. Without one the sirens are silent, or audible only while another resource happens to have that bank loaded — which reads as a pack that works sometimes.
Packs that ship a manifest
Declare it in the pack's fxmanifest.lua
tels_siren_pack 'tels_sirens.json'
files { 'tels_sirens.json' }Create the mapping file
your-siren-pack/tels_sirens.json
{
"soundsets": {
"MYPACK_SOUNDSET": "DLC_MYPACK\\SIRENS",
"MYPACK_SOUNDSET_TWO": "DLC_MYPACK\\SIRENS_TWO"
}
}- Each key is the SoundSet name you type into the editor
- Each value is the bank path you would pass to
RequestScriptAudioBank - In JSON a backslash is
\\, though\\\\and/also work - A bare object without the
"soundsets"wrapper is accepted
Reference it in the editor
/telsedit → Sirens → set Server Sound Ref to the SoundSet name and Server Sound
to the sound within it.
Start order does not matter, and a pack started mid-session needs no restart.
Packs that ship no manifest
Most existing packs, LG Mods included, carry no tels_siren_pack metadata. Map their
SoundSets yourself rather than editing someone else's resource.
tELS/siren_packs.json
{
"soundsets": {
"LGMODS_MEGASIREN_SOUNDSET": "DLC_LGMODS\\MEGASIREN"
}
}Same shape, same escaping leniency, optional. An entry here overrides the pack's own; built-in SoundSets cannot be overridden from either source. Then, in the server console:
tels_reload_siren_packs
Rules and limits
A pack that loads prints Siren pack '<resource>': registered N SoundSets.
| Rule | If you break it |
|---|---|
| The file must exist and be valid JSON | tELS names the resource and file; that pack's sirens do not load |
| SoundSet names ≤128 chars, bank paths ≤160 | The entry is ignored and counted in an "ignored N malformed entries" message |
| Maximum 256 SoundSets per pack | Entries past the limit are ignored |
| You cannot override a built-in SoundSet | The entry is ignored, and tELS says which one |
| Two packs claiming one SoundSet | First registered keeps it; tELS names both resources |
Cross-vehicle references
Reference patterns, triggers and sirens across similar vehicles instead of duplicating them.
Set them up from the editor's reference menu; this is the shape they take on disk. Pattern
and trigger refs live inline in the patterns / triggers arrays.
| Shape | JSON |
|---|---|
| One pattern | { "$ref": "police4", "patternName": "Code 3" } |
| One trigger | { "$ref": "police4", "triggerId": "c5d6e7f8a9b0c1d2" } |
| All patterns or triggers | { "$ref": "police4", "$all": true } |
| Siren config (top level) | "sirenRef": "police4" |
| Settings (top level) | "settingsRef": "police4" |
| Behaviour | |
|---|---|
| Resolution | At access time, never copied |
| Editing a referenced item | Edits the source vehicle, and every referent follows |
| Chaining | Not supported. A ref pointing at a ref will not resolve |
| Orphans | Cleaned up after any save |
| In the editor | Imported items show a link icon, items others reference a share icon |
Render and bloom constants
The same on every vehicle and client, in config/render_config.lua — plain Lua, outside
escrow, editable. A bad value is named in the server console at startup, with the fix.
| Constant | Default | What it does |
|---|---|---|
TELS_MAX_LEDS | 64 | Hard cap on LEDs rendered at once, per vehicle |
TELS_LED_DEFAULT_WIDTH | 0.044 | Half-width in metres of an LED whose entry omits sw |
TELS_LED_DEFAULT_HEIGHT | 0.020 | Half-height in metres of an LED whose entry omits sh |
TELS_ARGES_LED_DEFAULT_WIDTH | 0.037 | The same, for an Arges spotlight's virtual LED |
TELS_ARGES_LED_DEFAULT_HEIGHT | 0.030 | The same, for height |
TELS_BLOOM_DEFAULT | 1.25 | Bloom multiplier a player starts on |
TELS_BLOOM_MIN / TELS_BLOOM_MAX | 0.1 / 3.0 | The range auto-calibration may move bloom within |
TELS_EDITOR_CAMERA_FOV | 50.0 | Editor orbit camera FOV in degrees. Never affects what players see |
| Trap | Detail |
|---|---|
TELS_MAX_LEDS needs a resource restart | A vehicle over the cap renders the first TELS_MAX_LEDS and the rest never light, with the vehicle named in the console. Raising it costs draw calls per vehicle per frame. Author model markers against 64 regardless, per Model-defined LEDs |
Keep TELS_BLOOM_MIN ≤ TELS_BLOOM_DEFAULT ≤ TELS_BLOOM_MAX | A default outside the bounds is clamped the first time it is read, so nobody sees the look you shipped. Startup validation reports it |
TELS_EDITOR_CAMERA_FOV is unbounded | An extreme value gives an unusable viewport with no error |
Vehicle-developer export
Bundle a config inside the vehicle resource and it loads on server start, with nothing for
the owner to copy. tELS scans every running resource for the tels_config key and merges
the file it names. Server-owner edits in data.json take priority.
Add metadata to fxmanifest.lua
Omit the line entirely if the file is at the default path, tels.json.
tels_config 'data/tels.json'Create the config file
your-vehicle/data/tels.json
{
"police4": {
"leds": [],
"patterns": [],
"triggers": [],
"siren": {}
}
}Easiest route: configure the vehicle with /telsedit, then copy its entry out of
data.json.
Ship the resource
Owners install it as usual. tELS reports the pickup in the server console on start.
Discovery parameters
The strings to look for in the server console and your own listeners.
| Parameter | Value |
|---|---|
| Metadata key | tels_config |
| Default filename | tels.json |
| Local file | data.json |
| Log tag | Lightbar |
| Chat tag | [tELS] |
| Event prefix | tels |
| Receive event | tels:config_receive |
Schema reference
One entry per model name, in these five sections.
| Section | Holds |
|---|---|
leds | Positions, rotations, sizes, groups, bone attachments |
patterns | Palettes, frame sequences, timing, playback flags |
triggers | Compound condition rules with actions |
siren | Tone slots, airhorn, horn and chirp behaviour, suspend flags |
arges | Spotlight props. Not available in this build; existing entries are preserved |
Vehicles authored with model LED markers can omit
leds. An explicit leds array, including [], always overrides model discovery.
LED entry
{
"id": "a3f1b2c4d5e6f7a8",
"name": "LBF1",
"x": 0.1, "y": 0.5, "z": 0.7,
"yaw": 0, "pitch": 0, "roll": 0,
"sw": 0.044, "sh": 0.02,
"side": 1,
"bone": "siren1",
"groups": ["Right", "Front"]
}| Field | Type | Notes |
|---|---|---|
id | string | Stable identity patterns target: an editor UUID or a tels_led_NNN marker ID |
x, y, z | number | Local offset, relative to bone if set, otherwise the chassis |
yaw, pitch, roll | number | Degrees |
sw, sh | number | Surface half-width and half-height, metres |
side | number | Legacy. 1 Right, 2 Left, 3 Center. Nothing reads it at runtime — use groups |
bone | string | Optional vehicle bone name |
groups | string[] | Display and filter tags |
shape | string | "circle", or omit for a rectangle |
bloom | string | "corona", "both", or omit for sprite-only |
extra | number | GTA extra ID. The LED renders only when that extra is enabled |
Pattern entry
{
"name": "Code 3",
"fps": 10,
"colors": [
{ "r": 255, "g": 0, "b": 0, "a": 1.0, "name": "Red" },
{ "r": 0, "g": 120, "b": 255, "a": 1.0, "name": "Blue" }
],
"frames": [
{
"cells": { "a3f1b2c4d5e6f7a8": 1, "b4e2c3d5f6a7b8c9": 2 },
"dimCells": { "a3f1b2c4d5e6f7a8": true },
"duration": 1
}
],
"triggerOnly": false,
"syncNear": false,
"useEmergencyLights": false,
"useHighBeams": false,
"livery": 0,
"modkit": 1,
"extras": [{ "id": 3, "enable": true }],
"mods": [{ "modType": 49, "modIndex": 0 }]
}| Field | Type | Notes |
|---|---|---|
fps | number | 1–30. The editor clamps to that range |
cells | object | LED ID → 1-based colour index. 0 is off |
dimCells | object | LED ID → true to interpolate smoothly into the next frame |
duration | number | Ticks at the pattern's fps |
triggerOnly | boolean | Skipped by 9/0 cycling, still usable by trigger actions |
syncNear | boolean | Sync the frame index across clients from the server clock |
useEmergencyLights | boolean | Hold GTA's native emergency-lights flag while playing |
useHighBeams | boolean | Hold high beams while playing |
livery | number | Restrict to a livery index. Omit for any |
modkit | number | Modkit applied while active. Omit to leave the vehicle's alone |
extras | array | { "id": 1–12, "enable": true|false } — extras forced on or off while active |
mods | array | { "modType": 0–49, "modIndex": number, "customTires": boolean }. modIndex: -1 is stock |
modkit, extras and mods are restored when the pattern stops, by the owning client
only.
Trigger entry
{
"id": "c5d6e7f8a9b0c1d2",
"conditions": ["brake", "speed_30"],
"negated": [false, false],
"operator": "and",
"enabled": true,
"actions": [{ "type": "pattern_overlay", "patternName": "Brake Warning" }]
}| Field | Type | Notes |
|---|---|---|
id | string | 16-char hex UUID. Trigger refs target it |
conditions | string[] | See Editor → Condition reference |
negated | boolean[] | Parallel to conditions. true flips that condition |
operator | string | "and" or "or" |
actions | object[] | See Editor → Action types |
enabled | boolean | Ignored when false |
Legacy triggers shaped { trigger: "brake", patternName: "..." } auto-migrate on load.
Siren config
{
"tones": [
{
"name": "Wail",
"sound": "VEHICLES_HORNS_SIREN_1",
"serverSound": "", "serverSoundRef": "",
"rumblerSound": "", "rumblerServerSound": "", "rumblerServerSoundRef": "",
"enabled": true,
"triggerOnly": false
}
],
"airhorn": "SIRENS_AIRHORN",
"serverAirhorn": "", "serverAirhornRef": "",
"serverAirhornRumbler": "", "serverAirhornRumblerRef": "",
"hornInterrupt": true,
"parkKill": true,
"useNormalHorn": true,
"hornProgrammable": false,
"lightsSuspendTA": true,
"lightsSuspendTakedown": true,
"chirpTone": 1,
"chirpByCode": false,
"noUserControls": false,
"disabledExtras": []
}Up to 8 entries in tones[], one slot each on R and keys 1–8.
| Field | Type | Default | Notes |
|---|---|---|---|
name | string | — | Shown in the HUD and the editor |
sound | string | — | Vanilla GTA sound string, e.g. VEHICLES_HORNS_SIREN_1 |
serverSound | string | "" | Sound name inside a server-bundled SoundSet |
serverSoundRef | string | "" | The SoundSet it lives in. Both are required, or it falls back |
rumblerSound | string | "" | Vanilla sound while the rumbler is on. Main siren only |
rumblerServerSound / rumblerServerSoundRef | string | "" | Server-bundled rumbler sound and its SoundSet |
enabled | boolean | true | A disabled slot is skipped by every lookup |
triggerOnly | boolean | false | Skipped by R, 1–8 and cycling. Rules and exports still reach it |
Airhorn, horn and vehicle behaviour:
| Field | Type | Default | Notes |
|---|---|---|---|
airhorn | string | SIRENS_AIRHORN | Vanilla airhorn sound |
serverAirhorn / serverAirhornRef | string | "" | Server-bundled airhorn sound and its SoundSet |
serverAirhornRumbler / serverAirhornRumblerRef | string | "" | The same, while the rumbler is on |
hornInterrupt | boolean | true | Main siren pauses while the airhorn plays |
useNormalHorn | boolean | true | E plays the native horn with lights off. false = airhorn always |
hornProgrammable | boolean | false | Suppress the default horn audio and the interrupt; rules drive the horn |
parkKill | boolean | true | Sirens stop on driver exit and park_kill fires |
lightsSuspendTA | boolean | true | Traffic advisor suspends while lights are on |
lightsSuspendTakedown | boolean | true | Takedown suspends while lights are on |
chirpTone | number | 1 | Tone slot the park chirp plays |
chirpByCode | boolean | false | true holds the tone for the full chirp; false repeats 75–125 ms blips |
paEnabled | boolean | true | false disables the PA mic on this vehicle |
noUserControls | boolean | false | Disables every tELS keybind. GTA's own horn, radio wheel and cinematic camera stay available |
disabledExtras | number[] | [] | Extra IDs (1–12) forced off regardless of the vehicle's default |
liveryProfiles | object[] | — | Per-livery sound overrides, below |
Server-sided sounds play when configured and the player has Server-sided Sirens on;
otherwise the vanilla sound does. Third-party SoundSets also need an
audio bank mapping.
Per-livery siren sounds
"liveryProfiles": [
{
"livery": 0,
"tones": [
{ "serverSound": "police_wail", "serverSoundRef": "POLICE_SOUNDSET" },
{ "serverSound": "police_yelp", "serverSoundRef": "POLICE_SOUNDSET" }
],
"serverAirhorn": "police_horn",
"serverAirhornRef": "POLICE_SOUNDSET"
}
]One entry per zero-based native livery index. Tone entries line up with the existing default slots, and an empty object inherits one. A profile cannot add, reorder or rename slots, or change eligibility or vehicle behaviour.
| Overridable per tone | sound, serverSound, serverSoundRef, rumblerSound, rumblerServerSound, rumblerServerSoundRef |
| Also accepted | airhorn, serverAirhorn, serverAirhornRef, serverAirhornRumbler, serverAirhornRumblerRef |
| Missing field | Inherits. An empty string clears an optional sound and restores the usual fallback |
sirenRef | Inherits the default sounds and the profile collection, before matching the receiving vehicle's livery |
Size limits
Enforced on every config the server accepts, and on the catalogue.
| Limit | Value | On exceeding it |
|---|---|---|
| Frames per pattern | 512 | Frames past 512 are trimmed and the pattern kept. The console names the vehicle and pattern |
| Encoded size, one vehicle | 512 KB | The save is refused and the previous config stays. The console prints the actual size |
tELS
Still stuck? Support can answer it directly.
Was this page helpful?
TIMMYG Studios