Configuration

The data.json schema, per-vehicle sequence packs, admin settings, and player KVP overrides.

Reference

Where configuration lives

tAFK has three layers of configuration, resolved at playback time:

LayerScopeStorageOwner
Built-in defaultsAll playersshared/schema.luaResource — restored if data.json is missing
Server stateAll players, all vehiclesdata.json at resource rootAdmins via /tafk or direct JSON edit
Per-vehicle packOne model<otherResource>/tafk.jsonVehicle pack authors
Per-player overridesOne playertLib KVP (tafk:* keys)The player, via /tafk

Merge order (lowest to highest priority): defaults → data.json → player KVP for settings; data.json union per-vehicle pack union (never conflicts — different scopes) for sequences.


data.json shape

Lives at tAFK/data.json. Created on first boot from shared/schema.lua defaults. Read once at server start. Editing data.json on disk requires a resource restart to take effect. Broadcast to clients via tafk:config_receive.

data.json
{
  "version": 1,
  "settings": {
    "timeoutSeconds": 30,
    "useMusic": true,
    "musicVolume": 0.035,
    "hideHudInAFK": true,
    "beatAnchorMs": -15,
    "minDurationMs": 5000,
    "maxDurationMs": 10000
  },
  "sequences": [
    {
      "id": "seed_01",
      "name": "Low Ground Wide Side Pan",
      "enabled": true,
      "vehicles": ["*"],
      "start": {
        "offset": [-6.0, -7.0, 0.1],
        "rotation": [3.0, 0.0, 30.0],
        "fov": 55.0,
        "dof": { "near": 2.0, "far": 20.0, "strength": 0.7 }
      },
      "end": {
        "offset": [-5.0, -6.5, 0.1],
        "rotation": [3.0, 0.0, 28.0],
        "fov": 55.0,
        "dof": { "near": 2.0, "far": 20.0, "strength": 0.7 }
      }
    }
  ],
  "vehicleConfigs": {
    "bati801": {
      "sequences": [
        { "id": "bati_low_pass", "name": "Low Pass", "vehicles": ["bati801"], "enabled": true, "start": {...}, "end": {...} }
      ]
    }
  }
}

Music tracks aren't stored in data.json

Audio files are discovered automatically at server start by scanning the audio/ folder. See Music tracks below.

settings

KeyTypeDefaultDescription
timeoutSecondsint30Idle seconds before auto-AFK fires. Zero disables auto-trigger
useMusicbooltrueWhether to start music on AFK enter
musicVolumefloat (0–1)0.035NUI audio element target volume
hideHudInAFKbooltrueWhether to hide HUD + minimap while AFK. When true, DisplayHud(false) / DisplayRadar(false) fire on AFK enter
beatAnchorMsint-15Offset applied to next-beat timing. Negative = cut before beat (anticipation)
minDurationMsint5000Lower bound for sequence duration; beat-sync stays within range
maxDurationMsint10000Upper bound for sequence duration

sequences[]

Each entry:

FieldTypeNotes
idstringStable identifier. Used for player opt-outs, admin edits. Generate once (seq_<timestamp> is fine) and never change
namestringDisplay name in /tafk menus
enabledboolWhen false, skipped by the director
vehiclesstring[]["*"] = all vehicles. List specific model names (lowercase) to restrict. Match is case-insensitive
start / endobjectSee Keyframe shape

Keyframe shape

{
  "offset":   [x, y, z],
  "rotation": [pitch, roll, yaw],
  "fov":      55.0,
  "dof":      { "near": 2.0, "far": 20.0, "strength": 0.7 }
}
  • offset — vehicle-local coordinates (right = +x, forward = +y, up = +z). Metres
  • rotation — degrees. Applied as delta to the implicit "point at vehicle" rotation at runtime
  • fov — camera field of view in degrees (10–120)
  • dof.near / .far — depth-of-field range in metres
  • dof.strength — DOF intensity, 0 (no blur) to 1 (full)

Offsets also accept the alternate object form { "x": ..., "y": ..., "z": ... } — both shapes round-trip through tafkToVec3.

Music tracks

tAFK picks up audio files at server start. Supported extensions: .ogg, .mp3, .wav. There are two ways to get a file into the rotation:

Option 1 — name it one of the recognised patterns (zero config):

PatternRangeExample
bg<N>1–99bg1.ogg, bg6.ogg
track<N>1–99track1.mp3
afk<N>1–99afk1.ogg
music<N>1–99music1.ogg
cinematic<N>1–99cinematic1.wav

Option 2 — list any filename in audio/manifest.txt:

