Use race timer for ghosts if available

This commit is contained in:
Redix 2017-09-12 22:54:29 +02:00
parent 4c8c546c35
commit 1efa8023ea
5 changed files with 68 additions and 31 deletions

View file

@ -106,20 +106,43 @@ void CGhost::OnRender()
// only for race // only for race
CServerInfo ServerInfo; CServerInfo ServerInfo;
Client()->GetServerInfo(&ServerInfo); Client()->GetServerInfo(&ServerInfo);
if(!IsRace(&ServerInfo) || !g_Config.m_ClRaceGhost || Client()->State() != IClient::STATE_ONLINE) if(!IsRace(&ServerInfo) || !g_Config.m_ClRaceGhost || !m_pClient->m_Snap.m_pGameInfoObj || Client()->State() != IClient::STATE_ONLINE)
return; return;
if(m_pClient->m_Snap.m_pLocalCharacter && m_pClient->m_Snap.m_pLocalPrevCharacter) if(m_pClient->m_Snap.m_pLocalCharacter && m_pClient->m_Snap.m_pLocalPrevCharacter)
{ {
if(m_pClient->m_NewPredictedTick) bool RaceFlag = m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_RACETIME;
int RaceTick = -m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer;
static int s_NewRenderTick = -1;
int RenderTick = s_NewRenderTick;
if(!RaceFlag && m_pClient->m_NewPredictedTick)
{ {
vec2 PrevPos = m_pClient->m_PredictedPrevChar.m_Pos; vec2 PrevPos = m_pClient->m_PredictedPrevChar.m_Pos;
vec2 Pos = m_pClient->m_PredictedChar.m_Pos; vec2 Pos = m_pClient->m_PredictedChar.m_Pos;
if((!m_Rendering || !m_IsSolo) && CRaceHelper::IsStart(m_pClient, PrevPos, Pos)) bool Rendering = m_Rendering || RenderTick != -1;
StartRender(Client()->PredGameTick()); if((!Rendering || m_AllowRestart) && CRaceHelper::IsStart(m_pClient, PrevPos, Pos))
RenderTick = Client()->PredGameTick();
} }
if(m_pClient->m_NewTick) if(m_pClient->m_NewTick)
{
static int s_LastRaceTick = -1;
if(RaceFlag && s_LastRaceTick != RaceTick)
{
if(m_Recording && s_LastRaceTick != -1)
m_AllowRestart = true;
if(GhostRecorder()->IsRecording())
GhostRecorder()->Stop(0, -1);
int StartTick = RaceTick;
if(IsDDRace(&ServerInfo))
StartTick--;
StartRecord(StartTick);
RenderTick = StartTick;
}
else if(!RaceFlag)
{ {
int PrevTick = m_pClient->m_Snap.m_pLocalPrevCharacter->m_Tick; int PrevTick = m_pClient->m_Snap.m_pLocalPrevCharacter->m_Tick;
int CurTick = m_pClient->m_Snap.m_pLocalCharacter->m_Tick; int CurTick = m_pClient->m_Snap.m_pLocalCharacter->m_Tick;
@ -127,7 +150,7 @@ void CGhost::OnRender()
vec2 Pos = vec2(m_pClient->m_Snap.m_pLocalCharacter->m_X, m_pClient->m_Snap.m_pLocalCharacter->m_Y); vec2 Pos = vec2(m_pClient->m_Snap.m_pLocalCharacter->m_X, m_pClient->m_Snap.m_pLocalCharacter->m_Y);
// detecting death, needed because race allows immediate respawning // detecting death, needed because race allows immediate respawning
if((!m_Recording || !m_IsSolo) && m_LastDeathTick < PrevTick) if((!m_Recording || m_AllowRestart) && m_LastDeathTick < PrevTick)
{ {
// estimate the exact start tick // estimate the exact start tick
int RecordTick = -1; int RecordTick = -1;
@ -137,20 +160,34 @@ void CGhost::OnRender()
if(CRaceHelper::IsStart(m_pClient, mix(PrevPos, Pos, (float)i/TickDiff), mix(PrevPos, Pos, (float)(i+1)/TickDiff))) if(CRaceHelper::IsStart(m_pClient, mix(PrevPos, Pos, (float)i/TickDiff), mix(PrevPos, Pos, (float)(i+1)/TickDiff)))
{ {
RecordTick = PrevTick + i + 1; RecordTick = PrevTick + i + 1;
if(m_IsSolo) if(!m_AllowRestart)
break; break;
} }
} }
if(RecordTick != -1) if(RecordTick != -1)
{ {
if(m_Recording) if(GhostRecorder()->IsRecording())
GhostRecorder()->Stop(0, -1); GhostRecorder()->Stop(0, -1);
StartRecord(RecordTick); StartRecord(RecordTick);
} }
} }
}
if(m_Recording) if(m_Recording)
AddInfos(m_pClient->m_Snap.m_pLocalCharacter); AddInfos(m_pClient->m_Snap.m_pLocalCharacter);
s_LastRaceTick = RaceFlag ? RaceTick : -1;
}
if((RaceFlag && m_pClient->m_NewTick) || (!RaceFlag && m_pClient->m_NewPredictedTick))
{
// only restart rendering if it did not change since last tick to prevent stuttering
if(s_NewRenderTick != -1 && s_NewRenderTick == RenderTick)
{
StartRender(RenderTick);
RenderTick = -1;
}
s_NewRenderTick = RenderTick;
} }
} }
@ -492,5 +529,5 @@ void CGhost::OnMapLoad()
OnReset(); OnReset();
UnloadAll(); UnloadAll();
m_pClient->m_pMenus->GhostlistPopulate(); m_pClient->m_pMenus->GhostlistPopulate();
m_IsSolo = true; m_AllowRestart = false;
} }

