diff --git a/src/hacks/AutoBackstab.cpp b/src/hacks/AutoBackstab.cpp index e766b7ab..87e7796d 100644 --- a/src/hacks/AutoBackstab.cpp +++ b/src/hacks/AutoBackstab.cpp @@ -12,18 +12,38 @@ #include "hacks/Trigger.hpp" #include "hacks/AntiAntiAim.hpp" +namespace hacks::tf2::autobackstab +{ static settings::Bool enable{ "autobackstab.enable", "0" }; static settings::Bool silent{ "autobackstab.silent", "1" }; -namespace hacks::tf2::autobackstab +Vector rotateVector(Vector center, float radianAngle, Vector p) { + float s = sin(radianAngle); + float c = cos(radianAngle); + + // translate point back to origin: + p.x -= center.x; + p.y -= center.y; + + // rotate point + // float xnew = p.x * c - p.y * s; + // float ynew = p.x * s + p.y * c; + Vector vecNew{ p.x * c - p.y * s, p.x * s + p.y * c, 0 }; + + // translate point back: + p.x = vecNew.x + center.x; + p.y = vecNew.y + center.y; + return p; +} + // Function to find the closest hitbox to the v_Eye for a given ent int ClosestDistanceHitbox(CachedEntity *target) { int closest = -1; float closest_dist = 0.0f, dist = 0.0f; - for (int i = 0; i < target->hitboxes.GetNumHitboxes(); i++) + for (int i = spine_0; i < spine_3; i++) { dist = g_pLocalPlayer->v_Eye.DistTo(target->hitboxes.GetHitbox(i)->center); @@ -36,91 +56,46 @@ int ClosestDistanceHitbox(CachedEntity *target) return closest; } -// pPaste, thanks to F1ssi0N -const Vector GetWorldSpaceCenter(CachedEntity *ent) -{ - Vector vMin, vMax; - RAW_ENT(ent)->GetRenderBounds(vMin, vMax); - Vector vWorldSpaceCenter = RAW_ENT(ent)->GetAbsOrigin(); - vWorldSpaceCenter.z += (vMin.z + vMax.z) / 2; - return vWorldSpaceCenter; -} - -void traceEntity(int *result_eindex, Vector *result_pos, QAngle angle, - Vector loc, float meleeRange) -{ - Ray_t ray; - Vector forward; - float sp, sy, cp, cy; - trace_t trace; - - trace::filter_default.SetSelf(RAW_ENT(g_pLocalPlayer->entity)); - sy = sinf(DEG2RAD(angle[1])); - cy = cosf(DEG2RAD(angle[1])); - sp = sinf(DEG2RAD(angle[0])); - cp = cosf(DEG2RAD(angle[0])); - forward.x = cp * cy; - forward.y = cp * sy; - forward.z = -sp; - forward = forward * meleeRange + loc; - ray.Init(loc, forward); - g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_default, &trace); - if (result_pos) - *result_pos = trace.endpos; - if (result_eindex) - { - *result_eindex = 0; - } - if (trace.m_pEnt && result_eindex) - { - *result_eindex = ((IClientEntity *) (trace.m_pEnt))->entindex(); - } -} - -bool canBackstab(CachedEntity *tar, Vector angle, Vector loc, Vector hitboxLoc) +bool unifiedCanBackstab(Vector &vecAngle, Vector min, Vector max, + Vector hitboxLoc, CachedEntity *besttarget) { + // Get melee range float meleeRange = re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)); - Vector targetAngle = NET_VECTOR(RAW_ENT(tar), netvar.m_angEyeAngles); - if (fabsf(angle.y - targetAngle.y) < 45) - { - int IDX; - Vector hitLoc; - traceEntity(&IDX, &hitLoc, QAngle(angle.x, angle.y, angle.z), loc, meleeRange); - if (IDX == tar->m_IDX) - { - if (loc.DistTo(hitboxLoc) <= meleeRange) - return true; - } - } - return false; -} - -bool canBacktrackStab(hacks::shared::backtrack::BacktrackData &i, - Vector vecAngle, Vector loc, Vector hitboxLoc, float targetAngle) -{ - float meleeRange = re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)); - if (fabsf(vecAngle.y - targetAngle) >= 45) + if (fabsf(vecAngle.y - + NET_VECTOR(RAW_ENT(besttarget), netvar.m_angEyeAngles).y) >= 45) return false; - if (loc.DistTo(hitboxLoc) > meleeRange) - return false; - - auto min = i.spineMin; - auto max = i.spineMax; if (!min.x && !max.x) return false; + // Calculate head position + Vector currEye = g_pLocalPlayer->v_Eye; + float rotateRadians = atan2(currEye.x, currEye.y); + Vector center = (LOCAL_E->hitboxes.GetHitbox(upperArm_L)->center + + LOCAL_E->hitboxes.GetHitbox(upperArm_R)->center) / + 2; + center.z = currEye.z; + Vector head = rotateVector(center, rotateRadians, currEye); + + // Check if we are in range. Note: This has to be done in order to avoid + // false positives even when "forward" is only "meleeRange" away from the + // head. + if (head.DistTo(hitboxLoc) > meleeRange) + return false; + + // Calculate head x angle + Vector tr = (hitboxLoc - head); + Vector xAngle; + VectorAngles(tr, xAngle); + fClampAngle(xAngle); + vecAngle.x = xAngle.x; + // Get the min and max for the hitbox Vector minz(fminf(min.x, max.x), fminf(min.y, max.y), fminf(min.z, max.z)); Vector maxz(fmaxf(min.x, max.x), fmaxf(min.y, max.y), fmaxf(min.z, max.z)); -// if (!IsVectorVisible(g_pLocalPlayer->v_Eye, minz, true) && -// !IsVectorVisible(g_pLocalPlayer->v_Eye, maxz, true)) -// return false; - Vector forward; float sp, sy, cp, cy; QAngle angle = VectorToQAngle(vecAngle); - // Use math to get a vector in front of the player sy = sinf(DEG2RAD(angle[1])); cy = cosf(DEG2RAD(angle[1])); @@ -129,11 +104,11 @@ bool canBacktrackStab(hacks::shared::backtrack::BacktrackData &i, forward.x = cp * cy; forward.y = cp * sy; forward.z = -sp; - forward = forward * meleeRange + loc; + forward = forward * meleeRange + head; Vector hit; - if (hacks::shared::triggerbot::CheckLineBox( - minz, maxz, g_pLocalPlayer->v_Eye, forward, hit)) + // Check if we our line is within the targets hitbox + if (hacks::shared::triggerbot::CheckLineBox(minz, maxz, head, forward, hit)) return true; return false; } @@ -146,8 +121,9 @@ void CreateMove() return; if (g_pLocalPlayer->weapon()->m_iClassID() != CL_CLASS(CTFKnife)) return; + if (!CanShoot()) + return; CachedEntity *besttarget = nullptr; - for (int i = 0; i < g_IEngine->GetMaxClients(); i++) { CachedEntity *target = ENTITY(i); @@ -156,14 +132,14 @@ void CreateMove() 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_2)->center.DistTo( + if (target->hitboxes.GetHitbox(spine_3)->center.DistTo( g_pLocalPlayer->v_Eye) <= 300.0f) { if (CE_GOOD(besttarget)) { - if (target->hitboxes.GetHitbox(spine_2)->center.DistTo( + if (target->hitboxes.GetHitbox(spine_3)->center.DistTo( g_pLocalPlayer->v_Eye) < - besttarget->hitboxes.GetHitbox(spine_2)->center.DistTo( + besttarget->hitboxes.GetHitbox(spine_3)->center.DistTo( g_pLocalPlayer->v_Eye)) besttarget = target; } @@ -185,15 +161,16 @@ void CreateMove() besttarget->hitboxes .GetHitbox(ClosestDistanceHitbox(besttarget)) ->center; - // Get angles - Vector tr = (hitboxLoc - g_pLocalPlayer->v_Eye); - Vector xAngle; - VectorAngles(tr, xAngle); - // Clamping is important - fClampAngle(xAngle); - angle.x = xAngle.x; - if (!canBackstab(besttarget, angle, g_pLocalPlayer->v_Eye, - hitboxLoc)) + + if (!unifiedCanBackstab( + angle, + besttarget->hitboxes + .GetHitbox(ClosestDistanceHitbox(besttarget)) + ->min, + besttarget->hitboxes + .GetHitbox(ClosestDistanceHitbox(besttarget)) + ->max, + hitboxLoc, besttarget)) continue; current_user_cmd->viewangles = angle; current_user_cmd->buttons |= IN_ATTACK; @@ -207,15 +184,10 @@ void CreateMove() { int idx = besttarget->m_IDX; int tickcnt = 0; - int tickus = - (float(hacks::shared::backtrack::getLatency()) > 800.0f || - float(hacks::shared::backtrack::getLatency()) < 200.0f) - ? 12 - : 24; for (auto i : hacks::shared::backtrack::headPositions[idx]) { bool good_tick = false; - for (int j = 0; j < tickus; ++j) + 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 != @@ -225,18 +197,37 @@ void CreateMove() if (!good_tick) continue; - // Get angles - Vector tr = (i.spine - g_pLocalPlayer->v_Eye); - Vector xAngle; - VectorAngles(tr, xAngle); - // Clamping is important - fClampAngle(xAngle); - angle.x = xAngle.x; - - for (angle.y = -180.0f; angle.y < 180.0f; angle.y += 40.0f) + // Check if we are inside the target (which will in most cases + // result in a failstab) + std::pair collidableMinMax( + RAW_ENT(LOCAL_E)->GetCollideable()->OBBMins() + + g_pLocalPlayer->v_Origin, + RAW_ENT(LOCAL_E)->GetCollideable()->OBBMaxs() + + g_pLocalPlayer->v_Origin); + // Get dist Z to Z + float halfHeight = + (i.spineMin.DistTo( + Vector{ i.spineMin.x, i.spineMin.y, i.spineMax.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 }); + // 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 }); + if (LineIntersectsBox(collidableMinMax.first, + collidableMinMax.second, line1.first, + line1.second) || + LineIntersectsBox(collidableMinMax.first, + collidableMinMax.second, line2.first, + line2.second)) + continue; + for (angle.y = -180.0f; angle.y < 180.0f; angle.y += 20.0f) { - if (canBacktrackStab(i, angle, g_pLocalPlayer->v_Eye, - i.spine, NET_VECTOR(RAW_ENT(besttarget), netvar.m_angEyeAngles).y)) + if (unifiedCanBackstab(angle, i.spineMin, i.spineMax, + i.spine, besttarget)) { current_user_cmd->tick_count = i.tickcount; current_user_cmd->viewangles = angle;