Merge branch 'wipeloop-merged' into wipeloop-rebased

This commit is contained in:
Lactozilla 2023-12-26 19:53:12 -03:00
parent 2ef5ea86f3
commit cf03f5d91e
24 changed files with 1543 additions and 1156 deletions

View file

@ -289,113 +289,103 @@ void D_ProcessEvents(void)
}
//
// D_Display
// draw current display, possibly wiping it from the previous
// RENDERING
//
// wipegamestate can be set to -1 to force a wipe on the next draw
// added comment : there is a wipe eatch change of the gamestate
gamestate_t wipegamestate = GS_LEVEL;
// -1: Default; 0-n: Wipe index; INT16_MAX: do not wipe
INT16 wipetypepre = -1;
INT16 wipetypepost = -1;
INT16 wipetypepre = DEFAULTWIPE;
INT16 wipetypepost = DEFAULTWIPE;
static void D_Display(void)
static void D_Render(void)
{
boolean forcerefresh = false;
static boolean wipe = false;
INT32 wipedefindex = 0;
if (dedicated)
return;
if (nodrawers)
return; // for comparative timing/profiling
// Lactozilla: Switching renderers works by checking
// if the game has to do it right when the frame
// needs to render. If so, five things will happen:
// 1. Interface functions will be called so
// that switching to OpenGL creates a
// GL context, and switching to Software
// allocates screen buffers.
// 2. Software will set drawer functions,
// and OpenGL will load textures and
// create plane polygons, if necessary.
// 3. Functions related to switching video
// modes (resolution) are called.
// 4. The frame is ready to be drawn!
// Check for change of renderer or screen size (video mode)
if ((setrenderneeded || setmodeneeded) && !wipe)
SCR_SetMode(); // change video mode
// Recalc the screen
if (vid.recalc)
SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc()
// View morph
if (rendermode == render_soft && !splitscreen)
R_CheckViewMorph();
// Change the view size if needed
// Set by changing video mode or renderer
if (setsizeneeded)
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide && (!hidetitlemap))))
{
R_ExecuteSetViewSize();
forcerefresh = true; // force background redraw
PS_START_TIMING(ps_uitime);
return;
}
// draw buffered stuff to screen
// Used only by linux GGI version
I_UpdateNoBlit();
// save the current screen if about to wipe
wipe = (gamestate != wipegamestate);
if (wipe && wipetypepre != INT16_MAX)
// draw the view directly
if (!automapactive && !dedicated && (!titlecard.prelevel) && cv_renderview.value)
{
// set for all later
wipedefindex = gamestate; // wipe_xxx_toblack
if (gamestate == GS_INTERMISSION)
R_ApplyLevelInterpolators(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
PS_START_TIMING(ps_rendercalltime);
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
if (intertype == int_spec) // Special Stage
wipedefindex = wipe_specinter_toblack;
else if (intertype != int_coop) // Multiplayer
wipedefindex = wipe_multinter_toblack;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
if (wipetypepre < 0 || !F_WipeExists(wipetypepre))
wipetypepre = wipedefs[wipedefindex];
if (rendermode != render_none)
// render the second screen
if (splitscreen && players[secondarydisplayplayer].mo)
{
// Fade to black first
if ((wipegamestate == (gamestate_t)FORCEWIPE ||
(wipegamestate != (gamestate_t)FORCEWIPEOFF
&& !(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
) // fades to black on its own timing, always
&& wipetypepre != UINT8_MAX)
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
{
F_WipeStartScreen();
// Check for Mega Genesis fade
wipestyleflags = WSF_FADEOUT;
if (wipegamestate == (gamestate_t)FORCEWIPE)
F_WipeColorFill(31);
else if (F_TryColormapFade(31))
wipetypepost = -1; // Don't run the fade below this one
F_WipeEndScreen();
F_RunWipe(wipetypepre, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN);
}
viewwindowy = vid.height / 2;
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
F_WipeStartScreen();
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[secondarydisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
wipetypepre = -1;
// Image postprocessing effect
if (rendermode == render_soft)
{
if (!splitscreen)
R_ApplyViewMorph();
if (postimgtype)
V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
PS_STOP_TIMING(ps_rendercalltime);
R_RestoreLevelInterpolators();
}
if (lastdraw)
{
if (rendermode == render_soft)
{
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
Y_ConsiderScreenBuffer();
usebuffer = true;
}
lastdraw = false;
}
PS_START_TIMING(ps_uitime);
if (gamestate == GS_LEVEL)
{
ST_Drawer();
F_TextPromptDrawer();
HU_Drawer();
}
else
wipetypepre = -1;
F_TitleScreenDrawer();
}
// do buffered drawing
static void D_RenderNonLevel(void)
{
switch (gamestate)
{
case GS_TITLESCREEN:
@ -423,7 +413,7 @@ static void D_Display(void)
case GS_INTRO:
F_IntroDrawer();
if (wipegamestate == (gamestate_t)-1)
wipe = true;
WipeRunPost = true;
break;
case GS_ENDING:
@ -471,101 +461,75 @@ static void D_Display(void)
case GS_NULL:
break;
}
}
//
// Draws the entire screen frame.
//
static void D_Display(void)
{
boolean forcerefresh = false;
if (dedicated)
return;
if (nodrawers)
return; // for comparative timing/profiling
// Check for change of renderer or screen size (video mode)
if (setrenderneeded || setmodeneeded)
{
SCR_SetMode(); // change video mode
if (WipeInAction)
F_StopWipe();
}
// Recalc the screen
if (vid.recalc)
SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc()
// View morph
if (rendermode == render_soft && !splitscreen)
R_CheckViewMorph();
// Change the view size if needed
// Set by changing video mode or renderer
if (setsizeneeded)
{
R_ExecuteSetViewSize();
forcerefresh = true; // force background redraw
}
// draw buffered stuff to screen
// Used only by linux GGI version
I_UpdateNoBlit();
// save the current screen if about to wipe
// I'm scared of moving this way down there (before CON_Drawer mayhaps)
// but it's probably not a huge deal to leave it here...
// I'd have to make sure nothing during rendering is changing wipegamestate
if ((gamestate != wipegamestate) && wipetypepre != IGNOREWIPE)
F_WipeStartPre();
else
wipetypepre = DEFAULTWIPE;
// do buffered drawing
if (WipeInAction)
{
F_DisplayWipe();
if (gamestate == GS_LEVEL && !levelstarting)
TitleCard_DrawOverWipe();
}
else
D_RenderNonLevel();
// STUPID race condition...
if (wipegamestate == GS_INTRO && gamestate == GS_TITLESCREEN)
wipegamestate = FORCEWIPEOFF;
else
{
wipegamestate = gamestate;
// clean up border stuff
// see if the border needs to be initially drawn
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide && (!hidetitlemap)))
{
// draw the view directly
if (!automapactive && !dedicated && cv_renderview.value)
{
R_ApplyLevelInterpolators(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
PS_START_TIMING(ps_rendercalltime);
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
// render the second screen
if (splitscreen && players[secondarydisplayplayer].mo)
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
{
viewwindowy = vid.height / 2;
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[secondarydisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
// Image postprocessing effect
if (rendermode == render_soft)
{
if (!splitscreen)
R_ApplyViewMorph();
if (postimgtype)
V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
PS_STOP_TIMING(ps_rendercalltime);
R_RestoreLevelInterpolators();
}
if (lastdraw)
{
if (rendermode == render_soft)
{
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
Y_ConsiderScreenBuffer();
usebuffer = true;
}
lastdraw = false;
}
PS_START_TIMING(ps_uitime);
if (gamestate == GS_LEVEL)
{
ST_Drawer();
F_TextPromptDrawer();
HU_Drawer();
}
else
F_TitleScreenDrawer();
}
else
{
PS_START_TIMING(ps_uitime);
}
}
else if (!WipeInAction)
D_Render();
// change gamma if needed
// (GS_LEVEL handles this already due to level-specific palettes)
@ -594,66 +558,35 @@ static void D_Display(void)
// vid size change is now finished if it was on...
vid.recalc = 0;
if (!WipeInAction || (WipeInAction && (WipeDrawMenu || G_GetRetryFlag(RETRY_CUR))))
{
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of everything
M_Drawer(); // menu is drawn even on top of everything
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
I_unlock_mutex(m_menu_mutex);
#endif
}
// focus lost moved to M_Drawer
CON_Drawer();
PS_STOP_TIMING(ps_uitime);
//
// wipe update
//
if (wipe && wipetypepost != INT16_MAX)
if (WipeRunPost && !WipeInAction && wipetypepost != IGNOREWIPE)
{
// note: moved up here because NetUpdate does input changes
// and input during wipe tends to mess things up
wipedefindex += WIPEFINALSHIFT;
F_WipeStartPost();
F_DisplayWipe();
if (wipetypepost < 0 || !F_WipeExists(wipetypepost))
wipetypepost = wipedefs[wipedefindex];
if (rendermode != render_none)
{
F_WipeEndScreen();
// Funny.
if (WipeStageTitle && st_overlay)
{
lt_ticker--;
lt_lasttic = lt_ticker;
ST_preLevelTitleCardDrawer();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
F_WipeStartScreen();
}
// Check for Mega Genesis fade
if (F_ShouldColormapFade())
{
wipestyleflags |= WSF_FADEIN;
wipestyleflags &= ~WSF_FADEOUT;
}
F_RunWipe(wipetypepost, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN);
}
// reset counters so timedemo doesn't count the wipe duration
if (timingdemo)
{
framecount = 0;
demostarttime = I_GetTime();
}
wipetypepost = -1;
if (titlecard.running)
TitleCard_DrawOverWipe();
}
else
wipetypepost = -1;
wipetypepost = DEFAULTWIPE;
CON_Drawer();
PS_STOP_TIMING(ps_uitime);
NetUpdate(); // send out any new accumulation
@ -667,34 +600,31 @@ static void D_Display(void)
//
// normal update
//
if (!wipe)
if (cv_netstat.value)
{
if (cv_netstat.value)
{
char s[50];
Net_GetNetStat();
char s[50];
Net_GetNetStat();
s[sizeof s - 1] = '\0';
s[sizeof s - 1] = '\0';
snprintf(s, sizeof s - 1, "get %d b/s", getbps);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-40, V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "send %d b/s", sendbps);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-30, V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "GameMiss %.2f%%", gamelostpercent);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-20, V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "SysMiss %.2f%%", lostpercent);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
}
if (cv_perfstats.value)
{
M_DrawPerfStats();
}
PS_START_TIMING(ps_swaptime);
I_FinishUpdate(); // page flip or blit buffer
PS_STOP_TIMING(ps_swaptime);
snprintf(s, sizeof s - 1, "get %d b/s", getbps);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-40, V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "send %d b/s", sendbps);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-30, V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "GameMiss %.2f%%", gamelostpercent);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-20, V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "SysMiss %.2f%%", lostpercent);
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
}
if (cv_perfstats.value)
{
M_DrawPerfStats();
}
PS_START_TIMING(ps_swaptime);
I_FinishUpdate(); // page flip or blit buffer
PS_STOP_TIMING(ps_swaptime);
}
// =========================================================================
@ -708,7 +638,6 @@ void D_SRB2Loop(void)
tic_t entertic = 0, oldentertics = 0, realtics = 0, rendertimeout = INFTICS;
double deltatics = 0.0;
double deltasecs = 0.0;
static lumpnum_t gstartuplumpnum;
boolean interp = false;
boolean doDisplay = false;
@ -756,7 +685,7 @@ void D_SRB2Loop(void)
/* Smells like a hack... Don't fade Sonic's ass into the title screen. */
if (gamestate != GS_TITLESCREEN)
{
gstartuplumpnum = W_CheckNumForName("STARTUP");
lumpnum_t gstartuplumpnum = W_CheckNumForName("STARTUP");
if (gstartuplumpnum == LUMPERROR)
gstartuplumpnum = W_GetNumForName("MISSING");
V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(gstartuplumpnum, PU_PATCH));
@ -777,11 +706,13 @@ void D_SRB2Loop(void)
I_UpdateTime(cv_timescale.value);
#if 0
if (lastwipetic)
{
oldentertics = lastwipetic;
lastwipetic = 0;
}
#endif
// get real tics
entertic = I_GetTime();

View file

@ -306,9 +306,9 @@ static void F_NewCutscene(const char *basetext)
// =============
#define NUMINTROSCENES 17
INT32 intro_scenenum = 0;
INT32 intro_curtime = 0;
static INT32 intro_curtime = 0;
const char *introtext[NUMINTROSCENES];
static const char *introtext[NUMINTROSCENES];
static tic_t introscenetime[NUMINTROSCENES] =
{
@ -787,7 +787,7 @@ void F_IntroDrawer(void)
W_UnlockCachedPatch(background);
if (intro_scenenum == 4) // The asteroid SPINS!
if (intro_scenenum == INTRO_ASTEROID) // The asteroid SPINS!
{
if (intro_curtime > 1)
{
@ -827,7 +827,7 @@ void F_IntroDrawer(void)
V_DrawFixedPatch(x, y, scale, trans<<V_ALPHASHIFT, rockpat, R_GetTranslationColormap(TC_BLINK, SKINCOLOR_AQUA, GTC_CACHE));
}
}
else if (intro_scenenum == 1 && intro_curtime < 5*TICRATE)
else if (intro_scenenum == INTRO_FIRST && intro_curtime < 5*TICRATE)
{
INT32 trans = intro_curtime + 10 - (5*TICRATE);
if (trans < 0)
@ -838,6 +838,63 @@ void F_IntroDrawer(void)
V_DrawString(cx, cy, V_ALLOWLOWERCASE, cutscene_disptext);
}
static void F_IntroMidSceneWipe(void)
{
INT32 x = 8;
INT32 y = 128;
patch_t *patch;
if (intro_scenenum == INTRO_RADAR && intro_curtime == 5*TICRATE)
patch = W_CachePatchName("RADAR", PU_PATCH_LOWPRIORITY);
else if (intro_scenenum == INTRO_GRASS2 && intro_curtime == 6*TICRATE)
patch = W_CachePatchName("SGRASS2", PU_PATCH_LOWPRIORITY);
else if (intro_scenenum == INTRO_SONICDO2 && intro_curtime == 7*TICRATE)
{
patch = W_CachePatchName("SONICDO2", PU_PATCH_LOWPRIORITY);
x = 224;
y = 8;
}
else
return;
F_WipeStartScreen();
V_DrawSmallScaledPatch(0, 0, 0, patch);
W_UnlockCachedPatch(patch);
V_DrawString(x, y, V_ALLOWLOWERCASE, cutscene_disptext);
F_WipeEndScreenRestore();
wipestyle = WIPESTYLE_NORMAL;
F_StartWipe(99, true);
timetonext--;
}
#define F_IntroSceneCrossfades(scene) ((scene) != INTRO_STJR && (scene) != INTRO_SKYRUNNER && (scene) != INTRO_LAST)
static void F_IntroSpecialWipe(INT32 scene)
{
wipestyleflags = WSF_FADEOUT;
switch (scene)
{
case INTRO_STJR:
wipestyleflags |= WSF_INTROSTART;
break;
case INTRO_SKYRUNNER:
wipestyleflags |= WSF_TOWHITE;
break;
case INTRO_LAST:
wipestyleflags |= WSF_INTROEND;
break;
}
F_WipeStartScreen();
F_WipeDoTinted();
F_WipeEndScreenRestore();
F_StartWipe(99, true);
WipeRunPost = true;
}
//
// F_IntroTicker
//
@ -856,92 +913,26 @@ void F_IntroTicker(void)
wipestyleflags = WSF_CROSSFADE;
if (timetonext <= 0)
INT32 lastscene = intro_scenenum;
boolean next = timetonext <= 0;
if (next)
{
if (intro_scenenum == 0)
if (rendermode == render_none && intro_scenenum == INTRO_LAST)
{
if (rendermode != render_none)
{
wipestyleflags = WSF_FADEOUT;
F_WipeStartScreen();
F_TryColormapFade(31);
F_IntroDrawer();
F_WipeEndScreen();
F_RunWipe(99,true);
}
S_ChangeMusicInternal("_intro", false);
}
else if (intro_scenenum == 10)
{
if (rendermode != render_none)
{
wipestyleflags = (WSF_FADEOUT|WSF_TOWHITE);
F_WipeStartScreen();
F_TryColormapFade(0);
F_IntroDrawer();
F_WipeEndScreen();
F_RunWipe(99,true);
}
}
else if (intro_scenenum == 16)
{
if (rendermode != render_none)
{
wipestyleflags = WSF_FADEOUT;
F_WipeStartScreen();
F_TryColormapFade(31);
F_IntroDrawer();
F_WipeEndScreen();
F_RunWipe(99,true);
}
// Stay on black for a bit. =)
{
tic_t nowtime, quittime, lasttime;
nowtime = lasttime = I_GetTime();
quittime = nowtime + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds
while (quittime > nowtime)
{
while (!((nowtime = I_GetTime()) - lasttime))
{
I_Sleep(cv_sleep.value);
I_UpdateTime(cv_timescale.value);
}
lasttime = nowtime;
I_OsPolling();
I_UpdateNoBlit();
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of wipes
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
}
}
D_StartTitle();
wipegamestate = GS_INTRO;
return;
}
if (F_IntroSceneCrossfades(intro_scenenum))
{
F_WipeDoCrossfade();
next = false;
}
F_NewCutscene(introtext[++intro_scenenum]);
timetonext = introscenetime[intro_scenenum];
F_WipeStartScreen();
wipegamestate = -1;
animtimer = stoptimer = 0;
}
@ -949,36 +940,15 @@ void F_IntroTicker(void)
if (rendermode != render_none)
{
if (intro_scenenum == 0 && intro_curtime == 2*TICRATE-19)
if (next)
{
S_ChangeMusicInternal("_stjr", false);
wipestyleflags = WSF_FADEIN;
F_WipeStartScreen();
F_TryColormapFade(31);
F_IntroDrawer();
F_WipeEndScreen();
F_RunWipe(99,true);
F_IntroSpecialWipe(lastscene);
return;
}
else if ((intro_scenenum == 5 && intro_curtime == 5*TICRATE)
|| (intro_scenenum == 7 && intro_curtime == 6*TICRATE)
//|| (intro_scenenum == 11 && intro_curtime == 7*TICRATE)
|| (intro_scenenum == 15 && intro_curtime == 7*TICRATE))
{
F_WipeStartScreen();
F_WipeColorFill(31);
F_IntroDrawer();
F_WipeEndScreen();
F_RunWipe(99,true);
}
F_IntroMidSceneWipe();
F_IntroDrawer();
}
if (animtimer)
animtimer--;
}
//
@ -1764,7 +1734,7 @@ static void F_CacheGoodEnding(void)
void F_StartEnding(void)
{
G_SetGamestate(GS_ENDING);
wipetypepost = INT16_MAX;
wipetypepost = IGNOREWIPE;
// Just in case they're open ... somehow
M_ClearMenus(true);
@ -1788,7 +1758,7 @@ void F_EndingTicker(void)
if (++finalecount > STOPPINGPOINT)
{
F_StartCredits();
wipetypepre = INT16_MAX;
wipetypepre = IGNOREWIPE;
return;
}
@ -2425,8 +2395,6 @@ void F_StartTitleScreen(void)
if (titlemap)
{
mapthing_t *startpos;
gamestate_t prevwipegamestate = wipegamestate;
titlemapinaction = TITLEMAP_LOADING;
titlemapcameraref = NULL;
@ -2438,42 +2406,10 @@ void F_StartTitleScreen(void)
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
globalweather = mapheaderinfo[gamemap-1]->weather;
G_DoLoadLevel(true);
G_StartLevel(true);
if (!titlemap)
return;
players[displayplayer].playerstate = PST_DEAD; // Don't spawn the player in dummy (I'm still a filthy cheater)
// Set Default Position
if (playerstarts[0])
startpos = playerstarts[0];
else if (deathmatchstarts[0])
startpos = deathmatchstarts[0];
else
startpos = NULL;
if (startpos)
{
camera.x = startpos->x << FRACBITS;
camera.y = startpos->y << FRACBITS;
camera.subsector = R_PointInSubsector(camera.x, camera.y);
camera.z = camera.subsector->sector->floorheight + (startpos->z << FRACBITS);
camera.angle = (startpos->angle % 360)*ANG1;
camera.aiming = 0;
}
else
{
camera.x = camera.y = camera.z = camera.angle = camera.aiming = 0;
camera.subsector = NULL; // toast is filthy too
}
camera.chase = true;
camera.height = 0;
// Run enter linedef exec for MN_MAIN, since this is where we start
if (menupres[MN_MAIN].entertag)
P_LinedefExecute(menupres[MN_MAIN].entertag, players[displayplayer].mo, NULL);
wipegamestate = prevwipegamestate;
}
else
@ -3850,8 +3786,8 @@ static void F_AdvanceToNextScene(void)
{
V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,cutscenes[cutnum]->scene[scenenum].fadecolor);
F_WipeEndScreen();
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeinid, true);
F_WipeEndScreenRestore();
F_StartWipe(cutscenes[cutnum]->scene[scenenum].fadeinid, true);
F_WipeStartScreen();
}
@ -3895,7 +3831,7 @@ static void F_AdvanceToNextScene(void)
F_CutsceneDrawer();
F_WipeEndScreen();
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true);
F_StartWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true);
}
}
@ -4448,7 +4384,7 @@ void F_TextPromptDrawer(void)
// Data
patch_t *patch;
if (!promptactive)
if (!promptactive || titlecard.prelevel)
return;
iconlump = W_CheckNumForName(textprompts[cutnum]->page[scenenum].iconname);

