> For the complete documentation index, see [llms.txt](https://visionstore.gitbook.io/visionstore-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://visionstore.gitbook.io/visionstore-docs/scripts/advanced-clothing/configuration/showroom.md).

# Showroom

Let players shop inside a private showroom interior and send them back to the exact spot afterwards.

The showroom is **optional and off by default**. With it off, every shop opens right where the player stands and nothing on this page matters.

With it on, opening a store fades the screen to black, moves the player into a **routing bucket of their own** (nobody else can be seen or heard there) and teleports them into a showroom interior. When the session ends for any reason (confirm, cancel, death, disconnect or a resource restart), the player is put back on the exact spot and heading they left, in the shared world, and back in the vehicle seat they opened from.

## Turn it on

`config/config.lua`:

```lua
Config.Scene = {
    enabled = false,
    interiors = {
        { label = "Showroom", coords = vec4(-1003.24, -484.33, 44.68, 121.34) },
        -- { label = "My boutique", coords = vec4(0.0, 0.0, 0.0, 0.0) },
    },
    modes = { shop = true },        -- Constants.MODE_DEFAULTS keys that get the scene ("character_creator" is always refused)
    ...
}
```

1. Set `enabled = true`.
2. Make sure `interiors` lists an interior your server has.
3. Restart the resource.

## Choosing the interior

`interiors` is tried in order, and the **first entry whose interior (MLO) exists on your server** is used. Missing interiors are skipped, so it is safe to list MLOs you may not have. If none exists, the shop simply opens in place and F8 prints `Config.Scene: none of the configured showroom interiors exists on this server`.

Add your own MLO with one line. `coords` is `vec4(x, y, z, heading)`: the floor where the player stands and the direction they face.

```lua
{ label = "My boutique", coords = vec4(123.4, -567.8, 30.0, 90.0) },
```

Set `requireInterior = false` on an entry to skip the detection (an open-air spot, or a base-game room the game doesn't report as an interior).

`modes` lists which kinds of session get the showroom. Only clothing stores (`shop`) by default; add others like `boutique = true`. The character creator is never sent to the showroom: it has its own isolation through illenium's routing bucket.

## All options

```lua
    fadeOutMs = 500,                -- ms the screen takes to go black before the teleport
    fadeInMs = 500,                 -- ms the screen takes to come back after the teleport
    holdMs = 250,                   -- ms held on black AFTER the teleport (both ways), so the world can stream in
    collisionWaitMs = 2000,         -- max ms spent on black waiting for collision around the ped (0 = never wait)
    bucketWaitMs = 2000,            -- max ms on black waiting for the server to confirm a bucket swap
    handOverWaitMs = 2000,          -- max ms on black waiting for the cars this client simulated to be handed off
    simulatedVehicleRadius = 150.0, -- metres around the player those cars are looked for in
    vehicleWaitMs = 2000,           -- max ms on black waiting for the player's car to stream back in on exit
    freezeDuringTransition = true,
    restoreVehicle = true,          -- a player who opened from a vehicle is put back into the same seat
    privateBucket = true,           -- false => teleport only, everybody stays in bucket 0
    bucketBase = 700000,            -- bucket id = bucketBase + player server id, so it is unique per player.
    disablePopulation = true,       -- ambient peds / vehicles off inside the scene bucket
    verifyRadius = 30.0,            -- metres from a showroom's coords that still count as "in the showroom"
    verifyGraceMs = 15000,          -- ms after the grant before the position is enforced (fade + streaming)
    maxHoldMs = 30 * 60 * 1000,     -- hard ceiling on a single scene bucket (wedged NUI, AFK, exploit)
    sweepIntervalMs = 5000,         -- how often the server re-checks every held bucket (0 = never sweep)
    recoverOnRejoin = true,
    recoverDelayMs = 5000,          -- ms after the client starts before it asks the server for a pending return
    recoverExpiryMs = 60 * 60 * 1000, -- a recorded return older than this is dropped (he spawned elsewhere since)
```

| Option                                      | Default          | What it does                                                                                                                                |
| ------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `fadeOutMs` / `fadeInMs`                    | `500` / `500`    | Fade to black before the teleport / back in after it.                                                                                       |
| `holdMs`                                    | `250`            | Time held on black after the teleport so the world can load.                                                                                |
| `collisionWaitMs`                           | `2000`           | Maximum wait for collision around the ped.                                                                                                  |
| `bucketWaitMs`                              | `2000`           | Maximum wait for the server to confirm the bucket change.                                                                                   |
| `handOverWaitMs` / `simulatedVehicleRadius` | `2000` / `150.0` | Hand nearby vehicles this client was simulating to someone else before leaving.                                                             |
| `vehicleWaitMs`                             | `2000`           | Maximum wait for the player's own vehicle to load back in on exit.                                                                          |
| `freezeDuringTransition`                    | `true`           | Freeze the player from the moment the return spot is recorded until they land again.                                                        |
| `restoreVehicle`                            | `true`           | Put the player back in the vehicle seat they opened from.                                                                                   |
| `privateBucket`                             | `true`           | `false` = teleport only, everyone stays in the shared world.                                                                                |
| `bucketBase`                                | `700000`         | Bucket id = `bucketBase + server id`. Must stay above `1000` (`Config.SceneMinBucketBase`).                                                 |
| `disablePopulation`                         | `true`           | No ambient peds or traffic inside the showroom bucket.                                                                                      |
| `verifyRadius`                              | `30.0`           | Metres from a showroom that the server still counts as "in the showroom".                                                                   |
| `verifyGraceMs`                             | `15000`          | Time before the server starts checking that position.                                                                                       |
| `maxHoldMs`                                 | 30 minutes       | Hard limit on one showroom visit.                                                                                                           |
| `sweepIntervalMs`                           | `5000`           | How often the server re-checks every player in a showroom. A player outside the showroom or over the limit is released and the menu closes. |
| `recoverOnRejoin`                           | `true`           | A player who disconnects in the showroom is put back by the server on their next join.                                                      |
| `recoverDelayMs`                            | `5000`           | Delay after joining before that return happens.                                                                                             |
| `recoverExpiryMs`                           | 60 minutes       | A recorded return older than this is dropped.                                                                                               |

{% hint style="info" %}
The bucket is always chosen by the server from the player's server id; a client can only ask to enter or leave. While a player is in the showroom, the checkout distance check uses the spot the server recorded when the store opened.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://visionstore.gitbook.io/visionstore-docs/scripts/advanced-clothing/configuration/showroom.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
