diff --git a/include/RE/B/BGSTypedKeywordValueArray.h b/include/RE/B/BGSTypedKeywordValueArray.h index ed24923..1ef0fb8 100644 --- a/include/RE/B/BGSTypedKeywordValueArray.h +++ b/include/RE/B/BGSTypedKeywordValueArray.h @@ -33,9 +33,11 @@ namespace RE class BGSTypedKeywordValue { public: - // members std::uint16_t keywordIndex; // 0 + std::uint16_t pad02; // 2 + std::uint32_t pad04; // 4 }; + static_assert(sizeof(BGSTypedKeywordValue) == 0x8); namespace detail { @@ -48,8 +50,12 @@ namespace RE public: [[nodiscard]] bool HasKeyword(BGSKeyword* a_keyword) { - for (std::uint32_t i = 0; i < size; ++i) { - const auto kywd = detail::BGSKeywordGetTypedKeywordByIndex(TYPE, array[i].keywordIndex); + if (!a_keyword) { + return false; + } + + for (auto it = begin; it != end; ++it) { + const auto kywd = detail::BGSKeywordGetTypedKeywordByIndex(TYPE, it->keywordIndex); if (kywd == a_keyword) { return true; } @@ -57,10 +63,70 @@ namespace RE return false; } - // members - BGSTypedKeywordValue* array; // 00 - std::uint32_t size; // 08 - std::uint64_t unk10; // 10 + [[nodiscard]] bool AddKeyword(BGSKeyword* a_keyword) + { + if (!a_keyword) { + return false; + } + + auto first = reinterpret_cast(begin); + auto last = reinterpret_cast(end); + + for (auto it = first; it != last; ++it) { + if (*it && (*it)->formID == a_keyword->formID) { + return false; + } + } + + const auto oldSize = static_cast(last - first); + const auto newSize = oldSize + 1; + + auto* newData = static_cast( + RE::MemoryManager::GetSingleton()->Allocate(sizeof(BGSKeyword*) * newSize, 0, false)); + + if (!newData) { + return false; + } + + for (std::size_t i = 0; i < oldSize; ++i) { + newData[i] = first[i]; + } + + newData[oldSize] = a_keyword; + auto oldFirst = first; + auto oldLast = last; + auto oldCap = reinterpret_cast(capacityEnd); + + begin = reinterpret_cast*>(newData); + end = reinterpret_cast*>(newData + newSize); + capacityEnd = reinterpret_cast*>(newData + newSize); + return true; + } + + [[nodiscard]] bool RemoveKeyword(BGSKeyword* a_keyword) + { + if (!a_keyword) { + return false; + } + auto first = reinterpret_cast(begin); + auto last = reinterpret_cast(end); + for (auto it = first; it != last; ++it) { + if (*it && (*it)->formID == a_keyword->formID) { + for (auto jt = it; jt + 1 != last; ++jt) { + *jt = *(jt + 1); + } + --last; + *last = nullptr; + end = reinterpret_cast*>(last); + return true; + } + } + return false; + } + + BGSTypedKeywordValue* begin; // 00 + BGSTypedKeywordValue* end; // 08 + BGSTypedKeywordValue* capacityEnd; // 10 }; static_assert(sizeof(BGSTypedKeywordValueArray) == 0x18); }