View file

@ -18,6 +18,7 @@
#include "doomtype.h"
#include "d_event.h"
#include "p_mobj.h"
#include "screen.h"
//
// FINALE
@ -82,6 +83,23 @@ extern INT32 finalecount;
extern INT32 titlescrollxspeed;
extern INT32 titlescrollyspeed;
extern INT32 intro_scenenum;
enum
{
INTRO_STJR = 0,
INTRO_FIRST = 1,
INTRO_ASTEROID = 4,
INTRO_RADAR = 5,
INTRO_GRASS1 = 6,
INTRO_GRASS2 = 7,
INTRO_SKYRUNNER = 10,
INTRO_SONICDO1 = 14,
INTRO_SONICDO2 = 15,
INTRO_LAST = 16
};
typedef enum
{
TTMODE_NONE = 0,
@ -103,7 +121,6 @@ extern INT16 ttloop;
extern UINT16 tttics;
extern boolean ttavailable[6];
typedef enum
{
TITLEMAP_OFF = 0,
@ -112,7 +129,6 @@ typedef enum
} titlemap_enum;
// Current menu parameters
extern mobj_t *titlemapcameraref;
extern char curbgname[9];
extern SINT8 curfadevalue;
@ -125,6 +141,7 @@ extern boolean hidetitlemap;
extern boolean curhidepics;
extern ttmode_enum curttmode;
extern UINT8 curttscale;
// ttmode user vars
extern char curttname[9];
extern INT16 curttx;
@ -138,17 +155,28 @@ void F_InitMenuPresValues(void);
void F_MenuPresTicker(void);
//
// WIPE
// WIPES
//
#if NUMSCREENS < 5
#define NOWIPE // do not enable wipe image post processing for ARM, SH and MIPS CPUs
#endif
#define DEFAULTWIPE -1
#define IGNOREWIPE INT16_MAX
// HACK for menu fading while titlemapinaction; skips the level check
#define FORCEWIPE -3
#define FORCEWIPEOFF -2
extern boolean WipeInAction;
extern boolean WipeStageTitle;
extern boolean WipeRunPre;
extern boolean WipeRunPost;
extern boolean WipeDrawMenu;
typedef enum
{
WIPESTYLE_UNDEFINED,
WIPESTYLE_NORMAL,
WIPESTYLE_COLORMAP
} wipestyle_t;
@ -156,19 +184,47 @@ extern wipestyle_t wipestyle;
typedef enum
{
WSF_FADEOUT = 1,
WSF_FADEIN = 1<<1,
WSF_TOWHITE = 1<<2,
WSF_CROSSFADE = 1<<3,
WSF_FADEOUT = 1,
WSF_FADEIN = 1<<1,
WSF_TOWHITE = 1<<2,
WSF_CROSSFADE = 1<<3,
WSF_LEVELLOADING = 1<<4,
WSF_SPECIALSTAGE = 1<<5,
WSF_INTROSTART = 1<<6,
WSF_INTROEND = 1<<7,
WSF_ACTION = (WSF_LEVELLOADING|WSF_SPECIALSTAGE|WSF_INTROSTART|WSF_INTROEND)
} wipestyleflags_t;
extern wipestyleflags_t wipestyleflags;
// Even my function names are borderline
boolean F_ShouldColormapFade(void);
boolean F_TryColormapFade(UINT8 wipecolor);
#ifndef NOWIPE
void F_DecideWipeStyle(void);
#endif
typedef enum
{
SPECIALWIPE_NONE,
SPECIALWIPE_SSTAGE,
SPECIALWIPE_RETRY,
} specialwipe_t;
extern specialwipe_t ranspecialwipe;
extern UINT8 wipetype;
extern UINT8 wipeframe;
void F_WipeSetStyle(void);
void F_WipeStartScreen(void);
void F_WipeEndScreen(void);
void F_WipeEndScreenRestore(void);
void F_StartWipe(UINT8 type, boolean drawMenu);
void F_RunWipe(void);
void F_DisplayWipe(void);
void F_StopWipe(void);
void F_WipeStartPre(void);
void F_WipeStartPost(void);
void F_WipeDoCrossfade(void);
boolean F_WipeDoTinted(void);
#define F_WipeColorFill(c) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, c)
#define FADECOLORMAPDIV 8
#define FADECOLORMAPROWS (256/FADECOLORMAPDIV)
@ -177,19 +233,9 @@ void F_DecideWipeStyle(void);
#define FADEGREENFACTOR 15
#define FADEBLUEFACTOR 10
extern INT32 lastwipetic;
// Don't know where else to place this constant
// But this file seems appropriate
#define PRELEVELTIME 24 // frames in tics
void F_WipeStartScreen(void);
void F_WipeEndScreen(void);
void F_RunWipe(UINT8 wipetype, boolean drawMenu);
void F_WipeStageTitle(void);
#define F_WipeColorFill(c) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, c)
tic_t F_GetWipeLength(UINT8 wipetype);
boolean F_WipeExists(UINT8 wipetype);
tic_t F_GetWipeLength(UINT8 type);
boolean F_WipeExists(UINT8 type);
boolean F_WipeCanTint(void);
enum
{

View file

@ -16,6 +16,7 @@
#include "i_video.h"
#include "v_video.h"
#include "r_main.h" // framecount
#include "r_state.h" // fadecolormap
#include "r_draw.h" // transtable
#include "p_pspr.h" // tr_transxxx
@ -26,11 +27,11 @@
#include "i_time.h"
#include "i_system.h"
#include "i_threads.h"
#include "m_menu.h"
#include "console.h"
#include "d_main.h"
#include "g_game.h"
#include "y_inter.h" // intertype
#include "m_misc.h" // movie mode
#include "doomstat.h"
@ -41,10 +42,6 @@
#include "hardware/hw_main.h"
#endif
#if NUMSCREENS < 5
#define NOWIPE // do not enable wipe image post processing for ARM, SH and MIPS CPUs
#endif
typedef struct fademask_s {
UINT8* mask;
UINT16 width, height;
@ -92,11 +89,18 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
//--------------------------------------------------------------------------
boolean WipeInAction = false;
boolean WipeStageTitle = false;
INT32 lastwipetic = 0;
boolean WipeRunPre = false;
boolean WipeRunPost = false;
boolean WipeDrawMenu = false;
wipestyle_t wipestyle = WIPESTYLE_NORMAL;
UINT8 wipetype = 0;
UINT8 wipeframe = 0;
wipestyle_t wipestyle = WIPESTYLE_UNDEFINED;
wipestyleflags_t wipestyleflags = WSF_CROSSFADE;
specialwipe_t ranspecialwipe = SPECIALWIPE_NONE;
static INT32 wipedefindex = 0;
#ifndef NOWIPE
static UINT8 *wipe_scr_start; //screen 3
@ -110,7 +114,7 @@ static fixed_t paldiv = 0;
* \return fademask_t for lump
*/
static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) {
static char lumpname[10] = "FADEmmss";
static char lumpname[11] = "FADEmmss";
static fademask_t fm = {NULL,0,0,0,0,0};
lumpnum_t lumpnum;
UINT8 *lump, *mask;
@ -186,20 +190,6 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) {
return NULL;
}
/** Draw the stage title.
*/
void F_WipeStageTitle(void)
{
// draw level title
if ((WipeStageTitle && st_overlay)
&& (wipestyle == WIPESTYLE_COLORMAP)
&& G_IsTitleCardAvailable())
{
ST_runTitleCard();
ST_drawWipeTitleCard();
}
}
/** Wipe ticker
*
* \param fademask pixels to change
@ -427,99 +417,122 @@ static void F_DoColormapWipe(fademask_t *fademask, UINT8 *colormap)
}
#endif
/** Save the "before" screen of a wipe.
/** Saves the "before" screen of a wipe.
*/
void F_WipeStartScreen(void)
{
#ifndef NOWIPE
#ifdef HWRENDER
if(rendermode != render_soft)
if (rendermode == render_opengl)
{
HWR_StartScreenWipe();
return;
}
#endif
wipe_scr_start = screens[3];
I_ReadScreen(wipe_scr_start);
#endif
}
/** Save the "after" screen of a wipe.
/** Saves the "after" screen of a wipe.
*/
void F_WipeEndScreen(void)
{
#ifndef NOWIPE
#ifdef HWRENDER
if(rendermode != render_soft)
if (rendermode == render_opengl)
{
HWR_EndScreenWipe();
HWR_EndScreenWipe(false);
return;
}
#endif
wipe_scr_end = screens[4];
I_ReadScreen(wipe_scr_end);
V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start);
#endif
}
/** Verifies every condition for a colormapped fade.
/** Saves the "after" screen of a wipe, and copies the "before" screen into the main screen.
*/
boolean F_ShouldColormapFade(void)
void F_WipeEndScreenRestore(void)
{
#ifndef NOWIPE
#ifdef HWRENDER
if (rendermode == render_opengl)
{
HWR_EndScreenWipe(true);
return;
}
#endif
F_WipeEndScreen();
VID_BlitLinearScreen(screens[3], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
#endif
}
/** Verifies every condition for a tinted fade.
*/
boolean F_WipeCanTint(void)
{
if ((wipestyleflags & (WSF_FADEIN|WSF_FADEOUT)) // only if one of those wipestyleflags are actually set
&& !(wipestyleflags & WSF_CROSSFADE)) // and if not crossfading
{
// World
return (gamestate == GS_LEVEL
|| gamestate == GS_TITLESCREEN
// Finales
|| gamestate == GS_CONTINUING
|| gamestate == GS_CREDITS
|| gamestate == GS_EVALUATION
|| gamestate == GS_INTRO
|| gamestate == GS_ENDING
// Menus
|| gamestate == GS_TIMEATTACK);
switch (gamestate)
{
case GS_LEVEL:
case GS_TITLESCREEN:
case GS_CONTINUING:
case GS_CREDITS:
case GS_EVALUATION:
case GS_ENDING:
case GS_TIMEATTACK:
return true;
case GS_INTRO:
return (intro_scenenum <= INTRO_FIRST);
default:
return false;
}
}
#endif
return false;
}
/** Decides what wipe style to use.
*/
#ifndef NOWIPE
void F_DecideWipeStyle(void)
void F_WipeSetStyle(void)
{
// Set default wipe style
wipestyle = WIPESTYLE_NORMAL;
// Check for colormap wipe style
if (F_ShouldColormapFade())
if (F_WipeCanTint())
wipestyle = WIPESTYLE_COLORMAP;
}
#endif
/** Attempt to run a colormap fade,
provided all the conditionals were properly met.
Returns true if so.
I demand you call F_RunWipe after this function.
/** Attempts to run a tinted fade.
*
* \return if true, a tinted fade can run
*/
boolean F_TryColormapFade(UINT8 wipecolor)
boolean F_WipeDoTinted(void)
{
#ifndef NOWIPE
if (F_ShouldColormapFade())
UINT8 color = (wipestyleflags & WSF_TOWHITE) ? 0 : 31;
#endif
if (F_WipeCanTint())
{
#ifdef HWRENDER
#if !defined(NOWIPE) && defined(HWRENDER)
if (rendermode == render_opengl)
F_WipeColorFill(wipecolor);
F_WipeColorFill(color);
#endif
return true;
}
else
#endif
{
F_WipeColorFill(wipecolor);
#ifndef NOWIPE
F_WipeColorFill(color);
#endif
return false;
}
}
@ -527,44 +540,135 @@ boolean F_TryColormapFade(UINT8 wipecolor)
/** After setting up the screens you want to wipe,
* calling this will do a 'typical' wipe.
*/
void F_RunWipe(UINT8 wipetype, boolean drawMenu)
void F_StartWipe(UINT8 type, boolean drawMenu)
{
#ifdef NOWIPE
(void)wipetype;
(void)type;
(void)drawMenu;
#else
tic_t nowtime;
UINT8 wipeframe = 0;
fademask_t *fmask;
if (!paldiv)
paldiv = FixedDiv(257<<FRACBITS, 11<<FRACBITS);
// Init the wipe
F_DecideWipeStyle();
if (wipestyle == WIPESTYLE_UNDEFINED)
F_WipeSetStyle();
WipeInAction = true;
wipe_scr = screens[0];
WipeDrawMenu = drawMenu;
// lastwipetic should either be 0 or the tic we last wiped
// on for fade-to-black
for (;;)
wipetype = type;
wipeframe = 0;
#endif
}
/** Runs the current wipe.
*/
void F_RunWipe(void)
{
#ifndef NOWIPE
fademask_t *fmask = F_GetFadeMask(wipetype, wipeframe);
if (!fmask)
{
// get fademask first so we can tell if it exists or not
fmask = F_GetFadeMask(wipetype, wipeframe++);
if (!fmask)
break;
F_StopWipe();
return;
}
// wait loop
while (!((nowtime = I_GetTime()) - lastwipetic))
wipeframe++;
#else
F_StopWipe();
#endif
}
/** Stops running the current wipe.
*/
void F_StopWipe(void)
{
// TODO maybe just add callbacks instead
boolean runtitle = (wipestyleflags & WSF_INTROEND);
WipeInAction = false;
WipeDrawMenu = false;
if (titlecard.wipe)
titlecard.wipe = 0;
if (wipestyleflags & WSF_SPECIALSTAGE)
{
// #ifndef NOWIPE
#if 0
tic_t starttime = I_GetTime(), lasttime = starttime;
tic_t endtime = starttime + (3*TICRATE)/2;
tic_t nowtime = starttime;
// Hold on white for extra effect.
// TODO don't do this lol
while (nowtime < endtime)
{
I_Sleep(cv_sleep.value);
I_UpdateTime(cv_timescale.value);
while (!((nowtime = I_GetTime()) - lasttime))
I_Sleep();
lasttime = nowtime;
I_OsPolling();
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
}
lastwipetic = nowtime;
#endif
wipestyleflags &= ~WSF_SPECIALSTAGE;
}
// Wipe styles
if (wipestyle == WIPESTYLE_COLORMAP)
if (wipestyleflags & WSF_LEVELLOADING)
G_DoLoadLevel();
else if (wipestyleflags & WSF_INTROSTART)
S_ChangeMusicInternal("_intro", false);
wipestyleflags &= ~WSF_ACTION;
wipestyle = WIPESTYLE_UNDEFINED;
if (runtitle)
{
// #ifndef NOWIPE
#if 0
// Stay on black for a bit. =)
// TODO this neither
tic_t nowtime, quittime, lasttime;
nowtime = lasttime = I_GetTime();
quittime = nowtime + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds
while (quittime > nowtime)
{
while (!((nowtime = I_GetTime()) - lasttime))
I_Sleep();
lasttime = nowtime;
I_OsPolling();
I_UpdateNoBlit();
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of wipes
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
}
#endif
D_StartTitle();
wipegamestate = GS_INTRO;
}
}
#ifndef NOWIPE
/** Renders the current wipe into wipe_scr.
*/
static void F_RenderWipe(fademask_t *fmask)
{
switch (wipestyle)
{
case WIPESTYLE_COLORMAP:
#ifdef HWRENDER
if (rendermode == render_opengl)
{
@ -579,12 +683,8 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
colormap += (FADECOLORMAPROWS * 256);
F_DoColormapWipe(fmask, colormap);
}
// Draw the title card above the wipe
F_WipeStageTitle();
}
else
{
break;
case WIPESTYLE_NORMAL:
#ifdef HWRENDER
if (rendermode == render_opengl)
{
@ -594,78 +694,186 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
else
#endif
F_DoWipe(fmask);
}
break;
default:
break;
}
}
#endif
I_OsPolling();
I_UpdateNoBlit();
/** Displays the current wipe.
*/
void F_DisplayWipe(void)
{
#ifndef NOWIPE
fademask_t *fmask;
wipe_scr = screens[0];
if (drawMenu)
// get fademask first so we can tell if it exists or not
fmask = F_GetFadeMask(wipetype, wipeframe);
if (!fmask)
{
// Save screen for post-wipe
//if (WipeRunPre)
if (!(wipestyleflags & WSF_CROSSFADE))
{
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of wipes
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
fmask = F_GetFadeMask(wipetype, wipeframe-1);
WipeRunPre = false; // Disable post-wipe flag
if (!fmask)
return;
else
{
F_RenderWipe(fmask);
F_WipeStartScreen();
}
}
I_FinishUpdate(); // page flip or blit buffer
if (moviemode)
M_SaveFrame();
NetKeepAlive(); // Update the network so we don't cause timeouts
return;
}
WipeInAction = false;
WipeStageTitle = false;
F_RenderWipe(fmask);
#endif
}
/** Starts the "pre" type of a wipe.
*/
void F_WipeStartPre(void)
{
// set for all later
wipedefindex = gamestate; // wipe_xxx_toblack
if (gamestate == GS_INTERMISSION)
{
if (intertype == int_spec) // Special Stage
wipedefindex = wipe_specinter_toblack;
else if (intertype != int_coop) // Multiplayer
wipedefindex = wipe_multinter_toblack;
}
if (wipetypepre == DEFAULTWIPE || !F_WipeExists(wipetypepre))
wipetypepre = wipedefs[wipedefindex];
if (rendermode != render_none)
{
WipeRunPre = true;
// Fade to black first
if ((wipegamestate == (gamestate_t)FORCEWIPE ||
(wipegamestate != (gamestate_t)FORCEWIPEOFF
&& !(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
) // fades to black on its own timing, always
&& wipetypepre != UINT8_MAX)
{
F_WipeStartScreen();
// Do a tinted wipe.
wipestyleflags = WSF_FADEOUT;
if (wipegamestate == (gamestate_t)FORCEWIPE)
F_WipeColorFill(31);
else if (F_WipeDoTinted())
wipetypepost = DEFAULTWIPE;
F_WipeEndScreen();
F_StartWipe(wipetypepre, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN);
WipeRunPost = true;
}
}
wipetypepre = DEFAULTWIPE;
wipegamestate = gamestate;
}
/** Starts the "post" type of a wipe.
*/
void F_WipeStartPost(void)
{
wipedefindex += WIPEFINALSHIFT;
if (wipetypepost == DEFAULTWIPE || !F_WipeExists(wipetypepost))
wipetypepost = wipedefs[wipedefindex];
if (rendermode != render_none)
{
F_WipeEndScreen();
// Do a tinted wipe.
if (F_WipeCanTint())
{
wipestyleflags |= WSF_FADEIN;
wipestyleflags &= ~(WSF_FADEOUT|WSF_ACTION);
}
F_StartWipe(wipetypepost, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN);
}
// reset counters so timedemo doesn't count the wipe duration
if (timingdemo)
{
framecount = 0;
demostarttime = I_GetTime();
}
wipetypepost = DEFAULTWIPE;
WipeRunPost = false;
}
/** Does a crossfade.
*/
void F_WipeDoCrossfade(void)
{
// Set the wipe parameters
wipetypepost = wipedefs[gamestate + wipedefindex];
wipestyle = WIPESTYLE_NORMAL;
wipestyleflags = WSF_CROSSFADE;
// Capture the current screen. Last, if done during gamelogic.
F_WipeStartScreen();
WipeRunPost = true;
WipeInAction = false;
}
/** Returns tic length of wipe
* One lump equals one tic
*/
tic_t F_GetWipeLength(UINT8 wipetype)
tic_t F_GetWipeLength(UINT8 type)
{
#ifdef NOWIPE
(void)wipetype;
(void)type;
return 0;
#else
static char lumpname[10] = "FADEmmss";
static char lumpname[11] = "FADEmmss";
lumpnum_t lumpnum;
UINT8 wipeframe;
UINT8 frame;
if (wipetype > 99)
if (type > 99)
return 0;
for (wipeframe = 0; wipeframe < 100; wipeframe++)
for (frame = 0; frame < 100; frame++)
{
sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)wipetype, (UINT16)wipeframe);
sprintf(&lumpname[4], "%.2hu%.2hu", (UINT8)type, (UINT8)frame);
lumpnum = W_CheckNumForName(lumpname);
if (lumpnum == LUMPERROR)
return --wipeframe;
return --frame;
}
return --wipeframe;
return --frame;
#endif
}
/** Does the specified wipe exist?
*/
boolean F_WipeExists(UINT8 wipetype)
boolean F_WipeExists(UINT8 type)
{
#ifdef NOWIPE
(void)wipetype;
(void)type;
return false;
#else
static char lumpname[10] = "FADEmm00";
static char lumpname[11] = "FADEmm00";
lumpnum_t lumpnum;
if (wipetype > 99)
if (type > 99)
return false;
sprintf(&lumpname[4], "%.2hu00", (UINT16)wipetype);
sprintf(&lumpname[4], "%.2hu00", (UINT16)type);
lumpnum = W_CheckNumForName(lumpname);
return !(lumpnum == LUMPERROR);

View file

@ -60,6 +60,7 @@ boolean singledemo; // quit after playing a demo from cmdline
boolean demo_start; // don't start playing demo right away
boolean demo_forwardmove_rng; // old demo backwards compatibility
boolean demosynced = true; // console warning message
demoplayer_t *demoplayerinfo; // starting a demo
boolean metalrecording; // recording as metal sonic
mobj_t *metalplayback;
@ -1990,10 +1991,8 @@ void G_DoPlayDemo(char *defdemoname)
UINT8 i;
lumpnum_t l;
char skin[17],color[MAXCOLORNAME+1],*n,*pdemoname;
UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration;
pflags_t pflags;
UINT32 randseed, followitem;
fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight;
UINT8 version,subversion;
UINT32 randseed;
char msg[1024];
skin[16] = '\0';
@ -2189,35 +2188,47 @@ void G_DoPlayDemo(char *defdemoname)
M_Memcpy(color, demo_p, (demoversion < 0x000d) ? 16 : MAXCOLORNAME);
demo_p += (demoversion < 0x000d) ? 16 : MAXCOLORNAME;
charability = READUINT8(demo_p);
charability2 = READUINT8(demo_p);
actionspd = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
mindash = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
maxdash = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
normalspeed = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
runspeed = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
thrustfactor = READUINT8(demo_p);
accelstart = READUINT8(demo_p);
acceleration = READUINT8(demo_p);
height = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
spinheight = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
camerascale = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
shieldscale = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
jumpfactor = READFIXED(demo_p);
followitem = READUINT32(demo_p);
demoplayer_t *info = Z_Calloc(sizeof(demoplayer_t), PU_STATIC, NULL);
info->charability = READUINT8(demo_p);
info->charability2 = READUINT8(demo_p);
info->actionspd = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
info->mindash = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
info->maxdash = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
info->normalspeed = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
info->runspeed = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
info->thrustfactor = READUINT8(demo_p);
info->accelstart = READUINT8(demo_p);
info->acceleration = READUINT8(demo_p);
info->height = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
info->spinheight = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
info->camerascale = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
info->shieldscale = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
info->jumpfactor = READFIXED(demo_p);
info->followitem = READUINT32(demo_p);
// Set color
info->color = SKINCOLOR_NONE;
for (i = 0; i < numskincolors; i++)
if (!stricmp(skincolors[i].name,color))
{
info->color = i;
break;
}
demoplayerinfo = info;
// pflag data
{
UINT8 buf = READUINT8(demo_p);
pflags = 0;
info->pflags = 0;
if (buf & 0x01)
pflags |= PF_FLIPCAM;
info->pflags |= PF_FLIPCAM;
if (buf & 0x02)
pflags |= PF_ANALOGMODE;
info->pflags |= PF_ANALOGMODE;
if (buf & 0x04)
pflags |= PF_DIRECTIONCHAR;
info->pflags |= PF_DIRECTIONCHAR;
if (buf & 0x08)
pflags |= PF_AUTOBRAKE;
info->pflags |= PF_AUTOBRAKE;
CV_SetValue(&cv_showinputjoy, !!(buf & 0x10));
}
@ -2239,6 +2250,8 @@ void G_DoPlayDemo(char *defdemoname)
Z_Free(demobuffer);
demoplayback = false;
titledemo = false;
Z_Free(demoplayerinfo);
demoplayerinfo = NULL;
return;
}
@ -2262,15 +2275,17 @@ void G_DoPlayDemo(char *defdemoname)
playeringame[0] = true;
P_SetRandSeed(randseed);
G_InitNew(false, G_BuildMapName(gamemap), true, true, false);
}
void G_FinishLoadingDemo(void)
{
demoplayer_t *p = demoplayerinfo;
demo_start = true;
if (p == NULL)
return;
// Set color
players[0].skincolor = skins[players[0].skin].prefcolor;
for (i = 0; i < numskincolors; i++)
if (!stricmp(skincolors[i].name,color))
{
players[0].skincolor = i;
break;
}
players[0].skincolor = p->color;
if (players[0].mo)
{
players[0].mo->color = players[0].skincolor;
@ -2282,25 +2297,23 @@ void G_DoPlayDemo(char *defdemoname)
// Set saved attribute values
// No cheat checking here, because even if they ARE wrong...
// it would only break the replay if we clipped them.
players[0].camerascale = camerascale;
players[0].shieldscale = shieldscale;
players[0].charability = charability;
players[0].charability2 = charability2;
players[0].actionspd = actionspd;
players[0].mindash = mindash;
players[0].maxdash = maxdash;
players[0].normalspeed = normalspeed;
players[0].runspeed = runspeed;
players[0].thrustfactor = thrustfactor;
players[0].accelstart = accelstart;
players[0].acceleration = acceleration;
players[0].height = height;
players[0].spinheight = spinheight;
players[0].jumpfactor = jumpfactor;
players[0].followitem = followitem;
players[0].pflags = pflags;
demo_start = true;
players[0].camerascale = p->camerascale;
players[0].shieldscale = p->shieldscale;
players[0].charability = p->charability;
players[0].charability2 = p->charability2;
players[0].actionspd = p->actionspd;
players[0].mindash = p->mindash;
players[0].maxdash = p->maxdash;
players[0].normalspeed = p->normalspeed;
players[0].runspeed = p->runspeed;
players[0].thrustfactor = p->thrustfactor;
players[0].accelstart = p->accelstart;
players[0].acceleration = p->acceleration;
players[0].height = p->height;
players[0].spinheight = p->spinheight;
players[0].jumpfactor = p->jumpfactor;
players[0].followitem = p->followitem;
players[0].pflags = p->pflags;
}
//
@ -2858,6 +2871,10 @@ void G_StopDemo(void)
timingdemo = false;
singletics = false;
if (demoplayerinfo)
Z_Free(demoplayerinfo);
demoplayerinfo = NULL;
if (gamestate == GS_INTERMISSION)
Y_EndIntermission(); // cleanup

View file

@ -41,6 +41,16 @@ extern boolean demo_start;
extern boolean demo_forwardmove_rng;
extern boolean demosynced;
typedef struct
{
UINT8 charability,charability2,thrustfactor,accelstart,acceleration;
pflags_t pflags;
UINT32 followitem;
fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight;
INT32 color;
} demoplayer_t;
extern demoplayer_t *demoplayerinfo;
extern mobj_t *metalplayback;
// Only called by startup code.
@ -95,6 +105,7 @@ void G_LoadMetal(UINT8 **buffer);
void G_DeferedPlayDemo(const char *demo);
void G_DoPlayDemo(char *defdemoname);
void G_FinishLoadingDemo(void);
void G_TimeDemo(const char *name);
void G_AddGhost(char *defdemoname);
void G_FreeGhosts(void);

View file

@ -78,6 +78,9 @@ static void G_DoStartContinue(void);
static void G_DoContinued(void);
static void G_DoWorldDone(void);
static void G_CheckPlayerReborn(void);
static inline void G_TickerEnd(void);
char mapmusname[7]; // Music name
UINT16 mapmusflags; // Track and reset bit
UINT32 mapmusposition; // Position to jump to
@ -125,10 +128,15 @@ INT32 secondarydisplayplayer; // for splitscreen
tic_t gametic;
tic_t levelstarttic; // gametic at level start
boolean levelstarting; // starting the level
boolean levelresetplayer; // reset players at level load
UINT32 ssspheres; // old special stage
INT16 lastmap; // last level you were at (returning from special stages)
tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
titlecard_t titlecard;
INT16 spstage_start, spmarathon_start;
INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
@ -175,8 +183,7 @@ struct quake quake;
mapheader_t* mapheaderinfo[NUMMAPS] = {NULL};
static boolean exitgame = false;
static boolean retrying = false;
static boolean retryingmodeattack = false;
static boolean retrying[RETRY_MAX];
boolean stagefailed = false; // Used for GEMS BONUS? Also to see if you beat the stage.
@ -1171,9 +1178,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
!player->climbing && player->powers[pw_carry] != CR_MINECART;
// why build a ticcmd if we're paused?
// Or, if the level is starting.
// Or, for that matter, if we're being reborn.
// ...OR if we're blindfolded. No looking into the floor.
if (ignoregameinputs || paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG)
if (ignoregameinputs || paused || P_AutoPause() || (levelstarting || WipeInAction) || titlecard.prelevel
|| (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG)
&& (leveltime < hidetime * TICRATE) && (player->pflags & PF_TAGIT)))))
{//@TODO splitscreen player
cmd->angleturn = ticcmd_oldangleturn[forplayer];
@ -1832,17 +1841,19 @@ static void AutoBrake2_OnChange(void)
}
//
// G_DoLoadLevel
// G_StartLevel
//
void G_DoLoadLevel(boolean resetplayer)
void G_StartLevel(boolean resetplayer)
{
INT32 i;
levelstarting = true;
// Make sure objectplace is OFF when you first start the level!
OP_ResetObjectplace();
demosynced = true;
levelstarttic = gametic; // for time calculation
levelresetplayer = resetplayer;
if (wipegamestate == GS_LEVEL)
wipegamestate = -1; // force a wipe
@ -1850,6 +1861,57 @@ void G_DoLoadLevel(boolean resetplayer)
if (gamestate == GS_INTERMISSION)
Y_EndIntermission();
G_InitLevelGametype();
ranspecialwipe = SPECIALWIPE_NONE;
if (mapheaderinfo[gamemap-1]->runsoc[0] != '#')
P_RunSOC(mapheaderinfo[gamemap-1]->runsoc);
if (cv_runscripts.value && mapheaderinfo[gamemap-1]->scriptname[0] != '#')
P_RunLevelScript(mapheaderinfo[gamemap-1]->scriptname);
// clear cmd building stuff
memset(gamekeydown, 0, sizeof (gamekeydown));
for (i = 0;i < JOYAXISSET; i++)
{
joyxmove[i] = joyymove[i] = 0;
joy2xmove[i] = joy2ymove[i] = 0;
}
G_SetMouseDeltas(0, 0, 1);
G_SetMouseDeltas(0, 0, 2);
#ifndef NOWIPE
if (!G_GetRetryRA() && rendermode != render_none)
G_StartLevelWipe();
else
#endif
{
if (G_GetRetryRA())
{
ranspecialwipe = SPECIALWIPE_RETRY;
G_ClearRetryRA();
}
G_DoLoadLevel();
}
}
//
// G_InitLevelGametype
//
void G_InitLevelGametype(void)
{
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
gametyperules = gametypedefaultrules[gametype];
}
//
// G_DoLoadLevel
//
void G_DoLoadLevel(void)
{
G_ClearAllRetryFlags();
// cleanup
if (titlemapinaction == TITLEMAP_LOADING)
{
@ -1865,15 +1927,23 @@ void G_DoLoadLevel(boolean resetplayer)
else
titlemapinaction = TITLEMAP_OFF;
G_SetGamestate(GS_LEVEL);
I_UpdateMouseGrab();
for (i = 0; i < MAXPLAYERS; i++)
if (!titlemapinaction)
{
if (resetplayer || (playeringame[i] && players[i].playerstate == PST_DEAD))
players[i].playerstate = PST_REBORN;
INT32 i;
G_SetGamestate(GS_LEVEL);
for (i = 0; i < MAXPLAYERS; i++)
{
if (levelresetplayer || (playeringame[i] && players[i].playerstate == PST_DEAD))
players[i].playerstate = PST_REBORN;
}
}
levelstarting = false;
// Setup the level.
if (!P_LoadLevel(false, false)) // this never returns false?
{
@ -1882,6 +1952,19 @@ void G_DoLoadLevel(boolean resetplayer)
return;
}
if (netgame)
{
char *title = G_BuildMapTitle(gamemap);
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
if (title)
{
CONS_Printf(": %s", title);
Z_Free(title);
}
CONS_Printf("\"\n");
}
P_FindEmerald();
displayplayer = consoleplayer; // view the guy you are playing
@ -1893,81 +1976,243 @@ void G_DoLoadLevel(boolean resetplayer)
Z_CheckHeap(-2);
#endif
if (camera.chase)
P_ResetCamera(&players[displayplayer], &camera);
if (camera2.chase && splitscreen)
P_ResetCamera(&players[secondarydisplayplayer], &camera2);
// clear cmd building stuff
memset(gamekeydown, 0, sizeof (gamekeydown));
for (i = 0;i < JOYAXISSET; i++)
if (!titlemapinaction)
{
joyxmove[i] = joyymove[i] = 0;
joy2xmove[i] = joy2ymove[i] = 0;
if (camera.chase)
P_ResetCamera(&players[displayplayer], &camera);
if (camera2.chase && splitscreen)
P_ResetCamera(&players[secondarydisplayplayer], &camera2);
}
else
{
mapthing_t *startpos;
players[displayplayer].playerstate = PST_DEAD; // Don't spawn the player in dummy (I'm still a filthy cheater)
// Set Default Position
if (playerstarts[0])
startpos = playerstarts[0];
else if (deathmatchstarts[0])
startpos = deathmatchstarts[0];
else
startpos = NULL;
if (startpos)
{
camera.x = startpos->x << FRACBITS;
camera.y = startpos->y << FRACBITS;
camera.subsector = R_PointInSubsector(camera.x, camera.y);
camera.z = camera.subsector->sector->floorheight + (startpos->z << FRACBITS);
camera.angle = (startpos->angle % 360)*ANG1;
camera.aiming = 0;
}
else
{
camera.x = camera.y = camera.z = camera.angle = camera.aiming = 0;
camera.subsector = NULL; // toast is filthy too
}
camera.chase = true;
camera.height = 0;
// Run enter linedef exec for MN_MAIN, since this is where we start
if (menupres[MN_MAIN].entertag)
P_LinedefExecute(menupres[MN_MAIN].entertag, players[displayplayer].mo, NULL);
}
if (demoplayerinfo)
{
G_FinishLoadingDemo();
Z_Free(demoplayerinfo);
}
demoplayerinfo = NULL;
G_SetMouseDeltas(0, 0, 1);
G_SetMouseDeltas(0, 0, 2);
// clear hud messages remains (usually from game startup)
CON_ClearHUD();
if (demoplayback && !timingdemo)
precache = true;
if (timingdemo)
G_DoneLevelLoad();
if (metalrecording)
G_BeginMetal();
if (demorecording) // Okay, level loaded, character spawned and skinned,
G_BeginRecording(); // I AM NOW READY TO RECORD.
demo_start = true;
}
//
// Run the level's wipe.
//
void G_StartLevelWipe(void)
{
// Cancel all d_main.c fades
WipeRunPost = false;
wipegamestate = FORCEWIPEOFF;
wipestyle = WIPESTYLE_COLORMAP;
wipestyleflags = (WSF_FADEOUT|WSF_LEVELLOADING);
// Special stage fade to white
// This is handled BEFORE sounds are stopped.
if (rendermode != render_none && G_IsSpecialStage(gamemap))
{
// TODO call this after rendering the frame (because of F_WipeStartScreen calls)
P_RunSpecialStageWipe();
ranspecialwipe = SPECIALWIPE_SSTAGE;
}
// Let's fade to black here
// But only if we didn't do the special stage wipe
if (rendermode != render_none && ranspecialwipe == SPECIALWIPE_NONE)
{
// TODO same thing as the last one
P_RunLevelWipe();
// Fade out music here. Deduct 2 tics so the fade volume actually reaches 0.
// But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug.
if (!titlemapinaction && (RESETMUSIC ||
strnicmp(S_MusicName(),
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7)))
S_FadeMusic(0, FixedMul(
FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE));
}
}
//
// Start the title card.
//
void G_StartTitleCard(void)
void TitleCard_Start(void)
{
// The title card has been disabled for this map.
// Oh well.
if (!G_IsTitleCardAvailable())
// The title card has been disabled for this map
if (!TitleCard_Available())
{
WipeStageTitle = false;
st_translucency = cv_translucenthud.value; // Reset the HUD translucency!
WipeRunPost = true; // Start the post wipe.
return;
}
// clear the hud
CON_ClearHUD();
TitleCard_LoadGraphics();
// prepare status bar
ST_startTitleCard();
// Actually start it
titlecard.running = true;
titlecard.prelevel = true;
// start the title card
WipeStageTitle = (!titlemapinaction);
titlecard.ticker = 0;
titlecard.exitticker = 0;
titlecard.endtime = 2*TICRATE + 10;
titlecard.scroll = BASEVIDWIDTH * FRACUNIT;
titlecard.momentum = 0;
if (titlecard.patches[1])
{
patch_t *patch = (patch_t *)titlecard.patches[1];
titlecard.zigzag = -(SHORT(patch->width) * FRACUNIT);
}
wipetypepost = IGNOREWIPE;
}
//
// Run the title card before fading in to the level.
// Load the graphics for the title card.
//
void G_PreLevelTitleCard(void)
void TitleCard_LoadGraphics(void)
{
#ifndef NOWIPE
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (PRELEVELTIME*NEWTICRATERATIO);
tic_t nowtime = starttime;
tic_t lasttime = starttime;
while (nowtime < endtime)
#define SETPATCH(def, warning, custom, idx) \
{ \
lumpnum_t patlumpnum = LUMPERROR; \
if (mapheaderinfo[gamemap-1]->custom[0] != '\0') \
{ \
patlumpnum = W_CheckNumForName(mapheaderinfo[gamemap-1]->custom); \
if (patlumpnum != LUMPERROR) \
titlecard.patches[idx] = (patch_t *)W_CachePatchNum(patlumpnum, PU_HUDGFX); \
} \
if (patlumpnum == LUMPERROR) \
{ \
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE)) \
titlecard.patches[idx] = (patch_t *)W_CachePatchName(def, PU_HUDGFX); \
else \
titlecard.patches[idx] = (patch_t *)W_CachePatchName(warning, PU_HUDGFX); \
} \
}
SETPATCH("LTACTBLU", "LTACTRED", ltactdiamond, 0)
SETPATCH("LTZIGZAG", "LTZIGRED", ltzzpatch, 1)
SETPATCH("LTZZTEXT", "LTZZWARN", ltzztext, 2)
#undef SETPATCH
}
//
// Run the title card.
//
void TitleCard_Run(void)
{
if (!TitleCard_Available())
return;
if (titlecard.wipe)
titlecard.wipe++;
if (titlecard.ticker >= (titlecard.endtime + TICRATE))
{
// draw loop
while (!((nowtime = I_GetTime()) - lasttime))
{
I_Sleep(cv_sleep.value);
I_UpdateTime(cv_timescale.value);
}
lasttime = nowtime;
ST_runTitleCard();
ST_preLevelTitleCardDrawer();
I_FinishUpdate(); // page flip or blit buffer
NetKeepAlive(); // Prevent timeouts
if (moviemode)
M_SaveFrame();
if (takescreenshot) // Only take screenshots after drawing.
M_DoScreenShot();
titlecard.running = false;
return;
}
else if (titlecard.ticker >= PRELEVELTIME && titlecard.prelevel)
{
// Force a wipe
wipegamestate = -1;
WipeRunPost = true;
// TODO should be done after rendering
if (!cv_showhud.value)
F_WipeDoCrossfade();
// Disable prelevel flag
titlecard.prelevel = false;
titlecard.wipe = 1;
}
if (!(paused || P_AutoPause()))
{
// scroll to screen (level title)
if (!titlecard.exitticker)
{
if (abs(titlecard.scroll) > FRACUNIT)
titlecard.scroll -= (titlecard.scroll>>2);
else
titlecard.scroll = 0;
}
// scroll away from screen (level title)
else
{
titlecard.momentum -= FRACUNIT*6;
titlecard.scroll += titlecard.momentum;
}
// scroll to screen (zigzag)
if (!titlecard.exitticker)
{
if (abs(titlecard.zigzag) > FRACUNIT)
titlecard.zigzag -= (titlecard.zigzag>>2);
else
titlecard.zigzag = 0;
}
// scroll away from screen (zigzag)
else
titlecard.zigzag += titlecard.momentum;
// tick
titlecard.ticker++;
if (titlecard.ticker >= titlecard.endtime)
titlecard.exitticker++;
}
if (!cv_showhud.value)
wipestyleflags = WSF_CROSSFADE;
#endif
}
static boolean titlecardforreload = false;
@ -1975,7 +2220,7 @@ static boolean titlecardforreload = false;
//
// Returns true if the current level has a title card.
//
boolean G_IsTitleCardAvailable(void)
boolean TitleCard_Available(void)
{
// The current level header explicitly disabled the title card.
UINT16 titleflag = LF_NOTITLECARDFIRST;
@ -1985,6 +2230,8 @@ boolean G_IsTitleCardAvailable(void)
else if (titlecardforreload)
titleflag = LF_NOTITLECARDRESPAWN;
titlecardforreload = false;
if (mapheaderinfo[gamemap-1]->levelflags & titleflag)
return false;
@ -2190,7 +2437,7 @@ boolean G_Responder(event_t *ev)
pausedelay = 1+(NEWTICRATE/2);
else if (cv_instantretry.value || ++pausedelay > 1+(NEWTICRATE/2)+(NEWTICRATE/3))
{
G_SetModeAttackRetryFlag();
G_SetRetryRA();
return true;
}
pausedelay++; // counteract subsequent subtraction this frame
@ -2269,11 +2516,29 @@ boolean G_LuaResponder(event_t *ev)
return cancelled;
}
// see also SCR_DisplayMarathonInfo
static void G_MarathonTicker(void)
{
if (gamestate != GS_LEVEL)
return;
if ((marathonmode & (MA_INIT|MA_INGAME)) != MA_INGAME)
return;
// IGT doesn't increase during loads, unless the game's paused
if (!(paused || P_AutoPause()))
{
if (titlecard.prelevel || WipeInAction)
return;
}
marathontime++;
}
//
// G_Ticker
// Make ticcmd_ts for the players.
//
void G_Ticker(boolean run)
void G_Ticker(boolean run, tic_t tics)
{
UINT32 i;
INT32 buf;
@ -2295,71 +2560,49 @@ void G_Ticker(boolean run)
}
}
// see also SCR_DisplayMarathonInfo
if ((marathonmode & (MA_INIT|MA_INGAME)) == MA_INGAME && gamestate == GS_LEVEL)
marathontime++;
P_MapStart();
// do player reborns if needed
if (gamestate == GS_LEVEL)
// Run the current wipe
if (WipeInAction)
{
// Or, alternatively, retry.
if (!(netgame || multiplayer) && G_GetRetryFlag())
if (run)
{
G_ClearRetryFlag();
boolean loading = (wipestyleflags & WSF_LEVELLOADING);
if (modeattacking)
switch (gamestate)
{
pausedelay = INT32_MIN;
M_ModeAttackRetry(0);
case GS_LEVEL:
if ((loading && G_GetRetryFlag(RETRY_PAUSED)) || !(paused || P_AutoPause()))
F_RunWipe();
break;
default:
F_RunWipe();
break;
}
else
{
// Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run.
if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime)
{
player_t *p = &players[consoleplayer];
marathonmode |= MA_INIT;
marathontime = 0;
numgameovers = tokenlist = token = 0;
countdown = countdown2 = exitfadestarted = 0;
// Run the title card
if (titlecard.running && (wipestyleflags & WSF_FADEIN))
TitleCard_Run();
p->playerstate = PST_REBORN;
p->starpostx = p->starposty = p->starpostz = 0;
// Run Marathon Mode in-game timer
G_MarathonTicker();
p->lives = startinglivesbalance[0];
p->continues = 1;
// do player reborns if needed
if (!loading)
G_CheckPlayerReborn();
p->score = p->recordscore = 0;
// The latter two should clear by themselves, but just in case
p->pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS);
// Clear cheatcodes too, just in case.
p->pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
p->xtralife = 0;
// Reset unlockable triggers
unlocktriggers = 0;
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
}
else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
players[consoleplayer].lives -= 1;
G_DoReborn(consoleplayer);
}
G_TickerEnd();
}
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].playerstate == PST_REBORN)
G_DoReborn(i);
return;
}
P_MapEnd();
// Oh my God I hope this doesn't implode anything
if (levelstarting || G_GetExitGameFlag())
return;
// Run Marathon Mode in-game timer
G_MarathonTicker();
// do player reborns if needed
G_CheckPlayerReborn();
// do things to change the game state
while (gameaction != ga_nothing)
@ -2418,6 +2661,16 @@ void G_Ticker(boolean run)
switch (gamestate)
{
case GS_LEVEL:
if (titlecard.running)
{
if (run && tics <= 1)
TitleCard_Run();
if (titlecard.prelevel)
{
G_CheckPlayerReborn();
break;
}
}
if (titledemo)
F_TitleDemoTicker();
P_Ticker(run); // tic the game
@ -2498,26 +2751,100 @@ void G_Ticker(boolean run)
}
if (run)
G_TickerEnd();
}
static inline void G_TickerEnd(void)
{
if (pausedelay && pausedelay != INT32_MIN)
{
if (pausedelay && pausedelay != INT32_MIN)
{
if (pausedelay > 0)
pausedelay--;
else
pausedelay++;
}
if (camtoggledelay)
camtoggledelay--;
if (camtoggledelay2)
camtoggledelay2--;
if (gametic % NAMECHANGERATE == 0)
{
memset(player_name_changes, 0, sizeof player_name_changes);
}
if (pausedelay > 0)
pausedelay--;
else
pausedelay++;
}
if (camtoggledelay)
camtoggledelay--;
if (camtoggledelay2)
camtoggledelay2--;
if (gametic % NAMECHANGERATE == 0)
{
memset(player_name_changes, 0, sizeof player_name_changes);
}
}
static void G_CheckPlayerReborn(void)
{
UINT32 i;
P_MapStart();
if (gamestate == GS_LEVEL)
{
// Or, alternatively, retry.
if (!(netgame || multiplayer) && G_GetRetrySP())
{
G_ClearRetrySP();
if (WipeInAction)
F_StopWipe();
if (modeattacking)
{
pausedelay = INT32_MIN;
M_ModeAttackRetry(0);
}
else
{
// Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run.
if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime)
{
player_t *p = &players[consoleplayer];
marathonmode |= MA_INIT;
marathontime = 0;
numgameovers = tokenlist = token = 0;
countdown = countdown2 = exitfadestarted = 0;
p->playerstate = PST_REBORN;
p->starpostx = p->starposty = p->starpostz = 0;
p->lives = startinglivesbalance[0];
p->continues = 1;
p->score = p->recordscore = 0;
// The latter two should clear by themselves, but just in case
p->pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS);
// Clear cheatcodes too, just in case.
p->pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
p->xtralife = 0;
// Reset unlockable triggers
unlocktriggers = 0;
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
}
else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
players[consoleplayer].lives -= 1;
G_DoReborn(consoleplayer);
}
}
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].playerstate == PST_REBORN)
G_DoReborn(i);
}
P_MapEnd();
}
//
@ -3217,8 +3544,8 @@ void G_DoReborn(INT32 playernum)
}
// Do a wipe
wipegamestate = -1;
wipestyleflags = WSF_CROSSFADE;
// TODO should be done after rendering
F_WipeDoCrossfade();
if (camera.chase)
P_ResetCamera(&players[displayplayer], &camera);
@ -3263,8 +3590,7 @@ void G_DoReborn(INT32 playernum)
{
LUA_HookInt(gamemap, HOOK(MapChange));
titlecardforreload = true;
G_DoLoadLevel(true);
titlecardforreload = false;
G_StartLevel(true);
if (metalrecording)
G_BeginMetal();
return;
@ -5126,6 +5452,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
ultimatemode = pultmode;
automapactive = false;
imcontinuing = false;
titlemapinaction = TITLEMAP_OFF;
if (reset_skin)
D_SendPlayerConfig();
@ -5146,20 +5473,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene.
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer, FLS);
else
G_DoLoadLevel(resetplayer);
if (netgame)
{
char *title = G_BuildMapTitle(gamemap);
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
if (title)
{
CONS_Printf(": %s", title);
Z_Free(title);
}
CONS_Printf("\"\n");
}
G_StartLevel(resetplayer);
}
@ -5480,38 +5794,80 @@ boolean G_GetExitGameFlag(void)
return exitgame;
}
// Same deal with retrying.
void G_SetRetryFlag(void)
{
retrying = true;
//
// Retrying flags
//
#define CheckRetryFlag(type) \
{ \
if (type < 0 || type >= RETRY_MAX) \
I_Error("G_SetRetryFlag: out of bounds retry flag type (%d)", type); \
}
void G_ClearRetryFlag(void)
void G_SetRetryFlag(INT32 type)
{
retrying = false;
CheckRetryFlag(type);
retrying[type] = true;
}
boolean G_GetRetryFlag(void)
void G_ClearRetryFlag(INT32 type)
{
return retrying;
CheckRetryFlag(type);
retrying[type] = false;
}
void G_SetModeAttackRetryFlag(void)
boolean G_GetRetryFlag(INT32 type)
{
retryingmodeattack = true;
G_SetRetryFlag();
CheckRetryFlag(type);
return retrying[type];
}
void G_ClearModeAttackRetryFlag(void)
void G_ClearAllRetryFlags(void)
{
retryingmodeattack = false;
INT32 i = RETRY_MAX;
while (--i >= 0)
G_ClearRetryFlag(i);
}
boolean G_GetModeAttackRetryFlag(void)
// Sets RETRY_CUR, may set RETRY_PAUSED.
void G_SetRetrySP(void)
{
return retryingmodeattack;
G_SetRetryFlag(RETRY_SP);
G_SetRetryFlag(RETRY_CUR);
if (paused)
G_SetRetryFlag(RETRY_PAUSED);
}
void G_ClearRetrySP(void)
{
G_ClearRetryFlag(RETRY_SP);
}
boolean G_GetRetrySP(void)
{
return G_GetRetryFlag(RETRY_SP);
}
// Sets RETRY_RA and calls G_SetRetryFlag.
void G_SetRetryRA(void)
{
G_SetRetryFlag(RETRY_RA);
G_SetRetrySP();
}
void G_ClearRetryRA(void)
{
G_ClearRetryFlag(RETRY_RA);
}
boolean G_GetRetryRA(void)
{
return G_GetRetryFlag(RETRY_RA);
}
#undef CheckRetryFlag
// Time utility functions
INT32 G_TicsToHours(tic_t tics)
{

View file

@ -36,6 +36,10 @@ extern boolean playeringame[MAXPLAYERS];
// gametic at level start
extern tic_t levelstarttic;
extern boolean levelstarting; // starting the level
extern boolean leveldemoload; // starting a demo
extern boolean levelresetplayer; // reset players at level load
// for modding?
extern INT16 prevmap, nextmap;
extern INT32 gameovertics;
@ -177,10 +181,32 @@ void G_SpawnPlayer(INT32 playernum);
// Can be called by the startup code or M_Responder.
// A normal game starts at map 1, but a warp test can start elsewhere
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 character, boolean SSSG, boolean FLS);
void G_DoLoadLevel(boolean resetplayer);
void G_StartTitleCard(void);
void G_PreLevelTitleCard(void);
boolean G_IsTitleCardAvailable(void);
void G_StartLevel(boolean resetplayer);
void G_StartLevelWipe(void);
void G_InitLevelGametype(void);
void G_DoLoadLevel(void);
// Title card
void TitleCard_Start(void);
void TitleCard_Run(void);
void TitleCard_LoadGraphics(void);
boolean TitleCard_Available(void);
typedef struct
{
boolean running, prelevel;
UINT8 wipe;
tic_t ticker;
tic_t exitticker, endtime;
fixed_t zigzag, scroll, momentum;
void *patches[3];
} titlecard_t;
extern titlecard_t titlecard;
#define PRELEVELTIME 24 // frames in tics
// Can be called by the startup code or M_Responder, calls P_SetupLevel.
void G_LoadGame(UINT32 slot, INT16 mapoverride);
@ -223,7 +249,7 @@ void G_UseContinue(void);
void G_AfterIntermission(void);
void G_EndGame(void); // moved from y_inter.c/h and renamed
void G_Ticker(boolean run);
void G_Ticker(boolean run, tic_t tics);
boolean G_Responder(event_t *ev);
boolean G_LuaResponder(event_t *ev);
@ -233,13 +259,31 @@ void G_SetExitGameFlag(void);
void G_ClearExitGameFlag(void);
boolean G_GetExitGameFlag(void);
void G_SetRetryFlag(void);
void G_ClearRetryFlag(void);
boolean G_GetRetryFlag(void);
enum
{
RETRY_SP, // Retrying in Single Player.
RETRY_RA, // Retrying in Mode Attack.
void G_SetModeAttackRetryFlag(void);
void G_ClearModeAttackRetryFlag(void);
boolean G_GetModeAttackRetryFlag(void);
// Cleared at G_DoLoadLevel.
RETRY_CUR, // Currently retrying.
RETRY_PAUSED, // Retrying while paused.
RETRY_MAX,
};
void G_SetRetryFlag(INT32 type);
void G_ClearRetryFlag(INT32 type);
boolean G_GetRetryFlag(INT32 type);
void G_SetRetrySP(void);
void G_ClearRetrySP(void);
boolean G_GetRetrySP(void);
void G_SetRetryRA(void);
void G_ClearRetryRA(void);
boolean G_GetRetryRA(void);
void G_ClearAllRetryFlags(void);
void G_LoadGameData(gamedata_t *data);
void G_LoadGameSettings(void);

View file

@ -58,7 +58,7 @@ EXPORT INT32 HWRAPI(GetTextureUsed) (void);
EXPORT void HWRAPI(FlushScreenTextures) (void);
EXPORT void HWRAPI(StartScreenWipe) (void);
EXPORT void HWRAPI(EndScreenWipe) (void);
EXPORT void HWRAPI(EndScreenWipe) (boolean restore);
EXPORT void HWRAPI(DoScreenWipe) (void);
EXPORT void HWRAPI(DrawIntermissionBG) (void);
EXPORT void HWRAPI(MakeScreenTexture) (void);

View file

@ -6924,10 +6924,10 @@ void HWR_StartScreenWipe(void)
HWD.pfnStartScreenWipe();
}
void HWR_EndScreenWipe(void)
void HWR_EndScreenWipe(boolean restore)
{
//CONS_Debug(DBG_RENDER, "In HWR_EndScreenWipe()\n");
HWD.pfnEndScreenWipe();
HWD.pfnEndScreenWipe(restore);
}
void HWR_DrawIntermissionBG(void)

