Files

52 lines
3.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import type { Action, GameView } from '@/game/engine';
import { recruitsPlayAction } from '@/game/recruits';
import { faction } from '@/game/catalog';
import { Button } from '@/components/ui/button';
export function Recruits({ game, act, busy }: {
game: GameView;
act: (action: Action) => void;
busy: boolean;
}) {
const offer = game.recruitsPreview;
if (!offer || game.status !== 'playing' || game.phase !== 4 || (!offer.active && !offer.play))
return null;
const action = recruitsPlayAction(offer);
return (
<section className="m-4 space-y-3 rounded-xl border border-[#a88b60] p-4" aria-label="Recruits revival">
<h3 className="font-serif text-xl">Recruits{offer.active ? ' · Active this turn' : ''}</h3>
<p className="text-base leading-7">
{offer.active
? 'Free revival rates are doubled for this turn. The ordinary force limit is seven; factions with unlimited revival keep that advantage.'
: 'Play this card to double every faction’s free revival rate and raise the ordinary force limit to seven for this turn. Factions with unlimited revival keep that advantage.'}
</p>
<p className="fine">Already completed revivals still count. Paid forces retain their normal prices, and special-force revival limits still apply.</p>
<p className="notice">Provisional late-play accounting: prior paid revivals keep their payments and count toward the total force limit, but only recorded free returns consume the doubled free allowance. No refund or retroactive reclassification. This is a first-version policy, not a publisher clarification or numerical user ruling.</p>
{game.homeworlds && <p className="notice">Provisional current-rate composition: double the native free rate including its low-population bonus, capped by the seven-force total. Later separate requests recheck population and recorded free use; accepted returns keep their price. Normal and special counters retain native destinations and special-force limits.</p>}
<table className="w-full text-left text-sm">
<caption className="sr-only">Current revival rates</caption>
<thead><tr><th scope="col" className="pr-3">Faction</th><th scope="col" className="pr-3">Free rate</th><th scope="col">Force limit</th></tr></thead>
<tbody>{offer.rates.map((rate) => (
<tr key={rate.player}>
<th scope="row" className="py-1 pr-3 font-normal">{faction(game.players.find((p) => p.id === rate.player)!.faction).name}</th>
<td className="pr-3">{rate.freeRate}</td>
<td>{rate.limit === 20 ? 'Unlimited' : rate.limit}</td>
</tr>
))}</tbody>
</table>
{offer.play && (
<>
{offer.play.blocked && <p className="notice" id="recruits-unavailable">{offer.play.blocked}</p>}
<Button className="min-h-11 whitespace-normal" disabled={busy || !action}
aria-describedby={offer.play.blocked ? 'recruits-unavailable' : undefined}
onClick={() => { if (!busy && action) act(action); }}>
Play Recruits · Discard card
</Button>
</>
)}
</section>
);
}