Switching from a target script
How to move a server from ox_target, qb-target or qtarget to lation interact, what each of the three bridges supports, and where bridged scripts behave differently.
lation interact lists ox_target, qb-target and qtarget as provide in its manifest and answers their exports itself. A script that calls exports.ox_target:addBoxZone(...) or exports['qb-target']:AddTargetModel(...) reaches lation interact with no edits, and a script that checks GetResourceState('ox_target') == 'started' sees it running.
Switching over
Stop or delete ox_target, qb-target or qtarget, and take its ensure line out of server.cfg. Two resources can't provide the same name.
Ensure lation_interact after your framework and before your inventory and every script that registers targets. See install for the order.
Restart the whole server, so every script registers its targets again.
Run /interact_debug in game. Under registrations, each script that used ox_target shows via ox, and each that used qb-target or qtarget shows via qb. A script missing from the list started too early.
Zones, single entities, models, every vehicle, ped, player or object, bones, job, gang and item checks, canInteract, events, server events, commands, qb-target's ped spawner, and cleanup when a script stops all carry over.
A script, unchanged
The same desk bell, as a script would register it with each target. Every one works as it is:
exports.ox_target:addBoxZone({
coords = vec3(441.2, -981.9, 30.7),
size = vec3(2.0, 1.0, 2.0),
rotation = 0.0,
options = {
{
name = 'ring_bell',
label = 'Ring the bell',
icon = 'fa-solid fa-bell',
groups = 'police',
distance = 2.0,
event = 'police:ringBell'
}
}
})exports['qb-target']:AddBoxZone('front_desk', vec3(441.2, -981.9, 30.7), 1.0, 2.0, {
name = 'front_desk',
heading = 0.0,
minZ = 29.7,
maxZ = 31.7
}, {
options = {
{ type = 'client', event = 'police:ringBell', icon = 'fas fa-bell', label = 'Ring the bell', job = 'police' }
},
distance = 2.0
})exports.qtarget:AddBoxZone('front_desk', vec3(441.2, -981.9, 30.7), 1.0, 2.0, {
name = 'front_desk',
heading = 0.0,
minZ = 29.7,
maxZ = 31.7
}, {
options = {
{ event = 'police:ringBell', icon = 'fas fa-bell', label = 'Ring the bell', job = 'police' }
},
distance = 2.0
})In game, each one is a single chip reading Ring the bell, shown to players with the police job when they look at the desk from within 2 m of it.
How bridged targets behave
One list per spot. Every bridged option becomes its own entry, and options on the same entity at the same bone (or with no bone) merge into one list. A zone becomes one entry carrying all its options.
No title. ox_target and qb-target options have no title, so none is invented. A bridged list shows without a header and its first option leads; a lone option is a single chip.