View file

@ -58,7 +58,7 @@ void transform(float *cx, float *cy, float *cz);
INT32 HWR_GetTextureUsed(void);
void HWR_DoPostProcessor(player_t *player);
void HWR_StartScreenWipe(void);
void HWR_EndScreenWipe(void);
void HWR_EndScreenWipe(boolean restore);
void HWR_DrawIntermissionBG(void);
void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum);
void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum);

View file

@ -3162,71 +3162,8 @@ EXPORT void HWRAPI(FlushScreenTextures) (void)
finalScreenTexture = 0;
}
// Create Screen to fade from
EXPORT void HWRAPI(StartScreenWipe) (void)
{
INT32 texsize = 2048;
boolean firstTime = (startScreenWipe == 0);
// Use a power of two texture, dammit
if(screen_width <= 512)
texsize = 512;
else if(screen_width <= 1024)
texsize = 1024;
// Create screen texture
if (firstTime)
pglGenTextures(1, &startScreenWipe);
pglBindTexture(GL_TEXTURE_2D, startScreenWipe);
if (firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
}
else
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
tex_downloaded = startScreenWipe;
}
// Create Screen to fade to
EXPORT void HWRAPI(EndScreenWipe)(void)
{
INT32 texsize = 2048;
boolean firstTime = (endScreenWipe == 0);
// Use a power of two texture, dammit
if(screen_width <= 512)
texsize = 512;
else if(screen_width <= 1024)
texsize = 1024;
// Create screen texture
if (firstTime)
pglGenTextures(1, &endScreenWipe);
pglBindTexture(GL_TEXTURE_2D, endScreenWipe);
if (firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
}
else
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
tex_downloaded = endScreenWipe;
}
// Draw the last scene under the intermission
EXPORT void HWRAPI(DrawIntermissionBG)(void)
// Draws a screen texture.
static void DrawScreenTexture(GLuint tex)
{
float xfix, yfix;
INT32 texsize = 2048;
@ -3263,14 +3200,86 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void)
pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
pglBindTexture(GL_TEXTURE_2D, screentexture);
pglBindTexture(GL_TEXTURE_2D, tex);
pglColor4ubv(white);
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
tex_downloaded = screentexture;
tex_downloaded = tex;
}
// Create Screen to fade from
EXPORT void HWRAPI(StartScreenWipe) (void)
{
INT32 texsize = 2048;
boolean firstTime = (startScreenWipe == 0);
// Use a power of two texture, dammit
if(screen_width <= 512)
texsize = 512;
else if(screen_width <= 1024)
texsize = 1024;
// Create screen texture
if (firstTime)
pglGenTextures(1, &startScreenWipe);
pglBindTexture(GL_TEXTURE_2D, startScreenWipe);
if (firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
}
else
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
tex_downloaded = startScreenWipe;
}
// Create Screen to fade to
EXPORT void HWRAPI(EndScreenWipe)(boolean restore)
{
INT32 texsize = 2048;
boolean firstTime = (endScreenWipe == 0);
// Use a power of two texture, dammit
if(screen_width <= 512)
texsize = 512;
else if(screen_width <= 1024)
texsize = 1024;
// Create screen texture
if (firstTime)
pglGenTextures(1, &endScreenWipe);
pglBindTexture(GL_TEXTURE_2D, endScreenWipe);
if (firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
}
else
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
tex_downloaded = endScreenWipe;
// Draw the start screen wipe texture
if (restore)
DrawScreenTexture(startScreenWipe);
}
// Draw the last scene under the intermission
EXPORT void HWRAPI(DrawIntermissionBG)(void)
{
DrawScreenTexture(screentexture);
}
// Do screen fades!