View file

@ -102,7 +102,7 @@ private:
static void ConGPlay(IConsole::IResult *pResult, void *pUserData); static void ConGPlay(IConsole::IResult *pResult, void *pUserData);
public: public:
bool m_IsSolo; bool m_AllowRestart;
CGhost(); CGhost();

View file

@ -29,7 +29,7 @@ void CRaceDemo::OnRender()
return; return;
// start the demo // start the demo
bool AllowRestart = !m_IsSolo && m_RaceStartTick + 10 * Client()->GameTickSpeed() < Client()->GameTick(); bool AllowRestart = m_AllowRestart && m_RaceStartTick + 10 * Client()->GameTickSpeed() < Client()->GameTick();
if(m_RaceState == RACE_IDLE || m_RaceState == RACE_PREPARE || (m_RaceState == RACE_STARTED && AllowRestart)) if(m_RaceState == RACE_IDLE || m_RaceState == RACE_PREPARE || (m_RaceState == RACE_STARTED && AllowRestart))
{ {
vec2 PrevPos = vec2(m_pClient->m_Snap.m_pLocalPrevCharacter->m_X, m_pClient->m_Snap.m_pLocalPrevCharacter->m_Y); vec2 PrevPos = vec2(m_pClient->m_Snap.m_pLocalPrevCharacter->m_X, m_pClient->m_Snap.m_pLocalPrevCharacter->m_Y);
@ -108,7 +108,7 @@ void CRaceDemo::OnMessage(int MsgType, void *pRawMsg)
void CRaceDemo::OnMapLoad() void CRaceDemo::OnMapLoad()
{ {
m_IsSolo = true; m_AllowRestart = false;
} }
void CRaceDemo::StopRecord(int Time) void CRaceDemo::StopRecord(int Time)

View file

@ -25,7 +25,7 @@ class CRaceDemo : public CComponent
bool CheckDemo(int Time) const; bool CheckDemo(int Time) const;
public: public:
bool m_IsSolo; bool m_AllowRestart;
CRaceDemo(); CRaceDemo();

View file

@ -852,8 +852,8 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy)
if (i <= 16) if (i <= 16)
m_Teams.m_IsDDRace16 = true; m_Teams.m_IsDDRace16 = true;
m_pGhost->m_IsSolo = false; m_pGhost->m_AllowRestart = true;
m_pRaceDemo->m_IsSolo = false; m_pRaceDemo->m_AllowRestart = true;
} }
else if(MsgId == NETMSGTYPE_SV_PLAYERTIME) else if(MsgId == NETMSGTYPE_SV_PLAYERTIME)
{ {