Update tests for make-npc-talk sequences in RuntimeInteractionSystem
This commit is contained in:
@@ -589,9 +589,14 @@ 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 = [
|
||||||
|
{
|
||||||
|
...createNpcEntity({
|
||||||
|
id: "entity-npc-console",
|
||||||
|
dialogues: [
|
||||||
|
{
|
||||||
id: "dialogue-console",
|
id: "dialogue-console",
|
||||||
title: "Console",
|
title: "Console",
|
||||||
lines: [
|
lines: [
|
||||||
@@ -601,13 +606,42 @@ describe("RuntimeInteractionSystem", () => {
|
|||||||
text: "Access granted."
|
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,18 +652,25 @@ 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 = [
|
||||||
|
{
|
||||||
|
...createNpcEntity({
|
||||||
|
id: "entity-npc-sequence",
|
||||||
|
dialogues: [
|
||||||
|
{
|
||||||
id: "dialogue-sequence",
|
id: "dialogue-sequence",
|
||||||
title: "Sequence Dialogue",
|
title: "Sequence Dialogue",
|
||||||
lines: [
|
lines: [
|
||||||
@@ -639,15 +680,32 @@ describe("RuntimeInteractionSystem", () => {
|
|||||||
text: "Sequence started."
|
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,18 +726,25 @@ 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 = [
|
||||||
|
{
|
||||||
|
...createNpcEntity({
|
||||||
|
id: "entity-npc-console",
|
||||||
|
dialogues: [
|
||||||
|
{
|
||||||
id: "dialogue-console",
|
id: "dialogue-console",
|
||||||
title: "Console",
|
title: "Console",
|
||||||
lines: [
|
lines: [
|
||||||
@@ -689,13 +754,42 @@ describe("RuntimeInteractionSystem", () => {
|
|||||||
text: "Console online."
|
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,22 +825,27 @@ 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 = [
|
||||||
|
{
|
||||||
|
...createNpcEntity({
|
||||||
|
id: "entity-npc-threshold",
|
||||||
|
dialogues: [
|
||||||
|
{
|
||||||
id: "dialogue-threshold",
|
id: "dialogue-threshold",
|
||||||
title: "Threshold",
|
title: "Threshold",
|
||||||
lines: [
|
lines: [
|
||||||
@@ -756,13 +855,42 @@ describe("RuntimeInteractionSystem", () => {
|
|||||||
text: "You crossed the threshold."
|
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,18 +918,25 @@ 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 = [
|
||||||
|
{
|
||||||
|
...createNpcEntity({
|
||||||
|
id: "entity-npc-threshold",
|
||||||
|
dialogues: [
|
||||||
|
{
|
||||||
id: "dialogue-threshold",
|
id: "dialogue-threshold",
|
||||||
title: "Threshold",
|
title: "Threshold",
|
||||||
lines: [
|
lines: [
|
||||||
@@ -811,13 +946,42 @@ describe("RuntimeInteractionSystem", () => {
|
|||||||
text: "Welcome."
|
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", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user