@@ -33,9 +33,11 @@ namespace RE
3333 class BGSTypedKeywordValue
3434 {
3535 public:
36- // members
3736 std::uint16_t keywordIndex; // 0
37+ std::uint16_t pad02; // 2
38+ std::uint32_t pad04; // 4
3839 };
40+ static_assert (sizeof (BGSTypedKeywordValue<KeywordType::kNone >) == 0x8 );
3941
4042 namespace detail
4143 {
@@ -48,19 +50,83 @@ namespace RE
4850 public:
4951 [[nodiscard]] bool HasKeyword (BGSKeyword* a_keyword)
5052 {
51- for (std::uint32_t i = 0 ; i < size; ++i) {
52- const auto kywd = detail::BGSKeywordGetTypedKeywordByIndex (TYPE, array[i].keywordIndex );
53+ if (!a_keyword) {
54+ return false ;
55+ }
56+
57+ for (auto it = begin; it != end; ++it) {
58+ const auto kywd = detail::BGSKeywordGetTypedKeywordByIndex (TYPE, it->keywordIndex );
5359 if (kywd == a_keyword) {
5460 return true ;
5561 }
5662 }
5763 return false ;
5864 }
5965
60- // members
61- BGSTypedKeywordValue<TYPE>* array; // 00
62- std::uint32_t size; // 08
63- std::uint64_t unk10; // 10
66+ [[nodiscard]] bool AddKeyword (BGSKeyword* a_keyword)
67+ {
68+ if (!a_keyword) {
69+ return false ;
70+ }
71+
72+ auto first = reinterpret_cast <BGSKeyword**>(begin);
73+ auto last = reinterpret_cast <BGSKeyword**>(end);
74+
75+ for (auto it = first; it != last; ++it) {
76+ if (*it && (*it)->formID == a_keyword->formID ) {
77+ return false ;
78+ }
79+ }
80+
81+ const auto oldSize = static_cast <std::size_t >(last - first);
82+ const auto newSize = oldSize + 1 ;
83+
84+ auto * newData = static_cast <BGSKeyword**>(
85+ RE::MemoryManager::GetSingleton ()->Allocate (sizeof (BGSKeyword*) * newSize, 0 , false ));
86+
87+ if (!newData) {
88+ return false ;
89+ }
90+
91+ for (std::size_t i = 0 ; i < oldSize; ++i) {
92+ newData[i] = first[i];
93+ }
94+
95+ newData[oldSize] = a_keyword;
96+ auto oldFirst = first;
97+ auto oldLast = last;
98+ auto oldCap = reinterpret_cast <BGSKeyword**>(capacityEnd);
99+
100+ begin = reinterpret_cast <BGSTypedKeywordValue<TYPE>*>(newData);
101+ end = reinterpret_cast <BGSTypedKeywordValue<TYPE>*>(newData + newSize);
102+ capacityEnd = reinterpret_cast <BGSTypedKeywordValue<TYPE>*>(newData + newSize);
103+ return true ;
104+ }
105+
106+ [[nodiscard]] bool RemoveKeyword (BGSKeyword* a_keyword)
107+ {
108+ if (!a_keyword) {
109+ return false ;
110+ }
111+ auto first = reinterpret_cast <BGSKeyword**>(begin);
112+ auto last = reinterpret_cast <BGSKeyword**>(end);
113+ for (auto it = first; it != last; ++it) {
114+ if (*it && (*it)->formID == a_keyword->formID ) {
115+ for (auto jt = it; jt + 1 != last; ++jt) {
116+ *jt = *(jt + 1 );
117+ }
118+ --last;
119+ *last = nullptr ;
120+ end = reinterpret_cast <BGSTypedKeywordValue<TYPE>*>(last);
121+ return true ;
122+ }
123+ }
124+ return false ;
125+ }
126+
127+ BGSTypedKeywordValue<TYPE>* begin; // 00
128+ BGSTypedKeywordValue<TYPE>* end; // 08
129+ BGSTypedKeywordValue<TYPE>* capacityEnd; // 10
64130 };
65131 static_assert (sizeof (BGSTypedKeywordValueArray<KeywordType::kNone >) == 0x18 );
66132}
0 commit comments