Merge pull request #830 from nullworks/totallynotelite
Merge HWGS and other changes
This commit is contained in:
commit
5de55010dc
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -18,7 +18,7 @@
|
|||||||
url = https://github.com/nullworks/co-library.git
|
url = https://github.com/nullworks/co-library.git
|
||||||
[submodule "external/MicroPather"]
|
[submodule "external/MicroPather"]
|
||||||
path = external/MicroPather
|
path = external/MicroPather
|
||||||
url = https://github.com/leethomason/MicroPather
|
url = https://github.com/nullworks/MicroPather
|
||||||
[submodule "external/TF2_NavFile_Reader"]
|
[submodule "external/TF2_NavFile_Reader"]
|
||||||
path = external/TF2_NavFile_Reader
|
path = external/TF2_NavFile_Reader
|
||||||
url = https://github.com/nullworks/TF2_NavFile_Reader
|
url = https://github.com/nullworks/TF2_NavFile_Reader
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
<Option name="FakeOffset" value="15"/>
|
<Option name="FakeOffset" value="15"/>
|
||||||
<Option name="FakeEdge" value="16"/>
|
<Option name="FakeEdge" value="16"/>
|
||||||
<Option name="FakeHeck" value="17"/>
|
<Option name="FakeHeck" value="17"/>
|
||||||
|
<Option name="FakeSideways" value="18"/>
|
||||||
<Option name="FakeLeft" value="19"/>
|
<Option name="FakeLeft" value="19"/>
|
||||||
<Option name="FakeRight" value="20"/>
|
<Option name="FakeRight" value="20"/>
|
||||||
<Option name="FakeREdge" value="21"/>
|
<Option name="FakeREdge" value="21"/>
|
||||||
|
2
external/MicroPather
vendored
2
external/MicroPather
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 33a3b8403f1bc3937c9d364fe6c3977169bee3b5
|
Subproject commit c3960ea5af374f2ed6195eb39f803f2611b882a9
|
@ -32,15 +32,6 @@ struct BacktrackData
|
|||||||
int index{ 0 };
|
int index{ 0 };
|
||||||
matrix3x4_t bones[128]{};
|
matrix3x4_t bones[128]{};
|
||||||
};
|
};
|
||||||
struct BestTickData
|
|
||||||
{
|
|
||||||
int tickcount{ 0 };
|
|
||||||
int tick{ 0 };
|
|
||||||
bool operator<(const BestTickData &rhs) const
|
|
||||||
{
|
|
||||||
return tickcount < rhs.tickcount;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
void Init();
|
void Init();
|
||||||
void AddLatencyToNetchan(INetChannel *);
|
void AddLatencyToNetchan(INetChannel *);
|
||||||
void UpdateIncomingSequences();
|
void UpdateIncomingSequences();
|
||||||
|
@ -103,7 +103,7 @@ float DistToSqr(CachedEntity *entity);
|
|||||||
void fClampAngle(Vector &qaAng);
|
void fClampAngle(Vector &qaAng);
|
||||||
// const char* MakeInfoString(IClientEntity* player);
|
// const char* MakeInfoString(IClientEntity* player);
|
||||||
bool GetProjectileData(CachedEntity *weapon, float &speed, float &gravity);
|
bool GetProjectileData(CachedEntity *weapon, float &speed, float &gravity);
|
||||||
bool IsVectorVisible(Vector a, Vector b, bool enviroment_only = false, CachedEntity *self = LOCAL_E);
|
bool IsVectorVisible(Vector a, Vector b, bool enviroment_only = false, CachedEntity *self = LOCAL_E, unsigned int mask = MASK_SHOT_HULL);
|
||||||
Vector GetForwardVector(Vector origin, Vector viewangles, float distance);
|
Vector GetForwardVector(Vector origin, Vector viewangles, float distance);
|
||||||
Vector GetForwardVector(float distance);
|
Vector GetForwardVector(float distance);
|
||||||
bool IsSentryBuster(CachedEntity *ent);
|
bool IsSentryBuster(CachedEntity *ent);
|
||||||
|
@ -26,7 +26,9 @@ extern bool ReadyForCommands;
|
|||||||
extern std::atomic<init_status> status;
|
extern std::atomic<init_status> status;
|
||||||
|
|
||||||
// Nav to vector
|
// Nav to vector
|
||||||
bool navTo(Vector destination, int priority = 5, bool should_repath = true, bool nav_to_local = true, bool is_repath = false);
|
bool navTo(const Vector &destination, int priority = 5, bool should_repath = true, bool nav_to_local = true, bool is_repath = false);
|
||||||
|
// Find closest to vector area
|
||||||
|
CNavArea *findClosestNavSquare(const Vector &vec);
|
||||||
// Check and init navparser
|
// Check and init navparser
|
||||||
bool prepare();
|
bool prepare();
|
||||||
// Clear current path
|
// Clear current path
|
||||||
|
@ -14,8 +14,8 @@ class TextFile
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextFile();
|
TextFile();
|
||||||
void Load(std::string filename);
|
void Load(const std::string &filename);
|
||||||
bool TryLoad(std::string filename);
|
bool TryLoad(const std::string &filename);
|
||||||
size_t LineCount() const;
|
size_t LineCount() const;
|
||||||
const std::string &Line(size_t id) const;
|
const std::string &Line(size_t id) const;
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ static settings::Int equip_primary{ "achievement.equip-primary", "0" };
|
|||||||
static settings::Int equip_secondary{ "achievement.equip-secondary", "0" };
|
static settings::Int equip_secondary{ "achievement.equip-secondary", "0" };
|
||||||
static settings::Int equip_melee{ "achievement.equip-melee", "0" };
|
static settings::Int equip_melee{ "achievement.equip-melee", "0" };
|
||||||
static settings::Int equip_pda2{ "achievement.equip-pda2", "0" };
|
static settings::Int equip_pda2{ "achievement.equip-pda2", "0" };
|
||||||
|
static settings::Boolean hat_troll{ "misc.nohatsforyou", "false" };
|
||||||
|
|
||||||
bool checkachmngr()
|
bool checkachmngr()
|
||||||
{
|
{
|
||||||
@ -158,7 +159,6 @@ CatCommand unlock("achievement_unlock", "Unlock all achievements", Unlock);
|
|||||||
static bool accept_notifs;
|
static bool accept_notifs;
|
||||||
static bool equip_hats;
|
static bool equip_hats;
|
||||||
static bool equip;
|
static bool equip;
|
||||||
static bool equip_first_half;
|
|
||||||
std::vector<Autoequip_unlock_list> equip_queue;
|
std::vector<Autoequip_unlock_list> equip_queue;
|
||||||
|
|
||||||
void unlock_achievements_and_accept(std::vector<int> items)
|
void unlock_achievements_and_accept(std::vector<int> items)
|
||||||
@ -190,16 +190,26 @@ static CatCommand get_best_hats("achievement_cathats", "Get and equip the bencat
|
|||||||
hacks::shared::misc::generate_schema();
|
hacks::shared::misc::generate_schema();
|
||||||
hacks::shared::misc::Schema_Reload();
|
hacks::shared::misc::Schema_Reload();
|
||||||
equip_hats = true;
|
equip_hats = true;
|
||||||
equip_first_half = true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
struct queue_struct
|
||||||
|
{
|
||||||
|
int clazz;
|
||||||
|
int slot;
|
||||||
|
unsigned long long uuid;
|
||||||
|
};
|
||||||
|
static std::deque<queue_struct> gc_queue;
|
||||||
|
|
||||||
bool equip_item(int clazz, int slot, int id)
|
bool equip_item(int clazz, int slot, int id)
|
||||||
{
|
{
|
||||||
auto invmng = re::CTFInventoryManager::GTFInventoryManager();
|
auto invmng = re::CTFInventoryManager::GTFInventoryManager();
|
||||||
auto inv = invmng->GTFPlayerInventory();
|
auto inv = invmng->GTFPlayerInventory();
|
||||||
auto item_view = inv->GetFirstItemOfItemDef(id);
|
auto item_view = inv->GetFirstItemOfItemDef(id);
|
||||||
if (item_view)
|
if (item_view)
|
||||||
return invmng->EquipItemInLoadout(clazz, slot, item_view->UUID());
|
{
|
||||||
|
gc_queue.push_front({ clazz, slot, item_view->UUID() });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,6 +222,33 @@ bool equip_hats_fn(std::vector<int> hats, std::pair<int, int> classes)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<int> hat_list = { 302, 940, 941 };
|
||||||
|
// TNE didn't want me to put "epic_" infront of it :(
|
||||||
|
static Timer hat_steal_timer{};
|
||||||
|
static Timer gc_timer{};
|
||||||
|
|
||||||
|
void CreateMove()
|
||||||
|
{
|
||||||
|
if (gc_queue.size() && gc_timer.test_and_set(3000))
|
||||||
|
{
|
||||||
|
queue_struct item = gc_queue.at(gc_queue.size() - 1);
|
||||||
|
auto invmng = re::CTFInventoryManager::GTFInventoryManager();
|
||||||
|
invmng->EquipItemInLoadout(item.clazz, item.slot, item.uuid);
|
||||||
|
gc_queue.pop_back();
|
||||||
|
}
|
||||||
|
if (!hat_troll)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (CE_BAD(LOCAL_E))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (hat_steal_timer.test_and_set(15000))
|
||||||
|
{
|
||||||
|
std::rotate(hat_list.begin(), hat_list.begin() + 1, hat_list.end());
|
||||||
|
equip_hats_fn(hat_list, { g_pLocalPlayer->clazz, g_pLocalPlayer->clazz });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Callback(int after, int type)
|
void Callback(int after, int type)
|
||||||
{
|
{
|
||||||
if (!after)
|
if (!after)
|
||||||
@ -258,6 +295,84 @@ void Callback(int after, int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Paint()
|
||||||
|
{
|
||||||
|
// Start accepting
|
||||||
|
if (accept_notifs)
|
||||||
|
{
|
||||||
|
accept_time.update();
|
||||||
|
accept_notifs = false;
|
||||||
|
}
|
||||||
|
// "Trigger/Accept first notification" aka Achievement items
|
||||||
|
if (!accept_time.check(5000) && cooldowm.test_and_set(500))
|
||||||
|
g_IEngine->ClientCmd_Unrestricted("cl_trigger_first_notification");
|
||||||
|
|
||||||
|
// Hat equip code
|
||||||
|
if (equip_hats)
|
||||||
|
{
|
||||||
|
// If done start accepting notifications, also time out after a while
|
||||||
|
if (accept_time.check(5000) && !accept_time.check(10000) && cooldowm.test_and_set(500))
|
||||||
|
{
|
||||||
|
// Inventory Manager
|
||||||
|
auto invmng = re::CTFInventoryManager::GTFInventoryManager();
|
||||||
|
// Inventory
|
||||||
|
auto inv = invmng->GTFPlayerInventory();
|
||||||
|
// Frontline field recorder
|
||||||
|
auto item_view1 = inv->GetFirstItemOfItemDef(302);
|
||||||
|
// Gibus
|
||||||
|
auto item_view2 = inv->GetFirstItemOfItemDef(940);
|
||||||
|
// Skull Island Tropper
|
||||||
|
auto item_view3 = inv->GetFirstItemOfItemDef(941);
|
||||||
|
if (item_view1 && item_view2 && item_view3)
|
||||||
|
{
|
||||||
|
if (!accept_time.check(7500))
|
||||||
|
{
|
||||||
|
// Equip these hats on all classes
|
||||||
|
bool success = equip_hats_fn({ 302, 940, 941 }, { tf_scout, tf_engineer });
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
logging::Info("Equipping hats!");
|
||||||
|
equip_hats = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (accept_time.check(10000))
|
||||||
|
equip_hats = false;
|
||||||
|
}
|
||||||
|
// Equip weapons
|
||||||
|
if (equip)
|
||||||
|
{
|
||||||
|
// After 5 seconds of accept time, start
|
||||||
|
if (accept_time.check(5000) && !accept_time.check(10000) && cooldown_2.test_and_set(500))
|
||||||
|
{
|
||||||
|
// Watch for each item and equip it
|
||||||
|
for (int i = 0; i < equip_queue.size(); i++)
|
||||||
|
{
|
||||||
|
auto equip = equip_queue.at(i);
|
||||||
|
bool success = equip_item(equip.player_class, equip.slot, equip.item_id);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
logging::Info("Equipped Item!");
|
||||||
|
equip_queue.erase(equip_queue.begin() + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We did it
|
||||||
|
if (!equip_queue.size())
|
||||||
|
equip = false;
|
||||||
|
}
|
||||||
|
else if (accept_time.check(10000) && cooldown_2.test_and_set(500))
|
||||||
|
{
|
||||||
|
if (equip_queue.size())
|
||||||
|
{
|
||||||
|
logging::Info("Equipping failed!");
|
||||||
|
equip_queue.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static InitRoutine init([]() {
|
static InitRoutine init([]() {
|
||||||
// Primary list
|
// Primary list
|
||||||
primary.push_back(Autoequip_unlock_list("Force-A-Nature", 1036, 45, tf_scout, 0));
|
primary.push_back(Autoequip_unlock_list("Force-A-Nature", 1036, 45, tf_scout, 0));
|
||||||
@ -300,93 +415,16 @@ static InitRoutine init([]() {
|
|||||||
equip_melee.installChangeCallback([](settings::VariableBase<int> &, int after) { Callback(after, 2); });
|
equip_melee.installChangeCallback([](settings::VariableBase<int> &, int after) { Callback(after, 2); });
|
||||||
equip_pda2.installChangeCallback([](settings::VariableBase<int> &, int after) { Callback(after, 3); });
|
equip_pda2.installChangeCallback([](settings::VariableBase<int> &, int after) { Callback(after, 3); });
|
||||||
|
|
||||||
EC::Register(
|
EC::Register(EC::CreateMove, CreateMove, "cm_nohatsforyou");
|
||||||
EC::Paint,
|
EC::Register(EC::Paint, Paint, "achievement_autounlock");
|
||||||
[]() {
|
hat_troll.installChangeCallback([](settings::VariableBase<bool> &, bool after) {
|
||||||
// Start accepting
|
static bool init = false;
|
||||||
if (accept_notifs)
|
if (after && !init)
|
||||||
{
|
{
|
||||||
accept_time.update();
|
hacks::shared::misc::generate_schema();
|
||||||
accept_notifs = false;
|
hacks::shared::misc::Schema_Reload();
|
||||||
|
init = true;
|
||||||
}
|
}
|
||||||
// "Trigger/Accept first notification" aka Achievement items
|
});
|
||||||
if (!accept_time.check(5000) && cooldowm.test_and_set(500))
|
|
||||||
g_IEngine->ClientCmd_Unrestricted("cl_trigger_first_notification");
|
|
||||||
|
|
||||||
// Hat equip code
|
|
||||||
if (equip_hats)
|
|
||||||
{
|
|
||||||
// If done start accepting notifications, also time out after a while
|
|
||||||
if (accept_time.check(5000) && !accept_time.check(10000) && cooldowm.test_and_set(500))
|
|
||||||
{
|
|
||||||
// Inventory Manager
|
|
||||||
auto invmng = re::CTFInventoryManager::GTFInventoryManager();
|
|
||||||
// Inventory
|
|
||||||
auto inv = invmng->GTFPlayerInventory();
|
|
||||||
// Frontline field recorder
|
|
||||||
auto item_view1 = inv->GetFirstItemOfItemDef(302);
|
|
||||||
// Gibus
|
|
||||||
auto item_view2 = inv->GetFirstItemOfItemDef(940);
|
|
||||||
// Skull Island Tropper
|
|
||||||
auto item_view3 = inv->GetFirstItemOfItemDef(941);
|
|
||||||
if (item_view1 && item_view2 && item_view3)
|
|
||||||
{
|
|
||||||
if (!accept_time.check(7500) && equip_first_half)
|
|
||||||
{
|
|
||||||
// Equip these hats on all classes
|
|
||||||
bool success = equip_hats_fn({ 302, 940, 941 }, { tf_scout, tf_medic });
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
logging::Info("Equipped hats on first half!");
|
|
||||||
equip_first_half = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (accept_time.check(7500))
|
|
||||||
{
|
|
||||||
bool success = equip_hats_fn({ 302, 940, 941 }, { tf_heavy, tf_engineer });
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
logging::Info("Equipped hats on second half!");
|
|
||||||
equip_hats = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (accept_time.check(10000))
|
|
||||||
equip_hats = false;
|
|
||||||
}
|
|
||||||
// Equip weapons
|
|
||||||
if (equip)
|
|
||||||
{
|
|
||||||
// After 5 seconds of accept time, start
|
|
||||||
if (accept_time.check(5000) && !accept_time.check(10000) && cooldown_2.test_and_set(500))
|
|
||||||
{
|
|
||||||
// Watch for each item and equip it
|
|
||||||
for (int i = 0; i < equip_queue.size(); i++)
|
|
||||||
{
|
|
||||||
auto equip = equip_queue.at(i);
|
|
||||||
bool success = equip_item(equip.player_class, equip.slot, equip.item_id);
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
logging::Info("Equipped Item!");
|
|
||||||
equip_queue.erase(equip_queue.begin() + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// We did it
|
|
||||||
if (!equip_queue.size())
|
|
||||||
equip = false;
|
|
||||||
}
|
|
||||||
else if (accept_time.check(10000) && cooldown_2.test_and_set(500))
|
|
||||||
{
|
|
||||||
if (equip_queue.size())
|
|
||||||
{
|
|
||||||
logging::Info("Equipping failed!");
|
|
||||||
equip_queue.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"achievement_autounlock");
|
|
||||||
});
|
});
|
||||||
} // namespace hacks::tf2::achievement
|
} // namespace hacks::tf2::achievement
|
||||||
|
@ -21,6 +21,7 @@ static settings::Boolean enable{ "aimbot.enable", "false" };
|
|||||||
static settings::Button aimkey{ "aimbot.aimkey.button", "<null>" };
|
static settings::Button aimkey{ "aimbot.aimkey.button", "<null>" };
|
||||||
static settings::Int aimkey_mode{ "aimbot.aimkey.mode", "1" };
|
static settings::Int aimkey_mode{ "aimbot.aimkey.mode", "1" };
|
||||||
static settings::Boolean autoshoot{ "aimbot.autoshoot", "1" };
|
static settings::Boolean autoshoot{ "aimbot.autoshoot", "1" };
|
||||||
|
static settings::Boolean autoreload{ "aimbot.autoshoot.activate-heatmaker", "false" };
|
||||||
static settings::Boolean autoshoot_disguised{ "aimbot.autoshoot-disguised", "1" };
|
static settings::Boolean autoshoot_disguised{ "aimbot.autoshoot-disguised", "1" };
|
||||||
static settings::Boolean multipoint{ "aimbot.multipoint", "false" };
|
static settings::Boolean multipoint{ "aimbot.multipoint", "false" };
|
||||||
static settings::Int hitbox_mode{ "aimbot.hitbox-mode", "0" };
|
static settings::Int hitbox_mode{ "aimbot.hitbox-mode", "0" };
|
||||||
@ -97,6 +98,12 @@ bool IsBacktracking()
|
|||||||
return (aimkey ? aimkey.isKeyDown() : true) && shouldBacktrack();
|
return (aimkey ? aimkey.isKeyDown() : true) && shouldBacktrack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Am I holding Hitman's Heatmaker ?
|
||||||
|
static bool CarryingHeatmaker()
|
||||||
|
{
|
||||||
|
return CE_INT(LOCAL_W, netvar.iItemDefinitionIndex) == 752;
|
||||||
|
}
|
||||||
|
|
||||||
// Current Entity
|
// Current Entity
|
||||||
int target_eid{ 0 };
|
int target_eid{ 0 };
|
||||||
CachedEntity *target = 0;
|
CachedEntity *target = 0;
|
||||||
@ -787,7 +794,7 @@ void Aim(CachedEntity *entity)
|
|||||||
minz += (maxz - minz) / 6;
|
minz += (maxz - minz) / 6;
|
||||||
// Create Vectors
|
// Create Vectors
|
||||||
const Vector positions[13] = { { minx, centery, minz }, { maxx, centery, minz }, { minx, centery, maxz }, { maxx, centery, maxz }, { centerx, miny, minz }, { centerx, maxy, minz }, { centerx, miny, maxz }, { centerx, maxy, maxz }, { minx, miny, centerz }, { maxx, maxy, centerz }, { minx, miny, centerz }, { maxx, maxy, centerz }, hitboxcenter };
|
const Vector positions[13] = { { minx, centery, minz }, { maxx, centery, minz }, { minx, centery, maxz }, { maxx, centery, maxz }, { centerx, miny, minz }, { centerx, maxy, minz }, { centerx, miny, maxz }, { centerx, maxy, maxz }, { minx, miny, centerz }, { maxx, maxy, centerz }, { minx, miny, centerz }, { maxx, maxy, centerz }, hitboxcenter };
|
||||||
for (int i = 0; i < 14; ++i)
|
for (int i = 0; i < 13; ++i)
|
||||||
if (IsVectorVisible(g_pLocalPlayer->v_Eye, positions[i]))
|
if (IsVectorVisible(g_pLocalPlayer->v_Eye, positions[i]))
|
||||||
{
|
{
|
||||||
tr = (positions[i] - g_pLocalPlayer->v_Eye);
|
tr = (positions[i] - g_pLocalPlayer->v_Eye);
|
||||||
@ -905,7 +912,10 @@ void DoAutoshoot()
|
|||||||
attack = false;
|
attack = false;
|
||||||
|
|
||||||
if (attack)
|
if (attack)
|
||||||
current_user_cmd->buttons |= IN_ATTACK;
|
// TO DO: Sending both reload and attack will activate the hitmans heatmaker ability
|
||||||
|
// Don't activate it only on first kill (or somehow activate it before shoot)
|
||||||
|
current_user_cmd->buttons |= IN_ATTACK | (*autoreload && CarryingHeatmaker() ? IN_RELOAD : 0);
|
||||||
|
|
||||||
if (LOCAL_W->m_iClassID() == CL_CLASS(CTFLaserPointer))
|
if (LOCAL_W->m_iClassID() == CL_CLASS(CTFLaserPointer))
|
||||||
current_user_cmd->buttons |= IN_ATTACK2;
|
current_user_cmd->buttons |= IN_ATTACK2;
|
||||||
hacks::shared::antiaim::SetSafeSpace(1);
|
hacks::shared::antiaim::SetSafeSpace(1);
|
||||||
@ -1025,7 +1035,7 @@ int BestHitbox(CachedEntity *target)
|
|||||||
IF_GAME(IsTF())
|
IF_GAME(IsTF())
|
||||||
{
|
{
|
||||||
int ci = g_pLocalPlayer->weapon()->m_iClassID();
|
int ci = g_pLocalPlayer->weapon()->m_iClassID();
|
||||||
preferred = hitbox_t::pelvis;
|
preferred = hitbox_t::spine_2;
|
||||||
// Sniper rifle
|
// Sniper rifle
|
||||||
if (g_pLocalPlayer->holding_sniper_rifle)
|
if (g_pLocalPlayer->holding_sniper_rifle)
|
||||||
{
|
{
|
||||||
@ -1073,7 +1083,7 @@ int BestHitbox(CachedEntity *target)
|
|||||||
{
|
{
|
||||||
|
|
||||||
float cdmg = CE_FLOAT(LOCAL_W, netvar.flChargedDamage);
|
float cdmg = CE_FLOAT(LOCAL_W, netvar.flChargedDamage);
|
||||||
float bdmg = 50;
|
float bdmg = CarryingHeatmaker() ? 40 : 50;
|
||||||
// Darwins damage correction, protects against 15% of damage
|
// Darwins damage correction, protects against 15% of damage
|
||||||
// if (HasDarwins(target))
|
// if (HasDarwins(target))
|
||||||
// {
|
// {
|
||||||
@ -1125,20 +1135,20 @@ int BestHitbox(CachedEntity *target)
|
|||||||
auto ticks = bt::headPositions[target->m_IDX];
|
auto ticks = bt::headPositions[target->m_IDX];
|
||||||
for (int i = 0; i < 66; i++)
|
for (int i = 0; i < 66; i++)
|
||||||
{
|
{
|
||||||
if (!ticks->tickcount)
|
if (!ticks[i].tickcount)
|
||||||
continue;
|
continue;
|
||||||
if (!bt::ValidTick(ticks[i], target))
|
if (!bt::ValidTick(ticks[i], target))
|
||||||
continue;
|
continue;
|
||||||
if (*backtrackVischeckAll)
|
if (*backtrackVischeckAll)
|
||||||
for (int j = 0; j < 18; j++)
|
for (int j = 0; j < 18; j++)
|
||||||
{
|
{
|
||||||
if (IsEntityVectorVisible(target, ticks->hitboxes.at(j).center))
|
if (IsEntityVectorVisible(target, ticks[i].hitboxes[j].center))
|
||||||
{
|
{
|
||||||
good_tick = { i, target->m_IDX };
|
good_tick = { i, target->m_IDX };
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsEntityVectorVisible(target, ticks->hitboxes.at(0).center))
|
else if (IsEntityVectorVisible(target, ticks[i].hitboxes[0].center))
|
||||||
{
|
{
|
||||||
good_tick = { i, target->m_IDX };
|
good_tick = { i, target->m_IDX };
|
||||||
break;
|
break;
|
||||||
@ -1159,7 +1169,7 @@ int BestHitbox(CachedEntity *target)
|
|||||||
{
|
{
|
||||||
namespace bt = hacks::shared::backtrack;
|
namespace bt = hacks::shared::backtrack;
|
||||||
if (good_tick.first != -1)
|
if (good_tick.first != -1)
|
||||||
if (IsEntityVectorVisible(target, bt::headPositions[target->m_IDX][good_tick.first].hitboxes.at(preferred).center))
|
if (IsEntityVectorVisible(target, bt::headPositions[target->m_IDX - 1][good_tick.first].hitboxes[preferred].center))
|
||||||
return preferred;
|
return preferred;
|
||||||
}
|
}
|
||||||
else if (target->hitboxes.VisibilityCheck(preferred))
|
else if (target->hitboxes.VisibilityCheck(preferred))
|
||||||
@ -1191,11 +1201,11 @@ int BestHitbox(CachedEntity *target)
|
|||||||
auto ticks = bt::headPositions[target->m_IDX];
|
auto ticks = bt::headPositions[target->m_IDX];
|
||||||
for (int i = 0; i < 66; i++)
|
for (int i = 0; i < 66; i++)
|
||||||
{
|
{
|
||||||
if (!ticks->tickcount)
|
if (!ticks[i].tickcount)
|
||||||
continue;
|
continue;
|
||||||
if (!bt::ValidTick(ticks[i], target))
|
if (!bt::ValidTick(ticks[i], target))
|
||||||
continue;
|
continue;
|
||||||
if (IsEntityVectorVisible(target, ticks->hitboxes.at(hb).center))
|
if (IsEntityVectorVisible(target, ticks[i].hitboxes[hb].center))
|
||||||
{
|
{
|
||||||
good_tick = { i, target->m_IDX };
|
good_tick = { i, target->m_IDX };
|
||||||
break;
|
break;
|
||||||
@ -1216,11 +1226,11 @@ int BestHitbox(CachedEntity *target)
|
|||||||
auto ticks = bt::headPositions[target->m_IDX];
|
auto ticks = bt::headPositions[target->m_IDX];
|
||||||
for (int i = 0; i < 66; i++)
|
for (int i = 0; i < 66; i++)
|
||||||
{
|
{
|
||||||
if (!ticks->tickcount)
|
if (!ticks[i].tickcount)
|
||||||
continue;
|
continue;
|
||||||
if (!bt::ValidTick(ticks[i], target))
|
if (!bt::ValidTick(ticks[i], target))
|
||||||
continue;
|
continue;
|
||||||
if (IsEntityVectorVisible(target, ticks->hitboxes.at(hb).center))
|
if (IsEntityVectorVisible(target, ticks[i].hitboxes[hb].center))
|
||||||
{
|
{
|
||||||
good_tick = { i, target->m_IDX };
|
good_tick = { i, target->m_IDX };
|
||||||
break;
|
break;
|
||||||
|
@ -18,6 +18,8 @@ float used_yaw = 0.0f;
|
|||||||
static settings::Boolean enable{ "antiaim.enable", "0" };
|
static settings::Boolean enable{ "antiaim.enable", "0" };
|
||||||
static settings::Float yaw{ "antiaim.yaw.static", "0" };
|
static settings::Float yaw{ "antiaim.yaw.static", "0" };
|
||||||
static settings::Int yaw_mode{ "antiaim.yaw.mode", "0" };
|
static settings::Int yaw_mode{ "antiaim.yaw.mode", "0" };
|
||||||
|
static settings::Int yaw_sideways_min{ "antiaim.yaw.sideways.min", "0" };
|
||||||
|
static settings::Int yaw_sideways_max{ "antiaim.yaw.sideways.max", "4" };
|
||||||
|
|
||||||
static settings::Float pitch{ "antiaim.pitch.static", "0" };
|
static settings::Float pitch{ "antiaim.pitch.static", "0" };
|
||||||
static settings::Int pitch_mode{ "antiaim.pitch.mode", "0" };
|
static settings::Int pitch_mode{ "antiaim.pitch.mode", "0" };
|
||||||
@ -369,6 +371,14 @@ void ProcessUserCmd(CUserCmd *cmd)
|
|||||||
static bool bsendflip = true;
|
static bool bsendflip = true;
|
||||||
static float rngyaw = 0.0f;
|
static float rngyaw = 0.0f;
|
||||||
bool clamp = !no_clamping;
|
bool clamp = !no_clamping;
|
||||||
|
|
||||||
|
static int ticksUntilSwap = 0;
|
||||||
|
static bool swap = true;
|
||||||
|
|
||||||
|
if (ticksUntilSwap > 0 && *yaw_mode != 18) {
|
||||||
|
swap = true;
|
||||||
|
ticksUntilSwap = 0;
|
||||||
|
}
|
||||||
switch ((int) yaw_mode)
|
switch ((int) yaw_mode)
|
||||||
{
|
{
|
||||||
case 1: // FIXED
|
case 1: // FIXED
|
||||||
@ -481,8 +491,14 @@ void ProcessUserCmd(CUserCmd *cmd)
|
|||||||
clamp = false;
|
clamp = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 20:
|
|
||||||
case 18: // Fake sideways
|
case 18: // Fake sideways
|
||||||
|
if (*bSendPackets && ticksUntilSwap--) {
|
||||||
|
ticksUntilSwap = UniformRandomInt(*yaw_sideways_min, *yaw_sideways_max);
|
||||||
|
swap = !swap;
|
||||||
|
}
|
||||||
|
y += *bSendPackets ^ swap ? 90.0f : -90.0f;
|
||||||
|
break;
|
||||||
|
case 20: // Fake right
|
||||||
y += *bSendPackets ? 90.0f : -90.0f;
|
y += *bSendPackets ? 90.0f : -90.0f;
|
||||||
break;
|
break;
|
||||||
case 19: // Fake left
|
case 19: // Fake left
|
||||||
|
@ -611,39 +611,8 @@ void CreateMove()
|
|||||||
current_user_cmd->buttons |= IN_ATTACK2;
|
current_user_cmd->buttons |= IN_ATTACK2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!steamid && !enable)
|
if ((!steamid && !enable) || GetWeaponMode() != weapon_medigun)
|
||||||
return;
|
return;
|
||||||
if (GetWeaponMode() != weapon_medigun)
|
|
||||||
return;
|
|
||||||
/*if (force_healing_target)
|
|
||||||
{
|
|
||||||
CachedEntity *target = ENTITY(force_healing_target);
|
|
||||||
if (CE_GOOD(target))
|
|
||||||
{
|
|
||||||
if (target->player_info.friendsID != steamid || !CanHeal(force_healing_target))
|
|
||||||
force_healing_target = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
force_healing_target = 0;
|
|
||||||
}
|
|
||||||
else if (steamid)
|
|
||||||
{
|
|
||||||
for (int i = 1; i <= g_IEngine->GetMaxClients(); i++)
|
|
||||||
{
|
|
||||||
CachedEntity *ent = ENTITY(i);
|
|
||||||
if (CE_BAD(ent) || !ent->player_info.friendsID)
|
|
||||||
continue;
|
|
||||||
if (ent->player_info.friendsID == steamid && CanHeal(i))
|
|
||||||
{
|
|
||||||
force_healing_target = steamid;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
bool healing_steamid = false;
|
bool healing_steamid = false;
|
||||||
if (steamid)
|
if (steamid)
|
||||||
{
|
{
|
||||||
|
@ -24,6 +24,7 @@ static settings::Int slots{ "backtrack.slots", "0" };
|
|||||||
settings::Boolean enable{ "backtrack.enable", "false" };
|
settings::Boolean enable{ "backtrack.enable", "false" };
|
||||||
settings::Boolean backtrack_chams_glow{ "backtrack.chams_glow", "true" };
|
settings::Boolean backtrack_chams_glow{ "backtrack.chams_glow", "true" };
|
||||||
settings::Int latency{ "backtrack.latency", "0" };
|
settings::Int latency{ "backtrack.latency", "0" };
|
||||||
|
settings::Boolean enable_latency_rampup{ "backtrack.latency.rampup", "true" };
|
||||||
|
|
||||||
void EmptyBacktrackData(BacktrackData &i);
|
void EmptyBacktrackData(BacktrackData &i);
|
||||||
std::pair<int, int> getBestEntBestTick();
|
std::pair<int, int> getBestEntBestTick();
|
||||||
@ -51,19 +52,14 @@ void UpdateIncomingSequences()
|
|||||||
sequences.pop_back();
|
sequences.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddLatencyToNetchan(INetChannel *ch)
|
void AddLatencyToNetchan(INetChannel *ch)
|
||||||
{
|
{
|
||||||
if (!isBacktrackEnabled)
|
if (!isBacktrackEnabled)
|
||||||
return;
|
return;
|
||||||
float Latency = *latency;
|
|
||||||
if (Latency > 1000.0f)
|
|
||||||
Latency = 800.0f;
|
|
||||||
Latency -= getRealLatency();
|
|
||||||
if (Latency < 0.0f)
|
|
||||||
Latency = 0.0f;
|
|
||||||
for (auto &seq : sequences)
|
for (auto &seq : sequences)
|
||||||
{
|
{
|
||||||
if (g_GlobalVars->realtime - seq.curtime > Latency / 1000.0f)
|
if (g_GlobalVars->realtime - seq.curtime > getLatency() / 1000.0f)
|
||||||
{
|
{
|
||||||
ch->m_nInReliableState = seq.inreliablestate;
|
ch->m_nInReliableState = seq.inreliablestate;
|
||||||
ch->m_nInSequenceNr = seq.sequencenr;
|
ch->m_nInSequenceNr = seq.sequencenr;
|
||||||
@ -84,13 +80,21 @@ int BestTick = -1;
|
|||||||
int iBestTarget = -1;
|
int iBestTarget = -1;
|
||||||
bool istickvalid[33][66]{};
|
bool istickvalid[33][66]{};
|
||||||
bool istickinvalid[33][66]{};
|
bool istickinvalid[33][66]{};
|
||||||
|
static float latency_rampup = 0.0f;
|
||||||
|
|
||||||
static void Run()
|
static void Run()
|
||||||
{
|
{
|
||||||
if (!shouldBacktrack())
|
if (!shouldBacktrack())
|
||||||
{
|
{
|
||||||
isBacktrackEnabled = false;
|
isBacktrackEnabled = false;
|
||||||
|
latency_rampup = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Limit to 2 ticks
|
||||||
|
latency_rampup += 1.0f / 66.0f;
|
||||||
|
latency_rampup = std::min(latency_rampup, 1.0f);
|
||||||
|
|
||||||
UpdateIncomingSequences();
|
UpdateIncomingSequences();
|
||||||
isBacktrackEnabled = true;
|
isBacktrackEnabled = true;
|
||||||
|
|
||||||
@ -341,11 +345,11 @@ float getLatency()
|
|||||||
if (!ch)
|
if (!ch)
|
||||||
return 0;
|
return 0;
|
||||||
float Latency = *latency;
|
float Latency = *latency;
|
||||||
if (Latency > 1000.0f)
|
Latency = std::min(Latency, 800.0f);
|
||||||
Latency = 800.0f;
|
|
||||||
Latency -= getRealLatency();
|
Latency -= getRealLatency();
|
||||||
if (Latency < 0.0f)
|
Latency = std::max(Latency, 0.0f);
|
||||||
Latency = 0.0f;
|
if (enable_latency_rampup)
|
||||||
|
Latency = Latency * latency_rampup;
|
||||||
return Latency;
|
return Latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ IClientEntity *GetActiveTFWeapon_detour(IClientEntity *this_ /* C_TFPlayer * */)
|
|||||||
QAngle angle = *(QAngle *) &NET_VECTOR(this_, netvar.angEyeAngles);
|
QAngle angle = *(QAngle *) &NET_VECTOR(this_, netvar.angEyeAngles);
|
||||||
if (isLocal)
|
if (isLocal)
|
||||||
{
|
{
|
||||||
g_IEngine->GetViewAngles(angle);
|
angle = VectorToQAngle(current_user_cmd->viewangles);
|
||||||
eyePos = g_pLocalPlayer->v_Eye;
|
eyePos = g_pLocalPlayer->v_Eye;
|
||||||
}
|
}
|
||||||
Vector forward;
|
Vector forward;
|
||||||
|
@ -198,7 +198,7 @@ static bool isValidNearPosition(Vector vec, Vector target, const bot_class_confi
|
|||||||
float dist = vec.DistTo(target);
|
float dist = vec.DistTo(target);
|
||||||
if (dist < config.min || dist > config.max)
|
if (dist < config.min || dist > config.max)
|
||||||
return false;
|
return false;
|
||||||
if (!IsVectorVisible(vec, target, true))
|
if (!IsVectorVisible(vec, target, true, LOCAL_E, MASK_PLAYERSOLID))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -341,13 +341,12 @@ void createMove()
|
|||||||
{
|
{
|
||||||
if (current_index >= source->size())
|
if (current_index >= source->size())
|
||||||
current_index = 0;
|
current_index = 0;
|
||||||
if (random_order && source->size())
|
if (random_order && source->size() > 1)
|
||||||
{
|
{
|
||||||
current_index = rand() % source->size();
|
current_index = UniformRandomInt(0, source->size() - 1);
|
||||||
int tries = 0;
|
while (current_index == last_index)
|
||||||
while (current_index == last_index && tries++ < 1000)
|
|
||||||
{
|
{
|
||||||
current_index = rand() % source->size();
|
current_index = UniformRandomInt(0, source->size() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_index = current_index;
|
last_index = current_index;
|
||||||
|
@ -1177,7 +1177,7 @@ netvar.iHealth));
|
|||||||
return buf;
|
return buf;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
bool IsVectorVisible(Vector origin, Vector target, bool enviroment_only, CachedEntity *self)
|
bool IsVectorVisible(Vector origin, Vector target, bool enviroment_only, CachedEntity *self, unsigned int mask)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!enviroment_only)
|
if (!enviroment_only)
|
||||||
@ -1188,7 +1188,7 @@ bool IsVectorVisible(Vector origin, Vector target, bool enviroment_only, CachedE
|
|||||||
trace::filter_no_player.SetSelf(RAW_ENT(self));
|
trace::filter_no_player.SetSelf(RAW_ENT(self));
|
||||||
ray.Init(origin, target);
|
ray.Init(origin, target);
|
||||||
PROF_SECTION(IEVV_TraceRay);
|
PROF_SECTION(IEVV_TraceRay);
|
||||||
g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_no_player, &trace_visible);
|
g_ITrace->TraceRay(ray, mask, &trace::filter_no_player, &trace_visible);
|
||||||
return (trace_visible.fraction == 1.0f);
|
return (trace_visible.fraction == 1.0f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1199,7 +1199,7 @@ bool IsVectorVisible(Vector origin, Vector target, bool enviroment_only, CachedE
|
|||||||
trace::filter_no_entity.SetSelf(RAW_ENT(self));
|
trace::filter_no_entity.SetSelf(RAW_ENT(self));
|
||||||
ray.Init(origin, target);
|
ray.Init(origin, target);
|
||||||
PROF_SECTION(IEVV_TraceRay);
|
PROF_SECTION(IEVV_TraceRay);
|
||||||
g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_no_entity, &trace_visible);
|
g_ITrace->TraceRay(ray, mask, &trace::filter_no_entity, &trace_visible);
|
||||||
return (trace_visible.fraction == 1.0f);
|
return (trace_visible.fraction == 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,23 +10,17 @@ namespace hooked_methods
|
|||||||
{
|
{
|
||||||
DEFINE_HOOKED_METHOD(SendDatagram, int, INetChannel *ch, bf_write *buf)
|
DEFINE_HOOKED_METHOD(SendDatagram, int, INetChannel *ch, bf_write *buf)
|
||||||
{
|
{
|
||||||
if (!round(*hacks::shared::backtrack::latency) || !isHackActive())
|
if (!isHackActive() || !ch || CE_BAD(LOCAL_E) || !round(*hacks::shared::backtrack::latency))
|
||||||
return original::SendDatagram(ch, buf);
|
return original::SendDatagram(ch, buf);
|
||||||
int in = 0;
|
|
||||||
int state = 0;
|
int in = ch->m_nInSequenceNr;
|
||||||
if (CE_GOOD(LOCAL_E) && ch)
|
int state = ch->m_nInReliableState;
|
||||||
{
|
|
||||||
in = ch->m_nInSequenceNr;
|
|
||||||
state = ch->m_nInReliableState;
|
|
||||||
hacks::shared::backtrack::AddLatencyToNetchan(ch);
|
hacks::shared::backtrack::AddLatencyToNetchan(ch);
|
||||||
}
|
|
||||||
|
|
||||||
int ret = original::SendDatagram(ch, buf);
|
int ret = original::SendDatagram(ch, buf);
|
||||||
if (CE_GOOD(LOCAL_E) && ch)
|
|
||||||
{
|
|
||||||
ch->m_nInSequenceNr = in;
|
ch->m_nInSequenceNr = in;
|
||||||
ch->m_nInReliableState = state;
|
ch->m_nInReliableState = state;
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
} // namespace hooked_methods
|
} // namespace hooked_methods
|
||||||
|
@ -231,6 +231,9 @@ void UpdateTemporaryData()
|
|||||||
|
|
||||||
void StoreClientData()
|
void StoreClientData()
|
||||||
{
|
{
|
||||||
|
if (!peer)
|
||||||
|
return;
|
||||||
|
|
||||||
UpdateServerAddress();
|
UpdateServerAddress();
|
||||||
user_data_s &data = peer->memory->peer_user_data[peer->client_id];
|
user_data_s &data = peer->memory->peer_user_data[peer->client_id];
|
||||||
data.friendid = g_ISteamUser->GetSteamID().GetAccountID();
|
data.friendid = g_ISteamUser->GetSteamID().GetAccountID();
|
||||||
|
@ -15,11 +15,14 @@ namespace nav
|
|||||||
static settings::Boolean enabled{ "misc.pathing", "true" };
|
static settings::Boolean enabled{ "misc.pathing", "true" };
|
||||||
// Whether or not to run vischecks at pathtime
|
// Whether or not to run vischecks at pathtime
|
||||||
static settings::Boolean vischecks{ "misc.pathing.pathtime-vischecks", "true" };
|
static settings::Boolean vischecks{ "misc.pathing.pathtime-vischecks", "true" };
|
||||||
|
static settings::Boolean vischeckBlock{ "misc.pathing.pathtime-vischeck-block", "false" };
|
||||||
static settings::Boolean draw{ "misc.pathing.draw", "false" };
|
static settings::Boolean draw{ "misc.pathing.draw", "false" };
|
||||||
static settings::Boolean look{ "misc.pathing.look-at-path", "false" };
|
static settings::Boolean look{ "misc.pathing.look-at-path", "false" };
|
||||||
static settings::Int stuck_time{ "misc.pathing.stuck-time", "4000" };
|
static settings::Int stuck_time{ "misc.pathing.stuck-time", "4000" };
|
||||||
|
static settings::Int unreachable_time{ "misc.pathing.unreachable-time", "1000" };
|
||||||
|
|
||||||
static std::vector<Vector> crumbs;
|
static std::vector<CNavArea*> crumbs;
|
||||||
|
static Vector startPoint, endPoint;
|
||||||
|
|
||||||
enum ignore_status : uint8_t
|
enum ignore_status : uint8_t
|
||||||
{
|
{
|
||||||
@ -48,72 +51,57 @@ struct ignoredata
|
|||||||
Timer ignoreTimeout{};
|
Timer ignoreTimeout{};
|
||||||
};
|
};
|
||||||
|
|
||||||
CNavArea *getNavArea(Vector &vec)
|
Vector GetClosestCornerToArea(CNavArea *CornerOf, const Vector &target)
|
||||||
{
|
{
|
||||||
for (auto &i : navfile->m_areas)
|
std::array<Vector, 4> corners{
|
||||||
|
CornerOf->m_nwCorner, // NW
|
||||||
|
CornerOf->m_seCorner, // SE
|
||||||
|
{ CornerOf->m_seCorner.x, CornerOf->m_nwCorner.y, CornerOf->m_nwCorner.z },// NE
|
||||||
|
{ CornerOf->m_nwCorner.x, CornerOf->m_seCorner.y, CornerOf->m_seCorner.z } // SW
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector *bestVec = &corners[0], *bestVec2 = bestVec;
|
||||||
|
float bestDist = corners[0].DistTo(target), bestDist2 = bestDist;
|
||||||
|
|
||||||
|
for (size_t i = 1; i < corners.size(); i++)
|
||||||
{
|
{
|
||||||
if (vec == i.m_center)
|
float dist = corners[i].DistTo(target);
|
||||||
return &i;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (size_t i = 0; i < corners.size(); i++)
|
|
||||||
{
|
|
||||||
float dist = corners.at(i).DistTo(Target->m_center);
|
|
||||||
if (dist < bestDist)
|
if (dist < bestDist)
|
||||||
{
|
{
|
||||||
bestVec = corners.at(i);
|
bestVec = &corners[i];
|
||||||
bestDist = dist;
|
bestDist = dist;
|
||||||
}
|
}
|
||||||
}
|
if (corners[i] == *bestVec2)
|
||||||
|
|
||||||
Vector bestVec2{};
|
|
||||||
float bestDist2 = FLT_MAX;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < corners.size(); i++)
|
|
||||||
{
|
|
||||||
if (corners.at(i) == bestVec2)
|
|
||||||
continue;
|
continue;
|
||||||
float dist = corners.at(i).DistTo(Target->m_center);
|
|
||||||
if (dist < bestDist2)
|
if (dist < bestDist2)
|
||||||
{
|
{
|
||||||
bestVec2 = corners.at(i);
|
bestVec2 = &corners[i];
|
||||||
bestDist2 = dist;
|
bestDist2 = dist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (bestVec + bestVec2) / 2;
|
return (*bestVec + *bestVec2) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getZBetweenAreas(CNavArea *start, CNavArea *end)
|
float getZBetweenAreas(CNavArea *start, CNavArea *end)
|
||||||
{
|
{
|
||||||
float z1 = GetClosestCornerToArea(start, end).z;
|
float z1 = GetClosestCornerToArea(start, end->m_center).z;
|
||||||
float z2 = GetClosestCornerToArea(end, start).z;
|
float z2 = GetClosestCornerToArea(end, start->m_center).z;
|
||||||
|
|
||||||
return z2 - z1;
|
return z2 - z1;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ignoremanager
|
|
||||||
|
static std::unordered_map<std::pair<CNavArea *, CNavArea *>, ignoredata, boost::hash<std::pair<CNavArea *, CNavArea *>>> ignores;
|
||||||
|
namespace ignoremanager
|
||||||
{
|
{
|
||||||
static std::unordered_map<std::pair<CNavArea *, CNavArea *>, ignoredata, boost::hash<std::pair<CNavArea *, CNavArea *>>> ignores;
|
|
||||||
static bool vischeck(CNavArea *begin, CNavArea *end)
|
static bool vischeck(CNavArea *begin, CNavArea *end)
|
||||||
{
|
{
|
||||||
Vector first = begin->m_center;
|
Vector first = begin->m_center;
|
||||||
Vector second = end->m_center;
|
Vector second = end->m_center;
|
||||||
first.z += 42;
|
first.z += 42;
|
||||||
second.z += 42;
|
second.z += 42;
|
||||||
return IsVectorVisible(first, second, true);
|
return IsVectorVisible(first, second, true, LOCAL_E, MASK_PLAYERSOLID);
|
||||||
}
|
}
|
||||||
static ignore_status runIgnoreChecks(CNavArea *begin, CNavArea *end)
|
static ignore_status runIgnoreChecks(CNavArea *begin, CNavArea *end)
|
||||||
{
|
{
|
||||||
@ -197,8 +185,8 @@ class ignoremanager
|
|||||||
// Vischecks
|
// Vischecks
|
||||||
for (size_t i = 0; i < crumbs.size() - 1; i++)
|
for (size_t i = 0; i < crumbs.size() - 1; i++)
|
||||||
{
|
{
|
||||||
CNavArea *begin = getNavArea(crumbs.at(i));
|
CNavArea *begin = crumbs[i];
|
||||||
CNavArea *end = getNavArea(crumbs.at(i + 1));
|
CNavArea *end = crumbs[i + 1];
|
||||||
if (!begin || !end)
|
if (!begin || !end)
|
||||||
continue;
|
continue;
|
||||||
ignoredata &data = ignores[{ begin, end }];
|
ignoredata &data = ignores[{ begin, end }];
|
||||||
@ -218,14 +206,12 @@ class ignoremanager
|
|||||||
if (perform_repath)
|
if (perform_repath)
|
||||||
repath();
|
repath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
// 0 = Not ignored, 1 = low priority, 2 = ignored
|
// 0 = Not ignored, 1 = low priority, 2 = ignored
|
||||||
static int isIgnored(CNavArea *begin, CNavArea *end)
|
static int isIgnored(CNavArea *begin, CNavArea *end)
|
||||||
{
|
{
|
||||||
if (ignores[{ end, nullptr }].status == danger_found)
|
if (ignores[{ end, nullptr }].status == danger_found)
|
||||||
return 2;
|
return 2;
|
||||||
ignore_status &status = ignores[{ begin, end }].status;
|
ignore_status status = ignores[{ begin, end }].status;
|
||||||
if (status == unknown)
|
if (status == unknown)
|
||||||
status = runIgnoreChecks(begin, end);
|
status = runIgnoreChecks(begin, end);
|
||||||
if (status == vischeck_success)
|
if (status == vischeck_success)
|
||||||
@ -235,8 +221,27 @@ public:
|
|||||||
else
|
else
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
static bool addTime(ignoredata &connection, ignore_status status)
|
||||||
|
{
|
||||||
|
connection.status = status;
|
||||||
|
connection.ignoreTimeout.update();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static bool addTime(CNavArea *begin, CNavArea *end, ignore_status status)
|
||||||
|
{
|
||||||
|
logging::Info("Ignored Connection %i-%i", begin->m_id, end->m_id);
|
||||||
|
return addTime(ignores[{ begin, end }], status);
|
||||||
|
}
|
||||||
static bool addTime(CNavArea *begin, CNavArea *end, Timer &time)
|
static bool addTime(CNavArea *begin, CNavArea *end, Timer &time)
|
||||||
{
|
{
|
||||||
|
if (!begin || !end)
|
||||||
|
{
|
||||||
|
// We can't reach the destination vector. Destination vector might
|
||||||
|
// be out of bounds/reach.
|
||||||
|
clearInstructions();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
// Check if connection is already known
|
// Check if connection is already known
|
||||||
if (ignores.find({ begin, end }) == ignores.end())
|
if (ignores.find({ begin, end }) == ignores.end())
|
||||||
@ -247,27 +252,11 @@ public:
|
|||||||
connection.stucktime += duration_cast<milliseconds>(system_clock::now() - time.last).count();
|
connection.stucktime += duration_cast<milliseconds>(system_clock::now() - time.last).count();
|
||||||
if (connection.stucktime >= *stuck_time)
|
if (connection.stucktime >= *stuck_time)
|
||||||
{
|
{
|
||||||
connection.status = explicit_ignored;
|
|
||||||
connection.ignoreTimeout.update();
|
|
||||||
logging::Info("Ignored Connection %i-%i", begin->m_id, end->m_id);
|
logging::Info("Ignored Connection %i-%i", begin->m_id, end->m_id);
|
||||||
return true;
|
return addTime(connection, explicit_ignored);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool addTime(Vector &begin, Vector &end, Timer &time)
|
|
||||||
{
|
|
||||||
// todo: check nullptr
|
|
||||||
CNavArea *begin_area = getNavArea(begin);
|
|
||||||
CNavArea *end_area = getNavArea(end);
|
|
||||||
if (!begin_area || !end_area)
|
|
||||||
{
|
|
||||||
// We can't reach the destination vector. Destination vector might
|
|
||||||
// be out of bounds/reach.
|
|
||||||
crumbs.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return addTime(begin_area, end_area, time);
|
|
||||||
}
|
|
||||||
static void reset()
|
static void reset()
|
||||||
{
|
{
|
||||||
ignores.clear();
|
ignores.clear();
|
||||||
@ -329,21 +318,16 @@ public:
|
|||||||
{
|
{
|
||||||
return !(ignores[{ area, nullptr }].status == danger_found);
|
return !(ignores[{ area, nullptr }].status == danger_found);
|
||||||
}
|
}
|
||||||
ignoremanager() = delete;
|
|
||||||
};
|
};
|
||||||
std::unordered_map<std::pair<CNavArea *, CNavArea *>, ignoredata, boost::hash<std::pair<CNavArea *, CNavArea *>>> ignoremanager::ignores;
|
|
||||||
|
|
||||||
struct Graph : public micropather::Graph
|
struct Graph : public micropather::Graph
|
||||||
{
|
{
|
||||||
std::unique_ptr<micropather::MicroPather> pather;
|
std::unique_ptr<micropather::MicroPather> pather;
|
||||||
|
|
||||||
Graph()
|
Graph() {
|
||||||
{
|
|
||||||
pather = std::make_unique<micropather::MicroPather>(this, 3000, 6, true);
|
pather = std::make_unique<micropather::MicroPather>(this, 3000, 6, true);
|
||||||
}
|
}
|
||||||
~Graph() override
|
~Graph() override {}
|
||||||
{
|
|
||||||
}
|
|
||||||
void AdjacentCost(void *state, MP_VECTOR<micropather::StateCost> *adjacent) override
|
void AdjacentCost(void *state, MP_VECTOR<micropather::StateCost> *adjacent) override
|
||||||
{
|
{
|
||||||
CNavArea *center = static_cast<CNavArea *>(state);
|
CNavArea *center = static_cast<CNavArea *>(state);
|
||||||
@ -354,22 +338,21 @@ struct Graph : public micropather::Graph
|
|||||||
if (isIgnored == 2)
|
if (isIgnored == 2)
|
||||||
continue;
|
continue;
|
||||||
float distance = center->m_center.DistTo(i.area->m_center);
|
float distance = center->m_center.DistTo(i.area->m_center);
|
||||||
if (isIgnored == 1)
|
if (isIgnored == 1) {
|
||||||
|
if (*vischeckBlock)
|
||||||
|
continue;
|
||||||
distance += 50000;
|
distance += 50000;
|
||||||
micropather::StateCost cost{ static_cast<void *>(neighbour), distance };
|
}
|
||||||
adjacent->push_back(cost);
|
adjacent->emplace_back(micropather::StateCost{ reinterpret_cast<void *>(neighbour), distance });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float LeastCostEstimate(void *stateStart, void *stateEnd) override
|
float LeastCostEstimate(void *stateStart, void *stateEnd) override
|
||||||
{
|
{
|
||||||
CNavArea *start = static_cast<CNavArea *>(stateStart);
|
CNavArea *start = reinterpret_cast<CNavArea *>(stateStart);
|
||||||
CNavArea *end = static_cast<CNavArea *>(stateEnd);
|
CNavArea *end = reinterpret_cast<CNavArea *>(stateEnd);
|
||||||
return start->m_center.DistTo(end->m_center);
|
return start->m_center.DistTo(end->m_center);
|
||||||
}
|
}
|
||||||
void PrintStateInfo(void *) override
|
void PrintStateInfo(void *) override {}
|
||||||
{
|
|
||||||
// Uhh no
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Navfile containing areas
|
// Navfile containing areas
|
||||||
@ -414,6 +397,7 @@ void initThread()
|
|||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
|
endPoint.Invalidate();
|
||||||
ignoremanager::reset();
|
ignoremanager::reset();
|
||||||
status = initing;
|
status = initing;
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
@ -437,123 +421,100 @@ bool prepare()
|
|||||||
|
|
||||||
// This prevents the bot from gettings completely stuck in some cases
|
// This prevents the bot from gettings completely stuck in some cases
|
||||||
static std::vector<CNavArea *> findClosestNavSquare_localAreas(6);
|
static std::vector<CNavArea *> findClosestNavSquare_localAreas(6);
|
||||||
|
|
||||||
// Function for getting closest Area to player, aka "LocalNav"
|
// Function for getting closest Area to player, aka "LocalNav"
|
||||||
CNavArea *findClosestNavSquare(Vector vec)
|
CNavArea *findClosestNavSquare(const Vector &vec)
|
||||||
{
|
{
|
||||||
if (findClosestNavSquare_localAreas.size() > 5)
|
bool isLocal = vec == g_pLocalPlayer->v_Origin;
|
||||||
|
if (isLocal && findClosestNavSquare_localAreas.size() > 5)
|
||||||
findClosestNavSquare_localAreas.erase(findClosestNavSquare_localAreas.begin());
|
findClosestNavSquare_localAreas.erase(findClosestNavSquare_localAreas.begin());
|
||||||
|
|
||||||
bool is_local = vec == g_pLocalPlayer->v_Origin;
|
float ovBestDist = FLT_MAX, bestDist = FLT_MAX;
|
||||||
|
// If multiple candidates for LocalNav have been found, pick the closest
|
||||||
auto &areas = navfile->m_areas;
|
CNavArea *ovBestSquare = nullptr, *bestSquare = nullptr;
|
||||||
std::vector<CNavArea *> overlapping;
|
for (auto &i : navfile->m_areas)
|
||||||
|
|
||||||
for (auto &i : areas)
|
|
||||||
{
|
|
||||||
// Check if we are within x and y bounds of an area
|
|
||||||
if (i.IsOverlapping(vec))
|
|
||||||
{
|
{
|
||||||
// Make sure we're not stuck on the same area for too long
|
// Make sure we're not stuck on the same area for too long
|
||||||
if (std::count(findClosestNavSquare_localAreas.begin(), findClosestNavSquare_localAreas.end(), &i) < 3)
|
if (isLocal && std::count(findClosestNavSquare_localAreas.begin(),
|
||||||
|
findClosestNavSquare_localAreas.end(), &i) >= 3)
|
||||||
{
|
{
|
||||||
if (IsVectorVisible(vec, i.m_center, true))
|
continue;
|
||||||
overlapping.push_back(&i);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If multiple candidates for LocalNav have been found, pick the closest
|
|
||||||
float bestDist = FLT_MAX;
|
|
||||||
CNavArea *bestSquare = nullptr;
|
|
||||||
for (auto &i : overlapping)
|
|
||||||
{
|
|
||||||
float dist = i->m_center.DistTo(vec);
|
|
||||||
if (dist < bestDist)
|
|
||||||
{
|
|
||||||
bestDist = dist;
|
|
||||||
bestSquare = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bestSquare != nullptr)
|
|
||||||
{
|
|
||||||
if (is_local)
|
|
||||||
findClosestNavSquare_localAreas.push_back(bestSquare);
|
|
||||||
return bestSquare;
|
|
||||||
}
|
|
||||||
// If no LocalNav was found, pick the closest available Area
|
|
||||||
bestDist = FLT_MAX;
|
|
||||||
for (auto &i : areas)
|
|
||||||
{
|
|
||||||
float dist = i.m_center.DistTo(vec);
|
float dist = i.m_center.DistTo(vec);
|
||||||
if (dist < bestDist)
|
if (dist < bestDist)
|
||||||
{
|
|
||||||
if (std::count(findClosestNavSquare_localAreas.begin(), findClosestNavSquare_localAreas.end(), &i) < 3)
|
|
||||||
{
|
{
|
||||||
bestDist = dist;
|
bestDist = dist;
|
||||||
bestSquare = &i;
|
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))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
ovBestDist = dist;
|
||||||
|
ovBestSquare = &i;
|
||||||
}
|
}
|
||||||
if (is_local)
|
if (!ovBestSquare)
|
||||||
findClosestNavSquare_localAreas.push_back(bestSquare);
|
ovBestSquare = bestSquare;
|
||||||
return bestSquare;
|
|
||||||
|
if (isLocal)
|
||||||
|
findClosestNavSquare_localAreas.push_back(ovBestSquare);
|
||||||
|
|
||||||
|
return ovBestSquare;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Vector> findPath(Vector start, Vector end)
|
std::vector<CNavArea*> findPath(const Vector &start, const Vector &end)
|
||||||
{
|
{
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
if (status != on)
|
if (status != on)
|
||||||
return {};
|
return {};
|
||||||
CNavArea *local = findClosestNavSquare(start);
|
|
||||||
CNavArea *dest = findClosestNavSquare(end);
|
|
||||||
|
|
||||||
if (!local || !dest)
|
CNavArea *local, *dest;
|
||||||
|
if (!(local = findClosestNavSquare(start)) || !(dest = findClosestNavSquare(end)))
|
||||||
return {};
|
return {};
|
||||||
micropather::MPVector<void *> pathNodes;
|
|
||||||
|
logging::Info("Start: (%f,%f,%f)", local->m_center.x, local->m_center.y, local->m_center.z);
|
||||||
|
logging::Info("End: (%f,%f,%f)", dest->m_center.x, dest->m_center.y, dest->m_center.z);
|
||||||
float cost;
|
float cost;
|
||||||
std::chrono::time_point begin_pathing = std::chrono::high_resolution_clock::now();
|
std::vector<CNavArea*> pathNodes;
|
||||||
int result = Map.pather->Solve(static_cast<void *>(local), static_cast<void *>(dest), &pathNodes, &cost);
|
|
||||||
long long timetaken = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - begin_pathing).count();
|
time_point begin_pathing = high_resolution_clock::now();
|
||||||
|
int result = Map.pather->Solve(reinterpret_cast<void *>(local),
|
||||||
|
reinterpret_cast<void*>(dest),
|
||||||
|
reinterpret_cast<std::vector<void*>*>(&pathNodes), &cost);
|
||||||
|
long long timetaken = duration_cast<nanoseconds>(high_resolution_clock::now() - begin_pathing).count();
|
||||||
logging::Info("Pathing: Pather result: %i. Time taken (NS): %lld", result, timetaken);
|
logging::Info("Pathing: Pather result: %i. Time taken (NS): %lld", result, timetaken);
|
||||||
// If no result found, return empty Vector
|
// If no result found, return empty Vector
|
||||||
if (result == micropather::MicroPather::NO_SOLUTION)
|
if (result == micropather::MicroPather::NO_SOLUTION)
|
||||||
return std::vector<Vector>(0);
|
return {};
|
||||||
// Convert (void *) CNavArea * to Vector
|
|
||||||
std::vector<Vector> path;
|
return pathNodes;
|
||||||
for (size_t i = 0; i < pathNodes.size(); i++)
|
|
||||||
{
|
|
||||||
path.push_back(static_cast<CNavArea *>(pathNodes[i])->m_center);
|
|
||||||
}
|
|
||||||
// Add our destination to the std::vector
|
|
||||||
path.push_back(end);
|
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector loc(0.0f, 0.0f, 0.0f);
|
static Vector loc(0.0f, 0.0f, 0.0f);
|
||||||
static Vector last_area(0.0f, 0.0f, 0.0f);
|
static CNavArea *last_area = nullptr;
|
||||||
bool ReadyForCommands = true;
|
bool ReadyForCommands = true;
|
||||||
static Timer inactivity{};
|
static Timer inactivity{};
|
||||||
int curr_priority = 0;
|
int curr_priority = 0;
|
||||||
static bool ensureArrival = false;
|
static bool ensureArrival = false;
|
||||||
|
|
||||||
bool navTo(Vector destination, int priority, bool should_repath, bool nav_to_local, bool is_repath)
|
bool navTo(const Vector &destination, int priority, bool should_repath, bool nav_to_local, bool is_repath)
|
||||||
{
|
{
|
||||||
if (!prepare())
|
if (!prepare() || priority < curr_priority)
|
||||||
return false;
|
return false;
|
||||||
if (priority < curr_priority)
|
|
||||||
return false;
|
auto path = findPath(g_pLocalPlayer->v_Origin, destination);
|
||||||
std::vector<Vector> path = findPath(g_pLocalPlayer->v_Origin, destination);
|
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
{
|
{
|
||||||
crumbs.clear();
|
clearInstructions();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto crumb = crumbs.begin();
|
auto crumb = crumbs.begin();
|
||||||
if (crumb != crumbs.end())
|
if (crumb != crumbs.end() && ignoremanager::addTime(last_area, *crumb, inactivity))
|
||||||
{
|
|
||||||
if (ignoremanager::addTime(last_area, *crumb, inactivity))
|
|
||||||
ResetPather();
|
ResetPather();
|
||||||
}
|
|
||||||
auto path_it = path.begin();
|
auto path_it = path.begin();
|
||||||
last_area = *path_it;
|
last_area = *path_it;
|
||||||
if (!nav_to_local)
|
if (!nav_to_local)
|
||||||
@ -564,25 +525,32 @@ bool navTo(Vector destination, int priority, bool should_repath, bool nav_to_loc
|
|||||||
}
|
}
|
||||||
inactivity.update();
|
inactivity.update();
|
||||||
if (!is_repath)
|
if (!is_repath)
|
||||||
{
|
|
||||||
findClosestNavSquare_localAreas.clear();
|
findClosestNavSquare_localAreas.clear();
|
||||||
}
|
|
||||||
ensureArrival = should_repath;
|
ensureArrival = should_repath;
|
||||||
ReadyForCommands = false;
|
ReadyForCommands = false;
|
||||||
curr_priority = priority;
|
curr_priority = priority;
|
||||||
crumbs = std::move(path);
|
crumbs = std::move(path);
|
||||||
|
endPoint = destination;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void repath()
|
void repath()
|
||||||
{
|
{
|
||||||
if (ensureArrival)
|
if (!ensureArrival)
|
||||||
{
|
return;
|
||||||
Vector last = crumbs.back();
|
|
||||||
crumbs.clear();
|
Vector last;
|
||||||
|
if (!crumbs.empty())
|
||||||
|
last = crumbs.back()->m_center;
|
||||||
|
else if (endPoint.IsValid())
|
||||||
|
last = endPoint;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
clearInstructions();
|
||||||
ResetPather();
|
ResetPather();
|
||||||
navTo(last, curr_priority, true, true, true);
|
navTo(last, curr_priority, true, true, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Timer last_jump{};
|
static Timer last_jump{};
|
||||||
@ -596,51 +564,82 @@ static void cm()
|
|||||||
if (!LOCAL_E->m_bAlivePlayer())
|
if (!LOCAL_E->m_bAlivePlayer())
|
||||||
{
|
{
|
||||||
// Clear path if player dead
|
// Clear path if player dead
|
||||||
crumbs.clear();
|
clearInstructions();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ignoremanager::updateIgnores();
|
ignoremanager::updateIgnores();
|
||||||
auto crumb = crumbs.begin();
|
auto crumb = crumbs.begin();
|
||||||
|
const Vector *crumb_vec;
|
||||||
// Crumbs empty, prepare for next instruction
|
// Crumbs empty, prepare for next instruction
|
||||||
if (crumb == crumbs.end())
|
if (crumb == crumbs.end())
|
||||||
|
{
|
||||||
|
if (endPoint.IsValid())
|
||||||
|
crumb_vec = &endPoint;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
curr_priority = 0;
|
curr_priority = 0;
|
||||||
ReadyForCommands = true;
|
ReadyForCommands = true;
|
||||||
ensureArrival = false;
|
ensureArrival = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
crumb_vec = &(*crumb)->m_center;
|
||||||
|
|
||||||
ReadyForCommands = false;
|
ReadyForCommands = false;
|
||||||
// Remove old crumbs
|
// Remove old crumbs
|
||||||
if (g_pLocalPlayer->v_Origin.DistTo(Vector{ crumb->x, crumb->y, crumb->z }) < 50.0f)
|
if (g_pLocalPlayer->v_Origin.DistTo(*crumb_vec) < 50.0f)
|
||||||
{
|
{
|
||||||
|
inactivity.update();
|
||||||
|
if (crumb_vec == &endPoint)
|
||||||
|
{
|
||||||
|
endPoint.Invalidate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
last_area = *crumb;
|
last_area = *crumb;
|
||||||
crumbs.erase(crumb);
|
crumbs.erase(crumb);
|
||||||
inactivity.update();
|
|
||||||
crumb = crumbs.begin();
|
crumb = crumbs.begin();
|
||||||
if (crumb == crumbs.end())
|
if (crumb == crumbs.end())
|
||||||
|
{
|
||||||
|
if (!endPoint.IsValid())
|
||||||
|
{
|
||||||
|
logging::Info("navparser.cpp cm -> endPoint.IsValid() == false");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
crumb_vec = &endPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (look && LookAtPathTimer.check(1000))
|
if (look && LookAtPathTimer.check(1000))
|
||||||
{
|
{
|
||||||
Vector next = *crumb;
|
Vector next{crumb_vec->x, crumb_vec->y, g_pLocalPlayer->v_Eye.z};
|
||||||
next.z = g_pLocalPlayer->v_Eye.z;
|
next = GetAimAtAngles(g_pLocalPlayer->v_Eye, next);
|
||||||
Vector angle = GetAimAtAngles(g_pLocalPlayer->v_Eye, next);
|
DoSlowAim(next);
|
||||||
DoSlowAim(angle);
|
current_user_cmd->viewangles = next;
|
||||||
current_user_cmd->viewangles = angle;
|
|
||||||
}
|
}
|
||||||
// Detect when jumping is necessary
|
// Detect when jumping is necessary
|
||||||
if ((!(g_pLocalPlayer->holding_sniper_rifle && g_pLocalPlayer->bZoomed) && crumb->z - g_pLocalPlayer->v_Origin.z > 18 && last_jump.test_and_set(200)) || (last_jump.test_and_set(200) && inactivity.check(3000)))
|
if ((!(g_pLocalPlayer->holding_sniper_rifle && g_pLocalPlayer->bZoomed) &&
|
||||||
current_user_cmd->buttons |= IN_JUMP | IN_DUCK;
|
crumb_vec->z - g_pLocalPlayer->v_Origin.z > 18 && last_jump.test_and_set(200)) ||
|
||||||
// If inactive for too long
|
(last_jump.test_and_set(200) && inactivity.check(*stuck_time / 2)))
|
||||||
if (inactivity.check(*stuck_time))
|
|
||||||
{
|
{
|
||||||
// Ignore connection
|
current_user_cmd->buttons |= IN_JUMP;
|
||||||
|
}
|
||||||
|
// Walk to next crumb
|
||||||
|
WalkTo(*crumb_vec);
|
||||||
|
/* If can't go through for some time (doors aren't instantly opening)
|
||||||
|
* ignore that connection
|
||||||
|
* Or if inactive for too long
|
||||||
|
*/
|
||||||
|
if (inactivity.check(*stuck_time) || (inactivity.check(*unreachable_time) &&
|
||||||
|
!IsVectorVisible(g_pLocalPlayer->v_Origin, *crumb_vec + Vector(.0f, .0f, 41.5f),
|
||||||
|
false, LOCAL_E, MASK_PLAYERSOLID)))
|
||||||
|
{
|
||||||
|
/* crumb is invalid if endPoint is used */
|
||||||
|
if (crumb_vec != &endPoint)
|
||||||
ignoremanager::addTime(last_area, *crumb, inactivity);
|
ignoremanager::addTime(last_area, *crumb, inactivity);
|
||||||
|
|
||||||
repath();
|
repath();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Walk to next crumb
|
|
||||||
WalkTo(*crumb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_VISUALS
|
#if ENABLE_VISUALS
|
||||||
@ -654,16 +653,25 @@ static void drawcrumbs()
|
|||||||
return;
|
return;
|
||||||
if (crumbs.size() < 2)
|
if (crumbs.size() < 2)
|
||||||
return;
|
return;
|
||||||
for (size_t i = 0; i < crumbs.size() - 1; i++)
|
for (size_t i = 0; i < crumbs.size(); i++)
|
||||||
{
|
{
|
||||||
Vector wts1, wts2;
|
Vector wts1, wts2, *o1, *o2;
|
||||||
if (draw::WorldToScreen(crumbs[i], wts1) && draw::WorldToScreen(crumbs[i + 1], wts2))
|
if (crumbs.size() - 1 == i) {
|
||||||
|
if (!endPoint.IsValid())
|
||||||
|
break;
|
||||||
|
|
||||||
|
o2 = &endPoint;
|
||||||
|
} else
|
||||||
|
o2 = &crumbs[i + 1]->m_center;
|
||||||
|
|
||||||
|
o1 = &crumbs[i]->m_center;
|
||||||
|
if (draw::WorldToScreen(*o1, wts1) && draw::WorldToScreen(*o2, wts2))
|
||||||
{
|
{
|
||||||
draw::Line(wts1.x, wts1.y, wts2.x - wts1.x, wts2.y - wts1.y, colors::white, 0.3f);
|
draw::Line(wts1.x, wts1.y, wts2.x - wts1.x, wts2.y - wts1.y, colors::white, 0.3f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vector wts;
|
Vector wts;
|
||||||
if (!draw::WorldToScreen(crumbs[0], wts))
|
if (!draw::WorldToScreen(crumbs[0]->m_center, wts))
|
||||||
return;
|
return;
|
||||||
draw::Rectangle(wts.x - 4, wts.y - 4, 8, 8, colors::white);
|
draw::Rectangle(wts.x - 4, wts.y - 4, 8, 8, colors::white);
|
||||||
draw::RectangleOutlined(wts.x - 4, wts.y - 4, 7, 7, colors::white, 1.0f);
|
draw::RectangleOutlined(wts.x - 4, wts.y - 4, 7, 7, colors::white, 1.0f);
|
||||||
@ -688,7 +696,7 @@ bool isSafe(CNavArea *area)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CatCommand nav_find("nav_find", "Debug nav find", []() {
|
static CatCommand nav_find("nav_find", "Debug nav find", []() {
|
||||||
std::vector<Vector> path = findPath(g_pLocalPlayer->v_Origin, loc);
|
auto path = findPath(g_pLocalPlayer->v_Origin, loc);
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
{
|
{
|
||||||
logging::Info("Pathing: No path found");
|
logging::Info("Pathing: No path found");
|
||||||
@ -697,7 +705,7 @@ static CatCommand nav_find("nav_find", "Debug nav find", []() {
|
|||||||
std::string output = "Pathing: Path found! Path: ";
|
std::string output = "Pathing: Path found! Path: ";
|
||||||
for (int i = 0; i < path.size(); i++)
|
for (int i = 0; i < path.size(); i++)
|
||||||
{
|
{
|
||||||
output.append(format(path.at(i).x, ",", format(path.at(i).y), " "));
|
output.append(format(path[i]->m_center.x, ",", format(path[i]->m_center.y), " "));
|
||||||
}
|
}
|
||||||
logging::Info(output.c_str());
|
logging::Info(output.c_str());
|
||||||
});
|
});
|
||||||
@ -775,6 +783,7 @@ void DoSlowAim(Vector &input_angle)
|
|||||||
void clearInstructions()
|
void clearInstructions()
|
||||||
{
|
{
|
||||||
crumbs.clear();
|
crumbs.clear();
|
||||||
|
endPoint.Invalidate();
|
||||||
curr_priority = 0;
|
curr_priority = 0;
|
||||||
}
|
}
|
||||||
static CatCommand nav_stop("nav_cancel", "Cancel Navigation", []() { clearInstructions(); });
|
static CatCommand nav_stop("nav_cancel", "Cancel Navigation", []() { clearInstructions(); });
|
||||||
|
@ -13,7 +13,7 @@ TextFile::TextFile() : lines{}
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextFile::TryLoad(std::string name)
|
bool TextFile::TryLoad(const std::string &name)
|
||||||
{
|
{
|
||||||
if (name.length() == 0)
|
if (name.length() == 0)
|
||||||
return false;
|
return false;
|
||||||
@ -30,12 +30,15 @@ bool TextFile::TryLoad(std::string name)
|
|||||||
line.erase(line.length() - 1, 1);
|
line.erase(line.length() - 1, 1);
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
}
|
}
|
||||||
|
if (lines.size() > 0 && *lines.rbegin() == "\n")
|
||||||
|
lines.pop_back();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextFile::Load(std::string name)
|
void TextFile::Load(const std::string &name)
|
||||||
{
|
{
|
||||||
std::string filename = format(DATA_PATH "/", name);
|
std::string filename = DATA_PATH "/" + name;
|
||||||
std::ifstream file(filename, std::ios::in);
|
std::ifstream file(filename, std::ios::in);
|
||||||
if (file.bad())
|
if (file.bad())
|
||||||
{
|
{
|
||||||
|
@ -140,6 +140,9 @@ bool trace::FilterNoEntity::ShouldHitEntity(IHandleEntity *handle, int mask)
|
|||||||
// Hit doors, carts, etc
|
// Hit doors, carts, etc
|
||||||
switch (clazz->m_ClassID)
|
switch (clazz->m_ClassID)
|
||||||
{
|
{
|
||||||
|
case CL_CLASS(CWorld):
|
||||||
|
case CL_CLASS(CPhysicsProp):
|
||||||
|
case CL_CLASS(CDynamicProp):
|
||||||
case CL_CLASS(CBaseDoor):
|
case CL_CLASS(CBaseDoor):
|
||||||
case CL_CLASS(CBaseEntity):
|
case CL_CLASS(CBaseEntity):
|
||||||
return true;
|
return true;
|
||||||
|
Reference in New Issue
Block a user