Allow Fremen Nexus Betrayal before native worm rides
This commit is contained in:
1 parent
78bcf22bca
commit
725672364d
19 files changed
+1251
-20
No files matched your search
@@ -45,6 +45,7 @@ import { NexusMoritaniBetrayal } from './nexus-moritani-betrayal';
|
||||
import { buildRevision, buildRevisionLabel } from '@/lib/build-revision';
|
||||
import { NexusEcazBetrayal } from './nexus-ecaz-betrayal';
|
||||
import { NexusFremenBetrayal } from './nexus-fremen-betrayal';
|
||||
import { NexusFremenRideBetrayal } from './nexus-fremen-ride-betrayal';
|
||||
import { NexusEcazInquiry } from './nexus-ecaz-inquiry';
|
||||
import { NexusEcazDuke } from './nexus-ecaz-duke';
|
||||
import { NexusTleilaxu } from './nexus-tleilaxu';
|
||||
@@ -347,8 +348,8 @@ export function GameTable({
|
||||
const harkonnenBetrayalOwnsControls = !!g.nexusHarkonnenBetrayalReaction &&
|
||||
!g.response && !g.decision && !g.truthtrance && !g.phaseOpening &&
|
||||
!g.automaticContinuationPending && !g.nexusCards?.waiting.length && !g.nexusTraitors?.pending;
|
||||
const busy = reactionBusy || g.automaticContinuationPending || !!g.semutaReaction || !!g.kullReaction || !!g.richeseBetrayalReaction || !!g.guildBetrayalReaction || !!g.nexusIxianReplacement || ixianBetrayalOwnsControls || harkonnenBetrayalOwnsControls;
|
||||
const reactionOwnsControls = !!g.kullReaction || !!g.kullCounterEvent || !!g.richeseBetrayalReaction || !!g.guildBetrayalReaction || !!g.nexusIxianReplacement || ixianBetrayalOwnsControls || harkonnenBetrayalOwnsControls;
|
||||
const busy = reactionBusy || !!g.nexusFremenRideBetrayal || g.automaticContinuationPending || !!g.semutaReaction || !!g.kullReaction || !!g.richeseBetrayalReaction || !!g.guildBetrayalReaction || !!g.nexusIxianReplacement || ixianBetrayalOwnsControls || harkonnenBetrayalOwnsControls;
|
||||
const reactionOwnsControls = !!g.nexusFremenRideBetrayal || !!g.kullReaction || !!g.kullCounterEvent || !!g.richeseBetrayalReaction || !!g.guildBetrayalReaction || !!g.nexusIxianReplacement || ixianBetrayalOwnsControls || harkonnenBetrayalOwnsControls;
|
||||
const canSpendKarama = (card: Card, purpose: KullPurpose) =>
|
||||
!kullPurposeBlock(g, purpose) && canUseAsKaramaRole(g, me, card);
|
||||
const canActivateKarama = (card: Card) => canSpendKarama(card, kullSpecialPurpose(me.faction));
|
||||
@@ -1974,6 +1975,7 @@ export function GameTable({
|
||||
</div>
|
||||
{g.battle?.revealed && <a className="battle-display-link" href="#revealed-battle-plans">Compare revealed battle plans</a>}
|
||||
<PrivateBattlePlan game={g} />
|
||||
<NexusFremenRideBetrayal game={g} act={act} busy={reactionBusy} />
|
||||
<HomeworldEcazDuke game={g} act={act} busy={reactionBusy || !!g.roomControl?.paused || !!g.roomControl?.closed || !!me.autopilot} />
|
||||
<MovementPromises game={g} act={act} busy={reactionBusy} />
|
||||
{!reactionOwnsControls && g.semutaReaction && <SemutaReaction game={g} act={act} busy={reactionBusy} />}
|
||||
|
||||
@@ -18,7 +18,7 @@ export function NexusFremenBetrayal({ game, act, busy }: Props) {
|
||||
<p>{nexusCardReference('fremen').betrayal}</p>
|
||||
{fremen && <p className="fine">
|
||||
{offer.mode === 'worm'
|
||||
? `Declare before the first spice blow: ${fremen.name} cannot take ordinary or Cunning worm rides this turn. Worm destruction, survival, protection and Nexus still resolve.`
|
||||
? `Declare before the first spice blow, or respond at an actual before-ride opportunity: ${fremen.name} cannot take remaining ordinary or Cunning worm rides this turn. Worm destruction, survival, protection and Nexus still resolve.`
|
||||
: `This use suppresses ${fremen.name}’s native two-territory movement advantage for the rest of this turn. Independent ornithopters remain available.`}
|
||||
</p>}
|
||||
{offer.mode === 'worm' && game.discoveries && <p className="fine">
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
'use client';
|
||||
|
||||
import type { Action, GameView } from '@/game/engine';
|
||||
import { territory } from '@/game/board';
|
||||
import { Button } from './ui/button';
|
||||
|
||||
export function NexusFremenRideBetrayal({ game, act, busy }: {
|
||||
game: GameView;
|
||||
act: (action: Action) => void;
|
||||
busy: boolean;
|
||||
}) {
|
||||
const reaction = game.nexusFremenRideBetrayal;
|
||||
if (!reaction) return null;
|
||||
const source = reaction.source;
|
||||
const rider = game.players.find(player => player.id === source.player)?.name ?? 'The rider';
|
||||
const responder = game.players.find(player => player.id === reaction.player)?.name ?? 'The current responder';
|
||||
const hasPassed = reaction.passed.includes(game.me);
|
||||
const canRespond = reaction.player === game.me && !hasPassed;
|
||||
const disabled = busy || game.status !== 'playing';
|
||||
return (
|
||||
<section className="notice min-w-0 space-y-3" aria-label="Fremen Nexus before-ride Betrayal">
|
||||
<h3>Fremen Nexus Betrayal · before a ride</h3>
|
||||
<p>
|
||||
{source.kind === 'wormRide'
|
||||
? `${rider} has a worm ride from ${territory(source.territory).name} waiting.`
|
||||
: source.kind === 'nexusFremenCunningRide'
|
||||
? `${rider} has a Fremen Nexus Cunning ride waiting.`
|
||||
: `${rider} has a Great Maker ride waiting.`}
|
||||
</p>
|
||||
<p className="fine">
|
||||
This before-ride response is offered without revealing anyone’s secret
|
||||
Nexus identity. Continue to allow the original ride choices, or use an
|
||||
eligible Fremen Nexus to prevent the remaining rides this turn.
|
||||
</p>
|
||||
<p className="fine">
|
||||
The worm, Spice Blow and any Nexus that have already resolved stay
|
||||
resolved. Prevention does not move or destroy forces. Previous payments
|
||||
and effects are not repeated.
|
||||
</p>
|
||||
{!canRespond ? (
|
||||
<p aria-live="polite">
|
||||
{hasPassed
|
||||
? 'You have continued. Waiting for the remaining ride responses.'
|
||||
: `Waiting for ${responder} to respond before the ride.`}
|
||||
</p>
|
||||
) : (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button
|
||||
data-testid="nexus-fremen-ride-continue"
|
||||
className="game-action min-h-11 whitespace-normal"
|
||||
disabled={disabled}
|
||||
onClick={() => {
|
||||
if (!disabled) act({ type: 'decision', event: reaction.event, use: false });
|
||||
}}
|
||||
>
|
||||
Continue · allow rides
|
||||
</Button>
|
||||
{reaction.canUse && (
|
||||
<Button
|
||||
data-testid="nexus-fremen-ride-prevent"
|
||||
className="game-action min-h-11 whitespace-normal"
|
||||
disabled={disabled}
|
||||
onClick={() => {
|
||||
if (!disabled) act({ type: 'decision', event: reaction.event, use: true });
|
||||
}}
|
||||
>
|
||||
Use Fremen Nexus · prevent remaining rides
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user