# 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 book: all quests, unknown ones as "???" (2026-10-25) Request: every quest appears in the quest book; quests not yet activated show as "???", so a player knows how many quests an area holds without being told where they are. Notes: the quest table (g_quests 0xaa9e98, 0x124 per quest, game/engine/quests.h) lists all quests of the campaign, including the generic repeatable ones (ids 2600..3599, cloned by Quest_End) and DQ_ dynamic quests; which of them count for an area, and how the book groups by area, is still to be measured. ## Megamap zoomed view: markers shifted (2026-10-25) Reported: on the M map, clicking a location to zoom in shows the markers on the zoomed map wrong / shifted (megamap.cpp). ## Load / save progress screen: rock background (2026-10-25) Reported: the progress screen shown while loading / saving does not use the rock-wall background of the other menu screens yet (hud::RenderMenuFrame, docs/screens.md). The GDI progress screen is DxDriver7_LoadingScreen 0x6469d0 (1024x768, game/addresses.h); pictures PAK\loading0/1.bmp, loadgame.bmp, savegame.bmp, LoadingUW00/01.bmp.