MrPoulpi Labs
ox_target

Available scripts

FR
Documentation centre

Practical guides

Concrete ox_target tutorials — emote, shared emote, category, job interaction, external export, zone, model, custom revive/heal and secured server action.

Each guide gives the file to edit, a copyable example, the expected result and common mistakes. The resource, event and third-party export names used in the examples (my_pd, my_bank, my_hospital…) are fictional: replace them with those of your scripts. After every change to a config*.lua file, run restart ox_target.

Add an emote

File: config_interactions.lua, list Config.SelfInteractions.

{ name = 'emote_dance', menu = 'self_emotes', label = 'Dance', icon = 'fa-solid fa-music', type = 'emote', emote = 'dance' },

Result: “Dance” appears in the Self Emotes category. Common mistake: an emote name that does not exist in your emote script plays nothing, without any message.

Add a shared emote

File: config_interactions.lua, list Config.PlayerInteractions.

{ name = 'emote_hug2', menu = 'player_emotes', label = 'Hug (variant)', icon = 'fa-solid fa-heart', type = 'shared_emote', emote = 'hug2' },

Result: when targeting a player, Emotes › “Hug (variant)” runs nearby hug2, which sends the shared emote request to the closest player according to your emote script. Common mistake: the preset does not use the targeted player’s ID; to aim at that exact player, define the PlaySharedEmote(emote, targetServerId) hook.

Create a category

File: config_interactions.lua.

{ name = 'services', label = 'Services', icon = 'fa-solid fa-briefcase', type = 'category', opens = 'services_menu' },
{ name = 'call_taxi', menu = 'services_menu', label = 'Call a taxi', icon = 'fa-solid fa-taxi', type = 'command', command = 'taxi' },
{ name = 'call_mechanic', menu = 'services_menu', label = 'Call a tow truck', icon = 'fa-solid fa-wrench', type = 'command', command = 'towtruck' },

Result: a “Services” submenu with two commands. Common mistake: misspelled menu, the option never shows.

Job-restricted interaction

File: config_interactions.lua, list Config.PlayerInteractions.

{ name = 'pd_search', label = 'Search', icon = 'fa-solid fa-magnifying-glass', jobs = { police = 1 }, type = 'client_event', event = 'my_pd:search' },

Result: only police officers of grade 1 or higher see the option. Warning: jobs hides the option without securing the event. Your resource must check the job server side, or use a server action (last guide).

Call an external export

File: config_interactions.lua, list Config.VehicleInteractions.

{ name = 'open_glovebox', label = 'Glovebox', icon = 'fa-solid fa-box', type = 'export', resource = 'my_inventory', export = 'OpenGlovebox' },

Result: exports.my_inventory:OpenGlovebox(target) is called with the target object (netId, plate, entity…). Common mistake: the target resource is not started; F8 shows an error in the option.

Add a zone

File: config_interactions.lua, list Config.ZoneInteractions.

Config.ZoneInteractions = {
    {
        shape = 'box', name = 'cityhall_desk', coords = vec3(-544.9, -204.4, 38.2), size = vec3(1.4, 1.0, 2.0), rotation = 30,
        options = {
            { name = 'cityhall_papers', label = 'Request papers', icon = 'fa-solid fa-file-lines', type = 'client_event', event = 'my_cityhall:open' },
        },
    },
}

Result: a zone point appears when aiming at the desk; the option is available within Config.Distances.default (3 m). To place the zone, use Dev Tools › “Copy my coords” and enable debug = true while adjusting it. Common mistake: missing size for a box, or a poly shape (not handled here).

Interaction on a model

File: config_interactions.lua, list Config.ModelInteractions.

Config.ModelInteractions = {
    {
        models = { 'prop_atm_01', 'prop_atm_02', 'prop_atm_03', 'prop_fleeca_atm' },
        options = {
            { name = 'atm_use', label = 'Use the ATM', icon = 'fa-solid fa-money-bill', distance = 1.5, type = 'client_event', event = 'my_bank:openAtm' },
        },
    },
}

Result: ATMs get an outline and the option. To find a model name, use Dev Tools › “Copy prop name”.

Adapt revive and heal

Files: config.lua, then config_server.lua and config_client.lua.

  1. Set Config.MedicalScript = 'custom'.
  2. Plug your script in config_server.lua:
Config.ServerHooks.RevivePlayer = function(source, targetId)
    TriggerClientEvent('my_hospital:revive', targetId)
    return true
end

Config.ServerHooks.HealPlayer = function(source, targetId)
    TriggerClientEvent('my_hospital:heal', targetId)
end
  1. For self revive/heal (Config.Medical.selfMode = 'client'), in config_client.lua:
Config.ClientHooks.ReviveSelf = function()
    TriggerEvent('my_hospital:revive')
end

Config.ClientHooks.HealSelf = function()
    TriggerEvent('my_hospital:heal')
end

Result: the Admin › Revive / Heal and Self › Admin › Revive / Heal options use your script, with the revive, heal, selfRevive, selfHeal permissions. Common mistake: a RevivePlayer returning false shows the “no medical script configured” message. If your script already heals fully, set Config.Medical.nativeHealFallback to false.

Plug in a secured server action

Files: config_server.lua and config_interactions.lua.

Config.ServerActions = {
    give_fine = {
        permission  = 'everyone',
        jobs        = { police = 2 },
        target      = 'player',
        maxDistance = 3.0,
        cooldown    = 5000,
        args        = { { type = 'number', integer = true, min = 50, max = 5000 } },
        handler     = function(ctx)
            TriggerEvent('my_pd:fine', ctx.source, ctx.target, ctx.args[1])
            ctx.notify('Fine sent.', 'success')
            ctx.notifyTarget('You received a fine.', 'warning')
        end,
    },
}
{ name = 'give_fine', label = 'Fine $250', icon = 'fa-solid fa-receipt', jobs = { police = 2 }, type = 'server_action', action = 'give_fine', args = { 250 } },

Result: the server checks the job (grade 2 minimum), the targeted player’s existence and distance, the amount (integer from 50 to 5,000) and anti-spam before calling the handler. For an amount typed by the player, build args with a client-side function: args = function(target) … return { amount } end. Common mistake: forgetting jobs in the server definition; the option’s one only hides.

Search

Type a term: setting, export, error…