Skip to content

Pack Entity Reference

Kurt edited this page Jul 20, 2026 · 17 revisions

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/.


Part 1 — World entities (the zones: subtree)

Zone

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.

Room

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 door concept (closed/locked/key) in principle, but the importer never writes room-exit doors — only from_room / dir / to_room are stored. Room-exit doors are not wired. (Container locks, on item prototypes, are — see ContainerDTO below.)

Worked example: zones/00-midgaard/10-rooms.yaml.

Prototype (item or mob)

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:

  • physicalweight (int), size (int), material (string).
  • wearablelocations (list, each → a wear-slot ref).
  • weapondice_num (int), dice_size (int), damage_type (→ damage type), class (string), attack_verb (string). Semantics: Combat System.
  • containercapacity (int), weight_limit (int), closed (bool), locked (bool), key_ref (string). Container locks are honored (unlike room-exit doors).
  • materialmax_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.

Reset

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.

persistent is reserved in practice. Setting persistent: true means the object loads once from the durable object_instances store rather than being re-spawned. The path exists but is unexercised by the demo — treat it as reserved. Builders never author object_instances directly; it is the durable runtime store. If you want a durable object, you set persistent: true on a reset — you do not write object_instances.

Worked example: zones/00-midgaard/40-resets.yaml.


Part 2 — Pack-global def-tables

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.

Core rules

attributes — attribute definitions

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.

resources — resource pools

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.

damage_types

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.

combat_profiles

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).

commands — custom Lua verbs

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_defs and pack_meta are not authored as list sections — they come from the manifest's formulas map and pack scalars. See Pack MUD Settings.

Abilities & effects

abilities

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, and on_event ride the messages JSONB 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).

affects

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.

Character build & progression

tracks

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.

bundles

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 bundle with kind: class, a race is kind: race (see the reserved-tables note below).

Worked: bundles.yaml.

chargens

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_choicebundle_kind, pick.
  • point_buyattributes[], points, base, min, max, cost{target→cumulative}.
  • Future kinds (array, roll) are not implemented.

Semantics: Accounts & Auth Internals. Worked: chargens.yaml.

trust_tiers

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.

Items, loot & crafting

wear_slots

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).

rarity_tiers

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.

loot_tables

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.

affix_defs

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.

recipes

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.

World, comms & display

channels

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).

regions

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.

spawn_schedules

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.

display_defs

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).

toggle_defs

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.

help_defs

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.


Part 3 — Reserved / created-but-unused surface

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 as bundles with kind: 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, set persistent: true on 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, affect resist, the formulas names to_hit/soak/xp_for (defined but not wired — only regen is consulted), and reset persistent (path exists, unexercised).

Clone this wiki locally