From daa311cd7f423a2303740a7373a4ace11e5c0628 Mon Sep 17 00:00:00 2001 From: JSaurusRex Date: Wed, 6 Dec 2023 17:32:06 +0100 Subject: [PATCH] ghosts support added (not fully tested) --- src/game/client/components/ghost.cpp | 39 +++++++++++++++++++++++++--- src/game/client/components/ghost.h | 4 ++- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/game/client/components/ghost.cpp b/src/game/client/components/ghost.cpp index d15fa52a22b..c790108e72e 100644 --- a/src/game/client/components/ghost.cpp +++ b/src/game/client/components/ghost.cpp @@ -153,6 +153,7 @@ void CGhost::AddInfos(const CNetObj_Character *pChar, const CNetObj_DDNetCharact GhostRecorder()->Start(m_aTmpFilename, Client()->GetCurrentMap(), Client()->GetCurrentMapSha256(), m_CurGhost.m_aPlayer); GhostRecorder()->WriteData(GHOSTDATA_TYPE_START_TICK, &m_CurGhost.m_StartTick, sizeof(int)); + GhostRecorder()->WriteData(GHOSTDATA_TYPE_TICKRATE, &m_CurGhost.m_Tickrate, sizeof(int)); GhostRecorder()->WriteData(GHOSTDATA_TYPE_SKIN, &m_CurGhost.m_Skin, sizeof(CGhostSkin)); for(int i = 0; i < NumTicks; i++) GhostRecorder()->WriteData(GHOSTDATA_TYPE_CHARACTER, m_CurGhost.m_Path.Get(i), sizeof(CGhostCharacter)); @@ -321,8 +322,11 @@ void CGhost::OnRender() { if(Ghost.Empty()) continue; + + float speedDiff = Client()->GameTickSpeed() / (float)Ghost.m_Tickrate; - int GhostTick = Ghost.m_StartTick + PlaybackTick; + int GhostTick = Ghost.m_StartTick + floor(PlaybackTick / speedDiff); + int GhostTickUnscaled = Ghost.m_StartTick*speedDiff + PlaybackTick; while(Ghost.m_PlaybackPos >= 0 && Ghost.m_Path.Get(Ghost.m_PlaybackPos)->m_Tick < GhostTick) { if(Ghost.m_PlaybackPos < Ghost.m_Path.Size() - 1) @@ -346,9 +350,9 @@ void CGhost::OnRender() int TickDiff = Player.m_Tick - Prev.m_Tick; float IntraTick = 0.f; if(TickDiff > 0) - IntraTick = (GhostTick - Prev.m_Tick - 1 + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / TickDiff; + IntraTick = (GhostTickUnscaled - Prev.m_Tick*speedDiff - speedDiff + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / (TickDiff*speedDiff); - Player.m_AttackTick += Client()->GameTick(g_Config.m_ClDummy) - GhostTick; + Player.m_AttackTick += Client()->GameTick(g_Config.m_ClDummy) - GhostTickUnscaled; CTeeRenderInfo *pRenderInfo = &Ghost.m_RenderInfo; CTeeRenderInfo GhostNinjaRenderInfo; @@ -377,6 +381,25 @@ void CGhost::OnRender() } } + //convert positions + if(Ghost.m_Tickrate <= SERVER_TICK_SPEED && Client()->GameTickSpeed() > SERVER_TICK_SPEED) + { + Prev.m_X *= 4; + Prev.m_Y *= 4; + + Player.m_X *= 4; + Player.m_Y *= 4; + } + + if(Ghost.m_Tickrate > SERVER_TICK_SPEED && Client()->GameTickSpeed() <= SERVER_TICK_SPEED) + { + Prev.m_X /= 4; + Prev.m_Y /= 4; + + Player.m_X /= 4; + Player.m_Y /= 4; + } + m_pClient->m_Players.RenderHook(&Prev, &Player, pRenderInfo, -2, IntraTick); m_pClient->m_Players.RenderHookCollLine(&Prev, &Player, -2, IntraTick); m_pClient->m_Players.RenderPlayer(&Prev, &Player, pRenderInfo, -2, IntraTick); @@ -414,6 +437,7 @@ void CGhost::StartRecord(int Tick) m_Recording = true; m_CurGhost.Reset(); m_CurGhost.m_StartTick = Tick; + m_CurGhost.m_Tickrate = Client()->GameTickSpeed(); const CGameClient::CClientData *pData = &m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID]; str_copy(m_CurGhost.m_aPlayer, Client()->PlayerName()); @@ -538,6 +562,11 @@ int CGhost::Load(const char *pFilename) if(!GhostLoader()->ReadData(Type, &pGhost->m_StartTick, sizeof(int))) Error = true; } + else if(Type == GHOSTDATA_TYPE_TICKRATE) + { + if(!GhostLoader()->ReadData(Type, &pGhost->m_Tickrate, sizeof(int))) + Error = true; + } } GhostLoader()->Close(); @@ -562,6 +591,9 @@ int CGhost::Load(const char *pFilename) if(pGhost->m_StartTick == -1) pGhost->m_StartTick = pGhost->m_Path.Get(0)->m_Tick; + if(pGhost->m_Tickrate <= 0) + pGhost->m_Tickrate = SERVER_TICK_SPEED; + if(!FoundSkin) GetGhostSkin(&pGhost->m_Skin, "default", 0, 0, 0); InitRenderInfos(pGhost); @@ -593,6 +625,7 @@ void CGhost::SaveGhost(CMenus::CGhostItem *pItem) GhostRecorder()->Start(pItem->m_aFilename, Client()->GetCurrentMap(), Client()->GetCurrentMapSha256(), pItem->m_aPlayer); GhostRecorder()->WriteData(GHOSTDATA_TYPE_START_TICK, &pGhost->m_StartTick, sizeof(int)); + GhostRecorder()->WriteData(GHOSTDATA_TYPE_TICKRATE, &pGhost->m_Tickrate, sizeof(int)); GhostRecorder()->WriteData(GHOSTDATA_TYPE_SKIN, &pGhost->m_Skin, sizeof(CGhostSkin)); for(int i = 0; i < NumTicks; i++) GhostRecorder()->WriteData(GHOSTDATA_TYPE_CHARACTER, pGhost->m_Path.Get(i), sizeof(CGhostCharacter)); diff --git a/src/game/client/components/ghost.h b/src/game/client/components/ghost.h index 9a6d3867791..f9daf6fc66d 100644 --- a/src/game/client/components/ghost.h +++ b/src/game/client/components/ghost.h @@ -16,7 +16,8 @@ enum GHOSTDATA_TYPE_SKIN = 0, GHOSTDATA_TYPE_CHARACTER_NO_TICK, GHOSTDATA_TYPE_CHARACTER, - GHOSTDATA_TYPE_START_TICK + GHOSTDATA_TYPE_START_TICK, + GHOSTDATA_TYPE_TICKRATE }; struct CGhostSkin @@ -91,6 +92,7 @@ class CGhost : public CComponent CGhostSkin m_Skin; CGhostPath m_Path; int m_StartTick; + int m_Tickrate; char m_aPlayer[MAX_NAME_LENGTH]; int m_PlaybackPos;