Skip to content

Commit

Permalink
New Anti Latency System
Browse files Browse the repository at this point in the history
  • Loading branch information
sjrc6 committed Mar 28, 2022
1 parent 2564724 commit e0a8430
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 60 deletions.
1 change: 1 addition & 0 deletions src/engine/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ class IClient : public IInterface
virtual IFriends *Foes() = 0;

virtual void GetSmoothTick(int *pSmoothTick, float *pSmoothIntraTick, float MixAmount) = 0;
virtual void GetSmoothFreezeTick(int *pSmoothTick, float *pSmoothIntraTick, float MixAmount) = 0;

virtual SWarning *GetCurWarning() = 0;
virtual CChecksumData *ChecksumData() = 0;
Expand Down
28 changes: 19 additions & 9 deletions src/engine/client/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2099,7 +2099,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
m_GameTime[Conn].Update(&m_GametimeMarginGraph, (GameTick - 1) * time_freq() / 50, TimeLeft, 0);
}

if((m_ReceivedSnapshots[Conn] > 50 || (g_Config.m_ClRunOnJoinConsole && m_ReceivedSnapshots[Conn] > 2)) && !m_CodeRunAfterJoin[Conn])
if((m_ReceivedSnapshots[Conn] > g_Config.m_ClRunOnJoinDelay || (g_Config.m_ClRunOnJoinConsole && m_ReceivedSnapshots[Conn] > g_Config.m_ClRunOnJoinDelay)) && !m_CodeRunAfterJoin[Conn])
{
if(m_ServerCapabilities.m_ChatTimeoutCode || ShouldSendChatTimeoutCodeHeuristic())
{
Expand All @@ -2109,8 +2109,8 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
}
else
{
CNetMsg_Cl_Say Msg;
Msg.m_Team = 0;
CNetMsg_Cl_Say MsgP;
MsgP.m_Team = 0;
char aBuf[256];
if(g_Config.m_ClRunOnJoin[0])
{
Expand All @@ -2120,10 +2120,10 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
{
str_format(aBuf, sizeof(aBuf), "/timeout %s", m_aTimeoutCodes[Conn]);
}
Msg.m_pMessage = aBuf;
CMsgPacker Packer(Msg.MsgID(), false);
Msg.Pack(&Packer);
SendMsg(Conn, &Packer, MSGFLAG_VITAL);
MsgP.m_pMessage = aBuf;
CMsgPacker PackerTimeout(MsgP.MsgID(), false);
MsgP.Pack(&PackerTimeout);
SendMsg(Conn, &PackerTimeout, MSGFLAG_VITAL);
}
}
m_CodeRunAfterJoin[Conn] = true;
Expand Down Expand Up @@ -4564,7 +4564,17 @@ void CClient::GetSmoothTick(int *pSmoothTick, float *pSmoothIntraTick, float Mix
*pSmoothTick = (int)(SmoothTime * 50 / time_freq()) + 1;
*pSmoothIntraTick = (SmoothTime - (*pSmoothTick - 1) * time_freq() / 50) / (float)(time_freq() / 50);
}
void CClient::GetSmoothFreezeTick(int *pSmoothTick, float *pSmoothIntraTick, float MixAmount)
{
int64_t GameTime = m_GameTime[g_Config.m_ClDummy].Get(time_get());
int64_t PredTime = m_PredictedTime.Get(time_get());
int64_t UpperPredTime = clamp(PredTime - (time_freq() / 50) * g_Config.m_ClUnfreezeLagTicks, GameTime, PredTime);
int64_t LowestPredTime = clamp(PredTime, GameTime, UpperPredTime);
int64_t SmoothTime = clamp(LowestPredTime + (int64_t)(MixAmount * (PredTime - LowestPredTime)), LowestPredTime, PredTime);

*pSmoothTick = (int)(SmoothTime * 50 / time_freq()) + 1;
*pSmoothIntraTick = (SmoothTime - (*pSmoothTick - 1) * time_freq() / 50) / (float)(time_freq() / 50);
}
SWarning *CClient::GetCurWarning()
{
if(m_Warnings.empty())
Expand Down Expand Up @@ -4592,8 +4602,8 @@ int CClient::PredictionMargin() const
if(g_Config.m_ClAmIFrozen && g_Config.m_ClUnfreezeDelayHelper && m_CurGameTick[g_Config.m_ClDummy] - g_Config.m_ClFreezeTick > 17)
{
//min macro is broken on linux, manually typing it instead.
if(g_Config.m_ClWhatsMyPing * g_Config.m_ClUnfreezeHelperPercent / 100 < g_Config.m_ClUnfreezeHelperLimit)
return -g_Config.m_ClWhatsMyPing * g_Config.m_ClUnfreezeHelperPercent / 100;
if(g_Config.m_ClWhatsMyPing < g_Config.m_ClUnfreezeHelperLimit)
return -g_Config.m_ClWhatsMyPing;
else
return -g_Config.m_ClUnfreezeHelperLimit;
}
Expand Down
1 change: 1 addition & 0 deletions src/engine/client/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
virtual IFriends *Foes() { return &m_Foes; }

virtual void GetSmoothTick(int *pSmoothTick, float *pSmoothIntraTick, float MixAmount);
virtual void GetSmoothFreezeTick(int *pSmoothTick, float *pSmoothIntraTick, float MixAmount);

virtual SWarning *GetCurWarning();
virtual CChecksumData *ChecksumData() { return &m_Checksum.m_Data; }
Expand Down
131 changes: 92 additions & 39 deletions src/game/client/components/menus_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2562,11 +2562,10 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)

CUIRect Column, Section;

MainView.HSplitTop(10.0f, 0x0, &MainView);
//MainView.HSplitTop(10.0f, 0x0, &MainView);

const float LineMargin = 20.0f;


MainView.VSplitLeft(MainView.w * 0.5, &MainView, &Column);

MainView.HSplitTop(30.0f, &Section, &MainView);
Expand Down Expand Up @@ -2597,7 +2596,28 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
UI()->DoLabelScaled(&Label, aBuf, 14.0f, TEXTALIGN_LEFT);
g_Config.m_ClFrozenHudTeeSize = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClFrozenHudTeeSize, &Button, (g_Config.m_ClFrozenHudTeeSize - 8) / 19.0f) * 19.0f) + 8;
}
MainView.HSplitTop(30.0f, 0x0, &MainView);

