1
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-20 15:45:14 +08:00
parent 8a7bd90458
commit 1c72066bab
73 changed files with 7814 additions and 1018 deletions

View File

@@ -5,6 +5,7 @@ import {getLiveGamePlayTimeMs} from '../data/runtimeStats';
import type { HydratedSavedGameSnapshot } from '../persistence/runtimeSnapshotTypes';
import {getWorldCampScenePreset} from '../data/scenePresets';
import {BottomTab} from '../hooks/useGameFlow';
import {resolveActiveSceneActBlueprint} from '../services/customWorldSceneActRuntime';
import {
type BattleRewardUi,
type CharacterChatUi,
@@ -321,6 +322,33 @@ export function GameShell({session, story, entry, companions, audio}: GameShellP
() => getLiveGamePlayTimeMs(gameState.runtimeStats, clockNow),
[clockNow, gameState.runtimeStats],
);
const activeSceneAct = useMemo(
() => resolveActiveSceneActBlueprint({
profile: visibleGameState.customWorldProfile,
sceneId: visibleGameState.currentScenePreset?.id ?? null,
storyEngineMemory: visibleGameState.storyEngineMemory,
}),
[
visibleGameState.currentScenePreset?.id,
visibleGameState.customWorldProfile,
visibleGameState.storyEngineMemory,
],
);
const activeSceneChapter = useMemo(() => {
if (!visibleGameState.customWorldProfile || !visibleGameState.currentScenePreset?.id) {
return null;
}
return (
visibleGameState.customWorldProfile.sceneChapterBlueprints?.find(
entry => entry.sceneId === visibleGameState.currentScenePreset?.id
|| entry.linkedLandmarkIds.includes(visibleGameState.currentScenePreset?.id ?? ''),
) ?? null
);
}, [
visibleGameState.currentScenePreset?.id,
visibleGameState.customWorldProfile,
]);
const adventureStatistics = useMemo(
() => ({
@@ -415,8 +443,9 @@ export function GameShell({session, story, entry, companions, audio}: GameShellP
<div
className={`pixel-app-shell flex min-h-0 flex-1 flex-col ${isCharacterSelectionStage ? 'justify-center p-4 sm:p-5' : 'p-3 sm:p-4'}`}
style={{
background: isCharacterSelectionStage
? '#0d1016'
backgroundColor: isCharacterSelectionStage ? '#0d1016' : undefined,
backgroundImage: isCharacterSelectionStage
? undefined
: `linear-gradient(rgba(10, 12, 18, 0.55), rgba(10, 12, 18, 0.55)), url("${UI_CHROME.appBackground}")`,
backgroundPosition: isCharacterSelectionStage ? undefined : 'center',
backgroundRepeat: isCharacterSelectionStage ? undefined : 'repeat',
@@ -564,6 +593,18 @@ export function GameShell({session, story, entry, companions, audio}: GameShellP
journeyBeat={
visibleGameState.storyEngineMemory?.currentJourneyBeat ?? null
}
currentSceneActTitle={activeSceneAct?.title ?? null}
currentSceneActIndex={
activeSceneChapter && activeSceneAct
? (() => {
const actIndex = activeSceneChapter.acts.findIndex(
act => act.id === activeSceneAct.id,
);
return actIndex >= 0 ? actIndex + 1 : null;
})()
: null
}
currentSceneActCount={activeSceneChapter?.acts.length ?? null}
statistics={adventureStatistics}
musicVolume={musicVolume}
onMusicVolumeChange={onMusicVolumeChange}