Build a multi-objective quest
Description: Introduce several objectives at once, wait for all of them, and let a dialogue choice decide the ending.
This walkthrough follows Build a quest. That first quest has one objective and one ending; this one has three jobs the player can finish in any order, a conversation that returns a result to the quest, and both a successful and a failed ending.
Follow along: download the project this walkthrough starts from. The zip also contains
create_multi_objective_quest_final, the completed project, for comparison.
The case: a storm has trapped Detective Rowan Hale at Blackthorn Manor with a body, a witness, and two plausible suspects. Rowan must inspect the crime scene, recover the missing ledger, and question the witness before naming an accused. Accusing either suspect closes the case. Accusing the witness is technically a choice too, but it earns Rowan a reprimand and fails the quest.
The finished flow looks like this:
Main flow
Quest
-> Start Dialogue: At the Crime Scene
-> Inspect the scene
-> Recover the missing ledger
-> Question the witness
-> Gate: all three are complete
-> Start Dialogue: Make an accusation
-> Hub: who was accused?
-> either suspect -> Complete Quest (Success)
-> witness -> reprimand dialogue -> Complete Quest (Failure)
Parallel listener bodies
InspectedScene flag -> Update "Inspect the scene" -> Return
RecoveredLedger flag -> Update "Recover the missing ledger" -> Return
QuestionedWitness flag -> Update "Question the witness" -> Return
Set up the cast
Create five Character entities. The Add a character walkthrough covers the mechanics, so this time you only need their names and roles:
| Character | External ID | Role in this walkthrough | Stock portrait |
|---|---|---|---|
| Detective Rowan Hale | DetectiveRowanHale |
Player character; set Role to Protagonist |
male-5.png |
| Lord Ambrose Blackthorn | LordAmbroseBlackthorn |
The murder victim | male-2.png |
| Ada Finch | AdaFinch |
The witness | female-2.png |
| Lady Beatrice Blackthorn | LadyBeatriceBlackthorn |
Suspect | female-6.png |
| Julian Blackthorn | JulianBlackthorn |
Suspect | male-7.png |
The victim does not need to speak, but keeping them as a character still makes the case easy to expand later. The two suspects and the witness will be useful as dialogue speakers, so give them distinct names now.
As described in Add a character, you can select several images in the Stock Image picker and import them together. Assign the portraits in the table above so each speaker is immediately recognizable on a dialogue node.

Make the quest and its progress variables
In Quests & Dialogues, add a Quest named BlackthornMurder. Give it the
player-facing title Murder at Blackthorn Manor and a short description such
as "Find the evidence and name the killer before the storm passes."
Then add these four variables in the Variables view. The first three are
boolean progress flags, all with a default value of false. Your game sets them
when the player completes the corresponding world activity.
| Name | Type | Default | Set by your game when |
|---|---|---|---|
BlackthornMurder_InspectedScene |
boolean |
false |
The player inspects the study. |
BlackthornMurder_RecoveredLedger |
boolean |
false |
The player recovers the ledger. |
BlackthornMurder_QuestionedWitness |
boolean |
false |
The player finishes questioning Ada. |
BlackthornMurder_Accused |
string |
empty | The accusation dialogue records the player's choice. |
The boolean flags describe work happening in your game. BlackthornMurder_Accused
is different: Narratyr writes it itself, and the quest reads it after the
dialogue returns.

Open at the crime scene
Before introducing the objectives, give the quest a short opening conversation.
Add a Dialogue named BlackthornCrimeScene with the player-facing title
At the Crime Scene. Lady Beatrice and Julian are already in the study with
the detective, so two lines are enough to establish both the body and the
missing evidence:
Lady Beatrice: Detective, we found Lord Blackthorn here in the study. Neither of us touched the body.
Julian: His ledger is missing. I suppose that makes both of us look rather bad.
End the conversation after Julian's line. Return to BlackthornMurder, add a
Start Dialogue after the Quest node, and choose the entry node of
BlackthornCrimeScene. The quest will resume from that Start Dialogue node as
soon as the conversation ends.

Introduce all three objectives
Starting at the opening Start Dialogue node, add three Objective nodes in a row. An objective only introduces itself and immediately continues, so this sequence makes all three visible to the player before the quest waits for any of them.
Configure them as follows:
| Name | Objective Type | Fields |
|---|---|---|
| Inspect the scene | Generic |
None. This is a world action your game understands. |
| Recover the missing ledger | Fetch |
Set itemTypeId to missing_ledger and count to 1. |
| Question the witness | TalkTo |
Set targetId to Ada Finch's external ID, AdaFinch. |
Leave Optional and Hidden off for each. The objective type tells your
game what it needs to watch; it does not make Narratyr perform the action. In
particular, Generic is useful when the action has no standard Fetch, Kill, or
TalkTo shape.

