Skip to content

Recovery rates & healing spells: rest/meditation/ley draw, treatment days, spell healing with targets #41

Description

@StreamDemon

Plumbing landed in PR #40 (closed #38): current vitals, castSpell/applyDamage/heal/restoreVitals, live bars. This issue is the remaining book-rules layer. Full spec below (originally written on #38, verified against rendered pages; printed page = PDF page − 3).

PR #40 landed current vitals, castSpell (spends), applyDamage, heal (clamped, API-only), and restoreVitals. This follow-up adds the rates the book prescribes, plus healing spells. Page references verified by rendering (printed page = PDF page − 3).

The printed rules

P.P.E. — "Recovery of P.P.E." (printed p.186):

  • Natural recovery: ~5 P.P.E. per hour of rest or sleep (O.C.C.s may override).
  • Meditation: 10 per hour; an hour of meditation counts as an hour of restorative sleep.
  • Never above the permanent P.P.E. base (our rolled.ppe).
  • Ley line draw: most magic O.C.C.s take 10 P.P.E. per melee round on a ley line, 20 at a nexus — the Ley Line Walker draws double (20 / 40). Must be standing in/at it. (Special-time multipliers — dawn ×2, equinox ×3, solstice ×10, eclipses — are GM-territory flavor; out of scope.)

H.P. / S.D.C. — "Battle Injuries & Recovery" (printed p.354):

  • Non-professional treatment: 2 H.P. and 4 S.D.C. per day.
  • Professional treatment: 2 H.P./day for the first two days, then 4/day; S.D.C. at 6/day.
  • (Optional Blood Loss bleeding rule and coma resuscitation rolls: out of scope with the death/coma state machine.)

There is no D&D-style short/long rest: recovery is continuous time-based rates. Elapsed time stays GM-adjudicated input (hours rested, days treated, melees on the line) — never a wall clock — so the engine stays deterministic.

Rules layer

  • content/combat/recovery.json, page-stamped: the six numbers above + the nexus/ley-line draw table with per-O.C.C. override (LLW ×2).
  • Pure engine fns: restRecovery(hours, mode) (rest | meditation), treatmentRecovery(days, professional) (handles the 2/2-then-4 professional ramp), leyLineDraw(melees, at) (reads the O.C.C. override). All return raw amounts; clamping stays where it lives today (heal path, rolled max as the cap).

Backend

  • rest({ id, hours, mode }) → P.P.E. via rate × hours.
  • treat({ id, days, professional }) → H.P./S.D.C. via rates (professional ramp needs days-elapsed accounting — pass daysAlreadyTreated or store it; decide at impl).
  • leyLineDraw({ id, melees, atNexus }) → P.P.E.
  • All compute amounts server-side from the validated rates (client names time, never points) and land through the same clamped current path as heal. Every write still revalidates via deriveSheet.

Healing spells (self and other characters)

  • spellSchema gains an optional structured healing field — parallel to the printed damage string, but structured because the engine must apply it: { hitPoints?: <dice>, sdc?: <dice>, target: "self" | "touch" | "ranged" }.
  • castSpell gains optional targetId (defaults to the caster): spend the caster's P.P.E., roll the healing dice server-side (mutations have seeded randomness), apply to the target document through the clamped heal path — cross-document writes are fine inside one Convex mutation, and this is the first table-shaped interaction (VTT groundwork).
  • Content reality: the current level 1–4 catalog has no H.P./S.D.C.-restoring spell (Cure Minor Disorders L4 is condition relief). Real healing (Heal Wounds L6 etc.) arrives with Complete the spell list (levels 5-15) #13 spells 5–15 — transcribe exact dice + pages then. The schema/mutation shape should land first so Complete the spell list (levels 5-15) #13 is content-only.
  • Psionic healing (Psionics subsystem (I.S.P. + psychic powers) #14) reuses the same target/heal path.

Web

  • Telemetry rail gains a compact RECOVERY group: > Rest (hours input + rest/meditate toggle), > Ley Draw (one click per melee — 20 P.P.E. for the LLW, very on-brand for the cyan bar), > Treatment Day (professional toggle).
  • Healing casts: target picker only once multi-character play exists; until then self-target by default (API supports targetId from day one).
  • Telemetry lines follow the house voice: > REST :: 6 HR — P.P.E. +30 [84/84], > LEY DRAW :: +20 P.P.E. [64/84], > TREATMENT :: DAY 3 (PRO) — H.P. +4 · S.D.C. +6.

Out of scope (unchanged from the issue)

Blood Loss bleeding ticks, coma/death resuscitation rolls, M.D.C., temporary P.P.E. batteries, special-time ley multipliers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:backendConvex backendarea:frontendWeb app (builder + sheet)area:rulesRules engine (@riftforge/rules)

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions