Connect Kull and Semuta with independent cards
Verify and publish checkpoint container / container (push) Canceled after 0s
Verify and publish checkpoint container / container (push) Canceled after 0s
This commit is contained in:
1 parent
87d1887139
commit
bc0db31134
11 files changed
+412
-23
No files matched your search
+24
-12
@@ -6941,7 +6941,8 @@ type KullSemutaDiscardContinuation = Extract<
|
||||
function kullSemutaParentSupported(g: Game, frame?: NonNullable<Game['pendingKull']>): boolean {
|
||||
const battle = g.battle;
|
||||
const use = frame?.intent.kind === 'ordinary' ? frame.intent.use : undefined;
|
||||
const nativeResponse = !!frame && !g.advanced && bareBasicSemutaProfile(g) &&
|
||||
const nativeResponse = !!frame && !g.advanced &&
|
||||
(bareBasicSemutaProfile(g) || g.semutaRecruitsPreview === true && basicIndependentRecruitsSemutaProfile(g)) &&
|
||||
use?.kind === 'cancel' && JSON.stringify(use.response) === JSON.stringify(frame.resume.response) &&
|
||||
!frame.resume.decision && !frame.resume.pendingKarama && !frame.resume.phaseOpening;
|
||||
let revivalSupported = false;
|
||||
@@ -9477,7 +9478,9 @@ function semutaOfferSupported(
|
||||
!continuation.resume.response && !continuation.resume.decision &&
|
||||
!continuation.resume.pendingKarama && !continuation.resume.phaseOpening;
|
||||
if (continuation.kind === 'kullSuccessDiscard' || continuation.kind === 'kullCounterDiscard')
|
||||
return g.semutaPreview === true && g.advanced === false && bareBasicSemutaProfile(g) &&
|
||||
return (g.semutaPreview === true && bareBasicSemutaProfile(g) ||
|
||||
g.semutaRecruitsPreview === true && basicIndependentRecruitsSemutaProfile(g) &&
|
||||
(!g.pendingTreacheryDiscard || !!g.pendingTreacheryDiscard.reaction)) && g.advanced === false &&
|
||||
!!byFaction(g, 'richese') && kullSemutaParentSupported(kullSource(g, continuation.frame), continuation.frame) &&
|
||||
(!!g.battle === !!continuation.battleBinding) && entries.length === 1 &&
|
||||
entries[0].publicFace && entries[0].discardedBy === continuation.player &&
|
||||
@@ -9709,7 +9712,8 @@ function semutaOfferSupported(
|
||||
const independentNativeDiscard = ambassadorDiscard || continuation.kind === 'terrorDiscard' ||
|
||||
continuation.kind === 'choamSaleDiscard' || continuation.kind === 'choamKulonDiscard' ||
|
||||
continuation.kind === 'choamLaLaLaDiscard' || continuation.kind === 'choamBalisetDiscard' ||
|
||||
continuation.kind === 'choamGamontDiscard' || continuation.kind === 'choamJubbaDiscard';
|
||||
continuation.kind === 'choamGamontDiscard' || continuation.kind === 'choamJubbaDiscard' ||
|
||||
continuation.kind === 'karamaShipmentPriceDiscard';
|
||||
return (g.semutaPreview === true || g.semutaRecruitsPreview === true &&
|
||||
(!g.pendingTreacheryDiscard || !!g.pendingTreacheryDiscard.reaction) &&
|
||||
(independentNativeDiscard || continuation.kind === 'ordinaryCardDiscard' &&
|
||||
@@ -9717,6 +9721,7 @@ function semutaOfferSupported(
|
||||
continuation.kind === 'battleResolved' || continuation.kind === 'winnerMandatoryDiscard' ||
|
||||
continuation.kind === 'battleCleanup' && (continuation.source === 'winner' ||
|
||||
continuation.source === 'moritani' && !g.advanced && continuation.retention?.source === undefined) ||
|
||||
continuation.kind === 'residualPoisonDiscard' ||
|
||||
continuation.kind === 'nullentropyDiscard' || continuation.kind === 'distransDiscard' ||
|
||||
continuation.kind === 'truthtranceDiscard' && continuation.promise === null &&
|
||||
(continuation.record.question.kind === 'fact' || continuation.record.question.kind === 'freeform') ||
|
||||
@@ -10845,10 +10850,16 @@ function startModules(state: Game): Game {
|
||||
g.players.every(player => player.faction === 'choam' || player.faction === 'richese' || player.faction === 'ixians' ||
|
||||
player.faction === 'tleilaxu' || g.expansions.includes('ecaz') &&
|
||||
(player.faction === 'ecaz' || player.faction === 'moritani') || CLASSIC_FACTIONS[player.faction] === true) &&
|
||||
!options.leaderSkills && !options.ecazTreachery && !g.nexusCards && !g.discoveryEnabled &&
|
||||
!options.leaderSkills && !g.nexusCards && !g.discoveryEnabled &&
|
||||
!g.homeworlds && !g.techTokens && !g.strongholdCards;
|
||||
requireRule(supportedBasic || advancedKullLobbyEligible(state),
|
||||
'Kull preview needs CHOAM and Ix decks with no optional modules. Advanced currently supports CHOAM and classic factions only; Basic also supports the selected native expansion factions.');
|
||||
'Kull preview needs CHOAM and Ix decks. Advanced supports CHOAM and classic factions without optional modules; Basic also supports selected native expansion factions and independent Ecaz Treachery Cards.');
|
||||
if (options.ecazTreachery) {
|
||||
requireRule(supportedBasic, 'Kull with independent Ecaz cards currently needs the supported Basic native roster.');
|
||||
const initialized = initializeEcazTreacheryGameForAudit(g);
|
||||
initialized.kullPreview = true;
|
||||
return initialized;
|
||||
}
|
||||
return initializeKullGameForAudit(g);
|
||||
}
|
||||
if (options.ecazTreachery && options.leaderSkills) g.ecazTreachery = true;
|
||||
@@ -13081,7 +13092,8 @@ function ecazOccupyCompositionSupported(g: Game): boolean {
|
||||
// Family/roster checks below remain authoritative; optional configurations
|
||||
// retain their separate registered profiles rather than inheriting admission.
|
||||
const basicNatives = g.advanced === false && !g.strongholdCards &&
|
||||
((!g.ecazTreachery && (!g.techTokens || nativeFactionTechProfile(g))) || selectedIndependentCardsProfile(g));
|
||||
((!g.ecazTreachery && (!g.techTokens || nativeFactionTechProfile(g))) || selectedIndependentCardsProfile(g) ||
|
||||
g.kullPreview === true && selectedIndependentCardsProfile({...g,kullPreview:undefined}));
|
||||
if ((independentNexusProfile(g) || independentDiscoveryProfile(g)) && byFaction(g, 'ecaz')) return true;
|
||||
if (g.leaderSkills && nativeEcazLeaderSkillsProfile(g)) return true;
|
||||
if (g.ecazOccupyPreview === true && (mixedE3NexusProfile(g) || standaloneE3NexusProfile(g) || pairedE3NexusProfile(g)) &&
|
||||
@@ -13211,7 +13223,7 @@ function basicIndependentRecruitsSemutaProfile(g: Game): boolean {
|
||||
g.expansions.includes(faction(p.faction).expansion)) &&
|
||||
!g.homeworlds && !g.nexusCards && !g.leaderSkills && !g.techTokens && !g.strongholdCards &&
|
||||
!g.discoveryEnabled && !g.discoveries && !g.discoveryStash && !g.greatMaker &&
|
||||
!g.kullPreview && !g.nexusKullPreview && !g.moritaniAssassinatePreview;
|
||||
!g.nexusKullPreview && !g.moritaniAssassinatePreview;
|
||||
}
|
||||
function semutaCardProducerEnabled(g: Game): boolean {
|
||||
return g.semutaPreview === true || g.semutaRecruitsPreview === true && basicIndependentRecruitsSemutaProfile(g);
|
||||
@@ -19469,7 +19481,7 @@ function kullCostPromisesAllow(g: Game, p: Player, card: Card, fuelSource: 'prin
|
||||
}
|
||||
function kullCostCards(g: Game, p: Player, source: 'printed' | 'nexus' = 'printed'): Card[] {
|
||||
const original = g.pendingKull ? kullSource(g, g.pendingKull) : g;
|
||||
if (g.semutaPreview && (!kullSemutaParentSupported(original, g.pendingKull ?? undefined) || source !== 'printed')) return [];
|
||||
if (semutaCardProducerEnabled(g) && (!kullSemutaParentSupported(original, g.pendingKull ?? undefined) || source !== 'printed')) return [];
|
||||
if (source === 'nexus' && (!g.nexusKullPreview || p.faction !== 'choam' || p.ally ||
|
||||
(g.pendingKull?.selection?.source !== 'nexus' && g.nexusCards?.cards?.hands[p.id] !== 'choam')))
|
||||
return [];
|
||||
@@ -19884,7 +19896,7 @@ function spendKarama(g: Game, p: Player, card: Card, use: KaramaUse, kullOffered
|
||||
return stage && !stage.closed && windowCardOpportunity(g, effect, stage.source)?.source === stage.source;
|
||||
});
|
||||
})) guardTurnActionPrintedCardCost(g, p, used);
|
||||
if (g.semutaPreview && !g.advanced && g.pendingKull?.stage === 'counter' &&
|
||||
if (semutaCardProducerEnabled(g) && !g.advanced && g.pendingKull?.stage === 'counter' &&
|
||||
use.kind === 'cancel' && use.response.kind === 'choamWorthless' && use.response.intent === 'Kull Wahad') {
|
||||
const declaration = g.pendingChoamWorthless;
|
||||
requireRule(declaration && kullSemutaParentSupported(kullSource(g, g.pendingKull), g.pendingKull),
|
||||
@@ -19903,7 +19915,7 @@ function spendKarama(g: Game, p: Player, card: Card, use: KaramaUse, kullOffered
|
||||
stageTreacheryDiscard(g, 'karama:kullCounter', [{card:used, discardedBy:p.id, publicFace:true}], continuation);
|
||||
return;
|
||||
}
|
||||
const semutaRoleCost = g.semutaPreview && semutaKaramaRoleCost(g, p.id, card);
|
||||
const semutaRoleCost = semutaCardProducerEnabled(g) && semutaKaramaRoleCost(g, p.id, card);
|
||||
const guildShipmentDiscard = semutaRoleCost &&
|
||||
use.kind === 'cancel' && semutaGuildShipmentKaramaResponse(g, use.response);
|
||||
const bgConversionCancelDiscard = semutaRoleCost &&
|
||||
@@ -30821,7 +30833,7 @@ function playResidualPoison(
|
||||
`${p.name} played Residual Poison against ${target.name}. ${victim.name} was randomly selected from the available leaders and sent to the Tanks. No spice is awarded, no forces are lost, and battle preparation continues.`,
|
||||
{ faction: p.faction, name: 'Residual Poison' },
|
||||
);
|
||||
if (g.semutaPreview || g.semutaRecruitsPreview && basicIndependentSemutaProfile(g)) {
|
||||
if (g.semutaPreview || g.semutaRecruitsPreview && basicIndependentRecruitsSemutaProfile(g)) {
|
||||
const continuation: ResidualPoisonDiscardContinuation = {
|
||||
kind: 'residualPoisonDiscard', player: p.id, target: target.id,
|
||||
victim: victim.id, battleEvent: b.event!, card: used.id,
|
||||
@@ -37121,7 +37133,7 @@ function finishResponse(g: Game, canceled: boolean, settlement?: BureaucratSettl
|
||||
log(g, `${getPlayer(g, g.pendingKull!.owner).name} cannot activate ${restriction.purpose
|
||||
? kullPurposeLabel(restriction.purpose) : 'Karama'} for this phase. The attempted card stays held.`);
|
||||
resumeKullAttempt(g, true);
|
||||
if (g.semutaPreview && !g.advanced) {
|
||||
if (semutaCardProducerEnabled(g) && !g.advanced) {
|
||||
const continuation: KullSemutaDiscardContinuation = {
|
||||
kind: 'kullSuccessDiscard', player: choam.id, card: used.id, frame,
|
||||
resume: { response: g.response, decision: g.decision,
|
||||
|
||||
Reference in new issue
Block a user