ox_target addBoxZone, addModel and addLocalEntity: how to add targets
How to add ox_target interactions in FiveM: addBoxZone, addSphereZone, addModel, addLocalEntity and addGlobalVehicle, with options, groups, removal and debug.
You add a target in your script and in game nothing shows up. Or the console says:
No such export addBoxZone in resource ox_targetThis is the practical guide to ox_target on the client: the zone, model and entity exports, the options you can put on them, and how to remove and debug them.
Make sure ox_target is started first
The exports only exist while ox_target is running, and it needs ox_lib. In server.cfg, start them before your script:
ensure oxmysql
ensure ox_lib
ensure ox_target
ensure my_scriptAlso add it to your resource's fxmanifest.lua, so FiveM refuses to start the script without it:
dependency 'ox_target'All the calls below are client side. Put them in a client file, not a server one.
A box zone
A box zone is a rectangle in the world. It is the right choice for a counter, a door or an ATM:
local zoneId = exports.ox_target:addBoxZone({
coords = vec3(441.2, -981.9, 30.7),
size = vec3(1.5, 1.0, 2.0),
rotation = 90.0,
debug = false,
options = {
{
name = 'my_script_counter',
icon = 'fa-solid fa-box',
label = 'Open the counter',
distance = 2.0,
onSelect = function(data)
print('selected', data.name)
end,
},
},
})coords is the centre of the box, size is its width, length and height, and rotation turns it around the vertical axis. Keep the returned zoneId if you will remove the zone later.
A sphere zone
A sphere is simpler when you do not care about the shape, only about "near this point":
exports.ox_target:addSphereZone({
coords = vec3(-1037.5, -2737.9, 20.2),
radius = 1.5,
options = {
{
name = 'my_script_sphere',
icon = 'fa-solid fa-hand',
label = 'Talk',
onSelect = function()
print('talking')
end,
},
},
})Models, entities and vehicles
To target every object, ped or vehicle of a certain model, use addModel. It takes a model name or hash, or a list of them:
exports.ox_target:addModel({ `prop_vend_soda_01`, `prop_vend_soda_02` }, {
{
name = 'my_script_vending',
icon = 'fa-solid fa-bottle-water',
label = 'Use the machine',
distance = 1.5,
onSelect = function(data)
print('entity', data.entity)
end,
},
})To target one entity you already created on your client, use addLocalEntity:
local ped = CreatePed(4, `a_m_m_business_01`, 441.2, -981.9, 29.7, 90.0, false, true)
exports.ox_target:addLocalEntity(ped, {
{
name = 'my_script_ped',
icon = 'fa-solid fa-comment',
label = 'Talk to him',
onSelect = function(data)
print('talk to', data.entity)
end,
},
})To add an option to every vehicle, use addGlobalVehicle. Other global exports exist for peds, players and objects:
exports.ox_target:addGlobalVehicle({
{
name = 'my_script_inspect',
icon = 'fa-solid fa-magnifying-glass',
label = 'Inspect vehicle',
distance = 2.5,
onSelect = function(data)
print('vehicle', data.entity)
end,
},
})Tip:
addLocalEntityonly exists on the client that created the entity. For a networked entity that other players should see the option on, use the networked variant (addEntity) with the entity's network id.
The option fields
Each option is a table. These are the fields you will use most:
| Field | What it does |
|---|---|
name |
A unique name. Needed to remove the option later. |
icon |
A Font Awesome class, like fa-solid fa-box. |
label |
The text shown to the player. |
onSelect |
Function called when the player picks the option. |
distance |
How close the player must be, in metres. |
canInteract |
Function that returns true to show the option. |
groups |
Job or group needed to see the option. |
canInteract receives the entity and the distance, so you can hide an option based on any condition:
{
name = 'my_script_repair',
icon = 'fa-solid fa-wrench',
label = 'Repair',
distance = 2.0,
canInteract = function(entity, distance, coords, name, bone)
return GetVehicleEngineHealth(entity) < 900.0
end,
onSelect = function(data)
print('repair', data.entity)
end,
}For jobs, groups takes a name or a table, and works on ESX, QBCore and QBox through ox_target's own framework support:
groups = 'police',
-- or several, optionally with a minimum grade
groups = { police = 0, sheriff = 2 },Remove zones and options
Zones are removed with the id the call returned:
exports.ox_target:removeZone(zoneId)Options added to models, entities and global targets are removed by the name you gave them:
exports.ox_target:removeModel({ `prop_vend_soda_01` }, 'my_script_vending')
exports.ox_target:removeLocalEntity(ped, 'my_script_ped')
exports.ox_target:removeGlobalVehicle('my_script_inspect')Clean up when your resource stops, otherwise a restart can leave duplicates behind:
AddEventHandler('onResourceStop', function(resource)
if resource ~= GetCurrentResourceName() then return end
exports.ox_target:removeZone(zoneId)
exports.ox_target:removeLocalEntity(ped, 'my_script_ped')
end)Debug a zone that does not show
Set debug = true on the zone. ox_target then draws its shape in the world, so you see at once if the box is in the wrong place, too small, or buried in the floor. The usual causes:
- The zone is misplaced. The
coordsare the centre, so a box whose z sits at floor level is half underground. Raise it by half its height. - The distance is too small. The player has to be inside
distanceof the zone to see the option. - A check fails. A
groupsorcanInteractthat returns false hides the option with no error. Temporarily remove it to test. - Two targets are running. If qb-target is started as well, see qb-target vs ox_target.
By default you hold a key (Left Alt) to open the targeting eye, so test with it held down.
Checklist
| Symptom | Fix |
|---|---|
No such export addBoxZone in resource ox_target |
Start ox_target (and ox_lib) before your script |
| Option never shows | Turn on debug = true, check distance, groups and canInteract |
| Zone is half underground | coords is the centre: raise z by half the box height |
| Option shows for everyone | Add groups or a canInteract check |
| Duplicates after restarting your script | Remove zones and options in onResourceStop |
| Need to remove one option | Give it a name and call the matching remove... export |
Quick answers
How do I add an ox_target zone from my own script?
Call exports.ox_target:addBoxZone({ coords = ..., size = ..., rotation = ..., options = { ... } }) on the client. It returns an id that you keep so you can remove the zone later.
How do I show an option only to some jobs?
Use groups on the option, for example groups = 'police', or a table for several jobs. For anything more specific, return true or false from canInteract.
Why does my target not appear?
Usually the player is outside the option's distance, a groups or canInteract check fails, or ox_target is not started before your script. Turn on debug = true on the zone to see its shape.
Scripts that skip this problem
Shop CreatorBuild a shop in under a minute β owners, employees, vaults and robberies included.View script β
Quest CreatorA visual editor for quests and NPC dialogues, built node by node in game.View script β
Item Creator V2Create usable items with animations, props, effects and more β without writing code.View script β