Created
January 1, 2015 20:45
-
-
Save AltimorTASDK/7916872a3b4c478532ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Lag compensation has a bug where animation cycletime is off by two ticks, | |
* which makes it difficult to hit people jumping or transitioning to a duck. | |
* Altimor has taken a break from his Persona 3 toaster waifu to correct this | |
* catastrophe. APPLAUSE | |
*/ | |
#include "util.h" | |
#include "plugin.h" | |
#include "lagcomp.h" | |
#include "baseanimating.h" | |
#include <stdexcept> | |
#include <cstdint> | |
#include <Windows.h> | |
#include <detours.h> | |
// Returns in xmm0 | |
using SequenceDuration_t = __m128(__thiscall*)( | |
const CBaseAnimating *base_animating, | |
const void *studiohdr, | |
const int sequence); | |
// CBaseAnimating::SequenceDuration | |
static SequenceDuration_t SequenceDuration; | |
/** | |
* SequenceDuration_wrap - Make SequenceDuration usable from C++ code | |
* @base_animating: Pointer to the CBaseAnimating | |
* @sequence: Sequence number | |
* | |
* Return a 32 bit float instead of a 128 bit xmm register | |
*/ | |
static float SequenceDuration_wrap( | |
const CBaseAnimating *base_animating, | |
const int sequence) | |
{ | |
const auto *studiohdr = *(void**)((uintptr_t)(base_animating) + 0x490); | |
const auto xmm0 = SequenceDuration(base_animating, studiohdr, sequence); | |
float result; | |
_mm_store_ss(&result, xmm0); | |
return result; | |
} | |
ConVar cycle_offset("sv_lagcomp_anim_offset", "2"); | |
using UpdateLagRecords_t = void(__stdcall*)( | |
const CBaseAnimating *player, | |
CUtlFixedLinkedList<LagRecord> *track, | |
const int a3); | |
static UpdateLagRecords_t orig_UpdateLagRecords; | |
/** | |
* hook_UpdateLagRecords - Hook for CLagCompensationManager::UpdateLagRecords | |
* @player: Pointer to player to be updated | |
* @track: Pointer to list of LagRecords | |
* @a3: Never used in the original function, great job Valve | |
* | |
* Advance the master cycle and layer cycles by the desired number of ticks | |
*/ | |
static void __stdcall hook_UpdateLagRecords( | |
const CBaseAnimating *player, | |
CUtlFixedLinkedList<LagRecord> *track, | |
const int a3) | |
{ | |
orig_UpdateLagRecords(player, track, a3); | |
const auto apply_fix = [player](float *cycle, const int sequence) | |
{ | |
const auto duration = SequenceDuration_wrap(player, sequence); | |
*cycle += cycle_offset.GetFloat() / duration / 64.f; | |
}; | |
auto &record = track->Element(track->Head()); | |
apply_fix(&record.m_masterCycle, record.m_masterSequence); | |
for(auto &layer : record.m_layerRecords) | |
apply_fix(&layer.m_cycle, layer.m_sequence); | |
} | |
/** | |
* plugin::Load - Valve plugin load method override | |
* @interfaceFactory: engine.dll factory | |
* @gameServerFactory: server.dll factory | |
* | |
* Grab offsets and detour the function where anim cycletime is saved | |
*/ | |
bool plugin::Load( | |
CreateInterfaceFn interfaceFactory, | |
CreateInterfaceFn gameServerFactory) | |
{ | |
ConnectTier1Libraries(&interfaceFactory, 1); | |
ConnectTier2Libraries(&interfaceFactory, 1); | |
ConVar_Register(0); | |
uintptr_t start, end; | |
get_module_bounds("server.dll", &start, &end); | |
// Scan for CLagCompensationManager::UpdateLagRecords | |
uintptr_t UpdateLagRecords; | |
try { | |
const auto *UpdateLagRecords_sig = "\x53\x56\x57\x81\xF9"; | |
const auto *UpdateLagRecords_mask = "xxxxx"; | |
UpdateLagRecords = sigscan( | |
start, | |
end, | |
UpdateLagRecords_sig, | |
UpdateLagRecords_mask) - 0xF; | |
const auto *SequenceDuration_sig = "\x85\xF6\x75\x2F\x8B\x47\x5C"; | |
const auto *SequenceDuration_mask = "xxxxxxx"; | |
SequenceDuration = (SequenceDuration_t)(sigscan( | |
start, | |
end, | |
SequenceDuration_sig, | |
SequenceDuration_mask) - 0xA); | |
} catch(...) { | |
Error("Sigscans failed!\n"); | |
return false; | |
} | |
orig_UpdateLagRecords = (UpdateLagRecords_t)(DetourFunction( | |
(byte*)(UpdateLagRecords), | |
(byte*)(hook_UpdateLagRecords))); | |
return true; | |
} | |
/** | |
* plugin::Unload - Valve plugin unload method override | |
* | |
* Unregister the ICVar and disconnect libraries | |
*/ | |
void plugin::Unload() | |
{ | |
ConVar_Unregister(); | |
DisconnectTier2Libraries(); | |
DisconnectTier1Libraries(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment