Update tests for make-npc-talk sequences in RuntimeInteractionSystem

This commit is contained in:
2026-04-15 09:56:28 +02:00
parent ece9d8f280
commit db63dbb612

View File

@@ -589,25 +589,59 @@ describe("RuntimeInteractionSystem", () => {
]); ]);
}); });
it("dispatches start dialogue actions for authored interaction links", () => { it("dispatches make-npc-talk sequences for authored interaction links", () => {
const runtimeScene = createRuntimeSceneFixture(); const runtimeScene = createRuntimeSceneFixture();
runtimeScene.dialogues.dialogues["dialogue-console"] = { runtimeScene.entities.npcs = [
id: "dialogue-console", {
title: "Console", ...createNpcEntity({
lines: [ id: "entity-npc-console",
{ dialogues: [
id: "dialogue-line-1", {
speakerName: "System", id: "dialogue-console",
text: "Access granted." title: "Console",
} lines: [
] {
}; id: "dialogue-line-1",
speakerName: "System",
text: "Access granted."
}
]
}
],
defaultDialogueId: "dialogue-console"
}),
active: true,
activeRoutineId: null,
activeRoutineTitle: null,
authoredPosition: { x: 0, y: 0, z: 0 },
authoredYawDegrees: 0,
visible: true,
position: { x: 0, y: 0, z: 0 },
yawDegrees: 0,
animationClipName: null,
animationLoop: undefined,
resolvedPath: null
}
];
runtimeScene.sequences.sequences["sequence-console-dialogue"] =
createProjectSequence({
id: "sequence-console-dialogue",
title: "Console Dialogue Sequence",
effects: [
{
stepClass: "impulse",
type: "makeNpcTalk",
npcEntityId: "entity-npc-console",
dialogueId: "dialogue-console"
}
]
});
runtimeScene.interactionLinks = [ runtimeScene.interactionLinks = [
createStartDialogueInteractionLink({ createRunSequenceInteractionLink({
id: "link-start-dialogue", id: "link-run-sequence-dialogue",
sourceEntityId: "entity-interactable-console", sourceEntityId: "entity-interactable-console",
trigger: "click", trigger: "click",
dialogueId: "dialogue-console" sequenceId: "sequence-console-dialogue"
}) })
]; ];
@@ -618,36 +652,60 @@ describe("RuntimeInteractionSystem", () => {
"entity-interactable-console", "entity-interactable-console",
runtimeScene, runtimeScene,
createDispatcher({ createDispatcher({
startDialogue: (dialogueId, source) => { startNpcDialogue: (npcEntityId, dialogueId, source) => {
dispatches.push(`${source?.linkId}:${dialogueId}`); dispatches.push(`${source?.linkId}:${npcEntityId}:${dialogueId}`);
} }
}) })
); );
expect(dispatches).toEqual(["link-start-dialogue:dialogue-console"]); expect(dispatches).toEqual([
"link-run-sequence-dialogue:entity-npc-console:dialogue-console"
]);
}); });
it("dispatches run-sequence links through authored impulse steps", () => { it("dispatches run-sequence links through authored impulse steps", () => {
const runtimeScene = createRuntimeSceneFixture(); const runtimeScene = createRuntimeSceneFixture();
runtimeScene.dialogues.dialogues["dialogue-sequence"] = { runtimeScene.entities.npcs = [
id: "dialogue-sequence", {
title: "Sequence Dialogue", ...createNpcEntity({
lines: [ id: "entity-npc-sequence",
{ dialogues: [
id: "dialogue-line-sequence-1", {
speakerName: "Console", id: "dialogue-sequence",
text: "Sequence started." title: "Sequence Dialogue",
} lines: [
] {
}; id: "dialogue-line-sequence-1",
speakerName: "Console",
text: "Sequence started."
}
]
}
],
defaultDialogueId: "dialogue-sequence"
}),
active: true,
activeRoutineId: null,
activeRoutineTitle: null,
authoredPosition: { x: 0, y: 0, z: 0 },
authoredYawDegrees: 0,
visible: true,
position: { x: 0, y: 0, z: 0 },
yawDegrees: 0,
animationClipName: null,
animationLoop: undefined,
resolvedPath: null
}
];
runtimeScene.sequences.sequences["sequence-console-dialogue"] = runtimeScene.sequences.sequences["sequence-console-dialogue"] =
createProjectSequence({ createProjectSequence({
id: "sequence-console-dialogue", id: "sequence-console-dialogue",
title: "Console Dialogue Sequence", title: "Console Dialogue Sequence",
steps: [ effects: [
{ {
stepClass: "impulse", stepClass: "impulse",
type: "startDialogue", type: "makeNpcTalk",
npcEntityId: "entity-npc-sequence",
dialogueId: "dialogue-sequence" dialogueId: "dialogue-sequence"
} }
] ]
@@ -668,34 +726,70 @@ describe("RuntimeInteractionSystem", () => {
"entity-interactable-console", "entity-interactable-console",
runtimeScene, runtimeScene,
createDispatcher({ createDispatcher({
startDialogue: (dialogueId, source) => { startNpcDialogue: (npcEntityId, dialogueId, source) => {
dispatches.push(`${source?.linkId}:${dialogueId}`); dispatches.push(`${source?.linkId}:${npcEntityId}:${dialogueId}`);
} }
}) })
); );
expect(dispatches).toEqual(["link-run-sequence-dialogue:dialogue-sequence"]); expect(dispatches).toEqual([
"link-run-sequence-dialogue:entity-npc-sequence:dialogue-sequence"
]);
}); });
it("treats interactable dialogue links as click interactions even when the stored trigger is non-click", () => { it("treats interactable sequence links as click interactions even when the stored trigger is non-click", () => {
const runtimeScene = createRuntimeSceneFixture(); const runtimeScene = createRuntimeSceneFixture();
runtimeScene.dialogues.dialogues["dialogue-console"] = { runtimeScene.entities.npcs = [
id: "dialogue-console", {
title: "Console", ...createNpcEntity({
lines: [ id: "entity-npc-console",
{ dialogues: [
id: "dialogue-line-console-1", {
speakerName: "System", id: "dialogue-console",
text: "Console online." title: "Console",
} lines: [
] {
}; id: "dialogue-line-console-1",
speakerName: "System",
text: "Console online."
}
]
}
],
defaultDialogueId: "dialogue-console"
}),
active: true,
activeRoutineId: null,
activeRoutineTitle: null,
authoredPosition: { x: 0, y: 0, z: 0 },
authoredYawDegrees: 0,
visible: true,
position: { x: 0, y: 0, z: 0 },
yawDegrees: 0,
animationClipName: null,
animationLoop: undefined,
resolvedPath: null
}
];
runtimeScene.sequences.sequences["sequence-console-dialogue"] =
createProjectSequence({
id: "sequence-console-dialogue",
title: "Console Dialogue Sequence",
effects: [
{
stepClass: "impulse",
type: "makeNpcTalk",
npcEntityId: "entity-npc-console",
dialogueId: "dialogue-console"
}
]
});
runtimeScene.interactionLinks = [ runtimeScene.interactionLinks = [
createStartDialogueInteractionLink({ createRunSequenceInteractionLink({
id: "link-start-dialogue-console", id: "link-run-sequence-console",
sourceEntityId: "entity-interactable-console", sourceEntityId: "entity-interactable-console",
trigger: "enter", trigger: "enter",
dialogueId: "dialogue-console" sequenceId: "sequence-console-dialogue"
}) })
]; ];
@@ -731,38 +825,72 @@ describe("RuntimeInteractionSystem", () => {
"entity-interactable-console", "entity-interactable-console",
runtimeScene, runtimeScene,
createDispatcher({ createDispatcher({
startDialogue: (dialogueId, source) => { startNpcDialogue: (npcEntityId, dialogueId, source) => {
dispatches.push( dispatches.push(
`${source?.kind}:${source?.sourceEntityId}:${source?.trigger}:${dialogueId}` `${source?.kind}:${source?.sourceEntityId}:${source?.trigger}:${npcEntityId}:${dialogueId}`
); );
} }
}) })
); );
expect(dispatches).toEqual([ expect(dispatches).toEqual([
"interactionLink:entity-interactable-console:enter:dialogue-console" "interactionLink:entity-interactable-console:enter:entity-npc-console:dialogue-console"
]); ]);
}); });
it("dispatches trigger-volume dialogue starts once on enter", () => { it("dispatches trigger-volume make-npc-talk sequences once on enter", () => {
const runtimeScene = createRuntimeSceneFixture(); const runtimeScene = createRuntimeSceneFixture();
runtimeScene.dialogues.dialogues["dialogue-threshold"] = { runtimeScene.entities.npcs = [
id: "dialogue-threshold", {
title: "Threshold", ...createNpcEntity({
lines: [ id: "entity-npc-threshold",
{ dialogues: [
id: "dialogue-line-threshold-1", {
speakerName: null, id: "dialogue-threshold",
text: "You crossed the threshold." title: "Threshold",
} lines: [
] {
}; id: "dialogue-line-threshold-1",
speakerName: null,
text: "You crossed the threshold."
}
]
}
],
defaultDialogueId: "dialogue-threshold"
}),
active: true,
activeRoutineId: null,
activeRoutineTitle: null,
authoredPosition: { x: 0, y: 0, z: 0 },
authoredYawDegrees: 0,
visible: true,
position: { x: 0, y: 0, z: 0 },
yawDegrees: 0,
animationClipName: null,
animationLoop: undefined,
resolvedPath: null
}
];
runtimeScene.sequences.sequences["sequence-trigger-dialogue"] =
createProjectSequence({
id: "sequence-trigger-dialogue",
title: "Trigger Dialogue Sequence",
effects: [
{
stepClass: "impulse",
type: "makeNpcTalk",
npcEntityId: "entity-npc-threshold",
dialogueId: "dialogue-threshold"
}
]
});
runtimeScene.interactionLinks = [ runtimeScene.interactionLinks = [
createStartDialogueInteractionLink({ createRunSequenceInteractionLink({
id: "link-trigger-dialogue", id: "link-trigger-sequence",
sourceEntityId: "entity-trigger-main", sourceEntityId: "entity-trigger-main",
trigger: "enter", trigger: "enter",
dialogueId: "dialogue-threshold" sequenceId: "sequence-trigger-dialogue"
}) })
]; ];
@@ -777,8 +905,8 @@ describe("RuntimeInteractionSystem", () => {
}, },
runtimeScene, runtimeScene,
createDispatcher({ createDispatcher({
startDialogue: (dialogueId, source) => { startNpcDialogue: (npcEntityId, dialogueId, source) => {
dispatches.push(`${source?.linkId}:${dialogueId}`); dispatches.push(`${source?.linkId}:${npcEntityId}:${dialogueId}`);
} }
}) })
); );
@@ -790,34 +918,70 @@ describe("RuntimeInteractionSystem", () => {
}, },
runtimeScene, runtimeScene,
createDispatcher({ createDispatcher({
startDialogue: (dialogueId, source) => { startNpcDialogue: (npcEntityId, dialogueId, source) => {
dispatches.push(`${source?.linkId}:${dialogueId}`); dispatches.push(`${source?.linkId}:${npcEntityId}:${dialogueId}`);
} }
}) })
); );
expect(dispatches).toEqual(["link-trigger-dialogue:dialogue-threshold"]); expect(dispatches).toEqual([
"link-trigger-sequence:entity-npc-threshold:dialogue-threshold"
]);
}); });
it("treats trigger-volume dialogue links authored with click as enter interactions", () => { it("treats trigger-volume sequence links authored with click as enter interactions", () => {
const runtimeScene = createRuntimeSceneFixture(); const runtimeScene = createRuntimeSceneFixture();
runtimeScene.dialogues.dialogues["dialogue-threshold"] = { runtimeScene.entities.npcs = [
id: "dialogue-threshold", {
title: "Threshold", ...createNpcEntity({
lines: [ id: "entity-npc-threshold",
{ dialogues: [
id: "dialogue-line-threshold-1", {
speakerName: null, id: "dialogue-threshold",
text: "Welcome." title: "Threshold",
} lines: [
] {
}; id: "dialogue-line-threshold-1",
speakerName: null,
text: "Welcome."
}
]
}
],
defaultDialogueId: "dialogue-threshold"
}),
active: true,
activeRoutineId: null,
activeRoutineTitle: null,
authoredPosition: { x: 0, y: 0, z: 0 },
authoredYawDegrees: 0,
visible: true,
position: { x: 0, y: 0, z: 0 },
yawDegrees: 0,
animationClipName: null,
animationLoop: undefined,
resolvedPath: null
}
];
runtimeScene.sequences.sequences["sequence-trigger-dialogue"] =
createProjectSequence({
id: "sequence-trigger-dialogue",
title: "Trigger Dialogue Sequence",
effects: [
{
stepClass: "impulse",
type: "makeNpcTalk",
npcEntityId: "entity-npc-threshold",
dialogueId: "dialogue-threshold"
}
]
});
runtimeScene.interactionLinks = [ runtimeScene.interactionLinks = [
createStartDialogueInteractionLink({ createRunSequenceInteractionLink({
id: "link-trigger-dialogue-click", id: "link-trigger-sequence-click",
sourceEntityId: "entity-trigger-main", sourceEntityId: "entity-trigger-main",
trigger: "click", trigger: "click",
dialogueId: "dialogue-threshold" sequenceId: "sequence-trigger-dialogue"
}) })
]; ];
@@ -832,16 +996,16 @@ describe("RuntimeInteractionSystem", () => {
}, },
runtimeScene, runtimeScene,
createDispatcher({ createDispatcher({
startDialogue: (dialogueId, source) => { startNpcDialogue: (npcEntityId, dialogueId, source) => {
dispatches.push( dispatches.push(
`${source?.kind}:${source?.sourceEntityId}:${source?.trigger}:${dialogueId}` `${source?.kind}:${source?.sourceEntityId}:${source?.trigger}:${npcEntityId}:${dialogueId}`
); );
} }
}) })
); );
expect(dispatches).toEqual([ expect(dispatches).toEqual([
"interactionLink:entity-trigger-main:click:dialogue-threshold" "interactionLink:entity-trigger-main:click:entity-npc-threshold:dialogue-threshold"
]); ]);
}); });
@@ -865,13 +1029,58 @@ describe("RuntimeInteractionSystem", () => {
} }
]; ];
runtimeScene.interactionLinks = [ runtimeScene.interactionLinks = [
createStartDialogueInteractionLink({ createRunSequenceInteractionLink({
id: "link-body-trigger-dialogue", id: "link-body-trigger-sequence",
sourceEntityId: "entity-trigger-chest-height", sourceEntityId: "entity-trigger-chest-height",
trigger: "enter", trigger: "enter",
dialogueId: "dialogue-threshold" sequenceId: "sequence-trigger-dialogue"
}) })
]; ];
runtimeScene.entities.npcs = [
{
...createNpcEntity({
id: "entity-npc-threshold",
dialogues: [
{
id: "dialogue-threshold",
title: "Threshold",
lines: [
{
id: "dialogue-line-threshold-1",
speakerName: null,
text: "Welcome."
}
]
}
],
defaultDialogueId: "dialogue-threshold"
}),
active: true,
activeRoutineId: null,
activeRoutineTitle: null,
authoredPosition: { x: 0, y: 0, z: 0 },
authoredYawDegrees: 0,
visible: true,
position: { x: 0, y: 0, z: 0 },
yawDegrees: 0,
animationClipName: null,
animationLoop: undefined,
resolvedPath: null
}
];
runtimeScene.sequences.sequences["sequence-trigger-dialogue"] =
createProjectSequence({
id: "sequence-trigger-dialogue",
title: "Trigger Dialogue Sequence",
effects: [
{
stepClass: "impulse",
type: "makeNpcTalk",
npcEntityId: "entity-npc-threshold",
dialogueId: "dialogue-threshold"
}
]
});
const dispatches: string[] = []; const dispatches: string[] = [];
const interactionSystem = new RuntimeInteractionSystem(); const interactionSystem = new RuntimeInteractionSystem();
@@ -891,13 +1100,15 @@ describe("RuntimeInteractionSystem", () => {
}, },
runtimeScene, runtimeScene,
createDispatcher({ createDispatcher({
startDialogue: (dialogueId, source) => { startNpcDialogue: (npcEntityId, dialogueId, source) => {
dispatches.push(`${source?.linkId}:${dialogueId}`); dispatches.push(`${source?.linkId}:${npcEntityId}:${dialogueId}`);
} }
}) })
); );
expect(dispatches).toEqual(["link-body-trigger-dialogue:dialogue-threshold"]); expect(dispatches).toEqual([
"link-body-trigger-sequence:entity-npc-threshold:dialogue-threshold"
]);
}); });
it("resolves direct NPC dialogue prompts and dispatches them through the shared start path", () => { it("resolves direct NPC dialogue prompts and dispatches them through the shared start path", () => {