'use client'; import { useState } from 'react'; import type { Action, GameView } from '@/game/engine'; import { specialForceName } from '@/game/combat'; import { homeworldName, homeworldShipmentChoice, richeseHomeworldMarkerChoice, type HomeworldShipmentSources, } from '@/game/homeworld-shipment-options'; import { Button } from './ui/button'; import { Input } from './ui/input'; /** The concealed marker does not withdraw a reserve counter until revealed. */ export function HomeworldNoFieldShipment({ game, act, busy }: { game: GameView; act: (action: Action) => void; busy: boolean; }) { const me = game.players.find(player => player.id === game.me); const info = game.richeseNoField; const [selectedDestination, setSelectedDestination] = useState(''); const [selectedToken, setSelectedToken] = useState(''); const [allyPayment, setAllyPayment] = useState(0); const [forces, setForces] = useState({ normal: 0, elite: 0 }); if (!me || me.faction !== 'richese' || info?.owner !== me.id || !info.private) return null; const deployed = info.private.deployed; const source = deployed && 'homeworld' in deployed.location ? deployed.location.homeworld : undefined; const targets = (game.homeworlds?.worlds ?? []).filter(world => (world.native !== me.id || !!source && game.advanced) && world.native !== me.ally && world.id !== source); const destination = targets.find(world => world.id === selectedDestination) ?? targets.find(world => world.native !== me.id) ?? targets[0]; const tokens = info.private.tokens.filter(token => source ? token.id === deployed?.tokenId : token.id !== info.private!.lastShipped); const token = tokens.find(candidate => candidate.id === selectedToken) ?? tokens[0]; const pool = source ? game.homeworlds?.worlds?.find(world => world.id === source)?.forces[me.id] : { normal: me.reserves - (me.elites?.reserves ?? 0), elite: me.elites?.reserves ?? 0 }; const quote = richeseHomeworldMarkerChoice(game, destination?.id ?? '', token?.id ?? '', allyPayment, source, forces); return
; } export function HomeworldShipment({ game: g, act, busy, }: { game: GameView; act: (action: Action) => void; busy: boolean; }) { const worlds = g.homeworlds?.worlds ?? []; const me = g.players.find((player) => player.id === g.me)!; const available = worlds.filter((world) => { const force = world.forces[g.me]; return force && force.normal + force.elite > 0; }); const targets = worlds.filter( (world) => (g.advanced || world.native !== g.me || me.faction === 'guild') && !(!g.advanced && g.guildTransportCanceled && me.faction === 'guild' && world.native === me.id) && world.native !== me.ally, ); const [origin, setOrigin] = useState(available[0]?.id ?? ''); const [destination, setDestination] = useState( (targets.find((world) => world.id !== available[0]?.id && world.native !== g.me) ?? targets.find((world) => world.id !== available[0]?.id))?.id ?? '', ); const [sources, setSources] = useStateUse your shipment to send forces from one Homeworld to another. Native reserves and foreign garrisons have separate source pools.{' '} {g.advanced ? 'You may return a foreign garrison to your own Homeworld.' : me.faction === 'guild' ? g.guildTransportCanceled ? 'The native Guild return permission is canceled: Junction cannot be a destination, even with a purchased price.' : 'Guild may also return a foreign garrison to Junction.' : 'Your own Homeworld cannot be a destination.'}{' '} Allied Homeworlds cannot be destinations.
{useNexus ? 'Selected Guild Nexus price: one spice per two forces, rounded up.' : g.karamaShipping?.player === g.me ? 'Purchased Karama price: one spice per two forces, rounded up, paid entirely to the bank even if the native Guild rate is canceled.' : me.faction === 'guild' ? g.guildRateCanceled ? 'The native Guild rate is canceled: pay one spice per force.' : 'Guild pays one spice per two forces, rounded up.' : 'Pay one spice per force.'}{' '} This uses your shipment; your normal movement remains available.
{g.nexusGuildSecretAlly && (Spend the Nexus for its independent price of one spice per two forces, rounded up; it does not stack with a purchased Karama price. Existing source and destination restrictions still apply.
{g.nexusGuildSecretAlly.blocked && ({g.nexusGuildSecretAlly.blocked}
)}Available: {pool.normal} normal {pool.elite > 0 ? ` + ${pool.elite} ${special}` : ''}.
{(['normal', 'elite'] as const) .filter((kind) => kind === 'normal' || pool.elite > 0) .map((kind) => ( ))}Your available spice: {me.spice ?? 0}. Allied pledge:{' '} {g.aid.available}.