Support cohort-eligible Ambassador leader and KH repeats

Replace lifetime first-death caps with the selected provisional composition: first returns remain immediate, while later native leaders and KH must satisfy their existing ordinary death/cohort conditions. Extract one phase/slot/price-independent cohort quote for ordinary Revival and the independent Ambassador. Preserve ordinary timing, payment, prevention, native early service and one-leader controls.

Snapshot an opened cohort before a free return makes a leader alive, preserving remaining ordinary returns. Keep Ecaz identity tracking and the shared Duke permission separate. KH retains activation/loss history and five native discs; update its marker above the actual opened owner cycle and old marker. Independent grants retain ordinary allowance and income policies. Explain eligibility in persistent controls and source-labelled reference.

Verify related rules/controls, types/lint/build, controlled native/copied free-return-to-next-ordinary-Revival programmes layered on original public Basic paid-entry sources, controlled Advanced KH actual entry/return, income allow/cancel and twelve minimal legal policy continuations. Assigned repeat/cohort facts are explicitly controlled, not claimed original battle histories. Full modes, wider custody/module combinations, comprehensive assurance and deployed acceptance remain unfinished. No strategic calibration, saved-room operation, reset, restart or deployment.
This commit is contained in:
Quintine committed 2026-10-24 13:43:11 +11:00
1 parent 16f654071a
commit 152039be5b
12 files changed
+719 -51

No files matched your search

+9 -2
View File
@@ -15,7 +15,7 @@ import {
} from './leader-skill-combat';
import { quoteSukPhysicalRescue, quoteSukRescue, SukPhysicalRescueError, sukReceiptSignature, sukRescueOptions, type SukForceGroup, type SukPhysicalRescueQuote, type SukPhysicalRescueReceipt, type SukReserveDestinations, type SukRescueOption, type SukRescueReceipt } from './suk-graduate';
import { quoteTleilaxuAmbassadorForces, TleilaxuAmbassadorForceError } from './tleilaxu-ambassador-forces';
import { tleilaxuAmbassadorLeaderChoices, tleilaxuAmbassadorLeaderSelection } from './tleilaxu-ambassador-leaders';
import { tleilaxuAmbassadorLeaderChoices, tleilaxuAmbassadorLeaderSelection, tleilaxuAmbassadorLeaderOpening } from './tleilaxu-ambassador-leaders';
import { createAmbassadorRevivalReceipt, validateAmbassadorRevivalReceipt, AmbassadorRevivalIncomeError,
type AmbassadorRevivalReceipt, type AmbassadorRevivalReturn } from './tleilaxu-ambassador-income';
import { leaderSkillStrongholdCount, sandmasterVictorySpice, sandmasterVictoryPiles, type SandmasterVictorySpiceOffer } from './leader-skill-battle-board';
@@ -18353,7 +18353,7 @@ function resolveAmbassadorEffect(g: Game) {
g.decision = { kind: 'ecazAmbassador', player: p.id };
log(
g,
`${p.name} may revive one first-death own leader or return up to four physical forces for free through the Tleilaxu Ambassador. Ordinary revival allowances and income are unchanged.`,
`${p.name} may revive one eligible own leader or return up to four physical forces for free through the Tleilaxu Ambassador. Repeated native leaders retain their ordinary death-cohort condition provisionally. Ordinary revival allowances remain independent; a positive return can earn the existing free-revival income.`,
{ faction: 'tleilaxu', name: 'Tleilaxu Ambassador' },
);
return;
@@ -18610,6 +18610,8 @@ function decideAmbassador(g: Game, p: Player, action: Action) {
let name: string, returned: AmbassadorRevivalReturn;
if (selected === 'kwisatz') {
const kwisatz = p.kwisatz!;
const opening = tleilaxuAmbassadorLeaderOpening(g, p);
if (opening !== null) p.revivalCycle = Math.max(p.revivalCycle, opening);
kwisatz.dead = false;
delete kwisatz.usedAt;
kwisatz.revivalCycle = Math.max(p.revivalCycle, kwisatz.revivalCycle ?? 1) + 1;
@@ -18625,7 +18627,12 @@ function decideAmbassador(g: Game, p: Player, action: Action) {
returned = { kind: 'leader', leader: duke.id, deaths: duke.deaths };
g.dukeVidal = consumeDuke(g.dukeVidal!);
} else {
// A living leader would hide a newly opened ordinary cohort: preserve
// its quote before resurrection. Ecaz records identity against that same
// original dead state before generic cycle persistence.
const opening = tleilaxuAmbassadorLeaderOpening(g, p);
recordEcazLeaderReturn(g, selected);
if (opening !== null) p.revivalCycle = Math.max(p.revivalCycle, opening);
selected.dead = false;
delete selected.usedAt;
name = selected.name;