70 lines
2.0 KiB
TypeScript
70 lines
2.0 KiB
TypeScript
import type { ActState, ChapterState, GameState } from '../../types';
|
|
|
|
function resolveActIndex(chapterState: ChapterState | null | undefined) {
|
|
if (!chapterState) return 0;
|
|
if (chapterState.stage === 'climax' || chapterState.stage === 'aftermath') return 2;
|
|
if (chapterState.stage === 'turning_point') return 1;
|
|
return 0;
|
|
}
|
|
|
|
export function buildActPlan(params: {
|
|
state: GameState;
|
|
}) {
|
|
const primaryThreads = params.state.storyEngineMemory?.activeThreadIds ?? [];
|
|
return [
|
|
{
|
|
id: 'act-1',
|
|
title: '第一幕·起线',
|
|
actIndex: 0,
|
|
theme: '铺陈与引线',
|
|
primaryThreadIds: primaryThreads.slice(0, 2),
|
|
status: 'opening',
|
|
},
|
|
{
|
|
id: 'act-2',
|
|
title: '第二幕·扩张',
|
|
actIndex: 1,
|
|
theme: '冲突升级',
|
|
primaryThreadIds: primaryThreads.slice(0, 3),
|
|
status: 'midgame',
|
|
},
|
|
{
|
|
id: 'act-3',
|
|
title: '第三幕·收束',
|
|
actIndex: 2,
|
|
theme: '决战与余波',
|
|
primaryThreadIds: primaryThreads.slice(0, 3),
|
|
status: 'finale',
|
|
},
|
|
] satisfies ActState[];
|
|
}
|
|
|
|
export function resolveCurrentActState(params: {
|
|
state: GameState;
|
|
chapterState?: ChapterState | null;
|
|
}) {
|
|
const chapterState = params.chapterState ?? params.state.chapterState ?? null;
|
|
const actIndex = resolveActIndex(chapterState);
|
|
const actPlan = buildActPlan(params);
|
|
const candidate = actPlan[actIndex] ?? actPlan[0];
|
|
if (!candidate) return null;
|
|
|
|
return {
|
|
...candidate,
|
|
theme: chapterState?.theme ?? candidate.theme,
|
|
primaryThreadIds: chapterState?.primaryThreadIds ?? candidate.primaryThreadIds,
|
|
status:
|
|
chapterState?.stage === 'opening'
|
|
? 'opening'
|
|
: chapterState?.stage === 'expansion'
|
|
? 'midgame'
|
|
: chapterState?.stage === 'turning_point'
|
|
? 'late_game'
|
|
: chapterState?.stage === 'climax'
|
|
? 'finale'
|
|
: chapterState?.stage === 'aftermath'
|
|
? 'resolved'
|
|
: candidate.status,
|
|
} satisfies ActState;
|
|
}
|