diff --git a/scripts/verify-battle-save-normalization.mjs b/scripts/verify-battle-save-normalization.mjs index 6c8f41d..d531375 100644 --- a/scripts/verify-battle-save-normalization.mjs +++ b/scripts/verify-battle-save-normalization.mjs @@ -103,6 +103,8 @@ try { ['unknown status unit id', { battleStatuses: [{ ...validState.battleStatuses[0], unitId: 'ghost-unit' }] }], ['duplicate status unit kind', { battleStatuses: [validState.battleStatuses[0], { ...validState.battleStatuses[0] }] }], ['invalid stats shape', { battleStats: { 'liu-bei': { damageDealt: 10 } } }], + ['invalid stats value', { battleStats: { 'liu-bei': { ...validState.battleStats['liu-bei'], actions: 1.5 } } }], + ['too high stats value', { battleStats: { 'liu-bei': { ...validState.battleStats['liu-bei'], damageDealt: 1000000 } } }], ['unknown stats unit id', { battleStats: { 'ghost-unit': validState.battleStats['liu-bei'] } }], ['invalid enemy usable keys', { enemyUsableUseKeys: [1] }], ['malformed enemy usable key', { enemyUsableUseKeys: ['rebel-1:shout'] }], diff --git a/src/game/state/battleSaveState.ts b/src/game/state/battleSaveState.ts index 733ee8e..7fa714f 100644 --- a/src/game/state/battleSaveState.ts +++ b/src/game/state/battleSaveState.ts @@ -91,6 +91,7 @@ const maxBattleEffectLabelLength = 32; const maxBattleEffectTurns = 9; const maxBattleBuffBonus = 99; const maxBattleStatusPower = 99; +const maxBattleUnitStatValue = 999999; const maxStatusKindsPerUnit = 2; const maxBattleItemStockById: Record = { bean: 3, @@ -398,6 +399,10 @@ function isValidEffectLabel(value: unknown) { return typeof value === 'string' && value.length > 0 && value.length <= maxBattleEffectLabelLength; } +function isBattleUnitStatValue(value: unknown) { + return isIntegerInRange(value, 0, maxBattleUnitStatValue); +} + function isOptionalBuffArray(value: unknown, options: BattleSaveValidationOptions) { return ( value === undefined || @@ -454,11 +459,11 @@ function isOptionalStatsRecord(value: unknown, options: BattleSaveValidationOpti ([unitId, stats]) => isKnownUnitId(unitId, options) && isRecord(stats) && - isNonNegativeFiniteNumber(stats.damageDealt) && - isNonNegativeFiniteNumber(stats.damageTaken) && - isNonNegativeFiniteNumber(stats.defeats) && - isNonNegativeFiniteNumber(stats.actions) && - isNonNegativeFiniteNumber(stats.support) + isBattleUnitStatValue(stats.damageDealt) && + isBattleUnitStatValue(stats.damageTaken) && + isBattleUnitStatValue(stats.defeats) && + isBattleUnitStatValue(stats.actions) && + isBattleUnitStatValue(stats.support) ); }