WIP: Pathfinding Nr. 5
This commit is contained in:
parent
0054b64cb3
commit
c1797dfdfa
@ -36,6 +36,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#if not LAGBOT_MODE
|
#if not LAGBOT_MODE
|
||||||
#include "Walkbot.hpp"
|
#include "Walkbot.hpp"
|
||||||
|
#include "navparser.hpp"
|
||||||
#endif
|
#endif
|
||||||
#include "AutoJoin.hpp"
|
#include "AutoJoin.hpp"
|
||||||
#if not LAGBOT_MODE
|
#if not LAGBOT_MODE
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
namespace nav
|
||||||
|
{
|
||||||
|
extern bool init;
|
||||||
|
extern bool pathfinding;
|
||||||
|
std::vector<Vector> findPath(Vector loc, Vector dest);
|
||||||
|
bool Prepare();
|
||||||
|
void CreateMove();
|
||||||
|
}
|
@ -269,6 +269,10 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time,
|
|||||||
PROF_SECTION(CM_walkbot);
|
PROF_SECTION(CM_walkbot);
|
||||||
hacks::shared::walkbot::Move();
|
hacks::shared::walkbot::Move();
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
PROF_SECTION(CM_navbot);
|
||||||
|
nav::CreateMove();
|
||||||
|
}
|
||||||
// Walkbot can leave game.
|
// Walkbot can leave game.
|
||||||
if (!g_IEngine->IsInGame())
|
if (!g_IEngine->IsInGame())
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <menu/GuiInterface.hpp>
|
#include <menu/GuiInterface.hpp>
|
||||||
#include "HookedMethods.hpp"
|
#include "HookedMethods.hpp"
|
||||||
#include "MiscTemporary.hpp"
|
#include "MiscTemporary.hpp"
|
||||||
|
#include "navparser.hpp"
|
||||||
#if !LAGBOT_MODE
|
#if !LAGBOT_MODE
|
||||||
#include "hacks/Backtrack.hpp"
|
#include "hacks/Backtrack.hpp"
|
||||||
#endif
|
#endif
|
||||||
@ -58,6 +59,7 @@ DEFINE_HOOKED_METHOD(LevelInit, void, void *this_, const char *name)
|
|||||||
#endif
|
#endif
|
||||||
hacks::shared::autojoin::resetQueueTimer();
|
hacks::shared::autojoin::resetQueueTimer();
|
||||||
firstcm = true;
|
firstcm = true;
|
||||||
|
nav::init = false;
|
||||||
#if !LAGBOT_MODE
|
#if !LAGBOT_MODE
|
||||||
playerlist::Save();
|
playerlist::Save();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
#include "micropather.h"
|
#include "micropather.h"
|
||||||
#include "pwd.h"
|
#include "pwd.h"
|
||||||
|
|
||||||
namespace nav
|
namespace nav
|
||||||
{
|
{
|
||||||
static CNavFile navfile(nullptr);
|
static CNavFile navfile(nullptr);
|
||||||
// Todo: CNavArea* to navfile
|
// Todo: CNavArea* to navfile
|
||||||
static std::vector<CNavArea> areas;
|
static std::vector<CNavArea> areas;
|
||||||
// std::vector<CNavArea> SniperAreas;
|
// std::vector<CNavArea> SniperAreas;
|
||||||
|
bool init = false;
|
||||||
|
bool pathfinding = true;
|
||||||
|
static settings::Bool enabled{ "misc.pathing", "true" };
|
||||||
|
|
||||||
// Todo fix
|
// Todo fix
|
||||||
int FindInVector(int id)
|
int FindInVector(int id)
|
||||||
@ -20,6 +24,53 @@ int FindInVector(int id)
|
|||||||
|
|
||||||
struct MAP : public micropather::Graph
|
struct MAP : public micropather::Graph
|
||||||
{
|
{
|
||||||
|
Vector GetClosestCornerToArea(CNavArea *CornerOf, CNavArea *Target)
|
||||||
|
{
|
||||||
|
std::array<Vector, 4> 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)
|
float LeastCostEstimate(void *stateStart, void *stateEnd)
|
||||||
{
|
{
|
||||||
CNavArea *start = static_cast<CNavArea *>(stateStart);
|
CNavArea *start = static_cast<CNavArea *>(stateStart);
|
||||||
@ -33,6 +84,8 @@ struct MAP : public micropather::Graph
|
|||||||
auto &neighbours = area->m_connections;
|
auto &neighbours = area->m_connections;
|
||||||
for (auto i : neighbours)
|
for (auto i : neighbours)
|
||||||
{
|
{
|
||||||
|
if (GetZBetweenAreas(area, i.area) > 40)
|
||||||
|
continue;
|
||||||
micropather::StateCost cost;
|
micropather::StateCost cost;
|
||||||
cost.state =
|
cost.state =
|
||||||
static_cast<void *>(&areas.at(FindInVector(i.area->m_id)));
|
static_cast<void *>(&areas.at(FindInVector(i.area->m_id)));
|
||||||
@ -43,13 +96,11 @@ struct MAP : public micropather::Graph
|
|||||||
void PrintStateInfo(void *state)
|
void PrintStateInfo(void *state)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MAP()
|
MAP()
|
||||||
{
|
{
|
||||||
logging::Info("Init Map");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~MAP()
|
~MAP()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -79,46 +130,49 @@ void Init()
|
|||||||
for (auto i : navfile.m_areas)
|
for (auto i : navfile.m_areas)
|
||||||
areas.push_back(i);
|
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)
|
int findClosestNavSquare(Vector vec)
|
||||||
{
|
{
|
||||||
float bestDist = 999999.0f;
|
|
||||||
int bestSquare = -1;
|
|
||||||
for (int i = 0; i < areas.size(); i++)
|
for (int i = 0; i < areas.size(); i++)
|
||||||
{
|
{
|
||||||
float dist = areas.at(i).m_center.DistTo(vec);
|
if (areas.at(i).Contains(vec))
|
||||||
if (dist < bestDist)
|
return i;
|
||||||
{
|
|
||||||
bestDist = dist;
|
|
||||||
bestSquare = i;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return bestSquare;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Vector> findPath(Vector loc, Vector dest)
|
std::vector<Vector> findPath(Vector loc, Vector dest)
|
||||||
{
|
{
|
||||||
logging::Info("Starting findPath");
|
|
||||||
if (areas.empty())
|
if (areas.empty())
|
||||||
return std::vector<Vector>(0);
|
return std::vector<Vector>(0);
|
||||||
logging::Info("Finding closest Squares");
|
|
||||||
int id_loc = findClosestNavSquare(loc);
|
int id_loc = findClosestNavSquare(loc);
|
||||||
int id_dest = findClosestNavSquare(dest);
|
int id_dest = findClosestNavSquare(dest);
|
||||||
logging::Info("Initiating path_Nodes");
|
if (id_loc == -1 || id_dest == -1)
|
||||||
|
return std::vector<Vector>(0);
|
||||||
micropather::MPVector<void *> pathNodes;
|
micropather::MPVector<void *> pathNodes;
|
||||||
float cost;
|
|
||||||
logging::Info("Initiating map");
|
|
||||||
MAP TF2MAP;
|
MAP TF2MAP;
|
||||||
logging::Info("Initiating pather");
|
|
||||||
// Todo: Make MicroPather a member of TF2MAP
|
|
||||||
micropather::MicroPather pather(&TF2MAP, areas.size(), 8, true);
|
micropather::MicroPather pather(&TF2MAP, areas.size(), 8, true);
|
||||||
logging::Info("Solving");
|
float cost;
|
||||||
int result = pather.Solve(static_cast<void *>(&areas.at(id_loc)),
|
int result = pather.Solve(static_cast<void *>(&areas.at(id_loc)),
|
||||||
static_cast<void *>(&areas.at(id_dest)),
|
static_cast<void *>(&areas.at(id_dest)),
|
||||||
&pathNodes, &cost);
|
&pathNodes, &cost);
|
||||||
logging::Info(format("Result:", result).c_str());
|
logging::Info(format(result).c_str());
|
||||||
logging::Info("Converting to vector");
|
|
||||||
std::vector<Vector> path;
|
std::vector<Vector> path;
|
||||||
for (int i = 0; i < pathNodes.size(); i++)
|
for (int i = 0; i < pathNodes.size(); i++)
|
||||||
{
|
{
|
||||||
@ -127,13 +181,58 @@ std::vector<Vector> findPath(Vector loc, Vector dest)
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Timer inactivity{};
|
||||||
|
Timer lastJump{};
|
||||||
|
static std::vector<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",
|
CatCommand navinit("nav_init", "Debug nav init",
|
||||||
[](const CCommand &args) { Init(); });
|
[](const CCommand &args) { Prepare(); });
|
||||||
|
|
||||||
Vector loc;
|
Vector loc;
|
||||||
|
|
||||||
CatCommand navset("nav_set", "Debug nav set",
|
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) {
|
CatCommand navfind("nav_find", "Debug nav find", [](const CCommand &args) {
|
||||||
std::vector<Vector> path = findPath(g_pLocalPlayer->v_Origin, loc);
|
std::vector<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());
|
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
|
} // namespace nav
|
||||||
|
Reference in New Issue
Block a user