Skip to content

API Reference

Exports, state bags and network events for driving tELS from another resource.

Read with GetLightState, drive with the write exports. Every vehicle-taking export returns nil on a non-tELS entity.

Read exports

ExportArgumentsReturns
IsSirenActivevehicleAny siren playing — main, aux or burst
AreLightsActivevehicleEmergency lights on, meaning stage > 0
GetLightStatevehicleThe whole replicated state — below
GetTelsStatevehicleA capture for replay — below
IsPaActive—The calling client's own PA mic state. nil without pma-voice
IsPaAvailable—Whether pma-voice is running

For another player's PA, read lbarPaActive on the player state bag.

GetLightState

A vehicle's whole replicated state in one read.

lua
local st = exports['tELS']:GetLightState(vehicle)
if st and st.active and st.sirenOn then
    -- running code 3
end

Returns every tels:sync field — live local state, else the replicated bag, else the documented defaults — plus:

FieldTypeNotes
modelKeystringThe model name this vehicle's config is stored under
maxStagenumberHighest stage this model has rules for. 0 means no stages
patternNamestring | nilThe currently selected pattern
isOwnerbooleanYou own this vehicle and the server has confirmed it
canWritebooleanA write export would be accepted right now
canControlbooleanThe player sitting here can operate it — either front seat

GetTelsState

Captures a vehicle's lighting for replay.

lua
local captured = exports['tELS']:GetTelsState(vehicle)
KeyHolds
20 look fieldsactive, stage, cruiseOn, takedownOn, blackout, taMode, the six siren fields, hornActive, chirpActive, rumblerOn, presenceEnabled, and the four arges fields, always inert in this build
modelKey, patternIdx, patternName, liverypatternName is the stable identifier — editing the config renumbers patternIdx
phase{ netTime, frameIdx, tickCount, lerpT }
triggersThe live condition map, so rules re-fire on replay where they fired in the take, rising edges included

SetTelsState

Drives lighting from a capture. Pass nil to return control to live triggers. Returns false with no tELS config, and is safe every frame.

lua
exports['tELS']:SetTelsState(vehicle, captured)
exports['tELS']:SetTelsState(vehicle, nil)  -- release

SetTelsCinematicAudio

The audio half of a replay. Call it each frame with the captured audio fields.

lua
exports['tELS']:SetTelsCinematicAudio(vehicle, {
    sirenOn = true, sirenTone = 2,
    auxSirenOn = false,
    sirenBurst = false, burstTone = 1,
    hornActive = false,
    rumblerOn = false,
})
exports['tELS']:SetTelsCinematicAudio(vehicle, nil)  -- silence
spec fieldTypeEffect
sirenOnbooleanHold the main siren on sirenTone
sirenTonenumberA tone this vehicle does not have leaves the main siren silent
auxSirenOn / auxSirenToneboolean / numberThe aux channel. Never takes the rumbler variant
sirenBurstbooleanOne-shot on the rising edge, and only while sirenOn is false
burstTonenumberTone the burst plays. Defaults to 1
hornActivebooleanHold the airhorn
rumblerOnbooleanChanging it re-triggers whatever is playing

Idempotent: an unchanged spec makes no sound.

  • Returns nil with no tELS config
  • Returns false for an untracked vehicle, or one with a real player in either front seat. It silences what it had started as it refuses
  • An NPC driver puppet is not a player, so a recorded take keeps its sound

Write exports

These run the same code the keybinds run.

ReturnMeaning
nilNot a tELS vehicle. The same signal the read exports give, so you can probe with it
falseRefused: a bad argument, something this vehicle is not configured for, or a write this client may not make
trueApplied

When a write is refused

