Big performance increase due to getting rid of duplicate efforts (#1712)

This commit is contained in:
Stephen Martin 2022-07-27 13:43:38 -04:00 committed by GitHub
parent 2ace6a93f0
commit e0465691c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 442 additions and 327 deletions

View File

@ -218,7 +218,9 @@ public:
namespace entity_cache
{
extern CachedEntity array[MAX_ENTITIES]; // b1g fat array in
// b1g fat array in
extern std::vector<CachedEntity *> valid_ents;
extern CachedEntity array[MAX_ENTITIES];
inline CachedEntity &Get(int idx)
{
if (idx < 0 || idx >= 2048)

View File

@ -22,11 +22,10 @@ void Update()
return;
// Find flags if missing
if (!flags[0].ent || !flags[1].ent)
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
// We cannot identify a bad entity as a flag due to the unreliability of it
if (CE_BAD(ent) || ent->m_iClassID() != CL_CLASS(CCaptureFlag))
if (ent->m_iClassID() != CL_CLASS(CCaptureFlag))
continue;
// Store flags
@ -154,7 +153,7 @@ ETFFlagStatus getStatus(int team)
namespace plcontroller
{
// Array that controls all the payloads for each team. Red team is first, then comes blue team.
// Valid_ents that controls all the payloads for each team. Red team is first, then comes blue team.
static std::array<std::vector<CachedEntity *>, 2> payloads;
static Timer update_payloads{};
@ -167,11 +166,11 @@ void Update()
for (auto &entry : payloads)
entry.clear();
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
// Not the object we need or invalid (team)
if (CE_BAD(ent) || ent->m_iClassID() != CL_CLASS(CObjectCartDispenser) || ent->m_iTeam() < TEAM_RED || ent->m_iTeam() > TEAM_BLU)
if (ent->m_iClassID() != CL_CLASS(CObjectCartDispenser) || ent->m_iTeam() < TEAM_RED || ent->m_iTeam() > TEAM_BLU)
continue;
int team = ent->m_iTeam();
@ -241,10 +240,9 @@ void UpdateObjectiveResource()
if (CE_GOOD(objective_resource) && objective_resource->m_iClassID() == CL_CLASS(CTFObjectiveResource))
return;
// Find ObjectiveResource and gamerules
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent) || ent->m_iClassID() != CL_CLASS(CTFObjectiveResource))
if (ent->m_iClassID() != CL_CLASS(CTFObjectiveResource))
continue;
// Found it
objective_resource = ent;
@ -486,7 +484,9 @@ void LevelInit()
cpcontroller::LevelInit();
}
static InitRoutine init([]() {
EC::Register(EC::CreateMove, CreateMove, "capturelogic_update");
EC::Register(EC::LevelInit, LevelInit, "capturelogic_levelinit");
});
static InitRoutine init(
[]()
{
EC::Register(EC::CreateMove, CreateMove, "capturelogic_update");
EC::Register(EC::LevelInit, LevelInit, "capturelogic_levelinit");
});

View File

@ -28,10 +28,9 @@ void UpdateObjectiveResource()
if (CE_GOOD(objective_resource) && objective_resource->m_iClassID() == CL_CLASS(CTFObjectiveResource))
return;
// Find ObjectiveResource and gamerules
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent) || ent->m_iClassID() != CL_CLASS(CTFObjectiveResource))
if (ent->m_iClassID() != CL_CLASS(CTFObjectiveResource))
continue;
// Found it
objective_resource = ent;
@ -251,9 +250,11 @@ void LevelInit()
objective_resource = nullptr;
}
static InitRoutine init([]() {
EC::Register(EC::CreateMove, UpdateObjectiveResource, "cpcontroller_updateent");
EC::Register(EC::CreateMove, UpdateControlPoints, "cpcontroller_updatecp");
EC::Register(EC::LevelInit, LevelInit, "levelinit_cocontroller");
});
static InitRoutine init(
[]()
{
EC::Register(EC::CreateMove, UpdateObjectiveResource, "cpcontroller_updateent");
EC::Register(EC::CreateMove, UpdateControlPoints, "cpcontroller_updatecp");
EC::Register(EC::LevelInit, LevelInit, "levelinit_cocontroller");
});
} // namespace cpcontroller

View File

@ -137,19 +137,26 @@ std::optional<Vector> CachedEntity::m_vecDormantOrigin()
namespace entity_cache
{
CachedEntity array[MAX_ENTITIES]{};
std::vector<CachedEntity *> valid_ents;
void Update()
{
max = g_IEntityList->GetHighestEntityIndex();
valid_ents.clear(); // Reserving isn't necessary as this doesn't reallocate it
if (max >= MAX_ENTITIES)
{
max = MAX_ENTITIES - 1;
}
for (int i = 0; i <= max; i++)
{
array[i].Update();
if (CE_GOOD((&array[i])))
{
array[i].hitboxes.UpdateBones();
valid_ents.push_back(&array[i]);
}
}
}

View File

@ -22,11 +22,11 @@ void Update()
return;
// Find flags if missing
if (!flags[0].ent || !flags[1].ent)
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
// We cannot identify a bad entity as a flag due to the unreliability of it
if (CE_BAD(ent) || ent->m_iClassID() != CL_CLASS(CCaptureFlag))
if (ent->m_iClassID() != CL_CLASS(CCaptureFlag))
continue;
// Store flags
@ -149,8 +149,10 @@ ETFFlagStatus getStatus(int team)
// Mark as home if nothing is found
return TF_FLAGINFO_HOME;
}
static InitRoutine init([]() {
EC::Register(EC::CreateMove, Update, "flagcontroller_update");
EC::Register(EC::LevelInit, LevelInit, "flagcontroller_levelinit");
});
static InitRoutine init(
[]()
{
EC::Register(EC::CreateMove, Update, "flagcontroller_update");
EC::Register(EC::LevelInit, LevelInit, "flagcontroller_levelinit");
});
} // namespace flagcontroller

