feat: add walkable Guangzong sortie camp

This commit is contained in:
2026-07-27 22:37:55 +09:00
parent 43e5533515
commit 9d67e0ae1d
17 changed files with 3519 additions and 558 deletions

View File

@@ -20,6 +20,16 @@ try {
await server.ssrLoadModule(
'/src/game/data/secondBattleReliefExploration.ts'
);
const {
thirdCampCompanionDialogues,
thirdCampExplorationVisitId
} = await server.ssrLoadModule(
'/src/game/data/thirdCampExploration.ts'
);
const { thirdBattleReturnCampStep } =
await server.ssrLoadModule(
'/src/game/data/thirdBattleReturnDialogue.ts'
);
const scenarioData = await server.ssrLoadModule('/src/game/data/scenario.ts');
const { isCampaignStep } = await server.ssrLoadModule('/src/game/state/campaignState.ts');
const itemRewardArrays = collectItemRewardArrays(source);
@@ -28,14 +38,22 @@ try {
const campBattleIdKeys = new Set(campBattleIdEntries.map((entry) => entry.key));
validateCampBattleIdEntries(campBattleIdEntries, battleScenarios);
const knownBondsById = collectKnownBondsById(battleScenarios, scenarioData);
const dialogueEvents = collectCampEvents(source, 'campDialogues');
const dialogueEvents =
materializeCanonicalThirdCampCompanionDialogues(
collectCampEvents(source, 'campDialogues'),
thirdCampCompanionDialogues
);
const visitEvents = collectCampEvents(source, 'campVisits').map((event) =>
materializeCanonicalSecondBattleReliefVisit(
materializeCanonicalFirstPursuitVisit(
event,
firstPursuitScoutVisitDefinition
materializeCanonicalThirdCampExplorationVisit(
materializeCanonicalSecondBattleReliefVisit(
materializeCanonicalFirstPursuitVisit(
event,
firstPursuitScoutVisitDefinition
),
secondBattleReliefExplorationDefinition
),
secondBattleReliefExplorationDefinition
thirdCampExplorationVisitId,
thirdBattleReturnCampStep
)
);
const campaignStepReferences =
@@ -341,6 +359,40 @@ function collectCampEvents(text, arrayName) {
}));
}
function materializeCanonicalThirdCampCompanionDialogues(
events,
definitions
) {
const quote = (value) =>
`'${String(value).replaceAll('\\', '\\\\').replaceAll("'", "\\'")}'`;
return events.flatMap((event) => {
if (
!event.body.includes('...dialogue') ||
!event.body.includes('choices: dialogue.choices')
) {
return [event];
}
return definitions.map((definition) => {
const choiceSource = definition.choices
.map(
(choice) =>
`{ id: ${quote(choice.id)}, rewardExp: ${choice.rewardExp} }`
)
.join(', ');
return {
...event,
body:
`{ id: ${quote(definition.id)}, ` +
'availableAfterBattleIds: [campBattleIds.third], ' +
`unitIds: [${definition.unitIds.map(quote).join(', ')}], ` +
`bondId: ${quote(definition.bondId)}, ` +
`rewardExp: ${definition.rewardExp}, ` +
`choices: [${choiceSource}] }`
};
});
});
}
function materializeCanonicalFirstPursuitVisit(event, definition) {
if (!event.body.includes('...firstPursuitScoutVisitDefinition')) {
return event;
@@ -390,6 +442,26 @@ function materializeCanonicalSecondBattleReliefVisit(event, definition) {
};
}
function materializeCanonicalThirdCampExplorationVisit(
event,
visitId,
campStep
) {
if (!event.body.includes('id: thirdCampExplorationVisitId')) {
return event;
}
const quote = (value) =>
`'${String(value).replaceAll('\\', '\\\\').replaceAll("'", "\\'")}'`;
const canonicalSource =
`{ id: ${quote(visitId)}, ` +
'availableAfterBattleIds: [campBattleIds.third], ' +
`availableDuringSteps: [${quote(campStep)}], `;
return {
...event,
body: canonicalSource + event.body.slice(1)
};
}
function validateCampEventCollection(events, collectionName, campBattleIdKeys, isCampaignStep) {
const seenIds = new Map();
let campaignStepReferenceCount = 0;