From 223337cd2451cb1fe2eee05a3674a21077ff8c14 Mon Sep 17 00:00:00 2001 From: aUniqueUser Date: Mon, 28 Dec 2020 12:24:08 +0100 Subject: [PATCH] Visuals overhaul and chams rewrite Co-authored-by: BenCat07 --- data/menu/nullifiedcat/aimbot.xml | 6 +- data/menu/nullifiedcat/visuals.xml | 1 + data/menu/nullifiedcat/visuals/chams.xml | 106 ++- .../menu/nullifiedcat/visuals/chamshaders.xml | 81 ++ data/menu/nullifiedcat/visuals/colors.xml | 21 + data/menu/nullifiedcat/visuals/esp.xml | 4 +- include/hacks/Backtrack.hpp | 6 + include/visual/EffectChams.hpp | 69 -- include/visual/colors.hpp | 15 +- include/visual/drawing.hpp | 5 - src/crits.cpp | 14 +- src/hack.cpp | 1 - src/hacks/Aimbot.cpp | 11 +- src/hacks/AutoReflect.cpp | 2 +- src/hacks/Backtrack.cpp | 11 +- src/hacks/ESP.cpp | 14 +- src/hacks/LightESP.cpp | 2 +- src/hacks/Misc.cpp | 10 +- src/hacks/Radar.cpp | 8 +- src/hacks/SpyAlert.cpp | 2 +- src/hacks/Walkbot.cpp | 4 +- src/hooks/visual/DrawModelExecute.cpp | 874 ++++++++++++++---- src/hooks/visual/FrameStageNotify.cpp | 65 +- src/nospread.cpp | 2 +- src/visual/CMakeLists.txt | 1 - src/visual/EffectChams.cpp | 403 -------- src/visual/EffectGlow.cpp | 2 +- src/visual/colors.cpp | 38 + src/visual/drawmgr.cpp | 8 +- 29 files changed, 1064 insertions(+), 722 deletions(-) create mode 100644 data/menu/nullifiedcat/visuals/chamshaders.xml create mode 100644 data/menu/nullifiedcat/visuals/colors.xml delete mode 100644 include/visual/EffectChams.hpp delete mode 100644 src/visual/EffectChams.cpp diff --git a/data/menu/nullifiedcat/aimbot.xml b/data/menu/nullifiedcat/aimbot.xml index 489963e4..77f89cae 100755 --- a/data/menu/nullifiedcat/aimbot.xml +++ b/data/menu/nullifiedcat/aimbot.xml @@ -128,10 +128,6 @@ - - - - diff --git a/include/hacks/Backtrack.hpp b/include/hacks/Backtrack.hpp index af1aeee6..50fa0226 100644 --- a/include/hacks/Backtrack.hpp +++ b/include/hacks/Backtrack.hpp @@ -50,9 +50,15 @@ extern settings::Float latency; extern settings::Int bt_slots; #if ENABLE_VISUALS extern settings::Boolean chams; +extern settings::Boolean chams_wireframe; extern settings::Int chams_ticks; extern settings::Rgba chams_color; extern settings::Boolean chams_solid; +extern settings::Boolean chams_overlay; +extern settings::Rgba chams_color_overlay; +extern settings::Float chams_envmap_tint_r; +extern settings::Float chams_envmap_tint_g; +extern settings::Float chams_envmap_tint_b; #endif // Check if backtrack is enabled diff --git a/include/visual/EffectChams.hpp b/include/visual/EffectChams.hpp deleted file mode 100644 index 67c4a433..00000000 --- a/include/visual/EffectChams.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * EffectChams.hpp - * - * Created on: Apr 16, 2017 - * Author: nullifiedcat - */ - -#pragma once - -#include "common.hpp" -#include "sdk/ScreenSpaceEffects.h" -#include "core/sdk.hpp" - -namespace effect_chams -{ - -class EffectChams : public IScreenSpaceEffect -{ -public: - virtual void Init(); - virtual void Shutdown() - { - if (init) - { - mat_unlit.Shutdown(); - mat_unlit_z.Shutdown(); - mat_lit.Shutdown(); - mat_lit_z.Shutdown(); - init = false; - } - } - - inline virtual void SetParameters(KeyValues *params) - { - } - - virtual void Render(int x, int y, int w, int h); - - inline virtual void Enable(bool bEnable) - { - enabled = bEnable; - } - inline virtual bool IsEnabled() - { - return enabled; - } - - void SetEntityColor(CachedEntity *ent, rgba_t color); - rgba_t ChamsColor(IClientEntity *entity); - bool ShouldRenderChams(IClientEntity *entity); - void RenderChams(IClientEntity *entity); - void BeginRenderChams(); - void EndRenderChams(); - void RenderChamsRecursive(IClientEntity *entity); - -public: - bool init{ false }; - bool drawing{ false }; - bool enabled; - float orig_modulation[3]; - CMaterialReference mat_unlit; - CMaterialReference mat_unlit_z; - CMaterialReference mat_lit; - CMaterialReference mat_lit_z; -}; - -extern EffectChams g_EffectChams; -extern CScreenSpaceEffectRegistration *g_pEffectChams; -} // namespace effect_chams diff --git a/include/visual/colors.hpp b/include/visual/colors.hpp index a8de9fe1..382b2dc9 100644 --- a/include/visual/colors.hpp +++ b/include/visual/colors.hpp @@ -117,10 +117,17 @@ constexpr rgba_t black(0, 0, 0, 1); constexpr rgba_t pink = FromRGBA8(255, 105, 180, 255); -constexpr rgba_t red = FromRGBA8(237, 42, 42, 255), blu = FromRGBA8(28, 108, 237, 255); -constexpr rgba_t red_b = FromRGBA8(64, 32, 32, 178), blu_b = FromRGBA8(32, 32, 64, 178); // Background -constexpr rgba_t red_v = FromRGBA8(196, 102, 108, 255), blu_v = FromRGBA8(102, 182, 196, 255); // Vaccinator -constexpr rgba_t red_u = FromRGBA8(216, 34, 186, 255), blu_u = FromRGBA8(167, 75, 252, 255); // Ubercharged +extern rgba_t red; // RED team user controlled +extern rgba_t blu; // BLU team user controlled +extern rgba_t red_b; // Background +extern rgba_t blu_b; // Background +extern rgba_t red_v; // Vaccinator +extern rgba_t blu_v; // Vaccinator +extern rgba_t red_u; // Ubercharge +extern rgba_t blu_u; // Ubercharge +extern rgba_t gui; // GUI color +extern rgba_t target; // Aimbot target color +constexpr rgba_t red_s = FromRGBA8(237, 42, 42, 255); // Not user controlled constexpr rgba_t yellow = FromRGBA8(255, 255, 0, 255); constexpr rgba_t orange = FromRGBA8(255, 120, 0, 255); constexpr rgba_t green = FromRGBA8(0, 255, 0, 255); diff --git a/include/visual/drawing.hpp b/include/visual/drawing.hpp index 2ba7caf5..95139321 100644 --- a/include/visual/drawing.hpp +++ b/include/visual/drawing.hpp @@ -59,11 +59,6 @@ void Update(); extern const std::vector fonts; } // namespace fonts -constexpr rgba_t GUIColor() -{ - return colors::white; -} - void InitStrings(); void ResetStrings(); void AddCenterString(const std::string &string, const rgba_t &color = colors::white); diff --git a/src/crits.cpp b/src/crits.cpp index 34efb6ae..1fb1b794 100644 --- a/src/crits.cpp +++ b/src/crits.cpp @@ -724,7 +724,7 @@ void DrawCritStrings() float sx, sy; fonts::center_screen->stringSize(bar_string, &sx, &sy); // Center and draw below - draw::String(x - sx / 2, (y + sy), colors::red, bar_string.c_str(), *fonts::center_screen); + draw::String(x - sx / 2, (y + sy), colors::red_s, bar_string.c_str(), *fonts::center_screen); y += fonts::center_screen->size + 1; } @@ -783,22 +783,22 @@ void Draw() if (shouldCrit()) { if (can_crit) - AddCritString("Forcing Crits!", colors::red); + AddCritString("Forcing Crits!", colors::red_s); else - AddCritString("Weapon can currently not crit!", colors::red); + AddCritString("Weapon can currently not crit!", colors::red_s); } // Weapon can't randomly crit if (!re::C_TFWeaponBase::CanFireCriticalShot(RAW_ENT(LOCAL_W), false, nullptr) || !added_per_shot) { - AddCritString("Weapon cannot randomly crit.", colors::red); + AddCritString("Weapon cannot randomly crit.", colors::red_s); DrawCritStrings(); return; } // We are out of sync. RIP if (is_out_of_sync) - AddCritString("Out of sync.", colors::red); + AddCritString("Out of sync.", colors::red_s); // Observed crit chance is not low enough, display how much damage is needed until we can crit again else if (crit_mult_info.first > crit_mult_info.second && g_pLocalPlayer->weapon_mode != weapon_melee) AddCritString("Damage Until crit: " + std::to_string(damageUntilToCrit(wep)), colors::orange); @@ -811,7 +811,7 @@ void Draw() } // Mark bucket as ready/not ready - auto color = colors::red; + auto color = colors::red_s; if (can_crit && (crit_mult_info.first <= crit_mult_info.second || g_pLocalPlayer->weapon_mode != weapon_melee)) color = colors::green; AddCritString("Crit Bucket: " + std::to_string(bucket), color); @@ -829,7 +829,7 @@ void Draw() bucket_color = colors::FromRGBA8(0x34, 0xeb, 0xae, 255); // Color everything red if (!can_crit) - bucket_color = colors::red; + bucket_color = colors::red_s; // Get the percentage the bucket will take up float bucket_percentage = bucket / getBucketCap(); diff --git a/src/hack.cpp b/src/hack.cpp index f0f11b15..ec92e4e0 100644 --- a/src/hack.cpp +++ b/src/hack.cpp @@ -424,7 +424,6 @@ void hack::Shutdown() EC::run(EC::Shutdown); #if ENABLE_VISUALS g_pScreenSpaceEffects->DisableScreenSpaceEffect("_cathook_glow"); - g_pScreenSpaceEffects->DisableScreenSpaceEffect("_cathook_chams"); #if EXTERNAL_DRAWING xoverlay_destroy(); #endif diff --git a/src/hacks/Aimbot.cpp b/src/hacks/Aimbot.cpp index ba7da296..6978bf94 100644 --- a/src/hacks/Aimbot.cpp +++ b/src/hacks/Aimbot.cpp @@ -18,12 +18,6 @@ #include "hitrate.hpp" #include "FollowBot.hpp" -#if ENABLE_VISUALS -#ifndef FEATURE_EFFECTS_DISABLED -#include "EffectChams.hpp" -#endif -#endif - namespace hacks::shared::aimbot { static settings::Boolean normal_enable{ "aimbot.enable", "false" }; @@ -312,8 +306,7 @@ static void CreateMove() #if ENABLE_VISUALS if (target_entity->m_Type() == ENTITY_PLAYER) { - hacks::shared::esp::SetEntityColor(target_entity, colors::pink); - effect_chams::g_EffectChams.SetEntityColor(target_entity, colors::pink); + hacks::shared::esp::SetEntityColor(target_entity, colors::target); } #endif @@ -1551,7 +1544,7 @@ static void DrawText() // Dont show ring while player is dead if (CE_GOOD(LOCAL_E) && LOCAL_E->m_bAlivePlayer()) { - rgba_t color = GUIColor(); + rgba_t color = colors::gui; color.a = float(fovcircle_opacity); int width, height; diff --git a/src/hacks/AutoReflect.cpp b/src/hacks/AutoReflect.cpp index c55d8ccc..30cc478e 100644 --- a/src/hacks/AutoReflect.cpp +++ b/src/hacks/AutoReflect.cpp @@ -218,7 +218,7 @@ void Draw() // Dont show ring while player is dead if (CE_GOOD(LOCAL_E) && LOCAL_E->m_bAlivePlayer()) { - rgba_t color = GUIColor(); + rgba_t color = colors::gui; color.a = float(fovcircle_opacity); int width, height; diff --git a/src/hacks/Backtrack.cpp b/src/hacks/Backtrack.cpp index e155fce7..3c554a98 100644 --- a/src/hacks/Backtrack.cpp +++ b/src/hacks/Backtrack.cpp @@ -34,9 +34,14 @@ settings::Float latency{ "backtrack.latency", "0" }; settings::Int bt_slots{ "backtrack.slots", "0" }; #if ENABLE_VISUALS settings::Boolean chams{ "backtrack.chams", "false" }; +settings::Boolean chams_wireframe{ "backtrack.chams.wireframe", "false" }; settings::Int chams_ticks{ "backtrack.chams.ticks", "1" }; -settings::Rgba chams_color{ "backtrack.chams.color", "646464FF" }; -settings::Boolean chams_solid{ "backtrack.chams.color.solid", "false" }; +settings::Rgba chams_color{ "backtrack.chams.color", "ff00ff10" }; +settings::Boolean chams_overlay{ "backtrack.chams.overlay", "true" }; +settings::Rgba chams_color_overlay{ "backtrack.chams.color.overlay", "000000ff" }; +settings::Float chams_envmap_tint_r{ "backtrack.chams.envmap.tint.r", "1" }; +settings::Float chams_envmap_tint_g{ "backtrack.chams.envmap.tint.g", "0" }; +settings::Float chams_envmap_tint_b{ "backtrack.chams.envmap.tint.b", "1" }; #endif // Check if backtrack is enabled @@ -320,7 +325,7 @@ void Draw() rgba_t draw_color = colors::green; // Found our target tick if (bt_ent && tick.tickcount == (*bt_data).tickcount && i == bt_ent->m_IDX) - draw_color = colors::red; + draw_color = colors::red_s; draw::Rectangle(out.x, out.y, size / 4, size / 4, draw_color); } } diff --git a/src/hacks/ESP.cpp b/src/hacks/ESP.cpp index 8d2ab9b4..22458167 100644 --- a/src/hacks/ESP.cpp +++ b/src/hacks/ESP.cpp @@ -925,7 +925,7 @@ void _FASTCALL ProcessEntityPT(CachedEntity *ent) break; case 1: { // BOTTOM RIGHT - draw_point = Vector(max_x + 2, max_y - data.at(ent->m_IDX).string_count * 14, 0); + draw_point = Vector(max_x + 2, max_y - data.at(ent->m_IDX).string_count * 16, 0); } break; case 2: @@ -935,13 +935,23 @@ void _FASTCALL ProcessEntityPT(CachedEntity *ent) break; case 3: { // ABOVE - draw_point = Vector((min_x + max_x) / 2.0f, min_y - data.at(ent->m_IDX).string_count * 14, 0); + draw_point = Vector((min_x + max_x) / 2.0f, min_y - data.at(ent->m_IDX).string_count * 16, 0); } break; case 4: { // BELOW draw_point = Vector((min_x + max_x) / 2.0f, max_y, 0); } + break; + case 5: + { // ABOVE LEFT + draw_point = Vector(min_x + 2, min_y - data.at(ent->m_IDX).string_count * 16, 0); + } + break; + case 6: + { // ABOVE RIGHT + draw_point = Vector(max_x + 2, min_y - data.at(ent->m_IDX).string_count * 16, 0); + } } } } diff --git a/src/hacks/LightESP.cpp b/src/hacks/LightESP.cpp index 0fd3daa8..80e25a59 100644 --- a/src/hacks/LightESP.cpp +++ b/src/hacks/LightESP.cpp @@ -73,7 +73,7 @@ void draw() if (size < minsize) size = minsize; draw::Rectangle(out.x - fabsf(pout.x - pout2.x) / 4, out.y - fabsf(pout.y - pout2.y) / 4, fabsf(pout.x - pout2.x) / 2, fabsf(pout.y - pout2.y) / 2, hacks::shared::lightesp::LightESPColor(pEntity)); - draw::Rectangle(out.x - size / 8, out.y - size / 8, size / 4, size / 4, colors::red); + draw::Rectangle(out.x - size / 8, out.y - size / 8, size / 4, size / 4, colors::red_s); } } } diff --git a/src/hacks/Misc.cpp b/src/hacks/Misc.cpp index 56bf915a..10a3866e 100644 --- a/src/hacks/Misc.cpp +++ b/src/hacks/Misc.cpp @@ -38,6 +38,7 @@ static settings::Boolean unlimit_bumpercart_movement{ "misc.bumpercarthax.enable static settings::Boolean ping_reducer{ "misc.ping-reducer.enable", "false" }; static settings::Int force_ping{ "misc.ping-reducer.target", "0" }; static settings::Boolean force_wait{ "misc.force-enable-wait", "true" }; +static settings::Boolean scc{ "misc.scoreboard.match-custom-team-colors", "false" }; #if ENABLE_VISUALS static settings::Boolean god_mode{ "misc.god-mode", "false" }; @@ -382,7 +383,7 @@ void Draw() { case 4: observermode = "1st Person"; - color = colors::red; + color = colors::red_s; break; case 5: observermode = "3rd Person"; @@ -706,13 +707,16 @@ Color &GetPlayerColor(int idx, int team, bool dead = false) { static Color returnColor(0, 0, 0, 0); + int col_red[] = { scc ? int(colors::red.r * 255) : 255, scc ? int(colors::red.g * 255) : 64, scc ? int(colors::red.b * 255) : 64 }; + int col_blu[] = { scc ? int(colors::blu.r * 255) : 153, scc ? int(colors::blu.g * 255) : 204, scc ? int(colors::blu.b * 255) : 255 }; + switch (team) { case TEAM_RED: - returnColor.SetColor(255, 64, 64, 255); + returnColor.SetColor(col_red[0], col_red[1], col_red[2], 255); break; case TEAM_BLU: - returnColor.SetColor(153, 204, 255, 255); + returnColor.SetColor(col_blu[0], col_blu[1], col_blu[2],255); break; default: returnColor.SetColor(245, 229, 196, 255); diff --git a/src/hacks/Radar.cpp b/src/hacks/Radar.cpp index 7a836c4f..a3ad7798 100644 --- a/src/hacks/Radar.cpp +++ b/src/hacks/Radar.cpp @@ -223,7 +223,7 @@ void Draw() int radar_size = *size; int half_size = radar_size / 2; - outlineclr = GUIColor(); + outlineclr = colors::gui; if (*shape == 0) { @@ -273,13 +273,13 @@ void Draw() DrawEntity(x, y, LOCAL_E); const auto &wtr = WorldToRadar(g_pLocalPlayer->v_Origin.x, g_pLocalPlayer->v_Origin.y); if (!use_icons) - draw::RectangleOutlined(x + wtr.first, y + wtr.second, int(icon_size), int(icon_size), GUIColor(), 0.5f); + draw::RectangleOutlined(x + wtr.first, y + wtr.second, int(icon_size), int(icon_size), colors::gui, 0.5f); } if (show_cross) { - draw::Line(x + half_size, y + half_size / 2, 0, half_size, colors::Transparent(GUIColor(), 0.4f), 0.5f); - draw::Line(x + half_size / 2, y + half_size, half_size, 0, colors::Transparent(GUIColor(), 0.4f), 0.5f); + draw::Line(x + half_size, y + half_size / 2, 0, half_size, colors::Transparent(colors::gui, 0.4f), 0.5f); + draw::Line(x + half_size / 2, y + half_size, half_size, 0, colors::Transparent(colors::gui, 0.4f), 0.5f); } } diff --git a/src/hacks/SpyAlert.cpp b/src/hacks/SpyAlert.cpp index f5b23b51..bfd83a8a 100644 --- a/src/hacks/SpyAlert.cpp +++ b/src/hacks/SpyAlert.cpp @@ -80,7 +80,7 @@ void Draw() } if (voicemenu && lastVoicemenu.test_and_set(5000)) g_IEngine->ClientCmd_Unrestricted("voicemenu 1 1"); - AddCenterString(format("BACKSTAB WARNING! ", (int) (closest_spy_distance / 64 * 1.22f), "m (", spy_count, ")"), colors::red); + AddCenterString(format("BACKSTAB WARNING! ", (int) (closest_spy_distance / 64 * 1.22f), "m (", spy_count, ")"), colors::red_s); } else if (closest_spy_distance < (float) distance_warning) { diff --git a/src/hacks/Walkbot.cpp b/src/hacks/Walkbot.cpp index b340d65b..ad15af51 100644 --- a/src/hacks/Walkbot.cpp +++ b/src/hacks/Walkbot.cpp @@ -1054,7 +1054,7 @@ void DrawNode(index_t node, bool draw_back) node_size = 6; } if (node == state::active_node) - color = &colors::red; + color = &colors::red_s; draw::Rectangle(wts.x - node_size, wts.y - node_size, 2 * node_size, 2 * node_size, *color); } @@ -1112,7 +1112,7 @@ void Draw() } if (HasLowHealth()) { - AddSideString("Walkbot: LOW HEALTH", colors::red); + AddSideString("Walkbot: LOW HEALTH", colors::red_s); } } break; diff --git a/src/hooks/visual/DrawModelExecute.cpp b/src/hooks/visual/DrawModelExecute.cpp index 70317d6a..2798405e 100644 --- a/src/hooks/visual/DrawModelExecute.cpp +++ b/src/hooks/visual/DrawModelExecute.cpp @@ -1,96 +1,623 @@ /* - Created by Jenny White on 29.04.18. - Copyright (c) 2018 nullworks. All rights reserved. + This file is part of Cathook. + + Cathook is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Cathook is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Cathook. If not, see . */ -#include -#include -#include "HookedMethods.hpp" -#include "Backtrack.hpp" -#include -#include -#include "AntiAim.hpp" +// Codeowners: aUniqueUser +#include +#include "common.hpp" +#include "HookedMethods.hpp" +#include "MiscTemporary.hpp" +#include "Backtrack.hpp" +#include "EffectGlow.hpp" +#include "Aimbot.hpp" + +/* World visual rvars */ static settings::Boolean no_arms{ "remove.arms", "false" }; -static settings::Boolean arms_chams{ "chams.arms", "false" }; static settings::Boolean no_hats{ "remove.hats", "false" }; static settings::Boolean blend_zoom{ "zoom.blend", "false" }; -static settings::Rgba arm_overlaychams_color{ "chams.arms.overlaycolor", "FF6464FF" }; -static settings::Rgba arm_basechams_color{ "chams.arms.basecolor", "006464FF" }; -namespace effect_glow +static settings::Boolean enable{ "chams.enable", "false" }; +static settings::Boolean render_original{ "chams.original", "false" }; + +/* Cham target rvars */ +static settings::Boolean health{ "chams.health", "false" }; +static settings::Boolean teammates{ "chams.show.teammates", "false" }; +static settings::Boolean disguised{ "chams.show.disguised", "true" }; +static settings::Boolean players{ "chams.show.players", "true" }; +static settings::Boolean medkits{ "chams.show.medkits", "false" }; +static settings::Boolean ammobox{ "chams.show.ammoboxes", "false" }; +static settings::Boolean buildings{ "chams.show.buildings", "true" }; +static settings::Boolean stickies{ "chams.show.stickies", "true" }; +static settings::Boolean stickies_local{ "chams.show.stickies.local", "true" }; +static settings::Boolean pipes{ "chams.show.pipes", "true" }; +static settings::Boolean pipes_local{ "chams.show.pipes.local", "true" }; +static settings::Boolean teammate_buildings{ "chams.show.teammate-buildings", "false" }; +static settings::Boolean recursive{ "chams.recursive", "true" }; +static settings::Boolean legit{ "chams.legit", "false" }; +static settings::Boolean singlepass{ "chams.single-pass", "false" }; +static settings::Boolean chamsself{ "chams.self", "true" }; +static settings::Boolean weapons{ "chams.weapons", "false" }; +static settings::Rgba weapons_base{ "chams.weapons.basecolor", "ffffffff" }; +static settings::Rgba weapons_overlay{ "chams.weapons.overlaycolor", "ffffffff" }; +static settings::Float cham_alpha{ "chams.alpha", "1" }; +static settings::Boolean overlay_chams{ "chams.overlay", "false" }; + +/* Lighting rvars */ +static settings::Boolean phong_enable{ "chams.phong", "true" }; +static settings::Boolean halfambert{ "chams.halfambert", "true" }; +static settings::Boolean phong_fresnelrange{ "chams.phonefresnelranges", "true" }; +static settings::Int phong_boost{ "chams.phongboost", "2" }; +static settings::Int additive{ "chams.additive", "1" }; +static settings::Int pearlescent{ "chams.pearlescent", "8" }; + +static settings::Float phong_exponent{ "chams.phongexponent", "25" }; +static settings::Float phong_fresnelrange_1{ "chams.phongfresnelranges.1", "0" }; +static settings::Float phong_fresnelrange_2{ "chams.phongfresnelranges.2", "3" }; +static settings::Float phong_fresnelrange_3{ "chams.phongfresnelranges.3", "15" }; + +static settings::Boolean rimlighting{ "chams.rimlighting", "true" }; +static settings::Float rimlighting_boost{ "chams.rimlighting.boost", "1" }; +static settings::Float rimlighting_exponent{ "chams.rimlighting.exponent", "4" }; + +/* Customization of envmap */ +static settings::Boolean envmap{ "chams.envmap", "true" }; +static settings::Boolean envmap_matt{ "chams.envmap.matt", "false" }; +static settings::Float envmapfresnel{ "chams.envmapfresnel", "1" }; +static settings::Boolean envmap_tint{ "chams.envmap.tint", "true" }; +static settings::Float envmap_tint_red_r{ "chams.envmap.tint.red.r", "4" }; +static settings::Float envmap_tint_red_g{ "chams.envmap.tint.red.g", "0" }; +static settings::Float envmap_tint_red_b{ "chams.envmap.tint.red.b", "2" }; +static settings::Float envmap_tint_blu_r{ "chams.envmap.tint.blu.r", "0" }; +static settings::Float envmap_tint_blu_g{ "chams.envmap.tint.blu.g", "2" }; +static settings::Float envmap_tint_blu_b{ "chams.envmap.tint.blu.b", "4" }; +static settings::Float envmap_tint_weapons_r{ "chams.envmap.tint.weapons.r", "1" }; +static settings::Float envmap_tint_weapons_g{ "chams.envmap.tint.weapons.g", "1" }; +static settings::Float envmap_tint_weapons_b{ "chams.envmap.tint.weapons.b", "1" }; +static settings::Float envmap_tint_local_weapon_r{ "chams.envmap.tint.local-weapon.r", "1" }; +static settings::Float envmap_tint_local_weapon_g{ "chams.envmap.tint.local-weapon.g", "1" }; +static settings::Float envmap_tint_local_weapon_b{ "chams.envmap.tint.local-weapon.b", "1" }; +static settings::Float envmap_tint_arms_r{ "chams.envmap.tint.arms.r", "1" }; +static settings::Float envmap_tint_arms_g{ "chams.envmap.tint.arms.g", "1" }; +static settings::Float envmap_tint_arms_b{ "chams.envmap.tint.arms.b", "1" }; + +/* Overlay chams team highlight colors */ +static settings::Rgba chams_overlay_color_blu{ "chams.overlay.overlaycolor.blu", "000000ff" }; +static settings::Rgba chams_overlay_color_red{ "chams.overlay.overlaycolor.red", "000000ff" }; + +/* Seperate cham settings when ignorez */ +static settings::Boolean novis{ "chams.novis", "true" }; +static settings::Rgba novis_team_red{ "chams.novis.red", "ff8800ff" }; +static settings::Rgba novis_team_blu{ "chams.novis.blu", "bc00ffff" }; + +/* Customization of novis envmap */ +static settings::Float envmap_tint_red_r_novis{ "chams.novis.envmap.tint.red.r", "4" }; +static settings::Float envmap_tint_red_g_novis{ "chams.novis.envmap.tint.red.g", "4" }; +static settings::Float envmap_tint_red_b_novis{ "chams.novis.envmap.tint.red.b", "1" }; +static settings::Float envmap_tint_blu_r_novis{ "chams.novis.envmap.tint.blu.r", "4" }; +static settings::Float envmap_tint_blu_g_novis{ "chams.novis.envmap.tint.blu.g", "1" }; +static settings::Float envmap_tint_blu_b_novis{ "chams.novis.envmap.tint.blu.b", "4" }; + +/* Overlay chams novis team highlight colors */ +static settings::Rgba chams_overlay_color_blu_novis{ "chams.novis.overlay.overlaycolor.blu", "ff00ffff" }; +static settings::Rgba chams_overlay_color_red_novis{ "chams.novis.overlay.overlaycolor.red", "ff0000ff" }; + +/* Arm chams */ +static settings::Boolean arms_chams{ "chams.arms", "false" }; +static settings::Boolean arm_chams_original{ "chams.arms.original", "false" }; +static settings::Boolean arms_chams_team_color{ "chams.arms.team-colors", "true" }; +static settings::Boolean arms_chams_wireframe{ "chams.arms.wireframe", "false" }; +static settings::Boolean arm_chams_overlay_chams{ "chams.overlay.arms", "true" }; +static settings::Rgba arm_overlaychams_color{ "chams.arms.overlaycolor", "000000ff" }; +static settings::Rgba arm_basechams_color{ "chams.arms.basecolor", "00000055" }; + +/* Local weapon chams */ +static settings::Boolean local_weapon_chams{ "chams.local-weapon", "false" }; +static settings::Boolean local_weapon_chams_original{ "chams.local-weapon.original", "false" }; +static settings::Boolean local_weapon_chams_team_color{ "chams.local-weapon.team-colors", "true" }; +static settings::Boolean local_weapon_chams_wireframe{ "chams.local-weapon.wireframe", "false" }; +static settings::Boolean local_weapon_chams_overlay_chams{ "chams.overlay.local-weapon", "true" }; +static settings::Rgba local_weapon_overlaychams_color{ "chams.local-weapon.overlaycolor", "000000ff" }; +static settings::Rgba local_weapon_basechams_color{ "chams.local-weapon.basecolor", "000000ff" }; + +class Materials { -extern settings::Boolean enable; -} // namespace effect_glow -namespace effect_chams +public: + CMaterialReference mat_dme_unlit; + CMaterialReference mat_dme_lit; + CMaterialReference mat_dme_unlit_overlay_base; + CMaterialReference mat_dme_lit_overlay; + + // Sadly necessary ): + CMaterialReference mat_dme_lit_fp; + CMaterialReference mat_dme_unlit_overlay_base_fp; + CMaterialReference mat_dme_lit_overlay_fp; + + void Shutdown() + { + mat_dme_unlit.Shutdown(); + mat_dme_lit.Shutdown(); + mat_dme_unlit_overlay_base.Shutdown(); + mat_dme_lit_overlay.Shutdown(); + + mat_dme_lit_fp.Shutdown(); + mat_dme_unlit_overlay_base_fp.Shutdown(); + mat_dme_lit_overlay_fp.Shutdown(); + } +}; + +class ChamColors { -extern settings::Boolean enable; -} // namespace effect_chams +public: + float envmap_r, envmap_g, envmap_b; + rgba_t rgba; + + rgba_t rgba_overlay = colors::empty; + + ChamColors(rgba_t col = colors::empty, float r = 1.0f, float g = 1.0f, float b = 1.0f) + { + rgba = col; + envmap_r = r; + envmap_g = g; + envmap_b = b; + } +}; + namespace hooked_methods { -// Global scope so we can deconstruct on shutdown static bool init_mat = false; -static CMaterialReference mat_dme_chams; -static CMaterialReference mat_dme_arm1_chams; -static CMaterialReference mat_dme_arm_chams; +static Materials mats; + +template void rvarCallback(settings::VariableBase &, T) +{ + init_mat = false; +} + +class DrawEntry +{ +public: + int entidx; + int parentidx; + DrawEntry() + { + } + DrawEntry(int own_idx, int parent_idx) + { + entidx = own_idx; + parentidx = parent_idx; + } +}; + +std::vector attachment_draw_list; + static InitRoutine init_dme([]() { EC::Register( EC::LevelShutdown, []() { if (init_mat) { - mat_dme_chams.Shutdown(); + mats.Shutdown(); init_mat = false; } + attachment_draw_list.clear(); }, "dme_lvl_shutdown"); + + halfambert.installChangeCallback(rvarCallback); + additive.installChangeCallback(rvarCallback); + pearlescent.installChangeCallback(rvarCallback); + + phong_enable.installChangeCallback(rvarCallback); + phong_boost.installChangeCallback(rvarCallback); + phong_exponent.installChangeCallback(rvarCallback); + phong_fresnelrange.installChangeCallback(rvarCallback); + phong_fresnelrange_1.installChangeCallback(rvarCallback); + phong_fresnelrange_2.installChangeCallback(rvarCallback); + phong_fresnelrange_3.installChangeCallback(rvarCallback); + + rimlighting.installChangeCallback(rvarCallback); + rimlighting_boost.installChangeCallback(rvarCallback); + rimlighting_exponent.installChangeCallback(rvarCallback); + + envmap.installChangeCallback(rvarCallback); + envmapfresnel.installChangeCallback(rvarCallback); + envmap_tint.installChangeCallback(rvarCallback); + envmap_matt.installChangeCallback(rvarCallback); }); -bool aa_draw = false; + +// Purpose => Returns true if we should render provided internal entity +bool ShouldRenderChams(IClientEntity *entity) +{ + if (!enable || CE_BAD(LOCAL_E)) + return false; + if (entity->entindex() < 0) + return false; + CachedEntity *ent = ENTITY(entity->entindex()); + if (chamsself && ent->m_IDX == LOCAL_E->m_IDX) + return true; + switch (ent->m_Type()) + { + case ENTITY_BUILDING: + if (!buildings) + return false; + if (!ent->m_bEnemy() && !(teammate_buildings || teammates)) + return false; + if (ent->m_iHealth() == 0 || !ent->m_iHealth()) + return false; + if (CE_BYTE(LOCAL_E, netvar.m_bCarryingObject) && ent->m_IDX == HandleToIDX(CE_INT(LOCAL_E, netvar.m_hCarriedObject))) + return false; + return true; + case ENTITY_PLAYER: + if (!players) + return false; + if (!disguised && IsPlayerDisguised(ent)) + return false; + if (!teammates && !ent->m_bEnemy() && playerlist::IsDefault(ent)) + return false; + if (CE_BYTE(ent, netvar.iLifeState)) + return false; + return true; + case ENTITY_PROJECTILE: + if (ent->m_iClassID() == CL_CLASS(CTFGrenadePipebombProjectile)) + if (stickies || pipes) + { + if (CE_INT(ent, netvar.iPipeType) != 1) + { + if (pipes) + { + if (pipes_local && chamsself) + if ((CE_INT(ent, netvar.hThrower) & 0xFFF) == g_pLocalPlayer->entity->m_IDX) // Check if the sticky is the players own + return true; + if (ent->m_bEnemy()) + return true; + } + else + return false; + } + if (stickies_local && chamsself) + if ((CE_INT(ent, netvar.hThrower) & 0xFFF) == g_pLocalPlayer->entity->m_IDX) // Check if the sticky is the players own + return true; + if (ent->m_bEnemy()) + return true; + } + break; + case ENTITY_GENERIC: + switch (ent->m_ItemType()) + { + case ITEM_HEALTH_LARGE: + case ITEM_HEALTH_MEDIUM: + case ITEM_HEALTH_SMALL: + return *medkits; + case ITEM_AMMO_LARGE: + case ITEM_AMMO_MEDIUM: + case ITEM_AMMO_SMALL: + return *ammobox; + default: + break; + } + break; + default: + break; + } + return false; +} + +// Purpose => Get ChamColors struct from internal entity +static ChamColors GetChamColors(IClientEntity *entity, bool ignorez) +{ + CachedEntity *ent = ENTITY(entity->entindex()); + + if (CE_BAD(ent)) + return ChamColors(colors::white); + if (ent == hacks::shared::aimbot::CurrentTarget()) + return ChamColors(colors::target); + if (re::C_BaseCombatWeapon::IsBaseCombatWeapon(entity)) + { + IClientEntity *owner = re::C_TFWeaponBase::GetOwnerViaInterface(entity); + if (owner) + return GetChamColors(owner, ignorez); + } + switch (ent->m_Type()) + { + case ENTITY_BUILDING: + if (!ent->m_bEnemy() && !(teammates || teammate_buildings) && ent != LOCAL_E) + return ChamColors(); + if (health) + return ChamColors(colors::Health_dimgreen(ent->m_iHealth(), ent->m_iMaxHealth())); + break; + case ENTITY_PLAYER: + if (!players) + return ChamColors(); + if (health) + return ChamColors(colors::Health_dimgreen(ent->m_iHealth(), ent->m_iMaxHealth())); + break; + default: + break; + } + if (ent->m_Type() == ENTITY_PLAYER || ent->m_Type() == ENTITY_BUILDING || ent->m_Type() == ENTITY_PROJECTILE) + { + ChamColors result; + + if (ent->m_iTeam() == TEAM_BLU) + result = ChamColors(colors::blu, *envmap_tint_blu_r, *envmap_tint_blu_g, *envmap_tint_blu_b); + else if (ent->m_iTeam() == TEAM_RED) + result = ChamColors(colors::red, *envmap_tint_red_r, *envmap_tint_red_g, *envmap_tint_red_b); + if (novis && ignorez) + { + if (ent->m_iTeam() == TEAM_BLU) + result = ChamColors(*novis_team_blu, *envmap_tint_blu_r_novis, *envmap_tint_blu_g_novis, *envmap_tint_blu_b_novis); + else if (ent->m_iTeam() == TEAM_RED) + result = ChamColors(*novis_team_red, *envmap_tint_red_r_novis, *envmap_tint_red_g_novis, *envmap_tint_red_b_novis); + } + if (ent->m_Type() == ENTITY_PLAYER) + { + if (IsPlayerInvulnerable(ent)) + { + if (ent->m_iTeam() == TEAM_BLU) + result = ChamColors(colors::blu_u, *envmap_tint_blu_r, *envmap_tint_blu_g, *envmap_tint_blu_b); + else if (ent->m_iTeam() == TEAM_RED) + result = ChamColors(colors::red_u, *envmap_tint_red_r, *envmap_tint_red_g, *envmap_tint_red_b); + } + if (HasCondition(ent)) + { + if (ent->m_iTeam() == TEAM_BLU) + result = ChamColors(colors::blu_v, *envmap_tint_blu_r, *envmap_tint_blu_g, *envmap_tint_blu_b); + else if (ent->m_iTeam() == TEAM_RED) + result = ChamColors(colors::red_v, *envmap_tint_red_r, *envmap_tint_red_g, *envmap_tint_red_b); + } + } + auto o = player_tools::forceEspColor(ent); + if (o.has_value()) + result = ChamColors(*o); + + return result; + } + return ChamColors(colors::EntityF(ent)); +} + +// Purpose => Render entity attachments (weapons, hats) +void RenderAttachment(IClientEntity *entity, IClientEntity *attach, CMaterialReference &mat) +{ + if (attach->ShouldDraw()) + { + attachment_draw_list.emplace_back(attach->entindex(), entity->entindex()); + if (entity->GetClientClass()->m_ClassID == RCC_PLAYER && re::C_BaseCombatWeapon::IsBaseCombatWeapon(attach)) + { + // If separate weapon settings is used, apply them + if (weapons) + { + // Backup original color + rgba_t original; + g_IVRenderView->GetColorModulation(original.rgba); + g_IVRenderView->SetColorModulation(*weapons_base); + + // Setup material + g_IVRenderView->SetBlend((*weapons_base).a); + if (mat && envmap) + mat->FindVar("$envmaptint", nullptr)->SetVecValue(*envmap_tint_weapons_r, *envmap_tint_weapons_g, *envmap_tint_weapons_b); + + // Render + attach->DrawModel(1); + + if (overlay_chams) + { + // Setup material + g_IVRenderView->SetColorModulation(*weapons_overlay); + g_IVRenderView->SetBlend((*weapons_overlay).a); + if (mat && envmap) + mat->FindVar("$envmaptint", nullptr)->SetVecValue(*envmap_tint_weapons_r, *envmap_tint_weapons_g, *envmap_tint_weapons_b); + + // Render + attach->DrawModel(1); + } + + // Reset it! + g_IVRenderView->SetColorModulation(original.rgba); + } + else + { + attach->DrawModel(1); + } + } + else + attach->DrawModel(1); + } +} + +// Locked from drawing +bool chams_attachment_drawing = false; + +// Purpose => Render overriden model and and attachments +void RenderChamsRecursive(IClientEntity *entity, CMaterialReference &mat, IVModelRender *this_, const DrawModelState_t &state, const ModelRenderInfo_t &info, matrix3x4_t *bone) +{ +#if !ENFORCE_STREAM_SAFETY + if (!enable) + return; + original::DrawModelExecute(this_, state, info, bone); + + if (!*recursive) + return; + + IClientEntity *attach; + int passes = 0; + + attach = g_IEntityList->GetClientEntity(*(int *) ((uintptr_t) entity + netvar.m_Collision - 24) & 0xFFF); + while (attach && passes++ < 32) + { + chams_attachment_drawing = true; + RenderAttachment(entity, attach, mat); + chams_attachment_drawing = false; + attach = g_IEntityList->GetClientEntity(*(int *) ((uintptr_t) attach + netvar.m_Collision - 20) & 0xFFF); + } +#endif +} + +// Purpose => Apply and render chams according to settings +void ApplyChams(ChamColors colors, bool recurse, bool render_original, bool overlay, bool ignorez, bool wireframe, bool firstperson, IClientEntity *entity, IVModelRender *this_, const DrawModelState_t &state, const ModelRenderInfo_t &info, matrix3x4_t *bone) +{ + static auto &mat = firstperson ? overlay ? mats.mat_dme_unlit_overlay_base_fp : mats.mat_dme_lit_fp : overlay ? mats.mat_dme_unlit_overlay_base : mats.mat_dme_lit; + if (render_original) + recurse ? RenderChamsRecursive(entity, mat, this_, state, info, bone) : original::DrawModelExecute(this_, state, info, bone); + + // Setup material + g_IVRenderView->SetColorModulation(colors.rgba); + g_IVRenderView->SetBlend((colors.rgba).a); + mat->AlphaModulate((colors.rgba).a); + if (envmap && envmap_tint) + mat->FindVar("$envmaptint", nullptr)->SetVecValue(colors.envmap_r, colors.envmap_g, colors.envmap_b); + + // Setup wireframe and ignorez using material vars + mat->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, ignorez); + mat->SetMaterialVarFlag(MATERIAL_VAR_WIREFRAME, wireframe); + + // Override + g_IVModelRender->ForcedMaterialOverride(mat); + + // Apply our new material + recurse ? RenderChamsRecursive(entity, mat, this_, state, info, bone) : original::DrawModelExecute(this_, state, info, bone); + if (overlay) + { + // Use white if no color was supplied + if (colors.rgba_overlay == colors::empty && entity && IDX_GOOD(entity->entindex())) + { + CachedEntity *ent = ENTITY(entity->entindex()); + if (ent->m_Type() != ENTITY_PLAYER && ent->m_Type() != ENTITY_PROJECTILE && ent->m_Type() != ENTITY_BUILDING) + colors.rgba_overlay = colors::white; + else + colors.rgba_overlay = ent->m_iTeam() == TEAM_RED ? *chams_overlay_color_red : ent->m_iTeam() == TEAM_BLU ? *chams_overlay_color_blu : colors::white; + } + // Setup material + g_IVRenderView->SetColorModulation(colors.rgba_overlay); + g_IVRenderView->SetBlend((colors.rgba_overlay).a); + + static auto &mat_overlay = mats.mat_dme_lit_overlay; + if (envmap && envmap_tint) + mat_overlay->FindVar("$envmaptint", nullptr)->SetVecValue(colors.envmap_r, colors.envmap_g, colors.envmap_b); + + mat_overlay->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, ignorez); + mat_overlay->AlphaModulate((colors.rgba_overlay).a); + + // Override and apply + g_IVModelRender->ForcedMaterialOverride(mat_overlay); + recurse ? RenderChamsRecursive(entity, mat, this_, state, info, bone) : original::DrawModelExecute(this_, state, info, bone); + } +} + DEFINE_HOOKED_METHOD(DrawModelExecute, void, IVModelRender *this_, const DrawModelState_t &state, const ModelRenderInfo_t &info, matrix3x4_t *bone) { - if (!isHackActive()) - return original::DrawModelExecute(this_, state, info, bone); - - if (!(hacks::tf2::backtrack::isBacktrackEnabled /*|| (hacks::shared::antiaim::force_fakelag && hacks::shared::antiaim::isEnabled())*/ || blend_zoom || spectator_target || arms_chams || no_arms || no_hats || (*clean_screenshots && g_IEngine->IsTakingScreenshot()) || CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())) - { - return original::DrawModelExecute(this_, state, info, bone); - } - if (effect_glow::g_EffectGlow.drawing || effect_chams::g_EffectChams.drawing) + if (!isHackActive() || effect_glow::g_EffectGlow.drawing || chams_attachment_drawing || (*clean_screenshots && g_IEngine->IsTakingScreenshot()) || CE_BAD(LOCAL_E) || (!enable && !no_hats && !no_arms && !blend_zoom && !arms_chams && !local_weapon_chams && !(hacks::tf2::backtrack::chams && hacks::tf2::backtrack::isBacktrackEnabled))) return original::DrawModelExecute(this_, state, info, bone); PROF_SECTION(DrawModelExecute); if (!init_mat) { + const char *cubemap_str = *envmap_matt ? "effects/saxxy/saxxy_gold" : "env_cubemap"; { - KeyValues *kv = new KeyValues("UnlitGeneric"); - kv->SetString("$basetexture", "vgui/white_additive"); - kv->SetInt("$ignorez", 0); - mat_dme_chams.Init("__cathook_glow_unlit", kv); + auto *kv = new KeyValues("UnlitGeneric"); + kv->SetString("$basetexture", "white"); + mats.mat_dme_unlit.Init("__cathook_dme_chams_unlit", kv); } - + KeyValues *kv_vertex_lit = nullptr; { - KeyValues *kv = new KeyValues("UnlitGeneric"); - kv->SetString("$basetexture", "vgui/white_additive"); - kv->SetInt("$ignorez", 0); - kv->SetBool("$flat", true); - mat_dme_arm1_chams.Init("__cathook_arm_base", kv); + auto *kv = new KeyValues("VertexLitGeneric"); + kv->SetString("$basetexture", "white"); + kv->SetString("$bumpmap", "water/tfwater001_normal"); + kv->SetString("$lightwarptexture", "models/player/pyro/pyro_lightwarp"); + kv->SetBool("$halfambert", *halfambert); + kv->SetBool("$phong", *phong_enable); + kv->SetFloat("$phongexponent", *phong_exponent); + kv->SetFloat("$phongboost", *phong_boost); + if (phong_fresnelrange) + { + char buffer[100]; + snprintf(buffer, 100, "[%.2f %.2f %.2f]", *phong_fresnelrange_1, *phong_fresnelrange_2, *phong_fresnelrange_3); + kv->SetString("$phongfresnelranges", buffer); + } + if (envmap) + { + kv->SetString("$envmap", cubemap_str); + kv->SetFloat("$envmapfresnel", *envmapfresnel); + kv->SetString("$envmapfresnelminmaxexp", "[0.01 1 2]"); + kv->SetInt("$normalmapalphaenvmapmask", 1); + kv->SetInt("$selfillum", 1); + if (envmap_tint) + kv->SetString("$envmaptint", "[1 1 1]"); + } + kv->SetBool("$rimlight", *rimlighting); + kv->SetFloat("$rimlightexponent", *rimlighting_exponent); + kv->SetFloat("$rimlightboost", *phong_boost); + kv_vertex_lit = kv->MakeCopy(); + mats.mat_dme_lit.Init("__cathook_dme_chams_lit", kv); } - - { // - KeyValues *kv = new KeyValues("VertexLitGeneric"); - kv->SetString("$basetexture", "vgui/white_additive"); - kv->SetBool("$phong", true); - kv->SetInt("$phongboost", 4); - kv->SetBool("$rimlight", true); - kv->SetFloat("$rimlightexponent", 2.f); - kv->SetInt("$additive", 2); - kv->SetInt("$pearlescent", 8); + { + auto *kv = new KeyValues("UnlitGeneric"); + kv->SetString("$basetexture", "white"); + mats.mat_dme_unlit_overlay_base.Init("__cathook_dme_chams_lit_overlay_base", kv); + } + { + auto *kv = kv_vertex_lit; + kv->SetInt("$additive", *additive); + kv->SetInt("$pearlescent", *pearlescent); kv->SetBool("$flat", false); - kv->SetString("$envmap", "models/effects/cube_white"); - kv->SetFloat("$envmapfresnel", 1.f); - kv->SetInt("$ignorez", 0); - mat_dme_arm_chams.Init("__cathook_arm_overlay", kv); + mats.mat_dme_lit_overlay.Init("__cathook_dme_chams_lit_overlay", kv); + } + KeyValues *kv_vertex_lit_fp = nullptr; + { + auto *kv = new KeyValues("VertexLitGeneric"); + kv->SetString("$basetexture", "white"); + kv->SetString("$bumpmap", "water/tfwater001_normal"); + kv->SetString("$lightwarptexture", "models/player/pyro/pyro_lightwarp"); + kv->SetBool("$halfambert", *halfambert); + kv->SetBool("$phong", *phong_enable); + kv->SetFloat("$phongexponent", *phong_exponent); + kv->SetFloat("$phongboost", *phong_boost); + if (phong_fresnelrange) + { + char buffer[100]; + snprintf(buffer, 100, "[%.2f %.2f %.2f]", *phong_fresnelrange_1, *phong_fresnelrange_2, *phong_fresnelrange_3); + kv->SetString("$phongfresnelranges", buffer); + } + if (envmap) + { + kv->SetString("$envmap", cubemap_str); + kv->SetFloat("$envmapfresnel", *envmapfresnel); + kv->SetString("$envmapfresnelminmaxexp", "[0.01 1 2]"); + kv->SetInt("$normalmapalphaenvmapmask", 1); + kv->SetInt("$selfillum", 1); + if (envmap_tint) + kv->SetString("$envmaptint", "[1 1 1]"); + } + kv->SetBool("$rimlight", *rimlighting); + kv->SetFloat("$rimlightexponent", *rimlighting_exponent); + kv->SetFloat("$rimlightboost", *phong_boost); + kv_vertex_lit_fp = kv->MakeCopy(); + mats.mat_dme_lit_fp.Init("__cathook_dme_chams_lit_fp", kv); + } + { + auto *kv = new KeyValues("UnlitGeneric"); + kv->SetString("$basetexture", "white"); + mats.mat_dme_unlit_overlay_base_fp.Init("__cathook_dme_chams_lit_overlay_base_fp", kv); + } + { + auto *kv = kv_vertex_lit_fp; + kv->SetInt("$additive", *additive); + kv->SetInt("$pearlescent", *pearlescent); + kv->SetBool("$flat", false); + mats.mat_dme_lit_overlay_fp.Init("__cathook_dme_chams_lit_overlay_fp", kv); } init_mat = true; } @@ -101,138 +628,168 @@ DEFINE_HOOKED_METHOD(DrawModelExecute, void, IVModelRender *this_, const DrawMod if (name) { std::string sname = name; - if (sname.find("arms") != std::string::npos || sname.find("c_engineer_gunslinger") != std::string::npos) + if ((sname.find("arms") != std::string::npos && sname.find("yeti") == std::string::npos) || sname.find("c_engineer_gunslinger") != std::string::npos) { - if (no_arms && sname.find("arms") != std::string::npos) - { + if (no_arms) return; - } if (arms_chams) { + // Backup original colors rgba_t original_color; - g_IVRenderView->GetColorModulation(original_color); original_color.a = g_IVRenderView->GetBlend(); - g_IVModelRender->ForcedMaterialOverride(mat_dme_arm1_chams); - g_IVRenderView->SetBlend((*arm_basechams_color).a); - g_IVRenderView->SetColorModulation(*arm_basechams_color); - original::DrawModelExecute(this_, state, info, bone); + // Setup according to user settings using the ChamColors struct + auto colors = GetChamColors(LOCAL_E->InternalEntity(), false); + colors.rgba_overlay = LOCAL_E->m_iTeam() == TEAM_RED ? *chams_overlay_color_red : LOCAL_E->m_iTeam() == TEAM_BLU ? *chams_overlay_color_blu : colors::white; + if (!arms_chams_team_color) + { + colors = *arm_basechams_color; + colors.rgba_overlay = *arm_overlaychams_color; + colors.envmap_r = *envmap_tint_arms_r; + colors.envmap_g = *envmap_tint_arms_g; + colors.envmap_b = *envmap_tint_arms_b; + } + colors.rgba.a = (*arm_basechams_color).a; + colors.rgba_overlay.a = (*arm_overlaychams_color).a; - g_IVModelRender->ForcedMaterialOverride(mat_dme_arm_chams); - g_IVRenderView->SetBlend((*arm_overlaychams_color).a); - g_IVRenderView->SetColorModulation(*arm_overlaychams_color); - original::DrawModelExecute(this_, state, info, bone); + // Apply arm chams + IClientEntity *entity = g_IEntityList->GetClientEntity(info.entity_index); + ApplyChams(colors, false, *arm_chams_original, *arm_chams_overlay_chams, false, *arms_chams_wireframe, true, entity, this_, state, info, bone); + // Reset it! g_IVModelRender->ForcedMaterialOverride(nullptr); g_IVRenderView->SetColorModulation(original_color); g_IVRenderView->SetBlend(original_color.a); return; } } + // Workaround for attachments flickering + std::vector tmp_list; + bool do_draw = true; + for (auto &drawer : attachment_draw_list) + { + if (drawer.entidx == info.entity_index) + { + do_draw = false; + } + else + tmp_list.push_back(drawer); + } + attachment_draw_list = std::move(tmp_list); + if (!do_draw) + return; + + if (local_weapon_chams && info.entity_index == -1 && sname.find("arms") == std::string::npos && (sname.find("models/weapons") != std::string::npos || sname.find("models/workshop/weapons") != std::string::npos || sname.find("models/workshop_partner/weapons") != std::string::npos)) + { + // Backup original colors + rgba_t original_color; + g_IVRenderView->GetColorModulation(original_color); + original_color.a = g_IVRenderView->GetBlend(); + + auto colors = GetChamColors(LOCAL_E->InternalEntity(), false); + IClientEntity *entity = g_IEntityList->GetClientEntity(info.entity_index); + + // Setup according to user settings using the ChamColors struct + if (local_weapon_chams_team_color) + { + colors.rgba_overlay = LOCAL_E->m_iTeam() == TEAM_RED ? *chams_overlay_color_red : LOCAL_E->m_iTeam() == TEAM_BLU ? *chams_overlay_color_blu : colors::white; + } + else + { + colors = *local_weapon_basechams_color; + colors.rgba_overlay = *local_weapon_overlaychams_color; + colors.envmap_r = *envmap_tint_local_weapon_r; + colors.envmap_g = *envmap_tint_local_weapon_g; + colors.envmap_b = *envmap_tint_local_weapon_b; + } + colors.rgba.a = (*local_weapon_basechams_color).a; + colors.rgba_overlay.a = (*local_weapon_overlaychams_color).a; + + // Apply local weapon chams + ApplyChams(colors, false, *local_weapon_chams_original, *local_weapon_chams_overlay_chams, false, *local_weapon_chams_wireframe, true, entity, this_, state, info, bone); + + // Reset it! + g_IVModelRender->ForcedMaterialOverride(nullptr); + g_IVRenderView->SetColorModulation(original_color); + g_IVRenderView->SetBlend(original_color.a); + return; + } if (no_hats && sname.find("player/items") != std::string::npos) - { return; - } - /* - if(g_pLocalPlayer->bZoomed && sname.find("models/weapons") != std::string::npos) + // Player, entity and backtrack chams + if (IDX_GOOD(info.entity_index)) { - g_IVModelRender->ForcedMaterialOverride(nullptr); - g_IVRenderView->SetBlend(0.2f); - original::DrawModelExecute(this_, state, info, bone); - return; - } - */ - } - } - - // Used for fakes and for backtrack chams/glow - - // Maybe one day i'll get this working - /*if (aa_draw && info.entity_index == g_pLocalPlayer->entity_idx) - { - CMatRenderContextPtr ptr(GET_RENDER_CONTEXT); - rgba_t mod_original; - // Save color just in case, then set to white - g_IVRenderView->GetColorModulation(mod_original.rgba); - g_IVRenderView->SetColorModulation(colors::white); - // Important for Depth - ptr->DepthRange(0.0f, 1.0f); - // Apply our material - g_IVModelRender->ForcedMaterialOverride(mat_unlit); - // Run Original - original::DrawModelExecute(this_, state, info, bone); - // Revert - g_IVRenderView->SetColorModulation(mod_original.rgba); - g_IVModelRender->ForcedMaterialOverride(nullptr); - return; - } - if (hacks::shared::antiaim::force_fakelag && hacks::shared::antiaim::isEnabled() && info.entity_index == g_pLocalPlayer->entity_idx) - { - float fake = hacks::shared::antiaim::used_yaw; - Vector &angles = CE_VECTOR(LOCAL_E, netvar.m_angEyeAngles); - float backup = angles.y; - angles.y = fake; - aa_draw = true; - RAW_ENT(LOCAL_E)->DrawModel(1); - aa_draw = false; - angles.y = backup; - }*/ - if (hacks::tf2::backtrack::chams && hacks::tf2::backtrack::isBacktrackEnabled) - { - const char *name = g_IModelInfo->GetModelName(info.pModel); - if (name) - { - std::string sname = name; - if (sname.find("models/player") || sname.find("models/weapons") || sname.find("models/workshop/player") || sname.find("models/workshop/weapons")) - { - if (IDX_GOOD(info.entity_index) && info.entity_index <= g_IEngine->GetMaxClients() && info.entity_index != g_IEngine->GetLocalPlayer()) + // Get the internal entity from the index + IClientEntity *entity = g_IEntityList->GetClientEntity(info.entity_index); + if (ShouldRenderChams(entity)) { + // Ensure a valid entity CachedEntity *ent = ENTITY(info.entity_index); - if (CE_GOOD(ent) && ent->m_bAlivePlayer()) + if (CE_GOOD(ent)) { + // Get original to restore to later + rgba_t original_color; + g_IVRenderView->GetColorModulation(original_color); + original_color.a = g_IVRenderView->GetBlend(); - // Get Backtrack data for target entity - auto good_ticks = hacks::tf2::backtrack::getGoodTicks(info.entity_index); - - // Check if valid - if (!good_ticks.empty()) + // Player and entity chams + if (enable) { - // Make our own Chamsish Material - // Render Chams/Glow stuff - CMatRenderContextPtr ptr(GET_RENDER_CONTEXT); - // Backup Blend - float orig_blend = g_IVRenderView->GetBlend(); - // Make Backtrack stuff Use chams alpha - g_IVRenderView->SetBlend((*hacks::tf2::backtrack::chams_color).a); - - rgba_t mod_original; - // Save color just in case, then set to team color - g_IVRenderView->GetColorModulation(mod_original.rgba); - g_IVRenderView->SetColorModulation(*hacks::tf2::backtrack::chams_color); - // Important for Depth - ptr->DepthRange(0.0f, 1.0f); - // Apply our material - if (hacks::tf2::backtrack::chams_solid) - g_IVModelRender->ForcedMaterialOverride(mat_dme_chams); - - // Draw as many ticks as desired - for (unsigned i = 0; i <= (unsigned) std::max(*hacks::tf2::backtrack::chams_ticks, 1); i++) + // First time has ignorez, 2nd time not + for (int i = 1; i >= 0; i--) { - // Can't draw more than we have - if (i >= good_ticks.size()) - break; - if (!good_ticks[i].bones.empty()) - original::DrawModelExecute(this_, state, info, &good_ticks[i].bones[0]); + if (i && legit) + continue; + if (!i && singlepass) + continue; + + // Setup colors + auto colors = GetChamColors(entity, i); + colors.rgba.a = *cham_alpha; + + // Apply chams according to user settings + ApplyChams(colors, *recursive, *render_original, *overlay_chams, i, false, false, entity, this_, state, info, bone); } - // Revert - g_IVRenderView->SetColorModulation(mod_original.rgba); - g_IVModelRender->ForcedMaterialOverride(nullptr); - g_IVRenderView->SetBlend(orig_blend); } + // Backtrack chams + using namespace hacks::tf2; + if (backtrack::chams && backtrack::isBacktrackEnabled) + { + // TODO: Allow for a fade between the entity's color and a specified color, it would look cool but i'm lazy + if (ent->m_bAlivePlayer()) + { + // Get ticks + auto good_ticks = backtrack::getGoodTicks(info.entity_index); + if (!good_ticks.empty()) + { + // Setup chams according to user settings + ChamColors backtrack_colors; + backtrack_colors.rgba = *backtrack::chams_color; + backtrack_colors.rgba_overlay = *backtrack::chams_color_overlay; + backtrack_colors.envmap_r = *backtrack::chams_envmap_tint_r; + backtrack_colors.envmap_g = *backtrack::chams_envmap_tint_g; + backtrack_colors.envmap_b = *backtrack::chams_envmap_tint_b; + + for (unsigned i = 0; i <= (unsigned) std::max(*backtrack::chams_ticks, 1); i++) + { + // Can't draw more than we have + if (i >= good_ticks.size()) + break; + if (!good_ticks[i].bones.empty()) + ApplyChams(backtrack_colors, false, false, *backtrack::chams_overlay, false, *backtrack::chams_wireframe, false, entity, this_, state, info, &good_ticks[i].bones[0]); + } + } + } + } + // Reset it! + g_IVModelRender->ForcedMaterialOverride(nullptr); + g_IVRenderView->SetColorModulation(original_color); + g_IVRenderView->SetBlend(original_color.a); + return; } } } @@ -246,7 +803,6 @@ DEFINE_HOOKED_METHOD(DrawModelExecute, void, IVModelRender *this_, const DrawMod if (ent->entindex() == spectator_target) return; } - // Don't do it when we are trying to enforce backtrack chams if (!hacks::tf2::backtrack::isDrawing) return original::DrawModelExecute(this_, state, info, bone); diff --git a/src/hooks/visual/FrameStageNotify.cpp b/src/hooks/visual/FrameStageNotify.cpp index b7ccab25..2d21df17 100644 --- a/src/hooks/visual/FrameStageNotify.cpp +++ b/src/hooks/visual/FrameStageNotify.cpp @@ -18,14 +18,19 @@ static settings::Rgba nightmode_gui_color{ "visual.night-mode.gui-color", "00000 static settings::Rgba nightmode_world_color{ "visual.night-mode.world-color", "000000FF" }; static settings::Rgba nightmode_skybox_color{ "visual.night-mode.skybox-color", "000000FF" }; static settings::Boolean no_shake{ "visual.no-shake", "true" }; +static settings::Boolean override_textures{ "visual.override-textures", "false" }; +static settings::String override_textures_texture{ "visual.override-textures.custom-texture", "dev/dev_measuregeneric01b" }; -// Should we update nightmode? -static bool update_nightmode = false; +// Should we update? +static bool update_nightmode = false; +static bool update_override_textures = false; // Which strings trigger this nightmode option -std::vector world_strings = { "World" }; -std::vector skybox_strings = { "SkyBox" }; -std::vector gui_strings = { "Other", "VGUI" }; +std::vector world_strings = { "World" }; +std::vector skybox_strings = { "SkyBox" }; +std::vector gui_strings = { "Other", "VGUI" }; +std::vector dont_override_strings = { "glass", "door", "water", "tools", "player" }; +std::vector nodraw_strings = { "decal", "overlay", "hay" }; namespace hooked_methods { @@ -37,6 +42,52 @@ DEFINE_HOOKED_METHOD(FrameStageNotify, void, void *this_, ClientFrameStage_t sta PROF_SECTION(FrameStageNotify_TOTAL); + if (update_override_textures) + { + if (override_textures) + { + for (MaterialHandle_t i = g_IMaterialSystem->FirstMaterial(); i != g_IMaterialSystem->InvalidMaterial(); i = g_IMaterialSystem->NextMaterial(i)) + { + IMaterial *pMaterial = g_IMaterialSystem->GetMaterial(i); + if (!pMaterial) + continue; + + auto name = std::string(pMaterial->GetTextureGroupName()); + auto path = std::string(pMaterial->GetName()); + + // Ensure world mat + if (name.find("World") == std::string::npos) + continue; + // Don't override this stuff + bool good = true; + for (auto &entry : dont_override_strings) + if (path.find(entry) != path.npos) + { + good = false; + } + // Don't draw this stuff + for (auto &entry : nodraw_strings) + if (path.find(entry) != path.npos) + { + pMaterial->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, true); + good = false; + } + if (!good) + continue; + + if (!pMaterial->GetMaterialVarFlag(MATERIAL_VAR_NO_DRAW)) + { + auto *kv = new KeyValues(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("$surfaceprop", "concrete"); + pMaterial->SetShaderAndParams(kv); + } + } + } + update_override_textures = false; + } + if (update_nightmode) { static ConVar *r_DrawSpecificStaticProp = g_ICvar->FindVar("r_DrawSpecificStaticProp"); @@ -168,5 +219,9 @@ static InitRoutine init_fsn([]() { nightmode_gui_color.installChangeCallback(rvarCallback); nightmode_world_color.installChangeCallback(rvarCallback); nightmode_skybox_color.installChangeCallback(rvarCallback); + override_textures.installChangeCallback([](settings::VariableBase &, bool after) { update_override_textures = true; }); + override_textures_texture.installChangeCallback([](settings::VariableBase &, std::string after) { update_override_textures = true; }); + EC::Register( + EC::LevelInit, []() { update_nightmode = true; update_override_textures = true; }, "levelinit_fsn"); }); } // namespace hooked_methods diff --git a/src/nospread.cpp b/src/nospread.cpp index 7001e888..988f22da 100644 --- a/src/nospread.cpp +++ b/src/nospread.cpp @@ -905,7 +905,7 @@ static InitRoutine init_bulletnospread([]() { { if (bad_mantissa) { - draw_color = colors::red; + draw_color = colors::red_s; draw_string = "Server uptime too Low!"; } else diff --git a/src/visual/CMakeLists.txt b/src/visual/CMakeLists.txt index a7bc5a18..5137a908 100755 --- a/src/visual/CMakeLists.txt +++ b/src/visual/CMakeLists.txt @@ -2,7 +2,6 @@ set(files "${CMAKE_CURRENT_LIST_DIR}/atlas.cpp" "${CMAKE_CURRENT_LIST_DIR}/colors.cpp" "${CMAKE_CURRENT_LIST_DIR}/drawing.cpp" "${CMAKE_CURRENT_LIST_DIR}/drawmgr.cpp" - "${CMAKE_CURRENT_LIST_DIR}/EffectChams.cpp" "${CMAKE_CURRENT_LIST_DIR}/EffectGlow.cpp" "${CMAKE_CURRENT_LIST_DIR}/EventLogging.cpp" "${CMAKE_CURRENT_LIST_DIR}/fidgetspinner.cpp" diff --git a/src/visual/EffectChams.cpp b/src/visual/EffectChams.cpp deleted file mode 100644 index 46c1334f..00000000 --- a/src/visual/EffectChams.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* - * EffectChams.cpp - * - * Created on: Apr 16, 2017 - * Author: nullifiedcat - */ - -#include -#include -#include -#include "common.hpp" -#include "Backtrack.hpp" - -namespace effect_chams -{ -static settings::Boolean flat{ "chams.flat", "false" }; -static settings::Boolean health{ "chams.health", "false" }; -static settings::Boolean teammates{ "chams.show.teammates", "false" }; -static settings::Boolean disguised{ "chams.show.disguised", "true" }; -static settings::Boolean players{ "chams.show.players", "true" }; -static settings::Boolean medkits{ "chams.show.medkits", "false" }; -static settings::Boolean ammobox{ "chams.show.ammoboxes", "false" }; -static settings::Boolean buildings{ "chams.show.buildings", "true" }; -static settings::Boolean stickies{ "chams.show.stickies", "true" }; -static settings::Boolean teammate_buildings{ "chams.show.teammate-buildings", "false" }; -static settings::Boolean recursive{ "chams.recursive", "true" }; -static settings::Boolean weapons_white{ "chams.white-weapons", "true" }; -static settings::Boolean legit{ "chams.legit", "false" }; -static settings::Boolean singlepass{ "chams.single-pass", "false" }; -static settings::Boolean chamsself{ "chams.self", "true" }; -static settings::Boolean disco_chams{ "chams.disco", "false" }; - -settings::Boolean enable{ "chams.enable", "false" }; -CatCommand fix_black_chams("fix_black_chams", "Fix Black Chams", []() { - effect_chams::g_EffectChams.Shutdown(); - effect_chams::g_EffectChams.Init(); -}); - -void EffectChams::Init() -{ -#if !ENFORCE_STREAM_SAFETY - if (init) - return; - logging::Info("Init EffectChams..."); - { - KeyValues *kv = new KeyValues("UnlitGeneric"); - kv->SetString("$basetexture", "vgui/white_additive"); - kv->SetInt("$ignorez", 0); - mat_unlit.Init("__cathook_echams_unlit", kv); - } - { - KeyValues *kv = new KeyValues("UnlitGeneric"); - kv->SetString("$basetexture", "vgui/white_additive"); - kv->SetInt("$ignorez", 1); - mat_unlit_z.Init("__cathook_echams_unlit_z", kv); - } - { - KeyValues *kv = new KeyValues("VertexLitGeneric"); - kv->SetString("$basetexture", "vgui/white_additive"); - kv->SetInt("$ignorez", 0); - kv->SetInt("$halflambert", 1); - mat_lit.Init("__cathook_echams_lit", kv); - } - { - KeyValues *kv = new KeyValues("VertexLitGeneric"); - kv->SetString("$basetexture", "vgui/white_additive"); - kv->SetInt("$ignorez", 1); - kv->SetInt("$halflambert", 1); - mat_lit_z.Init("__cathook_echams_lit_z", kv); - } - logging::Info("Init done!"); - init = true; -#endif -} - -void EffectChams::BeginRenderChams() -{ -#if !ENFORCE_STREAM_SAFETY - drawing = true; - CMatRenderContextPtr ptr(GET_RENDER_CONTEXT); - g_IVRenderView->SetBlend(1.0f); -#endif -} - -void EffectChams::EndRenderChams() -{ -#if !ENFORCE_STREAM_SAFETY - drawing = false; - CMatRenderContextPtr ptr(GET_RENDER_CONTEXT); - g_IVModelRender->ForcedMaterialOverride(nullptr); -#endif -} -static rgba_t data[PLAYER_ARRAY_SIZE] = { colors::empty }; -void EffectChams::SetEntityColor(CachedEntity *ent, rgba_t color) -{ - if (ent->m_IDX > MAX_PLAYERS || ent->m_IDX < 0) - return; - data[ent->m_IDX] = color; -} -static Timer t{}; -static int prevcolor = -1; -rgba_t EffectChams::ChamsColor(IClientEntity *entity) -{ - if (!isHackActive() || !*effect_chams::enable) - return colors::empty; - - CachedEntity *ent = ENTITY(entity->entindex()); - if (disco_chams) - { - static rgba_t disco{ 0, 0, 0, 0 }; - if (t.test_and_set(200)) - { - int color = rand() % 20; - while (color == prevcolor) - color = rand() % 20; - prevcolor = color; - switch (color) - { - case 2: - disco = colors::pink; - break; - case 3: - disco = colors::red; - break; - case 4: - disco = colors::blu; - break; - case 5: - disco = colors::red_b; - break; - case 6: - disco = colors::blu_b; - break; - case 7: - disco = colors::red_v; - break; - case 8: - disco = colors::blu_v; - break; - case 9: - disco = colors::red_u; - break; - case 10: - disco = colors::blu_u; - break; - case 0: - case 1: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - case 18: - case 19: - float color1 = rand() % 256; - float color2 = rand() % 256; - float color3 = rand() % 256; - disco = { color1, color2, color3, 255.0f }; - } - } - return disco; - } - if (ent->m_IDX <= MAX_PLAYERS && ent->m_IDX >= 0) - { - if (data[entity->entindex()] != colors::empty) - { - auto toret = data[entity->entindex()]; - data[entity->entindex()] = colors::empty; - return toret; - } - } - if (CE_BAD(ent)) - return colors::white; - if (re::C_BaseCombatWeapon::IsBaseCombatWeapon(entity)) - { - IClientEntity *owner = re::C_TFWeaponBase::GetOwnerViaInterface(entity); - if (owner) - { - return ChamsColor(owner); - } - } - switch (ent->m_Type()) - { - case ENTITY_BUILDING: - if (!ent->m_bEnemy() && !(teammates || teammate_buildings) && ent != LOCAL_E) - { - return colors::empty; - } - if (health) - { - return colors::Health_dimgreen(ent->m_iHealth(), ent->m_iMaxHealth()); - } - break; - case ENTITY_PLAYER: - if (!players) - return colors::empty; - if (health) - { - return colors::Health_dimgreen(ent->m_iHealth(), ent->m_iMaxHealth()); - } - break; - default: - break; - } - return colors::EntityF(ent); -} - -bool EffectChams::ShouldRenderChams(IClientEntity *entity) -{ -#if ENFORCE_STREAM_SAFETY - return false; -#endif - if (!isHackActive() || !*effect_chams::enable || CE_BAD(LOCAL_E)) - return false; - if (entity->entindex() < 0) - return false; - CachedEntity *ent = ENTITY(entity->entindex()); - if (!chamsself && ent->m_IDX == LOCAL_E->m_IDX) - return false; - switch (ent->m_Type()) - { - case ENTITY_BUILDING: - if (!buildings) - return false; - if (!ent->m_bEnemy() && !(teammate_buildings || teammates)) - return false; - if (ent->m_iHealth() == 0 || !ent->m_iHealth()) - return false; - if (CE_BYTE(LOCAL_E, netvar.m_bCarryingObject) && ent->m_IDX == HandleToIDX(CE_INT(LOCAL_E, netvar.m_hCarriedObject))) - return false; - return true; - case ENTITY_PLAYER: - if (!players) - return false; - if (!disguised && IsPlayerDisguised(ent)) - return false; - if (!teammates && !ent->m_bEnemy() && playerlist::IsDefault(ent)) - return false; - if (CE_BYTE(ent, netvar.iLifeState)) - return false; - return true; - break; - case ENTITY_PROJECTILE: - if (!ent->m_bEnemy()) - return false; - if (stickies && ent->m_iClassID() == CL_CLASS(CTFGrenadePipebombProjectile)) - { - return true; - } - break; - case ENTITY_GENERIC: - switch (ent->m_ItemType()) - { - case ITEM_HEALTH_LARGE: - case ITEM_HEALTH_MEDIUM: - case ITEM_HEALTH_SMALL: - return *medkits; - case ITEM_AMMO_LARGE: - case ITEM_AMMO_MEDIUM: - case ITEM_AMMO_SMALL: - return *ammobox; - default: - break; - } - break; - default: - break; - } - return false; -} - -void EffectChams::RenderChamsRecursive(IClientEntity *entity) -{ -#if !ENFORCE_STREAM_SAFETY - if (!isHackActive() || !*effect_chams::enable) - return; - entity->DrawModel(1); - - if (!*recursive) - return; - - IClientEntity *attach; - int passes = 0; - - attach = g_IEntityList->GetClientEntity(*(int *) ((uintptr_t) entity + netvar.m_Collision - 24) & 0xFFF); - while (attach && passes++ < 32) - { - if (attach->ShouldDraw()) - { - if (entity->GetClientClass()->m_ClassID == RCC_PLAYER && re::C_BaseCombatWeapon::IsBaseCombatWeapon(attach)) - { - if (weapons_white) - { - rgba_t mod_original; - g_IVRenderView->GetColorModulation(mod_original.rgba); - g_IVRenderView->SetColorModulation(colors::white); - attach->DrawModel(1); - g_IVRenderView->SetColorModulation(mod_original.rgba); - } - else - { - attach->DrawModel(1); - } - } - else - attach->DrawModel(1); - } - attach = g_IEntityList->GetClientEntity(*(int *) ((uintptr_t) attach + netvar.m_Collision - 20) & 0xFFF); - } -#endif -} - -void EffectChams::RenderChams(IClientEntity *entity) -{ -#if !ENFORCE_STREAM_SAFETY - if (!isHackActive() || !*effect_chams::enable) - return; - CMatRenderContextPtr ptr(GET_RENDER_CONTEXT); - if (ShouldRenderChams(entity)) - { - rgba_t color = ChamsColor(entity); - rgba_t color_2 = color * 0.6f; - if (!legit) - { - mat_unlit_z->AlphaModulate(1.0f); - ptr->DepthRange(0.0f, 0.01f); - g_IVRenderView->SetColorModulation(color_2); - g_IVModelRender->ForcedMaterialOverride(flat ? mat_unlit_z : mat_lit_z); - RenderChamsRecursive(entity); - } - - if (legit || !singlepass) - { - mat_unlit->AlphaModulate(1.0f); - g_IVRenderView->SetColorModulation(color); - ptr->DepthRange(0.0f, 1.0f); - g_IVModelRender->ForcedMaterialOverride(flat ? mat_unlit : mat_lit); - RenderChamsRecursive(entity); - } - } -#endif -} -void EffectChams::Render(int x, int y, int w, int h) -{ -#if !ENFORCE_STREAM_SAFETY - PROF_SECTION(DRAW_chams); - if (!isHackActive() || disable_visuals) - return; - if (!effect_chams::enable && !(hacks::tf2::backtrack::chams && hacks::tf2::backtrack::isBacktrackEnabled)) - return; - if (g_Settings.bInvalid) - return; - if (!init && effect_chams::enable) - Init(); - if (!isHackActive() || (g_IEngine->IsTakingScreenshot() && clean_screenshots)) - return; - if (hacks::tf2::backtrack::chams && hacks::tf2::backtrack::isBacktrackEnabled) - { - CMatRenderContextPtr ptr(GET_RENDER_CONTEXT); - BeginRenderChams(); - // Don't mark as normal chams drawing - drawing = false; - for (int i = 1; i <= g_IEngine->GetMaxClients(); i++) - { - CachedEntity *ent = ENTITY(i); - if (CE_BAD(ent) || i == g_IEngine->GetLocalPlayer() || !ent->m_bAlivePlayer() || ent->m_Type() != ENTITY_PLAYER) - continue; - // Entity won't draw in some cases so help the chams a bit - hacks::tf2::backtrack::isDrawing = true; - RAW_ENT(ent)->DrawModel(1); - hacks::tf2::backtrack::isDrawing = false; - } - EndRenderChams(); - } - if (!effect_chams::enable) - return; - CMatRenderContextPtr ptr(GET_RENDER_CONTEXT); - BeginRenderChams(); - for (int i = 1; i <= HIGHEST_ENTITY; i++) - { - IClientEntity *entity = g_IEntityList->GetClientEntity(i); - if (!entity || entity->IsDormant() || CE_BAD(ENTITY(i))) - continue; - RenderChams(entity); - } - EndRenderChams(); -#endif -} -EffectChams g_EffectChams; -CScreenSpaceEffectRegistration *g_pEffectChams = nullptr; - -static InitRoutine init([]() { - EC::Register( - EC::LevelShutdown, []() { g_EffectChams.Shutdown(); }, "chams"); - if (g_ppScreenSpaceRegistrationHead && g_pScreenSpaceEffects) - { - effect_chams::g_pEffectChams = new CScreenSpaceEffectRegistration("_cathook_chams", &effect_chams::g_EffectChams); - g_pScreenSpaceEffects->EnableScreenSpaceEffect("_cathook_chams"); - } -}); -} // namespace effect_chams diff --git a/src/visual/EffectGlow.cpp b/src/visual/EffectGlow.cpp index ffbb16b1..6fb7bbb2 100644 --- a/src/visual/EffectGlow.cpp +++ b/src/visual/EffectGlow.cpp @@ -230,7 +230,7 @@ rgba_t EffectGlow::GlowColor(IClientEntity *entity) if (CE_BAD(ent)) return colors::white; if (ent == hacks::shared::aimbot::CurrentTarget()) - return colors::pink; + return colors::target; if (re::C_BaseCombatWeapon::IsBaseCombatWeapon(entity)) { owner = re::C_TFWeaponBase::GetOwnerViaInterface(entity); diff --git a/src/visual/colors.cpp b/src/visual/colors.cpp index e1d2cd03..6ba7d4f9 100644 --- a/src/visual/colors.cpp +++ b/src/visual/colors.cpp @@ -8,6 +8,44 @@ #include #include "common.hpp" +namespace colors +{ +settings::Rgba col_red{ "colors.team-red", "ed2a2aff" }; +settings::Rgba col_blu{ "colors.team-blu", "1c6cedff" }; +settings::Rgba col_red_b{ "colors.team-red.background", "402020ff" }; +settings::Rgba col_blu_b{ "colors.team-blu.background", "202040ff" }; +settings::Rgba col_red_v{ "colors.team-red.vaccinator", "c4666cff" }; +settings::Rgba col_blu_v{ "colors.team-blu.vaccinator", "66b6c4ff" }; +settings::Rgba col_red_u{ "colors.team-red.ubercharge", "ff6600ff" }; +settings::Rgba col_blu_u{ "colors.team-blu.ubercharge", "003399ff" }; +settings::Rgba col_guicolor{ "colors.guicolor", "ffffffff" }; +settings::Rgba col_target{ "colors.target", "00ff00ff" }; + +rgba_t red = *col_red; +rgba_t blu = *col_blu; +rgba_t red_b = *col_red_b; +rgba_t blu_b = *col_blu_b; +rgba_t red_v = *col_red_v; +rgba_t blu_v = *col_blu_v; +rgba_t red_u = *col_red_u; +rgba_t blu_u = *col_blu_u; +rgba_t gui = *col_guicolor; +rgba_t target = *col_target; + +static InitRoutine init([]() { + col_red.installChangeCallback([](settings::VariableBase &var, rgba_t after) { red = after; }); + col_blu.installChangeCallback([](settings::VariableBase &var, rgba_t after) { blu = after; }); + col_red_b.installChangeCallback([](settings::VariableBase &var, rgba_t after) { red_b = after; }); + col_blu_b.installChangeCallback([](settings::VariableBase &var, rgba_t after) { blu_b = after; }); + col_red_v.installChangeCallback([](settings::VariableBase &var, rgba_t after) { red_v = after; }); + col_blu_v.installChangeCallback([](settings::VariableBase &var, rgba_t after) { blu_v = after; }); + col_red_u.installChangeCallback([](settings::VariableBase &var, rgba_t after) { red_u = after; }); + col_blu_u.installChangeCallback([](settings::VariableBase &var, rgba_t after) { blu_u = after; }); + col_guicolor.installChangeCallback([](settings::VariableBase &var, rgba_t after) { gui = after; }); + col_target.installChangeCallback([](settings::VariableBase &var, rgba_t after) { target = after; }); +}); +} + rgba_t colors::EntityF(CachedEntity *ent) { rgba_t result, plclr; diff --git a/src/visual/drawmgr.cpp b/src/visual/drawmgr.cpp index 01f619b6..28154b62 100644 --- a/src/visual/drawmgr.cpp +++ b/src/visual/drawmgr.cpp @@ -85,11 +85,11 @@ void DrawCheatVisuals() if (!info_text_min) { AddSideString(hack::GetVersion(), - GUIColor()); // github commit and date - AddSideString(hack::GetType(), GUIColor()); // Compile type + colors::gui); // github commit and date + AddSideString(hack::GetType(), colors::gui); // Compile type #if ENABLE_GUI - AddSideString("Press '" + open_gui_button.toString() + "' key to open/close cheat menu.", GUIColor()); - AddSideString("Use mouse to navigate in menu.", GUIColor()); + AddSideString("Press '" + open_gui_button.toString() + "' key to open/close cheat menu.", colors::gui); + AddSideString("Use mouse to navigate in menu.", colors::gui); #endif } }