Account for Hidden Palace-like replacement levels in the round queue and ranking systems

- When a nextmapoverride is in play, do not insert the just-played map into the GP Rank
- Put all the behaviour that determines which Round icon to show in exactly one places

Also, fix a bug where it would show the skin realname for a spectating player's tally instead of the ROUND text.
This commit is contained in:
toaster 2023-11-19 17:34:27 +00:00
parent 66844457cd
commit b09a9b40c4
12 changed files with 118 additions and 130 deletions

View file

@ -3710,6 +3710,7 @@ void G_MapSlipIntoRoundQueue(UINT8 position, UINT16 map, UINT8 setgametype, bool
roundqueue.entries[position].gametype = setgametype;
roundqueue.entries[position].encore = setencore;
roundqueue.entries[position].rankrestricted = rankrestricted;
roundqueue.entries[position].overridden = false;
}
void G_MapIntoRoundQueue(UINT16 map, UINT8 setgametype, boolean setencore, boolean rankrestricted)
@ -3823,6 +3824,16 @@ void G_GetNextMap(void)
{
nextmap = (nextmapoverride-1);
setalready = true;
// Roundqueue integration: Override the current entry!
if (nextmap < nummapheaders
&& roundqueue.position > 0
&& roundqueue.position <= roundqueue.size)
{
UINT8 entry = roundqueue.position-1;
roundqueue.entries[entry].mapnum = nextmap;
roundqueue.entries[entry].overridden = true;
}
}
else if (roundqueue.size > 0)
{

View file

@ -60,6 +60,7 @@ struct roundentry_t
UINT16 gametype; // Gametype we want to play this in
boolean encore; // Whether this will be flipped
boolean rankrestricted; // For grand prix progression
boolean overridden; // For nextmapoverride
};
extern struct roundqueue

View file

@ -4791,36 +4791,20 @@ void M_DrawPause(void)
standings.showrank = true;
}
patch_t *smallroundpatch = NULL;
if (roundqueue.position > 0 && roundqueue.position <= roundqueue.size)
{
patch_t *smallroundpatch = ST_getRoundPicture(true);
if (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE)
{
if (gametypes[gametype]->gppicmini[0])
smallroundpatch = W_CachePatchName(gametypes[gametype]->gppicmini, PU_PATCH);
else
smallroundpatch = W_CachePatchName("TT_RNSX", PU_PATCH);
}
else if (roundqueue.size > 0)
{
if (roundqueue.roundnum > 0 && roundqueue.roundnum <= 10)
if (smallroundpatch != NULL)
{
smallroundpatch =
W_CachePatchName(
va("TT_RNS%d", roundqueue.roundnum),
PU_PATCH
);
V_DrawMappedPatch(
24, 152 + offset/2,
0,
smallroundpatch,
NULL);
}
}
if (smallroundpatch != NULL)
{
V_DrawMappedPatch(
24, 152 + offset/2,
0,
smallroundpatch,
NULL);
}
Y_RoundQueueDrawer(&standings, offset/2, false, false);
}
}

View file

@ -422,7 +422,7 @@ void podiumData_s::Draw(void)
Y_DrawIntermissionHeader(
(BASEVIDWIDTH * transition_i * FRACUNIT),
(header_centered + header_offset) * FRACUNIT,
false, header, 0, false
false, header, false, false
);
break;
@ -430,7 +430,7 @@ void podiumData_s::Draw(void)
Y_DrawIntermissionHeader(
0,
((header_centered * transition_i) + header_offset) * FRACUNIT,
false, header, 0, false
false, header, false, false
);
break;
@ -438,7 +438,7 @@ void podiumData_s::Draw(void)
Y_DrawIntermissionHeader(
0,
header_offset * FRACUNIT,
false, header, 0, false
false, header, false, false
);
break;
}

View file

