ox_target Reference
A performant and flexible standalone targeting resource or third-eye, with additional functionality for Cfx.re.
Target Options
- label:
string - name?:
string -
- An identifier used when removing an option.
- icon?:
string -
- Name of a Font Awesome icon.
- iconColor?:
string - distance?:
number -
- The max distance to display the option.
- bones?:
stringorstring[] -
- A bone name or array of bone names (see GetEntityBoneIndexByName).
- offset?:
vector3 -
- Offset the targetable area of an entity, relative to the model dimensions.
- offsetAbsolute?:
vector3 -
- Offset the targetable area of an entity, relative to the entity's world coords.
- offsetSize?:
number -
- The radius of the targetable area for an entity offset.
- groups?:
stringorstring[]ortable<string, number> -
- A group, array of groups, or pairs of groups-grades required to show the option.
-
- Groups are framework dependent, and may refer to jobs, gangs, etc.
- items?:
stringorstring[]ortable<string, number> -
- An item, array of items, or pairs of items-count required to show the option.
-
- Items are framework dependent.
- anyItem?:
boolean -
- Only require a single item from the items table to exist.
- canInteract?:
function(entity, distance, coords, name, bone) -
- Options will always display if this is undefined.
- menuName?:
string -
- The option is only displayed when a menu has been set with openMenu.
- openMenu?: string
-
- Sets the current menu name, displaying only options for the menuName.
- onSelect?:
function(data) - export?:
string - event?:
string - serverEvent?:
string - command?:
string
Overview
ox_target (previously known as qtarget) is a performant and flexible targeting resource for RedM. It allows players to interact with entities, zones, and models using a "third-eye" targeting system.
ox_target is already included and used extensively in RSG Framework resources!
Installation
ox_target is already included in RSG Framework. To use it in your custom resources:
dependencies {
'ox_target'
}Entity Targeting
addEntity
Add targeting options to a specific entity.
exports.ox_target:addEntity(entity, options)Parameters:
entity(number) - The entity handleoptions(table) - Array of target options
Example:
local npc = CreatePed(model, coords.x, coords.y, coords.z, heading, true, false, false, false)
exports.ox_target:addEntity(npc, {
{
label = 'Talk to Shopkeeper',
icon = 'fa-solid fa-comments',
distance = 2.5,
onSelect = function(data)
print('Talking to shopkeeper')
-- Open shop menu
end
},
{
label = 'Rob Shopkeeper',
icon = 'fa-solid fa-mask',
distance = 2.0,
canInteract = function(entity, distance, coords, name, bone)
local Player = RSGCore.Functions.GetPlayerData()
return Player.job.name ~= 'vallaw'
end,
onSelect = function(data)
-- Trigger robbery
TriggerEvent('robbery:client:start')
end
}
})removeEntity
Remove targeting options from a specific entity.
exports.ox_target:removeEntity(entity, optionNames)Parameters:
entity(number) - The entity handleoptionNames(string|table|nil) - Specific option names to remove, or nil to remove all
Example:
-- Remove specific option
exports.ox_target:removeEntity(npc, 'talk_option')
-- Remove all options
exports.ox_target:removeEntity(npc)Model Targeting
addModel
Add targeting options to all entities with specific models.
exports.ox_target:addModel(models, options)Parameters:
models(string|number|table) - Model hash(es) or name(s)options(table) - Array of target options
Example:
-- Target all hitching posts
exports.ox_target:addModel(`P_HITCHINGPOST01X`, {
{
label = 'Hitch Horse',
icon = 'fa-solid fa-horse',
distance = 3.0,
canInteract = function(entity, distance, coords, name, bone)
-- Check if player is on a horse
return IsPedOnMount(PlayerPedId())
end,
onSelect = function(data)
TriggerEvent('horses:client:hitchHorse', data.entity)
end
}
})
-- Multiple models
exports.ox_target:addModel({
`P_HITCHINGPOST01X`,
`P_HITCHINGPOST02X`,
`P_HITCHINGPOST03X`
}, {
{
label = 'Hitch Horse',
icon = 'fa-solid fa-horse',
distance = 3.0,
onSelect = function(data)
TriggerEvent('horses:client:hitchHorse', data.entity)
end
}
})removeModel
Remove targeting options from models.
exports.ox_target:removeModel(models, optionNames)Parameters:
models(string|number|table) - Model hash(es) or name(s)optionNames(string|table|nil) - Option names to remove, or nil for all
Example:
exports.ox_target:removeModel(`P_HITCHINGPOST01X`)Zone Targeting
addBoxZone
Add a box-shaped targeting zone.
exports.ox_target:addBoxZone(name, coords, size, rotation, options, targetoptions)Parameters:
name(string) - Unique zone identifiercoords(vector3) - Center coordinatessize(vector3) - Box dimensions (length, width, height)rotation(number) - Rotation in degreesoptions(table) - Array of target optionstargetoptions(table) - Additional zone settings
Example:
exports.ox_target:addBoxZone('valentine_bank', vector3(-308.36, 775.58, 118.70), vector3(2.0, 2.0, 2.0), 0, {
{
label = 'Access Bank',
icon = 'fa-solid fa-piggy-bank',
onSelect = function()
TriggerEvent('rsg-banking:client:openBank', 'valentine')
end
}
})addSphereZone
Add a sphere-shaped targeting zone.
exports.ox_target:addSphereZone(name, coords, radius, options, targetoptions)Parameters:
name(string) - Unique zone identifiercoords(vector3) - Center coordinatesradius(number) - Sphere radiusoptions(table) - Array of target optionstargetoptions(table) - Additional zone settings
Example:
exports.ox_target:addSphereZone('butcher_shop', vector3(-301.12, 800.34, 118.90), 2.5, {
{
label = 'Sell Meat',
icon = 'fa-solid fa-meat',
canInteract = function()
return exports['rsg-inventory']:HasItem(source, 'meat')
end,
onSelect = function()
TriggerServerEvent('butcher:server:sellMeat')
end
}
})removeZone
Remove a targeting zone.
exports.ox_target:removeZone(name)Parameters:
name(string) - Zone identifier
Example:
exports.ox_target:removeZone('valentine_bank')Advanced Options
Job Restrictions
Restrict interactions to specific jobs:
{
label = 'Access Evidence Locker',
icon = 'fa-solid fa-box',
groups = 'vallaw', -- Single job
onSelect = function()
-- Open evidence locker
end
}
-- Multiple jobs
{
label = 'Access Medical Supplies',
icon = 'fa-solid fa-briefcase-medical',
groups = {'doctor', 'vallaw'}, -- Array of jobs
onSelect = function()
-- Open supplies
end
}
-- Job with grade requirement
{
label = 'Access Sheriff Office',
icon = 'fa-solid fa-door-open',
groups = {
vallaw = 2 -- Valentine Law grade 2 or higher
},
onSelect = function()
-- Open office
end
}Item Requirements
Require specific items to see the interaction:
{
label = 'Repair Wagon',
icon = 'fa-solid fa-wrench',
items = 'repair_kit', -- Single item
onSelect = function()
-- Repair wagon
end
}
-- Multiple items (requires all)
{
label = 'Cook Stew',
icon = 'fa-solid fa-pot',
items = {'meat', 'vegetables', 'water'},
onSelect = function()
-- Cook stew
end
}
-- Items with quantity
{
label = 'Craft Bandage',
icon = 'fa-solid fa-bandage',
items = {
cloth = 3,
thread = 1
},
onSelect = function()
-- Craft bandage
end
}
-- Require ANY item (not all)
{
label = 'Feed Horse',
icon = 'fa-solid fa-carrot',
items = {'apple', 'carrot', 'hay'},
anyItem = true, -- Only needs one of these items
onSelect = function()
-- Feed horse
end
}Distance Control
Control interaction distance:
{
label = 'Open Door',
icon = 'fa-solid fa-door-open',
distance = 2.0, -- Can interact from 2 units away
onSelect = function()
-- Open door
end
}Bone Targeting
Target specific entity bones:
{
label = 'Pat Horse',
icon = 'fa-solid fa-hand',
bones = 'neck', -- Single bone
distance = 2.0,
onSelect = function(data)
-- Pat horse
end
}
-- Multiple bones
{
label = 'Check Saddle',
icon = 'fa-solid fa-saddle',
bones = {'saddle', 'back'},
distance = 2.0,
onSelect = function(data)
-- Check saddle
end
}Can Interact Function
Dynamic interaction visibility:
{
label = 'Lockpick Door',
icon = 'fa-solid fa-lock',
canInteract = function(entity, distance, coords, name, bone)
-- Check if player has lockpick
local hasLockpick = exports['rsg-inventory']:HasItem(source, 'lockpick')
-- Check if not a cop
local Player = RSGCore.Functions.GetPlayerData()
local isCop = Player.job.type == 'leo'
return hasLockpick and not isCop
end,
onSelect = function(data)
-- Start lockpicking
end
}Event Types
Different ways to handle interactions:
-- Client Event
{
label = 'Open Menu',
icon = 'fa-solid fa-bars',
event = 'myresource:client:openMenu' -- Triggers client event
}
-- Server Event
{
label = 'Purchase Item',
icon = 'fa-solid fa-shopping-cart',
serverEvent = 'shop:server:purchase', -- Triggers server event
args = { item = 'bread', price = 5 } -- Arguments passed to event
}
-- OnSelect Function
{
label = 'Custom Action',
icon = 'fa-solid fa-cog',
onSelect = function(data)
-- data.entity = entity handle
-- data.coords = entity coordinates
-- data.model = entity model
-- Custom code here
end
}
-- Export
{
label = 'Use Export',
icon = 'fa-solid fa-box',
export = 'myresource:openThing' -- Calls an export
}
-- Command
{
label = 'Run Command',
icon = 'fa-solid fa-terminal',
command = 'emote wave' -- Executes a command
}Complete Examples
Example 1: NPC Shopkeeper
CreateThread(function()
-- Create NPC
local model = `U_M_M_VALTHESKINNER_01`
lib.requestModel(model, 5000)
local coords = vector3(-324.28, 803.50, 117.88)
local npc = CreatePed(model, coords.x, coords.y, coords.z, 90.0, false, false, false, false)
SetEntityCanBeDamaged(npc, false)
SetEntityInvincible(npc, true)
FreezeEntityPosition(npc, true)
SetBlockingOfNonTemporaryEvents(npc, true)
-- Add targeting
exports.ox_target:addEntity(npc, {
{
label = 'Browse Goods',
icon = 'fa-solid fa-shopping-basket',
distance = 2.5,
onSelect = function()
TriggerServerEvent('shop:server:open', 'general')
end
},
{
label = 'Sell Items',
icon = 'fa-solid fa-dollar-sign',
distance = 2.5,
canInteract = function()
-- Only show if player has items to sell
return exports['rsg-inventory']:GetItemCount(source, {'meat', 'pelt'}) > 0
end,
onSelect = function()
TriggerEvent('shop:client:sellMenu')
end
}
})
end)Example 2: Job-Restricted Zones
-- Sheriff's Office Door
exports.ox_target:addBoxZone('sheriff_office', vector3(-275.42, 807.12, 119.38), vector3(1.5, 1.5, 2.5), 0, {
{
label = 'Enter Office',
icon = 'fa-solid fa-door-open',
groups = {
vallaw = 0 -- Any valentine law grade
},
onSelect = function()
-- Unlock and open door
TriggerEvent('doors:client:open', 'sheriff_office')
end
}
})
-- Evidence Locker (high rank only)
exports.ox_target:addBoxZone('evidence_locker', vector3(-270.11, 810.55, 119.38), vector3(2.0, 2.0, 2.0), 0, {
{
label = 'Access Evidence',
icon = 'fa-solid fa-box',
groups = {
vallaw = 3 -- Grade 3 or higher
},
onSelect = function()
TriggerServerEvent('police:server:openEvidence')
end
}
})Example 3: Crafting Station
exports.ox_target:addSphereZone('crafting_bench', vector3(-280.50, 815.22, 119.50), 2.0, {
{
label = 'Craft Bandages',
icon = 'fa-solid fa-bandage',
items = {
cloth = 2,
thread = 1
},
onSelect = function()
TriggerEvent('crafting:client:start', 'bandage')
end
},
{
label = 'Craft Repair Kit',
icon = 'fa-solid fa-toolbox',
items = {
metal = 5,
wood = 3,
oil = 1
},
onSelect = function()
TriggerEvent('crafting:client:start', 'repair_kit')
end
},
{
label = 'Craft Lockpick',
icon = 'fa-solid fa-key',
items = {
metal = 2
},
canInteract = function()
local Player = RSGCore.Functions.GetPlayerData()
return Player.metadata.rep.crafting and Player.metadata.rep.crafting >= 10
end,
onSelect = function()
TriggerEvent('crafting:client:start', 'lockpick')
end
}
})Example 4: Dynamic Hitching Posts
-- Target all hitching post models
local hitchingModels = {
`P_HITCHINGPOST01X`,
`P_HITCHINGPOST02X`,
`P_HITCHINGPOST03X`,
`P_HITCHINGPOST04X`,
`P_HITCHINGPOSTOLD01X`
}
exports.ox_target:addModel(hitchingModels, {
{
label = 'Hitch Horse',
icon = 'fa-solid fa-horse',
distance = 3.5,
canInteract = function(entity, distance, coords, name, bone)
return IsPedOnMount(PlayerPedId())
end,
onSelect = function(data)
local horse = GetMount(PlayerPedId())
if horse and horse ~= 0 then
TriggerServerEvent('horses:server:hitchHorse', NetworkGetNetworkIdFromEntity(horse), data.coords)
end
end
},
{
label = 'Retrieve Horse',
icon = 'fa-solid fa-hand-holding',
distance = 3.5,
canInteract = function(entity, distance, coords, name, bone)
-- Check if player has a horse hitched nearby
return not IsPedOnMount(PlayerPedId()) -- Not on horse
end,
onSelect = function(data)
TriggerServerEvent('horses:server:retrieveHorse', data.coords)
end
}
})Best Practices
Tip
Use canInteract for dynamic visibility: Hide options that aren't currently available instead of showing disabled options
Always validate on server: Never trust client-side data. Always re-check permissions and items on the server
Use appropriate distances: Keep interaction distances realistic (1.5-3.0 for most interactions)
Performance Tips
- Don't add too many zones: Each zone checks distance every frame
- Use models over entities: Model targeting is more efficient than entity targeting for common objects
- Efficient canInteract: Keep canInteract functions lightweight
- Clean up when done: Remove zones/entities when they're no longer needed
Troubleshooting
- Check distance - are you close enough?
- Verify canInteract function isn't returning false
- Check job/gang/item requirements
- Ensure ox_target is started before your resource
- Verify the groups parameter is set correctly
- Check player's actual job name (not label)
- Ensure grade requirements are correct
- Check zone coordinates are correct
- Verify size/radius is appropriate
- Make sure zone name is unique
- Check for Lua errors in F8 console
For more advanced usage, check the official ox_target documentation: https://overextended.dev/ox_target

