From 308bf4c8300c501c4ffac7090f3d3f766556bdf6 Mon Sep 17 00:00:00 2001 From: BenCat07 Date: Mon, 1 Jun 2020 14:55:32 +0200 Subject: [PATCH 1/2] Fix issues with no-lerp in entitycache after feedback Hosters report this to not work as expected, which is sad but oh well --- include/reclasses/C_BaseAnimating.hpp | 1 + src/entityhitboxcache.cpp | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/include/reclasses/C_BaseAnimating.hpp b/include/reclasses/C_BaseAnimating.hpp index 85ce97c8..591eeb69 100644 --- a/include/reclasses/C_BaseAnimating.hpp +++ b/include/reclasses/C_BaseAnimating.hpp @@ -17,6 +17,7 @@ public: static InvalidateBoneCache_t InvalidateBoneCache = InvalidateBoneCache_t(addr); InvalidateBoneCache(self); } + // Currently unused, might be useful in the near future though inline static bool Interpolate(IClientEntity *self, float time) { typedef bool (*fn_t)(IClientEntity *, float); diff --git a/src/entityhitboxcache.cpp b/src/entityhitboxcache.cpp index e1dd16fb..d1025445 100644 --- a/src/entityhitboxcache.cpp +++ b/src/entityhitboxcache.cpp @@ -129,12 +129,7 @@ matrix3x4_t *EntityHitboxCache::GetBones(int numbones) { // Reset game cache if (!bonecache_enabled && CE_GOOD(parent_ref)) - { re::C_BaseAnimating::InvalidateBoneCache(RAW_ENT(parent_ref)); - // Only use when nolerp is on as this breaks game visuals a tad - if (nolerp) - re::C_BaseAnimating::Interpolate(RAW_ENT(parent_ref), bones_setup_time); - } // If numbones is not set, get it from some terrible and unnamed variable if (numbones == -1) From 93780dc2a77ccbcaba97653a36316a74150dfd04 Mon Sep 17 00:00:00 2001 From: BenCat07 Date: Mon, 1 Jun 2020 14:59:20 +0200 Subject: [PATCH 2/2] Sync Player Animations properly Doing the job of the tf2 devs once again. This only works if the entity is in view as it changes animations, and bases on simtime. --- include/core/netvars.hpp | 1 + src/core/netvars.cpp | 1 + src/hooks/CMakeLists.txt | 1 + src/hooks/PlayerAnimFix.cpp | 57 +++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 src/hooks/PlayerAnimFix.cpp diff --git a/include/core/netvars.hpp b/include/core/netvars.hpp index dfcf1ac0..f5b8e37e 100644 --- a/include/core/netvars.hpp +++ b/include/core/netvars.hpp @@ -177,6 +177,7 @@ public: offset_t m_angEyeAnglesLocal; offset_t m_nSequence; offset_t m_flSimulationTime; + offset_t m_flAnimTime; offset_t m_angRotation; offset_t m_hOwnerEntity; diff --git a/src/core/netvars.cpp b/src/core/netvars.cpp index 0b8caf47..db81ebfc 100644 --- a/src/core/netvars.cpp +++ b/src/core/netvars.cpp @@ -29,6 +29,7 @@ void NetVars::Init() this->m_iClip2 = gNetvars.get_offset("DT_BaseCombatWeapon", "LocalWeaponData", "m_iClip2"); this->m_Collision = gNetvars.get_offset("DT_BaseEntity", "m_Collision"); this->m_flSimulationTime = gNetvars.get_offset("DT_BaseEntity", "m_flSimulationTime"); + this->m_flAnimTime = gNetvars.get_offset("DT_BaseEntity", "AnimTimeMustBeFirst", "m_flAnimTime"); this->m_angRotation = gNetvars.get_offset("DT_BaseEntity", "m_angRotation"); IF_GAME(IsTF2()) diff --git a/src/hooks/CMakeLists.txt b/src/hooks/CMakeLists.txt index b860f238..4f441b3d 100755 --- a/src/hooks/CMakeLists.txt +++ b/src/hooks/CMakeLists.txt @@ -10,6 +10,7 @@ set(files "${CMAKE_CURRENT_LIST_DIR}/CanPacket.cpp" "${CMAKE_CURRENT_LIST_DIR}/nographics.cpp" "${CMAKE_CURRENT_LIST_DIR}/others.cpp" "${CMAKE_CURRENT_LIST_DIR}/Paint.cpp" + "${CMAKE_CURRENT_LIST_DIR}/PlayerAnimFix.cpp" "${CMAKE_CURRENT_LIST_DIR}/PreDataUpdate.cpp" "${CMAKE_CURRENT_LIST_DIR}/RandomInt.cpp" "${CMAKE_CURRENT_LIST_DIR}/RunCommand.cpp" diff --git a/src/hooks/PlayerAnimFix.cpp b/src/hooks/PlayerAnimFix.cpp new file mode 100644 index 00000000..1d7c8b7e --- /dev/null +++ b/src/hooks/PlayerAnimFix.cpp @@ -0,0 +1,57 @@ +#include "common.hpp" +#include "DetourHook.hpp" + +namespace hacks::tf2::animfix +{ +DetourHook frameadvance_detour{}; +typedef float (*FrameAdvance_t)(IClientEntity *, float); + +std::vector previous_simtimes; + +// Credits to Blackfire62 for telling me how this could be realized +float FrameAdvance_hook(IClientEntity *self, float flInterval) +{ + float newInterval = flInterval; + + // Check if the entity is valid + if (self && IDX_GOOD(self->entindex()) && self->entindex() > 0 && self->entindex() <= (int) previous_simtimes.size()) + { + // Check if they are an alive player + CachedEntity *ent = ENTITY(self->entindex()); + // Set new interval based on their simtime + if (CE_GOOD(ent) && ent->m_Type() == ENTITY_PLAYER && ent->m_bAlivePlayer()) + { + float simtime = CE_FLOAT(ent, netvar.m_flSimulationTime); + // Calculate the time we need to animate by + float time_difference = simtime - previous_simtimes.at(ent->m_IDX - 1); + if (time_difference > 0.0f) + newInterval = time_difference; + previous_simtimes.at(ent->m_IDX - 1) = simtime; + // If the simtime didn't update we need to make sure that the original function also does not update + if (newInterval == 0.0f) + CE_FLOAT(ent, netvar.m_flAnimTime) = g_GlobalVars->curtime; + } + } + + FrameAdvance_t original = (FrameAdvance_t) frameadvance_detour.GetOriginalFunc(); + float return_value = original(self, newInterval); + frameadvance_detour.RestorePatch(); + return return_value; +} + +void LevelInit() +{ + previous_simtimes.clear(); + previous_simtimes.resize(g_IEngine->GetMaxClients()); +} + +static InitRoutine init([]() { + static auto FrameAdvance_signature = gSignatures.GetClientSignature("55 89 E5 57 56 53 83 EC 4C 8B 5D ? 80 BB ? ? ? ? 00 0F 85 ? ? ? ? 8B B3"); + frameadvance_detour.Init(FrameAdvance_signature, (void *) FrameAdvance_hook); + EC::Register(EC::LevelInit, LevelInit, "levelinit_animfix"); + LevelInit(); + + EC::Register( + EC::Shutdown, []() { frameadvance_detour.Shutdown(); }, "shutdown_animfix"); +}); +} // namespace hacks::tf2::animfix