Quests: restart resets variables, respawns giver and NPCs; final failures
Quest audit (docs/quest-audit.md, tools/questscript.mjs), fixes 2-8. New mods/questscript.cpp scans the script code once (giver, own variables, needed NPCs, QIS_OnEnter creations, story-ending failure labels). questfail: generic, giverless, story-ending and NPC-gone failures stay final; a restart restores the variables snapshot taken at Quest_Trigger, deletes OnEnter leftovers, respawns the giver and needed NPCs and gives the accept dialog back. questgiver slimmed on top of questscript. Not yet tested in game. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7ec0fa2b8e
commit
e13b82f040
10 files changed
+1557
-293
No files matched your search
@@ -0,0 +1,278 @@
|
||||
# Quest audit: how quests fail or get stuck (2026-10-30)
|
||||
|
||||
Request (2026-10-26, started 2026-10-30): "iterate through all quests in the
|
||||
game, and check their conditions for potential failing or stuck up points
|
||||
given the current implementation and our attempted reset". Done one quest at
|
||||
a time from the compiled scripts with `tools/questscript.mjs` (full dump:
|
||||
`<dir> <id>`; compact: `<dir> --facts <id>`).
|
||||
|
||||
Scripts: Ancaria per hero class `bin\TYPE_NPC_<class>\` (the game writes the
|
||||
one in use to `bin\sgf.bin`; this audit reads `TYPE_NPC_GLADIATOR`, the class
|
||||
variants differ in a few class quests), Underworld `bin\Addon\NetScriptCamp\`.
|
||||
Ancaria: 603 quests in the table (87 + 13 side quests, ~37 main quests, 352
|
||||
generic `DQ_` quests from 16 templates, multiplayer / unnamed sets);
|
||||
Underworld: 190.
|
||||
|
||||
## What our mods do (the "reset")
|
||||
|
||||
- **M1 failure restart** (`questfail.cpp`, `Quest_End` hook): after
|
||||
`LoseQuest` ran the quest's failure script (`QIS_OnLose<id>`), the flags go
|
||||
back to available (1), the book entry stays failed with its compass on the
|
||||
giver. Quest variables and NPC states are left as they are.
|
||||
- **M2 giver death** (`questgiver.cpp`): a label of a running quest run for
|
||||
its dead giver (the giver: the NPC spawned with a dialog that has the accept
|
||||
button) is skipped, unless the giver is hostile to the hero (2026-10-30);
|
||||
the quest restarts (M1 plus the variables only this quest writes: 0, the
|
||||
one named after the quest: 1) and the giver's spawn instruction runs again
|
||||
once the body is gone.
|
||||
- **M3 load repair** (`questgiver.cpp`): a running quest whose giver is not
|
||||
alive after loading gets M2, unless the quest morphs its giver.
|
||||
- **M4 followers** (`followers.cpp`): escorts back on the hero's follower
|
||||
list after loading; followers more than 40 cells away are teleported to the
|
||||
hero.
|
||||
|
||||
## General findings
|
||||
|
||||
- **G1 M1 keeps the quest variables.** Givers' dialogs choose their branch by
|
||||
bits of the quest variable (`IF 49(bit, "<id>")`); bits set while the quest
|
||||
ran stay set after a failure, so the giver shows a "still running" branch
|
||||
without the accept button and the quest can never be taken again. Example
|
||||
702: the girl's death runs `lose702`; variable 702 keeps bit 1, the giver
|
||||
answers "Qoffen01" with `ok702`. Fix: M1 resets the quest's own variables
|
||||
like M2.
|
||||
- **G2 generic quests (2600..3599)** are the game's random quest pool;
|
||||
`Quest_End` already copies them under a new id. M1 should leave them (and
|
||||
their runtime copies) to the game.
|
||||
- **G3 one-time world progress.** Many targets are spawned once by the start
|
||||
script or `Region<N>Init`, not by the quest. When M2/M3 reset the quest's
|
||||
variables after such a target died, the progress is lost and the target
|
||||
never comes back: stuck. Either keep the variables on M2/M3 or respawn the
|
||||
quest's one-time NPCs (see G6).
|
||||
- **G4 duplicates on re-accept.** `QIS_OnEnter` creates the quest's NPCs and
|
||||
objects again; after a failure the old ones may still be alive.
|
||||
- **G5 givers deleted by the script** (`DelNPC` on the giver): M3 restarts a
|
||||
quest whose giver is gone on purpose.
|
||||
- **G6 restart without the NPCs.** The restart is pointless when the NPCs the
|
||||
quest needs are one-time spawns and dead or deleted. Idea: respawn them from
|
||||
their spawn instructions like the giver.
|
||||
- **G7 quests without a giver** (trigger areas): M1 "restarts" them and erases
|
||||
the failed book entry.
|
||||
- **G8 givers turned hostile by `SetNPCState ... 08 12`** instead of `Morph`
|
||||
are not in `g_giverTurns`; M3 restarts those quests wrongly, M1 points the
|
||||
book at an enemy.
|
||||
- **G9 shared variables.** M2 doesn't reset quest variables another quest's
|
||||
label also writes, so the respawned giver shows a running branch.
|
||||
- **G10 giver killed after the quest ended** (by its own script): M2 doesn't
|
||||
act, the giver stays dead.
|
||||
- **G11 failure continues a chain.** Some failures are part of a quest chain
|
||||
(`LoseQuest` together with `SetUpQuest` of the next quest, giver's dialog
|
||||
moved on); M1 must not restart those.
|
||||
- **G12 state in dialogs (Underworld).** Underworld quests keep their state
|
||||
in the NPCs' dialogs; a failure sets a "done/lost" dialog (or none), and M1
|
||||
doesn't put the accept dialog back (7614, 10260).
|
||||
- **G13 named ids.** Spawns with named ids (`res:AUFTRAGGEBER_10254`,
|
||||
`res:Sam1_Knappe`) or the id after the type argument aren't read by
|
||||
`InstructionScriptId`; those givers aren't in `g_givers`.
|
||||
- **V1/V2 vanilla bugs:** 1101's time-out never ends the quest; Res:17163 is
|
||||
used by both 602 and 1202, and 602 deletes 1202's patient.
|
||||
|
||||
## Per quest
|
||||
|
||||
Columns: how it can fail (vanilla), what happens with our mods, verdict
|
||||
(ok / G<n> / finding).
|
||||
|
||||
| Quest | Fails by | With our mods | Verdict |
|
||||
|---|---|---|---|
|
||||
| 151 Tierischer Wilddieb | never (no LoseQuest); wolf Res:17081 (start script, death `stirb151`: bit 2, triggers the quest) | M2/M3 on giver death: variable 151 reset to 1; if the wolf is already dead, bit 2 is lost and the wolf never respawns: stuck | G3 |
|
||||
| 152 Botendienst | time limit (`SetTimer` 4320 -> `zeit152`: bit 4, `LoseQuest`) | M1: bits 1 + 4 stay, the giver answers "Qfail" / "Qpostfail" without the accept button: stuck. With G1 reset: offered again; re-accept spawns the parcel (Res:6027) and later the recipient Res:17077 again (the old recipient stays, dialog off) | G1, G4 |
|
||||
| 154 verschwundener Schmied | never | the script deletes the giver Res:17626 (`talkedbride154`, `take154`): after the next load M3 restarts the running quest and spawns the giver again | G5 |
|
||||
| 201 Vermisste Tochter nach Ausritt | daughter Res:18006 dies (`Tochtertot201`: bit 8, `LoseQuest`); she is spawned once (`Region2Init`) | M1: bit 8 stays, giver answers `okt201` then `ok201`: stuck. With G1: offered again, but the daughter stays dead: cannot be finished | G1, G6 |
|
||||
| 202 Eskorte für Händler | merchant Res:18012 (the giver) and bodyguard Res:18013 both dead, or the bodyguard alone at the bridge | the merchant's death is M2 (restart, respawn; his dialog has no bit tests); the bodyguard is not needed | ok |
|
||||
| 203 Schatzkarte | never | giver death -> M2; re-accept creates map + chest again (old chest stays) | ok (G4) |
|
||||
| 204 Die Bücher der Gelehrigkeit | never | giver death -> M2; the boss and the book come from `QIS_OnEnter204`, so a restart can be redone | ok |
|
||||
| 301 Orks auf Bauernhof | time limit (`SetTimer` 1440 -> `lose301`); farmer Res:17033 and daughter Res:17032 both dead | no giver (trigger area, deleted on start); `QIS_OnLose301` deletes both NPCs. M1 makes it available but nothing can start it again, and with no known giver its failed book entry is erased | G7 |
|
||||
| 302 Von Räubern und Rindern | six cattle dead (`302a` = 6, `LoseQuest`); the giver Res:17029 (escorted) dies (`tot1_302`) | giver death -> M2 (but `302a` is also set by `startcode`, so it is not "only this quest's" and keeps its count). Cattle failure -> M1: the dialog's `48(6,"302a")` branch sets bit 3 -> "ok" forever: stuck, also with G1 unless G1 counts start-script initialisation as the quest's own. Re-accept spawns the six cattle again | G1 (start-script variables), G4 |
|
||||
| 303 Bodycount Orks | never; ogre Res:17031 is a one-time spawn (`Region3Init`, death `tot303`: bit 2) | as 151: giver death resets bit 2, a dead ogre never returns: stuck | G3 |
|
||||
| 401 Jagd auf wildernde Wölfe | never; wolves one-time (`Region4Init`, death `stirb401`: bit 2) | as 151 | G3 |
|
||||
| 402 Kräuter für Kräuterhexe | never | herbs from a permanent `MouseEvent` (`Region4Init`), can be picked again after M2 | ok |
|
||||
| 403 Kühe vor Wölfen retten | all cows dead (bit 4), then the giver's answer runs `lose403` | M1: bits 4 + 5 stay, giver "ok403" forever: stuck. With G1: offered again, but the cows (`Region4Init`) are gone | G1, G6 |
|
||||
| 501 Geister auf Landsitz | never by `LoseQuest`; choice `change501` / `nochange501` | `postchange501` turns giver Res:17071 and Res:17070 hostile with `SetNPCState ... 08 12` (not Morph): M2 sees the hostility at death, but M3 after a load would restart the quest (only Morph is known as "turns") | G8 |
|
||||
| 502 Verstecktes Waffenlager | never | enemies and boss from `QIS_OnEnter502` (variant by `Globalchange1`): redoable after M2 | ok |
|
||||
| 503 Botschaft an Geliebte | never | giver Res:17105's death label `weg503` belongs to no quest (M2 does not react); not needed: the quest ends at the lover Res:17104 | ok |
|
||||
| 601 Kunstraub von Händler | never | thief Res:17135 gives the item by dialog; redoable after M2 | ok |
|
||||
| 602 Wegelagerer | never | the knight Res:17136 is beaten, not killed (`ritter602` sets his HP back); after M2 his dialog offers the fight again | ok |
|
||||
| 603 Entlaufener Bräutigam | never | the groom Res:17140 is beaten (`braut603` heals him), the fight can be repeated after M2 | ok |
|
||||
| 701 Vergifteter Brunnen | never (`lose701` is not called) | boss Res:17063 one-time (`Region7Init`, drops the items); M2 resets bit 20 (item taken): stuck if the boss is dead | G3 |
|
||||
| 702 Mädchen bei Ausritt verschwunden ("Familienbande") | the girl Res:17060 dies (`lose702`) | giver turned hostile and killed: handled (7ec0fa2). Girl's death -> M1: bit 1 stays, giver "Qoffen01": stuck; with G1 redoable (the girl comes from `QIS_OnEnter702`) | G1 |
|
||||
| 703 Objektschutz Wegbrücke | leaving the bridge area / region before the bandits are dead (`zeit703`: bit 4), then the giver's answer runs `lose703` | M1: bits 4 + 5 stay, giver "ok703": stuck. With G1: redoable (bandits not all dead, else the quest would have been won) | G1 |
|
||||
| 801 Holzfällerstreit mit den Elfen | the giver Res:17144 dies (`tod801` -> `lose801`) | giver death -> M2 (restart, respawn) instead of the failure | ok |
|
||||
| 802 Königliche Jäger Verschollen | never | hunters, herbs and amulet are one-time (`Region8Init`); M2 resets 802 (progress bits): stuck when they are used up | G3 |
|
||||
| 803 Kopfgeldjagd | never | targets one-time (`Region8Init`). On giver death M2 does not reset `803` (quest 801's elf dialog also sets a bit in it), so the respawned giver shows the running branch without accept and the flags say "available": stuck | G3, G9 |
|
||||
| 901 Soldaten verschleppen Frauen | time limit (`zeit901`, also kills quest 902's women); the women Res:17051..17054 die (`lose901`: bit 5), then the giver's answer runs `lose901` | M1: bit 6 stays, giver "ok901": stuck. With G1: redoable after the time limit; after the women died they are gone (`Region9Init`) | G1, G6 |
|
||||
| 902 Rache an Reichem Händler | never | boss Res:17049 one-time (`Region9Init`, death `tot902`: bit 2) | G3 |
|
||||
| 903 Robin Hood | never | Res:17045 is beaten and healed (`re903`), the choice can be made again after M2 | ok |
|
||||
| 1001 Übergriffe auf die Bevölkerung | never | boss Res:17041 one-time (`Region10Init`, drops the proof) | G3 |
|
||||
| 1002 Spionage | seen by the spy's group (tag 0x60 `lose1002` on the NPCs from `QIS_OnEnter1002`: bit 4, `LoseQuest`) | M1: giver sets bit 5, "ok" forever: stuck. With G1 redoable; the old group (now hostile) stays next to the new one | G1, G4 |
|
||||
| 1003 Schlägertypen | the giver Res:17034 dies (`verreckt1003`); seven villagers die (bit 4), then the giver's answer runs `lose1003` | giver death -> M2. Villagers -> M1: bit 5, "ok" forever: stuck. With G1 redoable (the attackers come from the accept trigger again) | G1 |
|
||||
| 1101 Sektenpriester opfern Jungfrauen | the virgin Res:17112 dies (`Verloren1101` -> `lose11a1`); time limit (`Zeitum1101`: demon instead of the virgin, bit 3) | death -> M1: giver sets bit 5, "ok": stuck; with G1 redoable (all from `QIS_OnEnter1101`, old priests stay). Time limit: vanilla never ends the quest (the giver's bit 3 branch has no `LoseQuest`): running forever | G1, V1 |
|
||||
| 1102 Kompromittierende Situatuion | time limit (`Zeitum1102`: bit 3, `LoseQuest`) | M1: bit 1 stays, giver "Ok1102": stuck; with G1 redoable (the lady and the letter come from `QIS_OnEnter1102`). After the time limit the lady's bit 3 answer kills the giver (`SetHP 0`); the quest is no longer running then, so M2 does not respawn him | G1, G10 |
|
||||
| 1103 Verhandelnder Räuber | never | the robber Res:17118 is beaten and healed (`tot1103`) | ok |
|
||||
| 1111 DeModreys Steuerpresser | the escorted Res:17121 dies (`lose1111` -> `geld1111`: bit 5, `LoseQuest`) | M1: giver sets bit 6, "ok": stuck. With G1: the boss Res:17123 is one-time (`Region111Init`) and `geld1111` deleted his proof Res:6051: cannot be finished | G1, G6 |
|
||||
| 1112 Animagus terrorisiert Bauernhof | the spared Animagus Res:17127 dies (`ex1112` with bit 4: `LoseQuest`) | M1: bit 4 stays, the giver's answer then runs `postchange1112` (turns the giver hostile) instead of an offer. With G1: the Animagus is one-time (`Region111Init`). `postchange1112` turns the giver hostile by `SetNPCState` (M3 after a load: G8) | G1, G6, G8 |
|
||||
| 1113 Elfischer Kunstraub | never | thief Res:17129 and the goal object Res:6052 one-time (`Region111Init`) | G3 |
|
||||
| 1201 Sekte beschwört kleine Dämonen | never | cult one-time (`Region13Init`, group dead: bit 2) | G3 |
|
||||
| 1202 Heilmittel für Händler | time limit (`zeit1202` kills the patient Res:17163, `LoseQuest`) | M1: giver sets bit 5, "ok": stuck. With G1 the patient (`Region13Init`) is dead: cannot be finished. Vanilla: quest 602's `ok1_602` / `ritterweg_602` walk away and delete `res:17163` too (the same id): finishing 602 removes 1202's patient | G1, G6, V2 |
|
||||
| 1203 Der Richter und sein Henker | never | judge Res:17166 and executioner Res:17167 one-time (`Region13Init`) | G3 |
|
||||
| 1301 Entlaufener Gladiatoren-Minotaurus | never | the giver's death label is the quest's end (`exit1301`): `attack1301` turns him hostile (M2 lets it run since 7ec0fa2), the quest ends at once (no M3). Minotaur from `QIS_OnEnter1301` | ok |
|
||||
| 1302 Das Soldaten-Tunier | timer → `lose1302` | after M1 bits 4/5 and `1302a` stay (G1); opponent Res:17173 is deleted by `attacke1302_1` and created only by region init (G6). Vanilla typos: `DelNPC res17173`/`res17174` (no colon), `attacke1302_2` attacks 17174 | G1 + G6 |
|
||||
| 1303 Händler - legaler Warentransport | timer → `lose1303` | after M1 bits 3/4 stay (G1); re-accept creates recipient Res:17177 again (G4) | G1 + G4 |
|
||||
| 1401 Händler - Warenschmuggel | the side chosen dies (`lose1401`) | after M1 bits 1-6 and `1401a`/`1401b` stay (G1); re-accept creates Res:17180/17181 again (G4). Vanilla: soldier's death label `attack1401` doesn't exist (`attacke1401`) | G1 + G4 |
|
||||
| 1402 Junge Dame vor Übergriffen eines Offiziers schützen | never | officer and soldiers from `QIS_OnEnter1402` | ok |
|
||||
| 1403 Eskortiere Händler zu geheimen Treffen | recipient after the escorted giver died (`losequest1403`) | giver death is caught by M2 first (restart, giver back); re-accept creates recipient Res:17187 again (G4). Vanilla typo `ok1024` | G4 |
|
||||
| 1404 Eskortiere Dame zu Treffen mit Geliebten | the lady dies (`lose1404`) | after M1 bits 1/4 stay (G1); lady Res:17189 and boss Res:17190 are one-time (region init), dead lady makes a restart pointless (G6) | G1 + G6 |
|
||||
| 1405 Sekte von Dämonenanbetern | never | sect leader Res:17195, cultists and the three captives are one-time (region init); M2 reset after the leader died loses the progress | G3 |
|
||||
| 1501 Menschlicher Wilderer | never | the giver follows; vanilla his death (`ex1501`) lets the quest go on, M2 restarts it and brings him back instead. Re-accept creates the poachers again (G4) | M2 changes vanilla + G4 |
|
||||
| 1502 Hetzjagd | a label deletes the giver Res:17015, then `losequest1502` | the giver is spawned once by trigger area `hetz1_1502` (deleted after use); after M1 the book points at a deleted giver and nothing spawns him again (G6). Vanilla: his death label `lose1502` doesn't exist | G6 |
|
||||
| 1503 Arak-Attack | never | spiders and the target from `QIS_OnEnter1503` | ok |
|
||||
| 1601 Kunstraub | never | thief from `QIS_OnEnter1601` | ok |
|
||||
| 1602 Attentäter abfangen | the target dies (`target1602`) | after M1 bit 4 stays (G1); target Res:17205 and assassin Res:17201 are one-time (region init), the target is dead (G6) | G1 + G6 |
|
||||
| 1603 Blockadebrecher | never | | ok |
|
||||
| 1701 Getrennte Liebende | the lover dies (`lose1701`); afterwards the giver turns hostile and fails it again (`ende1701`) | after M1 bit 6 stays, the giver's dialog runs `ende1701` (G1); lover Res:17209 one-time (G6); `ende1701` makes the giver hostile by `SetNPCState 08 12`, M1 then points at an enemy (G8) | G1 + G6 + G8 |
|
||||
| 1702 Korruption | never | official Res:17215 one-time (region init) | G3 |
|
||||
| 1703 Unschuldiger am Galgen | judge after the time-out (`lose1703`) | after M1 bits 6/7 stay (G1); victim Res:17218 and boss Res:17221 are deleted by `zeit1703`, the victim is one-time (G6). `lose1703` kills the giver by `SetHP 0` on purpose; M2 skips his death label `less1703` and brings him back | G1 + G6, M2 changes vanilla |
|
||||
| 1801 Monströsere Wilderer | never | poachers one-time (region init) | G3 |
|
||||
| 1802 Dunkle Priester beschwören Dämon | never | priests from `QIS_OnEnter1802` | ok |
|
||||
| 1803 Dunkelelfengift | time-out (`zeitum1803`) | after M1 bit 4 stays, the giver's dialog runs `losequest1803` again (G1); boss Res:17229 one-time (region init), once killed the poison can't drop again (G6) | G1 + G6 |
|
||||
| 1901 Rache an bösem Anführer in Dungeon | never | boss Res:17232 one-time (region init) | G3 |
|
||||
| 1902 Monster haben Item verschleppt in Dungeon | never | monster Res:17020 one-time (region init) | G3 |
|
||||
| 1903 Entlaufene 'Tochter' | the girl dies (`lose1903`) | after M1 bit 5 stays, the giver's dialog morphs him into the monster at once (G1); girl Res:17237 one-time (G6) | G1 + G6 |
|
||||
| 2001 Untote Kühe auf Wiesen | never | boss Res:17239 spawns on the 4th trigger area; `2001a` starts at 1 from the start script, a reset to 0 matches no branch of `move2001` and the boss never comes (G1 start-script variable); trigger bits in `2001` | G3 (start-script variable) |
|
||||
| 2002 Kämpfe gegen Wilde Monster | never | repeatable arena, waves from `monster2_2002` | ok |
|
||||
| 2003 Anführer der Dämonensekte | never | the giver is the cult leader: `QIS_OnEnter2003` makes him hostile by `SetNPCState 08 12` (G8, M3 would restart). His death runs (hostile, 7ec0fa2). Vanilla typo `res:174242` | G8 |
|
||||
| 2101 Hands of my Dragon | never | chain with 2102/2103 (and 2303's egg) on dragon Res:17245 (one-time); prince Res:17246 and his guards from `QIS_OnEnter2101`. Shared variables `riesendiamant`/`drachenei` are written by several of these quests (G9 if one is restarted) | ok |
|
||||
| 2102 Drache - Zahnstocher | never | prince is the giver; boss Res:17249 from `QIS_OnEnter2102` | ok |
|
||||
| 2103 Return for Refill | never | knights created one after the other by `ziel2103` | ok |
|
||||
| 2201 Kuss der Spinnefrau | the girl dies (`lose2201`) | after M1 bits stay (G1); girl Res:17283 one-time (G6); `postchange2201` turns the giver Res:17281 hostile by `SetNPCState 08 12` (G8) | G1 + G6 + G8 |
|
||||
| 2202 Narzisstische Zauberin | never | `change2202` turns the giver Res:17255 hostile by `SetNPCState 08 12` (G8) | G8 |
|
||||
| 2203 Hinterhältiger Giftmischer | never | poisoner Res:17260 and the six barrels (counter `2303a`) are one-time (region init) | G3 |
|
||||
| 2301 Besorge Reagentium | never | bush is a fixed MouseEvent, item re-created in OnEnter | ok |
|
||||
| 2302 Larbortiere | never | the four monsters are one-time (region init), counted in `2302b` | G3 |
|
||||
| 2401 Botschaft für Scouts | never | chain 2401-2404 on giver Res:17268 (his death label `mann2404` belongs to 2404); scouts one-time (region init), moved/morphed by the quest | G3 |
|
||||
| 2402 Verlaufene Sielder finden | the settler dies after joining (`losequest2402`) | the failure continues the chain (`SetUpQuest 2403`, giver's dialog set to 2403); M1 restarting 2402 is wrong (G11) | G11 |
|
||||
| 2403 Verschleppte Sielder befreien | all settlers die (`losequest2403`) | like 2402: the failure continues the chain with 2404 (G11) | G11 |
|
||||
| 2404 Verteidige Lager | never | vanilla the giver's death (`mann2404`) hands the reward to Res:17280; M2 restarts and brings him back instead | M2 changes vanilla |
|
||||
| 2411 Das Orkische Relikt | never | relic from `QIS_OnEnter2411` | ok |
|
||||
| 2412 Der Feige Hund | never | dog Res:17584 one-time (region init) | G3 |
|
||||
| 2413 Kleine Wuselorks | never | all from `QIS_OnEnter2413` | ok |
|
||||
| 2501 Finde Drachnschuppe für Rüstung | never | dragon Res:17292 one-time (region init); counts towards `finale` | G3 |
|
||||
| 2502 Eierdieb | the time-out, reported to the giver (`losequest2502`) | the failure counts towards the region's `finale` (bit 2 + `finalestart`) like a success (G11); after M1 bits 4/5 stay (G1) | G11 |
|
||||
| 2503 Drachentöter vertreiben | never | dragon slayers one-time (region init) | G3 |
|
||||
| 2504 Rette Jungfrau | the maiden (= giver) dies (`lose2504`) | M2 catches her death first: restart and respawn instead of failure + `finale` bit; redoable | M2 changes vanilla |
|
||||
| 9003 Versteckter Händler | `rg3_goodie1_lose` (merchant's death) | progress lives in the shared variable `goodies` (8 quests), M1/M2 can't reset it (G1 + G9): after M1 bit 1 stays and the dialog offers the reward branch (`ExitQuest`) without the quest running | G1 + G9 |
|
||||
| 9004 Vermisstes Kind | `rg1_goodie_lose` (child's death) | `goodies` bit 4 stays, the giver only answers "ok" (G1 + G9); child Res:17513 one-time (G6) | G1 + G6 + G9 |
|
||||
| 9005 Der Waldläufer | never | | ok |
|
||||
| 9006 Der unbekannte Krieger | never | progress in shared `goodies` | ok |
|
||||
| 9007 Jacquaire's Waffen | never | guards from `QIS_OnEnter9007` | ok |
|
||||
| 9008 Furchtbares Verbrechen | escorted giver Res:17539 dies (`losequest9008`) | M2 catches the death (restart, respawn); `QIS_OnEnter9008` sets the trigger area again | M2 changes vanilla |
|
||||
| 9009 Whiskeylieferung | never | | ok |
|
||||
| 9010 Vergrabene Sklaven | escorted giver Res:17575 dies (`lose9010`) | M2 restarts; but `9010` is a counter (0 = offer, needs key Res:17580 in the inventory), M2's reset to 1 shows the "follow" branch, and `QIS_OnEnter9010` deleted the key, so it can't be accepted again (G6) | G6 |
|
||||
| 9011 Jacquaires Vergangenheit | never | boss and target from `QIS_OnEnter9011` | ok |
|
||||
| main quests 1-81, 670 | never | started by trigger areas (`SelfTriggerQuest<N>`), no giver, so M1-M3 don't touch them; 31's giver is only set by `SetNPCState` (not in `g_givers`) | ok |
|
||||
| 65 Trockenlegung durch Zwergenstaudamm (main) | never | giver Res:18306 (Torfstecher, start script) is in `g_givers`. Vanilla his death leaves 65 unfinishable (61 is activated by `Exit65`); M2 brings him back, but resets `65` incl. bit 5 (pump switched by `SwitchPump65`); if the pump can't be used twice the quest is stuck (G3). Re-accept creates the rune Res:17569 again (G4) | G3 + G4 |
|
||||
| 210 Verschleppte Novizinnen in Räuberöhle | never | boss Res:17083 one-time (start script) | G3 |
|
||||
| 9000 Das Untotenlager | the shaman's drop is picked up while the quest runs | refusing makes the giver Res:17500 attackable by `SetNPCState 08 14` (not Morph, G8); killing him drops the item whose label opens the Khorad Nur gate (`ablehnensieg_goodie_wueste`). If M2 sees him as not hostile it skips `drop_goodie_wueste`: **no item, the gate (main quest 55's way) never opens**. Check `IsHostileTo` for `08 14` | G8, critical |
|
||||
| 5003 Opferritual | the hero refuses at the end (`nein5003`) | a story choice: the shaman Res:17699 and his tribe turn hostile (`SetNPCState 08 12`) and the quest fails. M1 restarts it with bit 6 kept, so the (now hostile) shaman would offer the choice again (G11 + G8) | G8 + G11 |
|
||||
| 5005 Pony Express | a time limit runs out (`losepe`) | `losepe` deletes the giver Res:17753 (spawned once by main quest label `NachOrkland55`) and all stations; after M1 the book points at nobody and the quest can't be taken again (G5/G6); `5005c` stays (G1) | G1 + G5 |
|
||||
| 6001 Die Invasion der Eiselfen | all elves of the camp die (`od_welfen6001`) | after M1 bits stay (G1); the elves (incl. giver Res:17706) are one-time, dead (G6); re-accept creates the invaders again (G4). Accept label starts with `SetNPCState`, so the giver isn't in `g_givers` (no M2/M3) | G1 + G4 + G6 |
|
||||
| 6002 Das Orklager | never | | ok |
|
||||
| 6003 Elfenbeschützer | the escorted elf Res:17750 dies (`lose6003`) | after M1 bit 3 stays (G1); the elf is one-time (G6); her dialog is set by `SetNPCState`, so she is probably not in `g_givers` (no M2) | G1 + G6 |
|
||||
| 2600-3599 generic quests (16 templates × 22 regions) | `DQ_RG<n>_..._LOSE_<id>` (and `_ABORT_` for escorts) | no giver (runtime-assigned NPC), so no M2/M3; M1 restarts them although `Quest_End` already copies them (G2) | G2 |
|
||||
|
||||
### Underworld (`bin\Addon\NetScriptCamp`)
|
||||
|
||||
Underworld quests keep their state in the NPCs' dialogs (`SetNPCState ...
|
||||
dialog"dlg_<npc>_<id>_<step>"`), rarely in variables, and most givers are
|
||||
spawned by `QIS_OnSetUp<id>` (run from the start script) without a dialog.
|
||||
|
||||
| Quest | Fails when | Finding | Class |
|
||||
|---|---|---|---|
|
||||
| 7612 Eskorte | escorted Nanoduk Res:19547 dies (`od_nanoduk`) | he is the giver and one-time (`QIS_OnSetUp7612`); after M1 nobody offers the quest (G6) | G6 |
|
||||
| 7614 Vermisstes Kind (Underworld) | the child Res:19549 dies (`od_erdriac`) | the giver's dialog is set to the "child is dead" step `_d` (only "ok"); M1 doesn't restore the accept dialog `_a`, so it can't be taken again (G12). The child comes from `QIS_OnEnter7614` | G12 |
|
||||
| 7617 Eskorte in den Süden | escorted giver Res:19586 dies (`od_7617`) | he is spawned with his accept dialog, so M2 catches his death: restart and respawn | M2 changes vanilla |
|
||||
| 7619 Tod den Toten | the giver Res:19545 dies (`od_threepwood_7619`) | his accept dialog is only set by `SetNPCState` in `QIS_OnSetUp7619` (not in `g_givers`); after M1 he is dead (G6) | G6 |
|
||||
| 9518 Unter der Herrschaft von Dämonen | the mother Res:19530 dies while following (`od_lose9518`) | after M1 bits 1/2/4 stay, the giver only answers "ok" (G1); re-accept creates mother and demons again (G4) | G1 + G4 |
|
||||
| 9520 Cookies Quest | the hero gives the cookies to Von Endlich, then the girl ends it (`btn_FinishLose9520`, gold for experience) | a story choice (G11); after M1 bit 4 stays, so the girl offers `btn_FinishLose9520` again and again (repeatable gold-for-experience trade) | G11 |
|
||||
| 10254 Der Hilferuf | the giver dies (`od_Auftraggeber_10254`) | the giver is spawned once when the letter is picked up (`ot_Brief_10254`); after M1 he's dead and the letter gone (G6). The 10250-10261 givers have named ids (`res:AUFTRAGGEBER_10254`, after the type argument), which `InstructionScriptId` doesn't read: none of them is in `g_givers` (G13) | G6 + G13 |
|
||||
| 10255 Panik vor Spinnen | never (its "lose" is a label name; the giver offers a restart himself) | | ok |
|
||||
| 10260 Das Rätsel in der Wüßte | the wrong chest is opened (`fillchest_chestQJ_0x`) | the giver's dialog is removed (`0a#0`); after M1 nobody offers it (G12) | G12 |
|
||||
| other Underworld quests (main 11-56, 7600-7630, 9511-9522, 9900, 11101-11110, 15001-15084) | never | main quests have no giver (untouched). Side quests: givers spawned with their accept dialog in `QIS_OnSetUp<id>` are in `g_givers` (7600, 7601, 7605, 7609, 7614, 7617, 7618, 7620, 7622-7624, 7626, 7630, 9511, 9513, 9515, 9518, 9520, 9521); a chain's later quests on the same giver (dialog by `SetNPCState`) are not. Their targets also come from `QIS_OnSetUp` (one-time), so M2 after a target died loses progress only where variables hold it (G3, rare here); named ids (`res:Sam1_Knappe`, `res:AUFTRAGGEBER_…`) are skipped (G13) | ok / G3 |
|
||||
|
||||
## Summary and proposed fixes
|
||||
|
||||
Counted over the side quests (Ancaria 151-2504, 9003-9011, 210, 65, the
|
||||
5003-6003 set and the Underworld quests that can fail): about a third are
|
||||
fine, the rest fall into the classes above. In order of impact:
|
||||
|
||||
1. **G8 critical, 9000** (Khorad Nur gate): verify by a log whether a creature
|
||||
set by `SetNPCState ... 08 14` is hostile to the hero (`IsHostileTo`). If
|
||||
not, M2 skips the shaman's death label and the gate never opens. Fix
|
||||
either way: treat a giver as "turned" when any of its quest's labels set
|
||||
`08 12`/`08 14` on it (extends `ScanGiverTurns` beyond Morph); that also
|
||||
fixes M3 for 1112, 1301, 1701, 2003, 2201, 2202, 501, 5003.
|
||||
2. **G1 reset on failure:** M1 resets the quest's own variables like M2
|
||||
(including the ones only start/region scripts initialise, with their
|
||||
initial values, e.g. 302a, 2001a = 1). Fixes most "giver only says ok"
|
||||
cases (152, 702, 703, 1002, 1003, 1302, 1303, 1401, 1404, 1602, 1803,
|
||||
1903, 9518, ...).
|
||||
3. **G11 failures that are part of a story or chain** (2402, 2403, 2502,
|
||||
5003, 9520): M1 must not restart a quest whose failure label also calls
|
||||
`SetUpQuest`/`finalestart`, or sets the giver hostile.
|
||||
4. **G2 generic quests:** M1 leaves 2600-3599 (and their runtime copies) to
|
||||
the game.
|
||||
5. **G6 restart without NPCs / G3 lost progress:** the bigger design
|
||||
question. Options: (a) on restart, respawn the quest's one-time NPCs from
|
||||
their spawn instructions in start/region scripts (like the giver), (b) keep
|
||||
the variables on M2/M3 (no progress loss, but the giver may answer with a
|
||||
running branch), (c) don't restart quests whose needed NPCs are gone and
|
||||
leave them failed. Recommendation: (a) for NPCs the quest's dialogs or
|
||||
death labels name, else (c).
|
||||
6. **G4 duplicates:** before re-running `QIS_OnEnter`, delete the quest's
|
||||
still-alive named NPCs/objects it is about to create.
|
||||
7. **G5/G7** (154, 301, 1502, 5005): M3 skips quests whose labels `DelNPC`
|
||||
their giver; M1 skips quests without a giver.
|
||||
8. **G9/G12/G13** (803, 9003/9004 `goodies`, 7614, 10260, named ids): lower
|
||||
priority; G12 needs the accept dialog put back (it is in the giver's spawn
|
||||
instruction or `QIS_OnSetUp`).
|
||||
|
||||
## Fixes (2026-10-30)
|
||||
|
||||
Request: "all, but leave 1, as i cant play for now" (2-8 above; G8 waits for a
|
||||
measurement in the game). Not yet tested in the game.
|
||||
|
||||
- `mods/questscript.cpp` (new) reads the script code once and keeps, per
|
||||
quest: the giver (spawned with the accept dialog, else given it by an NPC
|
||||
state instruction: the Underworld's `QIS_OnSetUp<id>`), its variables (set
|
||||
only by its labels, plus the one named after it: G9), what `QIS_OnEnter<id>`
|
||||
creates, the NPCs it needs (its labels set their state, don't create them),
|
||||
whether it morphs or deletes its giver, and the failure labels that end its
|
||||
story (`LoseQuest` with `SetUpQuest`/`ActivateQuest`, experience or gold, a
|
||||
call into another quest's label, or an NPC offering the quest turned hostile
|
||||
or set to 0 hit points: 1701 `ende1701`, 1703, 2402, 2403, 2502, 2504, 5003,
|
||||
9520). It also keeps the labels running (for `Quest_End`) and spawns NPCs
|
||||
once their bodies are gone.
|
||||
- `questfail.cpp`: at `Quest_Trigger` (first time) the quest's variables are
|
||||
kept ("questVariables" with the hero). A failed quest stays failed when it
|
||||
is a generic quest or a copy (G2), has no giver (G7), its failure ends the
|
||||
story (G11) or its giver / an NPC it needs is gone without a spawn
|
||||
instruction (G5/G6). Else the restart also: resets its variables to the kept
|
||||
values (G1; without them: 1 for the one named after the quest, 0 else),
|
||||
deletes what `QIS_OnEnter` created (G4), spawns dead needed NPCs and the giver
|
||||
again (G6, from region start labels, another quest's label or
|
||||
`QIS_OnSetUp`), and gives a living giver the accept dialog again (G12).
|
||||
After a load, failed quests restarted earlier get their variables reset
|
||||
(repairs saves stuck by G1).
|
||||
- `questgiver.cpp` uses the same scan; the load repair skips quests that
|
||||
delete their giver (G5); the giver comes back through `questfail::Restart`.
|
||||
- Not done: G8 (fix 1), G3 for progress held in one-time objects (2203's
|
||||
barrels), G10, G13 (named ids such as `res:AUFTRAGGEBER_10254`: the game's
|
||||
name table is unknown, those givers can't be checked or respawned).
|
||||
Reference in new issue
Block a user