A write is accepted only on the vehicle the caller owns, has been confirmed as owning by the server, and is currently sitting in. Test canWrite rather than branching on a false.

  • canControl is a different question — whether the player sitting in the vehicle can operate it. Both front seats can, so a passenger has canControl true and canWrite false at once. A script sits nowhere and is judged on canWrite
  • An open LED editor session refuses every write
  • No User Controls does not. It only stops tELS taking the driver's keys
  • Lights being off does not. Sirens, takedown, cruise, the traffic advisor and the rumbler are independent of the light stage

Lights

lua
exports['tELS']:SetLights(vehicle, true)      -- on (stage 1 if the model has stages)
exports['tELS']:SetStage(vehicle, 2)          -- straight to stage 2; 0 is off
exports['tELS']:CycleLights(vehicle)          -- off -> 1 -> 2 -> ... -> off
ExportArgumentsNotes
SetLightsvehicle, onon must be a boolean
SetStagevehicle, stage0 is off. A stage above maxStage is refused, and so is any stage on a model with no stages — use SetLights there
CycleLightsvehicleExactly the driver's toggle key

Patterns

lua
exports['tELS']:SetPattern(vehicle, 'Slow Cross')  -- by name
exports['tELS']:SetPattern(vehicle, 0)             -- lights only
exports['tELS']:CyclePattern(vehicle, -1)          -- step back one
ExportArgumentsNotes
SetPatternvehicle, nameOrIndex0 selects the lights-only slot
CyclePatternvehicle, deltadelta defaults to 1; negative steps backwards

Sirens and horn

lua
exports['tELS']:SetSiren(vehicle, true, 2)     -- main siren on, tone 2
exports['tELS']:SetSiren(vehicle, true)        -- main siren on, keep the current tone
exports['tELS']:SetAuxSiren(vehicle, false)    -- aux siren off
exports['tELS']:SetAirhorn(vehicle, true)      -- and false to release it
exports['tELS']:SetRumbler(vehicle, true)
ExportArgumentsNotes
SetSirenvehicle, on, tone?tone keeps the selected tone when omitted, and is ignored when switching off
SetAuxSirenvehicle, on, tone?Same shape. The aux channel never uses the rumbler variant
SetAirhornvehicle, onAirhorn with lights on, or when the config disabled the stock horn; the vehicle's own horn otherwise
SetRumblervehicle, onRestarts a running main siren so the change is audible
SetChirpvehicle, onA latch, like SetAirhorn — nothing releases it but false

A tone outside the vehicle's list is refused, and so is one whose slot is off. Trigger-only tones are available here.

Traffic advisor, takedown, cruise

lua
exports['tELS']:SetTrafficAdvisor(vehicle, 'left')
exports['tELS']:CycleTrafficAdvisor(vehicle)
exports['tELS']:SetTakedown(vehicle, true)
exports['tELS']:SetCruise(vehicle, false)
ExportArgumentsNotes
SetTrafficAdvisorvehicle, mode"off", "left", "right" or "center"
CycleTrafficAdvisorvehicleNext mode this vehicle has configured
SetTakedownvehicle, on
SetCruisevehicle, on

A direction with no trigger rule is refused. "off" is always accepted.

Blackout

lua
exports['tELS']:SetBlackout(vehicle, true)   -- run dark
exports['tELS']:SetBlackout(vehicle, false)  -- come back up exactly as before

Blackout hides the lighting without switching it off.

  • Stage, pattern, pattern position, cruise, takedown, traffic advisor and spotlight aim keep running underneath, so false restores exactly what was showing
  • Visual only — the siren and horn keep playing
  • It replicates. GetLightState reports blackout, with active still true

PA

lua
exports['tELS']:SetPa(vehicle, true)    -- and false to release

Hold-style: the caller releases it. Check IsPaAvailable first — without pma-voice this refuses where every other write export would succeed.

Spotlight

