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": "mítico"
|
||||
}
|
||||
},
|
||||
"ritual": {
|
||||
"title": "enfoca el canal",
|
||||
"none": "ninguna presencia que enfocar",
|
||||
"noneHint": "invoca un espíritu antes de intentar el rito",
|
||||
"begin": "comenzar el rito",
|
||||
"retry": "intentar de nuevo",
|
||||
"hold": "mantén para enfocar",
|
||||
"awaiting": "esperando la respuesta del velo…",
|
||||
"successTitle": "el canal se sostiene — la verdad emerge",
|
||||
"failureTitle": "el canal colapsa",
|
||||
"failureHint": "la verdad permanece oculta — el rito puede intentarse de nuevo",
|
||||
"traits": {
|
||||
"alignment": "alineación",
|
||||
"power": "poder",
|
||||
"volatility": "volatilidad",
|
||||
"deceptiveness": "engaño"
|
||||
},
|
||||
"steps": {
|
||||
"align": {
|
||||
"command": "> alineando el cable…",
|
||||
"locked": "> cable alineado ✓"
|
||||
},
|
||||
"breath": {
|
||||
"command": "> serenando el aliento…",
|
||||
"locked": "> aliento sereno ✓"
|
||||
},
|
||||
"trace": {
|
||||
"command": "> trazando el sigilo…",
|
||||
"locked": "> sigilo trazado ✓"
|
||||
},
|
||||
"lock": {
|
||||
"command": "> cerrando el canal…",
|
||||
"locked": "> canal cerrado ✓"
|
||||
}
|
||||
}
|
||||
},
|
||||
"judgment": {
|
||||
"title": "dicta juicio",
|
||||
"none": "ninguna presencia que juzgar",
|
||||
"noneHint": "invoca un espíritu primero",
|
||||
"trust": "confiar",
|
||||
"banish": "desterrar",
|
||||
"crossOver": "cruzar al más allá",
|
||||
"test": "poner a prueba",
|
||||
"pending": "esperando el veredicto…",
|
||||
"favor": "favor",
|
||||
"essence": "esencia",
|
||||
"reward": {
|
||||
"title": "el vínculo se sostiene",
|
||||
"body": "el espíritu responde a tu confianza de igual manera."
|
||||
},
|
||||
"escalation": {
|
||||
"title": "un ajuste de cuentas",
|
||||
"body": "confiado en error, se revuelve — la aparición se agudiza."
|
||||
},
|
||||
"withdrawal": {
|
||||
"title": "se retrae",
|
||||
"body": "desterrado en error, la presencia se retira, herida."
|
||||
},
|
||||
"crossedOver": {
|
||||
"title": "en paz",
|
||||
"body": "el espíritu se suelta, y la línea queda en silencio."
|
||||
},
|
||||
"resisted": {
|
||||
"title": "no se irá",
|
||||
"body": "un demonio no cruza al más allá — se aferra para quedarse."
|
||||
},
|
||||
"neutral": {
|
||||
"title": "ningún veredicto emitido",
|
||||
"body": "solo un pulso de diagnóstico — no se arriesga ni se gana nada."
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"rate_limited": "el velo es delgado — golpea más despacio",
|
||||
"veil_crowded": "demasiados espíritus se apiñan en la línea"
|
||||
|
||||
Reference in New Issue
Block a user