Aimbot fixes, ESP Fixes, some prediction fixes

This commit is contained in:
stephen 2024-01-01 13:29:08 -05:00
parent 9be3695f2d
commit 85b0d210cb
6 changed files with 205 additions and 123 deletions

View File

@ -143,8 +143,9 @@ bool IsVectorVisible(Vector a, Vector b, bool enviroment_only = false, CachedEnt
// A Special function for navparser to check if a Vector is visible. // A Special function for navparser to check if a Vector is visible.
bool IsVectorVisibleNavigation(Vector a, Vector b, unsigned int mask = MASK_SHOT_HULL); bool IsVectorVisibleNavigation(Vector a, Vector b, unsigned int mask = MASK_SHOT_HULL);
float ProjGravMult(int class_id, float x_speed); float ProjGravMult(int class_id, float x_speed);
bool didProjectileHit(Vector start_point, Vector end_point, CachedEntity *entity, float projectile_size, bool grav_comp, trace_t* tracer = nullptr); bool didProjectileHit(Vector start_point, Vector end_point, CachedEntity *entity, float projectile_size, bool grav_comp, trace_t *tracer = nullptr);
Vector getShootPos(Vector angle); Vector getShootPos(Vector angle);
bool is_rocket(int);
Vector GetForwardVector(Vector origin, Vector viewangles, float distance, CachedEntity *punch_entity = nullptr); Vector GetForwardVector(Vector origin, Vector viewangles, float distance, CachedEntity *punch_entity = nullptr);
Vector GetForwardVector(float distance, CachedEntity *punch_entity = nullptr); Vector GetForwardVector(float distance, CachedEntity *punch_entity = nullptr);
CachedEntity *getClosestEntity(Vector vec); CachedEntity *getClosestEntity(Vector vec);

View File

@ -199,14 +199,14 @@ inline float projectileHitboxSize(int projectile_size)
case CL_CLASS(CTFPipebombLauncher): case CL_CLASS(CTFPipebombLauncher):
case CL_CLASS(CTFGrenadeLauncher): case CL_CLASS(CTFGrenadeLauncher):
case CL_CLASS(CTFCannon): case CL_CLASS(CTFCannon):
return 6.5f; return 4.0f;
case CL_CLASS(CTFFlareGun): case CL_CLASS(CTFFlareGun):
case CL_CLASS(CTFFlareGun_Revenge): case CL_CLASS(CTFFlareGun_Revenge):
case CL_CLASS(CTFDRGPomson): case CL_CLASS(CTFDRGPomson):
return 3.0f; return 2.0f;
case CL_CLASS(CTFSyringeGun): case CL_CLASS(CTFSyringeGun):
case CL_CLASS(CTFCompoundBow): case CL_CLASS(CTFCompoundBow):
return 2.0f; return 1.0f;
default: default:
return 3.0f; return 3.0f;
} }
@ -1169,6 +1169,15 @@ bool IsTargetStateGood(CachedEntity *entity)
return false; return false;
} }
float secant_x(float in)
{
return 1.0f / (cos(in));
}
float csc_x(float in)
{
return 1.0f / (sin(in));
}
bool Aim(CachedEntity *entity) bool Aim(CachedEntity *entity)
{ {
if (*miss_chance > 0 && UniformRandomInt(0, 99) < *miss_chance) if (*miss_chance > 0 && UniformRandomInt(0, 99) < *miss_chance)
@ -1180,47 +1189,52 @@ bool Aim(CachedEntity *entity)
if (!IsEntityVectorVisible(entity, is_it_good, true, MASK_SHOT_HULL, nullptr, true)) if (!IsEntityVectorVisible(entity, is_it_good, true, MASK_SHOT_HULL, nullptr, true))
return false; return false;
Vector angles = GetAimAtAngles(g_pLocalPlayer->v_Eye, is_it_good, LOCAL_E); Vector player_velocity;
velocity::EstimateAbsVelocity(RAW_ENT(LOCAL_E), player_velocity);
Vector angles = GetAimAtAngles(g_pLocalPlayer->v_Eye + player_velocity * TICKS_TO_TIME(1), is_it_good, LOCAL_E);
if (projectileAimbotRequired) // unfortunately you have to check this twice, otherwise you'd have to run GetAimAtAngles far too early 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); const bool grav_comp = (0.01f < cur_proj_grav);
Vector shot_orig = getShootPos(angles);
if (grav_comp) if (grav_comp)
{ {
const QAngle &angl = VectorToQAngle(angles); float max_vel = cur_proj_speed;
Vector end_targ = is_it_good; float sv_gravity = g_ICvar->FindVar("sv_gravity")->GetFloat() * cur_proj_grav;
Vector fwd, right, up; float dist = (cur_proj_speed * cur_proj_speed) / (sv_gravity);
AngleVectors3(angl, &fwd, &right, &up); if (g_pLocalPlayer->v_Eye.DistTo(is_it_good) > dist)
// I have no clue why this is 200.0f, No where in the SDK explains this. return false;
// It appears to work though float angles_x = DEG2RAD(angles.x);
Vector vel = 0.9f * ((fwd * cur_proj_speed) + (up * 200.0f)); float angles_y = DEG2RAD(angles.y);
fwd.z = 0.0f; float t_x = ((is_it_good.x - shot_orig.x) * secant_x(angles_x) * secant_x(angles_y)) / cur_proj_speed;
fwd.NormalizeInPlace(); float t_y = ((is_it_good.y - shot_orig.y) * secant_x(angles_x) * csc_x(angles_y)) / cur_proj_speed;
float alongvel = std::sqrt(vel.x * vel.x + vel.y * vel.y); float t_z = -1.0f * (cur_proj_speed * sin(angles_x) + std::sqrt(-2 * sv_gravity * is_it_good.z + 2 * sv_gravity * shot_orig.z + cur_proj_speed * cur_proj_speed * sin(angles_x) * sin(angles_x))) / (cur_proj_grav);
fwd *= alongvel; if (!t_z)
const float gravity = cur_proj_grav * g_ICvar->FindVar("sv_gravity")->GetFloat() * -1.0f; t_z = 9999999999.0f;
const float maxTime = 2.5f;
const float timeStep = 0.01f; if (t_z < 0.0f)
Vector curr_pos = orig; t_z = 9999999999.0f;
trace_t ptr_trace; if (t_x < 0.0f)
Vector last_pos = orig; t_x = 999999999.0f;
const IClientEntity *rawest_ent = RAW_ENT(entity); if (t_y < 0.0f)
for (float t = 0.0f; t < maxTime; t += timeStep, last_pos = curr_pos) t_y = 99999999.0f;
float t_min = std::min(t_x, t_y);
t_min = std::min(t_min, t_z);
const float t_min_inc = t_min / 10.0f;
Vector second_iter = shot_orig;
for (float t = 0.0f; t < t_min; t += t_min_inc)
{ {
curr_pos.x = orig.x + fwd.x * t; Vector loop_vec = shot_orig;
curr_pos.y = orig.y + fwd.y * t; loop_vec.x += (cur_proj_speed * cos(angles_x) * cos(angles_y)) * t;
curr_pos.z = orig.z + vel.z * t + 0.5f * gravity * t * t; loop_vec.y += (cur_proj_speed * cos(angles_x) * sin(angles_y)) * t;
if (!didProjectileHit(last_pos, curr_pos, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), true, &ptr_trace) || (IClientEntity *) ptr_trace.m_pEnt == rawest_ent) loop_vec.z += (cur_proj_speed * -1.0f * sin(angles_x)) * t - 0.5f * sv_gravity * t * t;
break; if (!didProjectileHit(second_iter, loop_vec, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), grav_comp))
return false;
second_iter = loop_vec;
} }
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)) else if (!didProjectileHit(shot_orig, is_it_good, entity, projectileHitboxSize(LOCAL_W->m_iClassID()), grav_comp))
return false; return false;
} }
if (fov > 0 && cd.fov > fov) if (fov > 0 && cd.fov > fov)
@ -1512,7 +1526,7 @@ int autoHitbox(CachedEntity *target)
} }
// Rockets and stickies should aim at the foot if the target is on the ground // Rockets and stickies should aim at the foot if the target is on the ground
else if (ci == CL_CLASS(CTFPipebombLauncher) || ci == CL_CLASS(CTFRocketLauncher) || ci == CL_CLASS(CTFParticleCannon) || ci == CL_CLASS(CTFRocketLauncher_AirStrike) || ci == CL_CLASS(CTFRocketLauncher_Mortar) || ci == CL_CLASS(CTFRocketLauncher_DirectHit)) else if (ci == CL_CLASS(CTFPipebombLauncher) || is_rocket(ci))
{ {
bool ground = CE_INT(target, netvar.iFlags) & (1 << 0); bool ground = CE_INT(target, netvar.iFlags) & (1 << 0);
if (ground) if (ground)

View File

@ -76,13 +76,12 @@ static settings::Boolean proj_enemy{ "esp.projectile.enemy-only", "true" };
static settings::Boolean entity_info{ "esp.debug.entity", "false" }; static settings::Boolean entity_info{ "esp.debug.entity", "false" };
static settings::Boolean entity_model{ "esp.debug.model", "false" }; static settings::Boolean entity_model{ "esp.debug.model", "false" };
static settings::Boolean entity_id{ "esp.debug.id", "true" }; static settings::Boolean entity_id{ "esp.debug.id", "true" };
// Forward declarations // Forward declarations
class ESPData class ESPData
{ {
public: public:
int string_count{ 0 }; int string_count{ 0 };
boost::unordered_flat_map<std::string, rgba_t> strings{}; std::vector<std::pair<std::string, rgba_t>> strings{};
rgba_t color{ colors::empty }; rgba_t color{ colors::empty };
bool needs_paint{ false }; bool needs_paint{ false };
bool has_collide{ false }; bool has_collide{ false };
@ -95,8 +94,8 @@ boost::unordered_flat_map<u_int16_t, ESPData> data;
inline void AddEntityString(CachedEntity *entity, const std::string &string, const rgba_t &color = colors::empty) inline void AddEntityString(CachedEntity *entity, const std::string &string, const rgba_t &color = colors::empty)
{ {
ESPData &entity_data = data[entity->m_IDX]; ESPData &entity_data = data[entity->m_IDX];
if (entity_data.strings.try_emplace(string, color).second) entity_data.strings.emplace_back(string, color);
++(entity_data.string_count); ++(entity_data.string_count);
entity_data.needs_paint = true; entity_data.needs_paint = true;
} }
inline bool hitboxUpdate(CachedEntity *ent) inline bool hitboxUpdate(CachedEntity *ent)
@ -926,6 +925,8 @@ void ProcessEntityPT()
if (ent_data.string_count) if (ent_data.string_count)
DrawStrings(type, transparent, screen, ent_data, ent); DrawStrings(type, transparent, screen, ent_data, ent);
} }
for (auto &[key, esp_data] : data)
esp_data.strings.clear();
} }
static std::string write_str; static std::string write_str;
// Used to process entities from CreateMove // Used to process entities from CreateMove

