PR_INTERPHUDRANDOM

Fixes several things to do with the boss healthbar.
- Makes its randomised jitter work with interp/pause
- Constantly calling the external PRNG tanks performance, at least on Windows, so this solves that too

Done as a special non-netsynced random class so the author of this commit wouldn't have to create a third suite of duplicated Random functions.
This commit is contained in:
toaster 2023-10-25 12:55:44 +01:00
parent b87f57440c
commit bd5fdb3b82
7 changed files with 69 additions and 28 deletions

View file

@ -5590,7 +5590,7 @@ static INT16 Consistancy(void)
// Coop desynching enemies is painful
if (gamestate == GS_LEVEL)
{
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
if (i & 1)
{

View file

@ -853,8 +853,6 @@ void D_SRB2Loop(void)
realtics = entertic - oldentertics;
oldentertics = entertic;
refreshdirmenu = 0; // not sure where to put this, here as good as any?
if (demo.playback && gamestate == GS_LEVEL)
{
// Nicer place to put this.
@ -870,8 +868,16 @@ void D_SRB2Loop(void)
interp = R_UsingFrameInterpolation() && !dedicated;
doDisplay = false;
if (realtics > 0 || singletics)
renderisnewtic = (realtics > 0 || singletics);
bool timeisprogressing = (!(paused || P_AutoPause()) && !hu_stopped);
if (renderisnewtic)
{
refreshdirmenu = 0;
P_ResetInterpHudRandSeed(timeisprogressing);
// don't skip more than 10 frames at a time
// (fadein / fadeout cause massive frame skip!)
if (realtics > 8)
@ -906,19 +912,13 @@ void D_SRB2Loop(void)
doDisplay = true;
}
renderisnewtic = true;
}
else
{
renderisnewtic = false;
}
if (interp)
{
renderdeltatics = FLOAT_TO_FIXED(deltatics);
if (!(paused || P_AutoPause()) && !hu_stopped)
if (timeisprogressing)
{
rendertimefrac = g_time.timefrac;
}
@ -938,6 +938,9 @@ void D_SRB2Loop(void)
if ((interp || doDisplay) && !frameskip)
{
if (!renderisnewtic)
P_ResetInterpHudRandSeed(false);
ranwipe = D_Display();
}

View file

@ -364,7 +364,7 @@ void G_ReadDemoExtraData(void)
switch (p)
{
case DW_RNG:
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
rng = READUINT32(demobuf.p);
@ -507,7 +507,7 @@ void G_WriteDemoExtraData(void)
timeout = 16;
WRITEUINT8(demobuf.p, DW_RNG);
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
WRITEUINT32(demobuf.p, P_GetRandSeed(i));
}
@ -1202,7 +1202,7 @@ void G_GhostTicker(void)
else if (ziptic == DW_RNG)
{
INT32 i;
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
g->p += 4; // RNG seed
}
@ -2435,7 +2435,7 @@ void G_BeginRecording(void)
demotime_p = NULL;
}
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
WRITEUINT32(demobuf.p, P_GetInitSeed(i));
}
@ -2899,7 +2899,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
goto badreplay;
}
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
info.p += 4; // RNG seed
}
@ -3028,7 +3028,7 @@ void G_DoPlayDemo(const char *defdemoname)
char *pdemoname;
UINT8 availabilities[MAXPLAYERS][MAXAVAILABILITY];
UINT8 version,subversion;
UINT32 randseed[PRNUMCLASS];
UINT32 randseed[PRNUMSYNCED];
char msg[1024];
boolean spectator, bot;
@ -3308,7 +3308,7 @@ void G_DoPlayDemo(const char *defdemoname)
hu_demolap = READUINT32(demobuf.p);
// Random seed
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
randseed[i] = READUINT32(demobuf.p);
}
@ -3530,7 +3530,7 @@ void G_DoPlayDemo(const char *defdemoname)
R_ExecuteSetViewSize();
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
P_SetRandSeed(i, randseed[i]);
}
@ -3667,7 +3667,7 @@ void G_AddGhost(savebuffer_t *buffer, char *defdemoname)
if (flags & ATTACKING_LAP)
p += 4;
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
p += 4; // random seed
}
@ -3876,7 +3876,7 @@ staffbrief_t *G_GetStaffGhostBrief(UINT8 *buffer)
if (flags & ATTACKING_LAP)
temp.lap = READUINT32(p);
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
p += 4; // random seed
}

View file

