API Reference
Exports, events, state bags, and server-side admin events for integrating with tAFK.
Client exports
All exports live on exports['tAFK'] and operate on the local player.
IsAFK
Returns whether the local player is currently in the AFK cinematic.
local afk = exports['tAFK']:IsAFK()
-- true | falseNo parameters. Reflects real-time state — true from the moment the fade-in completes to the moment any input exits.
StartAFK
Triggers AFK manually on the local player. Equivalent to /afk when already valid.
local started = exports['tAFK']:StartAFK()
-- true — entered AFK (will fade in over 1s)
-- false — system disabled or not in a vehicleSets the internal manualAFK flag, which bypasses the idle-input sensitivity during fade-in (so the user's mouse movement from triggering the command doesn't instantly cancel).
StopAFK
Exits AFK immediately. No-op if not currently AFK.
exports['tAFK']:StopAFK()Returns nothing. Fires tafk:stateChanged(false) and clears the state bag.
ToggleAFK
local isAfkNow = exports['tAFK']:ToggleAFK()
-- true — was off, now on
-- false — was on, now off; OR system disabled / no vehicleDoes the right thing based on current state. Fires the appropriate event and state-bag write.
IsAFKEnabled
local enabled = exports['tAFK']:IsAFKEnabled()
-- true | falseReflects the session enable state, which respects the player's persistent tafk:playerDisabled KVP at boot. Different from IsAFK() — IsAFKEnabled says whether the system can trigger; IsAFK says whether it is triggering.
SetAFKEnabled
local ok = exports['tAFK']:SetAFKEnabled(false) -- suppress tAFK for this session
-- true on valid input; false if arg isn't a booleanSession-only switch. Pass false to disable auto and manual triggers and stop an in-progress cinematic. Pass true to re-enable. Does not persist to KVP — for persistent player preferences, use the /tafk dialog.
Client events
tafk:stateChanged
Fires on the local client every time AFK state changes.
AddEventHandler('tafk:stateChanged', function(isAfk)
if isAfk then
-- entering AFK
else
-- leaving AFK
end
end)Single argument: boolean. Fires before the state bag is written, so handlers see the new local state but remote clients may not yet have received the bag update.
Cross-client awareness — use the state bag
tafk:stateChanged is a local event on one client only. To react to another player's AFK status, read Player(src).state.afk or subscribe to the state-bag change handler.
State bags
LocalPlayer.state.afk
Replicated player-state bag, set on AFK enter/exit and on resource start:
-- Set internally by tAFK — do not write from other scripts
LocalPlayer.state:set('afk', true, true)Readable from any client or the server:
-- Client, any other client
local ok = Player(playerServerId).state.afk -- true | false | nil
-- Server
local ok = Player(source).state.afk
-- State-bag change handler (any script)
AddStateBagChangeHandler('afk', nil, function(bagName, key, value, reserved, replicated)
local playerId = GetPlayerFromStateBagName(bagName)
-- playerId is the server ID; handle transitions
end)nil means the player hasn't loaded tAFK yet (e.g., disconnected or resource not started). Treat nil as "not AFK" for most purposes.
Server-side admin events
All admin events are registered via exports['tLib']:RegisterAdminEvent(...), which gates on the tlib.admin ACE before the handler runs. Non-admins can trigger these events but the handler returns immediately.
Admin menus fire these from the client, but external scripts can too.
tafk:admin:updateSetting
TriggerServerEvent('tafk:admin:updateSetting', key, value)
-- key: 'timeoutSeconds' | 'minDurationMs' | 'maxDurationMs' | 'beatAnchorMs'
-- | 'musicVolume' | 'useMusic' | 'hideHudInAFK'
-- value: coerced to the expected type server-sideUnknown keys log a warning and no-op.
tafk:admin:upsertSequence
Create or update a global sequence.
TriggerServerEvent('tafk:admin:upsertSequence', {
id = 'custom_hero_shot',
name = 'Hero Shot',
enabled = true,
vehicles = { '*' },
start = { offset = { x = 0, y = 4, z = 1 }, rotation = { x = 0, y = 0, z = 180 }, fov = 45, dof = {...} },
['end'] = { ... },
})If an entry with the same id exists, it's replaced. Otherwise appended. Validated via tafkValidateSequence — failures toast back to the admin with the specific error.
tafk:admin:upsertVehicleSequence
Same as above but written into data.json.vehicleConfigs[<model>].sequences via the Discovery instance.
TriggerServerEvent('tafk:admin:upsertVehicleSequence', 'bati801', seqObject)tafk:admin:toggleSequence, tafk:admin:deleteSequence
TriggerServerEvent('tafk:admin:toggleSequence', 'seed_01', false) -- disable
TriggerServerEvent('tafk:admin:deleteSequence', 'seed_01') -- permanentNo music track events
Music is discovered from the audio/ folder at resource start (see Configuration → Music tracks). There are no register/toggle/delete events — drop files into audio/ and restart the resource.
Client config events
tafk:request_config
Client → server. Triggers the server to send its current config to this client. Useful if your script loads late.
TriggerServerEvent('tafk:request_config')
-- server replies with TriggerClientEvent('tafk:config_receive', src, mergedData)tafk:config_receive
Server → client. Carries the full data.json contents.
RegisterNetEvent('tafk:config_receive', function(data)
-- data = { version, settings, sequences, musicTracks, ... }
end)tAFK registers this internally — only subscribe from another resource if you need to mirror the config.
tafk:vcfg:config_receive
Per-vehicle configs from Discovery. Payload is { [model] = { sequences = [...] } }.
RegisterNetEvent('tafk:vcfg:config_receive', function(vehicleConfigs)
-- keyed by lowercase model name
end)Auto-requested on resource start via tafk:vcfg:config_request.
Deprecation note
If you're upgrading from the legacy tommys-afk resource:
| Old | New |
|---|---|
exports['tommys-afk']:IsAFK() | exports['tAFK']:IsAFK() |
exports['tommys-afk']:StartAFK() | exports['tAFK']:StartAFK() |
AddEventHandler('tommys-afk:stateChanged', ...) | AddEventHandler('tafk:stateChanged', ...) |
| (none) | Player(src).state.afk |
The resource name, all export names, and the event name changed. Update any integration code — there's no compatibility shim.
