# Spell

> Kinbarrow modding reference — content tree `45d0fe274f851548`, version `0.2.0+main.c05ef2b`.

`spells/<id>.srd.ron` — one spell per file; stem == id (the layout contract's promised one-file-per-entity collection). A spell is a COMPOSITION: one [`Delivery`] carrying a list of [`Effect`]s — data assembles new spells from the primitives with no engine code.

**Note on syntax:** these files are RON, not JSON. The shapes below are exact,
but punctuation follows RON — read a real `data/*.ron` file alongside.

## Fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `cantrip_steps` | `boolean` | required | Cantrip damage-dice steps at character levels 5/11/17 (SRD). |
| `cast` | `CastTime` | required | The casting time (action or bonus action). |
| `classes` | `string[]` | required | The class lists this spell is on (class ids, boot-resolved). |
| `concentration` | `boolean` | default `false` | This spell demands CONCENTRATION: its ongoing effects last only while the caster holds focus (one at a time; damage forces a save; a new concentration cast drops the old). Absent = instantaneous (the pre-0223 corpus). |
| `delivery` | `Delivery` | required | The one roll/selection gate between the caster and the effect list. |
| `duration_secs` | `integer` | optional | The spell's SRD duration in SECONDS (the ambient clock — a ward cast outside the bubble expires at now + duration). Absent = instantaneous (the strike-and-done corpus). A concentration spell's duration is its "up to" cap. |
| `effects` | `Effect[]` | required | The composed effect steps applied to each delivered target. |
| `id` | `string` | required |  |
| `level` | `uint32` | required | 0 = cantrip. |
| `name` | `string` | required |  |
| `range` | `SpellRange` | required | The spell's range. |
| `school` | `string` | required | A `tables/schools.srd.ron` id, boot-resolved. |
| `source` | `Source` | required |  |
| `target_type` | `string` | optional | The targeting gate: a `tables/creature_types.srd.ron` id the target's own creature type must match — hold person's "one humanoid". The one seam future type-gated spells plug into (charm person, dominate person → humanoid; banishment → a plane's natives) with no new machinery. Absent = the spell reads no type (the pre-0234 corpus). |
| `upcast` | `Upcast` | required | How the spell scales at higher slot levels. |

## Nested shapes

### Ability

The six ability scores (SRD 5.1). The engine's own `stats::Ability` is the runtime type; this is the data-layer mirror, bridged by [`Ability::engine`].

`Str`, `Dex`, `Con`, `Int`, `Wis`, `Cha`

### Area

An area of effect, resolved on the encounter board's 5 ft grid: a sphere centers on the TARGET, a cone/line throws from the CASTER toward it, a burst centers on the caster (thunderwave's "Self (15-foot cube)", radius-approximated on the Chebyshev grid).

#### Area::Sphere

A sphere of `radius_ft`, centered on the target point (fireball).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `radius_ft` | `uint32` | required |  |

#### Area::Cone

A cone of `length_ft`, thrown from the caster toward the target (burning hands).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `length_ft` | `uint32` | required |  |

#### Area::Line

A line of `length_ft`, thrown from the caster toward the target (lightning bolt).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `length_ft` | `uint32` | required |  |

#### Area::Burst

A burst of `radius_ft` centered on the caster (thunderwave's "Self" cube, radius-approximated on the grid).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `radius_ft` | `uint32` | required |  |

### CastTime

Casting time — the two the combat bubble's turn economy models; longer castings (the 10-minute prayer, rituals) are ledgered.

`Action`, `BonusAction`

### Delivery

How a cast DELIVERS its effects: the ONE roll/selection gate between the caster and whoever the effect list lands on. A spell is `delivery × effects` — a modded spell composes these primitives freely with no engine code; only a new PRIMITIVE (and, later, a scripted one through the Layer-2 modhost) needs code.

#### Delivery::Attack

A spell attack roll (d20 + PB + casting mod vs AC), once per ray — each hit delivers the effect list (scorching ray rolls three).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `rays` | `uint32` | required |  |

#### Delivery::Auto

Unerring bolts (magic missile): every dart lands, no roll.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `darts` | `uint32` | required |  |

#### Delivery::Save

A saving throw against the caster's DC for everyone caught — the named target, or every combatant an [`Area`] takes in. A SUCCESS spares per [`OnSave`]; non-damage effects land only on a failure.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `ability` | `Ability` | required |  |
| `area` | `Area` | optional |  |
| `on_save` | `OnSave` | required |  |

#### Delivery::Allies

The named ally plus the worst-hurt others in range, up to `targets` (mass healing word's six) — the derived-policy pick.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `targets` | `uint32` | required |  |

#### Delivery::Target

The named target alone, no roll — the touch utilities.

### Effect

One composable consequence, applied to each delivered target. The engine-implemented step vocabulary (the typing rule: enums for what code branches on); an SRD effect whose step does not exist here (concentration, conditions, summons, forced movement) is NOT transcribed — the ledger-don't-fake rule applied to the spell corpus.

#### Effect::Damage

`dice` (+ `plus`) damage of `kind` — halved by a resistance, spared per the delivery's save. A crit doubles the dice (attack deliveries).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `dice` | `string` | required |  |
| `kind` | `string` | required | A `tables/damage_kinds.srd.ron` id, boot-resolved. |
| `plus` | `int64` | default `0` |  |

#### Effect::Heal

Restore `dice` (+ the casting mod if `add_mod`) hit points.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `add_mod` | `boolean` | required |  |
| `dice` | `string` | required |  |

#### Effect::Stabilize

End a dying ally's death saves (spare the dying).

#### Effect::Kindle

Kindle the target as a carried flame for the hour (the LIT_UNTIL machinery, cast instead of struck), throwing `bright_ft` of bright light and `dim_ft` MORE of dim — the SRD's own phrasing ("bright light in a 20-foot radius and dim light for an additional 20 feet"). Light is the torch's 20/20; daylight throws 60/60.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `bright_ft` | `uint32` | required |  |
| `dim_ft` | `uint32` | required |  |

#### Effect::Guide

The glimmer (guiding bolt): the next attack roll against the target has advantage.

#### Effect::Modify

Bless/bane: `die` rides the bearer's own attack rolls and saving throws for the duration — added, or subtracted when `penalty`. A CONCENTRATION effect (the validator pins it), so it lifts when the caster's focus breaks.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `die` | `string` | required |  |
| `penalty` | `boolean` | default `false` |  |

#### Effect::Afflict

Inflict a condition on the target: the id resolves against `data/conditions/` at load — a condition is a DATA bundle of engine [`ConditionComponent`] reads, so hold person's paralysis and a mod's own affliction are the same one-file shape. Behind a `Save` delivery the bearer repeats that save at each of its turns to shake it (SRD save-ends); a CONCENTRATION effect.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `condition` | `string` | required |  |

#### Effect::Push

Forced movement: shove the target `distance_ft` directly AWAY from the effect's origin (the caster, for the self-centered burst/cone/ line spells that carry it), stopping at the first wall, occupied square, or board edge. A harmful, instantaneous rider behind a Save — forgone on a success. Thunderwave's ten-foot push is the first. LEDGERED: pushing away from a SPHERE's center rather than the caster (no shipped sphere-push spell needs it) and prone-on-collision.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `distance_ft` | `uint32` | required |  |

#### Effect::Pull

A pull: forced movement TOWARD the caster — thorn whip's vine yank, the mirror of Push. Drags the struck target `distance_ft` toward the caster (halting adjacent, never onto it). HARMFUL (it rides a to-hit or a save, like Push). LEDGERED: a pull toward a POINT other than the caster.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `distance_ft` | `uint32` | required |  |

#### Effect::Beam

A sustained beam: a CONCENTRATION drain that deals `dice` `kind` to the delivered target AUTOMATICALLY at the start of each of the caster's turns — vampiric touch's per-turn drain (the one-time hit is a separate `Damage` step; this is the sustain). HARMFUL (rides a to-hit or a save), an ongoing effect (concentration). LEDGERED: the SRD range-break (the beam ends if the target leaves range/cover — ours holds while concentration does), the life-drain self-HEAL (no heal-from-damage primitive yet), and the upcast.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `dice` | `string` | required |  |
| `kind` | `string` | required |  |

#### Effect::Teleport

Teleport: the delivered target vanishes and reappears up to `max_ft` away — misty step's blink. A BENEFICIAL self-move behind a Target delivery. The destination is AI-chosen (the unoccupied on-board square FARTHEST from the nearest enemy — the escape the world uses), following the world-first precedent; a PLAYER-picked destination, the "space you can see" line of sight, and bringing a willing creature (dimension door) are LEDGERED.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `max_ft` | `uint32` | required |  |

#### Effect::Aura

An aura: a CONCENTRATION area centered on the caster that bites foes who START their turn within `radius_ft` — an `ability` save for half of `dice` `kind` damage (spirit guardians). Established on the delivered target (the caster — a Target self-cast); BENEFICIAL for the delivery's side-legality (you cast it on yourself), the harm emergent per-turn. It moves WITH the caster and lifts when its concentration breaks. LEDGERED: the SRD "enters the area for the first time on a turn" movement trigger (start-turn-in only today), the speed-halving, and the upcast (+dice/slot).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `ability` | `Ability` | required |  |
| `dice` | `string` | required |  |
| `kind` | `string` | required |  |
| `radius_ft` | `uint32` | required |  |

#### Effect::Summon

A summon: a CONCENTRATION conjuring that mints `creature_id` from the bestiary onto the caster's side mid-fight — the conjured wolf of Conjure Animals. Established on the delivered target (the caster — a Target self-cast); BENEFICIAL (it adds an ally). The beast fights via the existing NPC AI and VANISHES when the caster's concentration breaks. LEDGERED: the variable creature COUNT (ship one; the CR-by-slot table is a fan-out) and the PLAYER's choice of what to conjure. Transient: commanded by its caster, it takes no plunder and is swept from the world when the fight ends.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `creature_id` | `string` | required |  |

#### Effect::Zone

A zone: a CONCENTRATION area anchored to a FIXED point on the board (the aura's board-bound sibling — an aura moves WITH its caster, a zone stands where it was cast) that bites whoever starts their turn within `radius_ft` — an `ability` save for half of `dice` `kind` damage (moonbeam). Established via a Target self-cast; BENEFICIAL for the delivery's side-legality (the harm is emergent per-turn, like the aura), the placement AI-chosen (the foe cluster within range, never an ally — the world-first precedent). LEDGERED: the SRD "enters the area" movement trigger (start-turn-in only today), a MOVABLE zone (moonbeam's beam-step), the cylinder/cube shapes (a Chebyshev radius today), the PLAYER-picked anchor, and the upcast. The movement-blocking WALL (Wall of Force/Stone — blocked squares + line-of-sight) is a distinct primitive, ledgered as the sibling.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `ability` | `Ability` | required |  |
| `dice` | `string` | required |  |
| `kind` | `string` | required |  |
| `radius_ft` | `uint32` | required |  |

#### Effect::Wall

A wall: a CONCENTRATION barrier of `length_ft` that stands a line of BLOCKED squares on the board — Wall of Stone / Wall of Force. It deals no direct damage; it BLOCKS. Every mover, the king-step pathing, the cover / line-of-sight trace, teleport, and forced movement already read `board.open`, so the wall gates all of them for free (the board footprint + cover seam). Established via a Target self-cast; BENEFICIAL for the delivery's side-legality (it harms no creature directly), the placement AI-chosen (a line cutting the caster off from the foe cluster, never through a creature — the world-first precedent). LEDGERED: the PLAYER-drawn shape/anchor, the panel/ring/sphere forms (a straight line today), a DAMAGING wall (Wall of Fire — a Wall+Zone compose), and the "creatures in the wall's space are shoved clear" rule (gaps at occupants).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `length_ft` | `uint32` | required |  |

#### Effect::WallDamage

A damaging wall: Wall of Fire — a CONCENTRATION barrier of `length_ft` that BLOCKS (like `Wall`) AND sears any of the caster's enemies who start their turn on or adjacent to it (an `ability` save for half of `dice` `kind`). Established via a Target self-cast; BENEFICIAL for side-legality (emergent per-turn, like the Zone). LEDGERED: the SRD wall of fire is PASSABLE (ours blocks — a fiery barrier, the fun-first read), its ONE damaging side (ours sears both), the opaque line-of-sight, the player-drawn shape/anchor, and the upcast.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `ability` | `Ability` | required |  |
| `dice` | `string` | required |  |
| `kind` | `string` | required |  |
| `length_ft` | `uint32` | required |  |

#### Effect::ZoneAfflict

A condition zone: the Zone's SNARING sibling — a CONCENTRATION area fixed to a board point that AFFLICTS rather than damages. A creature starting its turn within `radius_ft` makes an `ability` save; on a FAILURE it gains `condition` (a `conditions/` id) for that turn — web's restrained, sleet storm's prone, stinking cloud's incapacitated. Established via a Target self-cast; BENEFICIAL for side-legality (emergent per-turn, like the Zone), the placement AI-chosen. The condition RE-EVALUATES each turn the creature lingers (a made save frees it). LEDGERED: the escape/break-free check, the difficult-terrain rider, the enters-the-area trigger (start-turn-in only), and the upcast.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `ability` | `Ability` | required |  |
| `condition` | `string` | required |  |
| `radius_ft` | `uint32` | required |  |

#### Effect::TempHp

A temporary hit-point grant: the target gains `dice` + `plus` temporary hit points — false life's ward. BENEFICIAL, instantaneous (NOT concentration): temp HP sits on the combatant and is spent before real HP (the dark-one's-blessing pool), taking the HIGHER of any existing pool and the fresh grant (SRD "decide whether to keep"). LEDGERED: the SRD 1-hour duration (temp HP has no clock in the bubble) and false life's flat +5-per-slot upcast (a flat-per-slot axis unmodelled — DicePerSlot is dice).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `dice` | `string` | required |  |
| `plus` | `int64` | required |  |

#### Effect::Resist

A resistance grant: the delivered target gains resistance to `kind` damage — protection from energy's ward, halving that one kind — for the CONCENTRATION duration. BENEFICIAL (a Target/Allies self-or-ally cast); an ongoing effect sourced by the caster, lifting when its concentration breaks (the source-keyed `spell_resist` pool). LEDGERED: the player's choice among the five energy kinds (ship one — fire) and the SRD 1-hour cap.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `kind` | `string` | required |  |

### OnSave

What a failed save spares (SRD: "half as much damage on a successful one").

`Half`, `Nothing`

### Source

Every file's top-level value carries `source`.

#### Source::Srd51

SRD 5.1 — the System Reference Document, the shipped baseline.

#### Source::Original

Original content authored for this game (not from the SRD).

#### Source::Personal

A player's own transcription or third-party content in a mod tree — provenance stays honest without borrowing the base tree's markers. Never used by shipped files.

### SpellRange

A spell's range. `Caster` is the SRD's "Self" (a Rust-reserved word).

#### SpellRange::Touch

Touch — the caster must reach the target (SRD "Touch").

#### SpellRange::Feet

A ranged spell out to this many feet.

Carries `uint32`.

#### SpellRange::Caster

Self — the spell affects only the caster (SRD "Self").

### Upcast

How a spell scales (SRD "At Higher Levels" + the cantrip level steps).

#### Upcast::None

No higher-level text.

#### Upcast::DicePerSlot

+`String` dice per slot level above the spell's own: onto the FIRST cast-time dice step (its damage or its heal), and onto EACH ongoing damaging effect (zone/aura/wall-burn/beam), baked into the effect's stored dice at cast.

Carries `string`.

#### Upcast::ExtraPerSlot

+1 dart/ray per slot level above the spell's own.

#### Upcast::ExtraTargetPerSlot

+1 TARGET per slot level above the spell's own: bless's extra ally, hold person's extra foe. On an `Allies` delivery it bumps the target count; on a single-target `Save` (area `None`) it adds that many nearest enemies within range. The sibling of `ExtraPerSlot` — that fans out projectiles at one target, this fans out DISTINCT creatures.

#### Upcast::FlatPerSlot

+`i64` FLAT per slot level above the spell's own: false life's +5 temporary hit points a slot. Added to the first cast-time dice step's flat total (its rolled amount), NOT its dice — the flat-number axis `DicePerSlot` (dice) cannot express.

Carries `int64`.

#### Upcast::SummonsPerTwoSlots

A conjuring's creature COUNT doubles per TWO slots above the spell's own: conjure animals' "twice as many at 5th, three times at 7th, four times at 9th". Mints `1 + (slot − level) / 2` copies of the summon.

