Improve crithack and fix nospread with crithack

This commit is contained in:
BenCat07 2020-04-24 18:04:20 +02:00
parent ad4d09ce86
commit 85eeffa9e9
4 changed files with 64 additions and 21 deletions

View File

@ -4,4 +4,8 @@ namespace criticals
{ {
extern settings::Boolean enabled; extern settings::Boolean enabled;
extern settings::Boolean melee; extern settings::Boolean melee;
extern std::vector<int> crit_cmds;
extern int current_index;
extern bool isEnabled();
extern settings::Boolean old_mode;
} // namespace criticals } // namespace criticals

View File

@ -12,7 +12,7 @@ public:
// Convert IClientEntity to CTFPlayerShared // Convert IClientEntity to CTFPlayerShared
inline static CTFPlayerShared *GetPlayerShared(IClientEntity *ent) inline static CTFPlayerShared *GetPlayerShared(IClientEntity *ent)
{ {
return (CTFPlayerShared *) ((uintptr_t) ent + 0x5f3); return (CTFPlayerShared *) (((uintptr_t) ent) + 0x17cc);
} }
inline static bool IsDominatingPlayer(CTFPlayerShared *self, int ent_idx) inline static bool IsDominatingPlayer(CTFPlayerShared *self, int ent_idx)
{ {
@ -30,7 +30,7 @@ public:
{ {
static auto signature = gSignatures.GetClientSignature("55 89 E5 57 56 53 83 EC 6C 8B 7D ? C7 44 24 ? 0B 00 00 00"); static auto signature = gSignatures.GetClientSignature("55 89 E5 57 56 53 83 EC 6C 8B 7D ? C7 44 24 ? 0B 00 00 00");
typedef bool (*IsCritBoosted_t)(CTFPlayerShared *); typedef bool (*IsCritBoosted_t)(CTFPlayerShared *);
IsCritBoosted_t IsCritBoosted_fn = (IsCritBoosted_t) signature; static IsCritBoosted_t IsCritBoosted_fn = (IsCritBoosted_t) signature;
return IsCritBoosted_fn(self); return IsCritBoosted_fn(self);
} }
}; };

View File

@ -10,7 +10,7 @@ settings::Boolean enabled{ "crit.enabled", "false" };
static settings::Boolean draw{ "crit.draw-info", "false" }; static settings::Boolean draw{ "crit.draw-info", "false" };
settings::Boolean melee{ "crit.melee", "false" }; settings::Boolean melee{ "crit.melee", "false" };
static settings::Button crit_key{ "crit.key", "<null>" }; static settings::Button crit_key{ "crit.key", "<null>" };
static settings::Boolean old_mode{ "crit.old-mode", "false" }; settings::Boolean old_mode{ "crit.old-mode", "false" };
// How much is added to bucket per shot? // How much is added to bucket per shot?
static float added_per_shot = 0.0f; static float added_per_shot = 0.0f;
@ -245,7 +245,7 @@ static bool randomCritEnabled()
static int force_ticks = 0; static int force_ticks = 0;
// Is the hack enabled? // Is the hack enabled?
static bool isEnabled() bool isEnabled()
{ {
// No crits without random crits // No crits without random crits
if (!randomCritEnabled()) if (!randomCritEnabled())
@ -260,7 +260,7 @@ static bool isEnabled()
} }
// We cycle between the crit cmds so we want to store where we are currently at // We cycle between the crit cmds so we want to store where we are currently at
static std::vector<int> crit_cmds; std::vector<int> crit_cmds;
// We need to store a bunch of data for when we kill someone with a crit // We need to store a bunch of data for when we kill someone with a crit
struct player_status struct player_status
@ -269,6 +269,7 @@ struct player_status
bool was_jarated{}; bool was_jarated{};
bool was_markedfordeath{}; bool was_markedfordeath{};
}; };
int current_index = 0;
static std::array<player_status, 33> player_status_list{}; static std::array<player_status, 33> player_status_list{};
// Main function that forces a crit // Main function that forces a crit
@ -284,8 +285,7 @@ void force_crit()
// We have valid crit command numbers // We have valid crit command numbers
if (crit_cmds.size()) if (crit_cmds.size())
{ {
static int current_index = 0; if (current_index >= crit_cmds.size())
if (current_index > crit_cmds.size())
current_index = 0; current_index = 0;
// Magic crit cmds get used to force a crit // Magic crit cmds get used to force a crit
@ -315,7 +315,7 @@ void force_crit()
} }
// For everything else, wait for the crit cmd // For everything else, wait for the crit cmd
else if (current_late_user_cmd->command_number != next_crit) else if (current_late_user_cmd->command_number != next_crit)
current_user_cmd->buttons &= ~IN_ATTACK; current_late_user_cmd->buttons &= ~IN_ATTACK;
} }
} }
} }
@ -442,9 +442,14 @@ static void fixBucket(IClientEntity *weapon)
// Local server needs no fixing // Local server needs no fixing
if (addr.type == NA_LOOPBACK) if (addr.type == NA_LOOPBACK)
return; return;
// Melee doesn't either
// Melee doesn't Need fixing either, still needs firetime though
if (g_pLocalPlayer->weapon_mode == weapon_melee) if (g_pLocalPlayer->weapon_mode == weapon_melee)
{
if (g_pLocalPlayer->weapon_melee_damage_tick)
shot_weapon_mode = weapon_melee;
return; return;
}
static float last_bucket; static float last_bucket;
static int last_weapon; static int last_weapon;
@ -500,6 +505,9 @@ static void fixBucket(IClientEntity *weapon)
info.restore_data(weapon); info.restore_data(weapon);
} }
// Beggars
static bool should_crit_beggars = false;
static bool attacked_last_tick = false;
void CreateMove() void CreateMove()
{ {
// We need to update player states regardless, else we can't sync the observed crit chance // We need to update player states regardless, else we can't sync the observed crit chance
@ -541,8 +549,22 @@ void CreateMove()
if (!re::C_TFWeaponBase::CanFireCriticalShot(weapon, false, nullptr)) if (!re::C_TFWeaponBase::CanFireCriticalShot(weapon, false, nullptr))
return; return;
// Beggars check
if (CE_INT(LOCAL_W, netvar.iItemDefinitionIndex) == 730)
{
// Check if we released the barrage by releasing m1, also lock bool so people don't just release m1 and tap it again
if (!should_crit_beggars)
should_crit_beggars = !(current_late_user_cmd->buttons & IN_ATTACK) && attacked_last_tick;
// Update
attacked_last_tick = current_user_cmd->buttons & IN_ATTACK;
if (!CE_INT(LOCAL_W, netvar.m_iClip1))
{
// Reset
should_crit_beggars = false;
}
}
// Should we force crits? // Should we force crits?
if (force_ticks || (CanShoot() && current_late_user_cmd->buttons & IN_ATTACK)) if (force_ticks || should_crit_beggars || (CanShoot() && current_late_user_cmd->buttons & IN_ATTACK))
{ {
// Can we crit? // Can we crit?
if (canWeaponWithdraw(RAW_ENT(LOCAL_W))) if (canWeaponWithdraw(RAW_ENT(LOCAL_W)))
@ -653,23 +675,27 @@ public:
int victim = g_IEngine->GetPlayerForUserID(event->GetInt("userid")); int victim = g_IEngine->GetPlayerForUserID(event->GetInt("userid"));
if (victim != g_pLocalPlayer->entity_idx) if (victim != g_pLocalPlayer->entity_idx)
{ {
// This is only ranged damage and crit boost does not count towards it either // This is only ranged damage
if (shot_weapon_mode != weapon_melee && !re::CTFPlayerShared::IsCritBoosted(re::CTFPlayerShared::GetPlayerShared(RAW_ENT(LOCAL_E)))) if (shot_weapon_mode != weapon_melee)
{ {
// General damage counter // General damage counter
int damage = event->GetInt("damageamount"); int damage = event->GetInt("damageamount");
if (damage > player_status_list[victim].health) if (damage > player_status_list[victim].health)
damage = player_status_list[victim].health; damage = player_status_list[victim].health;
// Crit damage counter // Crit handling
if (event->GetBool("crit")) if (CE_BAD(LOCAL_E) || CE_BAD(LOCAL_W) || !re::CTFPlayerShared::IsCritBoosted(re::CTFPlayerShared::GetPlayerShared(RAW_ENT(LOCAL_E))))
crit_damage += damage;
// Mini crit case
if (event->GetBool("minicrit"))
{ {
if (!player_status_list[victim].was_jarated && !player_status_list[victim].was_markedfordeath) // Crit damage counter
if (event->GetBool("crit"))
crit_damage += damage; crit_damage += damage;
// Mini crit case
if (event->GetBool("minicrit"))
{
if (!player_status_list[victim].was_jarated && !player_status_list[victim].was_markedfordeath)
crit_damage += damage;
}
} }
cached_damage += damage; cached_damage += damage;
} }
@ -686,5 +712,7 @@ static InitRoutine init([]() {
EC::Register(EC::Draw, Draw, "crit_draw"); EC::Register(EC::Draw, Draw, "crit_draw");
EC::Register(EC::LevelShutdown, LevelShutdown, "crit_lvlshutdown"); EC::Register(EC::LevelShutdown, LevelShutdown, "crit_lvlshutdown");
g_IGameEventManager->AddListener(&listener, false); g_IGameEventManager->AddListener(&listener, false);
EC::Register(
EC::Shutdown, []() { g_IGameEventManager->RemoveListener(&listener); }, "crit_shutdown");
}); });
} // namespace criticals } // namespace criticals

View File

@ -4,6 +4,7 @@
*/ */
#include "common.hpp" #include "common.hpp"
#include "crits.hpp"
namespace hacks::tf2::nospread namespace hacks::tf2::nospread
{ {
@ -20,8 +21,18 @@ void CreateMove()
// Credits to https://www.unknowncheats.me/forum/team-fortress-2-a/139094-projectile-nospread.html // Credits to https://www.unknowncheats.me/forum/team-fortress-2-a/139094-projectile-nospread.html
// Set up Random Seed // Set up Random Seed
RandomSeed(MD5_PseudoRandom(current_user_cmd->command_number) & 0x7FFFFFFF); int cmd_num = current_user_cmd->command_number;
SharedRandomInt(MD5_PseudoRandom(current_user_cmd->command_number) & 0x7FFFFFFF, "SelectWeightedSequence", 0, 0, 0); // Crithack uses different things
if (criticals::isEnabled() && g_pLocalPlayer->weapon_mode != weapon_melee && !criticals::old_mode && criticals::crit_cmds.size())
{
int array_index = criticals::current_index;
if (array_index >= criticals::crit_cmds.size())
array_index = 0;
// Adjust for nospread
cmd_num = criticals::crit_cmds[array_index];
}
RandomSeed(MD5_PseudoRandom(cmd_num) & 0x7FFFFFFF);
SharedRandomInt(MD5_PseudoRandom(cmd_num) & 0x7FFFFFFF, "SelectWeightedSequence", 0, 0, 0);
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
RandomFloat(); RandomFloat();