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:
@@ -1,4 +1,10 @@
|
||||
import type {QuestGenerationContext} from '../services/aiTypes';
|
||||
import {
|
||||
buildFallbackActorNarrativeProfile,
|
||||
normalizeActorNarrativeProfile,
|
||||
} from '../services/storyEngine/actorNarrativeProfile';
|
||||
import { buildThemePackFromWorldProfile } from '../services/storyEngine/themePack';
|
||||
import { buildFallbackWorldStoryGraph } from '../services/storyEngine/worldStoryGraph';
|
||||
import type {
|
||||
EquipmentLoadout,
|
||||
GameState,
|
||||
@@ -78,12 +84,81 @@ function derivePlayerBuildGaps(playerBuildTags: string[]) {
|
||||
.slice(0, 3);
|
||||
}
|
||||
|
||||
function resolveRelatedNpcNarrativeProfile(params: {
|
||||
customWorldProfile: GameState['customWorldProfile'];
|
||||
encounter: GameState['currentEncounter'];
|
||||
}) {
|
||||
const { customWorldProfile, encounter } = params;
|
||||
if (!customWorldProfile || !encounter || encounter.kind !== 'npc') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const role =
|
||||
customWorldProfile.storyNpcs.find((npc) =>
|
||||
npc.id === encounter.id || npc.name === encounter.npcName,
|
||||
)
|
||||
?? customWorldProfile.playableNpcs.find((npc) =>
|
||||
npc.id === encounter.id || npc.name === encounter.npcName,
|
||||
);
|
||||
if (!role) {
|
||||
return encounter.narrativeProfile ?? null;
|
||||
}
|
||||
|
||||
const themePack =
|
||||
customWorldProfile.themePack ?? buildThemePackFromWorldProfile(customWorldProfile);
|
||||
const storyGraph =
|
||||
customWorldProfile.storyGraph
|
||||
?? buildFallbackWorldStoryGraph(customWorldProfile, themePack);
|
||||
|
||||
return normalizeActorNarrativeProfile(
|
||||
role.narrativeProfile,
|
||||
buildFallbackActorNarrativeProfile(role, storyGraph, themePack),
|
||||
);
|
||||
}
|
||||
|
||||
function resolveActiveThreadIds(params: {
|
||||
customWorldProfile: GameState['customWorldProfile'];
|
||||
relatedNpcNarrativeProfile: RuntimeItemGenerationContext['relatedNpcNarrativeProfile'];
|
||||
storyEngineMemory?: GameState['storyEngineMemory'] | QuestGenerationContext['activeThreadIds'];
|
||||
}) {
|
||||
const threadSource = params.storyEngineMemory;
|
||||
if (Array.isArray(threadSource) && threadSource.length > 0) {
|
||||
return threadSource.slice(0, 4);
|
||||
}
|
||||
|
||||
if (
|
||||
threadSource &&
|
||||
!Array.isArray(threadSource) &&
|
||||
threadSource.activeThreadIds?.length
|
||||
) {
|
||||
return threadSource.activeThreadIds.slice(0, 4);
|
||||
}
|
||||
|
||||
if (params.relatedNpcNarrativeProfile?.relatedThreadIds.length) {
|
||||
return params.relatedNpcNarrativeProfile.relatedThreadIds.slice(0, 4);
|
||||
}
|
||||
|
||||
if (!params.customWorldProfile) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const themePack =
|
||||
params.customWorldProfile.themePack
|
||||
?? buildThemePackFromWorldProfile(params.customWorldProfile);
|
||||
const storyGraph =
|
||||
params.customWorldProfile.storyGraph
|
||||
?? buildFallbackWorldStoryGraph(params.customWorldProfile, themePack);
|
||||
|
||||
return storyGraph.visibleThreads.slice(0, 3).map((thread) => thread.id);
|
||||
}
|
||||
|
||||
function buildBaseRuntimeContext(params: {
|
||||
worldType: GameState['worldType'];
|
||||
customWorldProfile: GameState['customWorldProfile'];
|
||||
scene: Pick<ScenePresetInfo, 'id' | 'name' | 'description' | 'treasureHints'> | null;
|
||||
encounter: GameState['currentEncounter'];
|
||||
relatedNpcState: GameState['npcStates'][string] | null;
|
||||
storyEngineMemory?: GameState['storyEngineMemory'] | QuestGenerationContext['activeThreadIds'];
|
||||
storyHistory: GameState['storyHistory'];
|
||||
playerCharacterId: string;
|
||||
playerBuildTags: string[];
|
||||
@@ -96,6 +171,7 @@ function buildBaseRuntimeContext(params: {
|
||||
scene,
|
||||
encounter,
|
||||
relatedNpcState,
|
||||
storyEngineMemory,
|
||||
storyHistory,
|
||||
playerCharacterId,
|
||||
playerBuildTags,
|
||||
@@ -103,6 +179,15 @@ function buildBaseRuntimeContext(params: {
|
||||
generationChannel,
|
||||
} = params;
|
||||
const recentStoryLines = buildRecentStoryLines(storyHistory);
|
||||
const relatedNpcNarrativeProfile = resolveRelatedNpcNarrativeProfile({
|
||||
customWorldProfile,
|
||||
encounter,
|
||||
});
|
||||
const activeThreadIds = resolveActiveThreadIds({
|
||||
customWorldProfile,
|
||||
relatedNpcNarrativeProfile,
|
||||
storyEngineMemory,
|
||||
});
|
||||
|
||||
return {
|
||||
worldType,
|
||||
@@ -117,9 +202,11 @@ function buildBaseRuntimeContext(params: {
|
||||
encounterNpcName: encounter?.npcName ?? null,
|
||||
encounterContextText: encounter?.context ?? null,
|
||||
relatedNpcState,
|
||||
relatedNpcNarrativeProfile,
|
||||
relatedScene: scene,
|
||||
recentStorySummary: buildRecentStorySummary(recentStoryLines),
|
||||
recentActions: recentStoryLines,
|
||||
activeThreadIds,
|
||||
playerCharacterId,
|
||||
playerBuildTags,
|
||||
playerBuildGaps: derivePlayerBuildGaps(playerBuildTags),
|
||||
@@ -146,6 +233,7 @@ export function buildLooseRuntimeItemGenerationContext(params: {
|
||||
scene: params.scene ?? null,
|
||||
encounter: params.encounter ?? null,
|
||||
relatedNpcState: params.relatedNpcState ?? null,
|
||||
storyEngineMemory: params.customWorldProfile?.storyGraph?.visibleThreads.map((thread) => thread.id) ?? [],
|
||||
storyHistory: params.storyHistory ?? [],
|
||||
playerCharacterId: params.playerCharacterId ?? 'runtime-loose-player',
|
||||
playerBuildTags: params.playerBuildTags ?? [],
|
||||
@@ -180,6 +268,7 @@ export function buildRuntimeItemGenerationContext(params: {
|
||||
scene,
|
||||
encounter,
|
||||
relatedNpcState,
|
||||
storyEngineMemory: state.storyEngineMemory,
|
||||
storyHistory: state.storyHistory,
|
||||
playerCharacterId: state.playerCharacter?.id ?? 'unknown-player',
|
||||
playerBuildTags,
|
||||
@@ -243,6 +332,7 @@ export function buildQuestRuntimeItemGenerationContext(params: {
|
||||
recruited: false,
|
||||
revealedFacts: [],
|
||||
},
|
||||
storyEngineMemory: context.activeThreadIds,
|
||||
storyHistory: context.recentStoryMoments ?? [],
|
||||
playerCharacterId: context.playerCharacter?.id ?? 'quest-player',
|
||||
playerBuildTags,
|
||||
|
||||
Reference in New Issue
Block a user