garages
Last updated on
Garage markers where a player brings out one of their own vehicles or puts the one they sit in away.
Glowing markers where players fetch and park their own vehicles. On foot at a menu point or at the entry point, the key (E by default) opens the list of every vehicle filed under that garage. Sitting in one of your own vehicles at the entry point, the same key puts it away. A vehicle comes out at the first free exit of the location you stand at. Garages are written in config/garages.lua; nothing is placed in game.
| Side | both |
| Requires | character (hard) |
| Optional | vehicles, prompts, downed, menu, vehiclekeys |
| Contract | garages v1 — server, client |
| Config | config/garages.lua (shared) |
| Data | opx77_garages (legacy, read-only) |
- Without
vehiclesevery request is refused. - Without
menuthe list cannot open;/opx.garages.bringstill works. - Without
promptsthe markers still draw, only the key row is missing. - With
vehiclekeys, the owner is given a key on the way out when their bag holds none to that plate; a full bag is said to the player and does not stop the car coming out.
How a garage works
- A garage is a key (e.g.
garage1). A vehicle'sgaragecolumn holds that key, so a car stored at one location comes out at every location of the same garage. - Each location has one
MENUpoint (opens the list), oneENTRYpoint (takes the car you sit in) and an ordered list ofEXITS. - Exits are tried in the order written. An exit is taken when any vehicle in the same routing bucket is within
EXIT_CLEARANCEmetres (the car being fetched never blocks its own exit), or when it is promised to another bring-out still spawning: two players fetching at once get two exits, never one car inside the other. A promise lapses after 10 s. All taken:garages.noFreeExit. - Put away or bring out is decided by the server from the host's seat assignment, never by the client. Sitting in someone else's car at the entry point is refused with
garages.notYours("Only your own vehicles go in here."), instead of bringing one of yours out beside you. On foot, the entry point opens the list and its prompt reads Open your garage; a player with two cars filed there picks one. - The list shows each car as
Villefort Cortes · 8XK2L0P: the same name as its key (OPX.Vehicle.DisplayName), the plate as the value. - A refused bring-out is one toast that names the garage (no more three toasts and a platform notice).
- Toasts name the car as the list does: Brought out Archer Hella · AA111AA., Put away …, Recalled … here. for a car already out that was moved. The staff bring command uses the same words.
- A player who is down is refused (
error.incapacitated). A refusal names back the garage key only when it is a known spot or garage. - E is shared with doors, dealers, fitting rooms, lifts and teleports: the nearer spot acts, and only its prompt row is drawn; while the list is open, E closes it (rank
OPEN). See One press, one owner. - A car with passengers is not put away:
garages.passengersuntil they get out. - The nearest point is searched in the player's own bucket only, so an instanced copy on the same spot does not get in the way.
- A car of yours already out elsewhere is moved to the exit (see
vehicles.Spawn); refused withvehicle.occupiedif anyone sits in it. KIND = 'garage'brings out ground vehicles only;KIND = 'avpad'AVs only. An AV is createdAV_LIFTmetres above the exit. Which records are AVs isAV_PREFIXESinconfig/shared.lua.
Legacy table opx77_garages
/opx.garages.addand/opx.garages.removeare gone.- At every boot the server reads
opx77_garagesand adopts each row whose key is not inGARAGESas a garage of one location whose menu, entry and only exit are the captured point. - Each adopted garage is printed to the server log as
[garages] config line: ..., ready to paste intoconfig/garages.lua, then a warning says how many exist only in the table. - A config garage with the same key wins. Nothing writes to or drops the table.
Commands
command.opx.garages.* grants both. Names come from COMMANDS.
Configuration
config/garages.lua sets OPX.Config.MODULES.garages. Shared script.
| Key | Default | Effect |
|---|---|---|
enabled | true | false switches the module off. |
USE_RADIUS | 4.0 | Flat metres from a point's X/Y within which it can be used. The server allows REACH_SLACK (1 m) more. |
EXIT_CLEARANCE | 3.0 | Flat metres around an exit that must be free of vehicles. |
MARKER | garage = cylinder/spawn/2.5, avpad = ring/objective/3.5, entry = ring/interaction/3.0 | Marker look per kind (menu points) and for entry points. Each { shape, style, RADIUS }. |
MAX_DISTANCE | 150.0 | Metres beyond which a marker is not drawn (1–500). |
GROUND_OFFSET | 0.06 | Metres the marker is lifted off Z (0–2). A ring at exact floor height is invisible. |
AV_LIFT | 1.2 | Metres above the exit an AV is created (0–10). |
SCAN_MS | 500 | Client marker scan interval. |
POLL_MS | 15000 | How often the client re-asks for its points. |
REQUEST_WINDOW_MS | 10000 | Length of the per-player request window. |
REQUESTS_PER_WINDOW | 6 | Requests per window (bring-outs and lists together). |
COOLDOWN_MS | 3000 | Minimum gap between two bring-outs from one player. |
KEY | { ID = 'opx.garages.use', NAME = 'garages.key.use', DEFAULT = 'E' } | The key mapping. ID is stable (rebinds are stored under it). DEFAULT = false registers no key. |
MENU | { ANCHOR = 'center', WIDTH = 560, HEIGHT = 560, MAX_HEIGHT_VH = 88, VISIBLE_ROWS = 12 } | Size of the list panel. The menu module clamps every value. |
COMMANDS | { list = 'opx.garages.list', bring = 'opx.garages.bring' } | Command names. An empty name registers nothing. |
GARAGES | garage1, garage2 (one location each) | Every garage. See below. |
Markers use the engine vocabulary: shape ring or cylinder; style interaction, objective, spawn or danger; RADIUS 0.1–50. A bad field falls back to the module default and is reported at boot.
GARAGES = {
garage1 = { -- the key: 1-48 chars, never rename it
LABEL = 'Watson Garage', -- shown to players, not translated; defaults to the key
KIND = 'garage', -- 'garage' (ground vehicles) or 'avpad' (AVs)
LOCATIONS = {
{
BUCKET = 0, -- routing bucket of the whole location
MENU = { X = -1527.21, Y = -218.56, Z = 7.86 },
ENTRY = { X = -1527.21, Y = -218.56, Z = 7.86, HEADING = 199.6 },
EXITS = {
{ X = -1527.21, Y = -218.56, Z = 7.86, HEADING = 199.6 },
},
},
},
},
}- Every point follows the shared spot rules (spot helpers):
X,Y,Zfinite and within ±1,000,000;HEADINGfinite (default0);BUCKETa whole number ≥ 0 (default0). Only X and Y are measured against. - A garage with any bad point, no location, or a location without exits is refused whole, with a boot warning naming it.
- To capture a point, stand on it facing the way a car should come out and run
/opx.admin.self.pos; it copies position and heading to your clipboard.
Never rename a garage key. Every vehicle filed under the old key is orphaned.
Refusal codes
Each code is also a locale key. Codes from vehicles (vehicle.occupied, vehicle.busy, vehicle.spawnRefused, …) pass through unchanged.
| Code | Meaning |
|---|---|
garages.noVehicles | No vehicles contract on this server. |
garages.noCharacter | No character loaded. |
garages.noPosition | The player's position could not be read. |
garages.noSuchSpot | No point underfoot, or the named key does not exist. |
garages.wrongBucket | The point is in another routing bucket. |
garages.tooFar | Further than USE_RADIUS from the point. |
garages.nothingHere | The player owns nothing of this garage's kind. |
vehicle.notFound | The named plate is not one of the player's eligible vehicles. |
garages.noFreeExit | Every exit of the location is taken. |
garages.notYours | Seated in a car that is not yours at the entry point. |
garages.passengers | Passengers are still in the car you want to put away. |
error.incapacitated | The player is down. |
garages.rateLimited | Cooldown or request window (bring-outs). |
error.tooFast | Request window (lists). |
error.noPermission | Client side only: another surface holds the keyboard. |