1
This commit is contained in:
@@ -412,6 +412,15 @@ function buildDefaultSceneActBackgroundPrompt(params: {
|
||||
return `${sceneText}的${phaseText}画面,${roleText}与玩家隔着可站立空间形成对峙,环境里保留“${params.eventDescription}”的冲突痕迹与清晰氛围。`;
|
||||
}
|
||||
|
||||
function buildDefaultSceneTaskDescription(landmark: CustomWorldLandmark) {
|
||||
const sceneName = landmark.name.trim() || '当前场景';
|
||||
const sceneDescription = landmark.description.trim();
|
||||
if (!sceneDescription) {
|
||||
return `首次进入${sceneName}时,确认当前场景的核心异常、关键角色与下一步行动方向。`;
|
||||
}
|
||||
return `首次进入${sceneName}时,围绕${sceneDescription}确认核心任务、关键角色与下一步行动。`;
|
||||
}
|
||||
|
||||
function buildDefaultSceneChapterBlueprint(params: {
|
||||
landmark: CustomWorldLandmark;
|
||||
fallbackImageSrc?: string | null;
|
||||
@@ -432,7 +441,7 @@ function buildDefaultSceneChapterBlueprint(params: {
|
||||
sceneId: params.landmark.id,
|
||||
title: params.chapterTitle?.trim() || params.landmark.name.trim() || '场景章节',
|
||||
summary: params.chapterSummary?.trim() || params.landmark.description.trim(),
|
||||
sceneTaskDescription: params.landmark.description.trim(),
|
||||
sceneTaskDescription: buildDefaultSceneTaskDescription(params.landmark),
|
||||
linkedThreadIds: dedupeTextValues(params.linkedThreadIds ?? []),
|
||||
linkedLandmarkIds: dedupeTextValues([
|
||||
params.landmark.id,
|
||||
@@ -502,11 +511,12 @@ function sanitizeSceneChapterBlueprint(params: {
|
||||
availableSceneNpcIdSet.size > 0
|
||||
? candidateNpcIds.filter((npcId) => availableSceneNpcIdSet.has(npcId))
|
||||
: candidateNpcIds;
|
||||
// 中文注释:已有幕只信任本幕保存的槽位;只有缺少整份幕蓝图的旧草稿才从场景角色里兜底,避免配置第一幕时把角色串到其他幕。
|
||||
const resolvedEncounterNpcIds =
|
||||
encounterNpcIds.length > 0
|
||||
? encounterNpcIds
|
||||
: availableSceneNpcIds.length > 0
|
||||
? availableSceneNpcIds.slice(0, 1)
|
||||
: currentAct
|
||||
? []
|
||||
: fallbackAct.encounterNpcIds;
|
||||
const primaryNpcId = resolvedEncounterNpcIds[0] ?? '';
|
||||
const oppositeNpcId = currentAct?.oppositeNpcId?.trim() || primaryNpcId;
|
||||
@@ -554,6 +564,13 @@ function sanitizeSceneChapterBlueprint(params: {
|
||||
id: params.chapter?.id?.trim() || fallbackChapter.id,
|
||||
title: params.chapter?.title?.trim() || fallbackChapter.title,
|
||||
summary: params.chapter?.summary?.trim() || fallbackChapter.summary,
|
||||
sceneTaskDescription: (() => {
|
||||
const currentTask = params.chapter?.sceneTaskDescription?.trim() ?? '';
|
||||
const sceneDescription = params.landmark.description.trim();
|
||||
return currentTask && currentTask !== sceneDescription
|
||||
? currentTask
|
||||
: fallbackChapter.sceneTaskDescription;
|
||||
})(),
|
||||
linkedThreadIds: dedupeTextValues(params.chapter?.linkedThreadIds ?? []),
|
||||
linkedLandmarkIds: dedupeTextValues([
|
||||
params.landmark.id,
|
||||
@@ -1651,9 +1668,10 @@ function SceneActNpcSlotPickerModal({
|
||||
<ModalShell
|
||||
title={`配置角色:${actLabel} · ${slotLabel}`}
|
||||
onClose={onClose}
|
||||
panelClassName="sm:max-w-4xl"
|
||||
panelClassName="flex max-h-[88vh] flex-col sm:max-w-4xl"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div className="flex min-h-0 flex-1 flex-col">
|
||||
<div className="min-h-0 flex-1 space-y-4 overflow-y-auto pr-1">
|
||||
<div className="rounded-2xl border border-white/8 bg-black/20 px-4 py-4">
|
||||
<div className="text-[11px] font-bold tracking-[0.16em] text-zinc-300">
|
||||
当前角色
|
||||
@@ -1746,7 +1764,9 @@ function SceneActNpcSlotPickerModal({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col-reverse gap-3 sm:flex-row sm:justify-end">
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex shrink-0 flex-col gap-3 border-t border-white/8 bg-zinc-950/95 pt-4 sm:flex-row sm:justify-end">
|
||||
{selectedNpc ? (
|
||||
<ActionButton
|
||||
label="移除角色"
|
||||
@@ -1757,7 +1777,6 @@ function SceneActNpcSlotPickerModal({
|
||||
tone="rose"
|
||||
/>
|
||||
) : null}
|
||||
<ActionButton label="取消" onClick={onClose} />
|
||||
<ActionButton
|
||||
label="保存角色"
|
||||
onClick={() => {
|
||||
@@ -5752,7 +5771,7 @@ export function LandmarkEditor({
|
||||
setIsCloseConfirmOpen(true);
|
||||
};
|
||||
|
||||
const updateSceneActDraft = (
|
||||
const updateSceneChapterDraft = (
|
||||
updater: (chapter: SceneChapterBlueprint) => SceneChapterBlueprint,
|
||||
) => {
|
||||
setSceneChapterDraft((current) =>
|
||||
@@ -5780,7 +5799,7 @@ export function LandmarkEditor({
|
||||
index: number,
|
||||
updater: (act: SceneActBlueprint) => SceneActBlueprint,
|
||||
) => {
|
||||
updateSceneActDraft((current) => ({
|
||||
updateSceneChapterDraft((current) => ({
|
||||
...current,
|
||||
acts: current.acts.map((act, actIndex) =>
|
||||
actIndex === index ? updater(act) : act,
|
||||
@@ -5794,7 +5813,7 @@ export function LandmarkEditor({
|
||||
return;
|
||||
}
|
||||
|
||||
updateSceneActDraft((current) => {
|
||||
updateSceneChapterDraft((current) => {
|
||||
const nextActCount = current.acts.length + 1;
|
||||
return {
|
||||
...current,
|
||||
@@ -5821,14 +5840,14 @@ export function LandmarkEditor({
|
||||
return;
|
||||
}
|
||||
|
||||
updateSceneActDraft((current) => ({
|
||||
updateSceneChapterDraft((current) => ({
|
||||
...current,
|
||||
acts: current.acts.filter((_act, actIndex) => actIndex !== index),
|
||||
}));
|
||||
};
|
||||
|
||||
const moveSceneAct = (index: number, delta: number) => {
|
||||
updateSceneActDraft((current) => ({
|
||||
updateSceneChapterDraft((current) => ({
|
||||
...current,
|
||||
acts: moveArrayItem(current.acts, index, index + delta),
|
||||
}));
|
||||
@@ -5836,7 +5855,7 @@ export function LandmarkEditor({
|
||||
|
||||
const updateSceneActSharedBackground = (imageSrc?: string | null) => {
|
||||
const resolvedImageSrc = imageSrc?.trim() || compatibilityImageSrc || '';
|
||||
updateSceneActDraft((current) => ({
|
||||
updateSceneChapterDraft((current) => ({
|
||||
...current,
|
||||
acts: current.acts.map((act) => ({
|
||||
...act,
|
||||
@@ -6004,6 +6023,18 @@ export function LandmarkEditor({
|
||||
rows={5}
|
||||
/>
|
||||
</Field>
|
||||
<Field label="场景任务">
|
||||
<TextArea
|
||||
value={renderedSceneChapterDraft.sceneTaskDescription}
|
||||
onChange={(value) =>
|
||||
updateSceneChapterDraft((current) => ({
|
||||
...current,
|
||||
sceneTaskDescription: value,
|
||||
}))
|
||||
}
|
||||
rows={3}
|
||||
/>
|
||||
</Field>
|
||||
<SectionPanel
|
||||
title="多幕配置"
|
||||
actions={
|
||||
|
||||
Reference in New Issue
Block a user