Elevator UI
The elevator panel is the React-based NUI interface that players see when they use an elevator. It is fully immersive, themed per elevator, and adapts to any screen resolution. This page documents every element, state, and interaction available in the panel.
Opening the UI
When a player enters the interaction zone of an elevator floor (either a Volumetric Box or an Entity Target) and presses the configured interact key (default: E), the elevator panel opens.
Before the panel becomes visible, the themed background image is preloaded silently. The UI only appears once the image is fully downloaded, preventing any visual flash or blank frame.
Pressing ESC closes the UI when idle. During a ride or after arriving, ESC is blocked — the player must interact with the panel buttons first.
Themed Background
Each elevator has an Animation Style (set in the Dashboard → General tab) that determines the full-screen background rendered behind the panel:
| Style | Internal Key | Visual |
|---|---|---|
Industrial Metal | Metal | Dark metallic industrial interior |
Classic Wood | Wood | Warm wooden panelling |
Luxury Gold | Gold | Elegant gold-trimmed cabin |
The background is resolution-aware and automatically selects the correct artwork variant based on the player's screen resolution:
| Resolution | Variant used |
|---|---|
| 1920×1080 | Regular |
| 2560×1080 (ultrawide) | Large |
| 2560×1440 | Regular |
| 3440×1440 (ultrawide) | Large |
| 3840×2160 (4K) | Large |
The entire panel UI also scales proportionally to the background using a cover-scale algorithm, so it always appears correctly positioned and sized relative to the cabin artwork regardless of resolution.
Panel Layout
The elevator panel is rendered as an in-world control interface, slightly rotated (0.7deg) to give a natural tilted-panel feel. It consists of four main zones stacked vertically:
┌─────────────────────────┐
│ [Watermark logo] │
│ ┌───────────────────┐ │
│ │ ▼ [0][7] ▲ │ │ ← HUD Display
│ └───────────────────┘ │
│ ┌───────────────────┐ │
│ │ [0] [1] [2] [3] │ │ ← Floor Buttons
│ │ [4] [5] [6] [7] │ │
│ └───────────────────┘ │
│ :::::::::::::::::::: │ ← Speaker grille (decorative)
│ ┌───────────────────┐ │
│ │ [◁❘▷] [+] [☏] │ │ ← Controls Row
│ └───────────────────┘ │
└─────────────────────────┘HUD Display
The segmented display at the top of the panel shows the current floor number in real-time as the elevator moves between floors.
| Element | Description |
|---|---|
| Two-digit display | Shows the current floor using a 7-segment font. Floors below 10 are zero-padded (e.g., floor 3 → 03). Negative floors show a - prefix. |
| ▼ arrow | Lit up in red when the elevator is moving downward (current floor > target floor). |
| ▲ arrow | Lit up in red when the elevator is moving upward (current floor < target floor). |
During the ride, the displayed floor number counts up or down one step at a time, synchronized with the Speed setting in config.lua (each step = one interval of Speed ms).
Floor Buttons
The panel displays one button for every floor configured in the Dashboard. Buttons are ordered numerically and rendered in a grid.
Button States
Each button can be in one of the following visual states:
| State | CSS class | Description |
|---|---|---|
| Default | (none) | Available floor, not selected, not current. |
| Locked | locked | This floor has access restrictions the player does not meet (wrong job or missing item). Clicking plays the error sound. |
| Active | active | The floor currently selected as the destination. Highlighted. |
| Passing | passing | The floor the elevator is currently passing through during motion. |
| No Click | noClick | Applied to all buttons when the player is a Guest (not the host). Buttons are visually disabled. |
Button Content
- Floor number — always shown (e.g.,
0,1,10). - Floor label — shown as a secondary line below the number only if the label is longer than 3 characters (configured via the Dashboard → Floors tab → Registry Label). Short labels (≤ 3 characters) are omitted to avoid clutter.
Click Behavior
When a valid floor is clicked:
- The target floor is set and the button becomes
active. - The door closing animation begins (1 second delay).
- The ride starts (see Ride Lifecycle).
Clicking an already active floor or the current floor plays the error sound and does nothing.
Controls Row
Three buttons are always shown at the bottom of the panel.
Open Doors (◁❘▷)
- Available only after arriving at a destination (state:
PRESS TO OPEN). - Clicking starts the door-opening animation (
openingstate) and plays the ding sound. - After 1.5 seconds, the server is notified, the teleport is finalized, and the UI auto-closes after 2 seconds.
- Disabled during motion (
inMotion = true).
Invite (+)
- Visible only to the Host (the player who opened the elevator).
- Clicking fetches the list of nearby players from the server and toggles the Invite Panel.
- Button appears
active(highlighted) while the invite panel is open.
Alarm (☏)
- Available to all players in the elevator (Host and Guests).
- Clicking plays the elevator alarm sound effect (
elevator_alarm.mp3). - Purely cosmetic / roleplay feature.
Invite Panel
When the Host clicks the + button, an overlay panel slides in over the floor buttons showing nearby players.
┌───────────────────────┐
│ NEARBY PLAYERS [x] │
│ ─────────────────── │
│ PlayerName [+] │
│ AnotherPlayer [+] │
│ (No players nearby) │
└───────────────────────┘| Element | Description |
|---|---|
| Header | Title text from MBT.Locale.nui_nearby. The [x] closes the panel. |
| Player row | Shows the player's name and an invite action button. |
| Empty state | If no players are nearby, shows the text from MBT.Locale.nui_no_players. |
Invite Button States
The invite button for each player cycles through states as the interaction progresses:
| Button | State | Meaning |
|---|---|---|
+ | Default | No invite sent yet. Click to send. |
... | sent | Invite sent, waiting for the guest to respond. |
✓ | accepted | Guest accepted. They are now synchronizing with this ride. |
x | refused | Guest declined the invite. |
Once an invite is sent, the button for that player is disabled (clicking again has no effect) until the status updates from the server.
Ride Lifecycle
A complete elevator ride goes through the following phases:
1. [IDLE] → Player clicks a floor button
2. [CLOSING] → Door animation plays (1 second)
3. [IN MOTION] → Floor counter ticks, trip audio plays
ESC is blocked during this phase
4. [ARRIVED] → Counter stops, "PRESS TO OPEN" appears
Trip audio stops, ESC still blocked
5. [OPENING] → Player clicks Open Doors, ding plays
6. [CLOSED] → Server teleports player, UI auto-closes after 2sLoading States
While the elevator is in motion or arrived, a centered overlay is shown:
| State | Text shown | Visual |
|---|---|---|
| In motion | MBT.Locale.nui_wait (default: PLEASE WAIT) | Animated spinning SVG |
| Arrived | MBT.Locale.nui_open (default: PRESS TO OPEN) | Text only, no spinner |
Co-op Ride Sync
When a guest accepts an invite:
- The server notifies the guest's client to open the elevator UI.
- The guest's UI enters Guest mode — all floor buttons receive the
noClickclass, preventing any interaction. - When the host selects a floor and departs, a
startSharedTripevent is sent to the guest. - The guest's UI starts the same ride animation independently, synchronized by floor target.
- The server handles the actual teleportation for both players simultaneously.
Guests see the full panel UI including the floor counter animation but cannot control the destination or open the doors.
Audio
The elevator UI uses four independent audio tracks:
| File | Volume | When played |
|---|---|---|
elevator_trip.mp3 | 0.4 | Loops during the ride (motion phase). Stops on arrival. |
elevator_ding.mp3 | 0.4 | Plays once when the player presses Open Doors. |
error.mp3 | 0.1 | Plays on invalid interactions: locked floor, clicking current floor, clicking while guest. |
elevator_alarm.mp3 | 0.4 | Plays when the alarm button is pressed. |
All audio is client-side only (Web Audio API via the browser NUI context).
Watermark
If MBT.ElevatorSettings.Watermark = true in config.lua, the MalibuTech logo is rendered above the panel. Set to false to remove it.
Localization
All text strings shown in the elevator UI are pulled from MBT.Locale in config.lua and sent to the NUI on resource start:
| Locale key | Where it appears |
|---|---|
nui_wait | Loading overlay during the ride |
nui_open | Loading overlay when arrived at destination |
nui_nearby | Invite panel header |
nui_no_players | Invite panel empty state |
Edit these values in config.lua to translate or customize the panel text without touching any UI files.
