> For the complete documentation index, see [llms.txt](https://organized-chaos.gitbook.io/organized-chaos-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://organized-chaos.gitbook.io/organized-chaos-docs/the-lost-treasure/placing-machines.md).

# Placing machines

Put cabinets into the world and set how players reach them.

With `Config.Machines` empty, the resource is command-only. Add one entry per cabinet in `config/config.lua`:

```lua
Config.Machines = {
    { coords = vector3(1093.6, 220.5, -49.4), heading = 145.0,
      label = 'The Lost Treasure' },

    { coords = vector3(1000.0, 100.0, 50.0), heading = 0.0,
      label = 'High Limit', job = 'casino', maxBetIndex = 16 },
}
```

Only `coords` is required.

## Keys of a machine

| Key                | Effect                                                                                     |
| ------------------ | ------------------------------------------------------------------------------------------ |
| `heading`          | Which way the machine faces                                                                |
| `label`            | Name in the prompt, on the blip and in `{label}`                                           |
| `job`              | A job name, or a list of them, that may play here. Left out, `''` or `{}` means everyone   |
| `minBetIndex`      | The lowest step of the bet ladder this machine takes                                       |
| `maxBetIndex`      | The highest step of the bet ladder this machine takes                                      |
| `defaultBetIndex`  | The bet it opens with. Without it the player keeps their last bet, moved inside the limits |
| `prop`             | The cabinet to spawn: a model name, or a table                                             |
| `blip`             | `false` for never on the map, a table for always, with its own look                        |
| `text3d`           | Text floating over the machine: a string, or a table                                       |
| `text2d`           | Text on the screen while standing close: a string, or a table                              |
| `marker`           | `false` for none, `true` or a table for this machine's own floor marker                    |
| `helpPrompt`       | `false` for none, `true` for the default, or this machine's own text                       |
| `interactKey`      | The control that opens this machine                                                        |
| `interactDistance` | How close to open it, in metres. The server checks the same value                          |
| `drawDistance`     | How close before its marker is drawn                                                       |
| `animation`        | `false` for none, `true` or a table for this machine's own animation                       |

A key that is left out falls back to the shared setting: `Config.Blip`, `Config.Interaction` or `Config.InteractDistance`. `false` switches one off for this machine. `true` or a table switches it on even if the shared setting is off.

The bet indexes point into `Config.Bet.Steps`. Step 1 is the lowest bet.

{% hint style="warning" %}
Job locks and bet caps are enforced on the server, but only at machines. While `Config.UseCommand = true`, anyone can open the game by command without them. Set it to `false` when those rules matter.
{% endhint %}

## Cabinets

`prop` takes a model name, or a table:

```lua
prop = { Model = 'lost_treasure_slot', Offset = vector3(0.0, 0.0, 0.0),
         Heading = 0.0, Ground = true },
```

The resource ships its own cabinet in twelve looks:

| Model                                                                  | Look                                                          |
| ---------------------------------------------------------------------- | ------------------------------------------------------------- |
| `lost_treasure_slot`                                                   | Teal and gold, arched sign                                    |
| `lost_treasure_slot_ruby`                                              | Red, light box with bulbs                                     |
| `lost_treasure_slot_temple`                                            | Sandstone, stepped temple                                     |
| `lost_treasure_slot_book`, `_hook`, `_compass`, `_binoculars`          | One per paying symbol, in its colours with its own sign shape |
| `lost_treasure_slot_gem_blue`, `_gem_green`, `_gem_red`, `_gem_purple` | One per gem                                                   |
| `lost_treasure_slot_character`                                         | The character symbol                                          |

Any GTA prop name works as well. `Offset` moves the prop from `coords`, and `Heading` turns it.

{% hint style="info" %}
`Ground = false` stops the cabinet being snapped onto the floor. Turn snapping off in an MLO interior whose floor the game does not know, where the cabinet would otherwise drop a storey.
{% endhint %}

## How a player reaches a machine

```lua
Config.Interaction = {
    Mode         = 'marker',   -- 'marker' | 'target' | 'both' | 'none'
    DrawDistance = 12.0,
    InteractKey  = 38,         -- E
    CloseKey     = 200,        -- ESC
    CloseOnVehicle = true,
    Marker = { Type = 29, Colour = { r = 180, g = 20, b = 60, a = 140 }, ... },
    Target = { Resource = 'auto', Radius = 1.2, Icon = 'fa-solid fa-dice' },
    Text3D = { Distance = 8.0, Offset = 1.35, Scale = 0.4, Font = 4, ... },
    Text2D = { X = 0.5, Y = 0.92, Align = 'centre', Scale = 0.45, ... },
}
```

| Mode       | How the machine opens              |
| ---------- | ---------------------------------- |
| `'marker'` | A floor marker and a key prompt    |
| `'target'` | Through `ox_target` or `qb-target` |
| `'both'`   | Either way                         |
| `'none'`   | Only by command                    |

`Target.Resource = 'auto'` picks up `ox_target` or `qb-target` if either is running. With neither installed, `Mode = 'target'` falls back to the marker and says so in the console.

If you change `InteractKey` away from 38, change `client.interactPrompt` in `config/locales.lua` too. The default prompt writes `~INPUT_CONTEXT~`, which shows whatever the player has bound to E.

A machine can set its own reach:

```lua
{
    coords = vector3(1000.0, 100.0, 50.0), label = 'High Limit',
    interactDistance = 2.0,
    drawDistance     = 15.0,
    interactKey      = 47,                                    -- G
    helpPrompt       = 'Press ~INPUT_DETONATE~ to play {label}',
    marker = { Colour = { r = 240, g = 190, b = 60 }, Pulse = true },
}
```

A machine with its own `interactKey` needs its own `helpPrompt` too. G is `~INPUT_DETONATE~` and H is `~INPUT_VEH_HEADLIGHT~`.

The server refuses an open from more than `interactDistance + 5` metres, and it reads the same per-machine value.

## Blips

Blips are off by default:

```lua
Config.Blip = { Enabled = false, Sprite = 679, Colour = 1, Scale = 0.7 }
```

A machine's own `blip` table puts it on the map even while `Config.Blip.Enabled` is `false`. It can override `Sprite`, `Colour`, `Scale`, `ShortRange` and `Display`, and `Label` gives it its own name on the map:

```lua
blip = { Sprite = 679, Colour = 5, Scale = 0.8, Label = 'High Limit Slots' },
```

## Texts at the machine

`text3d` floats over the machine, `text2d` is shown on screen while standing close. Both take a string, or a table with `Text` and any styling to override:

```lua
text3d = { Text = '~y~{label}~s~~n~Min. bet 5.00', Distance = 10.0 },
text2d = '~y~{label}~s~ - staff only',
```

In the text, `{label}` is the machine's label and `{brand}` the game's name. `~n~` starts a new line, and GTA's colour codes work: `~r~`, `~y~`, `~g~`, `~b~`, and `~s~` back to white. A text can also be given per language, as `{ en = '...', de = '...' }`.

The shared look is in `Config.Interaction.Text3D` and `Text2D`, so most machines need only the text.

| Key                 | Text3D                                        | Text2D                                        |
| ------------------- | --------------------------------------------- | --------------------------------------------- |
| `Distance`          | Drawn within this many metres (8.0)           | Shown within this many metres                 |
| `Offset`            | Metres above `coords`, or a vector3 (1.35)    |                                               |
| `X`, `Y`            |                                               | Screen position, 0.0 to 1.0 from the top left |
| `Align`             | `'centre'`, `'left'` or `'right'`             | Same                                          |
| `Scale`, `Font`     | Size and GTA font                             | Same                                          |
| `Colour`            | Red, green, blue, alpha                       | Same                                          |
| `Outline`, `Shadow` | Text outline and drop shadow                  | Same                                          |
| `Background`        | A box behind the text, or `false`             | Same                                          |
| `Perspective`       | Shrink with distance like a sign in the world |                                               |
| `Fade`              | Fade out over the last metres of `Distance`   | Same                                          |
| `HideWhenOpen`      | Hidden while the game is open                 | Same                                          |
| `HideInVehicle`     | Hidden while the player sits in a vehicle     | Same                                          |
| `RespectJob`        | Hidden from players the `job` lock keeps out  | Same                                          |
| `OnlyNearest`       |                                               | Only the nearest machine's text shows         |

## The player at the machine

```lua
Animation = {
    Enabled  = false,
    Scenario = 'WORLD_HUMAN_STAND_IMPATIENT',
    Dict = nil, Clip = nil, Flag = 1,
    Position = nil,            -- vector3 in the machine's frame
    FaceMachine = true, Heading = nil,
    Freeze = false,
},
```

This block is inside `Config.Interaction`. It is off by default, so the player just stands. With `Enabled = true` the player plays a scenario, or an animation (`Dict` and `Clip`), while the machine is open.

`Position` first moves the player to a point in the machine's own frame: `x` to its right, `y` in front of it, `z` up. One offset therefore works for every cabinet, whichever way it faces. `FaceMachine` turns the player towards the cabinet, and `Freeze` holds them in place.

A machine can set its own:

```lua
animation = { Scenario = 'PROP_HUMAN_SEAT_CHAIR_MP_PLAYER',
              Position = vector3(0.0, 0.7, 0.0), Freeze = true },
```

The casino's own slot animations are in `anim_casino_a@amb@casino@games@slots@male` and need a game build with the casino DLC (`sv_enforceGameBuild 2060` or newer). An animation that does not load prints a warning in the client console, and the player just stands.
