> ## 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 - Models

> Make every instance of a model interactive with one addModel rule

`addModel` registers a **rule**: every matching vehicle, NPC ped, or object near the player becomes interactive automatically - no spawn tracking, no handles, no per-entity registration. One line covers every vending machine in the city.

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

Returns a rule id (number) on success, or `nil` with a console error explaining what's wrong. `exports.lation_interact:remove(id)` removes the rule and every anchor it created, immediately. Rules are also cleaned up when your resource stops.

<Note>
  This page covers what `addModel` 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="models" type="string | number | (string | number)[]">
  Model name(s) or joaat hash(es) - a single value or an array, mixing names and hashes freely. Names are hashed for you. A call with no valid model rejects with a console error and returns `nil`.

  ```lua theme={null}
  addModel('prop_vend_soda_01', data)
  addModel({ 'prop_vend_soda_01', `prop_vend_soda_02`, -206690185 }, data)
  ```
</ParamField>

<ParamField path="data" type="table" required>
  The anchor template - all the shared [anchor fields](/docs/interact/api/options#anchor-fields) plus the same placement fields `addEntity` takes:

  * `bone` (string) - bone the anchor rides on each matching entity (e.g. `'boot'`); missing bones fall through to `offset`, then to the entity center
  * `offset` (vector3) - entity-**local** offset from the center, rotating with the entity
</ParamField>

A rule matches vehicles, NPC peds, and objects whose model is in the set. Player peds are never matched. Across all model and global rules combined, at most the nearest `24` matches are active at once - over the cap, the nearest win.

## Merging

When several sources target the same entity at the same spot (same `bone`/`offset`/center), they merge into **one stack**, ordered by priority: **explicit `addEntity` > model rules > globals**. The highest-priority contributor provides the presentation (`label`, `icon`, `stages`, `expand`, `reveal`); the options stack beneath it in priority order.

```lua theme={null}
-- every vehicle offers this at the trunk...
exports.lation_interact:addGlobalVehicle({
    label = 'Trunk',
    bone = 'boot',
    options = {
        { label = 'Open Trunk', key = 'E', event = 'vehicle:openTrunk' }
    }
})

-- ...and the one mission vehicle adds its own row ABOVE it
exports.lation_interact:addEntity(missionVehicle, {
    label = 'Evidence Van',
    bone = 'boot',
    options = {
        { label = 'Collect Evidence', key = 'G', groups = 'police', serverEvent = 'heist:collect' }
    }
})
```

The mission vehicle shows **one** trunk stack titled `Evidence Van` - never two overlapping anchors. A different `bone` or `offset` is a different spot and stays its own stack.

<Warning>
  On a rule-created anchor, the handler payload's `data.id` identifies which entity's stack fired - it is not the rule id. Keep the id your `addModel` call returned; that's the one `remove(id)` takes.
</Warning>

## Behavior Notes

<AccordionGroup>
  <Accordion title="Quiet until looked at" icon="eye">
    Rule-created anchors default to `reveal = 'focus'`: nothing renders until the player looks at the entity. Pass `reveal = 'ambient'` on the rule to mark every match with a grain of light from a distance - right for vending machines, wrong for traffic.
  </Accordion>

  <Accordion title="Your own vehicle" icon="car-side">
    The vehicle you're sitting in is skipped by default. Scripts that expect their options while seated need `Config.IncludeOwnVehicle = true`.
  </Accordion>

  <Accordion title="Moving entities" icon="gauge-high">
    A match moving faster than `3.0 m/s` holds at the grain stage and can't be focused. It becomes interactable the moment it slows down.
  </Accordion>

  <Accordion title="Shared export name" icon="code-merge">
    `addModel` is also an ox\_target export name, told apart by shape: a native spec always carries an `options` array, while ox-style calls route to the [compatibility bridge](/docs/interact/compat/ox-target).
  </Accordion>
</AccordionGroup>

## Example

```lua theme={null}
local vending = exports.lation_interact:addModel({ 'prop_vend_soda_01', 'prop_vend_soda_02' }, {
    label = 'Vending Machine',
    icon = 'bottle-water',
    reveal = 'ambient', -- placed furniture earns a grain
    options = {
        {
            label = 'Buy Soda ($5)',
            icon = 'hand-holding-dollar',
            key = 'E',
            serverEvent = 'shop:buySoda',
            args = { price = 5 }
        }
    }
})
```
