You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.)
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).
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.
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).
Plumbing landed in PR #40 (closed #38):
currentvitals, 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
currentvitals,castSpell(spends),applyDamage,heal(clamped, API-only), andrestoreVitals. 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):
rolled.ppe).H.P. / S.D.C. — "Battle Injuries & Recovery" (printed p.354):
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).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 (healpath,rolledmax 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 — passdaysAlreadyTreatedor store it; decide at impl).leyLineDraw({ id, melees, atNexus })→ P.P.E.currentpath asheal. Every write still revalidates viaderiveSheet.Healing spells (self and other characters)
spellSchemagains an optional structuredhealingfield — parallel to the printeddamagestring, but structured because the engine must apply it:{ hitPoints?: <dice>, sdc?: <dice>, target: "self" | "touch" | "ranged" }.castSpellgains optionaltargetId(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).Web
> 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).targetIdfrom day one).> 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.