diff --git a/include/RE/IDs.h b/include/RE/IDs.h index 19e5701..32963ac 100644 --- a/include/RE/IDs.h +++ b/include/RE/IDs.h @@ -276,6 +276,7 @@ namespace RE::ID { inline constexpr REL::ID ctor{ 137778 }; // 196025 inline constexpr REL::ID dtor{ 0 }; // 196032 - inlined + inline constexpr REL::ID dtorUnkSub{ 137823 }; inline constexpr REL::ID GetHandle{ 0 }; // 196069 - inlined inline constexpr REL::ID SetHandle{ 0 }; // 196079 inline constexpr REL::ID IncRef{ 0 }; // 37879 @@ -289,8 +290,8 @@ namespace RE::ID namespace ObjectTypeInfo { - inline constexpr REL::ID ctor{ 0 }; // 197047 - inline constexpr REL::ID dtor{ 0 }; // 196202 + inline constexpr REL::ID ctor{ 138400 }; // 197047 + inline constexpr REL::ID dtor{ 137885 }; // 196202 inline constexpr REL::ID Clear{ 0 }; // 196218 inline constexpr REL::ID CopyFromLinkedData{ 0 }; // 196219 inline constexpr REL::ID GetProperty{ 0 }; // 196241 diff --git a/include/RE/O/Object.h b/include/RE/O/Object.h index c55b58d..0416cde 100644 --- a/include/RE/O/Object.h +++ b/include/RE/O/Object.h @@ -14,17 +14,10 @@ namespace RE::BSScript class Object { public: - void dtor() - { - using func_t = decltype(&Object::dtor); - static REL::Relocation func{ ID::BSScript::Object::dtor }; - return func(this); - } + void dtor(); ~Object() { - // TODO: The destructor was inlined in version Starfield 1.15 and still needs to be - // pieced together or reimplemented dtor(); } @@ -66,7 +59,7 @@ namespace RE::BSScript std::uint32_t unk1C; // 1C BSTSmartPointer type; // 20 BSFixedString currentState; // 28 - void* lockStructure; // 30 + volatile void* lockStructure; // 30 IObjectHandlePolicy* handlePolicy; // 38 std::size_t handle; // 40 volatile std::uint32_t refCountAndHandleLock; // 48 diff --git a/src/RE/O/Object.cpp b/src/RE/O/Object.cpp index d9affb7..995c0e4 100644 --- a/src/RE/O/Object.cpp +++ b/src/RE/O/Object.cpp @@ -2,6 +2,33 @@ namespace RE::BSScript { + void Object::dtor() + { + static REL::Relocation UnkObjectDtorSubroutine{ ID::BSScript::Object::dtorUnkSub }; + typedef ObjectTypeInfo* (*ObjectTypeInfoDeallocator)(ObjectTypeInfo*, std::uint32_t); + static REL::Relocation ObjectTypeInfoDealloc{ ID::BSScript::ObjectTypeInfo::dtor }; + + this->lockStructure = + reinterpret_cast(reinterpret_cast(this->lockStructure) & 0xfffffffffffffffe); + + if (this->lockStructure != 0) { + _InterlockedExchangeAdd(reinterpret_cast(this->lockStructure), -1); + } + + ObjectTypeInfo* pType = this->type.get(); + + //BSTSmartPointer will decrement type's refcount automatically at end of scope + if (pType->QRefCount() == 1) { + //This stops the smart pointer from dereferencing a dangling ObjectTypeInfo pointer after + //ObjectTypeInfoDealloc frees Object::type (and also does unknown global/TLS variable plumbing) + this->type->IncRef(); + this->type.reset(); + ObjectTypeInfoDealloc(pType, 1); + } + + UnkObjectDtorSubroutine(this); + } + [[nodiscard]] std::uint32_t Object::DecRef() { std::int32_t iVar1;