View File

@ -747,11 +747,9 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
CachedEntity *target_highest_ent = nullptr;
target_highest_score = -256;
std::optional<hacks::tf2::backtrack::BacktrackData> bt_tick = std::nullopt;
for (int i = 1; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
ent = ENTITY(i);
if (CE_BAD(ent))
continue; // Check for null and dormant
// Check for null and dormant
// Check whether the current ent is good enough to target
bool isTargetGood = false;
@ -803,7 +801,7 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
}
case 2:
{
scr = 4096.0f - calculated_data_array[i].aim_position.DistTo(g_pLocalPlayer->v_Eye);
scr = 4096.0f - calculated_data_array[ent->m_IDX].aim_position.DistTo(g_pLocalPlayer->v_Eye);
break;
}
case 3: // Health Priority (Lowest)
@ -813,7 +811,7 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
}
case 4: // Distance Priority (Furthest Away)
{
scr = calculated_data_array[i].aim_position.DistTo(g_pLocalPlayer->v_Eye);
scr = calculated_data_array[ent->m_IDX].aim_position.DistTo(g_pLocalPlayer->v_Eye);
break;
}
case 5: // Health Priority (Highest)
@ -845,7 +843,7 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
// Restore tick
if (shouldBacktrack(ent))
hacks::tf2::backtrack::RestoreEntity(i);
hacks::tf2::backtrack::RestoreEntity(ent->m_IDX);
}
if (target_highest_ent && bt_tick)

View File

@ -32,11 +32,11 @@ static inline void CreateMove()
// Empty the array
sniperdot_array.fill(0);
// Find sniper dots
for (int i = g_IEngine->GetMaxClients() + 1; i <= HIGHEST_ENTITY; i++)
for (auto &dot_ent : entity_cache::valid_ents)
{
CachedEntity *dot_ent = ENTITY(i);
// Not a sniper dot
if (CE_BAD(dot_ent) || dot_ent->m_iClassID() != CL_CLASS(CSniperDot))
if (dot_ent->m_iClassID() != CL_CLASS(CSniperDot))
continue;
// Get the player it belongs to
auto ent_idx = HandleToIDX(CE_INT(dot_ent, netvar.m_hOwnerEntity));
@ -255,14 +255,16 @@ static void shutdown()
*original_ptrY = original_ProxyFnY;
}
static InitRoutine init([]() {
hook();
EC::Register(EC::Shutdown, shutdown, "antiantiaim_shutdown");
EC::Register(EC::CreateMove, CreateMove, "cm_antiantiaim");
EC::Register(EC::CreateMoveWarp, CreateMove, "cmw_antiantiaim");
static InitRoutine init(
[]()
{
hook();
EC::Register(EC::Shutdown, shutdown, "antiantiaim_shutdown");
EC::Register(EC::CreateMove, CreateMove, "cm_antiantiaim");
EC::Register(EC::CreateMoveWarp, CreateMove, "cmw_antiantiaim");
#if ENABLE_TEXTMODE
EC::Register(EC::CreateMove, modifyAngles, "cm_textmodeantiantiaim");
EC::Register(EC::CreateMoveWarp, modifyAngles, "cmw_textmodeantiantiaim");
EC::Register(EC::CreateMove, modifyAngles, "cm_textmodeantiantiaim");
EC::Register(EC::CreateMoveWarp, modifyAngles, "cmw_textmodeantiantiaim");
#endif
});
});
} // namespace hacks::shared::anti_anti_aim

View File

@ -133,8 +133,10 @@ void CreateMove()
noaa = false;
}
static InitRoutine EC([]() {
EC::Register(EC::CreateMove, CreateMove, "antibackstab", EC::late);
EC::Register(EC::CreateMoveWarp, CreateMove, "antibackstab_w", EC::late);
});
static InitRoutine EC(
[]()
{
EC::Register(EC::CreateMove, CreateMove, "antibackstab", EC::late);
EC::Register(EC::CreateMoveWarp, CreateMove, "antibackstab_w", EC::late);
});
} // namespace hacks::tf2::antibackstab

View File

@ -39,8 +39,10 @@ void cm()
}
}
}
static InitRoutine EC([]() {
EC::Register(EC::CreateMove, cm, "antidisguise", EC::average);
EC::Register(EC::CreateMoveWarp, cm, "antidisguise_w", EC::average);
});
static InitRoutine EC(
[]()
{
EC::Register(EC::CreateMove, cm, "antidisguise", EC::average);
EC::Register(EC::CreateMoveWarp, cm, "antidisguise_w", EC::average);
});
} // namespace hacks::tf2::antidisguise

View File

@ -21,11 +21,9 @@ int NearbyEntities()
int ret = 0;
if (CE_BAD(LOCAL_E) || CE_BAD(LOCAL_W))
return ret;
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent))
continue;
if (ent == LOCAL_E)
continue;
if (!ent->m_bAlivePlayer())
@ -54,11 +52,8 @@ static void CreateMove()
else
shouldm2 = false;
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent))
continue;
if (!IsProjectile(ent) && !ent->m_bGrenadeProjectile())
continue;
if (!ent->m_bEnemy())

View File

@ -85,13 +85,9 @@ void CreateMove()
targets.clear();
// Cycle through the ents and search for valid ents
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
// Assign the for loops tick number to an ent
CachedEntity *ent = ENTITY(i);
// Check for dormancy and if valid
if (CE_BAD(ent))
continue;
// Check if ent is a flare or suitable target and push to respective
// arrays
if (IsFlare(ent))

View File

