# Features

## The 3D map

The map is the same 3D layer as the [Koja Dispatcher](/new/dispatcher): GTA V radar tiles with level of detail, terrain from the in-game heightmap and extruded buildings, graded in the warm Koja Appearance colours. Up close it streams sharper tiles from the Rockstar map CDN (`Config.Map.OnlineDetail`).

| Control | Action |
| --- | --- |
| Left drag | Move the map |
| Right drag | Rotate and tilt the camera |
| Scroll | Zoom at the cursor |
| `+` / `−` / crosshair (right dock) | Zoom in, zoom out, back to the selected spot |
| Click a pin | Select it. Click the selected pin again to spawn |

When the map opens, the camera starts high above the island and glides down to the preselected spot. A pulsing ring and a light beam in the accent colour mark the selected location.

### Time and weather

The map follows the server: it gets darker and bluer at night, warm at dusk, grey and foggy in bad weather, and shows rain or snow falling (`Config.Map.ShowWorld`). The badge in the top right shows the game time and the weather.

### Route from the last location

When the player has a last location, the map draws the road route from there to the selected spot with its length ("1.8 km from last location"). It uses the koja-dispatch road graph (`data/roads.json`) and an A* search on the server (`Config.Roads`).

### Blips

Spawns can use GTA blip icons (`blip = 'radar_police_station'`), and game blips of the sprites in `Config.Map.GameBlips.Sprites` (police stations, hospitals, shops...) are shown on the map for orientation.

## Live preview

The card at the top of the panel is a window into the game: a scripted camera circles the selected spot and the player sees the real place — the time of day, the weather, the cars and people there. The UI is cut out around the window so nothing is drawn over the game.
A location with a photo shows the photo instead. Turn it off or tune the camera in `Config.LivePreview` (`Distance`, `Height`, `Fov`, `Orbit` degrees per second).

## The location panel

- **Header** — position in the list (`03 / 08`) and the server name.
- **Banners** — why the list is restricted (jail, hospital) or why the last location is locked.
- **Card** — live preview or photo, category, description, street, how long ago the last location was saved, the time left of an event and "With vehicle".
- **Search** — filters by name, description, street and zone.
- **Favourites** — the star on each row; favourites are listed first and get their own toolbar filter. Saved on the player's PC.
- **List** — every location grouped by category. Locked spots show a lock and their label ("Police only").
- **Toolbar** — at the top of the map, filters the list and the pins by category.
- **Footer** — **Spawn here**, and an exit button when cancelling is allowed.

| Key | Action |
| --- | --- |
| `↑` / `↓` or `W` / `S`, mouse wheel over the list | Browse |
| `Enter` | Spawn at the selected spot |
| `Esc` | Close, when cancelling is allowed |
| `+` / `-` | Zoom |

## Locks

Locks are decided on the server when the list is built:

1. `jobs` (with minimum grade and `onDuty`)
2. `gangs`
3. `ace`
4. `ServerEditable.CanAccess`
5. Every check added with `AddAccessCheck`
6. [Restrictions and last location rules](/new/spawn-selector/anti-combat-log)

The first one that says no locks the spot, and its reason becomes the label. When the player confirms, the server looks the spot up in the list it sent and refuses locked or unknown ids, so a modified UI cannot spawn anywhere else.

## Last location

The position of every spawned player is saved every `SaveInterval` seconds, on logout, on disconnect and when the resource stops.
Positions in a routing bucket other than 0 are skipped when `IgnoreBuckets` is on. Tracking starts only after the player landed. Combat logouts and deaths lock it — see [Anti combat log](/new/spawn-selector/anti-combat-log).

## Spawn in a vehicle

A spawn with `vehicle = 'sultan'` (or `{ model, plate, props, fuel, keys }`) puts the player in the driver seat. The vehicle is created when the camera reaches the street, the last camera move frames the car, keys are given through koja-lib and fuel is set. `ClientEditable.OnVehicleSpawned` runs afterwards.

## Sounds

All sounds are synthesised in the browser, so there are no audio files: a soft ambient pad while the selector is open, ticks when browsing, a chime on confirm and a whoosh for the flight. `Config.Sound` sets the volume, turns the ambient off, or plays your own `Music` URL instead.

## The camera flight

1. The ped is placed and frozen, streaming starts around the spot.
2. A top-down shot from `Height` metres.
3. A descent to a shot behind and above the ped.
4. The game waits for collision and the scene (up to `LoadTimeout`), then the ped (and vehicle) appears.
5. A last move over the shoulder and a blend into the gameplay camera.

A letterbox and a "Spawning into" card are shown over the flight. Set `Config.Cinematic.Enabled = false` or `cinematic = false` on a spawn for a plain fade.

## Integrations

| With | What happens |
| --- | --- |
| ESX | Opens on `esx:playerLoaded`. New characters skip it unless `Config.NewCharacter.UseSelector` is on |
| QBCore / QBox (qb-multicharacter) | Replaces `qb-spawn`. New characters with `qb-apartments` pick a starter apartment |
| [Koja Multicharacter](/new/multicharacter) | Opens this map after character selection |
| Housing | Owned properties are listed under Property for **qb-houses**, **qs-housing**, **ps-housing**, **esx_property**, **nolag_properties** and **bcs_housing** (`Config.Housing`) |
| Jail / ambulance | QB `injail` / `isdead`, ESX `users.jail_time`, `users.jail`, `users.is_dead` |
| screenshot-basic | Photos in the [location editor](/new/spawn-selector/admin-tools) |
| No locations at all | The player gets a message and spawns at `Config.Fallback` |

:::hint{type="info" title="Housing providers"}
qb-houses, ps-housing and esx_property are read straight from their published database schema. qs-housing, nolag_properties and bcs_housing are paid resources: their providers follow the schema / exports those scripts expose, wrapped so a different version can never break the screen. If one of them does not list your houses, set it to `false` in `Config.Housing` and add a [provider](/new/spawn-selector/developer-api#registerprovider-removeprovider) for your version.
:::
