diff --git a/include/helpers.hpp b/include/helpers.hpp index 68d474f9..a5b5e4bd 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -77,7 +77,9 @@ bool IsEntityVectorVisible(CachedEntity *entity, Vector endpos); bool VisCheckEntFromEnt(CachedEntity *startEnt, CachedEntity *endEnt); bool VisCheckEntFromEntVector(Vector startVector, CachedEntity *startEnt, CachedEntity *endEnt); -Vector VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, +Vector VischeckCorner(CachedEntity *player, CachedEntity *target, float maxdist, + bool checkWalkable); +std::pair VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, bool checkWalkable); float vectorMax(Vector i); Vector vectorAbs(Vector i); diff --git a/src/hacks/CatBot.cpp b/src/hacks/CatBot.cpp index 49039be1..ef201351 100644 --- a/src/hacks/CatBot.cpp +++ b/src/hacks/CatBot.cpp @@ -221,7 +221,7 @@ void smart_crouch() { bool foundtar = false; static bool crouch = false; - if (crouchcdr.test_and_set(1000)) + if (crouchcdr.test_and_set(2000)) { for (int i = 0; i < g_IEngine->GetMaxClients(); i++) { @@ -246,11 +246,8 @@ void smart_crouch() continue; if (!IsVectorVisible(ent->hitboxes.GetHitbox(0)->center, LOCAL_E->hitboxes.GetHitbox(j)->center) && !IsVectorVisible(ent->hitboxes.GetHitbox(0)->center, LOCAL_E->hitboxes.GetHitbox(j)->min) && !IsVectorVisible(ent->hitboxes.GetHitbox(0)->center, LOCAL_E->hitboxes.GetHitbox(j)->max)) continue; - else - { - foundtar = true; - crouch = true; - } + foundtar = true; + crouch = true; } } if (!foundtar && crouch) diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index ea0b2915..b9c2b550 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -35,8 +35,7 @@ CatCommand follow_steam("fb_steam", "Follow Steam Id", steamid = 0x0; return; } - unsigned tempid = atol(args.Arg(1)); - steamid = *(unsigned int *) &tempid; + steamid = atol(args.Arg(1)); }); static CatVar mimic_slot(CV_SWITCH, "fb_mimic_slot", "0", "Mimic weapon slot", @@ -55,7 +54,7 @@ static CatVar afktime( CV_INT, "fb_afk_time", "15000", "Max AFK Time", "Max time in ms spent standing still before player gets declared afk"); static CatVar corneractivate( - CV_SWITCH, "fb_activation_corners", "1", "Activate arround corners", + CV_SWITCH, "fb_activation_corners", "1", "Activate around corners", "Try to find an activation path to an entity behind a corner."); // Something to store breadcrumbs created by followed players @@ -144,6 +143,8 @@ int ClassPriority(CachedEntity *ent) return 0; } } +Timer waittime{}; +int lastent = 0; void WorldTick() { if (!followbot) @@ -199,12 +200,22 @@ void WorldTick() if (corneractivate) { Vector indirectOrigin = - VischeckWall(LOCAL_E, entity, 250, + VischeckCorner(LOCAL_E, entity, float(follow_activation) / 2, true); // get the corner location that the // future target is visible from - if (!indirectOrigin.z) // if we couldn't find it, exit - continue; - addCrumbs(entity, indirectOrigin); + std::pair corners; + if (!indirectOrigin.z && entity->m_IDX == lastent) // if we couldn't find it, run wallcheck instead + { + corners = VischeckWall(LOCAL_E, entity, float(follow_activation) / 2, true); + if (!corners.first.z || !corners.second.z) + continue; + addCrumbs(LOCAL_E, corners.first); + addCrumbs(entity, corners.second); + } + if (indirectOrigin.z) + addCrumbs(entity, indirectOrigin); + else if (!indirectOrigin.z && !corners.first.z) + continue; } else { @@ -266,9 +277,7 @@ void WorldTick() if (follow_target && ENTITY(follow_target)->m_flDistance() < entity->m_flDistance()) // favor closer entitys - { continue; - } // check if new target has a higher priority than current target if (ClassPriority(ENTITY(follow_target)) >= ClassPriority(ENTITY(i))) @@ -277,12 +286,24 @@ void WorldTick() if (corneractivate) { Vector indirectOrigin = - VischeckWall(LOCAL_E, entity, 250, + VischeckCorner(LOCAL_E, entity, 250, true); // get the corner location that the // future target is visible from - if (!indirectOrigin.z) // if we couldn't find it, exit - continue; - addCrumbs(entity, indirectOrigin); + std::pair corners; + corners.first.z = 0; + corners.second.z = 0; + if (!indirectOrigin.z && entity->m_IDX == lastent) // if we couldn't find it, run wallcheck instead + { + corners = VischeckWall(LOCAL_E, entity, 250, true); + if (!corners.first.z || !corners.second.z) + continue; + addCrumbs(LOCAL_E, corners.first); + addCrumbs(entity, corners.second); + } + if (indirectOrigin.z) + addCrumbs(entity, indirectOrigin); + else if (!indirectOrigin.z && !corners.first.z) + continue; } else { @@ -295,6 +316,9 @@ void WorldTick() afkTicks[i].update(); // set afk time to 0 } } + lastent++; + if (lastent > g_IEngine->GetMaxClients()) + lastent = 0; // last check for entity before we continue if (!follow_target) return; diff --git a/src/helpers.cpp b/src/helpers.cpp index 159da748..3e514429 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -108,7 +108,7 @@ void WalkTo(const Vector &vector) // Function to get the corner location that a vischeck to an entity is possible // from -Vector VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, +Vector VischeckCorner(CachedEntity *player, CachedEntity *target, float maxdist, bool checkWalkable) { int maxiterations = maxdist / 40; @@ -165,6 +165,93 @@ Vector VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, return { 0, 0, 0 }; } +// return Two Corners that connect perfectly to ent and local player +std::pair VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, + bool checkWalkable) +{ + int maxiterations = maxdist / 40; + Vector origin = player->m_vecOrigin(); + + // if we can see an entity, we don't need to run calculations + if (VisCheckEntFromEnt(player, target)) + { + std::pair orig(origin, target->m_vecOrigin()); + if (!checkWalkable) + return orig; + else if (canReachVector(origin, target->m_vecOrigin())) + return orig; + } + + for (int i = 0; i < 4; i++) // for loop for all 4 directions + { + // 40 * maxiterations = range in HU + for (int j = 0; j < maxiterations; j++) + { + Vector virtualOrigin = origin; + // what direction to go in + switch (i) + { + case 0: + virtualOrigin.x = virtualOrigin.x + 40 * (j + 1); + break; + case 1: + virtualOrigin.x = virtualOrigin.x - 40 * (j + 1); + break; + case 2: + virtualOrigin.y = virtualOrigin.y + 40 * (j + 1); + break; + case 3: + virtualOrigin.y = virtualOrigin.y - 40 * (j + 1); + break; + } + // check if player can see the players virtualOrigin + if (!IsVectorVisible(origin, virtualOrigin, true)) + continue; + for (int i = 0; i < 4; i++) // for loop for all 4 directions + { + // 40 * maxiterations = range in HU + for (int j = 0; j < maxiterations; j++) + { + Vector virtualOrigin2 = target->m_vecOrigin(); + // what direction to go in + switch (i) + { + case 0: + virtualOrigin2.x = virtualOrigin2.x + 40 * (j + 1); + break; + case 1: + virtualOrigin2.x = virtualOrigin2.x - 40 * (j + 1); + break; + case 2: + virtualOrigin2.y = virtualOrigin2.y + 40 * (j + 1); + break; + case 3: + virtualOrigin2.y = virtualOrigin2.y - 40 * (j + 1); + break; + } + // check if the virtualOrigin2 can see the target + if (!VisCheckEntFromEntVector(virtualOrigin2, player, target)) + continue; + if (!IsVectorVisible(virtualOrigin, virtualOrigin2, true)) + continue; + if (!IsVectorVisible(virtualOrigin2, target->m_vecOrigin(), true)) + continue; + std::pair toret(virtualOrigin, virtualOrigin2); + if (!checkWalkable) + return toret; + // check if the location is accessible + if (!canReachVector(origin, virtualOrigin) || !canReachVector(virtualOrigin2, virtualOrigin)) + continue; + if (canReachVector(virtualOrigin2, target->m_vecOrigin())) + return toret; + } + } + } + } + // if we didn't find anything, return an empty Vector + return { {0, 0, 0}, {0, 0, 0} }; +} + // Returns a vectors max value. For example: {123,-150, 125} = 125 float vectorMax(Vector i) { @@ -616,8 +703,7 @@ bool IsEntityVectorVisible(CachedEntity *entity, Vector endpos) g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_default, &trace_object); } - return (trace_object.fraction >= 0.99f || - (((IClientEntity *) trace_object.m_pEnt)) == RAW_ENT(entity)); + return (((IClientEntity *) trace_object.m_pEnt) == RAW_ENT(entity) || trace_object.fraction >= 0.99f); } // For when you need to vis check something that isnt the local player