Fix: Esp performance improvements

This should cut used performance down to ~1/10 in my testing
This commit is contained in:
TotallyNotElite 2020-11-22 12:30:18 +01:00 committed by LightCat
parent fd74ed8445
commit 4c3fcfd962
12 changed files with 139 additions and 120 deletions

View File

@ -4,7 +4,11 @@
*
*/
#pragma once
#include "common.hpp"
#include <cstdint>
#include <memory>
#include "bytepatch.hpp"
#define foffset(p, i) ((unsigned char *) &p)[i]

View File

@ -1,7 +1,7 @@
#include "common.hpp"
#pragma once
#include "common.hpp"
struct WeaponData_t
{
int m_nDamage;

View File

@ -6,7 +6,8 @@
*/
#pragma once
#include "common.hpp"
#include "config.h"
#include "timer.hpp"
namespace hacks::shared::autojoin
{
void updateSearch();

View File

@ -14,7 +14,7 @@
along with Cathook. If not, see <https://www.gnu.org/licenses/>.
*/
#include "common.hpp"
#include <string>
namespace hacks::shared::ChatCommands
{

View File

@ -7,51 +7,16 @@
#pragma once
#include "common.hpp"
#include "config.h"
#include "colors.hpp"
#if ENABLE_VISUALS
namespace hacks::shared::esp
{
// Strings
class ESPString
{
public:
std::string data{ "" };
rgba_t color{ colors::empty };
};
// Cached data
class ESPData
{
public:
int string_count{ 0 };
std::array<ESPString, 16> strings{};
rgba_t color{ colors::empty };
bool needs_paint{ false };
bool has_collide{ false };
Vector collide_max{ 0, 0, 0 };
Vector collide_min{ 0, 0, 0 };
bool transparent{ false };
};
// Init
void Init();
extern std::array<ESPData, 2048> data;
// Entity Processing
void __attribute__((fastcall)) ProcessEntity(CachedEntity *ent);
void __attribute__((fastcall)) ProcessEntityPT(CachedEntity *ent);
void __attribute__((fastcall)) emoji(CachedEntity *ent);
// helper funcs
void __attribute__((fastcall)) Draw3DBox(CachedEntity *ent, const rgba_t &clr);
void __attribute__((fastcall)) DrawBox(CachedEntity *ent, const rgba_t &clr);
void BoxCorners(int minx, int miny, int maxx, int maxy, const rgba_t &color, bool transparent);
bool GetCollide(CachedEntity *ent);
// Strings
void AddEntityString(CachedEntity *entity, const std::string &string, const rgba_t &color = colors::empty);
void SetEntityColor(CachedEntity *entity, const rgba_t &color);
void ResetEntityStrings();
} // namespace hacks::shared::esp
#endif

View File

@ -5,7 +5,7 @@
*
*/
#include "common.hpp"
#include "entitycache.hpp"
namespace hacks::shared::followbot
{

View File

@ -7,7 +7,6 @@
#pragma once
#include "common.hpp"
#include "config.h"
namespace hacks::shared::misc

View File

@ -6,7 +6,8 @@
*/
#pragma once
#include "common.hpp"
#include <string>
#include <vector>
class CatCommand;

View File

@ -7,7 +7,8 @@
#pragma once
#include "common.hpp"
#include <string>
#include <vector>
namespace hacks::tf::uberspam
{

View File

@ -1,5 +1,7 @@
#pragma once
#include "common.hpp"
struct INetMessage;
struct bf_read;
namespace hacks::tf2::nospread
{

View File

@ -7,7 +7,7 @@
#pragma once
#include "common.hpp"
#include "convar.h"
/*
* HECK off F1ssi0N

View File

@ -78,6 +78,41 @@ static settings::Boolean entity_info{ "esp.debug.entity", "false" };
static settings::Boolean entity_model{ "esp.debug.model", "false" };
static settings::Boolean entity_id{ "esp.debug.id", "true" };
// Forward declarations
void ResetEntityStrings(bool full_clear);
void AddEntityString(CachedEntity *entity, const std::string &string, const rgba_t &color = colors::empty);
// Entity Processing
void __attribute__((fastcall)) ProcessEntity(CachedEntity *ent);
void __attribute__((fastcall)) ProcessEntityPT(CachedEntity *ent);
void __attribute__((fastcall)) emoji(CachedEntity *ent);
// helper funcs
void __attribute__((fastcall)) Draw3DBox(CachedEntity *ent, const rgba_t &clr);
void __attribute__((fastcall)) DrawBox(CachedEntity *ent, const rgba_t &clr);
void BoxCorners(int minx, int miny, int maxx, int maxy, const rgba_t &color, bool transparent);
bool GetCollide(CachedEntity *ent);
// Strings
class ESPString
{
public:
std::string data;
rgba_t color{ colors::empty };
};
// Cached data
class ESPData
{
public:
int string_count{ 0 };
std::array<ESPString, 16> strings{};
rgba_t color{ colors::empty };
bool needs_paint{ false };
bool has_collide{ false };
Vector collide_max{ 0, 0, 0 };
Vector collide_min{ 0, 0, 0 };
bool transparent{ false };
};
// Unknown
std::mutex threadsafe_mutex;
// Storage array for keeping strings and other data
@ -212,7 +247,6 @@ struct bonelist_s
}*/
}
};
std::unordered_map<studiohdr_t *, bonelist_s> bonelist_map{};
// These are strings that never change and should only be constructed once
const std::string hoovy_str = "Hoovy";
@ -306,13 +340,15 @@ static void cm()
return;
if (CE_BAD(LOCAL_E))
return;
PROF_SECTION(DRAW_CM_PERFORMANCE);
// Something
std::lock_guard<std::mutex> esp_lock(threadsafe_mutex);
ResetEntityStrings(); // Clear any strings entities have
entities_need_repaint.clear(); // Clear data on entities that need redraw
int max_clients = g_IEngine->GetMaxClients();
// Update entites every 1/5s
const bool entity_tick = g_GlobalVars->tickcount % TIME_TO_TICKS(0.20f) == 0;
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;
// If not using any other special esp, we lower the min to the max
@ -320,6 +356,9 @@ static void cm()
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;
{ // Prof section ends when out of scope, these brackets here.
PROF_SECTION(CM_ESP_EntityLoop);
// Loop through entities
@ -329,42 +368,30 @@ static void cm()
CachedEntity *ent = ENTITY(i);
if (CE_INVALID(ent) || !ent->m_bAlivePlayer())
continue;
ProcessEntity(ent);
// Update Bones
if (i <= MAX_PLAYERS)
ent->hitboxes.GetHitbox(0);
// Dont know what this check is for
if (data[i].string_count)
bool player = i <= max_clients;
if (player)
{
// Set entity color
rgba_t color = colors::EntityF(ent);
if (RAW_ENT(ent)->IsDormant())
{
color.r *= 0.5f;
color.g *= 0.5f;
color.b *= 0.5f;
}
SetEntityColor(ent, color);
// If snow distance, add string here
if (show_distance)
{
AddEntityString(ent, format((int) ENTITY(i)->m_flDistance() / 64 * 1.22f, 'm'));
}
ProcessEntity(ent);
}
// No idea, this is confusing
else if (entity_tick)
{
ProcessEntity(ent);
}
if (data[ent->m_IDX].needs_paint)
{
if (vischeck)
// 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_flDistance() });
entities_need_repaint.push_back({ ent->m_IDX, ent->m_vecOrigin().DistToSqr(g_pLocalPlayer->v_Origin) });
}
}
}
// Render closer entities later in order to have their text in the foreground
std::sort(entities_need_repaint.begin(), entities_need_repaint.end(), [](std::pair<int, float> &a, std::pair<int, float> &b) { return a.second > b.second; });
}
} // namespace hacks::shared::esp
static draw::Texture atlas{ paths::getDataPath("/textures/atlas.png") };
static draw::Texture idspec{ paths::getDataPath("/textures/idspec.png") };
@ -480,8 +507,8 @@ void _FASTCALL ProcessEntityPT(CachedEntity *ent)
auto position = ent->m_vecDormantOrigin();
if (!position)
return;
static Vector screen, origin_screen;
if (!draw::EntityCenterToScreen(ent, screen) && !draw::WorldToScreen(*position, origin_screen))
static Vector screen;
if (!draw::EntityCenterToScreen(ent, screen))
return;
// Reset the collide cache
@ -615,8 +642,6 @@ void _FASTCALL ProcessEntityPT(CachedEntity *ent)
switch (type)
{
case ENTITY_PLAYER:
if (vischeck && !ent->IsVisible())
transparent = true;
if (!fg)
fg = colors::EntityF(ent);
if (transparent)
@ -909,11 +934,6 @@ void _FASTCALL ProcessEntityPT(CachedEntity *ent)
}
}
// if user setting allows vis check and ent isnt visable, make
// transparent
if (vischeck && !ent->IsVisible())
transparent = true;
// Loop through strings
for (int j = 0; j < ent_data.string_count; j++)
{
@ -1005,17 +1025,21 @@ void _FASTCALL ProcessEntityPT(CachedEntity *ent)
// Used to process entities from CreateMove
void _FASTCALL ProcessEntity(CachedEntity *ent)
{
if (!enable)
return; // Esp enable check
if (CE_INVALID(ent) || !ent->m_bAlivePlayer())
return; // CE_INVALID check to prevent crashes
// Dormant
if (RAW_ENT(ent)->IsDormant())
auto origin = ent->m_vecDormantOrigin();
// Dormant and no data
if (!origin)
return;
{
if (!ent->m_vecDormantOrigin())
// We don't actually care about this vector at all. It just exists so WorldToScreen can function normally
static Vector origin_screen;
if (!draw::WorldToScreen(*origin, origin_screen))
return;
}
if (max_dist && ent->m_flDistance() > *max_dist)
auto distance = ent->m_flDistance();
if (max_dist && distance > *max_dist)
return;
int classid = ent->m_iClassID();
// Entity esp
@ -1114,10 +1138,10 @@ void _FASTCALL ProcessEntity(CachedEntity *ent)
AddEntityString(ent, smg_str);
else if (classid == CL_CLASS(CWeaponRPG))
AddEntityString(ent, rpg_str);
if (string_count_backup != data[ent->m_IDX].string_count)
/*if (string_count_backup != data[ent->m_IDX].string_count)
{
SetEntityColor(ent, colors::yellow);
}
}*/
}
}
}
@ -1164,7 +1188,7 @@ void _FASTCALL ProcessEntity(CachedEntity *ent)
// Dropped weapon esp
if (item_dropped_weapons && classid == CL_CLASS(CTFDroppedWeapon))
{
AddEntityString(ent, std::string("Dropped Weapon"));
AddEntityString(ent, "Dropped Weapon");
}
// Gargoyle esp
else if (item_gargoyle && classid == CL_CLASS(CHalloweenGiftPickup))
@ -1231,7 +1255,7 @@ void _FASTCALL ProcessEntity(CachedEntity *ent)
}
else if (item_powerups && itemtype >= ITEM_POWERUP_FIRST && itemtype <= ITEM_POWERUP_LAST)
{
AddEntityString(ent, std::string(powerups[itemtype - ITEM_POWERUP_FIRST]));
AddEntityString(ent, powerups[itemtype - ITEM_POWERUP_FIRST]);
// TF2C weapon spawner esp
}
@ -1327,7 +1351,7 @@ void _FASTCALL ProcessEntity(CachedEntity *ent)
bool IsControlled = CE_BYTE(ent, netvar.m_bPlayerControlled);
int sentry_ammo = CE_INT(ent, netvar.m_iAmmoShells);
int sentry_rockets = CE_INT(ent, netvar.m_iAmmoRockets);
int max_ammo = 0;
int max_ammo = 0;
switch (CE_INT(ent, netvar.iUpgradeLevel))
{
@ -1362,14 +1386,15 @@ void _FASTCALL ProcessEntity(CachedEntity *ent)
{
float next_teleport = CE_FLOAT(ent, netvar.m_flTeleRechargeTime);
float yaw_to_exit = CE_FLOAT(ent, netvar.m_flTeleYawToExit);
std::string time = std::to_string((int) floor((next_teleport - g_GlobalVars->curtime) * 100) / 100);
std::string time = std::to_string((int) floor((next_teleport - g_GlobalVars->curtime) * 100) / 100);
time.append("s");
if (yaw_to_exit)
{
if (next_teleport < g_GlobalVars->curtime)
AddEntityString(ent, tp_ready_str);
else
AddEntityString(ent, time + "s");
AddEntityString(ent, time);
}
}
break;
@ -1379,13 +1404,12 @@ void _FASTCALL ProcessEntity(CachedEntity *ent)
if (IsSapped)
AddEntityString(ent, sapped_str, colors::FromRGBA8(220.0f, 220.0f, 220.0f, 255.0f));
else if (classid == CL_CLASS(CObjectTeleporter) && CE_INT(ent, netvar.m_iTeleState) <= 1 || (IsDisabled || IsPlasmaDisabled))
else if ((classid == CL_CLASS(CObjectTeleporter) && CE_INT(ent, netvar.m_iTeleState) <= 1) || IsDisabled || IsPlasmaDisabled)
AddEntityString(ent, disabled_str, colors::FromRGBA8(220.0f, 220.0f, 220.0f, 255.0f));
}
// Set the entity to repaint
espdata.needs_paint = true;
return;
// Player esp
}
@ -1545,10 +1569,10 @@ void _FASTCALL ProcessEntity(CachedEntity *ent)
// We want revving, zoomed and slowed to be mutually exclusive. Otherwise slowed and zoomed/revving will show at the same time.
// Revving
auto weapon_idx = CE_INT(ent, netvar.hActiveWeapon) & 0xFFF;
auto weapon_idx = CE_INT(ent, netvar.hActiveWeapon) & 0xFFF;
CachedEntity *weapon = IDX_GOOD(weapon_idx) ? ENTITY(weapon_idx) : nullptr;
if (CE_GOOD(weapon) && weapon->m_iClassID() == CL_CLASS(CTFMinigun) && CE_INT(weapon, netvar.iWeaponState) != 0)
AddEntityString(ent, revving_str, colors::FromRGBA8(220.0f, 220.0f, 220.0f, 255.0f));
AddEntityString(ent, revving_str, colors::FromRGBA8(220.0f, 220.0f, 220.0f, 255.0f));
// Zoomed
else if (HasCondition<TFCond_Zoomed>(ent))
AddEntityString(ent, zooming_str, colors::FromRGBA8(220.0f, 220.0f, 220.0f, 255.0f));
@ -1591,7 +1615,24 @@ void _FASTCALL ProcessEntity(CachedEntity *ent)
// Notify esp to repaint
espdata.needs_paint = true;
}
return;
}
if (espdata.needs_paint)
{
// Set entity color
rgba_t color = colors::EntityF(ent);
if (RAW_ENT(ent)->IsDormant())
{
color.r *= 0.5f;
color.g *= 0.5f;
color.b *= 0.5f;
}
// If show distance, add string here
if (show_distance)
{
AddEntityString(ent, format(int(distance / 64 * 1.22f), 'm'));
}
SetEntityColor(ent, color);
}
}
@ -1607,11 +1648,7 @@ void _FASTCALL Draw3DBox(CachedEntity *ent, const rgba_t &clr)
// Dormant
if (RAW_ENT(ent)->IsDormant())
{
auto vec = ent->m_vecDormantOrigin();
if (!vec)
origin = *vec;
else
return;
origin = *ent->m_vecDormantOrigin();
}
// Create a array for storing box points
@ -1847,14 +1884,23 @@ void AddEntityString(CachedEntity *entity, const std::string &string, const rgba
}
// Function to reset entitys strings
void ResetEntityStrings()
void ResetEntityStrings(bool full_clear)
{
for (auto &i : data)
{
i.string_count = 0;
i.color = colors::empty;
i.needs_paint = false;
}
if (full_clear)
for (auto &i : data)
{
i.string_count = 0;
i.color = colors::empty;
i.needs_paint = false;
}
else
for (std::size_t i = 0; i <= g_GlobalVars->maxClients; ++i)
{
auto &element = data[i];
element.string_count = 0;
element.color = colors::empty;
element.needs_paint = false;
}
}
// Sets an entitys esp color