Merge branch 'new-intermission' into 'master'

New intermission

See merge request KartKrew/Kart!1231
This commit is contained in:
Oni 2023-05-12 01:02:09 +00:00
commit aa50a34d7a
18 changed files with 1262 additions and 504 deletions

View file

@ -6110,6 +6110,8 @@ const char *COLOR_ENUMS[] = {
"POSNUM_BEST4",
"POSNUM_BEST5",
"POSNUM_BEST6",
"INTERMISSION",
};
const char *const KARTHUD_LIST[] = {

View file

@ -425,6 +425,8 @@ typedef enum
SKINCOLOR_POSNUM_BEST4,
SKINCOLOR_POSNUM_BEST5,
SKINCOLOR_POSNUM_BEST6,
SKINCOLOR_INTERMISSION,
SKINCOLOR_FIRSTFREESLOT,
SKINCOLOR_LASTFREESLOT = SKINCOLOR_FIRSTFREESLOT + NUMCOLORFREESLOTS - 1,

View file

@ -4066,7 +4066,7 @@ void G_MapIntoRoundQueue(UINT16 map, UINT8 setgametype, boolean setencore, boole
void G_GPCupIntoRoundQueue(cupheader_t *cup, UINT8 setgametype, boolean setencore)
{
UINT8 i, levelindex = 0, bonusindex = 0;
UINT8 bonusmodulo = (cup->numlevels+1)/(cup->numbonus+1);
UINT8 bonusmodulo = max(1, (cup->numlevels+1)/(cup->numbonus+1));
UINT16 cupLevelNum;
// Levels are added to the queue in the following pattern.
@ -4165,6 +4165,7 @@ static void G_GetNextMap(void)
}
else if (roundqueue.size > 0)
{
// See also Y_CalculateMatchData, M_DrawPause
boolean permitrank = false;
if (grandprixinfo.gp == true
&& grandprixinfo.gamespeed >= KARTSPEED_NORMAL)

View file

@ -60,6 +60,7 @@
#include "k_color.h"
#include "k_hud.h"
#include "r_fps.h"
#include "y_inter.h" // Y_PlayerStandingsDrawer
// coords are scaled
#define HU_INPUTX 0
@ -2131,17 +2132,24 @@ static void HU_DrawDemoInfo(void)
//
void HU_DrawSongCredits(void)
{
fixed_t x;
fixed_t y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 32) * FRACUNIT;
INT32 bgt;
if (!cursongcredit.def || cursongcredit.trans >= NUMTRANSMAPS) // No def
{
return;
}
bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans / 2);
x = R_InterpolateFixed(cursongcredit.old_x, cursongcredit.x);
fixed_t x = R_InterpolateFixed(cursongcredit.old_x, cursongcredit.x);
fixed_t y;
if (gamestate == GS_INTERMISSION)
{
y = (BASEVIDHEIGHT - 13) * FRACUNIT;
}
else
{
y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 32) * FRACUNIT;
}
INT32 bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans / 2);
if (bgt < NUMTRANSMAPS)
{
@ -2335,12 +2343,13 @@ Ping_gfx_color (int lag)
//
// HU_drawPing
//
void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, INT32 flags, boolean offline)
void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, INT32 flags, boolean offline, SINT8 toside)
{
UINT8 *colormap = NULL;
INT32 measureid = cv_pingmeasurement.value ? 1 : 0;
INT32 gfxnum; // gfx to draw
boolean drawlocal = (offline && cv_mindelay.value && lag <= (tic_t)cv_mindelay.value);
fixed_t x2, y2;
if (!server && lag <= (tic_t)cv_mindelay.value)
{
@ -2348,13 +2357,35 @@ void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, INT32 flags, boolean offline)
drawlocal = true;
}
x2 = x;
y2 = y + FRACUNIT;
if (toside == 0)
{
if (measureid == 1)
{
x2 += ((11 - pingmeasure[measureid]->width) * FRACUNIT);
}
else
{
x2 += (10 * FRACUNIT);
}
y2 += (8 * FRACUNIT);
}
else if (toside > 0)
{
x2 += (20 * FRACUNIT);
}
//else if (toside < 0)
gfxnum = Ping_gfx_num(lag);
if (measureid == 1)
{
V_DrawFixedPatch(
x + ((11 - pingmeasure[measureid]->width) * FRACUNIT),
y + (9 * FRACUNIT),
x2,
y2,
FRACUNIT, flags,
pingmeasure[measureid],
NULL
@ -2395,9 +2426,9 @@ void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, INT32 flags, boolean offline)
lag = (INT32)(lag * (1000.00f / TICRATE));
}
x = V_DrawPingNum(
x + (((measureid == 1) ? 11 - pingmeasure[measureid]->width : 10) * FRACUNIT),
y + (9 * FRACUNIT),
x2 = V_DrawPingNum(
x2,
y2,
flags, lag,
colormap
);
@ -2405,8 +2436,8 @@ void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, INT32 flags, boolean offline)
if (measureid == 0)
{
V_DrawFixedPatch(
x + ((1 - pingmeasure[measureid]->width) * FRACUNIT),
y + (9 * FRACUNIT),
x2 + ((1 - pingmeasure[measureid]->width) * FRACUNIT),
y2,
FRACUNIT, flags,
pingmeasure[measureid],
NULL
@ -2513,10 +2544,7 @@ static inline void HU_DrawSpectatorTicker(void)
//
static void HU_DrawRankings(void)
{
playersort_t tab[MAXPLAYERS];
INT32 i, j, scorelines, numplayersingame = 0, hilicol = highlightflags;
boolean completed[MAXPLAYERS];
UINT32 whiteplayer = MAXPLAYERS;
INT32 i, j, hilicol = highlightflags;
boolean timedone = false, pointsdone = false;
if (!automapactive)
@ -2625,23 +2653,21 @@ static void HU_DrawRankings(void)
V_DrawCenteredString(256, 16, hilicol, kartspeed_cons_t[1+gamespeed].strvalue);
}
// When you play, you quickly see your score because your name is displayed in white.
// When playing back a demo, you quickly see who's the view.
if (!r_splitscreen)
whiteplayer = demo.playback ? displayplayers[0] : consoleplayer;
boolean completed[MAXPLAYERS];
y_data_t standings;
scorelines = 0;
memset(completed, 0, sizeof (completed));
memset(tab, 0, sizeof (playersort_t)*MAXPLAYERS);
memset(&standings, 0, sizeof (standings));
UINT8 numplayersingame = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
tab[i].num = -1;
tab[i].name = NULL;
tab[i].count = INT32_MAX;
if (!playeringame[i] || players[i].spectator || !players[i].mo)
{
completed[i] = true;
continue;
}
numplayersingame++;
}
@ -2651,40 +2677,58 @@ static void HU_DrawRankings(void)
UINT8 lowestposition = MAXPLAYERS+1;
for (i = 0; i < MAXPLAYERS; i++)
{
if (completed[i] || !playeringame[i] || players[i].spectator || !players[i].mo)
if (completed[i])
continue;
if (players[i].position >= lowestposition)
continue;
tab[scorelines].num = i;
standings.num[standings.numplayers] = i;
lowestposition = players[i].position;
}
i = tab[scorelines].num;
i = standings.num[standings.numplayers];
completed[i] = true;
tab[scorelines].name = player_names[i];
standings.character[standings.numplayers] = players[i].skin;
standings.color[standings.numplayers] = players[i].skincolor;
standings.pos[standings.numplayers] = players[i].position;
if ((gametyperules & GTR_CIRCUIT))
#define strtime standings.strval[standings.numplayers]
if (players[i].pflags & PF_NOCONTEST)
{
tab[scorelines].count = players[i].laps;
standings.val[standings.numplayers] = (UINT32_MAX-1);
STRBUFCPY(strtime, "RETIRED.");
}
else if ((gametyperules & GTR_CIRCUIT))
{
standings.val[standings.numplayers] = players[i].laps;
if (players[i].exiting)
{
snprintf(strtime, sizeof strtime, "%i'%02i\"%02i", G_TicsToMinutes(players[i].realtime, true),
G_TicsToSeconds(players[i].realtime), G_TicsToCentiseconds(players[i].realtime));
}
else
{
snprintf(strtime, sizeof strtime, "Lap %d", standings.val[standings.numplayers]);
}
}
else
{
tab[scorelines].count = players[i].roundscore;
standings.val[standings.numplayers] = players[i].roundscore;
snprintf(strtime, sizeof strtime, "%d", standings.val[standings.numplayers]);
}
scorelines++;
#undef strtime
#if MAXPLAYERS > 16
if (scorelines > 16)
break; //dont draw past bottom of screen, show the best only
#endif
standings.numplayers++;
}
K_DrawTabRankings(((scorelines > 8) ? 32 : 40), 33, tab, scorelines, whiteplayer, hilicol);
// Returns early if there's no players to draw
Y_PlayerStandingsDrawer(&standings, 0);
// draw spectators in a ticker across the bottom
if (netgame && G_GametypeHasSpectators())