@ -215,11 +215,8 @@ int BlastDangerValue(CachedEntity *patient)
return 1;
}
// Find rockets/pipes nearby
for (int i = PLAYER_ARRAY_SIZE; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent))
continue;
if (!ent->m_bEnemy())
continue;
if (ent->m_Type() != ENTITY_PROJECTILE)
@ -228,7 +225,7 @@ int BlastDangerValue(CachedEntity *patient)
continue;
if (patient->m_vecOrigin().DistTo(ent->m_vecOrigin()) > (int) auto_vacc_proj_danger_range)
continue;
proj_data_array.push_back(proj_data_s{ i, ent->m_vecOrigin() });
proj_data_array.push_back(proj_data_s{ ent->m_IDX, ent->m_vecOrigin() });
}
return 0;
}
@ -250,11 +247,9 @@ int NearbyEntities()
int ret = 0;
if (CE_BAD(LOCAL_E) || CE_BAD(LOCAL_W))
return ret;
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent))
continue;
if (ent == LOCAL_E)
continue;
if (!ent->m_bAlivePlayer())

View File

@ -152,15 +152,12 @@ void CreateMove()
float closest_dist = 0.0f;
Vector closest_vec;
// Loop to find the closest entity
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
// Find an ent from the for loops current tick
CachedEntity *ent = ENTITY(i);
// Check if null or dormant
if (CE_BAD(ent))
continue;
// Check if ent should be reflected
if (!ShouldReflect(ent))
@ -268,11 +265,13 @@ void Draw()
#endif
}
static InitRoutine EC([]() {
EC::Register(EC::CreateMove, CreateMove, "cm_auto_reflect", EC::average);
EC::Register(EC::CreateMoveWarp, CreateMove, "cmw_auto_reflect", EC::average);
static InitRoutine EC(
[]()
{
EC::Register(EC::CreateMove, CreateMove, "cm_auto_reflect", EC::average);
EC::Register(EC::CreateMoveWarp, CreateMove, "cmw_auto_reflect", EC::average);
#if ENABLE_VISUALS
EC::Register(EC::Draw, Draw, "draw_auto_reflect", EC::average);
EC::Register(EC::Draw, Draw, "draw_auto_reflect", EC::average);
#endif
});
});
} // namespace hacks::tf::autoreflect

View File

