From 87dacfbb3dd16e7f55a82361eace98f9a39d75c8 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Sat, 27 Jun 2026 21:25:20 -0400 Subject: feat: room-specific objects can be defined inline in room yaml --- building_guide/objects.md | 59 +++++++++++++++++++++++++++++++++++++++++++--- building_guide/triggers.md | 12 ++++++---- 2 files changed, 63 insertions(+), 8 deletions(-) (limited to 'building_guide') diff --git a/building_guide/objects.md b/building_guide/objects.md index aaa13e8..37b8e23 100644 --- a/building_guide/objects.md +++ b/building_guide/objects.md @@ -15,15 +15,68 @@ and is still required there.) - **Generic, shared objects** (rocks, trees, altars, stations) use a semantic name and live flat in `data/objects/` — e.g. `data/objects/copper_rock.yaml`. -- **Room-specific one-offs** (signs, set-dressing, scenery for a single room) are prefixed - with the room number and placed in `data/objects/unique/` — e.g. - `data/objects/unique/1001_sign.yaml` (ID `1001_sign`, referenced from room `1001`). +- **Room-specific one-offs** (signs, set-dressing, scenery for a single room): if they are + description-only (the passive subset), prefer defining them **inline in the room** (see + [Inline objects](#inline-objects-defined-in-the-room) below). If a one-off needs + interactable behavior (`gather`/`talk`/`use`/etc.) it must be a file — prefix it with the + room number and place it in `data/objects/unique/`, e.g. `data/objects/unique/1002_sign.yaml` + (ID `1002_sign`, referenced from room `1002`). Loading walks `data/objects/` recursively, so subdirectories are purely organizational and need no changes to room references when a file is moved. They do **not** namespace IDs: every filename stem must be globally unique across all of `data/objects/`. Use `hidden: true` for signage/scenery so it doesn't appear in room listings. +### Inline objects (defined in the room) + +Room-specific **description / scenery** objects can be defined directly inside the room's +`objects:` list instead of as separate files in `data/objects/unique/`. An entry in the list +is treated as **inline** when it carries a `name:` (or any other content field — +`description`, `aliases`, `inroom_description`, `color`, `hidden`, `on_look`). An entry with +only `- id: ` is a plain **reference** to a file object, as before. `id:` is reserved +for references; **inline objects do not take an `id:`** — their identity comes from the name. + +```yaml +# in data/rooms/intro/1001.yaml +objects: + - id: workbench # reference: resolves to data/objects/workbench.yaml + - name: window # inline: identity derived from the name, no file + hidden: true + description: "A thick trim with rounded bolt heads frames the tiny window." + - name: sign + aliases: [safety card, frame] + inroom_description: A large framed sign is mounted near the cockpit door. + description: |- + Conditional or multi-line descriptions work exactly like file objects. + on_look: + set_player_flags: + 1001_look_sign: true +``` + +- **Identity comes from `name`.** Internally the object's id is the name, normalized + (lowercased, surrounding/redundant spaces trimmed, spaces kept — `"Instrument Panel"` → + `instrument panel`). You never write an `id:`; doing so on an inline entry is ignored and + warned about at startup. +- **Identity is room-scoped.** Two different rooms may each have an object named `sign` + without conflict — no room-number prefixing needed (unlike the old `data/objects/unique/` + files). +- **Each object in a room must have a unique name.** Two *distinct* objects in the same room + with the same exact name — whether both inline, both file references, or one of each — is a + startup **error** (the player could not disambiguate them). Multiple instances of the *same* + object are still fine via repeated references (e.g. two `- id: copper_rock`). +- **Partial-name siblings are fine.** `rusty sign` and `shiny sign` can coexist; `look sign` + matches both and prompts *"which one?"*, while `look rusty sign` resolves directly. +- Inline objects support only the **passive subset**: `name`, `aliases`, `color`, `hidden`, + `inroom_description`, `description` (including conditional variants), and `on_look`. +- Interactable / stateful behavior (`gather`, `talk`, `use`, `safespot`, `steal`, `guard_mob`, + `removal_item`, `use_interactions`, craft stations) **must** be a standalone object file; + startup validation errors if those appear inline. +- Inline objects are re-read from the room file on every access, so edits take effect + immediately (file objects are cached after first load). + +Prefer inline for one-room flavor; keep generic/reusable/interactable objects as files. + + Gathering object (mining): ```yaml name: copper rock diff --git a/building_guide/triggers.md b/building_guide/triggers.md index fa97e3a..8d6454c 100644 --- a/building_guide/triggers.md +++ b/building_guide/triggers.md @@ -32,13 +32,15 @@ triggers: ``` The sign object itself is unchanged — its `on_look` simply sets the flag. The trigger -and the object are cleanly separated: +and the object are cleanly separated. The sign is an inline object in room `1001`: ```yaml -# data/objects/unique/1001_sign.yaml -on_look: - set_player_flags: - 1001_look_sign: true +# data/rooms/intro/1001.yaml +objects: + - name: sign + on_look: + set_player_flags: + 1001_look_sign: true ``` This separation is deliberate. The object sets flags. The trigger watches flags. -- cgit v1.2.3