feat: unify victory reward experience
This commit is contained in:
@@ -134,6 +134,18 @@ export type FirstBattleReport = {
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
export type CampaignVictoryRewardPresentation = {
|
||||
baseRewardGold: number;
|
||||
rewardGold: number;
|
||||
itemRewards: string[];
|
||||
sortieOrderBonus?: {
|
||||
orderId: SortieOrderId;
|
||||
label: string;
|
||||
rewardGold: number;
|
||||
rewardItems: string[];
|
||||
};
|
||||
};
|
||||
|
||||
export type CampaignStep =
|
||||
| 'new'
|
||||
| 'prologue'
|
||||
@@ -448,6 +460,7 @@ export type CampaignState = {
|
||||
reserveTrainingAssignments: CampaignReserveTrainingAssignments;
|
||||
completedCampDialogues: string[];
|
||||
completedCampVisits: string[];
|
||||
acknowledgedVictoryRewardBattleIds: string[];
|
||||
battleHistory: Record<string, CampaignBattleSettlement>;
|
||||
latestBattleId?: string;
|
||||
firstBattleReport?: FirstBattleReport;
|
||||
@@ -652,6 +665,7 @@ export function createInitialCampaignState(): CampaignState {
|
||||
reserveTrainingAssignments: {},
|
||||
completedCampDialogues: [],
|
||||
completedCampVisits: [],
|
||||
acknowledgedVictoryRewardBattleIds: [],
|
||||
battleHistory: {}
|
||||
};
|
||||
}
|
||||
@@ -986,6 +1000,66 @@ export function getFirstBattleReport() {
|
||||
return report ? cloneReport(report) : undefined;
|
||||
}
|
||||
|
||||
export function campaignVictoryRewardPresentation(report: FirstBattleReport): CampaignVictoryRewardPresentation {
|
||||
const definition = report.outcome === 'victory' && report.sortieOrder?.rewardGranted
|
||||
? sortieOrderDefinition(report.sortieOrder.orderId)
|
||||
: undefined;
|
||||
const sortieOrderBonus = definition
|
||||
? {
|
||||
orderId: definition.id,
|
||||
label: definition.label,
|
||||
rewardGold: definition.rewardGold,
|
||||
rewardItems: [...definition.rewardItems]
|
||||
}
|
||||
: undefined;
|
||||
return {
|
||||
baseRewardGold: report.rewardGold,
|
||||
rewardGold: report.rewardGold + (sortieOrderBonus?.rewardGold ?? 0),
|
||||
itemRewards: [...report.itemRewards, ...(sortieOrderBonus?.rewardItems ?? [])],
|
||||
sortieOrderBonus
|
||||
};
|
||||
}
|
||||
|
||||
export function getPendingCampaignVictoryRewardReport() {
|
||||
const state = ensureCampaignState();
|
||||
const report = state.firstBattleReport;
|
||||
if (
|
||||
!report ||
|
||||
report.outcome !== 'victory' ||
|
||||
state.acknowledgedVictoryRewardBattleIds.includes(report.battleId)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
return cloneReport(report);
|
||||
}
|
||||
|
||||
export function acknowledgeCampaignVictoryReward(battleId: string) {
|
||||
const state = ensureCampaignState();
|
||||
const normalizedBattleId = normalizeKeyString(battleId);
|
||||
const report = state.firstBattleReport;
|
||||
const settlement = state.battleHistory[normalizedBattleId];
|
||||
const hasVictory = settlement?.outcome === 'victory' || (
|
||||
report?.battleId === normalizedBattleId && report.outcome === 'victory'
|
||||
);
|
||||
if (
|
||||
!normalizedBattleId ||
|
||||
!(normalizedBattleId in battleScenarios) ||
|
||||
!hasVictory
|
||||
) {
|
||||
return cloneCampaignState(state);
|
||||
}
|
||||
|
||||
if (!state.acknowledgedVictoryRewardBattleIds.includes(normalizedBattleId)) {
|
||||
state.acknowledgedVictoryRewardBattleIds = [
|
||||
...state.acknowledgedVictoryRewardBattleIds,
|
||||
normalizedBattleId
|
||||
];
|
||||
state.updatedAt = new Date().toISOString();
|
||||
persistCampaignState(state);
|
||||
}
|
||||
return cloneCampaignState(state);
|
||||
}
|
||||
|
||||
export function applyCampBondExp(dialogueId: string, bondId: string, amount: number) {
|
||||
const state = ensureCampaignState();
|
||||
if (!state.firstBattleReport) {
|
||||
@@ -1158,6 +1232,8 @@ function normalizeCampaignState(state: Partial<CampaignState>): CampaignState {
|
||||
.filter((bond): bond is CampBondSnapshot => Boolean(bond));
|
||||
normalized.completedCampDialogues = uniqueStrings(normalized.completedCampDialogues);
|
||||
normalized.completedCampVisits = uniqueStrings(normalized.completedCampVisits);
|
||||
normalized.acknowledgedVictoryRewardBattleIds = uniqueStrings(normalized.acknowledgedVictoryRewardBattleIds)
|
||||
.filter((battleId) => battleId in battleScenarios);
|
||||
normalized.inventory = normalizeInventory(normalized.inventory);
|
||||
const rosterUnitIds = normalizedRosterUnitIds(normalized.roster);
|
||||
const sortieUnitFilter = rosterUnitIds.size > 0 ? rosterUnitIds : undefined;
|
||||
@@ -1216,6 +1292,16 @@ function normalizeCampaignState(state: Partial<CampaignState>): CampaignState {
|
||||
if (normalized.firstBattleReport && sortieUnitFilter) {
|
||||
normalized.firstBattleReport = filterFirstBattleReportRosterReferences(normalized.firstBattleReport, sortieUnitFilter);
|
||||
}
|
||||
const recordedVictoryBattleIds = new Set(
|
||||
Object.entries(normalized.battleHistory)
|
||||
.filter(([, settlement]) => settlement.outcome === 'victory')
|
||||
.map(([battleId]) => battleId)
|
||||
);
|
||||
if (normalized.firstBattleReport?.outcome === 'victory') {
|
||||
recordedVictoryBattleIds.add(normalized.firstBattleReport.battleId);
|
||||
}
|
||||
normalized.acknowledgedVictoryRewardBattleIds = normalized.acknowledgedVictoryRewardBattleIds
|
||||
.filter((battleId) => recordedVictoryBattleIds.has(battleId));
|
||||
normalized.sortieOrderHistory = normalizeCampaignSortieOrderHistory(
|
||||
normalized.sortieOrderHistory,
|
||||
normalized.battleHistory,
|
||||
|
||||
Reference in New Issue
Block a user