From 53ca178872fda8b6fdb8d10bf15516952ce6df3c Mon Sep 17 00:00:00 2001 From: julianacat Date: Mon, 7 Aug 2017 23:03:52 -0500 Subject: [PATCH] Esp stuff --- src/hacks/Bunnyhop.cpp | 20 ++-- src/hacks/ESP.cpp | 250 +++++++++++++++++++++++++++-------------- 2 files changed, 177 insertions(+), 93 deletions(-) diff --git a/src/hacks/Bunnyhop.cpp b/src/hacks/Bunnyhop.cpp index 92ffc498..139eb068 100644 --- a/src/hacks/Bunnyhop.cpp +++ b/src/hacks/Bunnyhop.cpp @@ -14,8 +14,10 @@ namespace hacks { namespace shared { namespace bunnyhop { // Var for user settings CatVar enabled(CV_SWITCH, "bhop_enabled", "0", "Bunnyhop", "Enable Bunnyhop. All extra features like autojump and perfect jump limit were temporary removed."); +//CatVar perfect_jump_limit(CV_INT, "bhop_enabled", "0", "Bunnyhop", "Enable Bunnyhop. All extra features like autojump and perfect jump limit were temporary removed."); -int iTicksLastJump = 0; +static int ticks_last_jump = 0; +//static int perfect_jumps = 0; // Function called by game for movement void CreateMove() { @@ -26,26 +28,22 @@ void CreateMove() { // Check if there is usercommands if (!g_pUserCmd->command_number) return; - // Check if local player is airborne, if true then return - //if (CE_INT(g_pLocalPlayer->entity, netvar.movetype) == MOVETYPE_FLY) return; - - // Grab netvar for flags from the local player - int flags = CE_INT(g_pLocalPlayer->entity, netvar.iFlags); - // var for "if on ground" from the flags netvar - bool ground = (flags & (1 << 0)); + bool ground = CE_INT(g_pLocalPlayer->entity, netvar.iFlags) & (1 << 0); // Var for if the player is pressing jump bool jump = (g_pUserCmd->buttons & IN_JUMP); // Check if player is not on the ground and player is holding their jump key if (!ground && jump) { - // If the ticks since last jump are greater or equal to 7, then force the player to stop jumping + // If the ticks since last jump are greater or equal to 9, then force the player to stop jumping // The bot disables jump untill player hits the ground or lets go of jump - if (iTicksLastJump++ >= 9) g_pUserCmd->buttons = g_pUserCmd->buttons &~ IN_JUMP; + if (ticks_last_jump++ >= 9) { + g_pUserCmd->buttons = g_pUserCmd->buttons &~ IN_JUMP; + } } // If the players jump cmd has been used, then we reset our var - if (!jump) iTicksLastJump = 0; + if (!jump) ticks_last_jump = 0; // Finish the function with return return; diff --git a/src/hacks/ESP.cpp b/src/hacks/ESP.cpp index 38f8eef7..876903b3 100644 --- a/src/hacks/ESP.cpp +++ b/src/hacks/ESP.cpp @@ -50,11 +50,25 @@ 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"); +static CatVar box_healthbar(CV_SWITCH, "esp_box_healthbar", "1", "Box Healthbar"); +static CatVar draw_bones(CV_SWITCH, "esp_bones", "0", "Draw Bone ID's"); +static CatVar box_corner_size(CV_INT, "esp_box_corner_size", "10", "Corner Size"); +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 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"); +static CatVar box_corners(CV_SWITCH, "esp_box_corners", "1", "Box Corners"); +static CatVar powerup_esp(CV_SWITCH, "esp_powerups", "1", "Powerup ESP"); +// Storage arrays for keeping strings and other data std::mutex threadsafe_mutex; - std::array data; + +// Storage vars for entities that need to be re-drawn +std::vector entities_need_repaint {}; +std::mutex entities_need_repaint_mutex {}; +// Function to reset entitys strings void ResetEntityStrings() { for (auto& i : data) { i.string_count = 0; @@ -63,10 +77,12 @@ void ResetEntityStrings() { } } +// Sets an entitys esp color void SetEntityColor(CachedEntity* entity, const rgba_t& color) { data[entity->m_IDX].color = color; } +// Use to add a esp string to an entity void AddEntityString(CachedEntity* entity, const std::string& string, const rgba_t& color) { ESPData& entity_data = data[entity->m_IDX]; if (entity_data.string_count >= 15) return; @@ -77,28 +93,20 @@ void AddEntityString(CachedEntity* entity, const std::string& string, const rgba } -std::vector entities_need_repaint {}; -std::mutex entities_need_repaint_mutex {}; - -static CatVar box_corner_size(CV_INT, "esp_box_corner_size", "10", "Corner Size"); - +// Function to draw box corners void BoxCorners(int minx, int miny, int maxx, int maxy, const rgba_t& color, bool transparent) { const rgba_t& black = transparent ? colors::Transparent(colors::black) : colors::black; const int size = box_corner_size; // Black corners - // Top Left drawgl::FilledRect(minx, miny, size, 3, black); drawgl::FilledRect(minx, miny + 3, 3, size - 3, black); - // Top Right drawgl::FilledRect(maxx - size + 1, miny, size, 3, black); drawgl::FilledRect(maxx - 3 + 1, miny + 3, 3, size - 3, black); - // Bottom Left drawgl::FilledRect(minx, maxy - 3, size, 3, black); drawgl::FilledRect(minx, maxy - size, 3, size - 3, black); - // Bottom Right drawgl::FilledRect(maxx - size + 1, maxy - 3, size, 3, black); drawgl::FilledRect(maxx - 2, maxy - size, 3, size - 3, black); @@ -118,33 +126,54 @@ void BoxCorners(int minx, int miny, int maxx, int maxy, const rgba_t& color, boo drawgl::Line(maxx - 1, maxy - 2, 0, -(size - 2), color); } - +// Function called on create move void CreateMove() { + + // Check usersettings if enabled if (!enabled) return; + + // Something std::lock_guard esp_lock(threadsafe_mutex); - int limit; + + ResetEntityStrings(); // Clear any strings entities have + entities_need_repaint.clear(); // Clear data on entities that need redraw + + // TODO, Find the benefit of using max clients with this logic + // Get max clients and static int max_clients = g_IEngine->GetMaxClients(); - - ResetEntityStrings(); - entities_need_repaint.clear(); - limit = HIGHEST_ENTITY; - if (!buildings && !proj_esp && !item_esp) limit = min(max_clients, HIGHEST_ENTITY); - { + int limit = HIGHEST_ENTITY; + + // If not using any other special esp, we lower the min to the max clients + if (!buildings && !proj_esp && !item_esp) + limit = min(max_clients, HIGHEST_ENTITY); + + { // I still dont understand the purpose of prof_section and surrounding in brackets 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); ProcessEntity(ent); + + // Dont know what this check is for if (data[i].string_count) { + + // Set entity color SetEntityColor(ent, colors::EntityF(ent)); + + // If snow distance, add string here if (show_distance) { AddEntityString(ent, format((int)(ENTITY(i)->m_flDistance / 64 * 1.22f), 'm')); } } + // No idea, this is confusing if (data[ent->m_IDX].needs_paint) entities_need_repaint.push_back(ent->m_IDX); } } } +// Function called on draw void Draw() { std::lock_guard esp_lock(threadsafe_mutex); if (!enabled) return; @@ -153,43 +182,34 @@ void Draw() { } } -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 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"); -static CatVar box_corners(CV_SWITCH, "esp_box_corners", "1", "Box Corners"); -static CatVar powerup_esp(CV_SWITCH, "esp_powerups", "1", "Powerup ESP"); +// TODO, Unknown, find what this does const Vector dims_player[] = { { -16, -16, -4 }, { 16, 16, 72 } }; +// Draw a box around a player void _FASTCALL DrawBox(CachedEntity* ent, const rgba_t& clr, bool healthbar, int health, int healthmax) { - PROF_SECTION(PT_esp_drawbox); - Vector so, omin, omax, smin, smax; - float height, width; - bool cloak; - int min_x, min_y, max_x, max_y, hbh; - rgba_t hp, border; - + PROF_SECTION(PT_esp_drawbox); // Unknown + + // Potentially un-used vars + //Vector so, omin, omax, smin, smax; + //float height, width; + + // Check if ent is bad to prevent crashes if (CE_BAD(ent)) return; - + + // Get collision center, max, and mins const Vector& origin = RAW_ENT(ent)->GetCollideable()->GetCollisionOrigin(); Vector mins = RAW_ENT(ent)->GetCollideable()->OBBMins() + origin; Vector maxs = RAW_ENT(ent)->GetCollideable()->OBBMaxs() + origin; - cloak = (ent->m_iClassID == RCC_PLAYER) && IsPlayerInvisible(ent); - - //if (!a) return; - //logging::Info("%f %f", so.x, so.y); + // Unknown data.at(ent->m_IDX).esp_origin.Zero(); - Vector points_r[8]; - Vector points[8]; - bool set, success; - float x, y, z; - - set = false; - success = true; + // Create a array for storing box points + Vector points_r[8]; // World vectors + Vector points[8]; // Screen vectors + // If user setting for box expnad is true, spread the max and mins if (box_expand) { const float& exp = (float)box_expand; maxs.x += exp; @@ -200,9 +220,10 @@ void _FASTCALL DrawBox(CachedEntity* ent, const rgba_t& clr, bool healthbar, int mins.z -= exp; } - x = maxs.x - mins.x; - y = maxs.y - mins.y; - z = maxs.z - mins.z; + // Create points for the box based on max and mins + float x = maxs.x - mins.x; + float y = maxs.y - mins.y; + float 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); @@ -211,15 +232,20 @@ void _FASTCALL DrawBox(CachedEntity* ent, const rgba_t& clr, bool healthbar, int 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; + + // Check if any point of the box isnt on the screen + bool success = true; for (int i = 0; i < 8; i++) { if (!draw::WorldToScreen(points_r[i], points[i])) success = false; } + // If a point isnt on the screen, return here if (!success) return; - max_x = -1; - max_y = -1; - min_x = 65536; - min_y = 65536; + + // Get max and min of the box using the newly created screen vector + int max_x = -1; + int max_y = -1; + int min_x = 65536; + int 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; @@ -227,14 +253,7 @@ void _FASTCALL DrawBox(CachedEntity* ent, const rgba_t& clr, bool healthbar, int if (points[i].y < min_y) min_y = points[i].y; } - /*if (box_expand) { - const float& exp = (float)box_expand; - max_x += exp; - max_y += exp; - min_x -= exp; - min_y -= exp; - }*/ - + // Put Text on the position with a switch switch ((int)esp_box_text_position) { case 0: { // TOP RIGHT data.at(ent->m_IDX).esp_origin = Vector(max_x + 2, min_y, 0); @@ -251,10 +270,16 @@ void _FASTCALL DrawBox(CachedEntity* ent, const rgba_t& clr, bool healthbar, int data.at(ent->m_IDX).esp_origin = Vector(min_x, max_y, 0); } } - border = cloak ? colors::FromRGBA8(160, 160, 160, clr.a * 255.0f) : colors::Transparent(colors::black, clr.a); + + // Depending on whether the player is cloaked, we change the color acordingly + bool border = ((ent->m_iClassID == RCC_PLAYER) && IsPlayerInvisible(ent)) ? colors::FromRGBA8(160, 160, 160, clr.a * 255.0f) : colors::Transparent(colors::black, clr.a); + + // If box nodraw isnt true, we can draw our box if (!box_nodraw) { + // With box corners, we draw differently if (box_corners) BoxCorners(min_x, min_y, max_x, max_y, clr, (clr.a != 1.0f)); + // Otherwise, we just do simple draw funcs else { drawgl::Rect(min_x, min_y, max_x - min_x, max_y - min_y, border); drawgl::Rect(min_x + 1, min_y + 1, max_x - min_x - 2, max_y - min_y - 2, clr); @@ -262,19 +287,21 @@ void _FASTCALL DrawBox(CachedEntity* ent, const rgba_t& clr, bool healthbar, int } } + // If healthbar is enabled, create one here if (healthbar) { - hp = colors::Transparent(colors::Health(health, healthmax), clr.a); - hbh = (max_y - min_y - 2) * min((float)health / (float)healthmax, 1.0f); + rgba_t hp = colors::Transparent(colors::Health(health, healthmax), clr.a); + int hbh = (max_y - min_y - 2) * min((float)health / (float)healthmax, 1.0f); drawgl::Rect(min_x - 7, min_y, 7, max_y - min_y, border); drawgl::FilledRect(min_x - 6, max_y - hbh - 1, 5, hbh, hp); } } - + +// Used to process entities from CreateMove void _FASTCALL ProcessEntity(CachedEntity* ent) { - if (!enabled) return; - if (CE_BAD(ent)) return; + if (!enabled) return; // Esp enable check + if (CE_BAD(ent)) return; // CE_BAD check to prevent crashes - int string_count_backup, level, pclass, *weapon_list, handle, eid; + int string_count_backup, *weapon_list, handle, eid; bool shown; player_info_s info; powerup_type power; @@ -282,6 +309,7 @@ void _FASTCALL ProcessEntity(CachedEntity* ent) { const char* weapon_name; ESPData& espdata = data[ent->m_IDX]; + // Entity esp if (entity_info) { AddEntityString(ent, format(RAW_ENT(ent)->GetClientClass()->m_pNetworkName, " [", ent->m_iClassID, "]")); if (entity_id) { @@ -293,13 +321,18 @@ void _FASTCALL ProcessEntity(CachedEntity* ent) { } } + // Projectile esp if (ent->m_Type == ENTITY_PROJECTILE && proj_esp && (ent->m_bEnemy || (teammates && !proj_enemy))) { + + // Rockets 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, "[ ==> ]"); } } + + // Pills/Stickys } else if (ent->m_iClassID == CL_CLASS(CTFGrenadePipebombProjectile)) { switch (CE_INT(ent, netvar.iPipeType)) { case 0: @@ -312,6 +345,8 @@ void _FASTCALL ProcessEntity(CachedEntity* ent) { if ((int)proj_stickies == 2 && !ent->m_bCritProjectile) break; AddEntityString(ent, "[ {*} ]"); } + + // Huntsman } else if (ent->m_iClassID == CL_CLASS(CTFProjectile_Arrow)) { if ((int)proj_arrows != 2 || ent->m_bCritProjectile) { AddEntityString(ent, "[ >>---> ]"); @@ -319,6 +354,7 @@ void _FASTCALL ProcessEntity(CachedEntity* ent) { } } + // Hl2DM dropped item esp IF_GAME (IsHL2DM()) { if (item_esp && item_dropped_weapons) { if (CE_BYTE(ent, netvar.hOwner) == (unsigned char)-1) { @@ -341,10 +377,15 @@ void _FASTCALL ProcessEntity(CachedEntity* ent) { } } + // Tank esp if (ent->m_iClassID == CL_CLASS(CTFTankBoss) && tank) { AddEntityString(ent, "Tank"); + + // Dropped weapon esp } else if (ent->m_iClassID == CL_CLASS(CTFDroppedWeapon) && item_esp && item_dropped_weapons) { AddEntityString(ent, format("WEAPON ", RAW_ENT(ent)->GetClientClass()->GetName())); + + // MVM Money esp } else if (ent->m_iClassID == CL_CLASS(CCurrencyPack) && item_money) { if (CE_BYTE(ent, netvar.bDistributed)) { if (item_money_red) { @@ -353,24 +394,40 @@ void _FASTCALL ProcessEntity(CachedEntity* ent) { } else { AddEntityString(ent, "$$$"); } + + // Other item esp } else if (ent->m_ItemType != ITEM_NONE && item_esp) { + + // TODO, what does shown var do shown = false; + + // Health pack esp 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]"); + + // TF2C Adrenaline esp } else if (item_adrenaline && ent->m_ItemType == ITEM_TF2C_PILL) { AddEntityString(ent, "[a]"); + + // Ammo pack esp } 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}"); + + // Powerup esp } 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")); + + // TF2C weapon spawner esp } 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 --"); + + // Halloween spell esp } else if (item_spellbooks && (ent->m_ItemType == ITEM_SPELL || ent->m_ItemType == ITEM_SPELL_RARE)) { if (ent->m_ItemType == ITEM_SPELL) { AddEntityString(ent, "Spell", colors::green); @@ -378,48 +435,77 @@ void _FASTCALL ProcessEntity(CachedEntity* ent) { AddEntityString(ent, "Rare Spell", colors::FromRGBA8(139, 31, 221, 255)); } } + + // Building esp } else if (ent->m_Type == ENTITY_BUILDING && buildings) { + + // Check if enemy building 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()) { + + // TODO maybe... + /*if (legit && ent->m_iTeam != g_pLocalPlayer->team) { + if (ent->m_lLastSeen > v_iLegitSeenTicks->GetInt()) { return; - }*/ + } + }*/ + + // Make a name for the building based on the building type and level + if (show_name || show_class) { + const std::string& name = (ent->m_iClassID == CL_CLASS(CObjectTeleporter) ? "Teleporter" : (ent->m_iClassID == CL_CLASS(CObjectSentrygun) ? "Sentry Gun" : "Dispenser"));' + int level = CE_INT(ent, netvar.iUpgradeLevel); + AddEntityString(ent, format("LV ", level, ' ', name)); } - if (show_name || show_class) AddEntityString(ent, format("LV ", level, ' ', name)); + // If show health is true, then add a string with the health if (show_health) { AddEntityString(ent, format(ent->m_iHealth, '/', ent->m_iMaxHealth, " HP"), colors::Health(ent->m_iHealth, ent->m_iMaxHealth)); } + // Set the entity to repaint espdata.needs_paint = true; return; + + // Player esp } else if (ent->m_Type == ENTITY_PLAYER && ent->m_bAlivePlayer) { + + // Local player handling if (!(local_esp && g_IInput->CAM_IsThirdPerson()) && ent->m_IDX == g_IEngine->GetLocalPlayer()) return; - pclass = CE_INT(ent, netvar.iClass); + + // Get player class + int pclass = CE_INT(ent, netvar.iClass); + + // Attempt to get player info, and if cant, return if (!g_IEngine->GetPlayerInfo(ent->m_IDX, &info)) return; - // If target is enemy, always show powerups, if player is teammate, show powerups - // only if bTeammatePowerup or bTeammates is true + + // TODO, check if u can just use "ent->m_bEnemy" instead of m_iTeam + // Legit mode handling if (legit && ent->m_iTeam != g_pLocalPlayer->team && playerlist::IsDefault(info.friendsID)) { - if (IsPlayerInvisible(ent)) return; - if (vischeck && !ent->IsVisible()) return; - /*if (ent->m_lLastSeen > (unsigned)v_iLegitSeenTicks->GetInt()) { - return; - }*/ + if (IsPlayerInvisible(ent)) return; // Invis check + if (vischeck && !ent->IsVisible()) return; // Vis check + // TODO, maybe... + //if (ent->m_lLastSeen > (unsigned)v_iLegitSeenTicks->GetInt()) return; } + + // Powerup handling if (powerup_esp) { power = GetPowerupOnPlayer(ent); if (power != not_powerup) AddEntityString(ent, format("^ ", powerups[power], " ^")); } + + // Dont understand reasoning for this check if (ent->m_bEnemy || teammates || !playerlist::IsDefault(info.friendsID)) { + + // Playername if (show_name) AddEntityString(ent, std::string(info.name)); + // Player class if (show_class) { if (pclass > 0 && pclass < 10) AddEntityString(ent, classes[pclass - 1]); } + #ifdef IPC_ENABLED + // ipc bot esp 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) { @@ -429,6 +515,7 @@ void _FASTCALL ProcessEntity(CachedEntity* ent) { } } #endif + // Health esp if (show_health) { AddEntityString(ent, format(ent->m_iHealth, '/', ent->m_iMaxHealth, " HP"), colors::Health(ent->m_iHealth, ent->m_iMaxHealth)); } @@ -493,8 +580,7 @@ void _FASTCALL ProcessEntity(CachedEntity* ent) { return; } } -static CatVar box_healthbar(CV_SWITCH, "esp_box_healthbar", "1", "Box Healthbar"); -static CatVar draw_bones(CV_SWITCH, "esp_bones", "0", "Draw Bone ID's"); + const std::string bonenames_leg_r[] = { "bip_foot_R", "bip_knee_R", "bip_hip_R" }; const std::string bonenames_leg_l[] = { "bip_foot_L", "bip_knee_L", "bip_hip_L" };