Make NavBot alpha 2

This commit is contained in:
LightCat 2018-10-27 12:33:54 +02:00
parent 26618cd53b
commit bb37041c18
8 changed files with 358 additions and 29 deletions

View File

@ -1,6 +1,24 @@
#include "common.hpp"
namespace hacks::shared::NavBot
{
// Main Functions
void Init(bool from_LevelInit);
// Helper
bool CanPath();
bool HasLowHealth();
bool HasLowAmmo();
CachedEntity *nearestHealth();
CachedEntity *nearestAmmo();
CachedEntity *nearestEnemy();
Vector GetClosestValidByDist(CachedEntity *ent, float mindist, float maxdist, bool near);
void UpdateSlot();
void Jump();
// Path
bool NavToSniperSpot(int priority);
}
bool NavToNearestEnemy();
} // namespace hacks::shared::NavBot

View File

@ -19,13 +19,15 @@ extern std::unique_ptr<CNavFile> navfile;
// Current path priority
extern int curr_priority;
// Check if ready to recieve another NavTo (to avoid overwriting of instructions)
// Check if ready to recieve another NavTo (to avoid overwriting of
// instructions)
extern bool ReadyForCommands;
// Ignore. For level init only
extern std::atomic<init_status> status;
// Nav to vector
bool navTo(Vector destination, int priority = 5, bool should_repath = true, bool nav_to_local = true, bool is_repath = false);
bool navTo(Vector destination, int priority = 5, bool should_repath = true,
bool nav_to_local = true, bool is_repath = false);
// Check and init navparser
bool prepare();
// Clear current path

View File

