> For the complete documentation index, see [llms.txt](https://acestudios.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://acestudios.gitbook.io/docs/inventory-and-items/deployables/custom-interactables.md).

# Custom Interactables

Write your own Lua interaction for any deployable.

Any deployable can run a Lua function when a player interacts with it. Interactables are **client-side** files in `ace_deployables/interactables/`. Every `.lua` file in that folder is loaded automatically.

## Included interactables

| File                      | Name             | What it does                                                                                                                                                            |
| ------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `campfire.lua`            | `campfire`       | The player faces the object and plays the `WORLD_HUMAN_STAND_FIRE` scenario. Press <kbd>E</kbd> or move (<kbd>WASD</kbd>) to stop. Used by the Campfire and Hobo Stove. |
| `tent.lua`                | `tent`           | Fades the screen, moves the player inside the tent and plays a sleeping animation. Press <kbd>E</kbd> to wake up and leave.                                             |
| `interactableExample.lua` | `exampleFromAce` | Template that prints a message.                                                                                                                                         |

## Creating an interactable

{% stepper %}
{% step %}

### Create a file

Create a new file such as `interactables/chair.lua`:

{% code title="interactables/chair.lua" %}

```lua
Interactables = Interactables or {}

Interactables["chair"] = function(entity, uuid, deployableData)
    TaskStartScenarioAtPosition(
        PlayerPedId(),
        "PROP_HUMAN_SEAT_CHAIR",
        GetEntityCoords(entity),
        GetEntityHeading(entity),
        0,
        true,
        true
    )
end
```

{% endcode %}

Always start with `Interactables = Interactables or {}` so your file doesn't overwrite the others.
{% endstep %}

{% step %}

### Assign it to a deployable

In `ItemList.lua`, set `interactable` to the name you registered:

```lua
skidChair = {
    -- ...
    interactable = "chair",
},
```

{% endstep %}

{% step %}

### Restart the resource

{% endstep %}
{% endstepper %}

## Function parameters

| Parameter        | Type          | Description                                                                                |
| ---------------- | ------------- | ------------------------------------------------------------------------------------------ |
| `entity`         | entity handle | The spawned object the player interacted with.                                             |
| `uuid`           | string        | Unique ID of this deployed instance, for example `"550e8400-e29b-41d4-a716-446655440000"`. |
| `deployableData` | table         | Data for this deployed instance. See below.                                                |

### `deployableData` structure

```lua
{
    owner = "steam:110000000000000", -- identifier of the owner (when ownership is enabled)
    deployKey = "tent",              -- key from ItemConfig.Deployables
    model = `prop_tent_01`,          -- model hash
    deployTime = 1234567890,         -- timestamp of deployment
    position = vector3(x, y, z),     -- world coordinates
}
```

```lua
Interactables["exampleFromAce"] = function(entity, uuid, deployableData)
    print(deployableData.owner)
    print(deployableData.deployKey)
    print(deployableData.position)
end
```

{% hint style="warning" %}
**Performance tips from the included examples**

* Run long-running logic inside `CreateThread`. The included campfire and tent do this.
* Use a local state flag (for example `isSleeping`) so a second interaction doesn't start the same loop twice.
* Always give the player a way out (a key press) and clean up with `ClearPedTasks`.
  {% endhint %}
