From 5c07aa1283bd2ee39327cab15d9ad3cce3dca6c4 Mon Sep 17 00:00:00 2001 From: rei-2 <174158077+rei-2@users.noreply.github.com> Date: Mon, 17 Nov 2025 20:44:10 -0500 Subject: [PATCH] deal with instant respawn damage desync better --- Amalgam/src/Features/CritHack/CritHack.cpp | 19 ++++++++++++++++--- Amalgam/src/Features/CritHack/CritHack.h | 3 ++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Amalgam/src/Features/CritHack/CritHack.cpp b/Amalgam/src/Features/CritHack/CritHack.cpp index 9c31a97e..0efa4aa6 100644 --- a/Amalgam/src/Features/CritHack/CritHack.cpp +++ b/Amalgam/src/Features/CritHack/CritHack.cpp @@ -433,7 +433,10 @@ void CCritHack::Event(IGameEvent* pEvent, uint32_t uHash, CTFPlayer* pLocal) auto pVictim = I::ClientEntityList->GetClientEntity(iVictim)->As(); if (!iHealth) + { iDamage = std::clamp(iDamage, 0, tHistory.m_iNewHealth); + tHistory.m_iSpawnCounter = -1; + } else if (pVictim && (pVictim->m_bFeignDeathReady() || pVictim->InCond(TF_COND_FEIGN_DEATH))) // damage number is spoofed upon sending, correct it { int iOldHealth = (tHistory.m_mHistory.contains(iHealth) ? tHistory.m_mHistory[iHealth].m_iOldHealth : tHistory.m_iNewHealth) % 32768; @@ -514,20 +517,30 @@ void CCritHack::Store() { auto pPlayer = I::ClientEntityList->GetClientEntity(n)->As(); if (pPlayer && pPlayer->IsAlive() && !pPlayer->IsAGhost()) - StoreHealthHistory(pPlayer->entindex(), pPlayer->m_iHealth()); + StoreHealthHistory(n, pPlayer->m_iHealth(), pPlayer); } } -void CCritHack::StoreHealthHistory(int iIndex, int iHealth, bool bDamage) +void CCritHack::StoreHealthHistory(int iIndex, int iHealth, CTFPlayer* pPlayer) { bool bContains = m_mHealthHistory.contains(iIndex); auto& tHistory = m_mHealthHistory[iIndex]; + if (bContains && pPlayer) + { // deal with instant respawn damage desync better + if (pPlayer->IsDormant()) + tHistory.m_iSpawnCounter = -1; + else if (tHistory.m_iSpawnCounter == -1) + tHistory.m_iSpawnCounter = pPlayer->m_iSpawnCounter(); + else if (tHistory.m_iSpawnCounter != pPlayer->m_iSpawnCounter()) + return; // wait for event + } + if (!bContains) tHistory = { iHealth, iHealth }; else if (iHealth != tHistory.m_iNewHealth) { - tHistory.m_iOldHealth = std::max(bDamage && tHistory.m_mHistory.contains(iHealth % 32768) ? tHistory.m_mHistory[iHealth % 32768].m_iOldHealth : tHistory.m_iNewHealth, iHealth); + tHistory.m_iOldHealth = std::max(tHistory.m_iNewHealth, iHealth); tHistory.m_iNewHealth = iHealth; } diff --git a/Amalgam/src/Features/CritHack/CritHack.h b/Amalgam/src/Features/CritHack/CritHack.h index 70403799..9e0f523f 100644 --- a/Amalgam/src/Features/CritHack/CritHack.h +++ b/Amalgam/src/Features/CritHack/CritHack.h @@ -7,6 +7,7 @@ struct HealthHistory_t { int m_iNewHealth = 0; int m_iOldHealth = 0; + int m_iSpawnCounter = -1; struct HealthStorage_t { @@ -29,7 +30,7 @@ private: int GetCritRequest(CUserCmd* pCmd, CTFWeaponBase* pWeapon); void Reset(); - void StoreHealthHistory(int iIndex, int iHealth, bool bDamage = false); + void StoreHealthHistory(int iIndex, int iHealth, CTFPlayer* pPlayer = nullptr); int m_iCritDamage = 0; int m_iRangedDamage = 0;