{
CUIRect CheckBoxRect, CheckBoxRect2;
MainView.HSplitTop(LineMargin, &CheckBoxRect, &MainView);
CheckBoxRect.VSplitMid(&CheckBoxRect, &CheckBoxRect2);
if(DoButton_CheckBox(&g_Config.m_ClShowFrozenText, Localize("Tees Left Alive Text"), g_Config.m_ClShowFrozenText >= 1, &CheckBoxRect))
{
g_Config.m_ClShowFrozenText = g_Config.m_ClShowFrozenText >= 1 ? 0 : 1;
}
if(g_Config.m_ClShowFrozenText)
{
static int s_CountFrozenText = 0;
if(DoButton_CheckBox(&s_CountFrozenText, Localize("Count Frozen Tees"), g_Config.m_ClShowFrozenText == 2, &CheckBoxRect2))
{
g_Config.m_ClShowFrozenText = g_Config.m_ClShowFrozenText != 2 ? 2 : 1;
}
}
}



MainView.HSplitTop(10.0f, 0x0, &MainView);

// ***** MISCELLANEOUS ***** //
MainView.VSplitLeft(-5.0f, 0x0, &MainView);
Expand All @@ -2607,58 +2627,39 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
MainView.HSplitTop(5.0f, 0x0, &MainView);

DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClRunOnJoinConsole, ("Run cl_run_on_join as console command"), &g_Config.m_ClRunOnJoinConsole, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClFixKoGSpec, ("Spectator outline fix on KoG (slightly buggy)"), &g_Config.m_ClFixKoGSpec, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClFreezeUpdateFix, ("Update tee skin faster after being frozen (slightly buggy)"), &g_Config.m_ClFreezeUpdateFix, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowCenterLines, ("Show screen center"), &g_Config.m_ClShowCenterLines, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClPingNameCircle, ("Show ping colored circle before names"), &g_Config.m_ClPingNameCircle, &MainView, LineMargin);

