diff --git a/include/hacks/Backtrack.hpp b/include/hacks/Backtrack.hpp index c4cd5756..343a69ba 100644 --- a/include/hacks/Backtrack.hpp +++ b/include/hacks/Backtrack.hpp @@ -11,15 +11,17 @@ namespace hacks::shared::backtrack { +struct hitboxData +{ + Vector center{ 0.0f, 0.0f, 0.0f }; + Vector min{ 0.0f, 0.0f, 0.0f }; + Vector max{ 0.0f, 0.0f, 0.0f }; +}; + struct BacktrackData { int tickcount{ 0 }; - Vector hitboxpos{ 0.0f, 0.0f, 0.0f }; - Vector min{ 0.0f, 0.0f, 0.0f }; - Vector max{ 0.0f, 0.0f, 0.0f }; - Vector spine{ 0.0f, 0.0f, 0.0f }; - Vector spineMin{ 0.0f, 0.0f, 0.0f }; - Vector spineMax{ 0.0f, 0.0f, 0.0f }; + std::array hitboxes; float viewangles{ 0.0f }; float simtime{ 0.0f }; Vector entorigin{ 0.0f, 0.0f, 0.0f }; @@ -57,11 +59,9 @@ struct CIncomingSequence typedef boost::circular_buffer_space_optimized circular_buf; extern circular_buf sequences; extern BacktrackData headPositions[32][66]; -extern BestTickData sorted_ticks[66]; bool isBacktrackEnabled(); float getLatency(); int getTicks(); -// FIXME -int getTicks2(); +bool ValidTick(BacktrackData &i, CachedEntity *ent); } diff --git a/src/hacks/Aimbot.cpp b/src/hacks/Aimbot.cpp index 906ca28f..60d09e13 100644 --- a/src/hacks/Aimbot.cpp +++ b/src/hacks/Aimbot.cpp @@ -91,50 +91,40 @@ AimbotCalculatedData_s calculated_data_array[2048]{}; #define IsMelee GetWeaponMode() == weapon_melee bool BacktrackAimbot() { - if (!hacks::shared::backtrack::isBacktrackEnabled() || !backtrackAimbot) + if (!hacks::shared::backtrack::isBacktrackEnabled() || !*backtrackAimbot) return false; if (aimkey && !aimkey.isKeyDown()) - return false; + return true; if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer() || !CanShoot()) - return false; + return true; - if (zoomed_only && !g_pLocalPlayer->bZoomed && + if (*zoomed_only && !g_pLocalPlayer->bZoomed && !(current_user_cmd->buttons & IN_ATTACK)) - return false; + return true; int iBestTarget = hacks::shared::backtrack::iBestTarget; if (iBestTarget == -1) return true; int tickcnt = 0; - int tickus = (float(hacks::shared::backtrack::getLatency()) > 800.0f || float(hacks::shared::backtrack::getLatency()) < 200.0f) ? 12 : 24; + CachedEntity *tar = ENTITY(iBestTarget); + if (CE_BAD(tar)) + return false; for (auto i : hacks::shared::backtrack::headPositions[iBestTarget]) { - bool good_tick = false; - for (int j = 0; j < tickus; ++j) - if (tickcnt == hacks::shared::backtrack::sorted_ticks[j].tick && - hacks::shared::backtrack::sorted_ticks[j].tickcount != INT_MAX) - good_tick = true; - tickcnt++; - if (!i.hitboxpos.z) + if (hacks::shared::backtrack::ValidTick(i, tar)) + continue; + if (!i.hitboxes.at(head).center.z) continue; - if (!good_tick) - continue; - if (!IsVectorVisible(g_pLocalPlayer->v_Eye, i.hitboxpos, true)) + if (!IsVectorVisible(g_pLocalPlayer->v_Eye, i.hitboxes.at(head).center, true)) continue; float scr = abs(g_pLocalPlayer->v_OrigViewangles.y - i.viewangles); - - CachedEntity *tar = ENTITY(iBestTarget); - // ok just in case - if (CE_BAD(tar)) - continue; - // target_eid = tar->m_IDX; Vector &angles = NET_VECTOR(RAW_ENT(tar), netvar.m_angEyeAngles); float &simtime = CE_FLOAT(tar, netvar.m_flSimulationTime); angles.y = i.viewangles; simtime = i.simtime; current_user_cmd->tick_count = i.tickcount; - Vector tr = (i.hitboxpos - g_pLocalPlayer->v_Eye); + Vector tr = (i.hitboxes.at(head).center - g_pLocalPlayer->v_Eye); Vector angles2; VectorAngles(tr, angles2); // Clamping is important diff --git a/src/hacks/AutoBackstab.cpp b/src/hacks/AutoBackstab.cpp index 87e7796d..8d3213d0 100644 --- a/src/hacks/AutoBackstab.cpp +++ b/src/hacks/AutoBackstab.cpp @@ -14,6 +14,7 @@ namespace hacks::tf2::autobackstab { +namespace backtrack = hacks::shared::backtrack; static settings::Bool enable{ "autobackstab.enable", "0" }; static settings::Bool silent{ "autobackstab.silent", "1" }; @@ -38,15 +39,18 @@ Vector rotateVector(Vector center, float radianAngle, Vector p) } // Function to find the closest hitbox to the v_Eye for a given ent -int ClosestDistanceHitbox(CachedEntity *target) +int ClosestDistanceHitbox(CachedEntity *target, + backtrack::BacktrackData btd = {}) { int closest = -1; float closest_dist = 0.0f, dist = 0.0f; - for (int i = spine_0; i < spine_3; i++) { - dist = - g_pLocalPlayer->v_Eye.DistTo(target->hitboxes.GetHitbox(i)->center); + if (hacks::shared::backtrack::isBacktrackEnabled()) + dist = g_pLocalPlayer->v_Eye.DistTo(btd.hitboxes.at(i).center); + else + dist = g_pLocalPlayer->v_Eye.DistTo( + target->hitboxes.GetHitbox(i)->center); if (dist < closest_dist || closest == -1) { closest = i; @@ -62,7 +66,7 @@ bool unifiedCanBackstab(Vector &vecAngle, Vector min, Vector max, // Get melee range float meleeRange = re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)); if (fabsf(vecAngle.y - - NET_VECTOR(RAW_ENT(besttarget), netvar.m_angEyeAngles).y) >= 45) + NET_VECTOR(RAW_ENT(besttarget), netvar.m_angEyeAngles).y) >= 50) return false; if (!min.x && !max.x) return false; @@ -124,36 +128,58 @@ void CreateMove() if (!CanShoot()) return; CachedEntity *besttarget = nullptr; - for (int i = 0; i < g_IEngine->GetMaxClients(); i++) + if (!backtrack::isBacktrackEnabled()) { - CachedEntity *target = ENTITY(i); - if (CE_BAD(target)) - continue; - if (target == LOCAL_E || target->m_iTeam() == LOCAL_E->m_iTeam() || - !target->m_bAlivePlayer() || target->m_Type() != ENTITY_PLAYER) - continue; - if (target->hitboxes.GetHitbox(spine_3)->center.DistTo( - g_pLocalPlayer->v_Eye) <= 300.0f) + for (int i = 0; i < g_IEngine->GetMaxClients(); i++) { - if (CE_GOOD(besttarget)) + CachedEntity *target = ENTITY(i); + if (CE_BAD(target)) + continue; + if (target == LOCAL_E || target->m_iTeam() == LOCAL_E->m_iTeam() || + !target->m_bAlivePlayer() || target->m_Type() != ENTITY_PLAYER) + continue; + if (target->hitboxes.GetHitbox(spine_3)->center.DistTo( + g_pLocalPlayer->v_Eye) <= 200.0f) { - if (target->hitboxes.GetHitbox(spine_3)->center.DistTo( - g_pLocalPlayer->v_Eye) < - besttarget->hitboxes.GetHitbox(spine_3)->center.DistTo( - g_pLocalPlayer->v_Eye)) + if (CE_GOOD(besttarget)) + { + if (target->hitboxes.GetHitbox(spine_3)->center.DistTo( + g_pLocalPlayer->v_Eye) < + besttarget->hitboxes.GetHitbox(spine_3)->center.DistTo( + g_pLocalPlayer->v_Eye)) + besttarget = target; + } + else + { besttarget = target; - } - else - { - besttarget = target; + } } } } + else + { + // Run if backtrack is enabled + if (backtrack::iBestTarget == -1) + return; + CachedEntity *target = ENTITY(backtrack::iBestTarget); + // Various valid entity checks + if (CE_BAD(target)) + return; + if (target == LOCAL_E || target->m_iTeam() == LOCAL_E->m_iTeam() || + !target->m_bAlivePlayer() || target->m_Type() != ENTITY_PLAYER) + return; + // Check if besttick distance is < 200.0f + if (backtrack::headPositions[target->m_IDX][backtrack::BestTick] + .hitboxes.at(spine_3) + .center.DistTo(g_pLocalPlayer->v_Eye) < 200.0f) + besttarget = target; + } + if (CE_GOOD(besttarget)) { hacks::shared::anti_anti_aim::resolveEnt(besttarget->m_IDX); Vector angle = NET_VECTOR(RAW_ENT(LOCAL_E), netvar.m_angEyeAngles); - if (!hacks::shared::backtrack::isBacktrackEnabled()) + if (!backtrack::isBacktrackEnabled()) { for (angle.y = -180.0f; angle.y < 180.0f; angle.y += 10.0f) { @@ -182,20 +208,13 @@ void CreateMove() } else { - int idx = besttarget->m_IDX; - int tickcnt = 0; - for (auto i : hacks::shared::backtrack::headPositions[idx]) + int idx = besttarget->m_IDX; + for (auto i : backtrack::headPositions[idx]) { - bool good_tick = false; - for (int j = 0; j < hacks::shared::backtrack::getTicks2(); ++j) - if (tickcnt == - hacks::shared::backtrack::sorted_ticks[j].tick && - hacks::shared::backtrack::sorted_ticks[j].tickcount != - INT_MAX) - good_tick = true; - tickcnt++; - if (!good_tick) + if (!backtrack::ValidTick(i, besttarget)) continue; + backtrack::hitboxData &hitbox = + i.hitboxes.at(ClosestDistanceHitbox(besttarget, i)); // Check if we are inside the target (which will in most cases // result in a failstab) @@ -206,17 +225,18 @@ void CreateMove() g_pLocalPlayer->v_Origin); // Get dist Z to Z float halfHeight = - (i.spineMin.DistTo( - Vector{ i.spineMin.x, i.spineMin.y, i.spineMax.z })) / + (hitbox.min.DistTo( + Vector{ hitbox.min.x, hitbox.min.y, hitbox.max.z })) / 2; // Make our first diagonal line std::pair line1( - { i.spineMin.x, i.spineMin.y, i.spineMin.z + halfHeight }, - { i.spineMax.x, i.spineMax.y, i.spineMax.z - halfHeight }); + { hitbox.min.x, hitbox.min.y, hitbox.min.z + halfHeight }, + { hitbox.max.x, hitbox.max.y, hitbox.max.z - halfHeight }); // Make our second diagonal line std::pair line2( { line1.second.x, line1.first.y, line1.first.z }, { line1.first.x, line1.second.y, line1.first.z }); + // Check if one of the lines intersects with our collidable if (LineIntersectsBox(collidableMinMax.first, collidableMinMax.second, line1.first, line1.second) || @@ -224,10 +244,11 @@ void CreateMove() collidableMinMax.second, line2.first, line2.second)) continue; + for (angle.y = -180.0f; angle.y < 180.0f; angle.y += 20.0f) { - if (unifiedCanBackstab(angle, i.spineMin, i.spineMax, - i.spine, besttarget)) + if (unifiedCanBackstab(angle, hitbox.min, hitbox.max, + hitbox.center, besttarget)) { current_user_cmd->tick_count = i.tickcount; current_user_cmd->viewangles = angle; diff --git a/src/hacks/Backtrack.cpp b/src/hacks/Backtrack.cpp index 1ebb7d34..8d18fc7f 100644 --- a/src/hacks/Backtrack.cpp +++ b/src/hacks/Backtrack.cpp @@ -12,7 +12,6 @@ #include #include - static settings::Bool enable{ "backtrack.enable", "false" }; static settings::Bool draw_bt{ "backtrack.draw", "false" }; static settings::Int latency{ "backtrack.latency", "0" }; @@ -21,9 +20,9 @@ static settings::Int slots{ "backtrack.slots", "0" }; namespace hacks::shared::backtrack { - +void EmptyBacktrackData(BacktrackData &i); +std::pair getBestEntBestTick(); BacktrackData headPositions[32][66]{}; -BestTickData sorted_ticks[66]{}; int highesttick[32]{}; int lastincomingsequencenumber = 0; static bool shouldDrawBt; @@ -65,10 +64,7 @@ void Init() { for (int i = 0; i < 32; i++) for (int j = 0; j < 66; j++) - headPositions[i][j] = BacktrackData{ - 0, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, - { 0, 0, 0 }, { 0, 0, 0 }, 0, 0, { 0, 0, 0 } - }; + EmptyBacktrackData(headPositions[i][j]); } int BestTick = 0; @@ -90,12 +86,13 @@ void Run() CUserCmd *cmd = current_user_cmd; float bestFov = 99999; - BestTick = 0; - iBestTarget = -1; - bool IsMelee = GetWeaponMode() == weapon_melee; float prev_distance = 9999; + auto bestEntBestTick = getBestEntBestTick(); + BestTick = bestEntBestTick.second; + iBestTarget = bestEntBestTick.first; + for (int i = 1; i < g_IEngine->GetMaxClients(); i++) { CachedEntity *pEntity = ENTITY(i); @@ -103,10 +100,7 @@ void Run() if (CE_BAD(pEntity) || !pEntity->m_bAlivePlayer()) { for (BacktrackData &btd : headPositions[i]) - btd = BacktrackData{ 0, { 0, 0, 0 }, { 0, 0, 0 }, - { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, - { 0, 0, 0 }, 0, 0, - { 0, 0, 0 } }; + EmptyBacktrackData(btd); continue; } if (pEntity->m_iTeam() == LOCAL_E->m_iTeam()) @@ -115,97 +109,42 @@ void Run() continue; if (!pEntity->hitboxes.GetHitbox(0)) continue; - Vector hitboxpos = pEntity->hitboxes.GetHitbox(0)->center; - Vector min = pEntity->hitboxes.GetHitbox(0)->min; - Vector max = pEntity->hitboxes.GetHitbox(0)->max; - float _viewangles = - NET_VECTOR(RAW_ENT(pEntity), netvar.m_angEyeAngles).y; + float _viewangles = CE_VECTOR(pEntity, netvar.m_angEyeAngles).y; float viewangles = (_viewangles > 180) ? _viewangles - 360 : _viewangles; - float simtime = CE_FLOAT(pEntity, netvar.m_flSimulationTime); - Vector hitbox_spine = pEntity->hitboxes.GetHitbox(spine_3)->center; - Vector hitbox_min = pEntity->hitboxes.GetHitbox(spine_3)->min; - Vector hitbox_max = pEntity->hitboxes.GetHitbox(spine_3)->max; - Vector ent_orig = pEntity->InternalEntity()->GetAbsOrigin(); + float simtime = CE_FLOAT(pEntity, netvar.m_flSimulationTime); + std::array hbdArray; + for (size_t i = 0; i < hbdArray.max_size(); i++) + { + hbdArray.at(i).center = pEntity->hitboxes.GetHitbox(i)->center; + hbdArray.at(i).min = pEntity->hitboxes.GetHitbox(i)->min; + hbdArray.at(i).max = pEntity->hitboxes.GetHitbox(i)->max; + } + Vector ent_orig = pEntity->InternalEntity()->GetAbsOrigin(); auto hdr = g_IModelInfo->GetStudiomodel(RAW_ENT(pEntity)->GetModel()); headPositions[i][cmd->command_number % getTicks()] = - BacktrackData{ cmd->tick_count, hitboxpos, min, max, - hitbox_spine, hitbox_min, hitbox_max, viewangles, - simtime, ent_orig }; - float FOVDistance = GetFov(g_pLocalPlayer->v_OrigViewangles, - g_pLocalPlayer->v_Eye, hitboxpos); - float distance = g_pLocalPlayer->v_Eye.DistTo(hitbox_spine); - if (!IsMelee && bestFov > FOVDistance && FOVDistance < 60.0f) - { - bestFov = FOVDistance; - iBestTarget = i; - } - if (IsMelee && distance < prev_distance) - { - prev_distance = distance; - iBestTarget = i; - } + BacktrackData{ cmd->tick_count, hbdArray, viewangles, simtime, + ent_orig }; } if (iBestTarget != -1 && CanShoot()) { - int bestTick = 0; - float tempFOV = 9999; - float bestFOV = 180.0f; - float distance, prev_distance_ticks = 9999; - - for (int i = 0; i < getTicks(); ++i) - sorted_ticks[i] = BestTickData{ INT_MAX, i }; - for (int t = 0; t < getTicks(); ++t) + CachedEntity *tar = ENTITY(iBestTarget); + if (CE_GOOD(tar)) { - if (headPositions[iBestTarget][t].tickcount) - sorted_ticks[t] = - BestTickData{ headPositions[iBestTarget][t].tickcount, t }; - } - std::sort(sorted_ticks, sorted_ticks + getTicks()); - int tickus = getTicks2(); - for (int t = 0; t < getTicks(); ++t) - { - bool good_tick = false; - - for (int i = 0; i < tickus; ++i) - if (t == sorted_ticks[i].tick && - sorted_ticks[i].tickcount != INT_MAX && - sorted_ticks[i].tickcount) - good_tick = true; - if (!good_tick) - continue; - tempFOV = - GetFov(g_pLocalPlayer->v_OrigViewangles, g_pLocalPlayer->v_Eye, - headPositions[iBestTarget][t].hitboxpos); - if (IsMelee) + if (cmd->buttons & IN_ATTACK) { - distance = g_pLocalPlayer->v_Eye.DistTo( - headPositions[iBestTarget][t].spine); - if (distance < (float) mindistance) - continue; - if (distance < prev_distance_ticks && tempFOV < 90.0f) - prev_distance_ticks = distance, bestTick = t; + // ok just in case + if (CE_BAD(tar)) + return; + auto i = headPositions[iBestTarget][BestTick]; + cmd->tick_count = i.tickcount; + Vector &angles = + NET_VECTOR(RAW_ENT(tar), netvar.m_angEyeAngles); + float &simtime = + NET_FLOAT(RAW_ENT(tar), netvar.m_flSimulationTime); + angles.y = i.viewangles; + simtime = i.simtime; } - else - { - if (bestFOV > tempFOV) - bestTick = t, bestFOV = tempFOV; - } - } - - BestTick = bestTick; - if (cmd->buttons & IN_ATTACK) - { - CachedEntity *tar = ENTITY(iBestTarget); - // ok just in case - if (CE_BAD(tar)) - return; - auto i = headPositions[iBestTarget][bestTick]; - cmd->tick_count = i.tickcount; - Vector &angles = NET_VECTOR(RAW_ENT(tar), netvar.m_angEyeAngles); - float &simtime = NET_FLOAT(RAW_ENT(tar), netvar.m_flSimulationTime); - angles.y = i.viewangles; - simtime = i.simtime; } } } @@ -218,22 +157,18 @@ void Draw() return; if (!shouldDrawBt) return; - int tickus = getTicks2(); for (int i = 0; i < g_IEngine->GetMaxClients(); i++) { + CachedEntity *ent = ENTITY(i); + if (CE_BAD(ent)) + continue; for (int j = 0; j < getTicks(); j++) { - bool good_tick = false; - - for (int i = 0; i < tickus; ++i) - if (j == sorted_ticks[i].tick) - good_tick = true; - if (!good_tick) + if (!ValidTick(headPositions[i][j], ent)) continue; - auto hbpos = headPositions[i][j].hitboxpos; - auto tickount = headPositions[i][j].tickcount; - auto min = headPositions[i][j].min; - auto max = headPositions[i][j].max; + auto hbpos = headPositions[i][j].hitboxes.at(head).center; + auto min = headPositions[i][j].hitboxes.at(head).min; + auto max = headPositions[i][j].hitboxes.at(head).max; if (!hbpos.x && !hbpos.y && !hbpos.z) continue; Vector out; @@ -306,13 +241,87 @@ float getLatency() int getTicks() { - return max(min(int(*latency / 200.0f * 13.0f), 65), 12); + return max(min(int(*latency / 200.0f * 13.0f) + 12, 65), 12); } -int getTicks2() +bool ValidTick(BacktrackData &i, CachedEntity *ent) { - // Removed for now - //return (*latency > 800 || *latency < 200) ? 12 : 24; - return 12; + return fabsf(NET_FLOAT(RAW_ENT(ent), netvar.m_flSimulationTime) * 1000.0f - + getLatency() - i.simtime * 1000.0f) < 200.0f; } + +void EmptyBacktrackData(BacktrackData &i) +{ + i = {}; } + +// This func is internal only +std::pair getBestEntBestTick() +{ + int bestEnt = -1; + int bestTick = -1; + if (GetWeaponMode() == weapon_melee) + { + float bestDist = 9999.0f; + for (int i = 0; i < g_IEngine->GetMaxClients(); i++) + { + CachedEntity *tar = ENTITY(i); + if (CE_GOOD(tar)) + { + if (tar != LOCAL_E && tar->m_bEnemy()) + { + + for (int j = 0; j < getTicks(); j++) + { + if (ValidTick(headPositions[i][j], ENTITY(i))) + { + float dist = + headPositions[i][j] + .hitboxes.at(spine_3) + .center.DistTo(g_pLocalPlayer->v_Eye); + if (dist < bestDist && dist > *mindistance) + { + bestEnt = i; + bestTick = j; + bestDist = dist; + } + } + } + } + } + } + } + else + { + float bestFov = 0.0f; + for (int i = 0; i < g_IEngine->GetMaxClients(); i++) + { + CachedEntity *tar = ENTITY(i); + if (CE_GOOD(tar)) + { + if (tar != LOCAL_E && tar->m_bEnemy()) + { + for (int j = 0; j < getTicks(); j++) + { + if (ValidTick(headPositions[i][j], tar)) + { + float FOVDistance = GetFov( + g_pLocalPlayer->v_OrigViewangles, + g_pLocalPlayer->v_Eye, + headPositions[i][j].hitboxes.at(head).center); + if (bestFov > FOVDistance) + { + bestFov = FOVDistance; + bestEnt = i; + bestTick = j; + } + } + } + } + } + } + } + return std::make_pair(bestEnt, bestTick); +} + +} // namespace hacks::shared::backtrack diff --git a/src/hacks/Trigger.cpp b/src/hacks/Trigger.cpp index eb0a5052..4988eb25 100644 --- a/src/hacks/Trigger.cpp +++ b/src/hacks/Trigger.cpp @@ -41,21 +41,15 @@ int last_hb_traced = 0; Vector forward; bool CanBacktrack() { - int target = hacks::shared::backtrack::iBestTarget; - int tickcnt = 0; - int tickus = hacks::shared::backtrack::getTicks2(); - for (auto i : hacks::shared::backtrack::headPositions[target]) + CachedEntity *tar = ENTITY(hacks::shared::backtrack::iBestTarget); + if (CE_BAD(tar)) + return false; + for (auto i : hacks::shared::backtrack::headPositions[tar->m_IDX]) { - bool good_tick = false; - for (int j = 0; j < tickus; ++j) - if (tickcnt == hacks::shared::backtrack::sorted_ticks[j].tick && - hacks::shared::backtrack::sorted_ticks[j].tickcount != INT_MAX) - good_tick = true; - tickcnt++; - if (!good_tick) + if(!hacks::shared::backtrack::ValidTick(i, tar)) continue; - auto min = i.min; - auto max = i.max; + auto min = i.hitboxes.at(head).min; + auto max = i.hitboxes.at(head).max; if (!min.x && !max.x) continue; @@ -83,10 +77,6 @@ bool CanBacktrack() continue; if (CheckLineBox(minz, maxz, g_pLocalPlayer->v_Eye, forward, hit)) { - CachedEntity *tar = ENTITY(target); - // ok just in case - if (CE_BAD(tar)) - continue; Vector &angles = NET_VECTOR(RAW_ENT(tar), netvar.m_angEyeAngles); float &simtime = NET_FLOAT(RAW_ENT(tar), netvar.m_flSimulationTime); angles.y = i.viewangles;