This commit is contained in:
195
src/data/scenePresets.test.ts
Normal file
195
src/data/scenePresets.test.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user