if(g_Config.m_ClRunOnJoinConsole)
{
CUIRect Button, Label;
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(150.0f, &Label, &Button);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s: %i ", "Hook Line Width", g_Config.m_ClHookCollSize);
str_format(aBuf, sizeof(aBuf), "%s: %ims", "Delay", g_Config.m_ClRunOnJoinDelay * 20);
UI()->DoLabelScaled(&Label, aBuf, 14.0f, TEXTALIGN_LEFT);
g_Config.m_ClHookCollSize = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClHookCollSize, &Button, g_Config.m_ClHookCollSize / 20.0f) * 20.0f);
int Delay = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClRunOnJoinDelay, &Button, (g_Config.m_ClRunOnJoinDelay - 2) / 98.0f) * 98.0f) + 2;
if(Delay < 100 || g_Config.m_ClRunOnJoinDelay <= 100)
{
g_Config.m_ClRunOnJoinDelay = Delay;
}
}
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClFixKoGSpec, ("Spectator outline fix on KoG (slightly buggy)"), &g_Config.m_ClFixKoGSpec, &MainView, LineMargin);
if(g_Config.m_ClFixKoGSpec)
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClFixKoGSpecNames, ("Show names of spectating players on KoG"), &g_Config.m_ClFixKoGSpecNames, &MainView, LineMargin);

DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClFreezeUpdateFix, ("Update tee skin faster after being frozen (slightly buggy)"), &g_Config.m_ClFreezeUpdateFix, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowCenterLines, ("Show screen center"), &g_Config.m_ClShowCenterLines, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClPingNameCircle, ("Show ping colored circle before names"), &g_Config.m_ClPingNameCircle, &MainView, LineMargin);

MainView.HSplitTop(30.0f, 0x0, &MainView);

// ***** REACT HELPER ***** //

MainView.VSplitLeft(-5.0f, 0x0, &MainView);
MainView.HSplitTop(30.0f, &Section, &MainView);
UI()->DoLabelScaled(&Section, ("[!EXPERIMENTAL!] Unfreeze Reaction Helper"), 20.0f, TEXTALIGN_LEFT);
MainView.VSplitLeft(5.0f, 0x0, &MainView);

MainView.HSplitTop(20.0f, &Section, &MainView);
UI()->DoLabelScaled(&Section, ("Only use on gores maps! This will attempt to remove some"), 14.0f, TEXTALIGN_LEFT);
MainView.HSplitTop(20.0f, &Section, &MainView);
UI()->DoLabelScaled(&Section, ("of the lag when you are getting saved on high ping"), 14.0f, TEXTALIGN_LEFT);

MainView.HSplitTop(5.0f, 0x0, &MainView);

DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClUnfreezeDelayHelper, ("Enable"), &g_Config.m_ClUnfreezeDelayHelper, &MainView, LineMargin);
{
CUIRect Button, Label;
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(215.0f, &Label, &Button);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s: %i ", "Percent of ping", g_Config.m_ClUnfreezeHelperPercent);
UI()->DoLabelScaled(&Label, aBuf, 14.0f, TEXTALIGN_LEFT);
g_Config.m_ClUnfreezeHelperPercent = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClUnfreezeHelperPercent, &Button, (g_Config.m_ClUnfreezeHelperPercent) / 90.0f) * 90.0f);
}
{
CUIRect Button, Label;
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(215.0f, &Label, &Button);
Button.VSplitLeft(150.0f, &Label, &Button);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s: %ims", "Maximum delay fix", g_Config.m_ClUnfreezeHelperLimit);
str_format(aBuf, sizeof(aBuf), "%s: %i ", "Hook Line Width", g_Config.m_ClHookCollSize);
UI()->DoLabelScaled(&Label, aBuf, 14.0f, TEXTALIGN_LEFT);
g_Config.m_ClUnfreezeHelperLimit = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClUnfreezeHelperLimit, &Button, (g_Config.m_ClUnfreezeHelperLimit) / 60.0f) * 60.0f);
g_Config.m_ClHookCollSize = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClHookCollSize, &Button, g_Config.m_ClHookCollSize / 20.0f) * 20.0f);
}

MainView.HSplitTop(10.0f, 0x0, &MainView);

