> ## 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 - How It Works

> Stages, focus, input, and suppression - what players see and when

There's no key to hold and no crosshair. As a player approaches something interactable, it reveals itself in stages - and the thing they're looking at is the one that responds. Servers that want the classic hold-to-see feel turn on [passive mode](#passive-mode) instead.

## The Three Stages

| Stage     | Default distance | What the player sees                    |
| --------- | ---------------- | --------------------------------------- |
| **Grain** | `8.0m`           | A point of light marks the interactable |
| **Name**  | `4.5m`           | The label grows out of the grain        |
| **Reach** | `2.4m`           | Options unfold and input becomes live   |

Defaults live in `Config.Stages`, and any registration can override them with `stages = { grain = ..., name = ..., reach = ... }`. Native zones size their own stages from their shape, with reach meaning *inside* the zone; zones bridged from ox\_target / qb-target reach from `Config.Stages.reach` outside their surface instead - the way their eye targeted them from a step away.

## Focus

Only one thing ever speaks at a time: the anchor the player is looking at. Focus follows the camera, prefers what's near the center of the screen, and hands off smoothly - it never flickers between two nearby targets, and it never shows through walls. Fast-moving entities (a passing car) keep their point of light but can't be focused.

## Input

Three rules, in order:

1. **An option's own key activates that option** while its stack is open. Options can bind any keyboard key by name. Until the stack opens, the game owns the keyboard - a bound `F` beside a closed menu still enters your vehicle.
2. **The confirm key (`E` by default) activates the highlighted option** and opens closed lists. On a controller, LB fills this role.
3. **The interact control (Left Alt) is the mouse's way in.** Holding it keeps the camera and movement yours; with a stack on screen, a left click frees the cursor - hover to highlight, click to select, press-and-hold for hold options - and a right click hands the camera back. A click on a closed pill opens it in the same motion. This is how options without a key of their own are reached, and it's what reveals [passive](#passive-mode) interactions.

Options with `hold = <ms>` are hold-to-confirm: a ring fills while the key is held, and releasing early cancels.

### How lists open

`Config.ExpandMode` (or a per-anchor `expand = ...`) controls how a stack opens once you're in reach:

* `'smart'` *(default)* - single options unfold on their own; multi-option stacks wait for the confirm key
* `'auto'` - always unfolds on its own
* `'manual'` - always waits for the confirm key

## Reveal Modes

What renders *before* something is focused is its reveal mode (`Config.Reveal`, per-anchor `reveal = ...`):

* `'ambient'` - a grain of light marks it from a distance. The default for placed points - the grain is the invitation.
* `'focus'` - nothing renders until you look at it. The default for entities, so a street full of cars stays quiet.

<Note>
  Anchors coming through the ox\_target / qb-target compatibility layers follow `Config.Reveal.bridged` - `'focus'` by default, `'ambient'` to give them all grains.
</Note>

## Passive Mode

By default the layer is proactive: things reveal themselves as you approach. Passive mode is the classic target feel instead - nothing shows until the interact control is held, then everything follows its reveal mode as usual, and it all vanishes the instant the control lets go. Three scopes:

* `Config.Passive = true` - the whole server
* `Config.PassiveResources = { 'qb-drugs' }` - only what those resources register. Escrowed scripts included: both compatibility layers apply it by the registering resource, so what one script places for an illegal activity stays invisible until a player who knows holds the key, while the rest of the server stays proactive
* `passive = true` on any single registration

A hidden passive anchor doesn't exist for the focus system - no grain, no label, no input, nothing for a passer-by to notice.

## In a Vehicle

From a seat, anchors on other vehicles, peds, players and objects hide - none of them can be reached from inside a car - while points and zones stay live, since garages, drive-thrus and car washes are used from the driver's seat. `Config.InVehicle` sets both defaults; a registration's own `inVehicle = true|false` overrides them, and an option flagged `allowInVehicle = true` keeps its anchor live. The vehicle you're sitting in follows `Config.IncludeOwnVehicle`.

## Suppression

When the player is dead, cuffed, in the pause menu, running a progress bar (ox\_lib's or qb progressbar's), or another resource holds the UI (inventory, phone), the whole layer goes quiet - and wakes the moment the state clears. The automatic reasons are toggled in `Config.Suppress`; scripts can also hold the layer down themselves:

```lua theme={null}
exports.lation_interact:suppress('myscript')   -- quiet, until...
exports.lation_interact:release('myscript')    -- ...released
local quiet = exports.lation_interact:isSuppressed()
```

Tags are independent - two scripts never fight over one switch, and a tag is held until its owner releases it.
