# Interactions (/docs/es_extended/client/modules/interactions)

Interactions connect an action to the shared ESX interact key. You register a name, a function to run on key press and an optional condition. When the player presses the key, every interaction whose condition returns `true` runs. Combined with [points](/docs/es_extended/client/imports/point) this replaces the old `while true do ... IsControlJustReleased(0, 38)` loops.

## Overview [#overview]

| | |
|---|---|
| Resource | `es_extended` (implemented in `esx_lib`) |
| Side | Client |
| Key mapping | `+esx_interact`, default key `E`, label "Interact" |

Interactions are removed automatically when the resource that registered them stops.

## Functions [#functions]

### ESX.RegisterInteraction [#esxregisterinteraction]

```lua
ESX.RegisterInteraction(name, onPress, condition)
```

| Name | Type | Description |
|---|---|---|
| `name` | `string` | Unique name. Registering the same name again replaces the old interaction. |
| `onPress` | `function` | Runs when the key is pressed and the condition passes. |
| `condition` | `function?` | Returns `true` when the interaction is allowed. Default: always `true`. Errors in it count as `false`. |

**Returns:** nothing

```lua title="client/main.lua"
local nearArmory = false

local armory = ESX.Point:new({
    coords = vector3(452.6, -980.0, 30.7),
    distance = 1.5,
    enter = function()
        nearArmory = true
        ESX.TextUI(('[%s] Open armory'):format(ESX.GetInteractKey()))
    end,
    leave = function()
        nearArmory = false
        ESX.HideUI()
    end,
})

ESX.RegisterInteraction('police_armory', function()
    OpenArmoryMenu()
end, function()
    return nearArmory and ESX.PlayerData.job.name == 'police'
end)
```

<Callout type="warn">
Without a condition, `onPress` runs on every key press anywhere on the map. Always pass a condition unless that is what you want.
</Callout>

### ESX.RemoveInteraction [#esxremoveinteraction]

```lua
ESX.RemoveInteraction(name)
```

| Name | Type | Description |
|---|---|---|
| `name` | `string` | Name used in `RegisterInteraction`. |

**Returns:** nothing

```lua
ESX.RemoveInteraction('police_armory')
```

### ESX.GetInteractKey [#esxgetinteractkey]

```lua
ESX.GetInteractKey()
```

**Returns:** `string`, the label of the key currently bound to `+esx_interact` (for example `E`).

```lua
ESX.ShowHelpNotification(('Press %s to talk'):format(ESX.GetInteractKey()), true)
```

## Common issues [#common-issues]

- **Two interactions fire at once.** Every interaction with a passing condition runs. Make conditions specific (distance, job, vehicle state).
- **Interaction stops working after a restart.** It belongs to the resource that registered it. Register it again when your resource starts.

## Related [#related]

- [Points](/docs/es_extended/client/imports/point)
- [Client UI (TextUI)](/docs/es_extended/client/ui)
- [Client functions (RegisterInput)](/docs/es_extended/client/functions)
- [esx_lib](/docs/core/esx_lib)