// ***** OUTLINES ***** //

Expand Down Expand Up @@ -2722,8 +2723,60 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
DoLine_ColorPicker(&OutlineColorUnfreezeID, 25.0f, 200.0f, 14.0f, 0.0f, &Section, ("Unfreeze Outline Color"), &g_Config.m_ClOutlineColorUnfreeze, ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f), false);


// ***** ANTI LATENCY ***** //
MainView.HSplitTop(10.0f, 0x0, &MainView);

//MainView.VSplitLeft(-5.0f, 0x0, &MainView);
MainView.HSplitTop(30.0f, &Section, &MainView);
UI()->DoLabelScaled(&Section, ("Anti Latency Tools"), 20.0f, TEXTALIGN_LEFT);
MainView.VSplitLeft(15.0f, 0x0, &MainView);

MainView.HSplitTop(20.0f, &Section, &MainView);
UI()->DoLabelScaled(&Section, ("Only use on gores maps! Can help mitigate latency."), 14.0f, TEXTALIGN_LEFT);

MainView.HSplitTop(5.0f, 0x0, &MainView);
{
CUIRect Button, Label;
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(165.0f, &Label, &Button);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s: %ims", "Prediction Margin", g_Config.m_ClPredictionMargin);
UI()->DoLabelScaled(&Label, aBuf, 14.0f, TEXTALIGN_LEFT);
int PredictionMargin = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClPredictionMargin, &Button, (g_Config.m_ClPredictionMargin - 10) / 15.0f) * 15.0f) + 10;
if((PredictionMargin < 25 || g_Config.m_ClPredictionMargin <= 25) && g_Config.m_ClPredictionMargin >= 10)
{
g_Config.m_ClPredictionMargin = PredictionMargin;
}
}
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClUnfreezeDelayHelper, ("Remove prediction margin in freeze"), &g_Config.m_ClUnfreezeDelayHelper, &MainView, LineMargin);
{
CUIRect Button, Label;
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(220.0f, &Label, &Button);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s: %ims", "Negative margin (may lag)", g_Config.m_ClUnfreezeHelperLimit);
UI()->DoLabelScaled(&Label, aBuf, 14.0f, TEXTALIGN_LEFT);
g_Config.m_ClUnfreezeHelperLimit = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClUnfreezeHelperLimit, &Button, (g_Config.m_ClUnfreezeHelperLimit) / 40.0f) * 40.0f);
}
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClRemoveAnti, ("Remove prediction & antiping in freeze"), &g_Config.m_ClRemoveAnti, &MainView, LineMargin);
{
CUIRect Button, Label;
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(115.0f, &Label, &Button);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s: %ims", "Delay", g_Config.m_ClUnfreezeLagDelayTicks * 20);
UI()->DoLabelScaled(&Label, aBuf, 14.0f, TEXTALIGN_LEFT);
g_Config.m_ClUnfreezeLagDelayTicks = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClUnfreezeLagDelayTicks, &Button, (g_Config.m_ClUnfreezeLagDelayTicks) / 200.0f) * 200.0f);
}
{
CUIRect Button, Label;
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(200.0f, &Label, &Button);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s: %ims", "Amount Removed", g_Config.m_ClUnfreezeLagTicks * 20);
UI()->DoLabelScaled(&Label, aBuf, 14.0f, TEXTALIGN_LEFT);
g_Config.m_ClUnfreezeLagTicks = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClUnfreezeLagTicks, &Button, (g_Config.m_ClUnfreezeLagTicks) / 10.0f) * 10.0f);
}

}

