Connect Moritani Extortion through Mentat settlement
This commit is contained in:
1 parent
88829b7057
commit
745e4fa8ab
19 files changed
+901
-55
No files matched your search
@@ -213,6 +213,7 @@ import {
|
||||
import { TERROR_DEFINITIONS } from '@/game/moritani-terror';
|
||||
import { MoritaniRetention } from './moritani-retention';
|
||||
import { MoritaniAssassinate, MoritaniAssassinateHistory } from './moritani-assassinate';
|
||||
import { MoritaniExtortion, MoritaniExtortionNotice } from './moritani-extortion';
|
||||
export function GameTable({
|
||||
game: g,
|
||||
send,
|
||||
@@ -1048,6 +1049,7 @@ export function GameTable({
|
||||
<DukeVidal game={g} />
|
||||
<EcazLoyaltyCard loyalty={g.ecazLoyalty} />
|
||||
<MoritaniTerrorSupply game={g} />
|
||||
<MoritaniExtortionNotice game={g} />
|
||||
<MoritaniAssassinateHistory game={g} />
|
||||
<AmbassadorSupply game={g} />
|
||||
<AmbassadorInsights key={`${g.code}-${g.me}`} game={g} />
|
||||
@@ -2321,6 +2323,8 @@ export function GameTable({
|
||||
? g.decision.source === 'nexus' ? 'Moritani Nexus · after-loss choice' : 'Moritani · allied card retention'
|
||||
: g.decision.kind === 'moritaniTerror'
|
||||
? 'Moritani · Terror entry reaction'
|
||||
: g.decision.kind === 'moritaniExtortion'
|
||||
? 'Moritani · Extortion payment'
|
||||
: g.decision.kind === 'moritaniSetup'
|
||||
? 'Moritani · final deployment'
|
||||
: g.decision.kind === 'moritaniPlacement'
|
||||
@@ -2613,6 +2617,8 @@ export function GameTable({
|
||||
<EcazPlacement game={g} act={act} busy={busy} />
|
||||
) : g.decision.kind === 'moritaniPlacement' ? (
|
||||
<MoritaniPlacement game={g} act={act} busy={busy} />
|
||||
) : g.decision.kind === 'moritaniExtortion' ? (
|
||||
<MoritaniExtortion game={g} act={act} busy={busy} />
|
||||
) : g.decision.kind === 'choamStorm' ? (
|
||||
<ChoamStorm game={g} act={act} busy={busy} />
|
||||
) : g.decision.kind === 'choamMovement' ? (
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
'use client';
|
||||
|
||||
import type { Action, GameView } from '@/game/engine';
|
||||
import { Button } from './ui/button';
|
||||
|
||||
export function MoritaniExtortionNotice({ game }: { game: GameView }) {
|
||||
const deferred = game.extortion?.deferred ?? 0;
|
||||
const pending = game.extortion?.pending;
|
||||
if (!deferred && !pending) return null;
|
||||
|
||||
const payer = pending && game.players.find((player) => player.id === pending.player);
|
||||
return (
|
||||
<section className="notice" aria-label="Moritani Extortion status">
|
||||
{deferred > 0 && (
|
||||
<p>
|
||||
Moritani Extortion: {deferred} spice from the bank is set aside for
|
||||
Moritani to collect during Mentat Pause. It is not yet spendable.
|
||||
</p>
|
||||
)}
|
||||
{pending && (
|
||||
<p>
|
||||
Moritani has collected the bank award. {payer?.name ?? 'The current player'}
|
||||
{' '}may pay {pending.amount} spice to prevent Extortion’s return, or decline.
|
||||
The first payment ends the opportunity; if everyone declines, the token
|
||||
returns to Moritani’s hidden supply.
|
||||
</p>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export function MoritaniExtortion({
|
||||
game,
|
||||
act,
|
||||
busy,
|
||||
}: {
|
||||
game: GameView;
|
||||
act: (action: Action) => void;
|
||||
busy: boolean;
|
||||
}) {
|
||||
const decision = game.decision;
|
||||
const pending = game.extortion?.pending;
|
||||
if (
|
||||
decision?.kind !== 'moritaniExtortion' ||
|
||||
decision.player !== game.me ||
|
||||
!pending ||
|
||||
pending.player !== game.me ||
|
||||
pending.event !== decision.event
|
||||
) return null;
|
||||
|
||||
const disabled = busy || !!game.response || !!game.truthtrance;
|
||||
return (
|
||||
<section className="notice min-w-0 space-y-3" aria-label="Your Moritani Extortion payment choice">
|
||||
<p>
|
||||
Pay Moritani {pending.amount} spice to remove the Extortion token permanently,
|
||||
or decline. The five-spice bank award has already been collected.
|
||||
</p>
|
||||
{!pending.canPay && (
|
||||
<p className="fine">You do not have enough spice to pay. You may decline.</p>
|
||||
)}
|
||||
<Button
|
||||
className="min-h-11 w-full whitespace-normal"
|
||||
disabled={disabled || !pending.canPay}
|
||||
onClick={() => act({ type: 'decision', event: decision.event, pay: true })}
|
||||
>
|
||||
Pay {pending.amount} spice to Moritani
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="min-h-11 w-full whitespace-normal"
|
||||
disabled={disabled}
|
||||
onClick={() => act({ type: 'decision', event: decision.event, pay: false })}
|
||||
>
|
||||
Decline payment
|
||||
</Button>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user