audio/manifest.txt
# One filename per line. Blank lines and #-comments are ignored.
intro.ogg
chill-beat.mp3
synthwave drive.wav

Both methods run at boot and results are merged (files listed in both places de-dupe). Delete a file from audio/ or remove its line from manifest.txt and restart to drop the track.

Why manifest.txt rather than a real directory listing?

FiveM's Lua runtime has no directory-enumeration API — the server can't ask "what's in audio/?" on its own. The pattern scan uses LoadResourceFile to probe 1,485 known names at startup (99 × 5 prefixes × 3 extensions), completes in milliseconds. manifest.txt fills the gap for any other name without you having to rename your files.

vehicleConfigs

Managed by tLib's Discovery module — do not edit this section directly in data.json. The admin editor writes to it via tafk:admin:upsertVehicleSequence, and external vehicle packs contribute via tafk_config metadata. See below.


Per-vehicle sequence packs

Vehicle resources can bundle their own AFK sequences. When the pack starts, tLib's Discovery module scans it for a tafk_config metadata key, loads the referenced JSON, and merges the keyed entries into the global vehicleConfigs map.

Pack layout

my-vehicle-pack/
├── fxmanifest.lua
├── stream/mycar.yft, .ytd, ...
└── tafk.json

Manifest declaration

fxmanifest.lua
fx_version 'cerulean'
game 'gta5'

files { 'tafk.json' }

tafk_config 'tafk.json'

One metadata key per pack

tafk_config points at a single JSON file per resource. Multiple vehicles can live in the same file, keyed by model name.

JSON shape

tafk.json
{
  "mycar": {
    "sequences": [
      {
        "id": "mycar_front_pan",
        "name": "Front Bumper Pan",
        "enabled": true,
        "vehicles": ["mycar"],
        "start": {
          "offset": [-0.8, 3.5, 0.4],
          "rotation": [-2.0, 0.0, 175.0],
          "fov": 42.0,
          "dof": { "near": 0.5, "far": 4.0, "strength": 1.0 }
        },
        "end": {
          "offset": [0.8, 3.5, 0.4],
          "rotation": [-2.0, 0.0, 185.0],
          "fov": 42.0,
          "dof": { "near": 0.5, "far": 4.0, "strength": 1.0 }
        }
      }
    ]
  },
  "mysecondcar": {
    "sequences": [ { ... } ]
  }
}
  • Top-level keys are lowercase vehicle model names
  • Each value has { "sequences": [...] } with entries in the same shape as data.json.sequences[]
  • vehicles inside each entry should include the parent model for consistency but it's not enforced

Priority rules

When the same model name appears in multiple running resources, Discovery deduplicates: the first-scanned wins. Server-side admin edits through the tAFK UI write to data.json.vehicleConfigs and take priority over pack entries.

When configs refresh

  • Server start — Discovery scans every running resource once
  • onResourceStart — when a pack starts after server boot, its configs merge in and clients get a fresh broadcast
  • Admin saves — /tafkedit with scope=vehicle writes and broadcasts immediately

Admin settings via /tafk

Every field in settings is tunable from /tafk when the player has the tlib.admin ACE. Changes apply live:

  • Sliders fire tafk:admin:updateSetting on every value change (coerced server-side to the correct type, clamped where needed)
  • Checkboxes fire on toggle
  • Server persists with the read-merge-write pattern (preserves vehicleConfigs) and broadcasts updated config to all clients

Slider change frequency

Dragging a slider fires one event per step. With the step sizes chosen (5 for timeout, 500 for ms durations, 5 for beat anchor), a full drag produces ~100 events. This is intentional for live preview and stays well within FiveM's event-rate limits.


Player KVP overrides

Backed by tLib's KVP module. Keys are prefixed tafk::

KeyTypeDefaultSets when…
tafk:playerDisabledboolnot-set (→ enabled)Player toggles AFK System off in /tafk
tafk:musicboolnot-set (→ inherit)Player toggles Music
tafk:volumefloatnot-set (→ inherit)Player moves the Music Volume slider
tafk:hudHideboolnot-set (→ inherit)Player toggles Hide HUD While AFK
tafk:seqDisabledstring[] (JSON)[]Player unchecks a sequence in My Sequence Preferences

tafkGetSettings() in cl_bridge.lua layers these on top of the server-distributed values. tafkGetSequences(model) filters by tafk:seqDisabled.


Reloading after manual edits

data.json is read once at resource start. If you edit the file directly, restart the resource (restart tAFK from console) to apply changes. Audio files in the audio/ folder are also re-scanned on restart.

Invalid sequences are dropped with a warning log and never reach clients.

On this page

Need help?

Ask on Discord