From 577eaa3d691cd2ef775726a8b3753056435c0ec5 Mon Sep 17 00:00:00 2001 From: Viceroy <97338859+Viceroyy@users.noreply.github.com> Date: Thu, 8 Aug 2024 18:57:31 +0300 Subject: [PATCH] Added particle effect changers, Added WIP Streamer mode --- Fusion/Fusion.vcxproj | 6 + Fusion/Fusion.vcxproj.filters | 6 + .../Aimbot/AimbotHitscan/AimbotHitscan.cpp | 2 + Fusion/src/Features/ImGui/Menu/Menu.cpp | 10 +- Fusion/src/Features/Visuals/ESP/ESP.cpp | 17 ++- .../Visuals/SpectatorList/SpectatorList.cpp | 13 +- .../CAttributeManager_AttribHookValue.cpp | 29 +++++ Fusion/src/Hooks/CBaseHudChat_ChatPrintf.cpp | 23 ++++ ...entScoreBoardDialog_UpdatePlayerAvatar.cpp | 12 ++ Fusion/src/Hooks/CCvar_ConsoleColorPrintf.cpp | 18 +++ Fusion/src/Hooks/CParticleProperty_Create.cpp | 122 ++++++++++++++++++ .../Hooks/C_PlayerResource_GetPlayerName.cpp | 26 ++++ Fusion/src/Hooks/Panel_PaintTraverse.cpp | 18 +++ Fusion/src/Hooks/S_StartSound.cpp | 2 + Fusion/src/Hooks/TF_IsHolidayActive.cpp | 28 ++++ Fusion/src/SDK/SDK.cpp | 22 ++++ Fusion/src/SDK/SDK.h | 2 + Fusion/src/SDK/Vars.h | 9 ++ 18 files changed, 362 insertions(+), 3 deletions(-) create mode 100644 Fusion/src/Hooks/CAttributeManager_AttribHookValue.cpp create mode 100644 Fusion/src/Hooks/CClientScoreBoardDialog_UpdatePlayerAvatar.cpp create mode 100644 Fusion/src/Hooks/CCvar_ConsoleColorPrintf.cpp create mode 100644 Fusion/src/Hooks/CParticleProperty_Create.cpp create mode 100644 Fusion/src/Hooks/C_PlayerResource_GetPlayerName.cpp create mode 100644 Fusion/src/Hooks/Panel_PaintTraverse.cpp create mode 100644 Fusion/src/Hooks/TF_IsHolidayActive.cpp diff --git a/Fusion/Fusion.vcxproj b/Fusion/Fusion.vcxproj index 73fe39d..26a90fc 100644 --- a/Fusion/Fusion.vcxproj +++ b/Fusion/Fusion.vcxproj @@ -272,6 +272,7 @@ + @@ -284,6 +285,8 @@ + + @@ -303,6 +306,7 @@ + @@ -324,6 +328,7 @@ + @@ -341,6 +346,7 @@ + diff --git a/Fusion/Fusion.vcxproj.filters b/Fusion/Fusion.vcxproj.filters index da75840..d0f5a2b 100644 --- a/Fusion/Fusion.vcxproj.filters +++ b/Fusion/Fusion.vcxproj.filters @@ -163,6 +163,12 @@ + + + + + + diff --git a/Fusion/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp b/Fusion/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp index a3c85ea..affbcac 100644 --- a/Fusion/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp +++ b/Fusion/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp @@ -704,10 +704,12 @@ void CAimbotHitscan::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pC switch (nWeaponID) { case TF_WEAPON_MINIGUN: + { pCmd->buttons |= IN_ATTACK2; if (pWeapon->As()->m_iWeaponState() != AC_STATE_FIRING && pWeapon->As()->m_iWeaponState() != AC_STATE_SPINNING) return; break; + } case TF_WEAPON_SNIPERRIFLE: case TF_WEAPON_SNIPERRIFLE_DECAP: { diff --git a/Fusion/src/Features/ImGui/Menu/Menu.cpp b/Fusion/src/Features/ImGui/Menu/Menu.cpp index 05f368c..94d0bbc 100644 --- a/Fusion/src/Features/ImGui/Menu/Menu.cpp +++ b/Fusion/src/Features/ImGui/Menu/Menu.cpp @@ -625,6 +625,7 @@ void CMenu::MenuVisuals() FToggle("Clean screenshots", Vars::Visuals::UI::CleanScreenshots, FToggle_Middle); FToggle("Sniper sightlines", Vars::Visuals::UI::SniperSightlines); FToggle("Pickup timers", Vars::Visuals::UI::PickupTimers, FToggle_Middle); + FToggle("Streamer mode (WIP)", Vars::Visuals::UI::StreamerMode); } EndSection(); if (Section("Viewmodel")) { @@ -667,6 +668,13 @@ void CMenu::MenuVisuals() FToggle("MEDIC: Show injured teammates", Vars::Visuals::Other::ShowInjuredTeammatesWhenMedic); FToggle("Low graphics", Vars::Visuals::Other::ThePS2Inator); } EndSection(); + if (Section("Particles")) + { + FDropdown("Medigun beam", Vars::Visuals::Particle::MedigunBeamEffect, { "Off", "Dispenser heal", "PASS Time", "Bombonomicon spell", "White", "Uber" }, {}, FDropdown_Left); + FDropdown("Medigun charge", Vars::Visuals::Particle::MedigunChargeEffect, { "Off", "Fireball spell", "Spellbound", "Electrocuted", "Cloud 9", "Electrostatic", "Knifestorm", "Frostbite", "Haunted Phantasm Jr.", "Time Warp", "Stormy 13th Hour", "Terror-Watt", "Sunbeams", "Sunbeams new", "Disco beams", "Pumpkin" }, {}, FDropdown_Right); + FDropdown("Rocket trail", Vars::Visuals::Particle::RocketTrailEffect, { "Off", "Crit", "Bubbles", "Halloween", "Airstrike", "Monoculus", "Cow Mangler", "Cow Mangler charged" }, {}, FDropdown_Left); + FToggle("Rainbow footsteps", Vars::Visuals::Particle::RainbowFootstepEffect); + } EndSection(); if (Section("Bullet")) { FColorPicker("Bullet tracer color", Vars::Colors::BulletTracer); @@ -738,7 +746,7 @@ void CMenu::MenuVisuals() } EndSection(); if (Section("World")) { - FSDropdown("World texture", Vars::Visuals::World::WorldTexture, { "Default", "Dev", "Camo", "Black", "White", "Flat" }, FSDropdown_Custom); + FSDropdown("World texture", Vars::Visuals::World::WorldTexture, { "Default", "Dev", "Camo", "Black", "White" }, FSDropdown_Custom); FDropdown("Modulations", Vars::Visuals::World::Modulations, { "World", "Sky", "Prop", "Particle", "Fog" }, {}, FDropdown_Left | FDropdown_Multi); static std::vector skyNames = { "Off", "sky_tf2_04", "sky_upward", "sky_dustbowl_01", "sky_goldrush_01", "sky_granary_01", "sky_well_01", "sky_gravel_01", "sky_badlands_01", diff --git a/Fusion/src/Features/Visuals/ESP/ESP.cpp b/Fusion/src/Features/Visuals/ESP/ESP.cpp index 1d05b5e..e1320eb 100644 --- a/Fusion/src/Features/Visuals/ESP/ESP.cpp +++ b/Fusion/src/Features/Visuals/ESP/ESP.cpp @@ -156,7 +156,22 @@ void CESP::DrawPlayers(CTFPlayer* pLocal) if (Vars::ESP::Player.Value & 1 << 0) { tOffset += fFontName.m_nTall + 2; - H::Draw.String(fFontName, middle, y - tOffset, Vars::Menu::Theme::Active.Value, ALIGN_TOP, SDK::ConvertUtf8ToWide(pi.name).data()); + if (Vars::Visuals::UI::StreamerMode.Value) + { + const char* name; + if (nIndex == I::EngineClient->GetLocalPlayer()) + name = "You"; + else if (H::Entities.IsFriend(nIndex)) + name = "Friend"; + else if (pPlayer->m_iTeamNum() != pLocal->m_iTeamNum()) + name = "Enemy"; + else if (pPlayer->m_iTeamNum() == pLocal->m_iTeamNum()) + name = "Teammate"; + + H::Draw.String(fFontName, middle, y - tOffset, Vars::Menu::Theme::Active.Value, ALIGN_TOP, name); + } + else + H::Draw.String(fFontName, middle, y - tOffset, Vars::Menu::Theme::Active.Value, ALIGN_TOP, SDK::ConvertUtf8ToWide(pi.name).data()); } if (Vars::ESP::Player.Value & 1 << 12) diff --git a/Fusion/src/Features/Visuals/SpectatorList/SpectatorList.cpp b/Fusion/src/Features/Visuals/SpectatorList/SpectatorList.cpp index 0b6d571..1102d54 100644 --- a/Fusion/src/Features/Visuals/SpectatorList/SpectatorList.cpp +++ b/Fusion/src/Features/Visuals/SpectatorList/SpectatorList.cpp @@ -38,8 +38,19 @@ bool CSpectatorList::GetSpectators(CTFPlayer* pLocal) PlayerInfo_t pi{}; if (I::EngineClient->GetPlayerInfo(pPlayer->entindex(), &pi)) { + std::wstring name = SDK::ConvertUtf8ToWide(pi.name); + if (Vars::Visuals::UI::StreamerMode.Value) + { + if (H::Entities.IsFriend(pPlayer->entindex())) + name = L"Friend"; + else if (pPlayer->m_iTeamNum() != pLocal->m_iTeamNum()) + name = L"Enemy"; + else if (pPlayer->m_iTeamNum() == pLocal->m_iTeamNum()) + name = L"Teammate"; + } + Spectators.push_back({ - SDK::ConvertUtf8ToWide(pi.name), szMode, respawnIn, respawnTimeIncreased, H::Entities.IsFriend(pPlayer->entindex()), + name, szMode, respawnIn, respawnTimeIncreased, H::Entities.IsFriend(pPlayer->entindex()), pPlayer->m_iTeamNum(), pPlayer->entindex() }); } diff --git a/Fusion/src/Hooks/CAttributeManager_AttribHookValue.cpp b/Fusion/src/Hooks/CAttributeManager_AttribHookValue.cpp new file mode 100644 index 0000000..a4d2b7d --- /dev/null +++ b/Fusion/src/Hooks/CAttributeManager_AttribHookValue.cpp @@ -0,0 +1,29 @@ +#include "../SDK/SDK.h" + +// Credits to Mad? + +MAKE_SIGNATURE(CAttributeManager_AttribHookValue, "client.dll", "4C 8B DC 49 89 5B ? 49 89 6B ? 49 89 73 ? 57 41 54 41 55 41 56 41 57 48 83 EC ? 48 8B 3D ? ? ? ? 4C 8D 35", 0x0); +MAKE_SIGNATURE(FireEvent_AttribHookValue_Call, "client.dll", "E8 ? ? ? ? 8B F8 83 BE", 0x5); + +MAKE_HOOK(CAttributeManager_AttribHookValue, S::CAttributeManager_AttribHookValue(), int, __fastcall, + int baseVal, const char* str, void* pEnt, void* buffer, bool isGlobalConstStr) +{ + if (!Vars::Visuals::Particle::RainbowFootstepEffect.Value || I::EngineClient->IsTakingScreenshot() && Vars::Visuals::UI::CleanScreenshots.Value) + return CALL_ORIGINAL(baseVal, str, pEnt, buffer, isGlobalConstStr); + + static const auto dwDesired = S::FireEvent_AttribHookValue_Call(); + const auto dwRetAddr = std::uintptr_t(_ReturnAddress()); + + if (dwRetAddr == dwDesired) + { + static constexpr int HashedFootstepType = FNV1A::HashConst("halloween_footstep_type"); + auto Hashed = FNV1A::Hash(str); + if (Hashed == HashedFootstepType) + { + Color_t Color = SDK::Rainbow(); + return std::stoul(std::format("0x{:02X}{:02X}{:02X}", Color.r, Color.g, Color.b), nullptr, 16); + } + } + + return CALL_ORIGINAL(baseVal, str, pEnt, buffer, isGlobalConstStr); +} \ No newline at end of file diff --git a/Fusion/src/Hooks/CBaseHudChat_ChatPrintf.cpp b/Fusion/src/Hooks/CBaseHudChat_ChatPrintf.cpp index b121d62..632ab60 100644 --- a/Fusion/src/Hooks/CBaseHudChat_ChatPrintf.cpp +++ b/Fusion/src/Hooks/CBaseHudChat_ChatPrintf.cpp @@ -2,6 +2,9 @@ #include "../Features/Players/PlayerUtils.h" +std::string ColorRed = { '\x7', 'F', 'F', '3', 'F', '3', 'F' }; +std::string ColorBlue = { '\x7', '9', '9', 'C', 'C', 'F', 'F' }; + MAKE_HOOK(CBaseHudChat_ChatPrintf, U::Memory.GetVFunc(I::ClientModeShared->m_pChatElement, 19), void, __fastcall, void* ecx, int iPlayerIndex, int iFilter, const char* fmt, ...) { @@ -51,5 +54,25 @@ MAKE_HOOK(CBaseHudChat_ChatPrintf, U::Memory.GetVFunc(I::ClientModeShared->m_pCh } } + CTFPlayer* pEntity = I::ClientEntityList->GetClientEntity(iPlayerIndex)->As(); + auto pLocal = H::Entities.GetLocal(); + if (Vars::Visuals::UI::StreamerMode.Value && pEntity && pLocal) + { + std::string changedname; + if (iPlayerIndex == I::EngineClient->GetLocalPlayer()) + changedname = "You"; + else if (H::Entities.IsFriend(iPlayerIndex)) + changedname = "Friend"; + else if (pEntity->m_iTeamNum() != pLocal->m_iTeamNum()) + changedname = "Enemy"; + else if (pEntity->m_iTeamNum() == pLocal->m_iTeamNum()) + changedname = "Teammate"; + + std::string newname = pEntity->IsAlive() ? (changedname + "\x1") : changedname; + std::string finalname = (pEntity->m_iTeamNum() == TF_TEAM_RED ? ColorRed : ColorBlue) + newname; + std::string finalmessage = (pEntity->IsAlive() ? "" : "\x1*DEAD* ") + finalname; + finalMsg = finalMsg.replace(0, finalMsg.find(name) + name.length(), finalmessage.c_str()); + } + CALL_ORIGINAL(ecx, iPlayerIndex, iFilter, "%s", finalMsg.c_str()); } \ No newline at end of file diff --git a/Fusion/src/Hooks/CClientScoreBoardDialog_UpdatePlayerAvatar.cpp b/Fusion/src/Hooks/CClientScoreBoardDialog_UpdatePlayerAvatar.cpp new file mode 100644 index 0000000..d79c0ca --- /dev/null +++ b/Fusion/src/Hooks/CClientScoreBoardDialog_UpdatePlayerAvatar.cpp @@ -0,0 +1,12 @@ +#include "../SDK/SDK.h" + +MAKE_SIGNATURE(CClientScoreBoardDialog_UpdatePlayerAvatar, "client.dll", "4D 85 C0 0F 84 ? ? ? ? 53 55", 0x0); + +MAKE_HOOK(CClientScoreBoardDialog_UpdatePlayerAvatar, S::CClientScoreBoardDialog_UpdatePlayerAvatar(), void, __fastcall, + void* ecx, int playerIndex, KeyValues* kv) +{ + if (Vars::Visuals::UI::StreamerMode.Value) + return; // :trollface: + + CALL_ORIGINAL(ecx, playerIndex, kv); +} \ No newline at end of file diff --git a/Fusion/src/Hooks/CCvar_ConsoleColorPrintf.cpp b/Fusion/src/Hooks/CCvar_ConsoleColorPrintf.cpp new file mode 100644 index 0000000..0b0c3f6 --- /dev/null +++ b/Fusion/src/Hooks/CCvar_ConsoleColorPrintf.cpp @@ -0,0 +1,18 @@ +#include "../SDK/SDK.h" + +MAKE_HOOK(CCvar_ConsoleColorPrintf, U::Memory.GetVFunc(I::CVar, 23), void, __fastcall, + void* ecx, const Color_t& clr, const char* pFormat, ...) +{ + va_list marker; + char buffer[4096]; + va_start(marker, pFormat); + vsnprintf_s(buffer, sizeof(buffer), pFormat, marker); + va_end(marker); + + char* msg = buffer; + if (!*msg) { return; } + + std::string Message = msg; + + return CALL_ORIGINAL(ecx, clr, "%s", Message.c_str()); +} \ No newline at end of file diff --git a/Fusion/src/Hooks/CParticleProperty_Create.cpp b/Fusion/src/Hooks/CParticleProperty_Create.cpp new file mode 100644 index 0000000..53cc896 --- /dev/null +++ b/Fusion/src/Hooks/CParticleProperty_Create.cpp @@ -0,0 +1,122 @@ +#include "../SDK/SDK.h" + +// Credits to Mad? for the idea and medigun particle changer +// Credits to yaya for the x86 sigs, rocket trail particle changer and the whole code :trollface: + +MAKE_SIGNATURE(CParticleProperty_Create, "client.dll", "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC ? 48 8B 59 ? 49 8B F1", 0x0); + +MAKE_SIGNATURE(UpdateEffectsCall1, "client.dll", "E8 ? ? ? ? 49 8B CC F3 0F 11 74 24", 0x5); +MAKE_SIGNATURE(UpdateEffectsCall2, "client.dll", "E8 ? ? ? ? 41 8B 14 24 48 8B D8", 0x5); +MAKE_SIGNATURE(ManageChargeEffectCall, "client.dll", "E8 ? ? ? ? 48 89 86 ? ? ? ? 48 89 BE", 0x5); +MAKE_SIGNATURE(Rockettrail_UnderwaterCall, "client.dll", "E8 ? ? ? ? 48 8B 5C 24 ? 40 38 B7", 0x5); + +MAKE_HOOK(CParticleProperty_Create, S::CParticleProperty_Create(), int, __fastcall, + void* ecx, const char* pszParticleName, ParticleAttachment_t iAttachType, const char* pszAttachmentName) +{ + if (I::EngineClient->IsTakingScreenshot() && Vars::Visuals::UI::CleanScreenshots.Value) + return CALL_ORIGINAL(ecx, pszParticleName, iAttachType, pszAttachmentName); + + if (auto pLocal = H::Entities.GetLocal()) + { + static auto UpdateEffectsCall1 = S::UpdateEffectsCall1(); + static auto UpdateEffectsCall2 = S::UpdateEffectsCall2(); + static auto ManageChargeEffectCall = S::ManageChargeEffectCall(); + static auto Rockettrail_UnderwaterCall = S::Rockettrail_UnderwaterCall(); + + const auto dwRetAddr = std::uintptr_t(_ReturnAddress()); + + if (dwRetAddr == UpdateEffectsCall1 || dwRetAddr == UpdateEffectsCall2) + { + switch (Vars::Visuals::Particle::MedigunBeamEffect.Value) + { + case 0: break; + case 1: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "dispenser_heal_blue" : "dispenser_heal_red"; break; + case 2: pszParticleName = "passtime_beam"; break; + case 3: pszParticleName = "bombonomicon_spell_trail"; break; + case 4: pszParticleName = "medicgun_beam_machinery_stage3"; break; + case 5: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "medicgun_beam_blue_invun" : "medicgun_beam_red_invun"; break; + } + } + + if (dwRetAddr == ManageChargeEffectCall) + { + switch (Vars::Visuals::Particle::MedigunChargeEffect.Value) + { + case 0: break; + case 1: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "spell_fireball_small_trail_blue" : "spell_fireball_small_trail_red"; break; + case 2: pszParticleName = "unusual_spellbook_circle_purple"; break; + case 3: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "electrocuted_blue" : "electrocuted_red"; break; + case 4: pszParticleName = "unusual_hearts_bubbling"; break; + case 5: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "unusual_robot_orbiting_sparks" : "unusual_robot_orbiting_sparks2"; break; + case 6: pszParticleName = "unusual_storm_knives_clouds"; break; + case 7: pszParticleName = "unusual_eotl_frostbite"; break; + case 8: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "unusual_souls_green_parent" : "unusual_souls_purple_parent"; break; + case 9: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "unusual_robot_time_warp" : "unusual_robot_time_warp2"; break; + case 10: pszParticleName = "unusual_storm_spooky"; break; + case 11: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "unusual_zap_green" : "unusual_zap_yellow"; break; + case 12: pszParticleName = "superrare_beams1"; break; + case 13: pszParticleName = "superrare_beams1_newstyle"; break; + case 14: pszParticleName = "utaunt_disco_beams3"; break; + case 15: pszParticleName = "ghost_pumpkin"; break; + } + } + + if (dwRetAddr == Rockettrail_UnderwaterCall) + { + switch (Vars::Visuals::Particle::RocketTrailEffect.Value) + { + case 0: break; + case 1: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "critical_rocket_blue" : "critical_rocket_red"; break; + case 2: pszParticleName = "rockettrail_underwater"; break; + case 3: pszParticleName = "halloween_rockettrail"; break; + case 4: pszParticleName = "rockettrail_airstrike_line"; break; + case 5: pszParticleName = "eyeboss_projectile"; break; + case 6: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "drg_cow_rockettrail_normal_blue" : "drg_cow_rockettrail_normal"; break; + case 7: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "drg_cow_rockettrail_charged_blue" : "drg_cow_rockettrail_charged"; break; + } + } + } + + return CALL_ORIGINAL(ecx, pszParticleName, iAttachType, pszAttachmentName); +} + +MAKE_SIGNATURE(CParticleProperty_Create2, "client.dll", "44 89 4C 24 ? 44 89 44 24 ? 53", 0x0); + +MAKE_SIGNATURE(Rockettrail_AirstrikeCall, "client.dll", "E8 ? ? ? ? 48 8B CF E8 ? ? ? ? 48 8B D8 48 85 C0 0F 84", 0x5); +MAKE_SIGNATURE(Rockettrail_bUsingCustomCall, "client.dll", "E8 ? ? ? ? EB ? 4C 8D 0D ? ? ? ? 41 B8 ? ? ? ? 48 8D 15", 0x5); +MAKE_SIGNATURE(Halloween_RockettrailCall, "client.dll", "E8 ? ? ? ? E9 ? ? ? ? 48 85 DB 0F 85", 0x5); +MAKE_SIGNATURE(CTFProjectile_EnergyBallCall, "client.dll", "E8 ? ? ? ? 48 8B 7C 24 ? 48 89 83", 0x5); + +MAKE_HOOK(CParticleProperty_Create2, S::CParticleProperty_Create2(), int, __fastcall, + void* ecx, const char* pszParticleName, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset) +{ + if (I::EngineClient->IsTakingScreenshot() && Vars::Visuals::UI::CleanScreenshots.Value) + return CALL_ORIGINAL(ecx, pszParticleName, iAttachType, iAttachmentPoint, vecOriginOffset); + + if (auto pLocal = H::Entities.GetLocal()) + { + static auto Rockettrail_AirstrikeCall = S::Rockettrail_AirstrikeCall(); + static auto Rockettrail_bUsingCustomCall = S::Rockettrail_bUsingCustomCall(); + static auto Halloween_RockettrailCall = S::Halloween_RockettrailCall(); + static auto CTFProjectile_EnergyBallCall = S::CTFProjectile_EnergyBallCall(); + + const auto dwRetAddr = std::uintptr_t(_ReturnAddress()); + + if (dwRetAddr == Rockettrail_AirstrikeCall || dwRetAddr == Rockettrail_bUsingCustomCall || dwRetAddr == Halloween_RockettrailCall || dwRetAddr == CTFProjectile_EnergyBallCall) + { + switch (Vars::Visuals::Particle::RocketTrailEffect.Value) + { + case 0: break; + case 1: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "critical_rocket_blue" : "critical_rocket_red"; break; + case 2: pszParticleName = "rockettrail_underwater"; break; + case 3: pszParticleName = "halloween_rockettrail"; break; + case 4: pszParticleName = "rockettrail_airstrike_line"; break; + case 5: pszParticleName = "eyeboss_projectile"; break; + case 6: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "drg_cow_rockettrail_normal_blue" : "drg_cow_rockettrail_normal"; break; + case 7: pszParticleName = pLocal->m_iTeamNum() == TF_TEAM_BLUE ? "drg_cow_rockettrail_charged_blue" : "drg_cow_rockettrail_charged"; break; + } + } + } + + return CALL_ORIGINAL(ecx, pszParticleName, iAttachType, iAttachmentPoint, vecOriginOffset); +} \ No newline at end of file diff --git a/Fusion/src/Hooks/C_PlayerResource_GetPlayerName.cpp b/Fusion/src/Hooks/C_PlayerResource_GetPlayerName.cpp new file mode 100644 index 0000000..9574cbb --- /dev/null +++ b/Fusion/src/Hooks/C_PlayerResource_GetPlayerName.cpp @@ -0,0 +1,26 @@ +#include "../SDK/SDK.h" + +MAKE_SIGNATURE(C_PlayerResource_GetPlayerName, "client.dll", "48 89 5C 24 ? 56 48 83 EC ? 48 63 F2", 0x0); + +MAKE_HOOK(C_PlayerResource_GetPlayerName, S::C_PlayerResource_GetPlayerName(), const char*, __fastcall, + void* ecx, int iIndex) +{ + if (!Vars::Visuals::UI::StreamerMode.Value) + return CALL_ORIGINAL(ecx, iIndex); + + CTFPlayer* pEntity = I::ClientEntityList->GetClientEntity(iIndex)->As(); + auto pLocal = H::Entities.GetLocal(); + if (!pEntity || !pLocal) + return CALL_ORIGINAL(ecx, iIndex); + + if (iIndex == I::EngineClient->GetLocalPlayer()) + return "You"; + else if (H::Entities.IsFriend(iIndex)) + return "Friend"; + else if (pEntity->m_iTeamNum() != pLocal->m_iTeamNum()) + return "Enemy"; + else if (pEntity->m_iTeamNum() == pLocal->m_iTeamNum()) + return "Teammate"; + + return CALL_ORIGINAL(ecx, iIndex); +} \ No newline at end of file diff --git a/Fusion/src/Hooks/Panel_PaintTraverse.cpp b/Fusion/src/Hooks/Panel_PaintTraverse.cpp new file mode 100644 index 0000000..790f192 --- /dev/null +++ b/Fusion/src/Hooks/Panel_PaintTraverse.cpp @@ -0,0 +1,18 @@ +// this crashes, why? +#include "../SDK/SDK.h" + +MAKE_HOOK(Panel_PaintTraverse, U::Memory.GetVFunc(I::VGuiPanel, 41), void, __fastcall, + void* ecx, unsigned int VGuiPanel, bool forceRepaint, bool allowForce) +{ + /*const auto PanelName = I::VGuiPanel->GetName(VGuiPanel); + + constexpr auto SteamFriendsList = FNV1A::HashConst("SteamFriendsList"); + constexpr auto RankPanel = FNV1A::HashConst("RankPanel"); + constexpr auto avatar = FNV1A::HashConst("avatar");*/ + + if (I::VGuiPanel->GetName(VGuiPanel) == "SteamFriendsList" || I::VGuiPanel->GetName(VGuiPanel) == "RankPanel" || I::VGuiPanel->GetName(VGuiPanel) == "avatar") + return; + + SDK::Output("PaintTraverse", I::VGuiPanel->GetName(VGuiPanel)); + CALL_ORIGINAL(ecx, VGuiPanel, forceRepaint, allowForce); +} \ No newline at end of file diff --git a/Fusion/src/Hooks/S_StartSound.cpp b/Fusion/src/Hooks/S_StartSound.cpp index 500860e..00aa54d 100644 --- a/Fusion/src/Hooks/S_StartSound.cpp +++ b/Fusion/src/Hooks/S_StartSound.cpp @@ -1,5 +1,7 @@ #include "../SDK/SDK.h" +// Credits to yaya for the sig and general help + MAKE_SIGNATURE(S_StartSound, "engine.dll", "40 53 48 83 EC ? 48 83 79 ? ? 48 8B D9 75 ? 33 C0", 0x0); const static std::vector NOISEMAKER_SOUNDS{ "items\\halloween", "items\\football_manager", "items\\japan_fundraiser", "items\\samurai", "items\\summer", "misc\\happy_birthday_tf", "misc\\jingle_bells" }; diff --git a/Fusion/src/Hooks/TF_IsHolidayActive.cpp b/Fusion/src/Hooks/TF_IsHolidayActive.cpp new file mode 100644 index 0000000..f8037ea --- /dev/null +++ b/Fusion/src/Hooks/TF_IsHolidayActive.cpp @@ -0,0 +1,28 @@ +#include "../SDK/SDK.h" + +// Credits to Myzarfin + +enum EHoliday +{ + kHoliday_None = 0, // must stay at zero for backwards compatibility + kHoliday_TFBirthday, + kHoliday_Halloween, + kHoliday_Christmas, + kHoliday_CommunityUpdate, + kHoliday_EOTL, + kHoliday_Valentines, + kHoliday_MeetThePyro, + kHoliday_FullMoon, + kHoliday_HalloweenOrFullMoon, + kHoliday_HalloweenOrFullMoonOrValentines, + kHoliday_AprilFools, + kHolidayCount, +}; + +MAKE_SIGNATURE(TF_IsHolidayActive, "client.dll", "48 83 EC ? 48 8B 05 ? ? ? ? 44 8B C9", 0x0); + +MAKE_HOOK(TF_IsHolidayActive, S::TF_IsHolidayActive(), bool, __fastcall, + int eHoliday) +{ + return eHoliday == kHoliday_HalloweenOrFullMoon ? true : CALL_ORIGINAL(eHoliday); +} \ No newline at end of file diff --git a/Fusion/src/SDK/SDK.cpp b/Fusion/src/SDK/SDK.cpp index 3be927f..b5aba36 100644 --- a/Fusion/src/SDK/SDK.cpp +++ b/Fusion/src/SDK/SDK.cpp @@ -14,6 +14,28 @@ BOOL CALLBACK TeamFortressWindow(HWND hwnd, LPARAM lParam) return TRUE; } +Color_t SDK::Rainbow() +{ + float t = TICKS_TO_TIME(I::GlobalVars->tickcount); + + int r = static_cast(std::round(std::cos(I::GlobalVars->realtime + t + 0.0f) * 127.5f + 127.5f)); + int g = static_cast(std::round(std::cos(I::GlobalVars->realtime + t + 2.0f) * 127.5f + 127.5f)); + int b = static_cast(std::round(std::cos(I::GlobalVars->realtime + t + 4.0f) * 127.5f + 127.5f)); + + return Color_t{ static_cast(r), static_cast(g), static_cast(b), 255 }; +} + +Color_t SDK::RainbowTickOffset(int nTick) +{ + float t = TICKS_TO_TIME(nTick); + + int r = static_cast(std::lround(std::cos((I::GlobalVars->realtime * 2.0f) + t + 0.0f) * 127.5f + 127.5f)); + int g = static_cast(std::lround(std::cos((I::GlobalVars->realtime * 2.0f) + t + 2.0f) * 127.5f + 127.5f)); + int b = static_cast(std::lround(std::cos((I::GlobalVars->realtime * 2.0f) + t + 4.0f) * 127.5f + 127.5f)); + + return Color_t{ static_cast(r), static_cast(g), static_cast(b), 255 }; +} + Color_t SDK::WarningColor() { return I::GlobalVars->tickcount % 63 < 32 ? Color_t(250, 170, 10, 255) : Color_t(252, 92, 101, 255); diff --git a/Fusion/src/SDK/SDK.h b/Fusion/src/SDK/SDK.h index e3baf7a..ddf746a 100644 --- a/Fusion/src/SDK/SDK.h +++ b/Fusion/src/SDK/SDK.h @@ -107,6 +107,8 @@ enum DataCenter_t // i'm not sure all of these are actually used for tf2 servers namespace SDK { + Color_t Rainbow(); + Color_t RainbowTickOffset(int nTick); Color_t WarningColor(); void Output(const char* cFunction, const char* cLog, Color_t cColor = { 255, 255, 255, 255 }, bool bConsole = true, bool bChat = false, bool bDebug = false); diff --git a/Fusion/src/SDK/Vars.h b/Fusion/src/SDK/Vars.h index 937517a..a01bdae 100644 --- a/Fusion/src/SDK/Vars.h +++ b/Fusion/src/SDK/Vars.h @@ -415,6 +415,13 @@ namespace Vars CVar(ThePS2Inator, false) SUBNAMESPACE_END(Yes) + SUBNAMESPACE_BEGIN(Particle) + CVar(MedigunBeamEffect, 0, VISUAL) + CVar(MedigunChargeEffect, 0, VISUAL) + CVar(RocketTrailEffect, 0, VISUAL) + CVar(RainbowFootstepEffect, false, VISUAL) + SUBNAMESPACE_END(Particle) + SUBNAMESPACE_BEGIN(Removals) CVar(Scope, false, VISUAL) CVar(Interpolation, false) @@ -440,6 +447,7 @@ namespace Vars CVar(ScoreboardColors, false, VISUAL) CVar(SniperSightlines, false, VISUAL) CVar(PickupTimers, false, VISUAL) + CVar(StreamerMode, false, VISUAL) SUBNAMESPACE_END(Viewmodel) SUBNAMESPACE_BEGIN(Viewmodel) @@ -716,6 +724,7 @@ namespace Vars CVar(PropModulation, Color_t(255, 255, 255, 255), VISUAL) CVar(ParticleModulation, Color_t(255, 255, 255, 255), VISUAL) CVar(FogModulation, Color_t(255, 255, 255, 255), VISUAL) + CVar(FootstepParticle, Color_t(203, 166, 247, 255), VISUAL) CVar(BulletTracer, Color_t(255, 255, 255, 255), VISUAL) CVar(PredictionColor, Color_t(255, 255, 255, 255), VISUAL)