lua
exports['tELS']:SetArges(vehicle, true)                  -- beam on
exports['tELS']:SetArgesAim(vehicle, 'left', true)       -- start swinging left
exports['tELS']:SetArgesAim(vehicle, 'left', false)      -- stop
exports['tELS']:ReleaseArgesAim(vehicle)                 -- stop, whatever was held
ExportArgumentsNotes
SetArgesvehicle, onBeam on or off
SetArgesAimvehicle, dir, downdir is "up", "down", "left" or "right". Held, not absolute
ReleaseArgesAimvehicleReleases every held direction at once

Aim is held, not absolute: the beam swings while a direction is down.

  • A direction left down sweeps forever. If your key-up can go missing, call ReleaseArgesAim — it drops everything held and is safe when nothing is
  • SetArges(vehicle, false) does not cancel a trigger rule holding the spotlight on

Example

lua
-- Dispatch puts this unit into code 3.
local function goCode3()
    local veh = GetVehiclePedIsIn(PlayerPedId(), false)
    local st = exports['tELS']:GetLightState(veh)
    if not st then return end          -- not a tELS vehicle
    if not st.canWrite then return end -- not ours to drive right now

    if st.maxStage > 0 then
        exports['tELS']:SetStage(veh, st.maxStage)
    else
        exports['tELS']:SetLights(veh, true)
    end
    exports['tELS']:SetSiren(veh, true, 1)
end

State bags

Entity state bags

Read with Entity(vehicle).state['key'], from client or server. The server writes exactly four keys.

KeyTypeDescription
tels:synctableThe whole lighting and siren state. Fields below
tels:ownedBynumberServer ID of the player who claimed this vehicle
tels:presenceDetectedbooleanPresence condition currently satisfied
tels:argesAimtable{ argesAimYaw, argesAimPitch }. Never written in this build

tels:sync fields

A field is absent until first set, so always supply a default.

FieldTypeDefaultDescription
activebooleanfalseEmergency lights active
patternIdxnumber1Pattern index, 1-based. 0 is lights-only
stagenumber00 off, 1–3
sirenOnbooleanfalseMain siren playing
sirenTonenumber1Main siren tone index
auxSirenOnbooleanfalseAux siren playing
auxSirenTonenumber1Aux siren tone index
sirenBurstbooleanfalseBurst tone currently held
burstTonenumber1Tone the burst plays. Does not change sirenTone
hornActivebooleanfalseHorn or airhorn active
cruiseOnbooleanfalseCruise on
takedownOnbooleanfalseTakedown on
blackoutbooleanfalseRunning dark: lighting suppressed, state intact
taModestring"off""off", "left", "right", "center"
presenceEnabledbooleanfalsePresence detection armed
chirpActivebooleanfalseChirp tone running
rumblerOnbooleanfalseRumbler variant active
argesOnbooleanfalseSpotlight active. Never true in this build
argesAimYawnumber0.0Spotlight aim, horizontal degrees
argesAimPitchnumber0.0Spotlight aim, vertical degrees
paActivebooleanfalsePA mic broadcasting from this vehicle's driver

Player state bags

Read with Player(serverId).state['key'].

KeyTypeDescription
tels:ownerbooleantrue while that player owns any tELS vehicle. Used to filter other officers out of presence detection
lbarPaActivebooleantrue on the player currently holding the PA key

lbarPaActive and tels:sync.paActive are different facts: the vehicle field says the speaker is live, this one says who is talking. A front passenger's PA is relayed by the controller, so the two can differ.

Example

lua
-- React to a nearby vehicle going Code 3
CreateThread(function()
    while true do
        Wait(500)
        local veh = GetClosestVehicle(coords.x, coords.y, coords.z, 30.0, 0, 71)
        local sync = veh ~= 0 and Entity(veh).state['tels:sync']
        if sync and sync.active and (sync.stage or 0) >= 2 and sync.sirenOn then
            -- code 3 behavior
        end
    end
end)

tels:sync is nil on any vehicle tELS has never written state for. Check before indexing.

Network events

Server → client

