Ignore malformed campaign reward labels
This commit is contained in:
@@ -125,6 +125,15 @@ try {
|
|||||||
visitResynced.firstBattleReport?.completedCampVisits.includes('repeat-visit'),
|
visitResynced.firstBattleReport?.completedCampVisits.includes('repeat-visit'),
|
||||||
`Expected report-only camp visit completion to resync without duplicate rewards: ${JSON.stringify(visitResynced)}`
|
`Expected report-only camp visit completion to resync without duplicate rewards: ${JSON.stringify(visitResynced)}`
|
||||||
);
|
);
|
||||||
|
applyCampVisitReward('dirty-reward-visit', { itemRewards: ['', ' ', 'Bean -2', 'Bean +0', 'Bean x2'] });
|
||||||
|
const dirtyRewardVisit = getCampaignState();
|
||||||
|
assert(
|
||||||
|
dirtyRewardVisit.inventory.Bean === 7 &&
|
||||||
|
dirtyRewardVisit.inventory[''] === undefined &&
|
||||||
|
dirtyRewardVisit.inventory['Bean -'] === undefined &&
|
||||||
|
dirtyRewardVisit.completedCampVisits.includes('dirty-reward-visit'),
|
||||||
|
`Expected malformed reward labels to be ignored while valid rewards apply: ${JSON.stringify(dirtyRewardVisit)}`
|
||||||
|
);
|
||||||
const repeatBondId = firstScenario.bonds[0].id;
|
const repeatBondId = firstScenario.bonds[0].id;
|
||||||
applyCampBondExp('repeat-dialogue', repeatBondId, 10);
|
applyCampBondExp('repeat-dialogue', repeatBondId, 10);
|
||||||
const repeatedDialogueOnce = getCampaignState();
|
const repeatedDialogueOnce = getCampaignState();
|
||||||
|
|||||||
@@ -1399,7 +1399,12 @@ function createBattleSettlement(report: FirstBattleReport, reserveTraining: Camp
|
|||||||
|
|
||||||
function applyRewardDelta(inventory: Record<string, number>, rewards: string[], direction: 1 | -1) {
|
function applyRewardDelta(inventory: Record<string, number>, rewards: string[], direction: 1 | -1) {
|
||||||
return rewards.reduce<Record<string, number>>((nextInventory, reward) => {
|
return rewards.reduce<Record<string, number>>((nextInventory, reward) => {
|
||||||
const { label, amount } = parseRewardLabel(reward);
|
const parsed = parseRewardLabel(reward);
|
||||||
|
if (!parsed) {
|
||||||
|
return nextInventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { label, amount } = parsed;
|
||||||
const nextAmount = Math.max(0, (nextInventory[label] ?? 0) + amount * direction);
|
const nextAmount = Math.max(0, (nextInventory[label] ?? 0) + amount * direction);
|
||||||
const cap = direction === 1 ? campaignInventoryCaps[label] : undefined;
|
const cap = direction === 1 ? campaignInventoryCaps[label] : undefined;
|
||||||
nextInventory[label] = cap ? Math.min(nextAmount, cap) : nextAmount;
|
nextInventory[label] = cap ? Math.min(nextAmount, cap) : nextAmount;
|
||||||
@@ -1488,16 +1493,23 @@ function advanceReserveEquipment(unit: UnitData, amount: number) {
|
|||||||
|
|
||||||
function parseRewardLabel(reward: string) {
|
function parseRewardLabel(reward: string) {
|
||||||
const normalized = reward.replace(/\s+/g, ' ').trim();
|
const normalized = reward.replace(/\s+/g, ' ').trim();
|
||||||
const match = normalized.match(/^(.*?)(?:\s*[+xX]?\s*(\d+))$/);
|
if (!normalized) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = normalized.match(/^(.*?)(?:\s*([+xX-]?)\s*(\d+))$/);
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
return { label: normalized, amount: 1 };
|
return { label: normalized, amount: 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const amount = Number(match[3] ?? 1) * (match[2] === '-' ? -1 : 1);
|
||||||
label: match[1].trim() || normalized,
|
const label = match[1].trim();
|
||||||
amount: Number(match[2] ?? 1)
|
if (!label || !Number.isSafeInteger(amount) || amount <= 0) {
|
||||||
};
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { label, amount };
|
||||||
}
|
}
|
||||||
|
|
||||||
function cloneCampaignState(state: CampaignState): CampaignState {
|
function cloneCampaignState(state: CampaignState): CampaignState {
|
||||||
|
|||||||
Reference in New Issue
Block a user