diff --git a/include/WeaponData.hpp b/include/WeaponData.hpp new file mode 100644 index 00000000..f8d7a9ad --- /dev/null +++ b/include/WeaponData.hpp @@ -0,0 +1,84 @@ +#include "common.hpp" + +#pragma once + +struct WeaponData_t +{ + int m_nDamage; + int m_nBulletsPerShot; + float m_flRange; + float m_flSpread; + float m_flPunchAngle; + float m_flTimeFireDelay; // Time to delay between firing + float m_flTimeIdle; // Time to idle after firing + float m_flTimeIdleEmpty; // Time to idle after firing last bullet in clip + float m_flTimeReloadStart; // Time to start into a reload (ie. shotgun) + float m_flTimeReload; // Time to reload + bool m_bDrawCrosshair; // Should the weapon draw a crosshair + int m_iProjectile; // The type of projectile this mode fires + int m_iAmmoPerShot; // How much ammo each shot consumes + float m_flProjectileSpeed; // Start speed for projectiles (nail, etc.); NOTE: union with something non-projectile + float m_flSmackDelay; // how long after swing should damage happen for melee weapons + bool m_bUseRapidFireCrits; +}; + +class weapon_info +{ +public: + float crit_bucket{}; + unsigned int weapon_seed{}; + unsigned unknown1{}; + unsigned unknown2{}; + bool unknown3{}; + float unknown4{}; + int crit_attempts{}; + int crit_count{}; + float observed_crit_chance{}; + bool unknown7{}; + int weapon_mode{}; + int weapon_data{}; + weapon_info() + { + } + void Load(IClientEntity *weapon) + { + crit_bucket = *(float *) ((uintptr_t) weapon + 0xa38); + weapon_seed = *(unsigned int *) ((uintptr_t) weapon + 0xb3c); + unknown1 = *(unsigned int *) ((uintptr_t) weapon + 0xb30); + unknown2 = *(unsigned int *) ((uintptr_t) weapon + 0xb34); + unknown3 = *(bool *) ((uintptr_t) weapon + 0xb17); + unknown4 = *(float *) ((uintptr_t) weapon + 0xb40); + crit_attempts = *(int *) ((uintptr_t) weapon + 0xa3c); + crit_count = *(int *) ((uintptr_t) weapon + 0xa40); + observed_crit_chance = *(float *) ((uintptr_t) weapon + 0xbfc); + unknown7 = *(bool *) ((uintptr_t) weapon + 0xb18); + // No need to restore + weapon_mode = *(int *) ((uintptr_t) weapon + 0xb04); + weapon_data = *(int *) ((uintptr_t) weapon + 0xb10); + } + weapon_info(IClientEntity *weapon) + { + Load(weapon); + } + void restore_data(IClientEntity *weapon) + { + *(float *) ((uintptr_t) weapon + 0xa38) = crit_bucket; + *(unsigned int *) ((uintptr_t) weapon + 0xb3c) = weapon_seed; + *(unsigned int *) ((uintptr_t) weapon + 0xb30) = unknown1; + *(unsigned int *) ((uintptr_t) weapon + 0xb34) = unknown2; + *(bool *) ((uintptr_t) weapon + 0xb17) = unknown3; + *(float *) ((uintptr_t) weapon + 0xb40) = unknown4; + *(int *) ((uintptr_t) weapon + 0xa3c) = crit_attempts; + *(int *) ((uintptr_t) weapon + 0xa40) = crit_count; + *(float *) ((uintptr_t) weapon + 0xbfc) = observed_crit_chance; + *(bool *) ((uintptr_t) weapon + 0xb18) = unknown7; + } +}; + +inline WeaponData_t *GetWeaponData(IClientEntity *weapon) +{ + weapon_info info(weapon); + int WeaponData = info.weapon_data; + int WeaponMode = info.weapon_mode; + return (WeaponData_t *) (WeaponData + sizeof(WeaponData_t) * WeaponMode + 1784); +} diff --git a/include/crits.hpp b/include/crits.hpp index 711464f7..a116e036 100644 --- a/include/crits.hpp +++ b/include/crits.hpp @@ -11,57 +11,4 @@ extern int current_index; extern bool isEnabled(); extern bool force_crit_this_tick; void fixBucket(IClientEntity *weapon, CUserCmd *cmd); - -class weapon_info -{ -public: - float crit_bucket{}; - unsigned int weapon_seed{}; - unsigned unknown1{}; - unsigned unknown2{}; - bool unknown3{}; - float unknown4{}; - int crit_attempts{}; - int crit_count{}; - float observed_crit_chance{}; - bool unknown7{}; - int weapon_mode{}; - int weapon_data{}; - weapon_info() - { - } - void Load(IClientEntity *weapon) - { - crit_bucket = *(float *) ((uintptr_t) weapon + 0xa38); - weapon_seed = *(unsigned int *) ((uintptr_t) weapon + 0xb3c); - unknown1 = *(unsigned int *) ((uintptr_t) weapon + 0xb30); - unknown2 = *(unsigned int *) ((uintptr_t) weapon + 0xb34); - unknown3 = *(bool *) ((uintptr_t) weapon + 0xb17); - unknown4 = *(float *) ((uintptr_t) weapon + 0xb40); - crit_attempts = *(int *) ((uintptr_t) weapon + 0xa3c); - crit_count = *(int *) ((uintptr_t) weapon + 0xa40); - observed_crit_chance = *(float *) ((uintptr_t) weapon + 0xbfc); - unknown7 = *(bool *) ((uintptr_t) weapon + 0xb18); - // No need to restore - weapon_mode = *(int *) ((uintptr_t) weapon + 0xb04); - weapon_data = *(int *) ((uintptr_t) weapon + 0xb10); - } - weapon_info(IClientEntity *weapon) - { - Load(weapon); - } - void restore_data(IClientEntity *weapon) - { - *(float *) ((uintptr_t) weapon + 0xa38) = crit_bucket; - *(unsigned int *) ((uintptr_t) weapon + 0xb3c) = weapon_seed; - *(unsigned int *) ((uintptr_t) weapon + 0xb30) = unknown1; - *(unsigned int *) ((uintptr_t) weapon + 0xb34) = unknown2; - *(bool *) ((uintptr_t) weapon + 0xb17) = unknown3; - *(float *) ((uintptr_t) weapon + 0xb40) = unknown4; - *(int *) ((uintptr_t) weapon + 0xa3c) = crit_attempts; - *(int *) ((uintptr_t) weapon + 0xa40) = crit_count; - *(float *) ((uintptr_t) weapon + 0xbfc) = observed_crit_chance; - *(bool *) ((uintptr_t) weapon + 0xb18) = unknown7; - } -}; } // namespace criticals diff --git a/src/crits.cpp b/src/crits.cpp index e1d21a61..809bf418 100644 --- a/src/crits.cpp +++ b/src/crits.cpp @@ -1,6 +1,7 @@ #include "common.hpp" #include "crits.hpp" #include "Backtrack.hpp" +#include "WeaponData.hpp" #include "netadr.h" std::unordered_map command_number_mod{}; @@ -493,20 +494,13 @@ static void updateCmds() if (added_per_shot == 0.0f || previous_weapon != weapon->entindex()) { weapon_info info(weapon); - - // m_pWeaponInfo->GetWeaponData(m_iWeaponMode).m_nBulletsPerShot; - - int WeaponData = info.weapon_data; - int WeaponMode = info.weapon_mode; - // Size of one WeaponMode_t is 0x40, 0x6fc is the offset to projectiles per shot - int nProjectilesPerShot = *(int *) (WeaponData + 0x6fc + WeaponMode * 0x40); + int nProjectilesPerShot = GetWeaponData(weapon)->m_nBulletsPerShot; if (nProjectilesPerShot >= 1) nProjectilesPerShot = ATTRIB_HOOK_FLOAT(nProjectilesPerShot, "mult_bullets_per_shot", weapon, 0x0, true); else nProjectilesPerShot = 1; - // Size of one WeaponMode_t is 0x40, 0x6f8 is the offset to damage - added_per_shot = *(int *) (WeaponData + 0x6f8 + WeaponMode * 0x40); + added_per_shot = GetWeaponData(weapon)->m_nDamage; added_per_shot = ATTRIB_HOOK_FLOAT(added_per_shot, "mult_dmg", weapon, 0x0, true); added_per_shot *= nProjectilesPerShot; shots_to_fill_bucket = getBucketCap() / added_per_shot; @@ -514,8 +508,7 @@ static void updateCmds() if (isRapidFire(weapon)) { taken_per_crit = added_per_shot; - // Size of one WeaponMode_t is 0x40, 0x70c is the offset to Fire delay - taken_per_crit *= 2.0f / *(float *) (WeaponData + 0x70c + WeaponMode * 0x40); + taken_per_crit *= 2.0f / GetWeaponData(weapon)->m_flTimeFireDelay; // Yes this looks dumb but i want to ensure that it matches with valve code int bucket_cap_recasted = (int) getBucketCap(); diff --git a/src/helpers.cpp b/src/helpers.cpp index cffaea2c..6c6d4a2a 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -12,6 +12,7 @@ #include "MiscTemporary.hpp" #include "PlayerTools.hpp" #include "Ragdolls.hpp" +#include "WeaponData.hpp" static settings::Boolean tcm{ "debug.tcm", "true" }; static settings::Boolean should_correct_punch{ "debug.correct-punch", "true" }; @@ -838,9 +839,8 @@ void AngleVectors3(const QAngle &angles, Vector *forward, Vector *right, Vector bool isRapidFire(IClientEntity *wep) { - criticals::weapon_info info(wep); - // Taken from game, m_pWeaponInfo->GetWeaponData( m_iWeaponMode ).m_bUseRapidFireCrits; - bool ret = *(bool *) (info.weapon_data + 0x734 + info.weapon_mode * 0x40); + weapon_info info(wep); + bool ret = GetWeaponData(wep)->m_bUseRapidFireCrits; // Minigun changes mode once revved, so fix that return ret || wep->GetClientClass()->m_ClassID == CL_CLASS(CTFMinigun); } @@ -1606,7 +1606,7 @@ float ATTRIB_HOOK_FLOAT(float base_value, const char *search_string, IClientEnti { typedef float (*AttribHookFloat_t)(float, const char *, IClientEntity *, void *, bool); - static uintptr_t AttribHookFloat = gSignatures.GetClientSignature("55 89 E5 57 56 53 83 EC 6C C7 45 ? 00 00 00 00 A1 ? ? ? ? C7 45 ? 00 00 00 00 8B 75 ? 85 C0 0F 84 ? ? ? ? 8D 55 ? 89 04 24 31 DB 89 54 24"); + static uintptr_t AttribHookFloat = e8call_direct(gSignatures.GetClientSignature("E8 ? ? ? ? 8B 96 ? ? ? ? D9 5D")); static auto AttribHookFloat_fn = AttribHookFloat_t(AttribHookFloat); return AttribHookFloat_fn(base_value, search_string, ent, buffer, is_global_const_string); diff --git a/src/nospread.cpp b/src/nospread.cpp index 293e9da3..7001e888 100644 --- a/src/nospread.cpp +++ b/src/nospread.cpp @@ -28,34 +28,7 @@ #include "usercmd.hpp" #include "MiscTemporary.hpp" #include "AntiAim.hpp" - -struct WeaponData_t -{ - int m_nDamage; - int m_nBulletsPerShot; - float m_flRange; - float m_flSpread; - float m_flPunchAngle; - float m_flTimeFireDelay; // Time to delay between firing - float m_flTimeIdle; // Time to idle after firing - float m_flTimeIdleEmpty; // Time to idle after firing last bullet in clip - float m_flTimeReloadStart; // Time to start into a reload (ie. shotgun) - float m_flTimeReload; // Time to reload - bool m_bDrawCrosshair; // Should the weapon draw a crosshair - int m_iProjectile; // The type of projectile this mode fires - int m_iAmmoPerShot; // How much ammo each shot consumes - float m_flProjectileSpeed; // Start speed for projectiles (nail, etc.); NOTE: union with something non-projectile - float m_flSmackDelay; // how long after swing should damage happen for melee weapons - bool m_bUseRapidFireCrits; -}; - -WeaponData_t *GetWeaponData(IClientEntity *weapon) -{ - criticals::weapon_info info(weapon); - int WeaponData = info.weapon_data; - int WeaponMode = info.weapon_mode; - return (WeaponData_t *) (WeaponData + sizeof(WeaponData_t) * WeaponMode + 1784); -} +#include "WeaponData.hpp" namespace hacks::tf2::nospread {