feat: add sortie formation presets

This commit is contained in:
2026-07-10 21:26:54 +09:00
parent 481e870321
commit 7ba51d9243
4 changed files with 1174 additions and 36 deletions

View File

@@ -325,6 +325,16 @@ export type CampaignBattleSettlement = {
export type CampaignSortieItemAssignments = Record<string, Record<string, number>>;
export const campaignSortiePresetIds = ['elite', 'mobile', 'siege'] as const;
export type CampaignSortiePresetId = (typeof campaignSortiePresetIds)[number];
export type CampaignSortiePreset = {
selectedUnitIds: string[];
formationAssignments: SortieFormationAssignments;
};
export type CampaignSortieFormationPresets = Partial<Record<CampaignSortiePresetId, CampaignSortiePreset>>;
export type CampaignState = {
version: 1;
updatedAt: string;
@@ -337,6 +347,7 @@ export type CampaignState = {
selectedSortieUnitIds: string[];
sortieFormationAssignments: SortieFormationAssignments;
sortieItemAssignments: CampaignSortieItemAssignments;
sortieFormationPresets: CampaignSortieFormationPresets;
reserveTrainingFocus: CampaignReserveTrainingFocusId;
reserveTrainingAssignments: CampaignReserveTrainingAssignments;
completedCampDialogues: string[];
@@ -538,6 +549,7 @@ export function createInitialCampaignState(): CampaignState {
selectedSortieUnitIds: [],
sortieFormationAssignments: {},
sortieItemAssignments: {},
sortieFormationPresets: {},
reserveTrainingFocus: defaultCampaignReserveTrainingFocusId,
reserveTrainingAssignments: {},
completedCampDialogues: [],
@@ -926,6 +938,7 @@ function normalizeCampaignState(state: Partial<CampaignState>): CampaignState {
.filter((unitId) => !sortieUnitFilter || sortieUnitFilter.has(unitId));
normalized.sortieFormationAssignments = normalizeSortieFormationAssignments(recordOrEmpty(normalized.sortieFormationAssignments), sortieUnitFilter);
normalized.sortieItemAssignments = normalizeCampaignSortieItemAssignments(recordOrEmpty(normalized.sortieItemAssignments), sortieUnitFilter);
normalized.sortieFormationPresets = normalizeCampaignSortieFormationPresets(normalized.sortieFormationPresets, sortieUnitFilter);
normalized.reserveTrainingFocus = normalizeReserveTrainingFocusId(normalized.reserveTrainingFocus);
normalized.reserveTrainingAssignments = normalizeCampaignReserveTrainingAssignments(recordOrEmpty(normalized.reserveTrainingAssignments), sortieUnitFilter);
normalized.battleHistory = normalizeBattleHistory(normalized.battleHistory);
@@ -1316,6 +1329,32 @@ export function normalizeCampaignSortieItemAssignments(assignments?: Record<stri
}, {});
}
export function normalizeCampaignSortieFormationPresets(value: unknown, allowedUnitIds?: Set<string>) {
const source = recordOrEmpty(value);
return campaignSortiePresetIds.reduce<CampaignSortieFormationPresets>((presets, presetId) => {
const candidate = source[presetId];
if (!isPlainObject(candidate)) {
return presets;
}
const selectedUnitIds = uniqueStrings(candidate.selectedUnitIds)
.filter((unitId) => !allowedUnitIds || allowedUnitIds.has(unitId))
.slice(0, maxCampaignSortieAssignmentUnits);
if (selectedUnitIds.length === 0) {
return presets;
}
presets[presetId] = {
selectedUnitIds,
formationAssignments: normalizeSortieFormationAssignments(
recordOrEmpty(candidate.formationAssignments),
new Set(selectedUnitIds)
)
};
return presets;
}, {});
}
function normalizeReserveTrainingFocusId(focusId?: string): CampaignReserveTrainingFocusId {
return isReserveTrainingFocusId(focusId)
? focusId as CampaignReserveTrainingFocusId