Do some crits.cpp refactoring
This commit is contained in:
parent
ea6f2e0690
commit
43dc27c05f
294
src/crits.cpp
294
src/crits.cpp
@ -102,15 +102,6 @@ static void simulateNormalShot(IClientEntity *wep, float flDamage)
|
||||
info.restore_data(wep);
|
||||
}
|
||||
|
||||
// This is just a convenient wrapper which will most likely be inlined
|
||||
static bool canWeaponWithdraw(IClientEntity *wep)
|
||||
{
|
||||
// Check
|
||||
if (!isAllowedToWithdrawFromBucket(wep, added_per_shot))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calculate shots until crit
|
||||
static int shotsUntilCrit(IClientEntity *wep)
|
||||
{
|
||||
@ -245,8 +236,6 @@ static bool randomCritEnabled()
|
||||
}
|
||||
|
||||
// These are used when we want to force a crit regardless of states (e.g. for delayed weapons like sticky launchers)
|
||||
static int force_ticks = 0;
|
||||
static int prevent_ticks = 0;
|
||||
bool force_crit_this_tick = false;
|
||||
|
||||
// Is the hack enabled?
|
||||
@ -255,23 +244,103 @@ bool isEnabled()
|
||||
// No crits without random crits
|
||||
if (!randomCritEnabled())
|
||||
return false;
|
||||
// Check if
|
||||
// - forced crits
|
||||
// - melee enabled and holding melee
|
||||
// - master switch enabled and not using a melee + (button check)
|
||||
if (force_ticks || ((melee && g_pLocalPlayer->weapon_mode == weapon_melee) || (enabled && g_pLocalPlayer->weapon_mode != weapon_melee && (!crit_key || crit_key.isKeyDown()))))
|
||||
// Melee overrides the enabled switch
|
||||
if (melee || enabled)
|
||||
return true;
|
||||
// If none of these conditions pass, crithack is NOT on
|
||||
return false;
|
||||
}
|
||||
|
||||
bool shouldMeleeCrit()
|
||||
{
|
||||
if (!melee || g_pLocalPlayer->weapon_mode != weapon_melee)
|
||||
return false;
|
||||
namespace bt = hacks::shared::backtrack;
|
||||
if (bt::isBacktrackEnabled)
|
||||
{
|
||||
int target = bt::iBestTarget;
|
||||
// Valid backtrack target
|
||||
if (target > 1)
|
||||
{
|
||||
// Closest tick for melee
|
||||
int besttick = bt::BestTick;
|
||||
// Out of range, don't crit
|
||||
if (bt::headPositions[target][besttick].entorigin.DistTo(LOCAL_E->m_vecOrigin()) >= re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)) + 150.0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Normal check, get closest entity and check distance
|
||||
else
|
||||
{
|
||||
auto ent = getClosestEntity(LOCAL_E->m_vecOrigin());
|
||||
if (!ent || ent->m_flDistance() >= re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)) + 150.0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check some basic conditions
|
||||
bool shouldCrit()
|
||||
{
|
||||
// Melee mode with melee out and in range?
|
||||
if (shouldMeleeCrit())
|
||||
return true;
|
||||
// Crit key + enabled, for melee, the crit key MUST be set
|
||||
if (enabled && ((g_pLocalPlayer->weapon_mode != weapon_melee && !crit_key) || crit_key.isKeyDown()))
|
||||
return true;
|
||||
// Force crits on sticky launcher
|
||||
/*if (force_ticks)
|
||||
{
|
||||
if (LOCAL_W->m_iClassID() == CL_CLASS(CTFPipebombLauncher))
|
||||
return true;
|
||||
else
|
||||
force_ticks = 0;
|
||||
}*/
|
||||
// Tick is supposed to be forced because of something external to crithack
|
||||
if (force_crit_this_tick)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
// Should we Prevent crits?
|
||||
bool preventCrits()
|
||||
|
||||
// BeggarsCanWeaponCrit
|
||||
static bool can_beggars_crit = false;
|
||||
static bool attacked_last_tick = false;
|
||||
|
||||
bool canWeaponCrit(bool canShootCheck = true)
|
||||
{
|
||||
// Can't randomly crit
|
||||
if (!randomCritEnabled())
|
||||
// Is weapon elligible for crits?
|
||||
IClientEntity *weapon = RAW_ENT(LOCAL_W);
|
||||
if (!re::C_TFWeaponBase::IsBaseCombatWeapon(weapon))
|
||||
return false;
|
||||
if (g_pLocalPlayer->weapon_mode == weapon_melee || (force_no_crit && crit_key && !crit_key.isKeyDown()))
|
||||
return true;
|
||||
return false;
|
||||
if (!re::C_TFWeaponBase::AreRandomCritsEnabled(weapon) || !added_per_shot)
|
||||
return false;
|
||||
if (!re::C_TFWeaponBase::CanFireCriticalShot(weapon, false, nullptr))
|
||||
return false;
|
||||
if (!added_per_shot)
|
||||
return false;
|
||||
if (!getCritCap(weapon))
|
||||
return false;
|
||||
|
||||
// Misc checks
|
||||
if (!isAllowedToWithdrawFromBucket(weapon, added_per_shot))
|
||||
return false;
|
||||
if (canShootCheck && !CanShoot() && !isRapidFire(weapon))
|
||||
return false;
|
||||
if (CE_INT(LOCAL_W, netvar.iItemDefinitionIndex) == 730 && !can_beggars_crit)
|
||||
return false;
|
||||
// Check if we have done enough damage to crit
|
||||
auto crit_mult_info = critMultInfo(weapon);
|
||||
if (crit_mult_info.first > crit_mult_info.second && g_pLocalPlayer->weapon_mode != weapon_melee)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We cycle between the crit cmds so we want to store where we are currently at
|
||||
@ -306,27 +375,11 @@ bool prevent_crit()
|
||||
// Main function that forces a crit
|
||||
void force_crit()
|
||||
{
|
||||
// Crithack should not run
|
||||
if (!isEnabled() && !force_crit_this_tick && !preventCrits())
|
||||
return;
|
||||
// Can't crit
|
||||
if (!added_per_shot)
|
||||
return;
|
||||
|
||||
// Reset force ticks
|
||||
if (force_ticks && LOCAL_W->m_iClassID() != CL_CLASS(CTFPipebombLauncher))
|
||||
force_ticks = 0;
|
||||
// New mode stuff (well when not using melee nor using pipe launcher)
|
||||
if (g_pLocalPlayer->weapon_mode != weapon_melee && LOCAL_W->m_iClassID() != CL_CLASS(CTFPipebombLauncher))
|
||||
{
|
||||
// Force to not crit
|
||||
if (!force_crit_this_tick && crit_key && !crit_key.isKeyDown())
|
||||
{
|
||||
// Prevent Crit
|
||||
prevent_crit();
|
||||
}
|
||||
// We have valid crit command numbers
|
||||
else if (crit_cmds.size())
|
||||
if (crit_cmds.size())
|
||||
{
|
||||
if (current_index >= crit_cmds.size())
|
||||
current_index = 0;
|
||||
@ -338,67 +391,30 @@ void force_crit()
|
||||
}
|
||||
}
|
||||
// We can just force to nearest crit for melee, and sticky launchers apparently
|
||||
else if ((g_pLocalPlayer->weapon_mode == weapon_melee && (melee || force_crit_this_tick)) || (LOCAL_W->m_iClassID() == CL_CLASS(CTFPipebombLauncher) && (force_crit_this_tick || enabled)))
|
||||
else
|
||||
{
|
||||
int next_crit = nextCritTick();
|
||||
if (next_crit != -1)
|
||||
{
|
||||
if (LOCAL_W->m_iClassID() == CL_CLASS(CTFPipebombLauncher))
|
||||
{
|
||||
if (!force_ticks && isEnabled())
|
||||
/*if (!force_ticks && isEnabled())
|
||||
force_ticks = 3;
|
||||
if (force_ticks)
|
||||
force_ticks--;
|
||||
// Prevent crits
|
||||
if (!force_crit_this_tick && !prevent_ticks && !force_ticks && preventCrits())
|
||||
prevent_ticks = 3;
|
||||
force_ticks--;*/
|
||||
/*// Prevent crits
|
||||
prevent_ticks = 3;
|
||||
if (prevent_ticks)
|
||||
{
|
||||
prevent_crit();
|
||||
prevent_ticks--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Code for handling when to not crit with melee weapons
|
||||
else if (force_no_crit && !force_crit_this_tick)
|
||||
{
|
||||
if (hacks::shared::backtrack::isBacktrackEnabled)
|
||||
{
|
||||
int target = hacks::shared::backtrack::iBestTarget;
|
||||
// Valid backtrack target
|
||||
if (target > 1)
|
||||
{
|
||||
// Closest tick for melee
|
||||
int besttick = hacks::shared::backtrack::BestTick;
|
||||
// Out of range, don't crit
|
||||
if (hacks::shared::backtrack::headPositions[target][besttick].entorigin.DistTo(LOCAL_E->m_vecOrigin()) >= re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)) + 150.0f)
|
||||
{
|
||||
prevent_crit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prevent_crit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Normal check, get closest entity and check distance
|
||||
else
|
||||
{
|
||||
auto ent = getClosestEntity(LOCAL_E->m_vecOrigin());
|
||||
if (!ent || ent->m_flDistance() >= re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)) + 150.0f)
|
||||
{
|
||||
prevent_crit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
current_late_user_cmd->command_number = next_crit;
|
||||
current_late_user_cmd->random_seed = MD5_PseudoRandom(next_crit) & 0x7FFFFFFF;
|
||||
}
|
||||
}
|
||||
force_crit_this_tick = false;
|
||||
}
|
||||
|
||||
// Update the magic crit commands numbers
|
||||
@ -411,11 +427,7 @@ void force_crit()
|
||||
|
||||
static void updateCmds()
|
||||
{
|
||||
if (CE_BAD(LOCAL_E))
|
||||
return;
|
||||
auto weapon = RAW_ENT(LOCAL_W);
|
||||
if (CE_BAD(LOCAL_W))
|
||||
return;
|
||||
static int last_weapon;
|
||||
|
||||
// Current command number
|
||||
@ -549,10 +561,6 @@ void fixBucket(IClientEntity *weapon, CUserCmd *cmd)
|
||||
info.restore_data(weapon);
|
||||
}
|
||||
|
||||
// Beggars
|
||||
static bool should_crit_beggars = false;
|
||||
static bool attacked_last_tick = false;
|
||||
|
||||
// Damage this round
|
||||
void CreateMove()
|
||||
{
|
||||
@ -575,50 +583,80 @@ void CreateMove()
|
||||
}
|
||||
}
|
||||
|
||||
if (!enabled && !melee && !draw && !draw_meter)
|
||||
// Basic checks
|
||||
if (!isEnabled())
|
||||
return;
|
||||
// This is not a tick that will actually matter
|
||||
if (!current_late_user_cmd->command_number)
|
||||
return;
|
||||
if (CE_BAD(LOCAL_E) || CE_BAD(LOCAL_W))
|
||||
return;
|
||||
|
||||
// Update magic crit commands
|
||||
updateCmds();
|
||||
if (!enabled && !force_crit_this_tick && !melee)
|
||||
return;
|
||||
if (!force_ticks && !force_crit_this_tick && (!(melee && g_pLocalPlayer->weapon_mode == weapon_melee) && !force_no_crit && crit_key && !crit_key.isKeyDown()))
|
||||
return;
|
||||
if (!current_late_user_cmd->command_number)
|
||||
return;
|
||||
|
||||
// Is weapon elligible for crits?
|
||||
IClientEntity *weapon = RAW_ENT(LOCAL_W);
|
||||
if (!re::C_TFWeaponBase::IsBaseCombatWeapon(weapon))
|
||||
return;
|
||||
if (!re::C_TFWeaponBase::AreRandomCritsEnabled(weapon) || !added_per_shot)
|
||||
return;
|
||||
if (!re::C_TFWeaponBase::CanFireCriticalShot(weapon, false, nullptr))
|
||||
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;
|
||||
if (!can_beggars_crit)
|
||||
can_beggars_crit = !(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))
|
||||
attacked_last_tick = current_late_user_cmd->buttons & IN_ATTACK;
|
||||
if (!CE_INT(LOCAL_W, netvar.m_iClip1) && CE_INT(LOCAL_W, netvar.iReloadMode) == 0)
|
||||
{
|
||||
// Reset
|
||||
should_crit_beggars = false;
|
||||
can_beggars_crit = false;
|
||||
}
|
||||
}
|
||||
// Should we run crit logic?
|
||||
if ((force_no_crit && isAllowedToWithdrawFromBucket(RAW_ENT(LOCAL_W), added_per_shot)) || force_ticks || should_crit_beggars || ((CanShoot() || isRapidFire(RAW_ENT(LOCAL_W))) && current_late_user_cmd->buttons & IN_ATTACK))
|
||||
else
|
||||
can_beggars_crit = false;
|
||||
|
||||
// No point in forcing/preventing crits if we can't even crit
|
||||
if (!canWeaponCrit())
|
||||
return;
|
||||
|
||||
// Not in attack? Do nothing, unless using the beggars/Sticky launcher
|
||||
if (!(current_late_user_cmd->buttons & IN_ATTACK))
|
||||
{
|
||||
// Can we crit?
|
||||
if (canWeaponWithdraw(RAW_ENT(LOCAL_W)))
|
||||
force_crit();
|
||||
if (LOCAL_W->m_iClassID() == CL_CLASS(CTFPipebombLauncher))
|
||||
{
|
||||
float chargebegin = *((float *) ((uintptr_t) RAW_ENT(LOCAL_W) + 3152));
|
||||
float chargetime = g_GlobalVars->curtime - chargebegin;
|
||||
|
||||
static bool currently_charging_pipe = false;
|
||||
|
||||
// Sticky started charging
|
||||
if (chargetime < 6.0f && chargetime)
|
||||
currently_charging_pipe = true;
|
||||
|
||||
// Sticky was released
|
||||
if (!(current_user_cmd->buttons & IN_ATTACK) && currently_charging_pipe)
|
||||
{
|
||||
currently_charging_pipe = false;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if (!can_beggars_crit)
|
||||
return;
|
||||
}
|
||||
|
||||
// Should we even try to crit this tick?
|
||||
if (shouldCrit())
|
||||
{
|
||||
force_crit();
|
||||
}
|
||||
// Ok, we shouldn't crit for whatever reason, lets prevent crits
|
||||
else if (force_no_crit)
|
||||
{
|
||||
// if (prevent_ticks >= 1)
|
||||
// prevent_ticks--;
|
||||
prevent_crit();
|
||||
// if (LOCAL_W->m_iClassID() == CL_CLASS(CTFPipebombLauncher) && current_late_user_cmd->buttons & IN_ATTACK)
|
||||
// prevent_ticks = 3;
|
||||
}
|
||||
force_crit_this_tick = false;
|
||||
}
|
||||
|
||||
// Storage
|
||||
@ -675,6 +713,8 @@ static Timer update_shots{};
|
||||
|
||||
void Draw()
|
||||
{
|
||||
if (!isEnabled())
|
||||
return;
|
||||
if (!draw && !draw_meter)
|
||||
return;
|
||||
if (!g_IEngine->GetNetChannelInfo())
|
||||
@ -688,7 +728,7 @@ void Draw()
|
||||
// fixObservedCritchance(wep);
|
||||
|
||||
// Used by multiple things
|
||||
bool can_crit = canWeaponWithdraw(wep);
|
||||
bool can_crit = canWeaponCrit(false);
|
||||
|
||||
if (bucket != last_bucket || wep->entindex() != last_wep || update_shots.test_and_set(500))
|
||||
{
|
||||
@ -708,8 +748,13 @@ void Draw()
|
||||
if (draw)
|
||||
{
|
||||
// Display for when crithack is active
|
||||
if (isEnabled() && last_crit_tick != -1)
|
||||
AddCritString("Forcing Crits!", colors::red);
|
||||
if (shouldCrit())
|
||||
{
|
||||
if (can_crit)
|
||||
AddCritString("Forcing Crits!", colors::red);
|
||||
else
|
||||
AddCritString("Weapon can currently not crit!", colors::red);
|
||||
}
|
||||
|
||||
// Weapon can't randomly crit
|
||||
if (!re::C_TFWeaponBase::CanFireCriticalShot(RAW_ENT(LOCAL_W), false, nullptr) || !added_per_shot)
|
||||
@ -748,10 +793,10 @@ void Draw()
|
||||
{
|
||||
rgba_t bucket_color = colors::FromRGBA8(0x53, 0xbc, 0x31, 255);
|
||||
// Forcing crits, change crit bucket color to a nice azure blue
|
||||
if (isEnabled())
|
||||
if (shouldCrit())
|
||||
bucket_color = colors::FromRGBA8(0x34, 0xeb, 0xae, 255);
|
||||
// Color everything red
|
||||
if ((crit_mult_info.first > crit_mult_info.second && g_pLocalPlayer->weapon_mode != weapon_melee) || !can_crit)
|
||||
if (!can_crit)
|
||||
bucket_color = colors::red;
|
||||
|
||||
// Get the percentage the bucket will take up
|
||||
@ -800,10 +845,7 @@ void Draw()
|
||||
{
|
||||
if (!isRapidFire(wep))
|
||||
{
|
||||
if (shots_until_crit != 1)
|
||||
bar_string = std::to_string(shots_until_crit) + " Shots until Crit!";
|
||||
else
|
||||
bar_string = std::to_string(shots_until_crit) + " Shot until Crit!";
|
||||
bar_string = std::to_string(shots_until_crit) + " Shots until Crit!";
|
||||
}
|
||||
else
|
||||
bar_string = "Crit multiplier: " + std::to_string(getWithdrawMult(wep));
|
||||
|
@ -11,7 +11,7 @@ namespace hooked_methods
|
||||
DEFINE_HOOKED_METHOD(GetUserCmd, CUserCmd *, IInput *this_, int sequence_number)
|
||||
{
|
||||
// We need to overwrite this if crithack is on
|
||||
if (criticals::enabled || criticals::melee)
|
||||
if (criticals::isEnabled())
|
||||
return &GetCmds(this_)[sequence_number % VERIFIED_CMD_SIZE];
|
||||
else
|
||||
return original::GetUserCmd(this_, sequence_number);
|
||||
|
Reference in New Issue
Block a user