Start Converting CreateMove's

This commit is contained in:
LightCat 2018-09-15 16:52:09 +02:00
parent d4bc116a57
commit 86f854dac6
15 changed files with 974 additions and 986 deletions

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -9,5 +9,4 @@
class CachedEntity; class CachedEntity;
void UpdateHoovyList();
bool IsHoovy(CachedEntity *entity); bool IsHoovy(CachedEntity *entity);

View File

@ -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);

View File

@ -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()
{ {

View File

@ -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" };

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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)
{ {

View File

@ -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()
{ {