Files
sacred_k/docs/todo.md
T
khallaandClaude Opus 5.5 7ec0fa2b8e Quest givers: givers killed as enemies keep their death script
"Familienbande" (702) turns its giver hostile and wants him killed; the
giver death rule restarted it instead. A giver hostile to the hero at death
now runs the game's label, and the load repair skips quests whose script
changes their giver's creature type (opcode 0x4f). Deferred notes: frame
drops while walking, Eingraben clearing slows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 18:57:43 +01:00

287 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# To do
## Fixed: aura visuals missing after loading (2026-10-15)
Saving marks effect objects (cObjectFX) dead; loading keeps the buff but drops
the aura effect (type 842) that follows the hero. `src/mods/aura_restore.cpp`
recreates it after a load for Heldenmut (0x3f7) and Klingenblick (0x3f8). Spell
auras (Steinhaut, Lichtschild, ...) use other effects; the user confirmed on
2026-10-17 that their visuals are back after loading too.
## Data-driven arts instead of hardcoded art ids
Asked 2026-10-15: naming single arts as constants (`kArtHeldenmut`,
`kArtFlammenwerfer`, ... in `src/game/engine/arts.h`) does not scale. Mods
should decide by an art's properties, read from the game's own data:
- the definition tables `g_spellDefs` (`0x950a38`, 71 x 0x94) and
`g_combatMoveDefs` (`0x94ddb0`, 95 x 0x78): id, icon name, launch type,
usable mounted, ... (`tools/arttable.mjs` dumps them; most fields unnamed);
- map the remaining fields (regeneration group, lasting effect / aura,
duration, ...) and expose them as an `ArtInfo` lookup in `src/game/`;
- where the game itself hardcodes ids (e.g. the arts that always count as
magic in `cCreatureArts::AddGroupRegen`, the "already active" switch in
`IsValidArtTarget`), keep one table of those ids with the reason, instead of
named constants spread over the mods;
- optionally an own data file (JSON next to the DLL) for mod-side settings per
art, if we need values the game does not have.
## Art ranges: scaling and indicators
Asked 2026-10-15 (after making periodic aura hits strike everything in
range, docs/aura-hits.md):
- art ranges should scale with the art's level, and possibly with new
attributes;
- possibly show a range indicator (e.g. a ring around the hero for auras, or
at the cursor for aimed arts).
Known so far: the periodic-hit aura (effect kind 0x12) uses
`(cCreatureArts +0x56 + 20) * 10` world units, measured from the owner with
`cCreature::DistanceTo` (`0x536f20`); what +0x56 is (level? a stat?) is not
mapped yet. Other arts' ranges are not mapped. Fits the data-driven arts
item above (range as a property of an art, one place to compute it).
## Rename life leech to "omnivamp"
Asked 2026-10-15: life leech (property 0x349, "Lebensentzug") becomes
"omnivamp". To do: the in-game texts (item property, tooltips, character
window). The leech code is the game's (`0x5707a4`.., property 0x349, in the
damage code `0x56aff0`); it credits the hit's attacker (order +0x1c). Omnivamp usually means healing from all damage,
not only weapon hits: aura hits (docs/aura-hits.md) now name their attacker
so the game applies it;
other damage sources (spells, combat arts' extra hits, damage over time) may
follow.
## Map and map zoom in widened views
Reported 2026-10-15: the map (and zooming it) does not support the widened
render sizes yet. 2026-10-16: TAB map fixed (viewport shifted), M map spans
the render width (docs/hud.md, "Large map"), zoomed view and its markers included.
Confirmed in-game 2026-10-16.
## Quest dialog glitches in widened views
Reported 2026-10-15: accepting a quest, the dialog window "kept glitching"
and button clicks were not detected correctly. Probably the HUD layer
(src/mods/hud.cpp: windows shifted while they render / handle events): the
dialog may not be covered, or shifted twice. Details asked from the user.
## WASD walks around walls (caves)
Reported 2026-10-15: in caves WASD movement behaves "as if the player tries
to find another way to the target location if a wall comes up". WASD sends a
walk order to a point 300 world units ahead (docs/wasd.md); when that point is
behind a wall the pathfinder plans a detour. Idea: find the game's straight
line / walkability check and shorten the target when the line is blocked (or
stop / slide along the wall). Related to the pathfinder item above.
## Esc closes an open dialog first
Asked 2026-10-15: with any dialog open (quest, trader, inventory, ...), Esc
should close that dialog instead of opening the game menu (ESC menu,
`cUI_EscMenu`). Esc is handled in the engine / UI manager hotkeys
(docs/wasd.md: engine `0x618130`, UI manager `0x757120`).
## In-DLL smoke tests (later)
A test mode inside the mod DLL, started by an ini setting or command-line flag,
so builds can be checked without play-testing and without driving the real
mouse/keyboard like `tools/autotest-load.ps1`:
1. load a fixed test save;
2. play scripted input through the existing hooks (keys, casting arts, weapon
set switches, save + reload);
3. take back-buffer screenshots at checkpoints and log checks to
`sacredK.log` (aura effect present after reload, slot 6-7 inventories
survive a save, ...);
4. exit the game.
## Better pathfinder (mouse clicks and monsters)
Replace the game's pathfinding with a more reliable and efficient one, for
click-to-move and for monster AI. What we know so far:
- Walk orders are `cEvent_creature` command 4 with a ground target (+0x18/+0x1c),
sent through `cEngine::SendCreatureOrder` (`0x6170d0`), which snaps the
target to a walkable point (`0x616b70`) and hands it to
`cCreature::ReceiveOrder` (`0x52e400`, vf18, ~6400 decompiled lines).
- Far targets (~2000 world units) are rejected or followed badly.
- Still to map: the path search itself, the sector/tile collision data it
reads, and how monster AI issues its moves.
## Key bindings moved for WASD movement (temporary)
W, A and S were game hotkeys. With WASD movement (`src/mods/wasd.cpp`) their
actions moved to other keys for now; choose final bindings (and update the
in-game texts/tooltips that name the old keys):
| Key | Action | Temporary key (sacredK.ini) |
|---|---|---|
| W | potion kind 3 (`cEngine::UseActionSlot`, like Q/E/R/B/Space) | game potion keys switched off; `[keys] Potion1-5` (docs/options.md) |
| A | pick up items nearby (creature event 0x113) | Q (`[keys] PickUp`, 2026-10-17; was V) |
| S | save game window (`UI_WND_SAVEGAME`) | K (`[keys] SaveGame`) |
| D | unbound | - |
## Hard-coded game keys left (2026-10-19)
Noted after the key bindings page (docs/options.md): these game keys are
still hard-coded, not on the page. Each would go the way M / Tab / Alt went:
switch the game's key off at its source (switch index byte or compare), add
a binding that calls the same game code.
| Key | Where | What (as read, not all measured) |
|---|---|---|
| I / F / C | UI manager letter switch (`0x757120`, cases at index bytes `0x75868c` + char − 'C') | inventory window with tab 1 / 2 / 3 (`cCommand_onInvOpen`; again: close) |
| L | same | quest book `UI_WND_QUESTBOOK` toggle |
| H | same | toggles UI manager flag 0x200 (unmeasured) |
| T | same | toggles UI manager flag 0x1000 (unmeasured) |
| N | same | network info `UI_WND_NETINFO` (multiplayer only) |
| O | same, only while the options window is open | closes options (applies them) |
| S | same (`0x757775`) | save game window; works only while S is not bound (it is: *Nach unten*). *Spiel speichern* already calls this code. |
| A | engine `cEngine::ReceiveEvent` (`0x618130`, compare at `0x6188e7`) | pick up items nearby; same situation as S (A is *Nach links*); *Gegenstände aufheben* calls the code |
| P | engine (compare at `0x6188f0`) | pause, single player only |
| `` ` `` / ^ / `\` (key codes 0x60, 0x5e, 0xdc) | engine (`0x6188cf`), UI manager (`0x75758c`, `0x75759c`) | console |
| Esc | engine, UI manager `HandleEsc` | closes windows / ESC menu (escape.cpp builds on it) |
| Shift + Space | engine potion table (off with the potion keys) | - |
Digits 0-9 are taken by the skill keys (input.cpp `Reserved`). Bound keys are
swallowed before the game sees them, so a game key only acts while it is not
bound to something else: rebinding *Nach links* away from A brings back the
game's A (pickup), same for S. Individual windows may have more keys of
their own (not surveyed).
## Potion stacks
Asked 2026-10-17 (after the potion counts on the bottom bar,
`src/mods/potioncounts.cpp`): potions of the same type (e.g. minor healing)
stack in one inventory cell, up to 20 per stack (a full stack starts a new
one). Drag, sell and drop move the whole stack, as with any other item. The
counts on the potion slots then add up the stacks. In progress, see
docs/item-stacks.md (open: sale price per stack, splitting on the ground).
## Walking animation after loading (2026-10-17)
The hero sometimes plays a walking animation after a save game load while
standing still. Not reproduced yet: a load log (hero mode, action, animation
fields, orders) showed nothing unusual; right after a load the game itself
sends one walk order (0x4) while the hero is idle. Measure again when it shows.
## Multiplayer with characters (2026-10-19)
Characters became one file each with a world per difficulty
(`docs/characters.md`); vanilla multiplayer picks exported `Heronn.pax`
heroes, which no longer exist. Later: give multiplayer the shared hero of a
character file (the session's hero file +0x3a3c, as `SelectHeroSlot` does),
and decide what a multiplayer game does to the character's progress.
## Characters: open parts of the rework (2026-10-20)
From the characters rework (`docs/characters.md`, request of 2026-10-19):
- **Unlock difficulties by story completion.** Bronze and Silber stay open;
difficulty d >= 2 opens when the story on d - 1 is completed. The counters
are one byte per difficulty in cStatsManager +0x5704 (read 0x424be0) and
travel in the save header (+0x88..+0x98) and the hero file. Done
2026-10-20 (docs/characters.md).
- **Autosave interval in the options window.** Done 2026-10-20: Allgemein
page, "Spielstände" frame (docs/options.md).
- Quickload (row 0, `GAME00.PAK`) does not know characters; not needed
(user, 2026-10-20).
## Two saves in a row (2026-10-20, not reproduced)
Once two real saves ("saved", not "autosaved") went into the same character
1.8 s apart, about 77 s after loading, with the timed autosave off. Save
flag 0x40 is set in cEngine::ReceiveEvent at 0x618876 (quicksave),
0x618f08 and 0x6190c5 (save event 0xf: +0xc row, +0x18 autosave flag). A
log of the event that sets the flag (dwords 0..9) did not catch it again;
add it back if it shows.
Once (2026-10-20, not reproduced) an autosave seemed to fire right after a
new world started through the hero chain (Character08: hero world loaded,
then the new world). The log of that run had no save at all; the timed
autosave counts from the game start (OnGameStart).
## Savegames screen redesign ("Spielen")
Asked 2026-10-20: redesign the load window (cUI_Savegame, the "Spielen"
screen, characters.cpp): show a render of the selected character, use the
space far better. No 16:9 artwork exists for the game (user, 2026-10-20):
we design our own UIs, using the width beyond the 1024 frame (now drawn in
a centred 1024x768 viewport with black sides, hud.cpp FrameScope). Design
for 16:9 (1920x1080, 1365x768 UI units), not ultrawide (user). Screen done
2026-10-20 (docs/characters.md, "Spielen screen"; docs/screens.md). Hero
in 3D done 2026-10-20. Open: list scrolling beyond 9 characters, larger
heading font.
## Fine-tuning the Spielen and options screens (2026-10-21)
The user is very satisfied with the menu rework for now (rock background on
all menu screens, centred menu frame, logo, Spielen screen with the 3D
hero), but both the Spielen screen and the options window still need a lot
of fine-tuning. Details to be collected when we get to it; known so far:
list scrolling beyond 9 characters, larger heading font, the options
window's layout in the width beyond its 1024 frame.
## Quest NPCs after the quest (2026-10-25)
Request: NPCs related to a quest are drawn white on the minimaps and always
turn towards the player; once their quest is finished they should stop
turning and be drawn blue (like other NPCs). Done 2026-10-25
(docs/quests.md, "Quest NPCs after the quest").
## Audit how every quest can fail (2026-10-26)
Request: "at some point we need to check ALL the quests and how they possibly
can fail". Context: "Jagd auf die Wilderer" (1501) - the giver's death label
`ex1501` sets the quest variable and runs `tot1501`, which ends the quest as
solved without the reward once the poachers are dead; her survival is not
needed for the quest itself. `src/mods/questgiver.cpp` currently skips a dead
giver's label, restarts the quest and respawns the giver. Plan: from
FunkCode.bin (label table in Vectoren.bin, 0x54-byte records: name, +0x40
code offset, +0x44 size, +0x48 quest; instructions {u16 op, u16 size, args})
list per quest: death labels given to NPCs (spawn / follow instructions with
a 0x05 label), the labels that end it (opcode 0x0f) or lose it, and which
NPCs must survive (escorts). Then decide per kind: respawn the giver only,
or restart the quest.
## Quest giver death rule untested (2026-10-26)
`src/mods/questgiver.cpp` restarts a running quest whose giver died and
spawns the giver again at her start (docs/quests.md, "Quest givers come
back"). Built and checked against the scripts, not yet seen in the game: test
with an escort whose giver dies (e.g. "Jagd auf die Wilderer" on the
Gladiator, or "Hetzjagd"). Borf's case (the quest ended without the reward)
was repaired once by hand.
## Inventory drawn without its dark backgrounds (2026-10-25, intermittent)
Reported twice: on opening the inventory the item list had no dark
background behind the grid, and the tab texts had an odd background colour.
Looks like render state (texture / blend / colour) left behind by an earlier
draw; not reproduced yet. To find out: what was open or shown just before.
Possibly related (2026-10-25, once): right after a game start the main menu
texts were drawn as solid gold blocks (the gold text texture without the
font's letter mask). Gone after a restart; Alt+Tab does not cause it. The
log showed nothing unusual (all hooks and patches applied).
## Frame drops while walking (2026-10-27, deferred 2026-10-30)
Reported 2026-10-27. Measured 2026-10-29 (about 54 min, temporary timing in
the Flip, engine tick and map border, since removed): 549 frames over 40 ms,
mostly 0-1 per 10 s, worst 833 ms. Present (Flip) was slow only once; the
time goes to the game's own engine tick (227 ticks of 18-70 ms). Our tick
callbacks were slow only at the 10-min autosave. The map border is drawn only
while the map is open, so it is not the cause. Next step if resumed: time the
parts of the game tick (sector streaming while walking is the main suspect).
Deferred by the user 2026-10-30.
## Eingraben clears slows, roots and stuns (deferred 2026-10-30)
Step 3 of Eingraben (docs/dwarf-arts.md): cast clears slowing, rooting and
stunning effects on the hero. The effect kinds are unknown; plan: temporary
log of the effects added to the hero while the user gets slowed or frozen,
then remove those kinds on cast. Deferred by the user 2026-10-30.