Quests: main quest items no longer refused, restart resets bit-field variables

AddMainQuestItem refused every new main quest item once the list held an
entry with script id 0 (scripts give such items); the Goldbeeren of quest
402 were picked up and lost. The script id test is patched out.

Quest variables are bit fields (op 0x44 sets a bit): the quest giver
restart now writes the values directly, 0 and 1 (available) for the
variable named after the quest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
khallaandClaude Opus 5.5 committed 2026-10-28 00:07:06 +01:00
1 parent e539cab604
commit 55e48dd302
6 files changed
+126 -20

No files matched your search

+38 -3
View File
@@ -196,7 +196,8 @@ Dialogs without a quest (healers, closed shops: `geschlossen101`,
4 trigger area, 0x0f end quest, 0x14 start quest (#id), 0x17 named
position, 0x1a dialog text, 0x35 book text, 0x3a / 0x42 if / else if
(0x49 var == n, 0x40 "@npc"), 0x3c dialog answer (text, label), 0x3f
compass, 0x44 set variable, 0x48 move NPC, 0x56 dialog state.
compass, 0x43 / 0x44 / 0x45 / 0x4b variables (see below), 0x48 move NPC,
0x56 dialog state.
- Script NPC names: "Res:<n>" is a script id (object +0x3c, `0x44a390`); the
quest manager maps it to the object (`0x464ec0`, map +0x7668); a spawn sets
the entry.
@@ -227,8 +228,8 @@ load we need a repair ... if not completed or correctly running".
`mods/questgiver.cpp`: a quest's giver is the NPC whose spawn instruction
carries a dialog with an answer that accepts the quest (85 givers). When a
label of a running quest runs for its dead giver, it is skipped, the quest
restarts (failed entry at the giver, the variables only its labels set back to
0), and once the body is gone the spawn instruction runs again. After a load,
restarts (failed entry at the giver, the variables only its labels set back:
0, the one named after the quest 1), and once the body is gone the spawn instruction runs again. After a load,
an accepted quest (flag 4) without its giver gets the same. Not yet seen in
the game (the escort of "Hetzjagd" arrived alive); see `docs/todo.md` for the
audit of how quests can fail.
@@ -237,6 +238,40 @@ Lesson (2026-10-26): flag 1 means available, not running; a first version
took it for running and reset 16 available quests and spawned their NPCs on
Borf (repaired once, then saved).
## Quest variables are bit fields (measured 2026-10-28)
Found while repairing "Kräuter für Kräuterhexe" (402; the user knows it as
Windgeflüster). Variables live in the quest manager's vector +0x7550 /
+0x7554 (0x24-byte entries: name[0x20], value +0x20; `game::ScriptVariable`).
Script writes: 0x43 sets the value, 0x44 sets bit n (0x49bb30: value |= 1 <<
n), 0x45 clears bit n (0x49c450), 0x4b adds n (0x49cc20). Conditions
(`Script_Condition` 0x498aa0): 0x49 bit n set, 0x4a bit n clear (logged "if
IsNotVarBit"), 0x48 value == n; a missing variable is false. The variable
named after a quest has bit 0 while the quest is available: all 87 quests not
yet accepted in a dwarf save had value 1, and nothing in the quest's own labels
sets it. Quest 402: accepting sets bit 1, the berries bit 2, the reward bit 3;
the giver's dialog offers the quest on bit 0.
The quest giver restart first ran 0x44 with 0 ("variable = 0"), which set bit
0 and cleared nothing: the giver kept saying "Zögerst du in deinen Taten?".
A reset to 0 then matched no dialog branch at all. Now the value is written
directly: 0, or 1 for the quest's own variable. Confirmed 2026-10-28.
## Main quest items refused (request 2026-10-28)
"I cannot finish the Quest Windgeflüster." The berries (type 6029) are an item
`Region4Init` places once on the ground near the Goldbeerenbusch (op 0x5e,
pickup label `take402`); picking it up logged "cInventoryEntry::addMainQuestItem()
Already has mainQuestItem(6029)" and the item was gone.
`cInventoryEntry::AddMainQuestItem` (0x5d8240, thiscall (type, script id,
notify)) keeps {type, script id} pairs and refuses a new item when an entry
has the same type or script id 0 (0x5d83c6); scripts that give an item
without a "Res:" id add it with 0 (0x486bd8). The dwarf held {4609, 0}, so
every later main quest item was refused (a bug of the original).
`mods/questitems.cpp` removes the script id test. The save was repaired once
by running `take402` for the hero after the load (quest accepted, bit 2
missing); the quest then finished. Confirmed 2026-10-28.
## Escorts never left behind (2026-10-26)
"I have lost a follower NPC from the quest 'Die Sklaven der Orks', it's no