Add Engineer Bot support (#1524)

* readd engiebot to navbot, WIP

* Slot changes for engie

* Fix some Engi Bot problems

Co-authored-by: aUniqueUser <ds458@pm.me>
This commit is contained in:
LightCat 2021-08-10 13:29:07 +02:00 committed by GitHub
parent 1359e37131
commit b6a0b65c72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 473 additions and 86 deletions

View File

@ -17,6 +17,7 @@ enum Priority_list
ammo,
capture,
prio_melee,
engineer,
health,
danger,
};
@ -36,6 +37,7 @@ enum BlacklistReason_enum
STICKY,
ENEMY_NORMAL,
ENEMY_DORMANT,
BAD_BUILDING_SPOT,
// Always last
BLACKLIST_LENGTH
};

View File

@ -12,6 +12,7 @@
#include "Aimbot.hpp"
#include "navparser.hpp"
#include "MiscAimbot.hpp"
#include "Misc.hpp"
namespace hacks::tf2::NavBot
{
@ -33,6 +34,7 @@ static settings::Int blacklist_delay("navbot.proximity-blacklist.delay", "500");
static settings::Boolean blacklist_dormat("navbot.proximity-blacklist.dormant", "false");
static settings::Int blacklist_delay_dormat("navbot.proximity-blacklist.delay-dormant", "1000");
static settings::Int blacklist_slightdanger_limit("navbot.proximity-blacklist.slight-danger.amount", "2");
static settings::Boolean engie_mode("navbot.engineer-mode", "true");
#if ENABLE_VISUALS
static settings::Boolean draw_danger("navbot.draw-danger", "false");
#endif
@ -53,16 +55,20 @@ struct bot_class_config
bool prefer_far;
};
constexpr bot_class_config CONFIG_SHORT_RANGE = { 140.0f, 400.0f, 600.0f, false };
constexpr bot_class_config CONFIG_MID_RANGE = { 200.0f, 500.0f, 3000.0f, true };
constexpr bot_class_config CONFIG_LONG_RANGE = { 300.0f, 500.0f, 4000.0f, true };
bot_class_config selected_config = CONFIG_MID_RANGE;
constexpr bot_class_config CONFIG_SHORT_RANGE = { 140.0f, 400.0f, 600.0f, false };
constexpr bot_class_config CONFIG_MID_RANGE = { 200.0f, 500.0f, 3000.0f, true };
constexpr bot_class_config CONFIG_LONG_RANGE = { 300.0f, 500.0f, 4000.0f, true };
constexpr bot_class_config CONFIG_ENGINEER = { 200.0f, 500.0f, 3000.0f, false };
constexpr bot_class_config CONFIG_GUNSLINGER_ENGINEER = { 50.0f, 300.0f, 2000.0f, false };
bot_class_config selected_config = CONFIG_MID_RANGE;
static Timer health_cooldown{};
static Timer ammo_cooldown{};
// Should we search health at all?
bool shouldSearchHealth(bool low_priority = false)
{
if (!search_health)
return false;
// Check if being gradually healed in any way
if (HasCondition<TFCond_Healing>(LOCAL_E))
return false;
@ -78,13 +84,15 @@ bool shouldSearchHealth(bool low_priority = false)
// Should we search ammo at all?
bool shouldSearchAmmo()
{
if (!search_ammo)
return false;
if (CE_BAD(LOCAL_W))
return false;
// Priority too high
if (navparser::NavEngine::current_priority > ammo)
return false;
int *weapon_list = (int *) ((uint64_t)(RAW_ENT(LOCAL_E)) + netvar.hMyWeapons);
int *weapon_list = (int *) ((uint64_t) (RAW_ENT(LOCAL_E)) + netvar.hMyWeapons);
if (!weapon_list)
return false;
if (g_pLocalPlayer->holding_sniper_rifle && CE_INT(LOCAL_E, netvar.m_iAmmo + 4) <= 5)
@ -188,12 +196,13 @@ bool getHealth(bool low_priority = false)
return false;
}
static bool was_force = false;
// Find ammo if needed
bool getAmmo()
bool getAmmo(bool force = false)
{
if (!ammo_cooldown.check(1000))
if (!force && !ammo_cooldown.check(1000))
return navparser::NavEngine::current_priority == ammo;
if (shouldSearchAmmo())
if (force || shouldSearchAmmo())
{
// Already pathing, only try to repath every 2s
if (navparser::NavEngine::current_priority == ammo)
@ -202,6 +211,8 @@ bool getAmmo()
if (!repath_timer.test_and_set(2000))
return true;
}
else
was_force = false;
auto ammopacks = getEntities({ ITEM_AMMO_SMALL, ITEM_AMMO_MEDIUM, ITEM_AMMO_LARGE });
auto dispensers = getDispensers();
@ -217,10 +228,13 @@ bool getAmmo()
for (auto ammopack : total_ents)
// If we succeeed, don't try to path to other packs
if (navparser::NavEngine::navTo(ammopack->m_vecOrigin(), ammo, true, ammopack->m_vecOrigin().DistToSqr(g_pLocalPlayer->v_Origin) > 200.0f * 200.0f))
{
was_force = force;
return true;
}
ammo_cooldown.update();
}
else if (navparser::NavEngine::current_priority == ammo)
else if (navparser::NavEngine::current_priority == ammo && !was_force)
navparser::NavEngine::cancelPath();
return false;
}
@ -245,6 +259,199 @@ void refreshSniperSpots()
sniper_spots.emplace_back(hiding_spot.m_pos);
}
static std::pair<CachedEntity *, float> getNearestPlayerDistance()
{
float distance = FLT_MAX;
CachedEntity *best_ent = nullptr;
for (int i = 1; i <= g_IEngine->GetMaxClients(); i++)
{
CachedEntity *ent = ENTITY(i);
if (CE_VALID(ent) && ent->m_vecDormantOrigin() && ent->m_bAlivePlayer() && ent->m_bEnemy() && g_pLocalPlayer->v_Origin.DistTo(ent->m_vecOrigin()) < distance && player_tools::shouldTarget(ent) && !IsPlayerInvisible(ent))
{
distance = g_pLocalPlayer->v_Origin.DistTo(*ent->m_vecDormantOrigin());
best_ent = ent;
}
}
return { best_ent, distance };
}
static std::vector<Vector> building_spots;
inline bool HasGunslinger(CachedEntity *ent)
{
return HasWeapon(ent, 142);
}
inline bool isEngieMode()
{
return *engie_mode && g_pLocalPlayer->clazz == tf_engineer;
}
bool BlacklistedFromBuilding(CNavArea *area)
{
// FIXME: Better way of doing this ?
for (auto blacklisted_area : *navparser::NavEngine::getFreeBlacklist())
{
if (blacklisted_area.first == area && blacklisted_area.second.value == navparser::BlacklistReason_enum::BAD_BUILDING_SPOT)
return true;
}
return false;
}
static Timer refresh_buildingspots_timer;
void refreshBuildingSpots(bool force = false)
{
if (!isEngieMode())
return;
if (force || refresh_buildingspots_timer.test_and_set(HasGunslinger(LOCAL_E) ? 1000 : 5000))
{
building_spots.clear();
std::optional<Vector> target;
auto our_flag = flagcontroller::getFlag(g_pLocalPlayer->team);
target = our_flag.spawn_pos;
if (!target)
{
auto nearest = getNearestPlayerDistance();
if (CE_GOOD(nearest.first))
target = *nearest.first->m_vecDormantOrigin();
if (!target)
target = LOCAL_E->m_vecOrigin();
}
if (target)
{
// Search all nav areas for valid spots
for (auto &area : navparser::NavEngine::getNavFile()->m_areas)
{
// Blacklisted :(
if (BlacklistedFromBuilding(&area))
continue;
// BUG Ahead, these flag checks dont seem to work for me :/
// Don't try to build in spawn lol
if ((area.m_TFattributeFlags & TF_NAV_SPAWN_ROOM_RED) != 0 || (area.m_TFattributeFlags & TF_NAV_SPAWN_ROOM_BLUE) != 0 || (area.m_TFattributeFlags & TF_NAV_SPAWN_ROOM_EXIT) != 0)
continue;
if ((area.m_TFattributeFlags & TF_NAV_SENTRY_SPOT) != 0)
building_spots.emplace_back(area.m_center);
else
{
for (auto &hiding_spot : area.m_hidingSpots)
if (hiding_spot.HasGoodCover())
building_spots.emplace_back(hiding_spot.m_pos);
}
}
// Sort by distance to nearest, lower is better
// TODO: This isnt really optimal, need a dif way to where it is a good distance from enemies but also bots dont build in the same spot
std::sort(building_spots.begin(), building_spots.end(),
[target](Vector a, Vector b)
{
if (!HasGunslinger(LOCAL_E))
{
auto a_dist = a.DistTo(*target);
auto b_dist = b.DistTo(*target);
// Penalty for being in danger ranges
if (a_dist + 100.0f < selected_config.min_full_danger)
a_dist += 4000.0f;
if (b_dist + 100.0f < selected_config.min_full_danger)
b_dist += 4000.0f;
if (a_dist + 1000.0f < selected_config.min_slight_danger)
a_dist += 1500.0f;
if (b_dist + 1000.0f < selected_config.min_slight_danger)
b_dist += 1500.0f;
return a_dist < b_dist;
}
else
return a.DistTo(*target) < b.DistTo(*target);
});
}
}
}
static CachedEntity *mySentry = nullptr;
static CachedEntity *myDispenser = nullptr;
void refreshLocalBuildings()
{
if (isEngieMode())
{
mySentry = nullptr;
myDispenser = nullptr;
if (CE_GOOD(LOCAL_E))
{
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
{
CachedEntity *ent = ENTITY(i);
if (!ent || CE_BAD(ent) || ent->m_bEnemy() || !ent->m_bAlivePlayer())
continue;
auto cid = ent->m_iClassID();
if (cid != CL_CLASS(CObjectSentrygun) && cid != CL_CLASS(CObjectDispenser))
continue;
if (HandleToIDX(CE_INT(ent, netvar.m_hBuilder)) != LOCAL_E->m_IDX)
continue;
if (CE_INT(ent, netvar.m_bPlacing))
continue;
if (cid == CL_CLASS(CObjectSentrygun))
mySentry = ent;
else if (cid == CL_CLASS(CObjectDispenser))
myDispenser = ent;
}
}
}
}
static Vector current_building_spot;
static bool navToSentrySpot()
{
static Timer wait_until_path_sentry;
// Wait a bit before pathing again
if (!wait_until_path_sentry.test_and_set(300))
return false;
// Try to nav to our existing sentry spot
if (CE_GOOD(mySentry) && mySentry->m_bAlivePlayer() && mySentry->m_vecDormantOrigin())
{
// Don't overwrite current nav
if (navparser::NavEngine::current_priority == engineer)
return true;
if (navparser::NavEngine::navTo(*mySentry->m_vecDormantOrigin(), engineer))
return true;
}
else
mySentry = nullptr;
// No building spots
if (building_spots.empty())
return false;
// Don't overwrite current nav
if (navparser::NavEngine::current_priority == engineer)
return false;
// Max 10 attempts
for (int attempts = 0; attempts < 10 && attempts < building_spots.size(); ++attempts)
{
// Get a semi-random building spot to still keep distance preferrance
auto random_offset = RandomInt(0, std::min(3, (int) building_spots.size()));
Vector random;
// Wrap around
if (attempts - random_offset < 0)
random = building_spots[building_spots.size() + (attempts - random_offset)];
else
random = building_spots[attempts - random_offset];
// Try to nav there
if (navparser::NavEngine::navTo(random, engineer))
{
current_building_spot = random;
return true;
}
}
return false;
}
enum slots
{
primary = 1,
@ -754,6 +961,146 @@ bool snipeSentries()
return false;
}
enum building
{
dispenser = 0,
sentry = 2
};
static int build_attempts = 0;
static bool buildBuilding(int building)
{
// Blacklist this spot and refresh the building spots
if (build_attempts >= 15)
{
(*navparser::NavEngine::getFreeBlacklist())[navparser::NavEngine::findClosestNavSquare(g_pLocalPlayer->v_Origin)] = navparser::BlacklistReason_enum::BAD_BUILDING_SPOT;
refreshBuildingSpots(true);
current_building_spot.Invalidate();
build_attempts = 0;
return false;
}
// Make sure we have right amount of ammo
int required = (HasGunslinger(LOCAL_E) || building == dispenser) ? 100 : 130;
if (CE_INT(LOCAL_E, netvar.m_iAmmo + 12) < required)
return getAmmo(true);
// Try to build! we are close enough
if (current_building_spot.IsValid() && current_building_spot.DistTo(g_pLocalPlayer->v_Origin) <= (building == dispenser ? 500.0f : 200.0f))
{
// TODO: Rotate our angle to a valid building spot ? also rotate building itself to face enemies ?
current_user_cmd->viewangles.x = 20.0f;
current_user_cmd->viewangles.y += 2.0f;
// Gives us 4 1/2 seconds to build
static Timer attempt_timer;
if (attempt_timer.test_and_set(300))
build_attempts++;
if (hacks::shared::misc::getCarriedBuilding() == -1)
{
static Timer command_timer;
if (command_timer.test_and_set(100))
g_IEngine->ClientCmd_Unrestricted(strfmt("build %d", building).get());
}
else if (CE_INT(ENTITY(hacks::shared::misc::getCarriedBuilding()), netvar.m_bCanPlace))
current_user_cmd->buttons |= IN_ATTACK;
return true;
}
else
return navToSentrySpot();
return false;
}
static bool buildingNeedsToBeSmacked(CachedEntity *ent)
{
if (CE_BAD(ent))
return false;
if (CE_INT(ent, netvar.iUpgradeLevel) != 3 || ent->m_iHealth() / ent->m_iMaxHealth() <= 0.80f)
return true;
if (ent->m_iClassID() == CL_CLASS(CObjectSentrygun))
{
int max_ammo = 0;
switch (CE_INT(ent, netvar.iUpgradeLevel))
{
case 1:
max_ammo = 150;
break;
case 2:
case 3:
max_ammo = 200;
break;
}
return CE_INT(ent, netvar.m_iAmmoShells) / max_ammo <= 0.50f;
}
return false;
}
static bool smackBuilding(CachedEntity *ent)
{
if (CE_BAD(ent))
return false;
if (!CE_INT(LOCAL_E, netvar.m_iAmmo + 12))
return getAmmo(true);
if (ent->m_flDistance() <= 100.0f && g_pLocalPlayer->weapon_mode == weapon_melee)
{
AimAt(g_pLocalPlayer->v_Eye, GetBuildingPosition(ent), current_user_cmd);
current_user_cmd->buttons |= IN_ATTACK;
}
else if (navparser::NavEngine::current_priority != engineer)
return navparser::NavEngine::navTo(*ent->m_vecDormantOrigin(), engineer);
return true;
}
static bool runEngineerLogic()
{
if (!isEngieMode())
return false;
// Already have a sentry
if (CE_VALID(mySentry) && mySentry->m_bAlivePlayer())
{
if (HasGunslinger(LOCAL_E))
{
// Too far away, destroy it
// BUG Ahead, building isnt destroyed lol
if (mySentry->m_flDistance() >= 1800.0f)
{
// If we have a valid building
if (mySentry->m_Type() == CL_CLASS(CObjectSentrygun))
g_IEngine->ClientCmd_Unrestricted("destroy 2");
}
// Return false so we run another task
return false;
}
else
{
// Try to smack sentry first
if (buildingNeedsToBeSmacked(mySentry))
return smackBuilding(mySentry);
else
{
// We put dispenser by sentry
if (CE_BAD(myDispenser))
return buildBuilding(dispenser);
else
{
// We already have a dispenser, see if it needs to be smacked
if (buildingNeedsToBeSmacked(myDispenser))
return smackBuilding(myDispenser);
}
}
}
}
else
// Try to build a sentry
return buildBuilding(sentry);
return false;
}
enum capture_type
{
no_capture,
@ -928,7 +1275,7 @@ bool doRoam()
navparser::NavEngine::cancelPath();
return true;
}
if (navparser::NavEngine::navTo(*target, patrol))
if (navparser::NavEngine::navTo(*target, patrol, true, navparser::NavEngine::current_priority != patrol))
return true;
}
@ -970,9 +1317,12 @@ bool escapeDanger()
auto *local_nav = navparser::NavEngine::findClosestNavSquare(g_pLocalPlayer->v_Origin);
auto blacklist = navparser::NavEngine::getFreeBlacklist();
// In danger, try to run
// In danger, try to run (besides if it's a building spot, don't run away from that)
if (blacklist->find(local_nav) != blacklist->end())
{
if ((*blacklist)[local_nav].value == navparser::BlacklistReason_enum::BAD_BUILDING_SPOT)
return false;
static CNavArea *target_area = nullptr;
// Already running and our target is still valid
if (navparser::NavEngine::current_priority == danger && blacklist->find(target_area) == blacklist->end())
@ -1010,22 +1360,6 @@ bool escapeDanger()
return false;
}
static std::pair<CachedEntity *, float> getNearestPlayerDistance()
{
float distance = FLT_MAX;
CachedEntity *best_ent = nullptr;
for (int i = 1; i <= g_IEngine->GetMaxClients(); i++)
{
CachedEntity *ent = ENTITY(i);
if (CE_VALID(ent) && ent->m_vecDormantOrigin() && ent->m_bAlivePlayer() && ent->m_bEnemy() && g_pLocalPlayer->v_Origin.DistTo(ent->m_vecOrigin()) < distance && player_tools::shouldTarget(ent) && !IsPlayerInvisible(ent))
{
distance = g_pLocalPlayer->v_Origin.DistTo(*ent->m_vecDormantOrigin());
best_ent = ent;
}
}
return { best_ent, distance };
}
static int slot = primary;
static void autoJump(std::pair<CachedEntity *, float> &nearest)
@ -1091,6 +1425,20 @@ static slots getBestSlot(slots active_slot, std::pair<CachedEntity *, float> &ne
else
return primary;
}
case tf_engineer:
{
if (((CE_GOOD(mySentry) && mySentry->m_flDistance() <= 300) || (CE_GOOD(myDispenser) && myDispenser->m_flDistance() <= 500)) || (current_building_spot.IsValid() && current_building_spot.DistTo(g_pLocalPlayer->v_Origin) <= 500.0f))
{
if (active_slot >= melee && navparser::NavEngine::current_priority != prio_melee)
return active_slot;
else
return melee;
}
else if (nearest.second <= 500)
return primary;
else
return secondary;
}
default:
{
if (nearest.second <= 400)
@ -1129,6 +1477,8 @@ void CreateMove()
return;
refreshSniperSpots();
refreshLocalBuildings();
refreshBuildingSpots();
if (danger_config_custom)
{
@ -1143,6 +1493,9 @@ void CreateMove()
case tf_heavy:
selected_config = CONFIG_SHORT_RANGE;
break;
case tf_engineer:
selected_config = isEngieMode() ? HasGunslinger(LOCAL_E) ? CONFIG_GUNSLINGER_ENGINEER : CONFIG_ENGINEER : CONFIG_SHORT_RANGE;
break;
case tf_sniper:
selected_config = g_pLocalPlayer->weapon()->m_iClassID() == CL_CLASS(CTFCompoundBow) ? CONFIG_MID_RANGE : CONFIG_LONG_RANGE;
break;
@ -1166,6 +1519,9 @@ void CreateMove()
// If we aren't getting health, get ammo
else if (getAmmo())
return;
// Try to run engineer logic
else if (runEngineerLogic())
return;
else if (meleeAttack(slot, nearest))
return;
// Try to capture objectives
@ -1225,14 +1581,16 @@ void Draw()
}
#endif
static InitRoutine init([]() {
EC::Register(EC::CreateMove, CreateMove, "navbot_cm");
EC::Register(EC::CreateMoveWarp, CreateMove, "navbot_cm");
EC::Register(EC::LevelInit, LevelInit, "navbot_levelinit");
static InitRoutine init(
[]()
{
EC::Register(EC::CreateMove, CreateMove, "navbot_cm");
EC::Register(EC::CreateMoveWarp, CreateMove, "navbot_cm");
EC::Register(EC::LevelInit, LevelInit, "navbot_levelinit");
#if ENABLE_VISUALS
EC::Register(EC::Draw, Draw, "navbot_draw");
EC::Register(EC::Draw, Draw, "navbot_draw");
#endif
LevelInit();
});
LevelInit();
});
} // namespace hacks::tf2::NavBot

