/* * HEsp.cpp * * Created on: Oct 6, 2016 * Author: nullifiedcat */ #include "ESP.h" #include "../common.h" #include "../sdk.h" namespace hacks { namespace shared { namespace esp { CatVar show_weapon(CV_SWITCH, "esp_weapon", "1", "Show weapon name", "Show which weapon does the enemy use"); CatVar local_esp(CV_SWITCH, "esp_local", "1", "ESP Local Player", "Shows local player ESP in thirdperson"); CatVar buildings(CV_SWITCH, "esp_buildings", "1", "Building ESP", "Show buildings"); CatVar enabled(CV_SWITCH, "esp_enabled", "0", "ESP", "Master ESP switch"); CatVar entity_info(CV_SWITCH, "esp_entity", "0", "Entity ESP", "Show entity info (debug)"); CatVar teammates(CV_SWITCH, "esp_teammates", "0", "ESP Teammates", "Teammate ESP"); CatVar item_esp(CV_SWITCH, "esp_item", "1", "Item ESP", "Master Item ESP switch (health packs, etc.)"); CatVar show_bot_id(CV_SWITCH, "esp_followbot_id", "1", "Followbot ESP", "Show followbot ID"); CatVar item_dropped_weapons(CV_SWITCH, "esp_item_weapons", "0", "Dropped weapons", "Show dropped weapons"); CatVar item_ammo_packs(CV_SWITCH, "esp_item_ammo", "0", "Ammo packs", "Show ammo packs"); CatVar item_health_packs(CV_SWITCH, "esp_item_health", "1", "Health packs", "Show health packs"); CatVar item_powerups(CV_SWITCH, "esp_item_powerups", "1", "Powerups", "Show powerups"); CatVar item_money(CV_SWITCH, "esp_money", "1", "MvM money", "Show MvM money"); CatVar item_money_red(CV_SWITCH, "esp_money_red", "1", "Red MvM money", "Show red MvM money"); CatVar entity_id(CV_SWITCH, "esp_entity_id", "1", "Entity ID", "Used with Entity ESP. Shows entityID"); CatVar tank(CV_SWITCH, "esp_show_tank", "1", "Show tank", "Show tank"); CatVar box_esp(CV_SWITCH, "esp_box", "1", "Box", "Draw 2D box with healthbar. fancy."); CatVar show_distance(CV_SWITCH, "esp_distance", "1", "Distance ESP", "Show distance to target"); CatVar show_name(CV_SWITCH, "esp_name", "1", "Name ESP", "Show name"); CatVar show_class(CV_SWITCH, "esp_class", "1", "Class ESP", "Show class"); CatVar show_conditions(CV_SWITCH, "esp_conds", "1", "Conditions ESP", "Show conditions"); CatVar show_ubercharge(CV_SWITCH, "esp_ubercharge", "1", "Ubercharge ESP", "Show ubercharge percentage while players medigun is out"); CatVar vischeck(CV_SWITCH, "esp_vischeck", "1", "VisCheck", "ESP visibility check - makes enemy info behind walls darker, disable this if you get FPS drops"); CatVar legit(CV_SWITCH, "esp_legit", "0", "Legit Mode", "Don't show invisible enemies"); CatVar show_health(CV_SWITCH, "esp_health_num", "1", "Health numbers", "Show health in numbers"); CatEnum proj_esp_enum({ "OFF", "ALL", "CRIT" }); CatVar proj_rockets(proj_esp_enum, "esp_proj_rockets", "1", "Rockets", "Rockets"); CatVar proj_arrows(proj_esp_enum, "esp_proj_arrows", "1", "Arrows", "Arrows"); CatVar proj_pipes(proj_esp_enum, "esp_proj_pipes", "1", "Pipes", "Pipebombs"); CatVar proj_stickies(proj_esp_enum, "esp_proj_stickies", "1", "Stickies", "Stickybombs"); CatVar proj_enemy(CV_SWITCH, "esp_proj_enemy", "1", "Only enemy projectiles", "Don't show friendly projectiles"); CatVar proj_esp(CV_SWITCH, "esp_proj", "1", "Projectile ESP", "Projectile ESP"); CatVar entity_model(CV_SWITCH, "esp_model_name", "0", "Model name ESP", "Model name esp (DEBUG ONLY)"); CatVar item_weapon_spawners(CV_SWITCH, "esp_weapon_spawners", "1", "Show weapon spawners", "TF2C deathmatch weapon spawners"); CatVar item_adrenaline(CV_SWITCH, "esp_item_adrenaline", "0", "Show Adrenaline", "TF2C adrenaline pills"); std::array data; void ResetEntityStrings() { for (auto& i : data) { i.string_count = 0; i.color = 0; i.needs_paint = false; } } void SetEntityColor(CachedEntity* entity, int color) { data[entity->m_IDX].color = color; } void AddEntityString(CachedEntity* entity, const std::string& string, int color) { ESPData& entity_data = data[entity->m_IDX]; entity_data.strings[entity_data.string_count].data = string; entity_data.strings[entity_data.string_count].color = color; entity_data.string_count++; entity_data.needs_paint = true; } std::vector entities_need_repaint {}; void CreateMove() { int limit; static int max_clients = g_IEngine->GetMaxClients(); CachedEntity* ent; ResetEntityStrings(); entities_need_repaint.clear(); limit = HIGHEST_ENTITY; if (!buildings && !proj_esp && !item_esp) limit = min(max_clients, HIGHEST_ENTITY); for (int i = 0; i < limit; i++) { ent = ENTITY(i); ProcessEntity(ent); if (data[i].string_count) { SetEntityColor(ent, colors::EntityF(ent)); if (show_distance) { AddEntityString(ent, format((int)(ENTITY(i)->m_flDistance / 64 * 1.22f), 'm')); } } if (data[ent->m_IDX].needs_paint) entities_need_repaint.push_back(ent->m_IDX); } } void Draw() { for (auto& i : entities_need_repaint) { ProcessEntityPT(ENTITY(i)); } } static CatEnum esp_box_text_position_enum({"TOP RIGHT", "BOTTOM RIGHT", "CENTER", "ABOVE", "BELOW" }); static CatVar esp_box_text_position(esp_box_text_position_enum, "esp_box_text_position", "0", "Text position", "Defines text position"); static CatVar esp_3d_box_health(CV_SWITCH, "esp_3d_box_health", "1", "3D box health color", "Adds a health bar to 3d esp box"); static CatVar esp_3d_box_thick(CV_SWITCH, "esp_3d_box_thick", "1", "Thick 3D box", "Makes the 3d box thicker\nMost times, easier to see"); static CatVar esp_3d_box_expand_rate(CV_FLOAT, "esp_3d_box_expand_size", "10", "3D Box Expand Size", "Expand 3D box by X units", 50.0f); static CatVar esp_3d_box_expand(CV_SWITCH, "esp_3d_box_expand", "1", "Expand 3D box", "Makes the 3d bigger"); static CatEnum esp_3d_box_smoothing_enum({"None", "Origin offset", "Bone update (NOT IMPL)"}); static CatVar esp_3d_box_smoothing(esp_3d_box_smoothing_enum, "esp_3d_box_smoothing", "1", "3D box smoothing", "3D box smoothing method"); static CatVar esp_3d_box_nodraw(CV_SWITCH, "esp_3d_box_nodraw", "0", "Invisible 3D box", "Don't draw 3d box"); static CatVar esp_3d_box_healthbar(CV_SWITCH, "esp_3d_box_healthbar", "1", "Health bar", "Adds a health bar to the esp"); void Draw3DBox(CachedEntity* ent, int clr, bool healthbar, int health, int healthmax) { PROF_SECTION(PT_esp_draw3dbox); Vector mins, maxs; Vector points_r[8]; Vector points[8]; bool set, success, cloak; float x, y, z; int hbh, max_x, max_y, min_x, min_y; CachedHitbox* hb; set = false; success = true; for (int i = 0; i < ent->hitboxes.GetNumHitboxes(); i++) { hb = ent->hitboxes.GetHitbox(i); if (!hb) return; if (!set || hb->min.x < mins.x) mins.x = hb->min.x; if (!set || hb->min.y < mins.y) mins.y = hb->min.y; if (!set || hb->min.z < mins.z) mins.z = hb->min.z; if (!set || hb->max.x > maxs.x) maxs.x = hb->max.x; if (!set || hb->max.y > maxs.y) maxs.y = hb->max.y; if (!set || hb->max.z > maxs.z) maxs.z = hb->max.z; set = true; } // This is weird, smoothing only makes it worse on local servers if ((int)esp_3d_box_smoothing == 1) { mins += (RAW_ENT(ent)->GetAbsOrigin() - ent->m_vecOrigin); maxs += (RAW_ENT(ent)->GetAbsOrigin() - ent->m_vecOrigin); } //static const Vector expand_vector(8.5, 8.5, 8.5); if (esp_3d_box_expand) { const float& exp = (float)esp_3d_box_expand_rate; maxs.x += exp; maxs.y += exp; maxs.z += exp; mins.x -= exp; mins.y -= exp; mins.z -= exp; } x = maxs.x - mins.x; y = maxs.y - mins.y; z = maxs.z - mins.z; points_r[0] = mins; points_r[1] = mins + Vector(x, 0, 0); points_r[2] = mins + Vector(x, y, 0); points_r[3] = mins + Vector(0, y, 0); points_r[4] = mins + Vector(0, 0, z); points_r[5] = mins + Vector(x, 0, z); points_r[6] = mins + Vector(x, y, z); points_r[7] = mins + Vector(0, y, z); success = true; for (int i = 0; i < 8; i++) { if (!draw::WorldToScreen(points_r[i], points[i])) success = false; } if (!success) return; max_x = -1; max_y = -1; min_x = 65536; min_y = 65536; for (int i = 0; i < 8; i++) { if (points[i].x > max_x) max_x = points[i].x; if (points[i].y > max_y) max_y = points[i].y; if (points[i].x < min_x) min_x = points[i].x; if (points[i].y < min_y) min_y = points[i].y; } data.at(ent->m_IDX).esp_origin.Zero(); switch ((int)esp_box_text_position) { case 0: { // TOP RIGHT data.at(ent->m_IDX).esp_origin = Vector(max_x + 1, min_y, 0); } break; case 1: { // BOTTOM RIGHT data.at(ent->m_IDX).esp_origin = Vector(max_x + 1, max_y - data.at(ent->m_IDX).string_count * ((int)fonts::esp_height - 3), 0); } break; case 2: { // CENTER } break; case 3: { // ABOVE data.at(ent->m_IDX).esp_origin = Vector(min_x + 1, min_y - data.at(ent->m_IDX).string_count * ((int)fonts::esp_height - 3), 0); } break; case 4: { // BELOW data.at(ent->m_IDX).esp_origin = Vector(min_x + 1, max_y, 0); } } //draw::String(fonts::ESP, points[0].x, points[0].y, clr, 1, "MIN"); //draw::String(fonts::ESP, points[6].x, points[6].y, clr, 1, "MAX"); constexpr int indices[][2] = { { 0, 1 }, { 0, 3 }, { 1, 2 }, { 2, 3 }, { 4, 5 }, { 4, 7 }, { 5, 6 }, { 6, 7 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 } }; if (esp_3d_box_health) clr = colors::Health(health, healthmax); cloak = ent->m_Type == ENTITY_PLAYER && IsPlayerInvisible(ent); if (cloak) clr = colors::Transparent(clr, 0.2); if (esp_3d_box_healthbar) { draw::OutlineRect(min_x - 6, min_y, 6, max_y - min_y, colors::black); hbh = (max_y - min_y - 2) * min((float)health / (float)healthmax, 1.0f); draw::DrawRect(min_x - 5, max_y - 1 - hbh, 4, hbh, colors::Health(health, healthmax)); } if (!esp_3d_box_nodraw) { for (int i = 0; i < 12; i++) { // I'll let compiler optimize this. const Vector& p1 = points[indices[i][0]]; const Vector& p2 = points[indices[i][1]]; draw::DrawLine(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y, clr); if (esp_3d_box_thick) { draw::DrawLine(p1.x + 1, p1.y, p2.x - p1.x, p2.y - p1.y, clr); draw::DrawLine(p1.x, p1.y + 1, p2.x - p1.x, p2.y - p1.y, clr); draw::DrawLine(p1.x + 1, p1.y + 1, p2.x - p1.x, p2.y - p1.y, clr); } } } } static CatVar box_nodraw(CV_SWITCH, "esp_box_nodraw", "0", "Invisible 2D Box", "Don't draw 2D box"); static CatVar box_expand(CV_INT, "esp_box_expand", "0", "Expand 2D Box", "Expand 2D box by N units"); void _FASTCALL DrawBox(CachedEntity* ent, int clr, float widthFactor, float addHeight, bool healthbar, int health, int healthmax) { PROF_SECTION(PT_esp_drawbox); Vector min, max, origin, so, omin, omax, smin, smax; float height, width, trf; bool cloak; int min_x, min_y, max_x, max_y, border, hp, hbh; unsigned char alpha; if (CE_BAD(ent)) return; cloak = ent->m_iClassID == RCC_PLAYER && IsPlayerInvisible(ent); RAW_ENT(ent)->GetRenderBounds(min, max); origin = RAW_ENT(ent)->GetAbsOrigin(); draw::WorldToScreen(origin, so); //if (!a) return; //logging::Info("%f %f", so.x, so.y); omin = origin + Vector(0, 0, min.z); omax = origin + Vector(0, 0, max.z + addHeight); bool a = draw::WorldToScreen(omin, smin); a = a && draw::WorldToScreen(omax, smax); if (!a) return; height = abs(smax.y - smin.y); //logging::Info("height: %f", height); width = height / widthFactor; //bool a = draw::WorldToScreen(omin, smin); //a = a && draw::WorldToScreen(omax, smax); //if (!a) return; //draw::DrawString(min(smin.x, smax.x), min(smin.y, smax.y), clr, false, "min"); //draw::DrawString(max(smin.x, smax.x), max(smin.y, smax.y), clr, false, "max"); //draw::DrawString((int)so.x, (int)so.y, draw::white, false, "origin"); data.at(ent->m_IDX).esp_origin.Zero(); max_x = so.x + width / 2 + 1; min_y = so.y - height; max_y = so.y; min_x = so.x - width / 2; if (box_expand) { const float& exp = (float)box_expand; max_x += exp; max_y += exp; min_x -= exp; min_y -= exp; } switch ((int)esp_box_text_position) { case 0: { // TOP RIGHT data.at(ent->m_IDX).esp_origin = Vector(max_x, min_y, 0); } break; case 1: { // BOTTOM RIGHT data.at(ent->m_IDX).esp_origin = Vector(max_x, max_y - data.at(ent->m_IDX).string_count * ((int)fonts::esp_height - 3), 0); } break; case 2: { // CENTER } break; case 3: { // ABOVE data.at(ent->m_IDX).esp_origin = Vector(min_x + 1, min_y - data.at(ent->m_IDX).string_count * ((int)fonts::esp_height - 3), 0); } break; case 4: { // BELOW data.at(ent->m_IDX).esp_origin = Vector(min_x + 1, max_y, 0); } } alpha = clr >> 24; trf = (float)((float)alpha / 255.0f); border = cloak ? colors::Create(160, 160, 160, alpha) : colors::Transparent(colors::black, trf); if (!box_nodraw) { draw::OutlineRect(min_x, min_y, max_x - min_x, max_y - min_y, border); draw::OutlineRect(min_x + 1, min_y + 1, max_x - min_x - 2, max_y - min_y - 2, clr); draw::OutlineRect(min_x + 2, min_y + 2, max_x - min_x - 4, max_y - min_y - 4, border); } if (healthbar) { hp = colors::Transparent(colors::Health(health, healthmax), trf); hbh = (max_y - min_y - 2) * min((float)health / (float)healthmax, 1.0f); draw::OutlineRect(min_x - 6, min_y, 7, max_y - min_y, border); draw::DrawRect(min_x - 5, max_y - hbh - 1, 5, hbh, hp); } } void _FASTCALL ProcessEntity(CachedEntity* ent) { const model_t* model; int string_count_backup, level, pclass, *weapon_list, handle, eid; bool shown; player_info_s info; powerup_type power; CachedEntity* weapon; const char* weapon_name; if (!enabled) return; if (CE_BAD(ent)) return; ESPData& espdata = data[ent->m_IDX]; if (entity_info) { AddEntityString(ent, format(RAW_ENT(ent)->GetClientClass()->m_pNetworkName, " [", ent->m_iClassID, "]")); if (entity_id) { AddEntityString(ent, std::to_string(ent->m_IDX)); } if (entity_model) { model = RAW_ENT(ent)->GetModel(); if (model) AddEntityString(ent, std::string(g_IModelInfo->GetModelName(model))); } } if (ent->m_Type == ENTITY_PROJECTILE && proj_esp && (ent->m_bEnemy || (teammates && !proj_enemy))) { if (ent->m_iClassID == CL_CLASS(CTFProjectile_Rocket) || ent->m_iClassID == CL_CLASS(CTFProjectile_SentryRocket)) { if (proj_rockets) { if ((int)proj_rockets != 2 || ent->m_bCritProjectile) { AddEntityString(ent, "[ ==> ]"); } } } else if (ent->m_iClassID == CL_CLASS(CTFGrenadePipebombProjectile)) { switch (CE_INT(ent, netvar.iPipeType)) { case 0: if (!proj_pipes) break; if ((int)proj_pipes == 2 && !ent->m_bCritProjectile) break; AddEntityString(ent, "[ (PP) ]"); break; case 1: if (!proj_stickies) break; if ((int)proj_stickies == 2 && !ent->m_bCritProjectile) break; AddEntityString(ent, "[ {*} ]"); } } else if (ent->m_iClassID == CL_CLASS(CTFProjectile_Arrow)) { if ((int)proj_arrows != 2 || ent->m_bCritProjectile) { AddEntityString(ent, "[ >>---> ]"); } } } IF_GAME (IsHL2DM()) { if (item_esp && item_dropped_weapons) { if (CE_BYTE(ent, netvar.hOwner) == (unsigned char)-1) { string_count_backup = data[ent->m_IDX].string_count; if (ent->m_iClassID == CL_CLASS(CWeapon_SLAM)) AddEntityString(ent, "SLAM"); else if (ent->m_iClassID == CL_CLASS(CWeapon357)) AddEntityString(ent, ".357"); else if (ent->m_iClassID == CL_CLASS(CWeaponAR2)) AddEntityString(ent, "AR2"); else if (ent->m_iClassID == CL_CLASS(CWeaponAlyxGun)) AddEntityString(ent, "Alyx Gun"); else if (ent->m_iClassID == CL_CLASS(CWeaponAnnabelle)) AddEntityString(ent, "Annabelle"); else if (ent->m_iClassID == CL_CLASS(CWeaponBinoculars)) AddEntityString(ent, "Binoculars"); else if (ent->m_iClassID == CL_CLASS(CWeaponBugBait)) AddEntityString(ent, "Bug Bait"); else if (ent->m_iClassID == CL_CLASS(CWeaponCrossbow)) AddEntityString(ent, "Crossbow"); else if (ent->m_iClassID == CL_CLASS(CWeaponShotgun)) AddEntityString(ent, "Shotgun"); else if (ent->m_iClassID == CL_CLASS(CWeaponSMG1)) AddEntityString(ent, "SMG"); else if (ent->m_iClassID == CL_CLASS(CWeaponRPG)) AddEntityString(ent, "RPG"); if (string_count_backup != data[ent->m_IDX].string_count) { SetEntityColor(ent, colors::yellow); } } } } if (ent->m_iClassID == CL_CLASS(CTFTankBoss) && tank) { AddEntityString(ent, "Tank"); } else if (ent->m_iClassID == CL_CLASS(CTFDroppedWeapon) && item_esp && item_dropped_weapons) { AddEntityString(ent, format("WEAPON ", RAW_ENT(ent)->GetClientClass()->GetName())); } else if (ent->m_iClassID == CL_CLASS(CCurrencyPack) && item_money) { if (CE_BYTE(ent, netvar.bDistributed)) { if (item_money_red) { AddEntityString(ent, "~$~"); } } else { AddEntityString(ent, "$$$"); } } else if (ent->m_ItemType != ITEM_NONE && item_esp) { shown = false; if (item_health_packs && (ent->m_ItemType >= ITEM_HEALTH_SMALL && ent->m_ItemType <= ITEM_HEALTH_LARGE || ent->m_ItemType == ITEM_HL_BATTERY)) { if (ent->m_ItemType == ITEM_HEALTH_SMALL) AddEntityString(ent, "[+]"); if (ent->m_ItemType == ITEM_HEALTH_MEDIUM) AddEntityString(ent, "[++]"); if (ent->m_ItemType == ITEM_HEALTH_LARGE) AddEntityString(ent, "[+++]"); if (ent->m_ItemType == ITEM_HL_BATTERY) AddEntityString(ent, "[Z]"); } else if (item_adrenaline && ent->m_ItemType == ITEM_TF2C_PILL) { AddEntityString(ent, "[a]"); } else if (item_ammo_packs && ent->m_ItemType >= ITEM_AMMO_SMALL && ent->m_ItemType <= ITEM_AMMO_LARGE) { if (ent->m_ItemType == ITEM_AMMO_SMALL) AddEntityString(ent, "{i}"); if (ent->m_ItemType == ITEM_AMMO_MEDIUM) AddEntityString(ent, "{ii}"); if (ent->m_ItemType == ITEM_AMMO_LARGE) AddEntityString(ent, "{iii}"); } else if (item_powerups && ent->m_ItemType >= ITEM_POWERUP_FIRST && ent->m_ItemType <= ITEM_POWERUP_LAST) { AddEntityString(ent, format(powerups[ent->m_ItemType - ITEM_POWERUP_FIRST], " PICKUP")); } else if (item_weapon_spawners && ent->m_ItemType >= ITEM_TF2C_W_FIRST && ent->m_ItemType <= ITEM_TF2C_W_LAST) { AddEntityString(ent, format(tf2c_weapon_names[ent->m_ItemType - ITEM_TF2C_W_FIRST], " SPAWNER")); if (CE_BYTE(ent, netvar.bRespawning)) AddEntityString(ent, "-- RESPAWNING --"); } } else if (ent->m_Type == ENTITY_BUILDING && buildings) { if (!ent->m_bEnemy && !teammates) return; level = CE_INT(ent, netvar.iUpgradeLevel); const std::string& name = (ent->m_iClassID == CL_CLASS(CObjectTeleporter) ? "Teleporter" : (ent->m_iClassID == CL_CLASS(CObjectSentrygun) ? "Sentry Gun" : "Dispenser")); if (legit && ent->m_iTeam != g_pLocalPlayer->team) { /*if (ent->m_lLastSeen > v_iLegitSeenTicks->GetInt()) { return; }*/ } if (show_name || show_class) AddEntityString(ent, format("LV ", level, ' ', name)); if (show_health) { AddEntityString(ent, format(ent->m_iHealth, '/', ent->m_iMaxHealth, " HP"), colors::Health(ent->m_iHealth, ent->m_iMaxHealth)); } espdata.needs_paint = true; return; } else if (ent->m_Type == ENTITY_PLAYER && ent->m_bAlivePlayer) { if (!(local_esp && g_IInput->CAM_IsThirdPerson()) && ent->m_IDX == g_IEngine->GetLocalPlayer()) return; pclass = CE_INT(ent, netvar.iClass); if (!g_IEngine->GetPlayerInfo(ent->m_IDX, &info)) return; power = GetPowerupOnPlayer(ent); // If target is enemy, always show powerups, if player is teammate, show powerups // only if bTeammatePowerup or bTeammates is true if (legit && ent->m_iTeam != g_pLocalPlayer->team && playerlist::IsDefault(info.friendsID)) { if (IsPlayerInvisible(ent)) return; /*if (ent->m_lLastSeen > (unsigned)v_iLegitSeenTicks->GetInt()) { return; }*/ } if (power >= 0) { // FIXME Disabled powerup ESP. //AddEntityString(ent, format("HAS ", powerups[power])); } if (ent->m_bEnemy || teammates || !playerlist::IsDefault(info.friendsID)) { if (show_name) AddEntityString(ent, std::string(info.name)); if (show_class) { if (pclass > 0 && pclass < 10) AddEntityString(ent, classes[pclass - 1]); } #ifdef IPC_ENABLED if (show_bot_id && ipc::peer && ent != LOCAL_E) { for (unsigned i = 1; i < cat_ipc::max_peers; i++) { if (!ipc::peer->memory->peer_data[i].free && ipc::peer->memory->peer_user_data[i].friendid == info.friendsID) { AddEntityString(ent, format("BOT #", i)); break; } } } #endif if (show_health) { AddEntityString(ent, format(ent->m_iHealth, '/', ent->m_iMaxHealth, " HP"), colors::Health(ent->m_iHealth, ent->m_iMaxHealth)); } IF_GAME (IsTF()) { if (show_ubercharge) { if (CE_INT(ent, netvar.iClass) == tf_medic) { weapon_list = (int*)((unsigned)(RAW_ENT(ent)) + netvar.hMyWeapons); for (int i = 0; weapon_list[i]; i++) { handle = weapon_list[i]; eid = handle & 0xFFF; if (eid >= 32 && eid <= HIGHEST_ENTITY) { weapon = ENTITY(eid); if (!CE_BAD(weapon) && weapon->m_iClassID == CL_CLASS(CWeaponMedigun) && weapon) { if (CE_INT(weapon, netvar.iItemDefinitionIndex) != 998) { AddEntityString(ent, format(floor( CE_FLOAT(weapon, netvar.m_flChargeLevel) * 100 ), '%', " Uber"), colors::Health(( CE_FLOAT(weapon, netvar.m_flChargeLevel) * 100 ), 100)); } else AddEntityString(ent, format(floor( CE_FLOAT(weapon, netvar.m_flChargeLevel) * 100 ), '%', " Uber | Charges: ", floor( CE_FLOAT(weapon, netvar.m_flChargeLevel) / 0.25f )), colors::Health(( CE_FLOAT(weapon, netvar.m_flChargeLevel) * 100 ), 100)); break; } } } } } if (show_conditions) { if (IsPlayerInvisible(ent)) { AddEntityString(ent, "INVISIBLE"); } if (IsPlayerInvulnerable(ent)) { AddEntityString(ent, "INVULNERABLE"); } if (HasCondition(ent)) { AddEntityString(ent, "VACCINATOR ACTIVE"); } if (HasCondition(ent)) { AddEntityString(ent, "VACCINATOR PASSIVE"); } if (IsPlayerCritBoosted(ent)) { AddEntityString(ent, "CRIT BOOSTED"); } if (HasCondition(ent)) { AddEntityString(ent, "*ZOOMING*"); } if (HasCondition(ent)) { AddEntityString(ent, "*SLOWED*"); }; } } if (IsHoovy(ent)) AddEntityString(ent, "Hoovy"); weapon = ENTITY(CE_INT(ent, netvar.hActiveWeapon) & 0xFFF); if (CE_GOOD(weapon)) { if (show_weapon) { weapon_name = vfunc(RAW_ENT(weapon), 398, 0)(RAW_ENT(weapon)); if (weapon_name) AddEntityString(ent, std::string(weapon_name)); } } espdata.needs_paint = true; } return; } } static CatVar esp_3d_box(CV_SWITCH, "esp_3d_box", "0", "3D box"); static CatVar box_healthbar(CV_SWITCH, "esp_box_healthbar", "1", "Box Healthbar"); /* * According to profiler, this function is the most time-consuming (and gets called up to 200K times a second) */ void _FASTCALL ProcessEntityPT(CachedEntity* ent) { PROF_SECTION(PT_esp_process_entity); int fg, color; bool transparent, cloak, origin_is_zero; Vector screen, origin_screen, draw_point; if (CE_BAD(ent)) return; transparent = false; //if (!(local_esp && g_IInput->CAM_IsThirdPerson()) && // ent->m_IDX == g_IEngine->GetLocalPlayer()) return; const ESPData& ent_data = data[ent->m_IDX]; fg = ent_data.color; if (!draw::EntityCenterToScreen(ent, screen) && !draw::WorldToScreen(ent->m_vecOrigin, origin_screen)) return; if (box_esp) { switch (ent->m_Type) { case ENTITY_PLAYER: { cloak = IsPlayerInvisible(ent); //if (!ent->m_bEnemy && !teammates && playerlist::IsDefault(ent)) break; //if (!ent->m_bAlivePlayer) break; if (vischeck && !ent->IsVisible()) transparent = true; if (!fg) fg = colors::EntityF(ent); if (transparent) fg = colors::Transparent(fg); if (esp_3d_box) { Draw3DBox(ent, fg, true, CE_INT(ent, netvar.iHealth), ent->m_iMaxHealth); } else { DrawBox(ent, fg, 3.0f, -15.0f, static_cast(box_healthbar), CE_INT(ent, netvar.iHealth), ent->m_iMaxHealth); } break; } case ENTITY_BUILDING: { if (CE_INT(ent, netvar.iTeamNum) == g_pLocalPlayer->team && !teammates) break; if (!transparent && vischeck && !ent->IsVisible()) transparent = true; if (!fg) fg = colors::EntityF(ent); if (transparent) fg = colors::Transparent(fg); if (esp_3d_box) { Draw3DBox(ent, fg, true, CE_INT(ent, netvar.iBuildingHealth), CE_INT(ent, netvar.iBuildingMaxHealth)); } else { DrawBox(ent, fg, 1.0f, 0.0f, static_cast(box_healthbar), CE_INT(ent, netvar.iBuildingHealth), CE_INT(ent, netvar.iBuildingMaxHealth)); } break; } } } if (ent_data.string_count) { PROF_SECTION(PT_esp_drawstrings); origin_is_zero = !box_esp || ent_data.esp_origin.IsZero(1.0f); if (vischeck && !ent->IsVisible()) transparent = true; draw_point = origin_is_zero ? screen : ent_data.esp_origin; for (int j = 0; j < ent_data.string_count; j++) { const ESPString& string = ent_data.strings[j]; color = string.color ? string.color : ent_data.color; if (transparent) color = colors::Transparent(color); if (!origin_is_zero) { draw::String(fonts::ESP, draw_point.x, draw_point.y, color, 2, string.data); draw_point.y += (int)fonts::esp_height - 3; } else { auto l = draw::GetStringLength(fonts::ESP, string.data); draw::String(fonts::ESP, draw_point.x - l.first / 2, draw_point.y, color, 2, string.data); draw_point.y += (int)fonts::esp_height - 3; } } } } }}}