@ -1061,7 +1061,8 @@ int BestHitbox(CachedEntity *target)
if (CanHeadshot() &&
(std::floor(cdmg) >= target->m_iHealth() ||
IsPlayerCritBoosted(g_pLocalPlayer->entity) ||
!g_pLocalPlayer->bZoomed || target->m_iHealth() <= std::floor(bdmg)) &&
!g_pLocalPlayer->bZoomed ||
target->m_iHealth() <= std::floor(bdmg)) &&
target->m_iHealth() <= 150)
{
// We dont need to hit the head as a bodyshot will kill

View File

@ -1,16 +1,34 @@
#include "common.hpp"
#include "NavBot.hpp"
#include "PlayerTools.hpp"
#include "navparser.hpp"
#include "settings/Bool.hpp"
#include "settings/Float.hpp"
#include "HookedMethods.hpp"
// Rvars
static settings::Bool enable{ "navbot.enable", "false" };
static settings::Bool sniper_mode{ "navbot.sniper-mode", "true" };
static settings::Bool heavy_mode{ "navbot.heavy-mode", "false" };
static settings::Bool scout_mode{ "navbot.scout-mode", "false" };
static settings::Float jump_trigger{ "navbot.jump-distance", "500.0f" };
static settings::Bool spy_mode{ "navbot.spy-mode", "false" };
static settings::Bool stay_near{ "navbot.stay-near", "true" };
static settings::Bool path_health{ "navbot.path-health", "true" };
static settings::Bool path_ammo{ "navbot.path-ammo", "true" };
static settings::Bool pick_optimal_slot{ "navbot.best-slot", "true" };
// Timers
static Timer general_cooldown{};
static Timer init_cooldown{};
static Timer path_health_cooldown{};
static Timer path_ammo_cooldown{};
static Timer refresh_nearest_target{};
static Timer refresh_nearest_valid_vector{};
static Timer nav_to_nearest_enemy_cooldown{};
static Timer slot_timer{};
static Timer non_sniper_sniper_nav_cooldown{};
static Timer jump_cooldown{};
// Vectors
static std::vector<Vector *> default_spots{};
@ -27,6 +45,11 @@ namespace hacks::shared::NavBot
// Main Functions
void Init(bool from_LevelInit)
{
if (!*enable)
{
inited = false;
return;
}
if (from_LevelInit)
{
inited = false;
@ -53,37 +76,261 @@ void Init(bool from_LevelInit)
}
}
static HookedFunction CreateMove(HookedFunctions_types::HF_CreateMove, "NavBot", 10, [](){
static HookedFunction
CreateMove(HookedFunctions_types::HF_CreateMove, "NavBot", 10, []() {
// Master Switch
if (!*enable)
return;
// init pls
if (!inited)
{
if (init_cooldown.test_and_set(10000))
Init(false);
return;
}
// no nav file loaded/inited
if (!nav::prepare())
return;
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
return;
// Health and ammo have highest priority, but the stay near priorities has to be this high to override anything else
if (nav::curr_priority == 1337 && (HasLowAmmo() || HasLowHealth()))
nav::clearInstructions();
});
// Get health if low
if (path_health && HasLowHealth() &&
path_health_cooldown.test_and_set(500))
{
CachedEntity *health = nearestHealth();
if (CE_GOOD(health))
nav::navTo(health->m_vecOrigin(), 7, false, false);
}
// Get Ammo if low on ammo
if (path_ammo && HasLowAmmo() && path_ammo_cooldown.test_and_set(500))
{
CachedEntity *ammo = nearestAmmo();
if (CE_GOOD(ammo))
nav::navTo(ammo->m_vecOrigin(), 6, false, false);
}
// Stop pathing for ammo/Health if problem resolved
if ((!HasLowAmmo() && nav::curr_priority == 6) || ( nav::curr_priority == 7 && !HasLowHealth()))
nav::clearInstructions();
// If Zoning enabled then zone enemy
if (stay_near && nav_to_nearest_enemy_cooldown.test_and_set(100))
NavToNearestEnemy();
// Prevent path spam on sniper bots
if (CanPath())
{
if (sniper_mode)
NavToSniperSpot(5);
else if ((*heavy_mode || scout_mode) && nav_to_nearest_enemy_cooldown.test_and_set(100))
if (!NavToNearestEnemy() && non_sniper_sniper_nav_cooldown.test_and_set(10000))
NavToSniperSpot(5);
}
if (*pick_optimal_slot)
UpdateSlot();
if (*scout_mode)
Jump();
});
// Helpers
bool CanPath()
{
if ((*heavy_mode || *spy_mode) && general_cooldown.test_and_set(100))
if ((*heavy_mode || *spy_mode || *scout_mode) && general_cooldown.test_and_set(100))
return true;
else
else if (sniper_mode)
{
if (nav::ReadyForCommands && general_cooldown.test_and_set(100))
return true;
return false;
}
return false;
}
bool HasLowHealth()
{
return float(LOCAL_E->m_iHealth()) / float(LOCAL_E->m_iMaxHealth()) < 0.64;
}
bool HasLowAmmo()
{
int *weapon_list =
(int *) ((unsigned) (RAW_ENT(LOCAL_E)) + netvar.hMyWeapons);
if (g_pLocalPlayer->holding_sniper_rifle &&
CE_INT(LOCAL_E, netvar.m_iAmmo + 4) <= 5)
return true;
for (int i = 0; weapon_list[i]; i++)
{
int handle = weapon_list[i];
int eid = handle & 0xFFF;
if (eid >= 32 && eid <= HIGHEST_ENTITY)
{
IClientEntity *weapon = g_IEntityList->GetClientEntity(eid);
if (weapon and re::C_BaseCombatWeapon::IsBaseCombatWeapon(weapon) &&
re::C_TFWeaponBase::UsesPrimaryAmmo(weapon) &&
!re::C_TFWeaponBase::HasPrimaryAmmo(weapon))
return true;
}
}
return false;
}
CachedEntity *nearestHealth()
{
float bestscr = FLT_MAX;
CachedEntity *bestent = nullptr;
for (int i = 0; i < HIGHEST_ENTITY; i++)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent) || ent->m_iClassID() != CL_CLASS(CBaseAnimating))
continue;
if (ent->m_ItemType() != ITEM_HEALTH_SMALL &&
ent->m_ItemType() != ITEM_HEALTH_MEDIUM &&
ent->m_ItemType() != ITEM_HEALTH_LARGE)
continue;
if (ent->m_flDistance() < bestscr)
{
bestscr = ent->m_flDistance();
bestent = ent;
}
}
return bestent;
}
CachedEntity *nearestAmmo()
{
float bestscr = FLT_MAX;
CachedEntity *bestent = nullptr;
for (int i = 0; i < HIGHEST_ENTITY; i++)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent) || ent->m_iClassID() != CL_CLASS(CBaseAnimating))
continue;
if (ent->m_ItemType() != ITEM_AMMO_SMALL &&
ent->m_ItemType() != ITEM_AMMO_MEDIUM &&
ent->m_ItemType() != ITEM_AMMO_LARGE)
continue;
if (ent->m_flDistance() < bestscr)
{
bestscr = ent->m_flDistance();
bestent = ent;
}
}
return bestent;
}
static int last_target = -1;
CachedEntity *nearestEnemy()
{
if (refresh_nearest_target.test_and_set(3000))
{
CachedEntity *best_tar = nullptr;
float best_dist = FLT_MAX;
for (int i = 0; i < g_IEngine->GetMaxClients(); i++)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent) || !ent->m_bAlivePlayer() || !ent->m_bEnemy() ||
ent == LOCAL_E ||
player_tools::shouldTarget(ent) !=
player_tools::IgnoreReason::DO_NOT_IGNORE)
continue;
if (ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin()) < best_dist)
{
best_dist = ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin());
best_tar = ent;
}
}
if (CE_GOOD(best_tar))
{
last_target = best_tar->m_IDX;
return best_tar;
}
else
{
last_target = -1;
return nullptr;
}
}
else
{
if (last_target == -1)
return nullptr;
else
{
CachedEntity *ent = ENTITY(last_target);
if (CE_BAD(ent) || !ent->m_bAlivePlayer() || !ent->m_bEnemy() ||
ent == LOCAL_E ||
player_tools::shouldTarget(ent) !=
player_tools::IgnoreReason::DO_NOT_IGNORE)
{
last_target = -1;
return nullptr;
}
else
return ent;
}
}
}
static Vector cached_vector{0.0f, 0.0f, 0.0f};
static Vector empty{0.0f, 0.0f, 0.0f};
Vector GetClosestValidByDist(CachedEntity *ent, float mindist, float maxdist, bool near)
{
if (refresh_nearest_valid_vector.test_and_set(100))
{
if (CE_BAD(ent))
return empty;
Vector best_area{0.0f, 0.0f, 0.0f};
float best_dist = near ? FLT_MAX : 0.0f;
for (auto &i : nav::navfile->m_areas)
{
Vector center = i.m_center;
float dist = center.DistTo(ent->m_vecOrigin());
// Check if wihin the range specified
if (dist > maxdist || dist < mindist)
continue;
// We want to be standing the closest to them possible, besides as a sniper
if ((near && dist > best_dist) || (!near && dist < best_dist))
continue;
// Anti stuck in ground stuff
Vector zcheck = center;
zcheck.z += 48;
// Anti stuck in ground
Vector zent = ent->m_vecOrigin();
zent += 48;
if (!IsVectorVisible(zcheck, zent, false))
continue;
best_area = i.m_center;
best_dist = dist;
}
if (best_area.IsValid() && best_area.z )
{
cached_vector = best_area;
return best_area;
}
return empty;
}
// We Want a bit of caching
else
return cached_vector;
}
// Navigation
bool NavToSniperSpot(int priority)
{
// Already pathing currently and priority is below the wanted, so just return
// Already pathing currently and priority is below the wanted, so just
// return
if (priority < nav::curr_priority)
return true;
// Preferred yay or nay?
@ -91,7 +338,8 @@ bool NavToSniperSpot(int priority)
if (!use_preferred && default_spots.empty())
return false;
std::vector<Vector *> *sniper_spots = use_preferred ? &preferred_spots : &default_spots;
std::vector<Vector *> *sniper_spots =
use_preferred ? &preferred_spots : &default_spots;
// Wtf Nullptr!
if (!sniper_spots)
@ -129,7 +377,7 @@ bool NavToSniperSpot(int priority)
// Score of the match
float score = match->DistTo(LOCAL_E->m_vecOrigin());
if ( score < min_dist)
if (score < min_dist)
{
min_dist = score;
best_spot = idx;
@ -155,4 +403,61 @@ bool NavToSniperSpot(int priority)
return nav::navTo(*random_spot, priority);
}
}
bool CanNavToNearestEnemy()
{
if (HasLowAmmo() || HasLowHealth())
return false;
return true;
}
bool NavToNearestEnemy()
{
CachedEntity *ent = nearestEnemy();
if (CE_BAD(ent))
return false;
if (nav::curr_priority == 6 || nav::curr_priority == 7)
return false;
float min_dist = 800.0f;
float max_dist = 4000.0f;
bool stay_near = *sniper_mode ? false : true;
if (*heavy_mode || *scout_mode)
{
min_dist = 100.0f;
max_dist = 1000.0f;
}
Vector to_nav = GetClosestValidByDist(ent, min_dist, max_dist, stay_near);
if (to_nav.z)
return nav::navTo(to_nav, 1337, false, false);
return false;
}
void UpdateSlot()
{
if (!slot_timer.test_and_set(1000))
return;
if (CE_GOOD(LOCAL_E) && CE_GOOD(LOCAL_W) && !g_pLocalPlayer->life_state)
{
IClientEntity *weapon = RAW_ENT(LOCAL_W);
// IsBaseCombatWeapon()
if (re::C_BaseCombatWeapon::IsBaseCombatWeapon(weapon))
{
int slot = re::C_BaseCombatWeapon::GetSlot(weapon);
int newslot = 1;
if (*spy_mode)
newslot = 3;
if (slot != newslot - 1)
g_IEngine->ClientCmd_Unrestricted(
format("slot", newslot).c_str());
}
}
}
void Jump()
{
CachedEntity *ent = nearestEnemy();
if (CE_BAD(ent))
return;
if (ent->m_flDistance() < *jump_trigger && jump_cooldown.test_and_set(200))
current_user_cmd->buttons |= IN_JUMP;
}
} // namespace hacks::shared::NavBot

