22
22
// We're fixing it by caching results beforehand, when the game loads variation data files.
23
23
//
24
24
25
+ const static int8_t kAlternatesSizeof = 8 ;
26
+ const static int16_t kMaxNumAlternates = 160 ;
27
+
25
28
struct AlternateVariationsSwitchAsset // 0x1BC82D17
26
29
{
27
30
uint8_t component;
@@ -57,6 +60,12 @@ struct CAlternateVariations
57
60
atArray<AlternateVariationsPed> peds;
58
61
};
59
62
63
+ struct AlternatesVariationsPatternPair
64
+ {
65
+ std::string_view pattern;
66
+ int arrayCapacityoffset;
67
+ };
68
+
60
69
using TAlternateVariationsSwitchSet = std::set<AlternateVariationsSwitch*>;
61
70
using TAlternateVariationsCache = std::map<std::tuple<uint32_t , uint32_t , char , char >, TAlternateVariationsSwitchSet>;
62
71
@@ -192,6 +201,12 @@ static void UnloadAlternateVariationsFile(void* data)
192
201
}
193
202
}
194
203
204
+ static size_t GetExpectedAlternatesAtArrayCapacityForBuild ()
205
+ {
206
+ if (xbr::IsGameBuildOrGreater<2189 >()) return 160 ;
207
+ return 128 ;
208
+ }
209
+
195
210
static HookFunction initFunction ([]()
196
211
{
197
212
g_alternateVariations = hook::get_address<decltype (g_alternateVariations)>(hook::get_pattern (" 85 C0 7E 28 4C 8B 0D" , 7 ));
@@ -212,4 +227,21 @@ static HookFunction initFunction([]()
212
227
{
213
228
ClearAlternateVariationsCache ();
214
229
});
230
+
231
+ std::initializer_list<AlternatesVariationsPatternPair> alternateVariationsLocations = {
232
+ { " B8 ? ? ? ? 48 2B E0 48 8D 4C 24 ? 8B 01 48 8B B6" , 0x25 },
233
+ { " B8 ? ? ? ? 48 2B E0 48 8D 4C 24 ? 8B 01 44 8B 4D" , 0x22 },
234
+ { " B8 ? ? ? ? 48 2B E0 48 8D 4C 24 ? 8B 01 4C 8B BB" , 0x27 },
235
+ { " B8 ? ? ? ? 48 2B E0 48 8D 44 24 ? 48 89 45 ? 8B 00 44 88 5D" , 0x65 },
236
+ { " B8 ? ? ? ? 48 2B E0 48 8D 4C 24 ? 8B 01 8B 9C B7" , 0x28 }
237
+ };
238
+
239
+ for (auto & entry : alternateVariationsLocations)
240
+ {
241
+ auto location = hook::get_pattern<char >(entry.pattern );
242
+ auto prevAlternatesAtArrayCapacity = *(int16_t *)(location + entry.arrayCapacityoffset );
243
+ assert (prevAlternatesAtArrayCapacity == GetExpectedAlternatesAtArrayCapacityForBuild ());
244
+ hook::put<uint32_t >(location + 0x1 , kMaxNumAlternates * kAlternatesSizeof );
245
+ hook::put<int16_t >(location + entry.arrayCapacityoffset , kMaxNumAlternates );
246
+ }
215
247
});
0 commit comments