From b6a0b65c726a2d2948d6c9d4f2f9ae2da3c50a24 Mon Sep 17 00:00:00 2001 From: LightCat Date: Tue, 10 Aug 2021 13:29:07 +0200 Subject: [PATCH] Add Engineer Bot support (#1524) * readd engiebot to navbot, WIP * Slot changes for engie * Fix some Engi Bot problems Co-authored-by: aUniqueUser --- include/navparser.hpp | 2 + src/hacks/NavBot.cpp | 426 ++++++++++++++++++++++++++++++++++++++---- src/navparser.cpp | 129 ++++++++----- src/trace.cpp | 2 +- 4 files changed, 473 insertions(+), 86 deletions(-) diff --git a/include/navparser.hpp b/include/navparser.hpp index 7c2ce37c..9f83903f 100644 --- a/include/navparser.hpp +++ b/include/navparser.hpp @@ -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 }; diff --git a/src/hacks/NavBot.cpp b/src/hacks/NavBot.cpp index 3eba6ed8..5694664e 100644 --- a/src/hacks/NavBot.cpp +++ b/src/hacks/NavBot.cpp @@ -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(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 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 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 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 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 &nearest) @@ -1091,6 +1425,20 @@ static slots getBestSlot(slots active_slot, std::pair &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 diff --git a/src/navparser.cpp b/src/navparser.cpp index 8b9e9cbc..a6564518 100644 --- a/src/navparser.cpp +++ b/src/navparser.cpp @@ -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 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 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 after) { - if (after && g_IEngine->IsInGame()) - NavEngine::LevelInit(); + enabled.installChangeCallback( + [](settings::VariableBase &, bool after) + { + if (after && g_IEngine->IsInGame()) + NavEngine::LevelInit(); + }); }); -}); } // namespace navparser diff --git a/src/trace.cpp b/src/trace.cpp index 017742ae..a98128c1 100644 --- a/src/trace.cpp +++ b/src/trace.cpp @@ -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())