View file

@ -95,17 +95,6 @@ enum
extern char *shiftxform; // english translation shift table
extern char english_shiftxform[];
//------------------------------------
// sorted player lines
//------------------------------------
struct playersort_t
{
UINT32 count;
INT32 num;
const char *name;
};
//------------------------------------
// chat stuff
//------------------------------------
@ -157,11 +146,9 @@ void HU_TickSongCredits(void);
char HU_dequeueChatChar(void);
void HU_Erase(void);
void HU_clearChatChars(void);
void HU_drawPing(fixed_t x, fixed_t y, UINT32 ping, INT32 flags, boolean offline); // Lat': Ping drawer for scoreboard.
void HU_drawPing(fixed_t x, fixed_t y, UINT32 ping, INT32 flags, boolean offline, SINT8 toside); // Lat': Ping drawer for scoreboard.
void HU_drawMiniPing(INT32 x, INT32 y, UINT32 ping, INT32 flags);
INT32 HU_CreateTeamScoresTbl(playersort_t *tab, UINT32 dmtotals[]);
// CECHO interface.
void HU_ClearCEcho(void);
void HU_SetCEchoDuration(INT32 seconds);

View file

@ -29732,7 +29732,9 @@ skincolor_t skincolors[MAXSKINCOLORS] = {
{"Position Best 3", {112, 112, 113, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 110, 111, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_BEST3
{"Position Best 4", {255, 255, 122, 122, 123, 123, 141, 141, 142, 142, 143, 143, 138, 139, 254, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_BEST4
{"Position Best 5", {152, 152, 153, 153, 154, 154, 155, 155, 156, 156, 157, 158, 159, 253, 254, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_BEST5
{"Position Best 6", {181, 181, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186, 187, 187, 29, 30}, SKINCOLOR_NONE, 0, 0, false} // SKINCOLOR_POSNUM_BEST6
{"Position Best 6", {181, 181, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186, 187, 187, 29, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_BEST6
{"Intermission", {0,80,80,81,81,81,84,85,86,87,246,248,251,26,28,31}, SKINCOLOR_NONE, 0, 0, false} // SKINCOLOR_INTERMISSION
};
/** Patches the mobjinfo, state, and skincolor tables.

View file

@ -2277,156 +2277,6 @@ static void K_drawKartEmeralds(void)
}
}
//
// HU_DrawTabRankings -- moved here to take advantage of kart stuff!
//
void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol)
{
static tic_t alagles_timer = 9;
INT32 i, rightoffset = 240;
const UINT8 *colormap;
INT32 dupadjust = (vid.width/vid.dupx), duptweak = (dupadjust - BASEVIDWIDTH)/2;
int basey = y, basex = x, y2;
//this function is designed for 9 or less score lines only
//I_Assert(scorelines <= 9); -- not today bitch, kart fixed it up
V_DrawFill(1-duptweak, 26, dupadjust-2, 1, 0); // Draw a horizontal line because it looks nice!
scorelines--;
if (scorelines >= 8)
{
V_DrawFill(160, 26, 1, 147, 0); // Draw a vertical line to separate the two sides.
V_DrawFill(1-duptweak, 173, dupadjust-2, 1, 0); // And a horizontal line near the bottom.
rightoffset = (BASEVIDWIDTH/2) - 4 - x;
x = (BASEVIDWIDTH/2) + 4;
y += 18*(scorelines-8);
}
else
{
y += 18*scorelines;
}
for (i = scorelines; i >= 0; i--)
{
char strtime[MAXPLAYERNAME+1];
if (players[tab[i].num].spectator || !players[tab[i].num].mo)
continue; //ignore them.
if (netgame) // don't draw ping offline
{
if (players[tab[i].num].bot)
{
V_DrawScaledPatch(x + ((i < 8) ? -25 : rightoffset + 3), y-2, 0, kp_cpu);
}
else if (tab[i].num != serverplayer || !server_lagless)
{
HU_drawPing((x + ((i < 8) ? -17 : rightoffset + 11)) * FRACUNIT, (y-4) * FRACUNIT, playerpingtable[tab[i].num], 0, false);
}
}
STRBUFCPY(strtime, tab[i].name);
y2 = y;
if (netgame && playerconsole[tab[i].num] == 0 && server_lagless && !players[tab[i].num].bot)
{
y2 = ( y - 4 );
V_DrawScaledPatch(x + 20, y2, 0, kp_blagles[(leveltime / 3) % 6]);
// every 70 tics
if (( leveltime % 70 ) == 0)
{
alagles_timer = 9;
}
if (alagles_timer > 0)
{
V_DrawScaledPatch(x + 20, y2, 0, kp_alagles[alagles_timer]);
if (( leveltime % 2 ) == 0)
alagles_timer--;
}
else
V_DrawScaledPatch(x + 20, y2, 0, kp_alagles[0]);
y2 += SHORT (kp_alagles[0]->height) + 1;
}
if (scorelines >= 8)
V_DrawThinString(x + 20, y2, ((tab[i].num == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime);
else
V_DrawString(x + 20, y2, ((tab[i].num == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE, strtime);
if (players[tab[i].num].mo->color)
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE);
if (players[tab[i].num].mo->colorized)
colormap = R_GetTranslationColormap(TC_RAINBOW, players[tab[i].num].mo->color, GTC_CACHE);
else
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE);
V_DrawMappedPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin][FACE_RANK], colormap);
/*if ((gametyperules & GTR_BUMPERS) && players[tab[i].num].bumpers > 0) -- not enough space for this
{
INT32 bumperx = x+19;
V_DrawMappedPatch(bumperx-2, y-4, 0, kp_tinybumper[0], colormap);
for (j = 1; j < players[tab[i].num].bumpers; j++)
{
bumperx += 5;
V_DrawMappedPatch(bumperx, y-4, 0, kp_tinybumper[1], colormap);
}
}*/
}
if (tab[i].num == whiteplayer)
V_DrawScaledPatch(x, y-4, 0, kp_facehighlight[(leveltime / 4) % 8]);
if ((gametyperules & GTR_BUMPERS) && (players[tab[i].num].pflags & PF_ELIMINATED))
V_DrawScaledPatch(x-4, y-7, 0, kp_ranknobumpers);
else
{
INT32 pos = players[tab[i].num].position;
if (pos < 0 || pos > MAXPLAYERS)
pos = 0;
// Draws the little number over the face
V_DrawScaledPatch(x-5, y+6, 0, kp_facenum[pos]);
}
if ((gametyperules & GTR_CIRCUIT))
{
#define timestring(time) va("%i'%02i\"%02i", G_TicsToMinutes(time, true), G_TicsToSeconds(time), G_TicsToCentiseconds(time))
if (scorelines >= 8)
{
if (players[tab[i].num].exiting)
V_DrawRightAlignedThinString(x+rightoffset, y-1, hilicol|V_6WIDTHSPACE, timestring(players[tab[i].num].realtime));
else if (players[tab[i].num].pflags & PF_NOCONTEST)
V_DrawRightAlignedThinString(x+rightoffset, y-1, V_6WIDTHSPACE, "NO CONTEST.");
else
V_DrawRightAlignedThinString(x+rightoffset, y-1, V_6WIDTHSPACE, va("Lap %d", tab[i].count));
}
else
{
if (players[tab[i].num].exiting)
V_DrawRightAlignedString(x+rightoffset, y, hilicol, timestring(players[tab[i].num].realtime));
else if (players[tab[i].num].pflags & PF_NOCONTEST)
V_DrawRightAlignedThinString(x+rightoffset, y-1, 0, "NO CONTEST.");
else
V_DrawRightAlignedString(x+rightoffset, y, 0, va("Lap %d", tab[i].count));
}
#undef timestring
}
else
V_DrawRightAlignedString(x+rightoffset, y, 0, va("%u", tab[i].count));
y -= 18;
if (i == 8)
{
y = basey + 7*18;
x = basex;
}
}
}
static void K_drawKartLaps(void)
{
INT32 splitflags = V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN;

View file

@ -41,7 +41,6 @@ void K_LoadKartHUDGraphics(void);
void K_drawKartHUD(void);
void K_drawKartFreePlay(void);
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, UINT8 mode);
void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol);
void K_DrawMapThumbnail(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, UINT16 map, const UINT8 *colormap);
void K_DrawLikeMapThumbnail(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, patch_t *patch, const UINT8 *colormap);
void K_drawTargetHUD(const vector3_t *origin, player_t *player);

View file

@ -52,6 +52,8 @@
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#include "k_grandprix.h" // K_CanChangeRules
#include "y_inter.h" // Y_RoundQueueDrawer
#include "i_joy.h" // for joystick menu controls
// Condition Sets
@ -4074,6 +4076,34 @@ void M_DrawPause(void)
if (word2len)
V_DrawCenteredLSTitleLowString(220 + offset*2, 103, 0, word2);
}
if (gamestate != GS_INTERMISSION)
{
y_data_t standings;
memset(&standings, 0, sizeof (standings));
standings.mainplayer = (demo.playback ? displayplayers[0] : consoleplayer);
// See also G_GetNextMap, Y_CalculateMatchData
if (
grandprixinfo.gp == true
&& netgame == false // TODO netgame Special Mode support
&& grandprixinfo.gamespeed >= KARTSPEED_NORMAL
&& roundqueue.size > 1
&& roundqueue.entries[roundqueue.size - 1].rankrestricted == true
&& (
gamedata->everseenspecial == true
|| roundqueue.position == roundqueue.size
)
)
{
// Additional cases in which it should always be shown.
standings.showrank = true;
}
// Returns early if there's no roundqueue entries to draw
Y_RoundQueueDrawer(&standings, false, false);
}
}
void M_DrawPlaybackMenu(void)

View file

@ -529,8 +529,21 @@ void K_CeremonyDrawer(void)
}
case 7:
{
const char *emeraldstr = "???";
if (gamedata->everseenspecial == true)
{
emeraldstr =
(grandprixinfo.gp == true
&& grandprixinfo.cup != NULL
&& grandprixinfo.cup->emeraldnum > 0)
? "EMERALD"
: "PRIZE";
}
V_DrawString(x, y, V_ALLOWLOWERCASE,
va("EMERALD: %s", (podiumData.rank.specialWon == true) ? "YES" : "NO")
va("%s: %s",
emeraldstr,
(podiumData.rank.specialWon == true) ? "YES" : "NO")
);
break;
}

View file

@ -846,10 +846,14 @@ void Y_VoteDrawer(void)
{
const INT32 tickDown = (vote.timer + 1) / TICRATE;
V_DrawCenteredString(
BASEVIDWIDTH/2, 188,
V_YELLOWMAP,
va("Vote ends in %d", tickDown)
// See also y_inter.c
V__DrawOneScaleString(
2*FRACUNIT,
(BASEVIDHEIGHT - (2+8))*FRACUNIT,
FRACUNIT,
0, NULL,
OPPRF_FONT,
va("%d", tickDown)
);
}

View file

@ -500,6 +500,8 @@ void M_StartTimeAttack(INT32 choice)
paused = false;
S_StopMusicCredit();
// Early fadeout to let the sound finish playing
F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);

View file

@ -108,6 +108,10 @@ void M_CupSelectHandler(INT32 choice)
S_StartSound(NULL, sfx_s3k63);
paused = false;
S_StopMusicCredit();
// Early fadeout to let the sound finish playing
F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);