View file

@ -1817,7 +1817,7 @@ static inline void HU_DrawCrosshairs(void)
INT32 cross1 = cv_crosshair.value & 3;
INT32 cross2 = cv_crosshair2.value & 3;
if (automapactive || demoplayback)
if (automapactive || demoplayback || titlecard.prelevel)
return;
stplyr = ((stplyr == &players[displayplayer]) ? &players[secondarydisplayplayer] : &players[displayplayer]);

View file

@ -1437,8 +1437,8 @@ void LUA_SetHudHook(int hook, huddrawlist_h list)
case HUD_HOOK(titlecard):
LUA_PushUserdata(gL, stplyr, META_PLAYER);
lua_pushinteger(gL, lt_ticker);
lua_pushinteger(gL, (lt_endtime + TICRATE));
lua_pushinteger(gL, titlecard.ticker);
lua_pushinteger(gL, titlecard.endtime + TICRATE);
break;
case HUD_HOOK(intermission):

View file

@ -2961,19 +2961,19 @@ static void M_HandleMenuPresState(menu_t *newMenu)
)
{
if (gamestate == GS_TIMEATTACK)
wipetypepre = ((exitwipe && enterlevel <= exitlevel) || anceslevel < 0) ? exitwipe : -1; // force default
wipetypepre = ((exitwipe && enterlevel <= exitlevel) || anceslevel < 0) ? exitwipe : DEFAULTWIPE; // force default
else
// HACK: INT16_MAX signals to not wipe
// because 0 is a valid index and -1 means default
wipetypepre = ((exitwipe && enterlevel <= exitlevel) || anceslevel < 0) ? exitwipe : INT16_MAX;
wipetypepost = ((enterwipe && enterlevel >= exitlevel) || anceslevel < 0) ? enterwipe : INT16_MAX;
wipetypepre = ((exitwipe && enterlevel <= exitlevel) || anceslevel < 0) ? exitwipe : IGNOREWIPE;
wipetypepost = ((enterwipe && enterlevel >= exitlevel) || anceslevel < 0) ? enterwipe : IGNOREWIPE;
wipegamestate = FORCEWIPE;
// If just one of the above is a force not-wipe,
// mirror the other wipe.
if (wipetypepre != INT16_MAX && wipetypepost == INT16_MAX)
if (wipetypepre != IGNOREWIPE && wipetypepost == IGNOREWIPE)
wipetypepost = wipetypepre;
else if (wipetypepost != INT16_MAX && wipetypepre == INT16_MAX)
else if (wipetypepost != IGNOREWIPE && wipetypepre == IGNOREWIPE)
wipetypepre = wipetypepost;
// D_Display runs the next step of processing
@ -3166,7 +3166,10 @@ boolean M_Responder(event_t *ev)
if (gamestate == GS_TITLESCREEN && finalecount < (cv_tutorialprompt.value ? TICRATE : 0))
return false;
if (CON_Ready() && gamestate != GS_WAITINGPLAYERS)
if (gamestate == GS_TIMEATTACK && WipeInAction)
return false;
if (CON_Ready())
return false;
if (noFurtherInput)
@ -3565,15 +3568,13 @@ boolean M_Responder(event_t *ev)
//
void M_Drawer(void)
{
boolean wipe = WipeInAction;
if (currentMenu == &MessageDef)
menuactive = true;
if (menuactive)
{
// now that's more readable with a faded background (yeah like Quake...)
if (!wipe && (curfadevalue || (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK)))
if (curfadevalue || (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK))
V_DrawFadeScreen(0xFF00, (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK) ? 16 : curfadevalue);
if (currentMenu->drawroutine)
@ -3650,7 +3651,7 @@ void M_StartControlPanel(void)
}
else if (!(netgame || multiplayer)) // Single Player
{
if (gamestate != GS_LEVEL || ultimatemode) // intermission, so gray out stuff.
if (gamestate != GS_LEVEL || ultimatemode || G_GetRetryFlag(RETRY_CUR)) // Can't retry if you're already retrying... chief.
{
SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA, serverGamedata)) ? (IT_GRAYEDOUT) : (IT_DISABLED);
SPauseMenu[spause_retry].status = IT_GRAYEDOUT;
@ -3734,7 +3735,7 @@ void M_StartControlPanel(void)
void M_EndModeAttackRun(void)
{
G_ClearModeAttackRetryFlag();
G_ClearRetryRA();
M_ModeAttackEndGame(0);
}
@ -7000,7 +7001,7 @@ static void M_RetryResponse(INT32 ch)
return;
M_ClearMenus(true);
G_SetRetryFlag();
G_SetRetrySP();
}
static void M_Retry(INT32 choice)
@ -9321,7 +9322,6 @@ static void M_HandleChoosePlayerMenu(INT32 choice)
case KEY_ENTER:
S_StartSound(NULL, sfx_menu1);
char_scroll = 0; // finish scrolling the menu
M_DrawSetupChoosePlayerMenu(); // draw the finally selected character one last time for the fadeout
// Is this a hack?
charseltimer = 0;
M_ChoosePlayer(char_on);
@ -10649,7 +10649,7 @@ static void M_SetGuestReplay(INT32 choice)
void M_ModeAttackRetry(INT32 choice)
{
(void)choice;
// todo -- maybe seperate this out and G_SetRetryFlag() here instead? is just calling this from the menu 100% safe?
// todo -- maybe seperate this out and G_SetRetrySP() here instead? is just calling this from the menu 100% safe?
G_CheckDemoStatus(); // Cancel recording
if (modeattacking == ATTACKING_RECORD)
M_ChooseTimeAttack(0);

View file

@ -1239,7 +1239,7 @@ boolean TryRunTics(tic_t realtics)
if (update_stats)
PS_START_TIMING(ps_tictime);
G_Ticker((gametic % NEWTICRATERATIO) == 0);
G_Ticker((gametic % NEWTICRATERATIO) == 0, (neededtic - gametic));
ExtraDataTicker();
gametic++;
consistancy[gametic%BACKUPTICS] = Consistancy();

View file

@ -2086,16 +2086,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
LUA_HookInt(mapnumber, HOOK(MapChange));
G_InitNew(ultimatemode, mapname, resetplayer, skipprecutscene, FLS);
if (demoplayback && !timingdemo)
precache = true;
if (timingdemo)
G_DoneLevelLoad();
if (metalrecording)
G_BeginMetal();
if (demorecording) // Okay, level loaded, character spawned and skinned,
G_BeginRecording(); // I AM NOW READY TO RECORD.
demo_start = true;
}
static void Command_Pause(void)
@ -4599,7 +4589,7 @@ void Command_Retry_f(void)
else
{
M_ClearMenus(true);
G_SetRetryFlag();
G_SetRetrySP();
}
}

