Connect Leader Skill battle effects and private Rihani exchanges

Prototype Mentat/Bureaucrat score effects, automatic Sandmaster board spice, and Rihani inspection plus committed exchange. Preserve private views, physical custody, saved winner cleanup and captive/Suk sequencing. Remaining normal bands, missing skill families and combined modules remain gated.

Validation: 45 focused tests; typecheck, lint, 4465 offline tests, production build and 43 HTTP tests passed. Independent rules/privacy/persistence review completed. New isolated browser setup exercised inspection, draw, pending refresh, exchange and completed refresh. Two genuine four-profile Basic/Advanced samples completed without rejected candidates but did not trigger Rihani.

Preserved all 393 opening rooms and original seat/recovery rows (427 rooms after QA/HTTP). SQLite integrity and foreign keys passed. Server remained healthy after the reported outage; no restart or reset.

Verified source tree: c64ce9537269de94c0d785bc08b17346e826c5797352a636771e1dc6ce5e4859
This commit is contained in:
Quintine committed 2026-09-13 19:45:29 +10:00
1 parent af360c836b
commit 06f46c6f79
26 files changed
+1230 -122

No files matched your search

+8
View File
@@ -48,6 +48,8 @@ import { RicheseGift } from './richese-gift';
import { Distrans } from './distrans';
import { JuiceOfSapho } from './juice-of-sapho';
import { LeaderSkillsPanel } from './leader-skills';
import { LeaderSkillBattleGuide } from './leader-skill-battle-guide';
import { RihaniChoice, RihaniHistory } from './rihani-decipherer';
import { SukGraduatePanel } from './suk-graduate';
import { NullentropyBox, NullentropySearch } from './nullentropy-box';
import { OrnithopterMovement } from './ornithopter-movement';
@@ -1464,6 +1466,7 @@ export function GameTable({
<NexusTraitors game={g} act={act} busy={transportBusy || !!me.autopilot} />
<DiscoveryPanel game={g} act={act} busy={transportBusy || !!me.autopilot} />
<LeaderSkillsPanel skills={g.leaderSkills} leaders={g.allLeaders} players={g.players} act={act} busy={transportBusy || !!me.autopilot} />
<RihaniHistory game={g} />
<NexusChoamTrade game={g} act={act} busy={transportBusy || !!me.autopilot} />
<NexusTleilaxu game={g} act={act} busy={transportBusy || !!me.autopilot} />
<NexusSuboids game={g} act={act} busy={transportBusy || !!me.autopilot} />
@@ -2081,6 +2084,8 @@ export function GameTable({
? 'Position your skilled leader'
: g.decision.kind === 'leaderSkillRevival'
? 'Choose a skill for the revived leader'
: g.decision.kind === 'rihani'
? g.decision.stage === 'offer' ? 'Rihani Decipherer — optional draw' : 'Choose your Traitor exchange'
: g.decision.kind === 'sukRescue'
? 'Save your battle casualties'
: g.decision.kind === 'homeworldRevivalDeployment'
@@ -2883,6 +2888,8 @@ export function GameTable({
</>
) : g.decision.kind === 'sukRescue' ? (
<SukGraduatePanel key={g.decision.event} decision={g.decision} act={act} busy={transportBusy || !!me.autopilot} />
) : g.decision.kind === 'rihani' ? (
<RihaniChoice key={g.decision.event} game={g} act={act} busy={transportBusy || !!me.autopilot} />
) : g.decision.kind === 'battleLosses' ? (
<>
<p className="muted">
@@ -4282,6 +4289,7 @@ export function GameTable({
</>
) : (
<>
<LeaderSkillBattleGuide game={g} leader={committed.leader ? String(committed.leader.value ?? '') : leader} />
{g.battle.insight && (
<p className="notice">
{committed[g.battle.insight.field]