@ -124,13 +124,10 @@ void CreateMove()
targets.clear();
// Cycle through the ents and search for valid ents
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
// Assign the for loops index to an ent
CachedEntity *ent = ENTITY(i);
// Check for dormancy and if valid
if (CE_INVALID(ent))
continue;
// Check if ent is a bomb or suitable target and push to respective
// arrays
if (IsBomb(ent))
@ -188,7 +185,7 @@ void CreateMove()
shouldExplode = true;
else if (*legit == 2 && CE_GOOD(target) && IsVectorVisible(g_pLocalPlayer->v_Eye, bomb->m_vecOrigin(), true) && IsVectorVisible(g_pLocalPlayer->v_Eye, *position, true))
shouldExplode = true;
if (shouldExplode)
{
// Aim at bomb

View File

@ -41,9 +41,8 @@ public:
if (GetPlayerForUserID(event->GetInt("attacker")) == g_IEngine->GetLocalPlayer())
{
bool nearby = false;
for (int i = 1; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
auto ent = ENTITY(i);
if (CE_VALID(ent) && (ent->m_Type() == ENTITY_PLAYER || ent->m_iClassID() == CL_CLASS(CObjectSentrygun)) && ent->m_bEnemy() && ent->m_bAlivePlayer())
{
if (!player_tools::shouldTarget(ent))
@ -81,34 +80,37 @@ public:
AutoTauntListener listener;
InitRoutine init([]() {
g_IEventManager2->AddListener(&listener, "player_death", false);
EC::Register(
EC::Shutdown, []() { g_IEventManager2->RemoveListener(&listener); }, "Shutdown_Autotaunt");
EC::Register(
EC::CreateMove,
[]() {
if (prev_slot != -1 && CE_GOOD(LOCAL_E) && CE_GOOD(LOCAL_W) && LOCAL_E->m_bAlivePlayer() && taunt_t.test_and_set(100))
InitRoutine init(
[]()
{
g_IEventManager2->AddListener(&listener, "player_death", false);
EC::Register(
EC::Shutdown, []() { g_IEventManager2->RemoveListener(&listener); }, "Shutdown_Autotaunt");
EC::Register(
EC::CreateMove,
[]()
{
if (in_taunt)
if (prev_slot != -1 && CE_GOOD(LOCAL_E) && CE_GOOD(LOCAL_W) && LOCAL_E->m_bAlivePlayer() && taunt_t.test_and_set(100))
{
if (!HasCondition<TFCond_Taunting>(LOCAL_E))
if (in_taunt)
{
hack::ExecuteCommand(format("slot", prev_slot + 1));
prev_slot = -1;
in_taunt = false;
if (!HasCondition<TFCond_Taunting>(LOCAL_E))
{
hack::ExecuteCommand(format("slot", prev_slot + 1));
prev_slot = -1;
in_taunt = false;
}
else
taunt_t.update();
}
else
{
hack::ExecuteCommand("taunt");
in_taunt = true;
taunt_t.update();
}
}
else
{
hack::ExecuteCommand("taunt");
in_taunt = true;
taunt_t.update();
}
}
},
"Autotaunt_CM");
});
},
"Autotaunt_CM");
});
} // namespace hacks::tf::autotaunt

View File

@ -34,7 +34,7 @@ static void CreateMove()
// Bhop likelihood
if (UniformRandomInt(0, 99) > *bhop_chance)
return;
// var for "if on ground" from the flags netvar
bool ground = CE_INT(g_pLocalPlayer->entity, netvar.iFlags) & (1 << 0);
// Var for if the player is pressing jump

View File

@ -357,46 +357,81 @@ static void cm()
ResetEntityStrings(entity_tick); // Clear any strings entities have
entities_need_repaint.clear(); // Clear data on entities that need redraw
int max_clients = g_GlobalVars->maxClients;
int limit = HIGHEST_ENTITY;
int max_clients = g_GlobalVars->maxClients;
int limit = HIGHEST_ENTITY;
bool run_all_ents = false;
const bool vischeck_tick = g_GlobalVars->tickcount % TIME_TO_TICKS(0.50f) == 0;
// If not using any other special esp, we lower the min to the max
// clients
if (!buildings && !proj_esp && !item_esp)
limit = std::min(max_clients, HIGHEST_ENTITY);
{
// Do a vischeck every 1/2s
const bool vischeck_tick = g_GlobalVars->tickcount % TIME_TO_TICKS(0.50f) == 0;
// Do a vischeck every 1/2s
{ // Prof section ends when out of scope, these brackets here.
PROF_SECTION(CM_ESP_EntityLoop);
// Loop through entities
for (int i = 0; i <= limit; i++)
{
// Get an entity from the loop tick and process it
CachedEntity *ent = ENTITY(i);
if (CE_INVALID(ent) || !ent->m_bAlivePlayer())
continue;
bool player = i < max_clients;
if (player)
{ // Prof section ends when out of scope, these brackets here.
PROF_SECTION(CM_ESP_EntityLoop);
// Loop through entities
for (int i = 0; i <= max_clients; i++)
{
ProcessEntity(ent);
hitboxUpdate(ent);
// Get an entity from the loop tick and process it
CachedEntity *ent = ENTITY(i);
if (CE_INVALID(ent) || !ent->m_bAlivePlayer())
continue;
bool player = i < max_clients;
if (player)
{
ProcessEntity(ent);
hitboxUpdate(ent);
}
else if (entity_tick)
{
ProcessEntity(ent);
hitboxUpdate(ent);
}
if (data[ent->m_IDX].needs_paint)
{
// Checking this every tick is a waste of nanoseconds
if (vischeck_tick && vischeck)
data[ent->m_IDX].transparent = !ent->IsVisible();
entities_need_repaint.push_back({ ent->m_IDX, ent->m_vecOrigin().DistToSqr(g_pLocalPlayer->v_Origin) });
}
}
else if (entity_tick)
}
}
else
{
{ // Prof section ends when out of scope, these brackets here.
PROF_SECTION(CM_ESP_EntityLoop);
// Loop through entities
for (auto &ent_index : entity_cache::valid_ents)
{
ProcessEntity(ent);
hitboxUpdate(ent);
}
// Get an entity from the loop tick and process it
if (!ent_index->m_bAlivePlayer())
continue;
if (data[ent->m_IDX].needs_paint)
{
// Checking this every tick is a waste of nanoseconds
if (vischeck_tick && vischeck)
data[ent->m_IDX].transparent = !ent->IsVisible();
entities_need_repaint.push_back({ ent->m_IDX, ent->m_vecOrigin().DistToSqr(g_pLocalPlayer->v_Origin) });
bool player = ent_index->m_IDX < max_clients;
if (player)
{
ProcessEntity(ent_index);
hitboxUpdate(ent_index);
}
else if (entity_tick)
{
ProcessEntity(ent_index);
hitboxUpdate(ent_index);
}
if (data[ent_index->m_IDX].needs_paint)
{
// Checking this every tick is a waste of nanoseconds
if (vischeck_tick && vischeck)
data[ent_index->m_IDX].transparent = !ent_index->IsVisible();
entities_need_repaint.push_back({ ent_index->m_IDX, ent_index->m_vecOrigin().DistToSqr(g_pLocalPlayer->v_Origin) });
}
}
}
}

View File

@ -55,11 +55,8 @@ void draw()
return;
std::vector<Vector> points;
Vector screen;
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
auto ent = ENTITY(i);
if (CE_BAD(ent))
continue;
if (!ent->m_bEnemy())
continue;
if (ent->m_iClassID() != CL_CLASS(CTFGrenadePipebombProjectile))

View File

@ -451,41 +451,71 @@ static void cm()
if (roambot && !foundPreferredTarget && (!follow_target || change || ClassPriority(ENTITY(follow_target)) < 6))
{
// Try to get a new target
auto ent_count = followcart ? HIGHEST_ENTITY : g_IEngine->GetMaxClients();
for (int i = 1; i <= ent_count; i++)
if (!followcart)
{
auto entity = ENTITY(i);
if (!isValidTarget(entity))
continue;
if (!follow_target)
int ent_count = g_IEngine->GetMaxClients();
for (int i = 1; i <= ent_count; i++)
{
if (CE_INVALID(entity))
auto entity = ENTITY(i);
if (!isValidTarget(entity))
continue;
}
else
{
if (CE_BAD(entity))
if (!follow_target)
{
if (CE_INVALID(entity))
continue;
}
else
{
if (CE_BAD(entity))
continue;
}
if (entity->m_bEnemy())
continue;
// favor closer entitys
if (CE_GOOD(entity))
{
if (follow_target && ENTITY(follow_target)->m_flDistance() < entity->m_flDistance()) // favor closer entitys
continue;
// check if new target has a higher priority than current
// target
if (ClassPriority(ENTITY(follow_target)) >= ClassPriority(ENTITY(i)))
continue;
}
if (startFollow(entity, isNavBotCM))
{
// ooooo, a target
navinactivity.update();
follow_target = i;
afkTicks[i].update(); // set afk time to 03
break;
}
}
if (entity->m_bEnemy())
continue;
// favor closer entitys
if (CE_GOOD(entity))
}
else
{
for (auto &entity : entity_cache::valid_ents)
{
if (!isValidTarget(entity))
continue;
if (entity->m_bEnemy())
continue;
// favor closer entitys
if (follow_target && ENTITY(follow_target)->m_flDistance() < entity->m_flDistance()) // favor closer entitys
continue;
// check if new target has a higher priority than current
// target
if (ClassPriority(ENTITY(follow_target)) >= ClassPriority(ENTITY(i)))
if (ClassPriority(ENTITY(follow_target)) >= ClassPriority(entity))
continue;
}
if (startFollow(entity, isNavBotCM))
{
// ooooo, a target
navinactivity.update();
follow_target = i;
afkTicks[i].update(); // set afk time to 03
break;
if (startFollow(entity, isNavBotCM))
{
// ooooo, a target
navinactivity.update();
follow_target = entity->m_IDX;
afkTicks[follow_target].update(); // set afk time to 03
break;
}
}
}
}

View File

@ -137,16 +137,15 @@ int getCarriedBuilding()
{
if (CE_INT(LOCAL_E, netvar.m_bCarryingObject))
return HandleToIDX(CE_INT(LOCAL_E, netvar.m_hCarriedObject));
for (int i = 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
auto ent = ENTITY(i);
if (CE_BAD(ent) || ent->m_Type() != ENTITY_BUILDING)
if (ent->m_Type() != ENTITY_BUILDING)
continue;
if (HandleToIDX(CE_INT(ent, netvar.m_hBuilder)) != LOCAL_E->m_IDX)
continue;
if (!CE_INT(ent, netvar.m_bPlacing))
continue;
return i;
return ent->m_IDX;
}
return -1;
}
@ -750,11 +749,9 @@ static CatCommand dump_vars_by_name("debug_dump_netvars_name", "Dump netvars of
if (args.ArgC() < 2)
return;
std::string name(args.Arg(1));
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent))
continue;
ClientClass *clz = RAW_ENT(ent)->GetClientClass();
if (!clz)
continue;

View File

@ -115,10 +115,9 @@ bool shouldSearchAmmo()
std::vector<CachedEntity *> getDispensers()
{
std::vector<CachedEntity *> entities;
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent) || ent->m_iClassID() != CL_CLASS(CObjectDispenser) || ent->m_iTeam() != g_pLocalPlayer->team)
if (ent->m_iClassID() != CL_CLASS(CObjectDispenser) || ent->m_iTeam() != g_pLocalPlayer->team)
continue;
if (CE_BYTE(ent, netvar.m_bCarryDeploy) || CE_BYTE(ent, netvar.m_bHasSapper) || CE_BYTE(ent, netvar.m_bBuilding))
continue;
@ -138,11 +137,8 @@ std::vector<CachedEntity *> getDispensers()
std::vector<CachedEntity *> getEntities(const std::vector<k_EItemType> &itemtypes)
{
std::vector<CachedEntity *> entities;
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent))
continue;
for (auto &itemtype : itemtypes)
{
if (ent->m_ItemType() == itemtype)
@ -381,10 +377,9 @@ void refreshLocalBuildings()
myDispenser = nullptr;
if (CE_GOOD(LOCAL_E))
{
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (!ent || CE_BAD(ent) || ent->m_bEnemy() || !ent->m_bAlivePlayer())
if (ent->m_bEnemy() || !ent->m_bAlivePlayer())
continue;
auto cid = ent->m_iClassID();
if (cid != CL_CLASS(CObjectSentrygun) && cid != CL_CLASS(CObjectDispenser))
@ -945,9 +940,8 @@ bool snipeSentries()
if (!snipe_sentries_shortrange && (g_pLocalPlayer->clazz == tf_scout || g_pLocalPlayer->clazz == tf_pyro))
return false;
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
// Invalid sentry
if (!isSnipeTargetValid(ent))
continue;

View File

@ -239,16 +239,15 @@ void Draw()
if (enemies_over_teammates)
enemies.clear();
std::vector<CachedEntity *> sentries;
for (int i = 1; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
ent = ENTITY(i);
if (CE_INVALID(ent))
continue;
if (ent->m_iTeam() == 0)
continue;
if (!ent->m_bAlivePlayer())
continue;
if (i == g_IEngine->GetLocalPlayer())
if (ent->m_IDX == g_IEngine->GetLocalPlayer())
continue;
if (!show_teammates && ent->m_Type() == ENTITY_PLAYER && !ent->m_bEnemy())
continue;
@ -282,27 +281,29 @@ void Draw()
}
}
static InitRoutine init([]() {
// Background circles
for (int i = 0; i < 2; ++i)
tx_teams.push_back(textures::atlas().create_sprite(704, 384 + i * 64, 64, 64));
// Items
for (int i = 0; i < 2; ++i)
tx_items.push_back(textures::atlas().create_sprite(640, 384 + i * 64, 64, 64));
// Classes
for (int i = 0; i < 3; ++i)
static InitRoutine init(
[]()
{
tx_class.emplace_back();
for (int j = 0; j < 9; ++j)
tx_class[i].push_back(textures::atlas().create_sprite(j * 64, 320 + i * 64, 64, 64));
}
for (int i = 0; i < 2; i++)
tx_buildings.push_back(textures::atlas().create_sprite(576 + i * 64, 320, 64, 64));
for (int i = 0; i < 4; i++)
tx_sentry.push_back(textures::atlas().create_sprite(640 + i * 64, 256, 64, 64));
logging::Info("Radar sprites loaded");
EC::Register(EC::Draw, Draw, "radar", EC::average);
});
// Background circles
for (int i = 0; i < 2; ++i)
tx_teams.push_back(textures::atlas().create_sprite(704, 384 + i * 64, 64, 64));
// Items
for (int i = 0; i < 2; ++i)
tx_items.push_back(textures::atlas().create_sprite(640, 384 + i * 64, 64, 64));
// Classes
for (int i = 0; i < 3; ++i)
{
tx_class.emplace_back();
for (int j = 0; j < 9; ++j)
tx_class[i].push_back(textures::atlas().create_sprite(j * 64, 320 + i * 64, 64, 64));
}
for (int i = 0; i < 2; i++)
tx_buildings.push_back(textures::atlas().create_sprite(576 + i * 64, 320, 64, 64));
for (int i = 0; i < 4; i++)
tx_sentry.push_back(textures::atlas().create_sprite(640 + i * 64, 256, 64, 64));
logging::Info("Radar sprites loaded");
EC::Register(EC::Draw, Draw, "radar", EC::average);
});
} // namespace hacks::tf::radar
#endif

