Separate Guild transport permission, purchase price and loan approval

This commit is contained in:
Quintine committed 2026-10-15 22:52:37 +11:00
1 parent a12250320c
commit 11adb7dbf3
39 files changed
+1576 -121

No files matched your search

+1
View File
@@ -2319,6 +2319,7 @@ export function GameTable({
harkonnenTraitor: 'Harkonnen ally traitor',
guildIncome: 'Guild shipment income',
guildRate: 'Guild half-price shipment rate',
guildTransportPermission: 'Guild cross/return transport permission',
richeseNoField: 'Richese No-Field shipment',
advisor: 'Spiritual advisor',
emperorGift: 'Emperor spice gift',
+6 -3
View File
@@ -61,11 +61,14 @@ export function GuildHomeworldShipment({
Ship forces from one Arrakis territory to Junction or another faction’s
Homeworld. You may combine forces in different sectors of that
territory. Allied Homeworlds cannot be destinations.
{' '}A purchased price does not restore canceled native transport permission.
</p>
<p className="fine">
{g.guildRateCanceled
? 'The native Guild rate is canceled: pay one spice per force.'
: 'Pay 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.'
: g.guildRateCanceled
? 'The native Guild rate is canceled: pay one spice per force.'
: 'Pay one spice per two forces, rounded up.'}{' '}
This uses your shipment; your normal movement remains available.
</p>
{option.blocked && (
+21 -9
View File
@@ -29,6 +29,7 @@ export function HomeworldShipment({
const targets = worlds.filter(
(world) =>
(world.native !== g.me || me.faction === 'guild') &&
!(g.guildTransportCanceled && me.faction === 'guild' && world.native === me.id) &&
world.native !== me.ally,
);
const [origin, setOrigin] = useState(available[0]?.id ?? '');
@@ -39,7 +40,9 @@ export function HomeworldShipment({
const [allyPayment, setAllyPayment] = useState(0);
const [nexusEvent, setNexusEvent] = useState('');
const useNexus =
!!g.nexusGuildSecretAlly && nexusEvent === g.nexusGuildSecretAlly.event;
g.karamaShipping?.player !== g.me &&
!!g.nexusGuildSecretAlly &&
nexusEvent === g.nexusGuildSecretAlly.event;
const option = g.homeworldShipment;
if (!option) return null;
const imperial = g.advanced && me.faction === 'emperor';
@@ -71,18 +74,22 @@ export function HomeworldShipment({
Use your shipment to send forces from one Homeworld to another. Native
reserves and foreign garrisons have separate source pools.{' '}
{me.faction === 'guild'
? 'Guild may also return a foreign garrison to Junction.'
? 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.
</p>
<p className="fine">
{useNexus
? 'Selected Guild Nexus price: one spice per two forces, rounded up.'
: 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.'}{' '}
: 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.
</p>
{g.nexusGuildSecretAlly && (
@@ -91,7 +98,11 @@ export function HomeworldShipment({
<input
type="checkbox"
checked={useNexus}
disabled={busy || !!g.nexusGuildSecretAlly.blocked}
disabled={
busy ||
!!g.nexusGuildSecretAlly.blocked ||
g.karamaShipping?.player === g.me
}
onChange={(event) =>
setNexusEvent(
event.target.checked ? g.nexusGuildSecretAlly!.event : '',
@@ -101,7 +112,8 @@ export function HomeworldShipment({
Use Guild Nexus Secret Ally for Homeworld shipment
</label>
<p>
Spend the Nexus to pay one spice per two forces, rounded up.
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.
</p>
{g.nexusGuildSecretAlly.blocked && (
+2 -3
View File
@@ -3,7 +3,6 @@
import { useId, useState } from 'react';
import type { Action, GameView } from '@/game/engine';
import { territory, MOBILE_STRONGHOLD } from '@/game/board';
import { alliedNoFieldShipmentPricing } from '@/game/shipment-price';
import { Button } from './ui/button';
import { Input } from './ui/input';
@@ -28,7 +27,7 @@ export function RicheseAlliedNoFieldControls({
const info = game.richeseNoField;
const me = game.players.find((player) => player.id === game.me);
const ally = game.players.find((player) => player.id === me?.ally);
if (!info || info.owner !== game.me || !info.private || !me || !ally)
if (!info || info.owner !== game.me || !info.private || !info.allyPricing || !me || !ally)
return null;
const offer = info.allyOffer;
if (offer?.blocked)
@@ -57,7 +56,7 @@ export function RicheseAlliedNoFieldControls({
const selected =
available.find((candidate) => candidate.id === token) ?? available[0];
const target = territory(destination);
const pricing = alliedNoFieldShipmentPricing(game, ally);
const pricing = info.allyPricing;
const cost = target.type === 'stronghold' ? pricing.stronghold : pricing.other;
const selectedPayer =
payer === 'both' && cost === 2