View file

@ -15,6 +15,7 @@
#include "byteptr.h"
#include "d_main.h"
#include "doomstat.h"
#include "f_finale.h"
#include "g_game.h"
#include "m_random.h"
#include "m_misc.h"
@ -4530,12 +4531,23 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
tokenlist = READUINT32(save_p);
levelstarting = false;
if (!P_LoadLevel(true, reloading))
{
CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n"));
return false;
}
G_StartLevelWipe();
wipestyleflags &= ~WSF_ACTION;
F_StopWipe();
WipeRunPost = false;
wipetypepre = wipetypepost = IGNOREWIPE;
titlecard.prelevel = false;
// get the time
leveltime = READUINT32(save_p);
ssspheres = READUINT32(save_p);

View file

@ -7221,7 +7221,7 @@ void P_RespawnThings(void)
skyboxmo[1] = skyboxcenterpnts[(centerid >= 0) ? centerid : 0];
}
static void P_RunLevelScript(const char *scriptname)
void P_RunLevelScript(const char *scriptname)
{
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_SCRIPTISFILE))
{
@ -7533,12 +7533,8 @@ static void P_InitCamera(void)
}
}
static void P_RunSpecialStageWipe(void)
void P_RunSpecialStageWipe(void)
{
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (3*TICRATE)/2;
tic_t nowtime;
S_StartSound(NULL, sfx_s3kaf);
// Fade music! Time it to S3KAF: 0.25 seconds is snappy.
@ -7548,7 +7544,7 @@ static void P_RunSpecialStageWipe(void)
S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)
F_WipeStartScreen();
wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE);
wipestyleflags |= WSF_TOWHITE|WSF_SPECIALSTAGE;
#ifdef HWRENDER
// uh..........
@ -7557,35 +7553,12 @@ static void P_RunSpecialStageWipe(void)
#endif
F_WipeEndScreen();
F_RunWipe(wipedefs[wipe_speclevel_towhite], false);
I_OsPolling();
I_FinishUpdate(); // page flip or blit buffer
if (moviemode)
M_SaveFrame();
nowtime = lastwipetic;
// Hold on white for extra effect.
while (nowtime < endtime)
{
// wait loop
while (!((nowtime = I_GetTime()) - lastwipetic))
{
I_Sleep(cv_sleep.value);
I_UpdateTime(cv_timescale.value);
}
lastwipetic = nowtime;
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
NetKeepAlive(); // Prevent timeout
}
F_StartWipe(wipedefs[wipe_speclevel_towhite], false);
}
static void P_RunLevelWipe(void)
void P_RunLevelWipe(void)
{
F_WipeStartScreen();
wipestyleflags |= WSF_FADEOUT;
#ifdef HWRENDER
// uh..........
@ -7594,13 +7567,15 @@ static void P_RunLevelWipe(void)
#endif
F_WipeEndScreen();
// for titlemap: run a specific wipe if specified
// needed for exiting time attack
if (wipetypepre != INT16_MAX)
F_RunWipe(
(wipetypepre >= 0 && F_WipeExists(wipetypepre)) ? wipetypepre : wipedefs[wipe_level_toblack],
false);
wipetypepre = -1;
if (wipetypepre != IGNOREWIPE)
F_StartWipe(
(wipetypepre != DEFAULTWIPE && F_WipeExists(wipetypepre)) ? wipetypepre : wipedefs[wipe_level_toblack],
true);
wipetypepre = DEFAULTWIPE;
}
static void P_InitPlayers(void)
@ -7716,16 +7691,12 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// use gamemap to get map number.
// 99% of the things already did, so.
// Map header should always be in place at this point
INT32 i, ranspecialwipe = 0;
INT32 i;
sector_t *ss;
levelloading = true;
// This is needed. Don't touch.
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
gametyperules = gametypedefaultrules[gametype];
CON_Drawer(); // let the user know what we are going to do
I_FinishUpdate(); // page flip or blit buffer
if (fromnetsave)
G_InitLevelGametype();
// Reset the palette
if (rendermode != render_none)
@ -7743,12 +7714,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Clear CECHO messages
HU_ClearCEcho();
if (mapheaderinfo[gamemap-1]->runsoc[0] != '#')
P_RunSOC(mapheaderinfo[gamemap-1]->runsoc);
if (cv_runscripts.value && mapheaderinfo[gamemap-1]->scriptname[0] != '#')
P_RunLevelScript(mapheaderinfo[gamemap-1]->scriptname);
P_InitLevelSettings();
postimgtype = postimgtype2 = postimg_none;
@ -7780,52 +7745,13 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// will be set by player think.
players[consoleplayer].viewz = 1;
// Cancel all d_main.c fadeouts (keep fade in though).
if (reloadinggamestate)
wipegamestate = gamestate; // Don't fade if reloading the gamestate
else
wipegamestate = FORCEWIPEOFF;
wipestyleflags = 0;
// Special stage & record attack retry fade to white
// This is handled BEFORE sounds are stopped.
if (G_GetModeAttackRetryFlag())
{
if (modeattacking && !demoplayback)
{
ranspecialwipe = 2;
wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE);
}
G_ClearModeAttackRetryFlag();
}
else if (rendermode != render_none && G_IsSpecialStage(gamemap))
{
P_RunSpecialStageWipe();
ranspecialwipe = 1;
}
// Make sure all sounds are stopped before Z_FreeTags.
S_StopSounds();
S_ClearSfx();
// Fade out music here. Deduct 2 tics so the fade volume actually reaches 0.
// But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug.
if (!(reloadinggamestate || titlemapinaction) && (RESETMUSIC ||
strnicmp(S_MusicName(),
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7)))
{
S_FadeMusic(0, FixedMul(
FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE));
}
// Let's fade to black here
// But only if we didn't do the special stage wipe
if (rendermode != render_none && !(ranspecialwipe || reloadinggamestate))
P_RunLevelWipe();
if (!(reloadinggamestate || titlemapinaction))
{
if (ranspecialwipe == 2)
if (ranspecialwipe == SPECIALWIPE_RETRY)
{
pausedelay = -3; // preticker plus one
S_StartSound(NULL, sfx_s3k73);
@ -7844,11 +7770,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
V_DrawSmallString(1, 195, V_ALLOWLOWERCASE|V_TRANSLUCENT|V_SNAPTOLEFT|V_SNAPTOBOTTOM, tx);
I_UpdateNoVsync();
}
// As oddly named as this is, this handles music only.
// We should be fine starting it here.
// Don't do this during titlemap, because the menu code handles music by itself.
S_Start();
}
levelfadecol = (ranspecialwipe) ? 0 : 31;
@ -7973,6 +7894,14 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
levelloading = false;
if (!(reloadinggamestate || titlemapinaction))
{
// As oddly named as this is, this handles music only.
// We should be fine starting it here.
// Don't do this during titlemap, because the menu code handles music by itself.
S_Start();
}
P_RunCachedActions();
P_MapEnd(); // tmthing is no longer needed from this point onwards
@ -8015,18 +7944,27 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
R_ResetViewInterpolation(0);
R_UpdateMobjInterpolators();
// Title card!
G_StartTitleCard();
titlecard.running = false;
titlecard.prelevel = false;
titlecard.wipe = 0;
// Can the title card actually run, though?
if (!WipeStageTitle)
return true;
if (ranspecialwipe == 2)
return true;
if (ranspecialwipe == SPECIALWIPE_RETRY)
{
// Force a wipe
wipegamestate = -1;
wipestyleflags = (WSF_TOWHITE|WSF_FADEIN);
WipeRunPost = true;
// If so...
G_PreLevelTitleCard();
// Reset the HUD translucency!
st_translucency = cv_translucenthud.value;
}
else
{
// Start the title card.
TitleCard_Start();
}
ranspecialwipe = SPECIALWIPE_NONE;
return true;
}

