TC ScriptDocumentation

Integration and exports

Add options from your scripts: tcmenu, exports, events, ox_target / qb-target compatibility.

There are three ways to add options:

WayFor whomPermanent
/gestioncontexte (Options tab)The admin, without touching codeYes (database)
Config.Options in config.luaWhoever prefers a fileYes (reloaded at every start)
In a script's codeThe script developerAs long as the script runs

#In a script: the simplest method

fxmanifest.lua
shared_script '@tc-contextmenu/init.lua'
client.lua
tcmenu.add({
    label = 'Search', icon = 'search', types = { 'player' }, distance = 2.5,
    require = { jobs = { police = 0 } },
    onSelect = function(ctx) TriggerServerEvent('myscript:search', ctx.serverId) end,
})
tcmenu never crashes

If tc-contextmenu is missing or starts after your script, calls are queued then replayed (also if it restarts). Options disappear when your script stops.

#tcmenu functions

SideFunctions
Clientadd, addMany, addModel, addGlobal, addGlobalPlayer / Ped / Vehicle / Object / Self / World, addLocalEntity, addEntity, addSphereZone, addBoxZone, remove, removeZone, open, close, isOpen, disable
Serverregister, unregister, addOption, removeOption, getOptions

tcmenu.ready() tells whether tc-contextmenu is started.

#Fields of a code option

FieldRole
keyUnique key (final: <your_resource>:<key>)
labelText (or function function(ctx) return '…' end)
iconIcon name, emoji or image URL
types{ 'player', 'ped', 'vehicle', 'object', 'world', 'self' }
modelsTargeted models (names or hashes)
distanceMaximum distance
require{ jobs = { police = 0 }, items = { glove = 1 }, admin = true, ace = '…', inVehicle = true, onDuty = true }
canInteractfunction(ctx) return true end — dynamic condition
onSelectfunction(ctx) — Lua action
type, parentsubmenu / separator, and key of the parent submenu
Lua
tcmenu.add({ key = 'police', type = 'submenu', label = 'Police', icon = 'shield', types = { 'player' },
             require = { jobs = { police = 0 } } })
tcmenu.add({ parent = 'police', label = 'Handcuff', icon = 'lock', types = { 'player' },
             canInteract = function(ctx) return not IsPedCuffed(ctx.entity) end,
             onSelect = function(ctx) TriggerServerEvent('myscript:cuff', ctx.serverId) end })

#Dynamic label and item condition

Lua
tcmenu.add({
    label = function(ctx) return ('Search the bin (%s)'):format(ctx.model) end,
    types = { 'object' }, models = { 'prop_bin_01a', 'prop_dumpster_01a' },
    require = { items = { glove = 1 } },           -- checked server-side
    onSelect = function(ctx) print('bin', ctx.entity) end,
})

#Without writing a function

Lua
tcmenu.add({ label = 'Talk',  types = { 'ped' },     serverEvent = 'myscript:talk', args = { topic = 'rumor' } })
tcmenu.add({ label = 'Call',  types = { 'player' },  command = 'phone' })
tcmenu.add({ label = 'Open',  types = { 'vehicle' }, export = 'myscript.open' })          -- client: (ctx, args)
tcmenu.add({ label = 'Seize', types = { 'vehicle' }, serverExport = 'myscript.seize' })   -- server: (src, ctx, args)

#ox_target and qb-target compatible

Replace exports.ox_target or exports['qb-target'] with exports['tc-contextmenu']: same functions, same fields.

Functions: addModel, addEntity (netId), addLocalEntity, addGlobalPlayer / Ped / Vehicle / Object, addSphereZone, addBoxZone, removeZone, removeModel…

Fields: label, icon (the fa-solid fa-car format is accepted), distance, groups, items, canInteract(entity, distance, coords, name), onSelect(data), export, event, serverEvent, command.