Expand Down
11 changes: 8 additions & 3 deletions src/game/client/components/nameplates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ void CNamePlates::RenderNameplatePos(vec2 Position, const CNetObj_PlayerInfo *pP
{
Graphics()->TextureClear();
Graphics()->QuadsBegin();
ColorRGBA rgb = color_cast<ColorRGBA>(ColorHSLA((300.0f - clamp(m_pClient->m_Snap.m_paPlayerInfos[ClientID]->m_Latency, 0, 300)) / 1000.0f, 1.0f, 0.5f, 0.6f));
ColorRGBA rgb = color_cast<ColorRGBA>(ColorHSLA((300.0f - clamp(m_pClient->m_Snap.m_paPlayerInfos[ClientID]->m_Latency, 0, 300)) / 1000.0f, 1.0f, 0.5f, 0.8f));
Graphics()->SetColor(rgb);
float CircleSize = 7.0f;
RenderTools()->DrawCircle(Position.x - tw / 2.0f - CircleSize, YOffset + FontSize / 2.0f + 1.4f, CircleSize, 24);
Expand Down Expand Up @@ -340,9 +340,14 @@ void CNamePlates::OnRender()
continue;
}

if(m_pClient->m_aClients[i].m_SpecCharPresent)
if(m_pClient->m_aClients[i].m_SpecCharPresent || (g_Config.m_ClFixKoGSpec && g_Config.m_ClFixKoGSpecNames && m_pClient->m_aClients[i].m_Team== TEAM_SPECTATORS))
{
RenderNameplatePos(m_pClient->m_aClients[i].m_SpecChar, pInfo, 0.4f, true);
vec2 Pos = m_pClient->m_aClients[i].m_SpecChar;

if(g_Config.m_ClFixKoGSpec && g_Config.m_ClFixKoGSpecNames && m_pClient->m_aClients[i].m_Team == TEAM_SPECTATORS)
Pos = m_pClient->m_aClients[i].m_RenderPos;

RenderNameplatePos(Pos, pInfo, 0.4f, true);
}

// only render active characters
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/components/players.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ void CPlayers::OnRender()
{
m_aRenderInfo[i] = m_pClient->m_aClients[i].m_RenderInfo;
m_aRenderInfo[i].m_ShineDecoration = m_pClient->m_aClients[i].m_LiveFrozen;
if(m_pClient->m_Snap.m_aCharacters[i].m_Cur.m_Weapon == WEAPON_NINJA || (g_Config.m_ClAmIFrozen && g_Config.m_ClFreezeUpdateFix && m_pClient->m_Snap.m_LocalClientID == i) && g_Config.m_ClShowNinja)
if(m_pClient->m_Snap.m_aCharacters[i].m_Cur.m_Weapon == WEAPON_NINJA && g_Config.m_ClShowNinja || (g_Config.m_ClAmIFrozen && g_Config.m_ClFreezeUpdateFix && m_pClient->m_Snap.m_LocalClientID == i && g_Config.m_ClShowNinja))
{
// change the skin for the player to the ninja
int Skin = m_pClient->m_Skins.Find("x_ninja");
Expand Down
33 changes: 30 additions & 3 deletions src/game/client/gameclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1824,8 +1824,6 @@ void CGameClient::OnPredict()
}
}



// detect mispredictions of other players and make corrections smoother when possible
static vec2 s_aLastPos[MAX_CLIENTS] = {{0, 0}};
static bool s_aLastActive[MAX_CLIENTS] = {false};
Expand Down Expand Up @@ -2459,6 +2457,8 @@ void CGameClient::UpdateRenderedCharacters()
vec2(m_aClients[i].m_RenderPrev.m_X, m_aClients[i].m_RenderPrev.m_Y),
vec2(m_aClients[i].m_RenderCur.m_X, m_aClients[i].m_RenderCur.m_Y),
m_aClients[i].m_IsPredicted ? Client()->PredIntraGameTick(g_Config.m_ClDummy) : Client()->IntraGameTick(g_Config.m_ClDummy));
if(g_Config.m_ClRemoveAnti)
Pos = GetFreezePos(i);

if(i == m_Snap.m_LocalClientID)
{
Expand All @@ -2479,7 +2479,6 @@ void CGameClient::UpdateRenderedCharacters()
g_Config.m_ClAmIFrozen = 0;
g_Config.m_ClFreezeTick = Client()->GameTick(g_Config.m_ClDummy);
}

}
else
{
Expand All @@ -2489,6 +2488,8 @@ void CGameClient::UpdateRenderedCharacters()

if(g_Config.m_ClAntiPingSmooth)
Pos = GetSmoothPos(i);
if(g_Config.m_ClRemoveAnti && g_Config.m_ClAmIFrozen)
Pos = GetFreezePos(i);
}
}
m_Snap.m_aCharacters[i].m_Position = Pos;
Expand Down Expand Up @@ -2605,6 +2606,32 @@ vec2 CGameClient::GetSmoothPos(int ClientID)
return Pos;
}

