OPX//77
opx_infinityspawn

spawn

Last updated on

The spawn menu — where a character starts when it enters the world, chosen from a fixed list of places.

Shows a menu of places when a character enters the world and puts the character where the player clicks. Which joins get the menu is set by OFFER_POLICY: the shipped 'first' asks only a character that has never been placed, so a returning player resumes where they left. A player who picks nothing before the deadline is placed by character from their stored position, or at DEFAULT_SPAWN. The coordinates live in the config and never cross the wire: the client sends only the id of a place. Turn it off and every character is placed by character alone.

Sideboth
Requirescharacter (read with OPX.Api.Require at start)
Optionalentry (client: the menu waits for it)
Contractspawn v1 — server
Configconfig/spawn.lua (shared)
Datanone

How a choice runs

  1. When a joining character gets a living body, character calls spawn.Offer(source, citizenId). A /opx.select switch inside the world is placed directly and never offered the menu; a menu still open for the previous character is dropped when it unloads (or replaced by an offer for the new one).
  2. Offer answers false (character places the body itself, at once) when the module is off, the policy is 'never', no location is usable, a choice is already open, or the policy is 'first' and the character already has a stored position.
  3. Otherwise it sends opx:net:spawn:offer. The client opens the menu as soon as entry reports itself idle (name form and fitting room done) and reports opx:net:spawn:opened.
  4. The player's window (TIMEOUT_SECONDS) starts at that report. Before it, only HOLD_MAX_SECONDS can end the offer.
    • While the name form or the fitting room is up, the client tells the server every 30 s (opx:net:spawn:waiting). Each report pushes the hold a full HOLD_MAX_SECONDS on, never past 30 minutes from the offer, and stops once the menu is on screen. A slow new player is no longer placed under an open modal.
  5. A character whose row holds a position gets a first card, Where I left off (Là où j'étais, id resume): choosing it places the character with no target, so the stored position decides. A character that has never stood anywhere does not get it.
  6. A click sends the place id. The server looks it up in its own list and calls character.PlaceCharacter. A timeout places the character with no target (stored position, then DEFAULT_SPAWN). The menu goes down at once; "Spawned at …" is said only once the body has moved, and a refused placement says "You could not be moved there."

Configuration

config/spawn.lua sets OPX.Config.MODULES.spawn.

KeyDefaultEffect
enabledtruefalse does not load the module; every character is placed by character.
OFFER_POLICY'first''first': only a character with no stored position. 'always': every join (picking nothing resumes). 'never': nobody; no hold, no clock. Unknown values fall back to 'always' with a warning.
TIMEOUT_SECONDS45Time to choose once the menu is on screen (floor 5).
HOLD_MAX_SECONDS300Longest a character waits unplaced for a menu that never opens (floor 60). Covers the name form and fitting room too: do not set it below the time a new player needs for those.
CHOOSE_COOLDOWN_MS1000Rate limit on opx:net:spawn:choose.
WAIT_FOR_ENTRYtrueThe menu waits until entry reports idle (name and clothes done).
LOCATIONS11 placesList of { id, label, district, x, y, z, heading }. See below.
config/spawn.lua — one LOCATIONS entry
{ id = 'stoop', label = 'King Stoop forecourt', district = 'Watson', x = -410.22, y = 722.73, z = 115.0, heading = 147.0 },
  • id: 1–32 characters of letters, digits, _ : - .; unique. Sent on the wire, so do not rename one. resume is reserved for the Where I left off card: an entry with that id is dropped with a warning.
  • label: 1–48 characters, shown on the card.
  • district: up to 32 characters, the hint line. Optional.
  • Both are translatable: the menu and the Spawned at toast show the locale lines spawn.place.<id> and spawn.place.<id>.district when they exist (en and fr ship for every shipped place), else this config text.
  • x, y, z: finite numbers. Copy them from the game; a guessed coordinate can drop the player through the world.
  • heading: degrees; missing means 0.0 (north).
  • A bad entry is dropped with a warning at start. At most 64 entries are used.

Refusal codes

CodeMeaning
spawn.noChoiceNo choice is open for you, the id is not in the list, or resume was asked by a character with no stored position.
error.tooFastClicked again inside CHOOSE_COOLDOWN_MS.

On this page