From ae10a58aa452de51220db60a2954e4761538e5a0 Mon Sep 17 00:00:00 2001 From: wootguy Date: Tue, 19 Nov 2024 06:12:44 -0800 Subject: [PATCH] improve lag compensation reduced rewind error (about 20ms -> 10ms average). Blood splashes don't lag behind the monster. --- dlls/monster/CBaseMonster.cpp | 5 ++++- dlls/util/lagcomp.cpp | 37 ++++++++++++++++++++++++----------- dlls/util/lagcomp.h | 3 +++ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/dlls/monster/CBaseMonster.cpp b/dlls/monster/CBaseMonster.cpp index 80338791..03ef18c1 100644 --- a/dlls/monster/CBaseMonster.cpp +++ b/dlls/monster/CBaseMonster.cpp @@ -14,6 +14,7 @@ #include "defaultai.h" #include "CMonsterMaker.h" #include "hlds_hooks.h" +#include "lagcomp.h" #define MONSTER_CUT_CORNER_DIST 8 // 8 means the monster's bounding box is contained without the box of the node in WC @@ -4814,10 +4815,12 @@ void CBaseMonster::TraceAttack(entvars_t* pevAttacker, float flDamage, Vector ve UTIL_Shrapnel(ptr->vecEndPos, ptr->vecPlaneNormal, flDamage, bitsDamageType); } if (bitsDamageType & DMG_BLOOD) { + Vector bloodPos = ptr->vecEndPos + get_lagcomp_offset(entindex()); + // headshots should always show big blood, no matter how little damage was done. // The idea is that blood size should be used primarly as an indicator that you hit the weak point. float bloodSize = ptr->iHitgroup == HITGROUP_HEAD ? V_max(flDamage, 30) : flDamage; - SpawnBlood(ptr->vecEndPos, BloodColor(), bloodSize); + SpawnBlood(bloodPos, BloodColor(), bloodSize); TraceBleed(bloodSize, vecDir, ptr, bitsDamageType); } diff --git a/dlls/util/lagcomp.cpp b/dlls/util/lagcomp.cpp index c606d556..345c4a4b 100644 --- a/dlls/util/lagcomp.cpp +++ b/dlls/util/lagcomp.cpp @@ -21,7 +21,6 @@ struct WorldState { }; struct RewindInfo { - bool wasRewound; bool isCompensated; EntState restoreState; }; @@ -40,6 +39,18 @@ cvar_t* sv_unlag = NULL; int g_pingHistoryIdx = 0; float g_pingHistory[PING_SMOOTHING_COUNT][32]; +int g_currentRewindIdx = 0; + +Vector get_lagcomp_offset(int entindex) { + RewindInfo& info = g_rewinds[entindex]; + + if (info.isCompensated) { + return info.restoreState.origin - g_worldHistory[g_currentRewindIdx].ents[entindex].origin; + } + + return g_vecZero; +} + void update_player_pings() { for (int i = 1; i <= gpGlobals->maxClients; i++) { CBaseEntity* plr = UTIL_PlayerByIndex(i); @@ -137,18 +148,22 @@ void lagcomp_begin(CBasePlayer* plr) { bool foundState = false; float now = g_engfuncs.pfnTime(); float targetTime = now - ping; + float bestDelta = FLT_MAX; for (int i = 0; i < g_historyWritten; i++) { + float delta = fabs(g_worldHistory[i].time - targetTime); - if (g_worldHistory[idx].time <= targetTime) { + if (delta < bestDelta) { + bestDelta = delta; foundState = true; - break; - } - else if (--idx < 0) { - idx = MAX_UNLAG_STATES - 1; + idx = i; } } + g_currentRewindIdx = idx; + + //ALERT(at_console, "best delta %.3f, comp %.2f ago\n", bestDelta, now - targetTime); + if (!foundState) { ALERT(at_console, "Can't rewind for %.2fs ping.\n", ping); return; @@ -177,11 +192,11 @@ void lagcomp_begin(CBasePlayer* plr) { restoreState.sequence = vars.sequence; restoreState.frame = vars.frame; - EntState& entState = worldState.ents[i]; - vars.sequence = entState.sequence; - vars.frame = entState.frame; - vars.angles = entState.angles; - UTIL_SetOrigin(&vars, entState.origin); + EntState& rewindState = worldState.ents[i]; + vars.sequence = rewindState.sequence; + vars.frame = rewindState.frame; + vars.angles = rewindState.angles; + UTIL_SetOrigin(&vars, rewindState.origin); } g_didRewind = true; diff --git a/dlls/util/lagcomp.h b/dlls/util/lagcomp.h index 3d6b821f..9186812e 100644 --- a/dlls/util/lagcomp.h +++ b/dlls/util/lagcomp.h @@ -10,3 +10,6 @@ void lagcomp_begin(CBasePlayer* plr); // must be called after lagcomp_begin to restore the current world state after a rewind void lagcomp_end(); + +// returns difference between lag compensated position and server's position +Vector get_lagcomp_offset(int entindex); \ No newline at end of file