-
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). -
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 | Vital pool (0 ⇒ depletion/death path). Multiple vitals are supported — each is independently lethal and runs its own on_depleted. A pool with max <= 0 is natural immunity, never lethal. |
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. |
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 this vital pool hits 0 (per-pool). |
Two load-time lints cover the multi-vital surface: LintVitalResources (a pack defining vitals should
designate a primary) and LintDealDamageResources (a deal_damage op naming a resource that no
resource def declares). 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). |
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. |
avoidance |
opt | list | Ordered avoidance check bodies. |
damage_bonus |
opt | prefix-AST | Damage bonus formula. |
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. |
max_stacks |
opt | int | Stack ceiling. |
stack_scope |
opt | enum |
source / target. |
dispellable |
opt | bool | Can be dispelled. |
scope |
opt | enum |
entity / room. |
duration |
opt | int | Pulses. |
modifiers |
opt | list |
[{attr, op: add|mul, value}]. |
prevents |
opt | list | Tags this affect blocks (CC). |
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}. - Future kinds (
array,roll) are not implemented.
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. |
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). |
name |
opt | string | Display name. |
zones |
opt | list | Member zone refs. |
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