From 584965d45517bcb4dc913fd4dd3fb07a43590610 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Sun, 5 Jul 2026 10:32:00 +0900 Subject: [PATCH] Cover campaign reward resettlement --- .../verify-campaign-save-normalization.mjs | 55 ++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/scripts/verify-campaign-save-normalization.mjs b/scripts/verify-campaign-save-normalization.mjs index 75093a2..de48762 100644 --- a/scripts/verify-campaign-save-normalization.mjs +++ b/scripts/verify-campaign-save-normalization.mjs @@ -25,7 +25,15 @@ const server = await createServer({ }); try { - const { campaignStorageKey, loadCampaignState, normalizeCampaignSortieItemAssignments } = await server.ssrLoadModule('/src/game/state/campaignState.ts'); + const { + campaignStorageKey, + getCampaignState, + loadCampaignState, + normalizeCampaignSortieItemAssignments, + resetCampaignState, + setFirstBattleReport + } = await server.ssrLoadModule('/src/game/state/campaignState.ts'); + const { battleScenarios } = await server.ssrLoadModule('/src/game/data/battles.ts'); storage.clear(); const empty = loadCampaignState(); @@ -49,6 +57,49 @@ try { `Expected launch sortie supplies to share save normalization rules: ${JSON.stringify(normalizedLaunchSupplies)}` ); + resetCampaignState(); + const firstScenario = battleScenarios['first-battle-zhuo-commandery']; + const alliedFirstBattleUnits = firstScenario.units.filter((unit) => unit.faction === 'ally'); + const firstBattleReport = { + battleId: firstScenario.id, + battleTitle: firstScenario.title, + outcome: 'victory', + turnNumber: 5, + rewardGold: 100, + defeatedEnemies: 2, + totalEnemies: 4, + objectives: [], + units: alliedFirstBattleUnits, + bonds: firstScenario.bonds.map((bond) => ({ ...bond, battleExp: 0 })), + itemRewards: ['Bean x2'], + campaignRewards: { supplies: ['Bean x2'], equipment: [], reputation: [], recruits: [], unlocks: [] }, + completedCampDialogues: [], + completedCampVisits: [], + createdAt: '2026-07-03T09:00:00.000Z' + }; + setFirstBattleReport(firstBattleReport); + setFirstBattleReport(firstBattleReport); + const repeatedSettlement = getCampaignState(); + assert( + repeatedSettlement.gold === 100 && + repeatedSettlement.inventory.Bean === 2 && + repeatedSettlement.battleHistory[firstScenario.id]?.rewardGold === 100, + `Expected repeated battle report settlement to avoid duplicate gold/items: ${JSON.stringify(repeatedSettlement)}` + ); + setFirstBattleReport({ + ...firstBattleReport, + rewardGold: 140, + itemRewards: ['Bean x3', 'Wine'], + campaignRewards: { supplies: ['Bean x3', 'Wine'], equipment: [], reputation: [], recruits: [], unlocks: [] } + }); + const revisedSettlement = getCampaignState(); + assert( + revisedSettlement.gold === 140 && + revisedSettlement.inventory.Bean === 3 && + revisedSettlement.inventory.Wine === 1, + `Expected revised battle report settlement to replace previous rewards instead of stacking: ${JSON.stringify(revisedSettlement)}` + ); + storage.clear(); storage.set( campaignStorageKey, @@ -502,7 +553,7 @@ try { const fallback = loadCampaignState(); assert(fallback.step === 'second-camp' && fallback.activeSaveSlot === 2, `Expected valid slotted save fallback: ${JSON.stringify(fallback)}`); - console.log('Verified campaign save normalization, malformed-field/roster-equipment/bond-roster/report-reference/sortie-roster/latest-history/detail recovery, unknown-step/report/history recovery, unsupported-version rejection, and slotted fallback.'); + console.log('Verified campaign save normalization, reward resettlement, malformed-field/roster-equipment/bond-roster/report-reference/sortie-roster/latest-history/detail recovery, unknown-step/report/history recovery, unsupported-version rejection, and slotted fallback.'); } finally { await server.close(); }