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.
This commit is contained in:
BenCat07 2020-06-01 14:59:20 +02:00
parent 308bf4c830
commit 93780dc2a7
4 changed files with 60 additions and 0 deletions

View File

@ -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;

View File

@ -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())

View File

@ -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"

View File

@ -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<float> 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