View File

@ -135,10 +135,9 @@ CachedEntity *getClosestSpell()
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
return ent;
for (int i = g_IEngine->GetMaxClients(); i < HIGHEST_ENTITY; i++)
for (auto &spell : entity_cache::valid_ents)
{
CachedEntity *spell = ENTITY(i);
if (CE_INVALID(spell) || !spell->m_vecDormantOrigin() || (spell->m_ItemType() != ITEM_SPELL && spell->m_ItemType() != ITEM_SPELL_RARE))
if (!spell->m_vecDormantOrigin() || (spell->m_ItemType() != ITEM_SPELL && spell->m_ItemType() != ITEM_SPELL_RARE))
continue;
float dist = spell->m_flDistance();
if (dist < best_dist || (is_dormant && !RAW_ENT(spell)->IsDormant() && dist <= 300.0f))

View File

@ -124,59 +124,118 @@ void draw()
if (!enabled || CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
return;
// Loop all players
for (int i = 1; i < (*buildings ? MAX_ENTITIES : g_IEngine->GetMaxClients()); i++)
if (*buildings)
{
// Get and check player
auto ent = ENTITY(i);
Vector origin;
std::optional<rgba_t> color = std::nullopt;
if (CE_INVALID(ent))
for (auto &ent : entity_cache::valid_ents)
{
if (i > g_IEngine->GetMaxClients() || !g_pPlayerResource->isAlive(i))
continue;
if (g_pPlayerResource->GetTeam(i) == g_pLocalPlayer->team && !teammates)
continue;
auto vec = soundcache::GetSoundLocation(i);
if (!vec)
continue;
if (*max_dist && vec->DistTo(g_pLocalPlayer->v_Origin) > *max_dist)
continue;
origin = *vec;
color = colors::FromRGBA8(160, 160, 160, *opaque);
}
else
{
if ((!RAW_ENT(ent)->IsDormant() && !ent->m_bAlivePlayer()) || !ent->m_vecDormantOrigin())
continue;
if (i <= g_IEngine->GetMaxClients() && !g_pPlayerResource->isAlive(i))
continue;
origin = *ent->m_vecDormantOrigin();
if (*buildings)
if (ent->m_Type() != ENTITY_PLAYER && ent->m_Type() != ENTITY_BUILDING)
// Get and check player
const uint16_t curr_idx = ent->m_IDX;
Vector origin;
std::optional<rgba_t> color = std::nullopt;
if (CE_INVALID(ent))
{
if (curr_idx > g_IEngine->GetMaxClients() || !g_pPlayerResource->isAlive(curr_idx))
continue;
if (ent == LOCAL_E)
continue;
color = getColor(ent);
if (!color)
continue;
if (RAW_ENT(ent)->IsDormant())
color = colors::FromRGBA8(160, 160, 160, *opaque);
color->a = *opaque;
}
if (g_pPlayerResource->GetTeam(curr_idx) == g_pLocalPlayer->team && !teammates)
continue;
auto vec = soundcache::GetSoundLocation(curr_idx);
if (!vec)
continue;
if (*max_dist && vec->DistTo(g_pLocalPlayer->v_Origin) > *max_dist)
continue;
origin = *vec;
color = colors::FromRGBA8(160, 160, 160, *opaque);
}
else
{
if ((!RAW_ENT(ent)->IsDormant() && !ent->m_bAlivePlayer()) || !ent->m_vecDormantOrigin())
continue;
if (curr_idx <= g_IEngine->GetMaxClients() && !g_pPlayerResource->isAlive(curr_idx))
continue;
origin = *ent->m_vecDormantOrigin();
if (*buildings)
if (ent->m_Type() != ENTITY_PLAYER && ent->m_Type() != ENTITY_BUILDING)
continue;
if (ent == LOCAL_E)
continue;
color = getColor(ent);
if (!color)
continue;
if (RAW_ENT(ent)->IsDormant())
color = colors::FromRGBA8(160, 160, 160, *opaque);
color->a = *opaque;
}
Vector out;
if (!draw::WorldToScreen(origin, out))
Vector out;
if (!draw::WorldToScreen(origin, out))
{
// We need to flip on both x and y axis in case m_vecOrigin its not actually on screen
out.x = draw::width - out.x;
out.y = draw::height - out.y;
auto extended = toBorder(draw::width / 2, draw::height / 2, out.x, out.y, 0, 0, draw::width, draw::height);
out.x = extended.x;
out.y = extended.y;
}
draw::Line(draw::width / 2, draw::height / 2, out.x - draw::width / 2, out.y - draw::height / 2, *color, *line_thickness);
}
}
else
{
for (int i = 1; i <= g_IEngine->GetMaxClients(); i++)
{
// We need to flip on both x and y axis in case m_vecOrigin its not actually on screen
out.x = draw::width - out.x;
out.y = draw::height - out.y;
// Get and check player
auto ent = ENTITY(i);
Vector origin;
std::optional<rgba_t> color = std::nullopt;
auto extended = toBorder(draw::width / 2, draw::height / 2, out.x, out.y, 0, 0, draw::width, draw::height);
out.x = extended.x;
out.y = extended.y;
if (CE_INVALID(ent))
{
if (i > g_IEngine->GetMaxClients() || !g_pPlayerResource->isAlive(i))
continue;
if (g_pPlayerResource->GetTeam(i) == g_pLocalPlayer->team && !teammates)
continue;
auto vec = soundcache::GetSoundLocation(i);
if (!vec)
continue;
if (*max_dist && vec->DistTo(g_pLocalPlayer->v_Origin) > *max_dist)
continue;
origin = *vec;
color = colors::FromRGBA8(160, 160, 160, *opaque);
}
else
{
if ((!RAW_ENT(ent)->IsDormant() && !ent->m_bAlivePlayer()) || !ent->m_vecDormantOrigin())
continue;
if (i <= g_IEngine->GetMaxClients() && !g_pPlayerResource->isAlive(i))
continue;
origin = *ent->m_vecDormantOrigin();
if (*buildings)
if (ent->m_Type() != ENTITY_PLAYER && ent->m_Type() != ENTITY_BUILDING)
continue;
if (ent == LOCAL_E)
continue;
color = getColor(ent);
if (!color)
continue;
if (RAW_ENT(ent)->IsDormant())
color = colors::FromRGBA8(160, 160, 160, *opaque);
color->a = *opaque;
}
Vector out;
if (!draw::WorldToScreen(origin, out))
{
// We need to flip on both x and y axis in case m_vecOrigin its not actually on screen
out.x = draw::width - out.x;
out.y = draw::height - out.y;
auto extended = toBorder(draw::width / 2, draw::height / 2, out.x, out.y, 0, 0, draw::width, draw::height);
out.x = extended.x;
out.y = extended.y;
}
draw::Line(draw::width / 2, draw::height / 2, out.x - draw::width / 2, out.y - draw::height / 2, *color, *line_thickness);
}
draw::Line(draw::width / 2, draw::height / 2, out.x - draw::width / 2, out.y - draw::height / 2, *color, *line_thickness);
}
}

