-
Notifications
You must be signed in to change notification settings - Fork 0
Pack Entity Reference
Audience: Builder Status: ✅ Ready
This is the exhaustive field-level lookup for every entity and definition a content pack can declare: the world subtree (zones, rooms, exits, prototypes, resets) and every pack-global def-table. For each, this page gives the YAML keys, which are required vs optional, and what a field cross-references. Where a field's runtime behavior is owned by another subsystem (combat, abilities, progression, loot, crafting, scripting), the YAML shape is documented here and the semantics are cross-linked to the relevant Engine Developer deep-dive.
For the tree format and merge rules see Pack Authoring; for MUD-level manifest keys see Pack MUD Settings; for attaching Lua see Pack Lua Scripting and Pack Lua Hooks. The backing SQL tables are described in Persistence & Durability.
Conventions. "req" = required, "opt" = optional. A ref is a stable identifier and the
merge key; namespace it (e.g. midgaard:room:temple) so it stays globally unique. "→ X" means
the field holds the ref of an X entity. Best worked examples are in
internal/content/packs/demo/.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Stable zone id and merge key. |
name |
req | string | Display name. |
start_room |
opt | → room | Where a fresh login spawns. Also where a death inside an instance respawns — an instanceable zone without one evicts to the entry anchor instead, and is rejected at mint time. |
reset_secs |
opt | int | Timed-reset period; 0 = no timed reset. |
instanceable |
opt | bool | Opt in to runtime-minted private copies (Building Instanced Zones). Off by default — without the opt-in a player could mint a copy of any loaded zone, strip its resets, and walk out with them. Requires a valid start_room. Inside a copy, persistent resets and timed repop are refused and signal_region/signal_world are rejected — see the builder page for the full list. Rides the zones body JSONB. |
rooms |
opt | list | Rooms (below). |
item_prototypes |
opt | list | Item prototypes (below). |
mob_prototypes |
opt | list | Mob prototypes (below). |
resets |
opt | list | Spawn resets (below). |
A zone may be authored as one file or split across many files under zones/<zone>/; the loader
unions them (see Pack Authoring → merge semantics). Worked example:
zones/00-midgaard/00-zone.yaml.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Stable room id and exit target (e.g. midgaard:room:temple); may be referenced cross-zone. |
name |
req | string | Display name (decoupled from ref). |
long |
opt | string | Room description. |
sector |
opt | string | Free-form terrain/type tag. |
coord |
opt |
[x,y,z] ints |
Coordinates for the GMCP minimap; omit for topological fallback. |
exits |
opt | map |
direction → destination room ref. Cross-zone targets allowed (e.g. north: darkwood:room:grove); cross-pack not allowed (FK). |
instance_entrances |
opt | map |
direction → instanceable zone ref — a declared dungeon door (Instanced Zones). Deliberately a separate map from exits: every path that moves a player on someone else's initiative resolves directions through exits, so nothing can push a player through a door they cannot see. |
flags |
opt | list | Open-set room booleans (e.g. safe, arena, station/forge). The engine names none — packs define their own; scripts/abilities read them. |
lua |
opt | string (Lua) | A room trigger block: on(event, fn) + self.state. See Pack Lua Hooks. |
Reserved/unwired: exits can carry a
doorconcept (closed/locked/key) in principle, but the importer never writes room-exit doors — onlyfrom_room / dir / to_roomare stored. Room-exit doors are not wired. (Container locks, on item prototypes, are — see ContainerDTO below.)
Worked example: zones/00-midgaard/10-rooms.yaml.
Item prototypes and mob prototypes share one shape. A prototype is a mob if it carries a
living: component; otherwise it's an item. A nil (absent) component pointer means the
prototype simply lacks that aspect.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Stable prototype id / merge key. |
short |
req | string | Short description (NOT NULL — required even for mobs). |
long |
req | string | Long description (NOT NULL). |
keywords |
opt | list | Targeting tokens. |
physical |
opt | component | Weight/size/material (below). |
wearable |
opt | component | Wear locations (below). |
weapon |
opt | component | Weapon stats (below). |
container |
opt | component | Container stats (below). |
material |
opt | component | Stackable crafting material (below). |
living |
opt | component | Presence makes this a mob (below). |
bind |
opt | enum |
bind_on_pickup / bind_on_equip / unbound / "". |
tier |
opt | → rarity tier | Rarity. |
tags |
opt | list | Open-set item tags (e.g. material, magical, salvageable). |
salvage_table |
opt | → loot table | Per-item salvage override. |
no_salvage |
opt | bool | Block salvaging this item. |
lua |
opt | string (Lua) | Per-instance trigger block. |
Sub-components:
-
physical—weight(int),size(int),material(string). -
wearable—locations(list, each → a wear-slot ref),modifiers(list of{attr, op: add|mul, value}— static stat bonuses granted while worn: armor's+2 AC, a ring's+1 save; composed with any rolled affixes through the standard derivation), andequip_affects(list of affect refs applied to the wearer while equipped — on-equip magic and OnHit weapon procs like a flame-tongue, since an equip-affect subscribes the event bus like any active affect). Equip-affects are keyed by the item as source (two rings granting the same affect are distinct) and are derived state — re-derived on load, not saved, so a relog never re-fireson_apply. -
weapon—dice_num(int),dice_size(int),damage_type(→ damage type),class(string),attack_verb(string). Semantics: Combat System. -
container—capacity(int),weight_limit(int),closed(bool),locked(bool),key_ref(string). Container locks are honored (unlike room-exit doors). -
material—max_stack(int; a large default if< 1),type(string). Semantics: Loot, Spawns & Crafting. -
living(makes a mob) —attributes(map name→float, the mob's base stat sheet / per-entity overrides),combat_profile(→ combat profile),loot_table(→ loot table). Semantics: Combat System, Loot, Spawns & Crafting.
Worked mob stat sheets (with aggressive, max_reactions, etc.):
zones/02-crypt.yaml (skeleton / tomb-guardian). Worked items: zones/00-midgaard/20-items.yaml.
Resets populate a zone on boot and on each timed reset. Each reset is one op; there is no ref,
so resets are concatenated in file order (not merged).
| Key | Req | Type | Meaning |
|---|---|---|---|
op |
req | enum |
spawn_item or spawn_mob (the kind is advisory). |
proto |
req | → prototype | What to spawn. |
room |
req | → room | Where to spawn it. |
count |
opt | int | Boot count when max is unset; ≤ 0 ⇒ 1; ignored when max > 0. |
max |
opt | int | Top-up ceiling: keep at most this many live, spawning the shortfall each reset; 0 ⇒ use count. |
into |
opt | → container or mob | Spawn the item into the contents/inventory of a container or a mob already in the room (the demo spawns into a mob: into: crypt:mob:skeleton). |
roam |
opt | bool | Count this spawn's population zone-wide rather than in the spawn room. Required for a wandering mob: it leaves its spawn room, so a room-scoped top-up would find the room empty and leak a replacement every repop. One roamer anywhere in the zone satisfies the reset. Only meaningful for a mob spawn — see Pack Lua Hooks. |
persistent |
opt | bool | See below. |
persistentis reserved in practice. Settingpersistent: truemeans the object loads once from the durableobject_instancesstore rather than being re-spawned. The path exists but is unexercised by the demo — treat it as reserved. Builders never authorobject_instancesdirectly; it is the durable runtime store. If you want a durable object, you setpersistent: trueon a reset — you do not writeobject_instances.
Worked example: zones/00-midgaard/40-resets.yaml.
Every def-table row shares ref (or name/surface/verb where noted) plus pack, with the
remaining fields riding a JSONB body. Sections below list the authored YAML keys.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Attribute id. |
display_name |
req | string | Display label. |
value_kind |
req | enum |
int / float / derived. |
default_base |
opt | expr |
{lit: n} or {expr: <prefix-AST>}. |
min / max
|
opt | float | Nullable bounds. |
stat |
opt | bool | Surface in GMCP Char.Stats. |
Prefix-AST heads for expr: + - * / min max clamp floor, ["attr", name], ["lit", n]. The
engine names no attribute — the whole stat list is content. Derived/combat semantics:
Combat System. Worked: attributes.yaml.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Resource id. |
display_name |
req | string | Label. |
max_attr |
opt | → attribute | The derived attribute capping the pool. |
vital |
opt | bool | Whether emptying this pool causes DEATH. Since #406 that is all it means — every pool runs its own on_depleted. Multiple vitals are supported: each is independently lethal. A pool with max <= 0 is natural immunity, never lethal and never depleted. |
primary |
opt | bool | Marks the default-damage vital: the pool deal_damage hits when it names no resource. Rides the resource JSONB body, so adding it needs no migration. |
absorb |
opt | bool | A pre-vital buffer (temp HP / ward): soaks a blow before the pool it fronts, spilling only the remainder. Declares no max_attr — capacity is the amount written in (use set_resource). |
fronts |
opt | → resource | Which pool this absorb buffer sits in front of (default: the primary vital). |
regen |
opt | int | Regen per pulse. |
regen_in_combat |
opt | bool | Regen while fighting. |
per_round |
opt | bool | Regen cadence. |
gauge |
opt | bool | Surface as a GMCP vitals gauge. |
depleted_threshold |
opt | int | Reserved. |
on_event / on_event_lua
|
opt | map | event-name → op-list / Lua handler. |
on_reaction_lua |
opt | map | reaction-checkpoint → Lua (receives rx). |
on_depleted |
opt | op-list | Runs when DAMAGE empties this pool (per-pool). On a vital pool it is the death hook (and can cancel the death by reviving the pool); on a NON-vital pool it is a non-lethal consequence — the Call of Cthulhu shape, a sanity break applying insane — and can never reach death. See the notes below. |
Authoring on_depleted. It fires on the DAMAGE path only — an ability cost, a modify_resource, or a
max drop that brings a pool to 0 runs nothing. It is LEVEL-triggered: every blow that leaves the pool at 0
runs it, including a blow onto an already-empty pool. That is what makes a two-track system work (a stun
track has to keep carrying its excess over, not just once), and it has two consequences you must design for:
-
Make the hook idempotent. Guard with
if has_affect: <ref>and/or give the applied affectstacking: ignore, or the narration re-prints and the duration re-refreshes on every blow. -
Never put a rewarding op in one (
produce_item,advance_track,grant_ability, a currency grant). A pool held at 0 can be hit on purpose, which would make the reward farmable.LintDepletionHookGrantswarns at load if you do.
The blow's arithmetic is readable from any formula slot inside the hook, as ctx scalars in the same
family as $swing.index: $depletion.overflow (how far PAST 0 the blow drove the pool),
$depletion.applied (what the pool absorbed), and $depletion.amount (the whole blow;
applied + overflow == amount). That is what makes a carry-over authorable:
on_depleted:
- {op: deal_damage, target: self, resource: hp, type: trauma,
amount: 0, bonus: ["attr", "$depletion.overflow"]}Note amount is a plain NUMBER — a computed value goes in bonus (or dice_count); amount: ["attr", …]
silently reads 0. Name the destination resource explicitly (omitted, it routes to the primary vital), and
give the carry-over its own unresisted damage type or it is mitigated a second time.
Load-time lints over this surface: LintVitalResources (a pack defining vitals should designate a
primary), LintDealDamageResources (a deal_damage op naming an unknown resource), and
LintDepletionHookGrants (a rewarding op in a non-vital hook). Op-list / reaction / event semantics:
Abilities & Effects, Combat System, and the hook catalog in
Pack Lua Hooks. Worked: resources.yaml.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Damage-type id. |
display_name |
req | string | Label. |
color |
opt | string | Display color. |
resist |
opt | map |
damage-type ref → multiplier (1 neutral, <1 resist, >1 vulnerable, 0 immune). |
target_resource |
opt | → resource | Routes damage of THIS KIND to a named pool — psychic → sanity, bashing → a stun track. |
Routing precedence: op.resource ?? damage_type.target_resource ?? the primary vital. A type route is
how a system NAMES its tracks, and it is the only thing that routes damage your pack did not author — a
third-party spell, a mob's natural weapon, a Lua h:damage, and every melee SWING (which carries a weapon's
damage type but never a resource) would otherwise all land on the primary vital.
A target with no capacity in the routed pool (derived max <= 0) DISCARDS the blow entirely, before
mitigation and threat. That is what makes a routed type safe in a shared pack: creatures with no such track
are immune by construction. Give the capping attribute a default base of 0 and only entities your content
explicitly raises it for participate — the same lever max_reactions uses.
Never retrofit target_resource onto an existing damage type in a live pack: it re-aims every already
authored blow of that kind away from the pool it has always hit. Routing is a property a NEW type is born
with. LintDamageTypeResources (ERROR) catches a route naming an unknown resource — the whole damage kind
would silently do nothing — and LintDealDamageTypes (WARN) catches an op naming an unknown damage type,
which now loses its route as well as its resist matrix.
Mitigation semantics: Combat System. Worked: damage_types.yaml.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Profile id (a player's default is named by default_combat). |
to_hit |
opt | check body | The to-hit check (one, shared by all multiattack entries). |
avoidance |
opt | list | Ordered avoidance check bodies. |
damage_bonus |
opt | prefix-AST | Damage bonus formula. |
multiattack |
opt | list | A heterogeneous attack routine — ordered {dice, type, count, bonus?} entries the swing loop cycles (bite + 2 claws). Replaces the attacks count; each entry uses its own dice. Rides the profile JSONB body (no migration). |
Semantics: Combat System. Worked: combat_profiles.yaml (the melee profile).
| Key | Req | Type | Meaning |
|---|---|---|---|
verb |
req | string | The command word (PK; exact-match only). |
aliases |
opt | list | Alternate words. |
lua |
req | string (Lua) | Verb body (self, arg). |
Registered after built-ins and abilities, exact-match only; a verb colliding with a built-in is rejected at load. Semantics: Pack Lua Scripting. (The demo ships none via this section.)
formula_defsandpack_metaare not authored as list sections — they come from the manifest'sformulasmap and pack scalars. See Pack MUD Settings.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Ability id. |
name |
req | string | Display name. |
invocation |
req | enum |
command / proc / passive. |
words |
opt | list | Invocation words (command abilities). |
targeting |
opt | object |
{mode, scope, range, disposition, area}. |
tags |
opt | list | Tags. |
skill |
opt | string | Governing skill. |
requires_grant |
opt | bool | Must be explicitly granted. |
requires |
opt | object |
{not_prevented[], attr{}, profession}. |
costs |
opt | list |
[{resource, amount}]. |
cast_time / lag / cooldown
|
opt | int | Timing. |
on_resolve |
opt | op-list | Declarative resolve effects. |
on_resolve_lua |
opt | string (Lua) | Scripted resolve step. |
messages |
opt | object |
{actor, room} templates. |
on_event |
opt | map | Event handlers. |
Storage quirk (informational):
words,requires_grant,skill, andon_eventride themessagesJSONB rather than having their own columns. This doesn't change how you author them.
Ability lifecycle, the op vocabulary, targeting, and the PvP gate are owned by
Abilities & Effects and Combat System. Rich worked set:
abilities.yaml (fireball, cure, craft/salvage verbs, Lua spells).
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Affect id. |
name |
req | string | Display name. |
category |
opt | string | Category. |
stacking |
opt | enum |
refresh / stack / extend / ignore / highest (strongest instance only, not the sum). |
max_stacks |
opt | int | Stack ceiling. |
stack_scope |
opt | enum |
source / target. |
dispellable |
opt | bool | Can be dispelled. |
level |
opt | int | Potency: dispel strips highest-level first, and a dispel check reads $affect.level. |
concentration |
opt | bool | Opts into the caster's single concentration slot — a new one auto-expires the source's prior. |
scope |
opt | enum |
entity / room. |
duration |
opt | int | Pulses. |
duration_kind |
opt | enum |
indefinite — never counts down; ends only via dispel/remove_affect/death (replaces the huge-duration hack). |
rungs |
opt | list | A graded ladder: each rung its own {modifiers, prevents}, moved by increment_rung/decrement_rung. The current rung's set applies un-scaled. |
prevents_source |
opt | list | Tags blocked only against the affect's own source (charmed = prevents_source: [attack]). A targeting gate on cast + swing, not a hard "can't harm the source" firewall. |
modifiers |
opt | list |
[{attr, op: add|mul, value}]. |
prevents |
opt | list | Tags this affect blocks (CC). Conventional: act stops the bearer's auto-swings, react stops its out-of-turn reactions, cast stops tagged abilities. |
tags |
opt | list | What this affect is (charm, poison, mind) — matched by another affect's grants_immunity. |
grants_immunity |
opt | list | Tags/refs/categories of incoming affects the bearer rejects before attach (a clean no-op — no attach, no on_apply). Matches on the incoming affect's {ref} ∪ {category} ∪ tags. Distinct from prevents. |
suspends_death |
opt | bool | While active, a vital hitting 0 holds the bearer at 0 (downed/dying) instead of dying — no corpse, no respawn; regen pauses and auto-swings stop. The resolution (death-save loop, duration) is the affect's own. See Combat System. |
damage_taken_mult |
opt | map |
damage-type ref → multiplier applied to incoming damage after soak (a ward/vulnerability the bearer carries; product-composed, <1 resist, >1 vuln — gated as harm, 0 immune). |
tick |
opt | object |
{interval, on_tick: <op-list>}. |
on_apply / on_expire / resist
|
opt | op-list | Declarative hooks (resist reserved). |
on_apply_lua / on_expire_lua / on_dispel_lua
|
opt | string (Lua) | Scripted lifecycle hooks. |
on_event / on_event_lua
|
opt | map | Event handlers. |
on_reaction_lua |
opt | map | Reaction handlers (receive rx). |
Runtime, CC, and reaction semantics: Abilities & Effects and
Combat System. See Pack Lua Hooks for the important note that
on_tick is an op-list only — there is no on_tick_lua. Worked: affects.yaml.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Track id. |
progress_attr |
req | → attribute | The advancing attribute. |
level_attr |
opt | → attribute | Marks this as a level track. |
thresholds |
opt | list | Ascending step thresholds. |
steps |
opt | list | Per-step grant op-list (index i ⇒ step i+1). |
Semantics: Loot, Spawns & Crafting covers spawns/loot; progression
mechanics are described alongside abilities/effects and the combat/progression engine. Worked:
tracks.yaml.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Bundle id. |
kind |
req | enum |
class / race / background / feat / talent / profession. |
uncapped |
opt | bool | Profession only. |
grants |
opt | grant op-list | What the bundle confers. |
Classes and races are bundles. There is no separate class/race authoring — a class is a
bundlewithkind: class, a race iskind: race(see the reserved-tables note below).
Worked: bundles.yaml.
Read by telos-account, not the world.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Chargen flow id. |
steps |
req | list | Ordered steps. |
Step common fields: kind, id, prompt. Step kinds:
-
bundle_choice—bundle_kind,pick. -
point_buy—attributes[],points,base,min,max,cost{target→cumulative}. -
array_assign— the player assigns a fixed multiset (array, e.g. the 5e standard[15,14,13,12,10,8]) across the abilities; the validator accepts a submission iff it is a permutation of the array. No dice. -
roll— each ability gets an independent server-rolled score (roll_dice, default4d6dl1). The roll takes no player input:telos-accountrolls each score at submit with a fresh per-request RNG seeded fromcrypto/rand(unpredictable and unshared), and a client value submitted for a rolled attribute is ignored — so a forged score can't stick and there's no chargen-session state to trust.
Semantics: Accounts & Auth Internals. Worked: chargens.yaml.
Keyed by name (not ref). Loaded by both the world and telos-account.
| Key | Req | Type | Meaning |
|---|---|---|---|
name |
req | string | Tier name (PK). |
rank |
req | int | Higher = more trusted. |
flags |
opt | list | Only the reserved flags holylight, builder, admin are honored. |
Linted by LintTrustLadder; the demo ships none (uses the engine default player/builder/admin).
See Trust Tier Model.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Slot id (PK). |
label |
opt | string | Display label. |
order |
opt | int | Display/selection order. |
kind |
opt | enum |
worn / wield / hold. |
An empty section falls back to the engine's default Diku slot set. Worked: wear_slots.yaml
(adds a waist slot).
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Tier id. |
order |
opt | int | Ordinal. |
weight |
opt | float | Roll weight. |
color |
opt | string | Display color. |
binds |
opt | bool | Items of this tier bind. |
salvage_table / salvage_skill / salvage_bonus_step
|
opt | Derived salvage config. |
Semantics: Loot, Spawns & Crafting. Worked: rarity_tiers.yaml.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Loot-table id. |
rolls |
req | list | See below. |
on_roll |
opt | string (Lua) | Conditional-drop hatch returning item refs. |
Each rolls[] entry: kind (guaranteed / chance / weighted_one / weighted_n),
chance, n, quality_floor, pool[] ({item, tier, weight, quality{affixes[], count, level_min, level_max}}), pity{key, step, cap}. Resolver semantics:
Loot, Spawns & Crafting. Worked: loot_tables.yaml.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Affix id (referenced from a loot quality pool). |
attr |
req | → attribute | The attribute it modifies. |
min / max
|
opt | float | Roll range. |
Semantics: Loot, Spawns & Crafting. Worked: affix_defs.yaml.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Recipe id. |
name |
req | string | Display name. |
aliases |
opt | list | Alternate names. |
profession |
opt | → bundle | Required profession. |
track |
opt | → track | Skill track. |
skill / min_skill
|
opt | Skill gating. | |
station |
opt | string | Required room flag. |
inputs |
req | list |
[{item, qty}]. |
output |
req | object |
{item, qty, bind}. |
quality_base |
opt | Base output quality. |
Semantics: Loot, Spawns & Crafting. Worked: recipes.yaml.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Channel id. |
name |
req | string | Channel name. |
words |
opt | list | Command words. |
color |
opt | string | Display color. |
format |
opt | string | Template using $channel / $name / $t; default "[$channel] $name: $t". |
access |
opt | object |
{require_flag, min_attr{attr, min}} — who may speak. |
hear_access |
opt | object | Who hears; nil ⇒ mirrors access; {} ⇒ anyone hears. |
default_on |
opt | bool | On by default. |
history |
opt | int | Retained scrollback depth for the history <channel> command (0 ⇒ capture nothing). Shard-local; a line replays only to a viewer the channel's live hear_access still admits at fetch time. Removing the channel on a hot reload reaps its ring (no orphaned buffer pinning memory to restart). hear_access retroactively exposes lines buffered under the stricter rule — narrow retention or clear intent before loosening. |
The loader captures present-but-empty access conditions for a lint (LintChannelAccess). Comms
transport is owned by the comms subsystem; the storage shape is here. Worked: channels.yaml
(gossip / newbie / guild).
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Region id (also the telos.scope.region.<ref> scope token). Must be non-empty — an omitted ref would name the world director. |
name |
opt | string | Display name. |
zones |
opt | list | Member zone refs. |
script |
opt | string (Lua) | This region's own director script — the region-scoped sibling of world_script, run on that region's director actor. telos-director builds one director per entry. See Per-region director scripts. |
See Orchestration & Directors and
Scoped Event Bus. Worked: regions.yaml.
Director-owned scheduled spawns.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Schedule id. |
proto |
req | → mob | What to spawn. |
zone / room
|
req | Where. | |
interval_after_death_sec |
opt | int | Respawn delay after death. |
on_missed |
opt | enum |
spawn_if_overdue / skip_to_next. |
announce |
opt | string | Broadcast on spawn. |
Semantics: Loot, Spawns & Crafting,
Orchestration & Directors. Worked: spawn_schedules.yaml.
Keyed by (pack, surface).
| Key | Req | Type | Meaning |
|---|---|---|---|
surface |
req | string | The sheet: score, who, inventory, equipment, or room (the look/enter render — a room template that returns nil falls back to the built-in render, so a pack can own the display for some rooms only, e.g. an overworld minimap). |
render |
req | string (Lua) | A pure function returning the sheet string, using the ui toolkit. |
Rendering/ui-toolkit semantics: Pack Lua Scripting. Worked:
display_defs.yaml (score + who + the overworld room minimap).
A pack-defined on/off player preference — the generic form of the hard-wired vitals/color switches. The engine names no toggle; a pack decides which exist. Keyed by ref (per pack); merged last-write-wins by ref.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Toggle id (e.g. overworld). Content reads a viewer's state with self:toggle("<ref>"). |
words |
req | string[] | The verbs that flip it. Each registers as a low-priority player verb: the bare word reports current state, <word> on|off sets it (consulted after built-ins, exact-match, rejected at build if it collides with a core verb). |
default |
opt | bool | Off unless set. |
Per-player state is stored as a delta-from-default override in the comms-state bag, so it persists in the character's comms state and survives a cross-shard handoff for free (mirroring content-channel overrides). self:toggle returns player-controlled state — treat it as a display preference, never a trust/authorization signal. Backed by a toggle_defs table. Worked: the demo ships one, overworld (default off), which gates the minimap.
The browsable help topics behind help / help <topic>. Keyed by ref (per pack); merged last-write-wins by ref.
| Key | Req | Type | Meaning |
|---|---|---|---|
ref |
req | string | Topic id (e.g. help:combat). Its leaf (combat) is an implicit keyword. |
title |
req | string | Display heading. |
category |
opt | string | Groups topics in the index. |
keywords |
opt | string[] | Extra lookup terms beyond the ref leaf. |
body |
req | string | The help text; may carry {{TOKEN}} color markup (rendered at the edge, stripped for color off). |
see_also |
opt | string[] | Related topic refs/keywords shown as cross-references. Filtered per-viewer (see below). |
min_rank |
opt | int | Trust rank required to see the topic (default 0). A topic gated above 0 is invisible — in both the index and a direct help <topic> lookup — to any actor below that rank. |
The engine names no topic and auto-includes the registered command set on top of the pack's rows, so help yields a usable command index even with zero help_defs. Topic resolution is ref → keyword → prefix, with exact beating prefix and a deterministic tie-break. Crucially, both the command index and a direct command entry honor CmdHidden + MinRank exactly like dispatch — a staff verb never appears in a mortal's help (see Builder Commands, Trust Tier Model).
A help_def may itself carry an optional min_rank for a staff-only topic (not just a staff verb): a topic gated above 0 is invisible to a below-rank actor in both the browsable index and a direct help <topic> lookup, which falls through to the same "There is no help on …" path as a nonexistent topic — so the topic's existence never leaks, matching the wiz-command posture. see_also cross-references are filtered per-viewer, so a world-readable topic can't disclose a gated topic's existence or lookup keyword through a "See also:" link. The gate fails open by design: a dropped min_rank un-gates staff text (a disclosure at worst), never a capability. Backed by migration 00027_help_defs.sql. Worked: help_defs.yaml (getting-started / movement / combat / comms), plus a staff-only help:staff topic in the demo pack.
Be aware of these so you don't author against a dead path:
-
class_defs/race_defs— the tables exist "so the schema is whole," but the loader/importer have no code path for them. Do not author them. Model classes and races asbundleswithkind: class/kind: race. -
exits.door— the column exists but the importer never writes it. Room-exit doors (closed/locked/key) are not wired. Container locks (on item prototypes) are. -
object_instances— the durable runtime store, not a builder-authored section. For a durable object, setpersistent: trueon a reset. -
content_version/content_pack_registry— written only by the pull/reload machinery (ImportVersion/BumpContentVersion); never builder-authored. See Content Pack Operations. -
Reserved fields noted inline:
resources.depleted_threshold, affectresist, theformulasnamesto_hit/soak/xp_for(defined but not wired — onlyregenis consulted), and resetpersistent(path exists, unexercised).
TelosMUD — Wiki under construction.
- Builder Reference
- Builder Commands
- Trust Tier Model
- Pack Authoring
- Pack MUD Settings
- Pack Lua Scripting
- Pack Lua Hooks
- Pack Entity Reference
- Building Instanced Zones
- Engine Developer Reference
- Architecture Overview
- Entity Component Model
- Zone Runtime & Actor Model
- Instanced Zones
- Command Parser & Targeting
- Edge & Protocol
- GMCP Reference
- Persistence & Durability
- Content Loading & Hot Reload
- Abilities & Effects
- Combat System
- Loot, Spawns & Crafting
- Accounts & Auth Internals
- Orchestration & Directors
- Scoped Event Bus
- Cross-Shard Handoff
- Lua Sandbox Internals
- Distributed Systems Model
- RPC & Protobuf