Skip to content

Commit

Permalink
fix: AE EquipManager hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbeBryssinck committed Mar 28, 2022
1 parent 7e137ed commit 44fba81
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 48 deletions.
4 changes: 4 additions & 0 deletions Code/client/Events/EquipmentChangeEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@
struct EquipmentChangeEvent
{
uint32_t ActorId{ 0 };
bool Unequip = false;
bool IsLeft = false;
bool IsSpell = false;
bool IsShout = false;
};
1 change: 1 addition & 0 deletions Code/client/Games/Skyrim/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ void Actor::SetEquipment(const Equipment& acEquipment) noexcept
{
if (acEquipment.LeftHandWeapon)
{
// TODO: isn't the right hand the main weapon?
uint32_t mainHandWeaponId = modSystem.GetGameId(acEquipment.LeftHandWeapon);
pEquipManager->Equip(this, TESForm::GetById(mainHandWeaponId), nullptr, 1, DefaultObjectManager::Get().leftEquipSlot, false, true, false, false);
}
Expand Down
10 changes: 5 additions & 5 deletions Code/client/Games/Skyrim/DefaultObjectManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ struct DefaultObjectManager
static DefaultObjectManager& Get();

uint8_t padB8[0xB8];
void* leftEquipSlot;
void* rightEquipSlot; // also ammo slot?
void* eitherEquipSlot;
void* voiceEquipSlot;
void* potionEquipSlot;
TESForm* leftEquipSlot;
TESForm* rightEquipSlot; // also ammo slot?
TESForm* eitherEquipSlot;
TESForm* voiceEquipSlot;
TESForm* potionEquipSlot;
uint8_t pad0[0x220 - 0xE0];
BGSAction* someAction; // 220
uint8_t pad228[0xBC0 - 0x228];
Expand Down
120 changes: 82 additions & 38 deletions Code/client/Games/Skyrim/EquipManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
#include <Games/Skyrim/Forms/TESAmmo.h>
#include <AI/AIProcess.h>
#include <Games/Skyrim/Misc/MiddleProcess.h>
#include <DefaultObjectManager.h>

struct BGSEquipSlot : TESForm
{
};

struct EquipData
{
Expand Down Expand Up @@ -40,12 +45,25 @@ struct UnEquipData
bool unkb4;
};

struct MagicEquipParams
{
BGSEquipSlot* pEquipSlot;
bool bQueueEquip;
bool bForceEquip;
};

struct ShoutEquipParams
{
void* pUnk1;
bool bUnk2;
};

TP_THIS_FUNCTION(TUnEquip, void*, EquipManager, Actor* apActor, TESForm* apItem, UnEquipData* apData);
TP_THIS_FUNCTION(TEquip, void*, EquipManager, Actor* apActor, TESForm* apItem, EquipData* apData);
TP_THIS_FUNCTION(TEquipSpell, void*, EquipManager, Actor* apActor, TESForm* apSpell, void* apSlot);
TP_THIS_FUNCTION(TUnEquipSpell, void*, EquipManager, Actor* apActor, TESForm* apSpell, void* apSlot);
TP_THIS_FUNCTION(TEquipShout, void*, EquipManager, Actor* apActor, TESForm* apShout, void* apReturn);
TP_THIS_FUNCTION(TUnEquipShout, void*, EquipManager, Actor* apActor, TESForm* apShout, void* apReturn);
TP_THIS_FUNCTION(TEquipSpell, void*, EquipManager, Actor* apActor, TESForm* apSpell, MagicEquipParams* apParams);
TP_THIS_FUNCTION(TUnEquipSpell, void*, EquipManager, Actor* apActor, TESForm* apSpell, MagicEquipParams* apParams);
TP_THIS_FUNCTION(TEquipShout, void*, EquipManager, Actor* apActor, TESForm* apShout, ShoutEquipParams* apParams);
TP_THIS_FUNCTION(TUnEquipShout, void*, EquipManager, Actor* apActor, TESForm* apShout, ShoutEquipParams* apParams);

TUnEquip* RealUnEquip = nullptr;
TEquip* RealEquip = nullptr;
Expand Down Expand Up @@ -87,22 +105,24 @@ void* EquipManager::UnEquipSpell(Actor* apActor, TESForm* apSpell, uint32_t aSlo

void* EquipManager::EquipShout(Actor* apActor, TESForm* apShout)
{
uint8_t data[0x100];
TP_THIS_FUNCTION(TEquipShoutInternal, void*, EquipManager, Actor*, TESForm*);
POINTER_SKYRIMSE(TEquipShoutInternal, s_equipFunc, 38897);

ScopedEquipOverride equipOverride;

const auto result = ThisCall(RealEquipShout, this, apActor, apShout, data);
const auto result = ThisCall(s_equipFunc, this, apActor, apShout);

return result;
}

void* EquipManager::UnEquipShout(Actor* apActor, TESForm* apShout)
{
uint8_t data[0x100];
TP_THIS_FUNCTION(TUnEquipShoutInternal, void*, EquipManager, Actor*, TESForm*);
POINTER_SKYRIMSE(TUnEquipShoutInternal, s_unequipFunc, 38903);

ScopedEquipOverride equipOverride;

const auto result = ThisCall(RealUnEquipShout, this, apActor, apShout, data);
const auto result = ThisCall(s_unequipFunc, this, apActor, apShout);

return result;
}
Expand Down Expand Up @@ -134,6 +154,7 @@ void* EquipManager::UnEquip(Actor* apActor, TESForm* apItem, ExtraDataList* apEx

void* TP_MAKE_THISCALL(EquipHook, EquipManager, Actor* apActor, TESForm* apItem, EquipData* apData)
{
spdlog::info("Equip, slot: {:X}", apData->slot->formID);
if (!apActor)
return nullptr;

Expand All @@ -148,6 +169,9 @@ void* TP_MAKE_THISCALL(EquipHook, EquipManager, Actor* apActor, TESForm* apItem,
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.IsLeft = apData->slot == DefaultObjectManager::Get().leftEquipSlot;
evt.IsSpell = false;
evt.IsShout = false;

World::Get().GetRunner().Trigger(evt);
}
Expand All @@ -157,6 +181,7 @@ void* TP_MAKE_THISCALL(EquipHook, EquipManager, Actor* apActor, TESForm* apItem,

void* TP_MAKE_THISCALL(UnEquipHook, EquipManager, Actor* apActor, TESForm* apItem, UnEquipData* apData)
{
spdlog::info("Unequip, slot: {:X}", apData->slot->formID);
if (!apActor)
return nullptr;

Expand All @@ -168,15 +193,19 @@ void* TP_MAKE_THISCALL(UnEquipHook, EquipManager, Actor* apActor, TESForm* apIte
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.IsLeft = apData->slot == DefaultObjectManager::Get().leftEquipSlot;
evt.IsSpell = false;
evt.IsShout = false;

World::Get().GetRunner().Trigger(evt);
}

return ThisCall(RealUnEquip, apThis, apActor, apItem, apData);
}

void* TP_MAKE_THISCALL(EquipSpellHook, EquipManager, Actor* apActor, TESForm* apSpell, void* apSlot)
void* TP_MAKE_THISCALL(EquipSpellHook, EquipManager, Actor* apActor, TESForm* apSpell, MagicEquipParams* apParams)
{
spdlog::info("EquipSpell, slot: {:X}", apParams->pEquipSlot->formID);
if (!apActor)
return nullptr;

Expand All @@ -188,15 +217,19 @@ void* TP_MAKE_THISCALL(EquipSpellHook, EquipManager, Actor* apActor, TESForm* ap
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.IsLeft = apParams->pEquipSlot == DefaultObjectManager::Get().leftEquipSlot;
evt.IsSpell = true;
evt.IsShout = false;

World::Get().GetRunner().Trigger(evt);
}

return ThisCall(RealEquipSpell, apThis, apActor, apSpell, apSlot);
return ThisCall(RealEquipSpell, apThis, apActor, apSpell, apParams);
}

void* TP_MAKE_THISCALL(UnEquipSpellHook, EquipManager, Actor* apActor, TESForm* apSpell, void* apSlot)
void* TP_MAKE_THISCALL(UnEquipSpellHook, EquipManager, Actor* apActor, TESForm* apSpell, MagicEquipParams* apParams)
{
spdlog::info("UnequipSpell, slot: {:X}", apParams->pEquipSlot->formID);
if (!apActor)
return nullptr;

Expand All @@ -208,15 +241,19 @@ void* TP_MAKE_THISCALL(UnEquipSpellHook, EquipManager, Actor* apActor, TESForm*
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.IsLeft = apParams->pEquipSlot == DefaultObjectManager::Get().leftEquipSlot;
evt.IsSpell = true;
evt.IsShout = false;

World::Get().GetRunner().Trigger(evt);
}

return ThisCall(RealUnEquipSpell, apThis, apActor, apSpell, apSlot);
return ThisCall(RealUnEquipSpell, apThis, apActor, apSpell, apParams);
}

void* TP_MAKE_THISCALL(EquipShoutHook, EquipManager, Actor* apActor, TESForm* apShout, void* apReturn)
void* TP_MAKE_THISCALL(EquipShoutHook, EquipManager, Actor* apActor, TESForm* apShout, ShoutEquipParams* apParams)
{
spdlog::info("EquipShout");
if (!apActor)
return nullptr;

Expand All @@ -228,15 +265,19 @@ void* TP_MAKE_THISCALL(EquipShoutHook, EquipManager, Actor* apActor, TESForm* ap
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.IsLeft = false;
evt.IsSpell = false;
evt.IsShout = true;

World::Get().GetRunner().Trigger(evt);
}

return ThisCall(RealEquipShout, apThis, apActor, apShout, apReturn);
return ThisCall(RealEquipShout, apThis, apActor, apShout, apParams);
}

void* TP_MAKE_THISCALL(UnEquipShoutHook, EquipManager, Actor* apActor, TESForm* apShout, void* apReturn)
void* TP_MAKE_THISCALL(UnEquipShoutHook, EquipManager, Actor* apActor, TESForm* apShout, ShoutEquipParams* apParams)
{
spdlog::info("UnequipShout");
if (!apActor)
return nullptr;

Expand All @@ -248,34 +289,37 @@ void* TP_MAKE_THISCALL(UnEquipShoutHook, EquipManager, Actor* apActor, TESForm*
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.IsLeft = false;
evt.IsSpell = false;
evt.IsShout = true;

World::Get().GetRunner().Trigger(evt);
}

return ThisCall(RealUnEquipShout, apThis, apActor, apShout, apReturn);
return ThisCall(RealUnEquipShout, apThis, apActor, apShout, apParams);
}


static TiltedPhoques::Initializer s_equipmentHooks([]()
{
POINTER_SKYRIMSE(TEquip, s_equipFunc, 38929);
POINTER_SKYRIMSE(TUnEquip, s_unequipFunc, 38934);
POINTER_SKYRIMSE(TEquipSpell, s_equipSpellFunc, 38928);
POINTER_SKYRIMSE(TUnEquipSpell, s_unequipSpellFunc, 38902);
POINTER_SKYRIMSE(TEquipShout, s_equipShoutFunc, 38928);
POINTER_SKYRIMSE(TUnEquipShout, s_unequipShoutFunc, 38933);

RealUnEquip = s_unequipFunc.Get();
RealEquip = s_equipFunc.Get();
RealEquipSpell = s_equipSpellFunc.Get();
RealUnEquipSpell = s_unequipSpellFunc.Get();
RealEquipShout = s_equipShoutFunc.Get();
RealUnEquipShout = s_unequipShoutFunc.Get();

TP_HOOK(&RealUnEquip, UnEquipHook);
TP_HOOK(&RealEquip, EquipHook);
TP_HOOK(&RealEquipSpell, EquipSpellHook);
TP_HOOK(&RealUnEquipSpell, UnEquipSpellHook);
TP_HOOK(&RealEquipShout, EquipShoutHook);
TP_HOOK(&RealUnEquipShout, UnEquipShoutHook);
});
{
POINTER_SKYRIMSE(TEquip, s_equipFunc, 38929);
POINTER_SKYRIMSE(TUnEquip, s_unequipFunc, 38934);
POINTER_SKYRIMSE(TEquipSpell, s_equipSpellFunc, 38928);
POINTER_SKYRIMSE(TUnEquipSpell, s_unequipSpellFunc, 38933);
POINTER_SKYRIMSE(TEquipShout, s_equipShoutFunc, 38930);
POINTER_SKYRIMSE(TUnEquipShout, s_unequipShoutFunc, 38935);

RealUnEquip = s_unequipFunc.Get();
RealEquip = s_equipFunc.Get();
RealEquipSpell = s_equipSpellFunc.Get();
RealUnEquipSpell = s_unequipSpellFunc.Get();
RealEquipShout = s_equipShoutFunc.Get();
RealUnEquipShout = s_unequipShoutFunc.Get();

TP_HOOK(&RealUnEquip, UnEquipHook);
TP_HOOK(&RealEquip, EquipHook);
TP_HOOK(&RealEquipSpell, EquipSpellHook);
TP_HOOK(&RealUnEquipSpell, UnEquipSpellHook);
TP_HOOK(&RealEquipShout, EquipShoutHook);
TP_HOOK(&RealUnEquipShout, UnEquipShoutHook);
});
2 changes: 1 addition & 1 deletion Code/client/Services/Generic/InventoryService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ void InventoryService::OnNotifyEquipmentChanges(const NotifyEquipmentChanges& ac
if (!pActor)
return;

pActor->SetEquipment(acMessage.CurrentEquipment);
//pActor->SetEquipment(acMessage.CurrentEquipment);
}

void InventoryService::RunWeaponStateUpdates() noexcept
Expand Down
10 changes: 8 additions & 2 deletions Code/encoding/Messages/NotifyEquipmentChanges.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@
void NotifyEquipmentChanges::SerializeRaw(TiltedPhoques::Buffer::Writer& aWriter) const noexcept
{
Serialization::WriteVarInt(aWriter, ServerId);
CurrentEquipment.Serialize(aWriter);
EquippedItem.Serialize(aWriter);
Serialization::WriteBool(aWriter, IsLeft);
Serialization::WriteBool(aWriter, IsSpell);
Serialization::WriteBool(aWriter, IsShout);
}

void NotifyEquipmentChanges::DeserializeRaw(TiltedPhoques::Buffer::Reader& aReader) noexcept
{
ServerMessage::DeserializeRaw(aReader);

ServerId = Serialization::ReadVarInt(aReader) & 0xFFFFFFFF;
CurrentEquipment.Deserialize(aReader);
EquippedItem.Deserialize(aReader);
IsLeft == Serialization::ReadBool(aReader);
IsSpell == Serialization::ReadBool(aReader);
IsShout == Serialization::ReadBool(aReader);
}
11 changes: 9 additions & 2 deletions Code/encoding/Messages/NotifyEquipmentChanges.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Message.h"
#include <TiltedCore/Buffer.hpp>
#include <Structs/Equipment.h>
#include <Structs/Inventory.h>

struct NotifyEquipmentChanges final : ServerMessage
{
Expand All @@ -19,9 +20,15 @@ struct NotifyEquipmentChanges final : ServerMessage
{
return GetOpcode() == acRhs.GetOpcode() &&
ServerId == acRhs.ServerId &&
CurrentEquipment == acRhs.CurrentEquipment;
EquippedItem == acRhs.EquippedItem &&
IsLeft == acRhs.IsLeft &&
IsSpell == acRhs.IsSpell &&
IsShout == acRhs.IsShout;
}

uint32_t ServerId{};
Equipment CurrentEquipment{};
Inventory::Entry EquippedItem{};
bool IsLeft = false;
bool IsSpell = false;
bool IsShout = false;
};

0 comments on commit 44fba81

Please sign in to comment.