View File

@ -1804,15 +1804,9 @@ CatCommand print_classnames("debug_print_classnames", "Lists classnames currentl
CachedEntity *ent;
// Go through all the entities
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
// Get an entity
ent = ENTITY(i);
// Check for null/dormant
if (CE_BAD(ent))
continue;
// Print in console, the class name of the ent
logging::Info(format(RAW_ENT(ent)->GetClientClass()->m_pNetworkName).c_str());
}

View File

@ -81,7 +81,7 @@ DEFINE_HOOKED_METHOD(FrameStageNotify, void, void *this_, ClientFrameStage_t sta
{
auto *kv = new KeyValues("LightmappedGeneric" /*pMaterial->GetShaderName()*/);
kv->SetString("$basetexture", (*override_textures_texture).c_str());
//kv->SetString("$basetexturetransform", "center .5 .5 scale 6 6 rotate 0 translate 0 0");
// kv->SetString("$basetexturetransform", "center .5 .5 scale 6 6 rotate 0 translate 0 0");
kv->SetString("$surfaceprop", "concrete");
pMaterial->SetShaderAndParams(kv);
}
@ -214,16 +214,24 @@ template <typename T> void rvarCallback(settings::VariableBase<T> &, T)
{
update_nightmode = true;
}
static InitRoutine init_fsn([]() {
nightmode_gui.installChangeCallback(rvarCallback<float>);
nightmode_world.installChangeCallback(rvarCallback<float>);
nightmode_skybox.installChangeCallback(rvarCallback<float>);
nightmode_gui_color.installChangeCallback(rvarCallback<rgba_t>);
nightmode_world_color.installChangeCallback(rvarCallback<rgba_t>);
nightmode_skybox_color.installChangeCallback(rvarCallback<rgba_t>);
override_textures.installChangeCallback([](settings::VariableBase<bool> &, bool after) { update_override_textures = true; });
override_textures_texture.installChangeCallback([](settings::VariableBase<std::string> &, std::string after) { update_override_textures = true; });
EC::Register(
EC::LevelInit, []() { update_nightmode = true; update_override_textures = true; }, "levelinit_fsn");
});
static InitRoutine init_fsn(
[]()
{
nightmode_gui.installChangeCallback(rvarCallback<float>);
nightmode_world.installChangeCallback(rvarCallback<float>);
nightmode_skybox.installChangeCallback(rvarCallback<float>);
nightmode_gui_color.installChangeCallback(rvarCallback<rgba_t>);
nightmode_world_color.installChangeCallback(rvarCallback<rgba_t>);
nightmode_skybox_color.installChangeCallback(rvarCallback<rgba_t>);
override_textures.installChangeCallback([](settings::VariableBase<bool> &, bool after) { update_override_textures = true; });
override_textures_texture.installChangeCallback([](settings::VariableBase<std::string> &, std::string after) { update_override_textures = true; });
EC::Register(
EC::LevelInit,
[]()
{
update_nightmode = true;
update_override_textures = true;
},
"levelinit_fsn");
});
} // namespace hooked_methods

