Files
sacred_k/docs/todo.md
T
khallaandClaude Opus 5.5 5bccb0734e Characters: one file per character with a world per difficulty
- CharacterNN.sacredK holds the shared hero and one world per difficulty,
  plus an autosave file; the game works in save\characters\_work
- Load window: one row per character, a difficulty dialog on Laden
  (worlds, newer autosaves, "(neu)" starts a new game with the shared
  hero), Umbenennen, delete moves the character to characters\deleted
- The world keeps its own portals and hero position when the shared hero
  is put on
- K and the Esc menu's "Speichern" save directly (quicksave path)
- One-time migration of the old save rows and exported heroes, after a
  backup
- Startup no longer hangs in the game's foreground loop (0x810af0)
- Text overrides apply to our own text ids too; shared cUI_Button2
  helpers in game/ui/button.h

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-20 01:41:42 +02:00

10 KiB
Raw Blame History

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. Today every difficulty up to the highest played one is offered (and Silber).
  • Reset a difficulty. Remove one world from a character (the shared hero stays); a button / dialog entry in the load window.
  • Remove the export / import UI. The Esc menu's "Exportieren" and the character screen's import (cUI_Character mode 5, docs/char-export.md): characters replace exported heroes.
  • Silent autosave every 10 minutes (a setting later) into the autosave file, without the busy dialog, like the direct save (SaveOnTick) but marked as an autosave.
  • 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).