feat: add second-victory relief exploration

This commit is contained in:
2026-07-27 10:53:20 +09:00
parent e9fcd27611
commit f07a45c62b
24 changed files with 4583 additions and 282 deletions

View File

@@ -8,11 +8,15 @@ const sourceFilesToScan = [
'src/game/audio/SoundDirector.ts',
'src/game/scenes/BattleScene.ts',
'src/game/scenes/CampScene.ts',
'src/game/scenes/CampVisitExplorationScene.ts',
'src/game/scenes/EndingScene.ts',
'src/game/scenes/StoryScene.ts',
'src/game/scenes/TitleScene.ts'
];
const requiredBattlefieldAmbienceKeys = ['battle-rain', 'battle-fire'];
const requiredDaytimeExplorationAmbienceKeys = [
'riverside-village-day-ambience'
];
const requiredTacticalCueKeys = [
'ally-turn',
'enemy-turn',
@@ -68,6 +72,14 @@ const battlefieldSourceRecords = [
source: 'https://pixabay.com/sound-effects/film-special-effects-failure-1-89170/'
}
];
const riversideDaySourceRecord = {
trackKey: 'riverside-village-day-ambience',
projectFile:
'src/assets/audio/ambience/riverside-village-day-ambience.mp3',
source:
'https://pixabay.com/sound-effects/nature-stream-water-with-birds-459511/',
creator: 'loswin23'
};
const narrativeSourceRecord = {
projectFile: 'src/assets/audio/sfx/story-page-turn.mp3',
source: 'https://pixabay.com/sound-effects/film-special-effects-flipping-book-page-499646/',
@@ -130,10 +142,17 @@ try {
validateTrackMap(errors, 'ambience', ambienceTracks, 'ambience');
validateTrackMap(errors, 'effect', effectTracks, 'sfx');
validateRequiredTrackKeys(errors, 'battlefield ambience', ambienceTracks, requiredBattlefieldAmbienceKeys);
validateRequiredTrackKeys(
errors,
'daytime exploration ambience',
ambienceTracks,
requiredDaytimeExplorationAmbienceKeys
);
validateRequiredTrackKeys(errors, 'tactical cue', effectTracks, requiredTacticalCueKeys);
validateRequiredTrackKeys(errors, 'narrative cue', effectTracks, requiredNarrativeCueKeys);
validateRequiredTrackKeys(errors, 'semantic feedback cue', effectTracks, requiredSemanticFeedbackCueKeys);
validateBattlefieldSourceDocumentation(errors);
validateRiversideDaySource(errors, ambienceTracks);
validateNarrativeSourceDocumentation(errors);
validateSemanticFeedbackSourceDocumentation(errors);
validateMovementSourceDocumentation(errors);
@@ -465,6 +484,70 @@ function linearGainDb(gain) {
return 20 * Math.log10(Math.max(0.0001, gain));
}
function validateRiversideDaySource(errors, ambienceTracks) {
const docs = readFileSync(join('docs', 'audio-sources.md'), 'utf8');
const requiredDetails = [
'2026-07-27',
riversideDaySourceRecord.projectFile,
riversideDaySourceRecord.source,
'Stream Water with Birds',
riversideDaySourceRecord.creator,
'32-second',
'44.1 kHz stereo MP3',
'two-second end-to-start',
'-24.03 LUFS',
'128 kbps'
];
requiredDetails.forEach((detail) => {
if (!docs.includes(detail)) {
errors.push(
`docs/audio-sources.md is missing daytime riverside detail "${detail}"`
);
}
});
if (!audioInspectionToolsAvailable(errors)) {
return;
}
const url = ambienceTracks[riversideDaySourceRecord.trackKey];
const path = url ? assetUrlToPath(url) : undefined;
if (!path) {
errors.push('The daytime riverside ambience must resolve to a project asset.');
return;
}
const probe = probeAudio(path, errors, riversideDaySourceRecord.trackKey);
if (!probe) {
return;
}
if (probe.duration < 31.9 || probe.duration > 32.2) {
errors.push(
`${riversideDaySourceRecord.trackKey} must remain a 32-second loop; ` +
`received ${probe.duration.toFixed(3)} seconds`
);
}
if (probe.sampleRate !== 44_100 || probe.channels !== 2) {
errors.push(
`${riversideDaySourceRecord.trackKey} must be 44.1 kHz stereo; ` +
`received ${probe.sampleRate} Hz/${probe.channels} channels`
);
}
if (!probe.artist.includes(riversideDaySourceRecord.creator)) {
errors.push(
`${riversideDaySourceRecord.trackKey} metadata must retain creator ` +
`"${riversideDaySourceRecord.creator}"`
);
}
if (
!probe.comment.includes('Pixabay Content License') ||
!probe.comment.includes(riversideDaySourceRecord.source)
) {
errors.push(
`${riversideDaySourceRecord.trackKey} metadata must retain its Pixabay ` +
'license and source URL'
);
}
}
function validateBattlefieldSourceDocumentation(errors) {
const docs = readFileSync(join('docs', 'audio-sources.md'), 'utf8');
if (!docs.includes('2026-07-21')) {