Major NavBot improvements
- Don't mark World as Potentially Passable - Don't walk into enemy spawn - Don't try to exit spawn as blue in setup time - Don't run to other, blocked sections of the map
This commit is contained in:
parent
29fdc394e6
commit
0b70fc1b50
@ -54,6 +54,10 @@ public:
|
||||
// dispenser
|
||||
offset_t m_iAmmoMetal; // dispenser metal reserve
|
||||
|
||||
// round timer
|
||||
offset_t m_nSetupTimeLength;
|
||||
offset_t m_nState;
|
||||
|
||||
offset_t iLifeState;
|
||||
offset_t iCond;
|
||||
offset_t iCond1;
|
||||
|
@ -113,6 +113,8 @@ void fClampAngle(Vector &qaAng);
|
||||
// const char* MakeInfoString(IClientEntity* player);
|
||||
bool GetProjectileData(CachedEntity *weapon, float &speed, float &gravity);
|
||||
bool IsVectorVisible(Vector a, Vector b, bool enviroment_only = false, CachedEntity *self = LOCAL_E, unsigned int mask = MASK_SHOT_HULL);
|
||||
// A Special function for navparser to check if a Vector is visible.
|
||||
bool IsVectorVisibleNavigation(Vector a, Vector b, CachedEntity *self = LOCAL_E, unsigned int mask = MASK_SHOT_HULL);
|
||||
Vector GetForwardVector(Vector origin, Vector viewangles, float distance);
|
||||
Vector GetForwardVector(float distance);
|
||||
CachedEntity *getClosestEntity(Vector vec);
|
||||
|
@ -22,6 +22,11 @@ public:
|
||||
typedef bool (*fn_t)(IClientEntity *);
|
||||
return vfunc<fn_t>(self, offsets::PlatformOffset(184, offsets::undefined, 184), 0)(self);
|
||||
}
|
||||
inline static bool ShouldCollide(IClientEntity *self, int collisionGroup, int contentsMask)
|
||||
{
|
||||
typedef bool (*fn_t)(IClientEntity *, int, int);
|
||||
return vfunc<fn_t>(self, offsets::PlatformOffset(198, offsets::undefined, 198), 0)(self, collisionGroup, contentsMask);
|
||||
}
|
||||
inline static int &m_nPredictionRandomSeed()
|
||||
{
|
||||
static int placeholder = 0;
|
||||
|
17
include/teamroundtimer.hpp
Normal file
17
include/teamroundtimer.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
enum round_states
|
||||
{
|
||||
RT_STATE_SETUP = 0,
|
||||
RT_STATE_NORMAL
|
||||
};
|
||||
|
||||
class CTeamRoundTimer
|
||||
{
|
||||
public:
|
||||
int GetSetupTimeLength();
|
||||
round_states GetRoundState();
|
||||
void Update();
|
||||
|
||||
int entity;
|
||||
};
|
||||
extern CTeamRoundTimer *g_pTeamRoundTimer;
|
@ -41,6 +41,18 @@ public:
|
||||
void SetSelf(IClientEntity *self);
|
||||
virtual TraceType_t GetTraceType() const;
|
||||
};
|
||||
class FilterNavigation : public ITraceFilter
|
||||
{
|
||||
public:
|
||||
IClientEntity *m_pSelf;
|
||||
|
||||
public:
|
||||
virtual ~FilterNavigation();
|
||||
FilterNavigation();
|
||||
virtual bool ShouldHitEntity(IHandleEntity *entity, int mask);
|
||||
void SetSelf(IClientEntity *self);
|
||||
virtual TraceType_t GetTraceType() const;
|
||||
};
|
||||
|
||||
class FilterNoEntity : public ITraceFilter
|
||||
{
|
||||
@ -72,6 +84,7 @@ public:
|
||||
|
||||
extern FilterDefault filter_default;
|
||||
extern FilterNoPlayer filter_no_player;
|
||||
extern FilterNavigation filter_navigation;
|
||||
extern FilterNoEntity filter_no_entity;
|
||||
extern FilterPenetration filter_penetration;
|
||||
} // namespace trace
|
||||
|
@ -23,6 +23,7 @@ set(files "${CMAKE_CURRENT_LIST_DIR}/angles.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/sconvars.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/soundcache.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/targethelper.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/teamroundtimer.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/textmode.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/tfmm.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/trace.cpp"
|
||||
|
@ -88,6 +88,10 @@ void NetVars::Init()
|
||||
// dispenser
|
||||
this->m_iAmmoMetal = gNetvars.get_offset("DT_ObjectDispenser", "m_iAmmoMetal");
|
||||
|
||||
// Round timer
|
||||
this->m_nSetupTimeLength = gNetvars.get_offset("DT_TeamRoundTimer", "m_nSetupTimeLength");
|
||||
this->m_nState = gNetvars.get_offset("DT_TeamRoundTimer", "m_nState");
|
||||
|
||||
// any building
|
||||
this->m_iUpgradeMetal = gNetvars.get_offset("DT_BaseObject", "m_iUpgradeMetal");
|
||||
this->m_flPercentageConstructed = gNetvars.get_offset("DT_BaseObject", "m_flPercentageConstructed");
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <pwd.h>
|
||||
|
||||
#include <hacks/hacklist.hpp>
|
||||
#include "teamroundtimer.hpp"
|
||||
#if EXTERNAL_DRAWING
|
||||
#include "xoverlay.h"
|
||||
#endif
|
||||
@ -336,6 +337,7 @@ free(logname);*/
|
||||
InitNetVars();
|
||||
g_pLocalPlayer = new LocalPlayer();
|
||||
g_pPlayerResource = new TFPlayerResource();
|
||||
g_pTeamRoundTimer = new CTeamRoundTimer();
|
||||
|
||||
velocity::Init();
|
||||
playerlist::Load();
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "soundcache.hpp"
|
||||
#include "Misc.hpp"
|
||||
#include "MiscTemporary.hpp"
|
||||
#include "teamroundtimer.hpp"
|
||||
|
||||
namespace hacks::tf2::NavBot
|
||||
{
|
||||
@ -120,6 +121,19 @@ static void CreateMove()
|
||||
wait_until_path.update();
|
||||
else
|
||||
current_task = task::none;
|
||||
// Check if we should path at all
|
||||
if (!blocking)
|
||||
{
|
||||
round_states round_state = g_pTeamRoundTimer->GetRoundState();
|
||||
// Still in setuptime, if on fitting team, then do not path yet
|
||||
if (round_state == RT_STATE_SETUP && g_pLocalPlayer->team == TEAM_BLU)
|
||||
{
|
||||
// Clear instructions
|
||||
if (!nav::ReadyForCommands)
|
||||
nav::clearInstructions();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (autojump)
|
||||
autoJump();
|
||||
|
@ -1338,7 +1338,6 @@ netvar.iHealth));
|
||||
|
||||
bool IsVectorVisible(Vector origin, Vector target, bool enviroment_only, CachedEntity *self, unsigned int mask)
|
||||
{
|
||||
|
||||
if (!enviroment_only)
|
||||
{
|
||||
trace_t trace_visible;
|
||||
@ -1363,6 +1362,18 @@ bool IsVectorVisible(Vector origin, Vector target, bool enviroment_only, CachedE
|
||||
}
|
||||
}
|
||||
|
||||
bool IsVectorVisibleNavigation(Vector origin, Vector target, CachedEntity *self, unsigned int mask)
|
||||
{
|
||||
trace_t trace_visible;
|
||||
Ray_t ray;
|
||||
|
||||
trace::filter_no_entity.SetSelf(RAW_ENT(self));
|
||||
ray.Init(origin, target);
|
||||
PROF_SECTION(IEVV_TraceRay);
|
||||
g_ITrace->TraceRay(ray, mask, &trace::filter_navigation, &trace_visible);
|
||||
return (trace_visible.fraction == 1.0f);
|
||||
}
|
||||
|
||||
void WhatIAmLookingAt(int *result_eindex, Vector *result_pos)
|
||||
{
|
||||
Ray_t ray;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <hacks/AntiAntiAim.hpp>
|
||||
#include "NavBot.hpp"
|
||||
#include "HookTools.hpp"
|
||||
#include "teamroundtimer.hpp"
|
||||
|
||||
#include "HookedMethods.hpp"
|
||||
#include "PreDataUpdate.hpp"
|
||||
@ -242,6 +243,10 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, CUs
|
||||
PROF_SECTION(CM_PlayerResource);
|
||||
g_pPlayerResource->Update();
|
||||
}
|
||||
{
|
||||
PROF_SECTION(CM_TeamTimer);
|
||||
g_pTeamRoundTimer->Update();
|
||||
}
|
||||
{
|
||||
PROF_SECTION(CM_LocalPlayer);
|
||||
g_pLocalPlayer->Update();
|
||||
|
@ -33,6 +33,8 @@ enum ignore_status : uint8_t
|
||||
const_ignored,
|
||||
// LOS between areas is given
|
||||
vischeck_success,
|
||||
// LOS if we ignore entities
|
||||
vischeck_blockedentity,
|
||||
// No LOS between areas
|
||||
vischeck_failed,
|
||||
// Failed to actually walk thru connection
|
||||
@ -95,13 +97,22 @@ float getZBetweenAreas(CNavArea *start, CNavArea *end)
|
||||
static std::unordered_map<std::pair<CNavArea *, CNavArea *>, ignoredata, boost::hash<std::pair<CNavArea *, CNavArea *>>> ignores;
|
||||
namespace ignoremanager
|
||||
{
|
||||
static bool vischeck(CNavArea *begin, CNavArea *end)
|
||||
static ignore_status vischeck(CNavArea *begin, CNavArea *end)
|
||||
{
|
||||
Vector first = begin->m_center;
|
||||
Vector second = end->m_center;
|
||||
first.z += 70;
|
||||
second.z += 70;
|
||||
return IsVectorVisible(first, second, true, LOCAL_E, MASK_PLAYERSOLID);
|
||||
ignore_status status = vischeck_failed;
|
||||
// Is world blocking it?
|
||||
if (IsVectorVisibleNavigation(first, second, LOCAL_E, MASK_PLAYERSOLID))
|
||||
{
|
||||
status = vischeck_success;
|
||||
// Is something else blocking it?
|
||||
if (!IsVectorVisible(first, second, true, LOCAL_E, MASK_PLAYERSOLID))
|
||||
status = vischeck_blockedentity;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
static ignore_status runIgnoreChecks(CNavArea *begin, CNavArea *end)
|
||||
{
|
||||
@ -110,10 +121,7 @@ static ignore_status runIgnoreChecks(CNavArea *begin, CNavArea *end)
|
||||
return const_ignored;
|
||||
if (!vischecks)
|
||||
return vischeck_success;
|
||||
if (vischeck(begin, end))
|
||||
return vischeck_success;
|
||||
else
|
||||
return vischeck_failed;
|
||||
return vischeck(begin, end);
|
||||
}
|
||||
static void updateDanger()
|
||||
{
|
||||
@ -250,12 +258,21 @@ static void checkPath()
|
||||
ignoredata &data = ignores[{ begin, end }];
|
||||
if (data.status == vischeck_failed)
|
||||
return;
|
||||
if (!vischeck(begin, end))
|
||||
if (data.status == vischeck_blockedentity && vischeckBlock)
|
||||
return;
|
||||
auto vis_status = vischeck(begin, end);
|
||||
if (vis_status == vischeck_failed)
|
||||
{
|
||||
data.status = vischeck_failed;
|
||||
data.ignoreTimeout.update();
|
||||
perform_repath = true;
|
||||
}
|
||||
else if (vis_status == vischeck_blockedentity && vischeckBlock)
|
||||
{
|
||||
data.status = vischeck_blockedentity;
|
||||
data.ignoreTimeout.update();
|
||||
perform_repath = true;
|
||||
}
|
||||
else if (ignores[{ end, nullptr }].status == danger_found)
|
||||
{
|
||||
perform_repath = true;
|
||||
@ -274,7 +291,7 @@ static int isIgnored(CNavArea *begin, CNavArea *end)
|
||||
status = runIgnoreChecks(begin, end);
|
||||
if (status == vischeck_success)
|
||||
return 0;
|
||||
else if (status == vischeck_failed)
|
||||
else if (status == vischeck_blockedentity && !vischeckBlock)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
@ -352,6 +369,7 @@ static void updateIgnores()
|
||||
}
|
||||
break;
|
||||
case vischeck_failed:
|
||||
case vischeck_blockedentity:
|
||||
case vischeck_success:
|
||||
default:
|
||||
if (i.second.ignoreTimeout.check(30000))
|
||||
@ -510,7 +528,7 @@ CNavArea *findClosestNavSquare(const Vector &vec)
|
||||
bestSquare = &i;
|
||||
}
|
||||
// Check if we are within x and y bounds of an area
|
||||
if (ovBestDist >= dist || !i.IsOverlapping(vec) || !IsVectorVisible(vec, i.m_center, true, LOCAL_E, MASK_PLAYERSOLID))
|
||||
if (ovBestDist >= dist || !i.IsOverlapping(vec) || !IsVectorVisibleNavigation(vec, i.m_center, LOCAL_E, MASK_PLAYERSOLID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -628,6 +646,7 @@ static void cm()
|
||||
return;
|
||||
}
|
||||
ignoremanager::updateIgnores();
|
||||
|
||||
auto crumb = crumbs.begin();
|
||||
const Vector *crumb_vec;
|
||||
// Crumbs empty, prepare for next instruction
|
||||
|
38
src/teamroundtimer.cpp
Normal file
38
src/teamroundtimer.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "common.hpp"
|
||||
#include "teamroundtimer.hpp"
|
||||
|
||||
int CTeamRoundTimer::GetSetupTimeLength()
|
||||
{
|
||||
IClientEntity *ent;
|
||||
ent = g_IEntityList->GetClientEntity(entity);
|
||||
if (!ent || ent->GetClientClass()->m_ClassID != CL_CLASS(CTeamRoundTimer))
|
||||
return -1;
|
||||
return NET_INT(ent, netvar.m_nSetupTimeLength);
|
||||
};
|
||||
|
||||
round_states CTeamRoundTimer::GetRoundState()
|
||||
{
|
||||
IClientEntity *ent;
|
||||
ent = g_IEntityList->GetClientEntity(entity);
|
||||
if (!ent || ent->GetClientClass()->m_ClassID != CL_CLASS(CTeamRoundTimer))
|
||||
return RT_STATE_NORMAL;
|
||||
int state = NET_INT(ent, netvar.m_nState);
|
||||
return state == 1 ? RT_STATE_NORMAL : RT_STATE_SETUP;
|
||||
};
|
||||
|
||||
void CTeamRoundTimer::Update()
|
||||
{
|
||||
IClientEntity *ent;
|
||||
|
||||
entity = 0;
|
||||
for (int i = 0; i <= HIGHEST_ENTITY; i++)
|
||||
{
|
||||
ent = g_IEntityList->GetClientEntity(i);
|
||||
if (ent && ent->GetClientClass()->m_ClassID == CL_CLASS(CTeamRoundTimer))
|
||||
{
|
||||
entity = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
CTeamRoundTimer *g_pTeamRoundTimer{ nullptr };
|
@ -108,6 +108,60 @@ TraceType_t trace::FilterNoPlayer::GetTraceType() const
|
||||
{
|
||||
return TRACE_EVERYTHING;
|
||||
}
|
||||
|
||||
/* Navigation filter */
|
||||
|
||||
trace::FilterNavigation::FilterNavigation()
|
||||
{
|
||||
m_pSelf = nullptr;
|
||||
}
|
||||
|
||||
trace::FilterNavigation::~FilterNavigation(){};
|
||||
|
||||
void trace::FilterNavigation::SetSelf(IClientEntity *self)
|
||||
{
|
||||
if (self == nullptr)
|
||||
{
|
||||
logging::Info("nullptr in FilterNavigation::SetSelf");
|
||||
return;
|
||||
}
|
||||
m_pSelf = self;
|
||||
}
|
||||
|
||||
#define MOVEMENT_COLLISION_GROUP 8
|
||||
#define RED_CONTENTS_MASK 0x800
|
||||
#define BLU_CONTENTS_MASK 0x1000
|
||||
bool trace::FilterNavigation::ShouldHitEntity(IHandleEntity *handle, int mask)
|
||||
{
|
||||
IClientEntity *entity;
|
||||
ClientClass *clazz;
|
||||
|
||||
if (!handle)
|
||||
return false;
|
||||
entity = (IClientEntity *) handle;
|
||||
clazz = entity->GetClientClass();
|
||||
|
||||
// Ignore everything that is not the world or a CBaseEntity
|
||||
if (entity->entindex() != 0 && clazz->m_ClassID != CL_CLASS(CBaseEntity))
|
||||
{
|
||||
// Besides respawn room areas, we want to explicitly ignore those if they are not on our team
|
||||
if (clazz->m_ClassID == CL_CLASS(CFuncRespawnRoomVisualizer))
|
||||
if (CE_GOOD(LOCAL_E) && (g_pLocalPlayer->team == TEAM_RED || g_pLocalPlayer->team == TEAM_BLU))
|
||||
{
|
||||
// If we can't collide, hit it
|
||||
if (!re::C_BaseEntity::ShouldCollide(entity, MOVEMENT_COLLISION_GROUP, g_pLocalPlayer->team == TEAM_RED ? RED_CONTENTS_MASK : BLU_CONTENTS_MASK))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TraceType_t trace::FilterNavigation::GetTraceType() const
|
||||
{
|
||||
return TRACE_EVERYTHING;
|
||||
}
|
||||
|
||||
/* No-Entity filter */
|
||||
|
||||
trace::FilterNoEntity::FilterNoEntity()
|
||||
@ -215,5 +269,6 @@ void trace::FilterPenetration::Reset()
|
||||
|
||||
trace::FilterDefault trace::filter_default{};
|
||||
trace::FilterNoPlayer trace::filter_no_player{};
|
||||
trace::FilterNavigation trace::filter_navigation{};
|
||||
trace::FilterNoEntity trace::filter_no_entity{};
|
||||
trace::FilterPenetration trace::filter_penetration{};
|
||||
|
Reference in New Issue
Block a user