View File

@ -275,8 +275,8 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time,
if (firstcm)
{
DelayTimer.update();
// hacks::tf2::NavBot::Init();
// hacks::tf2::NavBot::initonce();
// hacks::tf2::NavBot::Init();
// hacks::tf2::NavBot::initonce();
nav::status = nav::off;
IRC::auth();
hacks::shared::NavBot::Init(true);

View File

@ -57,7 +57,7 @@ DEFINE_HOOKED_METHOD(LevelInit, void, void *this_, const char *name)
hacks::shared::backtrack::sequences.clear();
#endif
firstcm = true;
//nav::init = false;
// nav::init = false;
#if !LAGBOT_MODE
playerlist::Save();
#endif

View File

@ -506,7 +506,9 @@ static HookedFunction
if (crumbs.empty())
return;
// Detect when jumping is necessary
if ((!(g_pLocalPlayer->holding_sniper_rifle && g_pLocalPlayer->bZoomed) && crumbs.at(0).z - g_pLocalPlayer->v_Origin.z > 18 &&
if ((!(g_pLocalPlayer->holding_sniper_rifle &&
g_pLocalPlayer->bZoomed) &&
crumbs.at(0).z - g_pLocalPlayer->v_Origin.z > 18 &&
last_jump.test_and_set(200)) ||
(last_jump.test_and_set(200) && inactivity.check(3000)))
current_user_cmd->buttons |= IN_JUMP;

View File

@ -174,7 +174,8 @@ bool gui::handleSdlEvent(SDL_Event *event)
}
zerokernel::Menu::instance->handleSdlEvent(event);
if (!zerokernel::Menu::instance->isInGame() &&
(event->type == SDL_MOUSEBUTTONDOWN || event->type == SDL_TEXTINPUT || event->type == SDL_KEYDOWN))
(event->type == SDL_MOUSEBUTTONDOWN || event->type == SDL_TEXTINPUT ||
event->type == SDL_KEYDOWN))
return true;
else
return false;