EndCore Framework

en-target

Look-at interactions for peds, players, vehicles, objects and world zones, with job, group and item requirements.

en-target is EndCore's "third eye". Players hold Left Alt, look at a ped, another player, a vehicle, an object or a spot in the world, and a short list of options appears beside the reticle. The mouse wheel moves through the list; left-click or E picks an option.

The camera keeps moving while you look, because en-target never takes NUI focus. Vehicles and objects under the reticle get an orange outline (peds are not outlined). Looking is blocked while you are dead, in the pause menu, focused on another NUI, or not logged in to a character.

At a glance

Depends onen-core, en-ui
SideClient only (no server scripts)
Start afteren-core, en-ui. Start order does not matter for callers using encore.target.*
Database tablesNone
Config filesconfig/client.lua
Key bindsen_target_look, default Left Alt

How it works

While the look key is held (or toggled on), en-target casts a ray from the camera every Config.tickRate milliseconds. It collects the options that apply to whatever the ray hits:

  • Global options for every ped, player, vehicle or object.
  • Model options for specific model names or hashes.
  • Local entity options for specific entity handles you pass in.
  • Sphere zones placed at world coordinates.

Each option is then filtered by its own distance, bones, groups, items and canInteract checks. Only options that pass are shown. When the player picks one, looking stops first and then the action runs.

Options are tracked per registering resource and removed automatically when that resource stops. Deleted local entities are purged every 10 seconds.

Restart safety

If you register through the library wrapper encore.target.*, global, model and zone registrations are remembered and re-applied whenever en-target starts or restarts. Local entity registrations are not remembered across an en-target restart, so register those again when needed.

If en-target is not running, nothing shows. A resource that must keep working without it should fall back to encore.showPrompt. See Target interface.

Configuration

config/client.lua:

KeyDefaultWhat it does
Config.key'LMENU' (Left Alt)Default look key; players can rebind it in Settings > Key Bindings > FiveM
Config.togglefalsetrue = press to start and stop looking; false = hold
Config.rayLength8.0How far the look ray reaches (m). Options still check their own distance
Config.defaultDistance2.0Option distance when an option sets none
Config.tickRate50Look check interval (ms)
Config.boneRadius1.2Max distance from the look point to a listed bone
Config.debugZonesfalseDraw sphere zones within 30 m while looking
Config.disabledControlsweapon wheel 14-17, 37; attack/aim 24, 25, 257; E 38; melee 140-143, 263, 264Controls blocked while looking
lua
-- config/client.lua: press Alt once to start looking, again to stop
Config.key = 'LMENU'
Config.toggle = true
Config.rayLength = 10.0

Option shape

Every export takes one option or a list of options.

lua
{
    name = 'my-res:action',     -- unique; the same name replaces. Default '<resource>:<label>'
    label = 'Do thing',
    icon = 'box',               -- en-ui icon name
    distance = 2.0,             -- player-to-look-point distance
    bones = { 'boot' },         -- entity bones; nearest within Config.boneRadius
    groups = { medic = 2 },     -- see below
    items = 'lockpick',         -- see below
    canInteract = function(entity, distance, coords, name, bone) return true end,
    onSelect = function(data) end, -- data = { name, label, entity, coords, distance, zone, bone }
    -- used only when onSelect is absent, checked in this order:
    event = 'client:event',        -- TriggerEvent(event, data)
    serverEvent = 'server:event',  -- TriggerServerEvent; data.entity becomes a network id (0 if not networked)
    command = 'somecommand',       -- ExecuteCommand
}
FieldAccepted values
groups'medic', { 'medic', 'police' }, { medic = 2 } (job and minimum grade), 'group' (anyone in a player group), 'group:12' or { ['group:12'] = 2 } (a specific group, optionally with a minimum grade)
items'lockpick', { 'lockpick', 'torch' } (all required), { lockpick = 1, scrap = 3 } (minimum counts)
canInteractRuns on every check, so it must return quickly and must not wait

groups is checked against the player's job name and grade from exports['en-core']:GetPlayerData(), or their player group. items is checked with encore.inventory.getItemCount.

Exports

Client exports on exports['en-target']:

ExportArgumentsReturns
AddGlobalPed / RemoveGlobalPedoptions / names?Non-player peds
AddGlobalPlayer / RemoveGlobalPlayeroptions / names?Player peds
AddGlobalVehicle / RemoveGlobalVehicleoptions / names?
AddGlobalObject / RemoveGlobalObjectoptions / names?
AddModel / RemoveModelmodels, options / models, names?Model names or hashes
AddLocalEntity / RemoveLocalEntityentities, options / entities, names?Existing entity handles
AddSphereZonezone = { name?, coords, radius? (1.5), options, debug? }Zone name
RemoveZonename
IsActiveboolean, true while looking
Disablestatetrue disables and stops looking (cutscenes, cuffs); false re-enables
IsDisabledboolean

Calling a Remove* export with no names clears every option in that list.

encore.target wrapper

Prefer the library wrapper from en-core. It survives en-target restarts (except local entities) and runs onSelect in its own thread inside your resource, so your handler may wait on callbacks or progress bars.

FunctionNotes
encore.target.addGlobalPed/Vehicle/Object/Player(options)
encore.target.removeGlobalPed/Vehicle/Object/Player(names)
encore.target.addModel(models, options) / removeModel(models, names)
encore.target.addLocalEntity(entity, options) / removeLocalEntity(entity, names)
encore.target.addSphereZone(zone) / removeZone(name)
encore.target.isAvailable()Whether en-target is running

Events

en-target has no events of its own. It stops looking when it receives encore:client:playerUnloaded or encore:client:playerDied.

Examples

A searchable vending machine that needs a lockpick, and a radio tower anyone in a player group can use:

lua
-- client.lua
encore.target.addModel({ 'prop_vend_snack_01', 'prop_vend_soda_01' }, {
    name = 'my-scav:vending',
    label = 'Search vending machine',
    icon = 'search',
    distance = 1.8,
    items = 'lockpick',
    canInteract = function(entity) return not Entity(entity).state.searched end,
    onSelect = function(data)
        local ok = encore.callback.await('my-scav:search', NetworkGetNetworkIdFromEntity(data.entity))
    end,
})

encore.target.addSphereZone({
    name = 'my-scav:radio_tower',
    coords = vec3(750.2, 1300.5, 360.3),
    radius = 1.5,
    options = {
        { name = 'my-scav:broadcast', label = 'Use radio', icon = 'radio', groups = 'group', onSelect = function() end },
    },
})

Turn looking off during a scripted scene:

lua
exports['en-target']:Disable(true)
-- ... scene ...
exports['en-target']:Disable(false)