diff --git a/code/components/extra-natives-rdr3/src/WeaponExtraNatives.cpp b/code/components/extra-natives-rdr3/src/WeaponExtraNatives.cpp new file mode 100644 index 0000000000..2078813445 --- /dev/null +++ b/code/components/extra-natives-rdr3/src/WeaponExtraNatives.cpp @@ -0,0 +1,64 @@ +#include "StdInc.h" + +#include "ClientConfig.h" +#include "Hooking.h" +#include "Hooking.Stubs.h" + +static hook::cdecl_stub getLocalPlayerPed([]() +{ + static const auto addr = hook::get_pattern("E8 ? ? ? ? 48 85 C0 74 ? 48 8B D3 48 8B C8 E8 ? ? ? ? 84 C0 74 ? F3 0F 10 05"); + return hook::get_call( addr ); +}); + +struct CWeapon +{ + char gap_0[0x10]; // 0x00 - 0x0F + __int16 pad_10; // 0x10 + char gap_12[0x4E]; // 0x12 - 0x5F + + void* m_pWeaponInfo; // 0x60 + uint32_t m_weaponHash; // 0x68 + __int16 pad_6C; // 0x6C + char gap_6E[0x2A]; // 0x6E - 0x97 + + unsigned int m_uGlobalTime; // 0x98 + unsigned int m_uTimer; // 0x9C + char gap_A0[0x6]; // 0xA0 - 0xA5 + + __int16 m_iAmmoTotal; // 0xA6 + char gap_A8[0x40]; // 0xA8 - 0xE7 + + void* m_pDrawableEntity; // 0xE8 + void* m_pObserver; // 0xF0 + char gap_F8[0x8]; // 0xF8 - 0xFF +}; + +static bool ( *origGetNeedsToReload )( CWeapon*, bool ); +static bool GetNeedsToReload( CWeapon* thisptr, bool reloadWhenZero) +{ + using GetOwnerFn = const void* (__fastcall*)(void* self); + bool localPlayer = thisptr->m_pObserver == nullptr; + + if (thisptr->m_pObserver) + { + const void* owner = reinterpret_cast( + (*reinterpret_cast(thisptr->m_pObserver))[0x58 / 8] + )(thisptr->m_pObserver); + + localPlayer = owner == getLocalPlayerPed(); + } + if (!IsClientConfigEnabled(ClientConfigFlag::WeaponsNoAutoReload) || !localPlayer) + { + return origGetNeedsToReload( thisptr, reloadWhenZero ); + } + + return false; +} + +static HookFunction hookFunction([]() +{ + // Disable auto reload + { + origGetNeedsToReload = hook::trampoline(hook::get_call(hook::get_pattern("E8 ? ? ? ? 84 C0 74 ? 48 85 F6 0F 84 ? ? ? ? 41 8A D4")), GetNeedsToReload); + } +}); \ No newline at end of file