Rework story engine flow and reorganize project docs
Some checks failed
CI / verify (push) Has been cancelled
Some checks failed
CI / verify (push) Has been cancelled
This commit is contained in:
81
src/services/storyEngine/endingResolver.ts
Normal file
81
src/services/storyEngine/endingResolver.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import type {
|
||||
CompanionResolution,
|
||||
EndingState,
|
||||
FactionTensionState,
|
||||
GameState,
|
||||
} from '../../types';
|
||||
|
||||
function resolveEndingType(params: {
|
||||
activeThreadCount: number;
|
||||
fracturedCompanions: number;
|
||||
hottestFactionTemperature: number;
|
||||
}) {
|
||||
if (params.hottestFactionTemperature >= 78 && params.fracturedCompanions >= 2) {
|
||||
return 'tragic' as const;
|
||||
}
|
||||
if (params.activeThreadCount >= 3 && params.hottestFactionTemperature >= 70) {
|
||||
return 'bitter_sweet' as const;
|
||||
}
|
||||
if (params.fracturedCompanions >= 1) {
|
||||
return 'fractured' as const;
|
||||
}
|
||||
if (params.activeThreadCount >= 3) {
|
||||
return 'ascendant' as const;
|
||||
}
|
||||
return 'heroic' as const;
|
||||
}
|
||||
|
||||
export function resolveEndingState(params: {
|
||||
state: GameState;
|
||||
companionResolutions: CompanionResolution[];
|
||||
factionTensionStates: FactionTensionState[];
|
||||
}) {
|
||||
const activeThreadIds = params.state.storyEngineMemory?.activeThreadIds ?? [];
|
||||
const fracturedCompanions = params.companionResolutions.filter((resolution) =>
|
||||
resolution.resolutionType === 'estranged' || resolution.resolutionType === 'departed',
|
||||
).length;
|
||||
const hottestFactionTemperature =
|
||||
params.factionTensionStates.reduce(
|
||||
(max, item) => Math.max(max, item.temperature),
|
||||
0,
|
||||
);
|
||||
const endingType = resolveEndingType({
|
||||
activeThreadCount: activeThreadIds.length,
|
||||
fracturedCompanions,
|
||||
hottestFactionTemperature,
|
||||
});
|
||||
|
||||
return {
|
||||
id: `ending:${endingType}:${activeThreadIds.slice(0, 2).join('+') || 'main'}`,
|
||||
title:
|
||||
endingType === 'heroic'
|
||||
? '守住火种'
|
||||
: endingType === 'tragic'
|
||||
? '余烬之末'
|
||||
: endingType === 'bitter_sweet'
|
||||
? '代价之后'
|
||||
: endingType === 'fractured'
|
||||
? '裂开的同路'
|
||||
: '新秩序的门槛',
|
||||
endingType,
|
||||
summary:
|
||||
endingType === 'heroic'
|
||||
? '你勉强把局势拖回了可继续前行的方向。'
|
||||
: endingType === 'tragic'
|
||||
? '真相被揭开,但代价也一并吞没了许多人。'
|
||||
: endingType === 'bitter_sweet'
|
||||
? '你走到了终点,但一路上失去的东西无法被轻易抹平。'
|
||||
: endingType === 'fractured'
|
||||
? '你推进了主线,却没能把所有同行者一起带到终点。'
|
||||
: '你不只是解开旧线,也推开了一个更大的新局面。',
|
||||
contributingThreadIds: activeThreadIds,
|
||||
companionResolutions: params.companionResolutions,
|
||||
worldOutcomeSummary:
|
||||
params.factionTensionStates.length > 0
|
||||
? params.factionTensionStates
|
||||
.slice(0, 2)
|
||||
.map((item) => item.pressureSummary)
|
||||
.join(' ')
|
||||
: '世界在你的选择之后开始改口。',
|
||||
} satisfies EndingState;
|
||||
}
|
||||
Reference in New Issue
Block a user