Engie mode
This commit is contained in:
parent
e8f9133764
commit
f2f58403a9
@ -23,4 +23,3 @@ libtinfo.so.5.9.4.2
|
|||||||
libudev.so.1.6.6.4.7
|
libudev.so.1.6.6.4.7
|
||||||
libwrap.so.0.7.6.1.5
|
libwrap.so.0.7.6.1.5
|
||||||
libz.so.1.2.1.1.2.4
|
libz.so.1.2.1.1.2.4
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
<AutoVariable width="fill" target="navbot.enable" label="Enable NavBot"/>
|
<AutoVariable width="fill" target="navbot.enable" label="Enable NavBot"/>
|
||||||
<AutoVariable width="fill" target="navbot.spy-mode" label="Enable Spy Mode"/>
|
<AutoVariable width="fill" target="navbot.spy-mode" label="Enable Spy Mode"/>
|
||||||
<AutoVariable width="fill" target="navbot.heavy-mode" label="Enable Heavy Mode"/>
|
<AutoVariable width="fill" target="navbot.heavy-mode" label="Enable Heavy Mode"/>
|
||||||
|
<AutoVariable width="fill" target="navbot.engi-mode" label="Enable Engie Mode"/>
|
||||||
<AutoVariable width="fill" target="navbot.primary-only" label="Best Weapon only"/>
|
<AutoVariable width="fill" target="navbot.primary-only" label="Best Weapon only"/>
|
||||||
</List>
|
</List>
|
||||||
<Box name="Nav FollowBot" width="content" height="content" padding="12 6 6 6" y="90">
|
<Box name="Nav FollowBot" width="content" height="content" padding="12 6 6 6" y="90">
|
||||||
|
@ -63,6 +63,7 @@ public:
|
|||||||
offset_t hActiveWeapon;
|
offset_t hActiveWeapon;
|
||||||
offset_t flChargedDamage;
|
offset_t flChargedDamage;
|
||||||
offset_t iUpgradeLevel;
|
offset_t iUpgradeLevel;
|
||||||
|
offset_t m_hBuilder;
|
||||||
offset_t iPipeType;
|
offset_t iPipeType;
|
||||||
offset_t iBuildingHealth;
|
offset_t iBuildingHealth;
|
||||||
offset_t iBuildingMaxHealth;
|
offset_t iBuildingMaxHealth;
|
||||||
|
@ -120,6 +120,8 @@ void NetVars::Init()
|
|||||||
"DT_TFSniperRifle", "SniperRifleLocalData", "m_flChargedDamage");
|
"DT_TFSniperRifle", "SniperRifleLocalData", "m_flChargedDamage");
|
||||||
this->iUpgradeLevel =
|
this->iUpgradeLevel =
|
||||||
gNetvars.get_offset("DT_BaseObject", "m_iUpgradeLevel");
|
gNetvars.get_offset("DT_BaseObject", "m_iUpgradeLevel");
|
||||||
|
this->m_hBuilder =
|
||||||
|
gNetvars.get_offset("DT_BaseObject", "m_hBuilder");
|
||||||
this->iPipeType =
|
this->iPipeType =
|
||||||
gNetvars.get_offset("DT_TFProjectile_Pipebomb", "m_iType");
|
gNetvars.get_offset("DT_TFProjectile_Pipebomb", "m_iType");
|
||||||
this->iBuildingHealth =
|
this->iBuildingHealth =
|
||||||
|
@ -12,6 +12,7 @@ namespace hacks::tf2::NavBot
|
|||||||
static settings::Bool enable("navbot.enable", "false");
|
static settings::Bool enable("navbot.enable", "false");
|
||||||
static settings::Bool spy_mode("navbot.spy-mode", "false");
|
static settings::Bool spy_mode("navbot.spy-mode", "false");
|
||||||
static settings::Bool heavy_mode("navbot.heavy-mode", "false");
|
static settings::Bool heavy_mode("navbot.heavy-mode", "false");
|
||||||
|
static settings::Bool engi_mode("navbot.engi-mode", "false");
|
||||||
static settings::Bool primary_only("navbot.primary-only", "true");
|
static settings::Bool primary_only("navbot.primary-only", "true");
|
||||||
|
|
||||||
static settings::Bool enable_fb{ "navbot.medbot", "false" };
|
static settings::Bool enable_fb{ "navbot.medbot", "false" };
|
||||||
@ -157,16 +158,27 @@ CachedEntity *NearestEnemy()
|
|||||||
Timer cdr{};
|
Timer cdr{};
|
||||||
Timer cd2{};
|
Timer cd2{};
|
||||||
Timer cd3{};
|
Timer cd3{};
|
||||||
|
Timer engi_spot_cd{};
|
||||||
|
std::vector<Vector> preferred_sniper_spots;
|
||||||
std::vector<Vector> sniper_spots;
|
std::vector<Vector> sniper_spots;
|
||||||
|
std::vector<Vector> nest_spots;
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
sniper_spots.clear();
|
sniper_spots.clear();
|
||||||
|
preferred_sniper_spots.clear();
|
||||||
|
nest_spots.clear();
|
||||||
for (auto area : nav::areas)
|
for (auto area : nav::areas)
|
||||||
|
{
|
||||||
|
if (area.m_attributeFlags & NAV_MESH_NO_HOSTAGES)
|
||||||
|
preferred_sniper_spots.push_back(area.m_center);
|
||||||
|
if (area.m_attributeFlags & NAV_MESH_RUN)
|
||||||
|
nest_spots.push_back(area.m_center);
|
||||||
for (auto hide : area.m_hidingSpots)
|
for (auto hide : area.m_hidingSpots)
|
||||||
if (hide.IsGoodSniperSpot() || hide.IsIdealSniperSpot() ||
|
if (hide.IsGoodSniperSpot() || hide.IsIdealSniperSpot() ||
|
||||||
hide.IsExposed())
|
hide.IsExposed())
|
||||||
sniper_spots.push_back(hide.m_pos);
|
sniper_spots.push_back(hide.m_pos);
|
||||||
logging::Info("%d", sniper_spots.size());
|
}
|
||||||
|
logging::Info("Sniper spots: %d, Manual Sniper Spots: %d, Sentry Spots: %d", sniper_spots.size(), preferred_sniper_spots.size(), nest_spots.size());
|
||||||
}
|
}
|
||||||
void initonce()
|
void initonce()
|
||||||
{
|
{
|
||||||
@ -175,6 +187,7 @@ void initonce()
|
|||||||
cdr.update();
|
cdr.update();
|
||||||
cd2.update();
|
cd2.update();
|
||||||
cd3.update();
|
cd3.update();
|
||||||
|
engi_spot_cd.update();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +204,7 @@ void UpdateSlot()
|
|||||||
{
|
{
|
||||||
int slot = re::C_BaseCombatWeapon::GetSlot(weapon);
|
int slot = re::C_BaseCombatWeapon::GetSlot(weapon);
|
||||||
int newslot = 1;
|
int newslot = 1;
|
||||||
if (spy_mode)
|
if (spy_mode || engi_mode)
|
||||||
newslot = 3;
|
newslot = 3;
|
||||||
if (slot != newslot - 1)
|
if (slot != newslot - 1)
|
||||||
g_IEngine->ClientCmd_Unrestricted(
|
g_IEngine->ClientCmd_Unrestricted(
|
||||||
@ -199,6 +212,76 @@ void UpdateSlot()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
enum BuildingNum
|
||||||
|
{
|
||||||
|
DISPENSER = 0,
|
||||||
|
TELEPORT_ENT,
|
||||||
|
SENTRY,
|
||||||
|
TELEPORT_EXT,
|
||||||
|
};
|
||||||
|
std::vector<int> GetBuildings()
|
||||||
|
{
|
||||||
|
float bestscr = FLT_MAX;
|
||||||
|
std::vector<int> buildings;
|
||||||
|
for (int i = 0; i < HIGHEST_ENTITY; i++)
|
||||||
|
{
|
||||||
|
CachedEntity *ent = ENTITY(i);
|
||||||
|
if (CE_BAD(ent))
|
||||||
|
continue;
|
||||||
|
if (ent->m_Type() != ENTITY_BUILDING)
|
||||||
|
continue;
|
||||||
|
if ((CE_INT(ent, netvar.m_hBuilder) & 0xFFF) != g_pLocalPlayer->entity_idx)
|
||||||
|
continue;
|
||||||
|
if (ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin()) < bestscr)
|
||||||
|
{
|
||||||
|
buildings.push_back(i);
|
||||||
|
bestscr = ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buildings;
|
||||||
|
}
|
||||||
|
int cost[4] = {100, 50, 130, 50};
|
||||||
|
int GetBestBuilding(int metal)
|
||||||
|
{
|
||||||
|
bool hasSentry, hasDispenser;
|
||||||
|
if (!GetBuildings().empty())
|
||||||
|
for (auto build : GetBuildings())
|
||||||
|
{
|
||||||
|
CachedEntity *building = ENTITY(build);
|
||||||
|
if (building->m_iClassID() == CL_CLASS(CObjectSentrygun))
|
||||||
|
hasSentry = true;
|
||||||
|
if (building->m_iClassID() == CL_CLASS(CObjectDispenser))
|
||||||
|
hasDispenser = true;
|
||||||
|
}
|
||||||
|
if (metal >= cost[SENTRY] && !hasSentry)
|
||||||
|
return SENTRY;
|
||||||
|
else if (metal >= cost[DISPENSER] && !hasDispenser)
|
||||||
|
return DISPENSER;
|
||||||
|
if (hasSentry && hasDispenser)
|
||||||
|
return 3;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int GetClosestBuilding()
|
||||||
|
{
|
||||||
|
float bestscr = FLT_MAX;
|
||||||
|
int BestBuilding = -1;
|
||||||
|
for (int i = 0; i < HIGHEST_ENTITY; i++)
|
||||||
|
{
|
||||||
|
CachedEntity *ent = ENTITY(i);
|
||||||
|
if (CE_BAD(ent))
|
||||||
|
continue;
|
||||||
|
if (ent->m_Type() != ENTITY_BUILDING)
|
||||||
|
continue;
|
||||||
|
if ((CE_INT(ent, netvar.m_hBuilder) & 0xFFF) != g_pLocalPlayer->entity_idx)
|
||||||
|
continue;
|
||||||
|
if (ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin()) < bestscr)
|
||||||
|
{
|
||||||
|
BestBuilding = i;
|
||||||
|
bestscr = ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BestBuilding;
|
||||||
|
}
|
||||||
int follow_target = 0;
|
int follow_target = 0;
|
||||||
void CreateMove()
|
void CreateMove()
|
||||||
{
|
{
|
||||||
@ -212,42 +295,40 @@ void CreateMove()
|
|||||||
{
|
{
|
||||||
CachedEntity *med = nearestHealth();
|
CachedEntity *med = nearestHealth();
|
||||||
if (CE_GOOD(med))
|
if (CE_GOOD(med))
|
||||||
{
|
|
||||||
nav::NavTo(med->m_vecOrigin(), true, true, 7);
|
nav::NavTo(med->m_vecOrigin(), true, true, 7);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (HasLowAmmo() && cdr.test_and_set(5000))
|
if (HasLowAmmo() && cdr.test_and_set(5000))
|
||||||
{
|
{
|
||||||
CachedEntity *ammo = nearestAmmo();
|
CachedEntity *ammo = nearestAmmo();
|
||||||
if (CE_GOOD(ammo))
|
if (CE_GOOD(ammo))
|
||||||
{
|
|
||||||
nav::NavTo(ammo->m_vecOrigin(), true, true, 6);
|
nav::NavTo(ammo->m_vecOrigin(), true, true, 6);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if ((!HasLowHealth() && nav::priority == 7) || (!HasLowAmmo() && nav::priority == 6))
|
if ((!HasLowHealth() && nav::priority == 7) || (!HasLowAmmo() && nav::priority == 6))
|
||||||
nav::clearInstructions();
|
nav::clearInstructions();
|
||||||
if (enable)
|
if (enable)
|
||||||
{
|
{
|
||||||
if (!nav::ReadyForCommands && !spy_mode && !heavy_mode)
|
if (!nav::ReadyForCommands && !spy_mode && !heavy_mode && !engi_mode)
|
||||||
cd3.update();
|
cd3.update();
|
||||||
bool isready = (spy_mode || heavy_mode) ? 1 : nav::ReadyForCommands;
|
bool isready = (spy_mode || heavy_mode || engi_mode) ? 1 : nav::ReadyForCommands;
|
||||||
int waittime = (spy_mode || heavy_mode) ? 100 : 5000;
|
int waittime = (spy_mode || heavy_mode || engi_mode) ? 100 : 5000;
|
||||||
if (isready && cd3.test_and_set(waittime))
|
if (isready && cd3.test_and_set(waittime))
|
||||||
{
|
{
|
||||||
if (!spy_mode && !heavy_mode)
|
if (!spy_mode && !heavy_mode && !engi_mode)
|
||||||
{
|
{
|
||||||
cd3.update();
|
cd3.update();
|
||||||
Vector random_spot;
|
Vector random_spot;
|
||||||
if (cd2.test_and_set(5000))
|
if (cd2.test_and_set(5000))
|
||||||
Init();
|
Init();
|
||||||
if (!sniper_spots.size())
|
if (!sniper_spots.size() && !preferred_sniper_spots.size())
|
||||||
return;
|
return;
|
||||||
int rng = rand() % sniper_spots.size();
|
auto snip_spot = preferred_sniper_spots.size() ? preferred_sniper_spots : sniper_spots;
|
||||||
random_spot = sniper_spots.at(rng);
|
int rng = rand() % snip_spot.size();
|
||||||
|
random_spot = snip_spot.at(rng);
|
||||||
if (random_spot.z)
|
if (random_spot.z)
|
||||||
nav::NavTo(random_spot, true, true);
|
nav::NavTo(random_spot, true, true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else if (!engi_mode)
|
||||||
{
|
{
|
||||||
CachedEntity *tar = NearestEnemy();
|
CachedEntity *tar = NearestEnemy();
|
||||||
if (CE_BAD(tar) && last_tar == -1 && nav::ReadyForCommands)
|
if (CE_BAD(tar) && last_tar == -1 && nav::ReadyForCommands)
|
||||||
@ -255,10 +336,11 @@ void CreateMove()
|
|||||||
Vector random_spot;
|
Vector random_spot;
|
||||||
if (cd2.test_and_set(5000))
|
if (cd2.test_and_set(5000))
|
||||||
Init();
|
Init();
|
||||||
if (!sniper_spots.size())
|
if (!sniper_spots.size() && !preferred_sniper_spots.size())
|
||||||
return;
|
return;
|
||||||
int rng = rand() % sniper_spots.size();
|
auto snip_spot = preferred_sniper_spots.size() ? preferred_sniper_spots : sniper_spots;
|
||||||
random_spot = sniper_spots.at(rng);
|
int rng = rand() % snip_spot.size();
|
||||||
|
random_spot = snip_spot.at(rng);
|
||||||
if (random_spot.z)
|
if (random_spot.z)
|
||||||
nav::NavTo(random_spot, false);
|
nav::NavTo(random_spot, false);
|
||||||
return;
|
return;
|
||||||
@ -279,6 +361,120 @@ void CreateMove()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Engi Mode
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Init things
|
||||||
|
if (cd2.test_and_set(5000))
|
||||||
|
Init();
|
||||||
|
// If No spots set just return
|
||||||
|
if (nest_spots.empty())
|
||||||
|
return;
|
||||||
|
// Get Metal (offset of MAX metal is +8 and current metal +12)
|
||||||
|
int metal = CE_INT(LOCAL_E, netvar.m_iAmmo + 12);
|
||||||
|
// Best spot storage
|
||||||
|
static Vector best_spot{};
|
||||||
|
// Get Best spot based on distance
|
||||||
|
if (engi_spot_cd.test_and_set(10000))
|
||||||
|
{
|
||||||
|
float bestscr = FLT_MAX;
|
||||||
|
for (auto spot : nest_spots)
|
||||||
|
{
|
||||||
|
if (spot.DistTo(LOCAL_E->m_vecOrigin()) < bestscr)
|
||||||
|
{
|
||||||
|
bestscr = spot.DistTo(LOCAL_E->m_vecOrigin());
|
||||||
|
best_spot = spot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nav::priority == 1)
|
||||||
|
{
|
||||||
|
CachedEntity *ammo = nearestAmmo();
|
||||||
|
if (CE_GOOD(ammo))
|
||||||
|
{
|
||||||
|
nav::NavTo(ammo->m_vecOrigin(), false, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If Near The best spot and ready for commands
|
||||||
|
if (best_spot.DistTo(LOCAL_E->m_vecOrigin()) < 300.0f && (nav::ReadyForCommands || nav::priority == 1))
|
||||||
|
{
|
||||||
|
// Get the closest Building
|
||||||
|
int ClosestBuilding = GetClosestBuilding();
|
||||||
|
// If A Building was found
|
||||||
|
if (ClosestBuilding != -1)
|
||||||
|
{
|
||||||
|
CachedEntity *ent = ENTITY(ClosestBuilding);
|
||||||
|
// If we have more than 25 metal and the building is damaged or not fully upgraded hit it with the wrench
|
||||||
|
if (metal > 25 && (CE_INT(ent, netvar.iUpgradeLevel) < 3 || CE_INT(ent, netvar.iBuildingHealth) < CE_INT(ent, netvar.iBuildingMaxHealth)))
|
||||||
|
{
|
||||||
|
auto collide = RAW_ENT(ent)->GetCollideable();
|
||||||
|
Vector min = ent->m_vecOrigin() + collide->OBBMins();
|
||||||
|
Vector max = ent->m_vecOrigin() + collide->OBBMaxs();
|
||||||
|
// Distance check
|
||||||
|
if (min.DistTo(g_pLocalPlayer->v_Eye) > re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)) && max.DistTo(g_pLocalPlayer->v_Eye) > re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)) && GetBuildingPosition(ent).DistTo(g_pLocalPlayer->v_Eye) > re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)))
|
||||||
|
{
|
||||||
|
float min = min.DistTo(g_pLocalPlayer->v_Eye);
|
||||||
|
float max = max.DistTo(g_pLocalPlayer->v_Eye);
|
||||||
|
float center = GetBuildingPosition(ent).DistTo(g_pLocalPlayer->v_Eye);
|
||||||
|
float closest = fminf(min, fminf(max, center));
|
||||||
|
nav::NavTo(closest, false, false);
|
||||||
|
}
|
||||||
|
Vector tr = GetBuildingPosition(ent) - g_pLocalPlayer->v_Eye;
|
||||||
|
Vector angles;
|
||||||
|
VectorAngles(tr, angles);
|
||||||
|
// Clamping is important
|
||||||
|
fClampAngle(angles);
|
||||||
|
current_user_cmd->viewangles = angles;
|
||||||
|
current_user_cmd->buttons |= IN_ATTACK;
|
||||||
|
g_pLocalPlayer->bUseSilentAngles = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get A building, Sentry > Dispenser
|
||||||
|
int tobuild = GetBestBuilding(metal);
|
||||||
|
// If not enough metal then Find ammo
|
||||||
|
if (tobuild == -1)
|
||||||
|
{
|
||||||
|
CachedEntity *ammo = nearestAmmo();
|
||||||
|
if (CE_GOOD(ammo))
|
||||||
|
{
|
||||||
|
nav::NavTo(ammo->m_vecOrigin(), false, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Ammo is dormant, go and find it!
|
||||||
|
else if (sniper_spots.size() && nav::ReadyForCommands)
|
||||||
|
{
|
||||||
|
Vector random_spot;
|
||||||
|
if (cd2.test_and_set(5000))
|
||||||
|
Init();
|
||||||
|
if (!sniper_spots.size() && !preferred_sniper_spots.size())
|
||||||
|
return;
|
||||||
|
auto snip_spot = preferred_sniper_spots.size() ? preferred_sniper_spots : sniper_spots;
|
||||||
|
int rng = rand() % snip_spot.size();
|
||||||
|
random_spot = snip_spot.at(rng);
|
||||||
|
if (random_spot.z)
|
||||||
|
nav::NavTo(random_spot, false, false, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Build Building
|
||||||
|
else if (tobuild != 3)
|
||||||
|
{
|
||||||
|
// Make ENgi look slightly down
|
||||||
|
current_user_cmd->viewangles.x = 20.0f;
|
||||||
|
// Build buildings in a 360° angle around player
|
||||||
|
current_user_cmd->viewangles.y = 90.0f * (tobuild + 1);
|
||||||
|
// Build new one
|
||||||
|
g_IEngine->ServerCmd(format("build ", tobuild).c_str(), true);
|
||||||
|
current_user_cmd->buttons |= IN_ATTACK;
|
||||||
|
g_pLocalPlayer->bUseSilentAngles = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If not near best spot then navigate to it
|
||||||
|
else if (nav::ReadyForCommands)
|
||||||
|
nav::NavTo(best_spot, false, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (enable_fb)
|
else if (enable_fb)
|
||||||
|
Reference in New Issue
Block a user