Pack MUD Settings

Audience: Builder Status: ✅ Ready

The pack.yaml manifest is where a pack declares MUD-level settings — the handful of knobs that shape the whole game rather than one entity. This page documents every top-level key of the pack document, what it’s backed by, and — honestly — what is not modeled here. For the tree format and merge rules see Pack Authoring; for the entity/def-table schemas see the Pack Entity Reference.

There is no separate manifest schema

pack.yaml is not a special file with its own schema — it is simply the top-level of the pack document (the Pack struct). Any top-level key can appear in any file of the tree; by convention pack.yaml carries only the scalar/global head and lets the other tree files supply the big list sections. In the demo pack, pack.yaml contains just:

pack: demo
default_combat: melee

and core/pack.yaml contains only pack: core. Everything else (zones, abilities, …) lives in sibling files and merges in.

Top-level keys

YAML key Type Meaning
pack string The pack name — written to the pack= column on every row. Defaults to the directory/file name if omitted.
default_combat string The combat profile a player uses when its own prototype names none. Last non-empty wins across the tree. Empty means players have no profile (a degenerate auto-hit). Backed by pack_meta.body.default_combat.
pvp_lua string (Lua) Optional PvP consent policy: a Lua function(actor, target) returning a boolean. Empty means the engine’s default pvp_allowed; a missing or erroring policy fails closed (denies). Backed by pack_meta.body.pvp_lua.
license / attribution string Optional per-pack copyright/attribution (e.g. the 5e SRD’s CC-BY notice). Unlike the last-wins singletons, these accumulate per packMerge collects one PackCredit per crediting pack in load order, so a later pack can never erase an earlier one’s notice. Surfaced in-game by the credits verb; backed by pack_meta (per-pack).
formulas map<string,string> (Lua) Optional ruleset-formula overrides keyed by name (regen, and the reserved to_hit/soak/xp_for/…). Merged last-write-wins by name. Backed by formula_defs.
world_script string (Lua) Optional world-director orchestration script defining on_signal(event, payload) — sandboxed Lua the director runs to react to your zones’ signal-up events (write world state, broadcast down). Backed by pack_meta.body.world_script. See Pack Lua Hooks → world-director script and Orchestration & Directors.
zones list The world subtree — rooms, exits, prototypes, resets. See Pack Entity Reference §World entities.
the def-table sections list attributes, resources, damage_types, affects, abilities, combat_profiles, channels, regions, tracks, bundles, rarity_tiers, loot_tables, affix_defs, spawn_schedules, recipes, wear_slots, chargens, trust_tiers, display_defs. Each is documented in the Pack Entity Reference.
commands list Custom Lua verbs. Appended, not de-duplicated by ref. See Pack Lua Scripting.

default_combat, pvp_lua, formulas — semantics live elsewhere

These three keys are the pack’s “rules head”, but their runtime behavior is owned by the combat and scripting engine, not by the loader — this page documents only their shape and storage:

  • default_combat points at a combat_profile_defs ref (see the entity reference). What a combat profile does — to-hit, avoidance, damage — is described in Combat System.
  • pvp_lua is a policy hook; the gate that consults it, and the fail-closed behavior, are covered under scripting (Pack Lua Scripting) and combat.
  • formulas override named ruleset formulas. Only regen is actually consulted today; to_hit, soak, and xp_for are defined-but-not-wired (reserved). See Pack Lua Hooks for the live-vs-reserved list and Combat System for the formula semantics.

Where MUD-wide scalars are stored: pack_meta

pack_meta is the only “MUD-wide scalars” table: one row per pack, a JSONB body currently holding default_combat and pvp_lua. A practical consequence — adding a new pack-level scalar is a body-field write, not a schema migration. The registry/versioning tables (content_version, content_pack_registry) are written only by the pull/reload machinery and are not builder-authored (see Content Pack Operations).

What is not a pack.yaml setting

Two honest caveats, both flagged as not-implemented in the loader:

  • No version / dependencies / author fields. A pack does not carry its own version, declare dependencies on other packs, or record an author inside pack.yaml. Versioning and the content hash are the external manifest.yaml’s job (see Pack Authoring → ingestion paths). There is no dependency resolver — cross-pack ordering is purely the operator’s enabled-list order.
  • No hardcoded game flavor. Consistent with the engine’s pillar (see Overview), nothing here bakes in a specific ruleset: the stat list, the resources, the damage types, and the combat model are all def-table content, and pack.yaml only names which of your defs serve as defaults.