> ## Documentation Index
> Fetch the complete documentation index at: https://lationscripts.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Interact - Entities

> Attach an interaction stack to a live entity with addEntity - bones, offsets, and the anchor lifecycle

`addEntity` attaches an interaction stack to a **live entity** - a spawned vehicle, ped, or object you already hold a handle to. The anchor rides the entity as it moves: on a bone when you name one, at an offset otherwise, at the entity's center as the last resort.

```lua theme={null}
local id = exports.lation_interact:addEntity(entity, data)
```

Returns an anchor id (number) on success, or `nil` with a console error explaining what's wrong. Remove it any time with `exports.lation_interact:remove(id)`.

<Note>
  This page covers what `addEntity` adds on top of the shared vocabulary. The anchor fields (`label`, `options`, `icon`, `stages`, `expand`, `reveal`, `debug`), the option table, condition gates, and handlers are documented in [Options](/docs/interact/api/options).
</Note>

## Parameters

<ParamField path="entity" type="number" required>
  A client entity handle. The entity must exist at call time - a missing entity rejects the registration with a console error and returns `nil`.

  If the server hands you a network id, convert it first: `NetworkGetEntityFromNetworkId(netId)` (or `NetToVeh` / `NetToPed` / `NetToObj`).
</ParamField>

<ParamField path="data" type="table" required>
  The anchor spec - all the shared [anchor fields](/docs/interact/api/options#anchor-fields) plus the two placement fields below.
</ParamField>

### Placement

<ParamField path="bone" type="string">
  Entity bone name the anchor rides (e.g. `'boot'` for a vehicle's trunk, `'bonnet'` for the hood). The bone index is resolved lazily, once per anchor; a bone the entity doesn't have falls through to `offset`, then to the entity center.
</ParamField>

<ParamField path="offset" type="vector3">
  Entity-**local** offset from the entity center, rotating with the entity. Used when no `bone` is given, or as the fallback when the named bone is missing.
</ParamField>

The resolution order is always: **bone** (when given and present on the entity) → **offset** (when given) → **entity center**. Omit both and the stack sits at the center - fine for small props, vague on a vehicle.

## One Call, One Anchor

Each `addEntity` call creates exactly **one** anchor with one position and one option stack. To give an entity several interaction spots - trunk, hood, doors - register it several times, one call per spot. Each call returns its own id and is removed independently.

<Note>
  If an `addModel` or `addGlobal*` rule matches the same entity at the same bone or offset, its options **merge into the same stack** - explicit `addEntity` options first, then the model rule's, then the global's. One stack, never two overlapping anchors.
</Note>

## Lifecycle

Entity anchors clean up after themselves:

* **The entity stops existing** - deleted, or streamed out of the client's world - and the anchor is removed automatically, through the same path as an explicit `remove(id)`. It does **not** come back if a networked entity streams back in; re-register on stream-in, or use `addModel` for interactions that should exist wherever the model does.
* **Your resource stops** and every anchor it registered is dropped.
* **You call `remove(id)`** whenever the interaction's moment has passed.

<Info>
  Death does **not** remove an anchor - a dead ped still exists, and searching a body is a legitimate interaction. If an option shouldn't apply to the dead, gate it with `canInteract` and `IsEntityDead`.
</Info>

## Handler Payload

Handlers on entity anchors receive the entity in their payload:

```lua theme={null}
onSelect = function(data)
    -- data.id      the anchor id addEntity returned
    -- data.index   the option's index, in registration order
    -- data.args    the option's args, verbatim
    -- data.entity  the entity handle
    -- data.netId   the network id - only when the entity is networked
    -- data.coords  the entity's coords at activation
end
```

`event` receives the same table. `serverEvent` receives it **minus `entity`** - handles are client-local, so hand the server `data.netId` and let it call `NetworkGetEntityFromNetworkId`. A purely local entity (a client-spawned prop) has no `netId` at all. See [Handlers](/docs/interact/api/options#handlers) for the full dispatch order.

`canInteract` predicates also get `data.entity`, evaluated off the frame path - never per render frame.

## Behavior Notes

<AccordionGroup>
  <Accordion title="Quiet until looked at" icon="eye">
    Entity anchors default to `reveal = 'focus'` (`Config.Reveal.entity`): nothing renders until attention lands on the entity, so a street full of registered cars stays perfectly quiet. Pass `reveal = 'ambient'` to mark one with a grain of light from a distance - right for a mission-critical vehicle the player is meant to find.
  </Accordion>

  <Accordion title="Moving entities" icon="gauge-high">
    An entity moving faster than `3.0 m/s` holds at the grain stage and can't be focused - a passing car earns a point of light, not a prompt. It becomes interactable the moment it slows down.
  </Accordion>

  <Accordion title="Statebag conditions" icon="database">
    The `state` option gate reads `Entity(entity).state`, so it works on entity anchors (points and zones have no statebag). `state = 'trunkLocked'` shows a row while the statebag is truthy; `state = { key = 'trunkLocked', value = false }` while it equals the value. See [Condition Gates](/docs/interact/api/options#condition-gates).
  </Accordion>

  <Accordion title="Shared export name" icon="code-merge">
    `addEntity` is also an ox\_target export name, and the two are told apart by shape: a native spec always carries an `options` array, while ox-style calls (a bare option table, or an array of them) route to the [compatibility bridge](/docs/interact/compat/ox-target). As long as your spec has `options`, it's handled natively.
  </Accordion>
</AccordionGroup>

## Example

A trunk stack riding the `boot` bone, and the hood as its own second anchor - one call per spot:

```lua theme={null}
local vehicle = NetToVeh(netId)

local trunk = exports.lation_interact:addEntity(vehicle, {
    label = 'Trunk',
    icon = 'car-rear',
    bone = 'boot',
    options = {
        {
            label = 'Search Trunk',
            icon = 'magnifying-glass',
            key = 'E',
            hold = 1500, -- ring fills for 1.5s
            onSelect = function(data)
                -- the server resolves data.netId back to the vehicle
                TriggerServerEvent('evidence:searchTrunk', data.netId)
            end
        }
    }
})

local hood = exports.lation_interact:addEntity(vehicle, {
    label = 'Engine',
    icon = 'oil-can',
    bone = 'bonnet',
    options = {
        {
            label = 'Inspect Engine',
            icon = 'wrench',
            canInteract = function(data)
                return GetIsVehicleEngineRunning(data.entity) == false
            end,
            serverEvent = 'evidence:inspectEngine'
        }
    }
})

-- when the scene wraps up
exports.lation_interact:remove(trunk)
exports.lation_interact:remove(hood)
```

If the vehicle is deleted mid-scene, both anchors remove themselves - the `remove` calls at the end simply do nothing.
