Prototype CHOAM Nexus after-victory inspection

This commit is contained in:
Quintine committed 2026-09-28 10:34:09 +10:00
1 parent 209fb18a27
commit cb98ead411
15 files changed
+614 -37

No files matched your search

+4 -1
View File
@@ -28,7 +28,7 @@ import { GreatMakerDecision } from './great-maker';
import { DiscoveryPanel, DiscoveryDiscardDecision } from './discoveries';
import { DiscoveryEntryDecision } from './discovery-entry';
import { DiscoveryStormDecision } from './discovery-storm';
import { NexusChoamTrade } from './nexus-choam-trade';
import { NexusChoamTrade, NexusChoamInspectionDecision, NexusChoamInspectionInsight } from './nexus-choam-trade';
import { NexusChoamBetrayal } from './nexus-choam-betrayal';
import { NexusMoritaniBetrayal } from './nexus-moritani-betrayal';
import { buildRevision, buildRevisionLabel } from '@/lib/build-revision';
@@ -1040,6 +1040,7 @@ export function GameTable({
<AmbassadorSupply game={g} />
<AmbassadorInsights key={`${g.code}-${g.me}`} game={g} />
<AuditorInsight game={g} />
<NexusChoamInspectionInsight game={g} />
<div className="play-grid">
<aside className="players-panel">
<div className="eyebrow">THE GREAT HOUSES</div>
@@ -2667,6 +2668,8 @@ export function GameTable({
decline: true,
})}
</>
) : g.decision.kind === 'nexusChoamInspection' ? (
<NexusChoamInspectionDecision game={g} act={act} busy={busy} />
) : g.decision.kind === 'choamAudit' ||
g.decision.kind === 'choamAuditPayment' ? (
<AuditorDecision game={g} act={act} busy={busy} />
+51 -2
View File
@@ -3,7 +3,7 @@
import { useState } from 'react';
import type { Action, GameView } from '@/game/engine';
import { nexusChoamTradeAction } from '@/game/nexus-choam-trade-options';
import { CardInspector } from './card-inspector';
import { CardInspector, CardRules } from './card-inspector';
import { Button } from './ui/button';
type Props = { game: GameView; act: (action: Action) => void; busy: boolean };
@@ -30,7 +30,56 @@ export function NexusChoamTrade({ game, act, busy }: Props) {
onClick={() => { if (!busy && action) act(action); }}>
Trade {card?.name ?? 'a Worthless card'} for 2 spice
</Button>
<p className="fine">Optional: keep both cards by continuing the phase. This Nexus card’s battle inspection alternative is still in development.</p>
<p className="fine">Optional: keep both cards by continuing the phase. The same card can instead be spent after a battle victory to inspect one unused opposing card.</p>
</section>
);
}
export function NexusChoamInspectionDecision({ game, act, busy }: Props) {
const offer = game.nexusChoamInspection;
if (!offer) return null;
const opponent = game.players.find(player => player.id === offer.opponent);
return (
<section aria-label="Postbattle CHOAM Nexus choice" className="min-w-0 space-y-3">
<h3 className="font-serif text-xl">After victory · CHOAM Secret Ally</h3>
<p className="text-base leading-7">
Every winner receives this private choice. If you hold the CHOAM Nexus
card while unallied, you may spend it to inspect one random unused card
held by {opponent?.name ?? 'your opponent'}. Otherwise continue.
</p>
<div className="flex flex-wrap gap-2">
{offer.canInspect && (
<Button disabled={busy} onClick={() =>
act({ type: 'decision', event: offer.event, inspect: true })}>
Spend CHOAM Nexus · inspect one card
</Button>
)}
<Button variant="outline" disabled={busy} onClick={() =>
act({ type: 'decision', event: offer.event, inspect: false })}>
Continue without inspection
</Button>
</div>
</section>
);
}
export function NexusChoamInspectionInsight({ game }: { game: GameView }) {
const insight = game.nexusChoamInsight;
if (!insight) return null;
const opponent = game.players.find(player => player.id === insight.target);
return (
<section aria-label="Your private CHOAM Nexus inspection" className="notice min-w-0 space-y-3">
<h3 className="font-serif text-xl">Your CHOAM Nexus inspection · {opponent?.name}</h3>
<p className="text-base leading-7">
Only you see this card. It was in the opposing hand when the battle
ended; it may move afterward. This snapshot remains until the next
battle or turn.
</p>
<article className="min-w-0 space-y-3 rounded-lg border border-[#485542] p-4">
<h4 className="font-serif text-xl">{insight.card.name}</h4>
<CardRules card={insight.card} />
<CardInspector card={insight.card} />
</article>
</section>
);
}