diff --git a/include/helpers.hpp b/include/helpers.hpp index 3a1aba5a..82aa9d55 100755 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -77,7 +77,12 @@ 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 VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, + bool checkWalkable); +float vectorMax(Vector i); +Vector vectorAbs(Vector i); +bool canReachVector(Vector loc, Vector dest = {0,0,0}); +bool isJumping(Vector vec); bool LineIntersectsBox(Vector &bmin, Vector &bmax, Vector &lmin, Vector &lmax); diff --git a/src/hack.cpp b/src/hack.cpp index 1d203214..07e04634 100644 --- a/src/hack.cpp +++ b/src/hack.cpp @@ -491,10 +491,6 @@ free(logname);*/ #if ENABLE_VISUALS InitStrings(); -#if ENABLE_GUI - // cat_reloadscheme to load imgui - hack::command_stack().push("cat_reloadscheme"); -#endif #ifndef FEATURE_EFFECTS_DISABLED if (g_ppScreenSpaceRegistrationHead && g_pScreenSpaceEffects) { diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index f28e75f6..66424cf2 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -82,13 +82,6 @@ void checkAFK() } } -float vectormax(Vector i) // TODO: Move to helpers.cpp soon tm -{ -float res = fmaxf(i.x, i.y); -return fmaxf(res, i.z); -} - - void init() { for (int i = 0; i < afkTicks.size(); i++) @@ -99,55 +92,27 @@ void init() return; } - -bool canReachVector(Vector loc) -{ - trace_t trace; - Ray_t ray; - Vector down = loc; - down.z = down.z - 5; - ray.Init(loc, down); - g_ITrace->TraceRay(ray, MASK_PLAYERSOLID, &trace::filter_no_player, - &trace); - if (trace.startpos.z - trace.endpos.z <= 75) // higher as to avoid small false positives, player can jump 72 hu - return true; - return false; -} - // auto add checked crumbs for the walbot to follow bool addCrumbs(CachedEntity *target, Vector corner = g_pLocalPlayer->v_Origin) { + breadcrumbs.clear(); if (g_pLocalPlayer->v_Origin != corner) { Vector dist = corner - g_pLocalPlayer->v_Origin; - Vector distabs = dist; - distabs.x = fabsf(distabs.x); - distabs.y = fabsf(distabs.y); - distabs.z = fabsf(distabs.z); int maxiterations = floor(corner.DistTo(g_pLocalPlayer->v_Origin)) / 40; for (int i = 0; i < maxiterations; i++) { - Vector result = g_pLocalPlayer->v_Origin + dist / vectormax(distabs) * 40.0f * (i + 1); - if (!canReachVector(result)) - return false; - breadcrumbs.push_back(result); + breadcrumbs.push_back(g_pLocalPlayer->v_Origin + dist / vectorMax(vectorAbs(dist)) * 40.0f * (i + 1)); } } Vector dist = target->m_vecOrigin() - corner; - Vector distabs = dist; - distabs.x = fabsf(distabs.x); - distabs.y = fabsf(distabs.y); - distabs.z = fabsf(distabs.z); int maxiterations = floor(corner.DistTo(target->m_vecOrigin())) / 40; for (int i = 0; i < maxiterations; i++) { - Vector result = corner + dist / vectormax(distabs) * 40.0f * (i + 1); - if (!canReachVector(result)) - return false; - breadcrumbs.push_back(result); + breadcrumbs.push_back(corner + dist / vectorMax(vectorAbs(dist)) * 40.0f * (i + 1)); } - return false; + return true; } int ClassPriority(CachedEntity* ent) { @@ -218,6 +183,8 @@ void WorldTick() auto entity = ENTITY(i); if (CE_BAD(entity)) // Exist + dormant continue; + if (i == follow_target) + break; if (entity->m_Type() != ENTITY_PLAYER) continue; if (steamid != entity->player_info.friendsID) // steamid check @@ -227,7 +194,7 @@ void WorldTick() continue; if (corneractivate) { - Vector indirectOrigin = VischeckWall(LOCAL_E, entity, 250); //get the corner location that the future target is visible from + Vector indirectOrigin = VischeckWall(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; breadcrumbs.clear(); //we need to ensure that the breadcrumbs std::vector is empty @@ -287,18 +254,18 @@ void WorldTick() continue; if (corneractivate) { - Vector indirectOrigin = VischeckWall(LOCAL_E, entity, 250); //get the corner location that the future target is visible from + Vector indirectOrigin = VischeckWall(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; - //breadcrumbs.clear(); //we need to ensure that the breadcrumbs std::vector is empty - //breadcrumbs.push_back(indirectOrigin); //add the corner location to the breadcrumb list - addCrumbs(entity, indirectOrigin); + if (!addCrumbs(entity, indirectOrigin)) + continue; } else { if (!VisCheckEntFromEnt(LOCAL_E, entity)) continue; } + // favor closer entitys if (follow_target && ENTITY(follow_target)->m_flDistance() > entity->m_flDistance()) // favor closer entitys @@ -318,8 +285,11 @@ void WorldTick() CachedEntity *followtar = ENTITY(follow_target); // wtf is this needed - if (CE_BAD(followtar)) + if (CE_BAD(followtar) || !followtar->m_bAlivePlayer()) + { + follow_target = 0; return; + } // Check if we are following a disguised/spy if (IsPlayerDisguised(followtar) || IsPlayerInvisible(followtar)) { @@ -386,9 +356,10 @@ void WorldTick() // Follow the crumbs when too far away, or just starting to follow if (dist_to_target > (float) follow_distance) { - // Check for idle - if (autojump && idle_time.check(2000)) + // Check for jump + if (autojump && (idle_time.check(2000) || isJumping(breadcrumbs[0]))) g_pUserCmd->buttons |= IN_JUMP; + // Check for idle if (idle_time.test_and_set(5000)) { follow_target = 0; diff --git a/src/helpers.cpp b/src/helpers.cpp index 0392dae2..d7153cec 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -108,21 +108,29 @@ 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 VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, + bool checkWalkable) { int maxiterations = maxdist / 40; Vector origin = player->m_vecOrigin(); - if (VisCheckEntFromEnt(player, target)) // if we can see an entity, we don't - // need to run calculations - return origin; + // if we can see an entity, we don't need to run calculations + if (VisCheckEntFromEnt(player, target)) + { + if (!checkWalkable) + return origin; + else if (canReachVector(origin, target->m_vecOrigin())) + return origin; + } + for (int i = 0; i < 4; i++) // for loop for all 4 directions { - for (int j = 0; j < maxiterations; - j++) // 40 * maxiterations = range in HU + // 40 * maxiterations = range in HU + for (int j = 0; j < maxiterations; j++) { Vector virtualOrigin = origin; - switch (i) // what direction to go in + // what direction to go in + switch (i) { case 0: virtualOrigin.x = virtualOrigin.x + 40 * (j + 1); @@ -137,21 +145,161 @@ Vector VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist) virtualOrigin.y = virtualOrigin.y - 40 * (j + 1); break; } - if (!IsVectorVisible(origin, - virtualOrigin)) // check if player can see the - // players virtualOrigin + // check if player can see the players virtualOrigin + if (!IsVectorVisible(origin, virtualOrigin)) continue; - if (VisCheckEntFromEntVector( - virtualOrigin, player, - target)) // check if the virtualOrigin can see the target - if (abs(player->m_vecOrigin().z - virtualOrigin.z) < 400) // check for accidental height tracers - return virtualOrigin; // return the corner position that we know - // can see the target + // check if the virtualOrigin can see the target + if (!VisCheckEntFromEntVector(virtualOrigin, player, target)) + continue; + if (!checkWalkable) + return virtualOrigin; + + // check if the location is accessible + if (!canReachVector(origin, virtualOrigin)) + continue; + if (canReachVector(virtualOrigin, target->m_vecOrigin())) + return virtualOrigin; } } + // if we didn't find anything, return an empty Vector return { 0, 0, 0 }; } +// Returns a vectors max value. For example: {123,-150, 125} = 125 +float vectorMax(Vector i) +{ + return fmaxf(fmaxf(i.x, i.y), i.z); +} + +// Returns a vectors absolute value. For example {123,-150, 125} = {123,150, +// 125} +Vector vectorAbs(Vector i) +{ + Vector result = i; + result.x = fabsf(result.x); + result.y = fabsf(result.y); + result.z = fabsf(result.z); + return result; +} + +// check to see if we can reach a vector or if it is too high / doesn't leave +// enough space for the player, optional second vector +bool canReachVector(Vector loc, Vector dest) +{ + if (!dest.IsZero()) + { + Vector dist = dest - loc; + int maxiterations = floor(dest.DistTo(loc)) / 40; + for (int i = 0; i < maxiterations; i++) + { + Vector vec = loc + dist / vectorMax(vectorAbs(dist)) * 40.0f * (i + 1); + + trace_t trace; + Ray_t ray; + Vector down = vec; + down.z = down.z - 50; + ray.Init(vec, down); + g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, + &trace); + if (!(trace.startpos.DistTo(trace.endpos) <= 45)) + return false; + + for (int j = 0; j < 4; j++) + { + Vector directionalLoc = vec; + // what direction to check + switch (j) + { + case 0: + directionalLoc.x = directionalLoc.x + 40; + break; + case 1: + directionalLoc.x = directionalLoc.x - 40; + break; + case 2: + directionalLoc.y = directionalLoc.y + 40; + break; + case 3: + directionalLoc.y = directionalLoc.y - 40; + break; + } + trace_t trace2; + Ray_t ray2; + ray2.Init(vec, directionalLoc); + g_ITrace->TraceRay(ray2, 0x4200400B, &trace::filter_no_player, + &trace2); + // distance of trace < than 26 + if (trace2.startpos.DistTo(trace2.endpos) < 26.0f) + return false; + } + } + } + else + { + // check if the vector is too high above ground + trace_t trace; + Ray_t ray; + Vector down = loc; + down.z = down.z - 50; + ray.Init(loc, down); + g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, &trace); + // higher to avoid small false positives, player can jump 42 hu according to + // the tf2 wiki + if (!(trace.startpos.DistTo(trace.endpos) <= 45)) + return false; + // check if there is enough space arround the vector for a player to fit + // for loop for all 4 directions + for (int i = 0; i < 4; i++) + { + Vector directionalLoc = loc; + // what direction to check + switch (i) + { + case 0: + directionalLoc.x = directionalLoc.x + 40; + break; + case 1: + directionalLoc.x = directionalLoc.x - 40; + break; + case 2: + directionalLoc.y = directionalLoc.y + 40; + break; + case 3: + directionalLoc.y = directionalLoc.y - 40; + break; + } + trace_t trace2; + Ray_t ray2; + ray2.Init(loc, directionalLoc); + g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, &trace2); + // distance of trace < than 26 + if (trace2.startpos.DistTo(trace2.endpos) < 26.0f) + return false; + } + } + return true; +} + +// returns if the player is currently jumping/falling. +bool isJumping(Vector vec) +{ + // check if the vector is too high above ground + trace_t trace; + Ray_t ray; + Vector down = vec; + Vector loc = vec; + down.z = down.z - 50; + loc.z = loc.z + 5; + ray.Init(vec, down); + // trace::filter_no_player.SetSelf(RAW_ENT(g_pLocalPlayer->entity)); + g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, &trace); + // lower to avoid small false negatives, player can jump 42 hu according to + // the tf2 wiki, higher because loc.z = loc.z + 5; + if (trace.startpos.DistTo(trace.endpos) > 45) + return true; + return false; +} + std::string GetLevelName() { @@ -1082,7 +1230,7 @@ void PrintChat(const char *fmt, ...) CHudBaseChat *chat = (CHudBaseChat *) g_CHUD->FindElement("CHudChat"); if (chat) { - std::unique_ptr buf(new char[1024]); + std::unique_ptr buf(new char[1024]); va_list list; va_start(list, fmt); vsprintf(buf.get(), fmt, list);