feat: complete campaign flow and optimize battle assets

This commit is contained in:
2026-07-19 21:31:07 +09:00
parent f83296db7b
commit 31e1396ac8
211 changed files with 4219 additions and 281 deletions

View File

@@ -23,6 +23,7 @@ export type BattleSaveBondState = BattleBond & {
};
export type SavedBattleUnitState = Pick<UnitData, 'id' | 'level' | 'exp' | 'hp' | 'maxHp' | 'attack' | 'move' | 'x' | 'y'> & {
stats?: UnitData['stats'];
equipment: UnitData['equipment'];
direction?: UnitDirection;
};
@@ -112,7 +113,7 @@ export type BattleSaveState = {
triggeredBattleEvents?: string[];
};
type BattleSaveValidationOptions = {
export type BattleSaveValidationOptions = {
expectedBattleId?: string;
allowTacticalCommand?: boolean;
allowLegacyTacticalCommand?: boolean;
@@ -144,6 +145,7 @@ const maxBattleUnitStatValue = 999999;
const maxBattleUnitHp = 9999;
const maxBattleUnitAttack = 9999;
const maxBattleUnitMove = 99;
const maxBattleUnitAttribute = 999;
const maxBattleBondBattleExp = 999999;
const maxStatusKindsPerUnit = 2;
const tacticalCommandCounterplayThreshold = 3;
@@ -547,6 +549,7 @@ function isSavedBattleUnitState(value: unknown, options: BattleSaveValidationOpt
Number(value.hp) > Number(value.maxHp) ||
!isIntegerInRange(value.attack, 0, maxBattleUnitAttack) ||
!isIntegerInRange(value.move, 0, maxBattleUnitMove) ||
!isOptionalUnitAttributes(value.stats) ||
!Number.isInteger(value.x) ||
!Number.isInteger(value.y)
) {
@@ -564,6 +567,20 @@ function isSavedBattleUnitState(value: unknown, options: BattleSaveValidationOpt
return value.direction === undefined || unitDirections.has(value.direction as UnitDirection);
}
function isOptionalUnitAttributes(value: unknown): value is UnitData['stats'] | undefined {
if (value === undefined) {
return true;
}
if (!isRecord(value)) {
return false;
}
const keys: Array<keyof UnitData['stats']> = ['might', 'intelligence', 'leadership', 'agility', 'luck'];
return (
Object.keys(value).length === keys.length &&
keys.every((key) => isIntegerInRange(value[key], 0, maxBattleUnitAttribute))
);
}
function isEquipmentSet(value: unknown, options: BattleSaveValidationOptions): value is UnitData['equipment'] {
if (!isRecord(value) || Object.keys(value).length !== equipmentSlots.length) {
return false;