feat(frontend): ritual mini-game, judgment UI, and consequences (Workstream E)
Implements the Character Depth / Ghost Log spec's Workstream E: - RitualPanel.tsx: a 4-step "focus the channel" hold-to-charge sequence (align/breathe/trace/lock), sending ritual_step frames as the seeker progresses. Success reveals the entity's true hidden traits; failure reveals nothing. Sequencing/timing logic lives in the pure, unit-tested lib/ritual.ts rather than inline in the component. - JudgmentPanel.tsx: Trust/Banish/Cross Over/Test verdict buttons with rune-style SVG icons, sending the judgment frame and rendering a distinct treatment per judgment_result consequence — reward, escalation (also spikes the ambient haunting), withdrawal, resisted, neutral, and a calm glyph-fade farewell for crossed_over (deliberately not the reward treatment, since it's a goodbye). - lib/haunting.ts: IdleEscalator gains forceEscalate()/forcedUntil so a judgment's "escalation" consequence can spike the ambient haunting immediately instead of waiting on the 90s idle clock; exports a sharedIdleEscalator singleton and a forceEscalate() free function. HauntingLayer now paces itself off that shared instance instead of a private one, so the forced spike actually reaches the running layer. - state/seance.tsx: new ritual/judgmentResult state, a local_ritual_start action, and reducer cases for the ritual_complete/judgment_result server frames; SeanceContext exported for component testing; startRitual/ sendRitualStep/sendJudgment added to the provider API. - lib/types.ts: EntityTraits/JudgmentVerdict/JudgmentConsequence types and the new client/server WS frames, per the spec's Contract section. - i18n: seance.ritual.* / seance.judgment.* keys in en.json and es.json. Fast-forwarded this worktree's branch onto master first — it had been created from a stale ancestor commit predating the frontend scaffold entirely, with zero commits of its own ahead of that point. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -180,6 +180,78 @@
|
||||
"mythic": "mythic"
|
||||
}
|
||||
},
|
||||
"ritual": {
|
||||
"title": "focus the channel",
|
||||
"none": "no presence to focus on",
|
||||
"noneHint": "summon a spirit before attempting the rite",
|
||||
"begin": "begin the rite",
|
||||
"retry": "attempt again",
|
||||
"hold": "hold to focus",
|
||||
"awaiting": "awaiting the veil's answer…",
|
||||
"successTitle": "the channel holds — the truth surfaces",
|
||||
"failureTitle": "the channel collapses",
|
||||
"failureHint": "the truth stays hidden — the rite may be tried again",
|
||||
"traits": {
|
||||
"alignment": "alignment",
|
||||
"power": "power",
|
||||
"volatility": "volatility",
|
||||
"deceptiveness": "deceptiveness"
|
||||
},
|
||||
"steps": {
|
||||
"align": {
|
||||
"command": "> aligning the wire…",
|
||||
"locked": "> wire aligned ✓"
|
||||
},
|
||||
"breath": {
|
||||
"command": "> steadying the breath…",
|
||||
"locked": "> breath steadied ✓"
|
||||
},
|
||||
"trace": {
|
||||
"command": "> tracing the sigil…",
|
||||
"locked": "> sigil traced ✓"
|
||||
},
|
||||
"lock": {
|
||||
"command": "> locking the channel…",
|
||||
"locked": "> channel locked ✓"
|
||||
}
|
||||
}
|
||||
},
|
||||
"judgment": {
|
||||
"title": "render judgment",
|
||||
"none": "no presence to judge",
|
||||
"noneHint": "summon a spirit first",
|
||||
"trust": "trust",
|
||||
"banish": "banish",
|
||||
"crossOver": "cross over",
|
||||
"test": "test",
|
||||
"pending": "awaiting the verdict…",
|
||||
"favor": "favor",
|
||||
"essence": "essence",
|
||||
"reward": {
|
||||
"title": "the bond holds",
|
||||
"body": "the spirit answers your trust in kind."
|
||||
},
|
||||
"escalation": {
|
||||
"title": "a reckoning",
|
||||
"body": "wrongly trusted, it turns — the haunting sharpens."
|
||||
},
|
||||
"withdrawal": {
|
||||
"title": "it recoils",
|
||||
"body": "banished in error, the presence withdraws, wounded."
|
||||
},
|
||||
"crossedOver": {
|
||||
"title": "at peace",
|
||||
"body": "the spirit lets go, and the line falls quiet."
|
||||
},
|
||||
"resisted": {
|
||||
"title": "it will not go",
|
||||
"body": "a demon does not cross over — it claws back to stay."
|
||||
},
|
||||
"neutral": {
|
||||
"title": "no verdict rendered",
|
||||
"body": "a diagnostic pulse only — nothing risked, nothing gained."
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"rate_limited": "the veil is thin — slow your knocking",
|
||||
"veil_crowded": "too many spirits crowd the line"
|
||||
|
||||
Reference in New Issue
Block a user