@ -2422,8 +2422,8 @@ static void K_drawBossHealthBar(void)
randtemp = bossinfo.visualbar-(bossinfo.visualdiv/(2*FRACUNIT));
if (randtemp > 0)
randlen = M_RandomKey(randtemp)+1;
randsign = M_RandomChance(FRACUNIT/2);
randlen = P_RandomKey(PR_INTERPHUDRANDOM, randtemp)+1;
randsign = P_RandomChance(PR_INTERPHUDRANDOM, FRACUNIT/2);
// Right wing.
V_DrawScaledPatch(startx-1, starty, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_FLIP, kp_bossbar[0]);
@ -2439,10 +2439,10 @@ static void K_drawBossHealthBar(void)
{
randtemp = bossinfo.visualbar-(bossinfo.visualdiv/(2*FRACUNIT));
if (randtemp > 0)
randlen = M_RandomKey(randtemp)+1;
randlen = P_RandomKey(PR_INTERPHUDRANDOM, randtemp)+1;
if (barstatus > 1)
{
rolrand = M_RandomKey(barstatus)+1;
rolrand = P_RandomKey(PR_INTERPHUDRANDOM, barstatus)+1;
}
else
{

View file

@ -342,6 +342,37 @@ void P_SetRandSeedNetD(const char *rfile, INT32 rline, pr_class_t pr_class, UINT
rng.seed[pr_class] = seed;
}
/** Change PR_INTERPHUDRANDOM state.
* Used for interp-safe HUD randomisation.
*
* \sa P_SetRandSeed
*/
#ifndef DEBUGRANDOM
void P_ResetInterpHudRandSeed(boolean newframe)
{
#else
void P_ResetInterpHudRandSeedD(const char *rfile, INT32 rline, boolean newframe)
{
CONS_Printf("P_ResetInterpHudRandSeed(%c) at: %sp %d\n", (newframe ? 'T' : 'F'), rfile, rline);
#endif
if (newframe == true)
{
// Advance the initialisation to the current seed.
rng.init[PR_INTERPHUDRANDOM] = rng.seed[PR_INTERPHUDRANDOM];
}
else
{
// Rewind the seed to the last initialisation.
rng.seed[PR_INTERPHUDRANDOM] = rng.init[PR_INTERPHUDRANDOM];
}
// xorshift requires a nonzero seed
// this should never happen, but just in case it DOES, we check
if (!rng.seed[PR_INTERPHUDRANDOM])
rng.seed[PR_INTERPHUDRANDOM] = rng.init[PR_INTERPHUDRANDOM] = DEFAULT_SEED;
}
/** Initializes random seeds for all classes.
* Used at the beginning of a game.
*
@ -354,7 +385,7 @@ void P_ClearRandom(UINT32 seed)
if (!seed) seed = DEFAULT_SEED;
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
P_SetRandSeed(i, seed);

View file

@ -83,6 +83,10 @@ typedef enum
PR_FUZZ, // Stability testing
PRNUMSYNCED,
PR_INTERPHUDRANDOM = PRNUMSYNCED, // Interpolation-accomodating HUD randomisation
PRNUMCLASS
} pr_class_t;
@ -132,15 +136,18 @@ UINT32 P_RandomPeek(pr_class_t pr_class);
#define P_GetInitSeed(pr) P_GetInitSeedD(__FILE__, __LINE__, pr)
#define P_SetRandSeed(pr, s) P_SetRandSeedD(__FILE__, __LINE__, pr, s)
#define P_SetRandSeedNet(pr, i, s) P_SetRandSeedD(__FILE__, __LINE__, pr, i, s)
#define P_ResetInterpHudRandSeed(newframe) P_ResetInterpHudRandSeedD(__FILE__, __LINE__, newframe)
UINT32 P_GetRandSeedD(const char *rfile, INT32 rline, pr_class_t pr_class);
UINT32 P_GetInitSeedD(const char *rfile, INT32 rline, pr_class_t pr_class);
void P_SetRandSeedD(const char *rfile, INT32 rline, pr_class_t pr_class, UINT32 seed);
void P_SetRandSeedNetD(const char *rfile, INT32 rline, pr_class_t pr_class, UINT32 init, UINT32 seed);
void P_ResetInterpHudRandSeedD(const char *rfile, INT32 rline, boolean newframe);
#else
UINT32 P_GetRandSeed(pr_class_t pr_class);
UINT32 P_GetInitSeed(pr_class_t pr_class);
void P_SetRandSeed(pr_class_t pr_class, UINT32 seed);
void P_SetRandSeedNet(pr_class_t pr_class, UINT32 init, UINT32 seed);
void P_ResetInterpHudRandSeed(boolean newframe);
#endif
void P_ClearRandom(UINT32 seed);

View file

@ -6354,7 +6354,7 @@ static void P_NetArchiveRNG(savebuffer_t *save)
WRITEUINT32(save->p, ARCHIVEBLOCK_RNG);
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
WRITEUINT32(save->p, P_GetInitSeed(i));
WRITEUINT32(save->p, P_GetRandSeed(i));
@ -6368,7 +6368,7 @@ static inline void P_NetUnArchiveRNG(savebuffer_t *save)
if (READUINT32(save->p) != ARCHIVEBLOCK_RNG)
I_Error("Bad $$$.sav at archive block RNG");
for (i = 0; i < PRNUMCLASS; i++)
for (i = 0; i < PRNUMSYNCED; i++)
{
UINT32 init = READUINT32(save->p);
UINT32 seed = READUINT32(save->p);