ScriptsM ox_target Categories
ScriptsM ox_target Categories is a modified version of ox_target that adds a clean category and subcategory system without removing the original target functionality.
Instead of showing every interaction in one long list, related actions can be placed inside categories. Players can hover over a category to preview its actions or click it to keep the submenu open.
Standard ox_target options and categorized options can be used together in the same resource.
The original API remains compatible with the official ox_target documentation (opens in a new tab). Category-specific fields added by this version are documented below.
Installation
Download and extract the resource
Download the resource and place the ox_target folder inside your server's resources directory.
If you are replacing the original ox_target, stop the server and replace the old folder completely. Do not run two resources named ox_target at the same time.
Install the dependency
The resource requires ox_lib version 3.30.0 or newer.
ox_lib
ox_targetConfigure the resource start order
Make sure ox_lib starts before ox_target.
ensure ox_lib
ensure ox_targetOptional server configuration
Add any required convars before ensure ox_target in server.cfg.
# Use toggle mode instead of holding the targeting key.
setr ox_target:toggleHotkey 0
# Default targeting key.
setr ox_target:defaultHotkey LMENU
# Draw a sprite at the center of target zones.
setr ox_target:drawSprite 1
# Enable built-in options such as vehicle door interactions.
setr ox_target:defaults 1
# Enable debug zones, entity outlines, and the raycast indicator.
setr ox_target:debug 0
# Allow left click to select an option.
setr ox_target:leftClick 1Restart the server
Restart the server or run the following commands from the server console:
restart ox_lib
restart ox_targetSupported Frameworks
The targeting system works as a standalone resource. Optional framework bridges provide group, job, and item checks for:
ox_core
es_extended
qbx_coreQuick Start
Categories use the same exports as standard ox_target. Add usedouble = true to the parent option and place the available actions inside subcategory.
exports.ox_target:addModel('police', {
{
name = 'police_vehicle_actions',
usedouble = true,
labelcategory = 'Vehicle Actions',
iconcategory = 'fa-solid fa-car',
iconColor = '#3498db',
distance = 2.0,
bones = { 'boot' },
subcategory = {
{
name = 'open_trunk_storage',
label = 'Open trunk storage',
icon = 'fa-solid fa-box-open',
event = 'my_resource:openTrunk'
},
{
name = 'take_police_cone',
label = 'Take traffic cone',
icon = 'fa-solid fa-triangle-exclamation',
serverEvent = 'my_resource:takeCone'
},
{
name = 'inspect_vehicle',
label = 'Inspect vehicle',
icon = 'fa-solid fa-magnifying-glass',
onSelect = function(data)
print(('Selected vehicle: %s'):format(data.entity))
end
}
}
}
})Category Structure
The parent option controls the category itself and the conditions shared by every action inside it.
{
name = 'category_name',
usedouble = true,
labelcategory = 'Category Label',
iconcategory = 'fa-solid fa-folder',
iconColor = '#ffffff',
distance = 2.0,
groups = { police = 0 },
items = { 'radio' },
bones = { 'boot' },
canInteract = function(entity, distance, coords, name, bone)
return DoesEntityExist(entity)
end,
subcategory = {
-- Subcategory actions go here.
}
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Recommended | Unique option name used when replacing or removing the category. |
usedouble | boolean | Yes | Must be true to enable the category interface. |
labelcategory | string | Yes | Text displayed in the main target menu. |
iconcategory | string | No | Font Awesome icon used by the category. Defaults to a folder icon. |
iconColor | string | No | CSS color used by the category icon. |
subcategory | table | Yes | Non-empty array containing the actions shown in the secondary menu. |
distance | number | No | Maximum interaction distance for the whole category. Defaults to the normal target distance. |
groups | string/table | No | Framework groups or job grades allowed to see the category. |
items | string/table | No | Required item or items checked by the active framework bridge. |
anyItem | boolean | No | Allows any configured item to satisfy the item requirement. |
bones | string/table | No | Limits the category to one or more entity bones. |
offset | vector3 | No | Limits interaction to a model-relative offset. |
offsetSize | number | No | Allowed distance from the configured offset. |
canInteract | function | No | Controls visibility of the entire category. |
Subcategory Structure
Each subcategory entry represents one selectable action.
{
name = 'action_name',
label = 'Action Label',
icon = 'fa-solid fa-hand',
iconColor = '#ffffff',
canInteract = function(entity, distance, coords, name, bone)
return distance <= 2.0
end,
event = 'my_resource:clientEvent'
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Action identifier passed to canInteract and returned with selection data. |
label | string | Yes | Text displayed in the category submenu. |
icon | string | No | Font Awesome icon displayed next to the action. |
iconColor | string | No | CSS color used by the action icon. |
canInteract | function | No | Controls visibility of this individual action. |
onSelect | function | One action required | Executes a local Lua callback. |
event | string | One action required | Triggers a client event. |
serverEvent | string | One action required | Triggers a server event. |
export | string | One action required | Calls an export from the resource that registered the option. |
command | string | One action required | Executes a client command. |
Every subcategory entry must contain exactly one action handler: onSelect, event, serverEvent, export, or command.
Action Examples
onSelect
{
label = 'Inspect vehicle',
icon = 'fa-solid fa-magnifying-glass',
onSelect = function(data)
print(data.entity)
print(data.coords)
print(data.distance)
end
}Client event
{
label = 'Open storage',
icon = 'fa-solid fa-box-open',
event = 'my_resource:openStorage',
storageId = 'police_armory'
}
RegisterNetEvent('my_resource:openStorage', function(data)
print(data.storageId)
print(data.entity)
end)Server event
{
label = 'Take equipment',
icon = 'fa-solid fa-toolbox',
serverEvent = 'my_resource:takeEquipment',
item = 'police_cone'
}Command
{
label = 'Open vehicle menu',
icon = 'fa-solid fa-car',
command = 'vehiclemenu'
}Export
The export is resolved from the resource that registered the target option.
{
label = 'Open custom menu',
icon = 'fa-solid fa-list',
export = 'OpenCustomMenu'
}exports('OpenCustomMenu', function(_, data)
print(data.entity)
end)Dynamic Visibility
Use a parent canInteract function to hide the complete category.
canInteract = function(entity, distance)
return distance <= 2.0 and not IsEntityDead(entity)
endUse a subcategory canInteract function when only one action should be hidden.
subcategory = {
{
label = 'Repair vehicle',
icon = 'fa-solid fa-screwdriver-wrench',
canInteract = function(entity)
return GetVehicleEngineHealth(entity) < 900.0
end,
event = 'my_mechanic:repairVehicle'
},
{
label = 'Clean vehicle',
icon = 'fa-solid fa-soap',
event = 'my_mechanic:cleanVehicle'
}
}If every subcategory action is unavailable, the parent category is automatically hidden.
Zone Example
Categories work with zones, models, local entities, networked entities, global targets, vehicles, objects, peds, and players.
local zoneId = exports.ox_target:addBoxZone({
name = 'mechanic_workbench',
coords = vec3(-347.15, -133.42, 39.01),
size = vec3(2.0, 1.0, 1.5),
rotation = 70.0,
debug = false,
options = {
{
name = 'mechanic_services',
usedouble = true,
labelcategory = 'Mechanic Services',
iconcategory = 'fa-solid fa-screwdriver-wrench',
distance = 2.0,
subcategory = {
{
label = 'Repair vehicle',
icon = 'fa-solid fa-wrench',
event = 'my_mechanic:repair'
},
{
label = 'Order parts',
icon = 'fa-solid fa-boxes-stacked',
event = 'my_mechanic:orderParts'
}
}
}
}
})Migrating Existing Options
Original flat options:
exports.ox_target:addModel('police', {
{
name = 'take_cone',
label = 'Take cone',
icon = 'fa-solid fa-triangle-exclamation',
event = 'equipment:takeCone'
},
{
name = 'take_barrier',
label = 'Take barrier',
icon = 'fa-solid fa-road-barrier',
event = 'equipment:takeBarrier'
}
})Categorized version:
exports.ox_target:addModel('police', {
{
name = 'police_equipment',
usedouble = true,
labelcategory = 'Police Equipment',
iconcategory = 'fa-solid fa-toolbox',
subcategory = {
{
label = 'Take cone',
icon = 'fa-solid fa-triangle-exclamation',
event = 'equipment:takeCone'
},
{
label = 'Take barrier',
icon = 'fa-solid fa-road-barrier',
event = 'equipment:takeBarrier'
}
}
}
})Troubleshooting
The category does not appear
- Confirm
usedoubleis set totrue. - Confirm
labelcategoryis a non-empty string. - Confirm
subcategoryis a non-empty array. - Confirm at least one subcategory
canInteractfunction returnstrue. - Check the parent
distance,groups,items,bones, andcanInteractconditions.
The resource reports an action handler error
Each subcategory must contain exactly one of these fields:
onSelect
event
serverEvent
export
commandDo not add multiple action handlers to the same subcategory entry.
The submenu closes too quickly
Move the cursor directly from the category into the submenu or click the category to pin it open.
Duplicate options appear
Give every parent option a unique name and make sure the registration code runs only once. When replacing an existing integration, remove the old registration code first.
License and Credits
This resource is a modified version of ox_target (opens in a new tab), originally created by Overextended.
Original project copyright © 2022 Overextended and licensed under the MIT License. The original copyright notice and complete MIT License must remain included with every distributed copy of the resource.
Modifications © 2026 ScriptsM.