View File

@ -17,6 +17,7 @@
#include "Think.hpp" #include "Think.hpp"
#include "Aimbot.hpp" #include "Aimbot.hpp"
#include <Misc.hpp> #include <Misc.hpp>
#include <limits>
namespace hacks::tf2::warp namespace hacks::tf2::warp
{ {
static settings::Boolean enabled{ "warp.enabled", "false" }; static settings::Boolean enabled{ "warp.enabled", "false" };
@ -47,7 +48,7 @@ static settings::Boolean warp_left{ "warp.on-hit.left", "true" };
static settings::Boolean warp_right{ "warp.on-hit.right", "true" }; static settings::Boolean warp_right{ "warp.on-hit.right", "true" };
static settings::Boolean debug_seqout{ "debug.warp_seqout", "false" }; static settings::Boolean debug_seqout{ "debug.warp_seqout", "false" };
static std::vector<std::tuple<Vector, CachedEntity *>> proj_map; static boost::unordered_flat_map<CachedEntity *, Vector> proj_map;
// Hidden control rvars for communtiy servers // Hidden control rvars for communtiy servers
static settings::Int maxusrcmdprocessticks("warp.maxusrcmdprocessticks", "24"); static settings::Int maxusrcmdprocessticks("warp.maxusrcmdprocessticks", "24");
@ -261,118 +262,169 @@ bool shouldRapidfire()
return buttons_pressed; return buttons_pressed;
} }
void dodgeProj(CachedEntity *proj_ptr) void dodgeProj(CachedEntity *proj_ptr)
{ {
Vector eav; Vector eav;
const Vector player_origin = RAW_ENT(LOCAL_E)->GetAbsOrigin();
velocity::EstimateAbsVelocity(RAW_ENT(proj_ptr), eav); velocity::EstimateAbsVelocity(RAW_ENT(proj_ptr), eav);
// Sometimes EstimateAbsVelocity returns completely BS values (as in 0 for everything on say a rocket) // Sometimes EstimateAbsVelocity returns completely BS values (as in 0 for everything on say a rocket)
// The ent could also be an in-place sticky which we don't care about - we want to catch it while it's in the air // The ent could also be an in-place sticky which we don't care about - we want to catch it while it's in the air
if (1 < eav.Length()) if (1 < eav.Length())
{ {
Vector proj_pos = RAW_ENT(proj_ptr)->GetAbsOrigin(); Vector proj_pos = RAW_ENT(proj_ptr)->GetAbsOrigin();
Vector player_pos = RAW_ENT(LOCAL_E)->GetAbsOrigin(); float multipler = 2.0f;
float displacement = proj_pos.DistToSqr(player_pos);
float displacement_temp = displacement - 1;
float min_displacement = displacement_temp - 1;
float multipler = 0.01f;
bool add_grav = false; bool add_grav = false;
float high_time = 10;
float low_time = 0;
float high_displacement = std::numeric_limits<float>::max();
float curr_grav = g_ICvar->FindVar("sv_gravity")->GetFloat(); float curr_grav = g_ICvar->FindVar("sv_gravity")->GetFloat();
if (proj_ptr->m_Type() == ENTITY_PROJECTILE) if (proj_ptr->m_Type() == ENTITY_PROJECTILE && ProjGravMult(proj_ptr->m_iClassID(), eav.Length()) > 0.001f)
add_grav = true; add_grav = true;
// Couldn't find a cleaner way to get the projectiles gravity based on just having a pointer to the projectile itself // Couldn't find a cleaner way to get the projectiles gravity based on just having a pointer to the projectile itself
curr_grav = curr_grav * ProjGravMult(proj_ptr->m_iClassID(), eav.Length()); curr_grav = curr_grav * ProjGravMult(proj_ptr->m_iClassID(), eav.Length());
// Optimization loop. Just checks if the projectile can possibly hit within ~141HU // Optimization loop. Just checks if the projectile can possibly hit within ~141HU
while (displacement_temp < displacement)
if (!add_grav)
{
float c_1 = ((float) (player_origin - proj_pos).Dot(eav)) / ((float) eav.Dot(eav));
// logging::Info("C_1 is %f for the entity id %d, the velocity is %f. The distance is %f", c_1, proj_ptr->m_Type(), eav.Length(), (eav * c_1 + proj_pos).DistTo(player_origin));
if (c_1 > 0)
{
float dist = (eav * c_1 + proj_pos).DistToSqr(player_origin);
if (dist > 40000)
proj_map.insert({ proj_ptr, Vector(0, 0, 0) });
else
proj_map.insert({ proj_ptr, eav });
}
return;
}
float last_displacement = high_displacement;
int sign = 1;
int repeats = 0;
while (high_time > 0.01f)
{ {
Vector temp_pos = (eav * multipler) + proj_pos; Vector temp_pos = (eav * high_time) + proj_pos;
if (add_grav) temp_pos.z = temp_pos.z - 0.5 * curr_grav * high_time * high_time;
temp_pos.z = temp_pos.z - 0.5 * curr_grav * multipler * multipler; float curr_disp = temp_pos.DistToSqr(player_origin);
displacement_temp = temp_pos.DistToSqr(player_pos); if (curr_disp < high_displacement)
if (displacement_temp < min_displacement) {
min_displacement = displacement_temp; repeats = 0;
high_displacement = curr_disp;
high_time -= multipler * sign;
if (multipler > 0.05f)
multipler /= 2.0f;
}
else if (last_displacement < curr_disp)
{
++repeats;
sign *= -1;
}
else else
break; {
repeats = 0;
multipler += 0.01f; }
if (repeats > 2)
{
// logging::Info(" entity id %d, the velocity is %f. The distance is %f", proj_ptr->m_Type(), eav.Length(), curr_disp);
proj_map.insert({ proj_ptr, Vector(0, 0, 0) });
return;
}
last_displacement = curr_disp;
if (high_displacement < 40000)
{
// logging::Info(" entity id %d, the velocity is %f. The distance is %f", proj_ptr->m_Type(), eav.Length(), curr_disp);
proj_map.insert({ proj_ptr, eav });
return;
}
else
{
// logging::Info(" entity id %d, the velocity is %f. The distance is %f", proj_ptr->m_Type(), eav.Length(), curr_disp);
proj_map.insert({ proj_ptr, Vector(0, 0, 0) });
return;
}
} }
if (min_displacement < 20000)
proj_map.emplace_back((std::make_tuple(eav, proj_ptr)));
else
proj_map.emplace_back((std::make_tuple(Vector{ 0, 0, 0 }, proj_ptr)));
} }
} }
float hitbox_size_proj(int class_id)
{
switch (class_id)
{
case CL_CLASS(CTFProjectile_Rocket):
return 4.0f;
case CL_CLASS(CTFGrenadePipebombProjectile):
return 4.0f;
case CL_CLASS(CTFProjectile_Flare):
return 3.0f;
case CL_CLASS(CTFProjectile_EnergyBall):
return 8.0f;
case CL_CLASS(CTFProjectile_GrapplingHook):
case CL_CLASS(CTFProjectile_HealingBolt):
case CL_CLASS(CTFProjectile_Arrow):
return 1.0f;
case CL_CLASS(CTFProjectile_SentryRocket):
return 2.0f;
case CL_CLASS(CTFProjectile_Throwable):
return 4.0f;
}
return 1.0f;
}
static void dodgeProj_cm() static void dodgeProj_cm()
{ {
if (!LOCAL_E->m_bAlivePlayer() || proj_map.empty() || !dodge_projectile) if (!LOCAL_E->m_bAlivePlayer() || proj_map.empty() || !dodge_projectile)
return; return;
Vector player_pos = RAW_ENT(LOCAL_E)->GetAbsOrigin(); Vector player_pos = RAW_ENT(LOCAL_E)->GetAbsOrigin();
const int max_size = proj_map.size(); for (const auto &[proj_ptr, proj_vec] : proj_map)
for (int i = 0; i < max_size; ++i)
{ {
auto curr_tuple = proj_map[i]; if (proj_vec.Length() < 0.1f)
Vector key = std::get<0>(curr_tuple);
CachedEntity *val = std::get<1>(curr_tuple);
if (key.Length() < 0.1f)
{ {
if (CE_GOOD(val)) if (CE_GOOD(proj_ptr))
continue; continue;
else else
proj_map.erase((proj_map.begin() + i)); proj_map.erase(proj_ptr);
continue; continue;
} }
if (CE_GOOD(val)) if (CE_GOOD(proj_ptr))
{ {
// Since we are sending this warp next tick we need to compensate for fast moving projectiles // Since we are sending this warp next tick we need to compensate for fast moving projectiles
// 2 Ticks in advance is a fairly safe interval // 2 Ticks in advance is a fairly safe interval
Vector velocity_comp = key * 2 * TICK_INTERVAL; float c_1 = ((float) (g_pLocalPlayer->v_Origin - RAW_ENT(proj_ptr)->GetAbsOrigin()).Dot(proj_vec)) / ((float) proj_vec.Dot(proj_vec));
velocity_comp.z -= 2 * TICK_INTERVAL * g_ICvar->FindVar("sv_gravity")->GetFloat() * ProjGravMult(val->m_iClassID(), key.Length()); float ticks = TIME_TO_TICKS(c_1);
if (ticks > 30)
Vector proj_next_tik = RAW_ENT(val)->GetAbsOrigin() + velocity_comp; continue;
float diff = proj_next_tik.DistToSqr(player_pos); float max_speed = CE_FLOAT(LOCAL_E, netvar.m_flMaxspeed);
Vector dist = RAW_ENT(proj_ptr)->GetAbsOrigin();
float proj_hitbox = hitbox_size_proj(proj_ptr->m_iClassID());
// Warp sooner for fast moving projectiles. // Warp sooner for fast moving projectiles.
if (diff < (15000 * (key.Length() / 1000))) trace_t trace;
Ray_t ray;
ray.Init(dist, player_pos, Vector(-proj_hitbox, -proj_hitbox, -proj_hitbox), Vector(proj_hitbox, proj_hitbox, proj_hitbox));
g_ITrace->TraceRay(ray, MASK_SHOT_HULL, NULL, &trace);
if (((IClientEntity *) trace.m_pEnt) != RAW_ENT(LOCAL_E) && trace.endpos.DistToSqr(player_pos) < 10000 && (ProjGravMult(proj_ptr->m_iClassID(), proj_vec.Length()) < 0.001f || proj_ptr->m_iClassID() == CL_CLASS(CTFGrenadePipebombProjectile)))
{ {
trace_t trace;
Ray_t ray;
ray.Init(proj_next_tik, player_pos, Vector(0, -8, -8), Vector(0, 8, 8));
g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_default, &trace);
if (trace.DidHit())
{
// We need to determine wether the projectile is coming in from the left or right of us so we don't warp into the projectile. ray.Init(trace.endpos, player_pos, Vector(0, 0, 0), Vector(0, 0, 0));
Vector result = GetAimAtAngles(g_pLocalPlayer->v_Eye, RAW_ENT(val)->GetAbsOrigin(), LOCAL_E) - g_pLocalPlayer->v_OrigViewangles; g_ITrace->TraceRay(ray, MASK_SHOT_HULL, NULL, &trace);
}
if (((IClientEntity *) trace.m_pEnt) == RAW_ENT(LOCAL_E) || trace.DidHit() || trace.endpos.DistToSqr(player_pos) < 10)
{
// logging::Info("ENTERED");
// We need to determine wether the projectile is coming in from the left or right of us so we don't warp into the projectile.
Vector result = GetAimAtAngles(g_pLocalPlayer->v_Eye, RAW_ENT(proj_ptr)->GetAbsOrigin(), LOCAL_E) - g_pLocalPlayer->v_OrigViewangles;
if (0 <= result.y) if (0 <= result.y)
yaw_amount = -90.0f; yaw_amount = -90.0f;
else
yaw_amount = 90.0f;
if ((IClientEntity *) trace.m_pEnt == RAW_ENT(LOCAL_E))
{
was_hurt = true;
warp_dodge = true;
proj_map.erase((proj_map.begin() + i));
}
} // It didn't hit anything but it has been proven to be very close to us. Dodge. (This is for the huntsman+pills)
else else
{ yaw_amount = 90.0f;
was_hurt = true; was_hurt = true;
warp_dodge = true; warp_dodge = true;
Vector result = GetAimAtAngles(g_pLocalPlayer->v_Eye, RAW_ENT(val)->GetAbsOrigin(), LOCAL_E) - g_pLocalPlayer->v_OrigViewangles; proj_map.erase(proj_ptr);
if (0 <= result.y)
yaw_amount = -90.0f;
else
yaw_amount = 90.0f;
proj_map.erase((proj_map.begin() + i));
}
} }
} }
else else
proj_map.erase((proj_map.begin() + i)); proj_map.erase(proj_ptr);
} }
} }
// Should we warp? // Should we warp?
@ -720,7 +772,7 @@ static void CreateMove()
warpLogic(); warpLogic();
if ((bool) hacks::tf2::warp::dodge_projectile && CE_GOOD(g_pLocalPlayer->entity)) if ((bool) hacks::tf2::warp::dodge_projectile && CE_GOOD(g_pLocalPlayer->entity))
for (auto const &ent : entity_cache::valid_ents) for (auto const &ent : entity_cache::valid_ents)
if (ent->m_Type() == ENTITY_PROJECTILE && ent->m_bEnemy() && std::find_if(proj_map.begin(), proj_map.end(), [=](const auto &item) { return std::get<1>(item) == ent; }) == proj_map.end()) if (ent->m_Type() == ENTITY_PROJECTILE && ent->m_bEnemy() && proj_map.find(ent) == proj_map.end())
dodgeProj(ent); dodgeProj(ent);
// Either in rapidfire, or the tick just after. Either way we need to force bSendPackets in some way. // Either in rapidfire, or the tick just after. Either way we need to force bSendPackets in some way.
bool should_rapidfire = shouldRapidfire(); bool should_rapidfire = shouldRapidfire();
@ -1223,7 +1275,7 @@ static InitRoutine init(
EC::Register(EC::CreateMove, CreateMove, "warp_createmove", EC::very_late); EC::Register(EC::CreateMove, CreateMove, "warp_createmove", EC::very_late);
EC::Register(EC::CreateMoveWarp, CreateMove, "warp_createmovew", EC::very_late); EC::Register(EC::CreateMoveWarp, CreateMove, "warp_createmovew", EC::very_late);
EC::Register(EC::CreateMove_NoEnginePred, CreateMovePrePredict, "warp_prepredict"); EC::Register(EC::CreateMove_NoEnginePred, CreateMovePrePredict, "warp_prepredict");
EC::Register(EC::CreateMove, dodgeProj_cm, "warp_dodgeproj", EC::very_early); EC::Register(EC::CreateMove, dodgeProj_cm, "warp_dodgeproj", EC::average);
EC::Register(EC::CreateMoveEarly, CreateMoveEarly, "warp_createmove_early", EC::very_early); EC::Register(EC::CreateMoveEarly, CreateMoveEarly, "warp_createmove_early", EC::very_early);
g_IEventManager2->AddListener(&listener, "player_hurt", false); g_IEventManager2->AddListener(&listener, "player_hurt", false);
EC::Register( EC::Register(

View File

@ -28,7 +28,22 @@ std::vector<ConCommand *> &RegisteredCommandsList()
static std::vector<ConCommand *> list{}; static std::vector<ConCommand *> list{};
return list; return list;
} }
bool is_rocket(int class_id)
{
switch (class_id)
{
case CL_CLASS(CTFRocketLauncher):
case CL_CLASS(CTFParticleCannon):
case CL_CLASS(CTFRocketLauncher_AirStrike):
case CL_CLASS(CTFRocketLauncher_Mortar):
case CL_CLASS(CTFRocketLauncher_DirectHit):
return true;
default:
return false;
}
return false;
}
void BeginConVars() void BeginConVars()
{ {
logging::Info("Begin ConVars"); logging::Info("Begin ConVars");
@ -661,7 +676,7 @@ bool didProjectileHit(Vector start_point, Vector end_point, CachedEntity *entity
trace_obj = tracer; trace_obj = tracer;
else else
trace_obj = new trace_t; trace_obj = new trace_t;
ray.Init(start_point, end_point, Vector(0, -projectile_size, -projectile_size), Vector(0, projectile_size, projectile_size)); ray.Init(start_point, end_point, Vector(-projectile_size, -projectile_size, -projectile_size), Vector(projectile_size, projectile_size, projectile_size));
g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_default, trace_obj); g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_default, trace_obj);
return (((IClientEntity *) trace_obj->m_pEnt) == RAW_ENT(entity) || (grav_comp ? !trace_obj->DidHit() : false)); return (((IClientEntity *) trace_obj->m_pEnt) == RAW_ENT(entity) || (grav_comp ? !trace_obj->DidHit() : false));
} }
@ -1880,7 +1895,7 @@ Vector getShootPos(Vector angle)
// Huntsman // Huntsman
case CL_CLASS(CTFCompoundBow): case CL_CLASS(CTFCompoundBow):
vecOffset = Vector(23.5f, 8.0f, -3.0f); vecOffset = Vector(23.5f, -8.0f, -3.0f);
break; break;
default: default:

