Merge pull request #515 from TotallyNotElite/master

Followbot improvements (+ some other stuff)
This commit is contained in:
LightCat 2018-06-24 22:03:48 +02:00 committed by GitHub
commit 61f7077e50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 109 additions and 32 deletions

View File

@ -36,7 +36,7 @@ public:
void SetEntityColor(CachedEntity *ent, rgba_t color); void SetEntityColor(CachedEntity *ent, rgba_t color);
rgba_t ChamsColor(IClientEntity *entity); rgba_t ChamsColor(IClientEntity *entity);
bool ShouldRenderChams(IClientEntity *entity); bool ShouldRenderChams(IClientEntity *entity);
void RenderChams(int idx); void RenderChams(IClientEntity *entity);
void BeginRenderChams(); void BeginRenderChams();
void EndRenderChams(); void EndRenderChams();
void RenderChamsRecursive(IClientEntity *entity); void RenderChamsRecursive(IClientEntity *entity);
@ -54,4 +54,4 @@ public:
extern EffectChams g_EffectChams; extern EffectChams g_EffectChams;
extern CScreenSpaceEffectRegistration *g_pEffectChams; extern CScreenSpaceEffectRegistration *g_pEffectChams;
} }

View File

@ -24,7 +24,7 @@ int m_iNewTarget{ 0 };
static CatVar pop_uber_auto(CV_SWITCH, "autoheal_uber", "1", "AutoUber", static CatVar pop_uber_auto(CV_SWITCH, "autoheal_uber", "1", "AutoUber",
"Use ubercharge automatically"); "Use ubercharge automatically");
static CatVar static CatVar
pop_uber_percent(CV_FLOAT, "autoheal_uber_health", "30", pop_uber_percent(CV_FLOAT, "autoheal_uber_health", "0",
"Pop uber if health% <", "Pop uber if health% <",
"When under a percentage of health, use ubercharge"); "When under a percentage of health, use ubercharge");
static CatVar share_uber( static CatVar share_uber(
@ -351,9 +351,17 @@ bool IsPopped()
bool ShouldChargePlayer(int idx) bool ShouldChargePlayer(int idx)
{ {
CachedEntity *target = ENTITY(idx); CachedEntity *target = ENTITY(idx);
const int health = target->m_iHealth();
if (float(pop_uber_percent) > 0)
{
const float pophealth = target->m_iMaxHealth() * (float(pop_uber_percent) / 100);
if (health < pophealth)
return true;
}
else
{
const float damage_accum_duration = const float damage_accum_duration =
g_GlobalVars->curtime - data[idx].accum_damage_start; g_GlobalVars->curtime - data[idx].accum_damage_start;
const int health = target->m_iHealth();
if (!data[idx].accum_damage_start) if (!data[idx].accum_damage_start)
return false; return false;
if (health > 30 && data[idx].accum_damage < 45) if (health > 30 && data[idx].accum_damage < 45)
@ -366,6 +374,8 @@ bool ShouldChargePlayer(int idx)
if (health < 30 && data[idx].accum_damage > 10) if (health < 30 && data[idx].accum_damage > 10)
return true; return true;
return false; return false;
}
return false;
} }
bool ShouldPop() bool ShouldPop()

View File

@ -23,7 +23,7 @@ static CatVar draw_crumb(CV_SWITCH, "fb_draw", "1", "Draw crumbs",
"Self explanitory"); "Self explanitory");
static CatVar follow_distance(CV_INT, "fb_distance", "175", "Follow Distance", static CatVar follow_distance(CV_INT, "fb_distance", "175", "Follow Distance",
"How close the bots should stay to the target"); "How close the bots should stay to the target");
static CatVar follow_activation(CV_INT, "fb_activation", "175", static CatVar follow_activation(CV_INT, "fb_activation", "1000",
"Activation Distance", "Activation Distance",
"How close a player should be until the " "How close a player should be until the "
"followbot will pick them as a target"); "followbot will pick them as a target");
@ -45,14 +45,49 @@ static CatVar always_medigun(CV_SWITCH, "fb_always_medigun", "0",
"Always Medigun", "Always use medigun"); "Always Medigun", "Always use medigun");
static CatVar sync_taunt(CV_SWITCH, "fb_sync_taunt", "0", "Synced taunt", static CatVar sync_taunt(CV_SWITCH, "fb_sync_taunt", "0", "Synced taunt",
"Taunt when follow target does"); "Taunt when follow target does");
static CatVar change(CV_SWITCH, "fb_switch", "1", "Change followbot target", static CatVar change(CV_SWITCH, "fb_switch", "0", "Change followbot target",
"Always change roaming target when possible"); "Always change roaming target when possible");
static CatVar autojump(CV_SWITCH, "fb_autojump", "1", "Autojump",
"Automatically jump if stuck");
static CatVar afk(CV_SWITCH, "fb_afk", "1", "Switch target if AFK",
"Automatically switch target if the target is afk");
static CatVar afktime(
CV_INT, "fb_afk_time", "15000", "Max AFK Time",
"Max time in ms spent standing still before player gets declared afk");
// Something to store breadcrumbs created by followed players // Something to store breadcrumbs created by followed players
static std::vector<Vector> breadcrumbs; static std::vector<Vector> breadcrumbs;
static const int crumb_limit = 64; // limit static const int crumb_limit = 64; // limit
// Followed entity, externed for highlight color // Followed entity, externed for highlight color
int follow_target = 0; int follow_target = 0;
bool inited;
Timer lastTaunt{}; //time since taunt was last executed, used to avoid kicks
std::array<Timer, 32> afkTicks; //for how many ms the player hasn't been moving
void checkAFK()
{
for (int i = 0; i < g_GlobalVars->maxClients; i++)
{
auto entity = ENTITY(i);
if (CE_BAD(entity))
continue;
if (!CE_VECTOR(entity, netvar.vVelocity).IsZero(5.0f))
{
afkTicks[i].update();
}
}
}
void init()
{
for (int i; i < afkTicks.size(); i++)
{
afkTicks[i].update();
}
inited = true;
}
void WorldTick() void WorldTick()
{ {
@ -61,6 +96,8 @@ void WorldTick()
follow_target = 0; follow_target = 0;
return; return;
} }
if (!inited)
init();
// We need a local player to control // We need a local player to control
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer()) if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
@ -69,6 +106,9 @@ void WorldTick()
return; return;
} }
if (afk)
checkAFK();
// Still good check // Still good check
if (follow_target) if (follow_target)
{ {
@ -122,6 +162,12 @@ void WorldTick()
continue; continue;
if (entity == LOCAL_E) // Follow self lol if (entity == LOCAL_E) // Follow self lol
continue; continue;
if (entity->m_bEnemy())
continue;
if (afk && afkTicks[i].check(int(afktime))) //don't follow target that was determined afk
continue;
if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity))
continue;
if (!entity->m_bAlivePlayer()) // Dont follow dead players if (!entity->m_bAlivePlayer()) // Dont follow dead players
continue; continue;
if (follow_activation && if (follow_activation &&
@ -148,29 +194,51 @@ void WorldTick()
entity->m_flDistance()) // favor closer entitys entity->m_flDistance()) // favor closer entitys
continue; continue;
// ooooo, a target // ooooo, a target
follow_target = entity->m_IDX; follow_target = i;
afkTicks[i].update(); //set afk time to 0
} }
} }
// last check for entity before we continue // last check for entity before we continue
if (!follow_target) if (!follow_target)
return; return;
// If the player is close enough, we dont need to follow the path
CachedEntity *followtar = ENTITY(follow_target); CachedEntity *followtar = ENTITY(follow_target);
// wtf is this needed // wtf is this needed
if (CE_BAD(followtar)) if (CE_BAD(followtar))
return; return;
auto tar_orig = followtar->m_vecOrigin(); // Check if we are following a disguised/spy
auto loc_orig = LOCAL_E->m_vecOrigin(); if (IsPlayerDisguised(followtar) || IsPlayerInvisible(followtar))
auto dist_to_target = loc_orig.DistTo(tar_orig); {
if (dist_to_target < 30) follow_target = 0;
breadcrumbs.clear(); return;
}
//check if target is afk
if (afk)
{
if (afkTicks[follow_target].check(int(afktime)))
{
follow_target = 0;
return;
}
}
// Update timer on new target // Update timer on new target
static Timer idle_time{}; static Timer idle_time{};
if (breadcrumbs.empty()) if (breadcrumbs.empty())
idle_time.update(); idle_time.update();
// If the player is close enough, we dont need to follow the path
auto tar_orig = followtar->m_vecOrigin();
auto loc_orig = LOCAL_E->m_vecOrigin();
auto dist_to_target = loc_orig.DistTo(tar_orig);
if ((dist_to_target < (float) follow_distance) &&
VisCheckEntFromEnt(LOCAL_E, followtar))
{
idle_time.update();
}
// New crumbs, we add one if its empty so we have something to follow // New crumbs, we add one if its empty so we have something to follow
if ((breadcrumbs.empty() || if ((breadcrumbs.empty() ||
tar_orig.DistTo(breadcrumbs.at(breadcrumbs.size() - 1)) > 40.0F) && tar_orig.DistTo(breadcrumbs.at(breadcrumbs.size() - 1)) > 40.0F) &&
@ -179,26 +247,32 @@ void WorldTick()
// Prune old and close crumbs that we wont need anymore, update idle timer // Prune old and close crumbs that we wont need anymore, update idle timer
// too // too
while (breadcrumbs.size() > 1 && loc_orig.DistTo(breadcrumbs.at(0)) < 60.f) for (int i = 0; i < breadcrumbs.size(); i++)
{ {
idle_time.update(); if (loc_orig.DistTo(breadcrumbs.at(i)) < 60.f)
breadcrumbs.erase(breadcrumbs.begin()); {
idle_time.update();
for (int j = 0; j <= i; j++)
breadcrumbs.erase(breadcrumbs.begin());
}
}
//moved because its worthless otherwise
if (sync_taunt && HasCondition<TFCond_Taunting>(followtar) && lastTaunt.test_and_set(1000)) {
g_IEngine->ClientCmd("taunt");
} }
// Follow the crumbs when too far away, or just starting to follow // Follow the crumbs when too far away, or just starting to follow
if (dist_to_target > (float) follow_distance) if (dist_to_target > (float) follow_distance)
{ {
// Check for idle // Check for idle
if (idle_time.check(3000) || if (autojump && idle_time.check(3000))
(breadcrumbs.size() > 1 && LOCAL_E->m_vecVelocity.IsZero(5.0f)))
g_pUserCmd->buttons |= IN_JUMP; g_pUserCmd->buttons |= IN_JUMP;
if (idle_time.test_and_set(5000)) if (idle_time.test_and_set(5000))
{ {
follow_target = 0; follow_target = 0;
return; return;
} }
if (sync_taunt && HasCondition<TFCond_Taunting>(ENTITY(follow_target)))
g_IEngine->ClientCmd("taunt");
static float last_slot_check = 0.0f; static float last_slot_check = 0.0f;
if (g_GlobalVars->curtime < last_slot_check) if (g_GlobalVars->curtime < last_slot_check)
last_slot_check = 0.0f; last_slot_check = 0.0f;

View File

@ -227,8 +227,6 @@ bool EffectChams::ShouldRenderChams(IClientEntity *entity)
if (entity->entindex() < 0) if (entity->entindex() < 0)
return false; return false;
CachedEntity *ent = ENTITY(entity->entindex()); CachedEntity *ent = ENTITY(entity->entindex());
if (CE_BAD(ent))
return false;
if (ent->m_IDX == LOCAL_E->m_IDX && !chamsself) if (ent->m_IDX == LOCAL_E->m_IDX && !chamsself)
return false; return false;
switch (ent->m_Type()) switch (ent->m_Type())
@ -319,12 +317,9 @@ void EffectChams::RenderChamsRecursive(IClientEntity *entity)
} }
} }
void EffectChams::RenderChams(int idx) void EffectChams::RenderChams(IClientEntity *entity)
{ {
CMatRenderContextPtr ptr(GET_RENDER_CONTEXT); CMatRenderContextPtr ptr(GET_RENDER_CONTEXT);
IClientEntity *entity = g_IEntityList->GetClientEntity(idx);
if (entity && !entity->IsDormant())
{
if (ShouldRenderChams(entity)) if (ShouldRenderChams(entity))
{ {
rgba_t color = ChamsColor(entity); rgba_t color = ChamsColor(entity);
@ -348,7 +343,6 @@ void EffectChams::RenderChams(int idx)
g_IVModelRender->ForcedMaterialOverride(flat ? mat_unlit g_IVModelRender->ForcedMaterialOverride(flat ? mat_unlit
: mat_lit); : mat_lit);
RenderChamsRecursive(entity); RenderChamsRecursive(entity);
}
} }
} }
} }
@ -366,11 +360,10 @@ void EffectChams::Render(int x, int y, int w, int h)
BeginRenderChams(); BeginRenderChams();
for (int i = 1; i < HIGHEST_ENTITY; i++) for (int i = 1; i < HIGHEST_ENTITY; i++)
{ {
IClientEntity *ent = g_IEntityList->GetClientEntity(i); IClientEntity *entity = g_IEntityList->GetClientEntity(i);
if (ent && !ent->IsDormant()) if (!entity || entity->IsDormant() || CE_BAD(ENTITY(i)))
{ return;
RenderChams(i); RenderChams(entity);
}
} }
EndRenderChams(); EndRenderChams();
} }