docs: add plugin setup guide
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
#include "RE/A/Actor.h"
|
||||
|
||||
#include "RE/T/TESBoundObject.h"
|
||||
#include "RE/T/TESNPC.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
TESNPC* Actor::GetNPC() const noexcept
|
||||
{
|
||||
const auto objRef = GetObjectReference();
|
||||
assert(objRef->GetFormType() == ENUM_FORM_ID::kNPC_);
|
||||
return static_cast<TESNPC*>(objRef);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "RE/B/BGSCreatedObjectManager.h"
|
||||
|
||||
#include "RE/A/AlchemyItem.h"
|
||||
#include "RE/T/TESForm.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BGSCreatedObjectManager::BSTCreatedObjectSmartPointerPolicy<AlchemyItem>;
|
||||
static_assert(std::is_empty_v<BGSCreatedObjectManager::BSTCreatedObjectSmartPointerPolicy<AlchemyItem>>);
|
||||
|
||||
template class BGSCreatedObjectManager::BSTCreatedObjectSmartPointerPolicy<TESForm>;
|
||||
static_assert(std::is_empty_v<BGSCreatedObjectManager::BSTCreatedObjectSmartPointerPolicy<TESForm>>);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "RE/B/BGSInventoryItem.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
std::uint32_t BGSInventoryItem::GetCount() const noexcept
|
||||
{
|
||||
std::uint32_t count = 0;
|
||||
for (auto iter = stackData.get(); iter; iter = iter->nextStack.get()) {
|
||||
count += iter->GetCount();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "RE/B/BGSKeyword.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
BGSKeyword* BGSKeywordGetTypedKeywordByIndex(KeywordType a_type, std::uint16_t a_index)
|
||||
{
|
||||
return BGSKeyword::GetTypedKeywordByIndex(a_type, a_index);
|
||||
}
|
||||
|
||||
std::uint16_t BGSKeywordGetIndexForTypedKeyword(BGSKeyword* a_keyword, KeywordType a_type)
|
||||
{
|
||||
return BGSKeyword::GetIndexForTypedKeyword(a_keyword, a_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "RE/B/BGSKeywordForm.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void BGSKeywordForm::CopyKeywords(const std::vector<BGSKeyword*>& a_copiedData)
|
||||
{
|
||||
const auto oldData = keywords;
|
||||
|
||||
const auto newSize = a_copiedData.size();
|
||||
const auto newData = calloc<BGSKeyword*>(newSize);
|
||||
std::ranges::copy(a_copiedData, newData);
|
||||
|
||||
numKeywords = static_cast<std::uint32_t>(newSize);
|
||||
keywords = newData;
|
||||
|
||||
free(oldData);
|
||||
}
|
||||
|
||||
bool BGSKeywordForm::AddKeywords(const std::vector<BGSKeyword*>& a_keywords)
|
||||
{
|
||||
std::vector<BGSKeyword*> copiedData{ keywords, keywords + numKeywords };
|
||||
std::ranges::remove_copy_if(a_keywords, std::back_inserter(copiedData), [&](auto& keyword) {
|
||||
return std::ranges::find(copiedData, keyword) != copiedData.end();
|
||||
});
|
||||
CopyKeywords(copiedData);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BGSKeywordForm::ContainsKeywordString(std::string_view a_editorID) const
|
||||
{
|
||||
bool result = false;
|
||||
ForEachKeyword([&](const BGSKeyword* a_keyword) {
|
||||
if (a_keyword->formEditorID.contains(a_editorID)) {
|
||||
result = true;
|
||||
return BSContainer::ForEachResult::kStop;
|
||||
}
|
||||
return BSContainer::ForEachResult::kContinue;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BGSKeywordForm::HasKeywordID(TESFormID a_formID) const
|
||||
{
|
||||
bool result = false;
|
||||
ForEachKeyword([&](const BGSKeyword* a_keyword) {
|
||||
if (a_keyword->GetFormID() == a_formID) {
|
||||
result = true;
|
||||
return BSContainer::ForEachResult::kStop;
|
||||
}
|
||||
return BSContainer::ForEachResult::kContinue;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BGSKeywordForm::HasKeywordString(std::string_view a_editorID) const
|
||||
{
|
||||
bool result = false;
|
||||
ForEachKeyword([&](const BGSKeyword* a_keyword) {
|
||||
if (a_keyword->formEditorID == a_editorID) {
|
||||
result = true;
|
||||
return BSContainer::ForEachResult::kStop;
|
||||
}
|
||||
return BSContainer::ForEachResult::kContinue;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BGSKeywordForm::RemoveKeywords(const std::vector<BGSKeyword*>& a_keywords)
|
||||
{
|
||||
std::vector<BGSKeyword*> copiedData{ keywords, keywords + numKeywords };
|
||||
if (std::erase_if(copiedData, [&](auto& keyword) { return std::ranges::find(a_keywords, keyword) != a_keywords.end(); }) > 0) {
|
||||
CopyKeywords(copiedData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "RE/B/BGSLocation.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
bool BGSLocation::IsChild(const BGSLocation* a_possibleChild) const
|
||||
{
|
||||
if (a_possibleChild) {
|
||||
for (auto it = a_possibleChild->parentLoc; it; it = it->parentLoc) {
|
||||
if (this == it) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BGSLocation::IsParent(const BGSLocation* a_possibleParent) const
|
||||
{
|
||||
if (a_possibleParent) {
|
||||
for (auto it = parentLoc; it; it = it->parentLoc) {
|
||||
if (a_possibleParent == it) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "RE/B/BGSObjectInstanceExtra.h"
|
||||
|
||||
#include "RE/B/BGSMod.h"
|
||||
#include "RE/T/TESBoundObject.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void BGSObjectInstanceExtra::CreateBaseInstanceData(const TESBoundObject& a_object, BSTSmartPointer<TBO_InstanceData>& a_instanceData) const
|
||||
{
|
||||
if (values && itemIndex != static_cast<std::uint16_t>(-1)) {
|
||||
a_object.ApplyMods(a_instanceData, this);
|
||||
}
|
||||
}
|
||||
|
||||
std::span<BGSMod::ObjectIndexData> BGSObjectInstanceExtra::GetIndexData() const noexcept
|
||||
{
|
||||
return values->GetBuffer<BGSMod::ObjectIndexData>(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "RE/B/BSCRC32.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template struct BSCRC32<std::int8_t>;
|
||||
template struct BSCRC32<std::uint8_t>;
|
||||
template struct BSCRC32<std::int16_t>;
|
||||
template struct BSCRC32<std::uint16_t>;
|
||||
template struct BSCRC32<std::int32_t>;
|
||||
template struct BSCRC32<std::uint32_t>;
|
||||
template struct BSCRC32<std::int64_t>;
|
||||
template struct BSCRC32<std::uint64_t>;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "RE/B/BSFixedString.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template class BSFixedString<char, false>;
|
||||
static_assert(sizeof(BSFixedString<char, false>) == 0x8);
|
||||
|
||||
template class BSFixedString<char, true>;
|
||||
static_assert(sizeof(BSFixedString<char, true>) == 0x8);
|
||||
|
||||
template class BSFixedString<wchar_t, false>;
|
||||
static_assert(sizeof(BSFixedString<wchar_t, false>) == 0x8);
|
||||
|
||||
template class BSFixedString<wchar_t, true>;
|
||||
static_assert(sizeof(BSFixedString<wchar_t, true>) == 0x8);
|
||||
}
|
||||
|
||||
template struct BSCRC32<BSFixedString>;
|
||||
template struct BSCRC32<BSFixedStringCS>;
|
||||
template struct BSCRC32<BSFixedStringW>;
|
||||
template struct BSCRC32<BSFixedStringWCS>;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "RE/B/BSPointerHandle.h"
|
||||
|
||||
#include "RE/A/Actor.h"
|
||||
#include "RE/P/Projectile.h"
|
||||
#include "RE/T/TESObjectREFR.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSPointerHandle<Actor>;
|
||||
static_assert(sizeof(BSPointerHandle<Actor>) == 0x4);
|
||||
|
||||
template class BSPointerHandle<Projectile>;
|
||||
static_assert(sizeof(BSPointerHandle<Projectile>) == 0x4);
|
||||
|
||||
template class BSPointerHandle<TESObjectREFR>;
|
||||
static_assert(sizeof(BSPointerHandle<TESObjectREFR>) == 0x4);
|
||||
|
||||
template class BSUntypedPointerHandle<>;
|
||||
static_assert(sizeof(BSUntypedPointerHandle<>) == 0x4);
|
||||
|
||||
template class BSPointerHandleManagerInterface<Actor>;
|
||||
static_assert(std::is_empty_v<BSPointerHandleManagerInterface<Actor>>);
|
||||
|
||||
template class BSPointerHandleManagerInterface<Projectile>;
|
||||
static_assert(std::is_empty_v<BSPointerHandleManagerInterface<Projectile>>);
|
||||
|
||||
template class BSPointerHandleManagerInterface<TESObjectREFR>;
|
||||
static_assert(std::is_empty_v<BSPointerHandleManagerInterface<TESObjectREFR>>);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "RE/B/BSResource.h"
|
||||
|
||||
namespace RE::BSResource
|
||||
{
|
||||
ErrorCode GetOrCreateStream(const char* a_fileName, BSTSmartPointer<Stream>& a_result, bool a_writable, Location* a_optionalStart)
|
||||
{
|
||||
using func_t = decltype(&GetOrCreateStream);
|
||||
static REL::Relocation<func_t> func{ ID::BSResource::GetOrCreateStream };
|
||||
return func(a_fileName, a_result, a_writable, a_optionalStart);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "RE/B/BSResourceNiBinaryStream.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
BSResourceNiBinaryStream::BSResourceNiBinaryStream() :
|
||||
NiBinaryStream()
|
||||
{}
|
||||
|
||||
BSResourceNiBinaryStream::BSResourceNiBinaryStream(const char* a_file, bool a_writeable, BSResource::Location* a_optionalStart, bool a_fullReadHint) :
|
||||
NiBinaryStream()
|
||||
{
|
||||
using func_t = void (*)(BSResourceNiBinaryStream*, const char*, bool, BSResource::Location*, bool);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::Ctor };
|
||||
func(this, a_file, a_writeable, a_optionalStart, a_fullReadHint);
|
||||
}
|
||||
|
||||
BSResourceNiBinaryStream::~BSResourceNiBinaryStream()
|
||||
{
|
||||
using func_t = void (*)(BSResourceNiBinaryStream*);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::Dtor };
|
||||
func(this);
|
||||
}
|
||||
|
||||
void BSResourceNiBinaryStream::Seek(std::ptrdiff_t a_numBytes)
|
||||
{
|
||||
using func_t = decltype(&BSResourceNiBinaryStream::Seek);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::Seek };
|
||||
return func(this, a_numBytes);
|
||||
}
|
||||
|
||||
void BSResourceNiBinaryStream::GetBufferInfo(BufferInfo& a_buf)
|
||||
{
|
||||
using func_t = decltype(&BSResourceNiBinaryStream::GetBufferInfo);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::GetBufferInfo };
|
||||
return func(this, a_buf);
|
||||
}
|
||||
|
||||
std::size_t BSResourceNiBinaryStream::DoRead(void* a_buf, std::size_t a_toRead)
|
||||
{
|
||||
using func_t = decltype(&BSResourceNiBinaryStream::DoRead);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::DoRead };
|
||||
return func(this, a_buf, a_toRead);
|
||||
}
|
||||
|
||||
std::size_t BSResourceNiBinaryStream::DoWrite(const void* a_buf, std::size_t a_toWrite)
|
||||
{
|
||||
using func_t = decltype(&BSResourceNiBinaryStream::DoWrite);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::DoWrite };
|
||||
return func(this, a_buf, a_toWrite);
|
||||
}
|
||||
|
||||
[[nodiscard]] BSResourceNiBinaryStream* BSResourceNiBinaryStream::BinaryStreamWithRescan(const char* a_fileName)
|
||||
{
|
||||
using func_t = decltype(&BSResourceNiBinaryStream::BinaryStreamWithRescan);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::BinaryStreamWithRescan };
|
||||
return func(a_fileName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
#include "RE/B/BSResource_Stream.h"
|
||||
|
||||
namespace RE::BSResource
|
||||
{
|
||||
Stream::Stream() :
|
||||
Stream(0, false)
|
||||
{}
|
||||
|
||||
Stream::Stream(std::uint32_t a_totalSize, bool writable) :
|
||||
StreamBase(a_totalSize, writable)
|
||||
{}
|
||||
|
||||
Stream::Stream(const Stream& a_rhs) :
|
||||
StreamBase(a_rhs)
|
||||
{}
|
||||
|
||||
Stream::Stream(Stream&& a_rhs) :
|
||||
StreamBase(std::move(a_rhs))
|
||||
{}
|
||||
|
||||
ErrorCode Stream::DoSetEndOfStream()
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoPrefetchAt([[maybe_unused]] std::uint64_t a_v, [[maybe_unused]] std::uint64_t b_v, [[maybe_unused]] std::uint32_t c_v) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoPrefetchAll([[maybe_unused]] std::uint32_t a_v) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoStartTaggedPrioritizedRead([[maybe_unused]] void* a_buf,
|
||||
[[maybe_unused]] std::uint64_t a_v,
|
||||
[[maybe_unused]] std::uint64_t b_v,
|
||||
[[maybe_unused]] std::uint32_t c_v,
|
||||
[[maybe_unused]] std::uint32_t volatile* d_v,
|
||||
[[maybe_unused]] std::uint32_t& e_v,
|
||||
[[maybe_unused]] BSEventFlag* event_flag) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
bool Stream::DoGetName(BSFixedString& a_dst) const
|
||||
{
|
||||
a_dst = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoCreateAsync(BSTSmartPointer<BSResource::AsyncStream>&) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
bool Stream::DoGetIsFromArchive() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ErrorCode Stream::DoWaitTags([[maybe_unused]] volatile std::uint32_t* a_completionTag,
|
||||
[[maybe_unused]] std::uint32_t a_completionTagWaitValue,
|
||||
[[maybe_unused]] BSEventFlag* a_eventFlag) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
bool Stream::DoQTaggedPrioritizedReadSupported() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoCreateOp([[maybe_unused]] BSTSmartPointer<ICacheDriveOp>& p_op, [[maybe_unused]] char const* name) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoReadAt([[maybe_unused]] void* a_buffer,
|
||||
[[maybe_unused]] std::uint64_t a_offset,
|
||||
[[maybe_unused]] std::uint64_t a_toRead,
|
||||
[[maybe_unused]] std::uint64_t& a_read) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
// interface functions
|
||||
ErrorCode Stream::Read(void* a_buffer, std::uint64_t a_toRead, std::uint64_t& a_read) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
return DoRead(a_buffer, a_toRead, a_read);
|
||||
}
|
||||
|
||||
ErrorCode Stream::ReadAt(void* a_buffer, std::uint64_t a_offset, std::uint64_t a_toRead, std::uint64_t& a_read) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
return DoReadAt(a_buffer, a_offset, a_toRead, a_read);
|
||||
}
|
||||
|
||||
bool Stream::GetName(BSFixedString& a_dst) const
|
||||
{
|
||||
return DoGetName(a_dst);
|
||||
}
|
||||
|
||||
ErrorCode Stream::Open(bool buffered, bool readFullHint)
|
||||
{
|
||||
uint32_t _flags = kUnk3;
|
||||
if (buffered) {
|
||||
_flags |= kBuffered;
|
||||
}
|
||||
if (readFullHint) {
|
||||
_flags |= kBuffered | kFullReadHint;
|
||||
}
|
||||
static std::atomic_ref myflags{ flags };
|
||||
uint32_t old_flags = flags;
|
||||
while (!myflags.compare_exchange_strong(old_flags, (old_flags | _flags))) {
|
||||
old_flags = flags;
|
||||
}
|
||||
return DoOpen();
|
||||
}
|
||||
|
||||
ErrorCode Stream::Seek(std::uint64_t a_toSeek, SeekMode a_mode, std::uint64_t& a_sought) const
|
||||
{
|
||||
return DoSeek(a_toSeek, a_mode, a_sought);
|
||||
}
|
||||
|
||||
ErrorCode Stream::Write(const void* a_buffer, std::uint64_t a_toWrite, std::uint64_t& a_written) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return DoWrite(a_buffer, a_toWrite, a_written);
|
||||
}
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
ErrorCode Stream::CreateOp(BSTSmartPointer<ICacheDriveOp>& a_opOut, const char* name) const
|
||||
{
|
||||
return DoCreateOp(a_opOut, name);
|
||||
}
|
||||
|
||||
ErrorCode Stream::CreateAsync(BSTSmartPointer<AsyncStream>& a_streamOut) const
|
||||
{
|
||||
return DoCreateAsync(a_streamOut);
|
||||
}
|
||||
|
||||
ErrorCode Stream::PrefetchAll(std::uint32_t a_v) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
return DoPrefetchAll(a_v);
|
||||
}
|
||||
|
||||
ErrorCode Stream::PrefetchAt(std::uint64_t a_v, std::uint64_t b_v, std::uint32_t c_v) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
return DoPrefetchAt(a_v, b_v, c_v);
|
||||
}
|
||||
|
||||
std::uint32_t Stream::QFullReadHint() const
|
||||
{
|
||||
return flags & kFullReadHint;
|
||||
}
|
||||
|
||||
bool Stream::QTaggedPrioritizedReadSupported() const
|
||||
{
|
||||
return DoQTaggedPrioritizedReadSupported();
|
||||
}
|
||||
|
||||
ErrorCode Stream::StartTaggedPrioritizedRead(void* buf, std::uint64_t a_v, std::uint64_t b_v, std::uint32_t c_V, std::uint32_t volatile* d_v, std::uint32_t& e_v, BSEventFlag* event_flag) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
return DoStartTaggedPrioritizedRead(buf, a_v, b_v, c_V, d_v, e_v, event_flag);
|
||||
}
|
||||
|
||||
ErrorCode Stream::WaitTags(std::uint32_t volatile* a_v, std::uint32_t b_v, BSEventFlag* event_flag) const
|
||||
{
|
||||
return DoWaitTags(a_v, b_v, event_flag);
|
||||
}
|
||||
|
||||
std::uint32_t Stream::QBuffered() const
|
||||
{
|
||||
return flags & kBuffered;
|
||||
}
|
||||
|
||||
ErrorCode Stream::SetEndOfStream()
|
||||
{
|
||||
return DoSetEndOfStream();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "RE/B/BSResource_StreamBase.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSResource
|
||||
{
|
||||
StreamBase::StreamBase() :
|
||||
totalSize(0),
|
||||
flags(0)
|
||||
{}
|
||||
|
||||
StreamBase::StreamBase(const StreamBase& a_rhs) :
|
||||
totalSize(a_rhs.totalSize),
|
||||
flags(a_rhs.flags & ~kRefCountMask)
|
||||
{}
|
||||
|
||||
StreamBase::StreamBase(StreamBase&& a_rhs) :
|
||||
totalSize(a_rhs.totalSize),
|
||||
flags(a_rhs.flags & ~kRefCountMask)
|
||||
{}
|
||||
|
||||
StreamBase::StreamBase(std::uint32_t a_totalSize, bool writable) :
|
||||
totalSize(a_totalSize),
|
||||
flags(writable ? 1 : 0)
|
||||
{}
|
||||
|
||||
std::uint64_t StreamBase::DoGetKey() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ErrorCode StreamBase::DoGetInfo(Info&)
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
std::uint32_t StreamBase::DecRef()
|
||||
{
|
||||
REX::TAtomicRef myFlags{ flags };
|
||||
std::uint32_t expected;
|
||||
do {
|
||||
expected = myFlags;
|
||||
} while (!myFlags.compare_exchange_weak(expected, expected - kRefCountBeg));
|
||||
return (expected - kRefCountBeg) & kRefCountMask;
|
||||
}
|
||||
|
||||
std::uint32_t StreamBase::IncRef()
|
||||
{
|
||||
REX::TAtomicRef myFlags{ flags };
|
||||
std::uint32_t expected;
|
||||
do {
|
||||
expected = myFlags;
|
||||
} while (!myFlags.compare_exchange_weak(expected, expected + kRefCountBeg));
|
||||
return (expected - kRefCountBeg) & kRefCountMask;
|
||||
}
|
||||
|
||||
bool StreamBase::IsWritable() const
|
||||
{
|
||||
return static_cast<bool>(flags & kWritable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "RE/B/BSScaleformManager.h"
|
||||
|
||||
#include "RE/B/BSSystemFileStreamer.h"
|
||||
#include "RE/I/IMenu.h"
|
||||
#include "RE/S/Setting.h"
|
||||
#include "Scaleform/G/GFx_Loader.h"
|
||||
#include "Scaleform/G/GFx_MovieDef.h"
|
||||
#include "Scaleform/P/Ptr.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
bool BSScaleformManager::LoadMovieEx(
|
||||
IMenu& a_menu,
|
||||
std::string_view a_filePath,
|
||||
std::string_view a_menuObjPath,
|
||||
ScaleModeType a_scaleMode,
|
||||
float a_backgroundAlpha)
|
||||
{
|
||||
static REL::Relocation<SettingT<INISettingCollection>*> fileUncacheOnMenuOpen{ ID::BSScaleformManager::FileUncacheOnMenuOpen };
|
||||
if (fileUncacheOnMenuOpen && fileUncacheOnMenuOpen->GetBinary()) {
|
||||
BSSystemFileStreamer::UncacheAll(true);
|
||||
}
|
||||
|
||||
REX::TEnumSet loadConstants{
|
||||
Scaleform::GFx::Loader::LoadConstants::kKeepBindData,
|
||||
Scaleform::GFx::Loader::LoadConstants::kWaitFrame1
|
||||
};
|
||||
|
||||
const auto movieDef = Scaleform::Ptr{ loader->CreateMovie(a_filePath.data(), loadConstants.get()) };
|
||||
if (!movieDef) {
|
||||
return false;
|
||||
}
|
||||
movieDef->Release();
|
||||
|
||||
auto& movie = a_menu.uiMovie;
|
||||
movie.reset(movieDef->CreateInstance(true));
|
||||
if (!movie) {
|
||||
return false;
|
||||
}
|
||||
movie->Release();
|
||||
|
||||
movie->SetViewScaleMode(a_scaleMode);
|
||||
movie->SetBackgroundAlpha(a_backgroundAlpha);
|
||||
a_menu.DoAdvanceMovie(0.0);
|
||||
if (!a_menuObjPath.empty()) {
|
||||
a_menu.SetMenuCodeObject(*movie, a_menuObjPath);
|
||||
}
|
||||
a_menu.RefreshPlatform();
|
||||
InitMovieViewport(*movie, 1.0F, 1.0F);
|
||||
a_menu.OnSetSafeRect();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
#include "RE/B/BSScript_Array.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
Array::~Array()
|
||||
{
|
||||
}
|
||||
|
||||
// Array* Array::ctor(const TypeInfo *type_info, std::uint32_t initial_size)
|
||||
// {
|
||||
// using func_t = decltype(&Array::ctor);
|
||||
// REL::Relocation<func_t> func{ ID::BSScript_Array::ctor };
|
||||
// return func(this, type_info, initial_size);
|
||||
// }
|
||||
|
||||
[[nodiscard]] auto Array::operator[](size_type a_pos)
|
||||
-> reference
|
||||
{
|
||||
assert(a_pos < size());
|
||||
return elements[a_pos];
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::operator[](size_type a_pos) const
|
||||
-> const_reference
|
||||
{
|
||||
assert(a_pos < size());
|
||||
return elements[a_pos];
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::front()
|
||||
-> reference
|
||||
{
|
||||
return operator[](0);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::front() const
|
||||
-> const_reference
|
||||
{
|
||||
return operator[](0);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::back()
|
||||
-> reference
|
||||
{
|
||||
return operator[](size() - 1);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::back() const
|
||||
-> const_reference
|
||||
{
|
||||
return operator[](size() - 1);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::data() noexcept
|
||||
-> pointer
|
||||
{
|
||||
return size() > 0 ? elements.data() : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::data() const noexcept
|
||||
-> const_pointer
|
||||
{
|
||||
return size() > 0 ? elements.data() : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::begin() noexcept
|
||||
-> iterator
|
||||
{
|
||||
return elements.begin();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::begin() const noexcept
|
||||
-> const_iterator
|
||||
{
|
||||
return elements.begin();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::cbegin() const noexcept
|
||||
-> const_iterator
|
||||
{
|
||||
return elements.begin();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::end() noexcept
|
||||
-> iterator
|
||||
{
|
||||
return size() > 0 ? elements.end() : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::end() const noexcept
|
||||
-> const_iterator
|
||||
{
|
||||
return size() > 0 ? elements.end() : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::cend() const noexcept
|
||||
-> const_iterator
|
||||
{
|
||||
return elements.end();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::rbegin() noexcept
|
||||
-> reverse_iterator
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::rbegin() const noexcept
|
||||
-> const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::crbegin() const noexcept
|
||||
-> const_reverse_iterator
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::rend() noexcept
|
||||
-> reverse_iterator
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::rend() const noexcept
|
||||
-> const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::crend() const noexcept
|
||||
-> const_reverse_iterator
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Array::empty() const noexcept
|
||||
{
|
||||
return size() > 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::size() const noexcept
|
||||
-> size_type
|
||||
{
|
||||
return elements.size();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::max_size() const noexcept
|
||||
-> size_type
|
||||
{
|
||||
return elements.max_size();
|
||||
}
|
||||
|
||||
[[nodiscard]] TypeInfo& Array::type_info()
|
||||
{
|
||||
return elementType;
|
||||
}
|
||||
|
||||
[[nodiscard]] const TypeInfo& Array::type_info() const
|
||||
{
|
||||
return elementType;
|
||||
}
|
||||
|
||||
[[nodiscard]] TypeInfo::RawType Array::type() const
|
||||
{
|
||||
const REX::TEnumSet typeID = elementType.GetRawType();
|
||||
switch (*typeID) {
|
||||
case TypeInfo::RawType::kNone:
|
||||
case TypeInfo::RawType::kObject:
|
||||
case TypeInfo::RawType::kString:
|
||||
case TypeInfo::RawType::kInt:
|
||||
case TypeInfo::RawType::kFloat:
|
||||
case TypeInfo::RawType::kBool:
|
||||
return *(typeID + TypeInfo::RawType::kArrayStart);
|
||||
default:
|
||||
return *(typeID + TypeInfo::RawType::kObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "RE/B/BSScript_Internal_VirtualMachine.h"
|
||||
|
||||
#include "RE/G/GameScript.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
VirtualMachine* VirtualMachine::GetSingleton()
|
||||
{
|
||||
auto vm = GameVM::GetSingleton();
|
||||
return vm ? static_cast<VirtualMachine*>(vm->impl.get()) : nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#include "RE/B/BSScript_Object.h"
|
||||
|
||||
#include "RE/B/BSScript_IObjectHandlePolicy.h"
|
||||
#include "RE/B/BSScript_Internal_VirtualMachine.h"
|
||||
|
||||
namespace RE::BSScript
|
||||
{
|
||||
Object::~Object()
|
||||
{
|
||||
if (IsConstructed()) {
|
||||
const std::uint32_t size = type ? type->GetVariableCount() : 0;
|
||||
for (std::uint32_t i = 0; i < size; ++i) {
|
||||
variables[i].reset();
|
||||
}
|
||||
|
||||
constructed = false;
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
auto lock = reinterpret_cast<std::uintptr_t>(lockStructure) & ~static_cast<std::uintptr_t>(1);
|
||||
if (lock) {
|
||||
REX::TAtomicRef l{ lock };
|
||||
--l;
|
||||
}
|
||||
}
|
||||
ObjectTypeInfo* Object::GetTypeInfo()
|
||||
{
|
||||
return type.get();
|
||||
}
|
||||
|
||||
const ObjectTypeInfo* Object::GetTypeInfo() const
|
||||
{
|
||||
return type.get();
|
||||
}
|
||||
|
||||
void* Object::Resolve(std::uint32_t a_typeID) const
|
||||
{
|
||||
auto vm = Internal::VirtualMachine::GetSingleton();
|
||||
if (!vm) {
|
||||
return nullptr;
|
||||
}
|
||||
IObjectHandlePolicy& policy = vm->GetObjectHandlePolicy();
|
||||
auto myHandle = GetHandle();
|
||||
if (policy.HandleIsType(a_typeID, myHandle) && policy.IsHandleObjectAvailable(myHandle)) {
|
||||
return policy.GetObjectForHandle(a_typeID, myHandle);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
Variable* Object::GetProperty(const BSFixedString& a_name)
|
||||
{
|
||||
return const_cast<Variable*>(
|
||||
const_cast<const Object*>(this)->GetProperty(a_name));
|
||||
}
|
||||
|
||||
const Variable* Object::GetProperty(const BSFixedString& a_name) const
|
||||
{
|
||||
constexpr auto INVALID = static_cast<std::uint32_t>(-1);
|
||||
|
||||
auto idx = INVALID;
|
||||
for (auto cls = type.get(); cls && idx == INVALID; cls = cls->GetParent()) {
|
||||
idx = cls->GetPropertyIndex(a_name);
|
||||
}
|
||||
|
||||
return idx != INVALID ? std::addressof(variables[idx]) : nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
#include "RE/B/BSScript_ObjectTypeInfo.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
BSFixedString ObjectTypeInfo::UserFlagInfo::GetUserFlag() const
|
||||
{
|
||||
auto sanitizedType = data & ~kSetOnObject;
|
||||
return *reinterpret_cast<BSFixedString*>(&sanitizedType);
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::NamedStateInfo::GetFuncIter()
|
||||
-> Func*
|
||||
{
|
||||
return reinterpret_cast<Func*>((std::uintptr_t)this + memberFunctionOffset);
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::NamedStateInfo::GetFuncIter() const
|
||||
-> const Func*
|
||||
{
|
||||
return reinterpret_cast<const Func*>((std::uintptr_t)this + memberFunctionOffset);
|
||||
}
|
||||
|
||||
ObjectTypeInfo::~ObjectTypeInfo()
|
||||
{
|
||||
dtor();
|
||||
}
|
||||
|
||||
const char* ObjectTypeInfo::GetName() const
|
||||
{
|
||||
return name.c_str();
|
||||
}
|
||||
|
||||
ObjectTypeInfo* ObjectTypeInfo::GetParent()
|
||||
{
|
||||
return parentTypeInfo.get();
|
||||
}
|
||||
|
||||
const ObjectTypeInfo* ObjectTypeInfo::GetParent() const
|
||||
{
|
||||
return parentTypeInfo.get();
|
||||
}
|
||||
|
||||
TypeInfo::RawType ObjectTypeInfo::GetRawType() const
|
||||
{
|
||||
return TypeInfo::RawType::kObject;
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetUnlinkedFunctionIter()
|
||||
-> UnlinkedNativeFunction*
|
||||
{
|
||||
return reinterpret_cast<UnlinkedNativeFunction*>(data);
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetUnlinkedFunctionIter() const
|
||||
-> const UnlinkedNativeFunction*
|
||||
{
|
||||
return reinterpret_cast<const UnlinkedNativeFunction*>(data);
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetUserFlagIter()
|
||||
-> UserFlagInfo*
|
||||
{
|
||||
return reinterpret_cast<UserFlagInfo*>(data);
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetUserFlagIter() const
|
||||
-> const UserFlagInfo*
|
||||
{
|
||||
return reinterpret_cast<const UserFlagInfo*>(data);
|
||||
}
|
||||
|
||||
std::uint32_t ObjectTypeInfo::GetTotalNumVariables() const
|
||||
{
|
||||
auto numVars = GetNumVariables();
|
||||
for (auto iter = GetParent(); iter; iter = iter->GetParent()) {
|
||||
numVars += iter->GetNumVariables();
|
||||
}
|
||||
return numVars;
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetVariableIter()
|
||||
-> VariableInfo*
|
||||
{
|
||||
return reinterpret_cast<VariableInfo*>(GetUserFlagIter() + GetNumUserFlags());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetVariableIter() const
|
||||
-> const VariableInfo*
|
||||
{
|
||||
return reinterpret_cast<const VariableInfo*>(GetUserFlagIter() + GetNumUserFlags());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetInitialValueIter()
|
||||
-> InitialValueInfo*
|
||||
{
|
||||
return reinterpret_cast<InitialValueInfo*>(GetVariableIter() + GetNumVariables());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetInitialValueIter() const
|
||||
-> const InitialValueInfo*
|
||||
{
|
||||
return reinterpret_cast<const InitialValueInfo*>(GetVariableIter() + GetNumVariables());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetPropertyIter()
|
||||
-> PropertyInfo*
|
||||
{
|
||||
return reinterpret_cast<PropertyInfo*>(GetInitialValueIter() + GetNumInitalValues());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetPropertyIter() const
|
||||
-> const PropertyInfo*
|
||||
{
|
||||
return reinterpret_cast<const PropertyInfo*>(GetInitialValueIter() + GetNumInitalValues());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetGlobalFuncIter()
|
||||
-> GlobalFuncInfo*
|
||||
{
|
||||
return reinterpret_cast<GlobalFuncInfo*>(GetPropertyIter() + GetNumProperties());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetGlobalFuncIter() const
|
||||
-> const GlobalFuncInfo*
|
||||
{
|
||||
return reinterpret_cast<const GlobalFuncInfo*>(GetPropertyIter() + GetNumProperties());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetMemberFuncIter()
|
||||
-> MemberFuncInfo*
|
||||
{
|
||||
return reinterpret_cast<MemberFuncInfo*>(GetGlobalFuncIter() + GetNumGlobalFuncs());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetMemberFuncIter() const
|
||||
-> const MemberFuncInfo*
|
||||
{
|
||||
return reinterpret_cast<const MemberFuncInfo*>(GetGlobalFuncIter() + GetNumGlobalFuncs());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetNamedStateIter()
|
||||
-> NamedStateInfo*
|
||||
{
|
||||
return reinterpret_cast<NamedStateInfo*>(GetMemberFuncIter() + GetNumMemberFuncs());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetNamedStateIter() const
|
||||
-> const NamedStateInfo*
|
||||
{
|
||||
return reinterpret_cast<const NamedStateInfo*>(GetMemberFuncIter() + GetNumMemberFuncs());
|
||||
}
|
||||
|
||||
std::uint32_t ObjectTypeInfo::GetPropertyIndex(const BSFixedString& a_name) const
|
||||
{
|
||||
const auto props = GetPropertyIter();
|
||||
if (props) {
|
||||
for (std::uint32_t i = 0; i < GetNumProperties(); ++i) {
|
||||
const auto& prop = props[i];
|
||||
if (prop.name == a_name) {
|
||||
return prop.info.autoVarIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
return static_cast<std::uint32_t>(-1);
|
||||
}
|
||||
|
||||
constexpr bool ObjectTypeInfo::HasPropertyGroups() const
|
||||
{
|
||||
return propertyGroups.size();
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetInitialState() const -> const BSFixedString*
|
||||
{
|
||||
BSFixedString thing = "hello";
|
||||
return reinterpret_cast<const BSFixedString*>(GetNamedStateIter() + GetNumNamedStates());
|
||||
}
|
||||
|
||||
void ObjectTypeInfo::dtor()
|
||||
{
|
||||
using func_t = decltype(&ObjectTypeInfo::dtor);
|
||||
REL::Relocation<func_t> func{ ID::BSScript_ObjectTypeInfo::dtor };
|
||||
return func(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "RE/B/BSScript_PackedInstructionStream.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
namespace ByteCode
|
||||
{
|
||||
PackedInstructionStream::PackedInstructionStream() :
|
||||
numInstructionBits(0),
|
||||
jumpTargetBitCount(0),
|
||||
localVariableBitCount(0),
|
||||
memberVariableBitCount(0),
|
||||
instructions(nullptr)
|
||||
{}
|
||||
|
||||
PackedInstructionStream::PackedInstructionStream(
|
||||
void* a_instructions,
|
||||
std::uint32_t a_numInstrBits,
|
||||
std::uint16_t a_jumpTargetBitCount,
|
||||
std::int8_t a_localVariableBitCount,
|
||||
std::int8_t a_memberVariableBitCount) :
|
||||
numInstructionBits(a_numInstrBits),
|
||||
jumpTargetBitCount(a_jumpTargetBitCount),
|
||||
localVariableBitCount(a_localVariableBitCount),
|
||||
memberVariableBitCount(a_memberVariableBitCount),
|
||||
instructions(a_instructions)
|
||||
{}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "RE/B/BSScript_StackFrame.h"
|
||||
|
||||
#include "RE/B/BSScript_Internal_Stack.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
std::uint32_t StackFrame::GetPageForFrame() const
|
||||
{
|
||||
return parent->GetPageForFrame(this);
|
||||
}
|
||||
|
||||
Variable& StackFrame::GetStackFrameVariable(std::uint32_t a_index, std::uint32_t a_pageHint) const
|
||||
{
|
||||
return parent->GetStackFrameVariable(this, a_index, a_pageHint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "RE/B/BSScript_Struct.h"
|
||||
|
||||
namespace RE::BSScript
|
||||
{
|
||||
Struct::~Struct()
|
||||
{
|
||||
if (constructed) {
|
||||
const std::uint32_t size = type ? type->variables.size() : 0;
|
||||
for (std::uint32_t i = 0; i < size; ++i) {
|
||||
variables[i].reset();
|
||||
}
|
||||
|
||||
constructed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "RE/B/BSScript_StructTypeInfo.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
TypeInfo::RawType StructTypeInfo::GetRawType() const
|
||||
{
|
||||
return TypeInfo::RawType::kStruct;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "RE/B/BSScript_TypeInfo.h"
|
||||
|
||||
#include "RE/B/BSScript_IComplexType.h"
|
||||
|
||||
namespace RE::BSScript
|
||||
{
|
||||
auto TypeInfo::GetRawType() const
|
||||
-> RawType
|
||||
{
|
||||
if (IsComplex()) {
|
||||
const auto complex =
|
||||
reinterpret_cast<IComplexType*>(
|
||||
reinterpret_cast<std::uintptr_t>(data.complexTypeInfo) &
|
||||
~static_cast<std::uintptr_t>(1));
|
||||
uint32_t rtype = (uint32_t)complex->GetRawType();
|
||||
if (IsArray()) {
|
||||
rtype += 10;
|
||||
}
|
||||
return (RawType)rtype;
|
||||
} else {
|
||||
return *data.rawType;
|
||||
}
|
||||
}
|
||||
|
||||
IComplexType* TypeInfo::GetComplexType() const
|
||||
{
|
||||
return IsComplex() ? reinterpret_cast<IComplexType*>(
|
||||
reinterpret_cast<std::uintptr_t>(data.complexTypeInfo) &
|
||||
~static_cast<std::uintptr_t>(1)) :
|
||||
nullptr;
|
||||
}
|
||||
|
||||
ObjectTypeInfo* TypeInfo::GetObjectTypeInfo() const
|
||||
{
|
||||
return IsObject() || IsObjectArray() ? reinterpret_cast<ObjectTypeInfo*>(GetComplexType()) : nullptr;
|
||||
}
|
||||
|
||||
StructTypeInfo* TypeInfo::GetStructTypeInfo() const
|
||||
{
|
||||
return IsStruct() || IsStructArray() ? reinterpret_cast<StructTypeInfo*>(GetComplexType()) : nullptr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
#include "RE/B/BSScript_Variable.h"
|
||||
|
||||
#include "RE/B/BSScript_Array.h"
|
||||
#include "RE/B/BSScript_Object.h"
|
||||
#include "RE/B/BSScript_Struct.h"
|
||||
|
||||
namespace RE::BSScript
|
||||
{
|
||||
Variable& Variable::operator=(BSTSmartPointer<Object> a_object)
|
||||
{
|
||||
reset();
|
||||
if (a_object) {
|
||||
value.o = std::move(a_object);
|
||||
varType = value.o->type.get();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
assert(is<Object>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Variable& Variable::operator=(BSTSmartPointer<Struct> a_struct)
|
||||
{
|
||||
reset();
|
||||
if (a_struct) {
|
||||
value.t = std::move(a_struct);
|
||||
varType = value.t->type.get();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
assert(is<Struct>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Variable& Variable::operator=(BSTSmartPointer<Array> a_array)
|
||||
{
|
||||
reset();
|
||||
if (a_array) {
|
||||
value.a = std::move(a_array);
|
||||
varType = value.a->elementType;
|
||||
varType.SetArray(true);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
assert(is<Array>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Variable::reset()
|
||||
{
|
||||
switch (varType.GetRawType()) {
|
||||
case RawType::kObject:
|
||||
value.o.reset();
|
||||
break;
|
||||
case RawType::kString:
|
||||
value.s.~BSFixedString();
|
||||
break;
|
||||
case RawType::kVar:
|
||||
delete value.v;
|
||||
break;
|
||||
case RawType::kStruct:
|
||||
value.t.reset();
|
||||
break;
|
||||
case RawType::kArrayObject:
|
||||
case RawType::kArrayString:
|
||||
case RawType::kArrayInt:
|
||||
case RawType::kArrayFloat:
|
||||
case RawType::kArrayBool:
|
||||
case RawType::kArrayVar:
|
||||
case RawType::kArrayStruct:
|
||||
value.a.reset();
|
||||
break;
|
||||
case RawType::kNone:
|
||||
case RawType::kInt:
|
||||
case RawType::kFloat:
|
||||
case RawType::kBool:
|
||||
break;
|
||||
default:
|
||||
assert(false); // unhandled type
|
||||
break;
|
||||
}
|
||||
|
||||
varType = RawType::kNone;
|
||||
value.v = nullptr;
|
||||
assert(is<std::nullptr_t>());
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(misc-no-recursion)
|
||||
void Variable::copy(const Variable& a_rhs)
|
||||
{
|
||||
assert(varType.GetRawType() == RawType::kNone);
|
||||
assert(value.v == nullptr);
|
||||
|
||||
switch (a_rhs.varType.GetRawType()) {
|
||||
case RawType::kObject:
|
||||
value.o = a_rhs.value.o;
|
||||
break;
|
||||
case RawType::kString:
|
||||
value.s = a_rhs.value.s;
|
||||
break;
|
||||
case RawType::kVar:
|
||||
if (a_rhs.value.v) {
|
||||
value.v = new Variable(*a_rhs.value.v);
|
||||
}
|
||||
break;
|
||||
case RawType::kStruct:
|
||||
value.t = a_rhs.value.t;
|
||||
break;
|
||||
case RawType::kArrayObject:
|
||||
case RawType::kArrayString:
|
||||
case RawType::kArrayInt:
|
||||
case RawType::kArrayFloat:
|
||||
case RawType::kArrayBool:
|
||||
case RawType::kArrayVar:
|
||||
case RawType::kArrayStruct:
|
||||
value.a = a_rhs.value.a;
|
||||
break;
|
||||
case RawType::kNone:
|
||||
break;
|
||||
case RawType::kInt:
|
||||
value.u = a_rhs.value.u;
|
||||
break;
|
||||
case RawType::kFloat:
|
||||
value.f = a_rhs.value.f;
|
||||
break;
|
||||
case RawType::kBool:
|
||||
value.b = a_rhs.value.b;
|
||||
break;
|
||||
default:
|
||||
assert(false); // unhandled type
|
||||
break;
|
||||
}
|
||||
|
||||
varType = a_rhs.varType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "RE/B/BSSpinLock.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSAutoLockReadLockPolicy<BSReadWriteLock>;
|
||||
static_assert(std::is_empty_v<BSAutoLockReadLockPolicy<BSReadWriteLock>>);
|
||||
|
||||
template class BSAutoLockWriteLockPolicy<BSReadWriteLock>;
|
||||
static_assert(std::is_empty_v<BSAutoLockWriteLockPolicy<BSReadWriteLock>>);
|
||||
|
||||
template class BSAutoLockDefaultPolicy<BSSpinLock>;
|
||||
static_assert(std::is_empty_v<BSAutoLockDefaultPolicy<BSSpinLock>>);
|
||||
|
||||
template class BSAutoLock<BSReadWriteLock, BSAutoLockReadLockPolicy>;
|
||||
static_assert(sizeof(BSAutoLock<BSReadWriteLock, BSAutoLockReadLockPolicy>) == 0x8);
|
||||
|
||||
template class BSAutoLock<BSReadWriteLock, BSAutoLockWriteLockPolicy>;
|
||||
static_assert(sizeof(BSAutoLock<BSReadWriteLock, BSAutoLockWriteLockPolicy>) == 0x8);
|
||||
|
||||
template class BSAutoLock<BSSpinLock, BSAutoLockDefaultPolicy>;
|
||||
static_assert(sizeof(BSAutoLock<BSSpinLock, BSAutoLockDefaultPolicy>) == 0x8);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "RE/B/BSSpring_SpringState.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSSpring
|
||||
{
|
||||
template class SpringState<float>;
|
||||
static_assert(sizeof(SpringState<float>) == 0xC);
|
||||
|
||||
template class SpringState<NiPoint2>;
|
||||
static_assert(sizeof(SpringState<NiPoint2>) == 0x14);
|
||||
|
||||
template class SpringState<NiPoint3>;
|
||||
static_assert(sizeof(SpringState<NiPoint3>) == 0x1C);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/B/BSTArray.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSTAlignedHeapArrayAllocator<0x10>::Allocator;
|
||||
static_assert(sizeof(BSTAlignedHeapArrayAllocator<0x10>::Allocator) == 0x10);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "RE/B/BSTAtomicValue.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSTAtomicValue<std::int32_t>;
|
||||
static_assert(sizeof(BSTAtomicValue<std::int32_t>) == 0x4);
|
||||
|
||||
template class BSTAtomicValue<std::uint32_t>;
|
||||
static_assert(sizeof(BSTAtomicValue<std::uint32_t>) == 0x4);
|
||||
|
||||
template class BSTAtomicValue<std::int64_t>;
|
||||
static_assert(sizeof(BSTAtomicValue<std::int64_t>) == 0x8);
|
||||
|
||||
template class BSTAtomicValue<std::uint64_t>;
|
||||
static_assert(sizeof(BSTAtomicValue<std::uint64_t>) == 0x8);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "RE/B/BSTDataBuffer.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSTDataBuffer<1>;
|
||||
static_assert(sizeof(BSTDataBuffer<1>) == 0x10);
|
||||
|
||||
template class BSTDataBuffer<2>;
|
||||
static_assert(sizeof(BSTDataBuffer<2>) == 0x10);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/B/BSTInterpolator.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSTInterpolator<float, EaseOutInterpolator, GetCurrentPositionFunctor>;
|
||||
static_assert(sizeof(BSTInterpolator<float, EaseOutInterpolator, GetCurrentPositionFunctor>) == 0x18);
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
#include "RE/B/BSTPoint.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSTPoint2<std::int8_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::int8_t>) == 0x2);
|
||||
|
||||
template class BSTPoint2<std::uint8_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::uint8_t>) == 0x2);
|
||||
|
||||
template class BSTPoint2<std::int16_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::int16_t>) == 0x4);
|
||||
|
||||
template class BSTPoint2<std::uint16_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::uint16_t>) == 0x4);
|
||||
|
||||
template class BSTPoint2<std::int32_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::int32_t>) == 0x8);
|
||||
|
||||
template class BSTPoint2<std::uint32_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::uint32_t>) == 0x8);
|
||||
|
||||
template class BSTPoint2<float>;
|
||||
static_assert(sizeof(BSTPoint2<float>) == 0x8);
|
||||
|
||||
template class BSTPoint2<double>;
|
||||
static_assert(sizeof(BSTPoint2<double>) == 0x10);
|
||||
|
||||
template class BSTPoint2Base<std::int8_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::int8_t>) == 0x2);
|
||||
|
||||
template class BSTPoint2Base<std::uint8_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::uint8_t>) == 0x2);
|
||||
|
||||
template class BSTPoint2Base<std::int16_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::int16_t>) == 0x4);
|
||||
|
||||
template class BSTPoint2Base<std::uint16_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::uint16_t>) == 0x4);
|
||||
|
||||
template class BSTPoint2Base<std::int32_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::int32_t>) == 0x8);
|
||||
|
||||
template class BSTPoint2Base<std::uint32_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::uint32_t>) == 0x8);
|
||||
|
||||
template class BSTPoint2Base<float>;
|
||||
static_assert(sizeof(BSTPoint2Base<float>) == 0x8);
|
||||
|
||||
template class BSTPoint2Base<double>;
|
||||
static_assert(sizeof(BSTPoint2Base<double>) == 0x10);
|
||||
|
||||
template class BSTPoint3<std::int8_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::int8_t>) == 0x3);
|
||||
|
||||
template class BSTPoint3<std::uint8_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::uint8_t>) == 0x3);
|
||||
|
||||
template class BSTPoint3<std::int16_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::int16_t>) == 0x6);
|
||||
|
||||
template class BSTPoint3<std::uint16_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::uint16_t>) == 0x6);
|
||||
|
||||
template class BSTPoint3<std::int32_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::int32_t>) == 0xC);
|
||||
|
||||
template class BSTPoint3<std::uint32_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::uint32_t>) == 0xC);
|
||||
|
||||
template class BSTPoint3<float>;
|
||||
static_assert(sizeof(BSTPoint3<float>) == 0xC);
|
||||
|
||||
template class BSTPoint3<double>;
|
||||
static_assert(sizeof(BSTPoint3<double>) == 0x18);
|
||||
|
||||
template class BSTPoint3Base<std::int8_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::int8_t>) == 0x3);
|
||||
|
||||
template class BSTPoint3Base<std::uint8_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::uint8_t>) == 0x3);
|
||||
|
||||
template class BSTPoint3Base<std::int16_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::int16_t>) == 0x6);
|
||||
|
||||
template class BSTPoint3Base<std::uint16_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::uint16_t>) == 0x6);
|
||||
|
||||
template class BSTPoint3Base<std::int32_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::int32_t>) == 0xC);
|
||||
|
||||
template class BSTPoint3Base<std::uint32_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::uint32_t>) == 0xC);
|
||||
|
||||
template class BSTPoint3Base<float>;
|
||||
static_assert(sizeof(BSTPoint3Base<float>) == 0xC);
|
||||
|
||||
template class BSTPoint3Base<double>;
|
||||
static_assert(sizeof(BSTPoint3Base<double>) == 0x18);
|
||||
|
||||
template class BSTPointDefaultOps<std::int8_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::int8_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<std::uint8_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::uint8_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<std::int16_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::int16_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<std::uint16_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::uint16_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<std::int32_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::int32_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<std::uint32_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::uint32_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<float>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<float>>);
|
||||
|
||||
template class BSTPointDefaultOps<double>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<double>>);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "RE/B/BSVisit.h"
|
||||
|
||||
#include "RE/N/NiAVObject.h"
|
||||
#include "RE/N/NiNode.h"
|
||||
|
||||
namespace RE::BSVisit
|
||||
{
|
||||
BSVisitControl TraverseScenegraphGeometries(NiAVObject* a_object, std::function<BSVisitControl(BSGeometry*)> a_func)
|
||||
{
|
||||
if (a_object) {
|
||||
if (auto geom = a_object->IsGeometry())
|
||||
return a_func(geom);
|
||||
|
||||
if (const auto node = a_object->IsNode()) {
|
||||
for (const auto& child : node->children) {
|
||||
if (TraverseScenegraphGeometries(child.get(), a_func) == BSVisitControl::kStop) {
|
||||
return BSVisitControl::kStop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BSVisitControl::kContinue;
|
||||
}
|
||||
|
||||
BSVisitControl TraverseScenegraphObjects(NiAVObject* a_object, std::function<BSVisitControl(NiAVObject*)> a_func)
|
||||
{
|
||||
if (a_object) {
|
||||
if (a_func(a_object) == BSVisitControl::kStop)
|
||||
return BSVisitControl::kStop;
|
||||
|
||||
if (const auto node = a_object->IsNode()) {
|
||||
for (const auto& child : node->children) {
|
||||
if (TraverseScenegraphObjects(child.get(), a_func) == BSVisitControl::kStop) {
|
||||
return BSVisitControl::kStop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BSVisitControl::kContinue;
|
||||
}
|
||||
|
||||
BSVisitControl TraverseScenegraphCollision(const NiAVObject* a_object, std::function<BSVisitControl(bhkNPCollisionObject*)> a_func)
|
||||
{
|
||||
if (a_object) {
|
||||
if (const auto collision = a_object->GetCollisionObject()) {
|
||||
if (const auto collisionNP = collision->IsbhkNPCollisionObject()) {
|
||||
if (a_func(collisionNP) == BSVisitControl::kStop) {
|
||||
return BSVisitControl::kStop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto node = a_object->IsNode()) {
|
||||
for (const auto& child : node->children) {
|
||||
if (TraverseScenegraphCollision(child.get(), a_func) == BSVisitControl::kStop) {
|
||||
return BSVisitControl::kStop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BSVisitControl::kContinue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/B/ButtonEvent.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template ButtonEvent* InputEvent::As() noexcept;
|
||||
template const ButtonEvent* InputEvent::As() const noexcept;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "RE/C/Calendar.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
float Calendar::GetHoursPassed() const noexcept
|
||||
{
|
||||
const auto days = gameDaysPassed ? gameDaysPassed->GetValue() : 1.0F;
|
||||
return days * 24.0F;
|
||||
}
|
||||
|
||||
std::uint32_t Calendar::GetMonth() const noexcept
|
||||
{
|
||||
return gameMonth ? static_cast<std::uint32_t>(gameMonth->value) : 8;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/C/CharacterEvent.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template CharacterEvent* InputEvent::As() noexcept;
|
||||
template const CharacterEvent* InputEvent::As() const noexcept;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/C/CursorMoveEvent.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template CursorMoveEvent* InputEvent::As() noexcept;
|
||||
template const CursorMoveEvent* InputEvent::As() const noexcept;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/D/DeviceConnectEvent.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template DeviceConnectEvent* InputEvent::As() noexcept;
|
||||
template const DeviceConnectEvent* InputEvent::As() const noexcept;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "RE/E/ExtraInstanceData.h"
|
||||
|
||||
#include "RE/T/TBO_InstanceData.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
ExtraInstanceData::ExtraInstanceData() :
|
||||
ExtraInstanceData(nullptr, nullptr)
|
||||
{}
|
||||
|
||||
ExtraInstanceData::ExtraInstanceData(const TESBoundObject* a_base, BSTSmartPointer<TBO_InstanceData> a_data) :
|
||||
BSExtraData(TYPE),
|
||||
base(a_base),
|
||||
data(std::move(a_data))
|
||||
{
|
||||
REX::EMPLACE_VTABLE(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#include "RE/Fallout.h"
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/G/GetCurrentPositionFunctor.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class GetCurrentPositionFunctor<float>;
|
||||
static_assert(std::is_empty_v<GetCurrentPositionFunctor<float>>);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "RE/H/hkVector4.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
hkVector4f hkVector4f::GetNormalized() const
|
||||
{
|
||||
hkVector4f norm = *this;
|
||||
norm.Normalize();
|
||||
return norm;
|
||||
}
|
||||
|
||||
float hkVector4f::Length() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
hkVector4f& hkVector4f::Normalize()
|
||||
{
|
||||
float l = Length();
|
||||
if (l == 0) {
|
||||
this->x = 0;
|
||||
this->y = 0;
|
||||
this->z = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
this->x /= l;
|
||||
this->y /= l;
|
||||
this->z /= l;
|
||||
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/I/IDEvent.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template IDEvent* InputEvent::As<IDEvent>();
|
||||
template const IDEvent* InputEvent::As<IDEvent>() const;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "RE/I/InventoryInterface.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
std::uint32_t BSCRC32<InventoryInterface::Handle>::operator()(InventoryInterface::Handle a_data) const noexcept
|
||||
{
|
||||
return BSCRC32<std::uint32_t>()(a_data.id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/K/KinectEvent.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template KinectEvent* InputEvent::As() noexcept;
|
||||
template const KinectEvent* InputEvent::As() const noexcept;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "RE/M/MenuCursor.h"
|
||||
|
||||
#include "RE/S/Setting.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void MenuCursor::ConstrainForPipboy()
|
||||
{
|
||||
static REL::Relocation<Setting*> TLX{ ID::MenuCursor::PipboyConstraintTLX };
|
||||
static REL::Relocation<Setting*> TLY{ ID::MenuCursor::PipboyConstraintTLY };
|
||||
static REL::Relocation<Setting*> Width{ ID::MenuCursor::PipboyConstraintWidth };
|
||||
static REL::Relocation<Setting*> Height{ ID::MenuCursor::PipboyConstraintHeight };
|
||||
SetCursorConstraintsRaw(TLX->GetUInt(), TLY->GetUInt(), Width->GetUInt(), Height->GetUInt());
|
||||
}
|
||||
|
||||
void MenuCursor::ConstrainForPipboyPA()
|
||||
{
|
||||
static REL::Relocation<Setting*> TLX{ ID::MenuCursor::PipboyConstraintTLX_PowerArmor };
|
||||
static REL::Relocation<Setting*> TLY{ ID::MenuCursor::PipboyConstraintTLY_PowerArmor };
|
||||
static REL::Relocation<Setting*> Width{ ID::MenuCursor::PipboyConstraintWidth_PowerArmor };
|
||||
static REL::Relocation<Setting*> Height{ ID::MenuCursor::PipboyConstraintHeight_PowerArmor };
|
||||
SetCursorConstraintsRaw(TLX->GetUInt(), TLY->GetUInt(), Width->GetUInt(), Height->GetUInt());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/M/MouseMoveEvent.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template MouseMoveEvent* InputEvent::As() noexcept;
|
||||
template const MouseMoveEvent* InputEvent::As() const noexcept;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "RE/N/NiAVObject.h"
|
||||
|
||||
#include "RE/B/BSGeometry.h"
|
||||
#include "RE/B/BSVisit.h"
|
||||
#include "RE/N/NiNode.h"
|
||||
#include "RE/N/NiUpdateData.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
NiAVObject::NiAVObject()
|
||||
{
|
||||
REX::EMPLACE_VTABLE(this);
|
||||
local.MakeIdentity();
|
||||
world.MakeIdentity();
|
||||
previousWorld.MakeIdentity();
|
||||
flags.flags = 0xE;
|
||||
}
|
||||
|
||||
NiAVObject::~NiAVObject() {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
void NiAVObject::CullGeometry(bool a_cull)
|
||||
{
|
||||
BSVisit::TraverseScenegraphGeometries(this, [&](BSGeometry* a_geo) -> BSVisitControl {
|
||||
a_geo->SetAppCulled(a_cull);
|
||||
return BSVisitControl::kContinue;
|
||||
});
|
||||
}
|
||||
|
||||
void NiAVObject::CullNode(bool a_cull)
|
||||
{
|
||||
BSVisit::TraverseScenegraphObjects(this, [&](NiAVObject* a_object) -> BSVisitControl {
|
||||
a_object->SetAppCulled(a_cull);
|
||||
return BSVisitControl::kContinue;
|
||||
});
|
||||
}
|
||||
|
||||
void NiAVObject::Update(NiUpdateData& a_data)
|
||||
{
|
||||
UpdateDownwardPass(a_data, 0);
|
||||
if (parent && ((a_data.flags & 0x200) == 0)) {
|
||||
parent->UpdateUpwardPass(a_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "RE/N/NiBinaryStream.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void NiBinaryStream::GetBufferInfo(BufferInfo& a_buf)
|
||||
{
|
||||
a_buf.buffer = nullptr;
|
||||
a_buf.pos = 0;
|
||||
a_buf.bufferAllocSize = 0;
|
||||
a_buf.fileSize = 0;
|
||||
a_buf.bufferReadSize = 0;
|
||||
a_buf.absCurrentPos = 0;
|
||||
}
|
||||
|
||||
std::size_t NiBinaryStream::binary_read(void* a_buffer, std::size_t a_totalBytes)
|
||||
{
|
||||
std::size_t bytesRead = DoRead(a_buffer, a_totalBytes);
|
||||
absoluteCurrentPos += bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
std::size_t NiBinaryStream::binary_write(const void* a_buffer, std::size_t a_totalBytes)
|
||||
{
|
||||
std::size_t bytesWritten = DoWrite(a_buffer, a_totalBytes);
|
||||
absoluteCurrentPos += bytesWritten;
|
||||
return bytesWritten;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "RE/N/NiExtraData.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
NiExtraData::NiExtraData()
|
||||
{
|
||||
REX::EMPLACE_VTABLE(this);
|
||||
}
|
||||
|
||||
NiExtraData::NiExtraData(const BSFixedString& a_name) :
|
||||
name(a_name)
|
||||
{
|
||||
REX::EMPLACE_VTABLE(this);
|
||||
}
|
||||
|
||||
NiExtraData::~NiExtraData() = default;
|
||||
|
||||
const BSFixedString& NiExtraData::GetName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
void NiExtraData::SetName(const BSFixedString& a_name)
|
||||
{
|
||||
name = a_name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "RE/N/NiExtraDataContainer.h"
|
||||
|
||||
#include "RE/N/NiExtraData.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
NiExtraDataContainer::NiExtraDataContainer(const std::uint32_t a_count) :
|
||||
extra(a_count)
|
||||
{}
|
||||
|
||||
void NiExtraDataContainer::Add(NiExtraData* a_extra)
|
||||
{
|
||||
const BSAutoWriteLock l(lock);
|
||||
extra.push_back(a_extra);
|
||||
}
|
||||
|
||||
NiExtraData* NiExtraDataContainer::FindExtra(const BSFixedString& a_key) const
|
||||
{
|
||||
const BSAutoReadLock l(lock);
|
||||
for (auto& entry : extra)
|
||||
if (entry->GetName() == a_key)
|
||||
return entry.get();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::int32_t NiExtraDataContainer::FindIndex(const BSFixedString& a_key) const
|
||||
{
|
||||
const BSAutoReadLock l(lock);
|
||||
for (auto i = 0u; i < extra.size(); i++)
|
||||
if (extra[i]->GetName() == a_key)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::uint32_t NiExtraDataContainer::GetSize() const
|
||||
{
|
||||
const BSAutoReadLock l(lock);
|
||||
return extra.size();
|
||||
}
|
||||
|
||||
bool NiExtraDataContainer::RemoveExtra(const BSFixedString& a_key)
|
||||
{
|
||||
const BSAutoWriteLock l(lock);
|
||||
|
||||
const auto it = std::find_if(extra.begin(), extra.end(), [&](auto& entry) {
|
||||
return entry->GetName() == a_key;
|
||||
});
|
||||
|
||||
if (it != extra.end()) {
|
||||
extra.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "RE/N/NiMatrix3.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
bool NiMatrix3::ToEulerAnglesXYZ(NiPoint3& a_point) const
|
||||
{
|
||||
return ToEulerAnglesXYZ(a_point.x, a_point.y, a_point.z);
|
||||
}
|
||||
|
||||
bool NiMatrix3::ToEulerAnglesXYZ(float& a_x, float& a_y, float& a_z) const
|
||||
{
|
||||
using func_t = bool (*)(const NiMatrix3*, float&, float&, float&);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::ToEulerAnglesXYZ };
|
||||
return func(this, a_x, a_y, a_z);
|
||||
}
|
||||
|
||||
bool NiMatrix3::ToEulerAnglesXZY(float& a_x, float& a_z, float& a_y) const
|
||||
{
|
||||
using func_t = bool (*)(const NiMatrix3*, float&, float&, float&);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::ToEulerAnglesXZY };
|
||||
return func(this, a_x, a_z, a_y);
|
||||
}
|
||||
|
||||
bool NiMatrix3::ToEulerAnglesYXZ(float& a_y, float& a_x, float& a_z) const
|
||||
{
|
||||
using func_t = bool (*)(const NiMatrix3*, float&, float&, float&);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::ToEulerAnglesYXZ };
|
||||
return func(this, a_y, a_x, a_z);
|
||||
}
|
||||
|
||||
bool NiMatrix3::ToEulerAnglesYZX(float& a_y, float& a_z, float& a_x) const
|
||||
{
|
||||
using func_t = bool (*)(const NiMatrix3*, float&, float&, float&);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::ToEulerAnglesYZX };
|
||||
return func(this, a_y, a_z, a_x);
|
||||
}
|
||||
|
||||
bool NiMatrix3::ToEulerAnglesZYX(float& a_z, float& a_y, float& a_x) const
|
||||
{
|
||||
using func_t = bool (*)(const NiMatrix3*, float&, float&, float&);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::ToEulerAnglesZYX };
|
||||
return func(this, a_z, a_y, a_x);
|
||||
}
|
||||
|
||||
bool NiMatrix3::ToEulerAnglesZXY(float& a_z, float& a_x, float& a_y) const
|
||||
{
|
||||
using func_t = bool (*)(const NiMatrix3*, float&, float&, float&);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::ToEulerAnglesZXY };
|
||||
return func(this, a_z, a_x, a_y);
|
||||
}
|
||||
|
||||
void NiMatrix3::FromEulerAnglesXYZ(const NiPoint3& a_point)
|
||||
{
|
||||
FromEulerAnglesXYZ(a_point.x, a_point.y, a_point.z);
|
||||
}
|
||||
|
||||
void NiMatrix3::FromEulerAnglesXYZ(float a_x, float a_y, float a_z)
|
||||
{
|
||||
using func_t = void (*)(NiMatrix3*, float, float, float);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::FromEulerAnglesXYZ };
|
||||
return func(this, a_x, a_y, a_z);
|
||||
}
|
||||
|
||||
void NiMatrix3::FromEulerAnglesXZY(float a_x, float a_z, float a_y)
|
||||
{
|
||||
using func_t = void (*)(NiMatrix3*, float, float, float);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::FromEulerAnglesXZY };
|
||||
return func(this, a_x, a_z, a_y);
|
||||
}
|
||||
|
||||
void NiMatrix3::FromEulerAnglesYXZ(float a_y, float a_x, float a_z)
|
||||
{
|
||||
using func_t = void (*)(NiMatrix3*, float, float, float);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::FromEulerAnglesYXZ };
|
||||
return func(this, a_y, a_x, a_z);
|
||||
}
|
||||
|
||||
void NiMatrix3::FromEulerAnglesYZX(float a_y, float a_z, float a_x)
|
||||
{
|
||||
using func_t = void (*)(NiMatrix3*, float, float, float);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::FromEulerAnglesYZX };
|
||||
return func(this, a_y, a_z, a_x);
|
||||
}
|
||||
|
||||
void NiMatrix3::FromEulerAnglesZYX(float a_z, float a_y, float a_x)
|
||||
{
|
||||
using func_t = void (*)(NiMatrix3*, float, float, float);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::FromEulerAnglesZYX };
|
||||
return func(this, a_z, a_y, a_x);
|
||||
}
|
||||
|
||||
void NiMatrix3::FromEulerAnglesZXY(float a_z, float a_x, float a_y)
|
||||
{
|
||||
using func_t = void (*)(NiMatrix3*, float, float, float);
|
||||
static REL::Relocation<func_t> func{ ID::NiMatrix3::FromEulerAnglesZXY };
|
||||
return func(this, a_z, a_x, a_y);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "RE/N/NiObjectNET.h"
|
||||
|
||||
#include "RE/N/NiExtraData.h"
|
||||
#include "RE/N/NiRTTI.h"
|
||||
#include "RE/N/NiTimeController.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
NiObjectNET::NiObjectNET()
|
||||
{
|
||||
REX::EMPLACE_VTABLE(this);
|
||||
}
|
||||
|
||||
NiObjectNET::~NiObjectNET() = default;
|
||||
|
||||
bool NiObjectNET::AddExtraData(const BSFixedString& a_key, NiExtraData* a_extra)
|
||||
{
|
||||
if (a_key.empty())
|
||||
return false;
|
||||
|
||||
if (!a_extra)
|
||||
return false;
|
||||
|
||||
if (!a_extra->GetName().empty())
|
||||
a_extra->SetName(a_key);
|
||||
else if (a_key != a_extra->GetName())
|
||||
return false;
|
||||
|
||||
return InsertExtraData(a_extra);
|
||||
}
|
||||
|
||||
bool NiObjectNET::AddExtraData(NiExtraData* a_extra)
|
||||
{
|
||||
if (!a_extra)
|
||||
return false;
|
||||
|
||||
const auto& extraName = a_extra->GetName();
|
||||
if (extraName.empty()) {
|
||||
// TODO: Game handles nameless ExtraData by using the rtti name and a suffix?
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return InsertExtraData(a_extra);
|
||||
}
|
||||
|
||||
NiExtraData* NiObjectNET::GetExtraData(const BSFixedString& a_key) const
|
||||
{
|
||||
return extra ? extra->FindExtra(a_key) : nullptr;
|
||||
}
|
||||
|
||||
std::uint16_t NiObjectNET::GetExtraDataSize() const
|
||||
{
|
||||
return extra ? static_cast<std::uint16_t>(extra->GetSize()) : 0;
|
||||
}
|
||||
|
||||
bool NiObjectNET::HasExtraData(const BSFixedString& a_key) const
|
||||
{
|
||||
return extra ? extra->FindExtra(a_key) : false;
|
||||
}
|
||||
|
||||
bool NiObjectNET::InsertExtraData(NiExtraData* a_extra)
|
||||
{
|
||||
if (extra) {
|
||||
extra->Add(a_extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NiObjectNET::RemoveExtraData(const BSFixedString& a_key)
|
||||
{
|
||||
if (a_key.empty())
|
||||
return false;
|
||||
|
||||
return extra && extra->RemoveExtra(a_key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "RE/N/NiPoint3.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
float NiPoint3::GetDistance(const NiPoint3& a_point) const noexcept
|
||||
{
|
||||
// std math functions are not constexpr yet
|
||||
return std::sqrtf(GetSquaredDistance(a_point));
|
||||
}
|
||||
|
||||
float NiPoint3::GetZAngleFromVector() const
|
||||
{
|
||||
using func_t = decltype(&NiPoint3::GetZAngleFromVector);
|
||||
static REL::Relocation<func_t> func{ ID::NiPoint3::GetZAngleFromVector };
|
||||
return func(this);
|
||||
}
|
||||
|
||||
float NiPoint3::Length() const noexcept
|
||||
{
|
||||
return std::sqrtf(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
NiPoint3 NiPoint3::UnitCross(const NiPoint3& a_point) const noexcept
|
||||
{
|
||||
auto cross = Cross(a_point);
|
||||
cross.Unitize();
|
||||
return cross;
|
||||
}
|
||||
|
||||
float NiPoint3::Unitize() noexcept
|
||||
{
|
||||
auto length = Length();
|
||||
if (length == 1.f) {
|
||||
return length;
|
||||
} else if (length > FLT_EPSILON) {
|
||||
operator/=(length);
|
||||
} else {
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
z = 0.0;
|
||||
length = 0.0;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "RE/N/NiRect.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class NiRect<float>;
|
||||
static_assert(sizeof(NiRect<float>) == 0x10);
|
||||
|
||||
template class NiRect<std::int32_t>;
|
||||
static_assert(sizeof(NiRect<std::int32_t>) == 0x10);
|
||||
|
||||
template class NiRect<std::uint32_t>;
|
||||
static_assert(sizeof(NiRect<std::uint32_t>) == 0x10);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "RE/P/PlayerCharacter.h"
|
||||
|
||||
#include "RE/B/BGSEntryPoint.h"
|
||||
#include "RE/C/Calendar.h"
|
||||
#include "RE/S/Setting.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void PlayerCharacter::LockOutOfTerminal(ObjectRefHandle a_handle)
|
||||
{
|
||||
float TerminalLockoutTime{ 0.0f };
|
||||
if (auto INISettingCollection = RE::INISettingCollection::GetSingleton()) {
|
||||
if (auto setting = INISettingCollection->GetSetting("iTerminalLockoutTime:Gameplay")) {
|
||||
TerminalLockoutTime = static_cast<float>(setting->GetInt());
|
||||
}
|
||||
}
|
||||
|
||||
BGSEntryPoint::HandleEntryPoint(RE::BGSEntryPoint::ENTRY_POINT::kModTerminalLockoutTime, this, &TerminalLockoutTime);
|
||||
if (auto Calendar = RE::Calendar::GetSingleton()) {
|
||||
auto TimeScale = Calendar->timeScale ? Calendar->timeScale->GetValue() : 0.0f;
|
||||
TerminalLockoutTime *= TimeScale * 0.00027799999f;
|
||||
TerminalLockoutTime += Calendar->GetHoursPassed();
|
||||
}
|
||||
|
||||
lockedTerminals.emplace_back(a_handle, TerminalLockoutTime);
|
||||
}
|
||||
|
||||
bool PlayerCharacter::IsLockedOutOfTerminal(ObjectRefHandle a_handle)
|
||||
{
|
||||
float HoursPassed{ 24.0f };
|
||||
if (auto Calendar = RE::Calendar::GetSingleton()) {
|
||||
HoursPassed = Calendar->GetHoursPassed();
|
||||
}
|
||||
|
||||
for (std::uint32_t i = 0; i < lockedTerminals.size();) {
|
||||
auto& iter = lockedTerminals.at(i);
|
||||
if (HoursPassed <= iter.second) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
lockedTerminals.erase(&iter);
|
||||
}
|
||||
|
||||
for (auto& iter : lockedTerminals) {
|
||||
if (iter.first == a_handle) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "RE/S/SCRIPT_FUNCTION.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void SCRIPT_FUNCTION::SetParameters()
|
||||
{
|
||||
paramCount = 0;
|
||||
parameters = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "RE/S/Setting.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class SettingT<GameSettingCollection>;
|
||||
static_assert(sizeof(SettingT<GameSettingCollection>) == 0x18);
|
||||
|
||||
template class SettingT<INIPrefSettingCollection>;
|
||||
static_assert(sizeof(SettingT<INIPrefSettingCollection>) == 0x18);
|
||||
|
||||
template class SettingT<INISettingCollection>;
|
||||
static_assert(sizeof(SettingT<INISettingCollection>) == 0x18);
|
||||
|
||||
template class SettingT<LipSynchroSettingCollection>;
|
||||
static_assert(sizeof(SettingT<LipSynchroSettingCollection>) == 0x18);
|
||||
|
||||
template class SettingT<RegSettingCollection>;
|
||||
static_assert(sizeof(SettingT<RegSettingCollection>) == 0x18);
|
||||
|
||||
template class SettingCollection<Setting>;
|
||||
static_assert(sizeof(SettingCollection<Setting>) == 0x118);
|
||||
|
||||
template class SettingCollectionList<Setting>;
|
||||
static_assert(sizeof(SettingCollectionList<Setting>) == 0x128);
|
||||
|
||||
template class SettingCollectionMap<Setting>;
|
||||
static_assert(sizeof(SettingCollectionMap<Setting>) == 0x138);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
#include "RE/T/TES.h"
|
||||
|
||||
#include "RE/E/EXTERIOR_DATA.h"
|
||||
#include "RE/G/GridCellArray.h"
|
||||
#include "RE/T/TESObjectCELL.h"
|
||||
#include "RE/T/TESObjectREFR.h"
|
||||
#include "RE/T/TESWorldSpace.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void TES::ForEachReference(std::function<BSContainer::ForEachResult(TESObjectREFR* a_ref)> a_callback)
|
||||
{
|
||||
if (interiorCell) {
|
||||
interiorCell->ForEachReference([&](TESObjectREFR* a_ref) {
|
||||
return a_callback(a_ref);
|
||||
});
|
||||
} else {
|
||||
if (const auto gridLength = gridCells ? gridCells->dimension : 0; gridLength > 0) {
|
||||
std::uint32_t x = 0;
|
||||
do {
|
||||
std::uint32_t y = 0;
|
||||
do {
|
||||
if (const auto cell = gridCells->GetCell(x, y); cell && cell->IsAttached()) {
|
||||
cell->ForEachReference([&](TESObjectREFR* a_ref) {
|
||||
return a_callback(a_ref);
|
||||
});
|
||||
}
|
||||
++y;
|
||||
} while (y < gridLength);
|
||||
++x;
|
||||
} while (x < gridLength);
|
||||
}
|
||||
}
|
||||
if (const auto skyCell = worldSpace ? worldSpace->GetSkyCell() : nullptr; skyCell) {
|
||||
skyCell->ForEachReference([&](TESObjectREFR* a_ref) {
|
||||
return a_callback(a_ref);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void TES::ForEachReferenceInRange(const NiPoint3& a_origin, const float a_radius, std::function<BSContainer::ForEachResult(TESObjectREFR* a_ref)> a_callback)
|
||||
{
|
||||
if (a_radius > 0.0f) {
|
||||
if (interiorCell) {
|
||||
interiorCell->ForEachReferenceInRange(a_origin, a_radius, [&](TESObjectREFR* a_ref) {
|
||||
return a_callback(a_ref);
|
||||
});
|
||||
} else {
|
||||
if (const auto gridLength = gridCells ? gridCells->dimension : 0; gridLength > 0) {
|
||||
const float yPlus = a_origin.y + a_radius;
|
||||
const float yMinus = a_origin.y - a_radius;
|
||||
const float xPlus = a_origin.x + a_radius;
|
||||
const float xMinus = a_origin.x - a_radius;
|
||||
|
||||
std::uint32_t x = 0;
|
||||
do {
|
||||
std::uint32_t y = 0;
|
||||
do {
|
||||
if (const auto cell = gridCells->GetCell(x, y); cell && cell->IsAttached()) {
|
||||
if (const auto cellCoords = cell->GetCoordinates(); cellCoords) {
|
||||
const NiPoint2 worldPos{ cellCoords->worldX, cellCoords->worldY };
|
||||
if (worldPos.x < xPlus && (worldPos.x + 4096.0f) > xMinus && worldPos.y < yPlus && (worldPos.y + 4096.0f) > yMinus) {
|
||||
cell->ForEachReferenceInRange(a_origin, a_radius, [&](TESObjectREFR* a_ref) {
|
||||
return a_callback(a_ref);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
++y;
|
||||
} while (y < gridLength);
|
||||
++x;
|
||||
} while (x < gridLength);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto skyCell = worldSpace ? worldSpace->GetSkyCell() : nullptr; skyCell) {
|
||||
skyCell->ForEachReferenceInRange(a_origin, a_radius, [&](TESObjectREFR* a_ref) {
|
||||
return a_callback(a_ref);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
ForEachReference([&](TESObjectREFR* a_ref) {
|
||||
return a_callback(a_ref);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void TES::ForEachReferenceInRange(const TESObjectREFR* a_ref, const float a_radius, std::function<BSContainer::ForEachResult(TESObjectREFR* a_ref)> a_callback)
|
||||
{
|
||||
ForEachReferenceInRange(a_ref->GetPosition(), a_radius, a_callback);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "RE/T/TESFullName.h"
|
||||
|
||||
#include "RE/C/CHANGE_TYPES.h"
|
||||
#include "RE/T/TESActorBase.h"
|
||||
#include "RE/T/TESForm.h"
|
||||
#include "RE/T/TESFormUtil.h"
|
||||
#include "RE/T/TESObjectCELL.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
std::string_view TESFullName::GetFullName(const TESForm& a_form, bool a_strict)
|
||||
{
|
||||
if (const auto fullName = a_form.As<TESFullName>()) {
|
||||
const auto name = fullName->GetFullName();
|
||||
return name ? name : ""sv;
|
||||
} else {
|
||||
if (a_strict) {
|
||||
switch (a_form.GetFormType()) {
|
||||
case ENUM_FORM_ID::kKYWD: // BGSKeyword
|
||||
case ENUM_FORM_ID::kLCRT: // BGSLocationRefType
|
||||
case ENUM_FORM_ID::kAACT: // BGSAction
|
||||
case ENUM_FORM_ID::kLIGH: // TESObjectLIGH
|
||||
case ENUM_FORM_ID::kSTAT: // TESObjectSTAT
|
||||
case ENUM_FORM_ID::kSCOL: // BGSStaticCollection
|
||||
case ENUM_FORM_ID::kMSTT: // BGSMovableStatic
|
||||
case ENUM_FORM_ID::kFLST: // BGSListForm
|
||||
break;
|
||||
default:
|
||||
return ""sv;
|
||||
}
|
||||
}
|
||||
|
||||
const auto& map = GetSparseFullNameMap();
|
||||
const auto it = map.find(std::addressof(a_form));
|
||||
return it != map.end() ? it->second : ""sv;
|
||||
}
|
||||
}
|
||||
|
||||
void TESFullName::SetFullName(TESForm& a_form, std::string_view a_fullName)
|
||||
{
|
||||
if (const auto full = a_form.As<TESFullName>()) {
|
||||
full->fullName = a_fullName;
|
||||
if (const auto actor = a_form.As<TESActorBase>()) {
|
||||
actor->AddChange(CHANGE_TYPES::kActorBaseFullName);
|
||||
} else if (const auto cell = a_form.As<TESObjectCELL>()) {
|
||||
cell->AddChange(CHANGE_TYPES::kCellFullname);
|
||||
} else {
|
||||
a_form.AddChange(CHANGE_TYPES::kBaseObjectFullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "RE/T/TESNPC.h"
|
||||
|
||||
#include "RE/P/PlayerCharacter.h"
|
||||
#include "RE/T/TESRace.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void TESNPC::CopyPerkRankArray(const std::vector<PerkRankData>& a_copiedData)
|
||||
{
|
||||
const auto oldData = perks;
|
||||
|
||||
const auto newSize = a_copiedData.size();
|
||||
const auto newData = calloc<PerkRankData>(newSize);
|
||||
std::ranges::copy(a_copiedData, newData);
|
||||
|
||||
perkCount = static_cast<std::uint32_t>(newSize);
|
||||
perks = newData;
|
||||
|
||||
free(oldData);
|
||||
}
|
||||
|
||||
bool TESNPC::AddPerks(const std::vector<BGSPerk*>& a_perks, std::int8_t a_rank)
|
||||
{
|
||||
std::vector<PerkRankData> copiedData{ perks, perks + perkCount };
|
||||
std::ranges::for_each(a_perks, [&](auto& perk) {
|
||||
if (!GetPerkIndex(perk)) {
|
||||
const auto newPerk = new PerkRankData(perk, a_rank);
|
||||
copiedData.push_back(*newPerk);
|
||||
}
|
||||
});
|
||||
CopyPerkRankArray(copiedData);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TESNPC::ContainsKeyword(std::string_view a_editorID) const
|
||||
{
|
||||
if (ContainsKeywordString(a_editorID)) {
|
||||
return true;
|
||||
}
|
||||
if (const auto npcRace = GetFormRace(); npcRace && npcRace->ContainsKeywordString(a_editorID)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TESNPC::HasApplicableKeywordString(std::string_view a_editorID) const
|
||||
{
|
||||
if (HasKeywordString(a_editorID)) {
|
||||
return true;
|
||||
}
|
||||
if (const auto npcRace = GetFormRace(); npcRace && npcRace->HasKeywordString(a_editorID)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TESNPC::RemovePerks(const std::vector<BGSPerk*>& a_perks)
|
||||
{
|
||||
std::vector<PerkRankData> copiedData{ perks, perks + perkCount };
|
||||
if (std::erase_if(copiedData, [&](auto& perkRank) { return std::ranges::find(a_perks, perkRank.perk) != a_perks.end(); }) > 0) {
|
||||
CopyPerkRankArray(copiedData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TESNPC::UsingAlternateHeadPartList() const
|
||||
{
|
||||
if (const auto player = PlayerCharacter::GetSingleton(); IsPlayer() && player) {
|
||||
const auto& map = GetAlternateHeadPartListMap();
|
||||
return player->charGenRace && player->charGenRace != formRace && map.contains(player->GetNPC());
|
||||
} else {
|
||||
return originalRace && originalRace != formRace;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "RE/T/TESObjectCELL.h"
|
||||
|
||||
#include "RE/E/EXTERIOR_DATA.h"
|
||||
#include "RE/E/ExtraCellWaterType.h"
|
||||
#include "RE/E/ExtraDataList.h"
|
||||
#include "RE/T/TESObjectREFR.h"
|
||||
#include "RE/T/TESWorldSpace.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void TESObjectCELL::ForEachReference(std::function<BSContainer::ForEachResult(TESObjectREFR*)> a_callback)
|
||||
{
|
||||
const BSAutoLock locker(spinLock);
|
||||
for (const auto& ref : references) {
|
||||
if (ref && a_callback(ref.get()) == BSContainer::ForEachResult::kStop) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TESObjectCELL::ForEachReferenceInRange(const NiPoint3& a_origin, float a_radius, std::function<BSContainer::ForEachResult(TESObjectREFR*)> a_callback)
|
||||
{
|
||||
const float squaredRadius = a_radius * a_radius;
|
||||
ForEachReference([&](TESObjectREFR* a_ref) {
|
||||
const auto distance = a_origin.GetSquaredDistance(a_ref->GetPosition());
|
||||
if (distance <= squaredRadius)
|
||||
return a_callback(a_ref);
|
||||
|
||||
return BSContainer::ForEachResult::kContinue;
|
||||
});
|
||||
}
|
||||
|
||||
EXTERIOR_DATA* TESObjectCELL::GetCoordinates() const
|
||||
{
|
||||
return IsExterior() ? cellData.exterior : nullptr;
|
||||
}
|
||||
|
||||
TESWaterForm* TESObjectCELL::GetWaterType() const noexcept
|
||||
{
|
||||
const auto xWater = extraList ? extraList->GetByType<ExtraCellWaterType>() : nullptr;
|
||||
auto water = xWater ? xWater->water : nullptr;
|
||||
if (!water) {
|
||||
water = IsExterior() && worldSpace ? worldSpace->GetWaterType() : nullptr;
|
||||
if (!water) {
|
||||
static REL::Relocation<TESWaterForm**> defaultWater{ ID::TESObjectCELL::DefaultWater };
|
||||
water = *defaultWater;
|
||||
}
|
||||
}
|
||||
|
||||
return water;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "RE/T/TESValueForm.h"
|
||||
|
||||
#include "RE/C/CHANGE_TYPES.h"
|
||||
#include "RE/T/TESForm.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void TESValueForm::SetFormValue(TESForm& a_form, std::int32_t a_value)
|
||||
{
|
||||
if (const auto val = a_form.As<TESValueForm>()) {
|
||||
val->value = a_value;
|
||||
a_form.AddChange(CHANGE_TYPES::kBaseObjectValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/T/ThumbstickEvent.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template ThumbstickEvent* InputEvent::As() noexcept;
|
||||
template const ThumbstickEvent* InputEvent::As() const noexcept;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "RE/W/WorkbenchMenuBase.h"
|
||||
|
||||
#include "RE/P/PlayerCharacter.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
WorkbenchMenuBase::InitParams::InitParams()
|
||||
{
|
||||
workbenchFurniture.reset();
|
||||
inventorySource = RE::PlayerCharacter::GetPlayerHandle();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user