feat: connect sortie recommendations to battle results
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
import type { BattleBond, UnitData } from '../data/scenario';
|
||||
import { isCampaignStep, type CampaignStep } from './campaignState';
|
||||
import {
|
||||
isCampaignStep,
|
||||
normalizeCampaignSortieRecommendationSnapshot,
|
||||
type CampaignSortieRecommendationSnapshot,
|
||||
type CampaignStep
|
||||
} from './campaignState';
|
||||
import type { UnitDirection } from '../data/unitAssets';
|
||||
import { equipmentExpToNext, equipmentSlots, type EquipmentSlot } from '../data/battleItems';
|
||||
import type { SortieOrderId } from '../data/sortieOrders';
|
||||
@@ -47,6 +52,8 @@ export type BattleSaveUnitStats = {
|
||||
defeats: number;
|
||||
actions: number;
|
||||
support: number;
|
||||
strategyUses?: number;
|
||||
signatureStrategyUses?: number;
|
||||
sortieBonusDamage?: number;
|
||||
sortiePreventedDamage?: number;
|
||||
sortieBonusHealing?: number;
|
||||
@@ -83,6 +90,7 @@ export type BattleSaveState = {
|
||||
campaignStep?: CampaignStep;
|
||||
sortieOrderId?: SortieOrderId;
|
||||
sortieResonanceBondId?: string;
|
||||
sortieRecommendation?: CampaignSortieRecommendationSnapshot;
|
||||
coreResonanceStats?: BattleSaveCoreResonanceStats;
|
||||
savedAt: string;
|
||||
turnNumber: number;
|
||||
@@ -174,6 +182,15 @@ export function normalizeBattleSaveState(
|
||||
}
|
||||
|
||||
normalizeCoreResonanceSaveFields(cloned, options);
|
||||
const recommendation = normalizeCampaignSortieRecommendationSnapshot(cloned.sortieRecommendation, {
|
||||
expectedBattleId: typeof cloned.battleId === 'string' ? cloned.battleId : options.expectedBattleId,
|
||||
allowedUnitIds: options.validAllyUnitIds
|
||||
});
|
||||
if (recommendation) {
|
||||
cloned.sortieRecommendation = recommendation;
|
||||
} else {
|
||||
delete cloned.sortieRecommendation;
|
||||
}
|
||||
return isValidBattleSaveState(cloned, options) ? cloned : undefined;
|
||||
}
|
||||
|
||||
@@ -709,23 +726,32 @@ function isOptionalStatsRecord(value: unknown, options: BattleSaveValidationOpti
|
||||
return false;
|
||||
}
|
||||
|
||||
return Object.entries(value).every(
|
||||
([unitId, stats]) =>
|
||||
isKnownUnitId(unitId, options) &&
|
||||
isRecord(stats) &&
|
||||
return Object.entries(value).every(([unitId, stats]) => {
|
||||
if (!isKnownUnitId(unitId, options) || !isRecord(stats)) {
|
||||
return false;
|
||||
}
|
||||
const strategyUses = stats.strategyUses === undefined ? 0 : stats.strategyUses;
|
||||
const signatureStrategyUses = stats.signatureStrategyUses === undefined ? 0 : stats.signatureStrategyUses;
|
||||
return (
|
||||
isBattleUnitStatValue(stats.damageDealt) &&
|
||||
isBattleUnitStatValue(stats.damageTaken) &&
|
||||
isBattleUnitStatValue(stats.defeats) &&
|
||||
isBattleUnitStatValue(stats.actions) &&
|
||||
isBattleUnitStatValue(stats.support) &&
|
||||
isOptionalBattleUnitStatValue(stats.strategyUses) &&
|
||||
isOptionalBattleUnitStatValue(stats.signatureStrategyUses) &&
|
||||
isOptionalBattleUnitStatValue(stats.sortieBonusDamage) &&
|
||||
isOptionalBattleUnitStatValue(stats.sortiePreventedDamage) &&
|
||||
isOptionalBattleUnitStatValue(stats.sortieBonusHealing) &&
|
||||
isOptionalBattleUnitStatValue(stats.sortieExtendedBondTriggers) &&
|
||||
isOptionalBattleUnitStatValue(stats.intentDefeats) &&
|
||||
isOptionalBattleUnitStatValue(stats.intentLineBreaks) &&
|
||||
isOptionalBattleUnitStatValue(stats.intentGuardSuccesses)
|
||||
);
|
||||
isOptionalBattleUnitStatValue(stats.intentGuardSuccesses) &&
|
||||
typeof strategyUses === 'number' &&
|
||||
typeof signatureStrategyUses === 'number' &&
|
||||
signatureStrategyUses <= strategyUses
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function isOptionalBattleUnitStatValue(value: unknown) {
|
||||
|
||||
Reference in New Issue
Block a user