From f0c395ed10bb082ea623fc8e84020b5daa18bcb3 Mon Sep 17 00:00:00 2001 From: qudix <17361645+qudix@users.noreply.github.com> Date: Sat, 5 Oct 2024 20:01:36 -0500 Subject: [PATCH] feat: misc events and chargenmenu (#285) --- include/RE/A/Actor.h | 7 ++ include/RE/C/ChargenMenu.h | 127 ++++++++++++++++++++++++ include/RE/E/Events.h | 176 +++++++++++++++++++++++++++++++--- include/RE/G/GameMenuBase.h | 6 +- include/RE/I/IDataModel.h | 19 ++++ include/RE/I/IMenu.h | 1 + include/RE/M/MenuPaperDoll.h | 35 +++++++ include/RE/T/TESNPCData.h | 16 +--- include/RE/U/UICellRenderer.h | 29 ++++++ 9 files changed, 384 insertions(+), 32 deletions(-) create mode 100644 include/RE/C/ChargenMenu.h create mode 100644 include/RE/I/IDataModel.h create mode 100644 include/RE/M/MenuPaperDoll.h create mode 100644 include/RE/U/UICellRenderer.h diff --git a/include/RE/A/Actor.h b/include/RE/A/Actor.h index 74112bec..2b1ef597 100644 --- a/include/RE/A/Actor.h +++ b/include/RE/A/Actor.h @@ -36,6 +36,13 @@ namespace RE struct PerkEntryUpdatedEvent; } + enum class ACTOR_COMBAT_STATE : std::int32_t + { + kNone = 0, + kCombat = 1, + kSearching = 2, + }; + enum class ACTOR_CRITICAL_STAGE { kNone = 0, diff --git a/include/RE/C/ChargenMenu.h b/include/RE/C/ChargenMenu.h new file mode 100644 index 00000000..02265d1a --- /dev/null +++ b/include/RE/C/ChargenMenu.h @@ -0,0 +1,127 @@ +#pragma once + +#include "RE/G/GameMenuBase.h" +#include "RE/I/IDataModel.h" + +namespace RE +{ + class MenuPaperDoll; + class TESNPC; + + struct CharGen_CloseMenu; + struct CharGen_PresetChange; + struct CharGen_HeadpartPresetChange; + struct CharGen_SetSex; + struct CharGen_SetSlider; + struct CharGen_StartTextEntry; + struct CharGen_EndTextEntry; + struct CharGen_CancelTextEntry; + struct CharGen_ShowPlayerRenameMessage; + struct CharGen_ShowChooseBackgroundMessage; + struct CharGen_SetBodyValues; + struct CharGen_SetCameraPosition; + struct CharGen_HeadpartPlusSelectorChange; + struct CharGen_SkintoneChange; + struct CharGen_DirtScarsEtcChange; + struct CharGen_ToggleMarking; + struct CharGen_SetTrait; + struct CharGen_SetBackground; + struct CharGen_EyeColorChange; + struct CharGen_BrowChange; + struct CharGen_HairChange; + struct CharGen_HairColorChange; + struct CharGen_FacialHairChange; + struct CharGen_FacialHairColorChange; + struct CharGen_BrowColorChange; + struct CharGen_TeethChange; + struct CharGen_CyclePronoun; + struct CharGen_SetPronoun; + struct CharGen_TogglePreviewHabSuit; + struct CharGen_SwitchLocomotion; + struct CharGen_SwitchBodyType; + struct CharGen_RotatePaperdoll; + struct CharGen_RollOnLocomotion; + struct CharGen_RollOffLocomotion; + struct CharGen_TeethRollOn; + struct CharGen_TeethRollOff; + struct CharGen_JewelryChange; + struct CharGen_JewelryColorChange; + struct CharGen_StartBodyChange; + struct CharGen_EndBodyChange; + struct CharGen_SetAdditionalSlider; + struct CharGen_SetBlockInputUnderPopup; + struct CharGen_PostBlendFaceChange; + struct CharGen_PostBlendColorOptionChange; + struct CharGen_PostBlendIntensityChange; + struct CharGen_MakeupChange; + struct CharGen_MarkingsChange; + struct UIMenuChargenMenuDisablePaperdoll; + + class ChargenMenu : + public GameMenuBase, // 000 + public IDataModel, // 138 + public BSTEventSink, // 140 + public BSTEventSink, // 148 + public BSTEventSink, // 150 + public BSTEventSink, // 158 + public BSTEventSink, // 160 + public BSTEventSink, // 168 + public BSTEventSink, // 170 + public BSTEventSink, // 178 + public BSTEventSink, // 180 + public BSTEventSink, // 188 + public BSTEventSink, // 190 + public BSTEventSink, // 198 + public BSTEventSink, // 1A0 + public BSTEventSink, // 1A8 + public BSTEventSink, // 1B0 + public BSTEventSink, // 1B8 + public BSTEventSink, // 1C0 + public BSTEventSink, // 1C8 + public BSTEventSink, // 1D0 + public BSTEventSink, // 1D8 + public BSTEventSink, // 1E0 + public BSTEventSink, // 1E8 + public BSTEventSink, // 1F0 + public BSTEventSink, // 1F8 + public BSTEventSink, // 200 + public BSTEventSink, // 208 + public BSTEventSink, // 210 + public BSTEventSink, // 218 + public BSTEventSink, // 220 + public BSTEventSink, // 228 + public BSTEventSink, // 230 + public BSTEventSink, // 238 + public BSTEventSink, // 240 + public BSTEventSink, // 248 + public BSTEventSink, // 250 + public BSTEventSink, // 258 + public BSTEventSink, // 260 + public BSTEventSink, // 268 + public BSTEventSink, // 270 + public BSTEventSink, // 278 + public BSTEventSink, // 280 + public BSTEventSink, // 288 + public BSTEventSink, // 290 + public BSTEventSink, // 298 + public BSTEventSink, // 2A0 + public BSTEventSink, // 2A8 + public BSTEventSink, // 2B0 + public BSTEventSink // 2B8 + { + public: + SF_RTTI_VTABLE(ChargenMenu); + SF_MENU_NAME("ChargenMenu"); + + virtual ~ChargenMenu(); // 00 + + // members + MenuPaperDoll* paperDoll; // 2C8 + TESNPC* npc; // 2D0 + std::byte pad2D8[(0x5B8 - 0x2D8)]; // 2D8 + std::uint32_t cameraPosition; // 5B8 + std::uint32_t unk5BC; // 5BC + std::byte pad5C0[(0x650 - 0x5C0)]; // 5C0 + }; + static_assert(sizeof(ChargenMenu) == 0x650); +} diff --git a/include/RE/E/Events.h b/include/RE/E/Events.h index 2f44e9c5..69c03491 100644 --- a/include/RE/E/Events.h +++ b/include/RE/E/Events.h @@ -7,9 +7,13 @@ namespace RE { class Actor; + class TESBoundObject; + class TESObjectBOOK; class TESObjectCELL; class TESObjectREFR; + enum class ACTOR_COMBAT_STATE : std::int32_t; + struct TESLoadGameEvent { [[nodiscard]] static BSTEventSource* GetEventSource() @@ -100,11 +104,11 @@ namespace RE } // members - NiPointer actor; - TESFormID baseObject; - TESFormID origRef; - std::uint16_t uniqueID; - bool equipped; + NiPointer actor; // 00 + TESFormID baseObject; // 08 + TESFormID origRef; // 0C + std::uint16_t uniqueID; // 10 + bool equipped; // 12 }; static_assert(sizeof(TESEquipEvent) == 0x18); @@ -180,10 +184,11 @@ namespace RE } // members - NiPointer source; - NiPointer target; - std::uint32_t state; + NiPointer source; // 00 + NiPointer target; // 08 - nullptr when combat state is none + ACTOR_COMBAT_STATE state; // 10 }; + static_assert(sizeof(TESCombatEvent) == 0x18); struct UpdateActivateListenerEvent { @@ -209,13 +214,27 @@ namespace RE { struct Event { + enum class Type : std::int32_t + { + kFirst, + kThird, + }; + [[nodiscard]] static BSTEventSource* GetEventSource() { using func_t = decltype(&FirstThirdPersonSwitch::Event::GetEventSource); static REL::Relocation func{ REL::ID(34458) }; return func(); } + + [[nodiscard]] constexpr bool IsFirst() const noexcept { return type == Type::kFirst; } + [[nodiscard]] constexpr bool IsThird() const noexcept { return type == Type::kThird; } + + // members + Type oldType; + Type type; }; + static_assert(sizeof(FirstThirdPersonSwitch::Event) == 0x8); }; struct HideSubtitleEvent @@ -280,7 +299,13 @@ namespace RE static REL::Relocation func{ REL::ID(86518) }; return func(); } + + // members + TESBoundObject* item; + NiPointer itemRef; + NiPointer actor; }; + static_assert(sizeof(TESHarvestEvent::ItemHarvested) == 0x18); }; struct HUDNotification_MissionActiveWidgetUpdate @@ -325,13 +350,26 @@ namespace RE struct CellAttachDetachEvent { + enum class Type : std::int32_t + { + kPreAttach, + kPostAttach, + kPreDetach, + kPostDetach + }; + [[nodiscard]] static BSTEventSource* GetEventSource() { using func_t = decltype(&CellAttachDetachEvent::GetEventSource); static REL::Relocation func{ REL::ID(84784) }; return func(); } + + // members + TESObjectCELL* cell; // 00 + Type type; // 08 }; + static_assert(sizeof(CellAttachDetachEvent) == 0x10); namespace BGSPlanet { @@ -2070,6 +2108,26 @@ namespace RE } }; + struct CharGen_RollOffLocomotion + { + [[nodiscard]] static BSTEventSource* GetEventSource() + { + using func_t = decltype(&CharGen_RollOffLocomotion::GetEventSource); + static REL::Relocation func{ REL::ID(141208) }; + return func(); + } + }; + + struct CharGen_RollOnLocomotion + { + [[nodiscard]] static BSTEventSource* GetEventSource() + { + using func_t = decltype(&CharGen_RollOnLocomotion::GetEventSource); + static REL::Relocation func{ REL::ID(141209) }; + return func(); + } + }; + struct CharGen_RotatePaperdoll { [[nodiscard]] static BSTEventSource* GetEventSource() @@ -2100,6 +2158,16 @@ namespace RE } }; + struct CharGen_SetBlockInputUnderPopup + { + [[nodiscard]] static BSTEventSource* GetEventSource() + { + using func_t = decltype(&CharGen_SetBlockInputUnderPopup::GetEventSource); + static REL::Relocation func{ REL::ID(141213) }; + return func(); + } + }; + struct CharGen_SetBodyValues { [[nodiscard]] static BSTEventSource* GetEventSource() @@ -2220,6 +2288,16 @@ namespace RE } }; + struct CharGen_SwitchLocomotion + { + [[nodiscard]] static BSTEventSource* GetEventSource() + { + using func_t = decltype(&CharGen_SwitchLocomotion::GetEventSource); + static REL::Relocation func{ REL::ID(141226) }; + return func(); + } + }; + struct CharGen_TeethChange { [[nodiscard]] static BSTEventSource* GetEventSource() @@ -3457,6 +3535,9 @@ namespace RE static REL::Relocation func{ REL::ID(103540) }; return func(); } + + // members + TESObjectBOOK* book; // 00 }; }; @@ -3483,7 +3564,12 @@ namespace RE static REL::Relocation func{ REL::ID(106834) }; return func(); } + + // members + NiPointer source; // 00 + NiPointer target; // 08 }; + static_assert(sizeof(Activation::Event) == 0x10); }; struct ActorCellChangeEvent @@ -3498,7 +3584,7 @@ namespace RE } // members - NiPointer actor; + NiPointer actor; // 00 }; }; @@ -3550,7 +3636,12 @@ namespace RE static REL::Relocation func{ REL::ID(107136) }; return func(); } + + // members + NiPointer target; // 00 + NiPointer source; // 08 }; + static_assert(sizeof(TESActivateEvent) == 0x10); struct TESBookReadEvent { @@ -3560,7 +3651,10 @@ namespace RE static REL::Relocation func{ REL::ID(107141) }; return func(); } - }; + + // members + NiPointer ref; // 00 + }; struct TESCellFullyLoadedEvent { @@ -3572,7 +3666,7 @@ namespace RE } // members - NiPointer cell; + NiPointer cell; // 00 }; struct TESContainerChangedEvent @@ -3606,9 +3700,9 @@ namespace RE } // members - NiPointer actorDying; // 00 - NiPointer actorKiller; // 08 - bool dead; // 10 + NiPointer actorDying; // 00 + NiPointer actorKiller; // 08 + bool dead; // 10 }; static_assert(sizeof(TESDeathEvent) == 0x18); @@ -3624,6 +3718,7 @@ namespace RE // members TESFormID formID; }; + static_assert(sizeof(TESFormDeleteEvent) == 0x4); struct TESFormIDRemapEvent { @@ -3638,16 +3733,32 @@ namespace RE TESFormID oldFormID; TESFormID newFormID; }; + static_assert(sizeof(TESFormIDRemapEvent) == 0x8); struct TESFurnitureEvent { + enum class Type : std::int32_t + { + kEnter, + kExit + }; + [[nodiscard]] static BSTEventSource* GetEventSource() { using func_t = decltype(&TESFurnitureEvent::GetEventSource); static REL::Relocation func{ REL::ID(107168) }; return func(); } + + [[nodiscard]] constexpr bool IsEnter() const noexcept { return type == Type::kEnter; } + [[nodiscard]] constexpr bool IsExit() const noexcept { return type == Type::kExit; } + + // members + std::byte pad00[0x8]; // 00 - wtf is this now? it used to be an NiPointer in previous games + NiPointer furniture; // 08 + Type type; // 10 }; + static_assert(sizeof(TESFurnitureEvent) == 0x18); struct TESGrabReleaseEvent { @@ -3657,7 +3768,12 @@ namespace RE static REL::Relocation func{ REL::ID(107169) }; return func(); } + + // members + NiPointer target; // 00 + bool grabbed; // 08 }; + static_assert(sizeof(TESGrabReleaseEvent) == 0x10); struct TESMissionAcceptedEvent { @@ -3704,6 +3820,9 @@ namespace RE static REL::Relocation func{ REL::ID(107193) }; return func(); } + + // members + NiPointer ref; // 00 }; struct TESResolveNPCTemplatesEvent @@ -3752,6 +3871,10 @@ namespace RE static REL::Relocation func{ REL::ID(151162) }; return func(); } + + // members + TESBoundObject* item; // 00 + NiPointer actor; // 08 }; }; @@ -3778,7 +3901,13 @@ namespace RE static REL::Relocation func{ REL::ID(153651) }; return func(); } + + // members + TESFaction* faction; // 00 + std::int32_t bounty; // 08 + std::int32_t oldBounty; // 0C }; + static_assert(sizeof(Bounty::Event) == 0x10); }; struct CriticalHitEvent @@ -3830,7 +3959,11 @@ namespace RE static REL::Relocation func{ REL::ID(153662) }; return func(); } + + // members + std::uint32_t level; }; + static_assert(sizeof(LevelIncrease::Event) == 0x4); }; struct PlayerAmmoChanged @@ -3848,6 +3981,7 @@ namespace RE std::uint32_t clipCount; std::uint32_t reserveCount; }; + static_assert(sizeof(PlayerAmmoChanged::Event) == 0x8); }; struct TerminalHacked @@ -3862,4 +3996,18 @@ namespace RE } }; }; + + struct WeaponFiredEvent + { + [[nodiscard]] static auto GetEventSource() + { + static REL::Relocation*> ptr{ REL::ID(773902) }; + return ptr.get(); + } + + // members + void* unk00; // 00 + void* unk08; // 08 + NiPointer actor; // 10 + }; } diff --git a/include/RE/G/GameMenuBase.h b/include/RE/G/GameMenuBase.h index 6e8eb6b4..171f54fb 100644 --- a/include/RE/G/GameMenuBase.h +++ b/include/RE/G/GameMenuBase.h @@ -24,14 +24,14 @@ namespace RE virtual ~GameMenuBase() = default; // 00 //override - virtual uint64_t Unk10() override + virtual std::uint64_t Unk10() override { using func_t = decltype(&GameMenuBase::Unk10); static REL::Relocation func(REL::ID(141505)); return func(this); }; - virtual uint64_t Unk11() override + virtual std::uint64_t Unk11() override { using func_t = decltype(&GameMenuBase::Unk11); static REL::Relocation func(REL::ID(141506)); @@ -65,7 +65,7 @@ namespace RE return result; } - void RegisterNativeFunction(const char* a_name, uint64_t a_idx) + void RegisterNativeFunction(const char* a_name, std::uint64_t a_idx) { if (!uiMovie) { return; diff --git a/include/RE/I/IDataModel.h b/include/RE/I/IDataModel.h new file mode 100644 index 00000000..43c197c5 --- /dev/null +++ b/include/RE/I/IDataModel.h @@ -0,0 +1,19 @@ +#pragma once + +namespace RE +{ + class IDataModel + { + public: + SF_RTTI_VTABLE(IDataModel); + + virtual ~IDataModel(); + + virtual void Unk01(); + virtual void Unk02(); + virtual void Unk03(); + + // members + void* unk08; // 08 - model object? + }; +} diff --git a/include/RE/I/IMenu.h b/include/RE/I/IMenu.h index a9351137..2a2ab648 100644 --- a/include/RE/I/IMenu.h +++ b/include/RE/I/IMenu.h @@ -231,6 +231,7 @@ namespace RE std::uint64_t unk118; // 118 std::uint64_t unk120; // 120 std::uint64_t unk128; // 128 + std::uint64_t unk130; // 130 }; static_assert(offsetof(IMenu, uiMovie) == 0x088); static_assert(offsetof(IMenu, menuName) == 0x0B0); diff --git a/include/RE/M/MenuPaperDoll.h b/include/RE/M/MenuPaperDoll.h new file mode 100644 index 00000000..96457956 --- /dev/null +++ b/include/RE/M/MenuPaperDoll.h @@ -0,0 +1,35 @@ +#pragma once + +#include "RE/U/UICellRenderer.h" + +namespace RE +{ + class BGSKeyword; + class MenuActor; + class TESObjectREFR; + + class MenuPaperDoll : + public UICellRenderer + { + public: + SF_RTTI_VTABLE(MenuPaperDoll); + + virtual ~MenuPaperDoll(); // 00 + + // members + std::uint64_t unk070; // 070 + std::uint64_t unk078; // 078 + std::uint64_t unk080; // 080 + std::uint64_t unk088; // 088 + std::uint64_t unk090; // 090 + std::uint64_t unk098; // 098 + std::uint64_t unk0A0; // 0A0 + std::uint64_t unk0A8; // 0A8 + MenuActor* menuActor; // 0B0 + std::byte pad0B8[(0x1A0 - 0xB8)]; // 0B8 + BGSKeyword* unk1A0; // 1A0 + TESObjectREFR* unk1A8; // 1A8 + }; + static_assert(offsetof(MenuPaperDoll, menuActor) == 0xB0); + static_assert(offsetof(MenuPaperDoll, unk1A0) == 0x1A0); +} diff --git a/include/RE/T/TESNPCData.h b/include/RE/T/TESNPCData.h index 8f4d9ed6..9f3a5a15 100644 --- a/include/RE/T/TESNPCData.h +++ b/include/RE/T/TESNPCData.h @@ -1,25 +1,11 @@ #pragma once #include "RE/B/BSTSingleton.h" +#include "RE/I/IDataModel.h" namespace RE { class MenuActor; - - class IDataModel - { - public: - SF_RTTI_VTABLE(IDataModel); - - virtual ~IDataModel(); - - virtual void Unk01(); - virtual void Unk02(); - virtual void Unk03(); - - // members - void* unk08; // 08 - model object? - }; } namespace RE::TESNPCData diff --git a/include/RE/U/UICellRenderer.h b/include/RE/U/UICellRenderer.h new file mode 100644 index 00000000..c3891fa2 --- /dev/null +++ b/include/RE/U/UICellRenderer.h @@ -0,0 +1,29 @@ +#pragma once + +#include "RE/B/BSIntrusiveRefCounted.h" + +namespace RE +{ + class TESObjectCELL; + + class UICellRenderer : + public BSIntrusiveRefCounted + { + public: + SF_RTTI_VTABLE(UICellRenderer); + + virtual ~UICellRenderer(); // 00 + + // members + TESObjectCELL* unk10; // 10 + void* unk18; // 18 - const BSResource2::TEntryType<0,LoadedCellDB::DBTraits, BSResource2::DBDefaultStreamPolicy> + float unk20; // 20 + float unk24; // 24 + std::uint64_t unk28; // 28 + void* unk30[4]; // 30 - const BSResource2::TEntryType<0,TextureDB::DBTraits, BSResource2::DBDefaultStreamPolicy> + std::uint64_t unk50; // 50 + std::uint8_t unk58[8]; // 58 + std::uint64_t unk60; // 60 + std::uint64_t unk68; // 68 - BSMenu3D::Scene + }; +}