Files
khallaandClaude Opus 5.5 b452558122 Map: zoomed-view symbols centred, 10x reveal and enemy range; progress screen on the menu background
- Megamap / TAB map zoomed view: heroes' markers and the other symbols
  (integer 200h centre immediates) follow the view's centre.
- Map reveal: the hero's reveal stamp scaled 10x (mods/mapreveal.cpp,
  docs/map-reveal.md); creatures on the zoomed map shown within 10x the
  sight range.
- Load / save progress screen drawn on the rock background across the full
  width, the picture blended over it (mods/loadingscreen.cpp); the classic
  1024x768 frame is gone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 02:07:59 +02:00

6.1 KiB

16:9 menu screens

Request (2026-10-20): the game's menu screens are laid out for 1024x768; we design our own UIs for them. There is no 16:9 artwork for the game, so the background is our own, and the approach is shared by all menu screens. The background (user, 2026-10-20: "textured dark", the flat gradient looked black): the options window's rock wall, GUI_OPTION_BACKGROUND<row><column>.TGA (4 x 3 tiles of 256), scaled to cover the render target, tinted down, shaded towards the bottom and the sides. Game textures by name: game/ui/texture.h, drawn with game::DrawTextured (game/ui/draw.h). Target: 16:9, 1920x1080, which is 1365x768 in UI units; wider screens only get more background at the sides (not designed for ultrawide).

How a screen works

  • mods/screen.{h,cpp}: a screen replaces a full-screen window's drawing and mouse handling. Its render hook calls screen::Render(window, device, body, context): the background across the whole render target, then the body in canvas coordinates (1365x768, centred: hud::RenderCanvas, the HUD layer's offset machinery with Anchor::Canvas; drawing, the cursor and the window's hit tests shifted alike). Mouse events go through screen::Handle (hud::HandleCanvas). Keys stay the window's.
  • The main menu thread renders the full width (no 4:3 frame any more).
  • Parts: screen::Panel (dark backdrop and the game's frame, cUI_Frame, game/ui/frame.h, made anew when its rect changes), screen::Button (a button of the game's with the look of one of the window's, game::NewButtonLike), screen::Text, screen::Fill, screen::DoubleClick. Spacing constants from measurements: frames reach 0x20 beyond their rects and need a height of about 0x40, buttons reach 0x21. Frames are built of 64-unit pieces: widths and heights in steps of 64 (screen::kFrameStep), other sizes leave gaps (screenshot 2026-10-20).
  • Fonts (logged 2026-10-20): font 0 is another class (no line height field); the TrueType fonts 1..7 have line heights 20, 19, 25, 31, 25, 28, 13. Screens use font 1; 4 or 6 would suit headings.
  • Inside the canvas scope the HUD layer does not stretch "full 1024 layout" quads (g_canvasScope).

Main menu frame (2026-10-20)

Request: the background on all screens, the main menu's and the options window's own pictures removed.

  • cUI_Manager's UI render (0x7587b0, hooked in mods/screen.cpp) on the menu thread: the background first, then hud::RenderMenuFrame runs the render with drawing shifted by (render width - 1024) / 2 and a viewport on the frame (3D parts). Windows inside draw in frame coordinates (their own HUD scopes are nested, so they do nothing).
  • Mouse positions are given to the game in frame coordinates: the borderless mod's ToGame subtracts hud::MenuFrameOffsetX. The cursor sprite (cMouseCursor::DrawItem 0x6555e0, drawn after the UI) is shifted by drawing only.
  • While a 16:9 screen is shown the frame is not shifted (offset 0): the screen draws itself across the width.
  • Full-screen windows in a game (options, hud::RenderFramed) get the background beside the frame instead of black.
  • The windows' pictures are left out by texture: the HUD layer tracks the texture bound to stage 0 (SetTexture, device vtable 35) and skips quads drawn with a hidden one (hud::SetHiddenTextures). Logged on the menu thread (texture ids requested from the cache, by caller; names by trying the names in the texture pak): main menu GUI_UW_OPTION1..12 + UI_MAIN_SKY, options UW_OPTION_1_01..12. This install uses the Underworld versions; the Ancaria ones (GUI_OPTION1..12, ...) were not seen and are not listed.
  • The main menu's 3D scene (sky UI_UW_MAIN_CENTER, water with the SACRED logo UI_MAIN_REF; render 0x75e620 on the scene object 0x75df10) is called from cUI_MainMenu::Render (0x7122c0) at 0x712bd9; that call is redirected to an empty function. cUI_Character (0x70f41b) still draws it.
  • Logo top left (2026-10-21), 48 from the edges, 124 high: FX_SACREDLOGO.TGA, the emblem (horns around a ring of runes) glowing blue on black without alpha, drawn added (blend ONE/ONE, game::DrawTexturedAdded) as the game's effects draw it. Other candidates: GUI_MAIN_LOGO (plain golden lettering), SACREDSYMBOL01/02 (model atlases), the emblem on the loading pictures (PAK\loading*.bmp, not in the paks). Screens may overlap it.

Screens

  • Spielen (the load window, cUI_Savegame): docs/characters.md, "Spielen screen".

Fixes (2026-10-21)

  • The main menu came back unframed (old pictures, frame at the left) after a game: the set of shown 16:9 screens kept a window of the in-game UI that was destroyed while shown. Now only screens drawn on the menu thread count, and an entry expires after 2 menu frames without being drawn (screen::BeginMenuFrame).
  • Dialogs over a 16:9 screen in the main menu (e.g. "Spielstand laden?") sat at the left with the dimming 1024 wide: hud::OffsetFor gave every window offset 0 while the menu showed. Now only while the menu frame is drawn centred (it shifts the windows itself); otherwise dialogs are centred and their full-layout dimming stretched, as in a game.

Load / save progress screen (2026-10-25)

Request: the progress screen shown while loading / saving should use the menu screens' background. The game's screen (DxDriver7::LoadingScreen 0x6469d0, thiscall (progress, text)) draws with GDI into the back buffer's DC (surface +0xbc, GetDC vf 0x44 / ReleaseDC vf 0x68): the 1024x768 picture (HBITMAP +0x200) at 0, 0, the bar (+0x204 / +0x208) and the text at y 700, then Flip; it redraws only when the bar moves. Until now it was presented as a 1024x768 "classic" frame scaled to the monitor.

mods/loadingscreen.cpp: before the game's drawing, DrawBackground across the whole render width in a scene of its own (DxDriver7 BeginScene 0x646f50 / EndScene 0x646fd0); the game's GDI drawing is moved to the centred 1024 frame with SetViewportOrgEx on the back buffer's DC, caught in CreateCompatibleDC(hdc) which the game calls right after getting it. Every frame is now presented at the full render width (borderless.cpp has one layout).