View File

@ -319,7 +319,7 @@ void Prediction_PaintTraverse()
for (auto const &ent : entity_cache::player_cache) for (auto const &ent : entity_cache::player_cache)
{ {
if (CE_BAD(ent) || !ent->m_bAlivePlayer()) if (CE_BAD(ent) || !ent->m_bAlivePlayer())
continue; continue;
@ -504,11 +504,10 @@ Vector EnginePrediction(CachedEntity *entity, float time, Vector *vecVelocity)
} }
std::pair<Vector, Vector> ProjectilePrediction_Engine(CachedEntity *ent, int hb, float speed, float gravity, float entgmod, float proj_startvelocity) std::pair<Vector, Vector> ProjectilePrediction_Engine(CachedEntity *ent, int hb, float speed, float gravity, float entgmod, float proj_startvelocity)
{ {
Vector origin = ent->m_vecOrigin(); Vector origin = RAW_ENT(ent)->GetAbsOrigin();
Vector velocity; Vector velocity;
velocity::EstimateAbsVelocity(RAW_ENT(ent), velocity); velocity::EstimateAbsVelocity(RAW_ENT(ent), velocity);
Vector hitbox; Vector hitbox = ent->hitboxes.GetHitbox(hb)->center;
GetHitbox(ent, hb, hitbox);
Vector hitbox_offset = hitbox - origin; Vector hitbox_offset = hitbox - origin;
if (!sv_gravity) if (!sv_gravity)
@ -561,7 +560,7 @@ std::pair<Vector, Vector> ProjectilePrediction_Engine(CachedEntity *ent, int hb,
// Compensate for ping // Compensate for ping
besttime += g_IEngine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING) + cl_interp->GetFloat(); besttime += g_IEngine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING) + cl_interp->GetFloat();
bestpos.z += (sv_gravity->GetFloat() / 2.0f * besttime * besttime * gravity); bestpos.z += (sv_gravity->GetFloat() / 2.0f * besttime * besttime * gravity);
// S = at^2/2 ; t = sqrt(2S/a)*/ // S = at^2/2 ; t = sqrt(2S/a)*/
Vector result = bestpos + hitbox_offset; Vector result = bestpos + hitbox_offset;
Vector result_initialvel = result; Vector result_initialvel = result;
result_initialvel.z -= proj_startvelocity * besttime; result_initialvel.z -= proj_startvelocity * besttime;
@ -732,9 +731,9 @@ static InitRoutine init(
// Don't run if we don't use it // Don't run if we don't use it
if (!hacks::shared::aimbot::engine_projpred && !debug_pp_draw) if (!hacks::shared::aimbot::engine_projpred && !debug_pp_draw)
return; return;
for (auto const &ent: entity_cache::player_cache) for (auto const &ent : entity_cache::player_cache)
{ {
auto &buffer = previous_positions.at(ent->m_IDX - 1); auto &buffer = previous_positions.at(ent->m_IDX - 1);
if (CE_BAD(LOCAL_E) || CE_BAD(ent) || !ent->m_bAlivePlayer()) if (CE_BAD(LOCAL_E) || CE_BAD(ent) || !ent->m_bAlivePlayer())