Split custom world generation into staged lightweight batches
Some checks failed
CI / verify (push) Has been cancelled
Some checks failed
CI / verify (push) Has been cancelled
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
buildItemAttributeResonance,
|
||||
} from '../data/attributeProfileGenerator';
|
||||
import { mergeCustomWorldPlayableNpcTags } from '../data/customWorldBuildTags';
|
||||
import { normalizeCustomWorldLandmarks } from '../data/customWorldSceneGraph';
|
||||
import { CustomWorldProfile, WorldType } from '../types';
|
||||
import { normalizeCustomWorldProfile } from './customWorld';
|
||||
|
||||
@@ -95,37 +96,91 @@ export function buildExpandedCustomWorldProfile(
|
||||
): CustomWorldProfile {
|
||||
const profile = normalizeCustomWorldProfile(raw, settingText);
|
||||
const attributeSchema = profile.attributeSchema;
|
||||
const playableNpcs = dedupeByName(profile.playableNpcs)
|
||||
.slice(0, PLAYABLE_TEMPLATE_CHARACTER_IDS.length)
|
||||
.map((npc, index) => {
|
||||
const templateCharacterId =
|
||||
npc.templateCharacterId ?? getPlayableTemplateCharacterId(index);
|
||||
return {
|
||||
...npc,
|
||||
id: createEntryId('playable-npc', npc.name, index),
|
||||
templateCharacterId,
|
||||
tags: mergeCustomWorldPlayableNpcTags(profile, npc, {
|
||||
templateCharacterId,
|
||||
maxCount: 5,
|
||||
}),
|
||||
attributeProfile:
|
||||
npc.attributeProfile ??
|
||||
buildCustomWorldPlayableNpcAttributeProfile(npc, attributeSchema),
|
||||
};
|
||||
});
|
||||
const storyNpcs = dedupeByName(profile.storyNpcs).map((npc, index) => ({
|
||||
...npc,
|
||||
id: createEntryId('story-npc', npc.name, index),
|
||||
description: clampText(npc.description, 72),
|
||||
motivation: clampText(npc.motivation, 72),
|
||||
relationshipHooks: normalizeHooks(npc.relationshipHooks),
|
||||
attributeProfile:
|
||||
npc.attributeProfile ??
|
||||
buildCustomWorldStoryNpcAttributeProfile(npc, attributeSchema),
|
||||
}));
|
||||
const storyNpcIdByReference = new Map<string, string>();
|
||||
storyNpcs.forEach((npc) => {
|
||||
storyNpcIdByReference.set(npc.id, npc.id);
|
||||
storyNpcIdByReference.set(npc.name, npc.id);
|
||||
});
|
||||
profile.storyNpcs.forEach((npc) => {
|
||||
const nextNpc = storyNpcs.find((entry) => entry.name === npc.name);
|
||||
if (!nextNpc) {
|
||||
return;
|
||||
}
|
||||
storyNpcIdByReference.set(npc.id, nextNpc.id);
|
||||
storyNpcIdByReference.set(npc.name, nextNpc.id);
|
||||
});
|
||||
const landmarkDrafts = dedupeByName(profile.landmarks).map((landmark, index) => ({
|
||||
...landmark,
|
||||
id: createEntryId('landmark', landmark.name, index),
|
||||
description: clampText(landmark.description, 96),
|
||||
dangerLevel:
|
||||
landmark.dangerLevel ||
|
||||
(profile.templateWorldType === WorldType.XIANXIA ? 'high' : 'medium'),
|
||||
}));
|
||||
const landmarkIdByReference = new Map<string, string>();
|
||||
landmarkDrafts.forEach((landmark) => {
|
||||
landmarkIdByReference.set(landmark.id, landmark.id);
|
||||
landmarkIdByReference.set(landmark.name, landmark.id);
|
||||
});
|
||||
profile.landmarks.forEach((landmark) => {
|
||||
const nextLandmark = landmarkDrafts.find(
|
||||
(entry) => entry.name === landmark.name,
|
||||
);
|
||||
if (!nextLandmark) {
|
||||
return;
|
||||
}
|
||||
landmarkIdByReference.set(landmark.id, nextLandmark.id);
|
||||
landmarkIdByReference.set(landmark.name, nextLandmark.id);
|
||||
});
|
||||
const landmarks = normalizeCustomWorldLandmarks({
|
||||
landmarks: landmarkDrafts.map((landmark) => ({
|
||||
...landmark,
|
||||
sceneNpcIds: landmark.sceneNpcIds.map(
|
||||
(npcId) => storyNpcIdByReference.get(npcId) ?? npcId,
|
||||
),
|
||||
connections: landmark.connections.map((connection) => ({
|
||||
targetLandmarkId:
|
||||
landmarkIdByReference.get(connection.targetLandmarkId) ??
|
||||
connection.targetLandmarkId,
|
||||
relativePosition: connection.relativePosition,
|
||||
summary: connection.summary,
|
||||
})),
|
||||
})),
|
||||
storyNpcs,
|
||||
});
|
||||
|
||||
return {
|
||||
...profile,
|
||||
playableNpcs: dedupeByName(profile.playableNpcs)
|
||||
.slice(0, PLAYABLE_TEMPLATE_CHARACTER_IDS.length)
|
||||
.map((npc, index) => {
|
||||
const templateCharacterId =
|
||||
npc.templateCharacterId ?? getPlayableTemplateCharacterId(index);
|
||||
return {
|
||||
...npc,
|
||||
id: createEntryId('playable-npc', npc.name, index),
|
||||
templateCharacterId,
|
||||
tags: mergeCustomWorldPlayableNpcTags(profile, npc, {
|
||||
templateCharacterId,
|
||||
maxCount: 5,
|
||||
}),
|
||||
attributeProfile:
|
||||
npc.attributeProfile ??
|
||||
buildCustomWorldPlayableNpcAttributeProfile(npc, attributeSchema),
|
||||
};
|
||||
}),
|
||||
storyNpcs: dedupeByName(profile.storyNpcs).map((npc, index) => ({
|
||||
...npc,
|
||||
id: createEntryId('story-npc', npc.name, index),
|
||||
description: clampText(npc.description, 72),
|
||||
motivation: clampText(npc.motivation, 72),
|
||||
relationshipHooks: normalizeHooks(npc.relationshipHooks),
|
||||
attributeProfile:
|
||||
npc.attributeProfile ??
|
||||
buildCustomWorldStoryNpcAttributeProfile(npc, attributeSchema),
|
||||
})),
|
||||
playableNpcs,
|
||||
storyNpcs,
|
||||
items: dedupeByName(profile.items).map((item, index) => ({
|
||||
...item,
|
||||
id: createEntryId('item', item.name, index),
|
||||
@@ -134,13 +189,6 @@ export function buildExpandedCustomWorldProfile(
|
||||
attributeResonance:
|
||||
item.attributeResonance ?? buildItemAttributeResonance(item),
|
||||
})),
|
||||
landmarks: dedupeByName(profile.landmarks).map((landmark, index) => ({
|
||||
...landmark,
|
||||
id: createEntryId('landmark', landmark.name, index),
|
||||
description: clampText(landmark.description, 96),
|
||||
dangerLevel:
|
||||
landmark.dangerLevel ||
|
||||
(profile.templateWorldType === WorldType.XIANXIA ? 'high' : 'medium'),
|
||||
})),
|
||||
landmarks,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user