Fix mixed-deck Nexus Betrayal continuations
Verify and publish checkpoint container / container (push) Canceled after 0s

This commit is contained in:
Quintine committed 2026-10-30 18:12:45 +11:00
1 parent 6204efb7e4
commit 7680e1ee69
15 files changed
+487 -46

No files matched your search

+12 -4
View File
@@ -12535,8 +12535,10 @@ function harkonnenNexusBetrayalContext(g: Game) {
const plans = Object.fromEntries([b.attacker,b.defender].map(id => [id,{
leader:b.plans[id].leader,...(b.plans[id].kwisatz === undefined ? {} : {kwisatz:b.plans[id].kwisatz}),
}]));
const battle = {event:b.event!,attacker:b.attacker,defender:b.defender,plans,heroLeaderIds:[]};
const battle = {event:b.event!,attacker:b.attacker,defender:b.defender,plans,
heroLeaderIds:g.expansions.includes('ix') ? physicalTreacheryCards(g).filter(card => card.kind === 'hero').map(card => card.id) : []};
return {status:g.status,phase:g.phase,turn:g.turn,advanced:g.advanced,ecazTreachery:g.ecazTreachery === true,
...(g.expansions.length ? {expansions:g.expansions} : {}),
sequence:g.nexusHarkonnenBetrayalCursor!.sequence,players:g.players,
cards:g.nexusCards!.cards!,physicalCards:physicalTreacheryCards(g),
traitors:nexusTraitorSnapshot(g),universe:nexusTraitorUniverse(g),battle};
@@ -12601,7 +12603,9 @@ function harkonnenNexusBetrayalIntegrity(g: Game, mentatOpening = false): void {
(!g.pendingNexusHarkonnenReplacement || (g.status === 'playing' &&
g.pendingNexusHarkonnenReplacement.status === 'due' &&
g.pendingNexusHarkonnenReplacement.turn === g.turn &&
(g.phase === 6 || g.phase === 7 || (mentatOpening && g.phase === 8)))),
(g.phase === 6 || g.phase === 7 || (g.phase === 8 &&
(mentatOpening || g.phaseOpening?.initialize === true ||
g.response?.kind === 'emperorGift' && g.response.emperorPhaseOpeningGift?.opening.initialize === true))))),
'The private replacement lost its current native Mentat obligation.');
if (g.status !== 'setup' && g.status !== 'lobby')
nexusRule(() => validateNexusTraitorSnapshot(nexusTraitorSnapshot(g),universe));
@@ -12630,6 +12634,10 @@ function harkonnenNexusBetrayalIntegrity(g: Game, mentatOpening = false): void {
}
function offerHarkonnenNexusBetrayal(g: Game, provider: string, response?: ResponseWindow): boolean {
if (!g.nexusHarkonnenBetrayalPreview || getPlayer(g,provider).faction !== 'harkonnen') return false;
// The expanded physical census below currently covers Basic. Avoid blocking
// the original call in Advanced selected-deck games until their distinct
// Auditor and Loyalty inventories are supported.
if (g.advanced && g.expansions.length) return false;
const b = g.battle!;
const required = nexusRule(() => harkonnenBetrayalResponders(g.nexusCards!.cards!,g.players));
if (!required.length) return false;
@@ -12744,11 +12752,11 @@ function ixianNexusBetrayalModeSupported(g: Game): boolean {
function ixianNexusBetrayalContext(g: Game) {
return {status:g.status,phase:g.phase,turn:g.turn,advanced:g.advanced,
sequence:g.nexusIxianBetrayalCursor!.sequence,players:g.players,
...(g.ecazTreachery ? {expansions:g.expansions,ecazTreachery:true} : {}),
expansions:g.expansions,ecazTreachery:g.ecazTreachery === true,
cards:g.nexusCards!.cards!,physicalCards:physicalTreacheryCards(g)};
}
function ixianNexusCardConfiguration(g: Game) {
return g.ecazTreachery ? {expansions:g.expansions,ecazTreachery:true,richese:!!byFaction(g,'richese')} : undefined;
return {expansions:g.expansions,ecazTreachery:g.ecazTreachery === true,richese:!!byFaction(g,'richese')};
}
function ixianNexusBetrayalAuthority(g: Game, response: ResponseWindow) {
requireRule(response.kind === 'ixAuction' || response.kind === 'ixTechnology',