From 1145ef14aa705fa372c02509bce0f2c4d7831bb3 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Sun, 5 Jul 2026 13:52:42 +0900 Subject: [PATCH] Clamp campaign save numeric fields --- scripts/verify-campaign-save-normalization.mjs | 15 ++++++++------- src/game/state/campaignState.ts | 3 ++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/verify-campaign-save-normalization.mjs b/scripts/verify-campaign-save-normalization.mjs index 0c32671..1af1355 100644 --- a/scripts/verify-campaign-save-normalization.mjs +++ b/scripts/verify-campaign-save-normalization.mjs @@ -282,7 +282,7 @@ try { updatedAt: '', step: 'third-camp', activeSaveSlot: '2', - gold: '410', + gold: '1000000', roster: { corrupted: true }, bonds: [ { id: 'broken-bond', title: 'Broken Bond', unitIds: { corrupted: true }, level: 3, exp: 12, battleExp: 2 }, @@ -315,7 +315,7 @@ try { ); const malformed = loadCampaignState(); assert(malformed.step === 'third-camp', `Expected malformed save progress to survive: ${JSON.stringify(malformed)}`); - assert(malformed.activeSaveSlot === 2 && malformed.gold === 410, `Expected malformed numeric fields to normalize: ${JSON.stringify(malformed)}`); + assert(malformed.activeSaveSlot === 2 && malformed.gold === 999999, `Expected malformed numeric fields to normalize and clamp: ${JSON.stringify(malformed)}`); assert(Array.isArray(malformed.roster) && malformed.roster.length === 0, `Expected malformed roster to reset to an array: ${JSON.stringify(malformed)}`); assert( Array.isArray(malformed.bonds) && @@ -577,11 +577,11 @@ try { battleTitle: ' ', outcome: 'victory', turnNumber: '4', - rewardGold: '120', + rewardGold: '1000000', defeatedEnemies: '3', totalEnemies: '5', objectives: [ - { id: 'village', label: 'Village', achieved: true, detail: 12, summary: 'x'.repeat(220), rewardGold: '80' }, + { id: 'village', label: 'Village', achieved: true, detail: 12, summary: 'x'.repeat(220), rewardGold: '1000000' }, { id: '', label: 'Broken', achieved: true }, ...Array.from({ length: 30 }, (_, index) => ({ id: `bonus-${index}`, @@ -640,7 +640,7 @@ try { battleExp: 1 })) ], - mvp: { unitId: 'liu-bei', name: 'Liu Bei', damageDealt: '88', defeats: '2' }, + mvp: { unitId: 'liu-bei', name: 'Liu Bei', damageDealt: '1000000', defeats: '2' }, itemRewards: ['Bean', 'Bean', 10, 'x'.repeat(97)], campaignRewards: { supplies: [' Bean ', 'Bean', 20, 'x'.repeat(97)], @@ -673,14 +673,15 @@ try { malformedReport.firstBattleReport?.battleId === 'first-battle-zhuo-commandery' && malformedReport.firstBattleReport.battleTitle === firstScenario.title && malformedReport.firstBattleReport.turnNumber === 4 && + malformedReport.firstBattleReport.rewardGold === 999999 && malformedReport.firstBattleReport.objectives.length === 24 && - malformedReport.firstBattleReport.objectives[0].rewardGold === 80 && + malformedReport.firstBattleReport.objectives[0].rewardGold === 999999 && malformedReport.firstBattleReport.objectives[0].summary.length === 180 && malformedReport.firstBattleReport.units.length === 96 && malformedReport.firstBattleReport.units[0].level === 5 && malformedReport.firstBattleReport.bonds.length === 96 && malformedReport.firstBattleReport.bonds[0].battleExp === 4 && - malformedReport.firstBattleReport.mvp?.damageDealt === 88 && + malformedReport.firstBattleReport.mvp?.damageDealt === 999999 && malformedReport.firstBattleReport.itemRewards.length === 1 && malformedReport.firstBattleReport.campaignRewards?.supplies.length === 1 && malformedReport.firstBattleReport.campaignRewards?.supplies[0] === 'Bean' && diff --git a/src/game/state/campaignState.ts b/src/game/state/campaignState.ts index d486130..d7e3dca 100644 --- a/src/game/state/campaignState.ts +++ b/src/game/state/campaignState.ts @@ -276,6 +276,7 @@ const maxCampaignBattleBondEntries = 96; const maxCampaignReserveTrainingEntries = 96; const maxCampaignSortieAssignmentUnits = 96; const maxCampaignDisplayTextLength = 180; +const maxCampaignNumericValue = 999999; export const campaignReserveTrainingFocusDefinitions: CampaignReserveTrainingFocusDefinition[] = [ { @@ -945,7 +946,7 @@ function normalizedRosterUnitIds(roster: UnitData[]) { function normalizeNonNegativeInteger(value: unknown) { const numeric = Math.floor(Number(value)); - return Number.isFinite(numeric) && numeric > 0 ? numeric : 0; + return Number.isFinite(numeric) && numeric > 0 ? Math.min(numeric, maxCampaignNumericValue) : 0; } function normalizeCharacterLevel(value: unknown) {