View File

@ -11,7 +11,6 @@ static bool hoovy_list[PLAYER_ARRAY_SIZE] = { 0 };
bool HasSandvichOut(CachedEntity *entity)
{
IF_GAME(!IsTF2()) return false;
int weapon_idx;
CachedEntity *weapon;
@ -43,7 +42,7 @@ void UpdateHoovyList()
return;
static CachedEntity *ent;
for (int i = 1; i <= MAX_PLAYERS && i < g_IEntityList->GetHighestEntityIndex(); i++)
for (int i = 1; i <= MAX_PLAYERS; i++)
{
ent = ENTITY(i);
if (CE_GOOD(ent) && CE_BYTE(ent, netvar.iLifeState) == LIFE_ALIVE)

View File

@ -17,11 +17,10 @@ void Update()
for (auto &entry : payloads)
entry.clear();
for (int i = g_IEngine->GetMaxClients() + 1; i < MAX_ENTITIES; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
// Not the object we need or invalid (team)
if (CE_BAD(ent) || ent->m_iClassID() != CL_CLASS(CObjectCartDispenser) || ent->m_iTeam() < TEAM_RED || ent->m_iTeam() > TEAM_BLU)
if (ent->m_iClassID() != CL_CLASS(CObjectCartDispenser) || ent->m_iTeam() < TEAM_RED || ent->m_iTeam() > TEAM_BLU)
continue;
int team = ent->m_iTeam();
@ -62,8 +61,10 @@ void LevelInit()
entry.clear();
}
static InitRoutine init([]() {
EC::Register(EC::CreateMove, Update, "plcreatemove");
EC::Register(EC::LevelInit, LevelInit, "levelinit_plcontroller");
});
static InitRoutine init(
[]()
{
EC::Register(EC::CreateMove, Update, "plcreatemove");
EC::Register(EC::LevelInit, LevelInit, "levelinit_plcontroller");
});
} // namespace plcontroller

View File

@ -14,12 +14,12 @@ void TFPlayerResource::Update()
IClientEntity *ent;
entity = 0;
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent_not_raw : entity_cache::valid_ents)
{
ent = g_IEntityList->GetClientEntity(i);
auto ent = RAW_ENT(ent_not_raw);
if (ent && ent->GetClientClass()->m_ClassID == RCC_PLAYERRESOURCE)
{
entity = i;
entity = ent_not_raw->m_IDX;
return;
}
}