EventPayloadPurpose
tels:config_receiveconfigs (modelName → config), merge (boolean)Vehicle configs, sent latently. merge true carries only the changed model — apply it on top of what you hold. merge absent or false carries the whole map and replaces it
tels:serverDefaultsdefaultsAdmin display defaults, available layouts, isAdmin flag
tels:sirenBanksmap (SoundSet → bank path)Discovered third-party siren pack mappings
tels:ownershipAcknetIdYour tels:claimOwnership was accepted. Wait for it — every tels:stateBagRelay sent before it arrives is discarded
tels:frontSeatCommandnetId, action, a, bA front passenger's control, forwarded to the controller. Sent to that one client
tels:notifymsgInbound hook. Trigger it from your resource to show a tELS notification on the target client

Client → server

EventPayloadACEPurpose
tels:requestDefaults——Request server defaults and available layouts
tels:sirenBanks_request——Request the SoundSet → bank map
tels:saveServerDefaultsdatatlib.adminPersist new server defaults
tels:claimOwnershipnetId—Claim ownership for state relay. Answered with tels:ownershipAck
tels:releaseOwnershipnetId—Give up the relay right and clear tels:owner. Ignored unless the server still records you as owner
tels:paFlagnetId, active—Set lbarPaActive on yourself. A true needs a front seat in that vehicle; a false is always accepted. One per 100 ms
tels:frontSeatCommandnetId, action, a, b—Hand a control to the controller. Only from a front passenger who is not the controller; a and b must be nil, boolean, number, or a string ≤32 chars. One per 25 ms
tels:stateBagRelaynetId, delta, seq—Relay a state delta. seq is a required monotonic counter; a call omitting it is silently dropped. Only the registered owner is accepted
tels:presenceSyncnetId, detected—Report presence. Not ownership-gated. Aggregated per reporter; a true is a lease re-sent at least every 15 s. One per 500 ms per player, except re-sending a true you already hold
tels:ref_edit_pattern_deltamodel, patternName, editDatatlib.adminApply a pattern delta to a referenced source
tels:ref_edit_triggermodel, triggerId, newTriggertlib.adminReplace a trigger in a referenced source
tels:ref_edit_sirenmodel, newSirenConfigtlib.adminUpdate tones, airhorn and chirp on a referenced source
tels:ref_edit_settingsmodel, newConfigtlib.adminUpdate siren behaviour settings on a referenced source

Discovery events

EventDirectionPurpose
tels:config_receiveS → CAuthoritative config broadcast — see the merge flag above
tels:externalSourceInfoS → CWhich resource bundled each model's config
tels:exportTargetsS → CModels available for export or bundling
tels:config_requestC → SAsk for the whole map. Answered latently, to the requester only
tels:config_saveC → SPersist a model's config. The editor's channel — tlib.admin

Discovery metadata

FieldValue
Metadata keytels_config
Default filenametels.json
Local storagedata.json at the tELS resource root
Event prefixtels

Full setup: Configuration → Vehicle-developer export.

Internal globals

For scripts that merge into the tELS resource. Names and signatures may change.

GlobalSourcePurpose
lbarGetLocalState(vehicle)cl_lights.luaLocal state table. nil for a remote vehicle
lbarGetMaxStage(modelName)cl_lights.luaMax configured stage for a model
getVehicleConfig(modelName)cl_lights.luaFull resolved config
getCustomPatterns(modelName)cl_lights.luaResolved patterns, refs dereferenced
getResolvedTriggers(modelName)cl_lights.luaResolved triggers
getSirenConfig(modelName)cl_lights.luaResolved siren config
resolveColorIndex(led, ledIndex, frame, alias)shared/utils.luaPattern-cell lookup with legacy fallback. alias maps local → source keys for $ref patterns
renderLEDSet(veh, leds, colors, opts)cl_renderer.luaUnified LED render entry point

Still stuck? Support can answer it directly.

Was this page helpful?