@ -364,6 +364,12 @@ void K_InitGrandPrixRank(gpRank_t *rankData)
--------------------------------------------------*/
void gpRank_t::Update(void)
{
if (nextmapoverride != 0)
{
// This level does not matter if the roundqueue entry will be overridden
return;
}
if (numLevels >= ROUNDQUEUE_MAX)
{
CONS_Alert(CONS_ERROR, "gpRank_t::Update(): Too many courses recorded in rank, discarding this round");

View file

@ -382,7 +382,7 @@ void level_tally_t::Init(player_t *player)
}
header[0] = '\0';
gotThru = false;
gotThru = showRoundNum = false;
if (player->spectator == false)
{
@ -422,17 +422,7 @@ void level_tally_t::Init(player_t *player)
);
}
if (roundqueue.size > 0 && roundqueue.roundnum > 0)
{
if ((grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE))
{
roundNum = INTERMISSIONROUND_BONUS;
}
else
{
roundNum = roundqueue.roundnum;
}
}
showRoundNum = true;
}
else
{
@ -444,15 +434,15 @@ void level_tally_t::Init(player_t *player)
}
else
{
if (roundqueue.size > 0 && roundqueue.roundnum > 0
if (roundqueue.position > 0 && roundqueue.position <= roundqueue.size
&& (grandprixinfo.gp == false || grandprixinfo.eventmode == GPEVENT_NONE))
{
snprintf(
header, sizeof header,
"%s", skins[player->skin].realname
"ROUND"
);
roundNum = roundqueue.roundnum;
showRoundNum = true;
}
else if (K_CheckBossIntro() == true && bossinfo.enemyname)
{
@ -977,7 +967,7 @@ void level_tally_t::Draw(void)
Y_DrawIntermissionHeader(
(header_x * FRACUNIT) + (v_width * transition_i * FRACUNIT * h_transition_sign),
header_centered * FRACUNIT,
gotThru, header, roundNum, (r_splitscreen > 0)
gotThru, header, showRoundNum, (r_splitscreen > 0)
);
break;
@ -985,7 +975,7 @@ void level_tally_t::Draw(void)
Y_DrawIntermissionHeader(
header_x * FRACUNIT,
header_centered * transition_i * FRACUNIT,
gotThru, header, roundNum, (r_splitscreen > 0)
gotThru, header, showRoundNum, (r_splitscreen > 0)
);
break;
@ -993,7 +983,7 @@ void level_tally_t::Draw(void)
Y_DrawIntermissionHeader(
header_x * FRACUNIT,
0,
gotThru, header, roundNum, (r_splitscreen > 0)
gotThru, header, showRoundNum, (r_splitscreen > 0)
);
break;
}

View file

@ -66,7 +66,7 @@ struct level_tally_t
UINT16 gt;
boolean gotThru;
char header[64];
UINT8 roundNum;
boolean showRoundNum;
sfxenum_t gradeVoice;
// Stats

View file

@ -733,7 +733,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT16(save->p, players[i].tally.gt);
WRITEUINT8(save->p, players[i].tally.gotThru);
WRITESTRINGN(save->p, players[i].tally.header, 63);
WRITEUINT8(save->p, players[i].tally.roundNum);
WRITEUINT8(save->p, players[i].tally.showRoundNum);
WRITEINT32(save->p, players[i].tally.gradeVoice);
WRITEINT32(save->p, players[i].tally.time);
@ -1290,7 +1290,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
READSTRINGN(save->p, players[i].tally.header, 63);
players[i].tally.header[63] = '\0';
players[i].tally.roundNum = READUINT8(save->p);
players[i].tally.showRoundNum = (boolean)READUINT8(save->p);
players[i].tally.gradeVoice = READINT32(save->p);
players[i].tally.time = READINT32(save->p);
@ -1405,6 +1405,7 @@ static void P_NetArchiveRoundQueue(savebuffer_t *save)
WRITEUINT8(save->p, roundqueue.entries[i].gametype);
WRITEUINT8(save->p, (UINT8)roundqueue.entries[i].encore);
WRITEUINT8(save->p, (UINT8)roundqueue.entries[i].rankrestricted);
WRITEUINT8(save->p, (UINT8)roundqueue.entries[i].overridden);
}
}
@ -1429,6 +1430,7 @@ static void P_NetUnArchiveRoundQueue(savebuffer_t *save)
roundqueue.entries[i].gametype = READUINT8(save->p);
roundqueue.entries[i].encore = (boolean)READUINT8(save->p);
roundqueue.entries[i].rankrestricted = (boolean)READUINT8(save->p);
roundqueue.entries[i].overridden = (boolean)READUINT8(save->p);
}
}

