Files
sacred_k/src/game/ui/tabs.h
T
khallaandClaude Opus 5.5 838b1aa491 Options: tabs Allgemein / Beute / Tastenbelegung with key bindings
- Options window in three tabs; the auto-pickup settings move to Beute;
  sliders move with their page; black sides like the save game screen.
- Tastenbelegung: every binding settable (click, press key; Esc cancels,
  Backspace unbinds), "Alle zurücksetzen" as a game button, saved on OK.
- Potions bindable (default unbound), named by the game's potion texts; the
  game's own potion hotkeys are off; bar tooltips show the bound key.
- Map (M), overview map (Tab, held) and labels (Alt, held) bindable; the
  game's own M / Tab / Alt handling is switched off.
- Save game key calls the game's save window code instead of a posted key.
- Teleportationstrank: fixed text replacement from startup (also the
  Ausdauertrank items, potion kind 5 as well).

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

90 lines
3.7 KiB
C++

#pragma once
// cUI_TabSheet (0x80 bytes, vtable 0x895258): a control with tab headers
// (the inventory's "Rucksack" / "Kampfkünste" / "Combos"). Its cUI_TabControl
// at +0x78 (0x98 bytes, constructor 0x7278f0) holds the tabs: a vector of
// 0x18-byte entries at +0x78/+0x7c {text id, rect (+4 x, +8 y, +0xc w|h),
// header control (+0x10), page (+0x14)}, the active index at +0x84 (u16).
// Header controls: +0x24 x, +0x28 y, +0x2c w|h (relative to the sheet).
// Layout (0x729210) puts the headers in a row above the sheet; a click on a
// header reaches SetActive, which hides the old page and shows the new one
// (page vf24(show)). Selected / hover / normal look is the game's own
// (cUI_TabControl::Render 0x728090).
#include <cstddef>
#include <cstdint>
#include "game/ui/text.h"
namespace game {
constexpr size_t kTabSheetSize = 0x80;
constexpr size_t kTabSheetControl = 0x78; // cUI_TabControl*
constexpr size_t kTabControlTabs = 0x78; // entries begin; +0x7c end
constexpr size_t kTabEntrySize = 0x18;
constexpr size_t kTabEntryRect = 0x4;
constexpr size_t kTabEntryHeader = 0x10;
constexpr size_t kControlRect = 0x24; // a control's rect (x, y, w|h), relative to its parent
// The header art's height (left piece; static data filled when the UI loads).
constexpr uintptr_t kTabHeaderArtHeight = 0x009ed17c;
// The game's operator new (0x8485e2, cdecl): controls the UI deletes itself
// must come from it.
inline void* GameNew(size_t size) {
return reinterpret_cast<void*(__cdecl*)(size_t)>(0x008485e2)(size);
}
// cUI_TabSheet::cUI_TabSheet (0x728ed0, ret 0x18): (name, rect by value,
// parent, 5); the inventory passes 5 as the last argument.
inline void* NewTabSheet(const char* name, UiRect rect, void* parent) {
void* sheet = GameNew(kTabSheetSize);
using ConstructFn = void*(__fastcall*)(void*, void*, const char*, UiRect, void*, uint32_t);
return sheet ? reinterpret_cast<ConstructFn>(0x00728ed0)(sheet, nullptr, name, rect, parent, 5) : nullptr;
}
// cUI_TabSheet::AddTab (0x7290d0, ret 8): (text id, page control).
inline void AddTab(void* sheet, uint32_t textId, void* page) {
using AddFn = char(__fastcall*)(void*, void*, uint32_t, void*);
reinterpret_cast<AddFn>(0x007290d0)(sheet, nullptr, textId, page);
}
// cUI_TabSheet::SetActive (0x7291d0, ret 4).
inline void SetActiveTab(void* sheet, uint16_t index) {
using SetFn = void(__fastcall*)(void*, void*, uint32_t);
reinterpret_cast<SetFn>(0x007291d0)(sheet, nullptr, index);
}
inline uint8_t* TabControl(void* sheet) {
return *reinterpret_cast<uint8_t**>(static_cast<uint8_t*>(sheet) + kTabSheetControl);
}
constexpr size_t kTabControlActive = 0x84; // u16
inline uint16_t ActiveTab(void* sheet) {
const uint8_t* control = TabControl(sheet);
return control ? *reinterpret_cast<const uint16_t*>(control + kTabControlActive) : 0;
}
// The tab entries of a cUI_TabControl.
inline uint8_t* TabEntries(uint8_t* control) {
return *reinterpret_cast<uint8_t**>(control + kTabControlTabs);
}
inline size_t TabCount(uint8_t* control) {
uint8_t* begin = TabEntries(control);
uint8_t* end = *reinterpret_cast<uint8_t**>(control + kTabControlTabs + 4);
return begin ? static_cast<size_t>(end - begin) / kTabEntrySize : 0;
}
} // namespace game
namespace game {
// cUI_Window2::AddControl (0x727120, ret 4): the window renders the controls
// in its list (+0x78) and hands them its events (cUI_Window2::Render 0x727040,
// HandleEvent 0x726880). A control's parent alone doesn't do that.
inline void AddWindowControl(void* window, void* control) {
using AddFn = void(__fastcall*)(void*, void*, void*);
reinterpret_cast<AddFn>(0x00727120)(window, nullptr, control);
}
} // namespace game