feat: add playable inter-battle city stays
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { equipmentExpToNext, equipmentSlots, itemCatalog, type EquipmentSlot } from '../data/battleItems';
|
||||
import { unitClasses } from '../data/battleRules';
|
||||
import { battleScenarios, type BattleScenarioId } from '../data/battles';
|
||||
import { findCityStayAfterBattle, type CityStayId } from '../data/cityStays';
|
||||
import {
|
||||
campaignRecruitUnits,
|
||||
jianYongRecruitBond,
|
||||
@@ -508,6 +509,7 @@ export type CampaignState = {
|
||||
battleHistory: Record<string, CampaignBattleSettlement>;
|
||||
latestBattleId?: string;
|
||||
pendingAftermathBattleId?: BattleScenarioId;
|
||||
activeCityStayId?: CityStayId;
|
||||
firstBattleReport?: FirstBattleReport;
|
||||
};
|
||||
|
||||
@@ -808,6 +810,22 @@ export function listCampaignSaveSlots(): CampaignSaveSlotSummary[] {
|
||||
export function markCampaignStep(step: CampaignStep) {
|
||||
const state = ensureCampaignState();
|
||||
state.step = step;
|
||||
if (!normalizeActiveCityStayId(state.activeCityStayId, state.latestBattleId, step)) {
|
||||
delete state.activeCityStayId;
|
||||
}
|
||||
state.updatedAt = new Date().toISOString();
|
||||
persistCampaignState(state);
|
||||
return cloneCampaignState(state);
|
||||
}
|
||||
|
||||
export function setActiveCityStayId(cityStayId?: CityStayId) {
|
||||
const state = ensureCampaignState();
|
||||
const normalizedCityStayId = normalizeActiveCityStayId(cityStayId, state.latestBattleId, state.step);
|
||||
if (normalizedCityStayId) {
|
||||
state.activeCityStayId = normalizedCityStayId;
|
||||
} else {
|
||||
delete state.activeCityStayId;
|
||||
}
|
||||
state.updatedAt = new Date().toISOString();
|
||||
persistCampaignState(state);
|
||||
return cloneCampaignState(state);
|
||||
@@ -1026,6 +1044,7 @@ export function setFirstBattleReport(report: FirstBattleReport) {
|
||||
}
|
||||
state.step = retryStep;
|
||||
state.latestBattleId = battleId;
|
||||
delete state.activeCityStayId;
|
||||
delete state.pendingAftermathBattleId;
|
||||
state.updatedAt = new Date().toISOString();
|
||||
persistCampaignState(state);
|
||||
@@ -1075,6 +1094,7 @@ export function setFirstBattleReport(report: FirstBattleReport) {
|
||||
delete state.sortieRecommendationSelection;
|
||||
}
|
||||
state.latestBattleId = battleId;
|
||||
delete state.activeCityStayId;
|
||||
state.pendingAftermathBattleId = battleId as BattleScenarioId;
|
||||
state.updatedAt = new Date().toISOString();
|
||||
|
||||
@@ -1728,6 +1748,16 @@ function normalizeCampaignState(state: Partial<CampaignState>): CampaignState {
|
||||
);
|
||||
}
|
||||
normalized.latestBattleId = normalizeLatestBattleId(normalized.latestBattleId, normalized.battleHistory);
|
||||
const activeCityStayId = normalizeActiveCityStayId(
|
||||
normalized.activeCityStayId,
|
||||
normalized.latestBattleId,
|
||||
normalized.step
|
||||
);
|
||||
if (activeCityStayId) {
|
||||
normalized.activeCityStayId = activeCityStayId;
|
||||
} else {
|
||||
delete normalized.activeCityStayId;
|
||||
}
|
||||
const pendingAftermathBattleId = typeof normalized.pendingAftermathBattleId === 'string' &&
|
||||
normalized.pendingAftermathBattleId in battleScenarios
|
||||
? normalized.pendingAftermathBattleId as BattleScenarioId
|
||||
@@ -3228,6 +3258,27 @@ function cloneCampaignState(state: CampaignState): CampaignState {
|
||||
return JSON.parse(JSON.stringify(state)) as CampaignState;
|
||||
}
|
||||
|
||||
function normalizeActiveCityStayId(
|
||||
cityStayId: unknown,
|
||||
latestBattleId: string | undefined,
|
||||
step: CampaignStep
|
||||
): CityStayId | undefined {
|
||||
if (typeof cityStayId !== 'string' || !latestBattleId || !isCampCampaignStep(step)) {
|
||||
return undefined;
|
||||
}
|
||||
if (!(latestBattleId in battleScenarios)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const cityStay = findCityStayAfterBattle(latestBattleId as BattleScenarioId);
|
||||
const expectedCampStep = cityStay
|
||||
? campaignBattleSteps[cityStay.afterBattleId]?.victory
|
||||
: undefined;
|
||||
return cityStay?.id === cityStayId && expectedCampStep === step
|
||||
? cityStay.id
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function cloneReport(report: FirstBattleReport): FirstBattleReport {
|
||||
const cloned = JSON.parse(JSON.stringify(report)) as FirstBattleReport;
|
||||
cloned.itemRewards = normalizeRewardStrings(cloned.itemRewards);
|
||||
|
||||
Reference in New Issue
Block a user