mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-04 15:12:58 +00:00
Improve Demo end handing
- Demos/Ghosts that end before ticking once are now correctly ignored. (Resolves KartKrew/RingRacers#168) - There was code for discovering it on read! It was just placed slightly too early, probably due to the conversion for netreplays! I'm very mad! - As a preventative measure, demos *recorded* before ticking will simply not save in the first place. - This was also a frustratingly easy fix for the amount of headache it's caused us. - Reduced the amount of copypasted boilerplate by simplifying the places where DEMOMARKER can be written (and therefore read). - Previously, like half the write functions tried to guess their own output size and potentially end the demo at any point. - At best, this will grant us a few tics of reprireve for large netgames and MAYBE a handful of seconds for time attack, The Mode In Which The Aim Is To Go Fast. - Instead, double the size of the deadspace buffer extension and just check to see if we've crossed into that territory.
This commit is contained in:
parent
565733224f
commit
9e0510d674
3 changed files with 111 additions and 122 deletions
194
src/g_demo.cpp
194
src/g_demo.cpp
|
|
@ -270,6 +270,26 @@ static ticcmd_t oldcmd[MAXPLAYERS];
|
||||||
|
|
||||||
static mobj_t oldghost[MAXPLAYERS];
|
static mobj_t oldghost[MAXPLAYERS];
|
||||||
|
|
||||||
|
boolean G_ConsiderEndingDemoWrite(void)
|
||||||
|
{
|
||||||
|
// chill, we reserved extra memory so it's
|
||||||
|
// "safe" to have written a bit past the end
|
||||||
|
if (demobuf.p < demobuf.end)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
G_CheckDemoStatus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean G_ConsiderEndingDemoRead(void)
|
||||||
|
{
|
||||||
|
if (*demobuf.p != DEMOMARKER)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
G_CheckDemoStatus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void G_ReadDemoExtraData(void)
|
void G_ReadDemoExtraData(void)
|
||||||
{
|
{
|
||||||
INT32 p, extradata, i;
|
INT32 p, extradata, i;
|
||||||
|
|
@ -460,13 +480,6 @@ void G_ReadDemoExtraData(void)
|
||||||
|
|
||||||
p = READUINT8(demobuf.p);
|
p = READUINT8(demobuf.p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(demoflags & DF_GHOST) && *demobuf.p == DEMOMARKER)
|
|
||||||
{
|
|
||||||
// end of demo data stream
|
|
||||||
G_CheckDemoStatus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_WriteDemoExtraData(void)
|
void G_WriteDemoExtraData(void)
|
||||||
|
|
@ -623,13 +636,6 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
}
|
}
|
||||||
|
|
||||||
G_CopyTiccmd(cmd, &oldcmd[playernum], 1);
|
G_CopyTiccmd(cmd, &oldcmd[playernum], 1);
|
||||||
|
|
||||||
if (!(demoflags & DF_GHOST) && *demobuf.p == DEMOMARKER)
|
|
||||||
{
|
|
||||||
// end of demo data stream
|
|
||||||
G_CheckDemoStatus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
|
|
@ -739,14 +745,6 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
|
|
||||||
WRITEUINT16(botziptic_p, botziptic);
|
WRITEUINT16(botziptic_p, botziptic);
|
||||||
}
|
}
|
||||||
|
|
||||||
// attention here for the ticcmd size!
|
|
||||||
// latest demos with mouse aiming byte in ticcmd
|
|
||||||
if (!(demoflags & DF_GHOST) && ziptic_p > demobuf.end - 9)
|
|
||||||
{
|
|
||||||
G_CheckDemoStatus(); // no more space
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_GhostAddFlip(INT32 playernum)
|
void G_GhostAddFlip(INT32 playernum)
|
||||||
|
|
@ -794,8 +792,11 @@ void G_GhostAddHit(INT32 playernum, mobj_t *victim)
|
||||||
|
|
||||||
void G_WriteAllGhostTics(void)
|
void G_WriteAllGhostTics(void)
|
||||||
{
|
{
|
||||||
boolean toobig = false;
|
|
||||||
INT32 i, counter = leveltime;
|
INT32 i, counter = leveltime;
|
||||||
|
|
||||||
|
if (!demobuf.p || !(demoflags & DF_GHOST))
|
||||||
|
return; // No ghost data to write.
|
||||||
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (!playeringame[i] || players[i].spectator)
|
if (!playeringame[i] || players[i].spectator)
|
||||||
|
|
@ -811,22 +812,9 @@ void G_WriteAllGhostTics(void)
|
||||||
|
|
||||||
WRITEUINT8(demobuf.p, i);
|
WRITEUINT8(demobuf.p, i);
|
||||||
G_WriteGhostTic(players[i].mo, i);
|
G_WriteGhostTic(players[i].mo, i);
|
||||||
|
|
||||||
// attention here for the ticcmd size!
|
|
||||||
// latest demos with mouse aiming byte in ticcmd
|
|
||||||
if (demobuf.p >= demobuf.end - (13 + 9 + 9))
|
|
||||||
{
|
|
||||||
toobig = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITEUINT8(demobuf.p, 0xFF);
|
WRITEUINT8(demobuf.p, 0xFF);
|
||||||
|
|
||||||
if (toobig)
|
|
||||||
{
|
|
||||||
G_CheckDemoStatus(); // no more space
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
|
void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
|
||||||
|
|
@ -835,11 +823,6 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
|
||||||
UINT8 *ziptic_p;
|
UINT8 *ziptic_p;
|
||||||
UINT32 i;
|
UINT32 i;
|
||||||
|
|
||||||
if (!demobuf.p)
|
|
||||||
return;
|
|
||||||
if (!(demoflags & DF_GHOST))
|
|
||||||
return; // No ghost data to write.
|
|
||||||
|
|
||||||
ziptic_p = demobuf.p++; // the ziptic, written at the end of this function
|
ziptic_p = demobuf.p++; // the ziptic, written at the end of this function
|
||||||
|
|
||||||
#define MAXMOM (0xFFFF<<8)
|
#define MAXMOM (0xFFFF<<8)
|
||||||
|
|
@ -1061,7 +1044,7 @@ void G_ConsAllGhostTics(void)
|
||||||
{
|
{
|
||||||
UINT8 p;
|
UINT8 p;
|
||||||
|
|
||||||
if (!demobuf.p || !demo.deferstart)
|
if (!demobuf.p || !(demoflags & DF_GHOST) || !demo.deferstart)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p = READUINT8(demobuf.p);
|
p = READUINT8(demobuf.p);
|
||||||
|
|
@ -1071,13 +1054,6 @@ void G_ConsAllGhostTics(void)
|
||||||
G_ConsGhostTic(p);
|
G_ConsGhostTic(p);
|
||||||
p = READUINT8(demobuf.p);
|
p = READUINT8(demobuf.p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*demobuf.p == DEMOMARKER)
|
|
||||||
{
|
|
||||||
// end of demo data stream
|
|
||||||
G_CheckDemoStatus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uses ghost data to do consistency checks on your position.
|
// Uses ghost data to do consistency checks on your position.
|
||||||
|
|
@ -1089,9 +1065,6 @@ void G_ConsGhostTic(INT32 playernum)
|
||||||
mobj_t *testmo;
|
mobj_t *testmo;
|
||||||
UINT32 syncleeway;
|
UINT32 syncleeway;
|
||||||
|
|
||||||
if (!(demoflags & DF_GHOST))
|
|
||||||
return; // No ghost data to use.
|
|
||||||
|
|
||||||
testmo = players[playernum].mo;
|
testmo = players[playernum].mo;
|
||||||
|
|
||||||
// Grab ghost data.
|
// Grab ghost data.
|
||||||
|
|
@ -1282,13 +1255,6 @@ void G_ConsGhostTic(INT32 playernum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*demobuf.p == DEMOMARKER)
|
|
||||||
{
|
|
||||||
// end of demo data stream
|
|
||||||
G_CheckDemoStatus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_GhostTicker(void)
|
void G_GhostTicker(void)
|
||||||
|
|
@ -1309,11 +1275,31 @@ void G_GhostTicker(void)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
readghosttic:
|
readghosttic:
|
||||||
|
#define follow g->mo->tracer
|
||||||
|
|
||||||
// Skip normal demo data.
|
// Skip normal demo data.
|
||||||
ziptic = READUINT8(g->p);
|
ziptic = READUINT8(g->p);
|
||||||
xziptic = 0;
|
xziptic = 0;
|
||||||
|
|
||||||
|
// Demo ends after ghost data.
|
||||||
|
if (ziptic == DEMOMARKER)
|
||||||
|
{
|
||||||
|
fadeghost:
|
||||||
|
g->mo->momx = g->mo->momy = g->mo->momz = 0;
|
||||||
|
g->mo->fuse = TICRATE;
|
||||||
|
if (follow)
|
||||||
|
{
|
||||||
|
follow->fuse = TICRATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g->done = true;
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
p->next = g->next;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
while (ziptic != DW_END) // Get rid of extradata stuff
|
while (ziptic != DW_END) // Get rid of extradata stuff
|
||||||
{
|
{
|
||||||
if (ziptic < MAXPLAYERS)
|
if (ziptic < MAXPLAYERS)
|
||||||
|
|
@ -1414,9 +1400,11 @@ readghosttic:
|
||||||
// Grab ghost data.
|
// Grab ghost data.
|
||||||
ziptic = READUINT8(g->p);
|
ziptic = READUINT8(g->p);
|
||||||
|
|
||||||
|
if (ziptic == DEMOMARKER) // Had to end early for some reason
|
||||||
|
goto fadeghost;
|
||||||
if (ziptic == 0xFF)
|
if (ziptic == 0xFF)
|
||||||
goto skippedghosttic; // Didn't write ghost info this frame
|
goto skippedghosttic; // Didn't write ghost info this frame
|
||||||
else if (ziptic != 0)
|
if (ziptic != 0)
|
||||||
I_Error("Ghost is not a record attack ghost ZIPTIC"); //@TODO lmao don't blow up like this
|
I_Error("Ghost is not a record attack ghost ZIPTIC"); //@TODO lmao don't blow up like this
|
||||||
ziptic = READUINT8(g->p);
|
ziptic = READUINT8(g->p);
|
||||||
|
|
||||||
|
|
@ -1530,7 +1518,6 @@ readghosttic:
|
||||||
g->mo->renderflags &= ~RF_DONTDRAW;
|
g->mo->renderflags &= ~RF_DONTDRAW;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define follow g->mo->tracer
|
|
||||||
if (ziptic & GZT_FOLLOW)
|
if (ziptic & GZT_FOLLOW)
|
||||||
{ // Even more...
|
{ // Even more...
|
||||||
UINT8 followtic = READUINT8(g->p);
|
UINT8 followtic = READUINT8(g->p);
|
||||||
|
|
@ -1620,28 +1607,6 @@ skippedghosttic:
|
||||||
if (READUINT8(g->p) != 0xFF) // Make sure there isn't other ghost data here.
|
if (READUINT8(g->p) != 0xFF) // Make sure there isn't other ghost data here.
|
||||||
I_Error("Ghost is not a record attack ghost GHOSTEND"); //@TODO lmao don't blow up like this
|
I_Error("Ghost is not a record attack ghost GHOSTEND"); //@TODO lmao don't blow up like this
|
||||||
|
|
||||||
// Demo ends after ghost data.
|
|
||||||
if (*g->p == DEMOMARKER)
|
|
||||||
{
|
|
||||||
g->mo->momx = g->mo->momy = g->mo->momz = 0;
|
|
||||||
#if 0 // freeze frame (maybe more useful for time attackers) (2024-03-11: you leave it behind anyway!)
|
|
||||||
g->mo->colorized = true;
|
|
||||||
g->mo->fuse = 10*TICRATE;
|
|
||||||
if (follow)
|
|
||||||
follow->colorized = true;
|
|
||||||
#else // dissapearing act
|
|
||||||
g->mo->fuse = TICRATE;
|
|
||||||
if (follow)
|
|
||||||
follow->fuse = TICRATE;
|
|
||||||
#endif
|
|
||||||
g->done = true;
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
p->next = g->next;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the timer started, skip ahead until the ghost starts too.
|
// If the timer started, skip ahead until the ghost starts too.
|
||||||
if (starttime <= leveltime && !g->linecrossed && G_TimeAttackStart())
|
if (starttime <= leveltime && !g->linecrossed && G_TimeAttackStart())
|
||||||
goto readghosttic;
|
goto readghosttic;
|
||||||
|
|
@ -1885,7 +1850,7 @@ void G_RecordDemo(const char *name)
|
||||||
functions will check if they overran the buffer, but it
|
functions will check if they overran the buffer, but it
|
||||||
should be safe enough because they'll think there's less
|
should be safe enough because they'll think there's less
|
||||||
memory than there actually is and stop early. */
|
memory than there actually is and stop early. */
|
||||||
const size_t deadspace = 1024;
|
const size_t deadspace = 2048;
|
||||||
I_Assert(demobuf.size > deadspace);
|
I_Assert(demobuf.size > deadspace);
|
||||||
demobuf.size -= deadspace;
|
demobuf.size -= deadspace;
|
||||||
demobuf.end -= deadspace;
|
demobuf.end -= deadspace;
|
||||||
|
|
@ -3363,22 +3328,6 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
|
||||||
// Load "mapmusrng" used for altmusic selection
|
// Load "mapmusrng" used for altmusic selection
|
||||||
mapmusrng = READUINT8(demobuf.p);
|
mapmusrng = READUINT8(demobuf.p);
|
||||||
|
|
||||||
// Sigh ... it's an empty demo.
|
|
||||||
if (*demobuf.p == DEMOMARKER)
|
|
||||||
{
|
|
||||||
snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname);
|
|
||||||
CONS_Alert(CONS_ERROR, "%s", msg);
|
|
||||||
M_StartMessage("Demo Playback", msg, NULL, MM_NOTHING, NULL, "Return to Menu");
|
|
||||||
Z_Free(demo.skinlist);
|
|
||||||
demo.skinlist = NULL;
|
|
||||||
Z_Free(pdemoname);
|
|
||||||
Z_Free(demobuf.buffer);
|
|
||||||
demo.playback = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Z_Free(pdemoname);
|
|
||||||
|
|
||||||
memset(&oldcmd,0,sizeof(oldcmd));
|
memset(&oldcmd,0,sizeof(oldcmd));
|
||||||
memset(&oldghost,0,sizeof(oldghost));
|
memset(&oldghost,0,sizeof(oldghost));
|
||||||
memset(&ghostext,0,sizeof(ghostext));
|
memset(&ghostext,0,sizeof(ghostext));
|
||||||
|
|
@ -3607,6 +3556,22 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
|
||||||
players[p].lastfakeskin = lastfakeskin[p];
|
players[p].lastfakeskin = lastfakeskin[p];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sigh ... it's an empty demo.
|
||||||
|
if (*demobuf.p == DEMOMARKER)
|
||||||
|
{
|
||||||
|
snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname);
|
||||||
|
CONS_Alert(CONS_ERROR, "%s", msg);
|
||||||
|
M_StartMessage("Demo Playback", msg, NULL, MM_NOTHING, NULL, "Return to Menu");
|
||||||
|
Z_Free(demo.skinlist);
|
||||||
|
demo.skinlist = NULL;
|
||||||
|
Z_Free(pdemoname);
|
||||||
|
Z_Free(demobuf.buffer);
|
||||||
|
demo.playback = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Z_Free(pdemoname);
|
||||||
|
|
||||||
demo.deferstart = true;
|
demo.deferstart = true;
|
||||||
|
|
||||||
CV_StealthSetValue(&cv_playbackspeed, 1);
|
CV_StealthSetValue(&cv_playbackspeed, 1);
|
||||||
|
|
@ -3756,14 +3721,6 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
|
||||||
|
|
||||||
p++; // mapmusrng
|
p++; // mapmusrng
|
||||||
|
|
||||||
if (*p == DEMOMARKER)
|
|
||||||
{
|
|
||||||
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), defdemoname);
|
|
||||||
Z_Free(skinlist);
|
|
||||||
P_SaveBufferFree(buffer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
p++; // player number - doesn't really need to be checked, TODO maybe support adding multiple players' ghosts at once
|
p++; // player number - doesn't really need to be checked, TODO maybe support adding multiple players' ghosts at once
|
||||||
|
|
||||||
// any invalidating flags?
|
// any invalidating flags?
|
||||||
|
|
@ -3811,6 +3768,14 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*p == DEMOMARKER)
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), defdemoname);
|
||||||
|
Z_Free(skinlist);
|
||||||
|
P_SaveBufferFree(buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gh = static_cast<demoghost*>(Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL));
|
gh = static_cast<demoghost*>(Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL));
|
||||||
gh->sizes = ghostsizes;
|
gh->sizes = ghostsizes;
|
||||||
|
|
@ -4173,7 +4138,7 @@ boolean G_CheckDemoStatus(void)
|
||||||
// Keep the demo open and don't boot to intermission
|
// Keep the demo open and don't boot to intermission
|
||||||
// YET, pause demo playback.
|
// YET, pause demo playback.
|
||||||
if (!demo.waitingfortally && modeattacking && exitcountdown)
|
if (!demo.waitingfortally && modeattacking && exitcountdown)
|
||||||
demo.waitingfortally = true;
|
;
|
||||||
else if (!demo.attract)
|
else if (!demo.attract)
|
||||||
G_FinishExitLevel();
|
G_FinishExitLevel();
|
||||||
else
|
else
|
||||||
|
|
@ -4191,6 +4156,8 @@ boolean G_CheckDemoStatus(void)
|
||||||
D_SetDeferredStartTitle(true);
|
D_SetDeferredStartTitle(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
demo.waitingfortally = true; // if we've returned early for some reason...
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4235,6 +4202,13 @@ void G_SaveDemo(void)
|
||||||
if (currentMenu == &TitleEntryDef)
|
if (currentMenu == &TitleEntryDef)
|
||||||
M_ClearMenus(true);
|
M_ClearMenus(true);
|
||||||
|
|
||||||
|
if (!leveltime)
|
||||||
|
{
|
||||||
|
// Why would you save if nothing has been recorded
|
||||||
|
G_ResetDemoRecording();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure extrainfo pointer is always available, even if no info is present.
|
// Ensure extrainfo pointer is always available, even if no info is present.
|
||||||
if (demoinfo_p && *(UINT32 *)demoinfo_p == 0)
|
if (demoinfo_p && *(UINT32 *)demoinfo_p == 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,8 @@ extern UINT8 demo_writerng;
|
||||||
boolean G_CompatLevel(UINT16 level);
|
boolean G_CompatLevel(UINT16 level);
|
||||||
|
|
||||||
// Record/playback tics
|
// Record/playback tics
|
||||||
|
boolean G_ConsiderEndingDemoRead(void);
|
||||||
|
boolean G_ConsiderEndingDemoWrite(void);
|
||||||
void G_ReadDemoExtraData(void);
|
void G_ReadDemoExtraData(void);
|
||||||
void G_WriteDemoExtraData(void);
|
void G_WriteDemoExtraData(void);
|
||||||
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
|
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
|
||||||
|
|
|
||||||
37
src/p_tick.c
37
src/p_tick.c
|
|
@ -762,17 +762,23 @@ void P_Ticker(boolean run)
|
||||||
|
|
||||||
if (demo.recording)
|
if (demo.recording)
|
||||||
{
|
{
|
||||||
G_WriteDemoExtraData();
|
if (!G_ConsiderEndingDemoWrite())
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
{
|
||||||
if (playeringame[i])
|
G_WriteDemoExtraData();
|
||||||
G_WriteDemoTiccmd(&players[i].cmd, i);
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
if (playeringame[i])
|
||||||
|
G_WriteDemoTiccmd(&players[i].cmd, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (demo.playback && !demo.waitingfortally)
|
if (demo.playback && !demo.waitingfortally)
|
||||||
{
|
{
|
||||||
G_ReadDemoExtraData();
|
if (!G_ConsiderEndingDemoRead())
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
{
|
||||||
if (playeringame[i])
|
G_ReadDemoExtraData();
|
||||||
G_ReadDemoTiccmd(&players[i].cmd, i);
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
if (playeringame[i])
|
||||||
|
G_ReadDemoTiccmd(&players[i].cmd, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LUA_ResetTicTimers();
|
LUA_ResetTicTimers();
|
||||||
|
|
@ -1168,14 +1174,21 @@ void P_Ticker(boolean run)
|
||||||
|
|
||||||
if (demo.recording)
|
if (demo.recording)
|
||||||
{
|
{
|
||||||
G_WriteAllGhostTics();
|
|
||||||
|
|
||||||
if (cv_recordmultiplayerdemos.value && demo.savebutton && demo.savebutton + 3*TICRATE < leveltime)
|
if (cv_recordmultiplayerdemos.value && demo.savebutton && demo.savebutton + 3*TICRATE < leveltime)
|
||||||
G_CheckDemoTitleEntry();
|
G_CheckDemoTitleEntry();
|
||||||
|
|
||||||
|
if (!G_ConsiderEndingDemoWrite())
|
||||||
|
{
|
||||||
|
G_WriteAllGhostTics();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (demo.playback && !demo.waitingfortally) // Use Ghost data for consistency checks.
|
else if (demo.playback && !demo.waitingfortally)
|
||||||
{
|
{
|
||||||
G_ConsAllGhostTics();
|
if (!G_ConsiderEndingDemoRead())
|
||||||
|
{
|
||||||
|
// Use Ghost data for consistency checks.
|
||||||
|
G_ConsAllGhostTics();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modeattacking)
|
if (modeattacking)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue