80 lines
2.1 KiB
TypeScript
80 lines
2.1 KiB
TypeScript
import type {
|
|
CampaignPack,
|
|
CustomWorldProfile,
|
|
ScenarioPack,
|
|
} from '../../types';
|
|
import { buildActPlan } from './actPlanner';
|
|
import { resolveCampaignState } from './campaignDirector';
|
|
|
|
function slugify(value: string) {
|
|
const ascii = value
|
|
.trim()
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9\u4e00-\u9fa5]+/giu, '-')
|
|
.replace(/^-+|-+$/g, '');
|
|
return ascii || 'campaign';
|
|
}
|
|
|
|
export function buildCampaignPack(params: {
|
|
scenarioPackId: string;
|
|
profile: CustomWorldProfile;
|
|
authoringStyle?: string;
|
|
}) {
|
|
const { scenarioPackId, profile, authoringStyle = 'classic_story_rpg' } = params;
|
|
const campaignStateSeed = resolveCampaignState({
|
|
state: {
|
|
customWorldProfile: profile,
|
|
chapterState: null,
|
|
storyEngineMemory: {
|
|
activeThreadIds:
|
|
profile.storyGraph?.visibleThreads.slice(0, 3).map((thread) => thread.id) ?? [],
|
|
},
|
|
} as never,
|
|
});
|
|
const actTemplates = buildActPlan({
|
|
state: {
|
|
customWorldProfile: profile,
|
|
storyEngineMemory: {
|
|
activeThreadIds:
|
|
profile.storyGraph?.visibleThreads.slice(0, 3).map((thread) => thread.id) ?? [],
|
|
},
|
|
} as never,
|
|
});
|
|
|
|
return {
|
|
id: profile.campaignPackId ?? `campaign-pack:${slugify(profile.name)}`,
|
|
scenarioPackId,
|
|
title: `${profile.name} 主战役`,
|
|
authoringStyle,
|
|
campaignStateSeed,
|
|
actTemplates,
|
|
requiredCompanionIds: profile.playableNpcs.slice(0, 2).map((npc) => npc.id),
|
|
} satisfies CampaignPack;
|
|
}
|
|
|
|
export function compileCampaignFromWorldProfile(params: {
|
|
profile: CustomWorldProfile;
|
|
}) {
|
|
const scenarioPack: ScenarioPack = {
|
|
id: params.profile.scenarioPackId ?? `scenario-pack:${slugify(params.profile.name)}`,
|
|
title: `${params.profile.name} Scenario Pack`,
|
|
version: '0.1.0',
|
|
worldPackIds: [params.profile.id],
|
|
campaignIds: [],
|
|
sharedConstraintPackIds: [],
|
|
};
|
|
const campaignPack = buildCampaignPack({
|
|
scenarioPackId: scenarioPack.id,
|
|
profile: params.profile,
|
|
});
|
|
|
|
return {
|
|
scenarioPack: {
|
|
...scenarioPack,
|
|
campaignIds: [campaignPack.id],
|
|
sharedConstraintPackIds: [campaignPack.id],
|
|
},
|
|
campaignPack,
|
|
};
|
|
}
|