Skip to content

9. Add Victory and the Ending

The Drowned Belfry and Echo Warden are playable, but Checkpoint 8 deliberately stops before their events advance Quest 2. This chapter completes that wiring without turning every dungeon entry or combat victory into campaign progress.

Start from Checkpoint 8 or download Checkpoint 9.

  • How an event producer and a state-based objective consumer work together
  • How targetId prevents unrelated dungeon and combat events from advancing the story
  • Why stable, once-only triggers should write durable flags
  • How to separate a boss-victory milestone from the actual campaign ending
  • Why final dialogue branches must appear before broader active-quest branches
  • How an ending condition can become true during dialogue without interrupting the conversation

In Checkpoint 8, the enter_belfry and defeat_warden objectives had marker targets but no completion conditions. Add completeWhen to both objectives:

{
"id": "enter_belfry",
"text": "Enter the Drowned Belfry.",
"detail": "Travel north of Greyhaven and descend into the ruined belfry.",
"marker": {
"targetId": "tutorial_codex:drowned_belfry"
},
"completeWhen": {
"hasFlag": "tutorial_codex:belfry_entered"
}
},
{
"id": "defeat_warden",
"text": "Defeat the Echo Warden.",
"detail": "Reach the Bell Chamber on the final level and put the drowned guardian to rest.",
"marker": {
"targetId": "tutorial_codex:echo_warden"
},
"completeWhen": {
"hasFlag": "tutorial_codex:warden_defeated"
}
}

These conditions are consumers. They observe durable campaign state, but they do not create it.

The matching producers will be two targeted triggers:

Event Target Durable state
enterDungeon tutorial_codex:drowned_belfry tutorial_codex:belfry_entered
combatVictory tutorial_codex:echo_warden tutorial_codex:warden_defeated

This division is deliberate:

specific runtime event
→ targeted trigger
→ durable flag
→ objective condition
→ quest progression

The event happens once in the moment. The flag remains available after the moment has passed and after the game is saved.

Append this trigger after the Lysa recruitment trigger:

{
"id": "tutorial_codex:record_belfry_entry",
"event": "enterDungeon",
"targetId": "tutorial_codex:drowned_belfry",
"once": true,
"when": {
"questActive": "tutorial_codex:silence_drowned_bell"
},
"actions": [
{
"setFlag": "tutorial_codex:belfry_entered"
},
{
"showMessage": "Cold water moves across the Sunken Steps as though disturbed by a distant toll."
},
{
"playSFX": "quest_progress"
}
]
}

enterDungeon is a broad event name. The player may enter many dungeons during a campaign.

The targetId narrows this trigger to:

tutorial_codex:drowned_belfry

Entering another dungeon must not complete the Belfry objective.

The when condition prevents an early visit from recording quest progress before Quest 2 begins. The campaign wants to recognize entering this dungeon while pursuing this quest, not merely discovering the location at any time.

That choice is safe here because dungeon entry can happen again. If the player visits early, they can return after the quest starts and produce a new enterDungeon event.

Append the boss trigger:

{
"id": "tutorial_codex:resolve_echo_warden",
"event": "combatVictory",
"targetId": "tutorial_codex:echo_warden",
"once": true,
"when": {
"questActive": "tutorial_codex:silence_drowned_bell"
},
"actions": [
{
"completeQuestObjective": [
"tutorial_codex:silence_drowned_bell",
"defeat_warden"
]
},
{
"setFlag": "tutorial_codex:warden_defeated"
},
{
"openMessageBox": {
"title": "The Fourth Toll",
"text": "The Echo Warden collapses beneath the broken arch.\n\nFor one breath, the bell sounds from everywhere—the flooded stones, the dark water, the memories of the dead—and then the chamber falls silent.\n\nFar above, Greyhaven's windows stop trembling.",
"position": "center",
"blocking": true,
"buttons": [
{
"label": "Continue",
"action": [
{
"showMessage": "Return to Brother Oren so he can complete the shrine's rite."
}
]
}
]
}
},
{
"playSFX": "quest_progress"
}
]
}

The event is combatVictory, but the trigger is not intended for every won fight.

This target:

"targetId": "tutorial_codex:echo_warden"

means that defeating a skeleton, wolf, or unrelated boss cannot set the Warden flag.

The trigger does two related jobs:

  1. completeQuestObjective gives immediate quest progress at the victory moment.
  2. setFlag preserves the result for dialogue, save data, and the objective’s state condition.

The durable flag is the important downstream dependency. Brother Oren’s final branch does not depend on the combat event still being recent.

The message box is titled The Fourth Toll, but its button is only Continue. It does not claim the campaign is complete and does not teleport the player.

The player still has one explicit responsibility:

Return to Brother Oren

This creates a clean separation:

boss defeated
→ victory milestone
→ return to Oren
→ quest resolution
→ campaign-complete flag
→ ending presentation

Place this branch near the top of Oren’s quest branches, after the already-complete branch and before the broader Quest 2 branches:

{
"when": {
"all": [
{
"questActive": "tutorial_codex:silence_drowned_bell"
},
{
"hasFlag": "tutorial_codex:warden_defeated"
}
]
},
"text": "The guardian is at rest. I can finish the rite now, but Greyhaven will remember what you carried back from the dark.",
"actions": [
{
"completeQuestObjective": [
"tutorial_codex:silence_drowned_bell",
"return_to_oren"
]
},
{
"completeQuest": "tutorial_codex:silence_drowned_bell"
},
{
"setFlag": "tutorial_codex:campaign_complete"
},
{
"showMessage": "Brother Oren completes the shrine's rite. The Drowned Bell is silent."
},
{
"playSFX": "quest_progress"
},
{
"endDialogue": true
}
]
}

