diff --git a/scripts/verify-campaign-save-normalization.mjs b/scripts/verify-campaign-save-normalization.mjs index 56024ee..b824f2c 100644 --- a/scripts/verify-campaign-save-normalization.mjs +++ b/scripts/verify-campaign-save-normalization.mjs @@ -768,7 +768,15 @@ try { status: 'lost', detail: 12, rewardGold: '80', - targetTile: { x: '4', y: '5', radius: '2' } + targetTile: { x: '4', y: '5', radius: '200' } + }, + { + id: 'broken-target', + label: 'Broken target', + achieved: false, + detail: 'Bad target tile', + rewardGold: 0, + targetTile: { x: '-1', y: '5', radius: '2' } }, 'broken-objective', ...Array.from({ length: 30 }, (_, index) => ({ @@ -879,9 +887,12 @@ try { `Expected stale latestBattleId to recover to the latest valid settlement: ${JSON.stringify(malformedHistory)}` ); assert( - malformedHistory.battleHistory['first-battle-zhuo-commandery']?.objectives.length === 24 && + malformedHistory.battleHistory['first-battle-zhuo-commandery']?.objectives.length === 24 && malformedHistory.battleHistory['first-battle-zhuo-commandery']?.objectives[0].rewardGold === 80 && malformedHistory.battleHistory['first-battle-zhuo-commandery']?.objectives[0].targetTile?.x === 4 && + malformedHistory.battleHistory['first-battle-zhuo-commandery']?.objectives[0].targetTile?.radius === 99 && + malformedHistory.battleHistory['first-battle-zhuo-commandery']?.objectives[1].id === 'broken-target' && + malformedHistory.battleHistory['first-battle-zhuo-commandery']?.objectives[1].targetTile === undefined && malformedHistory.battleHistory['first-battle-zhuo-commandery']?.objectives[0].status === undefined && malformedHistory.battleHistory['first-battle-zhuo-commandery']?.units.length === 1 && malformedHistory.battleHistory['first-battle-zhuo-commandery']?.units[0].level === 4 && diff --git a/src/game/state/campaignState.ts b/src/game/state/campaignState.ts index 12b81ae..af3f19d 100644 --- a/src/game/state/campaignState.ts +++ b/src/game/state/campaignState.ts @@ -277,6 +277,7 @@ const maxCampaignReserveTrainingEntries = 96; const maxCampaignSortieAssignmentUnits = 96; const maxCampaignDisplayTextLength = 180; const maxCampaignNumericValue = 999999; +const maxCampaignObjectiveTargetRadius = 99; export const campaignReserveTrainingFocusDefinitions: CampaignReserveTrainingFocusDefinition[] = [ { @@ -1129,11 +1130,11 @@ function normalizeObjectiveTargetTile(value: unknown): BattleObjectiveSnapshot[' const x = Math.floor(Number(value.x)); const y = Math.floor(Number(value.y)); - if (!Number.isFinite(x) || !Number.isFinite(y)) { + if (!Number.isFinite(x) || !Number.isFinite(y) || x < 0 || y < 0) { return undefined; } - const radius = normalizeNonNegativeInteger(value.radius); + const radius = Math.min(normalizeNonNegativeInteger(value.radius), maxCampaignObjectiveTargetRadius); return radius > 0 ? { x, y, radius } : { x, y }; }