From f6f3894f632fb9d8a8209b1fb816d121fe34ffe1 Mon Sep 17 00:00:00 2001 From: rei-2 <174158077+rei-2@users.noreply.github.com> Date: Thu, 5 Feb 2026 02:16:28 -0500 Subject: [PATCH] spectated, zoomed, and aimed binds --- Amalgam/src/Features/Binds/Binds.cpp | 53 ++++++++++++++++++ Amalgam/src/Features/Binds/Binds.h | 3 +- Amalgam/src/Features/ImGui/Menu/Components.h | 3 +- Amalgam/src/Features/ImGui/Menu/Menu.cpp | 56 +++++++++++++++++++- 4 files changed, 111 insertions(+), 4 deletions(-) diff --git a/Amalgam/src/Features/Binds/Binds.cpp b/Amalgam/src/Features/Binds/Binds.cpp index 8b652d38..9c67d488 100644 --- a/Amalgam/src/Features/Binds/Binds.cpp +++ b/Amalgam/src/Features/Binds/Binds.cpp @@ -120,6 +120,59 @@ static inline void GetBinds(int iParent, CTFPlayer* pLocal, CTFWeaponBase* pWeap tBind.m_bActive = !tBind.m_bActive; break; } + case BindEnum::Misc: + { + switch (tBind.m_iInfo) + { + case BindEnum::MiscEnum::Spectated: + case BindEnum::MiscEnum::SpectatedFirst: + case BindEnum::MiscEnum::SpectatedThird: + { + bool bFirst = false, bThird = false; + if (auto pResource = H::Entities.GetResource()) + { + int iLocal = I::EngineClient->GetLocalPlayer(); + for (int n = 1; n <= I::EngineClient->GetMaxClients(); n++) + { + auto pPlayer = I::ClientEntityList->GetClientEntity(n)->As(); + + if (iLocal == n || pResource->IsFakePlayer(n) + || !pPlayer || !pPlayer->IsPlayer() || pPlayer->IsAlive() || pPlayer->IsDormant() + || pResource->m_iTeam(iLocal) != pResource->m_iTeam(n)) + continue; + + int iObserverTarget = pPlayer->m_hObserverTarget().GetEntryIndex(); + int iObserverMode = pPlayer->m_iObserverMode(); + if (iObserverTarget != iLocal) + continue; + + switch (iObserverMode) + { + case OBS_MODE_FIRSTPERSON: bFirst = true; break; + case OBS_MODE_THIRDPERSON: bThird = true; break; + } + } + } + + switch (tBind.m_iInfo) + { + case BindEnum::MiscEnum::Spectated: tBind.m_bActive = bFirst || bThird; break; + case BindEnum::MiscEnum::SpectatedFirst: tBind.m_bActive = bFirst; break; + case BindEnum::MiscEnum::SpectatedThird: tBind.m_bActive = bThird; break; + } + break; + } + case BindEnum::MiscEnum::Zoomed: + tBind.m_bActive = pLocal ? pLocal->InCond(TF_COND_ZOOMED) : false; + break; + case BindEnum::MiscEnum::Aiming: + tBind.m_bActive = pLocal ? pLocal->InCond(TF_COND_AIMING) : false; + break; + } + if (tBind.m_bNot) + tBind.m_bActive = !tBind.m_bActive; + break; + } } } diff --git a/Amalgam/src/Features/Binds/Binds.h b/Amalgam/src/Features/Binds/Binds.h index f5bff74a..d1bd3dcc 100644 --- a/Amalgam/src/Features/Binds/Binds.h +++ b/Amalgam/src/Features/Binds/Binds.h @@ -1,13 +1,14 @@ #pragma once #include "../../SDK/SDK.h" -Enum(Bind, Key, Class, WeaponType, ItemSlot) +Enum(Bind, Key, Class, WeaponType, ItemSlot, Misc) namespace BindEnum { Enum(Key, Hold, Toggle, DoubleClick) Enum(Class, Scout, Soldier, Pyro, Demoman, Heavy, Engineer, Medic, Sniper, Spy) Enum(WeaponType, Hitscan, Projectile, Melee, Throwable) //Enum(ItemType, First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth) + Enum(Misc, Spectated, SpectatedFirst, SpectatedThird, Zoomed, Aiming) } Enum(BindVisibility, Always, WhileActive, Hidden) diff --git a/Amalgam/src/Features/ImGui/Menu/Components.h b/Amalgam/src/Features/ImGui/Menu/Components.h index a51bf217..0a5505da 100644 --- a/Amalgam/src/Features/ImGui/Menu/Components.h +++ b/Amalgam/src/Features/ImGui/Menu/Components.h @@ -2535,7 +2535,7 @@ namespace ImGui SetCursorPos(vOriginalPos); } - FDropdown("Type", &tBind.m_iType, { "Key", "Class", "Weapon type", "Item slot" }, {}, FDropdownEnum::Left, 0, "None", &bHovered); + FDropdown("Type", &tBind.m_iType, { "Key", "Class", "Weapon type", "Item slot", "Misc" }, {}, FDropdownEnum::Left, 0, "None", &bHovered); bLastHovered = bLastHovered || bHovered; switch (tBind.m_iType) { @@ -2543,6 +2543,7 @@ namespace ImGui case BindEnum::Class: tBind.m_iInfo = std::clamp(tBind.m_iInfo, 0, 8); FDropdown("Class", &tBind.m_iInfo, { "Scout", "Soldier", "Pyro", "Demoman", "Heavy", "Engineer", "Medic", "Sniper", "Spy" }, {}, FDropdownEnum::Right, 0, "None", &bHovered); break; case BindEnum::WeaponType: tBind.m_iInfo = std::clamp(tBind.m_iInfo, 0, 3); FDropdown("Weapon type", &tBind.m_iInfo, { "Hitscan", "Projectile", "Melee", "Throwable" }, {}, FDropdownEnum::Right, 0, "None", &bHovered); break; case BindEnum::ItemSlot: tBind.m_iInfo = std::max(tBind.m_iInfo, 0); FDropdown("Item slot", &tBind.m_iInfo, { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, {}, FDropdownEnum::Right, 0, "None", &bHovered); break; + case BindEnum::Misc: tBind.m_iInfo = std::max(tBind.m_iInfo, 0, 4); FDropdown("Misc", &tBind.m_iInfo, { "Spectated", "Spectated 1st", "Spectated 3rd", "##Divider", "Zoomed", "Aiming" }, {}, FDropdownEnum::Right); break; } bLastHovered = bLastHovered || bHovered; diff --git a/Amalgam/src/Features/ImGui/Menu/Menu.cpp b/Amalgam/src/Features/ImGui/Menu/Menu.cpp index fb8e0765..e9830fec 100644 --- a/Amalgam/src/Features/ImGui/Menu/Menu.cpp +++ b/Amalgam/src/Features/ImGui/Menu/Menu.cpp @@ -2543,13 +2543,14 @@ void CMenu::MenuSettings(int iTab) if (FButton(std::format("Parent: {}", sParent).c_str(), FButtonEnum::Right | FButtonEnum::SameLine | FButtonEnum::NoUpper, { 0, 40 })) bParent = 2; } - FDropdown("Type", &tBind.m_iType, { "Key", "Class", "Weapon type", "Item slot" }, {}, FDropdownEnum::Left); + FDropdown("Type", &tBind.m_iType, { "Key", "Class", "Weapon type", "Item slot", "Misc" }, {}, FDropdownEnum::Left); switch (tBind.m_iType) { case BindEnum::Key: tBind.m_iInfo = std::clamp(tBind.m_iInfo, 0, 2); FDropdown("Behavior", &tBind.m_iInfo, { "Hold", "Toggle", "Double click" }, {}, FDropdownEnum::Right); break; case BindEnum::Class: tBind.m_iInfo = std::clamp(tBind.m_iInfo, 0, 8); FDropdown("Class", &tBind.m_iInfo, { "Scout", "Soldier", "Pyro", "Demoman", "Heavy", "Engineer", "Medic", "Sniper", "Spy" }, {}, FDropdownEnum::Right); break; case BindEnum::WeaponType: tBind.m_iInfo = std::clamp(tBind.m_iInfo, 0, 3); FDropdown("Weapon type", &tBind.m_iInfo, { "Hitscan", "Projectile", "Melee", "Throwable" }, {}, FDropdownEnum::Right); break; case BindEnum::ItemSlot: tBind.m_iInfo = std::max(tBind.m_iInfo, 0); FDropdown("Item slot", &tBind.m_iInfo, { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, {}, FDropdownEnum::Right); break; + case BindEnum::Misc: tBind.m_iInfo = std::max(tBind.m_iInfo, 0); FDropdown("Misc", &tBind.m_iInfo, { "Spectated", "Spectated 1st", "Spectated 3rd", "##Divider", "Zoomed", "Aiming" }, {}, FDropdownEnum::Right); break; } } EndChild(); @@ -2693,6 +2694,31 @@ void CMenu::MenuSettings(int iTab) sType = "slot"; sInfo = std::format("{}", _tBind.m_iInfo + 1); break; + case BindEnum::Misc: + switch (_tBind.m_iInfo) + { + case BindEnum::MiscEnum::Spectated: + case BindEnum::MiscEnum::SpectatedFirst: + case BindEnum::MiscEnum::SpectatedThird: + sType = "spectated"; + switch (_tBind.m_iInfo) + { + case BindEnum::MiscEnum::Spectated: { sInfo = "any"; break; } + case BindEnum::MiscEnum::SpectatedFirst: { sInfo = "1st"; break; } + case BindEnum::MiscEnum::SpectatedThird: { sInfo = "3rd"; break; } + } + break; + case BindEnum::MiscEnum::Zoomed: + case BindEnum::MiscEnum::Aiming: + sType = "cond"; + switch (_tBind.m_iInfo) + { + case BindEnum::MiscEnum::Zoomed: { sInfo = "zoomed"; break; } + case BindEnum::MiscEnum::Aiming: { sInfo = "aiming"; break; } + } + break; + } + break; } if (_tBind.m_bNot && (_tBind.m_iType != BindEnum::Key || _tBind.m_iInfo == BindEnum::KeyEnum::Hold)) sType = std::format("not {}", sType); @@ -2814,13 +2840,14 @@ void CMenu::MenuSettings(int iTab) _tBind.m_sName = sInput; } - FDropdown("Type", &_tBind.m_iType, { "Key", "Class", "Weapon type", "Item slot" }, {}, FDropdownEnum::Left); + FDropdown("Type", &_tBind.m_iType, { "Key", "Class", "Weapon type", "Item slot", "Misc" }, {}, FDropdownEnum::Left); switch (_tBind.m_iType) { case BindEnum::Key: _tBind.m_iInfo = std::clamp(_tBind.m_iInfo, 0, 2); FDropdown("Behavior", &_tBind.m_iInfo, { "Hold", "Toggle", "Double click" }, {}, FDropdownEnum::Right); break; case BindEnum::Class: _tBind.m_iInfo = std::clamp(_tBind.m_iInfo, 0, 8); FDropdown("Class", &_tBind.m_iInfo, { "Scout", "Soldier", "Pyro", "Demoman", "Heavy", "Engineer", "Medic", "Sniper", "Spy" }, {}, FDropdownEnum::Right); break; case BindEnum::WeaponType: _tBind.m_iInfo = std::clamp(_tBind.m_iInfo, 0, 3); FDropdown("Weapon type", &_tBind.m_iInfo, { "Hitscan", "Projectile", "Melee", "Throwable" }, {}, FDropdownEnum::Right); break; case BindEnum::ItemSlot: _tBind.m_iInfo = std::max(_tBind.m_iInfo, 0); FDropdown("Item slot", &_tBind.m_iInfo, { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, {}, FDropdownEnum::Right); break; + case BindEnum::Misc: _tBind.m_iInfo = std::max(_tBind.m_iInfo, 0); FDropdown("Misc", &_tBind.m_iInfo, { "Spectated", "Spectated 1st", "Spectated 3rd", "##Divider", "Zoomed", "Aiming" }, {}, FDropdownEnum::Right); break; } if (_tBind.m_iType == BindEnum::Key) FKeybind("Key", _tBind.m_iKey); @@ -3567,6 +3594,31 @@ void CMenu::DrawBinds() sType = "slot"; sInfo = std::format("{}", tBind.m_iInfo + 1); break; + case BindEnum::Misc: + switch (tBind.m_iInfo) + { + case BindEnum::MiscEnum::Spectated: + case BindEnum::MiscEnum::SpectatedFirst: + case BindEnum::MiscEnum::SpectatedThird: + sType = "spectated"; + switch (tBind.m_iInfo) + { + case BindEnum::MiscEnum::Spectated: { sInfo = "any"; break; } + case BindEnum::MiscEnum::SpectatedFirst: { sInfo = "1st"; break; } + case BindEnum::MiscEnum::SpectatedThird: { sInfo = "3rd"; break; } + } + break; + case BindEnum::MiscEnum::Zoomed: + case BindEnum::MiscEnum::Aiming: + sType = "cond"; + switch (tBind.m_iInfo) + { + case BindEnum::MiscEnum::Zoomed: { sInfo = "zoomed"; break; } + case BindEnum::MiscEnum::Aiming: { sInfo = "aiming"; break; } + } + break; + } + break; } if (tBind.m_bNot && (tBind.m_iType != BindEnum::Key || tBind.m_iInfo == BindEnum::KeyEnum::Hold)) sInfo = std::format("not {}", sInfo);