From c1797dfdfa4f730dfe99bb70d0313be1ae7da114 Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Thu, 16 Aug 2018 22:10:26 +0200 Subject: [PATCH] WIP: Pathfinding Nr. 5 --- include/hacks/hacklist.hpp | 1 + include/navparser.hpp | 12 +++ src/hooks/CreateMove.cpp | 4 + src/hooks/LevelInit.cpp | 2 + src/navparser.cpp | 160 +++++++++++++++++++++++++++++++------ 5 files changed, 154 insertions(+), 25 deletions(-) diff --git a/include/hacks/hacklist.hpp b/include/hacks/hacklist.hpp index d26947aa..6ca28f0a 100755 --- a/include/hacks/hacklist.hpp +++ b/include/hacks/hacklist.hpp @@ -36,6 +36,7 @@ #endif #if not LAGBOT_MODE #include "Walkbot.hpp" +#include "navparser.hpp" #endif #include "AutoJoin.hpp" #if not LAGBOT_MODE diff --git a/include/navparser.hpp b/include/navparser.hpp index e69de29b..b9f5762b 100755 --- a/include/navparser.hpp +++ b/include/navparser.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "common.hpp" + +namespace nav +{ +extern bool init; +extern bool pathfinding; +std::vector findPath(Vector loc, Vector dest); +bool Prepare(); +void CreateMove(); +} diff --git a/src/hooks/CreateMove.cpp b/src/hooks/CreateMove.cpp index 6a9cc693..97b96c20 100755 --- a/src/hooks/CreateMove.cpp +++ b/src/hooks/CreateMove.cpp @@ -269,6 +269,10 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, PROF_SECTION(CM_walkbot); hacks::shared::walkbot::Move(); } + { + PROF_SECTION(CM_navbot); + nav::CreateMove(); + } // Walkbot can leave game. if (!g_IEngine->IsInGame()) { diff --git a/src/hooks/LevelInit.cpp b/src/hooks/LevelInit.cpp index fe588767..e58b61a0 100755 --- a/src/hooks/LevelInit.cpp +++ b/src/hooks/LevelInit.cpp @@ -8,6 +8,7 @@ #include #include "HookedMethods.hpp" #include "MiscTemporary.hpp" +#include "navparser.hpp" #if !LAGBOT_MODE #include "hacks/Backtrack.hpp" #endif @@ -58,6 +59,7 @@ DEFINE_HOOKED_METHOD(LevelInit, void, void *this_, const char *name) #endif hacks::shared::autojoin::resetQueueTimer(); firstcm = true; + nav::init = false; #if !LAGBOT_MODE playerlist::Save(); #endif diff --git a/src/navparser.cpp b/src/navparser.cpp index f60a6a32..eb5048b1 100755 --- a/src/navparser.cpp +++ b/src/navparser.cpp @@ -1,12 +1,16 @@ #include "common.hpp" #include "micropather.h" #include "pwd.h" + namespace nav { static CNavFile navfile(nullptr); // Todo: CNavArea* to navfile static std::vector areas; // std::vector SniperAreas; +bool init = false; +bool pathfinding = true; +static settings::Bool enabled{ "misc.pathing", "true" }; // Todo fix int FindInVector(int id) @@ -20,6 +24,53 @@ int FindInVector(int id) struct MAP : public micropather::Graph { + Vector GetClosestCornerToArea(CNavArea *CornerOf, CNavArea *Target) + { + std::array corners; + corners.at(0) = CornerOf->m_nwCorner; // NW + corners.at(1) = CornerOf->m_seCorner; // SE + corners.at(2) = Vector{ CornerOf->m_seCorner.x, CornerOf->m_nwCorner.y, + CornerOf->m_nwCorner.z }; // NE + corners.at(3) = Vector{ CornerOf->m_nwCorner.x, CornerOf->m_seCorner.y, + CornerOf->m_seCorner.z }; // SW + + Vector bestVec; + float bestDist = FLT_MAX; + + for (int i = 0; i < corners.size(); i++) + { + float dist = corners.at(i).DistTo(Target->m_center); + if (dist < bestDist) + { + bestVec = corners.at(i); + bestDist = dist; + } + } + + Vector bestVec2; + float bestDist2 = FLT_MAX; + + for (int i = 0; i < corners.size(); i++) + { + if (corners.at(i) == bestVec2) + continue; + float dist = corners.at(i).DistTo(Target->m_center); + if (dist < bestDist2) + { + bestVec2 = corners.at(i); + bestDist2 = dist; + } + } + return (bestVec + bestVec2) / 2; + } + + float GetZBetweenAreas(CNavArea *start, CNavArea *end) + { + float z1 = GetClosestCornerToArea(start, end).z; + float z2 = GetClosestCornerToArea(end, start).z; + + return z2 - z1; + } float LeastCostEstimate(void *stateStart, void *stateEnd) { CNavArea *start = static_cast(stateStart); @@ -33,6 +84,8 @@ struct MAP : public micropather::Graph auto &neighbours = area->m_connections; for (auto i : neighbours) { + if (GetZBetweenAreas(area, i.area) > 40) + continue; micropather::StateCost cost; cost.state = static_cast(&areas.at(FindInVector(i.area->m_id))); @@ -43,13 +96,11 @@ struct MAP : public micropather::Graph void PrintStateInfo(void *state) { } - MAP() { - logging::Info("Init Map"); } - virtual ~MAP() + ~MAP() { } }; @@ -62,7 +113,7 @@ void Init() lvlname = lvlname.substr(0, dotpos); std::string lvldir("/home/"); - passwd *pwd = getpwuid(getuid()); + passwd *pwd = getpwuid(getuid()); lvldir.append(pwd->pw_name); lvldir.append("/.steam/steam/steamapps/common/Team Fortress 2/tf/"); lvldir.append(lvlname); @@ -79,46 +130,49 @@ void Init() for (auto i : navfile.m_areas) areas.push_back(i); } + pathfinding = true; +} + +bool Prepare() +{ + if (!enabled) + return false; + if (!init) + { + pathfinding = false; + init = true; + Init(); + } + if (!pathfinding) + return false; + return true; } int findClosestNavSquare(Vector vec) { - float bestDist = 999999.0f; - int bestSquare = -1; for (int i = 0; i < areas.size(); i++) { - float dist = areas.at(i).m_center.DistTo(vec); - if (dist < bestDist) - { - bestDist = dist; - bestSquare = i; - } + if (areas.at(i).Contains(vec)) + return i; } - return bestSquare; } std::vector findPath(Vector loc, Vector dest) { - logging::Info("Starting findPath"); if (areas.empty()) return std::vector(0); - logging::Info("Finding closest Squares"); int id_loc = findClosestNavSquare(loc); int id_dest = findClosestNavSquare(dest); - logging::Info("Initiating path_Nodes"); + if (id_loc == -1 || id_dest == -1) + return std::vector(0); micropather::MPVector pathNodes; - float cost; - logging::Info("Initiating map"); MAP TF2MAP; - logging::Info("Initiating pather"); - // Todo: Make MicroPather a member of TF2MAP micropather::MicroPather pather(&TF2MAP, areas.size(), 8, true); - logging::Info("Solving"); + float cost; int result = pather.Solve(static_cast(&areas.at(id_loc)), static_cast(&areas.at(id_dest)), &pathNodes, &cost); - logging::Info(format("Result:", result).c_str()); - logging::Info("Converting to vector"); + logging::Info(format(result).c_str()); std::vector path; for (int i = 0; i < pathNodes.size(); i++) { @@ -127,13 +181,58 @@ std::vector findPath(Vector loc, Vector dest) return path; } +static Timer inactivity{}; +Timer lastJump{}; +static std::vector crumbs; + +bool NavTo(Vector dest) +{ + if (CE_BAD(LOCAL_E)) + return false; + if (!Prepare()) + return false; + auto path = findPath(g_pLocalPlayer->v_Origin, dest); + if (path.empty()) + return false; + crumbs.clear(); + crumbs = std::move(path); + inactivity.update(); + return true; +} + +void CreateMove() +{ + if (!enabled) + return; + if (CE_BAD(LOCAL_E)) + return; + if (!crumbs.empty() && g_pLocalPlayer->v_Origin.DistTo(crumbs.at(0)) < 40.0f) + { + crumbs.erase(crumbs.begin()); + inactivity.update(); + } + if (crumbs.empty()) + return; + if (inactivity.check(2000) && lastJump.test_and_set(1000)) + { + current_user_cmd->buttons |= IN_JUMP; + } + if (inactivity.test_and_set(5000)) + { + logging::Info("NavBot inactive for too long. Canceling tasks..."); + crumbs.clear(); + return; + } + WalkTo(crumbs.at(0)); +} + CatCommand navinit("nav_init", "Debug nav init", - [](const CCommand &args) { Init(); }); + [](const CCommand &args) { Prepare(); }); Vector loc; CatCommand navset("nav_set", "Debug nav set", - [](const CCommand &args) { loc = g_pLocalPlayer->v_Origin; }); + [](const CCommand &args) { loc = LOCAL_E->m_vecOrigin(); }); CatCommand navfind("nav_find", "Debug nav find", [](const CCommand &args) { std::vector path = findPath(g_pLocalPlayer->v_Origin, loc); @@ -150,4 +249,15 @@ CatCommand navfind("nav_find", "Debug nav find", [](const CCommand &args) { logging::Info(output.c_str()); }); +CatCommand navpath("nav_path", "Debug nav path", [](const CCommand &args) { + if (NavTo(loc)) + { + logging::Info("Pathing: Success! Walking to path..."); + } + else + { + logging::Info("Pathing: Failed!"); + } +}); + } // namespace nav