View file

@ -93,15 +93,23 @@ INT32 P_CheckLevelFlat(const char *flatname);
extern size_t nummapthings;
extern mapthing_t *mapthings;
void P_SetupLevelSky(INT32 skynum, boolean global);
#ifdef SCANTHINGS
void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
#endif
void P_RespawnThings(void);
boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
void P_SetupLevelSky(INT32 skynum, boolean global);
#ifdef HWRENDER
void HWR_LoadLevel(void);
#endif
void P_RunLevelWipe(void);
void P_RunSpecialStageWipe(void);
void P_RunLevelScript(const char *scriptname);
boolean P_AddWadFile(const char *wadfilename);
boolean P_AddFolder(const char *folderpath);
boolean P_RunSOC(const char *socfilename);

View file

@ -585,7 +585,7 @@ void SCR_DisplayMarathonInfo(void)
if (gamecomplete)
flags |= V_YELLOWMAP;
else if (marathonmode & MA_INGAME)
; // see also G_Ticker
; // see also G_MarathonTicker
else if (marathonmode & MA_INIT)
marathonmode &= ~MA_INIT;
else

View file

@ -207,11 +207,9 @@ static boolean st_stopped = true;
void ST_Ticker(boolean run)
{
(void)run;
if (st_stopped)
return;
if (run)
ST_runTitleCard();
}
// 0 is default, any others are special palettes.
@ -1246,145 +1244,45 @@ static void ST_drawInput(void)
V_DrawThinString(x, y, hudinfo[HUD_LIVES].f|((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!");
}
static patch_t *lt_patches[3];
static INT32 lt_scroll = 0;
static INT32 lt_mom = 0;
static INT32 lt_zigzag = 0;
tic_t lt_ticker = 0, lt_lasttic = 0;
tic_t lt_exitticker = 0, lt_endtime = 0;
//
// Load the graphics for the title card.
// Don't let LJ see this
//
static void ST_cacheLevelTitle(void)
{
#define SETPATCH(default, warning, custom, idx) \
{ \
lumpnum_t patlumpnum = LUMPERROR; \
if (mapheaderinfo[gamemap-1]->custom[0] != '\0') \
{ \
patlumpnum = W_CheckNumForName(mapheaderinfo[gamemap-1]->custom); \
if (patlumpnum != LUMPERROR) \
lt_patches[idx] = (patch_t *)W_CachePatchNum(patlumpnum, PU_HUDGFX); \
} \
if (patlumpnum == LUMPERROR) \
{ \
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE)) \
lt_patches[idx] = (patch_t *)W_CachePatchName(default, PU_HUDGFX); \
else \
lt_patches[idx] = (patch_t *)W_CachePatchName(warning, PU_HUDGFX); \
} \
}
SETPATCH("LTACTBLU", "LTACTRED", ltactdiamond, 0)
SETPATCH("LTZIGZAG", "LTZIGRED", ltzzpatch, 1)
SETPATCH("LTZZTEXT", "LTZZWARN", ltzztext, 2)
#undef SETPATCH
}
//
// Start the title card.
//
void ST_startTitleCard(void)
{
// cache every HUD patch used
ST_cacheLevelTitle();
// initialize HUD variables
lt_ticker = lt_exitticker = lt_lasttic = 0;
lt_endtime = 2*TICRATE + (10*NEWTICRATERATIO);
lt_scroll = BASEVIDWIDTH * FRACUNIT;
lt_zigzag = -((lt_patches[1])->width * FRACUNIT);
lt_mom = 0;
}
//
// What happens before drawing the title card.
// Which is just setting the HUD translucency.
//
void ST_preDrawTitleCard(void)
void TitleCard_PreDraw(void)
{
if (!G_IsTitleCardAvailable())
if (!TitleCard_Available() || !titlecard.running)
return;
if (lt_ticker >= (lt_endtime + TICRATE))
if (titlecard.ticker >= (titlecard.endtime + TICRATE))
return;
if (!lt_exitticker)
if (!titlecard.exitticker)
st_translucency = 0;
else
st_translucency = max(0, min((INT32)lt_exitticker-4, cv_translucenthud.value));
}
//
// Run the title card.
// Called from ST_Ticker.
//
void ST_runTitleCard(void)
{
boolean run = !(paused || P_AutoPause());
if (!G_IsTitleCardAvailable())
return;
if (lt_ticker >= (lt_endtime + TICRATE))
return;
if (run || (lt_ticker < PRELEVELTIME))
{
// tick
lt_ticker++;
if (lt_ticker >= lt_endtime)
lt_exitticker++;
// scroll to screen (level title)
if (!lt_exitticker)
{
if (abs(lt_scroll) > FRACUNIT)
lt_scroll -= (lt_scroll>>2);
else
lt_scroll = 0;
}
// scroll away from screen (level title)
else
{
lt_mom -= FRACUNIT*6;
lt_scroll += lt_mom;
}
// scroll to screen (zigzag)
if (!lt_exitticker)
{
if (abs(lt_zigzag) > FRACUNIT)
lt_zigzag -= (lt_zigzag>>2);
else
lt_zigzag = 0;
}
// scroll away from screen (zigzag)
else
lt_zigzag += lt_mom;
}
st_translucency = max(0, min((INT32)titlecard.exitticker-4, cv_translucenthud.value));
}
//
// Draw the title card itself.
//
void ST_drawTitleCard(void)
void TitleCard_Draw(void)
{
char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl;
char *subttl = mapheaderinfo[gamemap-1]->subttl;
UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
INT32 lvlttlxpos, ttlnumxpos, zonexpos;
INT32 subttlxpos = BASEVIDWIDTH/2;
INT32 ttlscroll = FixedInt(lt_scroll);
INT32 zzticker;
INT32 ttlscroll = FixedInt(titlecard.scroll);
patch_t *actpat, *zigzag, *zztext;
UINT8 colornum;
const UINT8 *colormap;
if (!TitleCard_Available())
return;
if (!titlecard.running)
return;
if (players[consoleplayer].skincolor)
colornum = players[consoleplayer].skincolor;
else
@ -1392,22 +1290,17 @@ void ST_drawTitleCard(void)
colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE);
if (!G_IsTitleCardAvailable())
return;
if (titlecard.prelevel)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
if (!LUA_HudEnabled(hud_stagetitle))
if (!LUA_HudEnabled(hud_stagetitle) || titlecard.ticker >= (titlecard.endtime + TICRATE))
{
goto luahook;
}
if (lt_ticker >= (lt_endtime + TICRATE))
goto luahook;
if ((lt_ticker-lt_lasttic) > 1)
lt_ticker = lt_lasttic+1;
ST_cacheLevelTitle();
actpat = lt_patches[0];
zigzag = lt_patches[1];
zztext = lt_patches[2];
actpat = titlecard.patches[0];
zigzag = titlecard.patches[1];
zztext = titlecard.patches[2];
lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2));
@ -1423,11 +1316,11 @@ void ST_drawTitleCard(void)
if (!splitscreen || (splitscreen && stplyr == &players[displayplayer]))
{
zzticker = lt_ticker;
V_DrawMappedPatch(FixedInt(lt_zigzag), (-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap);
V_DrawMappedPatch(FixedInt(lt_zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap);
V_DrawMappedPatch(FixedInt(lt_zigzag), (-zztext->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap);
V_DrawMappedPatch(FixedInt(lt_zigzag), (zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap);
INT32 zzticker = titlecard.ticker;
V_DrawMappedPatch(FixedInt(titlecard.zigzag), (-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap);
V_DrawMappedPatch(FixedInt(titlecard.zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap);
V_DrawMappedPatch(FixedInt(titlecard.zigzag), (-zztext->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap);
V_DrawMappedPatch(FixedInt(titlecard.zigzag), (zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap);
}
if (actnum)
@ -1447,8 +1340,6 @@ void ST_drawTitleCard(void)
V_DrawLevelTitle(zonexpos + ttlscroll, 104, V_PERPLAYER, M_GetText("Zone"));
V_DrawCenteredString(subttlxpos - ttlscroll, 135, V_PERPLAYER|V_ALLOWLOWERCASE, subttl);
lt_lasttic = lt_ticker;
luahook:
//if (renderisnewtic)
{
@ -1459,30 +1350,22 @@ luahook:
}
//
// Drawer for G_PreLevelTitleCard.
// Draws title cards for every player.
//
void ST_preLevelTitleCardDrawer(void)
void TitleCard_DrawOverWipe(void)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
ST_drawWipeTitleCard();
I_OsPolling();
I_UpdateNoBlit();
}
if (!(titlecard.running && titlecard.wipe && st_overlay))
return;
//
// Draw the title card while on a wipe.
// Also used in G_PreLevelTitleCard.
//
void ST_drawWipeTitleCard(void)
{
stplyr = &players[consoleplayer];
ST_preDrawTitleCard();
ST_drawTitleCard();
TitleCard_PreDraw();
TitleCard_Draw();
if (splitscreen)
{
stplyr = &players[secondarydisplayplayer];
ST_preDrawTitleCard();
ST_drawTitleCard();
TitleCard_PreDraw();
TitleCard_Draw();
}
}
@ -2666,16 +2549,16 @@ static boolean ST_doItemFinderIconsAndSound(void)
//
static void ST_overlayDrawer(void)
{
// Decide whether to draw the stage title or not
// Decides whether to draw the stage title or not.
boolean stagetitle = false;
// Check for a valid level title
// If the HUD is enabled
// And, if Lua is running, if the HUD library has the stage title enabled
if (G_IsTitleCardAvailable() && *mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer)))
if (TitleCard_Available() && !(hu_showscores && (netgame || multiplayer)))
{
stagetitle = true;
ST_preDrawTitleCard();
TitleCard_PreDraw();
}
// hu_showscores = auto hide score/time/rings when tab rankings are shown
@ -2817,8 +2700,8 @@ static void ST_overlayDrawer(void)
}
// draw level title Tails
if (stagetitle && (!WipeInAction) && (!WipeStageTitle))
ST_drawTitleCard();
if (stagetitle && !WipeInAction && !titlecard.wipe)
TitleCard_Draw();
if (!hu_showscores && (netgame || multiplayer) && LUA_HudEnabled(hud_textspectator))
ST_drawTextHUD();
@ -2831,6 +2714,8 @@ static void ST_overlayDrawer(void)
void ST_Drawer(void)
{
void (*drawfunc)(void) = ST_overlayDrawer;
if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo)
{
INT32 c = 0;
@ -2890,16 +2775,18 @@ void ST_Drawer(void)
st_translucency = cv_translucenthud.value;
if (st_overlay)
{
// No deadview!
stplyr = &players[displayplayer];
ST_overlayDrawer();
if (titlecard.prelevel)
drawfunc = TitleCard_Draw;
else if (!st_overlay)
return;
if (splitscreen)
{
stplyr = &players[secondarydisplayplayer];
ST_overlayDrawer();
}
// No deadview!
stplyr = &players[displayplayer];
drawfunc();
if (splitscreen)
{
stplyr = &players[secondarydisplayplayer];
drawfunc();
}
}

View file

@ -47,16 +47,10 @@ void ST_ReloadSkinFaceGraphics(void);
void ST_doPaletteStuff(void);
// title card
void ST_startTitleCard(void);
void ST_runTitleCard(void);
void ST_drawTitleCard(void);
void ST_preDrawTitleCard(void);
void ST_preLevelTitleCardDrawer(void);
void ST_drawWipeTitleCard(void);
extern tic_t lt_ticker, lt_lasttic;
extern tic_t lt_exitticker, lt_endtime;
// Title card
void TitleCard_Draw(void);
void TitleCard_PreDraw(void);
void TitleCard_DrawOverWipe(void);
// return if player a is in the same team as player b
boolean ST_SameTeam(player_t *a, player_t *b);

View file

@ -3349,7 +3349,7 @@ INT32 V_LevelNameHeight(const char *string)
return w;
}
// For ST_drawTitleCard
// For TitleCard_Draw
// Returns the width of the act num patch(es)
INT16 V_LevelActNumWidth(UINT8 num)
{