Shared chest tabs, rune stacks and rune master, Q pickup, Kettenblitz tooltip and range

- Shared chest: tabs "Truhe"/"Gemeinsam" as a column left of the grid
  (game tab sheet), grids placed every tick, persistent across heroes
- Inventory tab texts capitalized (RegisterText / CapitalizeText)
- Combat-art runes stack like potions (itemstack, renamed from potionstack)
- Rune master: any rune for any number of runes, price by rune count
  (4 runes = 1,000, x10 per missing rune), bought rune goes into the
  backpack, Buy disabled without runes, gold or room, last rune remembered
  per hero (saved), the chosen rune's name below its icon, dropping a
  stack gives up one rune
- Keys: the old key handling no longer takes over after the save screen
  (text field focus only counts while its dialog is shown)
- Esc crash: tooltips forgotten when the game destroys them
- Pick up (Q) sends the pickup order directly; search reach doubled
- Kettenblitz: tooltip shows hits per chain, chains, cast and jump range;
  cast range 900 (longer ray segments), jumps half of that

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
khallaandClaude Opus 5.5 committed 2026-10-17 03:40:42 +02:00
1 parent 3d9d864c25
commit 6ca96d54b4
29 files changed
+2006 -171

No files matched your search

+44
View File
@@ -24,6 +24,28 @@ inline int ItemPotionKind(uint32_t type) {
return table ? reinterpret_cast<Fn>(0x0043f630)(table, nullptr, type) : 0;
}
// The item class of item type `type` (type table entry: 0x80 bytes, class u8
// at +0x2e; read by ItemPotionKind). Usable from the inventory
// (cCreature::UseItem 0x54a8f0): 9 (potions), 0x10, 0x1c (runes).
constexpr size_t kItemTypeEntrySize = 0x80;
constexpr size_t kItemTypeClass = 0x2e;
inline uint8_t ItemClass(uint32_t type) {
const auto* table = *reinterpret_cast<const uint8_t* const*>(kItemTypeTable);
return table ? table[type * kItemTypeEntrySize + kItemTypeClass] : 0;
}
// Item classes (type table +0x2e), measured: 5 weapons / armour, 7, 9 potions,
// 0x1c combat-art runes (1x1).
constexpr uint8_t kItemClassPotion = 9;
constexpr uint8_t kItemClassRune = 0x1c;
// 0x43f5f0 (stdcall, ret 4): the item type is a potion or a rune (class 9 or
// 0x1c). Items of one such type are alike apart from their object state
// (measured: two runes of one type serialize the same past the object part).
inline bool ItemIsConsumable(uint32_t type) {
return reinterpret_cast<bool(__stdcall*)(uint32_t)>(0x0043f5f0)(type);
}
inline uint32_t ItemType(const void* item) {
return *reinterpret_cast<const uint32_t*>(static_cast<const uint8_t*>(item) + kItemType);
}
@@ -74,3 +96,25 @@ void ForEachGridItem(const uint8_t* inventory, Fn fn) {
}
} // namespace game
#include <vector>
namespace game {
// Item objects as hero files store them (ItemDataMgr::saveHero / loadHero,
// docs/shared-chest.md): the type plus the object's own serializer
// vf1c(stream, write, version), ret 0xc.
constexpr uint32_t kItemFileVersion = 0x1b; // the hero file version handed to the item readers
constexpr size_t kItemOwner = 0x39; // u8: the owner hero's id
std::vector<uint8_t> SerializeItem(void* item);
// A new item object of `type` read from `data`, as loadHero recreates one
// (cObjectManager::Create, the serializer, its new id, flags, the owner).
// Returns its id, 0 on failure.
uint32_t CreateItem(uint32_t type, const std::vector<uint8_t>& data, uint32_t ownerHeroId);
// A copy of item `id` as a new object (same type and data, same owner).
uint32_t CloneItem(uint32_t id);
} // namespace game