diff --git a/data/menu/nullifiedcat/weapons/aimbot.xml b/data/menu/nullifiedcat/weapons/aimbot.xml index 98727b50..59702f5c 100755 --- a/data/menu/nullifiedcat/weapons/aimbot.xml +++ b/data/menu/nullifiedcat/weapons/aimbot.xml @@ -26,8 +26,8 @@ - + @@ -86,6 +86,13 @@ + + + diff --git a/include/hacks/Aimbot.hpp b/include/hacks/Aimbot.hpp index 1e8ba2ff..95df743f 100644 --- a/include/hacks/Aimbot.hpp +++ b/include/hacks/Aimbot.hpp @@ -43,9 +43,11 @@ bool IsTargetStateGood(CachedEntity *entity); bool Aim(CachedEntity *entity); void DoAutoshoot(CachedEntity *target = nullptr); int notVisibleHitbox(CachedEntity *target, int preferred); -int autoHitbox(CachedEntity* target); -bool hitscanSpecialCases(CachedEntity* target_entity, int weapon_case); -bool projectileSpecialCases(CachedEntity* target_entity, int weapon_case); +std::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); int BestHitbox(CachedEntity *target); bool isHitboxMedium(int hitbox); int ClosestHitbox(CachedEntity *target); diff --git a/include/helpers.hpp b/include/helpers.hpp index 784f2c0a..21a06fa0 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -118,6 +118,7 @@ bool GetProjectileData(CachedEntity *weapon, float &speed, float &gravity, float bool IsVectorVisible(Vector a, Vector b, bool enviroment_only = false, CachedEntity *self = LOCAL_E, unsigned int mask = MASK_SHOT_HULL); // 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 didProjectileHit(Vector start_point, Vector end_point, CachedEntity *entity, int projectile_size); Vector getShootPos(Vector angle); Vector GetForwardVector(Vector origin, Vector viewangles, float distance, CachedEntity *punch_entity = nullptr); Vector GetForwardVector(float distance, CachedEntity *punch_entity = nullptr); diff --git a/include/prediction.hpp b/include/prediction.hpp index 39066041..44c04878 100644 --- a/include/prediction.hpp +++ b/include/prediction.hpp @@ -24,10 +24,9 @@ Vector SimpleLatencyPrediction(CachedEntity *ent, int hb); // The first entry ignores initial velocity, the second one does not. // Used for vischeck things. -std::pair BuildingPrediction(CachedEntity *building, Vector vec, float speed, float gravity, float proj_startvelocity = 0.0f); std::pair ProjectilePrediction(CachedEntity *ent, int hb, float speed, float gravitymod, float entgmod, float proj_startvelocity = 0.0f); std::pair ProjectilePrediction_Engine(CachedEntity *ent, int hb, float speed, float gravitymod, float entgmod, float proj_startvelocity = 0.0f); - +std::pair BuildingPrediction(CachedEntity *building, Vector vec, float speed, float gravity, float proj_startvelocity); std::vector Predict(CachedEntity *player, Vector pos, float offset, Vector vel, Vector acceleration, std::pair minmax, int count, bool vischeck = true); Vector PredictStep(Vector pos, Vector &vel, const Vector &acceleration, std::pair *minmax, float steplength = g_GlobalVars->interval_per_tick, StrafePredictionData *strafepred = nullptr, bool vischeck = true, std::optional grounddistance = std::nullopt); float PlayerGravityMod(CachedEntity *player); diff --git a/src/hacks/Aimbot.cpp b/src/hacks/Aimbot.cpp index 25545fd8..fc1f93bf 100644 --- a/src/hacks/Aimbot.cpp +++ b/src/hacks/Aimbot.cpp @@ -29,6 +29,7 @@ static settings::Boolean autoshoot{ "aimbot.autoshoot", "1" }; static settings::Boolean autoreload{ "aimbot.autoshoot.activate-heatmaker", "false" }; static settings::Boolean autoshoot_disguised{ "aimbot.autoshoot-disguised", "1" }; static settings::Boolean multipoint{ "aimbot.multipoint", "0" }; +static settings::Int vischeck_hitboxes{ "aimbot.vischeck-hitboxes", "0" }; static settings::Int hitbox_mode{ "aimbot.hitbox-mode", "0" }; static settings::Float normal_fov{ "aimbot.fov", "0" }; static settings::Int priority_mode{ "aimbot.priority-mode", "0" }; @@ -147,7 +148,7 @@ std::vector getValidHitpoints(CachedEntity *ent, int hitbox) hitpoints.push_back(hb->center); } - if (!multipoint) + if (!*multipoint) return hitpoints; // Multipoint @@ -186,6 +187,77 @@ std::vector getValidHitpoints(CachedEntity *ent, int hitbox) positions.insert(positions.end(), corners, &corners[8]); positions.insert(positions.end(), line_positions, &line_positions[12]); + for (int i = 0; i < 20; ++i) + { + trace_t trace; + if (IsEntityVectorVisible(ent, positions[i], true, MASK_SHOT_HULL, &trace)) + { + if (trace.hitbox == hitbox) + hitpoints.push_back(positions[i]); + } + } + if (*vischeck_hitboxes) + { + if (*vischeck_hitboxes == 1 && playerlist::AccessData(ent).state != playerlist::k_EState::RAGE) + { + return hitpoints; + } + int i = 0; + while (hitpoints.empty() && i <= 17) // Prevents returning empty at all costs. Loops through every hitbox + { + if (hitbox == i) + i++; + hitpoints = getHitpointsVischeck(ent, i); + i++; + } + } + + return hitpoints; +} +std::vector getHitpointsVischeck(CachedEntity *ent, int hitbox) +{ + std::vector hitpoints; + auto hb = ent->hitboxes.GetHitbox(hitbox); + if (!*multipoint) + { + hitpoints.push_back(hb->center); + return hitpoints; + } + auto bboxmin = hb->bbox->bbmin; + auto bboxmax = hb->bbox->bbmax; + + auto transform = ent->hitboxes.GetBones()[hb->bbox->bone]; + QAngle rotation; + Vector origin; + + MatrixAngles(transform, rotation, origin); + + Vector corners[8]; + GenerateBoxVertices(origin, rotation, bboxmin, bboxmax, corners); + + float shrink_size = 1; + + if (!isHitboxMedium(hitbox)) // hitbox should be chosen based on size. + shrink_size = 3; + else + shrink_size = 6; + + // Shrink positions by moving towards opposing corner + for (int i = 0; i < 8; i++) + corners[i] += (corners[7 - i] - corners[i]) / shrink_size; + + // Generate middle points on line segments + // Define cleans up code + + const Vector line_positions[12] = { GET_MIDDLE(0, 1), GET_MIDDLE(0, 2), GET_MIDDLE(1, 3), GET_MIDDLE(2, 3), GET_MIDDLE(7, 6), GET_MIDDLE(7, 5), GET_MIDDLE(6, 4), GET_MIDDLE(5, 4), GET_MIDDLE(0, 4), GET_MIDDLE(1, 5), GET_MIDDLE(2, 6), GET_MIDDLE(3, 7) }; + + // Create combined vector + std::vector positions; + + positions.reserve(sizeof(Vector) * 20); + positions.insert(positions.end(), corners, &corners[8]); + positions.insert(positions.end(), line_positions, &line_positions[12]); + for (int i = 0; i < 20; ++i) { trace_t trace; @@ -845,6 +917,36 @@ bool IsTargetStateGood(CachedEntity *entity) AimbotCalculatedData_s &cd = calculated_data_array[entity->m_IDX]; cd.hitbox = BestHitbox(entity); + if (*vischeck_hitboxes && !*multipoint) + { + if (*vischeck_hitboxes == 1 && playerlist::AccessData(entity).state != playerlist::k_EState::RAGE) + { + return true; + } + + else + { + int i = 0; + trace_t first_tracer; + if (IsEntityVectorVisible(entity, entity->hitboxes.GetHitbox(cd.hitbox)->center, true, MASK_SHOT_HULL, &first_tracer)) + return true; + while (i <= 17) // Prevents returning empty at all costs. Loops through every hitbox + { + if (i == cd.hitbox) + i++; + trace_t test_trace; + std::vector centered_hitbox = getHitpointsVischeck(entity, i); + + if (IsEntityVectorVisible(entity, centered_hitbox[0], true, MASK_SHOT_HULL, &test_trace)) + { + cd.hitbox = i; + return true; + } + i++; + } + return false; // It looped through every hitbox and found nothing. It isn't visible. + } + } return true; break; } @@ -960,7 +1062,34 @@ bool IsTargetStateGood(CachedEntity *entity) return false; } +float projectileHitboxSize(int projectile_size) +{ + float projectile_hitbox_size = 6.3f; + switch (projectile_size) + { + case CL_CLASS(CTFRocketLauncher): + case CL_CLASS(CTFRocketLauncher_Mortar): + case CL_CLASS(CTFRocketLauncher_AirStrike): + case CL_CLASS(CTFRocketLauncher_DirectHit): + case CL_CLASS(CTFPipebombLauncher): + case CL_CLASS(CTFGrenadeLauncher): + case CL_CLASS(CTFCannon): + break; + case CL_CLASS(CTFFlareGun): + case CL_CLASS(CTFFlareGun_Revenge): + case CL_CLASS(CTFDRGPomson): + projectile_hitbox_size = 3; + break; + case CL_CLASS(CTFSyringeGun): + case CL_CLASS(CTFCompoundBow): + projectile_hitbox_size = 1; + break; + default: + break; + } + return projectile_hitbox_size; +} // A function to aim at a specific entitiy bool Aim(CachedEntity *entity) { @@ -969,22 +1098,24 @@ bool Aim(CachedEntity *entity) // Get angles from eye to target Vector is_it_good = PredictEntity(entity); - bool should_aim; - if (extrapolate || projectileAimbotRequired || entity->m_Type() != ENTITY_PLAYER) + if (!projectileAimbotRequired) { - should_aim = IsEntityVectorVisible(entity, is_it_good, true); + if (!IsEntityVectorVisible(entity, is_it_good, false)) + return false; } - else + + 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 { - should_aim = IsEntityVectorVisible(entity, is_it_good, false); + + if (!didProjectileHit(getShootPos(angles), is_it_good, entity, projectileHitboxSize(LOCAL_W->m_iClassID()))) + return false; } - if (!should_aim) - return false; AimbotCalculatedData_s &cd = calculated_data_array[entity->m_IDX]; if (fov > 0 && cd.fov > fov) return false; - Vector angles = GetAimAtAngles(g_pLocalPlayer->v_Eye, is_it_good, LOCAL_E); // Slow aim if (slow_aim) DoSlowAim(angles); @@ -1156,16 +1287,13 @@ Vector PredictEntity(CachedEntity *entity) // Buildings case ENTITY_BUILDING: { - if (projectileAimbotRequired) + if (cur_proj_grav != 0) { - std::pair tmp_result; - tmp_result = BuildingPrediction(entity, GetBuildingPosition(entity), cur_proj_speed, cur_proj_grav, cur_proj_start_vel); - result = tmp_result.second; // Buildings don't have velocity but I'll keep it in nonetheless + std::pair temp_result = BuildingPrediction(entity, GetBuildingPosition(entity), cur_proj_speed, cur_proj_grav, cur_proj_start_vel); + result = temp_result.second; } else - { result = GetBuildingPosition(entity); - } break; } // NPCs (Skeletons, merasmus, etc) @@ -1308,6 +1436,7 @@ int BestHitbox(CachedEntity *target) // Hitbox machine :b:roke return -1; } + // Function to find the closesnt hitbox to the crosshair for a given ent int ClosestHitbox(CachedEntity *target) { diff --git a/src/helpers.cpp b/src/helpers.cpp index d952e929..140a4708 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -651,6 +651,18 @@ powerup_type GetPowerupOnPlayer(CachedEntity *player) return powerup_type::supernova; return powerup_type::not_powerup; } +bool didProjectileHit(Vector start_point, Vector end_point, CachedEntity *entity, int projectile_size) +{ + + trace::filter_default.SetSelf(RAW_ENT(g_pLocalPlayer->entity)); + Ray_t ray; + trace_t trace_obj; + trace_t *tracer = &trace_obj; + ray.Init(start_point, end_point, Vector(0, -projectile_size, -projectile_size), Vector(0, projectile_size, projectile_size)); + g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_default, tracer); + return (((IClientEntity *) tracer->m_pEnt) == RAW_ENT(entity) || !tracer->DidHit()); +} + // A function to find a weapon by WeaponID int getWeaponByID(CachedEntity *player, int weaponid) { @@ -1017,7 +1029,7 @@ std::mutex trace_lock; bool IsEntityVectorVisible(CachedEntity *entity, Vector endpos, bool use_weapon_offset, unsigned int mask, trace_t *trace) { trace_t trace_object; - + if (!trace) trace = &trace_object; Ray_t ray; @@ -1035,6 +1047,7 @@ bool IsEntityVectorVisible(CachedEntity *entity, Vector endpos, bool use_weapon_ if (!tcm || g_Settings.is_create_move) g_ITrace->TraceRay(ray, mask, &trace::filter_default, trace); } + return (((IClientEntity *) trace->m_pEnt) == RAW_ENT(entity) || !trace->DidHit()); } diff --git a/src/prediction.cpp b/src/prediction.cpp index a44762c1..974fac73 100644 --- a/src/prediction.cpp +++ b/src/prediction.cpp @@ -501,7 +501,6 @@ Vector EnginePrediction(CachedEntity *entity, float time, Vector *vecVelocity) return result; } - std::pair ProjectilePrediction_Engine(CachedEntity *ent, int hb, float speed, float gravity, float entgmod, float proj_startvelocity) { Vector origin = ent->m_vecOrigin(); @@ -514,24 +513,22 @@ std::pair ProjectilePrediction_Engine(CachedEntity *ent, int hb, if (!sv_gravity) sv_gravity = g_ICvar->FindVar("sv_gravity"); - if (speed == 0.0f || !sv_gravity) + if (speed == 0.0f || !sv_gravity) return { Vector(), Vector() }; - + float currenttime = g_pLocalPlayer->v_Eye.DistTo(hitbox) / speed - 1.5f; - if (currenttime <= 0.0f) + if (currenttime <= 0.0f) currenttime = 0.01f; - + float besttime = currenttime; float mindelta = 65536.0f; + float no_regression = 66534.0f; Vector bestpos = origin; Vector current = origin; Vector current_velocity = velocity; int maxsteps = (int) debug_pp_steps; float steplength = g_GlobalVars->interval_per_tick; - - Vector ent_mins = RAW_ENT(ent)->GetCollideable()->OBBMins(); - Vector ent_maxs = RAW_ENT(ent)->GetCollideable()->OBBMaxs(); - + bool has_run_before = false; for (int steps = 0; steps < maxsteps; steps++, currenttime += steplength) { ent->m_vecOrigin() = current; @@ -553,6 +550,10 @@ std::pair ProjectilePrediction_Engine(CachedEntity *ent, int hb, bestpos = current; mindelta = timedelta; } + else if (mindelta < no_regression) + { + break; + } } // logging::Info("besttime: %f, currenttime: %f, old currenttime: %f", besttime, currenttime, currenttime - steplength * maxsteps); const_cast(RAW_ENT(ent)->GetAbsOrigin()) = origin; @@ -568,32 +569,6 @@ std::pair ProjectilePrediction_Engine(CachedEntity *ent, int hb, result.y - origin.y, result.z - origin.z);*/ return { result, result_initialvel }; } -std::pair BuildingPrediction(CachedEntity *building, Vector vec, float speed, float gravity, float proj_startvelocity) -{ - if (!vec.z || CE_BAD(building)) - return { Vector(), Vector() }; - Vector result = vec; - - if (!sv_gravity) - sv_gravity = g_ICvar->FindVar("sv_gravity"); - - if (speed == 0.0f || !sv_gravity) - return { Vector(), Vector() }; - - trace::filter_no_player.SetSelf(RAW_ENT(building)); - - // Buildings do not move. We don't need to do any steps here - float time = g_pLocalPlayer->v_Eye.DistTo(result) / speed; - // Compensate for ping - time += g_IEngine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING) + cl_interp->GetFloat(); - - result.z += (sv_gravity->GetFloat() / 2.0f * time * time * gravity); - Vector result_initialvel = result; - result_initialvel.z -= proj_startvelocity * time; - // S = at^2/2 ; t = sqrt(2S/a)*/ - return { result, result_initialvel }; -} - std::pair ProjectilePrediction(CachedEntity *ent, int hb, float speed, float gravitymod, float entgmod, float proj_startvelocity) { Vector origin = ent->m_vecOrigin(); @@ -677,6 +652,32 @@ float DistanceToGround(CachedEntity *ent) return DistanceToGround(origin, mins, maxs); } +std::pair BuildingPrediction(CachedEntity *building, Vector vec, float speed, float gravity, float proj_startvelocity) +{ + if (!vec.z || CE_BAD(building)) + return { Vector(), Vector() }; + Vector result = vec; + + if (!sv_gravity) + sv_gravity = g_ICvar->FindVar("sv_gravity"); + + if (speed == 0.0f || !sv_gravity) + return { Vector(), Vector() }; + + trace::filter_no_player.SetSelf(RAW_ENT(building)); + + // Buildings do not move. We don't need to do any steps here + float time = g_pLocalPlayer->v_Eye.DistTo(result) / speed; + // Compensate for ping + time += g_IEngine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING) + cl_interp->GetFloat(); + + result.z += (sv_gravity->GetFloat() / 2.0f * time * time * gravity); + Vector result_initialvel = result; + result_initialvel.z -= proj_startvelocity * time; + // S = at^2/2 ; t = sqrt(2S/a)*/ + return { result, result_initialvel }; +} + float DistanceToGround(Vector origin, Vector mins, Vector maxs) { // First, ensure we're not slightly below the floor, up to 18 HU will snap up