# 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** (now only `sacredK.ini` `[characters] AutosaveMinutes`). - **Quickload (row 0) does not know characters.** Ctrl+Z saves into the current character, but the quickload event (0x116, engine +0x68 = row, flag 0x200) loads `GAME00.PAK`, which is not listed; make it reload the current character's world (or its newer autosave). ## 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. ## 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. The user looks for 16:9 artwork so the screens can be widened beyond the 1024 frame (now drawn in a centred 1024x768 viewport with black sides, hud.cpp FrameScope).