From 71d24c1bde3bef7e39db43573c8cbb18d966add9 Mon Sep 17 00:00:00 2001 From: Zeno Date: Tue, 25 Aug 2026 01:15:35 +0900 Subject: [PATCH 1/5] Add classes and functions needed for LooksMenu --- include/RE/A/AIProcess.h | 22 ++++++ include/RE/B/BGSCharacterTint.h | 60 ++++++++++++++- include/RE/B/BGSChargenUtils.h | 14 ++++ include/RE/B/BGSColorForm.h | 7 ++ include/RE/B/BGSInventoryItem.h | 9 +++ include/RE/B/BSEffectShaderMaterial.h | 43 +++++++++++ include/RE/B/BSEffectShaderProperty.h | 27 +++++++ include/RE/B/BSFaceGenUtils.h | 16 ++++ include/RE/B/BSGeometry.h | 2 +- include/RE/B/BSGraphics.h | 19 +++++ .../RE/B/BSLightingShaderMaterialSkinTint.h | 17 +++++ include/RE/B/BSLightingShaderProperty.h | 7 ++ include/RE/B/BSModelDB.h | 41 ++++++++++ include/RE/B/BSResourceNiBinaryStream.h | 4 +- include/RE/B/BSShaderData.h | 7 ++ include/RE/B/BSShaderMaterial.h | 28 +++++++ include/RE/B/BSShaderProperty.h | 2 +- include/RE/B/BSShaderUtil.h | 11 ++- include/RE/B/BipedAnim.h | 7 ++ include/RE/C/ControlMap.h | 17 +++++ include/RE/Fallout.h | 4 + include/RE/IDs.h | 63 +++++++++++++++- include/RE/L/LooksMenu.h | 8 ++ include/RE/N/NiProperty.h | 2 +- include/RE/P/PlayerCharacter.h | 8 +- include/RE/R/RESET_3D_FLAGS.h | 2 + include/RE/T/TESFile.h | 3 +- include/RE/T/TESModelDB.h | 23 ++++++ include/RE/T/TESNPC.h | 75 +++++++++++++++++++ include/RE/T/TESObjectREFR.h | 2 +- include/RE/U/UI.h | 9 +++ src/RE/B/BGSCharacterTint.cpp | 65 ++++++++++++++++ src/RE/B/BSGraphics.cpp | 28 +++++++ src/RE/B/BSResourceNiBinaryStream.cpp | 7 ++ 34 files changed, 646 insertions(+), 13 deletions(-) create mode 100644 include/RE/B/BSEffectShaderMaterial.h create mode 100644 include/RE/B/BSEffectShaderProperty.h create mode 100644 include/RE/B/BSLightingShaderMaterialSkinTint.h create mode 100644 include/RE/T/TESModelDB.h create mode 100644 src/RE/B/BGSCharacterTint.cpp create mode 100644 src/RE/B/BSGraphics.cpp diff --git a/include/RE/A/AIProcess.h b/include/RE/A/AIProcess.h index fc95d853..8c9fe634 100644 --- a/include/RE/A/AIProcess.h +++ b/include/RE/A/AIProcess.h @@ -8,6 +8,7 @@ #include "RE/B/BSSimpleList.h" #include "RE/D/DEFAULT_OBJECT.h" #include "RE/N/NiPoint3.h" +#include "RE/R/RESET_3D_FLAGS.h" namespace RE { @@ -177,6 +178,27 @@ namespace RE return func(this); } + void Set3DUpdateFlag(RESET_3D_FLAGS a_flags) + { + using func_t = decltype(&AIProcess::Set3DUpdateFlag); + static REL::Relocation func{ ID::AIProcess::Set3DUpdateFlag }; + return func(this, a_flags); + } + + void Apply3DUpdateFlag(Actor* a_actor, RESET_3D_FLAGS a_flags) + { + using func_t = decltype(&AIProcess::Apply3DUpdateFlag); + static REL::Relocation func{ ID::AIProcess::Apply3DUpdateFlag }; + return func(this, a_actor, a_flags); + } + + void Update3DModel(Actor* a_actor, bool a_queueUpdate) + { + using func_t = decltype(&AIProcess::Update3DModel); + static REL::Relocation func{ ID::AIProcess::Update3DModel }; + return func(this, a_actor, a_queueUpdate); + } + // members MiddleLowProcessData* middleLow; // 00 MiddleHighProcessData* middleHigh; // 08 diff --git a/include/RE/B/BGSCharacterTint.h b/include/RE/B/BGSCharacterTint.h index 5b403ce1..da3ef7b3 100644 --- a/include/RE/B/BGSCharacterTint.h +++ b/include/RE/B/BGSCharacterTint.h @@ -74,11 +74,13 @@ namespace RE virtual ~Entry(); // 00 + F4_HEAP_REDEFINE_NEW(Entry); + // add virtual float GetDefaultValue() { return 0.0F; } // 01 virtual void InitItem(TESForm* a_owner); // 02 virtual void CopyData(BGSCharacterTint::Template::Entry* a_copy); // 03 - virtual void LoadImpl(TESFile* a_file) = 0; // 04 + virtual void LoadImpl(TESFile* a_file); // 04 // members BGSLocalizedString name; // 08 @@ -92,6 +94,9 @@ namespace RE class Group { public: + Entry* GetTemplateBySlot(BGSCharacterTint::EntrySlot a_slot); + Entry* GetTemplateByUniqueID(std::uint16_t a_id); + // members BGSLocalizedString name; // 00 std::uint32_t id; // 08 @@ -103,11 +108,28 @@ namespace RE class Groups { public: + Entry* GetTemplateBySlot(BGSCharacterTint::EntrySlot a_slot); + Entry* GetTemplateByUniqueID(std::uint16_t a_id); + // members BSTArray groups; // 00 }; static_assert(sizeof(Groups) == 0x18); + class __declspec(novtable) Mask : + public Entry + { + public: + static constexpr auto RTTI{ RTTI::BGSCharacterTint__Template__Mask }; + static constexpr auto VTABLE{ VTABLE::BGSCharacterTint__Template__Mask }; + + // Members + BSFixedString maskTextureName; + BGSCharacterTint::BlendOp blendOp; + std::uint32_t unk2C; + }; + static_assert(sizeof(Mask) == 0x30); + class __declspec(novtable) Palette : public Entry { @@ -125,12 +147,30 @@ namespace RE }; static_assert(sizeof(ColorValue) == 0x18); + ColorValue* GetColorDataBySwatchID(std::uint16_t a_id); + // Members BSFixedString maskTextureName; std::uint32_t defaultIndex; BSTArray colorValues; }; static_assert(sizeof(Palette) == 0x48); + + class __declspec(novtable) TextureSet : + public Entry + { + public: + static constexpr auto RTTI{ RTTI::BGSCharacterTint__Template__TextureSet }; + static constexpr auto VTABLE{ VTABLE::BGSCharacterTint__Template__TextureSet }; + + // Members + BSFixedString diffuse; + BSFixedString normal; + BSFixedString specular; + BGSCharacterTint::BlendOp blendOp; + float defaultValue; + }; + static_assert(sizeof(TextureSet) == 0x40); } class __declspec(novtable) Entry @@ -147,6 +187,10 @@ namespace RE virtual bool GetMatchesTemplateDefault(const Template::Entry* entry); // 20 virtual EntryType GetType(); // 28 + [[nodiscard]] static Entry* CreateCharacterTintEntry(std::uint32_t a_id) noexcept; + static void ClearCharacterTints(class Entries* a_src) noexcept; + static void CopyCharacterTints(class Entries* a_dst, class Entries* a_src) noexcept; + // Members Entry* templateEntry; // 08 std::uint16_t idLink; // 10 @@ -178,8 +222,18 @@ namespace RE static constexpr auto VTABLE{ VTABLE::BGSCharacterTint__PaletteEntry }; // members - std::uint32_t tintingColor; // 18 - std::uint16_t swatchID; // 1C + union + { + struct + { + std::uint8_t r; + std::uint8_t g; + std::uint8_t b; + std::uint8_t x; + } tintingChannels; + std::uint32_t tintingColor; + }; // 18 + std::uint16_t swatchID; // 1C }; static_assert(sizeof(PaletteEntry) == 0x20); diff --git a/include/RE/B/BGSChargenUtils.h b/include/RE/B/BGSChargenUtils.h index 0072f3b8..fd9a04fd 100644 --- a/include/RE/B/BGSChargenUtils.h +++ b/include/RE/B/BGSChargenUtils.h @@ -71,6 +71,20 @@ namespace RE }; static_assert(sizeof(UndoData) == 0x70); + [[nodiscard]] static BGSChargenUtils* GetSingleton() + { + static REL::Relocation characterIndex{ ID::BGSChargenUtils::CharacterIndex }; + static REL::Relocation singleton{ ID::BGSChargenUtils::Singleton }; + return *singleton ? (*singleton)[*characterIndex] : nullptr; + } + + void LoadPreset(std::uint32_t a_presetIndex) + { + using func_t = decltype(&BGSChargenUtils::LoadPreset); + static REL::Relocation func{ ID::BGSChargenUtils::LoadPreset }; + return func(this, a_presetIndex); + } + // members Actor* targetActor; // 058 TESNPC* targetNPC; // 060 diff --git a/include/RE/B/BGSColorForm.h b/include/RE/B/BGSColorForm.h index 7fabfcfa..d3af8eb8 100644 --- a/include/RE/B/BGSColorForm.h +++ b/include/RE/B/BGSColorForm.h @@ -24,6 +24,13 @@ namespace RE // members union { + struct + { + std::uint8_t r; + std::uint8_t g; + std::uint8_t b; + std::uint8_t x; + } channels; std::uint32_t color; float remappingIndex; }; // 30 diff --git a/include/RE/B/BGSInventoryItem.h b/include/RE/B/BGSInventoryItem.h index cfff4943..281f6600 100644 --- a/include/RE/B/BGSInventoryItem.h +++ b/include/RE/B/BGSInventoryItem.h @@ -33,6 +33,13 @@ namespace RE [[nodiscard]] std::uint32_t GetCount() const noexcept { return count; } [[nodiscard]] bool IsEquipped() const noexcept { return flags.any(Flag::kSlotMask); } + bool Visit(const std::function f) + { + if (f(this) && nextStack) + return nextStack->Visit(f); + return true; // Continue + } + // members BSTSmartPointer nextStack; // 10 BSTSmartPointer extra; // 18 @@ -252,4 +259,6 @@ namespace RE BSTSmartPointer stackData; // 08 }; static_assert(sizeof(BGSInventoryItem) == 0x10); + + REX_DEFINE_ENUM_CLASS_FLAGS(BGSInventoryItem::Stack::Flag); } diff --git a/include/RE/B/BSEffectShaderMaterial.h b/include/RE/B/BSEffectShaderMaterial.h new file mode 100644 index 00000000..6f16e723 --- /dev/null +++ b/include/RE/B/BSEffectShaderMaterial.h @@ -0,0 +1,43 @@ +#pragma once + +#include "RE/B/BSShaderMaterial.h" + +namespace RE +{ + class __declspec(novtable) BSEffectShaderMaterial : + public BSShaderMaterial // 00 + { + public: + static constexpr auto RTTI{ RTTI::BSEffectShaderMaterial }; + static constexpr auto VTABLE{ VTABLE::BSEffectShaderMaterial }; + + // members + float falloffStartAngle; // 38 + float falloffStopAngle; // 3C + float falloffStartOpacity; // 40 + float falloffStopOpacity; // 44 + NiColorA baseColor; // 48 - Alpha is Material Alpha + NiPointer baseTexture; // 58 + NiPointer grayscaleTexture; // 60 + NiPointer environmentMapTexture; // 68 + NiPointer environmentMapMaskTexture; // 70 + NiPointer normalTexture; // 78 + float softDepth; // 80 + float baseColorScale; // 84 + BSFixedString baseTextureName; // 88 + BSFixedString grayscaleTextureName; // 90 + BSFixedString envMapTextureName; // 98 + BSFixedString envMapMaskTextureName; // A0 + BSFixedString normalTextureName; // A8 + union + { + float environmentMaskScale; // B0 + float refractionPower; // B0 - Needs kShaderFlags_Refraction + }; + std::uint8_t uTextureClampMode; // B4 + std::uint8_t uLightingInfluence; // B5 - divided by 255 + std::uint8_t uEnvironmentMapMinLOD; // B6 + std::uint8_t unkB7; // B7 + }; + static_assert(sizeof(BSEffectShaderMaterial) == 0xB8); +} diff --git a/include/RE/B/BSEffectShaderProperty.h b/include/RE/B/BSEffectShaderProperty.h new file mode 100644 index 00000000..4dfde3bc --- /dev/null +++ b/include/RE/B/BSEffectShaderProperty.h @@ -0,0 +1,27 @@ +#pragma once + +#include "RE/B/BSShaderProperty.h" +#include "RE/N/NiColor.h" + +namespace RE +{ + class BSParticleShaderCubeEmitter; + + class __declspec(novtable) BSEffectShaderProperty : + public BSShaderProperty // 00 + { + public: + static constexpr auto RTTI{ RTTI::BSEffectShaderProperty }; + static constexpr auto VTABLE{ VTABLE::BSEffectShaderProperty }; + static constexpr auto Ni_RTTI{ Ni_RTTI::BSEffectShaderProperty }; + + F4_HEAP_REDEFINE_NEW(BSEffectShaderProperty); + + // members + BSParticleShaderCubeEmitter* envCubeEmitter; // 70 + NiColor* externalEmitColor; // 78 + std::uint32_t baseTextureIndex; // 80 + float unk84; // 84 + }; + static_assert(sizeof(BSEffectShaderProperty) == 0x88); +} diff --git a/include/RE/B/BSFaceGenUtils.h b/include/RE/B/BSFaceGenUtils.h index ae12fd71..3d6aa186 100644 --- a/include/RE/B/BSFaceGenUtils.h +++ b/include/RE/B/BSFaceGenUtils.h @@ -5,6 +5,8 @@ namespace RE { + struct BSFaceGenPendingHeadData; + namespace BSTextureArray { class StaticTextureIndexed; @@ -23,5 +25,19 @@ namespace RE std::uint32_t stamp; // 234 }; static_assert(sizeof(FaceGenData) == 0x238); + + inline void StartFaceCustomizationGenerationForNPC(TESNPC* a_npc, const BSTArray& a_entries, FaceGenData* a_faceGenData, void* a_customizationBuffer, std::uint32_t a_uiLoadingPriority, bool a_bForceMaxLayers) + { + using func_t = decltype(&BSFaceGenUtils::StartFaceCustomizationGenerationForNPC); + static REL::Relocation func{ ID::BSFaceGenUtils::StartFaceCustomizationGenerationForNPC }; + func(a_npc, a_entries, a_faceGenData, a_customizationBuffer, a_uiLoadingPriority, a_bForceMaxLayers); + } + + inline void PrepareHeadPartForShaders(BSFaceGenNiNode* a_node, BGSHeadPart* a_headPart, TESNPC* a_npc, BSFaceGenPendingHeadData* a_pendingHeadData) + { + using func_t = decltype(&BSFaceGenUtils::PrepareHeadPartForShaders); + static REL::Relocation func{ ID::BSFaceGenUtils::PrepareHeadPartForShaders }; + func(a_node, a_headPart, a_npc, a_pendingHeadData); + } } } diff --git a/include/RE/B/BSGeometry.h b/include/RE/B/BSGeometry.h index 9c717725..788a806f 100644 --- a/include/RE/B/BSGeometry.h +++ b/include/RE/B/BSGeometry.h @@ -8,7 +8,7 @@ namespace RE { namespace BSSkin { - class Instance; + class Instance : public NiObject {}; } class BSCombinedTriShape; diff --git a/include/RE/B/BSGraphics.h b/include/RE/B/BSGraphics.h index 9d24e472..aceed6de 100644 --- a/include/RE/B/BSGraphics.h +++ b/include/RE/B/BSGraphics.h @@ -22,6 +22,8 @@ namespace RE { enum class Format; class Texture; + class TriShape; + class VertexDesc; enum class MultiSampleLevel : std::int32_t { @@ -316,6 +318,12 @@ namespace RE public: using ResetRenderTargets_t = void (*)(); + [[nodiscard]] static Renderer* GetSingleton() + { + static REL::Relocation singleton{ ID::BSGraphics::Renderer::Singleton }; + return *singleton; + } + void IncRef(Buffer* a_vertexBuffer) { using func_t = decltype(&BSGraphics::Renderer::IncRef); @@ -358,6 +366,10 @@ namespace RE return func(this); } + [[nodiscard]] TriShape* CreateTriShape(std::uint32_t* a_dataSize, void* a_data, VertexDesc a_vertexDesc, IndexBuffer* a_indexBuffer); + [[nodiscard]] VertexBuffer* CreateVertexBuffer(std::uint32_t* a_dataSize, void* a_data, std::uint32_t a_stride); + [[nodiscard]] IndexBuffer* CreateIndexBuffer(std::uint32_t a_indexCount, const std::uint16_t* a_indices); + // members bool skipNextPresent; // 00 ResetRenderTargets_t resetRenderTargets; // 08 @@ -726,6 +738,13 @@ namespace RE return func(this, a_enableDynamicResolution); } + void CreateRenderTarget(std::uint32_t a_index, const RenderTargetProperties& properties, std::uint8_t a_persistent) + { + using func_t = decltype(&RenderTargetManager::CreateRenderTarget); + static REL::Relocation func{ ID::BSGraphics::RenderTargetManager::CreateRenderTarget }; + return func(this, a_index, properties, a_persistent); + } + // members RenderTargetProperties renderTargetData[100]; // 000 DepthStencilTargetProperties depthStencilTargetData[12]; // C80 diff --git a/include/RE/B/BSLightingShaderMaterialSkinTint.h b/include/RE/B/BSLightingShaderMaterialSkinTint.h new file mode 100644 index 00000000..2eb813bf --- /dev/null +++ b/include/RE/B/BSLightingShaderMaterialSkinTint.h @@ -0,0 +1,17 @@ +#pragma once + +#include "RE/B/BSLightingShaderMaterialBase.h" + +namespace RE +{ + class __declspec(novtable) BSLightingShaderMaterialSkinTint : + public BSLightingShaderMaterialBase // 00 + { + public: + static constexpr auto RTTI{ RTTI::BSLightingShaderMaterialSkinTint }; + static constexpr auto VTABLE{ VTABLE::BSLightingShaderMaterialSkinTint }; + + NiColorA kTintColor; // C0 + }; + static_assert(sizeof(BSLightingShaderMaterialSkinTint) == 0xD0); +} diff --git a/include/RE/B/BSLightingShaderProperty.h b/include/RE/B/BSLightingShaderProperty.h index 387df942..aecd83f3 100644 --- a/include/RE/B/BSLightingShaderProperty.h +++ b/include/RE/B/BSLightingShaderProperty.h @@ -14,6 +14,13 @@ namespace RE static constexpr auto VTABLE{ VTABLE::BSLightingShaderProperty }; static constexpr auto Ni_RTTI{ Ni_RTTI::BSLightingShaderProperty }; + void LoadTextureSet(std::uint32_t unused = 0) noexcept + { + using func_t = decltype(&BSLightingShaderProperty::LoadTextureSet); + static REL::Relocation func{ ID::BSLightingShaderProperty::LoadTextureSet }; + return func(this, unused); + } + // members NiColorA projectedUVParams; // 70 NiColorA projectedUVColor; // 80 diff --git a/include/RE/B/BSModelDB.h b/include/RE/B/BSModelDB.h index 1ad27c32..7f204282 100644 --- a/include/RE/B/BSModelDB.h +++ b/include/RE/B/BSModelDB.h @@ -69,5 +69,46 @@ namespace RE static REL::Relocation func{ ID::BSModelDB::Demand2 }; return func(a_name, a_result, a_args); } + + struct ModelData + { + std::uint64_t unk00; // 00 + + enum + { + kFlag_Unk1 = (1 << 0), + kFlag_Dynamic = (1 << 1), + kFlag_PostProcess = (1 << 3), + kFlag_Unk2 = (1 << 4), + kFlag_Unk3 = (1 << 5) + }; + + std::uint8_t modelFlags; // 08 + // ... + }; + + class __declspec(novtable) BSModelProcessor + { + public: + static constexpr auto RTTI{ RTTI::BSModelDB__BSModelProcessor }; + static constexpr auto VTABLE{ VTABLE::BSModelDB__BSModelProcessor }; + + [[nodiscard]] static BSModelProcessor* GetSingleton() + { + static REL::Relocation ptr{ ID::BSModelProcessor::Singleton }; + return *ptr; + } + + static void SetSingleton(BSModelDB::BSModelProcessor* a_processor) + { + static REL::Relocation ptr{ ID::BSModelProcessor::Singleton }; + *ptr = a_processor; + } + + virtual ~BSModelProcessor() = default; // 00 + + virtual void Process(ModelData* modelData, const char* modelName, NiAVObject** root, std::uint32_t* typeOut); // 01 + }; + static_assert(sizeof(BSModelProcessor) == 0x08); }; } diff --git a/include/RE/B/BSResourceNiBinaryStream.h b/include/RE/B/BSResourceNiBinaryStream.h index 1c84ca9c..a164b45c 100644 --- a/include/RE/B/BSResourceNiBinaryStream.h +++ b/include/RE/B/BSResourceNiBinaryStream.h @@ -32,7 +32,9 @@ namespace RE std::size_t GetPosition() const noexcept override { return streamPos; }; // 03 - { return streamPos; } void GetBufferInfo(BufferInfo& a_buf) override; // 04 std::size_t DoRead(void* a_buf, std::size_t a_bytes) override; // 05 - std::size_t DoWrite(const void* a_buf, std::size_t a_bytes) override; // 05 + std::size_t DoWrite(const void* a_buf, std::size_t a_bytes) override; // 06 + + std::uint32_t ReadLine(char * a_buf, std::uint32_t a_bytes, std::uint32_t a_term); // 07 [[nodiscard]] static BSResourceNiBinaryStream* BinaryStreamWithRescan(const char* a_fileName); diff --git a/include/RE/B/BSShaderData.h b/include/RE/B/BSShaderData.h index 3313620d..e3d8e1bf 100644 --- a/include/RE/B/BSShaderData.h +++ b/include/RE/B/BSShaderData.h @@ -36,6 +36,13 @@ namespace RE kTallGrass = 0x4 }; + void ApplyMaterialData(BSGeometry * a_trishape, bool unk1) noexcept + { + using func_t = decltype(&BSShaderData::ApplyMaterialData); + static REL::Relocation func{ ID::BSShaderData::ApplyMaterialData }; + func(this, a_trishape, unk1); + } + // members REX::TEnumSet lightingShader; // 004 bool specularEnabled; // 008 diff --git a/include/RE/B/BSShaderMaterial.h b/include/RE/B/BSShaderMaterial.h index 1ed925ff..3bc1929f 100644 --- a/include/RE/B/BSShaderMaterial.h +++ b/include/RE/B/BSShaderMaterial.h @@ -50,6 +50,34 @@ namespace RE virtual ~BSShaderMaterial(); + void SetOffsetUV(float u, float v) + { + texCoordOffset[0].x = u; + texCoordOffset[1].x = u; + texCoordOffset[0].y = v; + texCoordOffset[1].y = v; + } + + void GetOffsetUV(float * u, float * v) + { + *u = texCoordOffset[0].x; + *v = texCoordOffset[0].y; + } + + void SetScaleUV(float u, float v) + { + texCoordScale[0].x = u; + texCoordScale[1].x = u; + texCoordScale[0].y = v; + texCoordScale[1].y = v; + } + + void GetScaleUV(float * u, float * v) + { + *u = texCoordScale[0].x; + *v = texCoordScale[0].y; + } + // add virtual BSShaderMaterial* Create(); // 01 virtual void CopyMembers(const BSShaderMaterial* a_other); // 02 diff --git a/include/RE/B/BSShaderProperty.h b/include/RE/B/BSShaderProperty.h index ab805c52..6f52461e 100644 --- a/include/RE/B/BSShaderProperty.h +++ b/include/RE/B/BSShaderProperty.h @@ -119,7 +119,7 @@ namespace RE static_assert(sizeof(RenderPassArray) == 0x8); // add - virtual RenderPassArray* GetRenderPasses(BSGeometry* a_geom, std::uint32_t a_renderMode, BSShaderAccumulator* a_accumulator) = 0; // 2B + virtual RenderPassArray* GetRenderPasses(BSGeometry* a_geom, std::uint32_t a_renderMode, BSShaderAccumulator* a_accumulator) { return nullptr; } // 2B virtual RenderPassArray* GetRenderPasses_ShadowMapOrMask(BSGeometry*, std::uint32_t, BSShaderAccumulator*) { return nullptr; } // 2C virtual RenderPassArray* GetRenderPasses_LocalMap(BSGeometry*, std::uint32_t, BSShaderAccumulator*) { return nullptr; } // 2D virtual BSRenderPass* CreateVatsMaskRenderPass(BSGeometry*) { return nullptr; } // 2E diff --git a/include/RE/B/BSShaderUtil.h b/include/RE/B/BSShaderUtil.h index 2ec0023b..fd64d578 100644 --- a/include/RE/B/BSShaderUtil.h +++ b/include/RE/B/BSShaderUtil.h @@ -2,16 +2,23 @@ namespace RE { - class NiAvObject; + class NiAVObject; class NiSwitchNode; namespace BSShaderUtil { - inline void SetMaterialAlpha(NiAvObject* a_object, float a_alpha, bool a_onlyFade) + inline void SetMaterialAlpha(NiAVObject* a_object, float a_alpha, bool a_onlyFade) { using func_t = decltype(&BSShaderUtil::SetMaterialAlpha); static REL::Relocation func{ ID::BSShaderUtil::SetMaterialAlpha }; return func(a_object, a_alpha, a_onlyFade); } + + inline void ClearRenderPasses(NiAVObject* a_object) + { + using func_t = decltype(&BSShaderUtil::ClearRenderPasses); + static REL::Relocation func{ ID::BSShaderUtil::ClearRenderPasses }; + return func(a_object); + } } } diff --git a/include/RE/B/BipedAnim.h b/include/RE/B/BipedAnim.h index 969b701e..f2f33d4b 100644 --- a/include/RE/B/BipedAnim.h +++ b/include/RE/B/BipedAnim.h @@ -33,6 +33,13 @@ namespace RE return root; } + NiNode* AttachSkinnedObject(NiNode* a_objectRoot, NiNode* a_parent, std::uint32_t a_bipedIndex, bool a_bFirstPerson) noexcept + { + using func_t = decltype(&BipedAnim::AttachSkinnedObject); + static REL::Relocation func{ ID::BipedAnim::AttachSkinnedObject }; + return func(this, a_objectRoot, a_parent, a_bipedIndex, a_bFirstPerson); + } + // members NiNode* root; // 0008 BIPOBJECT object[std::to_underlying(BIPED_OBJECT::kTotal)]; // 0010 diff --git a/include/RE/C/ControlMap.h b/include/RE/C/ControlMap.h index 4439bb0d..9966688d 100644 --- a/include/RE/C/ControlMap.h +++ b/include/RE/C/ControlMap.h @@ -113,6 +113,23 @@ namespace RE return func(this, a_enable); } + std::int8_t AllowTextInput(bool a_allow) + { + if (a_allow) + { + assert(byTextEntryCount < 0xFF); + if (byTextEntryCount < 0xFF) + byTextEntryCount++; + } + else + { + assert(byTextEntryCount > 0); + if (byTextEntryCount > 0) + byTextEntryCount--; + } + return byTextEntryCount; + } + void SetIgnoreKeyboardMouse(bool a_value) noexcept { ignoreKeyboardMouse = a_value; } // members diff --git a/include/RE/Fallout.h b/include/RE/Fallout.h index 461a7dda..aa755f8a 100644 --- a/include/RE/Fallout.h +++ b/include/RE/Fallout.h @@ -265,6 +265,8 @@ #include "RE/B/BSCriticalSection.h" #include "RE/B/BSCubeMapCamera.h" #include "RE/B/BSCullingProcess.h" +#include "RE/B/BSEffectShaderMaterial.h" +#include "RE/B/BSEffectShaderProperty.h" #include "RE/B/BSEventFlag.h" #include "RE/B/BSExternalAudioIO.h" #include "RE/B/BSExtraData.h" @@ -303,6 +305,7 @@ #include "RE/B/BSLensFlareSpriteData.h" #include "RE/B/BSLightingShaderMaterial.h" #include "RE/B/BSLightingShaderMaterialBase.h" +#include "RE/B/BSLightingShaderMaterialSkinTint.h" #include "RE/B/BSLightingShaderProperty.h" #include "RE/B/BSLog.h" #include "RE/B/BSMTAManager.h" @@ -1335,6 +1338,7 @@ #include "RE/T/TESMagicEffectApplyEvent.h" #include "RE/T/TESMagicTargetForm.h" #include "RE/T/TESModel.h" +#include "RE/T/TESModelDB.h" #include "RE/T/TESModelRDT.h" #include "RE/T/TESModelTri.h" #include "RE/T/TESNPC.h" diff --git a/include/RE/IDs.h b/include/RE/IDs.h index 97a2685d..7407249d 100644 --- a/include/RE/IDs.h +++ b/include/RE/IDs.h @@ -121,6 +121,9 @@ namespace RE::ID inline constexpr REL::ID AddToProcedureIndexRunning{ 2718412 }; inline constexpr REL::ID ComputeLastTimeProcessed{ 2231541 }; inline constexpr REL::ID GetActorLightLevel{ 2231981 }; + inline constexpr REL::ID Set3DUpdateFlag{ 2232389 }; + inline constexpr REL::ID Apply3DUpdateFlag{ 2232144 }; + inline constexpr REL::ID Update3DModel{ 2231882 }; } namespace AITimer @@ -150,6 +153,11 @@ namespace RE::ID inline constexpr REL::ID GetCapsOwedByPlayer{ 2222714 }; } + namespace BipedAnim + { + inline constexpr REL::ID AttachSkinnedObject{ 2194388 }; + } + namespace BGSAnimationSystemUtils { inline constexpr REL::ID GetActiveSyncInfo{ 2214289 }; @@ -168,6 +176,20 @@ namespace RE::ID inline constexpr REL::ID GetUIOutputModel{ 2214800 }; } + namespace BGSCharacterTint + { + inline constexpr REL::ID CreateCharacterTintEntry{ 2196524 }; + inline constexpr REL::ID CopyCharacterTints{ 2196507 }; + inline constexpr REL::ID ClearCharacterTints{ 2196606 }; + } + + namespace BGSChargenUtils + { + inline constexpr REL::ID Singleton{ 4803944 }; + inline constexpr REL::ID CharacterIndex{ 4803938 }; + inline constexpr REL::ID LoadPreset{ 2227269 }; + } + namespace BGSConstructibleObject { inline constexpr REL::ID PlayerPassesConditions{ 2197318 }; @@ -528,6 +550,12 @@ namespace RE::ID inline constexpr REL::ID Process2{ 2275932 }; } + namespace BSFaceGenUtils + { + inline constexpr REL::ID StartFaceCustomizationGenerationForNPC{ 2209525 }; + inline constexpr REL::ID PrepareHeadPartForShaders{ 2209538 }; + } + namespace BSGFxDisplayObject { inline constexpr REL::ID RemoveChild{ 2287327 }; @@ -553,18 +581,23 @@ namespace RE::ID { namespace Renderer { + inline constexpr REL::ID Singleton{ 2704525 }; inline constexpr REL::ID IncRef{ 2276869 }; inline constexpr REL::ID DecRef{ 2276870 }; inline constexpr REL::ID Begin{ 2276833 }; inline constexpr REL::ID End{ 2276834 }; inline constexpr REL::ID Lock{ 2276828 }; inline constexpr REL::ID Unlock{ 2276829 }; + inline constexpr REL::ID CreateTriShape{ 2276843 }; + inline constexpr REL::ID CreateVertexBuffer{ 2276868 }; + inline constexpr REL::ID CreateIndexBuffer{ 2276871 }; } namespace RenderTargetManager { inline constexpr REL::ID Singleton{ 2666735 }; inline constexpr REL::ID SetEnableDynamicResolution{ 2277197 }; + inline constexpr REL::ID CreateRenderTarget{ 2277176 }; } namespace State @@ -607,12 +640,22 @@ namespace RE::ID inline constexpr REL::ID EnableOtherEvent{ 2268265 }; } + namespace BSLightingShaderProperty + { + inline constexpr REL::ID LoadTextureSet{ 2316425 }; + } + namespace BSModelDB { inline constexpr REL::ID Demand1{ 2275153 }; inline constexpr REL::ID Demand2{ 2275154 }; } + namespace BSModelProcessor + { + inline constexpr REL::ID Singleton{ 4796429 }; + } + namespace BSPointerHandle { namespace BSPointerHandleManagerInterface @@ -688,6 +731,7 @@ namespace RE::ID inline constexpr REL::ID Ctor{ 2269830 }; inline constexpr REL::ID Dtor{ 2269832 }; inline constexpr REL::ID BinaryStreamWithRescan{ 2205871 }; + inline constexpr REL::ID ReadLine{ 2269837 }; } namespace BSScaleformManager @@ -769,9 +813,15 @@ namespace RE::ID inline constexpr REL::ID CreateObject{ 2316324 }; } + namespace BSShaderData + { + inline constexpr REL::ID ApplyMaterialData{ 2316352 }; + } + namespace BSShaderUtil { inline constexpr REL::ID SetMaterialAlpha{ 2317566 }; + inline constexpr REL::ID ClearRenderPasses{ 2317600 }; } namespace BSSoundHandle @@ -1457,6 +1507,11 @@ namespace RE::ID inline constexpr REL::ID GetEventSource{ 2249292 }; } + namespace LooksMenu + { + inline constexpr REL::ID LoadCharacterParameters{ 2223356 }; + } + namespace MagicTarget { inline constexpr REL::ID IsTakingHealthDamageFromActiveEffect{ 2226397 }; @@ -1822,7 +1877,8 @@ namespace RE::ID } inline constexpr REL::ID Singleton{ 4798212 }; - inline constexpr REL::ID GetPlayerHandle{ 2698072 }; + inline constexpr REL::ID PlayerHandle{ 2698072 }; + inline constexpr REL::ID Player{ 2698073 }; inline constexpr REL::ID GetDifficultyLevel{ 2233056 }; inline constexpr REL::ID IsGodMode{ 2232986 }; inline constexpr REL::ID IsHolotapePlaying{ 2233206 }; @@ -2213,10 +2269,15 @@ namespace RE::ID { inline constexpr REL::ID AlternateHeadPartListMap{ 2662368 }; inline constexpr REL::ID GetSex{ 2207107 }; + inline constexpr REL::ID SetFacialBoneMorphIntensity{ 2207415 }; inline constexpr REL::ID GetFacialBoneMorphIntensity{ 2207416 }; inline constexpr REL::ID SetHairColor{ 2207426 }; inline constexpr REL::ID GetShortName{ 2207405 }; inline constexpr REL::ID GetXPValue{ 2207384 }; + inline constexpr REL::ID HasOverlays{ 2207500 }; + inline constexpr REL::ID GetOverlayHeadParts{ 2207501 }; + inline constexpr REL::ID GetNumOverlayHeadParts{ 2207502 }; + inline constexpr REL::ID ChangeHeadPart{ 2207463 }; } namespace TESObjectARMO diff --git a/include/RE/L/LooksMenu.h b/include/RE/L/LooksMenu.h index ef2edf9a..ec47771b 100644 --- a/include/RE/L/LooksMenu.h +++ b/include/RE/L/LooksMenu.h @@ -13,6 +13,14 @@ namespace RE public BSTEventSink { public: + void LoadCharacterParameters() noexcept + { + using func_t = decltype(&LooksMenu::LoadCharacterParameters); + static REL::Relocation func{ ID::LooksMenu::LoadCharacterParameters }; + return func(this); + } + + // members BSTSmartPointer inputLayer; // 0x0E8 LooksInputRepeatHandler inputRepeatHandler; // 0x0F0 void* bracketExtents; // 0x138 - std::unique_ptr diff --git a/include/RE/N/NiProperty.h b/include/RE/N/NiProperty.h index f5180f82..03160a7d 100644 --- a/include/RE/N/NiProperty.h +++ b/include/RE/N/NiProperty.h @@ -15,7 +15,7 @@ namespace RE static constexpr auto Ni_RTTI{ Ni_RTTI::NiProperty }; // add - virtual std::int32_t Type() = 0; // 28 + virtual std::int32_t Type(); // 28 virtual void Update(NiUpdateData& a_updateData); // 29 }; static_assert(sizeof(NiProperty) == 0x28); diff --git a/include/RE/P/PlayerCharacter.h b/include/RE/P/PlayerCharacter.h index 38b84763..0d846284 100644 --- a/include/RE/P/PlayerCharacter.h +++ b/include/RE/P/PlayerCharacter.h @@ -172,10 +172,16 @@ namespace RE [[nodiscard]] static ActorHandle GetPlayerHandle() { - static REL::Relocation singleton{ ID::PlayerCharacter::GetPlayerHandle }; + static REL::Relocation singleton{ ID::PlayerCharacter::PlayerHandle }; return *singleton; } + [[nodiscard]] static PlayerCharacter* GetPlayer() + { + static REL::Relocation*> singleton{ ID::PlayerCharacter::Player }; + return singleton->get(); + } + DifficultyLevel GetDifficultyLevel() { using func_t = decltype(&PlayerCharacter::GetDifficultyLevel); diff --git a/include/RE/R/RESET_3D_FLAGS.h b/include/RE/R/RESET_3D_FLAGS.h index 8195397f..d448ba2a 100644 --- a/include/RE/R/RESET_3D_FLAGS.h +++ b/include/RE/R/RESET_3D_FLAGS.h @@ -17,4 +17,6 @@ namespace RE kKeepHead = 1u << 10, kDismemberment = 1u << 11 }; + + REX_DEFINE_ENUM_CLASS_FLAGS(RESET_3D_FLAGS); } diff --git a/include/RE/T/TESFile.h b/include/RE/T/TESFile.h index 44bb2b1d..de670089 100644 --- a/include/RE/T/TESFile.h +++ b/include/RE/T/TESFile.h @@ -42,7 +42,8 @@ namespace RE [[nodiscard]] std::string_view GetFilename() const noexcept { return { filename }; } [[nodiscard]] std::uint16_t GetSmallFileCompileIndex() const noexcept { return smallFileCompileIndex; } [[nodiscard]] bool IsActive() const noexcept { return GetCompileIndex() != 0xFF; } - [[nodiscard]] bool IsLight() const noexcept { return flags.all(RecordFlag::kSmallFile); }; + [[nodiscard]] bool IsLight() const noexcept { return flags.all(RecordFlag::kSmallFile); } + [[nodiscard]] std::uint32_t GetPartialIndex() const noexcept { return !IsLight() ? GetCompileIndex() : 0xFE000 | GetSmallFileCompileIndex(); } [[nodiscard]] bool CloseTES(bool a_forceClose) { diff --git a/include/RE/T/TESModelDB.h b/include/RE/T/TESModelDB.h new file mode 100644 index 00000000..c4a8dbaa --- /dev/null +++ b/include/RE/T/TESModelDB.h @@ -0,0 +1,23 @@ +#pragma once + +#include "RE/B/BSModelDB.h" + +namespace RE +{ + class __declspec(novtable) TESModelDB : + public BSModelDB // 00 + { + public: + class __declspec(novtable) TESProcessor : public BSModelProcessor + { + public: + static constexpr auto RTTI{ RTTI::TESModelDB____TESProcessor }; + static constexpr auto VTABLE{ VTABLE::TESModelDB____TESProcessor }; + + virtual ~TESProcessor(); // 00 + + virtual void Process(ModelData* modelData, const char* modelName, NiAVObject** root, std::uint32_t* typeOut) override; // 01 + }; + static_assert(sizeof(TESProcessor) == 0x08); + }; +} diff --git a/include/RE/T/TESNPC.h b/include/RE/T/TESNPC.h index fd9081d2..d22bdbf2 100644 --- a/include/RE/T/TESNPC.h +++ b/include/RE/T/TESNPC.h @@ -15,6 +15,7 @@ #include "RE/P/PerkRankData.h" #include "RE/S/SEX.h" #include "RE/T/TESActorBase.h" +#include "RE/T/TESRace.h" #include "RE/T/TESRaceForm.h" #include "RE/T/TESSpellList.h" @@ -149,6 +150,13 @@ namespace RE [[nodiscard]] bool UsingAlternateHeadPartList() const; + void SetFacialBoneMorphIntensity(float a_intensity) + { + using func_t = decltype(&TESNPC::SetFacialBoneMorphIntensity); + static REL::Relocation func{ ID::TESNPC::SetFacialBoneMorphIntensity }; + return func(this, a_intensity); + } + float GetFacialBoneMorphIntensity() { using func_t = decltype(&TESNPC::GetFacialBoneMorphIntensity); @@ -163,6 +171,24 @@ namespace RE return func(this, a_col); } + BGSColorForm* GetHairColor() + { + if (!headRelatedData) + return nullptr; + + if (headRelatedData->hairColor == nullptr) + { + if (formRace) { + TESRace::FaceRelatedData* raceRelatedData = formRace->faceRelatedData[std::to_underlying(GetSex())]; + if(raceRelatedData) { + return raceRelatedData->defaultHairColor; + } + } + } + + return headRelatedData->hairColor; + } + [[nodiscard]] const char* GetShortName() noexcept { using func_t = decltype(&TESNPC::GetShortName); @@ -170,6 +196,55 @@ namespace RE return func(this); } + [[nodiscard]] bool HasOverlays() noexcept + { + using func_t = decltype(&TESNPC::HasOverlays); + static REL::Relocation func{ ID::TESNPC::HasOverlays }; + return func(this); + } + + [[nodiscard]] BGSHeadPart** GetOverlayHeadParts() noexcept + { + using func_t = decltype(&TESNPC::GetOverlayHeadParts); + static REL::Relocation func{ ID::TESNPC::GetOverlayHeadParts }; + return func(this); + } + + [[nodiscard]] std::uint32_t GetNumOverlayHeadParts() noexcept + { + using func_t = decltype(&TESNPC::GetNumOverlayHeadParts); + static REL::Relocation func{ ID::TESNPC::GetNumOverlayHeadParts }; + return func(this); + } + + void ChangeHeadPart(BGSHeadPart* a_headPart) noexcept + { + using func_t = decltype(&TESNPC::ChangeHeadPart); + static REL::Relocation func{ ID::TESNPC::ChangeHeadPart }; + return func(this, a_headPart); + } + + BGSHeadPart* GetHeadPartByType(BGSHeadPart::HeadPartType a_type, bool bOverlays = false) + { + BGSHeadPart** parts = headParts; + std::uint32_t numParts = numHeadParts; + if(bOverlays) { + parts = GetOverlayHeadParts(); + numParts = GetNumOverlayHeadParts(); + } + + for(std::uint32_t i = 0; i < numParts; ++i) + { + BGSHeadPart* part = parts[i]; + if(part && part->type == a_type) + { + return part; + } + } + + return nullptr; + } + // members BGSAttachParentArray attachParents; // 220 NPC_DATA data; // 238 diff --git a/include/RE/T/TESObjectREFR.h b/include/RE/T/TESObjectREFR.h index fefea4c6..b29f095b 100644 --- a/include/RE/T/TESObjectREFR.h +++ b/include/RE/T/TESObjectREFR.h @@ -598,7 +598,7 @@ namespace RE LOADED_REF_DATA* loadedData; // 0x0F0 BGSInventoryList* inventoryList; // 0x0F8 BSTSmartPointer extraList; // 0x100 - std::uint16_t refScale; // 0x018 + std::uint16_t refScale; // 0x108 std::int8_t modelState; // 0x10A bool predestroyed; // 0x10B }; diff --git a/include/RE/U/UI.h b/include/RE/U/UI.h index 73334415..a545d8ff 100644 --- a/include/RE/U/UI.h +++ b/include/RE/U/UI.h @@ -66,6 +66,15 @@ namespace RE return it != menuMap.end() ? it->second.menu : nullptr; } + [[nodiscard]] Scaleform::Ptr GetMenuByMovie(const Scaleform::GFx::Movie* a_movie) const + { + BSAutoReadLock l{ GetMenuMapRWLock() }; + const auto it = std::find_if(menuMap.begin(), menuMap.end(), [a_movie](const auto& item) { + return item.second.menu ? item.second.menu->uiMovie.get() == a_movie : false; + }); + return it != menuMap.end() ? it->second.menu : nullptr; + } + template [[nodiscard]] Scaleform::Ptr GetMenu() const requires(requires { T::MENU_NAME; }) diff --git a/src/RE/B/BGSCharacterTint.cpp b/src/RE/B/BGSCharacterTint.cpp new file mode 100644 index 00000000..8bdeef7e --- /dev/null +++ b/src/RE/B/BGSCharacterTint.cpp @@ -0,0 +1,65 @@ +#include "RE/B/BGSCharacterTint.h" + +namespace RE::BGSCharacterTint +{ + Template::Entry* Template::Group::GetTemplateBySlot(BGSCharacterTint::EntrySlot a_slot) + { + auto it = std::find_if(entries.begin(), entries.end(), [a_slot](Entry* entry){ return entry->slot == a_slot; }); + return it != entries.end() ? *it : nullptr; + } + + Template::Entry* Template::Group::GetTemplateByUniqueID(std::uint16_t a_id) + { + auto it = std::find_if(entries.begin(), entries.end(), [a_id](Entry* entry){ return entry->uniqueID == a_id; }); + return it != entries.end() ? *it : nullptr; + } + + Template::Entry* Template::Groups::GetTemplateBySlot(BGSCharacterTint::EntrySlot a_slot) + { + for (Group* group : groups) + { + Entry* entry = group->GetTemplateBySlot(a_slot); + if (entry) + return entry; + } + return nullptr; + } + + Template::Entry* Template::Groups::GetTemplateByUniqueID(std::uint16_t a_id) + { + for (Group* group : groups) + { + Entry* entry = group->GetTemplateByUniqueID(a_id); + if (entry) + return entry; + } + return nullptr; + } + + Template::Palette::ColorValue* Template::Palette::GetColorDataBySwatchID(std::uint16_t a_id) + { + auto it = std::find_if(colorValues.begin(), colorValues.end(), [a_id](ColorValue& color){ return color.swatchID == a_id; }); + return it != colorValues.end() ? &*it : nullptr; + } + + [[nodiscard]] Entry* Entry::CreateCharacterTintEntry(std::uint32_t a_id) noexcept + { + using func_t = decltype(&CreateCharacterTintEntry); + static REL::Relocation func{ ID::BGSCharacterTint::CreateCharacterTintEntry }; + return func(a_id); + } + + void Entry::ClearCharacterTints(Entries* a_src) noexcept + { + using func_t = decltype(&ClearCharacterTints); + static REL::Relocation func{ ID::BGSCharacterTint::ClearCharacterTints }; + return func(a_src); + } + + void Entry::CopyCharacterTints(Entries* a_dst, Entries* a_src) noexcept + { + using func_t = decltype(&CopyCharacterTints); + static REL::Relocation func{ ID::BGSCharacterTint::CopyCharacterTints }; + return func(a_dst, a_src); + } +} diff --git a/src/RE/B/BSGraphics.cpp b/src/RE/B/BSGraphics.cpp new file mode 100644 index 00000000..141a4c42 --- /dev/null +++ b/src/RE/B/BSGraphics.cpp @@ -0,0 +1,28 @@ +#include "RE/B/BSGraphics.h" + +namespace RE +{ + namespace BSGraphics + { + TriShape* Renderer::CreateTriShape(std::uint32_t* a_dataSize, void* a_data, VertexDesc a_vertexDesc, IndexBuffer* a_indexBuffer) + { + using func_t = decltype(&BSGraphics::Renderer::CreateTriShape); + static REL::Relocation func{ ID::BSGraphics::Renderer::CreateTriShape }; + return func(this, a_dataSize, a_data, a_vertexDesc, a_indexBuffer); + } + + VertexBuffer* Renderer::CreateVertexBuffer(std::uint32_t* a_dataSize, void* a_data, std::uint32_t a_stride) + { + using func_t = decltype(&BSGraphics::Renderer::CreateVertexBuffer); + static REL::Relocation func{ ID::BSGraphics::Renderer::CreateVertexBuffer }; + return func(this, a_dataSize, a_data, a_stride); + } + + IndexBuffer* Renderer::CreateIndexBuffer(std::uint32_t a_indexCount, const std::uint16_t* a_indices) + { + using func_t = decltype(&BSGraphics::Renderer::CreateIndexBuffer); + static REL::Relocation func{ ID::BSGraphics::Renderer::CreateIndexBuffer }; + return func(this, a_indexCount, a_indices); + } + } +} diff --git a/src/RE/B/BSResourceNiBinaryStream.cpp b/src/RE/B/BSResourceNiBinaryStream.cpp index 87cf2287..95c79539 100644 --- a/src/RE/B/BSResourceNiBinaryStream.cpp +++ b/src/RE/B/BSResourceNiBinaryStream.cpp @@ -49,6 +49,13 @@ namespace RE return func(this, a_buf, a_toWrite); } + std::uint32_t BSResourceNiBinaryStream::ReadLine(char * a_buf, std::uint32_t a_bytes, std::uint32_t a_term) + { + using func_t = decltype(&BSResourceNiBinaryStream::ReadLine); + static REL::Relocation func{ ID::BSResourceNiBinaryStream::ReadLine }; + return func(this, a_buf, a_bytes, a_term); + } + [[nodiscard]] BSResourceNiBinaryStream* BSResourceNiBinaryStream::BinaryStreamWithRescan(const char* a_fileName) { using func_t = decltype(&BSResourceNiBinaryStream::BinaryStreamWithRescan); From 57ce197c80ba392d51a29738b7368b2fba725b41 Mon Sep 17 00:00:00 2001 From: Zeno Date: Wed, 26 Aug 2026 03:25:18 +0900 Subject: [PATCH 2/5] NiNode: Add missing vtable to default constructor --- include/RE/N/NiNode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/RE/N/NiNode.h b/include/RE/N/NiNode.h index 0cf78f8a..8d03b01b 100644 --- a/include/RE/N/NiNode.h +++ b/include/RE/N/NiNode.h @@ -18,7 +18,7 @@ namespace RE // NOLINTNEXTLINE(modernize-use-equals-default) NiNode() : NiNode(0) - {} + { REX::EMPLACE_VTABLE(this); } explicit NiNode(std::uint32_t a_numChildren) : children(a_numChildren) From f0701f3f42f581af8b2d7b249c095d6f49dcd0d2 Mon Sep 17 00:00:00 2001 From: Zeno Date: Wed, 26 Aug 2026 03:25:49 +0900 Subject: [PATCH 3/5] BSLightingShaderProperty: Implement constructor --- include/RE/B/BSLightingShaderProperty.h | 14 ++++++++++++++ include/RE/IDs.h | 1 + 2 files changed, 15 insertions(+) diff --git a/include/RE/B/BSLightingShaderProperty.h b/include/RE/B/BSLightingShaderProperty.h index aecd83f3..5bee6c41 100644 --- a/include/RE/B/BSLightingShaderProperty.h +++ b/include/RE/B/BSLightingShaderProperty.h @@ -14,6 +14,12 @@ namespace RE static constexpr auto VTABLE{ VTABLE::BSLightingShaderProperty }; static constexpr auto Ni_RTTI{ Ni_RTTI::BSLightingShaderProperty }; + BSLightingShaderProperty() + { + REX::EMPLACE_VTABLE(this); + ctor(); + } + void LoadTextureSet(std::uint32_t unused = 0) noexcept { using func_t = decltype(&BSLightingShaderProperty::LoadTextureSet); @@ -37,6 +43,14 @@ namespace RE std::uint32_t clearCommandBufferCount; // DC std::uint16_t debugTintIndex; // E0 std::uint32_t stencilRef; // E4 + + private: + void ctor() + { + using func_t = decltype(&BSLightingShaderProperty::ctor); + static REL::Relocation func{ ID::BSLightingShaderProperty::ctor }; + return func(this); + } }; static_assert(sizeof(BSLightingShaderProperty) == 0xE8); } diff --git a/include/RE/IDs.h b/include/RE/IDs.h index 7407249d..0cb498ba 100644 --- a/include/RE/IDs.h +++ b/include/RE/IDs.h @@ -642,6 +642,7 @@ namespace RE::ID namespace BSLightingShaderProperty { + inline constexpr REL::ID ctor{ 2316416 }; inline constexpr REL::ID LoadTextureSet{ 2316425 }; } From 079dad6405d9fe3fc4439243d926202e59429f38 Mon Sep 17 00:00:00 2001 From: Zeno Date: Wed, 26 Aug 2026 03:26:04 +0900 Subject: [PATCH 4/5] BSEffectShaderProperty: Implement constructor --- include/RE/B/BSEffectShaderProperty.h | 14 +++++++++++++- include/RE/IDs.h | 5 +++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/RE/B/BSEffectShaderProperty.h b/include/RE/B/BSEffectShaderProperty.h index 4dfde3bc..b8d32ae9 100644 --- a/include/RE/B/BSEffectShaderProperty.h +++ b/include/RE/B/BSEffectShaderProperty.h @@ -15,13 +15,25 @@ namespace RE static constexpr auto VTABLE{ VTABLE::BSEffectShaderProperty }; static constexpr auto Ni_RTTI{ Ni_RTTI::BSEffectShaderProperty }; - F4_HEAP_REDEFINE_NEW(BSEffectShaderProperty); + BSEffectShaderProperty() + { + REX::EMPLACE_VTABLE(this); + ctor(); + } // members BSParticleShaderCubeEmitter* envCubeEmitter; // 70 NiColor* externalEmitColor; // 78 std::uint32_t baseTextureIndex; // 80 float unk84; // 84 + + private: + void ctor() + { + using func_t = decltype(&BSEffectShaderProperty::ctor); + static REL::Relocation func{ ID::BSEffectShaderProperty::ctor }; + return func(this); + } }; static_assert(sizeof(BSEffectShaderProperty) == 0x88); } diff --git a/include/RE/IDs.h b/include/RE/IDs.h index 0cb498ba..a4fe1aa1 100644 --- a/include/RE/IDs.h +++ b/include/RE/IDs.h @@ -550,6 +550,11 @@ namespace RE::ID inline constexpr REL::ID Process2{ 2275932 }; } + namespace BSEffectShaderProperty + { + inline constexpr REL::ID ctor{ 2316383 }; + } + namespace BSFaceGenUtils { inline constexpr REL::ID StartFaceCustomizationGenerationForNPC{ 2209525 }; From c374258c26fe67faa4a1137d47c385558f81f668 Mon Sep 17 00:00:00 2001 From: Zeno Date: Wed, 26 Aug 2026 03:28:21 +0900 Subject: [PATCH 5/5] BGSCharacterTint: Add missing constructors --- include/RE/B/BGSCharacterTint.h | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/include/RE/B/BGSCharacterTint.h b/include/RE/B/BGSCharacterTint.h index da3ef7b3..f91fe091 100644 --- a/include/RE/B/BGSCharacterTint.h +++ b/include/RE/B/BGSCharacterTint.h @@ -72,7 +72,8 @@ namespace RE kTakesSkinTone = 0x4 }; - virtual ~Entry(); // 00 + Entry() { REX::EMPLACE_VTABLE(this); } + virtual ~Entry() = default; // 00 F4_HEAP_REDEFINE_NEW(Entry); @@ -123,6 +124,8 @@ namespace RE static constexpr auto RTTI{ RTTI::BGSCharacterTint__Template__Mask }; static constexpr auto VTABLE{ VTABLE::BGSCharacterTint__Template__Mask }; + Mask() { REX::EMPLACE_VTABLE(this); } + // Members BSFixedString maskTextureName; BGSCharacterTint::BlendOp blendOp; @@ -137,6 +140,8 @@ namespace RE static constexpr auto RTTI{ RTTI::BGSCharacterTint__Template__Palette }; static constexpr auto VTABLE{ VTABLE::BGSCharacterTint__Template__Palette }; + Palette() { REX::EMPLACE_VTABLE(this); } + class ColorValue { public: @@ -163,6 +168,8 @@ namespace RE static constexpr auto RTTI{ RTTI::BGSCharacterTint__Template__TextureSet }; static constexpr auto VTABLE{ VTABLE::BGSCharacterTint__Template__TextureSet }; + TextureSet() { REX::EMPLACE_VTABLE(this); } + // Members BSFixedString diffuse; BSFixedString normal; @@ -179,7 +186,10 @@ namespace RE static constexpr auto RTTI{ RTTI::BGSCharacterTint__Entry }; static constexpr auto VTABLE{ VTABLE::BGSCharacterTint__Entry }; - virtual ~Entry(); // 00 + Entry() { REX::EMPLACE_VTABLE(this); } + virtual ~Entry() = default; // 00 + + F4_HEAP_REDEFINE_NEW(Entry); virtual bool GetIsIdentical(const Entry* entry); // 08 virtual bool CopyData(const Entry entry); // 10 @@ -211,6 +221,8 @@ namespace RE public: static constexpr auto RTTI{ RTTI::BGSCharacterTint__MaskEntry }; static constexpr auto VTABLE{ VTABLE::BGSCharacterTint__MaskEntry }; + + MaskEntry() { REX::EMPLACE_VTABLE(this); } }; static_assert(sizeof(MaskEntry) == 0x18); @@ -221,6 +233,8 @@ namespace RE static constexpr auto RTTI{ RTTI::BGSCharacterTint__PaletteEntry }; static constexpr auto VTABLE{ VTABLE::BGSCharacterTint__PaletteEntry }; + PaletteEntry() { REX::EMPLACE_VTABLE(this); } + // members union { @@ -243,6 +257,8 @@ namespace RE public: static constexpr auto RTTI{ RTTI::BGSCharacterTint__TextureSetEntry }; static constexpr auto VTABLE{ VTABLE::BGSCharacterTint__TextureSetEntry }; + + TextureSetEntry() { REX::EMPLACE_VTABLE(this); } }; static_assert(sizeof(TextureSetEntry) == 0x18); }