Open native advisor preparation before the first shipment
Allow Advanced BG preparation in phases2–5 at quiet boundaries, preserving original phase/auction/readiness and native eligibility. Close a current-turn receipt only on committed shipments, including marker and Sneak Attack entry. Retain the legacy phase5 queue and qualify the per-territory prevention policy. Connect persistent controls, minimal bot support and focused native evidence. Complete modes and browser/deployed acceptance remain open.
This commit is contained in:
1 parent
0e3d6a250e
commit
660b0a0c25
18 files changed
+1269
-13
No files matched your search
@@ -0,0 +1,72 @@
|
||||
'use client';
|
||||
|
||||
import { ArrowRight } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { territory } from '@/game/board';
|
||||
import type { Action, GameView } from '@/game/engine';
|
||||
|
||||
export function AdvisorPreparation({
|
||||
game,
|
||||
act,
|
||||
busy,
|
||||
}: {
|
||||
game: GameView;
|
||||
act: (action: Action) => void;
|
||||
busy: boolean;
|
||||
}) {
|
||||
const offer = game.advisorPreparation;
|
||||
const me = game.players.find((player) => player.id === game.me);
|
||||
if (!offer || game.status !== 'playing' || !game.advanced ||
|
||||
game.phase < 2 || game.phase > 5 || me?.faction !== 'beneGesserit') return null;
|
||||
const priorityPending = !!game.response || !!game.decision || !!game.phaseOpening;
|
||||
const blocked = offer.blocked || (priorityPending
|
||||
? 'Finish the current response, decision or phase opening before preparing advisors.'
|
||||
: null);
|
||||
const disabled = busy || !!blocked || !!game.truthtrance || !!game.nexusTraitors?.pending;
|
||||
return (
|
||||
<section className="notice space-y-3" aria-label="Bene Gesserit advisor preparation">
|
||||
<h3 className="font-serif text-xl">Prepare advisors for battle</h3>
|
||||
<p className="muted">
|
||||
After Spice Blow and any Nexus, you may prepare advisors until the first
|
||||
actual shipment has occurred. This window includes Charity, Bidding, Revival
|
||||
and the opening of Shipment and Movement.
|
||||
</p>
|
||||
<p className="fine">
|
||||
Choose a territory to turn all your advisors there into fighters, across
|
||||
every sector. Storm, ordinary allied occupation and fresh-advisor restrictions
|
||||
still apply. The existing supported Ecaz co-side composition retains its
|
||||
separate eligibility.
|
||||
</p>
|
||||
<p className="fine">
|
||||
Provisional Karama policy: a canceled preparation blocks that territory
|
||||
until this window ends. Other eligible territories remain available.
|
||||
Intrusion, Nexus conversion and automatic advisor flips remain independent.
|
||||
</p>
|
||||
<p className="fine">
|
||||
The ordinary advisor chooser during Shipment and Movement remains
|
||||
available. Declining that choice does not close this preparation window.
|
||||
</p>
|
||||
{blocked && <p className="notice" id="advisor-preparation-unavailable">{blocked}</p>}
|
||||
{!offer.territories.length && (
|
||||
<p className="muted">No advisor territory is currently eligible for preparation.</p>
|
||||
)}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{offer.territories.map((id) => (
|
||||
<Button
|
||||
key={id}
|
||||
data-testid={`advisor-preparation-${id}`}
|
||||
className="game-action min-h-11 whitespace-normal"
|
||||
disabled={disabled}
|
||||
aria-describedby={blocked ? 'advisor-preparation-unavailable' : undefined}
|
||||
onClick={() => {
|
||||
if (!disabled) act({ type: 'prepareAdvisors', territory: id });
|
||||
}}
|
||||
>
|
||||
Prepare advisors · {territory(id).name}
|
||||
<ArrowRight size={15} />
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -53,6 +53,7 @@ import { TerrorBoardMarkers } from './terror-board-markers';
|
||||
import { AmbassadorBoardMarkers } from './ambassador-board-markers';
|
||||
import { CharityClaim } from './charity-claim';
|
||||
import { FremenRevivalGrant } from './fremen-revival-grant';
|
||||
import { AdvisorPreparation } from './advisor-preparation';
|
||||
import { homeworldRevivalActionBlock } from '@/game/homeworld-revival-deployment-options';
|
||||
import { GuildHomeworldShipment } from './guild-homeworld-shipment';
|
||||
import { JunctionTransport } from './junction-transport';
|
||||
@@ -1973,6 +1974,7 @@ export function GameTable({
|
||||
{!reactionOwnsControls && <>
|
||||
<NexusCards game={g} act={act} busy={busy} />
|
||||
<Recruits game={g} act={act} busy={busy} />
|
||||
<AdvisorPreparation game={g} act={act} busy={transportBusy || !!g.roomControl?.paused || !!g.roomControl?.closed || !!me.autopilot} />
|
||||
<NexusTraitors game={g} act={act} busy={transportBusy || (!!g.roomControl?.paused || !!g.roomControl?.closed) || !!me.autopilot} />
|
||||
<DiscoveryPanel game={g} act={act} busy={transportBusy || (!!g.roomControl?.paused || !!g.roomControl?.closed) || !!me.autopilot} />
|
||||
<LeaderSkillsPanel skills={g.leaderSkills} leaders={g.allLeaders} players={g.players} act={act} busy={transportBusy || (!!g.roomControl?.paused || !!g.roomControl?.closed) || !!me.autopilot} />
|
||||
@@ -2548,6 +2550,9 @@ export function GameTable({
|
||||
allow five forces.
|
||||
</p>
|
||||
)}
|
||||
{g.response.kind === 'advisorFlip' && g.response.advisorResume === 'preparation' && (
|
||||
<p className="notice">Bene Gesserit declared native advisor preparation before the first shipment. Karama can prevent this territory’s flip. The current phase and its original auction, readiness or movement control continue afterward.</p>
|
||||
)}
|
||||
{g.response.kind === 'fremenRevivalGrant' && (
|
||||
<p className="notice">
|
||||
Fremen offered their current ally the ordinary free-revival rate of three.
|
||||
|
||||
Reference in new issue
Block a user