Lua
exports['tc-contextmenu']:addGlobalVehicle({
    { label = 'Repair', icon = 'fa-solid fa-wrench', groups = { mechanic = 0 }, event = 'myscript:repair' },
})
Limits

Zones are spherical (a box becomes an enclosing sphere) and bones (bones) are ignored.

#With no dependency at all

Lua
TriggerEvent('tc-contextmenu:add', { label = 'Search', types = { 'player' }, serverEvent = 'myscript:search' }, GetCurrentResourceName())
TriggerEvent('tc-contextmenu:remove', 'search', GetCurrentResourceName())

#From a server script

Lua
-- not persistent, removed when the script stops
exports['tc-contextmenu']:register({ label = 'Talk', types = { 'ped' }, serverEvent = 'myscript:talk' })

-- PERMANENT, in the database (editable with /gestioncontexte)
exports['tc-contextmenu']:addOption({
    key = 'ped_talk', label = 'Talk', icon = 'phone',
    target = { types = { 'ped' } }, distance = 3.0,
    action = { type = 'server_event', name = 'myscript:talk', args = { topic = 'rumor' } },
})

-- also: TriggerEvent('tc-contextmenu:server:register', def, 'my_resource')

#Exports reference

SideExports
Clientadd, addMany, remove, open, close, isOpen, disable(true|false), + the ox_target / qb-target names above
Serverregister, unregister, addOption, removeOption, getOptions

#Full example (by code)

An examples file (examples/examples.lua) ships with the script; it is not loaded by the manifest, copy what you need:

examples/examples.luaDownload
-- Exemples d'options ajoutées PAR CODE (client). À copier dans ton propre script, ce fichier n'est pas chargé par le manifest.
-- Les options sont retirées automatiquement quand ta ressource s'arrête.
local CM = exports['tc-contextmenu']

-- 1. Bouton simple sur les véhicules, avec callback Lua
CM:add({
    key = 'veh_lock',                       -- clé finale : "<ta_ressource>:veh_lock"
    label = 'Verrouiller / déverrouiller',
    icon = 'lock',
    target = { types = { 'vehicle' } },
    distance = 5.0,
    onSelect = function(ctx)
        local lock = GetVehicleDoorLockStatus(ctx.entity)
        SetVehicleDoorsLocked(ctx.entity, lock == 2 and 1 or 2)
    end,
})

-- 2. Sous-menu + enfants, réservés à un métier
CM:add({ key = 'police', type = 'submenu', label = 'Police', icon = 'shield', target = { types = { 'player' } },
         require = { jobs = { police = 0 } } })
CM:add({ parent = 'police', label = 'Fouiller', icon = 'search', target = { types = { 'player' } },
         onSelect = function(ctx) TriggerServerEvent('monscript:fouiller', ctx.serverId) end })
CM:add({ parent = 'police', label = 'Menotter', icon = 'lock', target = { types = { 'player' } },
         canInteract = function(ctx) return not IsPedCuffed(ctx.entity) end,         -- condition dynamique
         onSelect = function(ctx) TriggerServerEvent('monscript:menotter', ctx.serverId) end })

-- 3. Libellé dynamique + condition d'objet (vérifiée côté serveur) sur un modèle précis
CM:add({
    label = function(ctx) return ('Fouiller la poubelle (%s)'):format(ctx.model) end,
    target = { types = { 'object' }, models = { 'prop_bin_01a', 'prop_dumpster_01a' } },
    require = { items = { gant = 1 } },
    onSelect = function(ctx) print('poubelle', ctx.entity) end,
})

-- 4. Option PERMANENTE créée depuis un script serveur (stockée en base, modifiable avec /gestioncontexte) :
--   exports['tc-contextmenu']:addOption({
--       key = 'pnj_parler', label = 'Parler', icon = 'phone',
--       target = { types = { 'ped' } }, distance = 3.0,
--       action = { type = 'server_event', name = 'monscript:parler', args = { sujet = 'rumeur' } },
--   })
Last updated : 7 November 2026© 2026 TC Script