Fix issues with aimbot that caused priority to not properly work
Removed cd variable in favour of passing a target around. Removed vischeck from Aim and added to GetTarget function which replaces IsTargetStateGood serving same purpose but making a target instead. Run aim after target has been got as calling no longer needed in RetrieveBestTarget (this is what fixes priority issue)
This commit is contained in:
parent
d2df394e15
commit
0287636dfc
@ -12,13 +12,26 @@
|
||||
class ConVar;
|
||||
class IClientEntity;
|
||||
|
||||
|
||||
namespace hacks::shared::aimbot
|
||||
{
|
||||
struct AimbotTarget_t
|
||||
{
|
||||
unsigned long predict_tick{ 0 };
|
||||
bool predict_type{ 0 };
|
||||
Vector aim_position{ 0 };
|
||||
unsigned long vcheck_tick{ 0 };
|
||||
CachedEntity* ent { nullptr };
|
||||
bool visible{ false };
|
||||
float fov{ 0 };
|
||||
int hitbox{ 0 };
|
||||
bool valid { false };
|
||||
};
|
||||
extern settings::Boolean ignore_cloak;
|
||||
extern unsigned last_target_ignore_timer;
|
||||
// Used to store aimbot data to prevent calculating it again
|
||||
// Functions used to calculate aimbot data, and if already calculated use it
|
||||
Vector PredictEntity(CachedEntity *entity);
|
||||
Vector PredictEntity(AimbotTarget_t& entity);
|
||||
|
||||
// Functions called by other functions for when certian game calls are run
|
||||
void Reset();
|
||||
@ -27,16 +40,16 @@ void Reset();
|
||||
bool isAiming();
|
||||
CachedEntity *CurrentTarget();
|
||||
bool ShouldAim();
|
||||
CachedEntity *RetrieveBestTarget(bool aimkey_state);
|
||||
bool IsTargetStateGood(CachedEntity *entity);
|
||||
bool Aim(CachedEntity *entity);
|
||||
void DoAutoshoot(CachedEntity *target = nullptr);
|
||||
AimbotTarget_t RetrieveBestTarget(bool aimkey_state);
|
||||
AimbotTarget_t GetTarget(CachedEntity *entity);
|
||||
bool Aim(AimbotTarget_t entity);
|
||||
void DoAutoshoot(AimbotTarget_t target = {});
|
||||
int notVisibleHitbox(CachedEntity *target, int preferred);
|
||||
std::vector<Vector> getHitpointsVischeck(CachedEntity *ent, int hitbox);
|
||||
float projectileHitboxSize(int projectile_size);
|
||||
int autoHitbox(CachedEntity *target);
|
||||
bool hitscanSpecialCases(CachedEntity *target_entity, int weapon_case);
|
||||
bool projectileSpecialCases(CachedEntity *target_entity, int weapon_case);
|
||||
bool hitscanSpecialCases(AimbotTarget_t target_entity, int weapon_case);
|
||||
bool projectileSpecialCases(AimbotTarget_t target_entity, int weapon_case);
|
||||
int BestHitbox(CachedEntity *target);
|
||||
bool isHitboxMedium(int hitbox);
|
||||
int ClosestHitbox(CachedEntity *target);
|
||||
|
@ -88,16 +88,6 @@ static settings::Float specfov("aimbot.spectator.fov", "0");
|
||||
static settings::Int specslow("aimbot.spectator.slow", "0");
|
||||
|
||||
settings::Boolean engine_projpred{ "aimbot.debug.engine-pp", "1" };
|
||||
struct AimbotCalculatedData_s
|
||||
{
|
||||
unsigned long predict_tick{ 0 };
|
||||
bool predict_type{ 0 };
|
||||
Vector aim_position{ 0 };
|
||||
unsigned long vcheck_tick{ 0 };
|
||||
bool visible{ false };
|
||||
float fov{ 0 };
|
||||
int hitbox{ 0 };
|
||||
} static cd;
|
||||
int slow_aim;
|
||||
float fov;
|
||||
bool enable;
|
||||
@ -149,8 +139,6 @@ inline bool isHitboxMedium(int hitbox)
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
inline bool playerTeamCheck(CachedEntity *entity)
|
||||
|
||||
@ -472,7 +460,7 @@ void doAutoZoom(bool target_found)
|
||||
}
|
||||
|
||||
// Current Entity
|
||||
CachedEntity *target_last = 0;
|
||||
AimbotTarget_t target_last;
|
||||
bool aimed_this_tick = false;
|
||||
Vector viewangles_this_tick(0.0f);
|
||||
|
||||
@ -497,17 +485,17 @@ static void CreateMove()
|
||||
spectatorUpdate();
|
||||
if (!enable)
|
||||
{
|
||||
target_last = nullptr;
|
||||
target_last.valid = false;
|
||||
return;
|
||||
}
|
||||
else if (!LOCAL_E->m_bAlivePlayer() || !g_pLocalPlayer->entity)
|
||||
{
|
||||
target_last = nullptr;
|
||||
target_last.valid = false;
|
||||
return;
|
||||
}
|
||||
else if (!aimkey_status || !ShouldAim())
|
||||
{
|
||||
target_last = nullptr;
|
||||
target_last.valid = false;
|
||||
return;
|
||||
}
|
||||
// Unless we're using slow aim, we do not want to aim while reloading
|
||||
@ -529,8 +517,10 @@ static void CreateMove()
|
||||
if (should_backtrack)
|
||||
updateShouldBacktrack();
|
||||
target_last = RetrieveBestTarget(aimkey_status);
|
||||
if (target_last)
|
||||
|
||||
if (target_last.valid)
|
||||
{
|
||||
Aim(target_last);
|
||||
if (should_zoom)
|
||||
doAutoZoom(true);
|
||||
int weapon_case = LOCAL_W->m_iClassID();
|
||||
@ -544,8 +534,9 @@ static void CreateMove()
|
||||
if (should_backtrack)
|
||||
updateShouldBacktrack();
|
||||
target_last = RetrieveBestTarget(aimkey_status);
|
||||
if (target_last)
|
||||
if (target_last.valid)
|
||||
{
|
||||
Aim(target_last);
|
||||
DoAutoshoot(target_last);
|
||||
}
|
||||
break;
|
||||
@ -559,7 +550,7 @@ static void CreateMove()
|
||||
projectile_mode = GetProjectileData(g_pLocalPlayer->weapon(), cur_proj_speed, cur_proj_grav, cur_proj_start_vel);
|
||||
if (!projectile_mode)
|
||||
{
|
||||
target_last = nullptr;
|
||||
target_last.valid = false;
|
||||
return;
|
||||
}
|
||||
if (proj_speed)
|
||||
@ -569,12 +560,12 @@ static void CreateMove()
|
||||
if (proj_start_vel)
|
||||
cur_proj_start_vel = *proj_start_vel;
|
||||
target_last = RetrieveBestTarget(aimkey_status);
|
||||
if (target_last)
|
||||
if (target_last.valid)
|
||||
{
|
||||
int weapon_case = g_pLocalPlayer->weapon()->m_iClassID();
|
||||
if (projectileSpecialCases(target_last, weapon_case))
|
||||
{
|
||||
|
||||
Aim(target_last);
|
||||
DoAutoshoot(target_last);
|
||||
}
|
||||
}
|
||||
@ -584,7 +575,7 @@ static void CreateMove()
|
||||
}
|
||||
}
|
||||
|
||||
bool projectileSpecialCases(CachedEntity *target_entity, int weapon_case)
|
||||
bool projectileSpecialCases(AimbotTarget_t target_entity, int weapon_case)
|
||||
{
|
||||
|
||||
switch (weapon_case)
|
||||
@ -601,7 +592,7 @@ bool projectileSpecialCases(CachedEntity *target_entity, int weapon_case)
|
||||
charge = 0.0f;
|
||||
int damage = std::floor(50.0f + 70.0f * fminf(1.0f, charge));
|
||||
int charge_damage = std::floor(50.0f + 70.0f * fminf(1.0f, charge)) * 3.0f;
|
||||
if (HasCondition<TFCond_Slowed>(LOCAL_E) && (autoshoot || !(current_user_cmd->buttons & IN_ATTACK)) && (!wait_for_charge || (charge >= 1.0f || damage >= target_entity->m_iHealth() || charge_damage >= target_entity->m_iHealth())))
|
||||
if (HasCondition<TFCond_Slowed>(LOCAL_E) && (autoshoot || !(current_user_cmd->buttons & IN_ATTACK)) && (!wait_for_charge || (charge >= 1.0f || damage >= target_entity.ent->m_iHealth() || charge_damage >= target_entity.ent->m_iHealth())))
|
||||
release = true;
|
||||
return release;
|
||||
break;
|
||||
@ -655,7 +646,7 @@ bool projectileSpecialCases(CachedEntity *target_entity, int weapon_case)
|
||||
return true;
|
||||
}
|
||||
int tapfire_delay = 0;
|
||||
bool hitscanSpecialCases(CachedEntity *target_entity, int weapon_case)
|
||||
bool hitscanSpecialCases(AimbotTarget_t target_entity, int weapon_case)
|
||||
{
|
||||
switch (weapon_case)
|
||||
{
|
||||
@ -669,7 +660,7 @@ bool hitscanSpecialCases(CachedEntity *target_entity, int weapon_case)
|
||||
tapfire_delay++;
|
||||
|
||||
// This is the exact delay needed to hit
|
||||
if (17 <= tapfire_delay || target_entity->m_flDistance() <= 1250.0f)
|
||||
if (17 <= tapfire_delay || target_entity.ent->m_flDistance() <= 1250.0f)
|
||||
{
|
||||
DoAutoshoot(target_entity);
|
||||
tapfire_delay = 0;
|
||||
@ -763,17 +754,17 @@ bool ShouldAim()
|
||||
}
|
||||
|
||||
// Function to find a suitable target
|
||||
CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
AimbotTarget_t RetrieveBestTarget(bool aimkey_state)
|
||||
{
|
||||
// If we have a previously chosen target, target lock is on, and the aimkey
|
||||
// is allowed, then attemt to keep the previous target
|
||||
|
||||
if (target_lock && target_last && aimkey_state)
|
||||
if (target_lock && target_last.valid && aimkey_state)
|
||||
{
|
||||
|
||||
if (shouldBacktrack(target_last))
|
||||
AimbotTarget_t target = GetTarget(target_last.ent);
|
||||
if (shouldBacktrack(target_last.ent))
|
||||
{
|
||||
auto good_ticks_tmp = hacks::tf2::backtrack::getGoodTicks(target_last);
|
||||
auto good_ticks_tmp = hacks::tf2::backtrack::getGoodTicks(target_last.ent);
|
||||
if (good_ticks_tmp)
|
||||
{
|
||||
auto good_ticks = *good_ticks_tmp;
|
||||
@ -787,18 +778,18 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
if (!validateTickFOV(bt_tick))
|
||||
continue;
|
||||
hacks::tf2::backtrack::MoveToTick(bt_tick);
|
||||
if (IsTargetStateGood(target_last) && Aim(target_last))
|
||||
return target_last;
|
||||
if (target.valid)
|
||||
return target;
|
||||
// Restore if bad target
|
||||
hacks::tf2::backtrack::RestoreEntity(target_last->m_IDX);
|
||||
hacks::tf2::backtrack::RestoreEntity(target_last.ent->m_IDX);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if previous target is still good
|
||||
else if (!shouldbacktrack_cache && IsTargetStateGood(target_last) && Aim(target_last))
|
||||
else if (!shouldbacktrack_cache && target.valid)
|
||||
{
|
||||
// If it is then return it again
|
||||
return target_last;
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -806,15 +797,14 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
hacks::shared::aimbot::last_target_ignore_timer = 0;
|
||||
|
||||
float target_highest_score, scr = 0.0f;
|
||||
CachedEntity *target_highest_ent = nullptr;
|
||||
AimbotTarget_t target_best;
|
||||
target_highest_score = -256;
|
||||
std::optional<hacks::tf2::backtrack::BacktrackData> bt_tick = std::nullopt;
|
||||
for (auto const &ent : entity_cache::valid_ents)
|
||||
{
|
||||
// Check for null and dormant
|
||||
// Check whether the current ent is good enough to target
|
||||
bool isTargetGood = false;
|
||||
|
||||
AimbotTarget_t target;
|
||||
static std::optional<hacks::tf2::backtrack::BacktrackData> temp_bt_tick = std::nullopt;
|
||||
if (shouldBacktrack(ent))
|
||||
{
|
||||
@ -832,9 +822,9 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
if (!validateTickFOV(bt_tick))
|
||||
continue;
|
||||
hacks::tf2::backtrack::MoveToTick(bt_tick);
|
||||
if (IsTargetStateGood(ent) && Aim(ent))
|
||||
target = GetTarget(ent);
|
||||
if (target.valid)
|
||||
{
|
||||
isTargetGood = true;
|
||||
temp_bt_tick = bt_tick;
|
||||
break;
|
||||
}
|
||||
@ -844,10 +834,9 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsTargetStateGood(ent) && Aim(ent))
|
||||
isTargetGood = true;
|
||||
target = GetTarget(ent);
|
||||
}
|
||||
if (isTargetGood) // Melee mode straight up won't swing if the target is too far away. No need to prioritize based on distance. Just use whatever the user chooses.
|
||||
if (target.valid) // Melee mode straight up won't swing if the target is too far away. No need to prioritize based on distance. Just use whatever the user chooses.
|
||||
{
|
||||
switch ((int) priority_mode)
|
||||
{
|
||||
@ -858,12 +847,12 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
}
|
||||
case 1: // Fov Priority
|
||||
{
|
||||
scr = 360.0f - cd.fov;
|
||||
scr = 360.0f - target.fov;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
scr = 4096.0f - cd.aim_position.DistTo(g_pLocalPlayer->v_Eye);
|
||||
scr = 4096.0f - target.aim_position.DistTo(g_pLocalPlayer->v_Eye);
|
||||
break;
|
||||
}
|
||||
case 3: // Health Priority (Lowest)
|
||||
@ -873,7 +862,7 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
}
|
||||
case 4: // Distance Priority (Furthest Away)
|
||||
{
|
||||
scr = cd.aim_position.DistTo(g_pLocalPlayer->v_Eye);
|
||||
scr = target.aim_position.DistTo(g_pLocalPlayer->v_Eye);
|
||||
break;
|
||||
}
|
||||
case 5: // Health Priority (Highest)
|
||||
@ -884,7 +873,7 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
case 6: // Fast
|
||||
{
|
||||
|
||||
return ent;
|
||||
return target;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
@ -898,7 +887,7 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
if (scr > target_highest_score)
|
||||
{
|
||||
target_highest_score = scr;
|
||||
target_highest_ent = ent;
|
||||
target_best = target;
|
||||
bt_tick = temp_bt_tick;
|
||||
}
|
||||
}
|
||||
@ -907,18 +896,21 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
if (shouldBacktrack(ent))
|
||||
hacks::tf2::backtrack::RestoreEntity(ent->m_IDX);
|
||||
}
|
||||
if (target_highest_ent && bt_tick)
|
||||
if (target_best.valid && bt_tick)
|
||||
hacks::tf2::backtrack::MoveToTick(*bt_tick);
|
||||
return target_highest_ent;
|
||||
return target_best;
|
||||
}
|
||||
|
||||
// A second check to determine whether a target is good enough to be aimed at
|
||||
bool IsTargetStateGood(CachedEntity *entity)
|
||||
// Get the target information from a entity, valid is set to false replacing the bool return value
|
||||
AimbotTarget_t GetTarget(CachedEntity *entity)
|
||||
{
|
||||
PROF_SECTION(PT_aimbot_targetstatecheck);
|
||||
|
||||
AimbotTarget_t t;
|
||||
t.ent = entity;
|
||||
const int current_type = entity->m_Type();
|
||||
bool is_player = false;
|
||||
|
||||
|
||||
switch (current_type)
|
||||
{
|
||||
|
||||
@ -926,30 +918,30 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
{
|
||||
// Local player check
|
||||
if (entity == LOCAL_E)
|
||||
return false;
|
||||
return t;
|
||||
// Dead
|
||||
else if (!entity->m_bAlivePlayer())
|
||||
return false;
|
||||
return t;
|
||||
// Teammates
|
||||
else if (!playerTeamCheck(entity))
|
||||
return false;
|
||||
return t;
|
||||
else if (!player_tools::shouldTarget(entity))
|
||||
return false;
|
||||
return t;
|
||||
// Invulnerable players, ex: uber, bonk
|
||||
else if (IsPlayerInvulnerable(entity))
|
||||
return false;
|
||||
return t;
|
||||
// Distance
|
||||
is_player = true;
|
||||
float targeting_range = EffectiveTargetingRange();
|
||||
if (entity->m_flDistance() - 40 > targeting_range && tickcount > hacks::shared::aimbot::last_target_ignore_timer) // m_flDistance includes the collision box. You have to subtract it (Should be the same for every model)
|
||||
return false;
|
||||
return t;
|
||||
|
||||
// Rage only check
|
||||
if (rageonly)
|
||||
{
|
||||
if (playerlist::AccessData(entity).state != playerlist::k_EState::RAGE)
|
||||
{
|
||||
return false;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
@ -995,7 +987,7 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
int health = entity->m_iHealth();
|
||||
if (!(health <= hsdmg || health <= cdmg || !g_pLocalPlayer->bZoomed || (maxCharge && health > maxhs)))
|
||||
{
|
||||
return false;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1010,75 +1002,73 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
if (HasWeapon(entity, 59))
|
||||
{
|
||||
if (ignore_deadringer)
|
||||
return false;
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ignore_cloak && !(HasCondition<TFCond_OnFire>(entity)) && !(HasCondition<TFCond_CloakFlicker>(entity)))
|
||||
return false;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Vaccinator
|
||||
if (ignore_vaccinator && IsPlayerResistantToCurrentWeapon(entity))
|
||||
return false;
|
||||
return t;
|
||||
|
||||
cd.hitbox = BestHitbox(entity);
|
||||
t.hitbox = BestHitbox(entity);
|
||||
// ngl i would love to avoid nesting this many ifs by using a goto but i have morals.
|
||||
if (*vischeck_hitboxes && !*multipoint && is_player)
|
||||
{
|
||||
if (*vischeck_hitboxes == 1 && playerlist::AccessData(entity).state != playerlist::k_EState::RAGE || (projectileAimbotRequired && 0.01f < cur_proj_grav))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
else
|
||||
if (!(*vischeck_hitboxes == 1 && playerlist::AccessData(entity).state != playerlist::k_EState::RAGE || (projectileAimbotRequired && 0.01f < cur_proj_grav)))
|
||||
{
|
||||
int i = 0;
|
||||
trace_t first_tracer;
|
||||
|
||||
if (IsEntityVectorVisible(entity, entity->hitboxes.GetHitbox(cd.hitbox)->center, true, MASK_SHOT_HULL, &first_tracer, true))
|
||||
return true;
|
||||
|
||||
const u_int8_t max_box = entity->hitboxes.GetNumHitboxes();
|
||||
while (i < max_box) // Prevents returning empty at all costs. Loops through every hitbox
|
||||
if (!IsEntityVectorVisible(entity, entity->hitboxes.GetHitbox(t.hitbox)->center, true, MASK_SHOT_HULL, &first_tracer, true))
|
||||
{
|
||||
if (i == cd.hitbox)
|
||||
const u_int8_t max_box = entity->hitboxes.GetNumHitboxes();
|
||||
bool found = false;
|
||||
while (i < max_box) // Prevents returning empty at all costs. Loops through every hitbox
|
||||
{
|
||||
if (i == t.hitbox)
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
trace_t test_trace;
|
||||
|
||||
Vector centered_hitbox = entity->hitboxes.GetHitbox(i)->center;
|
||||
|
||||
if (IsEntityVectorVisible(entity, centered_hitbox, true, MASK_SHOT_HULL, &test_trace, true))
|
||||
{
|
||||
t.hitbox = i;
|
||||
found = true;
|
||||
}
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
trace_t test_trace;
|
||||
|
||||
Vector centered_hitbox = entity->hitboxes.GetHitbox(i)->center;
|
||||
|
||||
if (IsEntityVectorVisible(entity, centered_hitbox, true, MASK_SHOT_HULL, &test_trace, true))
|
||||
{
|
||||
cd.hitbox = i;
|
||||
return true;
|
||||
}
|
||||
++i;
|
||||
if (!found)
|
||||
return t; // It looped through every hitbox and found nothing. It isn't visible.
|
||||
}
|
||||
return false; // It looped through every hitbox and found nothing. It isn't visible.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
t.valid = true;
|
||||
break;
|
||||
}
|
||||
// Check for buildings
|
||||
// Check for buildings
|
||||
case (ENTITY_BUILDING):
|
||||
{
|
||||
// Enabled check
|
||||
if (!(buildings_other || buildings_sentry))
|
||||
return false;
|
||||
return t;
|
||||
// Teammates, Even with friendly fire enabled, buildings can NOT be
|
||||
// damaged
|
||||
else if (!entity->m_bEnemy())
|
||||
return false;
|
||||
return t;
|
||||
// Distance
|
||||
else if (EffectiveTargetingRange())
|
||||
{
|
||||
if (entity->m_flDistance() - 40 > EffectiveTargetingRange() && tickcount > hacks::shared::aimbot::last_target_ignore_timer)
|
||||
return false;
|
||||
return t;
|
||||
}
|
||||
|
||||
// Building type
|
||||
@ -1088,20 +1078,17 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
if (entity->m_iClassID() == CL_CLASS(CObjectSentrygun))
|
||||
{
|
||||
if (!buildings_sentry)
|
||||
return false;
|
||||
return t;
|
||||
// Other
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!buildings_other)
|
||||
return false;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
// Grab the prediction var
|
||||
|
||||
// Vis and fov check
|
||||
return true;
|
||||
t.valid = true;
|
||||
break;
|
||||
}
|
||||
case (ENTITY_NPC):
|
||||
{
|
||||
@ -1109,21 +1096,19 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
|
||||
// NPC targeting is disabled
|
||||
if (!npcs)
|
||||
return false;
|
||||
return t;
|
||||
|
||||
// Cannot shoot this
|
||||
else if (entity->m_iTeam() == LOCAL_E->m_iTeam())
|
||||
return false;
|
||||
return t;
|
||||
|
||||
// Distance
|
||||
float targeting_range = EffectiveTargetingRange();
|
||||
|
||||
if (entity->m_flDistance() - 40 > targeting_range && tickcount > hacks::shared::aimbot::last_target_ignore_timer)
|
||||
return false;
|
||||
return t;
|
||||
|
||||
// Grab the prediction var
|
||||
|
||||
return true;
|
||||
t.valid = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1134,104 +1119,120 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
{
|
||||
// Enabled
|
||||
if (!stickybot)
|
||||
return false;
|
||||
return t;
|
||||
|
||||
// Only hitscan weapons can break stickys so check for them.
|
||||
else if (!(GetWeaponMode() == weapon_hitscan || GetWeaponMode() == weapon_melee))
|
||||
return false;
|
||||
return t;
|
||||
|
||||
// Distance
|
||||
float targeting_range = EffectiveTargetingRange();
|
||||
if (entity->m_flDistance() > targeting_range)
|
||||
return false;
|
||||
return t;
|
||||
|
||||
// Teammates, Even with friendly fire enabled, stickys can NOT be
|
||||
// destroied
|
||||
if (!entity->m_bEnemy())
|
||||
return false;
|
||||
return t;
|
||||
|
||||
// Check if target is a pipe bomb
|
||||
if (CE_INT(entity, netvar.iPipeType) != 1)
|
||||
return false;
|
||||
return t;
|
||||
|
||||
// Moving Sticky?
|
||||
Vector velocity;
|
||||
velocity::EstimateAbsVelocity(RAW_ENT(entity), velocity);
|
||||
if (!velocity.IsZero())
|
||||
return false;
|
||||
return t;
|
||||
|
||||
// Grab the prediction var
|
||||
|
||||
// Vis and fov check
|
||||
|
||||
return true;
|
||||
t.valid = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (t.valid)
|
||||
{
|
||||
Vector is_it_good = PredictEntity(t);
|
||||
if (!projectileAimbotRequired)
|
||||
{
|
||||
if (!IsEntityVectorVisible(entity, is_it_good, true, MASK_SHOT_HULL, nullptr, true))
|
||||
{
|
||||
t.valid = false;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
Vector angles = GetAimAtAngles(g_pLocalPlayer->v_Eye, is_it_good, LOCAL_E);
|
||||
|
||||
if (projectileAimbotRequired) // unfortunately you have to check this twice, otherwise you'd have to run GetAimAtAngles far too early
|
||||
{
|
||||
const Vector &orig = getShootPos(angles);
|
||||
const bool grav_comp = (0.01f < cur_proj_grav);
|
||||
if (grav_comp)
|
||||
{
|
||||
const QAngle &angl = VectorToQAngle(angles);
|
||||
Vector end_targ = is_it_good;
|
||||
Vector fwd, right, up;
|
||||
AngleVectors3(angl, &fwd, &right, &up);
|
||||
// I have no clue why this is 200.0f, No where in the SDK explains this.
|
||||
// It appears to work though
|
||||
Vector vel = 0.9f * ((fwd * cur_proj_speed) + (up * 200.0f));
|
||||
fwd.z = 0.0f;
|
||||
fwd.NormalizeInPlace();
|
||||
float alongvel = std::sqrt(vel.x * vel.x + vel.y * vel.y);
|
||||
fwd *= alongvel;
|
||||
const float gravity = cur_proj_grav * g_ICvar->FindVar("sv_gravity")->GetFloat() * -1.0f;
|
||||
const float maxTime = 2.5f;
|
||||
const float timeStep = 0.01f;
|
||||
Vector curr_pos = orig;
|
||||
trace_t ptr_trace;
|
||||
Vector last_pos = orig;
|
||||
const IClientEntity *rawest_ent = RAW_ENT(entity);
|
||||
for (float tm = 0.0f; tm < maxTime; tm += timeStep, last_pos = curr_pos)
|
||||
{
|
||||
curr_pos.x = orig.x + fwd.x * tm;
|
||||
curr_pos.y = orig.y + fwd.y * tm;
|
||||
curr_pos.z = orig.z + vel.z * tm + 0.5f * gravity * tm * tm;
|
||||
if (!didProjectileHit(last_pos, curr_pos, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), true, &ptr_trace) || (IClientEntity *) ptr_trace.m_pEnt == rawest_ent)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!didProjectileHit(end_targ, ptr_trace.endpos, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), true, &ptr_trace))
|
||||
{
|
||||
t.valid = false;
|
||||
return t;
|
||||
}
|
||||
Vector ent_check = entity->m_vecOrigin();
|
||||
if (!didProjectileHit(last_pos, ent_check, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), false))
|
||||
{
|
||||
t.valid = false;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
else if (!didProjectileHit(orig, is_it_good, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), grav_comp))
|
||||
{
|
||||
t.valid = false;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
if (fov > 0 && t.fov > fov)
|
||||
t.valid = false;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
bool Aim(CachedEntity *entity)
|
||||
bool Aim(AimbotTarget_t target)
|
||||
{
|
||||
if (*miss_chance > 0 && UniformRandomInt(0, 99) < *miss_chance)
|
||||
return true;
|
||||
|
||||
// Get angles from eye to target
|
||||
Vector is_it_good = PredictEntity(entity);
|
||||
if (!projectileAimbotRequired)
|
||||
if (!IsEntityVectorVisible(entity, is_it_good, true, MASK_SHOT_HULL, nullptr, true))
|
||||
return false;
|
||||
|
||||
Vector angles = GetAimAtAngles(g_pLocalPlayer->v_Eye, is_it_good, LOCAL_E);
|
||||
|
||||
if (projectileAimbotRequired) // unfortunately you have to check this twice, otherwise you'd have to run GetAimAtAngles far too early
|
||||
{
|
||||
const Vector &orig = getShootPos(angles);
|
||||
const bool grav_comp = (0.01f < cur_proj_grav);
|
||||
if (grav_comp)
|
||||
{
|
||||
const QAngle &angl = VectorToQAngle(angles);
|
||||
Vector end_targ = is_it_good;
|
||||
Vector fwd, right, up;
|
||||
AngleVectors3(angl, &fwd, &right, &up);
|
||||
// I have no clue why this is 200.0f, No where in the SDK explains this.
|
||||
// It appears to work though
|
||||
Vector vel = 0.9f * ((fwd * cur_proj_speed) + (up * 200.0f));
|
||||
fwd.z = 0.0f;
|
||||
fwd.NormalizeInPlace();
|
||||
float alongvel = std::sqrt(vel.x * vel.x + vel.y * vel.y);
|
||||
fwd *= alongvel;
|
||||
const float gravity = cur_proj_grav * g_ICvar->FindVar("sv_gravity")->GetFloat() * -1.0f;
|
||||
const float maxTime = 2.5f;
|
||||
const float timeStep = 0.01f;
|
||||
Vector curr_pos = orig;
|
||||
trace_t ptr_trace;
|
||||
Vector last_pos = orig;
|
||||
const IClientEntity *rawest_ent = RAW_ENT(entity);
|
||||
for (float t = 0.0f; t < maxTime; t += timeStep, last_pos = curr_pos)
|
||||
{
|
||||
curr_pos.x = orig.x + fwd.x * t;
|
||||
curr_pos.y = orig.y + fwd.y * t;
|
||||
curr_pos.z = orig.z + vel.z * t + 0.5f * gravity * t * t;
|
||||
if (!didProjectileHit(last_pos, curr_pos, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), true, &ptr_trace) || (IClientEntity *) ptr_trace.m_pEnt == rawest_ent)
|
||||
break;
|
||||
}
|
||||
if (!didProjectileHit(end_targ, ptr_trace.endpos, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), true, &ptr_trace))
|
||||
return false;
|
||||
Vector ent_check = entity->m_vecOrigin();
|
||||
if (!didProjectileHit(last_pos, ent_check, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), false))
|
||||
return false;
|
||||
}
|
||||
else if (!didProjectileHit(orig, is_it_good, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), grav_comp))
|
||||
return false;
|
||||
}
|
||||
if (fov > 0 && cd.fov > fov)
|
||||
return false;
|
||||
Vector angles = GetAimAtAngles(g_pLocalPlayer->v_Eye, target.aim_position, LOCAL_E);
|
||||
// Slow aim
|
||||
if (slow_aim)
|
||||
DoSlowAim(angles);
|
||||
|
||||
#if ENABLE_VISUALS
|
||||
if (entity->m_Type() == ENTITY_PLAYER)
|
||||
hacks::shared::esp::SetEntityColor(entity, colors::target);
|
||||
if (target.ent->m_Type() == ENTITY_PLAYER)
|
||||
hacks::shared::esp::SetEntityColor(target.ent, colors::target);
|
||||
#endif
|
||||
// Set angles
|
||||
current_user_cmd->viewangles = angles;
|
||||
@ -1239,8 +1240,8 @@ bool Aim(CachedEntity *entity)
|
||||
if (silent && !slow_aim)
|
||||
g_pLocalPlayer->bUseSilentAngles = true;
|
||||
// Set tick count to targets (backtrack messes with this)
|
||||
if (!shouldBacktrack(entity) && nolerp && entity->m_IDX <= g_IEngine->GetMaxClients())
|
||||
current_user_cmd->tick_count = TIME_TO_TICKS(CE_FLOAT(entity, netvar.m_flSimulationTime));
|
||||
if (!shouldBacktrack(target.ent) && nolerp && target.ent->m_IDX <= g_IEngine->GetMaxClients())
|
||||
current_user_cmd->tick_count = TIME_TO_TICKS(CE_FLOAT(target.ent, netvar.m_flSimulationTime));
|
||||
aimed_this_tick = true;
|
||||
viewangles_this_tick = angles;
|
||||
// Finish function
|
||||
@ -1250,7 +1251,7 @@ bool Aim(CachedEntity *entity)
|
||||
// A function to check whether player can autoshoot
|
||||
bool begancharge = false;
|
||||
int begansticky = 0;
|
||||
void DoAutoshoot(CachedEntity *target_entity)
|
||||
void DoAutoshoot(AimbotTarget_t target)
|
||||
{
|
||||
// Enable check
|
||||
if (!autoshoot)
|
||||
@ -1335,10 +1336,10 @@ void DoAutoshoot(CachedEntity *target_entity)
|
||||
// TO DO: Sending both reload and attack will activate the hitmans heatmaker ability
|
||||
// Don't activate it only on first kill (or somehow activate it before a shot)
|
||||
current_user_cmd->buttons |= IN_ATTACK | (*autoreload && CarryingHeatmaker() ? IN_RELOAD : 0);
|
||||
if (target_entity)
|
||||
if (target.valid)
|
||||
{
|
||||
auto hitbox = cd.hitbox;
|
||||
hitrate::AimbotShot(target_entity->m_IDX, hitbox != head);
|
||||
auto hitbox = target.hitbox;
|
||||
hitrate::AimbotShot(target.ent->m_IDX, hitbox != head);
|
||||
}
|
||||
*bSendPackets = true;
|
||||
}
|
||||
@ -1347,11 +1348,11 @@ void DoAutoshoot(CachedEntity *target_entity)
|
||||
}
|
||||
|
||||
// Grab a vector for a specific ent
|
||||
Vector PredictEntity(CachedEntity *entity)
|
||||
Vector PredictEntity(AimbotTarget_t& target)
|
||||
{
|
||||
// Pull out predicted data
|
||||
Vector &result = cd.aim_position;
|
||||
const short int curr_type = entity->m_Type();
|
||||
Vector &result = target.aim_position;
|
||||
const short int curr_type = target.ent->m_Type();
|
||||
|
||||
// Players
|
||||
|
||||
@ -1365,9 +1366,9 @@ Vector PredictEntity(CachedEntity *entity)
|
||||
std::pair<Vector, Vector> tmp_result;
|
||||
// Use prediction engine if user settings allow
|
||||
if (engine_projpred)
|
||||
tmp_result = ProjectilePrediction_Engine(entity, cd.hitbox, cur_proj_speed, cur_proj_grav, PlayerGravityMod(entity), cur_proj_start_vel);
|
||||
tmp_result = ProjectilePrediction_Engine(target.ent, target.hitbox, cur_proj_speed, cur_proj_grav, PlayerGravityMod(target.ent), cur_proj_start_vel);
|
||||
else
|
||||
tmp_result = ProjectilePrediction(entity, cd.hitbox, cur_proj_speed, cur_proj_grav, PlayerGravityMod(entity), cur_proj_start_vel);
|
||||
tmp_result = ProjectilePrediction(target.ent, target.hitbox, cur_proj_speed, cur_proj_grav, PlayerGravityMod(target.ent), cur_proj_start_vel);
|
||||
|
||||
// Don't use the intial velocity compensated one in vischecks
|
||||
result = tmp_result.second;
|
||||
@ -1376,18 +1377,18 @@ Vector PredictEntity(CachedEntity *entity)
|
||||
{
|
||||
// If using extrapolation, then predict a vector
|
||||
if (extrapolate)
|
||||
result = SimpleLatencyPrediction(entity, cd.hitbox);
|
||||
result = SimpleLatencyPrediction(target.ent, target.hitbox);
|
||||
// else just grab strait from the hitbox
|
||||
else
|
||||
{
|
||||
// Allow multipoint logic to run
|
||||
if (!*multipoint)
|
||||
{
|
||||
result = entity->hitboxes.GetHitbox(cd.hitbox)->center;
|
||||
result = target.ent->hitboxes.GetHitbox(target.hitbox)->center;
|
||||
break;
|
||||
}
|
||||
|
||||
std::optional<Vector> best_pos = getBestHitpoint(entity, cd.hitbox);
|
||||
std::optional<Vector> best_pos = getBestHitpoint(target.ent, target.hitbox);
|
||||
if (best_pos)
|
||||
result = *best_pos;
|
||||
}
|
||||
@ -1399,30 +1400,30 @@ Vector PredictEntity(CachedEntity *entity)
|
||||
{
|
||||
if (cur_proj_grav != 0)
|
||||
{
|
||||
std::pair<Vector, Vector> temp_result = BuildingPrediction(entity, GetBuildingPosition(entity), cur_proj_speed, cur_proj_grav, cur_proj_start_vel);
|
||||
std::pair<Vector, Vector> temp_result = BuildingPrediction(target.ent, GetBuildingPosition(target.ent), cur_proj_speed, cur_proj_grav, cur_proj_start_vel);
|
||||
result = temp_result.second;
|
||||
}
|
||||
else
|
||||
result = GetBuildingPosition(entity);
|
||||
result = GetBuildingPosition(target.ent);
|
||||
break;
|
||||
}
|
||||
// NPCs (Skeletons, merasmus, etc)
|
||||
case ENTITY_NPC:
|
||||
{
|
||||
result = entity->hitboxes.GetHitbox(std::max(0, entity->hitboxes.GetNumHitboxes() / 2 - 1))->center;
|
||||
result = target.ent->hitboxes.GetHitbox(std::max(0, target.ent->hitboxes.GetNumHitboxes() / 2 - 1))->center;
|
||||
break;
|
||||
}
|
||||
|
||||
// Other
|
||||
default:
|
||||
{
|
||||
result = entity->m_vecOrigin();
|
||||
result = target.ent->m_vecOrigin();
|
||||
break;
|
||||
}
|
||||
}
|
||||
cd.predict_tick = tickcount;
|
||||
cd.fov = GetFov(g_pLocalPlayer->v_OrigViewangles, g_pLocalPlayer->v_Eye, result);
|
||||
|
||||
target.predict_tick = tickcount;
|
||||
target.fov = GetFov(g_pLocalPlayer->v_OrigViewangles, g_pLocalPlayer->v_Eye, result);
|
||||
target.aim_position = result;
|
||||
// Return the found vector
|
||||
return result;
|
||||
}
|
||||
@ -1632,13 +1633,13 @@ bool isAiming()
|
||||
// A function used by gui elements to determine the current target
|
||||
CachedEntity *CurrentTarget()
|
||||
{
|
||||
return target_last;
|
||||
return target_last.valid ? target_last.ent : nullptr;
|
||||
}
|
||||
|
||||
// Used for when you join and leave maps to reset aimbot vars
|
||||
void Reset()
|
||||
{
|
||||
target_last = nullptr;
|
||||
target_last = {};
|
||||
projectile_mode = false;
|
||||
}
|
||||
|
||||
@ -1681,7 +1682,7 @@ static void DrawText()
|
||||
|
||||
Vector screen;
|
||||
Vector oscreen;
|
||||
if (draw::WorldToScreen(cd.aim_position, screen) && draw::WorldToScreen(ent->m_vecOrigin(), oscreen))
|
||||
if (draw::WorldToScreen(target_last.aim_position, screen) && draw::WorldToScreen(ent->m_vecOrigin(), oscreen))
|
||||
{
|
||||
draw::Rectangle(screen.x - 2, screen.y - 2, 4, 4, colors::white);
|
||||
draw::Line(oscreen.x, oscreen.y, screen.x - oscreen.x, screen.y - oscreen.y, colors::EntityF(ent), 0.5f);
|
||||
|
Reference in New Issue
Block a user