feat: improve first-session combat and visual assets
This commit is contained in:
@@ -44,6 +44,7 @@ try {
|
||||
validateReachability(errors, recruitTemplates, recruitRewardRefs);
|
||||
validateUniqueRecruitRewards(errors, recruitRewardRefs);
|
||||
validateSortieRecruitAvailability(errors, scenarioEntries);
|
||||
validateEarlyJianYongChoice(errors, battleScenarios);
|
||||
|
||||
if (errors.length) {
|
||||
console.error(`Campaign recruit data verification failed with ${errors.length} issue(s):`);
|
||||
@@ -214,6 +215,58 @@ function validateSortieRecruitAvailability(errors, scenarioEntries) {
|
||||
});
|
||||
}
|
||||
|
||||
function validateEarlyJianYongChoice(errors, battleScenarios) {
|
||||
const firstBattleId = 'first-battle-zhuo-commandery';
|
||||
const earlyChoiceBattleIds = [
|
||||
'second-battle-yellow-turban-pursuit',
|
||||
'third-battle-guangzong-road',
|
||||
'fourth-battle-guangzong-camp',
|
||||
'fifth-battle-sishui-vanguard',
|
||||
'sixth-battle-jieqiao-relief',
|
||||
'seventh-battle-xuzhou-rescue'
|
||||
];
|
||||
const foundingTrio = ['liu-bei', 'guan-yu', 'zhang-fei'];
|
||||
const earlyRoster = [...foundingTrio, 'jian-yong'];
|
||||
|
||||
const firstScenario = battleScenarios[firstBattleId];
|
||||
if (!firstScenario?.campaignReward?.recruits?.includes('jian-yong')) {
|
||||
errors.push(`${firstBattleId}: first victory must recruit jian-yong`);
|
||||
}
|
||||
const firstVictoryCopy = firstScenario?.victoryPages?.map((page) => `${page.text ?? ''} ${page.cutscene?.title ?? ''} ${page.cutscene?.subtitle ?? ''}`).join(' ') ?? '';
|
||||
if (!firstVictoryCopy.includes('간옹') || !firstVictoryCopy.includes('최대 3명')) {
|
||||
errors.push(`${firstBattleId}: victory story must explain Jian Yong's arrival and the four-officer/three-slot choice`);
|
||||
}
|
||||
|
||||
earlyChoiceBattleIds.forEach((battleId) => {
|
||||
const scenario = battleScenarios[battleId];
|
||||
if (!scenario) {
|
||||
errors.push(`${battleId}: missing early-choice battle scenario`);
|
||||
return;
|
||||
}
|
||||
const allyIds = new Set(scenario.units.filter((unit) => unit.faction === 'ally').map((unit) => unit.id));
|
||||
earlyRoster.forEach((unitId) => {
|
||||
if (!allyIds.has(unitId)) {
|
||||
errors.push(`${battleId}: early 4-of-3 roster is missing ${unitId}`);
|
||||
}
|
||||
});
|
||||
if (scenario.sortie?.sortieLimit !== 3) {
|
||||
errors.push(`${battleId}: early formation must keep sortieLimit 3, got ${scenario.sortie?.sortieLimit}`);
|
||||
}
|
||||
const recommendedIds = new Set((scenario.sortie?.recommendedUnits ?? []).map((entry) => entry.unitId));
|
||||
if (recommendedIds.size !== foundingTrio.length || foundingTrio.some((unitId) => !recommendedIds.has(unitId))) {
|
||||
errors.push(`${battleId}: recommended formation must remain the founding trio`);
|
||||
}
|
||||
if (!scenario.bonds.some((bond) => bond.id === 'liu-bei__jian-yong')) {
|
||||
errors.push(`${battleId}: missing liu-bei__jian-yong resonance`);
|
||||
}
|
||||
});
|
||||
|
||||
const seventhRecruits = battleScenarios['seventh-battle-xuzhou-rescue']?.campaignReward?.recruits ?? [];
|
||||
if (seventhRecruits.includes('jian-yong') || !seventhRecruits.includes('mi-zhu')) {
|
||||
errors.push('seventh-battle-xuzhou-rescue: must recruit only the new Xuzhou officer Mi Zhu, not Jian Yong again');
|
||||
}
|
||||
}
|
||||
|
||||
function assertNonEmptyString(errors, value, context) {
|
||||
if (typeof value !== 'string' || value.trim().length === 0) {
|
||||
errors.push(`${context} must be a non-empty string`);
|
||||
|
||||
Reference in New Issue
Block a user