Overview
The spawn screen is the first thing every player sees, every session. Sal's Kewl Spawn Selector replaces qb-spawn with a menu that shows each location as a tile with its own preview image, a live camera fly-over of the spot under the cursor, and a list that changes per player based on their job, gang, licences, items or citizen ID.
It registers itself as a qb-spawn provider, so resources that expect
one keep working.
What it does
- General and job spawns — everyone sees the general list; police see stations, EMS see hospitals, mechanics see garages.
- Last location, with anti-abuse: hidden while a player is dead or in laststand, and optionally for a cooldown after combat, so logging out mid-fight is not a free escape.
- Owned properties through loaf_housing.
- Favorites and recents, starred by the player and stored in their metadata.
- Search, for servers with a long list.
- An in-game editor for admins — see below.
Server-authoritative by design
The client never sends coordinates. It sends an opaque spawn id; the server checks that id against the list that player was actually offered and returns the real coordinates itself. Restricted spawns are never sent to a client who cannot use them, so they cannot be discovered by reading network traffic, and a modified client cannot inject a spawn point, poison its own last location, or refill its own stats.
Requirements
Framework: qb-core, qbx_core or es_extended. Detection is
automatic; Config.Framework = "auto" works out which you run. Force it
with "qb" or "esx" if detection picks wrong.
There are no hard dependencies. Everything below is optional and detected at runtime, so a missing resource degrades gracefully instead of stopping the resource from starting.
| Resource | What you lose without it |
|---|---|
screenshot-basic | The live camera background behind the menu, and image capture in the spawn editor. Tiles still show their configured images. |
loaf_housing | The Properties section. Everything else is unaffected. |
illenium-appearance | Appearance loading before the menu opens. Falls back to qb-clothing if that is running. |
oxmysql | Used only by the illenium-appearance lookup. |
ESX servers, read this. The framework bridge covers ESX for jobs,
metadata, inventory, stats, revive and notifications, but three things are QB-only
and will simply never match on ESX: restrict.gangs (ESX has no gang
concept), restrict.licenses (ESX licences live in a separate resource),
and Config.LastLocation.SuppressWhenDead. Job, grade, citizen ID and item
rules all work normally.
Installation
- Drop the folder into your
resources/directory assals_kewlspawnselector. - Add
ensure sals_kewlspawnselectortoserver.cfg, after your framework and any housing or appearance resource. - Open
config.luaand set your spawn points — or start the server and place them in-game with the editor. - Restart the server.
Replacing qb-spawn
Remove or comment out ensure qb-spawn in server.cfg and
ensure this resource instead. The manifest declares provide 'qb-spawn', so
anything that depends on qb-spawn being present is satisfied.
If your multichar or character-creation resource opens the spawn menu itself, point it at this event instead — see Integration.
Check it started cleanly
With Config.ValidateOnStart on (the default), the server console reports
the framework it detected and then validates every spawn, naming any that are missing a
label, carry invalid coordinates, or point at an image that is not in
html/images/:
[sals_kewlspawnselector] Server loaded (v2.1.0, framework: qb).
[sals_kewlspawnselector] Config validation passed.
A missing image is a warning, not an error — the tile falls back to
default.png.
Where spawns come from
There are two places spawns can live, and it is worth understanding which one your server is using before you start editing.
config.lua | The file you ship with. The defaults, and the only source until somebody saves in the in-game editor. |
|---|---|
data/overrides.json | Written by the in-game editor. Layered
on top of config.lua every time the resource starts. |
The split exists so the editor can never destroy your file.
config.lua is never rewritten — your comments, your
formatting and your ordering all survive.
The two layer differently, and the difference matters:
- Spawn lists — once an admin saves in the editor,
data/overrides.jsonownsConfig.SpawnLocationsandConfig.JobSpawnsoutright. Editing those blocks inconfig.luaafterwards will appear to do nothing. - Settings — merged key by key, so anything you never touched in
the editor still comes from
config.lua.
It tells you when this bites. If you edit the spawn lists in
config.lua after the editor has saved, the resource notices at start and
says so in the server console, and the editor shows a banner. You will not be left
wondering why the file you just edited did nothing.
Putting the file back in charge
Either one works:
- Press Reset to config.lua in the editor, or
- delete
data/overrides.jsonand restart the resource.
Making in-game work permanent
Press Export as Lua in the editor. It generates a
config.lua-shaped block; paste it over the matching blocks at the bottom
of the file, then delete data/overrides.json.
If you would rather never deal with any of this, set
Config.Editor.Enabled = false and config.lua is the only
source, always.
In-game spawn editor
New in 2.1.0. An admin runs /spawnedit and gets a full editor over the
game: add, rename, reorder, duplicate and delete spawns without touching
config.lua or restarting anything.
Permission is checked server-side against
Config.Editor.Permission, the same way the spawn command is. The client
only ever asks; the server decides whether the editor opens at all.
The free-cam
Every spawn needs two positions — where the player lands, and where the preview camera sits — and both are miserable to guess by hand. Press Place with free-cam on any spawn and fly to the spot instead:
| Key | Action |
|---|---|
| W A S D | Fly |
| Q / E | Up / down |
| Shift / Ctrl | Faster / slower |
| G | Drop the spawn point here, snapped to the ground |
| C | Set the preview camera to this exact view |
| X | Capture the tile image from this view |
| Enter | Back to the editor |
A live coordinate readout sits in the corner while you fly, and your character is put back exactly where they were standing when you exit.
Capturing tile images
X screenshots the current view, downscales it, and saves it
into html/images/ under a filename derived from the spawn's name. This
needs screenshot-basic running — the same optional resource the menu
backgrounds use. Turn the whole feature off with
Config.Editor.AllowImageCapture = false.
A freshly captured image cannot be served from disk until the resource restarts, because FiveM expands a manifest's file list once at start. Until then the picture travels inline with the spawn data so players see it immediately, and the resource drops the inline copy by itself on the next start once the file is being served properly. You do not have to do anything.
Access rules and per-spawn actions
The full access rule set is editable per spawn as plain comma-separated fields, so you can gate a spawn behind a job, a gang, an item or a licence without writing Lua. Teleport & test drops you on the spawn point to check it before you commit.
Settings tab
With Config.Editor.AllowSettings on, the editor also exposes the runtime
settings — menu theme and search, feature toggles, favorites, on-spawn stats and the
last-location rules. Saving applies them on the server and pushes them to every
connected player straight away.
Framework, locale, debug and command settings are deliberately not editable
in-game. They are read once when the resource starts, so changing them at runtime would
tell you something untrue. Those stay in config.lua.
Editor settings
Config.Editor = {
Enabled = true, -- Master switch for the editor
Command = "spawnedit", -- Command that opens it
Permission = "god", -- "god", "admin", "mod" or "all"
AllowSettings = true, -- Also allow editing settings, not just spawns
AllowImageCapture = true, -- Allow screenshotting tile images
MaxSpawns = 200, -- Safety cap on how many spawns can be saved
ImageWidth = 640, -- Captured images are downscaled to this width
ImageQuality = 0.82, -- JPEG quality for captured images (0.1 - 1.0)
MaxImageSizeKB = 512 -- Reject a captured image larger than this
}
Do not set Permission = "all". That hands every
player on your server the ability to rewrite your spawn configuration.
Everything the editor sends is re-validated on the server before it is stored — coordinates, labels, job lists, access rules, settings and images alike. If a second admin saves while you have the editor open, your save is refused rather than silently overwriting their work; reopen the editor to pick up their changes.
Spawn & job spawn config
Coordinates use the v4(x, y, z, heading) helper defined at the top of
config.lua. cameraCoords is where the preview camera sits when
a player hovers the tile; leave it out and the camera defaults to 30 m directly
above the spawn.
General spawns
Shown to everyone, unless you add a restrict block.
Config.SpawnLocations = {
{
label = "Downtown Plaza",
coords = v4(215.80, -810.30, 30.70, 338.70),
image = "downtown_plaza.png",
cameraCoords = v4(221.94, -821.05, 30.35, 338.70)
},
}
Job spawns
Only shown to players whose job is in the jobs list. Always use the
array form, even for one job.
Config.JobSpawns = {
{
jobs = { "police", "bcso", "lspd" },
label = "Police HQ",
coords = v4(635.01, 3.46, 82.74, 50.54),
cameraCoords = v4(667.92, -27.50, 82.54, 50.54),
image = "police_hq.png"
},
}
By default the player's job label is prefixed to the tile title
(Police — Police HQ). Turn that off with
Config.UI.HideJobNameInSpawns = true.
Images
Images live in html/images/ and are named in the spawn's
image field. A missing file falls back to default.png rather
than showing a broken tile. Tiles render at roughly 200×120, so there is nothing
to gain from very large source images — and every player downloads them on first
join.
Access rules
Any spawn — general or job — can carry an optional restrict table. A
player sees the spawn only if they pass every rule present. Rules are
evaluated server-side, so a spawn a player cannot use is never sent to them.
{
label = "VIP Lounge",
coords = v4(x, y, z, h),
image = "vip.png",
restrict = {
jobs = { "police", "sheriff" }, -- job must be one of these
minGrade = 2, -- job grade must be >= this
gangs = { "ballas" }, -- gang must be one of these
citizenids = { "ABC12345" }, -- citizenid must be one of these
licenses = { "weapon" }, -- must hold one of these licences
items = { "vip_pass" }, -- must carry one of these items
}
}
Rules combine with AND; the lists inside each rule are OR. The example above means a police or sheriff of grade 2 or higher, who is in the Ballas, whose citizen ID is ABC12345, who holds a weapon licence and is carrying a VIP pass — which is probably nobody. Use one or two rules, not all six.
The jobs = { … } shorthand on a job spawn still works and is equivalent
to restrict.jobs.
All six are editable in the in-game editor without writing Lua. See the ESX note for the two rules that do not apply there.
Settings reference
Everything below lives in config.lua. The groups marked editor
can also be changed in-game on the editor's Settings tab.
General
| Setting | Default | What it does |
|---|---|---|
Config.Debug | false | Verbose client and server logging. Ships off; turn it on only while diagnosing something. |
Config.Locale | "en" | Active language file in locales/. |
Config.ValidateOnStart | true | Check spawns and images at start and report problems. |
Config.Framework | "auto" | "auto", "qb" or "esx". |
Menu — editor
| Setting | Default | What it does |
|---|---|---|
UI.Theme | "dark" | "dark" or "light". |
UI.showCancelButton | false | Let a player back out of the normal spawn flow. |
UI.HideJobNameInSpawns | false | Drop the job label prefix from job spawn titles. |
UI.EnableSearch | true | Show the search box. |
UI.PreviewSettleTime | 250 | Milliseconds to let the camera settle before the background screenshot. |
Features — editor
| Setting | Default | What it does |
|---|---|---|
Features.EnableHousing | true | Show owned properties (needs loaf_housing). |
Features.UseIlleniumAppearance | true | Load appearance via illenium-appearance. |
Features.EnableDynamicBackgrounds | true | Live screenshot behind the menu (needs screenshot-basic). |
Favorites & recents — editor
| Setting | Default | What it does |
|---|---|---|
Favorites.Enabled | true | Let players star spawns and see a Recent row. |
Favorites.MaxRecents | 4 | How many recent spawns to remember. |
On spawn — editor
Applied server-side from config, never from anything the client sends.
| Setting | Default | What it does |
|---|---|---|
Spawn.SetStats | true | Set hunger and thirst on spawn. |
Spawn.Food / Spawn.Water | 100 | The values used when SetStats is on. |
Spawn.SetHealth | true | Restore health on spawn. |
Spawn.SetArmor / ArmorValue | false / 0 | Give armor on spawn. |
Spawn.Invincible.Enabled | true | Brief invincibility so a player cannot die the instant they load in. |
Spawn.Invincible.Duration | 1000 | How long, in milliseconds. |
Last location — editor
| Setting | Default | What it does |
|---|---|---|
LastLocation.Enabled | true | Offer the player's last saved position. |
LastLocation.SuppressWhenDead | true | Hide it while they are dead or in laststand. QB only. |
LastLocation.TrackCombat | false | Watch for combat so the option can be withheld afterwards. |
LastLocation.CombatCooldownSeconds | 300 | How long to withhold it after combat. Needs TrackCombat. |
TrackCombat is the setting that stops players from logging out in a
fight and dropping straight back onto the same spot. It is off by default because it
runs a lightweight client-side check; turn it on if combat logging is a problem on
your server.
Commands
Both are permission-gated, and both check permission on the server.
| Command | Does | Default permission |
|---|---|---|
/sals_testspawn | Opens the spawn selector on demand. Name,
permission and cancel-button behaviour are set in Config.Command. |
god |
/spawnedit | Opens the spawn editor.
Set in Config.Editor. | god |
Permission levels are "god", "admin", "mod"
and "all". On QB these map to the framework's own permission system; on ESX
they map to ACE principals. Set enabled / Enabled to
false to remove either command entirely.
Integration
Opening the selector from another resource
The normal spawn flow — multichar, character creation, respawn — is driven by one client event:
-- Server-side, for a specific player:
TriggerClientEvent('sals_kewlspawnselector:openSelector', playerId)
-- Client-side, e.g. from your own multichar handler:
TriggerEvent('sals_kewlspawnselector:openSelector')
When a player finishes spawning, the resource fires
sals_kewlspawnselector:spawned on the client for your scripts to listen
for.
Customisation files
Two files exist to be edited and are kept separate from the rest so they survive updates:
client_customize.lua | Appearance loading and the housing
lookup. Replace CustomFunctions.GetPlayerHouses to support a housing
resource other than loaf_housing — it returns a list of
{ propertyId, label, coords, image, cameraCoords }. |
|---|---|
server_customize.lua | CanOpenMenu(src) —
return false to block the menu for a player. OnPlayerSpawned(src,
key) — runs after a spawn is committed. |
Translations
No user-facing text is hardcoded. locales/en.lua is the baseline; copy
it to locales/<code>.lua, translate the values, and set
Config.Locale. Missing keys fall back to English, so a partial translation
is safe to ship.
Troubleshooting
| Symptom | What to check |
|---|---|
Edits to config.lua spawns do nothing |
The in-game editor has saved, so data/overrides.json owns the spawn
lists. The server console says so at start. See
Where spawns come from. |
| Players fall through the map | The z in that spawn's coordinates is below the floor. Stand on the
spot and use Use my position in the editor, or
G in the free-cam, which snaps to ground level. |
| Black screen, no menu | Check the server console for a config validation failure, and that
ensure sals_kewlspawnselector comes after your framework in
server.cfg. If another resource also handles spawning, they will fight
— qb-spawn in particular must not be running. |
| Job spawns do not appear | Job names in jobs = { … } must match your framework's internal job
names exactly, not the display labels. Turn on Config.Debug to see the
job the server read for that player. |
| Properties do not appear | loaf_housing must be started and
Config.Features.EnableHousing on. Another housing resource needs
CustomFunctions.GetPlayerHouses adapted — see
Integration. |
| Tiles show the default image | The named file is not in html/images/. Start-up validation names
every spawn this affects. Filenames are case-sensitive on Linux servers. |
| No live background behind the menu | screenshot-basic is not running, or
Config.Features.EnableDynamicBackgrounds is off. |
/spawnedit does nothing |
Permission is checked server-side — you are not in the group named by
Config.Editor.Permission. The editor also refuses to open while the
normal spawn menu is up, since the two would fight over the camera. |
| A captured image will not save | The resource folder must be writable by the server process. The editor reports the failure on screen and the server console names the file it could not write. |
When something is not behaving, Config.Debug = true logs the spawn flow
on both sides. Turn it back off afterwards — it is noisy.
Support
Support, release news and coupon codes are on Discord. Purchases are handled by Tebex, who own the checkout, billing support and refunds.
The resource ships its own copy of this manual at
docs/help.html inside the download, including the full changelog.