Implement mixed Planetologist advisor gather continuation
This commit is contained in:
1 parent
bc37cd38fe
commit
c265f0638e
16 files changed
+512
-171
No files matched your search
@@ -97,7 +97,7 @@ import { NexusHarkonnenBetrayal } from './nexus-harkonnen-betrayal';
|
||||
import { OrnithopterMovement } from './ornithopter-movement';
|
||||
import { DiscoveryOrnithopterMovement } from './discovery-flight-movement';
|
||||
import { PlanetologistMovement } from './planetologist-movement';
|
||||
import { selectedOriginElites } from '@/game/planetologist-movement';
|
||||
import { selectedOriginElites, advisorFlipMovementBlocked } from '@/game/planetologist-movement';
|
||||
import { SandmasterMovement } from './sandmaster-movement';
|
||||
import { SandmasterWormChoice } from './sandmaster-worm';
|
||||
import { sandmasterWormCollection } from '@/game/sandmaster-worm';
|
||||
@@ -796,6 +796,7 @@ export function GameTable({
|
||||
sector,
|
||||
...(includesNoField ? {} : { amount }),
|
||||
};
|
||||
const advisorFlipRouteBlocked = ordinaryMovementAction.fighters === true && advisorFlipMovementBlocked(g, me);
|
||||
const transportAction: Action = {
|
||||
type: 'guildShip',
|
||||
...(useGuildSecret ? {nexus: guildSecretEvent} : {}),
|
||||
@@ -2583,6 +2584,14 @@ export function GameTable({
|
||||
unchanged.
|
||||
</p>
|
||||
)}
|
||||
{g.response.kind === 'advisorFlip' && g.response.advisorResume === 'planetologistGather' && (
|
||||
<p className="notice">
|
||||
Provisional mixed Planetologist gather: allow one common fighter
|
||||
arrival before either group moves, or cancel the native advisor
|
||||
flip. Cancellation keeps both groups and the movement allowance
|
||||
unchanged, with flipping blocked for that movement opportunity.
|
||||
</p>
|
||||
)}
|
||||
{g.response.kind === 'nexusGuildCunning' && <p className="notice">
|
||||
Allow one second Guild shipment at its normal price, or cancel this extra opportunity.
|
||||
The completed first shipment and movement stay unchanged; the Nexus is already spent.
|
||||
@@ -4792,6 +4801,12 @@ export function GameTable({
|
||||
territory
|
||||
</label>
|
||||
)}
|
||||
{advisorFlipRouteBlocked && (
|
||||
<p className="notice" id="movement-advisor-flip-unavailable">
|
||||
Advisor flipping was canceled for this movement. Turn off
|
||||
the fighter request or choose a group that is already fighting.
|
||||
</p>
|
||||
)}
|
||||
{!g.ornithopter?.active && (
|
||||
<>
|
||||
{actionButton(
|
||||
@@ -4802,18 +4817,21 @@ export function GameTable({
|
||||
!source ||
|
||||
canceledFremenRouteBlocked ||
|
||||
ordinaryMovementRouteBlocked ||
|
||||
advisorFlipRouteBlocked ||
|
||||
selectedDestinationInStorm ||
|
||||
(me.moved ?? 0) >= (me.movesAllowed ?? 1) ||
|
||||
(includesNoField
|
||||
? !validMarkerGroup
|
||||
: (me.forces[source] ?? 0) === 0),
|
||||
selectedDestinationInStorm
|
||||
? 'movement-storm-unavailable'
|
||||
: ordinaryMovementRouteBlocked
|
||||
? 'movement-route-unavailable'
|
||||
: canceledFremenRouteBlocked
|
||||
? 'movement-range-unavailable'
|
||||
: undefined,
|
||||
advisorFlipRouteBlocked
|
||||
? 'movement-advisor-flip-unavailable'
|
||||
: selectedDestinationInStorm
|
||||
? 'movement-storm-unavailable'
|
||||
: ordinaryMovementRouteBlocked
|
||||
? 'movement-route-unavailable'
|
||||
: canceledFremenRouteBlocked
|
||||
? 'movement-range-unavailable'
|
||||
: undefined,
|
||||
)}
|
||||
{canceledFremenRouteBlocked &&
|
||||
!selectedDestinationInStorm && (
|
||||
@@ -4879,6 +4897,7 @@ export function GameTable({
|
||||
move={
|
||||
!source ||
|
||||
!movementAvailable ||
|
||||
advisorFlipRouteBlocked ||
|
||||
(me.moved ?? 0) >= (me.movesAllowed ?? 1) ||
|
||||
(includesNoField
|
||||
? !validMarkerGroup
|
||||
@@ -4901,7 +4920,7 @@ export function GameTable({
|
||||
act={act}
|
||||
busy={busy}
|
||||
move={
|
||||
!source || !movementAvailable ||
|
||||
!source || !movementAvailable || advisorFlipRouteBlocked ||
|
||||
(includesNoField ? !validMarkerGroup : (me.forces[source] ?? 0) === 0)
|
||||
? null
|
||||
: {
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
planetologistLeader,
|
||||
planetologistMovementModeSupported,
|
||||
selectedOriginElites,
|
||||
planetologistGatherAdvisorEntry,
|
||||
type PlanetologistMoveMode,
|
||||
} from '@/game/planetologist-movement';
|
||||
import { botGroundMoveAllowed } from '@/game/bot-mobility';
|
||||
@@ -15,8 +16,6 @@ import {
|
||||
splitLocation,
|
||||
territory,
|
||||
} from '@/game/board';
|
||||
import { isAdvisor } from '@/game/advisors';
|
||||
import { presenceAt } from '@/game/force-presence';
|
||||
import { Button } from './ui/button';
|
||||
import { Input } from './ui/input';
|
||||
|
||||
@@ -76,20 +75,8 @@ export function planetologistMoveDraft(
|
||||
? 'Select forces from one territory.'
|
||||
: 'Select forces from exactly two different territories.',
|
||||
};
|
||||
if (
|
||||
game.advanced &&
|
||||
me.faction === 'beneGesserit' &&
|
||||
new Set([...origins].map((origin) => isAdvisor(me, origin))).size > 1 &&
|
||||
!presenceAt(me, destination) &&
|
||||
game.players.some(
|
||||
(player) => player.id !== me.id && presenceAt(player, destination),
|
||||
)
|
||||
)
|
||||
return {
|
||||
action: null,
|
||||
blocked:
|
||||
'Gathering advisors and fighters into an enemy-only territory is still being implemented.',
|
||||
};
|
||||
const entry = planetologistGatherAdvisorEntry(game, me, [...origins], destination);
|
||||
if (entry.blocked) return { action: null, blocked: entry.blocked };
|
||||
const target = location(destination, sector);
|
||||
if (
|
||||
selected.some(
|
||||
@@ -109,6 +96,7 @@ export function planetologistMoveDraft(
|
||||
action: {
|
||||
type: 'move',
|
||||
planetologist: mode,
|
||||
...(entry.requiresFlip ? { fighters: true } : {}),
|
||||
forces: Object.fromEntries(selected),
|
||||
...(me.elites
|
||||
? {
|
||||
@@ -196,6 +184,14 @@ export function PlanetologistMovement({
|
||||
Destination: {territory(destination).name}, sector {sector}. Select the
|
||||
physical forces to move below.
|
||||
</p>
|
||||
{draft.action?.fighters === true && (
|
||||
<p className="notice">
|
||||
Provisional mixed-gather policy: both groups arrive as fighters. The
|
||||
advisor flip is declared before either group moves. If canceled, both
|
||||
groups stay in place and no movement is spent; flipping remains blocked
|
||||
for that movement opportunity.
|
||||
</p>
|
||||
)}
|
||||
{me.faction === 'ixians' && (
|
||||
<p className="fine">
|
||||
Each origin uses its own selected cyborgs for movement range. Cyborgs
|
||||
|
||||
Reference in new issue
Block a user