Story
Quests
The act4 quest runs from Corran to the choice. Then one of three path quests starts, by act4.path. Progress is worked out from flags, as for the Prologue. act4.stage counts the main beats (0 Corran, 1 summons answered, 2 at the rim, 3 both camps heard, 4 the fire, 5 the dawn glyph, 6 chosen, 7 outcome, 8 home); act4.phase counts the finale (1 phase one won, 2 phase two won, 3 held).
Data/Quests/act4.json:
{
"id": "act4",
"title": "The Heart Pane",
"description": "Both sides have gone to the last unbroken piece of the Mere. Ondine means to sing it still. Iver means to cut it free. Each of them wants your hands to finish it.",
"startWhen": { "flag": "act3.done", "op": "!=", "value": 0 },
"stages": [
{
"id": "summons",
"text": "Read the two letters that came to Corran.",
"completeWhen": { "flag": "act4.stage", "op": ">=", "value": 1 }
},
{
"id": "inner_ring",
"text": "Cross the inner Shardfield to the Heart Pane.",
"completeWhen": { "flag": "act4.stage", "op": ">=", "value": 2 }
},
{
"id": "two_rites",
"text": "Hear out both camps at the Pane's rim.",
"completeWhen": {
"all": [
{ "flag": "act4.heard_ondine", "op": "!=", "value": 0 },
{ "flag": "act4.heard_iver", "op": "!=", "value": 0 },
{ "flag": "act4.stage", "op": ">=", "value": 3 }
]
}
},
{
"id": "aske_fire",
"text": "Sit at Aske's fire.",
"completeWhen": { "flag": "act4.stage", "op": ">=", "value": 4 }
},
{
"id": "pane_dawn",
"text": "Walk out onto the Pane at dawn.",
"completeWhen": { "flag": "act4.stage", "op": ">=", "value": 5 }
},
{
"id": "choose",
"text": "Choose: sing it still, cut it free, or neither.",
"completeWhen": {
"all": [
{ "flag": "act4.stage", "op": ">=", "value": 6 },
{ "flag": "act4.path", "op": "!=", "value": 0 }
]
}
}
]
}
Data/Quests/act4_mending.json:
{
"id": "act4_mending",
"title": "The Last Note",
"description": "You chose Ondine. Keep the chorus singing, stop the Cutter, and sing the last note.",
"startWhen": { "flag": "act4.path", "op": "==", "value": 1 },
"stages": [
{
"id": "guard_chorus",
"text": "Guard the mirrored chorus from the Culet cut.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 1 },
{ "flag": "act4.phase", "op": ">=", "value": 1 }
]
}
},
{
"id": "stop_iver",
"text": "Stop Iver's shattering.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 1 },
{ "flag": "act4.phase", "op": ">=", "value": 2 }
]
}
},
{
"id": "last_note",
"text": "Sing the last note.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 1 },
{ "flag": "act4.outcome", "op": "==", "value": 1 }
]
}
},
{
"id": "home",
"text": "Go home to Sallowbank.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 1 },
{ "flag": "act4.stage", "op": ">=", "value": 8 }
]
}
}
]
}
Data/Quests/act4_shattering.json:
{
"id": "act4_shattering",
"title": "The Last Cut",
"description": "You chose Iver. Break the chorus, then cut the Pane free with him.",
"startWhen": { "flag": "act4.path", "op": "==", "value": 2 },
"stages": [
{
"id": "break_chorus",
"text": "Break Ondine's mirrored chorus.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 2 },
{ "flag": "act4.phase", "op": ">=", "value": 1 }
]
}
},
{
"id": "break_ward",
"text": "Break the Prelate's last ward.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 2 },
{ "flag": "act4.phase", "op": ">=", "value": 2 }
]
}
},
{
"id": "last_cut",
"text": "Draw the last cut with Iver.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 2 },
{ "flag": "act4.outcome", "op": "==", "value": 2 }
]
}
},
{
"id": "home",
"text": "Go home to Sallowbank.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 2 },
{ "flag": "act4.stage", "op": ">=", "value": 8 }
]
}
}
]
}
Data/Quests/act4_hold.json:
{
"id": "act4_hold",
"title": "The First Pair",
"description": "You chose neither. Stop the chorus, stop the cut, and hold the Pane the way the First Pair drew it.",
"startWhen": { "flag": "act4.path", "op": "==", "value": 3 },
"stages": [
{
"id": "break_chorus",
"text": "Break Ondine's mirrored chorus.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 3 },
{ "flag": "act4.phase", "op": ">=", "value": 1 }
]
}
},
{
"id": "stop_iver",
"text": "Stop Iver's shattering.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 3 },
{ "flag": "act4.phase", "op": ">=", "value": 2 }
]
}
},
{
"id": "hold_pane",
"text": "Hold the Pane with a thread from both sides.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 3 },
{ "flag": "act4.phase", "op": ">=", "value": 3 },
{ "flag": "act4.outcome", "op": "==", "value": 3 }
]
}
},
{
"id": "home",
"text": "Go home to Sallowbank.",
"completeWhen": {
"all": [
{ "flag": "act4.path", "op": "==", "value": 3 },
{ "flag": "act4.stage", "op": ">=", "value": 8 }
]
}
}
]
}
Side quest act4_side_last_wagon (scene 4.10) is a one-stage quest: start when act4.stage ≥ 2, complete when act4.wagon_escorted = 1.
New flags
| Flag | Values | Set in |
|---|---|---|
act4.stage | 0–8 (above) | Throughout |
act4.path | 1 Ondine, 2 Iver, 3 neither | 4.13 |
act4.phase | 1, 2, 3 (above) | 4.14, 4.16, 4.17 |
act4.outcome | 1 Mended, 2 Shattered, 3 Held | 4.18; the world state after the act |
act4.letter_ondine, act4.letter_iver | 1 | 4.2 |
act4.saw_underside | 1 | 4.4 |
act4.heard_ondine, act4.challenged_ondine, act4.rehearsed | 1 | 4.6, 4.7 |
act4.heard_iver, act4.asked_cost | 1 | 4.8 |
act4.lio_heard, act4.lio_hope | 1 | 4.9 |
act4.wagon_escorted | 1 | 4.10 |
act4.saw_first_pair, composite.known.first_pair | 1 | 4.12 |
tamsin.stepped_out, rook.stepped_out | 1 | 4.14, 4.15 |
act4.boon_tamsin, act4.boon_rook | 1 | 4.15 |
What the code would need
Act 4 asks for more new game code than any earlier act. Each item is a separate ticket.
- Battle: enemies with several parts that break one at a time (the chorus's voices); an allied HP bar to protect (
pane_chorus_guard); encounters with waves; floor hazards (cracks); effects on the player (shorter breath, silence); enemy effects (reflect damage, a ward that resists one drawing tier); battle barks between attacks; per-encounter rules such as the Pane rule and its gauge. - Spells: recognising a cast's drawing tier and whether a composite is cross-side; the composite effect
reflectNextAttackSeconds; a recognizer check, because the First Pair's stroke overlaps Thornshield (Coil into Facet Seal) at 0.55. - Dialogue commands:
<<learn_composite id>>,<<prompt_cast_style mirrored|parallel|asymmetric>>,<<hold_pane>>,<<epilogue id>>. - Locations: lighting states by flag (day, night, dawn; one per outcome after the act).
- Screens: the epilogue cards; the Pane gauge and the ally bar on the battle HUD.