From 249d3ad2905f5a90055cc8ec77b1bffbd584ef4e Mon Sep 17 00:00:00 2001 From: gir489 <100792176+gir489returns@users.noreply.github.com> Date: Sun, 16 Jul 2023 11:49:13 -0400 Subject: [PATCH] Added stuff for Allow All Weapons in Vehicle. (#122) --- classes.cpp | 2 + rage/atArray.hpp | 153 ++++++++++++++++++++++++- vehicle/CDriveBySeatDefault.hpp | 14 +++ vehicle/CDriveByWeaponGroupDefault.hpp | 105 +++++++++++++++++ vehicle/CDrivebyWeaponGroups.hpp | 9 ++ vehicle/CVehicleDriveByAnimInfo.hpp | 36 ++++++ vehicle/CVehicleDriveByMetadataMgr.hpp | 9 ++ vehicle/CVehicleLayoutMetaData.hpp | 11 ++ vehicle/CVehicleModelInfo.hpp | 11 +- vehicle/CVehicleModelInfoLayout.hpp | 15 +++ vehicle/CVehicleSeatAnimInfo.hpp | 13 +++ vehicle/CVehicleSeatAnimInfos.hpp | 23 ++++ vehicle/CVehicleSeatMetadataMgr.hpp | 9 ++ vehicle_stuff_from_gir.rcnet | Bin 0 -> 16829 bytes 14 files changed, 401 insertions(+), 9 deletions(-) create mode 100644 vehicle/CDriveBySeatDefault.hpp create mode 100644 vehicle/CDriveByWeaponGroupDefault.hpp create mode 100644 vehicle/CDrivebyWeaponGroups.hpp create mode 100644 vehicle/CVehicleDriveByAnimInfo.hpp create mode 100644 vehicle/CVehicleDriveByMetadataMgr.hpp create mode 100644 vehicle/CVehicleLayoutMetaData.hpp create mode 100644 vehicle/CVehicleModelInfoLayout.hpp create mode 100644 vehicle/CVehicleSeatAnimInfo.hpp create mode 100644 vehicle/CVehicleSeatAnimInfos.hpp create mode 100644 vehicle/CVehicleSeatMetadataMgr.hpp create mode 100644 vehicle_stuff_from_gir.rcnet diff --git a/classes.cpp b/classes.cpp index 547ec38..1d5041f 100644 --- a/classes.cpp +++ b/classes.cpp @@ -179,6 +179,8 @@ #include "vehicle/CHandlingObject.hpp" #include "vehicle/CVehicle.hpp" #include "vehicle/CVehicleModelInfo.hpp" +#include "vehicle/CVehicleDriveByMetadataMgr.hpp" +#include "vehicle/CVehicleSeatMetadataMgr.hpp" #include "weapon/CAmmoInfo.hpp" #include "weapon/CAmmoProjectileInfo.hpp" #include "weapon/CAmmoRocketInfo.hpp" diff --git a/rage/atArray.hpp b/rage/atArray.hpp index 08548a6..b453a2f 100644 --- a/rage/atArray.hpp +++ b/rage/atArray.hpp @@ -4,9 +4,7 @@ #include #include -#include "sysMemAllocator.hpp" - - +#include "script/tlsContext.hpp" namespace rage { @@ -20,7 +18,17 @@ namespace rage m_size(0), m_count(0) { - + + } + +#if _WIN32 + atArray(const atArray& right) + { + m_count = right.m_count; + m_size = right.m_size; + + m_data = (T*)tlsContext::get()->m_allocator->Allocate(m_size * sizeof(T), 16, 0); + std::uninitialized_copy(right.m_data, right.m_data + right.m_count, m_data); } atArray(void* data_ptr, std::uint16_t size, std::uint16_t count) : @@ -31,6 +39,127 @@ namespace rage } + void clear() + { + m_count = 0; + m_size = 0; + + if (m_data) + { + tlsContext::get()->m_allocator->Free(m_data); + + m_data = nullptr; + } + } + + bool append(atArray value_array) + { + auto value_array_size = value_array.size(); + auto old_capacity = m_count; + + if ((value_array_size + m_count) > std::numeric_limits::max()) + return false; + + auto size = (uint16_t)value_array_size; + expand(m_count + size); + m_size += size; + + auto i = old_capacity; + for (auto iter_value : value_array) + { + m_data[i] = iter_value; + i++; + } + return true; + } + + bool append(std::vector value_array) + { + auto value_array_size = value_array.size(); + auto old_capacity = m_count; + + if ((value_array_size + m_count) > std::numeric_limits::max()) + return false; + + auto size = (uint16_t)value_array_size; + expand(m_count + size); + m_size += size; + + auto i = old_capacity; + for (auto iter_value : value_array) + { + m_data[i] = iter_value; + i++; + } + return true; + } + + bool append(const std::initializer_list value_array) + { + auto value_array_size = value_array.size(); + auto old_capacity = m_count; + + if ((value_array_size + m_count) > std::numeric_limits::max()) + return false; + + auto size = (uint16_t)value_array_size; + expand(m_count + size); + m_size += size; + + auto i = old_capacity; + for (const T* it = value_array.begin(); it != value_array.end(); ++it) + { + m_data[i] = *it; + i++; + } + return true; + } + + void set(uint16_t offset, const T& value) + { + if (offset >= m_count) + { + expand(offset + 1); + } + + if (offset >= m_size) + { + m_size = offset + 1; + } + + m_data[offset] = value; + } + + void expand(uint16_t newSize) + { + if (m_count >= newSize) + { + return; + } + + T* newOffset = (T*)tlsContext::get()->m_allocator->Allocate(newSize * sizeof(T), 16, 0); + + + // initialize the new entries + std::uninitialized_fill(newOffset, newOffset + newSize, T()); + + // copy the existing entries + if (m_data) + { + std::copy(m_data, m_data + m_size, newOffset); + tlsContext::get()->m_allocator->Free(m_data); + } + + m_data = newOffset; + m_count = newSize; + } +#endif + + void append(T value) + { + set(m_count, value); + } + T* begin() const { return &m_data[0]; @@ -61,10 +190,22 @@ namespace rage return m_data[index]; } + bool contains(T comparator) + { + for (auto iter_value : this) + { + if (iter_value == comparator) + { + return true; + } + } + return false; + } + friend std::ostream& operator<<(std::ostream& o, const atArray& j) { o << "Array Size: " << j.size() << std::endl; - for(int i = 0; i < j.size(); i++) + for (int i = 0; i < j.size(); i++) { T item = j[i]; if (std::is_pointer()) @@ -84,4 +225,4 @@ namespace rage }; static_assert(sizeof(rage::atArray) == 0x10, "rage::atArray is not properly sized"); #pragma pack(pop) -} \ No newline at end of file +} diff --git a/vehicle/CDriveBySeatDefault.hpp b/vehicle/CDriveBySeatDefault.hpp new file mode 100644 index 0000000..850d6d3 --- /dev/null +++ b/vehicle/CDriveBySeatDefault.hpp @@ -0,0 +1,14 @@ +#include "CVehicleDriveByAnimInfo.hpp" + +#pragma pack(push, 4) +class CDriveBySeatDefault +{ +private: + char pad_0000[320]; //0x0000 +public: + class CVehicleDriveByAnimInfo* m_driveby_standard_front_left; //0x0140 + class CVehicleDriveByAnimInfo* m_driveby_standard_front_right; //0x0148 + class CVehicleDriveByAnimInfo* m_driveby_standard_rear_left; //0x0150 + class CVehicleDriveByAnimInfo* m_driveby_standard_rear_right; //0x0158 +}; //Size: 0x0160 +#pragma pack(pop) \ No newline at end of file diff --git a/vehicle/CDriveByWeaponGroupDefault.hpp b/vehicle/CDriveByWeaponGroupDefault.hpp new file mode 100644 index 0000000..dbd4f96 --- /dev/null +++ b/vehicle/CDriveByWeaponGroupDefault.hpp @@ -0,0 +1,105 @@ +#include "../rage/atArray.hpp" +#include "script/types.hpp" + +class CDriveByWeaponGroupDefault +{ +public: + Hash m_driveby_default_unarmed; //0x0000 +private: + char pad_0004[4]; //0x0004 +public: + rage::atArray m_driveby_default_unarmed_weapon_group_names; //0x0008 + rage::atArray m_driveby_default_unarmed_weapon_type_names; //0x0018 +private: + char pad_0028[8]; //0x0028 +public: + Hash m_driveby_default_one_handed; //0x0030 +private: + char pad_0034[4]; //0x0034 +public: + rage::atArray m_driveby_default_one_handed_weapon_group_names; //0x0038 + rage::atArray m_driveby_default_one_handed_weapon_type_names; //0x0048 +private: + char pad_0058[8]; //0x0058 +public: + Hash m_driveby_default_two_handed; //0x0060 +private: + char pad_0064[4]; //0x0064 +public: + rage::atArray m_driveby_default_two_handed_weapon_group_names; //0x0068 + rage::atArray m_driveby_default_two_handed_weapon_type_names; //0x0078 +private: + char pad_0088[8]; //0x0088 +public: + Hash m_driveby_heli_two_handed; //0x0090 +private: + char pad_0094[4]; //0x0094 +public: + rage::atArray m_driveby_heli_two_handed_weapon_group_names; //0x0098 + rage::atArray m_driveby_heli_two_handed_weapon_type_names; //0x00A8 +private: + char pad_00B8[56]; //0x00B8 +public: + Hash m_driveby_heli_rpg; //0x00F0 +private: + char pad_00F4[4]; //0x00F4 +public: + rage::atArray m_driveby_heli_rpg_weapon_group_names; //0x00F8 + rage::atArray m_driveby_heli_rpg_weapon_type_names; //0x0108 +private: + char pad_0118[8]; //0x0118 +public: + Hash m_driveby_default_rear_one_handed; //0x0120 +private: + char pad_0124[4]; //0x0124 +public: + rage::atArray m_driveby_default_rear_one_handed_weapon_group_names; //0x0128 + rage::atArray m_driveby_default_rear_one_handed_weapon_type_names; //0x0138 +private: + char pad_0148[8]; //0x0148 +public: + Hash m_driveby_bike_one_handed; //0x0150 +private: + char pad_0154[4]; //0x0154 +public: + rage::atArray m_driveby_bike_one_handed_weapon_group_names; //0x0158 + rage::atArray m_driveby_bike_one_handed_weapon_type_names; //0x0168 +private: + char pad_0178[56]; //0x0178 +public: + Hash m_driveby_bike_melee; //0x01B0 +private: + char pad_01B4[4]; //0x01B4 +public: + rage::atArray m_driveby_bike_melee_weapon_group_names; //0x01B8 + rage::atArray m_driveby_bike_melee_weapon_type_names; //0x01C8 +private: + char pad_01D8[56]; //0x01D8 +public: + Hash m_driveby_mounted_throw; //0x0210 +private: + char pad_0214[4]; //0x0214 +public: + rage::atArray m_driveby_mounted_throw_weapon_group_names; //0x0218 + rage::atArray m_driveby_mounted_throw_weapon_type_names; //0x0228 +private: + char pad_0238[8]; //0x0238 +public: + Hash m_driveby_throw; //0x0240 +private: + char pad_0244[4]; //0x0244 +public: + rage::atArray m_driveby_throw_weapon_group_names; //0x0248 + rage::atArray m_driveby_throw_weapon_type_names; //0x0258 +private: + char pad_0268[8]; //0x0268 +public: + Hash m_driveby_vehicle_weapon_group; //0x0270 +private: + char pad_0274[4]; //0x0274 +public: + rage::atArray m_driveby_vehicle_weapon_group_weapon_group_names; //0x0278 + rage::atArray m_driveby_vehicle_weapon_group_weapon_type_names; //0x0288 +private: + char pad_0298[8]; //0x0298 +}; //Size: 0x02A0 \ No newline at end of file diff --git a/vehicle/CDrivebyWeaponGroups.hpp b/vehicle/CDrivebyWeaponGroups.hpp new file mode 100644 index 0000000..e7e0e41 --- /dev/null +++ b/vehicle/CDrivebyWeaponGroups.hpp @@ -0,0 +1,9 @@ +#include "CDriveByWeaponGroupDefault.hpp" + +#pragma pack(push, 4) +class CDrivebyWeaponGroups +{ +public: + class CDriveByWeaponGroupDefault* m_drive_by_default; //0x0000 +}; //Size: 0x0008 +#pragma pack(pop) \ No newline at end of file diff --git a/vehicle/CVehicleDriveByAnimInfo.hpp b/vehicle/CVehicleDriveByAnimInfo.hpp new file mode 100644 index 0000000..65a397c --- /dev/null +++ b/vehicle/CVehicleDriveByAnimInfo.hpp @@ -0,0 +1,36 @@ +#include "../rage/atArray.hpp" + +#pragma once + +#pragma pack(push, 4) +class CVehicleDriveByAnimInfo +{ +public: + uint32_t m_name; //0x0000 + float m_min_aim_sweep_heading_angle_degs; //0x0004 + float m_max_aim_sweep_heading_angle_degs; //0x0008 + float m_first_person_min_aim_sweep_heading_angle_degs; //0x000C + float m_first_person_max_aim_sweep_heading_angle_degs; //0x0010 + float m_first_person_unarmed_min_aim_sweep_heading_angle_degs; //0x0014 + float m_first_person_unarmed_max_aim_sweep_heading_angle_degs; //0x0018 + uint64_t m_unk1; //0x001C + float m_min_restricted_aim_sweep_heading_angle_degs; //0x0024 + float m_max_restricted_aim_sweep_heading_angle_degs; //0x0028 + float m_min_smash_window_angle_degs; //0x002C + float m_max_smash_window_angle_degs; //0x0030 + float m_min_smash_window_angle_first_person_degs; //0x0034 + float m_max_smash_window_angle_first_person_degs; //0x0038 + float m_max_speed_param; //0x003C + float m_max_longitudinal_lean_blend_weight_delta; //0x0040 + float m_max_lateral_lean_blend_weight_delta; //0x0044 + float m_approach_speed_to_within_max_blend_delta; //0x0048 + float m_spine_additive_blend_in_delay; //0x004C + float m_spine_additive_blend_in_duration_still; //0x0050 + float m_spine_additive_blend_in_duration; //0x0054 + float m_spine_additive_blend_out_delay; //0x0058 + float m_spine_additive_blend_out_duration; //0x005C + float m_min_unarmed_driveby_yaw_if_window_rolled_up; //0x0060 + float m_max_unarmed_driveby_yaw_if_window_rolled_up; //0x0064 + rage::atArray m_drive_by_anim_infos; //0x0068 +}; //Size: 0x0078 +#pragma pack(pop) \ No newline at end of file diff --git a/vehicle/CVehicleDriveByMetadataMgr.hpp b/vehicle/CVehicleDriveByMetadataMgr.hpp new file mode 100644 index 0000000..79f4355 --- /dev/null +++ b/vehicle/CVehicleDriveByMetadataMgr.hpp @@ -0,0 +1,9 @@ +#include "CDrivebyWeaponGroups.hpp" + +#pragma pack(push, 4) +class CVehicleDriveByMetadataMgr +{ +public: + class CDrivebyWeaponGroups* m_drive_by_weapon_groups; //0x0000 +}; //Size: 0x0008 +#pragma pack(pop) \ No newline at end of file diff --git a/vehicle/CVehicleLayoutMetaData.hpp b/vehicle/CVehicleLayoutMetaData.hpp new file mode 100644 index 0000000..d7e3587 --- /dev/null +++ b/vehicle/CVehicleLayoutMetaData.hpp @@ -0,0 +1,11 @@ +#include "CVehicleSeatAnimInfos.hpp" + +#pragma pack(push, 4) +class CVehicleLayoutMetaData +{ +private: + char pad_0000[8]; //0x0000 +public: + class CVehicleSeatAnimInfos* m_seat_info; //0x0008 +}; //Size: 0x0010 +#pragma pack(pop) \ No newline at end of file diff --git a/vehicle/CVehicleModelInfo.hpp b/vehicle/CVehicleModelInfo.hpp index a1b7580..6e4372e 100644 --- a/vehicle/CVehicleModelInfo.hpp +++ b/vehicle/CVehicleModelInfo.hpp @@ -1,6 +1,7 @@ #pragma once #include "../base/CBaseModelInfo.hpp" +#include "vehicle/CVehicleModelInfoLayout.hpp" #include @@ -56,7 +57,8 @@ enum class eVehicleClass : std::uint8_t class CVehicleModelInfo : public CBaseModelInfo { public: - char pad_00A4[72]; //0x00A4 + CVehicleModelInfoLayout* m_vehicle_layout; //0x00B0 + char pad_00B8[64]; //0x00B8 uint8_t m_primary_color_combinations[25]; //0x00F8 uint8_t m_secondary_color_combinations[25]; //0x0111 uint8_t m_unk_color_combos1[25]; //0x012A @@ -73,8 +75,11 @@ public: char pad_02D9[103]; //0x02D9 eVehicleType m_vehicle_type; //0x0340 uint32_t m_unk_vehicle_type; //0x0344 - uint32_t m_diffuse_tint; //0x0348 - char pad_034C[20]; //0x034C + uint16_t m_diffuse_tint; //0x0348 + int8_t m_max_seats; //0x034A + char pad_034B[5]; //0x034B + CVehicleLayoutMetaData* m_layout_metadata; //0x0350 + char pad_0358[8]; //0x0358 rage::fvector3 m_first_person_driveby_ik_offset; //0x0360 char pad_036C[4]; //0x036C rage::fvector3 m_first_person_driveby_unarmed_ik_offset; //0x0370 diff --git a/vehicle/CVehicleModelInfoLayout.hpp b/vehicle/CVehicleModelInfoLayout.hpp new file mode 100644 index 0000000..2cbcbd6 --- /dev/null +++ b/vehicle/CVehicleModelInfoLayout.hpp @@ -0,0 +1,15 @@ +#include "CVehicleLayoutMetaData.hpp" + +#pragma pack(push, 4) +class CVehicleModelInfoLayout +{ +private: + char pad_0000[842]; //0x0000 +public: + int8_t m_max_seats; //0x034A +private: + char pad_034B[5]; //0x034B +public: + class CVehicleLayoutMetaData* m_layout_metadata; //0x0350 +}; //Size: 0x0358 +#pragma pack(pop) \ No newline at end of file diff --git a/vehicle/CVehicleSeatAnimInfo.hpp b/vehicle/CVehicleSeatAnimInfo.hpp new file mode 100644 index 0000000..0a85228 --- /dev/null +++ b/vehicle/CVehicleSeatAnimInfo.hpp @@ -0,0 +1,13 @@ +#include "CVehicleDriveByAnimInfo.hpp" + +#pragma pack(push, 4) +class CVehicleSeatAnimInfo +{ +public: + uint32_t name; //0x0000 +private: + char pad_0004[4]; //0x0004 +public: + class CVehicleDriveByAnimInfo* m_drive_by_info; //0x0008 +}; //Size: 0x0010 +#pragma pack(pop) \ No newline at end of file diff --git a/vehicle/CVehicleSeatAnimInfos.hpp b/vehicle/CVehicleSeatAnimInfos.hpp new file mode 100644 index 0000000..262289b --- /dev/null +++ b/vehicle/CVehicleSeatAnimInfos.hpp @@ -0,0 +1,23 @@ +#include "CVehicleSeatAnimInfo.hpp" + +#pragma pack(push, 4) +class CVehicleSeatAnimInfos +{ +private: + char pad_0000[8]; //0x0000 +public: + class CVehicleSeatAnimInfo* m_front_left; //0x0008 +private: + char pad_0010[8]; //0x0010 +public: + class CVehicleSeatAnimInfo* m_front_right; //0x0018 +private: + char pad_0020[8]; //0x0020 +public: + class CVehicleSeatAnimInfo* m_rear_left; //0x0028 +private: + char pad_0030[8]; //0x0030 +public: + class CVehicleSeatAnimInfo* m_rear_right; //0x0038 +}; //Size: 0x0040 +#pragma pack(pop) \ No newline at end of file diff --git a/vehicle/CVehicleSeatMetadataMgr.hpp b/vehicle/CVehicleSeatMetadataMgr.hpp new file mode 100644 index 0000000..5a20dab --- /dev/null +++ b/vehicle/CVehicleSeatMetadataMgr.hpp @@ -0,0 +1,9 @@ +#include "vehicle/CDriveBySeatDefault.hpp" + +#pragma pack(push, 4) +class CVehicleSeatMetadataMgr +{ +public: + class CDriveBySeatDefault* m_drive_by_seat_defaults; //0x0000 +}; //Size: 0x0008 +#pragma pack(pop) \ No newline at end of file diff --git a/vehicle_stuff_from_gir.rcnet b/vehicle_stuff_from_gir.rcnet new file mode 100644 index 0000000000000000000000000000000000000000..c4aefe5352db43f440e0e8a32b4e12c8613bb629 GIT binary patch literal 16829 zcmeHv2UJu`)-EDJC5e(nP*6Z}&QU}_KqO0Sa*&MVD4;|IBsI_kMS=v0EkQzqNX{TR z=S(B1Nlm}g&D=Zx{4@8>oq6wHYu;K|Y4?{Dv2)s@aZb^4joWgIdrEUYV7H;Ozp z4wjrrm1MB646ow=C0JOGOk7PkJ?-tb(mGujbIya zxwhwL$0o$*-)DDF$i&6w$LdnzT5h)FiRLfn#;?t4GZ(%ge)74eR9jc~iDICXID@!9 zEOlY#7=}7U`5th=xwN^ai6^F9%Fjepq0jKK$ z_u6MdUkq)!2b}ny3`TCM9!DNFMZ)|Y^I;SLs<9K%XJ*zOoyeUP%9T^((spmLQJpUE zIWFY}iPWital(-6=>y%x4x!sS!Ju37g&ZAVu0wjx&|*-%$8xssdUIs)w}L7EmppKY z-`@OCcQi45GKe1x9+=+PjcStkkFi;sC9y7pnK~w6Cf#vvpM;h%|sNB zuieRp>bRu7eF{=2vMEC-qw2V^PW30Gz+J$15QJJ-=Bt$YhWMBf>Hr&Co|!z~TQ>8M z^4+hVKYZDY>?MzuvT~5J+78%mB=;ZLtn5TIpUy*~QSN(VAXHOZZg;CHBs7DrUyxqP zp3Z+<{A_;%`5nbyI}zZB{A@@`9sr;s5Wd`iLv3TreV+(3?Sf$FVK z{KYoiK``Z+6$?6L$FfXC(6m3;cfxy+q_SrhEK|GWb9|aMk61fEb!`SN9+$!KowMc2 z$J^yW5{jKUuZEj_tLg`iUFt?(*>`3X9W*^AG#Qn&n|gC*e^A}x7w^O3DM8^|Gra|I z6B2h=-0z~ZU37m=s83zCxHq61A_rCqT?-NC(H&!IJY`=?;bu3Wj}RBH&DROlervSY zs7r4&=Yn*v){kJ!+xCAiRnPtM?0cqO@~uG^Rt_m9t%qr*Q?-WmHpDHjJgzO|FuO-I z(tr^a%67wF!+%9G+1O7o%Q=)Y?2UbgZvS}7;}26Ws5*!~9oahdJL)wkR&bNBE7ZyQ zMl3kZ{$}e(iq(w7X|24l=Q0=jou7$k*j#ZnRZ&zwQCHHnu04bMCRL3|#m;DVC9c&`#Vp|rMe5u{ z5TC5RlchC5521Zy@<)MG>L&>NudX-0Idk+7ewpj)qnR@BHc%2urW;|f{NkbaA%MCM zMz{*X+vmD`0#-X3>CV|=?u=f}^y2H9Sn~IXnAIsR@|bCGoLYsaN$BNT2{7f;`Sa<=NO)Vdnp3=kYS`A0}Xc-(N{Wn)K}{r>>XH2IfhO!t%n5u z(n*KVQSv!>8+5hZ#Z93D6{V0gxeGad13mS@k!NZf>pN`Dw2yObvojs9RSr^t+yfoW z*72#pDLrNkkm9LaHLC0fGKHcAUF;-z;a%^gC`px6r|`u%zMn&zmGC&n`JDRG10xR! z4WL%DnG%;Nx2UVEdmH3@eq%wRk{x)Zif|o7muGX#i2stE=n((oL|OH$Qe+j>(H-W@ z(FeQs2kHFE$vNr1U)F(q9|CdZB+6bOKd9bJ40p@2d?JHZUd;ZMW_iDl-}8Bs!3xMW z*d$=^;pW{`8~3PBdZ~@+HtyP(JaEFnYPMp6x@yZkXUskFg)^Ry-~wUA6OrIA>OID6 z7AgBx6hbnE>JCBAAMpKb{VI&gSMP!4$L|%hE}a!T5&4~5KPo!9iDCD_cz;U`ShBcy zRIJ<$&jK%nTqESxG=B9F`!XRpmGS5Q6qbesxo3VMwrYabY+l(laV_n@+z!?qOq~9vxni{ZP zUr-OE0$=-4rFo|%yX-@N2*6=iT#`n)V6JIbLB#u9_$T1Y$j-p?i{ikroNJHxweDo* zVUwzmhgs(fKZ>&kEHb39UhmhmxvruHbc82=oWxf_bo*Q+Ct!SJXYl!w3~Kj7fL9;v z4~nr@L6`Q6u}*ZbkZiBc$)!=(J_O+Q!Tz9_=|g~uG%DrQxxgi)E%wO>&VKRLRnW~o z*zb(&Mca3_f#=yccIXTc+fZHsnc?H~mo7y6qo6*;YY4_rKF6MSM*MJ*uNv`DPWev@ z0$ujr4Ivh^^qknDf5zeCMiHZqtGo& zRQ0^Hsy&U64R?piO8-OE6yQ_ey?Ts8wa%iop(m}>UIZEr=VSDrRTWeLL~G~w!s&i>>w-}2Gajt)jREf`0EqGcUHY(p(Y6MqZFw!e@D7i866Nc{`)^Iu3k zEwqWoLW~J%ZH$TQ7bac-B7lk73lj!f_nVKkaK7Zn&Y!VjYhS?fFJM|2SWG^~GwBOh z>IF>s0+x+|t(>ubR~u50oVp*Ls*4jm1(M{ z@;%yl4j7lwU=wrFi_x3{H_k_o+*i{&_jrtg~4PP)~ecBkaujnymYojsVPRe7x1RIRE z*ibagt>t)#dPT=76_oZnL3_2)^@39+TK2*$h5qh1?}+z47yxRUs% z3E`;Mv%)um78I^TG2Z=uhNueKEBLPodymcj>Pl(8Ytb`nWQlGOqUo@HyxDhX^Kh@S z>9|avNdBJGHOcrh<-jW5hn1cNcQ|j2*FT5a#}X&2C_})CB{p%31oX8YIcv!IMz=aq z=)8?;Yyr&%q0aR|>Y_V2dtg7-ydYrV1)8_Jx#G16~+(X!m*9dixBh*DF#e4<_ zAgdOnQEs!Ak$Xsi_tx8<-PW(tC}5QY)=&0T5XC+h!3h}mFH7r1F@rEq8pSGz^h459 zg8kwv>dL?htb@avGl-333nCx12|Opi6uAbKMn!yRb_G^qxmika?#10!a9A%<=OVXFwNiweeE zRPb48ugx*fgEYT)7VhyK7JAE%q4Ay2_e$&u1Hz|q>X^_PRM5ArU+qP8P;hs^{`08%Jh@^WNqHSkH_*F z9h^Gdp(dx*K8I@XkMk?M9Sl_8TB$9n`MgToROW+8!rLeKf5}ZSMG9_w&s3%yn|<2F zatqe+5v=6Pwl!)e)i;t%PD8qkGhF6L}^SpU?hsjNEmP`;k`KL{w#^@DG^;}%eM#c{SvkE8r1Cy2>>2TIl z0)rrV>p1jR9d){U6X<*q*O}eW-6jcB$j`U&8Qt5q0ZE{@c>y|3bY4s3p?llI3_$TY z`JC!Hy0=|tLBno?T*cMUl5Z{~WiKQ%F_I=~7|A}2q?~6wrh`3tg6Ymo*%$)}7ceC> z%=Q}4u~qU0B1#@$JX*Z~_+9`WUI0E_0Ms#dzUN`=+|^o#3ZqyV3jxU$ki~25yutai zg10-YZhEN!38bdkPb2q=dA}F_v~fPydi*&-l%ogMaivl{xA|Cy`mPSf$r82;n*b9S zJZBd+g8<}Caikbdk8h>p;pI`$H<4)^i1MY9b$Y>_>!B#Sh4CeS#6f41%?z{PP5!S} zCe?H0lE(KW4En|yl9bXYtnEqrmNYUN?D5(^1`wa#9;z+GV$9WW!buBaTqUEG$(_9- ziYwpuKse}WBdP1Ps1LufsAb^LD)I(RKKI98ft-w%J$KevL=LZ03~;Z(#N`@soQ6|U z>Wh%}-d(C_8-GpT&&SF8V{5-ICzHkeD$tqwc-teO=Dahqpui&Fh2FLbq=3GNFC2#C ze_yqBx>XVv?rD^=4Gk6KTppQn^-~Cj z{k$rvjDRtFR*!9KjfipI{QRa9-o}@D; zFuVVY_H(oLxkdeR0mrDEm`QV)+fV2uyE~-6CE@37(q)zT5G6>&#<&L`uL*7--OIhx z@v)x{NNd*Mt8LLe`s#CiXj|r=6Q_JT(;0z?bHZB09j?ycT6U7%GV!*~-M$heB2YtwoZor()^#X=t=3X`u;}w z|2;wq7fEp8*5CN}CkWgaFuAmmHkOy}rA3Q>LX68}+0b9g^23QaB$fX62c(ebUN zKat2k1pG^h8WS_SL&ES%JPd314t87cm4Ao8>|`jf0ANCfSKMJ(-|t`p1T7&01gB6n zjAEGi5y8gI%r^&D`@f&Owl?v52yK%Ld}ou1YsyniOWHr+wa>z<9>>Ug&A@Y{5b?yc z_lhQin1;i*=!R>({65=^_c|eLsl_3cO)sXoJVN7sR&gJgyV-4o+3Fa(KPIxY`uQib z$E3F05zm9we$c#S82(T^Y)n>)_bE((O0KYx#gyo8xc|?v!s3f%vV4gcmTd2<`x_Aa zO|(Tlb{M_m#D1{&^|t^F_VJuR8%eQ@zvmYd|5hjvXOU+2ATq7CB}x;X6H0~I zA{lHCq8nAVF%5>nINLP$oJQ^h*5F;86!-(yAtnM7-|X80SOdZ_Hu=1A7gxUrW-PRF z&;dUF`|0Qa(r*zME>1H&V0$sonkgj zds{n}&oeTQh6=WyNo{UBjs$o)yM5h+`HzM2A5??x*-K`Hx8I8Mv>MMU$$>}w9QSR5 z*H@qDpTcDkC1k#XhzXO*(-RBJ0SKy&w(e~&88_r<6wOQ>wxwKRjz#iG)^n(#DTOZB zb0H!NUd~C#d2m=V;`TkEvzR!N6AXg?U7+6A&fINyGX$PBRNy!g*?mN$FarW9YIpZ^ z>C*X9RNq`EmKMBp>7ho+PP3-Q(fonJ?m_e1p;~tbYY|nlwX+p_{#B2b%=vYna0*O* z2n>@gIReP9Fbcs1QjTrqC(T1!q#SlFjCzyQr4i*^{qsFxS_V^e{n$t)-AXIFLrt6Y z!?(jCequn(c8D7!Krg6s%9u%iKZDn-Eq_5yV7r@2xy_;_hDdR_gO`U_N@1M6ZSpRm zJ@~|w>fx{1j%~2G1aIJ#vDwK?$JoY+CS`M~8#9)i?RdxXHx1q&o-g3chkncunDQ@2 zen^o-)=q90rwn;Co%;@=enJc0i~QVVq4{-gSdR&iqsVRb&-z9*a zE8^l9y>c*FQM_b>nA1r87W$=TTr%5U ze)vc3R1?1Ke8A~`UdA`tbi2y#(9$T^eTHw{Lvt%$&Y(jZiFIMg4WnpLdyUmKh)VKW z(AsW{YqQCU3D2V9tpP!snoOvQWZDR%_=@MeNWh)phjX^;*!gv ziM|y3Lq-xGYrM5b+2EDUT9uAQuu4jW%8Vd_Uhr75Jy>$hqU`DE&uH*<7~-eu#-3^b zn8MJJrqVjDaJ9K~Tn>CxxDnSUAiMHJh&^TZe9JG2L%f=3)Kvyrb;Yqo3y+e6^E<>j zp;0a}a>vrZ!l{3rp_W>Q+Tah_yqdg4yj4KNxET%ZgH?6RW&(Q$Gz6GQSc4;h%>!Bw zHZrn+kQ10}Fv>fgRg0GxXPCk7O3~F-3)M*2$D;HP=_G{`0tWJ#M(jxC1?isJkCq-d zSyAxnfM_4W(+aN;WZ-Bl^S*a18>p!8m>Ur}>lHdy*iShU><)*^wnlo)fbJ66gV@If z6+^o^o-lF684ohGQ%ZWml?P9oDa$!IpBAY3urK7a4Vtb-{2)#fcb#xo)F0)4paDKC z;zmAWm-Jg*96ve?%qWu_h6|9l%DhHooGZc`21i;2Rch)5>~Ddty22Jk z-%^`F>N1ei>^Qa}W}!c?C?@dqrKxb)2qM1a_5{5A-n4@~#do4tMH$s?H-`d#g zK?x{{4`dt=_s%70*F*d)l^FaohP2!)`QlQT9h5Xbq|x<;Jaa`Xty(bpoqLAupHCku ziYYK39IqZC_Y8AI(tr8EMO8cRiL8l!LIz*+nzS^KT(B2=%3MRTE4)TEH7LYs7?<#I zHHgZN=0@C-*Sw)ZoQX+rX?F}K#a3~+gehs$VJpeTcJ9{oUty|J`|-@+7ZFqM#H%|u zn8XLwdX>FL^F%yzetA7m&EtM2&Tq@Rw%l_sjiZyDeo;kO^WzDJpTttfPB=y7BZX>S zU;H4V&&?d9>P3VZ*3L?=+^(JrJRjI!JFvUgb^*+nh*>F8-Kvva^_O=D*YuD9N z&b98lz2f_(+rb`+V1cz~CnhW;H7qbo`*SmEPN5BWirb#$Xr@};wMm}OWbWLOwJ`kv zm*lo2e_x#)FLh|U4Pvz})-4?BEfwG~C1?I*|LQ0~)k_<%)KhPGPj3 zcPhC&ZR6yaZExwO?-w}+Y@}UA=(0Lx$njObdl7ibZY=3`X<38v@3N2WxpZzBw?^j5 zL!vI5!>ON^_$frX3)?+j3U@XglC-4^UyE=cHJ90l)cDBp9%8}kVEN+rzaCAMmgM|) zVGRL;xflKO%0o_X3gjaBw3^6^C^&jFiFB&;puaJ-heOy5IM5vskO6vYk<(Y8>m~%B zHy(s->eb@wNY+xVYuVtzEJ{0d)y%#d^0)WvmI*hkIh=)mS}V*P(!MMe(I_Kcb{9+Xg$( zWy@2Vzp%2HZ^fkBNqd)FT5HGq6NJdSbl=6W)KbaUvy_VIiH0tp(_^67HnFooa0vU$ zF9FYl<|hvHk2&p4=G!cMLvHM3>8o28&LYI=JZNK&PU)gAZ{=bA!!);zd&PrGy2|HL zjsnG<$vR=8ZGUrX;jNgptv;uht|t?!(aqEHE1F)GgJmuUgV%Jx22t;zWPqcrT?Ze?K86WcjT%26b4-fpoOMxjGjw#e)Lh~SpGoRUyh6hccbBh2m0w`J%# zNA*5^zxvx=wSvAyRF^iyQp%-?pC`td!v<_x5?!J6i$ZQ9+o{RAhD<_goKw!~-B+cX z^kEfBJY;ecZ>D?zDHk$(%AEUK->2^a#JvcB_3-gTHkCx?*1)@pPa(ZqYDzTK2ZalU9c>}q~a$v4LmAw(UkU-!hDM^r;i9|#p0{|7T|)y!!LGm%zD+z zoo@m>p?0U7sfYpJa8~pNtMJBH3k<9}O<`;p)MPod` zWJoNDdpmW~FAcc3eA^fA@mGEkCm#Hf$ztmo*YYtnu6uiDma|>Y;|9pT&Ty;YgXaO9Zd0=+Sn0+D+w9HL|aOQq&zaX|>z>KEqbUz)KmaZ240Oqm0F|%M9;biMRUTP<`6Q>oK+16jqfuTwQUezBv zb9tzpZ>el?%gy6$N%P;Ei(^o;@f}w5Sa@67c?h}7_Ymx4QaS@lNr}Oe^ z$h8-B2C!r2XVCr9MHQ?wyK+k!&(kDw?c?W#;|2y#YWP*}P4nVh+bOk}UGs4yg9niP z{3!C`wqvq`CY2+VN5TMi5ravNNY*XKB!^lW$0XBq3gBu$Xq>y7bl9^=dN*`=(gtdx zU1`WS&E331X%BYTu&OnTc;Epw{Fc}1Swps<05zPvG_U;9_?I*OY3pL>SpHZVO21s} z@s3aaf$j3tuj%56J}Q{)?8DI@2qVQLZRzZC7_N{!dsS5laCQF_r%C||Txb#6_frns z4K8}#dl#8d^B5nGfwpSab#}SvvXDo0$||~J>)bR%uPiSz(TiJ0%Iboig35kVfuCER z&sX_S`|bw^@9*!;)Su2d&ZxprHj?jAD8KWC4SN41HjRQ7$W_tnI(CN8Hut~@Z-Y{| zer&@;whCZ;cDghV%MmDbl5?bWM!{sMQsu|9oyJxR<>Lx&lMlu_1h5|ty40b5xvcs- zXzMgZ+0j*bWQlCiJ5p77;LsruDZB^$k($GK^e}}!|Ed&3CN43fLAOsowis^P!lA(< zJ!pf;>qv!23SnLRtK)R{tbJlWY_*5+EA$;2bf5lwDFDZ;B9hZ!6MI1W4FIVC?fVz7R5=jl+eu$JmJG)P#B zWL{GuOoM20?j!pO@yNNF_inr1VjaHHO3>FS!sip+PIu_~zl#G^7^tQVlZTd+%Kml< zl+avPMK6H&#jVh>mZFekbPWP6(2M-GbjV)`Vs=Jg`B*B}cSJ#GYv2-#~z~ zR=+3QRnYH=_8Bl&0IHr~RA~aU2u%0`uxSERC16y22Ih?bn^!{U(>cNlXd~HyKOX@* z2VTt4JANn_9kr$T@C4I5U(M0YbN|*w7HEc{)=beE@XRw7#a#q=+-i3nt;{kQZHDI- z+Dz2g9kiJwA|4K+vb#V)3OG3wX(ouNY`F~D!z3cKhyN9tZ6b*F!v&}*KMuNaKHbI0 z6Jg}7uK@Dk*buZuAi4z(3Aqj&XHvR)i)sYOUgk*UWQz{~=haRqJqST)15tD6u6KuO zI>^|QAZU)`N=W5jiQi?c62(F=y|Q%&-Iceg>d}?B-Gu4NW=Cirf0sq;o8<9DyY^>6 z!jl*c?wG;Q(}U44=7rH9hBo_PEpY+J(gM%j@J>dkS3y?)jnMiK03@5)EX?;Mn1}Xm z?h)YX?^`^sC{pxSdLamW4*iQsMFy1;bdI|VV{b#1-9dE*opBNTAt8niwg>3Ope$t0 z!MMjDia$+=#Gsa>&%u|ELBxvz|1m_T3<~={%cK9W2KxW*{PR9rJ$M8H)varHJ9r=} zH(<3@-}DYaFv1EFn||W(Qu}nO6_xpN_xDLfs}zm=J@irJQ@&OQ(I2ZP3+a8${wAdD z+kv|{`#6BuVSnZCvZAq7lu5Y(Jao(NYvggw#-A;~mukq!cO}*g_3LkW$ek6iar?5na9W3(c6v(qK2t%M|;k zFQ0Wx%4SdPO5r`un=tr-$Pd+CjHcJ~9zRZFB;in*m=sb0FHVR4AWK#m=ii9!@zM!# z>EAa*IExooc2+ixg+fe_ph`$Vr}uMyodV>MhSJQ64G%}pVt;p(ctt2BQ}osj$5yCU zz$Xcqp3p?($6NB($ZtN-I*(87kS4zrddXTbXDs0@xy%W#Bjn7Ns*x`-F-~Q_qjQ(4|ovZ#i%!G z8EtI>k;u#*-8?R&wBwp_V)`&gm2u*tC=1)HL>XO%g^d`!yuKRm)#h$p(aTf*h2MOR z`Rz^y^fYoyIl~4{*Cow4Tgn1>7H6;^)`@Jt!*k z4eo6@f{9-g9Coex&<2}Srqv@|t|}_+U{g4sAd0*Hw~B_zGvSLuKA^v{QKb) z6gcD@>{nRzo?q95N|!I9i^SV&g>hKTKa6KM3c;%opvzHWb4%WR<6OhokM)l&s$Q8Y zhz7@Wrfdam%TGQ=25zu4ItqWdCZkMPWb4j$U+lltj`k$T5H zU#J=O;8Z%j-pwNF0#_ZZ%MkCIR;3$#H*?Tyjzw%x zdZLBkJ$!F<(?YgbL9xk0Zm8jUq>1q2W690cneg59i38I;$L`Q>t$Ql6;BehQn*;JB zZP34!J=db#l`%uPo{7h22nr%;ev}CpHiZ7kFx?kuY z4w*8XcRyY>xHK)|GANn*`J3$_U)8|OR*@mS_dUn)ud^>*`8T3Mo&9t5-A5>zpV7lW zy@RbC3%0uJA-7)+#Y4I?O#a)cS&(Np_={|Ow_$!ig>f8en9D1uPt=D+#}4vJn*Q3?`Meep1R5&!Lza6RB8kJ%V-7j|(@C_@Ev^* zihcpZQ+zobxRLqmiyIFuIHv4nX%ip%m2YM6lru<(^=y7%@H{E-Pb_iMyDg=?pW!vu zn>ZPxz5MezGN4CJYVcDS86aFxTkl@x^`w-Vs>i`Y^m`M)KY%wQ@bY^q5E55@`1!z_Lc7r`O za46v3eRS~~j?71qVzD=>RPOYDr%==V+~5xiMAl=U*5#-hY7%TBQW!6*ag@y1KCzbj z+Thj|N$^tUoy%cCgm)fO8{c=2&VmmmbOBUB{*V)5IdqBblet zWdFh0J$xj=ANk17(ngvZd3LH8+7NAyax=8*H0i%*0ebzz^^3}Q%<&I$cau=#Ao`9P zxIW1#p(3>8 z<1;9k>>QPawUFx`D1>AWsV;j<)P>#8rvbMMEZ_TWrqhLX7uxGPcJGawuBm}TT#f+e znu{4SQ124&BxnnqF=~lSKs?U$6dSErQj4(zI7+W@7~WdS&8P}s-76AA-~y6`ciZTI5Cf0 z2Fu9cP{X>QWwW&~O{(u!Eiy&U9j+(+^&b^;1L{CW86k+%P_XyW3eT6J68~~3)QLrU zIzO}MR`ZE4bIPQ$e+%;?<`^2OKoD1AQ@)O}ps9Mqnyc~?p0o%>q;`)2C`V;^SMJ71 zZGu(2pyD9dEB4fXRcQk8<(CIY*H3B_rFFh#xl047qQheJvgq1pKP>S#azN;Guh*Ca z)UO4+7#~_-q{?B5de=yAA$K&dw|odzttkyS8xD9gU`y9A6QQ0w>qFlwWFHYs5R-DS^WM=jhIs&qkYcvSE&bAheZ&H@ApA?%ORHVe_mCf< zmwCAz2Y*o7L)ga)2_kt7&4W+hF@9m3xjQx7yUL=;YKaw1(YmF@7N<8f`b%L$aiQ;h zcs;#ub=x;d#qPd#z61M#lt$*eS;$QBk}cxmvu=;=Z(F-AC@}DrZk7-6>5G@n)w-QJ z@bKIhp6t8r^a5tm z5O=G^xi=@}6W=Exl#5ucp+k|okZNE67BeNWi2begN(n6D4#Bi_OWFlJ+Iahpv<*@Y zpkS%zAdCXv0^+jb{fNL-XWIaHyuf(Hqevbq%rX%#HUiw;6v>J%?Don132|k zRlBOrUiQ!LX1H*3Ce!05NT@}2%6D-L!{snJI66sx(~pdUlb*-JK+<%(%J;{a=iCJF zBm~Y_Y0Ihyl=W<-L<}n~9QNP1k<0$VpJ>Z}a_M-&gy&Ua1_!Mb=NpYACEvAnF7K$p z(STk#)to7s+avRYs$aWlhUN*2Swx!Hs@893Hd7mYRJ