diff --git a/include/reclasses/CTFPlayerShared.hpp b/include/reclasses/CTFPlayerShared.hpp new file mode 100644 index 00000000..610d1647 --- /dev/null +++ b/include/reclasses/CTFPlayerShared.hpp @@ -0,0 +1,13 @@ +class CTFPlayerShared +{ +public: + inline static float GetCritMult(CTFPlayerShared *self) + { + return ((fminf(fmaxf(*(unsigned(self) + 672) * 0.0039215689f, 0.0f), 1.0f) * 3.0f) + 1.0f); + } + inline static bool IsCritBoosted(CTFPlayerShared *self) + { + // TODO signature + return false; + } +}; \ No newline at end of file diff --git a/include/reclasses/C_BaseEntity.hpp b/include/reclasses/C_BaseEntity.hpp index 3aec4f3b..9cb7cddf 100644 --- a/include/reclasses/C_BaseEntity.hpp +++ b/include/reclasses/C_BaseEntity.hpp @@ -15,6 +15,11 @@ public: typedef bool(*fn_t)(IClientEntity *); return vfunc(self, offsets::PlatformOffset(184, offsets::undefined, 184), 0)(self); } + inline int& m_nPredictionRandomSeed() + { + static int placeholder = 0; + return placeholder; + } }; diff --git a/include/reclasses/C_BasePlayer.hpp b/include/reclasses/C_BasePlayer.hpp new file mode 100644 index 00000000..77ca47bc --- /dev/null +++ b/include/reclasses/C_BasePlayer.hpp @@ -0,0 +1,8 @@ +class C_BasePlayer: public C_BaseEntity +{ +public: + inline static CTFPlayerShared& shared_(IClientEntity *self) + { + return *((CTFPlayerShared *)(unsigned(self) + 6092)) + } +}; \ No newline at end of file diff --git a/include/reclasses/C_TFWeaponBase.hpp b/include/reclasses/C_TFWeaponBase.hpp index 39a4a04f..c7042b60 100644 --- a/include/reclasses/C_TFWeaponBase.hpp +++ b/include/reclasses/C_TFWeaponBase.hpp @@ -40,6 +40,59 @@ public: typedef bool(*fn_t)(IClientEntity *); return vfunc(self, offsets::PlatformOffset(461, offsets::undefined, 461), 0)(self); } + inline static bool CanFireCriticalShot(IClientEntity *self, bool unknown1, IClientEntity *unknown2) + { + typedef bool(*fn_t)(IClientEntity *, bool, IClientEntity *); + return vfunc(self, offsets::PlatformOffset(489, offsets::undefined, 489), 0)(self, unknown1, unknown2); + } + inline static void AddToCritBucket(IClientEntity *self, float value) + { + constexpr float max_bucket_capacity = 1000.0f; + bucket = fminf(bucket_() + value, max_bucket_capacity); + } + inline static bool IsAllowedToWithdrawFromCritBucket(IClientEntity *self, float value) + { + uint16_t weapon_info_handle = weapon_info_handle_(self); + void *weapon_info = nullptr; // GetFileWeaponInfoFromHandle(weapon_info_handle); + /* + if (!weapon_info->unk_1736) + { + + } + */ + } + inline static bool CalcIsAttackCriticalHelper_re(IClientEntity *self) + { + IClientEntity *owner = GetOwnerViaInterface(self); + + if (owner == nullptr) + return false; + + if (!C_BaseEntity::IsPlayer(owner)) + return false; + + CTFPlayerShared *shared = C_BasePlayer::shared_(owner); + float critmult = CTFPlayerShared::GetCritMult(shared); + if (!CanFireCriticalShot(self, 0, nullptr)) + return false; + + if (CTFPlayerShared::IsCritBoosted(shared)) + return true; + + + float multiplier = 0.5f; + int seed = C_BaseEntity::m_nPredictionRandomSeed() ^ (owner->entindex() | self->entindex()); + RandomSeed(seed); + + bool result = true; + if (multiplier * 10000.0f <= RandomInt(0, 9999)) + { + result = false; + multiplier = 0.0f; + } + + return false; + } inline static int CalcIsAttackCritical(IClientEntity *self) { IClientEntity *owner = GetOwnerViaInterface(self); @@ -78,6 +131,10 @@ public: return 0; } + inline static uint16_t& weapon_info_handle_(IClientEntity *self) + { + return *(uint16_t *)(unsigned(self) + 2750u); + } inline static float& crit_bucket_(IClientEntity *self) { return *(float *)(unsigned(self) + 2616u); diff --git a/include/reclasses/reclasses.hpp b/include/reclasses/reclasses.hpp index 14140341..36f3342a 100644 --- a/include/reclasses/reclasses.hpp +++ b/include/reclasses/reclasses.hpp @@ -13,6 +13,8 @@ namespace re { #include "C_BaseEntity.hpp" +#include "CTFPlayerShared.hpp" +#include "C_BasePlayer.hpp" #include "C_BaseCombatWeapon.hpp" #include "C_TFWeaponBase.hpp" #include "C_TFWeaponBaseMelee.hpp"