docs: add plugin setup guide

This commit is contained in:
2026-05-30 18:33:24 +12:00
parent f3db41c402
commit b61043a3fe
1776 changed files with 122386 additions and 2 deletions
@@ -0,0 +1,45 @@
#pragma once
#include "RE/B/BSTSmartPointer.h"
#include "RE/E/ExtraDataList.h"
#include "RE/N/NiPoint3.h"
namespace RE
{
class BGSObjectInstanceExtra;
class BGSPrimitive;
class INSTANCE_FILTER;
class __declspec(novtable) NEW_REFR_DATA
{
public:
static constexpr auto RTTI{ RTTI::NEW_REFR_DATA };
static constexpr auto VTABLE{ VTABLE::NEW_REFR_DATA };
NEW_REFR_DATA()
{
REX::EMPLACE_VTABLE(this);
}
virtual void HandlePre3D(TESObjectREFR*) { return; }
// members
NiPoint3 location; // 08
NiPoint3 direction; // 14
TESBoundObject* object{ nullptr }; // 20
TESObjectCELL* interior{ nullptr }; // 28
TESWorldSpace* world{ nullptr }; // 30
TESObjectREFR* reference{ nullptr }; // 38
BGSPrimitive* addPrimitive{ nullptr }; // 40
void* additionalData{ nullptr }; // 48
BSTSmartPointer<ExtraDataList> extra{ nullptr }; // 50
INSTANCE_FILTER* instanceFilter{ nullptr }; // 58
BGSObjectInstanceExtra* modExtra{ nullptr }; // 60
std::uint16_t maxLevel{ 0 }; // 68
bool forcePersist{ false }; // 6A
bool clearStillLoadingFlag{ false }; // 6B
bool initializeScripts{ true }; // 6C
bool initiallyDisabled{ false }; // 6D
};
static_assert(sizeof(NEW_REFR_DATA) == 0x70);
}
@@ -0,0 +1,15 @@
#pragma once
namespace RE
{
class NPC_DATA
{
public:
// members
std::int16_t autoCalcHealth; // 0
std::int16_t autoCalcActionPoints; // 2
std::uint16_t farDistance; // 4
std::int8_t gearedUpWeapons; // 6
};
static_assert(sizeof(NPC_DATA) == 0x8);
}
@@ -0,0 +1,26 @@
#pragma once
#include "RE/B/BSNavmesh.h"
#include "RE/T/TESChildCell.h"
#include "RE/T/TESForm.h"
namespace RE
{
class __declspec(novtable) NavMesh :
public TESForm, // 00
public TESChildCell, // 20
public BSNavmesh // 28
{
public:
static constexpr auto RTTI{ RTTI::NavMesh };
static constexpr auto VTABLE{ VTABLE::NavMesh };
static constexpr auto FORM_ID{ ENUM_FORM_ID::kNAVM };
// add
virtual void Save() { return; } // 4A
virtual bool SavesBefore([[maybe_unused]] FORM* a_groupFORM) { return false; } // 4B
virtual bool SavesBefore([[maybe_unused]] TESForm* a_form) { return false; } // 4C
virtual bool ProcessBeforeSave() { return false; } // 4D
};
static_assert(sizeof(NavMesh) == 0x230);
}
@@ -0,0 +1,33 @@
#pragma once
#include "RE/B/BSNavmeshInfoMap.h"
#include "RE/B/BSTArray.h"
#include "RE/B/BSTHashMap.h"
#include "RE/P/PrecomputedNavmeshInfoPathMap.h"
#include "RE/T/TESForm.h"
namespace RE
{
class BSNavmeshInfo;
class NavMeshInfo;
class __declspec(novtable) NavMeshInfoMap :
public TESForm, // 000
public BSNavmeshInfoMap, // 020
public PrecomputedNavmeshInfoPathMap // 030
{
public:
static constexpr auto RTTI{ RTTI::NavMeshInfoMap };
static constexpr auto VTABLE{ VTABLE::NavMeshInfoMap };
static constexpr auto FORM_ID{ ENUM_FORM_ID::kNAVI };
// members
bool updateAll; // 078
BSTArray<BSNavmeshInfo*> staleNavmeshInfos; // 080
BSTHashMap<std::uint32_t, NavMeshInfo*> infoMap; // 098
BSTHashMap<std::size_t, BSTArray<BSNavmeshInfo*>*> ckNavMeshInfoMap; // 0C8
BSReadWriteLock mapLock; // 0F8
bool init; // 100
};
static_assert(sizeof(NavMeshInfoMap) == 0x108);
}
@@ -0,0 +1,91 @@
#pragma once
#include "RE/N/NiBound.h"
#include "RE/N/NiCollisionObject.h"
#include "RE/N/NiObjectNET.h"
#include "RE/N/NiPointer.h"
#include "RE/N/NiTFlags.h"
#include "RE/N/NiTransform.h"
namespace RE
{
class NiAlphaProperty;
class NiCullingProcess;
class NiNode;
class NiUpdateData;
class PerformOpFunc;
class __declspec(novtable) NiAVObject :
public NiObjectNET // 000
{
public:
F4_HEAP_REDEFINE_ALIGNED_NEW(NiAVObject);
static constexpr auto RTTI{ RTTI::NiAVObject };
static constexpr auto VTABLE{ VTABLE::NiAVObject };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiAVObject };
NiAVObject();
virtual ~NiAVObject(); // NOLINT(modernize-use-override) 00
// add
virtual void UpdateControllers(NiUpdateData& a_data); // 28
virtual void PerformOp(PerformOpFunc& a_operation); // 29
virtual void AttachProperty([[maybe_unused]] NiAlphaProperty* a_prop) { return; } // 2A
virtual void SetMaterialNeedsUpdate(bool) { return; } // 2B
virtual void SetDefaultMaterialNeedsUpdateFlag(bool) { return; } // 2C
virtual void SetAppCulled(bool a_appCulled); // 2D
virtual NiAVObject* GetObjectByName(const BSFixedString& a_name) { return name == a_name ? this : nullptr; } // 2E
virtual void SetSelectiveUpdateFlags(bool& a_selectiveUpdate, bool a_selectiveUpdateTransforms, bool& a_rigid); // 2F
virtual void UpdateDownwardPass(NiUpdateData& a_data, std::uint32_t a_flags); // 30
virtual void UpdateSelectedDownwardPass(NiUpdateData& a_data, std::uint32_t a_flags); // 31
virtual void UpdateRigidDownwardPass(NiUpdateData& a_data, std::uint32_t a_flags); // 32
virtual void UpdateWorldBound() { return; } // 33
virtual void UpdateWorldData(NiUpdateData* a_data); // 34
virtual void UpdateTransformAndBounds(NiUpdateData& a_data); // 35
virtual void UpdateTransforms(NiUpdateData& a_data) { UpdateWorldData(std::addressof(a_data)); } // 36
virtual void PreAttachUpdate(NiNode* a_eventualParent, NiUpdateData& a_data); // 37
virtual void PostAttachUpdate(); // 38
virtual void OnVisible([[maybe_unused]] NiCullingProcess& a_culler) { return; } // 39
bool GetAppCulled() const noexcept { return flags.flags & 1; }
NiPointer<NiCollisionObject> GetCollisionObject() const noexcept { return collisionObject; }
std::uint64_t GetFlags() const noexcept { return flags.flags; }
const NiMatrix3& GetLocalRotate() const noexcept { return local.rotate; }
float GetLocalScale() const noexcept { return local.scale; }
const NiTransform& GetLocalTransform() const noexcept { return local; }
const NiPoint3& GetLocalTranslate() const noexcept { return local.translate; }
const NiMatrix3& GetWorldRotate() const noexcept { return world.rotate; }
float GetWorldScale() const noexcept { return world.scale; }
const NiTransform& GetWorldTransform() const noexcept { return world; }
const NiPoint3& GetWorldTranslate() const noexcept { return world.translate; }
void SetLocalRotate(const NiMatrix3& a_rotate) noexcept { local.rotate = a_rotate; }
void SetLocalScale(float a_scale) noexcept { local.scale = a_scale; }
void SetLocalTransform(const NiTransform& a_transform) noexcept { local = a_transform; }
void SetLocalTranslate(const NiPoint3& a_translate) noexcept { local.translate = a_translate; }
void SetWorldRotate(const NiMatrix3& a_rotate) noexcept { world.rotate = a_rotate; }
void SetWorldScale(float a_scale) noexcept { world.scale = a_scale; }
void SetWorldTransform(const NiTransform& a_transform) noexcept { world = a_transform; }
void SetWorldTranslate(const NiPoint3& a_translate) noexcept { world.translate = a_translate; }
bool ShadowCaster() const noexcept { return ~(flags.flags >> 40) & 1; }
void CullGeometry(bool a_cull);
void CullNode(bool a_cull);
void Update(NiUpdateData& a_data);
// members
NiNode* parent{ nullptr }; // 027
NiTransform local; // 030
NiTransform world; // 070
NiBound worldBound; // 0B0
NiTransform previousWorld; // 0C0
NiPointer<NiCollisionObject> collisionObject; // 100
NiTFlags<std::uint64_t, NiAVObject> flags; // 108
std::uintptr_t userData{ 0 }; // 110
float fadeAmount{ 1.0F }; // 118
std::int8_t multType{ 0 }; // 11C
std::int8_t meshLODFadingLevel{ 0 }; // 11D
std::int8_t currentMeshLODLevel{ 0 }; // 11E
std::int8_t previousMeshLODLevel{ 0 }; // 11F
};
static_assert(sizeof(NiAVObject) == 0x120);
}
@@ -0,0 +1,27 @@
#pragma once
#include "RE/N/NiVisibleArray.h"
namespace RE
{
class __declspec(novtable) NiAccumulator :
public NiObject // 00
{
public:
static constexpr auto RTTI{ RTTI::NiAccumulator };
static constexpr auto VTABLE{ VTABLE::NiAccumulator };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiAccumulator };
// add
virtual void StartAccumulating(const NiCamera* a_camera); // 28
virtual void FinishAccumulating(); // 29
virtual void RegisterObjectArray(NiVisibleArray* a_unk0); // 2A
virtual void StartGroupingAlphas(const NiBound* a_unk0, bool a_unk1); // 2B
virtual void StopGroupingAlphas(); // 2C
virtual void RegisterObject(BSGeometry* a_unk0); // 2D
// members
const NiCamera* camera; // 10
};
static_assert(sizeof(NiAccumulator) == 0x18);
}
@@ -0,0 +1,21 @@
#pragma once
#include "RE/N/NiBackToFrontAccumulator.h"
namespace RE
{
class __declspec(novtable) NiAlphaAccumulator :
public NiBackToFrontAccumulator // 00
{
public:
static constexpr auto RTTI{ RTTI::NiAlphaAccumulator };
static constexpr auto VTABLE{ VTABLE::NiAlphaAccumulator };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiAlphaAccumulator };
// members
bool observeNoSortHint; // 50
bool sortByClosestPoint; // 51
bool interfaceSort; // 52
};
static_assert(sizeof(NiAlphaAccumulator) == 0x58);
}
@@ -0,0 +1,100 @@
#pragma once
#include "RE/N/NiProperty.h"
#include "RE/N/NiTFlags.h"
namespace RE
{
class __declspec(novtable) NiAlphaProperty :
public NiProperty // 00
{
public:
static constexpr auto RTTI{ RTTI::NiAlphaProperty };
static constexpr auto VTABLE{ VTABLE::NiAlphaProperty };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiAlphaProperty };
enum class AlphaFunction
{
kOne,
kZero,
kSrcColor,
kInvSrcColor,
kDestColor,
kInvDestColor,
kSrcAlpha,
kInvSrcAlpha,
kDestAlpha,
kInvDestAlpha,
kSrcAlphaTest
};
enum class TestFunction
{
kAlways,
kLess,
kEqual,
kLessEqual,
kGreater,
kNotEqual,
kGreaterEqual,
kNever
};
NiAlphaProperty()
{
REX::EMPLACE_VTABLE(this);
NiTFlags<std::uint16_t, NiProperty> f;
f.flags = 0xEC;
flags = f;
alphaTestRef = 0;
}
virtual ~NiAlphaProperty();
virtual std::int32_t Type()
{
return 0;
}
F4_HEAP_REDEFINE_ALIGNED_NEW(NiAlphaProperty);
void SetDestBlendMode(AlphaFunction f)
{
using func_t = decltype(&NiAlphaProperty::SetDestBlendMode);
static REL::Relocation<func_t> func{ ID::NiAlphaProperty::SetDestBlendMode };
return func(this, f);
}
void SetSrcBlendMode(AlphaFunction f)
{
using func_t = decltype(&NiAlphaProperty::SetSrcBlendMode);
static REL::Relocation<func_t> func{ ID::NiAlphaProperty::SetSrcBlendMode };
return func(this, f);
}
void SetTestMode(TestFunction f)
{
using func_t = decltype(&NiAlphaProperty::SetTestMode);
static REL::Relocation<func_t> func{ ID::NiAlphaProperty::SetTestMode, 0x20 };
return func(this, f);
}
void SetAlphaBlending(bool b)
{
using func_t = decltype(&NiAlphaProperty::SetAlphaBlending);
static REL::Relocation<func_t> func{ ID::NiAlphaProperty::SetAlphaBlending };
return func(this, b);
}
void SetAlphaTesting(bool b)
{
using func_t = decltype(&NiAlphaProperty::SetAlphaTesting);
static REL::Relocation<func_t> func{ ID::NiAlphaProperty::SetAlphaTesting, 0x20 };
return func(this, b);
}
// members
NiTFlags<std::uint16_t, NiProperty> flags; // 28
std::int8_t alphaTestRef; // 2A
};
static_assert(sizeof(NiAlphaProperty) == 0x30);
}
@@ -0,0 +1,27 @@
#pragma once
#include "RE/N/NiAccumulator.h"
#include "RE/N/NiTPointerList.h"
namespace RE
{
class BSGeometry;
class __declspec(novtable) NiBackToFrontAccumulator :
public NiAccumulator // 000
{
public:
static constexpr auto RTTI{ RTTI::NiBackToFrontAccumulator };
static constexpr auto VTABLE{ VTABLE::NiBackToFrontAccumulator };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiBackToFrontAccumulator };
// members
NiTPointerList<BSGeometry*> items; // 18
std::int32_t numItems; // 30
std::int32_t maxItems; // 34
BSGeometry** pkItems; // 38
float* depths; // 40
std::int32_t currItem; // 48
};
static_assert(sizeof(NiBackToFrontAccumulator) == 0x50);
}
@@ -0,0 +1,28 @@
#pragma once
namespace RE
{
class __declspec(novtable) alignas(0x10) NiBillboardNode :
public NiNode // 00
{
public:
static constexpr auto RTTI{ RTTI::NiBillboardNode };
static constexpr auto VTABLE{ VTABLE::NiBillboardNode };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiBillboardNode };
virtual ~NiBillboardNode();
enum class FaceMode
{
kAlwaysFaceCamera = 0x0,
kRotateAboutUp = 0x1,
kRigidFaceCamera = 0x3,
kAlwaysFaceCenter = 0x4,
kBSRotateAboutUp = 0x5
};
// members
NiTFlags<std::uint32_t, NiBillboardNode> flags; // 140
};
static_assert(sizeof(NiBillboardNode) == 0x150);
}
@@ -0,0 +1,52 @@
#pragma once
#include "RE/N/NiExtraData.h"
namespace RE
{
class __declspec(novtable) NiBinaryExtraData :
public NiExtraData
{
public:
static constexpr auto RTTI{ RTTI::NiBinaryExtraData };
static constexpr auto VTABLE{ VTABLE::NiBinaryExtraData };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiBinaryExtraData };
NiBinaryExtraData() :
NiExtraData()
{
REX::EMPLACE_VTABLE(this);
}
NiBinaryExtraData(void* a_value, const std::uint32_t a_size) :
NiExtraData(), value(a_value), size(a_size)
{
REX::EMPLACE_VTABLE(this);
}
NiBinaryExtraData(const BSFixedString& a_name, void* a_value, const std::uint32_t a_size) :
NiExtraData(a_name), value(a_value), size(a_size)
{
REX::EMPLACE_VTABLE(this);
}
public:
void GetValue(void** a_value, std::uint32_t* a_size) const
{
*a_value = value;
*a_size = size;
}
void SetValue(void* a_value, const std::uint32_t a_size)
{
value = a_value;
size = a_size;
}
protected:
// members
void* value{ nullptr }; // 0x18
std::uint32_t size{ 0 }; // 0x20
};
static_assert(sizeof(NiBinaryExtraData) == 0x28);
}
@@ -0,0 +1,116 @@
#pragma once
namespace RE
{
class __declspec(novtable) NiBinaryStream
{
public:
static constexpr auto RTTI{ RTTI::NiBinaryStream };
static constexpr auto VTABLE{ VTABLE::NiBinaryStream };
class BufferInfo
{
public:
void* buffer; // 00
std::size_t fileSize; // 08
std::size_t bufferAllocSize; // 10
std::size_t bufferReadSize; // 18
std::size_t pos; // 20
std::size_t absCurrentPos; // 28
};
static_assert(sizeof(BufferInfo) == 0x30);
NiBinaryStream() = default;
virtual ~NiBinaryStream() = default; // 00
// add
virtual explicit operator bool() const = 0; // 01
virtual void Seek(std::ptrdiff_t a_numBytes) = 0; // 02
virtual std::size_t GetPosition() const { return absoluteCurrentPos; } // 03
virtual void GetBufferInfo(BufferInfo& a_info); // 04
virtual std::size_t DoRead(void* a_buffer, std::size_t a_bytes) = 0; // 05
virtual std::size_t DoWrite(const void* a_buffer, std::size_t a_bytes) = 0; // 06
template <class CharT>
bool get(CharT& a_ch);
template <class CharT>
bool read(CharT* a_str, std::size_t a_count);
template <class CharT>
bool put(CharT a_ch);
template <class CharT>
bool write(const CharT* a_str, std::size_t a_count);
std::size_t binary_read(void* a_buffer, std::size_t a_totalBytes);
std::size_t binary_write(const void* a_buffer, std::size_t a_totalBytes);
// members
std::size_t absoluteCurrentPos{ 0 }; // 08
};
static_assert(sizeof(NiBinaryStream) == 0x10);
template <class CharT>
inline bool NiBinaryStream::get(CharT& a_ch)
{
return read(&a_ch, 1);
}
template <class CharT>
inline bool NiBinaryStream::read(CharT* a_str, std::size_t a_count)
{
std::size_t size = sizeof(CharT);
std::size_t toRead = a_count * size;
std::size_t bytesRead = binary_read(a_str, toRead);
return bytesRead == toRead;
}
template <class CharT>
inline bool NiBinaryStream::put(CharT a_ch)
{
return write(&a_ch, 1);
}
template <class CharT>
inline bool NiBinaryStream::write(const CharT* a_str, std::size_t a_count)
{
std::size_t size = sizeof(CharT);
std::size_t toWrite = a_count * size;
std::size_t bytesWritten = binary_write(a_str, toWrite);
return bytesWritten == toWrite;
}
}
namespace std
{
template <class CharT, class Traits, class Allocator>
inline bool getline(RE::NiBinaryStream& a_input, std::basic_string<CharT, Traits, Allocator>& a_str)
{
CharT delim = std::use_facet<std::ctype<CharT>>(std::locale()).widen('\n');
return getline(a_input, a_str, delim);
}
template <class CharT, class Traits, class Allocator>
inline bool getline(RE::NiBinaryStream& a_input, std::basic_string<CharT, Traits, Allocator>& a_str, CharT a_delim)
{
a_str.erase();
CharT c;
auto notEOF = a_input.get(c);
if (notEOF) {
do {
if (!std::char_traits<CharT>::eq(c, a_delim)) {
a_str.push_back(c);
} else {
break;
}
if (a_str.size() != a_str.max_size()) {
notEOF = a_input.get(c);
} else {
break;
}
} while (notEOF);
return true;
} else {
return false;
}
}
}
@@ -0,0 +1,49 @@
#pragma once
#include "RE/N/NiExtraData.h"
namespace RE
{
class __declspec(novtable) NiBooleanExtraData :
public NiExtraData
{
public:
static constexpr auto RTTI{ RTTI::NiBooleanExtraData };
static constexpr auto VTABLE{ VTABLE::NiBooleanExtraData };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiBooleanExtraData };
NiBooleanExtraData() :
NiExtraData()
{
REX::EMPLACE_VTABLE(this);
}
NiBooleanExtraData(const bool a_value) :
NiExtraData(), value(a_value)
{
REX::EMPLACE_VTABLE(this);
}
NiBooleanExtraData(const BSFixedString& a_name, const bool a_value) :
NiExtraData(a_name), value(a_value)
{
REX::EMPLACE_VTABLE(this);
}
public:
bool GetValue() const
{
return value;
}
void SetValue(const bool a_value)
{
value = a_value;
}
protected:
// members
bool value{ 0 }; // 0x18
};
static_assert(sizeof(NiBooleanExtraData) == 0x20);
}
@@ -0,0 +1,19 @@
#pragma once
#include "RE/N/NiPoint3.h"
namespace RE
{
class NiBound
{
public:
// members
NiPoint3 center; // 00
union
{
float fRadius;
std::int32_t iRadius{ 0 };
}; // 0C
};
static_assert(sizeof(NiBound) == 0x10);
}
@@ -0,0 +1,80 @@
#pragma once
#include "RE/N/NiAVObject.h"
#include "RE/N/NiFrustum.h"
#include "RE/N/NiRect.h"
namespace RE
{
class __declspec(novtable) NiCamera :
public NiAVObject // 00
{
public:
static constexpr auto RTTI{ RTTI::NiCamera };
static constexpr auto VTABLE{ VTABLE::NiCamera };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiCamera };
virtual ~NiCamera(); // 00
// override
virtual const NiRTTI* GetRTTI() const override; // 02
virtual NiObject* CreateClone(NiCloningProcess& a_cloneData) override; // 1A
virtual void LoadBinary(NiStream& a_stream) override; // 1B
virtual void LinkObject(NiStream& a_stream) override; // 1C
virtual bool RegisterStreamables(NiStream& a_stream) override; // 1D
virtual void SaveBinary(NiStream& a_stream) override; // 1E
virtual bool IsEqual(NiObject* a_object) override; // 1F
virtual void UpdateWorldBound() override; // 33
virtual void UpdateWorldData(NiUpdateData* a_data) override; // 34
static bool BoundInFrustum(const NiBound& a_bound, NiCamera* a_camera)
{
using func_t = decltype(&NiCamera::BoundInFrustum);
static REL::Relocation<func_t> func{ ID::NiCamera::BoundInFrustum };
return func(a_bound, a_camera);
}
bool NodeInFrustum(NiAVObject* a_node)
{
if (!a_node) {
return false;
}
return BoundInFrustum(a_node->worldBound, this);
}
bool PointInFrustum(const NiPoint3& a_point, float a_radius)
{
const NiBound bound{ a_point, { a_radius } };
return BoundInFrustum(bound, this);
}
bool WorldPtToScreenPt3(const NiPoint3& a_point, float& a_x, float& a_y, float& a_z, float a_zeroTolerance) const
{
return WorldPtToScreenPt3(worldToCam, port, a_point, a_x, a_y, a_z, a_zeroTolerance);
}
static bool WorldPtToScreenPt3(const float a_matrix[4][4], const NiRect<float>& a_port, const NiPoint3& a_point, float& a_x, float& a_y, float& a_z, float a_zeroTolerance)
{
using func_t = bool (*)(const float[4][4], const NiRect<float>&, const NiPoint3&, float&, float&, float&, float);
static REL::Relocation<func_t> func{ ID::NiCamera::WorldPtToScreenPt3 };
return func(a_matrix, a_port, a_point, a_x, a_y, a_z, a_zeroTolerance);
}
void ViewPointToRay(float a_vx, float a_vy, NiPoint3* a_origin, NiPoint3* a_dir)
{
using func_t = decltype(&NiCamera::ViewPointToRay);
static REL::Relocation<func_t> func{ ID::NiCamera::ViewPointToRay };
return func(this, a_vx, a_vy, a_origin, a_dir);
}
// members
float worldToCam[4][4]; // 120
NiFrustum viewFrustum; // 160
float minNearPlaneDist; // 17C
float maxFarNearRatio; // 180
NiRect<float> port; // 184
float lodAdjust; // 194
};
static_assert(sizeof(NiCamera) == 0x1A0);
}
@@ -0,0 +1,28 @@
#pragma once
#include "RE/B/BSTHashMap.h"
#include "RE/N/NiPoint3.h"
namespace RE
{
class NiObject;
class NiCloningProcess
{
public:
enum class CopyType
{
kNone = 0,
kCopyExact,
kCopyUnique,
};
// members
BSTHashMap<NiObject*, NiObject*> cloneMap; // 00
BSTHashMap<NiObject*, bool> processMap; // 30
REX::TEnumSet<CopyType, std::uint32_t> copyType; // 60
char appendChar; // 64
NiPoint3 scale; // 68
};
static_assert(sizeof(NiCloningProcess) == 0x78);
}
@@ -0,0 +1,33 @@
#pragma once
#include "RE/N/NiObject.h"
namespace RE
{
class NiAVObject;
class NiUpdateData;
class __declspec(novtable) NiCollisionObject :
public NiObject // 00
{
public:
static constexpr auto RTTI{ RTTI::NiCollisionObject };
static constexpr auto VTABLE{ VTABLE::NiCollisionObject };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiCollisionObject };
// add
virtual void SetSceneGraphObject(NiAVObject* a_sceneObject); // 28
virtual void UpdateWorldData(NiUpdateData& a_updateData); // 29
virtual void Initialize([[maybe_unused]] void* a_data) { return; } // 2A
virtual void Convert([[maybe_unused]] std::uint32_t a_version, [[maybe_unused]] void* a_data) { return; } // 2B
NiAVObject* GetSceneGraphObject() const
{
return sceneObject;
}
// members
NiAVObject* sceneObject; // 10
};
static_assert(sizeof(NiCollisionObject) == 0x18);
}
@@ -0,0 +1,41 @@
#pragma once
namespace RE
{
class NiColor
{
public:
constexpr NiColor() = default;
constexpr NiColor(const float a_red, const float a_green, const float a_blue) :
r(a_red), g(a_green), b(a_blue)
{}
// members
float r{ 0 }; // 0x0
float g{ 0 }; // 0x4
float b{ 0 }; // 0x8
};
static_assert(sizeof(NiColor) == 0xC);
class NiColorA
{
public:
constexpr NiColorA() = default;
constexpr NiColorA(const float a_red, const float a_green, const float a_blue, const float a_alpha) :
r(a_red), g(a_green), b(a_blue), a(a_alpha)
{}
constexpr NiColorA(const NiColor& a_color) :
r(a_color.r), g(a_color.g), b(a_color.b)
{}
// members
float r{ 0 }; // 0x0
float g{ 0 }; // 0x4
float b{ 0 }; // 0x8
float a{ 0 }; // 0xC
};
static_assert(sizeof(NiColorA) == 0x10);
}
@@ -0,0 +1,55 @@
#pragma once
#include "RE/N/NiColor.h"
#include "RE/N/NiExtraData.h"
namespace RE
{
class __declspec(novtable) NiColorExtraData :
public NiExtraData
{
public:
static constexpr auto RTTI{ RTTI::NiColorExtraData };
static constexpr auto VTABLE{ VTABLE::NiColorExtraData };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiColorExtraData };
NiColorExtraData() :
NiExtraData()
{
REX::EMPLACE_VTABLE(this);
}
NiColorExtraData(const NiColorA& a_value) :
NiExtraData(), value(a_value)
{
REX::EMPLACE_VTABLE(this);
}
NiColorExtraData(const BSFixedString& a_name, const NiColorA& a_value) :
NiExtraData(a_name), value(a_value)
{
REX::EMPLACE_VTABLE(this);
}
public:
const NiColorA& GetValue() const
{
return value;
}
void SetValue(const NiColor& a_value)
{
value = a_value;
}
void SetValue(const NiColorA& a_value)
{
value = a_value;
}
protected:
// members
NiColorA value; // 0x18
};
static_assert(sizeof(NiColorExtraData) == 0x28);
}
@@ -0,0 +1,61 @@
#pragma once
#include "RE/B/BSFixedString.h"
#include "RE/B/BSTHashMap.h"
#include "RE/N/NiControllerSequence.h"
#include "RE/N/NiPointer.h"
#include "RE/N/NiTArray.h"
#include "RE/N/NiTimeController.h"
namespace RE
{
class BSAnimNoteListener;
class NiAVObjectPalette;
class NiControllerManager :
public NiTimeController // 00
{
public:
static constexpr auto RTTI{ RTTI::NiControllerManager };
static constexpr auto VTABLE{ VTABLE::NiControllerManager };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiControllerManager };
[[nodiscard]] static NiControllerManager* GetNiControllerManager(const NiObjectNET* a_object)
{
using func_t = decltype(&NiControllerManager::GetNiControllerManager);
static REL::Relocation<func_t> func{ ID::NiControllerManager::GetNiControllerManager };
return func(a_object);
}
[[nodiscard]] NiControllerSequence* GetSequenceByName(const BSFixedString& a_name)
{
using func_t = decltype(&NiControllerManager::GetSequenceByName);
static REL::Relocation<func_t> func{ ID::NiControllerManager::GetSequenceByName };
return func(this, a_name);
}
[[nodiscard]] NiControllerSequence* GetSequenceAt(std::uint16_t a_index)
{
if (a_index >= 0 && a_index < sequenceArray.size()) {
return sequenceArray[a_index].get();
}
return nullptr;
}
[[nodiscard]] std::uint16_t GetSequenceCount() const noexcept
{
return sequenceArray.size();
}
// members
NiTObjectArray<NiPointer<NiControllerSequence>> sequenceArray; // 48
std::byte activeSequences[0x70 - 0x60]; // 60 - TODO
BSTHashMap<BSFixedString, NiControllerSequence*> stringMap; // 70
BSAnimNoteListener* listener; // A0
bool cumulative; // A8
std::byte tempBlendSeqs[0xC0 - 0xB0]; // B0 - TODO
NiPointer<NiAVObjectPalette> objectPalette; // C0
};
static_assert(sizeof(NiControllerManager) == 0xC8);
}
@@ -0,0 +1,86 @@
#pragma once
#include "RE/B/BSFixedString.h"
#include "RE/N/NiObject.h"
#include "RE/N/NiPointer.h"
namespace RE
{
class BSAnimNote;
class NiAVObject;
class NiControllerManager;
class NiStringPalette;
class NiTextKeyExtraData;
class NiControllerSequence :
public NiObject // 00
{
public:
static constexpr auto RTTI{ RTTI::NiControllerSequence };
static constexpr auto VTABLE{ VTABLE::NiControllerSequence };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiControllerSequence };
enum class AnimState : std::int32_t
{
kInactive = 0x0,
kAnimating = 0x1,
kEaseIn = 0x2,
kEaseOut = 0x3,
kTransSource = 0x4,
kTransDest = 0x5,
kMorphSource = 0x6
};
class IDTag
{
public:
// members
BSFixedString avObjectName; // 00
BSFixedString propertyType; // 08
BSFixedString ctrlType; // 10
BSFixedString ctrlID; // 18
BSFixedString interpolatorID; // 20
};
static_assert(sizeof(IDTag) == 0x28);
class InterpArrayItem;
bool Activate(std::uint8_t a_priority, bool a_startOver, float a_weight, float a_easeInTime, NiControllerSequence* a_timeSyncSeq, bool a_transition)
{
using func_t = decltype(&NiControllerSequence::Activate);
static REL::Relocation<func_t> func{ ID::NiControllerSequence::Activate };
return func(this, a_priority, a_startOver, a_weight, a_easeInTime, a_timeSyncSeq, a_transition);
}
// members
BSFixedString name; // 10
std::uint32_t arraySize; // 18
std::uint32_t arrayGrowBy; // 1C
InterpArrayItem* interpArray; // 20
IDTag* idTagArray; // 28
float seqWeight; // 30
NiPointer<NiTextKeyExtraData> textKeys; // 38
std::byte cycleType[4]; // 40
float frequency; // 44
float beginKeyTime; // 48
float endKeyTime; // 4C
float lastTime; // 50
float weightedLastTime; // 54
float lastScaledTime; // 58
NiControllerManager* owner; // 60
REX::TEnumSet<AnimState, std::int32_t> state; // 68
float offset; // 6C
float startTime; // 70
float endTime; // 74
float destFrame; // 78
NiControllerSequence* partnerSequence; // 80
BSFixedString accumRootName; // 88
NiAVObject* accumRoot; // 90
NiPointer<NiStringPalette> deprecatedStringPalette; // 98
std::int16_t curAnimNIdx; // A0
NiPointer<BSAnimNote>* animNotes; // A8
std::uint16_t numNotes; // B0
bool removableObjects; // B2
};
static_assert(sizeof(NiControllerSequence) == 0xB8);
}
@@ -0,0 +1,57 @@
#pragma once
#include "RE/N/NiVisibleArray.h"
namespace RE
{
class __declspec(novtable) NiCullingProcess
{
public:
static constexpr auto RTTI{ RTTI::NiCullingProcess };
static constexpr auto VTABLE{ VTABLE::NiCullingProcess };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiCullingProcess };
// add
virtual const NiRTTI* GetRTTI() const; // 00
virtual const NiNode* IsNode() const; // 01
virtual NiNode* IsNode(); // 02
virtual NiSwitchNode* IsSwitchNode(); // 03
virtual BSFadeNode* IsFadeNode(); // 04
virtual BSMultiBoundNode* IsMultiBoundNode(); // 05
virtual BSGeometry* IsGeometry(); // 06
virtual NiTriStrips* IsTriStrips(); // 07
virtual BSTriShape* IsTriShape(); // 08
virtual BSDynamicTriShape* IsDynamicTriShape(); // 09
virtual BSSegmentedTriShape* IsSegmentedTriShape(); // 0A
virtual BSSubIndexTriShape* IsSubIndexTriShape(); // 0B
virtual NiGeometry* IsNiGeometry(); // 0C
virtual NiTriBasedGeom* IsNiTriBasedGeom(); // 0D
virtual NiTriShape* IsNiTriShape(); // 0E
virtual NiParticles* IsParticlesGeom(); // 0F
virtual NiParticleSystem* IsParticleSystem(); // 10
virtual BSLines* IsLinesGeom(); // 11
virtual NiLight* IsLight(); // 12
virtual bhkNiCollisionObject* IsBhkNiCollisionObject(); // 13
virtual bhkBlendCollisionObject IsBhkBlendCollisionObject(); // 14
virtual bhkRigidBody IsBhkRigidBody(); // 15
virtual bhkLimitedHingeConstraint IsBhkLimitedHingeConstraint(); // 16
virtual bhkNPCollisionObject IsbhkNPCollisionObject(); // 17
virtual ~NiCullingProcess(); // 18
virtual void Process(NiAVObject* a_object); // 19
virtual void Process(const NiCamera* a_camera, NiAVObject* a_scene, NiVisibleArray* a_visibleSet); // 1A
virtual void AppendVirtual(BSGeometry* a_visible); // 1B
// members
bool useVirtualAppend; // 08
NiVisibleArray* visibleSet; // 10
NiCamera* camera; // 18
NiFrustum frustum; // 20
NiFrustumPlanes planes; // 3C
NiFrustumPlanes customCullPlanes; // AC
bool cameraRelatedUpdates; // 11C
bool updateAccumulateFlag; // 11D
bool ignorePreprocess; // 11E
bool bCustomCullPlanes; // 11F
};
static_assert(sizeof(NiCullingProcess) == 0x120);
}
@@ -0,0 +1,34 @@
#pragma once
#include "RE/B/BSFixedString.h"
#include "RE/N/NiObject.h"
namespace RE
{
class __declspec(novtable) NiExtraData :
public NiObject // 0x00
{
public:
static constexpr auto RTTI{ RTTI::NiExtraData };
static constexpr auto VTABLE{ VTABLE::NiExtraData };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiExtraData };
NiExtraData();
NiExtraData(const BSFixedString& a_name);
virtual ~NiExtraData(); // 00
// add
virtual bool KeepForExport() const { return false; } // 28
virtual bool KeepForExporterOnly() const { return false; } // 29
virtual bool IsStreamable() const { return true; } // 2A
virtual bool IsCloneable() const { return true; } // 2B
const BSFixedString& GetName() const;
void SetName(const BSFixedString& a_name);
// members
BSFixedString name; // 0x10
};
static_assert(sizeof(NiExtraData) == 0x18);
}
@@ -0,0 +1,34 @@
#pragma once
#include "RE/B/BSFixedString.h"
#include "RE/B/BSSpinLock.h"
#include "RE/B/BSTArray.h"
#include "RE/N/NiPointer.h"
namespace RE
{
class NiExtraData;
class NiExtraDataContainer
{
public:
NiExtraDataContainer(const std::uint32_t a_count);
void Add(NiExtraData* a_extra);
NiExtraData* FindExtra(const BSFixedString& a_key) const;
std::int32_t FindIndex(const BSFixedString& a_key) const;
std::uint32_t GetSize() const;
bool RemoveExtra(const BSFixedString& a_key);
template <class T>
T* FindExtra(const BSFixedString& a_key) const
{
return static_cast<T*>(FindExtra(a_key));
}
// members
BSTArray<NiPointer<NiExtraData>> extra;
mutable BSReadWriteLock lock;
};
static_assert(sizeof(NiExtraDataContainer) == 0x20);
}
@@ -0,0 +1,34 @@
#pragma once
#include "RE/B/BSSystemFile.h"
#include "RE/N/NiBinaryStream.h"
namespace RE
{
class __declspec(novtable) NiFile :
public NiBinaryStream // 00
{
public:
static constexpr auto RTTI{ RTTI::NiFile };
static constexpr auto VTABLE{ VTABLE::NiFile };
enum class OpenMode : std::int32_t
{
kReadOnly,
kWriteOnly,
kAppendOnly,
kReadWrite,
};
// members
std::size_t bufferAllocSize; // 10
std::size_t bufferReadSize; // 18
std::size_t pos; // 20
std::size_t currentFilePos; // 28
char* buffer; // 30
BSSystemFile systemFile; // 38
REX::TEnumSet<OpenMode, std::int32_t> mode; // 48
bool good; // 4C
};
static_assert(sizeof(NiFile) == 0x50);
}
@@ -0,0 +1,49 @@
#pragma once
#include "RE/N/NiExtraData.h"
namespace RE
{
class __declspec(novtable) NiFloatExtraData :
public NiExtraData
{
public:
static constexpr auto RTTI{ RTTI::NiFloatExtraData };
static constexpr auto VTABLE{ VTABLE::NiFloatExtraData };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiFloatExtraData };
NiFloatExtraData() :
NiExtraData()
{
REX::EMPLACE_VTABLE(this);
}
NiFloatExtraData(const float a_value) :
NiExtraData(), value(a_value)
{
REX::EMPLACE_VTABLE(this);
}
NiFloatExtraData(const BSFixedString& a_name, const float a_value) :
NiExtraData(a_name), value(a_value)
{
REX::EMPLACE_VTABLE(this);
}
public:
float GetValue() const
{
return value;
}
void SetValue(const float a_value)
{
value = a_value;
}
protected:
// members
float value{ 0 }; // 0x18
};
static_assert(sizeof(NiIntegerExtraData) == 0x20);
}
@@ -0,0 +1,17 @@
#pragma once
namespace RE
{
class NiFrustum
{
public:
float left; // 00
float right; // 04
float top; // 08
float bottom; // 0C
float near; // 10
float far; // 14
bool ortho; // 18
};
static_assert(sizeof(NiFrustum) == 0x1C);
}
@@ -0,0 +1,27 @@
#pragma once
#include "RE/N/NiPlane.h"
namespace RE
{
class NiFrustumPlanes
{
public:
enum class Plane
{
kNearPlane = 0x0,
kFarPlane = 0x1,
kLeftPlane = 0x2,
kRightPlane = 0x3,
kTopPlane = 0x4,
kBottomPlane = 0x5
};
// members
NiPlane cullingPlanes[6]; // 00
std::uint32_t activePlanes; // 60
std::uint32_t basePlaneStates; //64
std::byte pad[0x8]; // 68
};
static_assert(sizeof(NiFrustumPlanes) == 0x70);
}
@@ -0,0 +1,49 @@
#pragma once
#include "RE/N/NiExtraData.h"
namespace RE
{
class __declspec(novtable) NiIntegerExtraData :
public NiExtraData
{
public:
static constexpr auto RTTI{ RTTI::NiIntegerExtraData };
static constexpr auto VTABLE{ VTABLE::NiIntegerExtraData };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiIntegerExtraData };
NiIntegerExtraData() :
NiExtraData()
{
REX::EMPLACE_VTABLE(this);
}
NiIntegerExtraData(const std::int32_t a_value) :
NiExtraData(), value(a_value)
{
REX::EMPLACE_VTABLE(this);
}
NiIntegerExtraData(const BSFixedString& a_name, const std::int32_t a_value) :
NiExtraData(a_name), value(a_value)
{
REX::EMPLACE_VTABLE(this);
}
public:
std::int32_t GetValue() const
{
return value;
}
void SetValue(const std::int32_t a_value)
{
value = a_value;
}
protected:
// members
std::int32_t value{ 0 }; // 0x18
};
static_assert(sizeof(NiIntegerExtraData) == 0x20);
}
@@ -0,0 +1,26 @@
#pragma once
#include "RE/N/NiAVObject.h"
#include "RE/N/NiBound.h"
#include "RE/N/NiColor.h"
namespace RE
{
class __declspec(novtable) NiLight :
public NiAVObject // 000
{
public:
static constexpr auto RTTI{ RTTI::NiLight };
static constexpr auto VTABLE{ VTABLE::NiLight };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiLight };
// members
NiColor amb; // 120
NiColor diff; // 12C
NiColor spec; // 138
float dimmer; // 144
alignas(16) NiBound modelBound; // 150
void* rendererData; // 160
};
static_assert(sizeof(NiLight) == 0x170);
}
@@ -0,0 +1,175 @@
#pragma once
#include "RE/N/NiPoint4.h"
namespace RE
{
class alignas(0x10) NiMatrix3
{
public:
static const NiMatrix3 ZERO;
static const NiMatrix3 IDENTITY;
constexpr NiMatrix3() noexcept = default;
constexpr NiMatrix3(const NiPoint4& a_point0, const NiPoint4& a_point1, const NiPoint4& a_point2) noexcept;
constexpr NiMatrix3(
float a_x0, float a_y0, float a_z0, float a_w0,
float a_x1, float a_y1, float a_z1, float a_w1,
float a_x2, float a_y2, float a_z2, float a_w2) noexcept;
constexpr NiPoint4& operator[](std::size_t a_pos) noexcept;
constexpr const NiPoint4& operator[](std::size_t a_pos) const noexcept;
constexpr bool operator==(const NiMatrix3& a_rhs) const noexcept;
constexpr bool operator!=(const NiMatrix3& a_rhs) const noexcept;
constexpr NiMatrix3 operator*(const NiMatrix3& a_rhs) const noexcept;
constexpr NiMatrix3 operator*(float a_scalar) const noexcept;
constexpr NiPoint3 operator*(const NiPoint3& a_rhs) const noexcept;
constexpr void MakeIdentity() noexcept;
constexpr NiMatrix3 Transpose() const noexcept;
bool ToEulerAnglesXYZ(NiPoint3& a_point) const;
bool ToEulerAnglesXYZ(float& a_x, float& a_y, float& a_z) const;
bool ToEulerAnglesXZY(float& a_x, float& a_z, float& a_y) const;
bool ToEulerAnglesYXZ(float& a_y, float& a_x, float& a_z) const;
bool ToEulerAnglesYZX(float& a_y, float& a_z, float& a_x) const;
bool ToEulerAnglesZYX(float& a_z, float& a_y, float& a_x) const;
bool ToEulerAnglesZXY(float& a_z, float& a_y, float& a_x) const;
void FromEulerAnglesXYZ(const NiPoint3& a_point);
void FromEulerAnglesXYZ(float a_x, float a_y, float a_z);
void FromEulerAnglesXZY(float a_x, float a_z, float a_y);
void FromEulerAnglesYXZ(float a_y, float a_x, float a_z);
void FromEulerAnglesYZX(float a_y, float a_z, float a_x);
void FromEulerAnglesZYX(float a_z, float a_y, float a_x);
void FromEulerAnglesZXY(float a_z, float a_x, float a_y);
// members
NiPoint4 entry[3]; // 00
};
static_assert(sizeof(NiMatrix3) == 0x30);
}
namespace RE
{
inline const NiMatrix3 NiMatrix3::ZERO = { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F };
inline const NiMatrix3 NiMatrix3::IDENTITY = { NiPoint4::IDENTITY0, NiPoint4::IDENTITY0, NiPoint4::IDENTITY0 };
constexpr NiMatrix3::NiMatrix3(const NiPoint4& a_point0, const NiPoint4& a_point1, const NiPoint4& a_point2) noexcept
{
entry[0] = a_point0;
entry[1] = a_point1;
entry[2] = a_point2;
}
constexpr NiMatrix3::NiMatrix3(
float a_x0, float a_y0, float a_z0, float a_w0,
float a_x1, float a_y1, float a_z1, float a_w1,
float a_x2, float a_y2, float a_z2, float a_w2) noexcept
{
entry[0] = { a_x0, a_y0, a_z0, a_w0 };
entry[1] = { a_x1, a_y1, a_z1, a_w1 };
entry[2] = { a_x2, a_y2, a_z2, a_w2 };
}
constexpr NiPoint4& NiMatrix3::operator[](std::size_t a_pos) noexcept
{
assert(a_pos < 3);
return entry[a_pos];
}
constexpr const NiPoint4& NiMatrix3::operator[](std::size_t a_pos) const noexcept
{
assert(a_pos < 3);
return entry[a_pos];
}
constexpr bool NiMatrix3::operator==(const NiMatrix3& a_rhs) const noexcept
{
return (entry[0] == a_rhs[0]) && (entry[1] == a_rhs[1]) && (entry[2] == a_rhs[2]);
}
constexpr bool NiMatrix3::operator!=(const NiMatrix3& a_rhs) const noexcept
{
return !operator==(a_rhs);
}
constexpr NiMatrix3 NiMatrix3::operator*(const NiMatrix3& a_rhs) const noexcept
{
NiMatrix3 result;
result[0][0] = entry[0][0] * a_rhs[0][0] + entry[0][1] * a_rhs[1][0] + entry[0][2] * a_rhs[2][0];
result[1][0] = entry[1][0] * a_rhs[0][0] + entry[1][1] * a_rhs[1][0] + entry[1][2] * a_rhs[2][0];
result[2][0] = entry[2][0] * a_rhs[0][0] + entry[2][1] * a_rhs[1][0] + entry[2][2] * a_rhs[2][0];
result[0][1] = entry[0][0] * a_rhs[0][1] + entry[0][1] * a_rhs[1][1] + entry[0][2] * a_rhs[2][1];
result[1][1] = entry[1][0] * a_rhs[0][1] + entry[1][1] * a_rhs[1][1] + entry[1][2] * a_rhs[2][1];
result[2][1] = entry[2][0] * a_rhs[0][1] + entry[2][1] * a_rhs[1][1] + entry[2][2] * a_rhs[2][1];
result[0][2] = entry[0][0] * a_rhs[0][2] + entry[0][1] * a_rhs[1][2] + entry[0][2] * a_rhs[2][2];
result[1][2] = entry[1][0] * a_rhs[0][2] + entry[1][1] * a_rhs[1][2] + entry[1][2] * a_rhs[2][2];
result[2][2] = entry[2][0] * a_rhs[0][2] + entry[2][1] * a_rhs[1][2] + entry[2][2] * a_rhs[2][2];
return result;
}
constexpr NiMatrix3 NiMatrix3::operator*(float a_scalar) const noexcept
{
NiMatrix3 result;
result[0][0] = entry[0][0] * a_scalar;
result[0][1] = entry[0][1] * a_scalar;
result[0][2] = entry[0][2] * a_scalar;
result[1][0] = entry[1][0] * a_scalar;
result[1][1] = entry[1][1] * a_scalar;
result[1][2] = entry[1][2] * a_scalar;
result[2][0] = entry[2][0] * a_scalar;
result[2][1] = entry[2][1] * a_scalar;
result[2][2] = entry[2][2] * a_scalar;
return result;
}
constexpr NiPoint3 NiMatrix3::operator*(const NiPoint3& a_rhs) const noexcept
{
return NiPoint3(
entry[0][0] * a_rhs.x + entry[0][1] * a_rhs.y + entry[0][2] * a_rhs.z,
entry[1][0] * a_rhs.x + entry[1][1] * a_rhs.y + entry[1][2] * a_rhs.z,
entry[2][0] * a_rhs.x + entry[2][1] * a_rhs.y + entry[2][2] * a_rhs.z);
}
constexpr void NiMatrix3::MakeIdentity() noexcept
{
entry[0] = NiPoint4::IDENTITY0;
entry[1] = NiPoint4::IDENTITY1;
entry[2] = NiPoint4::IDENTITY2;
}
constexpr NiMatrix3 NiMatrix3::Transpose() const noexcept
{
NiMatrix3 result;
result[0][0] = entry[0][0];
result[0][1] = entry[1][0];
result[0][2] = entry[2][0];
result[0][3] = entry[0][3];
result[1][0] = entry[0][1];
result[1][1] = entry[1][1];
result[1][2] = entry[2][1];
result[1][3] = entry[1][3];
result[2][0] = entry[0][2];
result[2][1] = entry[1][2];
result[2][2] = entry[2][2];
result[2][3] = entry[2][3];
return result;
}
}
template <>
struct std::formatter<RE::NiMatrix3>
{
template <class ParseContext>
constexpr auto parse(ParseContext& a_ctx)
{
return a_ctx.begin();
}
template <class FormatContext>
constexpr auto format(const RE::NiMatrix3& a_matrix, FormatContext& a_ctx) const
{
return format_to(a_ctx.out(), "[{}, {}, {}]", a_matrix[0], a_matrix[1], a_matrix[2]);
}
};
@@ -0,0 +1,34 @@
#pragma once
namespace RE
{
inline void NiFree(void* a_ptr)
{
using func_t = decltype(&NiFree);
static REL::Relocation<func_t> func{ ID::NiFree };
return func(a_ptr);
}
inline void* NiMalloc(std::size_t a_num)
{
using func_t = decltype(&NiMalloc);
static REL::Relocation<func_t> func{ ID::NiMalloc };
return func(a_num);
}
template <class T>
class NiTMallocInterface
{
public:
[[nodiscard]] static T* allocate(std::size_t a_num) { return NiMalloc(sizeof(T) * a_num); }
static void deallocate(T* a_ptr) { NiFree(a_ptr); }
};
template <class T>
class NiTNewInterface
{
public:
[[nodiscard]] static T* allocate(std::size_t a_num) { return new T[a_num]; }
static void deallocate(T* a_ptr) { delete[] a_ptr; }
};
}
@@ -0,0 +1,30 @@
#pragma once
#include "RE/N/NiBinaryStream.h"
namespace RE
{
class __declspec(novtable) NiMemStream :
public NiBinaryStream // 00
{
public:
static constexpr auto RTTI{ RTTI::NiMemStream };
static constexpr auto VTABLE{ VTABLE::NiMemStream };
enum class OpenMode
{
kReadOnly = 0x0,
kWriteOnly = 0x1,
kAppendOnly = 0x2,
kReadWrite = 0x3
};
// members
void* buffer; // 10
std::size_t pos; // 18
std::size_t bufferAllocSize; // 20
std::size_t currentFilePos; // 28
bool good; // 30
};
static_assert(sizeof(NiMemStream) == 0x38);
}
@@ -0,0 +1,14 @@
#pragma once
namespace RE
{
class NiNPShortPoint3
{
public:
// members
std::int16_t x; // 0
std::int16_t y; // 2
std::int16_t z; // 4
};
static_assert(sizeof(NiNPShortPoint3) == 0x6);
}
@@ -0,0 +1,50 @@
#pragma once
#include "RE/B/BSTAtomicValue.h"
#include "RE/N/NiAVObject.h"
#include "RE/N/NiPointer.h"
#include "RE/N/NiTArray.h"
namespace RE
{
class __declspec(novtable) NiNode :
public NiAVObject // 000
{
public:
static constexpr auto RTTI{ RTTI::NiNode };
static constexpr auto VTABLE{ VTABLE::NiNode };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiNode };
// NOLINTNEXTLINE(modernize-use-equals-default)
NiNode() :
NiNode(0)
{}
explicit NiNode(std::uint32_t a_numChildren) :
children(a_numChildren)
{
REX::EMPLACE_VTABLE(this);
static REL::Relocation<std::uintptr_t> childrenVTable{ ID::NiNode::ChildrenVTable };
reinterpret_cast<std::uintptr_t&>(children) = childrenVTable.address();
}
// add
virtual void AttachChild(NiAVObject* a_child, bool a_firstAvail); // 3A
virtual void InsertChildAt(std::uint32_t a_idx, NiAVObject* a_child); // 3B
virtual void DetachChild(NiAVObject* a_child); // 3D
virtual void DetachChild(NiAVObject* a_child, NiPointer<NiAVObject>& a_avObject); // 3C
virtual void DetachChildAt(std::uint32_t a_idx); // 3F
virtual void DetachChildAt(std::uint32_t a_idx, NiPointer<NiAVObject>& a_avObject); // 3E
virtual void SetAt(std::uint32_t a_idx, NiAVObject* a_child); // 41
virtual void SetAt(std::uint32_t a_idx, NiAVObject* a_child, NiPointer<NiAVObject>& a_avObject); // 40
virtual void UpdateUpwardPass(NiUpdateData& a_data); // 42
F4_HEAP_REDEFINE_ALIGNED_NEW(NiNode);
// members
NiTObjectArray<NiPointer<NiAVObject>> children; // 120
BSTAtomicValue<std::uint32_t> dirtyState; // 138
float meshLODFadeAmount{ 0.0F }; // 13C
};
static_assert(sizeof(NiNode) == 0x140);
}
@@ -0,0 +1,89 @@
#pragma once
#include "RE/N/NiRefObject.h"
namespace RE
{
class bhkBlendCollisionObject;
class bhkLimitedHingeConstraint;
class bhkNiCollisionObject;
class bhkNPCollisionObject;
class bhkRigidBody;
class BSDynamicTriShape;
class BSFadeNode;
class BSGeometry;
class BSLines;
class BSMultiBoundNode;
class BSSegmentedTriShape;
class BSSubIndexTriShape;
class BSTriShape;
class NiCloningProcess;
class NiControllerManager;
class NiGeometry;
class NiLight;
class NiNode;
class NiObjectGroup;
class NiParticles;
class NiParticleSystem;
class NiRTTI;
class NiStream;
class NiSwitchNode;
class NiTriBasedGeom;
class NiTriShape;
class NiTriStrips;
class __declspec(novtable) NiObject :
public NiRefObject // 00
{
public:
static constexpr auto RTTI{ RTTI::NiObject };
static constexpr auto VTABLE{ VTABLE::NiObject };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiObject };
NiObject() { REX::EMPLACE_VTABLE(this); }
virtual ~NiObject() = default; // NOLINT(modernize-use-override) 00
// add
virtual const NiRTTI* GetRTTI() const { return nullptr; } // 02
virtual NiNode* IsNode() { return nullptr; } // 04
virtual const NiNode* IsNode() const { return nullptr; } // 03
virtual NiSwitchNode* IsSwitchNode() { return nullptr; } // 05
virtual BSFadeNode* IsFadeNode() { return nullptr; } // 06
virtual BSMultiBoundNode* IsMultiBoundNode() { return nullptr; } // 07
virtual BSGeometry* IsGeometry() { return nullptr; } // 08
virtual NiTriStrips* IsTriStrips() { return nullptr; } // 09
virtual BSTriShape* IsTriShape() { return nullptr; } // 0A
virtual BSDynamicTriShape* IsDynamicTriShape() { return nullptr; } // 0B
virtual BSSegmentedTriShape* IsSegmentedTriShape() { return nullptr; } // 0C
virtual BSSubIndexTriShape* IsSubIndexTriShape() { return nullptr; } // 0D
virtual NiGeometry* IsNiGeometry() { return nullptr; } // 0E
virtual NiTriBasedGeom* IsNiTriBasedGeom() { return nullptr; } // 0F
virtual NiTriShape* IsNiTriShape() { return nullptr; } // 10
virtual NiParticles* IsParticlesGeom() { return nullptr; } // 11
virtual NiParticleSystem* IsParticleSystem() { return nullptr; } // 12
virtual BSLines* IsLinesGeom() { return nullptr; } // 13
virtual NiLight* IsLight() { return nullptr; } // 14
virtual bhkNiCollisionObject* IsBhkNiCollisionObject() { return nullptr; } // 15
virtual bhkBlendCollisionObject* IsBhkBlendCollisionObject() { return nullptr; } // 16
virtual bhkRigidBody* IsBhkRigidBody() { return nullptr; } // 17
virtual bhkLimitedHingeConstraint* IsBhkLimitedHingeConstraint() { return nullptr; } // 18
virtual bhkNPCollisionObject* IsbhkNPCollisionObject() { return nullptr; } // 19
virtual NiObject* CreateClone([[maybe_unused]] NiCloningProcess& a_cloneData) { return nullptr; } // 1A
virtual void LoadBinary([[maybe_unused]] NiStream& a_stream) { return; } // 1B
virtual void LinkObject([[maybe_unused]] NiStream& a_stream) { return; } // 1C
virtual bool RegisterStreamables([[maybe_unused]] NiStream& a_stream) { return false; } // 1D
virtual void SaveBinary([[maybe_unused]] NiStream& a_stream) { return; } // 1E
virtual bool IsEqual([[maybe_unused]] NiObject* a_object) { return false; } // 1F
virtual void ProcessClone([[maybe_unused]] NiCloningProcess& a_cloning) {} // 20
virtual void PostLinkObject([[maybe_unused]] NiStream& a_stream) { return; } // 21
virtual bool StreamCanSkip() { return false; } // 22
virtual const NiRTTI* GetStreamableRTTI() { return GetRTTI(); } // 23
virtual std::uint32_t GetBlockAllocationSize() const { return 0; } // 24
virtual NiObjectGroup* GetGroup() const { return nullptr; } // 25
virtual void SetGroup([[maybe_unused]] NiObjectGroup*) { return; } // 26
virtual NiControllerManager* IsNiControllerManager() { return nullptr; } // 27
F4_HEAP_REDEFINE_NEW(NiObject);
};
static_assert(sizeof(NiObject) == 0x10);
}
@@ -0,0 +1,54 @@
#pragma once
#include "RE/B/BSFixedString.h"
#include "RE/N/NiExtraDataContainer.h"
#include "RE/N/NiObject.h"
#include "RE/N/NiPointer.h"
#include "RE/N/NiTimeController.h"
namespace RE
{
class NiExtraData;
class __declspec(novtable) NiObjectNET :
public NiObject // 00
{
public:
static constexpr auto RTTI{ RTTI::NiObjectNET };
static constexpr auto VTABLE{ VTABLE::NiObjectNET };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiObjectNET };
enum class CopyType
{
kNone = 0x0,
kExact = 0x1,
kUnique = 0x2
};
NiObjectNET();
virtual ~NiObjectNET(); // NOLINT(modernize-use-override) 00
F4_HEAP_REDEFINE_NEW(NiObjectNET);
bool AddExtraData(const BSFixedString& a_key, NiExtraData* a_extra);
bool AddExtraData(NiExtraData* a_extra);
NiExtraData* GetExtraData(const BSFixedString& a_key) const;
std::uint16_t GetExtraDataSize() const;
const BSFixedString& GetName() const { return name; }
bool HasExtraData(const BSFixedString& a_key) const;
bool InsertExtraData(NiExtraData* a_extra);
bool RemoveExtraData(const BSFixedString& a_key);
template <class T>
T* GetExtraData(const BSFixedString& a_key) const
{
return static_cast<T*>(GetExtraData(a_key));
}
// members
BSFixedString name{ "" }; // 10
NiPointer<NiTimeController> controllers; // 18
NiExtraDataContainer* extra{ nullptr }; // 20
};
static_assert(sizeof(NiObjectNET) == 0x28);
}
@@ -0,0 +1,21 @@
#pragma once
#include "RE/N/NiPoint3.h"
namespace RE
{
class NiParticleInfo
{
public:
// members
NiPoint3 velocity; // 00
float age; // 0C
float lifeSpan; // 10
float lastUpdate; // 14
std::uint16_t generation; // 18
std::uint16_t code; // 1A
std::int16_t subTexFrame; // 1C
std::uint16_t subTexFrameCount; // 1E
};
static_assert(sizeof(NiParticleInfo) == 0x20);
}
@@ -0,0 +1,13 @@
#pragma once
namespace RE
{
class NiPlane
{
public:
// members
NiPoint3 normal; // 00
float constant; // 0C
};
static_assert(sizeof(NiPlane) == 0x10);
}
@@ -0,0 +1,194 @@
#pragma once
namespace RE
{
class NiPoint2
{
public:
static const NiPoint2 ZERO;
static const NiPoint2 UNIT;
static const NiPoint2 UNIT_X;
static const NiPoint2 UNIT_Y;
constexpr NiPoint2() noexcept = default;
constexpr NiPoint2(float a_x, float a_y) noexcept;
constexpr float& operator[](std::size_t a_pos) noexcept;
constexpr const float& operator[](std::size_t a_pos) const noexcept;
constexpr bool operator==(const NiPoint2& a_rhs) const noexcept;
constexpr bool operator!=(const NiPoint2& a_rhs) const noexcept;
constexpr bool operator<(const NiPoint2& a_rhs) const noexcept;
constexpr bool operator>(const NiPoint2& a_rhs) const noexcept;
constexpr NiPoint2 operator+(const NiPoint2& a_rhs) const noexcept;
constexpr NiPoint2 operator-(const NiPoint2& a_rhs) const noexcept;
constexpr NiPoint2 operator*(const NiPoint2& a_rhs) const noexcept;
constexpr NiPoint2 operator/(const NiPoint2& a_rhs) const noexcept;
constexpr NiPoint2 operator*(float a_scalar) const noexcept;
constexpr NiPoint2 operator/(float a_scalar) const noexcept;
constexpr NiPoint2 operator-() const noexcept;
constexpr NiPoint2& operator+=(const NiPoint2& a_rhs) noexcept;
constexpr NiPoint2& operator-=(const NiPoint2& a_rhs) noexcept;
constexpr NiPoint2& operator*=(const NiPoint2& a_rhs) noexcept;
constexpr NiPoint2& operator/=(const NiPoint2& a_rhs) noexcept;
constexpr NiPoint2& operator+=(float a_scalar) noexcept;
constexpr NiPoint2& operator-=(float a_scalar) noexcept;
constexpr NiPoint2& operator*=(float a_scalar) noexcept;
constexpr NiPoint2& operator/=(float a_scalar) noexcept;
// members
float x{ 0.0F }; // 0x00
float y{ 0.0F }; // 0x04
};
static_assert(sizeof(NiPoint2) == 0x8);
}
namespace RE
{
constexpr NiPoint2::NiPoint2(float a_x, float a_y) noexcept :
x(a_x), y(a_y)
{}
constexpr float& NiPoint2::operator[](std::size_t a_pos) noexcept
{
assert(a_pos < 2);
return std::addressof(x)[a_pos];
}
constexpr const float& NiPoint2::operator[](std::size_t a_pos) const noexcept
{
assert(a_pos < 2);
return std::addressof(x)[a_pos];
}
constexpr bool NiPoint2::operator==(const NiPoint2& a_rhs) const noexcept
{
return (x == a_rhs.x) && (y == a_rhs.y);
}
constexpr bool NiPoint2::operator!=(const NiPoint2& a_rhs) const noexcept
{
return !operator==(a_rhs);
}
constexpr bool NiPoint2::operator<(const NiPoint2& a_rhs) const noexcept
{
return std::tie(x, y) < std::tie(a_rhs.x, a_rhs.y);
}
constexpr bool NiPoint2::operator>(const NiPoint2& a_rhs) const noexcept
{
return std::tie(x, y) > std::tie(a_rhs.x, a_rhs.y);
}
constexpr NiPoint2 NiPoint2::operator+(const NiPoint2& a_rhs) const noexcept
{
return NiPoint2(x + a_rhs.x, y + a_rhs.y);
}
constexpr NiPoint2 NiPoint2::operator-(const NiPoint2& a_rhs) const noexcept
{
return NiPoint2(x - a_rhs.x, y - a_rhs.y);
}
constexpr NiPoint2 NiPoint2::operator*(const NiPoint2& a_rhs) const noexcept
{
return NiPoint2(x * a_rhs.x, y * a_rhs.y);
}
constexpr NiPoint2 NiPoint2::operator/(const NiPoint2& a_rhs) const noexcept
{
return NiPoint2(x / a_rhs.x, y / a_rhs.y);
}
constexpr NiPoint2 NiPoint2::operator*(float a_scalar) const noexcept
{
return NiPoint2(x * a_scalar, y * a_scalar);
}
constexpr NiPoint2 NiPoint2::operator/(float a_scalar) const noexcept
{
return NiPoint2(x / a_scalar, y / a_scalar);
}
constexpr NiPoint2 NiPoint2::operator-() const noexcept
{
return NiPoint2(-x, -y);
}
constexpr NiPoint2& NiPoint2::operator+=(const NiPoint2& a_rhs) noexcept
{
x += a_rhs.x;
y += a_rhs.y;
return *this;
}
constexpr NiPoint2& NiPoint2::operator-=(const NiPoint2& a_rhs) noexcept
{
x -= a_rhs.x;
y -= a_rhs.y;
return *this;
}
constexpr NiPoint2& NiPoint2::operator*=(const NiPoint2& a_rhs) noexcept
{
x *= a_rhs.x;
y *= a_rhs.y;
return *this;
}
constexpr NiPoint2& NiPoint2::operator/=(const NiPoint2& a_rhs) noexcept
{
x /= a_rhs.x;
y /= a_rhs.y;
return *this;
}
constexpr NiPoint2& NiPoint2::operator+=(float a_scalar) noexcept
{
x += a_scalar;
y += a_scalar;
return *this;
}
constexpr NiPoint2& NiPoint2::operator-=(float a_scalar) noexcept
{
x -= a_scalar;
y -= a_scalar;
return *this;
}
constexpr NiPoint2& NiPoint2::operator*=(float a_scalar) noexcept
{
x *= a_scalar;
y *= a_scalar;
return *this;
}
constexpr NiPoint2& NiPoint2::operator/=(float a_scalar) noexcept
{
x /= a_scalar;
y /= a_scalar;
return *this;
}
inline const NiPoint2 NiPoint2::ZERO = { 0.0F, 0.0F };
inline const NiPoint2 NiPoint2::UNIT = { 1.0F, 1.0F };
inline const NiPoint2 NiPoint2::UNIT_X = { 1.0F, 0.0F };
inline const NiPoint2 NiPoint2::UNIT_Y = { 0.0F, 1.0F };
}
template <>
struct std::formatter<RE::NiPoint2>
{
template <class ParseContext>
constexpr auto parse(ParseContext& a_ctx)
{
return a_ctx.begin();
}
template <class FormatContext>
constexpr auto format(const RE::NiPoint2& a_point, FormatContext& a_ctx) const
{
return format_to(a_ctx.out(), "({}, {})", a_point.x, a_point.y);
}
};
@@ -0,0 +1,268 @@
#pragma once
#include "RE/N/NiPoint2.h"
namespace RE
{
class NiPoint3
{
public:
static const NiPoint3 ZERO;
static const NiPoint3 UNIT;
static const NiPoint3 UNIT_X;
static const NiPoint3 UNIT_Y;
static const NiPoint3 UNIT_Z;
constexpr NiPoint3() noexcept = default;
constexpr NiPoint3(const NiPoint2& a_point) noexcept;
constexpr NiPoint3(float a_x, float a_y, float a_z) noexcept;
constexpr float& operator[](std::size_t a_pos) noexcept;
constexpr const float& operator[](std::size_t a_pos) const noexcept;
constexpr bool operator==(const NiPoint3& a_rhs) const noexcept;
constexpr bool operator!=(const NiPoint3& a_rhs) const noexcept;
constexpr bool operator<(const NiPoint3& a_rhs) const noexcept;
constexpr bool operator>(const NiPoint3& a_rhs) const noexcept;
constexpr NiPoint3 operator+(const NiPoint3& a_rhs) const noexcept;
constexpr NiPoint3 operator-(const NiPoint3& a_rhs) const noexcept;
constexpr NiPoint3 operator*(const NiPoint3& a_rhs) const noexcept;
constexpr NiPoint3 operator/(const NiPoint3& a_rhs) const noexcept;
constexpr NiPoint3 operator*(float a_scalar) const noexcept;
constexpr NiPoint3 operator/(float a_scalar) const noexcept;
constexpr NiPoint3 operator-() const noexcept;
constexpr NiPoint3& operator+=(const NiPoint3& a_rhs) noexcept;
constexpr NiPoint3& operator-=(const NiPoint3& a_rhs) noexcept;
constexpr NiPoint3& operator*=(const NiPoint3& a_rhs) noexcept;
constexpr NiPoint3& operator/=(const NiPoint3& a_rhs) noexcept;
constexpr NiPoint3& operator+=(float a_scalar) noexcept;
constexpr NiPoint3& operator-=(float a_scalar) noexcept;
constexpr NiPoint3& operator*=(float a_scalar) noexcept;
constexpr NiPoint3& operator/=(float a_scalar) noexcept;
constexpr NiPoint3 Cross(const NiPoint3& a_point) const noexcept;
constexpr float Dot(const NiPoint3& a_point) const noexcept;
constexpr float GetSquaredDistance(const NiPoint3& a_point) const noexcept;
constexpr float SqrLength() const noexcept;
float GetDistance(const NiPoint3& a_point) const noexcept;
float GetZAngleFromVector() const;
float Length() const noexcept;
NiPoint3 UnitCross(const NiPoint3& a_point) const noexcept;
float Unitize() noexcept;
// members
float x{ 0.0F }; // 0x00
float y{ 0.0F }; // 0x04
float z{ 0.0F }; // 0x08
};
static_assert(sizeof(NiPoint3) == 0xC);
class alignas(0x10) NiPoint3A :
public NiPoint3
{
public:
static const NiPoint3A ZERO;
static const NiPoint3A UNIT;
static const NiPoint3A UNIT_X;
static const NiPoint3A UNIT_Y;
static const NiPoint3A UNIT_Z;
using NiPoint3::NiPoint3;
};
static_assert(sizeof(NiPoint3A) == 0x10);
}
namespace RE
{
constexpr NiPoint3::NiPoint3(const NiPoint2& a_point) noexcept :
x(a_point.x), y(a_point.y)
{}
constexpr NiPoint3::NiPoint3(float a_x, float a_y, float a_z) noexcept :
x(a_x), y(a_y), z(a_z)
{}
constexpr float& NiPoint3::operator[](std::size_t a_pos) noexcept
{
assert(a_pos < 3);
return std::addressof(x)[a_pos];
}
constexpr const float& NiPoint3::operator[](std::size_t a_pos) const noexcept
{
assert(a_pos < 3);
return std::addressof(x)[a_pos];
}
constexpr bool NiPoint3::operator==(const NiPoint3& a_rhs) const noexcept
{
return (x == a_rhs.x) && (y == a_rhs.y) && (z == a_rhs.z);
}
constexpr bool NiPoint3::operator!=(const NiPoint3& a_rhs) const noexcept
{
return !operator==(a_rhs);
}
constexpr bool NiPoint3::operator<(const NiPoint3& a_rhs) const noexcept
{
return std::tie(x, y, z) < std::tie(a_rhs.x, a_rhs.y, a_rhs.z);
}
constexpr bool NiPoint3::operator>(const NiPoint3& a_rhs) const noexcept
{
return std::tie(x, y, z) > std::tie(a_rhs.x, a_rhs.y, a_rhs.z);
}
constexpr NiPoint3 NiPoint3::operator+(const NiPoint3& a_rhs) const noexcept
{
return NiPoint3(x + a_rhs.x, y + a_rhs.y, z + a_rhs.z);
}
constexpr NiPoint3 NiPoint3::operator-(const NiPoint3& a_rhs) const noexcept
{
return NiPoint3(x - a_rhs.x, y - a_rhs.y, z - a_rhs.z);
}
constexpr NiPoint3 NiPoint3::operator*(const NiPoint3& a_rhs) const noexcept
{
return NiPoint3(x * a_rhs.x, y * a_rhs.y, z * a_rhs.z);
}
constexpr NiPoint3 NiPoint3::operator/(const NiPoint3& a_rhs) const noexcept
{
return NiPoint3(x / a_rhs.x, y / a_rhs.y, z / a_rhs.z);
}
constexpr NiPoint3 NiPoint3::operator*(float a_scalar) const noexcept
{
return NiPoint3(x * a_scalar, y * a_scalar, z * a_scalar);
}
constexpr NiPoint3 NiPoint3::operator/(float a_scalar) const noexcept
{
return NiPoint3(x / a_scalar, y / a_scalar, z / a_scalar);
}
constexpr NiPoint3 NiPoint3::operator-() const noexcept
{
return NiPoint3(-x, -y, -z);
}
constexpr NiPoint3& NiPoint3::operator+=(const NiPoint3& a_rhs) noexcept
{
x += a_rhs.x;
y += a_rhs.y;
z += a_rhs.z;
return *this;
}
constexpr NiPoint3& NiPoint3::operator-=(const NiPoint3& a_rhs) noexcept
{
x -= a_rhs.x;
y -= a_rhs.y;
z -= a_rhs.z;
return *this;
}
constexpr NiPoint3& NiPoint3::operator*=(const NiPoint3& a_rhs) noexcept
{
x *= a_rhs.x;
y *= a_rhs.y;
z *= a_rhs.z;
return *this;
}
constexpr NiPoint3& NiPoint3::operator/=(const NiPoint3& a_rhs) noexcept
{
x /= a_rhs.x;
y /= a_rhs.y;
z /= a_rhs.z;
return *this;
}
constexpr NiPoint3& NiPoint3::operator+=(float a_scalar) noexcept
{
x += a_scalar;
y += a_scalar;
z += a_scalar;
return *this;
}
constexpr NiPoint3& NiPoint3::operator-=(float a_scalar) noexcept
{
x -= a_scalar;
y -= a_scalar;
z -= a_scalar;
return *this;
}
constexpr NiPoint3& NiPoint3::operator*=(float a_scalar) noexcept
{
x *= a_scalar;
y *= a_scalar;
z *= a_scalar;
return *this;
}
constexpr NiPoint3& NiPoint3::operator/=(float a_scalar) noexcept
{
x /= a_scalar;
y /= a_scalar;
z /= a_scalar;
return *this;
}
constexpr NiPoint3 NiPoint3::Cross(const NiPoint3& a_point) const noexcept
{
return NiPoint3(
y * a_point.z - z * a_point.y,
z * a_point.x - x * a_point.z,
x * a_point.y - y * a_point.x);
}
constexpr float NiPoint3::Dot(const NiPoint3& a_point) const noexcept
{
return x * a_point.x + y * a_point.y + z * a_point.z;
}
constexpr float NiPoint3::GetSquaredDistance(const NiPoint3& a_point) const noexcept
{
const float dx = a_point.x - x;
const float dy = a_point.y - y;
const float dz = a_point.z - z;
return dx * dx + dy * dy + dz * dz;
}
constexpr float NiPoint3::SqrLength() const noexcept
{
return x * x + y * y + z * z;
}
inline const NiPoint3 NiPoint3::ZERO = { 0.0F, 0.0F, 0.0F };
inline const NiPoint3 NiPoint3::UNIT = { 1.0F, 1.0F, 1.0F };
inline const NiPoint3 NiPoint3::UNIT_X = { 1.0F, 0.0F, 0.0F };
inline const NiPoint3 NiPoint3::UNIT_Y = { 0.0F, 1.0F, 0.0F };
inline const NiPoint3 NiPoint3::UNIT_Z = { 0.0F, 0.0F, 1.0F };
inline const NiPoint3A NiPoint3A::ZERO = { 0.0F, 0.0F, 0.0F };
inline const NiPoint3A NiPoint3A::UNIT = { 1.0F, 1.0F, 1.0F };
inline const NiPoint3A NiPoint3A::UNIT_X = { 1.0F, 0.0F, 0.0F };
inline const NiPoint3A NiPoint3A::UNIT_Y = { 0.0F, 1.0F, 0.0F };
inline const NiPoint3A NiPoint3A::UNIT_Z = { 0.0F, 0.0F, 1.0F };
}
template <>
struct std::formatter<RE::NiPoint3>
{
template <class ParseContext>
constexpr auto parse(ParseContext& a_ctx)
{
return a_ctx.begin();
}
template <class FormatContext>
constexpr auto format(const RE::NiPoint3& a_point, FormatContext& a_ctx) const
{
return format_to(a_ctx.out(), "({}, {}, {})", a_point.x, a_point.y, a_point.z);
}
};
@@ -0,0 +1,226 @@
#pragma once
#include "RE/N/NiPoint3.h"
namespace RE
{
class NiPoint4
{
public:
static const NiPoint4 ZERO;
static const NiPoint4 IDENTITY0;
static const NiPoint4 IDENTITY1;
static const NiPoint4 IDENTITY2;
static const NiPoint4 IDENTITY3;
constexpr NiPoint4() noexcept = default;
constexpr NiPoint4(const NiPoint2& a_point) noexcept;
constexpr NiPoint4(const NiPoint3& a_point) noexcept;
constexpr NiPoint4(float a_x, float a_y, float a_z, float a_w) noexcept;
constexpr float& operator[](std::size_t a_pos) noexcept;
constexpr const float& operator[](std::size_t a_pos) const noexcept;
constexpr bool operator==(const NiPoint4& a_rhs) const noexcept;
constexpr bool operator!=(const NiPoint4& a_rhs) const noexcept;
constexpr bool operator<(const NiPoint4& a_rhs) const noexcept;
constexpr bool operator>(const NiPoint4& a_rhs) const noexcept;
constexpr NiPoint4 operator+(const NiPoint4& a_rhs) const noexcept;
constexpr NiPoint4 operator-(const NiPoint4& a_rhs) const noexcept;
constexpr NiPoint4 operator*(const NiPoint4& a_rhs) const noexcept;
constexpr NiPoint4 operator/(const NiPoint4& a_rhs) const noexcept;
constexpr NiPoint4 operator*(float a_scalar) const noexcept;
constexpr NiPoint4 operator/(float a_scalar) const noexcept;
constexpr NiPoint4 operator-() const noexcept;
constexpr NiPoint4& operator+=(const NiPoint4& a_rhs) noexcept;
constexpr NiPoint4& operator-=(const NiPoint4& a_rhs) noexcept;
constexpr NiPoint4& operator*=(const NiPoint4& a_rhs) noexcept;
constexpr NiPoint4& operator/=(const NiPoint4& a_rhs) noexcept;
constexpr NiPoint4& operator+=(float a_scalar) noexcept;
constexpr NiPoint4& operator-=(float a_scalar) noexcept;
constexpr NiPoint4& operator*=(float a_scalar) noexcept;
constexpr NiPoint4& operator/=(float a_scalar) noexcept;
// members
float x{ 0.0F }; // 0x00
float y{ 0.0F }; // 0x04
float z{ 0.0F }; // 0x08
float w{ 0.0F }; // 0x0C
};
static_assert(sizeof(NiPoint4) == 0x10);
}
namespace RE
{
constexpr NiPoint4::NiPoint4(const NiPoint2& a_point) noexcept :
x(a_point.x), y(a_point.y)
{}
constexpr NiPoint4::NiPoint4(const NiPoint3& a_point) noexcept :
x(a_point.x), y(a_point.y), z(a_point.z)
{}
constexpr NiPoint4::NiPoint4(float a_x, float a_y, float a_z, float a_w) noexcept :
x(a_x), y(a_y), z(a_z), w(a_w)
{}
constexpr float& NiPoint4::operator[](std::size_t a_pos) noexcept
{
assert(a_pos < 4);
return std::addressof(x)[a_pos];
}
constexpr const float& NiPoint4::operator[](std::size_t a_pos) const noexcept
{
assert(a_pos < 4);
return std::addressof(x)[a_pos];
}
constexpr bool NiPoint4::operator==(const NiPoint4& a_rhs) const noexcept
{
return (x == a_rhs.x) && (y == a_rhs.y) && (z == a_rhs.z) && (w == a_rhs.w);
}
constexpr bool NiPoint4::operator!=(const NiPoint4& a_rhs) const noexcept
{
return !operator==(a_rhs);
}
constexpr bool NiPoint4::operator<(const NiPoint4& a_rhs) const noexcept
{
return std::tie(x, y, z, w) < std::tie(a_rhs.x, a_rhs.y, a_rhs.z, a_rhs.w);
}
constexpr bool NiPoint4::operator>(const NiPoint4& a_rhs) const noexcept
{
return std::tie(x, y, z, w) > std::tie(a_rhs.x, a_rhs.y, a_rhs.z, a_rhs.w);
}
constexpr NiPoint4 NiPoint4::operator+(const NiPoint4& a_rhs) const noexcept
{
return NiPoint4(x + a_rhs.x, y + a_rhs.y, z + a_rhs.z, w + a_rhs.w);
}
constexpr NiPoint4 NiPoint4::operator-(const NiPoint4& a_rhs) const noexcept
{
return NiPoint4(x - a_rhs.x, y - a_rhs.y, z - a_rhs.z, w - a_rhs.w);
}
constexpr NiPoint4 NiPoint4::operator*(const NiPoint4& a_rhs) const noexcept
{
return NiPoint4(x * a_rhs.x, y * a_rhs.y, z * a_rhs.z, w * a_rhs.w);
}
constexpr NiPoint4 NiPoint4::operator/(const NiPoint4& a_rhs) const noexcept
{
return NiPoint4(x / a_rhs.x, y / a_rhs.y, z / a_rhs.z, w / a_rhs.w);
}
constexpr NiPoint4 NiPoint4::operator*(float a_scalar) const noexcept
{
return NiPoint4(x * a_scalar, y * a_scalar, z * a_scalar, w * a_scalar);
}
constexpr NiPoint4 NiPoint4::operator/(float a_scalar) const noexcept
{
return operator*(1.0F / a_scalar);
}
constexpr NiPoint4 NiPoint4::operator-() const noexcept
{
return NiPoint4(-x, -y, -z, -w);
}
constexpr NiPoint4& NiPoint4::operator+=(const NiPoint4& a_rhs) noexcept
{
x += a_rhs.x;
y += a_rhs.y;
z += a_rhs.z;
w += a_rhs.w;
return *this;
}
constexpr NiPoint4& NiPoint4::operator-=(const NiPoint4& a_rhs) noexcept
{
x -= a_rhs.x;
y -= a_rhs.y;
z -= a_rhs.z;
w -= a_rhs.w;
return *this;
}
constexpr NiPoint4& NiPoint4::operator*=(const NiPoint4& a_rhs) noexcept
{
x *= a_rhs.x;
y *= a_rhs.y;
z *= a_rhs.z;
w *= a_rhs.w;
return *this;
}
constexpr NiPoint4& NiPoint4::operator/=(const NiPoint4& a_rhs) noexcept
{
x /= a_rhs.x;
y /= a_rhs.y;
z /= a_rhs.z;
w /= a_rhs.w;
return *this;
}
constexpr NiPoint4& NiPoint4::operator+=(float a_scalar) noexcept
{
x += a_scalar;
y += a_scalar;
z += a_scalar;
w += a_scalar;
return *this;
}
constexpr NiPoint4& NiPoint4::operator-=(float a_scalar) noexcept
{
x -= a_scalar;
y -= a_scalar;
z -= a_scalar;
w -= a_scalar;
return *this;
}
constexpr NiPoint4& NiPoint4::operator*=(float a_scalar) noexcept
{
x *= a_scalar;
y *= a_scalar;
z *= a_scalar;
w *= a_scalar;
return *this;
}
constexpr NiPoint4& NiPoint4::operator/=(float a_scalar) noexcept
{
x /= a_scalar;
y /= a_scalar;
z /= a_scalar;
w /= a_scalar;
return *this;
}
inline const NiPoint4 NiPoint4::ZERO = { 0.0F, 0.0F, 0.0F, 0.0F };
inline const NiPoint4 NiPoint4::IDENTITY0 = { 1.0F, 0.0F, 0.0F, 0.0F };
inline const NiPoint4 NiPoint4::IDENTITY1 = { 0.0F, 1.0F, 0.0F, 0.0F };
inline const NiPoint4 NiPoint4::IDENTITY2 = { 0.0F, 0.0F, 1.0F, 0.0F };
inline const NiPoint4 NiPoint4::IDENTITY3 = { 0.0F, 0.0F, 0.0F, 1.0F };
}
template <>
struct std::formatter<RE::NiPoint4>
{
template <class ParseContext>
constexpr auto parse(ParseContext& a_ctx)
{
return a_ctx.begin();
}
template <class FormatContext>
constexpr auto format(const RE::NiPoint4& a_point, FormatContext& a_ctx) const
{
return format_to(a_ctx.out(), "({}, {}, {}, {})", a_point.x, a_point.y, a_point.z, a_point.w);
}
};
@@ -0,0 +1,201 @@
#pragma once
#include "RE/B/BSCRC32.h"
namespace RE
{
template <class T>
class NiPointer
{
public:
using element_type = T;
// 1)
NiPointer() noexcept = default;
// 2)
NiPointer(std::nullptr_t) noexcept {}
// 3)
template <class Y>
NiPointer(Y* a_rhs)
requires(std::convertible_to<Y*, element_type*>)
:
_ptr(static_cast<element_type*>(a_rhs))
{
TryAttach();
}
// 9a)
NiPointer(const NiPointer& a_rhs) :
_ptr(a_rhs._ptr)
{
TryAttach();
}
// 9b)
template <class Y>
NiPointer(const NiPointer<Y>& a_rhs)
requires(std::convertible_to<Y*, element_type*>)
:
_ptr(static_cast<element_type*>(a_rhs._ptr))
{
TryAttach();
}
// 10a)
NiPointer(NiPointer&& a_rhs) noexcept :
_ptr(std::exchange(a_rhs._ptr, nullptr))
{}
// 10b)
template <class Y>
NiPointer(NiPointer<Y>&& a_rhs) noexcept
requires(std::convertible_to<Y*, element_type*>)
:
_ptr(static_cast<element_type*>(std::exchange(a_rhs._ptr, nullptr)))
{}
~NiPointer() noexcept { reset(); }
// 1a)
NiPointer& operator=(const NiPointer& a_rhs)
{
if (this != std::addressof(a_rhs)) {
TryDetach();
_ptr = a_rhs._ptr;
TryAttach();
}
return *this;
}
// 1b)
template <class Y>
NiPointer& operator=(const NiPointer<Y>& a_rhs)
requires(std::convertible_to<Y*, element_type*>)
{
TryDetach();
_ptr = static_cast<element_type*>(a_rhs._ptr);
TryAttach();
return *this;
}
// 2a)
NiPointer& operator=(NiPointer&& a_rhs) noexcept
{
if (this != std::addressof(a_rhs)) {
TryDetach();
_ptr = std::exchange(a_rhs._ptr, nullptr);
}
return *this;
}
// 2b)
template <class Y>
NiPointer& operator=(NiPointer<Y>&& a_rhs) noexcept
requires(std::convertible_to<Y*, element_type*>)
{
TryDetach();
_ptr = std::exchange(a_rhs._ptr, nullptr);
return *this;
}
// 1)
void reset() { TryDetach(); }
// 2)
template <class Y>
void reset(Y* a_ptr)
requires(std::convertible_to<Y*, element_type*>)
{
if (_ptr != a_ptr) {
TryDetach();
_ptr = static_cast<element_type*>(a_ptr);
TryAttach();
}
}
[[nodiscard]] element_type* get() const noexcept { return _ptr; }
[[nodiscard]] element_type& operator*() const noexcept
{
assert(static_cast<bool>(*this));
return *_ptr;
}
[[nodiscard]] element_type* operator->() const noexcept
{
assert(static_cast<bool>(*this));
return _ptr;
}
[[nodiscard]] explicit operator bool() const noexcept { return _ptr != nullptr; }
protected:
template <class>
friend class NiPointer;
void TryAttach()
{
if (_ptr) {
_ptr->IncRefCount();
}
}
void TryDetach()
{
if (_ptr) {
_ptr->DecRefCount();
_ptr = nullptr;
}
}
// members
element_type* _ptr{ nullptr }; // 0
};
//static_assert(sizeof(NiPointer<void*>) == 0x8);
template <class T, class... Args>
[[nodiscard]] NiPointer<T> make_nismart(Args&&... a_args)
{
return NiPointer<T>{ new T(std::forward<Args>(a_args)...) };
}
// 1)
template <class T, class U>
[[nodiscard]] bool operator==(const NiPointer<T>& a_lhs, const NiPointer<U>& a_rhs) noexcept
{
return a_lhs.get() == a_rhs.get();
}
// 7)
template <class T, class U>
[[nodiscard]] std::strong_ordering operator<=>(const NiPointer<T>& a_lhs, const NiPointer<U>& a_rhs) noexcept
{
return std::compare_three_way{}(a_lhs.get(), a_rhs.get());
}
// 8)
template <class T>
[[nodiscard]] bool operator==(const NiPointer<T>& a_lhs, std::nullptr_t) noexcept
{
return !a_lhs;
}
// 20)
template <class T>
[[nodiscard]] std::strong_ordering operator<=>(const NiPointer<T>& a_lhs, std::nullptr_t) noexcept
{
return std::compare_three_way{}(a_lhs.get(), static_cast<typename NiPointer<T>::element_type*>(nullptr));
}
template <class T>
struct BSCRC32<NiPointer<T>>
{
public:
[[nodiscard]] std::uint32_t operator()(const NiPointer<T>& a_key) const noexcept
{
return BSCRC32<T*>()(a_key.get());
}
};
}
@@ -0,0 +1,22 @@
#pragma once
#include "RE/N/NiObjectNET.h"
namespace RE
{
class NiUpdateData;
class __declspec(novtable) NiProperty :
public NiObjectNET // 00
{
public:
static constexpr auto RTTI{ RTTI::NiProperty };
static constexpr auto VTABLE{ VTABLE::NiProperty };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiProperty };
// add
virtual std::int32_t Type() = 0; // 28
virtual void Update(NiUpdateData& a_updateData); // 29
};
static_assert(sizeof(NiProperty) == 0x28);
}
@@ -0,0 +1,14 @@
#pragma once
namespace RE
{
class NiQuaternion
{
public:
float w; // 00
float x; // 04
float y; // 08
float z; // 0C
};
static_assert(sizeof(NiQuaternion) == 0x10);
}
@@ -0,0 +1,133 @@
#pragma once
namespace RE
{
class NiRTTI
{
public:
NiRTTI(const char* a_name, const NiRTTI* a_baseRTTI) :
name(a_name), baseRTTI(a_baseRTTI)
{}
[[nodiscard]] constexpr const char* GetName() const noexcept { return name; }
[[nodiscard]] constexpr const NiRTTI* GetBaseRTTI() const noexcept { return baseRTTI; }
[[nodiscard]] constexpr bool IsKindOf(const NiRTTI* a_rtti) const noexcept
{
for (auto iter = this; iter; iter = iter->GetBaseRTTI()) {
if (iter == a_rtti) {
return true;
}
}
return false;
}
// members
const char* name; // 00
const NiRTTI* baseRTTI; // 08
};
static_assert(sizeof(NiRTTI) == 0x10);
namespace Ni_Impl
{
template <class T>
using remove_cvpr_t =
std::remove_pointer_t<
std::remove_reference_t<
std::remove_cv_t<T>>>;
template <class To, class From>
struct types_are_compat :
std::false_type
{};
template <class To, class From>
struct types_are_compat<To&, From> :
std::is_lvalue_reference<
std::remove_cv_t<From>>
{};
template <class To, class From>
struct types_are_compat<To*, From> :
std::is_pointer<
std::remove_cv_t<From>>
{};
template <class Base, class Derived>
struct is_base_of_no_cvpr :
std::is_base_of<
remove_cvpr_t<Base>,
remove_cvpr_t<Derived>>
{};
template <class T, class Enable = void>
struct _has_rtti :
std::false_type
{};
template <class T>
struct _has_rtti<T, std::void_t<decltype(T::Ni_RTTI)>> :
std::true_type
{};
template <class T>
struct has_rtti :
_has_rtti<remove_cvpr_t<T>>
{};
template <class To, class From>
struct cast_is_valid :
std::conjunction<
types_are_compat<To, From>,
is_base_of_no_cvpr<From, To>,
has_rtti<To>,
has_rtti<From>>
{};
template <class To, class From>
inline constexpr bool cast_is_valid_v = cast_is_valid<To, From>::value;
}
}
// downcast
template <
class To,
class From,
std::enable_if_t<
RE::Ni_Impl::cast_is_valid_v<
To,
const From*>,
int> = 0>
To netimmerse_cast(const From* a_from)
{
if (!a_from) {
return nullptr;
}
static REL::Relocation<const RE::NiRTTI*> to{ RE::Ni_Impl::remove_cvpr_t<To>::Ni_RTTI };
const RE::NiRTTI* toRTTI = to.get();
const RE::NiRTTI* fromRTTI = a_from->GetRTTI();
while (fromRTTI) {
if (fromRTTI == toRTTI) {
return static_cast<To>(const_cast<From*>(a_from));
}
fromRTTI = fromRTTI->GetBaseRTTI();
}
return nullptr;
}
// upcast
template <
class To,
class From,
std::enable_if_t<
RE::Ni_Impl::cast_is_valid_v<
const From*,
To>,
int> = 0>
To netimmerse_cast(const From* a_from)
{
return static_cast<To>(const_cast<From*>(a_from));
}
@@ -0,0 +1,25 @@
#pragma once
namespace RE
{
template <class T>
class NiRect
{
public:
constexpr NiRect() = default;
constexpr NiRect(T a_left, T a_right, T a_top, T a_bottom) :
left(a_left), right(a_right), top(a_top), bottom(a_bottom)
{}
// members
T left; // 00
T right; // ??
T top; // ??
T bottom; // ??
};
extern template class NiRect<float>;
extern template class NiRect<std::int32_t>;
extern template class NiRect<std::uint32_t>;
}
@@ -0,0 +1,53 @@
#pragma once
#include "RE/M/MemoryManager.h"
namespace RE
{
class __declspec(novtable) alignas(0x08) NiRefObject
{
public:
static constexpr auto RTTI{ RTTI::NiRefObject };
static constexpr auto VTABLE{ VTABLE::NiRefObject };
NiRefObject()
{
REX::EMPLACE_VTABLE(this);
static REL::Relocation<std::uint32_t*> objects{ ID::NiRefObject::Objects };
REX::TAtomicRef myObjects{ *objects };
++myObjects;
}
virtual ~NiRefObject() // 00
{
static REL::Relocation<std::uint32_t*> objects{ ID::NiRefObject::Objects };
REX::TAtomicRef myObjects{ *objects };
--myObjects;
}
// add
virtual void DeleteThis() { delete this; } // 01
F4_HEAP_REDEFINE_NEW(NiRefObject);
std::uint32_t DecRefCount()
{
REX::TAtomicRef myRefCount{ refCount };
const auto newRefCount = --myRefCount;
if (newRefCount == 0) {
DeleteThis();
}
return newRefCount;
}
std::uint32_t IncRefCount()
{
REX::TAtomicRef myRefCount{ refCount };
return ++myRefCount;
}
// members
std::uint32_t refCount{ 0 }; // 08
};
static_assert(sizeof(NiRefObject) == 0x10);
}
@@ -0,0 +1,19 @@
#pragma once
#include "RE/N/NiProperty.h"
namespace RE
{
class __declspec(novtable) NiShadeProperty :
public NiProperty // 00
{
public:
static constexpr auto RTTI{ RTTI::NiShadeProperty };
static constexpr auto VTABLE{ VTABLE::NiShadeProperty };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiShadeProperty };
// add
virtual bool SetupGeometry([[maybe_unused]] BSGeometry* a_geometry) { return true; } // 2A
};
static_assert(sizeof(NiShadeProperty) == 0x28);
}
@@ -0,0 +1,83 @@
#pragma once
#include "RE/B/BSFixedString.h"
#include "RE/B/BSStreamHeader.h"
#include "RE/B/BSTArray.h"
#include "RE/N/NiPointer.h"
#include "RE/N/NiTArray.h"
#include "RE/N/NiTLargeArray.h"
#include "RE/N/NiTPointerMap.h"
namespace RE
{
class NiBinaryStream;
class NiObject;
class NiObjectGroup;
class NiSearchPath;
class __declspec(novtable) NiStream
{
public:
static constexpr auto RTTI{ RTTI::NiStream };
static constexpr auto VTABLE{ VTABLE::NiStream };
virtual ~NiStream(); // 00
// add
bool Load(NiBinaryStream* a_istr); // 01
bool Load(char* a_buffer, std::uint64_t a_bufferSize); // 02
bool Load(const char* a_fileName); // 03
bool Save(NiBinaryStream* a_ostr); // 04
bool Save(char*& a_buffer, std::uint64_t& a_bufferSize); // 05
bool Save(const char* a_fileName); // 06
bool RegisterFixedString(const BSFixedString& a_string); // 07
bool RegisterSaveObject(NiObject* a_object); // 08
void ChangeObject(NiObject* a_newObject); // 09
std::uint32_t GetLinkIDFromObject(const NiObject* a_object) const; // 0A
void SaveLinkID(const NiObject* a_object); // 0B
bool LoadHeader(); // 0C
void SaveHeader(); // 0D
bool LoadStream(); // 0E
bool SaveStream(); // 0F
void RegisterObjects(); // 10
void LoadTopLevelObjects(); // 11
void SaveTopLevelObjects(); // 12
bool LoadObject(); // 13
std::uint64_t PreSaveObjectSizeTable(); // 14
bool SaveObjectSizeTable(std::uint64_t a_startOffset); // 15
bool LoadObjectSizeTable(); // 16
[[nodiscard]] std::string_view GetFileName() const { return fileName; }
// members
BSStreamHeader bsStreamHeader; // 008
BSTSmallArray<NiObjectGroup*, 4> groups; // 1D0
std::uint32_t nifFileVersion; // 200
std::uint32_t nifFileUserDefinedVersion; // 204
char fileName[260]; // 208
bool saveLittleEndian; // 30C
bool sourceIsLittleEndian; // 30D
NiSearchPath* searchPath; // 310
NiTLargeObjectArray<NiPointer<NiObject>> objects; // 318
NiTLargePrimitiveArray<std::uint32_t> objectSizes; // 338
NiTLargeObjectArray<NiPointer<NiObject>> topObjects; // 358
NiTLargeObjectArray<BSFixedString> fixedStrings; // 378
NiBinaryStream* istr; // 398
NiBinaryStream* ostr; // 3A0
std::uint32_t linkIndex; // 3A8
std::uint32_t linkBlockIndex; // 3AC
NiTPointerMap<const NiObject*, std::uint32_t> registerMap; // 3B0
std::uint16_t niAVObjectFlags; // 3D0
std::uint16_t niTimeControllerFlags; // 3D2
std::uint16_t niPropertyFlags; // 3D4
std::uint16_t streamFlags; // 3D6
std::uint32_t load; // 3D8
std::uint32_t link; // 3DC
std::uint32_t postLink; // 3E0
char lastLoadedRTTI[260]; // 3E4
std::uint32_t lastError; // 4E8
char lastErrorMessage[260]; // 4EC
char filePath[260]; // 5F0
};
static_assert(sizeof(NiStream) == 0x6F8);
}
@@ -0,0 +1,49 @@
#pragma once
#include "RE/N/NiExtraData.h"
namespace RE
{
class __declspec(novtable) NiStringExtraData :
public NiExtraData
{
public:
static constexpr auto RTTI{ RTTI::NiStringExtraData };
static constexpr auto VTABLE{ VTABLE::NiStringExtraData };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiStringExtraData };
NiStringExtraData() :
NiExtraData()
{
REX::EMPLACE_VTABLE(this);
}
NiStringExtraData(const BSFixedString& a_value) :
NiExtraData(), value(a_value)
{
REX::EMPLACE_VTABLE(this);
}
NiStringExtraData(const BSFixedString& a_name, const BSFixedString& a_value) :
NiExtraData(a_name), value(a_value)
{
REX::EMPLACE_VTABLE(this);
}
public:
const BSFixedString& GetValue() const
{
return value;
}
void SetValue(const BSFixedString& a_value)
{
value = a_value;
}
protected:
// members
BSFixedString value; // 0x18
};
static_assert(sizeof(NiStringExtraData) == 0x20);
}
@@ -0,0 +1,200 @@
#pragma once
#include "RE/N/NiMemManager.h"
namespace RE
{
template <class T, class Allocator>
class NiTArray
{
public:
using value_type = T;
using allocator_type = Allocator;
using size_type = std::uint16_t;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
template <class U>
class iterator_base
{
public:
using difference_type = std::ptrdiff_t;
using value_type = std::remove_const_t<U>;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::bidirectional_iterator_tag;
~iterator_base() noexcept = default;
iterator_base() noexcept = default;
iterator_base(const volatile iterator_base&) = delete;
iterator_base& operator=(const volatile iterator_base&) = delete;
template <class V>
iterator_base(const iterator_base<V>& a_rhs) //
requires(std::convertible_to<typename iterator_base<V>::reference, reference>)
:
_pos(a_rhs._pos),
_head(a_rhs._head),
_tail(a_rhs._tail)
{}
template <class V>
iterator_base& operator=(const iterator_base<V>& a_rhs) //
requires(std::convertible_to<typename iterator_base<V>::reference, reference>)
{
_pos = a_rhs._pos;
_head = a_rhs._head;
_tail = a_rhs._tail;
return *this;
}
[[nodiscard]] reference operator*() const noexcept
{
assert(validate());
return *_pos;
}
[[nodiscard]] pointer operator->() const noexcept
{
return std::pointer_traits<pointer>::pointer_to(operator*());
}
template <class V>
[[nodiscard]] bool operator==(const iterator_base<V>& a_rhs) const noexcept
{
assert(_head == a_rhs._head);
assert(_tail == a_rhs._tail);
return _pos == a_rhs._pos;
}
template <class V>
[[nodiscard]] bool operator!=(const iterator_base<V>& a_rhs) const noexcept
{
return !operator==(a_rhs);
}
iterator_base& operator++() noexcept
{
assert(validate());
do {
++_pos;
} while (_pos < _tail && !slot_filled());
return *this;
}
iterator_base operator++(int) noexcept
{
iterator_base tmp{ *this };
operator++();
return tmp;
}
iterator_base& operator--() noexcept
{
assert(validate());
do {
--_pos;
} while (_head <= _pos && !slot_filled());
return *this;
}
iterator_base operator--(int) noexcept
{
iterator_base tmp{ *this };
operator--();
return tmp;
}
private:
friend iterator_base;
friend NiTArray;
explicit iterator_base(pointer a_pos, pointer a_head, pointer a_tail) noexcept :
_pos(a_pos),
_head(a_head),
_tail(a_tail)
{}
[[nodiscard]] bool validate() const noexcept
{
return _pos != nullptr &&
_head != nullptr &&
_tail != nullptr &&
_head <= _pos && _pos < _tail;
}
[[nodiscard]] bool slot_filled() const noexcept
{
assert(validate());
return static_cast<bool>(*_pos);
}
pointer _pos{ nullptr };
pointer _head{ nullptr };
pointer _tail{ nullptr };
};
public:
using iterator = iterator_base<value_type>;
using const_iterator = iterator_base<const value_type>;
explicit NiTArray(std::uint32_t a_maxSize = 0, std::uint32_t a_growBy = 1) :
_capacity(static_cast<std::uint16_t>(a_maxSize)),
_growthSize(static_cast<std::uint16_t>(a_growBy))
{
if (capacity() > 0) {
_data = allocator_type::allocate(capacity());
}
}
virtual ~NiTArray() { allocator_type::deallocate(_data); } // 00
[[nodiscard]] reference operator[](size_type a_pos) noexcept
{
assert(a_pos < capacity());
return _data[a_pos];
}
[[nodiscard]] const_reference operator[](size_type a_pos) const noexcept
{
assert(a_pos < capacity());
return _data[a_pos];
}
[[nodiscard]] const_pointer data() const noexcept { return _data; }
[[nodiscard]] iterator begin() noexcept { return make_iterator<iterator>(0); }
[[nodiscard]] const_iterator begin() const noexcept { return make_iterator<const_iterator>(0); }
[[nodiscard]] const_iterator cbegin() const noexcept { return make_iterator<const_iterator>(0); }
[[nodiscard]] iterator end() noexcept { return make_iterator<iterator>(_capacity); }
[[nodiscard]] const_iterator end() const noexcept { return make_iterator<const_iterator>(_capacity); }
[[nodiscard]] const_iterator cend() const noexcept { return make_iterator<const_iterator>(_capacity); }
[[nodiscard]] bool empty() const noexcept { return size() == 0; }
[[nodiscard]] size_type size() const noexcept { return _size; }
[[nodiscard]] size_type capacity() const noexcept { return _capacity; }
private:
template <class U>
[[nodiscard]] U make_iterator(size_type a_pos) const noexcept
{
return U(_data + a_pos, _data, _data + _capacity);
}
// members
pointer _data{ nullptr }; // 08
size_type _capacity{ 0 }; // 10
size_type _freeIdx{ 0 }; // 12
size_type _size{ 0 }; // 14
size_type _growthSize{ 0 }; // 16
};
template <class T>
using NiTObjectArray = NiTArray<T, NiTNewInterface<T>>;
template <class T>
using NiTPrimitiveArray = NiTArray<T, NiTMallocInterface<T>>;
}
@@ -0,0 +1,13 @@
#pragma once
namespace RE
{
template <class T>
class DFALL
{
public:
};
template <class T>
using NiTDefaultAllocator = DFALL<T>;
}
@@ -0,0 +1,18 @@
#pragma once
namespace RE
{
template <class Integral, class>
class NiTFlags
{
public:
using integral_type = Integral;
static_assert(std::is_integral_v<integral_type>);
constexpr NiTFlags() noexcept {} // NOLINT(moderinize-use-equals-default)
// members
integral_type flags{ 0 }; // 00
};
}
@@ -0,0 +1,31 @@
#pragma once
#include "RE/N/NiMemManager.h"
namespace RE
{
template <class T, class Allocator>
class NiTLargeArray
{
public:
using value_type = T;
using allocator_type = Allocator;
using size_type = std::uint32_t;
using pointer = value_type*;
virtual ~NiTLargeArray();
private:
pointer _data; // 08
size_type _capacity; // 10
size_type _freeIdx; // 14
size_type _size; // 18
size_type _growBy; // 1C
};
template <class T>
using NiTLargeObjectArray = NiTLargeArray<T, NiTNewInterface<T>>;
template <class T>
using NiTLargePrimitiveArray = NiTLargeArray<T, NiTMallocInterface<T>>;
}
@@ -0,0 +1,47 @@
#pragma once
#include "RE/N/NiTDefaultAllocator.h"
namespace RE
{
template <class T>
class NiTListItem
{
public:
NiTListItem* next; // 00
NiTListItem* prev; // 08
T element; // 10
};
template <class Allocator, class T>
class NiTListBase
{
public:
class AntiBloatAllocator :
public Allocator
{
public:
// members
std::uint32_t size; // ??
};
// members
NiTListItem<T>* head; // 00
NiTListItem<T>* tail; // 08
AntiBloatAllocator allocator; // 10
};
template <class Allocator, class T>
class NiTPointerListBase :
public NiTListBase<Allocator, T> // 00
{
public:
};
template <class T>
class NiTList :
public NiTPointerListBase<NiTDefaultAllocator<T>, T> // 00
{
public:
};
}
@@ -0,0 +1,83 @@
#pragma once
#include "RE/M/MemoryManager.h"
#include "RE/N/NiTDefaultAllocator.h"
namespace RE
{
template <class Key, class T>
class NiTMapItem
{
public:
using key_type = Key;
using mapped_type = T;
F4_HEAP_REDEFINE_NEW(NiTMapItem);
// members
NiTMapItem* next; // 00
key_type first; // 08
mapped_type second; // ??
};
template <class Allocator, class Key, class T>
class NiTMapBase
{
public:
using key_type = Key;
using mapped_type = T;
using value_type = NiTMapItem<Key, T>;
using size_type = std::uint32_t;
class AntiBloatAllocator :
public Allocator // 00
{
public:
// members
size_type size{ 0 }; // ??
};
using allocator_type = AntiBloatAllocator;
virtual ~NiTMapBase(); // 00
protected:
virtual std::uint32_t hash_function(key_type a_key) const { return static_cast<std::uint32_t>((std::size_t)a_key % _capacity); } // 01
virtual bool key_eq(key_type a_lhs, key_type a_rhs) const { return a_lhs == a_rhs; } // 02
virtual void assign_value(value_type* a_value, key_type a_key, mapped_type a_mapped) // 03
{
a_value->first = a_key;
a_value->second = a_mapped;
}
virtual void clear_value([[maybe_unused]] value_type* a_value) { return; } // 04
virtual value_type* malloc_value() = 0; // 05
virtual void free_value(value_type* a_value) = 0; // 06
private:
// members
std::uint32_t _capacity; // 08
value_type** _data; // 10
allocator_type _allocator; // 18
};
template <class Key, class T>
class NiTMap :
public NiTMapBase<DFALL<NiTMapItem<Key, T>>, Key, T> // 00
{
private:
using super = NiTMapBase<DFALL<NiTMapItem<Key, T>>, Key, T>;
public:
using key_type = typename super::key_type;
using mapped_type = typename super::mapped_type;
using value_type = typename super::value_type;
using size_type = typename super::size_type;
using allocator_type = typename super::allocator_type;
protected:
value_type* malloc_value() override { return new value_type(); }; // 05
void free_value(value_type* a_value) override { delete a_value; }; // 06
};
}
@@ -0,0 +1,13 @@
#pragma once
#include "RE/B/BSPointerAllocator.h"
namespace RE
{
template <class T>
class NiTPointerAllocator :
public BSPointerAllocator // 0
{
public:
};
}
@@ -0,0 +1,14 @@
#pragma once
#include "RE/N/NiTList.h"
#include "RE/N/NiTPointerAllocator.h"
namespace RE
{
template <class T>
class NiTPointerList : public NiTPointerListBase<NiTPointerAllocator<std::uintptr_t>, T>
{
public:
};
static_assert(sizeof(NiTPointerList<void*>) == 0x18);
}
@@ -0,0 +1,26 @@
#pragma once
#include "RE/N/NiTMap.h"
#include "RE/N/NiTPointerAllocator.h"
namespace RE
{
template <class Key, class T>
class NiTPointerMap :
public NiTMapBase<NiTPointerAllocator<std::size_t>, Key, T> // 00
{
private:
using super = NiTMapBase<NiTPointerAllocator<std::size_t>, Key, T>;
public:
using key_type = typename super::key_type;
using mapped_type = typename super::mapped_type;
using value_type = typename super::value_type;
using size_type = typename super::size_type;
using allocator_type = typename super::allocator_type;
protected:
value_type* malloc_value() override; // 05
void free_value(value_type* a_value) override; // 06
};
}
@@ -0,0 +1,53 @@
#pragma once
#include "RE/B/BSFixedString.h"
#include "RE/B/BSResource_Stream.h"
#include "RE/B/BSTSmartPointer.h"
#include "RE/N/NiObject.h"
namespace RE
{
namespace BSGraphics
{
class Texture;
}
namespace BSTextureArray
{
class Texture;
}
class __declspec(novtable) NiTexture :
public NiObject // 00
{
public:
static constexpr auto RTTI{ RTTI::NiTexture };
static constexpr auto VTABLE{ VTABLE::NiTexture };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiTexture };
// add
virtual BSTextureArray::Texture* IsBSTextureArray() { return nullptr; } // 28
static void SetAllowDegrade(bool a_allow)
{
using func_t = decltype(&NiTexture::SetAllowDegrade);
static REL::Relocation<func_t> func{ ID::NiTexture::SetAllowDegrade };
return func(a_allow);
}
[[nodiscard]] std::string_view GetName() const { return name; }
// members
BSFixedString name; // 10
std::uint32_t flags; // 18
NiTexture* prev; // 29
NiTexture* next; // 28
BSTSmartPointer<BSResource::Stream> stream; // 30
BSGraphics::Texture* rendererTexture; // 38
std::int8_t desiredDegradeLevel; // 40
std::int8_t savedDegradeLevel; // 41
bool isDDX: 1; // 42:0
bool isSRGB: 1; // 42:1
};
static_assert(sizeof(NiTexture) == 0x48);
}
@@ -0,0 +1,46 @@
#pragma once
#include "RE/N/NiObject.h"
#include "RE/N/NiPointer.h"
#include "RE/N/NiTFlags.h"
namespace RE
{
class NiObjectNET;
class NiUpdateData;
class __declspec(novtable) NiTimeController :
public NiObject // 00
{
public:
static constexpr auto RTTI{ RTTI::NiTimeController };
static constexpr auto VTABLE{ VTABLE::NiTimeController };
static constexpr auto Ni_RTTI{ Ni_RTTI::NiTimeController };
// add
virtual void Start(float a_time); // 28
virtual void Stop(); // 28
virtual void Update(NiUpdateData& a_updateData) = 0; // 29
virtual void SetTarget(NiObjectNET* a_target); // 2A
virtual bool IsTransformController() const { return false; } // 2B
virtual bool IsVertexController() const { return false; } // 2C
virtual float ComputeScaledTime(float a_time); // 2D
virtual void OnPreDisplay() { return; } // 2E
virtual bool IsStreamable() const { return true; } // 2F
virtual void Start() = 0; // 30
// members
NiTFlags<std::uint16_t, NiTimeController> flags; // 10
float frequency; // 14
float phase; // 18
float loKeyTime; // 1C
float hiKeyTime; // 20
float startTime; // 24
float lastTime; // 28
float weightedLastTime; // 2C
float scaledTime; // 30
NiObjectNET* target; // 38
NiPointer<NiTimeController> next; // 40
};
static_assert(sizeof(NiTimeController) == 0x48);
}
@@ -0,0 +1,100 @@
#pragma once
#include "RE/N/NiMatrix3.h"
#include "RE/N/NiPoint3.h"
namespace RE
{
class NiTransform
{
public:
static const NiTransform ZERO;
static const NiTransform IDENTITY;
constexpr NiTransform() noexcept = default;
constexpr NiTransform(const NiMatrix3& a_rotation, const NiPoint3& a_translation, const float a_scale = 1.0F) noexcept;
constexpr bool operator==(const NiTransform& a_rhs) const noexcept;
constexpr bool operator!=(const NiTransform& a_rhs) const noexcept;
constexpr NiTransform operator*(const NiTransform& a_rhs) const noexcept;
constexpr NiPoint3 operator*(const NiPoint3& a_rhs) const noexcept;
constexpr NiTransform Invert() const noexcept;
constexpr NiTransform& MakeIdentity() noexcept;
constexpr NiTransform& MakeInvert() noexcept;
// members
NiMatrix3 rotate; // 00
NiPoint3 translate; // 30
float scale{ 1.0F }; // 3C
};
static_assert(sizeof(NiTransform) == 0x40);
}
namespace RE
{
inline const NiTransform NiTransform::ZERO = { NiMatrix3::ZERO, NiPoint3::ZERO, 0.0F };
inline const NiTransform NiTransform::IDENTITY = { NiMatrix3::IDENTITY, NiPoint3::ZERO, 1.0F };
constexpr NiTransform::NiTransform(const NiMatrix3& a_rotation, const NiPoint3& a_translation, const float a_scale) noexcept :
rotate(a_rotation), translate(a_translation), scale(a_scale)
{}
constexpr bool NiTransform::operator==(const NiTransform& a_rhs) const noexcept
{
return (rotate == a_rhs.rotate) && (translate == a_rhs.translate) && (scale == a_rhs.scale);
}
constexpr bool NiTransform::operator!=(const NiTransform& a_rhs) const noexcept
{
return !operator==(a_rhs);
}
constexpr NiTransform NiTransform::operator*(const NiTransform& a_rhs) const noexcept
{
return NiTransform(rotate * a_rhs.rotate, translate + (rotate * a_rhs.translate) * scale, scale * a_rhs.scale);
}
constexpr NiPoint3 NiTransform::operator*(const NiPoint3& a_rhs) const noexcept
{
return NiPoint3(((rotate * a_rhs) * scale) + translate);
}
constexpr NiTransform NiTransform::Invert() const noexcept
{
NiTransform transform(*this);
return transform.MakeInvert();
}
constexpr NiTransform& NiTransform::MakeIdentity() noexcept
{
rotate = NiMatrix3::IDENTITY;
translate = NiPoint3::ZERO;
scale = 1.0F;
return *this;
}
constexpr NiTransform& NiTransform::MakeInvert() noexcept
{
rotate = rotate.Transpose();
scale = 1.0f / scale;
translate = (rotate * -translate) * scale;
return *this;
}
}
template <>
struct std::formatter<RE::NiTransform>
{
template <class ParseContext>
constexpr auto parse(ParseContext& a_ctx)
{
return a_ctx.begin();
}
template <class FormatContext>
constexpr auto format(const RE::NiTransform& a_transform, FormatContext& a_ctx) const
{
return format_to(a_ctx.out(), "<{}, {}>", a_transform.rotate, a_transform.translate, a_transform.scale);
}
};
@@ -0,0 +1,18 @@
#pragma once
namespace RE
{
class NiCamera;
class NiUpdateData
{
public:
// members
float time{ 0.0f }; // 00
NiCamera* camera{ nullptr }; // 08
std::uint32_t flags{ 0 }; // 10
std::uint32_t renderObjects{ 0 }; // 14
std::uint32_t fadeNodeDepth{ 0 }; // 18
};
static_assert(sizeof(NiUpdateData) == 0x20);
}
@@ -0,0 +1,13 @@
#pragma once
namespace RE
{
class alignas(0x08) NiVisibleArray
{
BSGeometry** array; // 00
std::uint32_t currentSize; // 08
std::uint32_t allocatedSize; // 0C
std::uint32_t growBy; // 10
};
static_assert(sizeof(0x18));
}
@@ -0,0 +1,15 @@
#pragma once
namespace RE
{
namespace NonMorphFaceManagement
{
class InstanceData
{
public:
// members
void* instanceData; // 00
};
static_assert(sizeof(InstanceData) == 0x8);
}
}
@@ -0,0 +1,30 @@
#pragma once
#include "RE/B/BSFixedString.h"
namespace RE
{
namespace nsHUDNotifications
{
[[nodiscard]] inline bool IsQuestNotification(const BSFixedString* a_type)
{
using func_t = decltype(&nsHUDNotifications::IsQuestNotification);
static REL::Relocation<func_t> func{ ID::nsHUDNotifications::IsQuestNotification };
return func(a_type);
}
[[nodiscard]] inline bool IsObjectiveNotification(const BSFixedString* a_type)
{
using func_t = decltype(&nsHUDNotifications::IsObjectiveNotification);
static REL::Relocation<func_t> func{ ID::nsHUDNotifications::IsObjectiveNotification };
return func(a_type);
}
[[nodiscard]] inline bool IsLocationDiscoveredNotification(const BSFixedString* a_type)
{
using func_t = decltype(&nsHUDNotifications::IsLocationDiscoveredNotification);
static REL::Relocation<func_t> func{ ID::nsHUDNotifications::IsLocationDiscoveredNotification };
return func(a_type);
}
}
}
@@ -0,0 +1,40 @@
#pragma once
#include "RE/B/BSFixedString.h"
#include "RE/B/BSTArray.h"
#include "RE/B/BSTOptional.h"
#include "RE/C/CountdownTimer.h"
#include "RE/X/XPChangeData.h"
namespace RE
{
class TESQuest;
namespace nsHUDTypes
{
class ObjectiveData
{
public:
// members
BSFixedStringCS objectiveName; // 00
bool completed; // 08
bool orWithPrevious; // 09
};
static_assert(sizeof(ObjectiveData) == 0x10);
class NotificationInfo
{
public:
// members
BSFixedStringCS title; // 00
BSFixedStringCS prefix; // 08
BSFixedStringCS soundName; // 10
BSTArray<nsHUDTypes::ObjectiveData> objectives; // 18
BSFixedString messageType; // 30
TESQuest* quest; // 38
CountdownTimer waitTime; // 40
BSTOptional<XPChangeData> xpChange; // 58
};
static_assert(sizeof(NotificationInfo) == 0x70);
}
}
@@ -0,0 +1,14 @@
#pragma once
namespace RE
{
namespace nsStatsMenuUtils
{
inline void GetEffectDisplayInfo(MagicItem* a_item, EffectItem* a_effect, float& a_magnitude, float& a_duration)
{
using func_t = decltype(&nsStatsMenuUtils::GetEffectDisplayInfo);
static REL::Relocation<func_t> func{ ID::nsStatsMenuUtils::GetEffectDisplayInfo };
return func(a_item, a_effect, a_magnitude, a_duration);
}
}
}