View file

@ -573,8 +573,8 @@ static patch_t *tccirclebg;
static patch_t *tcbanner;
static patch_t *tcbanner2;
static patch_t *tcroundnum[10];
static patch_t *tcroundbonus;
static patch_t *tcroundnum[10], *tsroundnum[10];
static patch_t *tcroundbonus, *tsroundbonus;
static patch_t *tcactnum[10];
static patch_t *tcact;
@ -644,13 +644,20 @@ static void ST_cacheLevelTitle(void)
ttext[1] = (patch_t *)W_CachePatchName("K_BOST02", PU_HUDGFX);
// Cache round #
for (i=1; i < 11; i++)
for (i=1; i <= 10; i++)
{
sprintf(buf, "TT_RND%d", i);
tcroundnum[i-1] = (patch_t *)W_CachePatchName(buf, PU_HUDGFX);
}
tcroundbonus = (patch_t *)W_CachePatchName("TT_RNDX", PU_HUDGFX);
for (i=1; i <= 10; i++)
{
sprintf(buf, "TT_RNS%d", i);
tsroundnum[i-1] = (patch_t *)W_CachePatchName(buf, PU_HUDGFX);
}
tsroundbonus = (patch_t *)W_CachePatchName("TT_RNSX", PU_HUDGFX);
// Cache act #
for (i=0; i < 10; i++)
{
@ -708,6 +715,34 @@ void ST_preDrawTitleCard(void)
// Kart: nothing
}
patch_t *ST_getRoundPicture(boolean small)
{
patch_t *roundico = NULL;
if (roundqueue.position > 0 && roundqueue.position <= roundqueue.size)
{
if (roundqueue.entries[roundqueue.position-1].overridden == true)
{
roundico = small ? tsroundbonus : tcroundbonus;
}
else if (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE)
{
const char *gppic = (small ? gametypes[gametype]->gppicmini : gametypes[gametype]->gppic);
if (gppic[0])
roundico = W_CachePatchName(gppic, PU_PATCH);
else
roundico = tcroundbonus;
}
else if (roundqueue.roundnum > 0 && roundqueue.roundnum <= 10)
{
patch_t **source = small ? tsroundnum : tcroundnum;
roundico = source[roundqueue.roundnum-1];
}
}
return roundico;
}
//
// Run the title card.
// Called from ST_Ticker.
@ -716,7 +751,7 @@ void ST_runTitleCard(void)
{
boolean run = !(paused || P_AutoPause());
INT32 auxticker;
boolean doroundicon = (marathonmode || (roundqueue.size > 0 && roundqueue.position > 0));
boolean doroundicon = (ST_getRoundPicture(false) != NULL);
if (run && lt_fade < 16)
{
@ -930,7 +965,6 @@ void ST_drawTitleCard(void)
char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl;
char *zonttl = mapheaderinfo[gamemap-1]->zonttl; // SRB2kart
UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
boolean doroundicon = (marathonmode || (roundqueue.size > 0 && roundqueue.position > 0));
INT32 acttimer;
fixed_t actscale;
@ -1069,14 +1103,17 @@ void ST_drawTitleCard(void)
V_DrawFixedPatch((chev1x)*FRACUNIT, (chev1y)*FRACUNIT, FRACUNIT, chevtflag, tcchev1, NULL);
V_DrawFixedPatch((chev2x)*FRACUNIT, (chev2y)*FRACUNIT, FRACUNIT, chevtflag, tcchev2, NULL);
patch_t *roundico = ST_getRoundPicture(false);
// Draw ROUND bar, scroll it downwards.
V_DrawFixedPatch(roundx*FRACUNIT, ((-32) + (lt_ticker%32))*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT, tcroundbar, NULL);
// Draw ROUND text
if (doroundicon)
if (roundico)
{
V_DrawFixedPatch((roundx+10)*FRACUNIT, roundy*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT,
((grandprixinfo.gp && grandprixinfo.eventmode != GPEVENT_NONE) ? tcbonus : tcround),
NULL);
}
// round num background
V_DrawFixedPatch(roundnumx*FRACUNIT, roundnumy*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tccirclebg, NULL);
@ -1094,26 +1131,9 @@ void ST_drawTitleCard(void)
}
// If possible, draw round number/icon
if (doroundicon)
if (roundico)
{
patch_t *roundico = NULL;
if (marathonmode)
; // TODO: Ruby
else if (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE)
{
if (gametypes[gametype]->gppic[0])
roundico = W_CachePatchName(gametypes[gametype]->gppic, PU_PATCH);
else
roundico = tcroundbonus; // Generic star
}
else if (roundqueue.size > 0)
{
if (roundqueue.roundnum > 0 && roundqueue.roundnum < 11) // We DEFINITELY need to check boundaries.
roundico = tcroundnum[roundqueue.roundnum-1];
}
if (roundico)
V_DrawFixedPatch(roundnumx*FRACUNIT, roundnumy*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, roundico, NULL);
V_DrawFixedPatch(roundnumx*FRACUNIT, roundnumy*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, roundico, NULL);
}
// Draw both halves of the egg

View file

@ -72,6 +72,8 @@ void ST_drawTitleCard(void);
void ST_preDrawTitleCard(void);
void ST_preLevelTitleCardDrawer(void);
patch_t *ST_getRoundPicture(boolean small);
extern tic_t lt_ticker, lt_lasttic;
extern tic_t lt_exitticker, lt_endtime;
extern tic_t lt_fade;

View file

@ -188,7 +188,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
memset(data.character, 0, sizeof (data.character));
memset(completed, 0, sizeof (completed));
data.numplayers = 0;
data.roundnum = 0;
data.showroundnum = false;
data.isduel = (numplayersingame <= 2);
@ -381,17 +381,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
skins[players[i].skin].realname);
}
if (roundqueue.size > 0 && roundqueue.roundnum > 0)
{
if ((grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE))
{
data.roundnum = INTERMISSIONROUND_BONUS;
}
else
{
data.roundnum = roundqueue.roundnum;
}
}
data.showroundnum = true;
}
else
{
@ -402,17 +392,14 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
}
else
{
if (roundqueue.size > 0
&& roundqueue.roundnum > 0
&& (grandprixinfo.gp == false
|| grandprixinfo.eventmode == GPEVENT_NONE)
)
if (roundqueue.position > 0 && roundqueue.position <= roundqueue.size
&& (grandprixinfo.gp == false || grandprixinfo.eventmode == GPEVENT_NONE))
{
snprintf(data.headerstring,
sizeof data.headerstring,
"ROUND");
data.roundnum = roundqueue.roundnum;
data.showroundnum = true;
}
else if (K_CheckBossIntro() == true && bossinfo.enemyname)
{
@ -1036,7 +1023,8 @@ void Y_RoundQueueDrawer(y_data_t *standings, INT32 offset, boolean doanimations,
}
// 24 pixels when all is said and done
playerx += through * 3;
if (!nextmapoverride)
playerx += through * 3;
if (upwa == false)
{
@ -1299,8 +1287,10 @@ void Y_RoundQueueDrawer(y_data_t *standings, INT32 offset, boolean doanimations,
// This shouldn't show up in regular play, but don't hide it entirely.
chose_dot = prize_dot;
}
else if (grandprixinfo.gp == true
&& roundqueue.entries[i].gametype != roundqueue.entries[0].gametype
else if (
roundqueue.entries[i].overridden == true
|| (grandprixinfo.gp == true
&& roundqueue.entries[i].gametype != roundqueue.entries[0].gametype)
)
{
if ((gametypes[roundqueue.entries[i].gametype]->rules & GTR_PRISONS) == GTR_PRISONS)
@ -1436,7 +1426,7 @@ void Y_DrawIntermissionButton(INT32 startslide, INT32 through)
}
}
void Y_DrawIntermissionHeader(fixed_t x, fixed_t y, boolean gotthrough, const char *headerstring, UINT8 roundnum, boolean small)
void Y_DrawIntermissionHeader(fixed_t x, fixed_t y, boolean gotthrough, const char *headerstring, boolean showroundnum, boolean small)
{
const INT32 v_width = (small ? BASEVIDWIDTH/2 : BASEVIDWIDTH);
const fixed_t frac = (small ? FRACUNIT/2 : FRACUNIT);
@ -1473,40 +1463,24 @@ void Y_DrawIntermissionHeader(fixed_t x, fixed_t y, boolean gotthrough, const ch
}
// Draw round numbers
patch_t *roundpatch = NULL;
if (roundnum == INTERMISSIONROUND_BONUS)
if (showroundnum == true)
{
const char *gppic = (small ? gametypes[gametype]->gppicmini : gametypes[gametype]->gppic);
if (gppic[0])
roundpatch = W_CachePatchName(gppic, PU_PATCH);
else
roundpatch = W_CachePatchName(
va("TT_RN%cX", (small ? 'S' : 'D')),
PU_PATCH
);
}
else if (roundnum > 0 && roundnum <= 10)
{
roundpatch = W_CachePatchName(
va("TT_RN%c%d", (small ? 'S' : 'D'), roundnum),
PU_PATCH
);
}
patch_t *roundpatch = ST_getRoundPicture(small);
if (roundpatch)
{
fixed_t roundx = (v_width * 3 * FRACUNIT) / 4;
if (headerwidth != 0)
if (roundpatch)
{
const fixed_t roundoffset = (8 * frac) + (roundpatch->width * FRACUNIT);
fixed_t roundx = (v_width * 3 * FRACUNIT) / 4;
roundx = headerx + roundoffset;
headerx -= roundoffset/2;
if (headerwidth != 0)
{
const fixed_t roundoffset = (8 * frac) + (roundpatch->width * FRACUNIT);
roundx = headerx + roundoffset;
headerx -= roundoffset/2;
}
V_DrawFixedPatch(x + roundx, (39 * frac) + y, FRACUNIT, small_flag, roundpatch, NULL);
}
V_DrawFixedPatch(x + roundx, (39 * frac) + y, FRACUNIT, small_flag, roundpatch, NULL);
}
V_DrawTitleCardStringFixed(x + headerx, y + headery, FRACUNIT, headerstring, small_flag, false, 0, 0, small);
@ -1599,7 +1573,7 @@ void Y_IntermissionDrawer(void)
}
// Draw the header bar
Y_DrawIntermissionHeader(x << FRACBITS, 0, data.gotthrough, data.headerstring, data.roundnum, false);
Y_DrawIntermissionHeader(x << FRACBITS, 0, data.gotthrough, data.headerstring, data.showroundnum, false);
// Returns early if there's no players to draw
Y_PlayerStandingsDrawer(&data, x);

View file

@ -16,8 +16,6 @@
extern "C" {
#endif
#define INTERMISSIONROUND_BONUS UINT8_MAX
typedef struct
{
boolean rankingsmode; // rankings mode
@ -25,7 +23,7 @@ typedef struct
boolean showrank; // show rank-restricted queue entry at the end, if it exists
boolean encore; // encore mode
boolean isduel; // duel mode
UINT8 roundnum; // round number
boolean showroundnum; // round number
char headerstring[64]; // holds levelnames up to 64 characters
@ -47,7 +45,7 @@ typedef struct
INT32 linemeter; // For GP only
} y_data_t;
void Y_DrawIntermissionHeader(INT32 x, INT32 y, boolean gotthrough, const char *headerstring, UINT8 roundnum, boolean small);
void Y_DrawIntermissionHeader(INT32 x, INT32 y, boolean gotthrough, const char *headerstring, boolean showroundnum, boolean small);
void Y_IntermissionDrawer(void);
void Y_Ticker(void);