Quest NPCs turn blue and stop facing the hero once their quest is done
A dialog's quest comes from the game's script labels ("Dialog:<name>",
quest at +0x48). When that quest is done and not in progress, IsQuestNpc
answers false (blue on the minimap) and the idle action's type check
skips the turn towards the hero.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
9bc557cd95
commit
c0eedbce7f
6 files changed
+235
-1
No files matched your search
@@ -101,3 +101,53 @@ ShowCompleted`, default 1) and calls `cUI_Book::Rebuild` 0x6b1670 (thiscall,
|
||||
no arguments; keeps tab and page if the page still exists, else ours clamps
|
||||
it). Off leaves out solved entries (main and side) and areas whose quests are
|
||||
all known and solved; failed quests stay (restartable).
|
||||
|
||||
## Quest NPCs after the quest (request 2026-10-25)
|
||||
|
||||
Request: NPCs related to a quest are drawn white on the minimaps and turn
|
||||
towards the player; once their quest is finished they should be drawn blue
|
||||
and stop turning, like other NPCs. `src/mods/questnpc.cpp`.
|
||||
|
||||
Measured:
|
||||
|
||||
- The zoomed map view (0x6cc950, call at 0x6cec6b) draws a creature white
|
||||
when `cCreature::IsQuestNpc` (0x54fa30) is true: creature flags +0x200 bit
|
||||
0x100 / 0x200 (escorted NPCs, set by the quest manager 0x46ae54..), or a
|
||||
dialog +0x245 in 1..59999 whose type (`cDialogManager::DialogType`
|
||||
0x49a180, record +0x48 of the 0x50-byte records at manager 0xaaaf00
|
||||
+0x755c, name at record +4) is below 50.
|
||||
- Some quests move their giver on to dialog 0 at the end
|
||||
(`DLG_15074_START` type 10 → `_OFFEN` 126 → `_ZIEL` 11 → 0); many leave it
|
||||
on the quest's dialog: `auftrag10`, `auftrag2411`, `AuftragEnde202`,
|
||||
`auftrag303` kept their dialog with the quest done (flags 3, book entry
|
||||
solved).
|
||||
- The turning, found with a hardware write watch (DR0) on the facing +0x70:
|
||||
the idle action (`cCreature::IdleAction` 0x544700, Think's action 0
|
||||
handler) turns every creature with a dialog +0x245 in 1..99999 towards the
|
||||
local hero each Think step (0x546334..0x5463d5, `cCreature::SetDirection`
|
||||
0x44df60 → 0x44ddc0), unless its type is of kind 4 in the type table
|
||||
(`TypeTable_IsKind4` 0x4265c0, call at 0x546357) or object flag +0x14 bit 2
|
||||
is set. So every NPC with a dialog turns, not only quest NPCs.
|
||||
|
||||
- Script labels (vector 0xaa9688..0xaa968c, 0x54 bytes each; quest scripts
|
||||
and dialog answers are indices into it, run by `Script_RunLabel` 0x46bd80):
|
||||
name +0, the quest the label belongs to +0x48 (-1 none; the label only runs
|
||||
once that quest is triggered, 0x46bf11). Each dialog has a label
|
||||
`Dialog:<dialog name>` (logged 2026-10-25: `Dialog:rg1_goodie1_auftrag`
|
||||
9004 Vermisstes Kind, the Aufgeregter Bauer; `Dialog:auftrag_wueste` 9000;
|
||||
`Dialog:auftrag11a1` 1101; `Dialog:DLG_15003_ZIEL` 15003;
|
||||
`Dialog:geschlossen101` none).
|
||||
|
||||
The quest of a dialog is its label's quest (`game/engine/quests.h`, script
|
||||
labels), looked up by the dialog record's name; cached per dialog. A first
|
||||
version read the quest id from the numbers in the dialog's name; that missed
|
||||
dialogs without one (the Aufgeregter Bauer's `rg1_goodie1_auftrag`, user
|
||||
report 2026-10-25) and misread others (`auftrag11a1`). When that quest
|
||||
exists, is done (flag 0x2) and not in progress (0x4):
|
||||
|
||||
- the hook on `IsQuestNpc` returns false (blue on the minimap);
|
||||
- the type check call at 0x546357 is redirected to a thunk that also answers
|
||||
true, so the idle action skips the turn.
|
||||
|
||||
Dialogs without a quest (healers, closed shops: `geschlossen101`,
|
||||
`heilen_global`) stay as the game has them.
|
||||
Reference in new issue
Block a user