View File

@ -520,6 +520,8 @@ bool navTo(const Vector &destination, int priority, bool should_repath, bool nav
// Don't path, priority is too low
if (priority < current_priority)
return false;
if (log_pathing)
logging::Info("Priority: %d", priority);
CNavArea *start_area = map->findClosestNavSquare(g_pLocalPlayer->v_Origin);
CNavArea *dest_area = map->findClosestNavSquare(destination);
@ -630,6 +632,21 @@ static void followCrumbs()
if (!(entry <= 0.01f && entry >= -0.01f))
reset_z = false;
}
if (reset_z)
{
reset_z = false;
Ray_t ray;
trace_t trace;
Vector end = g_pLocalPlayer->v_Origin;
end.z -= 100.0f;
ray.Init(g_pLocalPlayer->v_Origin, end, RAW_ENT(LOCAL_E)->GetCollideable()->OBBMins(), RAW_ENT(LOCAL_E)->GetCollideable()->OBBMaxs());
g_ITrace->TraceRay(ray, MASK_PLAYERSOLID, &trace::filter_default, &trace);
// Only reset if we are standing on a building
if (trace.DidHit() && trace.m_pEnt && ENTITY(((IClientEntity *) trace.m_pEnt)->entindex())->m_Type() == ENTITY_BUILDING)
reset_z = true;
}
Vector current_vec = crumbs[0].vec;
if (reset_z)
@ -1006,64 +1023,74 @@ static CatCommand nav_path("nav_path", "Debug nav path", []() { NavEngine::navTo
static CatCommand nav_path_noreapth("nav_path_norepath", "Debug nav path", []() { NavEngine::navTo(loc, 20, false, true, false); });
static CatCommand nav_init("nav_init", "Reload nav mesh", []() {
NavEngine::map.reset();
NavEngine::LevelInit();
});
static CatCommand nav_init("nav_init", "Reload nav mesh",
[]()
{
NavEngine::map.reset();
NavEngine::LevelInit();
});
static CatCommand nav_debug_check("nav_debug_check", "Perform nav checks between two areas. First area: cat_nav_set Second area: Your location while running this command.", []() {
if (!NavEngine::isReady())
return;
auto next = NavEngine::map->findClosestNavSquare(g_pLocalPlayer->v_Origin);
auto current = NavEngine::map->findClosestNavSquare(loc);
static CatCommand nav_debug_check("nav_debug_check", "Perform nav checks between two areas. First area: cat_nav_set Second area: Your location while running this command.",
[]()
{
if (!NavEngine::isReady())
return;
auto next = NavEngine::map->findClosestNavSquare(g_pLocalPlayer->v_Origin);
auto current = NavEngine::map->findClosestNavSquare(loc);
auto points = determinePoints(current, next);
auto points = determinePoints(current, next);
points.center = handleDropdown(points.center, points.next);
points.center = handleDropdown(points.center, points.next);
// Too high for us to jump!
if (points.center_next.z - points.center.z > PLAYER_JUMP_HEIGHT)
// Too high for us to jump!
if (points.center_next.z - points.center.z > PLAYER_JUMP_HEIGHT)
{
return logging::Info("Nav: Area too high!");
}
points.current.z += PLAYER_JUMP_HEIGHT;
points.center.z += PLAYER_JUMP_HEIGHT;
points.next.z += PLAYER_JUMP_HEIGHT;
if (IsPlayerPassableNavigation(points.current, points.center) && IsPlayerPassableNavigation(points.center, points.next))
{
logging::Info("Nav: Area is player passable!");
}
else
{
logging::Info("Nav: Area is NOT player passable! %.2f,%.2f,%.2f %.2f,%.2f,%.2f %.2f,%.2f,%.2f", points.current.x, points.current.y, points.current.z, points.center.x, points.center.y, points.center.z, points.next.x, points.next.y, points.next.z);
}
});
static CatCommand nav_debug_blacklist("nav_debug_blacklist", "Blacklist connection between two areas for 30s. First area: cat_nav_set Second area: Your location while running this command.",
[]()
{
if (!NavEngine::isReady())
return;
auto next = NavEngine::map->findClosestNavSquare(g_pLocalPlayer->v_Origin);
auto current = NavEngine::map->findClosestNavSquare(loc);
std::pair<CNavArea *, CNavArea *> key(current, next);
NavEngine::map->vischeck_cache[key].expire_tick = TICKCOUNT_TIMESTAMP(30);
NavEngine::map->vischeck_cache[key].vischeck_state = false;
NavEngine::map->pather.Reset();
logging::Info("Nav: Connection %d->%d Blacklisted.", current->m_id, next->m_id);
});
static InitRoutine init(
[]()
{
return logging::Info("Nav: Area too high!");
}
points.current.z += PLAYER_JUMP_HEIGHT;
points.center.z += PLAYER_JUMP_HEIGHT;
points.next.z += PLAYER_JUMP_HEIGHT;
if (IsPlayerPassableNavigation(points.current, points.center) && IsPlayerPassableNavigation(points.center, points.next))
{
logging::Info("Nav: Area is player passable!");
}
else
{
logging::Info("Nav: Area is NOT player passable! %.2f,%.2f,%.2f %.2f,%.2f,%.2f %.2f,%.2f,%.2f", points.current.x, points.current.y, points.current.z, points.center.x, points.center.y, points.center.z, points.next.x, points.next.y, points.next.z);
}
});
static CatCommand nav_debug_blacklist("nav_debug_blacklist", "Blacklist connection between two areas for 30s. First area: cat_nav_set Second area: Your location while running this command.", []() {
if (!NavEngine::isReady())
return;
auto next = NavEngine::map->findClosestNavSquare(g_pLocalPlayer->v_Origin);
auto current = NavEngine::map->findClosestNavSquare(loc);
std::pair<CNavArea *, CNavArea *> key(current, next);
NavEngine::map->vischeck_cache[key].expire_tick = TICKCOUNT_TIMESTAMP(30);
NavEngine::map->vischeck_cache[key].vischeck_state = false;
NavEngine::map->pather.Reset();
logging::Info("Nav: Connection %d->%d Blacklisted.", current->m_id, next->m_id);
});
static InitRoutine init([]() {
EC::Register(EC::CreateMove_NoEnginePred, NavEngine::CreateMove, "navengine_cm");
EC::Register(EC::LevelInit, NavEngine::LevelInit, "navengine_levelinit");
EC::Register(EC::CreateMove_NoEnginePred, NavEngine::CreateMove, "navengine_cm");
EC::Register(EC::LevelInit, NavEngine::LevelInit, "navengine_levelinit");
#if ENABLE_VISUALS
EC::Register(EC::Draw, NavEngine::Draw, "navengine_draw");
EC::Register(EC::Draw, NavEngine::Draw, "navengine_draw");
#endif
enabled.installChangeCallback([](settings::VariableBase<bool> &, bool after) {
if (after && g_IEngine->IsInGame())
NavEngine::LevelInit();
enabled.installChangeCallback(
[](settings::VariableBase<bool> &, bool after)
{
if (after && g_IEngine->IsInGame())
NavEngine::LevelInit();
});
});
});
} // namespace navparser

View File

@ -52,7 +52,7 @@ bool trace::FilterDefault::ShouldHitEntity(IHandleEntity *handle, int mask)
if (m_pSelf)
{
// If what we hit is an enemy it does not matter
if (entity && CE_VALID(ENTITY(entity->entindex())) && ENTITY(entity->entindex())->m_iTeam() == ENTITY(m_pSelf->entindex())->m_iTeam())
if (entity && entity->entindex() != 0 && CE_VALID(ENTITY(entity->entindex())) && ENTITY(entity->entindex())->m_iTeam() == ENTITY(m_pSelf->entindex())->m_iTeam())
{
auto ent = ENTITY(m_pSelf->entindex());
if (CE_GOOD(ent) && ent->m_bAlivePlayer())