Support staged group Guild transport
Verify and publish checkpoint container / container (push) Successful in 12m5s
Verify and publish checkpoint container / container (push) Successful in 12m5s
This commit is contained in:
1 parent
478b38f5de
commit
2fe97ddd1f
10 files changed
+424
-23
No files matched your search
+47
-15
@@ -1407,6 +1407,7 @@ type PendingGuildTransport = {
|
||||
elite: number;
|
||||
cost: number;
|
||||
allyPayment: number;
|
||||
coalitionContributions?: CoalitionContribution[];
|
||||
advisors: boolean;
|
||||
/** Fresh board transports retain their actual source stance at foreign arrivals.
|
||||
* Absent on declarations recorded before this source cutover. */
|
||||
@@ -38198,12 +38199,14 @@ function guildTransportSignature(intent: PendingGuildTransport): string {
|
||||
if (intent.permission !== undefined) fields.push(intent.permission);
|
||||
if (intent.advisorArrivalSource !== undefined) fields.push(intent.advisorArrivalSource);
|
||||
if (intent.noField !== undefined) fields.push(intent.noField);
|
||||
if (intent.coalitionContributions !== undefined) fields.push(intent.coalitionContributions);
|
||||
return JSON.stringify(fields);
|
||||
}
|
||||
function ordinaryGuildTransportFullCost(g: Game, p: Player, frame: GuildTransportOrder): number | null {
|
||||
const guild = byFaction(g, 'guild');
|
||||
if (!guild ||
|
||||
(p.id !== guild.id && !(p.ally === guild.id && guild.ally === p.id)) ||
|
||||
(p.id !== guild.id && !(p.ally === guild.id && guild.ally === p.id) &&
|
||||
!(coalitionFundingAvailable(g, p) && guildGroupAlly(g, p))) ||
|
||||
g.karamaShipping?.player === p.id ||
|
||||
(g.guildRateBlocked?.turn === g.turn && g.guildRateBlocked.player === p.id))
|
||||
return null;
|
||||
@@ -38256,6 +38259,8 @@ function validateGuildTransportWindow(g: Game, response: ResponseWindow) {
|
||||
Number.isSafeInteger(intent.elite) && intent.elite >= 0 && intent.elite <= intent.amount - Number(!!marker) &&
|
||||
Number.isSafeInteger(intent.allyPayment) && intent.allyPayment >= 0 &&
|
||||
intent.allyPayment <= intent.cost && typeof intent.advisors === 'boolean' &&
|
||||
(intent.coalitionContributions === undefined || Array.isArray(intent.coalitionContributions) &&
|
||||
intent.allyPayment === 0 && !marker) &&
|
||||
(intent.advisorArrivalSource === undefined || g.advanced && shipper.faction === 'beneGesserit' &&
|
||||
!intent.fromReserves && intent.to !== 'reserves' && intent.advisorArrivalSource === intent.origin) &&
|
||||
(marker === undefined || typeof marker === 'object' && marker !== null &&
|
||||
@@ -38299,6 +38304,7 @@ function guildTransportOrder(intent: PendingGuildTransport, cost = intent.cost):
|
||||
group: intent.group, eliteGroup: intent.eliteGroup, to: intent.to,
|
||||
sector: intent.sector, amount: intent.amount, elite: intent.elite,
|
||||
cost, allyPayment: intent.allyPayment, advisors: intent.advisors,
|
||||
...(intent.coalitionContributions !== undefined ? {coalitionContributions:intent.coalitionContributions.map(share => ({...share}))} : {}),
|
||||
...(intent.noField ? {noField:{...intent.noField}} : {}),
|
||||
...(intent.advisorArrivalSource !== undefined ? {advisorArrivalSource:intent.advisorArrivalSource} : {}),
|
||||
};
|
||||
@@ -38361,7 +38367,8 @@ function nativeGuildTransportPermission(g: Game, p: Player): boolean {
|
||||
if (guildTransportCanceled(g, p.id)) return false;
|
||||
if (p.faction === 'guild') return true;
|
||||
const guild = byFaction(g, 'guild');
|
||||
return !!guild && p.ally === guild.id && guild.ally === p.id;
|
||||
return !!guild && (p.ally === guild.id && guild.ally === p.id ||
|
||||
coalitionFundingAvailable(g, p) && guildGroupAlly(g, p));
|
||||
}
|
||||
function validateGuildTransportForCommit(
|
||||
g: Game, p: Player, frame: GuildTransportOrder, fromReserves: boolean, guildSecretEvent?:string,
|
||||
@@ -38410,8 +38417,14 @@ function validateGuildTransportForCommit(
|
||||
requireRule(cost === guildShipmentCost(
|
||||
to === 'reserves' ? 'reserves' : territory(to).type, amount, halfRate),
|
||||
'The declared Guild transport price no longer matches its rate.');
|
||||
contribution(g, p, cost, allyPayment);
|
||||
checkShipmentIncomeFunding(g, p, cost, allyPayment);
|
||||
if (frame.coalitionContributions !== undefined) {
|
||||
requireRule(allyPayment === 0 && !frame.noField && !guildSecretEvent &&
|
||||
Array.isArray(frame.coalitionContributions), 'Group funding requires a physical native Guild transport.');
|
||||
coalitionShipmentQuote(g, p, cost, frame.coalitionContributions);
|
||||
} else {
|
||||
contribution(g, p, cost, allyPayment);
|
||||
checkShipmentIncomeFunding(g, p, cost, allyPayment);
|
||||
}
|
||||
checkShipmentPromises(g, p, fromReserves ? { territory: to, amount, sector } : null);
|
||||
}
|
||||
function commitGuildTransport(
|
||||
@@ -38433,18 +38446,32 @@ function commitGuildTransport(
|
||||
if (guildSecretEvent) recordGuildSecretShipment(g, p.id, guildSecretEvent, 'cross',
|
||||
{ ...frame, guildSecretEvent });
|
||||
bindGuildCunningShipment(g, p, 'guild', frame);
|
||||
payWithAlly(g, p, cost, allyPayment);
|
||||
if (frame.coalitionContributions !== undefined) {
|
||||
const result = coalitionRule(() => settleCoalitionFunding({seats:g.players, coalitionState:g.coalitionState,
|
||||
authorizations:g.coalitionEscrow!.authorizations, pledges:g.coalitionEscrow!.pledges,
|
||||
purpose:'shipment', payer:p.id, cost, ownAvailable:uncommittedSpice(g, p),
|
||||
contributions:frame.coalitionContributions!}));
|
||||
p.spice -= result.quote.own;
|
||||
g.coalitionEscrow = {...g.coalitionEscrow!, pledges:result.pledges};
|
||||
} else payWithAlly(g, p, cost, allyPayment);
|
||||
if (settlement?.recipient) getPlayer(g, settlement.recipient).spice += cost;
|
||||
if (!movementPreparation) {
|
||||
const guild = byFaction(g, 'guild');
|
||||
const guildPayment = guildShipmentIncome({
|
||||
const groupShares = frame.coalitionContributions;
|
||||
const groupTotal = groupShares?.reduce((sum, share) => sum + share.amount, 0) ?? 0;
|
||||
const groupContributors = groupShares ? [{payer:p.id, amount:cost-groupTotal},
|
||||
...groupShares.map(share => ({payer:share.donor, amount:share.amount}))]
|
||||
.filter(share => share.payer !== guild?.id && share.amount > 0) : null;
|
||||
const guildPayment = groupContributors ? groupContributors.reduce((sum, share) => sum + share.amount, 0) : guildShipmentIncome({
|
||||
guild: guild?.id, shipper: p.id, ally: p.ally, cost, allyPayment,
|
||||
bankOnly: g.karamaShipping?.player === p.id,
|
||||
});
|
||||
if (!settlement?.recipient && guild && guildPayment > 0)
|
||||
g.response = guildPaymentResponse(g, guild.id, shipmentIncomeContributions(g, p, cost, allyPayment),
|
||||
allyPayment ? undefined : p.id, [{ payer: p.id, amount: p.id === guild.id ? 0 : cost - allyPayment },
|
||||
...(allyPayment && p.ally !== guild.id ? [{ payer: p.ally!, amount: allyPayment }] : [])]);
|
||||
g.response = guildPaymentResponse(g, guild.id,
|
||||
groupContributors ? groupContributors.map(share => share.amount) : shipmentIncomeContributions(g, p, cost, allyPayment),
|
||||
groupShares || allyPayment ? undefined : p.id, groupContributors ??
|
||||
[{ payer: p.id, amount: p.id === guild.id ? 0 : cost - allyPayment },
|
||||
...(allyPayment && p.ally !== guild.id ? [{ payer: p.ally!, amount: allyPayment }] : [])]);
|
||||
settleBankerShipmentIncome(g, p, cost, allyPayment);
|
||||
}
|
||||
if (fromReserves) {
|
||||
@@ -45278,15 +45305,20 @@ function applyActionInner(
|
||||
!(g.guildRateBlocked?.turn === g.turn && g.guildRateBlocked.player === id);
|
||||
const cost = guildShipmentCost(
|
||||
to === 'reserves' ? 'reserves' : territory(to).type, n, halfRate);
|
||||
requireRule(
|
||||
p.spice + (aidFor(g, p)?.amount ?? 0) >= cost,
|
||||
'Not enough spice.',
|
||||
);
|
||||
const allyPayment = contribution(g, p, cost, action.allyPayment);
|
||||
checkShipmentIncomeFunding(g, p, cost, allyPayment);
|
||||
let coalitionContributions: CoalitionContribution[] | undefined;
|
||||
if (action.coalitionContributions !== undefined) {
|
||||
requireRule(execution === 'live' && Array.isArray(action.coalitionContributions) &&
|
||||
!noField && !guildSecretEvent && (action.allyPayment === undefined || action.allyPayment === 0),
|
||||
'Group funding requires a physical native Guild transport.');
|
||||
coalitionContributions = action.coalitionContributions as CoalitionContribution[];
|
||||
coalitionShipmentQuote(g, p, cost, coalitionContributions);
|
||||
} else requireRule(p.spice + (aidFor(g, p)?.amount ?? 0) >= cost, 'Not enough spice.');
|
||||
const allyPayment = coalitionContributions === undefined ? contribution(g, p, cost, action.allyPayment) : 0;
|
||||
if (coalitionContributions === undefined) checkShipmentIncomeFunding(g, p, cost, allyPayment);
|
||||
const frame: GuildTransportOrder = {
|
||||
turn: g.turn, player: id, origin, group, eliteGroup, to, sector,
|
||||
amount: n, elite, cost, allyPayment, advisors,
|
||||
...(coalitionContributions !== undefined ? {coalitionContributions:coalitionContributions.map(share => ({...share}))} : {}),
|
||||
...(noField ? {noField:{...noField}} : {}),
|
||||
...(advisorArrivalSource !== undefined ? {advisorArrivalSource} : {}),
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user