A later Oren branch matches any active Quest 2 state:

{
"when": {
"questActive": "tutorial_codex:silence_drowned_bell"
}
}

If that broad branch appears before the Warden-defeated branch, it may capture the conversation first and prevent the final resolution from running.

Use this order:

campaign already complete
Warden defeated while Quest 2 is active
Lysa not recruited
general active Quest 2 guidance
earlier Quest 1 branches
fallback

The more specific conditions belong before the broader conditions they overlap.

Oren’s branch is the only producer of:

tutorial_codex:campaign_complete

That gives the ending one clear dependency and prevents a boss trigger, incidental dialogue, or unrelated event from completing the campaign independently.

Checkpoint 9 also adds short campaign_complete branches for Mara, Oren, and Lysa.

For example, Mara’s completion branch is:

{
"when": {
"hasFlag": "tutorial_codex:campaign_complete"
},
"text": "The bell is silent. That is all the reward Greyhaven needed.",
"actions": [
{
"endDialogue": true
}
]
}

These branches are not required to fire the ending. They keep repeated conversations coherent after completion and prevent NPCs from continuing to give obsolete quest instructions.

Replace the empty ending object with:

{
"id": "tutorial_codex:when_the_bell_falls_silent",
"title": "When the Bell Falls Silent",
"completeWhen": {
"hasFlag": "tutorial_codex:campaign_complete"
},
"actions": [
{
"playSong": "fanfare"
},
{
"openMessageBox": {
"title": "When the Bell Falls Silent",
"text": "Greyhaven sleeps through the night.\n\nAt dawn, Mara opens the tavern shutters without first listening for the bell. Oren seals the courier's letter inside the shrine archive, and Lysa watches the northern hills until the last mist leaves the ruined tower.\n\nNo one calls the silence a victory. In Greyhaven, silence is simply something worth keeping.\n\nVictory: you have completed The Drowned Bell. Free-roam exploration is now available, and you may continue adventuring throughout the world.",
"position": "center",
"blocking": true,
"buttons": [
{
"label": "Continue Exploring"
}
]
}
},
{
"showMessage": "The Drowned Bell is complete."
}
]
}

The ending observes tutorial_codex:campaign_complete; it does not produce that flag itself.

The button says Continue Exploring because the game remains available after the ending. The text explicitly tells the player that the campaign is complete and free-roam play may continue.

Oren sets the completion flag during dialogue and then ends the conversation. The runtime defers the ending presentation until the dialogue can close rather than placing a blocking ending box on top of an active conversation.

You still need to playtest that handoff. Static validation cannot prove that input focus, message ordering, and controls resume correctly.

The validator should resolve this chain:

record_belfry_entry.targetId
→ tutorial_codex:drowned_belfry
resolve_echo_warden.targetId
→ tutorial_codex:echo_warden
enter_belfry.completeWhen
→ tutorial_codex:belfry_entered
defeat_warden.completeWhen
→ tutorial_codex:warden_defeated
Oren final branch
→ tutorial_codex:silence_drowned_bell / return_to_oren
ending.completeWhen
→ tutorial_codex:campaign_complete

Also confirm:

  • every trigger ID is unique,
  • both new triggers use once: true,
  • the boss trigger targets the custom monster ID,
  • the final Oren branch appears before the general Quest 2 branch,
  • the ending uses a stable namespaced ID,
  • the ending button does not invent an unsupported teleport or close action.

Validation can establish that the shapes and references are acceptable. It cannot prove that the events occur in the intended order or that the ending feels correct.

Use a fresh game and test the normal path:

  1. Complete The Missing Courier.
  2. Recruit Lysa.
  3. Enter the Drowned Belfry.
  4. Confirm enter_belfry completes once.
  5. Defeat a normal dungeon enemy and confirm the boss trigger does not fire.
  6. Defeat the Echo Warden.
  7. Confirm The Fourth Toll appears once.
  8. Confirm the next instruction is to return to Oren.
  9. Save, reload, and return to Oren.
  10. Complete Oren’s final conversation.
  11. Confirm When the Bell Falls Silent appears after the dialogue closes.
  12. Select Continue Exploring and confirm normal controls resume.
  13. Speak with Mara, Oren, and Lysa again and confirm their completed-state dialogue.
  14. Save and reload after completion; confirm the ending does not repeat incorrectly.

Also test the negative targets:

  • enter another dungeon, when available,
  • defeat a non-boss enemy,
  • repeat Oren’s dialogue after completion.

The campaign now has a complete intended path from opening to ending:

Mara
→ courier letter
→ Oren
→ Lysa
→ Drowned Belfry
→ Echo Warden
→ Oren
→ campaign ending

Checkpoint 9 adds:

  • durable Belfry-entry and Warden-victory state,
  • targeted, once-only event producers,
  • automatic completion conditions for the two event-driven objectives,
  • a boss-victory milestone,
  • final Oren resolution,
  • post-completion NPC dialogue,
  • a one-shot campaign ending with continued free-roam play.

The campaign can now validate cleanly and still contain a serious progression flaw. Chapter 10 demonstrates exactly that.

Continue to Chapter 10: Diagnose a Validator-Clean Soft Lock.