Route classic Homeworld Harass returns through native custody

This commit is contained in:
Quintine committed 2026-10-16 11:07:14 +11:00
1 parent 5509abf1e5
commit 643add3f85
18 files changed
+1174 -83

No files matched your search

+19 -1
View File
@@ -5129,7 +5129,14 @@ export function GameTable({
{g.players.find(p => p.id === g.battle!.smugglerCollection!.player)?.name}’s Smuggler has {g.battle.smugglerCollection.amount} spice pending from the reveal-time piles.
If the leader survives, collection resolves before battle settlement, even after defeat. A partial collection across several piles requires its owner’s sector choice. That spice is not yet spendable.
</p>}
{!g.battle.traitorSubmitted.includes(me.id) && (
{!g.battle.traitorVoters.includes(me.id) && (
<p className="notice">
Only the native faction may declare Traitors here.
Wait for that decision; any legal invader late defense
follows through its own original control.
</p>
)}
{g.battle.traitorVoters.includes(me.id) && !g.battle.traitorSubmitted.includes(me.id) && (
<>
{actionButton(
'Reveal traitor',
@@ -5358,6 +5365,17 @@ export function GameTable({
</label>
))}
<HarassWithdrawGuide preview={g.battle.harassWithdraw} state={harassControl} />
{g.homeworlds && g.battle.harassWithdraw && (
<p className="notice">
Classic Homeworld timing: actual undialed counters
return to your native reserve Homeworlds, never to
the Tanks. In Advanced, Emperor normal forces return
to Kaitain and Sardaukar to Salusa; Basic retains
its original single primary World. Your original
dial/support stay committed across population
thresholds. Harass cannot be played on any own World.
</p>
)}
{g.battle.reinforcements && (
<p className="notice">
Reinforcements may occupy either card slot but is neither a weapon nor a defense.
+12 -2
View File
@@ -47,7 +47,9 @@ export function harassWithdrawChoiceState(
}
}
function locationLabel(key: string) {
function locationLabel(g: GameView, key: string) {
if (key.startsWith('homeworld:'))
return g.combatLocations?.find(place => place.id === key)?.name ?? key;
const location = splitLocation(key);
return `${territory(location.territory).name} · sector ${location.sector}`;
}
@@ -118,6 +120,14 @@ export function HarassWithdrawChoice({
Your Battle Plan is revealed. Choose the exact undialed counters that
return to reserves before the Traitor decision.
</p>
{g.homeworlds && (
<p className="fine">
These counters return to native Homeworld reserves. Advanced Emperor
ordinary counters go to Kaitain and Sardaukar to Salusa; Basic keeps
both types on its original primary World. Original commitment/support
does not change when that population rises.
</p>
)}
<label htmlFor={`${id}-commitment`}>Dialed physical commitment</label>
<select
id={`${id}-commitment`}
@@ -156,7 +166,7 @@ export function HarassWithdrawChoice({
.sort(([a], [b]) => a.localeCompare(b))
.map(([key, available]) => (
<fieldset key={key} className="grid gap-2 rounded-lg border p-3">
<legend>{locationLabel(key)}</legend>
<legend>{locationLabel(g, key)}</legend>
{(['normal', 'elite'] as const).map((kind) => (
<label key={kind}>
Return {kind === 'normal' ? 'ordinary' : 'elite'} (0–