Start Converting CreateMove's
This commit is contained in:
parent
d4bc116a57
commit
86f854dac6
@ -9,7 +9,6 @@
|
|||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
namespace hacks::shared::autojoin
|
namespace hacks::shared::autojoin
|
||||||
{
|
{
|
||||||
void update();
|
|
||||||
void updateSearch();
|
void updateSearch();
|
||||||
void onShutdown();
|
void onShutdown();
|
||||||
} // namespace hacks::shared::autojoin
|
} // namespace hacks::shared::autojoin
|
||||||
|
@ -38,7 +38,6 @@ public:
|
|||||||
void Init();
|
void Init();
|
||||||
extern std::array<ESPData, 2048> data;
|
extern std::array<ESPData, 2048> data;
|
||||||
|
|
||||||
void CreateMove();
|
|
||||||
void Draw();
|
void Draw();
|
||||||
|
|
||||||
// Entity Processing
|
// Entity Processing
|
||||||
|
@ -11,7 +11,6 @@ namespace hacks::shared::followbot
|
|||||||
{
|
{
|
||||||
|
|
||||||
void DrawTick();
|
void DrawTick();
|
||||||
void WorldTick();
|
|
||||||
int ClassPriority(CachedEntity *ent);
|
int ClassPriority(CachedEntity *ent);
|
||||||
|
|
||||||
bool isEnabled();
|
bool isEnabled();
|
||||||
|
@ -9,5 +9,4 @@ namespace hacks::tf2::NavBot
|
|||||||
{
|
{
|
||||||
void Init();
|
void Init();
|
||||||
void initonce();
|
void initonce();
|
||||||
void CreateMove();
|
|
||||||
} // namespace hacks::tf2::NavBot
|
} // namespace hacks::tf2::NavBot
|
@ -16,6 +16,5 @@ void Initialize();
|
|||||||
#if ENABLE_VISUALS
|
#if ENABLE_VISUALS
|
||||||
void Draw();
|
void Draw();
|
||||||
#endif
|
#endif
|
||||||
void Move();
|
|
||||||
void OnLevelInit();
|
void OnLevelInit();
|
||||||
} // namespace hacks::shared::walkbot
|
} // namespace hacks::shared::walkbot
|
||||||
|
@ -9,5 +9,4 @@
|
|||||||
|
|
||||||
class CachedEntity;
|
class CachedEntity;
|
||||||
|
|
||||||
void UpdateHoovyList();
|
|
||||||
bool IsHoovy(CachedEntity *entity);
|
bool IsHoovy(CachedEntity *entity);
|
||||||
|
@ -22,7 +22,6 @@ bool NavTo(Vector dest, bool navToLocalCenter = true, bool persistent = true,
|
|||||||
void clearInstructions();
|
void clearInstructions();
|
||||||
int findClosestNavSquare(Vector vec);
|
int findClosestNavSquare(Vector vec);
|
||||||
bool Prepare();
|
bool Prepare();
|
||||||
void CreateMove();
|
|
||||||
void Draw();
|
void Draw();
|
||||||
|
|
||||||
int FindInVector(size_t id);
|
int FindInVector(size_t id);
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <settings/Int.hpp>
|
#include <settings/Int.hpp>
|
||||||
|
#include "HookTools.hpp"
|
||||||
#include <hacks/AutoJoin.hpp>
|
#include <hacks/AutoJoin.hpp>
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
@ -157,26 +158,26 @@ void updateSearch()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
static HookedFunction
|
||||||
void update()
|
update(HookedFunctions_types::HF_CreateMove, "Autojoin", 1, []() {
|
||||||
{
|
|
||||||
#if !LAGBOT_MODE
|
#if !LAGBOT_MODE
|
||||||
if (autoteam_timer.test_and_set(500))
|
if (autoteam_timer.test_and_set(500))
|
||||||
{
|
|
||||||
if (autojoin_team and UnassignedTeam())
|
|
||||||
{
|
{
|
||||||
hack::ExecuteCommand("autoteam");
|
if (autojoin_team and UnassignedTeam())
|
||||||
|
{
|
||||||
|
hack::ExecuteCommand("autoteam");
|
||||||
|
}
|
||||||
|
else if (autojoin_class and UnassignedClass())
|
||||||
|
{
|
||||||
|
if (int(autojoin_class) < 10)
|
||||||
|
g_IEngine->ExecuteClientCmd(
|
||||||
|
format("join_class ",
|
||||||
|
classnames[int(autojoin_class) - 1])
|
||||||
|
.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (autojoin_class and UnassignedClass())
|
|
||||||
{
|
|
||||||
if (int(autojoin_class) < 10)
|
|
||||||
g_IEngine->ExecuteClientCmd(
|
|
||||||
format("join_class ", classnames[int(autojoin_class) - 1])
|
|
||||||
.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
});
|
||||||
|
|
||||||
void onShutdown()
|
void onShutdown()
|
||||||
{
|
{
|
||||||
|
@ -247,64 +247,66 @@ void Draw()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function called on create move
|
// Function called on create move
|
||||||
void CreateMove()
|
static HookedFunction
|
||||||
{
|
CreateMove(HookedFunctions_types::HF_CreateMove, "ESP", 18, []() {
|
||||||
|
// Check usersettings if enabled
|
||||||
|
if (!*enable)
|
||||||
|
return;
|
||||||
|
if (CE_BAD(LOCAL_E))
|
||||||
|
return;
|
||||||
|
// Something
|
||||||
|
std::lock_guard<std::mutex> esp_lock(threadsafe_mutex);
|
||||||
|
|
||||||
// Check usersettings if enabled
|
ResetEntityStrings(); // Clear any strings entities have
|
||||||
if (!*enable)
|
entities_need_repaint
|
||||||
return;
|
.clear(); // Clear data on entities that need redraw
|
||||||
|
int max_clients = g_IEngine->GetMaxClients();
|
||||||
|
int limit = HIGHEST_ENTITY;
|
||||||
|
|
||||||
// Something
|
// If not using any other special esp, we lower the min to the max
|
||||||
std::lock_guard<std::mutex> esp_lock(threadsafe_mutex);
|
// clients
|
||||||
|
if (!buildings && !proj_esp && !item_esp)
|
||||||
|
limit = std::min(max_clients, HIGHEST_ENTITY);
|
||||||
|
|
||||||
ResetEntityStrings(); // Clear any strings entities have
|
{ // Prof section ends when out of scope, these brackets here.
|
||||||
entities_need_repaint.clear(); // Clear data on entities that need redraw
|
PROF_SECTION(CM_ESP_EntityLoop);
|
||||||
int max_clients = g_IEngine->GetMaxClients();
|
// Loop through entities
|
||||||
int limit = HIGHEST_ENTITY;
|
for (int i = 0; i < limit; i++)
|
||||||
|
|
||||||
// If not using any other special esp, we lower the min to the max clients
|
|
||||||
if (!buildings && !proj_esp && !item_esp)
|
|
||||||
limit = std::min(max_clients, HIGHEST_ENTITY);
|
|
||||||
|
|
||||||
{ // Prof section ends when out of scope, these brackets here.
|
|
||||||
PROF_SECTION(CM_ESP_EntityLoop);
|
|
||||||
// Loop through entities
|
|
||||||
for (int i = 0; i < limit; i++)
|
|
||||||
{
|
|
||||||
// Get an entity from the loop tick and process it
|
|
||||||
CachedEntity *ent = ENTITY(i);
|
|
||||||
if (CE_BAD(ent))
|
|
||||||
continue;
|
|
||||||
ProcessEntity(ent);
|
|
||||||
// Update Bones
|
|
||||||
if (i <= 32)
|
|
||||||
ent->hitboxes.GetHitbox(0);
|
|
||||||
// Dont know what this check is for
|
|
||||||
if (data[i].string_count)
|
|
||||||
{
|
{
|
||||||
|
// Get an entity from the loop tick and process it
|
||||||
// Set entity color
|
CachedEntity *ent = ENTITY(i);
|
||||||
SetEntityColor(ent, colors::EntityF(ent));
|
if (CE_BAD(ent))
|
||||||
|
continue;
|
||||||
// If snow distance, add string here
|
ProcessEntity(ent);
|
||||||
if (show_distance)
|
// Update Bones
|
||||||
|
if (i <= 32)
|
||||||
|
ent->hitboxes.GetHitbox(0);
|
||||||
|
// Dont know what this check is for
|
||||||
|
if (data[i].string_count)
|
||||||
{
|
{
|
||||||
AddEntityString(
|
|
||||||
ent,
|
// Set entity color
|
||||||
format((int) (ENTITY(i)->m_flDistance() / 64 * 1.22f),
|
SetEntityColor(ent, colors::EntityF(ent));
|
||||||
'm'));
|
|
||||||
|
// If snow distance, add string here
|
||||||
|
if (show_distance)
|
||||||
|
{
|
||||||
|
AddEntityString(
|
||||||
|
ent, format((int) (ENTITY(i)->m_flDistance() / 64 *
|
||||||
|
1.22f),
|
||||||
|
'm'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No idea, this is confusing
|
||||||
|
if (data[ent->m_IDX].needs_paint)
|
||||||
|
{
|
||||||
|
if (vischeck)
|
||||||
|
data[ent->m_IDX].transparent = !ent->IsVisible();
|
||||||
|
entities_need_repaint.push_back(ent->m_IDX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No idea, this is confusing
|
|
||||||
if (data[ent->m_IDX].needs_paint)
|
|
||||||
{
|
|
||||||
if (vischeck)
|
|
||||||
data[ent->m_IDX].transparent = !ent->IsVisible();
|
|
||||||
entities_need_repaint.push_back(ent->m_IDX);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
static glez::texture atlas{ DATA_PATH "/textures/atlas.png" };
|
static glez::texture atlas{ DATA_PATH "/textures/atlas.png" };
|
||||||
static glez::texture idspec{ DATA_PATH "/textures/idspec.png" };
|
static glez::texture idspec{ DATA_PATH "/textures/idspec.png" };
|
||||||
|
@ -168,347 +168,350 @@ int ClassPriority(CachedEntity *ent)
|
|||||||
}
|
}
|
||||||
Timer waittime{};
|
Timer waittime{};
|
||||||
int lastent = 0;
|
int lastent = 0;
|
||||||
void WorldTick()
|
#if ENABLE_IPC
|
||||||
{
|
static HookedFunction
|
||||||
if (!enable)
|
WorldTick(HookedFunctions_types::HF_CreateMove, "followbot", 20, []() {
|
||||||
{
|
if (!enable)
|
||||||
follow_target = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!inited)
|
|
||||||
init();
|
|
||||||
|
|
||||||
// We need a local player to control
|
|
||||||
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
|
|
||||||
{
|
|
||||||
follow_target = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (afk)
|
|
||||||
checkAFK();
|
|
||||||
|
|
||||||
// Still good check
|
|
||||||
if (follow_target)
|
|
||||||
{
|
|
||||||
// Overflow protection
|
|
||||||
if (breadcrumbs.size() > crumb_limit)
|
|
||||||
follow_target = 0;
|
|
||||||
// Still good check
|
|
||||||
else if (CE_BAD(ENTITY(follow_target)))
|
|
||||||
follow_target = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!follow_target)
|
|
||||||
breadcrumbs.clear(); // no target == no path
|
|
||||||
// Target Selection
|
|
||||||
if (steamid)
|
|
||||||
{
|
|
||||||
// Find a target with the steam id, as it is prioritized
|
|
||||||
auto ent_count = HIGHEST_ENTITY;
|
|
||||||
for (int i = 0; i < ent_count; i++)
|
|
||||||
{
|
{
|
||||||
auto entity = ENTITY(i);
|
follow_target = 0;
|
||||||
if (CE_BAD(entity)) // Exist + dormant
|
return;
|
||||||
continue;
|
|
||||||
if (i == follow_target)
|
|
||||||
break;
|
|
||||||
if (entity->m_Type() != ENTITY_PLAYER)
|
|
||||||
continue;
|
|
||||||
if (steamid != entity->player_info.friendsID) // steamid check
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!entity->m_bAlivePlayer()) // Dont follow dead players
|
|
||||||
continue;
|
|
||||||
if (corneractivate)
|
|
||||||
{
|
|
||||||
Vector indirectOrigin =
|
|
||||||
VischeckCorner(LOCAL_E, entity, *follow_activation / 2,
|
|
||||||
true); // get the corner location that the
|
|
||||||
// future target is visible from
|
|
||||||
std::pair<Vector, Vector> 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);
|
|
||||||
addCrumbPair(LOCAL_E, entity, corners);
|
|
||||||
}
|
|
||||||
if (indirectOrigin.z)
|
|
||||||
addCrumbs(entity, indirectOrigin);
|
|
||||||
else if (!indirectOrigin.z && !corners.first.z)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!VisCheckEntFromEnt(LOCAL_E, entity))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
follow_target = entity->m_IDX;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
if (!inited)
|
||||||
// If we dont have a follow target from that, we look again for someone
|
init();
|
||||||
// else who is suitable
|
|
||||||
if ((!follow_target || change ||
|
// We need a local player to control
|
||||||
(ClassPriority(ENTITY(follow_target)) < 6 &&
|
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
|
||||||
ENTITY(follow_target)->player_info.friendsID != steamid)) &&
|
|
||||||
roambot)
|
|
||||||
{
|
|
||||||
// Try to get a new target
|
|
||||||
auto ent_count =
|
|
||||||
followcart ? HIGHEST_ENTITY : g_IEngine->GetMaxClients();
|
|
||||||
for (int i = 0; i < ent_count; i++)
|
|
||||||
{
|
{
|
||||||
auto entity = ENTITY(i);
|
follow_target = 0;
|
||||||
if (CE_BAD(entity)) // Exist + dormant
|
return;
|
||||||
continue;
|
}
|
||||||
if (!followcart)
|
|
||||||
|
if (afk)
|
||||||
|
checkAFK();
|
||||||
|
|
||||||
|
// Still good check
|
||||||
|
if (follow_target)
|
||||||
|
{
|
||||||
|
// Overflow protection
|
||||||
|
if (breadcrumbs.size() > crumb_limit)
|
||||||
|
follow_target = 0;
|
||||||
|
// Still good check
|
||||||
|
else if (CE_BAD(ENTITY(follow_target)))
|
||||||
|
follow_target = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!follow_target)
|
||||||
|
breadcrumbs.clear(); // no target == no path
|
||||||
|
// Target Selection
|
||||||
|
if (steamid)
|
||||||
|
{
|
||||||
|
// Find a target with the steam id, as it is prioritized
|
||||||
|
auto ent_count = HIGHEST_ENTITY;
|
||||||
|
for (int i = 0; i < ent_count; i++)
|
||||||
|
{
|
||||||
|
auto entity = ENTITY(i);
|
||||||
|
if (CE_BAD(entity)) // Exist + dormant
|
||||||
|
continue;
|
||||||
|
if (i == follow_target)
|
||||||
|
break;
|
||||||
if (entity->m_Type() != ENTITY_PLAYER)
|
if (entity->m_Type() != ENTITY_PLAYER)
|
||||||
continue;
|
continue;
|
||||||
if (entity == LOCAL_E) // Follow self lol
|
if (steamid != entity->player_info.friendsID) // steamid check
|
||||||
continue;
|
continue;
|
||||||
if (entity->m_bEnemy())
|
|
||||||
continue;
|
|
||||||
if (afk &&
|
|
||||||
afkTicks[i].check(int(
|
|
||||||
afktime))) // don't follow target that was determined afk
|
|
||||||
continue;
|
|
||||||
if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity))
|
|
||||||
continue;
|
|
||||||
if (!entity->m_bAlivePlayer()) // Dont follow dead players
|
|
||||||
continue;
|
|
||||||
if (follow_activation &&
|
|
||||||
entity->m_flDistance() > (float) follow_activation)
|
|
||||||
continue;
|
|
||||||
const model_t *model =
|
|
||||||
ENTITY(follow_target)->InternalEntity()->GetModel();
|
|
||||||
// FIXME follow cart/point
|
|
||||||
/*if (followcart && model &&
|
|
||||||
(lagexploit::pointarr[0] || lagexploit::pointarr[1] ||
|
|
||||||
lagexploit::pointarr[2] || lagexploit::pointarr[3] ||
|
|
||||||
lagexploit::pointarr[4]) &&
|
|
||||||
(model == lagexploit::pointarr[0] ||
|
|
||||||
model == lagexploit::pointarr[1] ||
|
|
||||||
model == lagexploit::pointarr[2] ||
|
|
||||||
model == lagexploit::pointarr[3] ||
|
|
||||||
model == lagexploit::pointarr[4]))
|
|
||||||
follow_target = entity->m_IDX;*/
|
|
||||||
if (entity->m_Type() != ENTITY_PLAYER)
|
|
||||||
continue;
|
|
||||||
// favor closer entitys
|
|
||||||
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)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (corneractivate)
|
if (!entity->m_bAlivePlayer()) // Dont follow dead players
|
||||||
{
|
continue;
|
||||||
Vector indirectOrigin =
|
if (corneractivate)
|
||||||
VischeckCorner(LOCAL_E, entity, 250,
|
|
||||||
true); // get the corner location that the
|
|
||||||
// future target is visible from
|
|
||||||
std::pair<Vector, Vector> 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);
|
Vector indirectOrigin = VischeckCorner(
|
||||||
if (!corners.first.z || !corners.second.z)
|
LOCAL_E, entity, *follow_activation / 2,
|
||||||
|
true); // get the corner location that the
|
||||||
|
// future target is visible from
|
||||||
|
std::pair<Vector, Vector> 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);
|
||||||
|
addCrumbPair(LOCAL_E, entity, corners);
|
||||||
|
}
|
||||||
|
if (indirectOrigin.z)
|
||||||
|
addCrumbs(entity, indirectOrigin);
|
||||||
|
else if (!indirectOrigin.z && !corners.first.z)
|
||||||
continue;
|
continue;
|
||||||
addCrumbPair(LOCAL_E, entity, corners);
|
|
||||||
}
|
}
|
||||||
if (indirectOrigin.z)
|
else
|
||||||
addCrumbs(entity, indirectOrigin);
|
{
|
||||||
else if (!indirectOrigin.z && !corners.first.z)
|
if (!VisCheckEntFromEnt(LOCAL_E, entity))
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
follow_target = entity->m_IDX;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!VisCheckEntFromEnt(LOCAL_E, entity))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ooooo, a target
|
|
||||||
follow_target = i;
|
|
||||||
afkTicks[i].update(); // set afk time to 0
|
|
||||||
}
|
}
|
||||||
}
|
// If we dont have a follow target from that, we look again for someone
|
||||||
lastent++;
|
// else who is suitable
|
||||||
if (lastent > g_IEngine->GetMaxClients())
|
if ((!follow_target || change ||
|
||||||
lastent = 0;
|
(ClassPriority(ENTITY(follow_target)) < 6 &&
|
||||||
// last check for entity before we continue
|
ENTITY(follow_target)->player_info.friendsID != steamid)) &&
|
||||||
if (!follow_target)
|
roambot)
|
||||||
return;
|
{
|
||||||
|
// Try to get a new target
|
||||||
|
auto ent_count =
|
||||||
|
followcart ? HIGHEST_ENTITY : g_IEngine->GetMaxClients();
|
||||||
|
for (int i = 0; i < ent_count; i++)
|
||||||
|
{
|
||||||
|
auto entity = ENTITY(i);
|
||||||
|
if (CE_BAD(entity)) // Exist + dormant
|
||||||
|
continue;
|
||||||
|
if (!followcart)
|
||||||
|
if (entity->m_Type() != ENTITY_PLAYER)
|
||||||
|
continue;
|
||||||
|
if (entity == LOCAL_E) // Follow self lol
|
||||||
|
continue;
|
||||||
|
if (entity->m_bEnemy())
|
||||||
|
continue;
|
||||||
|
if (afk &&
|
||||||
|
afkTicks[i].check(int(afktime))) // don't follow target that
|
||||||
|
// was determined afk
|
||||||
|
continue;
|
||||||
|
if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity))
|
||||||
|
continue;
|
||||||
|
if (!entity->m_bAlivePlayer()) // Dont follow dead players
|
||||||
|
continue;
|
||||||
|
if (follow_activation &&
|
||||||
|
entity->m_flDistance() > (float) follow_activation)
|
||||||
|
continue;
|
||||||
|
const model_t *model =
|
||||||
|
ENTITY(follow_target)->InternalEntity()->GetModel();
|
||||||
|
// FIXME follow cart/point
|
||||||
|
/*if (followcart && model &&
|
||||||
|
(lagexploit::pointarr[0] || lagexploit::pointarr[1] ||
|
||||||
|
lagexploit::pointarr[2] || lagexploit::pointarr[3] ||
|
||||||
|
lagexploit::pointarr[4]) &&
|
||||||
|
(model == lagexploit::pointarr[0] ||
|
||||||
|
model == lagexploit::pointarr[1] ||
|
||||||
|
model == lagexploit::pointarr[2] ||
|
||||||
|
model == lagexploit::pointarr[3] ||
|
||||||
|
model == lagexploit::pointarr[4]))
|
||||||
|
follow_target = entity->m_IDX;*/
|
||||||
|
if (entity->m_Type() != ENTITY_PLAYER)
|
||||||
|
continue;
|
||||||
|
// favor closer entitys
|
||||||
|
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)))
|
||||||
|
continue;
|
||||||
|
|
||||||
CachedEntity *followtar = ENTITY(follow_target);
|
if (corneractivate)
|
||||||
// wtf is this needed
|
{
|
||||||
if (CE_BAD(followtar) || !followtar->m_bAlivePlayer())
|
Vector indirectOrigin = VischeckCorner(
|
||||||
{
|
LOCAL_E, entity, 250,
|
||||||
follow_target = 0;
|
true); // get the corner location that the
|
||||||
return;
|
// future target is visible from
|
||||||
}
|
std::pair<Vector, Vector> corners;
|
||||||
// Check if we are following a disguised/spy
|
corners.first.z = 0;
|
||||||
if (IsPlayerDisguised(followtar) || IsPlayerInvisible(followtar))
|
corners.second.z = 0;
|
||||||
{
|
if (!indirectOrigin.z &&
|
||||||
follow_target = 0;
|
entity->m_IDX == lastent) // if we couldn't find it, run
|
||||||
return;
|
// wallcheck instead
|
||||||
}
|
{
|
||||||
// check if target is afk
|
corners = VischeckWall(LOCAL_E, entity, 250, true);
|
||||||
if (afk)
|
if (!corners.first.z || !corners.second.z)
|
||||||
{
|
continue;
|
||||||
if (afkTicks[follow_target].check(int(afktime)))
|
addCrumbPair(LOCAL_E, entity, corners);
|
||||||
|
}
|
||||||
|
if (indirectOrigin.z)
|
||||||
|
addCrumbs(entity, indirectOrigin);
|
||||||
|
else if (!indirectOrigin.z && !corners.first.z)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!VisCheckEntFromEnt(LOCAL_E, entity))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ooooo, a target
|
||||||
|
follow_target = i;
|
||||||
|
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;
|
||||||
|
|
||||||
|
CachedEntity *followtar = ENTITY(follow_target);
|
||||||
|
// wtf is this needed
|
||||||
|
if (CE_BAD(followtar) || !followtar->m_bAlivePlayer())
|
||||||
{
|
{
|
||||||
follow_target = 0;
|
follow_target = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
// Check if we are following a disguised/spy
|
||||||
|
if (IsPlayerDisguised(followtar) || IsPlayerInvisible(followtar))
|
||||||
|
{
|
||||||
|
follow_target = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// check if target is afk
|
||||||
|
if (afk)
|
||||||
|
{
|
||||||
|
if (afkTicks[follow_target].check(int(afktime)))
|
||||||
|
{
|
||||||
|
follow_target = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update timer on new target
|
// Update timer on new target
|
||||||
static Timer idle_time{};
|
static Timer idle_time{};
|
||||||
if (breadcrumbs.empty())
|
if (breadcrumbs.empty())
|
||||||
idle_time.update();
|
idle_time.update();
|
||||||
|
|
||||||
// If the player is close enough, we dont need to follow the path
|
// If the player is close enough, we dont need to follow the path
|
||||||
auto tar_orig = followtar->m_vecOrigin();
|
auto tar_orig = followtar->m_vecOrigin();
|
||||||
auto loc_orig = LOCAL_E->m_vecOrigin();
|
auto loc_orig = LOCAL_E->m_vecOrigin();
|
||||||
auto dist_to_target = loc_orig.DistTo(tar_orig);
|
auto dist_to_target = loc_orig.DistTo(tar_orig);
|
||||||
|
|
||||||
if ((dist_to_target < (float) follow_distance) &&
|
if ((dist_to_target < (float) follow_distance) &&
|
||||||
VisCheckEntFromEnt(LOCAL_E, followtar))
|
VisCheckEntFromEnt(LOCAL_E, followtar))
|
||||||
{
|
|
||||||
idle_time.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
// New crumbs, we add one if its empty so we have something to follow
|
|
||||||
if ((breadcrumbs.empty() ||
|
|
||||||
tar_orig.DistTo(breadcrumbs.at(breadcrumbs.size() - 1)) > 40.0F) &&
|
|
||||||
DistanceToGround(ENTITY(follow_target)) < 45)
|
|
||||||
breadcrumbs.push_back(tar_orig);
|
|
||||||
|
|
||||||
// Prune old and close crumbs that we wont need anymore, update idle timer
|
|
||||||
// too
|
|
||||||
for (int i = 0; i < breadcrumbs.size(); i++)
|
|
||||||
{
|
|
||||||
if (loc_orig.DistTo(breadcrumbs.at(i)) < 60.f)
|
|
||||||
{
|
{
|
||||||
idle_time.update();
|
idle_time.update();
|
||||||
for (int j = 0; j <= i; j++)
|
|
||||||
breadcrumbs.erase(breadcrumbs.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tauntsync
|
|
||||||
if (sync_taunt && HasCondition<TFCond_Taunting>(followtar) &&
|
|
||||||
lastTaunt.test_and_set(1000))
|
|
||||||
{
|
|
||||||
g_IEngine->ClientCmd("taunt");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Follow the crumbs when too far away, or just starting to follow
|
|
||||||
if (dist_to_target > (float) follow_distance)
|
|
||||||
{
|
|
||||||
// Check for jump
|
|
||||||
if (autojump && lastJump.check(1000) &&
|
|
||||||
(idle_time.check(2000) ||
|
|
||||||
DistanceToGround({ breadcrumbs[0].x, breadcrumbs[0].y,
|
|
||||||
breadcrumbs[0].z + 5 }) > 47))
|
|
||||||
{
|
|
||||||
current_user_cmd->buttons |= IN_JUMP;
|
|
||||||
lastJump.update();
|
|
||||||
}
|
|
||||||
// Check if still moving. 70 HU = Sniper Zoomed Speed
|
|
||||||
if (idle_time.check(3000) &&
|
|
||||||
CE_VECTOR(g_pLocalPlayer->entity, netvar.vVelocity).IsZero(60.0f))
|
|
||||||
{
|
|
||||||
follow_target = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Basic idle check
|
|
||||||
if (idle_time.test_and_set(5000))
|
|
||||||
{
|
|
||||||
follow_target = 0;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static float last_slot_check = 0.0f;
|
// New crumbs, we add one if its empty so we have something to follow
|
||||||
if (g_GlobalVars->curtime < last_slot_check)
|
if ((breadcrumbs.empty() ||
|
||||||
last_slot_check = 0.0f;
|
tar_orig.DistTo(breadcrumbs.at(breadcrumbs.size() - 1)) > 40.0F) &&
|
||||||
if (follow_target && (always_medigun || mimic_slot) &&
|
DistanceToGround(ENTITY(follow_target)) < 45)
|
||||||
(g_GlobalVars->curtime - last_slot_check > 1.0f) &&
|
breadcrumbs.push_back(tar_orig);
|
||||||
!g_pLocalPlayer->life_state &&
|
|
||||||
!CE_BYTE(ENTITY(follow_target), netvar.iLifeState))
|
// Prune old and close crumbs that we wont need anymore, update idle
|
||||||
|
// timer too
|
||||||
|
for (int i = 0; i < breadcrumbs.size(); i++)
|
||||||
{
|
{
|
||||||
|
if (loc_orig.DistTo(breadcrumbs.at(i)) < 60.f)
|
||||||
|
{
|
||||||
|
idle_time.update();
|
||||||
|
for (int j = 0; j <= i; j++)
|
||||||
|
breadcrumbs.erase(breadcrumbs.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We are checking our slot so reset the timer
|
// Tauntsync
|
||||||
last_slot_check = g_GlobalVars->curtime;
|
if (sync_taunt && HasCondition<TFCond_Taunting>(followtar) &&
|
||||||
|
lastTaunt.test_and_set(1000))
|
||||||
|
{
|
||||||
|
g_IEngine->ClientCmd("taunt");
|
||||||
|
}
|
||||||
|
|
||||||
// Get the follow targets active weapon
|
// Follow the crumbs when too far away, or just starting to follow
|
||||||
int owner_weapon_eid =
|
if (dist_to_target > (float) follow_distance)
|
||||||
(CE_INT(ENTITY(follow_target), netvar.hActiveWeapon) & 0xFFF);
|
{
|
||||||
IClientEntity *owner_weapon =
|
// Check for jump
|
||||||
g_IEntityList->GetClientEntity(owner_weapon_eid);
|
if (autojump && lastJump.check(1000) &&
|
||||||
|
(idle_time.check(2000) ||
|
||||||
|
DistanceToGround({ breadcrumbs[0].x, breadcrumbs[0].y,
|
||||||
|
breadcrumbs[0].z + 5 }) > 47))
|
||||||
|
{
|
||||||
|
current_user_cmd->buttons |= IN_JUMP;
|
||||||
|
lastJump.update();
|
||||||
|
}
|
||||||
|
// Check if still moving. 70 HU = Sniper Zoomed Speed
|
||||||
|
if (idle_time.check(3000) &&
|
||||||
|
CE_VECTOR(g_pLocalPlayer->entity, netvar.vVelocity)
|
||||||
|
.IsZero(60.0f))
|
||||||
|
{
|
||||||
|
follow_target = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Basic idle check
|
||||||
|
if (idle_time.test_and_set(5000))
|
||||||
|
{
|
||||||
|
follow_target = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If both the follow targets and the local players weapons arnt
|
static float last_slot_check = 0.0f;
|
||||||
// null or
|
if (g_GlobalVars->curtime < last_slot_check)
|
||||||
// dormant
|
last_slot_check = 0.0f;
|
||||||
if (owner_weapon && CE_GOOD(g_pLocalPlayer->weapon()))
|
if (follow_target && (always_medigun || mimic_slot) &&
|
||||||
|
(g_GlobalVars->curtime - last_slot_check > 1.0f) &&
|
||||||
|
!g_pLocalPlayer->life_state &&
|
||||||
|
!CE_BYTE(ENTITY(follow_target), netvar.iLifeState))
|
||||||
{
|
{
|
||||||
|
|
||||||
// IsBaseCombatWeapon()
|
// We are checking our slot so reset the timer
|
||||||
if (re::C_BaseCombatWeapon::IsBaseCombatWeapon(
|
last_slot_check = g_GlobalVars->curtime;
|
||||||
RAW_ENT(g_pLocalPlayer->weapon())) &&
|
|
||||||
re::C_BaseCombatWeapon::IsBaseCombatWeapon(owner_weapon))
|
// Get the follow targets active weapon
|
||||||
|
int owner_weapon_eid =
|
||||||
|
(CE_INT(ENTITY(follow_target), netvar.hActiveWeapon) &
|
||||||
|
0xFFF);
|
||||||
|
IClientEntity *owner_weapon =
|
||||||
|
g_IEntityList->GetClientEntity(owner_weapon_eid);
|
||||||
|
|
||||||
|
// If both the follow targets and the local players weapons arnt
|
||||||
|
// null or
|
||||||
|
// dormant
|
||||||
|
if (owner_weapon && CE_GOOD(g_pLocalPlayer->weapon()))
|
||||||
{
|
{
|
||||||
|
|
||||||
// Get the players slot numbers and store in some vars
|
// IsBaseCombatWeapon()
|
||||||
int my_slot = re::C_BaseCombatWeapon::GetSlot(
|
if (re::C_BaseCombatWeapon::IsBaseCombatWeapon(
|
||||||
RAW_ENT(g_pLocalPlayer->weapon()));
|
RAW_ENT(g_pLocalPlayer->weapon())) &&
|
||||||
int owner_slot =
|
re::C_BaseCombatWeapon::IsBaseCombatWeapon(
|
||||||
re::C_BaseCombatWeapon::GetSlot(owner_weapon);
|
owner_weapon))
|
||||||
|
|
||||||
// If the local player is a medic and user settings allow,
|
|
||||||
// then
|
|
||||||
// keep the medigun out
|
|
||||||
if (g_pLocalPlayer->clazz == tf_medic && always_medigun)
|
|
||||||
{
|
{
|
||||||
if (my_slot != 1)
|
|
||||||
|
// Get the players slot numbers and store in some vars
|
||||||
|
int my_slot = re::C_BaseCombatWeapon::GetSlot(
|
||||||
|
RAW_ENT(g_pLocalPlayer->weapon()));
|
||||||
|
int owner_slot =
|
||||||
|
re::C_BaseCombatWeapon::GetSlot(owner_weapon);
|
||||||
|
|
||||||
|
// If the local player is a medic and user settings
|
||||||
|
// allow, then keep the medigun out
|
||||||
|
if (g_pLocalPlayer->clazz == tf_medic && always_medigun)
|
||||||
{
|
{
|
||||||
g_IEngine->ExecuteClientCmd("slot2");
|
if (my_slot != 1)
|
||||||
|
{
|
||||||
|
g_IEngine->ExecuteClientCmd("slot2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else we attemt to keep our weapon mimiced with
|
||||||
|
// our follow target
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Else we attemt to keep our weapon mimiced with our
|
|
||||||
// follow
|
|
||||||
// target
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (my_slot != owner_slot)
|
|
||||||
{
|
{
|
||||||
g_IEngine->ExecuteClientCmd(
|
if (my_slot != owner_slot)
|
||||||
format("slot", owner_slot + 1).c_str());
|
{
|
||||||
|
g_IEngine->ExecuteClientCmd(
|
||||||
|
format("slot", owner_slot + 1).c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
WalkTo(breadcrumbs[0]);
|
||||||
}
|
}
|
||||||
WalkTo(breadcrumbs[0]);
|
else
|
||||||
}
|
idle_time.update();
|
||||||
else
|
});
|
||||||
idle_time.update();
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
void DrawTick()
|
void DrawTick()
|
||||||
{
|
{
|
||||||
#if ENABLE_VISUALS
|
#if ENABLE_VISUALS
|
||||||
|
@ -436,222 +436,155 @@ CatCommand debug_tele("navbot_debug", "debug", []() {
|
|||||||
CE_FLOAT(ent, netvar.m_flTeleYawToExit), g_GlobalVars->curtime,
|
CE_FLOAT(ent, netvar.m_flTeleYawToExit), g_GlobalVars->curtime,
|
||||||
g_GlobalVars->curtime * g_GlobalVars->interval_per_tick);
|
g_GlobalVars->curtime * g_GlobalVars->interval_per_tick);
|
||||||
});
|
});
|
||||||
|
|
||||||
int follow_target = 0;
|
int follow_target = 0;
|
||||||
void CreateMove()
|
static HookedFunction
|
||||||
{
|
CreateMove(HookedFunctions_types::HF_CreateMove, "NavBot", 16, []() {
|
||||||
if ((!enable && !enable_fb) || !nav::Prepare())
|
if ((!enable && !enable_fb) || !nav::Prepare())
|
||||||
return;
|
|
||||||
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
|
|
||||||
return;
|
|
||||||
if (primary_only && enable)
|
|
||||||
UpdateSlot();
|
|
||||||
if (*stay_near && nav_enemy_cd.test_and_set(1000) &&
|
|
||||||
(!HasLowAmmo()) & (!HasLowHealth()))
|
|
||||||
NavToEnemy();
|
|
||||||
if (HasLowHealth() && cdr.test_and_set(5000))
|
|
||||||
{
|
|
||||||
CachedEntity *med = nearestHealth();
|
|
||||||
if (CE_GOOD(med))
|
|
||||||
{
|
|
||||||
if (nav::priority == 1337)
|
|
||||||
nav::clearInstructions();
|
|
||||||
nav::NavTo(med->m_vecOrigin(), true, true, 7);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (HasLowAmmo() && cdr.test_and_set(5000))
|
|
||||||
{
|
|
||||||
CachedEntity *ammo = nearestAmmo();
|
|
||||||
if (CE_GOOD(ammo))
|
|
||||||
{
|
|
||||||
if (nav::priority == 1337)
|
|
||||||
nav::clearInstructions();
|
|
||||||
nav::NavTo(ammo->m_vecOrigin(), true, true, 6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((!HasLowHealth() && nav::priority == 7) ||
|
|
||||||
(!HasLowAmmo() && nav::priority == 6))
|
|
||||||
nav::clearInstructions();
|
|
||||||
static int waittime = (spy_mode || heavy_mode || engi_mode) ? 100 : 2000;
|
|
||||||
if (*take_tele)
|
|
||||||
{
|
|
||||||
int idx = GetClosestTeleporter();
|
|
||||||
if (idx != -1)
|
|
||||||
{
|
|
||||||
CachedEntity *ent = ENTITY(idx);
|
|
||||||
if (CE_GOOD(ent) && ent->m_flDistance() < 300.0f)
|
|
||||||
if (CE_FLOAT(ent, netvar.m_flTeleYawToExit) &&
|
|
||||||
CE_FLOAT(ent, netvar.m_flTeleRechargeTime) <
|
|
||||||
g_GlobalVars->curtime)
|
|
||||||
{
|
|
||||||
waittime = 1000;
|
|
||||||
cd3.update();
|
|
||||||
if (nav::priority == 1337)
|
|
||||||
nav::clearInstructions();
|
|
||||||
nav::NavTo(GetBuildingPosition(ent), false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (enable)
|
|
||||||
{
|
|
||||||
if (!nav::ReadyForCommands && !spy_mode && !heavy_mode && !engi_mode)
|
|
||||||
cd3.update();
|
|
||||||
if (target_sentry && NavToSentry(3))
|
|
||||||
return;
|
return;
|
||||||
bool isready = (spy_mode || heavy_mode || engi_mode)
|
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
|
||||||
? true
|
return;
|
||||||
: nav::ReadyForCommands;
|
if (primary_only && enable)
|
||||||
if (isready && cd3.test_and_set(waittime))
|
UpdateSlot();
|
||||||
|
if (*stay_near && nav_enemy_cd.test_and_set(1000) &&
|
||||||
|
(!HasLowAmmo()) & (!HasLowHealth()))
|
||||||
|
NavToEnemy();
|
||||||
|
if (HasLowHealth() && cdr.test_and_set(5000))
|
||||||
{
|
{
|
||||||
waittime = (spy_mode || heavy_mode || engi_mode) ? 100 : 2000;
|
CachedEntity *med = nearestHealth();
|
||||||
if (!spy_mode && !heavy_mode && !engi_mode)
|
if (CE_GOOD(med))
|
||||||
{
|
{
|
||||||
cd3.update();
|
if (nav::priority == 1337)
|
||||||
if (cd2.test_and_set(5000))
|
nav::clearInstructions();
|
||||||
Init();
|
nav::NavTo(med->m_vecOrigin(), true, true, 7);
|
||||||
if (!NavToSniperSpot(5))
|
|
||||||
waittime = 1;
|
|
||||||
}
|
}
|
||||||
else if (!engi_mode)
|
}
|
||||||
|
if (HasLowAmmo() && cdr.test_and_set(5000))
|
||||||
|
{
|
||||||
|
CachedEntity *ammo = nearestAmmo();
|
||||||
|
if (CE_GOOD(ammo))
|
||||||
{
|
{
|
||||||
CachedEntity *tar = NearestEnemy();
|
if (nav::priority == 1337)
|
||||||
if (CE_BAD(tar) && last_tar == -1 && nav::ReadyForCommands)
|
nav::clearInstructions();
|
||||||
|
nav::NavTo(ammo->m_vecOrigin(), true, true, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((!HasLowHealth() && nav::priority == 7) ||
|
||||||
|
(!HasLowAmmo() && nav::priority == 6))
|
||||||
|
nav::clearInstructions();
|
||||||
|
static int waittime =
|
||||||
|
(spy_mode || heavy_mode || engi_mode) ? 100 : 2000;
|
||||||
|
if (*take_tele)
|
||||||
|
{
|
||||||
|
int idx = GetClosestTeleporter();
|
||||||
|
if (idx != -1)
|
||||||
|
{
|
||||||
|
CachedEntity *ent = ENTITY(idx);
|
||||||
|
if (CE_GOOD(ent) && ent->m_flDistance() < 300.0f)
|
||||||
|
if (CE_FLOAT(ent, netvar.m_flTeleYawToExit) &&
|
||||||
|
CE_FLOAT(ent, netvar.m_flTeleRechargeTime) <
|
||||||
|
g_GlobalVars->curtime)
|
||||||
|
{
|
||||||
|
waittime = 1000;
|
||||||
|
cd3.update();
|
||||||
|
if (nav::priority == 1337)
|
||||||
|
nav::clearInstructions();
|
||||||
|
nav::NavTo(GetBuildingPosition(ent), false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
if (!nav::ReadyForCommands && !spy_mode && !heavy_mode &&
|
||||||
|
!engi_mode)
|
||||||
|
cd3.update();
|
||||||
|
if (target_sentry && NavToSentry(3))
|
||||||
|
return;
|
||||||
|
bool isready = (spy_mode || heavy_mode || engi_mode)
|
||||||
|
? true
|
||||||
|
: nav::ReadyForCommands;
|
||||||
|
if (isready && cd3.test_and_set(waittime))
|
||||||
|
{
|
||||||
|
waittime = (spy_mode || heavy_mode || engi_mode) ? 100 : 2000;
|
||||||
|
if (!spy_mode && !heavy_mode && !engi_mode)
|
||||||
{
|
{
|
||||||
|
cd3.update();
|
||||||
if (cd2.test_and_set(5000))
|
if (cd2.test_and_set(5000))
|
||||||
Init();
|
Init();
|
||||||
if (!NavToSniperSpot(4))
|
if (!NavToSniperSpot(5))
|
||||||
waittime = 1;
|
waittime = 1;
|
||||||
}
|
}
|
||||||
if (CE_GOOD(tar))
|
else if (!engi_mode)
|
||||||
{
|
{
|
||||||
if (!spy_mode ||
|
CachedEntity *tar = NearestEnemy();
|
||||||
!hacks::shared::backtrack::isBacktrackEnabled)
|
if (CE_BAD(tar) && last_tar == -1 && nav::ReadyForCommands)
|
||||||
{
|
{
|
||||||
if (!nav::NavTo(tar->m_vecOrigin(), false))
|
if (cd2.test_and_set(5000))
|
||||||
last_tar = -1;
|
Init();
|
||||||
|
if (!NavToSniperSpot(4))
|
||||||
|
waittime = 1;
|
||||||
}
|
}
|
||||||
else
|
if (CE_GOOD(tar))
|
||||||
{
|
{
|
||||||
int bestscr = INT_MAX;
|
if (!spy_mode ||
|
||||||
hacks::shared::backtrack::BacktrackData besttick{};
|
!hacks::shared::backtrack::isBacktrackEnabled)
|
||||||
for (auto i : hacks::shared::backtrack::headPositions
|
|
||||||
[tar->m_IDX])
|
|
||||||
{
|
{
|
||||||
if (!hacks::shared::backtrack::ValidTick(i, tar))
|
if (!nav::NavTo(tar->m_vecOrigin(), false))
|
||||||
|
last_tar = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int bestscr = INT_MAX;
|
||||||
|
hacks::shared::backtrack::BacktrackData besttick{};
|
||||||
|
for (auto i : hacks::shared::backtrack::
|
||||||
|
headPositions[tar->m_IDX])
|
||||||
{
|
{
|
||||||
int scr = i.tickcount;
|
if (!hacks::shared::backtrack::ValidTick(i,
|
||||||
if (scr < bestscr)
|
tar))
|
||||||
{
|
{
|
||||||
bestscr = scr;
|
int scr = i.tickcount;
|
||||||
besttick = i;
|
if (scr < bestscr)
|
||||||
|
{
|
||||||
|
bestscr = scr;
|
||||||
|
besttick = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (besttick.tickcount)
|
||||||
if (besttick.tickcount)
|
nav::NavTo(besttick.entorigin, false, false);
|
||||||
nav::NavTo(besttick.entorigin, false, false);
|
else if (!nav::NavTo(tar->m_vecOrigin(), false))
|
||||||
else if (!nav::NavTo(tar->m_vecOrigin(), false))
|
last_tar = -1;
|
||||||
last_tar = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Engi Mode
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Init things
|
|
||||||
if (cd2.test_and_set(5000))
|
|
||||||
Init();
|
|
||||||
// If No spots set just return
|
|
||||||
if (nest_spots.empty())
|
|
||||||
return;
|
|
||||||
// Get Metal (offset of MAX metal is +8 and current metal +12)
|
|
||||||
int metal = CE_INT(LOCAL_E, netvar.m_iAmmo + 12);
|
|
||||||
// Best spot storage
|
|
||||||
static Vector best_spot{};
|
|
||||||
// Get Best spot based on distance
|
|
||||||
if (engi_spot_cd.test_and_set(10000))
|
|
||||||
{
|
|
||||||
float bestscr = FLT_MAX;
|
|
||||||
for (auto spot : nest_spots)
|
|
||||||
{
|
|
||||||
if (spot.DistTo(LOCAL_E->m_vecOrigin()) < bestscr)
|
|
||||||
{
|
|
||||||
bestscr = spot.DistTo(LOCAL_E->m_vecOrigin());
|
|
||||||
best_spot = spot;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nav::priority == 1)
|
// Engi Mode
|
||||||
|
else
|
||||||
{
|
{
|
||||||
CachedEntity *ammo = nearestAmmo();
|
// Init things
|
||||||
if (CE_GOOD(ammo))
|
if (cd2.test_and_set(5000))
|
||||||
{
|
Init();
|
||||||
nav::NavTo(ammo->m_vecOrigin(), false, true);
|
// If No spots set just return
|
||||||
|
if (nest_spots.empty())
|
||||||
return;
|
return;
|
||||||
}
|
// Get Metal (offset of MAX metal is +8 and current metal
|
||||||
}
|
// +12)
|
||||||
// If Near The best spot and ready for commands
|
int metal = CE_INT(LOCAL_E, netvar.m_iAmmo + 12);
|
||||||
if (best_spot.DistTo(LOCAL_E->m_vecOrigin()) < 200.0f &&
|
// Best spot storage
|
||||||
(nav::ReadyForCommands || nav::priority == 1))
|
static Vector best_spot{};
|
||||||
{
|
// Get Best spot based on distance
|
||||||
// Get the closest Building
|
if (engi_spot_cd.test_and_set(10000))
|
||||||
int ClosestBuilding = GetClosestBuilding();
|
|
||||||
// If A Building was found
|
|
||||||
if (ClosestBuilding != -1)
|
|
||||||
{
|
{
|
||||||
CachedEntity *ent = ENTITY(ClosestBuilding);
|
float bestscr = FLT_MAX;
|
||||||
// If we have more than 25 metal and the building is
|
for (auto spot : nest_spots)
|
||||||
// damaged or not fully upgraded hit it with the wrench
|
|
||||||
if (metal > 25 &&
|
|
||||||
(CE_INT(ent, netvar.iUpgradeLevel) < 3 ||
|
|
||||||
CE_INT(ent, netvar.iBuildingHealth) <
|
|
||||||
CE_INT(ent, netvar.iBuildingMaxHealth)))
|
|
||||||
{
|
{
|
||||||
auto collide = RAW_ENT(ent)->GetCollideable();
|
if (spot.DistTo(LOCAL_E->m_vecOrigin()) < bestscr)
|
||||||
Vector min =
|
|
||||||
ent->m_vecOrigin() + collide->OBBMins();
|
|
||||||
Vector max =
|
|
||||||
ent->m_vecOrigin() + collide->OBBMaxs();
|
|
||||||
// Distance check
|
|
||||||
if (min.DistTo(g_pLocalPlayer->v_Eye) >
|
|
||||||
re::C_TFWeaponBaseMelee::GetSwingRange(
|
|
||||||
RAW_ENT(LOCAL_W)) &&
|
|
||||||
max.DistTo(g_pLocalPlayer->v_Eye) >
|
|
||||||
re::C_TFWeaponBaseMelee::GetSwingRange(
|
|
||||||
RAW_ENT(LOCAL_W)) &&
|
|
||||||
GetBuildingPosition(ent).DistTo(
|
|
||||||
g_pLocalPlayer->v_Eye) >
|
|
||||||
re::C_TFWeaponBaseMelee::GetSwingRange(
|
|
||||||
RAW_ENT(LOCAL_W)))
|
|
||||||
{
|
{
|
||||||
float minf = min.DistTo(g_pLocalPlayer->v_Eye);
|
bestscr = spot.DistTo(LOCAL_E->m_vecOrigin());
|
||||||
float maxf = max.DistTo(g_pLocalPlayer->v_Eye);
|
best_spot = spot;
|
||||||
float center = GetBuildingPosition(ent).DistTo(
|
|
||||||
g_pLocalPlayer->v_Eye);
|
|
||||||
float closest =
|
|
||||||
fminf(minf, fminf(maxf, center));
|
|
||||||
Vector tonav =
|
|
||||||
(minf == closest)
|
|
||||||
? min
|
|
||||||
: (maxf == closest)
|
|
||||||
? max
|
|
||||||
: GetBuildingPosition(ent);
|
|
||||||
nav::NavTo(tonav, false, false);
|
|
||||||
}
|
}
|
||||||
Vector tr = GetBuildingPosition(ent) -
|
|
||||||
g_pLocalPlayer->v_Eye;
|
|
||||||
Vector angles;
|
|
||||||
VectorAngles(tr, angles);
|
|
||||||
// Clamping is important
|
|
||||||
fClampAngle(angles);
|
|
||||||
current_user_cmd->viewangles = angles;
|
|
||||||
current_user_cmd->buttons |= IN_ATTACK;
|
|
||||||
g_pLocalPlayer->bUseSilentAngles = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get A building, Sentry > Dispenser
|
if (nav::priority == 1)
|
||||||
int tobuild = GetBestBuilding(metal);
|
|
||||||
// If not enough metal then Find ammo
|
|
||||||
if (tobuild == -1)
|
|
||||||
{
|
{
|
||||||
CachedEntity *ammo = nearestAmmo();
|
CachedEntity *ammo = nearestAmmo();
|
||||||
if (CE_GOOD(ammo))
|
if (CE_GOOD(ammo))
|
||||||
@ -659,276 +592,357 @@ void CreateMove()
|
|||||||
nav::NavTo(ammo->m_vecOrigin(), false, true);
|
nav::NavTo(ammo->m_vecOrigin(), false, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Ammo is dormant, go and find it!
|
}
|
||||||
else if (sniper_spots.size() && nav::ReadyForCommands)
|
// If Near The best spot and ready for commands
|
||||||
|
if (best_spot.DistTo(LOCAL_E->m_vecOrigin()) < 200.0f &&
|
||||||
|
(nav::ReadyForCommands || nav::priority == 1))
|
||||||
|
{
|
||||||
|
// Get the closest Building
|
||||||
|
int ClosestBuilding = GetClosestBuilding();
|
||||||
|
// If A Building was found
|
||||||
|
if (ClosestBuilding != -1)
|
||||||
{
|
{
|
||||||
if (cd2.test_and_set(5000))
|
CachedEntity *ent = ENTITY(ClosestBuilding);
|
||||||
Init();
|
// If we have more than 25 metal and the building is
|
||||||
if (!NavToSniperSpot(1))
|
// damaged or not fully upgraded hit it with the
|
||||||
waittime = 1;
|
// wrench
|
||||||
return;
|
if (metal > 25 &&
|
||||||
|
(CE_INT(ent, netvar.iUpgradeLevel) < 3 ||
|
||||||
|
CE_INT(ent, netvar.iBuildingHealth) <
|
||||||
|
CE_INT(ent, netvar.iBuildingMaxHealth)))
|
||||||
|
{
|
||||||
|
auto collide = RAW_ENT(ent)->GetCollideable();
|
||||||
|
Vector min =
|
||||||
|
ent->m_vecOrigin() + collide->OBBMins();
|
||||||
|
Vector max =
|
||||||
|
ent->m_vecOrigin() + collide->OBBMaxs();
|
||||||
|
// Distance check
|
||||||
|
if (min.DistTo(g_pLocalPlayer->v_Eye) >
|
||||||
|
re::C_TFWeaponBaseMelee::GetSwingRange(
|
||||||
|
RAW_ENT(LOCAL_W)) &&
|
||||||
|
max.DistTo(g_pLocalPlayer->v_Eye) >
|
||||||
|
re::C_TFWeaponBaseMelee::GetSwingRange(
|
||||||
|
RAW_ENT(LOCAL_W)) &&
|
||||||
|
GetBuildingPosition(ent).DistTo(
|
||||||
|
g_pLocalPlayer->v_Eye) >
|
||||||
|
re::C_TFWeaponBaseMelee::GetSwingRange(
|
||||||
|
RAW_ENT(LOCAL_W)))
|
||||||
|
{
|
||||||
|
float minf =
|
||||||
|
min.DistTo(g_pLocalPlayer->v_Eye);
|
||||||
|
float maxf =
|
||||||
|
max.DistTo(g_pLocalPlayer->v_Eye);
|
||||||
|
float center =
|
||||||
|
GetBuildingPosition(ent).DistTo(
|
||||||
|
g_pLocalPlayer->v_Eye);
|
||||||
|
float closest =
|
||||||
|
fminf(minf, fminf(maxf, center));
|
||||||
|
Vector tonav =
|
||||||
|
(minf == closest)
|
||||||
|
? min
|
||||||
|
: (maxf == closest)
|
||||||
|
? max
|
||||||
|
: GetBuildingPosition(ent);
|
||||||
|
nav::NavTo(tonav, false, false);
|
||||||
|
}
|
||||||
|
Vector tr = GetBuildingPosition(ent) -
|
||||||
|
g_pLocalPlayer->v_Eye;
|
||||||
|
Vector angles;
|
||||||
|
VectorAngles(tr, angles);
|
||||||
|
// Clamping is important
|
||||||
|
fClampAngle(angles);
|
||||||
|
current_user_cmd->viewangles = angles;
|
||||||
|
current_user_cmd->buttons |= IN_ATTACK;
|
||||||
|
g_pLocalPlayer->bUseSilentAngles = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get A building, Sentry > Dispenser
|
||||||
|
int tobuild = GetBestBuilding(metal);
|
||||||
|
// If not enough metal then Find ammo
|
||||||
|
if (tobuild == -1)
|
||||||
|
{
|
||||||
|
CachedEntity *ammo = nearestAmmo();
|
||||||
|
if (CE_GOOD(ammo))
|
||||||
|
{
|
||||||
|
nav::NavTo(ammo->m_vecOrigin(), false, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Ammo is dormant, go and find it!
|
||||||
|
else if (sniper_spots.size() &&
|
||||||
|
nav::ReadyForCommands)
|
||||||
|
{
|
||||||
|
if (cd2.test_and_set(5000))
|
||||||
|
Init();
|
||||||
|
if (!NavToSniperSpot(1))
|
||||||
|
waittime = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Build Building
|
||||||
|
else if (tobuild != 3)
|
||||||
|
{
|
||||||
|
// Make ENgi look slightly down
|
||||||
|
current_user_cmd->viewangles.x = 20.0f;
|
||||||
|
// Build buildings in a 360° angle around player
|
||||||
|
current_user_cmd->viewangles.y =
|
||||||
|
90.0f * (tobuild + 1);
|
||||||
|
// Build new one
|
||||||
|
g_IEngine->ServerCmd(
|
||||||
|
format("build ", tobuild).c_str(), true);
|
||||||
|
current_user_cmd->buttons |= IN_ATTACK;
|
||||||
|
g_pLocalPlayer->bUseSilentAngles = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Build Building
|
// If not near best spot then navigate to it
|
||||||
else if (tobuild != 3)
|
else if (nav::ReadyForCommands)
|
||||||
{
|
nav::NavTo(best_spot, false, true);
|
||||||
// Make ENgi look slightly down
|
|
||||||
current_user_cmd->viewangles.x = 20.0f;
|
|
||||||
// Build buildings in a 360° angle around player
|
|
||||||
current_user_cmd->viewangles.y = 90.0f * (tobuild + 1);
|
|
||||||
// Build new one
|
|
||||||
g_IEngine->ServerCmd(format("build ", tobuild).c_str(),
|
|
||||||
true);
|
|
||||||
current_user_cmd->buttons |= IN_ATTACK;
|
|
||||||
g_pLocalPlayer->bUseSilentAngles = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// If not near best spot then navigate to it
|
|
||||||
else if (nav::ReadyForCommands)
|
|
||||||
nav::NavTo(best_spot, false, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (enable_fb)
|
||||||
else if (enable_fb)
|
|
||||||
{
|
|
||||||
// We need a local player to control
|
|
||||||
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
|
|
||||||
{
|
{
|
||||||
follow_target = 0;
|
// We need a local player to control
|
||||||
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (afk)
|
|
||||||
checkAFK();
|
|
||||||
|
|
||||||
// Still good check
|
|
||||||
if (follow_target)
|
|
||||||
if (CE_BAD(ENTITY(follow_target)))
|
|
||||||
follow_target = 0;
|
|
||||||
|
|
||||||
if (!follow_target)
|
|
||||||
nav::NavTo(LOCAL_E->m_vecOrigin(), true,
|
|
||||||
false); // no target == no path
|
|
||||||
// Target Selection
|
|
||||||
if (steamid)
|
|
||||||
{
|
|
||||||
// Find a target with the steam id, as it is prioritized
|
|
||||||
auto ent_count = HIGHEST_ENTITY;
|
|
||||||
for (int i = 0; i < ent_count; i++)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!entity->m_bAlivePlayer()) // Dont follow dead players
|
|
||||||
continue;
|
|
||||||
follow_target = entity->m_IDX;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If we dont have a follow target from that, we look again for someone
|
|
||||||
// else who is suitable
|
|
||||||
if ((!follow_target || change_tar ||
|
|
||||||
(hacks::shared::followbot::ClassPriority(ENTITY(follow_target)) <
|
|
||||||
6 &&
|
|
||||||
ENTITY(follow_target)->player_info.friendsID != steamid)) &&
|
|
||||||
roambot)
|
|
||||||
{
|
|
||||||
// Try to get a new target
|
|
||||||
auto ent_count = g_IEngine->GetMaxClients();
|
|
||||||
for (int i = 0; i < ent_count; i++)
|
|
||||||
{
|
|
||||||
auto entity = ENTITY(i);
|
|
||||||
if (CE_BAD(entity)) // Exist + dormant
|
|
||||||
continue;
|
|
||||||
if (entity->m_Type() != ENTITY_PLAYER)
|
|
||||||
continue;
|
|
||||||
if (entity == LOCAL_E) // Follow self lol
|
|
||||||
continue;
|
|
||||||
if (entity->m_bEnemy())
|
|
||||||
continue;
|
|
||||||
if (afk &&
|
|
||||||
afkTicks[i].check(int(afktime))) // don't follow target that
|
|
||||||
// was determined afk
|
|
||||||
continue;
|
|
||||||
if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity))
|
|
||||||
continue;
|
|
||||||
if (!entity->m_bAlivePlayer()) // Dont follow dead players
|
|
||||||
continue;
|
|
||||||
if (follow_activation &&
|
|
||||||
entity->m_flDistance() > (float) follow_activation)
|
|
||||||
continue;
|
|
||||||
const model_t *model =
|
|
||||||
ENTITY(follow_target)->InternalEntity()->GetModel();
|
|
||||||
// FIXME follow cart/point
|
|
||||||
/*if (followcart && model &&
|
|
||||||
(lagexploit::pointarr[0] || lagexploit::pointarr[1] ||
|
|
||||||
lagexploit::pointarr[2] || lagexploit::pointarr[3] ||
|
|
||||||
lagexploit::pointarr[4]) &&
|
|
||||||
(model == lagexploit::pointarr[0] ||
|
|
||||||
model == lagexploit::pointarr[1] ||
|
|
||||||
model == lagexploit::pointarr[2] ||
|
|
||||||
model == lagexploit::pointarr[3] ||
|
|
||||||
model == lagexploit::pointarr[4]))
|
|
||||||
follow_target = entity->m_IDX;*/
|
|
||||||
if (entity->m_Type() != ENTITY_PLAYER)
|
|
||||||
continue;
|
|
||||||
// favor closer entitys
|
|
||||||
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 (hacks::shared::followbot::ClassPriority(
|
|
||||||
ENTITY(follow_target)) >=
|
|
||||||
hacks::shared::followbot::ClassPriority(ENTITY(i)))
|
|
||||||
continue;
|
|
||||||
// ooooo, a target
|
|
||||||
follow_target = i;
|
|
||||||
afkTicks[i].update(); // set afk time to 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// last check for entity before we continue
|
|
||||||
if (!follow_target)
|
|
||||||
{
|
|
||||||
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CachedEntity *followtar = ENTITY(follow_target);
|
|
||||||
// wtf is this needed
|
|
||||||
if (CE_BAD(followtar) || !followtar->m_bAlivePlayer())
|
|
||||||
{
|
|
||||||
follow_target = 0;
|
|
||||||
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Check if we are following a disguised/spy
|
|
||||||
if (IsPlayerDisguised(followtar) || IsPlayerInvisible(followtar))
|
|
||||||
{
|
|
||||||
follow_target = 0;
|
|
||||||
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// check if target is afk
|
|
||||||
if (afk)
|
|
||||||
{
|
|
||||||
if (afkTicks[follow_target].check(int(afktime)))
|
|
||||||
{
|
{
|
||||||
follow_target = 0;
|
follow_target = 0;
|
||||||
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Update timer on new target
|
if (afk)
|
||||||
static Timer idle_time{};
|
checkAFK();
|
||||||
if (nav::ReadyForCommands)
|
|
||||||
idle_time.update();
|
|
||||||
|
|
||||||
// If the player is close enough, we dont need to follow the path
|
// Still good check
|
||||||
auto tar_orig = followtar->m_vecOrigin();
|
if (follow_target)
|
||||||
auto loc_orig = LOCAL_E->m_vecOrigin();
|
if (CE_BAD(ENTITY(follow_target)))
|
||||||
auto dist_to_target = loc_orig.DistTo(tar_orig);
|
follow_target = 0;
|
||||||
if (!CE_VECTOR(followtar, netvar.vVelocity).IsZero(20.0f))
|
|
||||||
idle_time.update();
|
|
||||||
|
|
||||||
// Tauntsync
|
if (!follow_target)
|
||||||
if (sync_taunt && HasCondition<TFCond_Taunting>(followtar) &&
|
nav::NavTo(LOCAL_E->m_vecOrigin(), true,
|
||||||
lastTaunt.test_and_set(1000))
|
false); // no target == no path
|
||||||
g_IEngine->ClientCmd("taunt");
|
// Target Selection
|
||||||
|
if (steamid)
|
||||||
|
{
|
||||||
|
// Find a target with the steam id, as it is prioritized
|
||||||
|
auto ent_count = HIGHEST_ENTITY;
|
||||||
|
for (int i = 0; i < ent_count; i++)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
continue;
|
||||||
|
|
||||||
// Check for jump
|
if (!entity->m_bAlivePlayer()) // Dont follow dead players
|
||||||
if (autojump && lastJump.check(1000) && idle_time.check(2000))
|
continue;
|
||||||
{
|
follow_target = entity->m_IDX;
|
||||||
current_user_cmd->buttons |= IN_JUMP;
|
break;
|
||||||
lastJump.update();
|
}
|
||||||
}
|
}
|
||||||
// Check if still moving. 70 HU = Sniper Zoomed Speed
|
// If we dont have a follow target from that, we look again for
|
||||||
if (idle_time.check(3000) &&
|
// someone else who is suitable
|
||||||
CE_VECTOR(g_pLocalPlayer->entity, netvar.vVelocity).IsZero(60.0f))
|
if ((!follow_target || change_tar ||
|
||||||
{
|
(hacks::shared::followbot::ClassPriority(
|
||||||
follow_target = 0;
|
ENTITY(follow_target)) < 6 &&
|
||||||
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
ENTITY(follow_target)->player_info.friendsID != steamid)) &&
|
||||||
return;
|
roambot)
|
||||||
}
|
{
|
||||||
// Basic idle check
|
// Try to get a new target
|
||||||
if (idle_time.test_and_set(5000))
|
auto ent_count = g_IEngine->GetMaxClients();
|
||||||
{
|
for (int i = 0; i < ent_count; i++)
|
||||||
follow_target = 0;
|
{
|
||||||
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
auto entity = ENTITY(i);
|
||||||
return;
|
if (CE_BAD(entity)) // Exist + dormant
|
||||||
}
|
continue;
|
||||||
|
if (entity->m_Type() != ENTITY_PLAYER)
|
||||||
|
continue;
|
||||||
|
if (entity == LOCAL_E) // Follow self lol
|
||||||
|
continue;
|
||||||
|
if (entity->m_bEnemy())
|
||||||
|
continue;
|
||||||
|
if (afk && afkTicks[i].check(
|
||||||
|
int(afktime))) // don't follow target that
|
||||||
|
// was determined afk
|
||||||
|
continue;
|
||||||
|
if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity))
|
||||||
|
continue;
|
||||||
|
if (!entity->m_bAlivePlayer()) // Dont follow dead players
|
||||||
|
continue;
|
||||||
|
if (follow_activation &&
|
||||||
|
entity->m_flDistance() > (float) follow_activation)
|
||||||
|
continue;
|
||||||
|
const model_t *model =
|
||||||
|
ENTITY(follow_target)->InternalEntity()->GetModel();
|
||||||
|
// FIXME follow cart/point
|
||||||
|
/*if (followcart && model &&
|
||||||
|
(lagexploit::pointarr[0] || lagexploit::pointarr[1] ||
|
||||||
|
lagexploit::pointarr[2] || lagexploit::pointarr[3] ||
|
||||||
|
lagexploit::pointarr[4]) &&
|
||||||
|
(model == lagexploit::pointarr[0] ||
|
||||||
|
model == lagexploit::pointarr[1] ||
|
||||||
|
model == lagexploit::pointarr[2] ||
|
||||||
|
model == lagexploit::pointarr[3] ||
|
||||||
|
model == lagexploit::pointarr[4]))
|
||||||
|
follow_target = entity->m_IDX;*/
|
||||||
|
if (entity->m_Type() != ENTITY_PLAYER)
|
||||||
|
continue;
|
||||||
|
// favor closer entitys
|
||||||
|
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 (hacks::shared::followbot::ClassPriority(
|
||||||
|
ENTITY(follow_target)) >=
|
||||||
|
hacks::shared::followbot::ClassPriority(ENTITY(i)))
|
||||||
|
continue;
|
||||||
|
// ooooo, a target
|
||||||
|
follow_target = i;
|
||||||
|
afkTicks[i].update(); // set afk time to 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// last check for entity before we continue
|
||||||
|
if (!follow_target)
|
||||||
|
{
|
||||||
|
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static float last_slot_check = 0.0f;
|
CachedEntity *followtar = ENTITY(follow_target);
|
||||||
if (g_GlobalVars->curtime < last_slot_check)
|
// wtf is this needed
|
||||||
last_slot_check = 0.0f;
|
if (CE_BAD(followtar) || !followtar->m_bAlivePlayer())
|
||||||
if (follow_target && (always_medigun || mimic_slot) &&
|
{
|
||||||
(g_GlobalVars->curtime - last_slot_check > 1.0f) &&
|
follow_target = 0;
|
||||||
!g_pLocalPlayer->life_state &&
|
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
||||||
!CE_BYTE(ENTITY(follow_target), netvar.iLifeState))
|
return;
|
||||||
{
|
}
|
||||||
|
// Check if we are following a disguised/spy
|
||||||
|
if (IsPlayerDisguised(followtar) || IsPlayerInvisible(followtar))
|
||||||
|
{
|
||||||
|
follow_target = 0;
|
||||||
|
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// check if target is afk
|
||||||
|
if (afk)
|
||||||
|
{
|
||||||
|
if (afkTicks[follow_target].check(int(afktime)))
|
||||||
|
{
|
||||||
|
follow_target = 0;
|
||||||
|
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We are checking our slot so reset the timer
|
// Update timer on new target
|
||||||
last_slot_check = g_GlobalVars->curtime;
|
static Timer idle_time{};
|
||||||
|
if (nav::ReadyForCommands)
|
||||||
|
idle_time.update();
|
||||||
|
|
||||||
// Get the follow targets active weapon
|
// If the player is close enough, we dont need to follow the path
|
||||||
int owner_weapon_eid =
|
auto tar_orig = followtar->m_vecOrigin();
|
||||||
(CE_INT(ENTITY(follow_target), netvar.hActiveWeapon) & 0xFFF);
|
auto loc_orig = LOCAL_E->m_vecOrigin();
|
||||||
IClientEntity *owner_weapon =
|
auto dist_to_target = loc_orig.DistTo(tar_orig);
|
||||||
g_IEntityList->GetClientEntity(owner_weapon_eid);
|
if (!CE_VECTOR(followtar, netvar.vVelocity).IsZero(20.0f))
|
||||||
|
idle_time.update();
|
||||||
|
|
||||||
// If both the follow targets and the local players weapons arnt
|
// Tauntsync
|
||||||
// null or
|
if (sync_taunt && HasCondition<TFCond_Taunting>(followtar) &&
|
||||||
// dormant
|
lastTaunt.test_and_set(1000))
|
||||||
if (owner_weapon && CE_GOOD(g_pLocalPlayer->weapon()))
|
g_IEngine->ClientCmd("taunt");
|
||||||
|
|
||||||
|
// Check for jump
|
||||||
|
if (autojump && lastJump.check(1000) && idle_time.check(2000))
|
||||||
|
{
|
||||||
|
current_user_cmd->buttons |= IN_JUMP;
|
||||||
|
lastJump.update();
|
||||||
|
}
|
||||||
|
// Check if still moving. 70 HU = Sniper Zoomed Speed
|
||||||
|
if (idle_time.check(3000) &&
|
||||||
|
CE_VECTOR(g_pLocalPlayer->entity, netvar.vVelocity)
|
||||||
|
.IsZero(60.0f))
|
||||||
|
{
|
||||||
|
follow_target = 0;
|
||||||
|
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Basic idle check
|
||||||
|
if (idle_time.test_and_set(5000))
|
||||||
|
{
|
||||||
|
follow_target = 0;
|
||||||
|
nav::NavTo(LOCAL_E->m_vecOrigin(), true, false, 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float last_slot_check = 0.0f;
|
||||||
|
if (g_GlobalVars->curtime < last_slot_check)
|
||||||
|
last_slot_check = 0.0f;
|
||||||
|
if (follow_target && (always_medigun || mimic_slot) &&
|
||||||
|
(g_GlobalVars->curtime - last_slot_check > 1.0f) &&
|
||||||
|
!g_pLocalPlayer->life_state &&
|
||||||
|
!CE_BYTE(ENTITY(follow_target), netvar.iLifeState))
|
||||||
{
|
{
|
||||||
|
|
||||||
// IsBaseCombatWeapon()
|
// We are checking our slot so reset the timer
|
||||||
if (re::C_BaseCombatWeapon::IsBaseCombatWeapon(
|
last_slot_check = g_GlobalVars->curtime;
|
||||||
RAW_ENT(g_pLocalPlayer->weapon())) &&
|
|
||||||
re::C_BaseCombatWeapon::IsBaseCombatWeapon(owner_weapon))
|
// Get the follow targets active weapon
|
||||||
|
int owner_weapon_eid =
|
||||||
|
(CE_INT(ENTITY(follow_target), netvar.hActiveWeapon) &
|
||||||
|
0xFFF);
|
||||||
|
IClientEntity *owner_weapon =
|
||||||
|
g_IEntityList->GetClientEntity(owner_weapon_eid);
|
||||||
|
|
||||||
|
// If both the follow targets and the local players weapons arnt
|
||||||
|
// null or
|
||||||
|
// dormant
|
||||||
|
if (owner_weapon && CE_GOOD(g_pLocalPlayer->weapon()))
|
||||||
{
|
{
|
||||||
|
|
||||||
// Get the players slot numbers and store in some vars
|
// IsBaseCombatWeapon()
|
||||||
int my_slot = re::C_BaseCombatWeapon::GetSlot(
|
if (re::C_BaseCombatWeapon::IsBaseCombatWeapon(
|
||||||
RAW_ENT(g_pLocalPlayer->weapon()));
|
RAW_ENT(g_pLocalPlayer->weapon())) &&
|
||||||
int owner_slot =
|
re::C_BaseCombatWeapon::IsBaseCombatWeapon(
|
||||||
re::C_BaseCombatWeapon::GetSlot(owner_weapon);
|
owner_weapon))
|
||||||
|
|
||||||
// If the local player is a medic and user settings allow,
|
|
||||||
// then
|
|
||||||
// keep the medigun out
|
|
||||||
if (g_pLocalPlayer->clazz == tf_medic && always_medigun)
|
|
||||||
{
|
{
|
||||||
if (my_slot != 1)
|
|
||||||
|
// Get the players slot numbers and store in some vars
|
||||||
|
int my_slot = re::C_BaseCombatWeapon::GetSlot(
|
||||||
|
RAW_ENT(g_pLocalPlayer->weapon()));
|
||||||
|
int owner_slot =
|
||||||
|
re::C_BaseCombatWeapon::GetSlot(owner_weapon);
|
||||||
|
|
||||||
|
// If the local player is a medic and user settings
|
||||||
|
// allow, then keep the medigun out
|
||||||
|
if (g_pLocalPlayer->clazz == tf_medic && always_medigun)
|
||||||
{
|
{
|
||||||
g_IEngine->ExecuteClientCmd("slot2");
|
if (my_slot != 1)
|
||||||
|
{
|
||||||
|
g_IEngine->ExecuteClientCmd("slot2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else we attemt to keep our weapon mimiced with
|
||||||
|
// our follow target
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Else we attemt to keep our weapon mimiced with our
|
|
||||||
// follow
|
|
||||||
// target
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (my_slot != owner_slot)
|
|
||||||
{
|
{
|
||||||
g_IEngine->ExecuteClientCmd(
|
if (my_slot != owner_slot)
|
||||||
format("slot", owner_slot + 1).c_str());
|
{
|
||||||
|
g_IEngine->ExecuteClientCmd(
|
||||||
|
format("slot", owner_slot + 1).c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
nav::NavTo(tar_orig, false, true, 5);
|
||||||
}
|
}
|
||||||
nav::NavTo(tar_orig, false, true, 5);
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace hacks::tf2::NavBot
|
} // namespace hacks::tf2::NavBot
|
||||||
|
@ -1216,75 +1216,78 @@ void OnLevelInit()
|
|||||||
Timer quit_timer{};
|
Timer quit_timer{};
|
||||||
Timer map_check{};
|
Timer map_check{};
|
||||||
int erasedelay = 0;
|
int erasedelay = 0;
|
||||||
void Move()
|
static HookedFunction
|
||||||
{
|
Move(HookedFunctions_types::HF_CreateMove, "Walkbot", 16, []() {
|
||||||
if (state::state == WB_DISABLED)
|
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
|
||||||
return;
|
return;
|
||||||
switch (state::state)
|
if (state::state == WB_DISABLED)
|
||||||
{
|
return;
|
||||||
case WB_RECORDING:
|
switch (state::state)
|
||||||
{
|
|
||||||
UpdateClosestNode();
|
|
||||||
if (recording_key.isKeyDown() and ShouldSpawnNode())
|
|
||||||
{
|
{
|
||||||
RecordNode();
|
case WB_RECORDING:
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WB_EDITING:
|
|
||||||
{
|
|
||||||
UpdateClosestNode();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WB_REPLAYING:
|
|
||||||
{
|
|
||||||
if (leave_if_empty)
|
|
||||||
{
|
{
|
||||||
if (nodes.size() == 0 || g_IEngine->GetLevelName() != prevlvlname)
|
UpdateClosestNode();
|
||||||
|
if (recording_key.isKeyDown() and ShouldSpawnNode())
|
||||||
{
|
{
|
||||||
prevlvlname = g_IEngine->GetLevelName();
|
RecordNode();
|
||||||
if (!boost::contains(prevlvlname, "pl_"))
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WB_EDITING:
|
||||||
|
{
|
||||||
|
UpdateClosestNode();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WB_REPLAYING:
|
||||||
|
{
|
||||||
|
if (leave_if_empty)
|
||||||
|
{
|
||||||
|
if (nodes.size() == 0 ||
|
||||||
|
g_IEngine->GetLevelName() != prevlvlname)
|
||||||
{
|
{
|
||||||
Load("default");
|
prevlvlname = g_IEngine->GetLevelName();
|
||||||
if (leave_if_empty && nodes.size() == 0 &&
|
if (!boost::contains(prevlvlname, "pl_"))
|
||||||
quit_timer.test_and_set(5000))
|
|
||||||
{
|
{
|
||||||
logging::Info("No map file, abandon");
|
Load("default");
|
||||||
tfmm::abandon();
|
if (leave_if_empty && nodes.size() == 0 &&
|
||||||
return;
|
quit_timer.test_and_set(5000))
|
||||||
|
{
|
||||||
|
logging::Info("No map file, abandon");
|
||||||
|
tfmm::abandon();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*prevlvlname = g_IEngine->GetLevelName();
|
||||||
|
std::string prvlvlname(prevlvlname);
|
||||||
|
if (boost::contains(prvlvlname, "pl_") ||
|
||||||
|
boost::contains(prvlvlname, "cp_"))
|
||||||
|
{
|
||||||
|
logging::Info("1");
|
||||||
|
bool ret = false;
|
||||||
|
if (lagexploit::pointarr[0] || lagexploit::pointarr[1] ||
|
||||||
|
lagexploit::pointarr[2] || lagexploit::pointarr[3] ||
|
||||||
|
lagexploit::pointarr[4])
|
||||||
|
{
|
||||||
|
hacks::shared::followbot::followbot = 1;
|
||||||
|
hacks::shared::followbot::roambot = 1;
|
||||||
|
hacks::shared::followbot::followcart = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hacks::shared::followbot::followbot = 0;
|
||||||
|
hacks::shared::followbot::roambot = 0;
|
||||||
|
hacks::shared::followbot::followcart = false;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
if (nodes.size() == 0)
|
||||||
|
return;
|
||||||
|
if (force_slot)
|
||||||
|
UpdateSlot();
|
||||||
|
UpdateWalker();
|
||||||
}
|
}
|
||||||
/*prevlvlname = g_IEngine->GetLevelName();
|
break;
|
||||||
std::string prvlvlname(prevlvlname);
|
}
|
||||||
if (boost::contains(prvlvlname, "pl_") ||
|
});
|
||||||
boost::contains(prvlvlname, "cp_"))
|
|
||||||
{
|
|
||||||
logging::Info("1");
|
|
||||||
bool ret = false;
|
|
||||||
if (lagexploit::pointarr[0] || lagexploit::pointarr[1] ||
|
|
||||||
lagexploit::pointarr[2] || lagexploit::pointarr[3] ||
|
|
||||||
lagexploit::pointarr[4])
|
|
||||||
{
|
|
||||||
hacks::shared::followbot::followbot = 1;
|
|
||||||
hacks::shared::followbot::roambot = 1;
|
|
||||||
hacks::shared::followbot::followcart = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hacks::shared::followbot::followbot = 0;
|
|
||||||
hacks::shared::followbot::roambot = 0;
|
|
||||||
hacks::shared::followbot::followcart = false;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
if (nodes.size() == 0)
|
|
||||||
return;
|
|
||||||
if (force_slot)
|
|
||||||
UpdateSlot();
|
|
||||||
UpdateWalker();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace hacks::shared::walkbot
|
} // namespace hacks::shared::walkbot
|
||||||
|
@ -109,7 +109,13 @@ static int attackticks = 0;
|
|||||||
|
|
||||||
namespace hooked_methods
|
namespace hooked_methods
|
||||||
{
|
{
|
||||||
|
static HookedFunction viewangs(HookedFunctions_types::HF_CreateMove, "set_ang",
|
||||||
|
21, []() {
|
||||||
|
if (CE_BAD(LOCAL_E))
|
||||||
|
return;
|
||||||
|
g_pLocalPlayer->v_OrigViewangles =
|
||||||
|
current_user_cmd->viewangles;
|
||||||
|
});
|
||||||
DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time,
|
DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time,
|
||||||
CUserCmd *cmd)
|
CUserCmd *cmd)
|
||||||
{
|
{
|
||||||
@ -249,9 +255,6 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time,
|
|||||||
g_pLocalPlayer->Update();
|
g_pLocalPlayer->Update();
|
||||||
}
|
}
|
||||||
g_Settings.bInvalid = false;
|
g_Settings.bInvalid = false;
|
||||||
|
|
||||||
hacks::shared::autojoin::update();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
PROF_SECTION(CM_AAA);
|
PROF_SECTION(CM_AAA);
|
||||||
hacks::shared::anti_anti_aim::createMove();
|
hacks::shared::anti_anti_aim::createMove();
|
||||||
@ -261,45 +264,11 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time,
|
|||||||
PROF_SECTION(CM_WRAPPER);
|
PROF_SECTION(CM_WRAPPER);
|
||||||
HookTools::CM();
|
HookTools::CM();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_IPC
|
|
||||||
#if !LAGBOT_MODE
|
|
||||||
if (hacks::shared::followbot::isEnabled())
|
|
||||||
{
|
|
||||||
hacks::shared::followbot::WorldTick();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
if (CE_GOOD(g_pLocalPlayer->entity))
|
if (CE_GOOD(g_pLocalPlayer->entity))
|
||||||
{
|
{
|
||||||
#if !LAGBOT_MODE
|
|
||||||
IF_GAME(IsTF2())
|
|
||||||
{
|
|
||||||
UpdateHoovyList();
|
|
||||||
}
|
|
||||||
g_pLocalPlayer->v_OrigViewangles = cmd->viewangles;
|
|
||||||
#if ENABLE_VISUALS
|
|
||||||
{
|
|
||||||
PROF_SECTION(CM_esp);
|
|
||||||
hacks::shared::esp::CreateMove();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
if (!g_pLocalPlayer->life_state && CE_GOOD(g_pLocalPlayer->weapon()))
|
if (!g_pLocalPlayer->life_state && CE_GOOD(g_pLocalPlayer->weapon()))
|
||||||
{
|
{
|
||||||
#if !LAGBOT_MODE
|
#if !LAGBOT_MODE
|
||||||
{
|
|
||||||
PROF_SECTION(CM_walkbot);
|
|
||||||
hacks::shared::walkbot::Move();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
PROF_SECTION(CM_navparse);
|
|
||||||
nav::CreateMove();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
PROF_SECTION(CM_navbot);
|
|
||||||
hacks::tf2::NavBot::CreateMove();
|
|
||||||
}
|
|
||||||
// Walkbot can leave game.
|
// Walkbot can leave game.
|
||||||
if (!g_IEngine->IsInGame())
|
if (!g_IEngine->IsInGame())
|
||||||
{
|
{
|
||||||
|
37
src/hoovy.cpp
Executable file → Normal file
37
src/hoovy.cpp
Executable file → Normal file
@ -37,28 +37,31 @@ bool IsHoovyHelper(CachedEntity *entity)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateHoovyList()
|
static HookedFunction UpdateHoovyList(
|
||||||
{
|
HookedFunctions_types::HF_CreateMove, "HoovyList", 19, []() {
|
||||||
static CachedEntity *ent;
|
if (CE_BAD(LOCAL_E))
|
||||||
|
return;
|
||||||
|
|
||||||
for (int i = 1; i < 32 && i < g_IEntityList->GetHighestEntityIndex(); i++)
|
static CachedEntity *ent;
|
||||||
{
|
for (int i = 1; i < 32 && i < g_IEntityList->GetHighestEntityIndex();
|
||||||
ent = ENTITY(i);
|
i++)
|
||||||
if (CE_GOOD(ent) && CE_BYTE(ent, netvar.iLifeState) == LIFE_ALIVE)
|
|
||||||
{
|
{
|
||||||
if (!hoovy_list[i - 1])
|
ent = ENTITY(i);
|
||||||
|
if (CE_GOOD(ent) && CE_BYTE(ent, netvar.iLifeState) == LIFE_ALIVE)
|
||||||
{
|
{
|
||||||
if (IsHoovyHelper(ent))
|
if (!hoovy_list[i - 1])
|
||||||
hoovy_list[i - 1] = true;
|
{
|
||||||
}
|
if (IsHoovyHelper(ent))
|
||||||
else
|
hoovy_list[i - 1] = true;
|
||||||
{
|
}
|
||||||
if (!HasSandvichOut(ent))
|
else
|
||||||
hoovy_list[i - 1] = false;
|
{
|
||||||
|
if (!HasSandvichOut(ent))
|
||||||
|
hoovy_list[i - 1] = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
bool IsHoovy(CachedEntity *entity)
|
bool IsHoovy(CachedEntity *entity)
|
||||||
{
|
{
|
||||||
|
@ -367,78 +367,78 @@ void Repath()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Main movement function, gets path from NavTo
|
// Main movement function, gets path from NavTo
|
||||||
void CreateMove()
|
static HookedFunction
|
||||||
{
|
CreateMove(HookedFunctions_types::HF_CreateMove, "NavParser", 17, []() {
|
||||||
if (!enabled || !threadingFinished.load())
|
if (!enabled || !threadingFinished.load())
|
||||||
return;
|
return;
|
||||||
if (CE_BAD(LOCAL_E))
|
if (CE_BAD(LOCAL_E))
|
||||||
return;
|
return;
|
||||||
if (!LOCAL_E->m_bAlivePlayer())
|
if (!LOCAL_E->m_bAlivePlayer())
|
||||||
{
|
{
|
||||||
// Clear path if player dead
|
// Clear path if player dead
|
||||||
crumbs.clear();
|
crumbs.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ignoreManagerCM();
|
ignoreManagerCM();
|
||||||
// Crumbs empty, prepare for next instruction
|
// Crumbs empty, prepare for next instruction
|
||||||
if (crumbs.empty())
|
if (crumbs.empty())
|
||||||
{
|
{
|
||||||
priority = 0;
|
priority = 0;
|
||||||
ReadyForCommands = true;
|
ReadyForCommands = true;
|
||||||
ensureArrival = false;
|
ensureArrival = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ReadyForCommands = false;
|
ReadyForCommands = false;
|
||||||
// Remove old crumbs
|
// Remove old crumbs
|
||||||
if (g_pLocalPlayer->v_Origin.DistTo(Vector{ crumbs.at(0).x, crumbs.at(0).y,
|
if (g_pLocalPlayer->v_Origin.DistTo(Vector{
|
||||||
g_pLocalPlayer->v_Origin.z }) <
|
crumbs.at(0).x, crumbs.at(0).y, g_pLocalPlayer->v_Origin.z }) <
|
||||||
30.0f)
|
30.0f)
|
||||||
{
|
{
|
||||||
lastArea = crumbs.at(0);
|
lastArea = crumbs.at(0);
|
||||||
crumbs.erase(crumbs.begin());
|
crumbs.erase(crumbs.begin());
|
||||||
inactivity.update();
|
inactivity.update();
|
||||||
}
|
}
|
||||||
if (crumbs.empty())
|
if (crumbs.empty())
|
||||||
return;
|
return;
|
||||||
// Detect when jumping is necessary
|
// Detect when jumping is necessary
|
||||||
if (crumbs.at(0).z - g_pLocalPlayer->v_Origin.z > 18 &&
|
if (crumbs.at(0).z - g_pLocalPlayer->v_Origin.z > 18 &&
|
||||||
lastJump.test_and_set(200))
|
lastJump.test_and_set(200))
|
||||||
current_user_cmd->buttons |= IN_JUMP;
|
current_user_cmd->buttons |= IN_JUMP;
|
||||||
// Check if were dealing with a type 2 connection
|
// Check if were dealing with a type 2 connection
|
||||||
if (inactivity.check(3000) &&
|
if (inactivity.check(3000) &&
|
||||||
TF2MAP->inactiveTracker.CheckType2({ lastArea, crumbs.at(0) }))
|
TF2MAP->inactiveTracker.CheckType2({ lastArea, crumbs.at(0) }))
|
||||||
{
|
{
|
||||||
logging::Info("Pathing: Type 2 connection detected!");
|
logging::Info("Pathing: Type 2 connection detected!");
|
||||||
TF2MAP->pather->Reset();
|
|
||||||
Repath();
|
|
||||||
inactivity.update();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Check for new sentries
|
|
||||||
if (sentryCheck.test_and_set(1000) &&
|
|
||||||
TF2MAP->inactiveTracker.ShouldCancelPath(crumbs))
|
|
||||||
{
|
|
||||||
logging::Info("Pathing: New Sentry found!");
|
|
||||||
TF2MAP->pather->Reset();
|
|
||||||
Repath();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// If inactive for too long
|
|
||||||
if (inactivity.check(5000))
|
|
||||||
{
|
|
||||||
// Ignore connection
|
|
||||||
bool resetPather = false;
|
|
||||||
TF2MAP->inactiveTracker.AddTime({ lastArea, crumbs.at(0) }, inactivity,
|
|
||||||
resetPather);
|
|
||||||
if (resetPather)
|
|
||||||
TF2MAP->pather->Reset();
|
TF2MAP->pather->Reset();
|
||||||
Repath();
|
Repath();
|
||||||
inactivity.update();
|
inactivity.update();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Walk to next crumb
|
// Check for new sentries
|
||||||
WalkTo(crumbs.at(0));
|
if (sentryCheck.test_and_set(1000) &&
|
||||||
}
|
TF2MAP->inactiveTracker.ShouldCancelPath(crumbs))
|
||||||
|
{
|
||||||
|
logging::Info("Pathing: New Sentry found!");
|
||||||
|
TF2MAP->pather->Reset();
|
||||||
|
Repath();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If inactive for too long
|
||||||
|
if (inactivity.check(5000))
|
||||||
|
{
|
||||||
|
// Ignore connection
|
||||||
|
bool resetPather = false;
|
||||||
|
TF2MAP->inactiveTracker.AddTime({ lastArea, crumbs.at(0) },
|
||||||
|
inactivity, resetPather);
|
||||||
|
if (resetPather)
|
||||||
|
TF2MAP->pather->Reset();
|
||||||
|
Repath();
|
||||||
|
inactivity.update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Walk to next crumb
|
||||||
|
WalkTo(crumbs.at(0));
|
||||||
|
});
|
||||||
|
|
||||||
void Draw()
|
void Draw()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user