1
This commit is contained in:
@@ -15,6 +15,9 @@ type ParsedRole = {
|
||||
title: string;
|
||||
role: string;
|
||||
description: string;
|
||||
visualDescription: string;
|
||||
actionDescription: string;
|
||||
sceneVisualDescription: string;
|
||||
backstory: string;
|
||||
personality: string;
|
||||
motivation: string;
|
||||
@@ -34,6 +37,7 @@ type ParsedLandmark = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
visualDescription: string;
|
||||
dangerLevel: string;
|
||||
sceneNpcIds: string[];
|
||||
connections: ParsedLandmarkConnection[];
|
||||
@@ -220,6 +224,9 @@ function normalizeRole(value: unknown): ParsedRole | null {
|
||||
title: title || role || '角色',
|
||||
role,
|
||||
description: toText(record.description),
|
||||
visualDescription: toText(record.visualDescription),
|
||||
actionDescription: toText(record.actionDescription),
|
||||
sceneVisualDescription: toText(record.sceneVisualDescription),
|
||||
backstory: toText(record.backstory),
|
||||
personality: toText(record.personality),
|
||||
motivation: toText(record.motivation),
|
||||
@@ -275,6 +282,7 @@ function normalizeLandmark(value: unknown): ParsedLandmark | null {
|
||||
id,
|
||||
name,
|
||||
description: toText(record.description),
|
||||
visualDescription: toText(record.visualDescription),
|
||||
dangerLevel: toText(record.dangerLevel, 'medium'),
|
||||
sceneNpcIds: toStringArray(record.sceneNpcIds, 12),
|
||||
connections,
|
||||
@@ -326,7 +334,11 @@ function buildRoleReferenceText(roles: ParsedRole[], emptyText: string) {
|
||||
role.backstory || '未写'
|
||||
} / 性格:${role.personality || '未写'} / 动机:${
|
||||
role.motivation || '未写'
|
||||
} / 标签:${role.tags.join('、') || '暂无'}`,
|
||||
} / 形象:${role.visualDescription || '未写'} / 动作表现:${
|
||||
role.actionDescription || '未写'
|
||||
} / 场景画面:${role.sceneVisualDescription || '未写'} / 标签:${
|
||||
role.tags.join('、') || '暂无'
|
||||
}`,
|
||||
)
|
||||
.join('\n');
|
||||
}
|
||||
@@ -361,7 +373,9 @@ function buildLandmarkReferenceText(profile: ParsedProfile) {
|
||||
|
||||
return `${index + 1}. ${landmark.name} / 危险度:${
|
||||
landmark.dangerLevel || 'medium'
|
||||
} / 描述:${landmark.description || '未写'} / 场景角色:${
|
||||
} / 描述:${landmark.description || '未写'} / 画面:${
|
||||
landmark.visualDescription || '未写'
|
||||
} / 场景角色:${
|
||||
sceneNpcNames || '暂无'
|
||||
} / 连接:${connectionNames || '暂无'}`;
|
||||
})
|
||||
@@ -437,6 +451,24 @@ function buildFallbackRoleDraft(
|
||||
: `长期活跃于当前世界暗面,能补足场景视角的关键角色。`,
|
||||
60,
|
||||
),
|
||||
visualDescription: clampText(
|
||||
kind === 'playable'
|
||||
? `他保留着适合长期同行的鲜明外形识别点,服装、装备和体态都能直接看出其职责、出身和会如何与玩家并肩行动。`
|
||||
: `他身上带着与当前局势强绑定的外观痕迹,衣着、器具和整体气质会暴露其长期活动环境与所站的位置。`,
|
||||
96,
|
||||
),
|
||||
actionDescription: clampText(
|
||||
kind === 'playable'
|
||||
? '动作表现偏向协作推进与稳定压制,起手克制,发力明确,收招干净。'
|
||||
: '动作表现偏向试探、牵制与借势,节奏谨慎,但关键时刻会突然加重攻击或位移。',
|
||||
72,
|
||||
),
|
||||
sceneVisualDescription: clampText(
|
||||
profile.landmarks[0]?.description
|
||||
? `他的主要活动空间与${profile.landmarks[0].name}相连,场景里能看到${profile.landmarks[0].description}`
|
||||
: `他的主要活动空间与${profile.name}当前冲突线直接相关,环境里会留下势力痕迹、旧装置和仍在运转的局势线索。`,
|
||||
96,
|
||||
),
|
||||
backstory: clampText(
|
||||
`他与${profile.name}当前正在扩张的冲突链紧密相连,知道一些还未公开的内情。`,
|
||||
80,
|
||||
@@ -535,6 +567,10 @@ function buildFallbackLandmarkDraft(profile: ParsedProfile) {
|
||||
`承接${profile.name}当前主冲突的一处关键新场景,适合继续向外扩张世界关系网。`,
|
||||
72,
|
||||
),
|
||||
visualDescription: clampText(
|
||||
`这里延续${profile.name}当前主冲突的视觉气质,能看到明确的空间层次、可站立地面、核心建筑或地貌,以及仍在运转的局势痕迹。`,
|
||||
88,
|
||||
),
|
||||
dangerLevel: 'medium',
|
||||
sceneNpcNames,
|
||||
connections: targetLandmarkNames.map((targetLandmarkName, index) => ({
|
||||
@@ -560,6 +596,9 @@ function buildPlayablePrompt(profile: ParsedProfile) {
|
||||
'- 必须与当前世界设定、已有可扮演角色、已有场景角色、已有场景形成互补,不要重复定位。',
|
||||
'- 必须保留明确的协作价值、成长空间和入队理由。',
|
||||
'- 不要生成泛用模板角色,必须让角色与当前世界的具体势力、地点、冲突或禁忌发生绑定。',
|
||||
'- visualDescription 只写与角色设定相关的外形、服装、材质、武器、体态、色彩和识别特征,禁止写角色以外的周边环境等与角色不想管的设定。',
|
||||
'- actionDescription 只写这个角色的动作表现与战斗气质,不要写镜头切换或参数。',
|
||||
'- sceneVisualDescription 只写该角色首次登场或主要活动区域的场景画面感,不要写“提示词”字样。',
|
||||
'- 只返回 JSON,不要输出解释或 Markdown。',
|
||||
'JSON 结构:',
|
||||
'{',
|
||||
@@ -568,6 +607,9 @@ function buildPlayablePrompt(profile: ParsedProfile) {
|
||||
' "title": "称号",',
|
||||
' "role": "身份",',
|
||||
' "description": "一句到两句定位描述",',
|
||||
' "visualDescription": "角色形象描述",',
|
||||
' "actionDescription": "动作表现描述",',
|
||||
' "sceneVisualDescription": "角色关联场景画面描述",',
|
||||
' "backstory": "背景经历",',
|
||||
' "personality": "性格特点",',
|
||||
' "motivation": "当前动机",',
|
||||
@@ -608,6 +650,9 @@ function buildStoryPrompt(profile: ParsedProfile) {
|
||||
'- 必须与当前世界设定、已有可扮演角色、已有场景角色、已有场景形成互补,不要重复定位。',
|
||||
'- 必须像能直接进入游戏的场景角色,而不是抽象设定条目。',
|
||||
'- 角色应与具体场景、关系链或局势变化发生绑定。',
|
||||
'- visualDescription 只写与角色设定匹配的外形、服装、材质、武器、体态、色彩和识别特征,不要写“提示词”、镜头参数或构图规则。',
|
||||
'- actionDescription 只写这个角色的动作表现与战斗气质,不要写镜头切换或参数。',
|
||||
'- sceneVisualDescription 只写该角色首次登场或主要活动区域的场景画面感,不要写“提示词”字样。',
|
||||
'- 只返回 JSON,不要输出解释或 Markdown。',
|
||||
'JSON 结构:',
|
||||
'{',
|
||||
@@ -616,6 +661,9 @@ function buildStoryPrompt(profile: ParsedProfile) {
|
||||
' "title": "称号",',
|
||||
' "role": "身份",',
|
||||
' "description": "一句到两句定位描述",',
|
||||
' "visualDescription": "角色形象描述",',
|
||||
' "actionDescription": "动作表现描述",',
|
||||
' "sceneVisualDescription": "角色关联场景画面描述",',
|
||||
' "backstory": "背景经历",',
|
||||
' "personality": "性格特点",',
|
||||
' "motivation": "当前动机",',
|
||||
@@ -656,12 +704,14 @@ function buildLandmarkPrompt(profile: ParsedProfile) {
|
||||
'- 必须与当前世界设定、已有可扮演角色、已有场景角色、已有场景形成互补,不要重复。',
|
||||
'- 必须给出适合出现在这个新场景里的 sceneNpcNames,且只能从已有场景角色里选择至少 3 个名字。',
|
||||
'- 必须给出 connections,且 targetLandmarkName 只能引用已有场景名,不要连向自己。',
|
||||
'- visualDescription 只写这个场景的空间层次、地面、主体建筑或自然景观、氛围、色彩和可见装置,不要写“提示词”、镜头参数或构图规则。',
|
||||
'- 只返回 JSON,不要输出解释或 Markdown。',
|
||||
'JSON 结构:',
|
||||
'{',
|
||||
' "landmark": {',
|
||||
' "name": "场景名",',
|
||||
' "description": "场景描述",',
|
||||
' "visualDescription": "场景画面描述",',
|
||||
' "dangerLevel": "low|medium|high|extreme",',
|
||||
' "sceneNpcNames": ["场景角色1", "场景角色2", "场景角色3"],',
|
||||
' "connections": [',
|
||||
@@ -737,6 +787,21 @@ function sanitizeGeneratedRole(
|
||||
toText(record?.description, fallbackDraft.description),
|
||||
120,
|
||||
),
|
||||
visualDescription: clampText(
|
||||
toText(record?.visualDescription, fallbackDraft.visualDescription),
|
||||
180,
|
||||
),
|
||||
actionDescription: clampText(
|
||||
toText(record?.actionDescription, fallbackDraft.actionDescription),
|
||||
140,
|
||||
),
|
||||
sceneVisualDescription: clampText(
|
||||
toText(
|
||||
record?.sceneVisualDescription,
|
||||
fallbackDraft.sceneVisualDescription,
|
||||
),
|
||||
180,
|
||||
),
|
||||
backstory: clampText(toText(record?.backstory, fallbackDraft.backstory), 260),
|
||||
personality: clampText(
|
||||
toText(record?.personality, fallbackDraft.personality),
|
||||
@@ -962,6 +1027,10 @@ function sanitizeGeneratedLandmark(rawValue: unknown, profile: ParsedProfile) {
|
||||
toText(record?.description, fallbackDraft.description),
|
||||
140,
|
||||
),
|
||||
visualDescription: clampText(
|
||||
toText(record?.visualDescription, fallbackDraft.visualDescription),
|
||||
180,
|
||||
),
|
||||
dangerLevel: (() => {
|
||||
const level = toText(record?.dangerLevel, fallbackDraft.dangerLevel);
|
||||
return level === 'low' ||
|
||||
|
||||
Reference in New Issue
Block a user