Wait until every lead is resolved
After the third objective, add a Gate and choose Wait on Expression. Set its condition to:
(
BlackthornMurder_InspectedScene
&& BlackthornMurder_RecoveredLedger
&& BlackthornMurder_QuestionedWitness
)
The gate opens only when all three flags are true. They can become true in any order: the player may interview Ada before finding the ledger, for example. This is the useful distinction between introducing objectives in sequence and requiring them in sequence — the graph does the first, while the single combined condition controls the second.
When an expression contains more than one condition, wrap the whole expression
in parentheses and start each && or || clause on a new line. This keeps the
Gate node narrow enough to scan without hiding how its conditions are grouped.

Complete each objective as its flag changes
The Gate controls when the main path may continue, but it should not delay the quest log. Add three Event Listener nodes in empty canvas space, separate from the main path. Give each listener a condition and a short body:
| Listener condition | Update Objective target |
|---|---|
BlackthornMurder_InspectedScene |
Inspect the scene |
BlackthornMurder_RecoveredLedger |
Recover the missing ledger |
BlackthornMurder_QuestionedWitness |
Question the witness |
From each Event Listener, connect an Update Objective node. Point it at the matching objective and leave Completion Status set to Completed. Finish each listener body with a Return node. Leave Async off: these bodies are short, do not pause, and should return immediately to whatever the quest was doing when the flag changed.
An Event Listener fires when its condition changes from false to true. That means finding the ledger completes Recover the missing ledger immediately, even if the other two flags are still false and the main flow is still waiting at the Gate. The Return node then resumes that waiting flow. The three listener bodies are independent, so the player can complete the objectives in any order.
This is the same pattern used by 006 Parallel Multi-Objective Any Order Quest
in EngineTest.ntproj: listeners keep individual objective state current, while
one combined Gate decides when every prerequisite has been satisfied.

Build the accusation dialogue
Add a Dialogue named BlackthornAccusation. Its entry line can be very
short; set Rowan Hale as the speaker and write:
I have heard enough. One of you killed Lord Blackthorn.
Add a second Dialogue Node with Rowan as its speaker, leave its line empty, and add three choices:
Accuse Lady Beatrice.Accuse Julian.Accuse Ada, the witness.
The choices belong on Rowan's node because the player is choosing Rowan's words. For each choice, add an Instruction node, then an End Conversation node. Name the instruction after the choice and set its instruction text to one of these assignments:

BlackthornMurder_Accused = "LadyBeatrice"
BlackthornMurder_Accused = "Julian"
BlackthornMurder_Accused = "Ada"
All three instructions can connect to the same End Conversation node. An instruction changes shared state without pausing. Once the conversation ends, the quest that started it resumes at the node after its Start Dialogue node.

Start the dialogue and branch on its result
Return to BlackthornMurder. After the Gate, add Start Dialogue and choose
the entry node of BlackthornAccusation as its target.
The quest pauses while the dialogue is on screen, then continues after the
player makes a choice.
Add a Hub Node after Start Dialogue. Give it three outputs and set their conditions to:
BlackthornMurder_Accused == "LadyBeatrice"
BlackthornMurder_Accused == "Julian"
BlackthornMurder_Accused == "Ada"
The Hub does not wait: it immediately takes the output whose condition is true. This is the companion to a Gate. The Gate waited for the investigation to be ready; the Hub reads the choice that is already known.

End the case
Connect the Lady Beatrice and Julian outputs to Complete Quest nodes with status Success. The tutorial is about the graph shape rather than solving a fair mystery, so either suspect is a successful case conclusion.
For the Ada output, add a short Dialogue named WitnessReprimand, then
start it from the Hub's Ada branch. A line from Lady Beatrice is enough:
Lady Beatrice: Detective, she is the witness. Please stop accusing the only person who called for help.
End that dialogue and connect back to a Complete Quest node with status Failure. The three terminal nodes make the outcomes explicit to your game: the two suspect branches succeed, while the joke accusation fails after its small narrative payoff.


Read the finished graph
Use Auto Arrange to lay out the quest. Its main path should read left to right from the three introductions through the gate and accusation dialogue. The Hub's two successful branches end at their success nodes, while the witness branch drops to the reprimand and failure node. The three Event Listener bodies sit outside that main spine, each flowing through its matching objective update to a Return node.

This pattern scales well: add another objective by introducing it, add an Event Listener that completes it when its flag changes, and include one more clause in the final Gate expression. The listener keeps that objective current on its own; the Gate remains the single place that defines when the investigation as a whole may continue.