vec2 CGameClient::GetFreezePos(int ClientID)
{
vec2 Pos = mix(m_aClients[ClientID].m_PrevPredicted.m_Pos, m_aClients[ClientID].m_Predicted.m_Pos, Client()->PredIntraGameTick(g_Config.m_ClDummy));
int64_t Now = time_get();
for(int i = 0; i < 2; i++)
{
//int64_t Len = clamp(m_aClients[ClientID].m_SmoothLen[i], (int64_t)1, time_freq());
//int64_t TimePassed = Now - m_aClients[ClientID].m_SmoothStart[i];
float MixAmount = 0.0f;
int SmoothTick;
float SmoothIntra;
int TicksFrozen = Client()->GameTick(g_Config.m_ClDummy) - g_Config.m_ClFreezeTick;
if(g_Config.m_ClAmIFrozen && g_Config.m_ClRemoveAnti)
{
MixAmount = mix(0.0f, 1.0f, 1.0f - (float)std::min(TicksFrozen, g_Config.m_ClUnfreezeLagDelayTicks) / (float)g_Config.m_ClUnfreezeLagDelayTicks);
}
else
{
MixAmount = 1.0f;
}
Client()->GetSmoothFreezeTick(&SmoothTick, &SmoothIntra, MixAmount);
if(SmoothTick > 0 && m_aClients[ClientID].m_PredTick[(SmoothTick - 1) % 200] >= Client()->PrevGameTick(g_Config.m_ClDummy) && m_aClients[ClientID].m_PredTick[SmoothTick % 200] <= Client()->PredGameTick(g_Config.m_ClDummy))
Pos[i] = mix(m_aClients[ClientID].m_PredPos[(SmoothTick - 1) % 200][i], m_aClients[ClientID].m_PredPos[SmoothTick % 200][i], SmoothIntra);
}
return Pos;
}
void CGameClient::Echo(const char *pString)
{
m_Chat.Echo(pString);
Expand Down
1 change: 1 addition & 0 deletions src/game/client/gameclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ class CGameClient : public IGameClient
void UpdateRenderedCharacters();
void DetectStrongHook();
vec2 GetSmoothPos(int ClientID);
vec2 GetFreezePos(int ClientID);

int m_PredictedDummyID;
int m_IsDummySwapping;
Expand Down
17 changes: 16 additions & 1 deletion src/game/client/render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,22 @@ void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote

Graphics()->SetColor(pInfo->m_ColorFeet.r * cs, pInfo->m_ColorFeet.g * cs, pInfo->m_ColorFeet.b * cs, Alpha);

Graphics()->TextureSet(OutLine == 1 ? pSkinTextures->m_FeetOutline : pSkinTextures->m_Feet);
if(g_Config.m_ClWhiteFeet && pInfo->m_CustomColoredSkin)
{
CTeeRenderInfo WhiteFeetInfo;
int Skin = GameClient()->m_Skins.Find("x_ninja");
if(Skin != -1)
{
const CSkin *pSkin = GameClient()->m_Skins.Get(Skin);
WhiteFeetInfo.m_OriginalRenderSkin = pSkin->m_OriginalSkin;
WhiteFeetInfo.m_ColorFeet = ColorRGBA(1, 1, 1);
const CSkin::SSkinTextures *pWhiteFeetTextures = &WhiteFeetInfo.m_OriginalRenderSkin;
Graphics()->TextureSet(OutLine == 1 ? pWhiteFeetTextures->m_FeetOutline : pWhiteFeetTextures->m_Feet);
}
}
else
Graphics()->TextureSet(OutLine == 1 ? pSkinTextures->m_FeetOutline : pSkinTextures->m_Feet);

Graphics()->RenderQuadContainerAsSprite(m_TeeQuadContainerIndex, QuadOffset, Position.x + pFoot->m_X * AnimScale, Position.y + pFoot->m_Y * AnimScale, w / 64.f, h / 32.f);
}
}
Expand Down
Loading

0 comments on commit e0a8430

Please sign in to comment.