diff --git a/sfse/GameEvents.h b/sfse/GameEvents.h index 1aec2a0..1ed4571 100644 --- a/sfse/GameEvents.h +++ b/sfse/GameEvents.h @@ -4,6 +4,7 @@ namespace BSTEventDetail { class SinkBase { + public: virtual ~SinkBase() = 0; }; } diff --git a/sfse/GameFormComponents.h b/sfse/GameFormComponents.h index 6ef6034..ca6bc58 100644 --- a/sfse/GameFormComponents.h +++ b/sfse/GameFormComponents.h @@ -200,7 +200,7 @@ static_assert(sizeof(TESAIForm) == 0x40); class TESFullName : public BaseFormComponent { public: - void* strFullName; // 08 + BSFixedString strFullName; // 08 }; static_assert(sizeof(TESFullName) == 0x10); @@ -326,3 +326,11 @@ class BGSNativeTerminalForm : public BaseFormComponent BGSTerminal* pTerminal; // 08 }; static_assert(sizeof(BGSNativeTerminalForm) == 0x10); + +class BGSAttachParentArray : public BaseFormComponent +{ +public: + void*/*BGSTypedKeywordValue<2>*/ pArray; // 08 + u32 uiSize; // 10 +}; +static_assert(sizeof(BGSAttachParentArray) == 0x18); diff --git a/sfse/GameForms.h b/sfse/GameForms.h index 056ebd9..37b7aab 100644 --- a/sfse/GameForms.h +++ b/sfse/GameForms.h @@ -7,7 +7,7 @@ class TESFile; class TESObjectREFR; -class TESForm : public BaseFormComponent, public TESFormRefCount, public BSReflection::IObject +class TESForm : public BaseFormComponent, public BSReflection::IObject, public TESFormRefCount { public: virtual ~TESForm(); // 00 @@ -144,3 +144,20 @@ static_assert(sizeof(OBJ_REFR) == 0x30); //using _LookupByEDID = TESForm * (*)(const char* a_edid); //inline RelocAddr<_LookupByEDID> LookupByEDID(0x014D7F0C); + +class BGSListForm : + public TESForm +{ +public: + BSTArray ArrayOfForms; // 38 + u64 unk48; // 48 + u64 unk50; // 50 + u64 unk58; // 58 + u64 unk60; // 60 + u64 unk68; // 68 + u64 unk70; // 70 + u64 unk78; // 78 + u64 unk80; // 80 + u64 unk88; // 88 +}; +static_assert(sizeof(BGSListForm) == 0x90); \ No newline at end of file diff --git a/sfse/GameObjects.h b/sfse/GameObjects.h index 10f5606..bfb86f8 100644 --- a/sfse/GameObjects.h +++ b/sfse/GameObjects.h @@ -2,6 +2,14 @@ #include "sfse/GameForms.h" #include "sfse/GameFormComponents.h" +#include "sfse/GameEvents.h" + +class TESClass; +class TESCombatStyle; +class BGSOutfit; +class BGSListForm; +class TESFaction; +class BGSHeadPart; class TESObject : public TESForm { @@ -92,52 +100,73 @@ class TESActorBase : virtual void Unk_83(); // 83 virtual void Unk_84(); // 84 virtual void Unk_85(); // 85 - - /* - TESActorBaseData actorBaseData; // 118 - TESContainer container; // 188 - TESSpellList spellList; // 1A0 - TESAIForm aiForm; // 1B8 - TESFullName fullName; // 1F8 - ActorValueOwner actorValue; // 208 - BGSDestructibleObjectForm destructibleObject; // 210 - BGSSkinForm skinForm; // 220 - BGSKeywordForm keywords; // 230 - BGSAttackDataForm attackData; // 260 - BGSPerkRankArray perkRankArray; // 270 - BGSPropertySheet propertySheet; // 288 - */ }; -/*static_assert(offsetof(TESActorBase, actorBaseData) == 0x118); -static_assert(offsetof(TESActorBase, container) == 0x188); -static_assert(offsetof(TESActorBase, spellList) == 0x1A0); -static_assert(offsetof(TESActorBase, aiForm) == 0x1B8); -static_assert(offsetof(TESActorBase, fullName) == 0x1F8); -static_assert(offsetof(TESActorBase, actorValue) == 0x208); -static_assert(offsetof(TESActorBase, destructibleObject) == 0x210); -static_assert(offsetof(TESActorBase, skinForm) == 0x220); -static_assert(offsetof(TESActorBase, keywords) == 0x230); -static_assert(offsetof(TESActorBase, attackData) == 0x260); -static_assert(offsetof(TESActorBase, perkRankArray) == 0x270); -static_assert(offsetof(TESActorBase, propertySheet) == 0x288);*/ class TESNPC : public TESActorBase, - public TESRaceForm, // 298 - public BGSOverridePackCollection, // 2A8 - public BGSForcedLocRefType, // 2F0 - public BGSNativeTerminalForm // 308 + public TESRaceForm, // 298 + public BGSOverridePackCollection, // 2A8 + public BGSForcedLocRefType, // 2F0 + public BGSNativeTerminalForm, // 308 + public BSTEventSink // 318 { public: - /*TESRaceForm raceForm; // 298 - BGSOverridePackCollection overridePackCollection; // 2A8 - BGSForcedLocRefType forcedLocRefType; // 2F0 - BGSNativeTerminalForm terminalForm; // 308 - */ - - // More here, havent decoded this yet + BGSAttachParentArray AttachParents; // 320 + u64 unk338; // 338 + u32 unk340; // 340 + u32 unk344; // 344 + TESClass* pCl; // 348 + u64 unk350; // 350 + u64 unk358; // 358 + TESCombatStyle* pCombatStyle; // 360 + u32 unk368; // 368 + u32 unk36C; // 36C + u64 unk370; // 370 + u64 unk378; // 378 + u32 unk380; // 380 + float unk384; // 384 + float unk388; // 388 + float unk38C; // 38C + float unk390; // 390 + u32 unk394; // 394 + u64 unk398; // 398 + u64 unk3A0; // 3A0 + u64 unk3A8; // 3A8 + void* unk3B0; // 3B0 + u64 unk3B8; // 3B8 + u64 unk3C0; // 3C0 + BGSOutfit* pDefOutfit; // 3C8 + BGSOutfit* pSleepOutfit; // 3D0 + BGSListForm* pDefaultPackList; // 3D8 + TESFaction* pCrimeFaction; // 3E0 + u64 unk3F8; // 3E8 + BSTArray HeadPartsA; // 3F0 + u64 unk400; + void* unk408; + void* unk410; + void* unk418; + struct HeadPartData + { + u32 unk00; + u32 unk04; + BSFixedString unk08; + BSFixedString unk10; + BSFixedString texture; + u32 unk20; + u32 unk24; + }; + BSTArray HeadPartDataA; // 420 + u32 unk430; // 430 + u32 unk434; // 434 + u64 unk438; // 438 + u64 unk440; // 440 + BSFixedString unk448; + BSFixedString unk450; + BSFixedString unk458; + BSFixedString unk460; + u64 unk468; + u64 unk470; + u64 unk478; + u64 unk480; }; -/*static_assert(offsetof(TESNPC, raceForm) == 0x298); -static_assert(offsetof(TESNPC, overridePackCollection) == 0x2A8); -static_assert(offsetof(TESNPC, forcedLocRefType) == 0x2F0); -static_assert(offsetof(TESNPC, terminalForm) == 0x308);*/ +static_assert(sizeof(TESNPC) == 0x488); \ No newline at end of file diff --git a/sfse/GameTypes.cpp b/sfse/GameTypes.cpp new file mode 100644 index 0000000..b3446c7 --- /dev/null +++ b/sfse/GameTypes.cpp @@ -0,0 +1,4 @@ +#include "sfse/GameTypes.h" + +decltype(BSStringPool::Entry::GetEntry) BSStringPool::Entry::GetEntry(0x03149530); +decltype(BSStringPool::Entry::Release) BSStringPool::Entry::Release(0x00836C2C); \ No newline at end of file diff --git a/sfse/GameTypes.h b/sfse/GameTypes.h index 708862d..460ad15 100644 --- a/sfse/GameTypes.h +++ b/sfse/GameTypes.h @@ -1,5 +1,8 @@ #pragma once +#include "sfse_common/Types.h" +#include "sfse_common/Relocation.h" + template class BSSimpleList { @@ -12,6 +15,66 @@ class BSSimpleList Node node; }; +template +class BSTArray +{ +public: + u32 size; // 00 + u32 capacity; // 04 + T* pData; // 08 +}; + +namespace BSStringPool +{ + class Entry + { + public: + enum + { + kFlags_External = 0x2 + }; + BSStringPool::Entry* pLeft; // 00 + u64 uiLengthOrPtr; // 08 + u32 unk10; // 10 + u8 uFlags; // 14 + u8 pad[3]; // 15 + char pData[0]; // 18 + + const char* GetStringC() + { + Entry* iter = this; + while (iter->uFlags & kFlags_External) + iter = reinterpret_cast(uiLengthOrPtr); + return static_cast(iter->pData); + } + + using GetEntryT = void (*)(Entry*& entry, const char* apString, bool abCaseSensitive); + static RelocAddr GetEntry; + + using ReleaseT = void (*)(Entry*& entry); + static RelocAddr Release; + }; +} + +class BSFixedString +{ +public: + BSFixedString(const char* apString) + { + pData = nullptr; + BSStringPool::Entry::GetEntry(pData, apString, false); + } + ~BSFixedString() + { + if (pData) + BSStringPool::Entry::Release(pData); + } + const char* c_str() const { return pData ? pData->GetStringC() : nullptr; } + operator const char* () const { return pData ? pData->GetStringC() : nullptr; } + + BSStringPool::Entry* pData; +}; + // 08 struct BSIntrusiveRefCounted {