Taskbar: 7 weapon sets and 7 combat-art slots

cUI_Taskbar2's slot arrays move behind the (enlarged) object with room
for 7 each; all instructions addressing them, the relative accesses
between the two arrays, the slot loops and the count clamp are patched
from tables in game/addresses.h (belt loops untouched). Slots 6 / 7
unlock at levels 45 / 65; AssignArtToSlot accepts slots up to 6. Slot
keys call the taskbar's selection directly (honouring COMBINE_SLOTS).

Shared code: re::PatchAll / PatchInstructionByte for patch tables,
game/engine/objects.h for object, RTTI and kernel calls, slot-hook
templates in skillslots.cpp.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
khallaandClaude Opus 5.5 committed 2026-10-15 00:38:34 +02:00
1 parent 998e315d98
commit dbc632750b
12 files changed
+364 -145

No files matched your search

+2 -13
View File
@@ -20,6 +20,7 @@
#include <windows.h>
#include "game/engine/objects.h"
#include "mods/input.h"
#include "re/hook.h"
@@ -27,16 +28,9 @@ namespace mods::wasd {
namespace {
// --- sacred.exe ---------------------------------------------------------------
constexpr uint32_t kObjectManager = 0x00ad3bc0; // object manager**
constexpr uint32_t kEventCreatureVtable = 0x0088e95c;
constexpr uint32_t kTypeObject = 0x008e9648; // RTTI type descriptors
constexpr uint32_t kTypeCreature = 0x008e9660;
using GetObjectFn = void*(__fastcall*)(void* manager, void* edx, uint32_t id);
using DynamicCastFn = void*(__cdecl*)(void* object, int vfDelta, uint32_t source, uint32_t target, int isReference);
using SendOrderFn = void(__fastcall*)(void* engine, void* edx, void* creature, void* event);
const auto GetObjectById = reinterpret_cast<GetObjectFn>(0x005fe060);
const auto DynamicCast = reinterpret_cast<DynamicCastFn>(0x00849701);
const auto SendOrder = reinterpret_cast<SendOrderFn>(0x006170d0); // adjusts ground targets, then vf18
// cEngine fields.
@@ -65,12 +59,7 @@ bool KeyDown(int key) {
}
void* ControlledCreature(uint8_t* engine) {
void* manager = *reinterpret_cast<void**>(kObjectManager);
if (!manager) {
return nullptr;
}
void* object = GetObjectById(manager, nullptr, *reinterpret_cast<uint32_t*>(engine + kEngineControlledId));
return object ? DynamicCast(object, 0, kTypeObject, kTypeCreature, 0) : nullptr;
return game::GetCreature(*reinterpret_cast<uint32_t*>(engine + kEngineControlledId));
}
void SendWalk(uint8_t* engine, void* creature, int x, int y) {