feat: add dev diary and ending thumbnails, update chapter endings display

This commit is contained in:
2026-06-14 11:51:32 +08:00
parent d373cb8fc0
commit 92966331d3
3 changed files with 76 additions and 14 deletions

View File

@@ -117,6 +117,43 @@ function endingStatus(endingId: string) {
return props.visitedIds.has(props.endings.find(e => e.id === endingId)?.sceneId ?? '')
}
function isKeyMoment(sceneId: string): boolean {
const scene = props.scenes[sceneId]
if (!scene) return false
if (scene.keyMoment !== undefined) return scene.keyMoment
if (props.chapters.some(c => c.startScene === sceneId)) return true
if (scene.choices && scene.choices.length > 0) return true
if (props.endings.some(e => e.sceneId === sceneId)) return true
return false
}
function collectKeyTargets(sceneId: string, depth: number, pathSet: Set<string>): string[] {
if (depth > 10 || pathSet.has(sceneId)) return []
pathSet.add(sceneId)
const scene = props.scenes[sceneId]
if (!scene) return []
if (isKeyMoment(sceneId)) return [sceneId]
const results: string[] = []
function pushTarget(target: string | undefined) {
if (!target) return
results.push(...collectKeyTargets(target, depth + 1, pathSet))
}
if (scene.choices) for (const c of scene.choices) pushTarget(c.targetScene)
if (scene.nextScene) {
if (Array.isArray(scene.nextScene)) {
for (const r of scene.nextScene) pushTarget(r.targetScene)
} else {
pushTarget(scene.nextScene)
}
}
if (scene.qte) {
pushTarget(scene.qte.successScene)
pushTarget(scene.qte.failScene)
}
if (scene.hotspots) for (const h of scene.hotspots) pushTarget(h.targetScene)
return results
}
function resolveInitialChapter(): string {
const saved = localStorage.getItem('story_chapter')
if (saved && props.chapters.some(c => c.id === saved)) return saved
@@ -146,21 +183,24 @@ function buildPlayerTree(sceneId: string, chapterId: string, depth: number, path
if (scene) {
function pushChild(target: string | undefined) {
if (!target) return
if (isOtherChapterStart(target, chapterId)) {
const gatewayCh = props.chapters.find(c => c.startScene === target)
children.push({
sceneId: '',
label: gatewayCh ? (t(gatewayCh.labelKey || gatewayCh.label)) : target,
visited: false,
locked: !props.unlockedChapterIds.has(gatewayCh?.id ?? ''),
children: [],
isGateway: true,
gatewayChapterId: gatewayCh?.id,
})
return
const keyIds = collectKeyTargets(target, 0, new Set())
for (const keyId of keyIds) {
if (isOtherChapterStart(keyId, chapterId)) {
const gatewayCh = props.chapters.find(c => c.startScene === keyId)
children.push({
sceneId: '',
label: gatewayCh ? (t(gatewayCh.labelKey || gatewayCh.label)) : keyId,
visited: false,
locked: !props.unlockedChapterIds.has(gatewayCh?.id ?? ''),
children: [],
isGateway: true,
gatewayChapterId: gatewayCh?.id,
})
} else {
const child = buildPlayerTree(keyId, chapterId, depth + 1, pathSet)
if (child) children.push(child)
}
}
const child = buildPlayerTree(target, chapterId, depth + 1, pathSet)
if (child) children.push(child)
}
if (scene.choices) {
for (const c of scene.choices) pushChild(c.targetScene)