Intégration et exports
Ajouter des options depuis tes scripts : tcmenu, exports, événements, compatibilité ox_target / qb-target.
Il y a trois façons d'ajouter des options :
| Façon | Pour qui | Permanent |
|---|---|---|
/gestioncontexte (onglet Options) | L'admin, sans toucher au code | Oui (base) |
Config.Options dans config.lua | Celui qui préfère un fichier | Oui (relu à chaque démarrage) |
| Dans le code d'un script | Le développeur du script | Tant que le script tourne |
#Dans un script : la méthode la plus simple
shared_script '@tc-contextmenu/init.lua'tcmenu.add({
label = 'Fouiller', icon = 'search', types = { 'player' }, distance = 2.5,
require = { jobs = { police = 0 } },
onSelect = function(ctx) TriggerServerEvent('monscript:fouiller', ctx.serverId) end,
})Si tc-contextmenu est absent ou démarre après ton script, les appels sont mis en attente puis rejoués (aussi s'il redémarre). Les options disparaissent quand ton script s'arrête.
#Fonctions de tcmenu
| Côté | Fonctions |
|---|---|
| Client | add, addMany, addModel, addGlobal, addGlobalPlayer / Ped / Vehicle / Object / Self / World, addLocalEntity, addEntity, addSphereZone, addBoxZone, remove, removeZone, open, close, isOpen, disable |
| Serveur | register, unregister, addOption, removeOption, getOptions |
tcmenu.ready() indique si tc-contextmenu est démarré.
#Champs d'une option par code
| Champ | Rôle |
|---|---|
key | Clé unique (finale : <ta_ressource>:<key>) |
label | Texte (ou fonction function(ctx) return '…' end) |
icon | Nom d'icône, emoji ou URL d'image |
types | { 'player', 'ped', 'vehicle', 'object', 'world', 'self' } |
models | Modèles ciblés (noms ou hash) |
distance | Distance maximale |
require | { jobs = { police = 0 }, items = { gant = 1 }, admin = true, ace = '…', inVehicle = true, onDuty = true } |
canInteract | function(ctx) return true end — condition dynamique |
onSelect | function(ctx) — action Lua |
type, parent | submenu / separator, et clé du sous-menu parent |
#Sous-menu et conditions
tcmenu.add({ key = 'police', type = 'submenu', label = 'Police', icon = 'shield', types = { 'player' },
require = { jobs = { police = 0 } } })
tcmenu.add({ parent = 'police', label = 'Menotter', icon = 'lock', types = { 'player' },
canInteract = function(ctx) return not IsPedCuffed(ctx.entity) end,
onSelect = function(ctx) TriggerServerEvent('monscript:menotter', ctx.serverId) end })#Libellé dynamique et condition d'objet
tcmenu.add({
label = function(ctx) return ('Fouiller la poubelle (%s)'):format(ctx.model) end,
types = { 'object' }, models = { 'prop_bin_01a', 'prop_dumpster_01a' },
require = { items = { gant = 1 } }, -- vérifié côté serveur
onSelect = function(ctx) print('poubelle', ctx.entity) end,
})#Sans écrire de fonction
tcmenu.add({ label = 'Parler', types = { 'ped' }, serverEvent = 'monscript:parler', args = { sujet = 'rumeur' } })
tcmenu.add({ label = 'Appeler', types = { 'player' }, command = 'phone' })
tcmenu.add({ label = 'Ouvrir', types = { 'vehicle' }, export = 'monscript.ouvrir' }) -- client : (ctx, args)
tcmenu.add({ label = 'Saisir', types = { 'vehicle' }, serverExport = 'monscript.saisir' }) -- serveur : (src, ctx, args)#Compatible ox_target et qb-target
Remplace exports.ox_target ou exports['qb-target'] par exports['tc-contextmenu'] : mêmes fonctions, mêmes champs.
Fonctions : addModel, addEntity (netId), addLocalEntity, addGlobalPlayer / Ped / Vehicle / Object, addSphereZone, addBoxZone, removeZone, removeModel…
Champs : label, icon (le format fa-solid fa-car est accepté), distance, groups, items, canInteract(entity, distance, coords, name), onSelect(data), export, event, serverEvent, command.
exports['tc-contextmenu']:addGlobalVehicle({
{ label = 'Réparer', icon = 'fa-solid fa-wrench', groups = { mechanic = 0 }, event = 'monscript:reparer' },
})Fonctions : AddTargetModel, AddTargetEntity, AddGlobalPlayer / Ped / Vehicle / Object, AddCircleZone, AddBoxZone, RemoveZone, RemoveTargetModel…
Champs : label, icon, event, type, job, item, action(entity), canInteract, et la forme { options = {...}, distance = 2.5 }.
Les zones sont sphériques (une boîte devient une sphère englobante) et les os (bones) sont ignorés.
#Sans aucune dépendance
TriggerEvent('tc-contextmenu:add', { label = 'Fouiller', types = { 'player' }, serverEvent = 'monscript:fouiller' }, GetCurrentResourceName())
TriggerEvent('tc-contextmenu:remove', 'fouiller', GetCurrentResourceName())#Depuis un script serveur
-- non persistant, retiré à l'arrêt du script
exports['tc-contextmenu']:register({ label = 'Parler', types = { 'ped' }, serverEvent = 'monscript:parler' })
-- PERMANENT, 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' } },
})
-- aussi : TriggerEvent('tc-contextmenu:server:register', def, 'ma_ressource')#Référence des exports
| Côté | Exports |
|---|---|
| Client | add, addMany, remove, open, close, isOpen, disable(true|false), + les noms ox_target / qb-target ci-dessus |
| Serveur | register, unregister, addOption, removeOption, getOptions |
#Exemple complet (par code)
Un fichier d'exemples (examples/examples.lua) est fourni avec le script ; il n'est pas chargé par le manifeste, copie ce dont tu as besoin :
-- 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' } },
-- })