196 lines
6.7 KiB
TypeScript
196 lines
6.7 KiB
TypeScript
import { afterEach, describe, expect, it } from 'vitest';
|
|
|
|
import { buildExpandedCustomWorldProfile } from '../services/customWorldBuilder';
|
|
import { WorldType } from '../types';
|
|
import { setRuntimeCustomWorldProfile } from './customWorldRuntime';
|
|
import { buildEncounterFromSceneNpc, getScenePresetsByWorld } from './scenePresets';
|
|
|
|
function createPlayableNpc(index: number) {
|
|
return {
|
|
name: `可扮演角色${index + 1}`,
|
|
title: `可扮演头衔${index + 1}`,
|
|
role: `可扮演身份${index + 1}`,
|
|
description: `可扮演角色描述${index + 1}`,
|
|
backstory: `可扮演角色背景${index + 1}`,
|
|
personality: `可扮演角色性格${index + 1}`,
|
|
motivation: `可扮演角色动机${index + 1}`,
|
|
combatStyle: `可扮演角色战斗风格${index + 1}`,
|
|
initialAffinity: 18,
|
|
relationshipHooks: [`切入口${index + 1}`],
|
|
tags: [`标签${index + 1}`],
|
|
backstoryReveal: {
|
|
publicSummary: `公开背景${index + 1}`,
|
|
chapters: [
|
|
{
|
|
id: `surface-${index + 1}`,
|
|
title: '表层来意',
|
|
affinityRequired: 10,
|
|
teaser: `提示${index + 1}-1`,
|
|
content: `内容${index + 1}-1`,
|
|
contextSnippet: `摘要${index + 1}-1`,
|
|
},
|
|
{
|
|
id: `scar-${index + 1}`,
|
|
title: '旧事裂痕',
|
|
affinityRequired: 30,
|
|
teaser: `提示${index + 1}-2`,
|
|
content: `内容${index + 1}-2`,
|
|
contextSnippet: `摘要${index + 1}-2`,
|
|
},
|
|
{
|
|
id: `hidden-${index + 1}`,
|
|
title: '隐藏执念',
|
|
affinityRequired: 55,
|
|
teaser: `提示${index + 1}-3`,
|
|
content: `内容${index + 1}-3`,
|
|
contextSnippet: `摘要${index + 1}-3`,
|
|
},
|
|
{
|
|
id: `final-${index + 1}`,
|
|
title: '最终底牌',
|
|
affinityRequired: 80,
|
|
teaser: `提示${index + 1}-4`,
|
|
content: `内容${index + 1}-4`,
|
|
contextSnippet: `摘要${index + 1}-4`,
|
|
},
|
|
],
|
|
},
|
|
skills: [
|
|
{ name: `技能${index + 1}-1`, summary: '技能摘要1', style: '起手压制' },
|
|
{ name: `技能${index + 1}-2`, summary: '技能摘要2', style: '机动周旋' },
|
|
{ name: `技能${index + 1}-3`, summary: '技能摘要3', style: '爆发终结' },
|
|
],
|
|
initialItems: [
|
|
{
|
|
name: `物品${index + 1}-1`,
|
|
category: '武器',
|
|
quantity: 1,
|
|
rarity: 'rare',
|
|
description: '物品描述1',
|
|
tags: ['物品标签1'],
|
|
},
|
|
{
|
|
name: `物品${index + 1}-2`,
|
|
category: '消耗品',
|
|
quantity: 2,
|
|
rarity: 'uncommon',
|
|
description: '物品描述2',
|
|
tags: ['物品标签2'],
|
|
},
|
|
{
|
|
name: `物品${index + 1}-3`,
|
|
category: '专属物品',
|
|
quantity: 1,
|
|
rarity: 'rare',
|
|
description: '物品描述3',
|
|
tags: ['物品标签3'],
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
describe('scenePresets custom world npc mapping', () => {
|
|
afterEach(() => {
|
|
setRuntimeCustomWorldProfile(null);
|
|
});
|
|
|
|
it('preserves custom world npc dossier fields into scene npcs and encounters', () => {
|
|
const profile = buildExpandedCustomWorldProfile(
|
|
{
|
|
name: '雾潮世界',
|
|
subtitle: '潮雾未散',
|
|
summary: '一座围绕码头、断桥和旧潮路展开的自定义世界。',
|
|
tone: '克制、潮湿、危险',
|
|
playerGoal: '查清雾潮里失踪的人和桥下的旧案。',
|
|
templateWorldType: 'WUXIA',
|
|
playableNpcs: Array.from({ length: 5 }, (_, index) =>
|
|
createPlayableNpc(index),
|
|
),
|
|
storyNpcs: [
|
|
{
|
|
...createPlayableNpc(10),
|
|
name: '沈雾',
|
|
title: '潮路领航人',
|
|
role: '码头向导',
|
|
description: '熟悉潮路和暗栈的旧向导。',
|
|
backstory: '少年时曾在断桥坠潮夜里失去整队同伴。',
|
|
personality: '谨慎冷静,先观察再表态。',
|
|
motivation: '想把雾潮深处那条失踪航线重新找出来。',
|
|
combatStyle: '短刀试探后再借地形逼近。',
|
|
relationshipHooks: ['潮路', '断桥旧案'],
|
|
tags: ['码头', '旧潮路'],
|
|
imageSrc: '/custom/npcs/shenwu.png',
|
|
},
|
|
{
|
|
...createPlayableNpc(11),
|
|
name: '陆沉',
|
|
title: '断桥守更',
|
|
role: '守桥人',
|
|
description: '夜里守着断桥口的旧灯火。',
|
|
},
|
|
{
|
|
...createPlayableNpc(12),
|
|
name: '顾潮',
|
|
title: '潮册记录员',
|
|
role: '记录员',
|
|
description: '在潮账房里整理各路失踪名单。',
|
|
},
|
|
],
|
|
landmarks: [
|
|
{
|
|
name: '雾潮码头',
|
|
description: '旧船桩和潮雾把视线切成断续的几段。',
|
|
sceneNpcNames: ['沈雾', '陆沉', '顾潮'],
|
|
connections: [
|
|
{
|
|
targetLandmarkName: '断桥旧道',
|
|
relativePosition: 'north',
|
|
summary: '顺着潮路向北可抵断桥。',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: '断桥旧道',
|
|
description: '半塌的桥面上还挂着旧索和残旗。',
|
|
sceneNpcNames: ['沈雾', '陆沉', '顾潮'],
|
|
connections: [
|
|
{
|
|
targetLandmarkName: '雾潮码头',
|
|
relativePosition: 'south',
|
|
summary: '沿旧潮路南返能回码头。',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
'玩家想要一个围绕雾潮码头与断桥旧案展开的世界。',
|
|
);
|
|
|
|
setRuntimeCustomWorldProfile(profile);
|
|
|
|
const scene = getScenePresetsByWorld(WorldType.CUSTOM).find(
|
|
(entry) => entry.name === '雾潮码头',
|
|
);
|
|
const npc = scene?.npcs?.find((entry) => entry.name === '沈雾');
|
|
|
|
expect(scene).toBeTruthy();
|
|
expect(npc).toBeTruthy();
|
|
expect(npc?.characterId).toBe(npc?.id);
|
|
expect(npc?.title).toBe('潮路领航人');
|
|
expect(npc?.backstory).toContain('断桥坠潮夜');
|
|
expect(npc?.personality).toContain('谨慎冷静');
|
|
expect(npc?.motivation).toContain('失踪航线');
|
|
expect(npc?.skills).toHaveLength(3);
|
|
expect(npc?.initialItems).toHaveLength(3);
|
|
expect(npc?.avatar).toBe('/custom/npcs/shenwu.png');
|
|
|
|
const encounter = buildEncounterFromSceneNpc(npc!);
|
|
|
|
expect(encounter.title).toBe('潮路领航人');
|
|
expect(encounter.backstoryReveal?.publicSummary).toBe('公开背景11');
|
|
expect(encounter.skills?.[0]?.name).toBe('技能11-1');
|
|
expect(encounter.initialItems?.[0]?.name).toBe('物品11-1');
|
|
expect(encounter.imageSrc).toBe('/custom/npcs/shenwu.png');
|
|
});
|
|
});
|