View File

@ -14,13 +14,12 @@ Vector prevloc[2048]{};
void Update()
{
for (int i = 1; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
CachedEntity *ent = ENTITY(i);
if (CE_BAD(ent))
continue;
const model_t *model = RAW_ENT(ent)->GetModel();
bool issandwich = false;
const uint16_t curr_idx = ent->m_IDX;
if (model && tickcount % 33 == 0)
{
std::string model_name(g_IModelInfo->GetModelName(model));
@ -28,9 +27,9 @@ void Update()
{
issandwich = true;
Vector abs_orig = RAW_ENT(ent)->GetAbsOrigin();
float movement = prevloc[i].DistTo(abs_orig);
float movement = prevloc[curr_idx].DistTo(abs_orig);
logging::Info("Sandwich movement: %f", movement);
prevloc[i] = abs_orig;
prevloc[curr_idx] = abs_orig;
}
}
if (ent->m_Type() == ENTITY_PROJECTILE || issandwich)
@ -41,9 +40,9 @@ void Update()
if (tickcount % 20 == 0)
{
Vector abs_orig = RAW_ENT(ent)->GetAbsOrigin();
float movement = prevloc[i].DistTo(abs_orig);
float movement = prevloc[curr_idx].DistTo(abs_orig);
logging::Info("movement: %f", movement);
prevloc[i] = abs_orig;
prevloc[curr_idx] = abs_orig;
const Vector &v = ent->m_vecVelocity;
Vector eav;
velocity::EstimateAbsVelocity(RAW_ENT(ent), eav);
@ -54,7 +53,7 @@ void Update()
// v.Length(), a.x, a.y, a.z);
logging::Info("%d [%s]: CatVelocity: %.2f %.2f %.2f (%.2f) | "
"EAV: %.2f %.2f %.2f (%.2f)",
i, RAW_ENT(ent)->GetClientClass()->GetName(), v.x, v.y, v.z, v.Length(), eav.x, eav.y, eav.z, eav.Length());
curr_idx, RAW_ENT(ent)->GetClientClass()->GetName(), v.x, v.y, v.z, v.Length(), eav.x, eav.y, eav.z, eav.Length());
}
}
}

View File

@ -25,19 +25,21 @@ void CTeamRoundTimer::Update()
IClientEntity *ent;
entity = 0;
for (int i = 0; i <= HIGHEST_ENTITY; i++)
for (auto &ent : entity_cache::valid_ents)
{
ent = g_IEntityList->GetClientEntity(i);
if (ent && ent->GetClientClass()->m_ClassID == CL_CLASS(CTeamRoundTimer))
auto result_ent = ent->InternalEntity();
if (ent && result_ent->GetClientClass()->m_ClassID == CL_CLASS(CTeamRoundTimer))
{
entity = i;
entity = ent->m_IDX;
return;
}
}
}
CTeamRoundTimer *g_pTeamRoundTimer{ nullptr };
static InitRoutine init_trt([]() {
EC::Register(
EC::CreateMove, []() { g_pTeamRoundTimer->Update(); }, "update_teamroundtimer", EC::early);
});
static InitRoutine init_trt(
[]()
{
EC::Register(
EC::CreateMove, []() { g_pTeamRoundTimer->Update(); }, "update_teamroundtimer", EC::early);
});

View File

@ -465,10 +465,10 @@ void EffectGlow::Render(int x, int y, int w, int h)
CMatRenderContextPtr ptr(GET_RENDER_CONTEXT);
orig = ptr->GetRenderTarget();
BeginRenderGlow();
for (int i = 1; i <= HIGHEST_ENTITY; i++)
for (auto &ent_non_raw : entity_cache::valid_ents)
{
ent = g_IEntityList->GetClientEntity(i);
if (ent && !ent->IsDormant() && ShouldRenderGlow(ent))
auto ent = RAW_ENT(ent_non_raw);
if (ent && ShouldRenderGlow(ent))
{
RenderGlow(ent);
}
@ -478,10 +478,10 @@ void EffectGlow::Render(int x, int y, int w, int h)
{
ptr->ClearStencilBufferRectangle(x, y, w, h, 0);
StartStenciling();
for (int i = 1; i <= HIGHEST_ENTITY; i++)
for (auto &non_raw : entity_cache::valid_ents)
{
ent = g_IEntityList->GetClientEntity(i);
if (ent && !ent->IsDormant() && ShouldRenderGlow(ent))
auto ent = RAW_ENT(non_raw);
if (ent && ShouldRenderGlow(ent))
{
DrawToStencil(ent);
}