View file

@ -538,6 +538,8 @@ void M_LevelSelected(INT16 add)
paused = false;
S_StopMusicCredit();
// Early fadeout to let the sound finish playing
F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);

View file

@ -660,7 +660,7 @@ void SCR_DisplayLocalPing(void)
{
INT32 dispy = cv_ticrate.value ? 160 : 181;
offline = (consoleplayer == serverplayer);
HU_drawPing(307 * FRACUNIT, dispy * FRACUNIT, ping, V_SNAPTORIGHT | V_SNAPTOBOTTOM | V_HUDTRANS, offline);
HU_drawPing(307 * FRACUNIT, dispy * FRACUNIT, ping, V_SNAPTORIGHT | V_SNAPTOBOTTOM | V_HUDTRANS, offline, 0);
}
}

View file

@ -139,9 +139,6 @@ TYPEDEF (demoghost);
TYPEDEF (roundentry_t);
TYPEDEF (mapsearchfreq_t);
// hu_stuff.h
TYPEDEF (playersort_t);
// i_joy.h
TYPEDEF (JoyType_t);

File diff suppressed because it is too large Load diff

View file

@ -16,9 +16,40 @@
extern "C" {
#endif
typedef struct
{
boolean rankingsmode; // rankings mode
boolean gotthrough; // show "got through"
boolean showrank; // show rank-restricted queue entry at the end, if it exists
boolean encore; // encore mode
char headerstring[64]; // holds levelnames up to 64 characters
UINT8 numplayers; // Number of players being displayed
SINT8 num[MAXPLAYERS]; // Player #
UINT8 pos[MAXPLAYERS]; // player positions. used for ties
UINT8 character[MAXPLAYERS]; // Character #
UINT16 color[MAXPLAYERS]; // Color #
UINT32 val[MAXPLAYERS]; // Gametype-specific value
char strval[MAXPLAYERS][MAXPLAYERNAME+1];
INT16 increase[MAXPLAYERS]; // how much did the score increase by?
UINT8 jitter[MAXPLAYERS]; // wiggle
UINT8 mainplayer; // Most successful local player
INT32 linemeter; // For GP only
} y_data_t;
void Y_IntermissionDrawer(void);
void Y_Ticker(void);
// Specific sub-drawers
void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset);
void Y_RoundQueueDrawer(y_data_t *standings, boolean doanimations, boolean widescreen);
void Y_StartIntermission(void);
void Y_EndIntermission(void);