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:
1 parent
998e315d98
commit
dbc632750b
12 files changed
+364
-145
No files matched your search
+59
-97
@@ -79,168 +79,130 @@ unsigned Slot(uint32_t value) {
|
||||
return value & 0xffff;
|
||||
}
|
||||
|
||||
// Runs a slot method: slots 0-4 on the inventory, 5-6 on its shadow (with
|
||||
// slot - 5; created on demand if `create`), others not at all (result 0).
|
||||
template <class Original, class... Args>
|
||||
auto ForSlot(Original original, void* self, uint32_t slot, bool create, Args... args) {
|
||||
if (Slot(slot) < kGameSlots) {
|
||||
return original(self, nullptr, slot, args...);
|
||||
}
|
||||
uint8_t* shadow = Slot(slot) < kSlots ? ShadowFor(self, create) : nullptr;
|
||||
if (!shadow) {
|
||||
return decltype(original(self, nullptr, slot, args...))();
|
||||
}
|
||||
return original(shadow, nullptr, Slot(slot) - kGameSlots, args...);
|
||||
}
|
||||
|
||||
// Runs a method on the inventory and, if it has one, on its shadow.
|
||||
template <class Original, class... Args>
|
||||
void WithShadow(Original original, void* self, Args... args) {
|
||||
original(self, nullptr, args...);
|
||||
if (uint8_t* shadow = ShadowFor(self, false)) {
|
||||
original(shadow, nullptr, args...);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// --- weapon sets ---------------------------------------------------------------
|
||||
|
||||
// --- weapon sets: (set, hand, ...) ---------------------------------------------
|
||||
|
||||
uint32_t __fastcall Inv_GetWeaponSetItem(void* self, void* edx, uint32_t set, uint32_t hand);
|
||||
RE_HOOK(0x005d86c0, Inv_GetWeaponSetItem);
|
||||
uint32_t __fastcall Inv_GetWeaponSetItem(void* self, void* edx, uint32_t set, uint32_t hand) {
|
||||
if (Slot(set) < kGameSlots) {
|
||||
return Inv_GetWeaponSetItem_original(self, edx, set, hand);
|
||||
}
|
||||
uint8_t* shadow = Slot(set) < kSlots ? ShadowFor(self, false) : nullptr;
|
||||
return shadow ? Inv_GetWeaponSetItem_original(shadow, edx, Slot(set) - kGameSlots, hand) : 0;
|
||||
uint32_t __fastcall Inv_GetWeaponSetItem(void* self, void*, uint32_t set, uint32_t hand) {
|
||||
return ForSlot(Inv_GetWeaponSetItem_original, self, set, false, hand);
|
||||
}
|
||||
|
||||
void __fastcall Inv_SetWeaponSetItem(void* self, void* edx, uint32_t set, uint32_t hand, int id, int notify);
|
||||
RE_HOOK(0x005d86f0, Inv_SetWeaponSetItem);
|
||||
void __fastcall Inv_SetWeaponSetItem(void* self, void* edx, uint32_t set, uint32_t hand, int id, int notify) {
|
||||
if (Slot(set) < kGameSlots) {
|
||||
return Inv_SetWeaponSetItem_original(self, edx, set, hand, id, notify);
|
||||
}
|
||||
if (Slot(set) < kSlots) {
|
||||
if (uint8_t* shadow = ShadowFor(self, true)) {
|
||||
Inv_SetWeaponSetItem_original(shadow, edx, Slot(set) - kGameSlots, hand, id, notify);
|
||||
}
|
||||
}
|
||||
void __fastcall Inv_SetWeaponSetItem(void* self, void*, uint32_t set, uint32_t hand, int id, int notify) {
|
||||
ForSlot(Inv_SetWeaponSetItem_original, self, set, true, hand, id, notify);
|
||||
}
|
||||
|
||||
void __fastcall Inv_SetWeaponSet(void* self, void* edx, uint32_t set, int left, int right, int notify);
|
||||
RE_HOOK(0x005d8930, Inv_SetWeaponSet);
|
||||
void __fastcall Inv_SetWeaponSet(void* self, void* edx, uint32_t set, int left, int right, int notify) {
|
||||
if (Slot(set) < kGameSlots) {
|
||||
return Inv_SetWeaponSet_original(self, edx, set, left, right, notify);
|
||||
}
|
||||
if (Slot(set) < kSlots) {
|
||||
if (uint8_t* shadow = ShadowFor(self, true)) {
|
||||
Inv_SetWeaponSet_original(shadow, edx, Slot(set) - kGameSlots, left, right, notify);
|
||||
}
|
||||
}
|
||||
void __fastcall Inv_SetWeaponSet(void* self, void*, uint32_t set, int left, int right, int notify) {
|
||||
ForSlot(Inv_SetWeaponSet_original, self, set, true, left, right, notify);
|
||||
}
|
||||
|
||||
uint32_t __fastcall Inv_TakeWeaponSetItem(void* self, void* edx, uint32_t set, uint32_t hand, void* out, int flag);
|
||||
RE_HOOK(0x005d8be0, Inv_TakeWeaponSetItem);
|
||||
uint32_t __fastcall Inv_TakeWeaponSetItem(void* self, void* edx, uint32_t set, uint32_t hand, void* out, int flag) {
|
||||
if (Slot(set) < kGameSlots) {
|
||||
return Inv_TakeWeaponSetItem_original(self, edx, set, hand, out, flag);
|
||||
}
|
||||
uint8_t* shadow = Slot(set) < kSlots ? ShadowFor(self, false) : nullptr;
|
||||
return shadow ? Inv_TakeWeaponSetItem_original(shadow, edx, Slot(set) - kGameSlots, hand, out, flag) : 0;
|
||||
uint32_t __fastcall Inv_TakeWeaponSetItem(void* self, void*, uint32_t set, uint32_t hand, void* out, int flag) {
|
||||
return ForSlot(Inv_TakeWeaponSetItem_original, self, set, false, hand, out, flag);
|
||||
}
|
||||
|
||||
uint32_t __fastcall Inv_GetWeaponSetItemPos(void* self, void* edx, uint32_t set, uint32_t hand, void* out);
|
||||
RE_HOOK(0x005d8d00, Inv_GetWeaponSetItemPos);
|
||||
uint32_t __fastcall Inv_GetWeaponSetItemPos(void* self, void* edx, uint32_t set, uint32_t hand, void* out) {
|
||||
if (Slot(set) < kGameSlots) {
|
||||
return Inv_GetWeaponSetItemPos_original(self, edx, set, hand, out);
|
||||
}
|
||||
uint8_t* shadow = Slot(set) < kSlots ? ShadowFor(self, false) : nullptr;
|
||||
return shadow ? Inv_GetWeaponSetItemPos_original(shadow, edx, Slot(set) - kGameSlots, hand, out) : 0;
|
||||
uint32_t __fastcall Inv_GetWeaponSetItemPos(void* self, void*, uint32_t set, uint32_t hand, void* out) {
|
||||
return ForSlot(Inv_GetWeaponSetItemPos_original, self, set, false, hand, out);
|
||||
}
|
||||
|
||||
// --- combat-art slots ----------------------------------------------------------
|
||||
// --- combat-art slots: (slot, ...) ---------------------------------------------
|
||||
|
||||
uint32_t __fastcall Inv_GetArtSlotType(void* self, void* edx, uint32_t slot);
|
||||
RE_HOOK(0x005d93e0, Inv_GetArtSlotType);
|
||||
uint32_t __fastcall Inv_GetArtSlotType(void* self, void* edx, uint32_t slot) {
|
||||
if (Slot(slot) < kGameSlots) {
|
||||
return Inv_GetArtSlotType_original(self, edx, slot);
|
||||
}
|
||||
uint8_t* shadow = Slot(slot) < kSlots ? ShadowFor(self, false) : nullptr;
|
||||
return shadow ? Inv_GetArtSlotType_original(shadow, edx, Slot(slot) - kGameSlots) : 0;
|
||||
uint32_t __fastcall Inv_GetArtSlotType(void* self, void*, uint32_t slot) {
|
||||
return ForSlot(Inv_GetArtSlotType_original, self, slot, false);
|
||||
}
|
||||
|
||||
uint32_t __fastcall Inv_GetArtSlotRef(void* self, void* edx, uint32_t slot);
|
||||
RE_HOOK(0x005d9420, Inv_GetArtSlotRef);
|
||||
uint32_t __fastcall Inv_GetArtSlotRef(void* self, void* edx, uint32_t slot) {
|
||||
if (Slot(slot) < kGameSlots) {
|
||||
return Inv_GetArtSlotRef_original(self, edx, slot);
|
||||
}
|
||||
uint8_t* shadow = Slot(slot) < kSlots ? ShadowFor(self, false) : nullptr;
|
||||
return shadow ? Inv_GetArtSlotRef_original(shadow, edx, Slot(slot) - kGameSlots) : 0;
|
||||
uint32_t __fastcall Inv_GetArtSlotRef(void* self, void*, uint32_t slot) {
|
||||
return ForSlot(Inv_GetArtSlotRef_original, self, slot, false);
|
||||
}
|
||||
|
||||
uint32_t __fastcall Inv_GetArtSlotData(void* self, void* edx, uint32_t slot);
|
||||
RE_HOOK(0x005d9450, Inv_GetArtSlotData);
|
||||
uint32_t __fastcall Inv_GetArtSlotData(void* self, void* edx, uint32_t slot) {
|
||||
if (Slot(slot) < kGameSlots) {
|
||||
return Inv_GetArtSlotData_original(self, edx, slot);
|
||||
}
|
||||
uint8_t* shadow = Slot(slot) < kSlots ? ShadowFor(self, false) : nullptr;
|
||||
return shadow ? Inv_GetArtSlotData_original(shadow, edx, Slot(slot) - kGameSlots) : 0;
|
||||
uint32_t __fastcall Inv_GetArtSlotData(void* self, void*, uint32_t slot) {
|
||||
return ForSlot(Inv_GetArtSlotData_original, self, slot, false);
|
||||
}
|
||||
|
||||
void __fastcall Inv_SetArtSlot(void* self, void* edx, uint32_t slot, uint32_t type, uint32_t data, void* refs);
|
||||
RE_HOOK(0x005d9480, Inv_SetArtSlot);
|
||||
void __fastcall Inv_SetArtSlot(void* self, void* edx, uint32_t slot, uint32_t type, uint32_t data, void* refs) {
|
||||
if (Slot(slot) < kGameSlots) {
|
||||
return Inv_SetArtSlot_original(self, edx, slot, type, data, refs);
|
||||
}
|
||||
if (Slot(slot) < kSlots) {
|
||||
if (uint8_t* shadow = ShadowFor(self, true)) {
|
||||
Inv_SetArtSlot_original(shadow, edx, Slot(slot) - kGameSlots, type, data, refs);
|
||||
}
|
||||
}
|
||||
void __fastcall Inv_SetArtSlot(void* self, void*, uint32_t slot, uint32_t type, uint32_t data, void* refs) {
|
||||
ForSlot(Inv_SetArtSlot_original, self, slot, true, type, data, refs);
|
||||
}
|
||||
|
||||
void __fastcall Inv_ClearArtSlot(void* self, void* edx, uint32_t slot);
|
||||
RE_HOOK(0x005d9680, Inv_ClearArtSlot);
|
||||
void __fastcall Inv_ClearArtSlot(void* self, void* edx, uint32_t slot) {
|
||||
if (Slot(slot) < kGameSlots) {
|
||||
return Inv_ClearArtSlot_original(self, edx, slot);
|
||||
}
|
||||
if (uint8_t* shadow = Slot(slot) < kSlots ? ShadowFor(self, false) : nullptr) {
|
||||
Inv_ClearArtSlot_original(shadow, edx, Slot(slot) - kGameSlots);
|
||||
}
|
||||
void __fastcall Inv_ClearArtSlot(void* self, void*, uint32_t slot) {
|
||||
ForSlot(Inv_ClearArtSlot_original, self, slot, false);
|
||||
}
|
||||
|
||||
// SelectSlot(slot, kind 0 weapon set / 1 art slot, apply, notify): stores the
|
||||
// selection; for an art slot also tells the engine which art the right mouse
|
||||
// button uses (read from the slot entry).
|
||||
// button uses (read from the slot entry, hence run on the shadow for 5-6).
|
||||
void __fastcall Inv_SelectSlot(void* self, void* edx, uint32_t slot, uint32_t kind, int apply, int notify);
|
||||
RE_HOOK(0x005d9820, Inv_SelectSlot);
|
||||
void __fastcall Inv_SelectSlot(void* self, void* edx, uint32_t slot, uint32_t kind, int apply, int notify) {
|
||||
if (Slot(slot) < kGameSlots) {
|
||||
return Inv_SelectSlot_original(self, edx, slot, kind, apply, notify);
|
||||
}
|
||||
if (Slot(slot) >= kSlots || Slot(kind) > 1) {
|
||||
void __fastcall Inv_SelectSlot(void* self, void*, uint32_t slot, uint32_t kind, int apply, int notify) {
|
||||
if (Slot(kind) > 1) {
|
||||
return;
|
||||
}
|
||||
if (uint8_t* shadow = ShadowFor(self, true)) {
|
||||
Inv_SelectSlot_original(shadow, edx, Slot(slot) - kGameSlots, kind, apply, notify);
|
||||
ForSlot(Inv_SelectSlot_original, self, slot, true, kind, apply, notify);
|
||||
if (Slot(slot) >= kGameSlots && Slot(slot) < kSlots) {
|
||||
auto* selected = reinterpret_cast<uint16_t*>(static_cast<uint8_t*>(self) + mods::skillslots::kSelected);
|
||||
selected[Slot(kind)] = static_cast<uint16_t>(Slot(slot));
|
||||
}
|
||||
auto* selected = reinterpret_cast<uint16_t*>(static_cast<uint8_t*>(self) + mods::skillslots::kSelected);
|
||||
selected[Slot(kind)] = static_cast<uint16_t>(Slot(slot));
|
||||
}
|
||||
|
||||
// --- methods over all slots ----------------------------------------------------
|
||||
|
||||
void __fastcall Inv_Clear(void* self, void* edx, int full, uint32_t arg);
|
||||
RE_HOOK(0x005d7d30, Inv_Clear);
|
||||
void __fastcall Inv_Clear(void* self, void* edx, int full, uint32_t arg) {
|
||||
Inv_Clear_original(self, edx, full, arg);
|
||||
if (uint8_t* shadow = ShadowFor(self, false)) {
|
||||
Inv_Clear_original(shadow, edx, full, arg);
|
||||
}
|
||||
void __fastcall Inv_Clear(void* self, void*, int full, uint32_t arg) {
|
||||
WithShadow(Inv_Clear_original, self, full, arg);
|
||||
}
|
||||
|
||||
void __fastcall Inv_ReplaceItemId(void* self, void* edx, int oldId, int newId);
|
||||
RE_HOOK(0x005d80e0, Inv_ReplaceItemId);
|
||||
void __fastcall Inv_ReplaceItemId(void* self, void* edx, int oldId, int newId) {
|
||||
Inv_ReplaceItemId_original(self, edx, oldId, newId);
|
||||
if (uint8_t* shadow = ShadowFor(self, false)) {
|
||||
Inv_ReplaceItemId_original(shadow, edx, oldId, newId);
|
||||
}
|
||||
void __fastcall Inv_ReplaceItemId(void* self, void*, int oldId, int newId) {
|
||||
WithShadow(Inv_ReplaceItemId_original, self, oldId, newId);
|
||||
}
|
||||
|
||||
void __fastcall Inv_FixInventory(void* self, void* edx);
|
||||
RE_HOOK(0x005de8a0, Inv_FixInventory);
|
||||
void __fastcall Inv_FixInventory(void* self, void* edx) {
|
||||
Inv_FixInventory_original(self, edx);
|
||||
if (uint8_t* shadow = ShadowFor(self, false)) {
|
||||
Inv_FixInventory_original(shadow, edx);
|
||||
}
|
||||
void __fastcall Inv_FixInventory(void* self, void*) {
|
||||
WithShadow(Inv_FixInventory_original, self);
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
Reference in new issue
Block a user