No keys of their own. Bridged options carry no key. On a list of several, E runs the first row, and the others are picked by holding Alt and clicking them. Titles, a key per option, holds, and notes or reasons on the row come with the native API.
Distances match the original. Both bridges gate each option at its own distance, 7.0 m when none is given, like the originals. Distance to an entity is measured to its bounding box, the way the originals measure to the point the aim lands on its surface. Distance to a zone is measured to its edge: exactly for a sphere, and for a box to the circle around its footprint, which is a little lenient on its faces.
Zones work from outside. A bridged zone goes live up to Config.Stages.reach (2.4 m) outside its shape, and never further than the zone's own distance. A zone wrapped around a desk or a small sphere on the floor can be used without standing inside it.
Zones reveal on focus. Bridged zones follow Config.Reveal.bridged, which is 'focus' by default: no point of light until the player looks at them. Set it to 'ambient' to give them one.
Passive by script. Config.PassiveResources applies to scripts that register through the bridges, escrowed ones included.
From a seat. An option with allowInVehicle = true stays live from inside a vehicle.
Vehicle doors. The built-in door toggles take the place of ox_target's default door options. They follow Config.VehicleDoors, not qb-target's Config.EnableDefaultOptions.
No targeting mode. There is no target eye and no held targeting state. Functions that report whether targeting is active return true while the player has a list open.
ox_target
Exports
| Export | Notes |
|---|---|
addGlobalVehicle, addGlobalPed, addGlobalPlayer, addGlobalObject | Options on every entity of that class. |
removeGlobalVehicle, removeGlobalPed, removeGlobalPlayer, removeGlobalObject | Removes by option name. |
addGlobalOption, removeGlobalOption | Registered on vehicles, peds, players and objects. Zones keep their own options. |
addModel, removeModel | Model names or hashes. A numeric string such as '123456789' stays that hash. removeModel without names clears every option on those models, from every resource, as in ox_target. |
addEntity, removeEntity | Network ids. The options come back when the entity streams in again. removeEntity without names clears everything on those entities, from every resource. |
addLocalEntity, removeLocalEntity | Entity handles. The options go when the entity stops existing. |
addSphereZone | radius defaults to 2.0. Returns the zone id. |
addBoxZone | size defaults to 2 x 2 x 2 when missing or unusable. rotation is honored. Returns the zone id. |
addPolyZone | Approximated as a sphere. See limits. Returns the zone id. |
removeZone | By zone id or zone name. |
zoneExists | By zone id or zone name. |
getTargetOptions | Returns the option tables scripts registered, keyed global, model, entity and localEntity. |
disableTargeting | true hides the whole layer until it is called with false. The debug report names the reason ox_target. |
isActive | true while the player has a list open. |
Zone coords take a vector3, a vector4 or a plain table, as ox_lib does. A zone with debug = true draws its volume.
Option fields
| Field | Notes |
|---|---|
label | Shows as Interact when missing. |
name | A second option with the same name from the same resource replaces the first in place. Used by the remove exports. |
icon | 'fa-solid fa-car', 'fas fa-car' or 'car'. Regular and brand styles render as solid icons. |
iconColor | Honored. |
distance | Defaults to 7.0. |
groups | Checked through bridge/client.lua, as a name, a list or { police = 2 }. |
items, anyItem | All of the items, or any of them with anyItem = true. |
canInteract | Called with ox_target's arguments: entity, distance, coords, name, bone. entity is 0 in zones and bone is the bone index. |
onSelect, export, event, serverEvent, command | The first one present runs, in that order, as in ox_target. |
bones | The option is placed at every listed bone the entity has. Of those, the one nearest the player's aim takes focus. |
offset, absoluteOffset | offset is a fraction of the model's bounds; with absoluteOffset = true it is a local offset. |
allowInVehicle | Keeps the option live from a seat. |
menu, menuName, openMenu | Nested menus are flattened. See limits. |
qtarget | onSelect gets the entity handle instead of the response table, as in ox_target. |
What handlers receive
onSelect, export and event handlers receive a copy of your option without its handler and check fields (icon, groups, items, anyItem, bones, canInteract, onSelect, export, event, serverEvent, command), plus:
| Field | Value |
|---|---|
entity | The entity handle, or 0 when there is none. A serverEvent gets the network id instead. |
coords | Where the player's aim met the entity, otherwise the interaction's own position. |
distance | Distance from the player, measured the same way as the distance check. |
zone | The zone id, for zone options. |
resource | The resource that registered the option. |
Events
ox_target:removeEntity
Client event
TriggerClientEvent('ox_target:removeEntity', target, netIds, names)Parameters
netIdsnumber | table- One network id or a list of them
namesstring | tableoptional- Option names to remove; all of them when left out
The same as removeEntity(netIds, names) on the client, so a server can push removals to clients, for example when it deletes an entity that had options.
TriggerClientEvent('ox_target:removeEntity', -1, NetworkGetNetworkIdFromEntity(crate))ox_target:toggleEntityDoor
Server event
TriggerServerEvent('ox_target:toggleEntityDoor', netId, door)Parameters
netIdnumber- The vehicle's network id
doornumber- 0 front driver door, 1 front passenger, 2 rear driver, 3 rear passenger, 4 hood, 5 trunk
Opens a shut door or shuts an open one, like the built-in door toggles. The server passes it to the game that controls the vehicle; a locked vehicle's doors don't move. The client event of the same name toggles the door on that client directly. lation_interact:toggleVehicleDoor does the same under lation interact's own name.
Limits
- Poly zones become a sphere around the center of their points, with a radius that reaches the furthest point and is at least half the zone's
thickness(4 when not set). The console notes this once. - Nested menus flatten into one list. Rows that only open a sub-menu and have no handler of their own are dropped. The console notes this once.
offsetSizehas no meaning here, since there is no crosshair that must land inside it.- No server side. The
hasTargetOptionsstatebag is never set, and there is no server-side sweep of deleted entities. getTargetOptionsis best effort: it returns the tables scripts registered, not live internal state.- Bad option tables are skipped with a console warning, where ox_target would raise an error.
- Network id options are re-applied when the entity streams back in, checked every 2 seconds. Options re-applied this way are owned by lation interact, so
Config.PassiveResourcesno longer applies to them.
qb-target
Exports
| Group | Exports |
|---|---|
| Zones | AddCircleZone, AddBoxZone, AddPolyZone, AddComboZone, AddEntityZone, RemoveZone |
| Bones | AddTargetBone, RemoveTargetBone |
| Entities | AddTargetEntity, RemoveTargetEntity |
| Models | AddTargetModel, RemoveTargetModel |
| Globals | AddGlobalType, AddGlobalPed, AddGlobalVehicle, AddGlobalObject, AddGlobalPlayer, RemoveGlobalType, RemoveGlobalPed, RemoveGlobalVehicle, RemoveGlobalObject, RemoveGlobalPlayer |
| Data | GetGlobalTypeData, GetZoneData, GetTargetBoneData, GetTargetEntityData, GetTargetModelData, GetGlobalPedData, GetGlobalVehicleData, GetGlobalObjectData, GetGlobalPlayerData, UpdateGlobalTypeData, UpdateZoneData, UpdateTargetBoneData, UpdateTargetEntityData, UpdateTargetModelData, UpdateGlobalPedData, UpdateGlobalVehicleData, UpdateGlobalObjectData, UpdateGlobalPlayerData |
| Peds | SpawnPed, RemoveSpawnedPed, DeletePeds, GetPeds, UpdatePedsData |
| Utilities | RaycastCamera, CheckBones, AllowTargeting, IsTargetActive, IsTargetSuccess |
| No effect | DisableTarget, DisableNUI, EnableNUI, LeftTarget, DrawOutlineEntity, CheckEntity |
RemoveType and RemoveGlobalTypeOptions also work, as aliases of RemoveGlobalType. qb-target's own docs name them but no qb-target release has them.
Options are stored the way qb-target stores them: keyed by label inside each container, by reference. Adding the same label again replaces it, Remove* removes by label or clears the container, and Get*Data returns the very table that was registered. Update* stores the table you give it as is.
Option fields
| Field | Notes |
|---|---|
label | Keys the option. Zone options may leave it out; it then shows as Interact. |
icon | 'fas fa-box', 'fa-solid fa-box' or 'box'. |
distance | Clamped to the registration's distance, which defaults to 7.0. |
job, excludejob | 'all', a job name, or { police = 2 } for a minimum grade. |
jobType, excludejobType | A job type, or a set of them. |
gang, excludegang | Same shapes as job. |
item, required_item | One item, or a list meaning all of them. |
citizenid | One citizen id, or a set of them. |
canInteract | Called with qb-target's arguments: entity, distance, data. |
action | Called with the entity. Runs instead of event when both are set. |
event, type | type is 'client' (the default), 'server', 'command' or 'qbcommand'. |
num | Orders options inside a zone. |
allowInVehicle | Keeps the option live from a seat. |
Job, gang and citizen id are read from the framework's player data through bridge/client.lua, cached for a second. Eye cosmetics such as targeticon, drawColor and drawDistance, and outlines, are ignored.
What handlers receive
The payload is the option table you registered, with entity (0 when there is none) and coords (the entity's position, or the zone's) set on every select, as in qb-target. action receives the entity. A 'server' event receives the table; a 'qbcommand' goes through QBCore:CallCommand.
Zones
| Export | Notes |
|---|---|
AddCircleZone(name, center, radius, options, targetoptions) | radius defaults to 2.0. |
AddBoxZone(name, center, length, width, options, targetoptions) | length runs along options.heading, width across it. options.minZ and options.maxZ bound the height; without both, the box is 10 m tall and centered on the center's z. |
AddPolyZone(name, points, options, targetoptions) | Approximated as a sphere with a radius of at least 2.0. |
AddComboZone(zones, options, targetoptions) | One sphere over the member zones' centers. Needs options.name. Skipped if no member exposes a center. |
AddEntityZone(name, entity, options, targetoptions) | A networked entity's zone comes back when it streams in again. |
RemoveZone(name) | By name. |
Adding a zone with a name that exists replaces it. The Add*Zone exports return the zone record, which has a destroy method. targetoptions.distance caps every option in the zone and defaults to 7.0. options.debugPoly draws the zone's volume. A zone center given in 2D takes the player's height when it is registered. A zone with no options is stored but does nothing, and the console says so.
Bones
AddTargetBone puts an option on every vehicle that has the bone. As in qb-target, only bones on qb-target's vehicle bone list show; others are stored and never shown. The list: chassis, windscreen, seat_pside_r, seat_dside_r, bodyshell, suspension_lm, suspension_lr, platelight, attach_female, attach_male, bonnet, boot, chassis_dummy, chassis_Control, door_dside_f, door_dside_r, door_pside_f, door_pside_r, Gun_GripR, windscreen_f, VFX_Emitter, window_lf, window_lr, window_rf, window_rr, engine, gun_ammo, ROPE_ATTATCH, wheel_lf, wheel_lr, wheel_rf, wheel_rr, exhaust, overheat, seat_dside_f, seat_pside_f, Gun_Nuzzle, seat_r.
Entities and globals
AddTargetEntity takes entity handles or raw network ids. Networked entities are tracked by network id and their options come back when they stream in again. Local entities are tracked by handle and their options go with the entity.
AddGlobalType takes 1 for peds, 2 for vehicles and 3 for objects. AddGlobalPed also matches player peds, as it does in qb-target.
Ped spawner
SpawnPed
Client export (qb-target)
exports['qb-target']:SpawnPed(data)Parameters
datatable- One ped, or a list of them
data.modelstring | number- The ped model
data.coordsvector4- Where it stands, and its heading
data.minusOnebooleanoptional- Lowers it by 1 m, for coordinates taken at a player's height
data.networkedbooleanoptionaldefaultfalse- Spawns a networked ped
data.freezebooleanoptional- Freezes it in place
data.invinciblebooleanoptional- Makes it invincible
data.blockeventsbooleanoptional- Stops it reacting to the world
data.animDictstringoptional- With
anim, an animation to play;flagsets its flags (1 when not set) data.scenariostringoptional- A scenario to play in place
data.pedrelationstableoptionalgroupname,toplayer,toowngroup: its relationship groupdata.weapontableoptionalname,ammo,hidden: a weapon to give itdata.targettableoptionaloptions,distance,useModel: options on the ped, or on its model withuseModel = truedata.actionfunctionoptional- Called with the ped's table once it has spawned
data.spawnNowbooleanoptional- Spawns it at once
A ped with spawnNow = true spawns at once. The rest spawn when the client event QBCore:Client:OnPlayerLoaded fires, and every spawned ped is deleted on QBCore:Client:OnPlayerUnload. ESX fires neither, so on ESX give each ped spawnNow = true.
exports['qb-target']:SpawnPed({
model = 'a_m_m_business_01',
coords = vec4(149.4, -1042.1, 29.4, 340.0),
minusOne = true,
freeze = true,
invincible = true,
blockevents = true,
scenario = 'WORLD_HUMAN_CLIPBOARD',
spawnNow = true,
target = {
options = {
{ type = 'client', event = 'bank:open', icon = 'fas fa-building-columns', label = 'Open the bank' }
},
distance = 2.0
}
})RemoveSpawnedPed(peds) deletes a ped handle or a list of them, DeletePeds() deletes every spawned ped, GetPeds() returns the list, and UpdatePedsData(index, data) replaces one entry.
Utilities
RaycastCamera
Client export (qb-target)
local endCoords, distance, entityHit, entityType = exports['qb-target']:RaycastCamera(flag, playerCoords)Parameters
flagnumberoptionaldefault-1- The shape test flags
playerCoordsvector3optional- Where to measure
distancefrom; the player's position when left out
Returns
vector3, number, number, number- Where a 16 m ray from the camera stopped, how far that is, the entity it hit (0 for none) and its type
A utility for scripts that call it; lation interact's own targeting doesn't use it.
CheckBones
Client export (qb-target)
local boneId, bonePos, boneName = exports['qb-target']:CheckBones(coords, entity, bonelist)Parameters
coordsvector3- The point to measure from
entitynumber- The entity whose bones to check
bonelisttable- Bone names to consider
Returns
number, vector3, string- The bone index, position and name of the bone from
bonelistnearestcoordsthat has options fromAddTargetBone, orfalsewhen there is none
AllowTargeting
Client export (qb-target)
exports['qb-target']:AllowTargeting(state)Parameters
statebooleanfalsehides the whole layer,trueshows it again
The layer stays hidden until the same call is made with true. The debug report names the reason qb-target. IsTargetActive() and IsTargetSuccess() return true while the player has a list open.
Limits
- Poly zones become a sphere around the center of their points. Combo zones become one sphere over their members. The console notes each once.
- Zone distance is measured to the shape's bounding surface, not the aim point: exact on spheres, a little lenient on box faces.
numorders options inside a zone. Across separate model or global registrations, registration order applies.- Default options follow
Config.VehicleDoors, not qb-target'sConfig.EnableDefaultOptions. DisableTarget,DisableNUIandEnableNUIdo nothing, since there is no target eye. UseAllowTargetingto hide the layer.- Network id options are re-applied when the entity streams back in, checked every 2 seconds. Options re-applied this way are owned by lation interact, so
Config.PassiveResourcesno longer applies to them.
qtarget
The qtarget exports run through the qb-target bridge, so they take qb-target's option shape (job, item or required_item, canInteract, action, or event with type). They share its registries: a zone added through qtarget can be removed through qb-target.
| Group | Exports |
|---|---|
| Zones | AddCircleZone, AddBoxZone, AddPolyZone, AddEntityZone, RemoveZone |
| Bones | AddTargetBone, RemoveTargetBone |
| Entities | AddTargetEntity, RemoveTargetEntity |
| Models | AddTargetModel, RemoveTargetModel |
| Globals | Ped, Vehicle, Object, Player, RemovePed, RemoveVehicle, RemoveObject, RemovePlayer |
Calling them on lation_interact
Every ox_target and qb-target export above can also be called as exports.lation_interact:<name>. The qtarget names can't.
Some ox_target names are also native exports: addEntity, addModel, addGlobalVehicle, addGlobalPed, addGlobalPlayer, addGlobalObject and removeEntity. lation interact tells the two apart by what you pass. For the add exports, a table with an options field is a native registration, and a single option or a list of options is an ox_target one. For removeEntity, a lation interact id with no names removes that registration, and anything else is treated as ox_target's removeEntity(netIds, names). See developers.
Still stuck? Ask in our Discord: the people who write the scripts answer.
Last updated
Players
What players see with lation interact, from the point of light to the open list, and how they use it, by looking and pressing a key or by holding Alt and clicking.
Configuration
Every option in lation interact's config.lua with its default value, plus the theme it takes from lation ui, the language convar and the open files you can edit.