diff --git a/src/doomstat.h b/src/doomstat.h index efce0e5d6..4f3a5ac58 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -36,6 +36,10 @@ extern "C" { // Selected map etc. // ============================= +#define ROUNDQUEUE_MAX 10 // sane max? maybe make dynamically allocated later +#define ROUNDQUEUE_CLEAR UINT16_MAX // lives in gametype field of packets +// The roundqueue itself is resident in g_game.h + // Selected by user. extern INT16 gamemap; extern char mapmusname[7]; diff --git a/src/g_game.c b/src/g_game.c index 6e92351f3..2e1222f17 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -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) { @@ -5640,7 +5651,7 @@ void G_SaveGameData(void) // Can be called by the startup code or the menu task. // -#define SAV_VERSIONMINOR 2 +#define SAV_VERSIONMINOR 3 void G_LoadGame(void) { diff --git a/src/g_game.h b/src/g_game.h index 6d050c75d..9bf444b34 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -54,15 +54,13 @@ typedef enum NEXTMAP_SPECIAL = NEXTMAP_INVALID } nextmapspecial_t; -#define ROUNDQUEUE_MAX 10 // sane max? maybe make dynamically allocated later -#define ROUNDQUEUE_CLEAR UINT16_MAX // lives in gametype field of packets - struct roundentry_t { UINT16 mapnum; // Map number at this position 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 diff --git a/src/k_menudraw.c b/src/k_menudraw.c index ca030b7a1..e73087c6f 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -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); } } diff --git a/src/k_podium.cpp b/src/k_podium.cpp index a0c275846..6635071a3 100644 --- a/src/k_podium.cpp +++ b/src/k_podium.cpp @@ -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; } @@ -714,6 +714,15 @@ void podiumData_s::Draw(void) true, (rank.position > 3) ); + + if (state == PODIUM_ST_DONE) + { + Y_DrawIntermissionButton(delay, 0); + } + else if (state == PODIUM_ST_EXIT) + { + Y_DrawIntermissionButton(-1, (2*TICRATE) - delay); + } } } @@ -1130,9 +1139,4 @@ void K_CeremonyDrawer(void) } g_podiumData.Draw(); - - if (g_podiumData.state >= PODIUM_ST_DONE) - { - Y_DrawIntermissionButton(0, 0); - } } diff --git a/src/k_rank.cpp b/src/k_rank.cpp index 94208a9ed..702a55fe8 100644 --- a/src/k_rank.cpp +++ b/src/k_rank.cpp @@ -364,6 +364,18 @@ 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"); + return; + } + gpRank_level_t *const lvl = &levels[numLevels]; prisons += numtargets; diff --git a/src/k_rank.h b/src/k_rank.h index c50e49a82..2548aacf0 100644 --- a/src/k_rank.h +++ b/src/k_rank.h @@ -62,7 +62,7 @@ struct gpRank_t boolean specialWon; UINT8 numLevels; - gpRank_level_t levels[8]; + gpRank_level_t levels[ROUNDQUEUE_MAX]; #ifdef __cplusplus void Init(void); diff --git a/src/k_tally.cpp b/src/k_tally.cpp index 392209186..f54d59b38 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -386,7 +386,7 @@ void level_tally_t::Init(player_t *player) } header[0] = '\0'; - gotThru = false; + gotThru = showRoundNum = false; if (player->spectator == false) { @@ -426,17 +426,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 { @@ -448,15 +438,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) { @@ -981,7 +971,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; @@ -989,7 +979,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; @@ -997,7 +987,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; } diff --git a/src/k_tally.h b/src/k_tally.h index 1eb37020f..ff4870184 100644 --- a/src/k_tally.h +++ b/src/k_tally.h @@ -66,7 +66,7 @@ struct level_tally_t UINT16 gt; boolean gotThru; char header[64]; - UINT8 roundNum; + boolean showRoundNum; sfxenum_t gradeVoice; // Stats diff --git a/src/p_saveg.c b/src/p_saveg.c index f837a73c4..ea80ea855 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -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); } } @@ -5882,53 +5884,92 @@ static inline void P_ArchiveMisc(savebuffer_t *save) WRITEUINT8(save->p, roundqueue.roundnum); UINT8 i; + UINT16 mapnum; for (i = 0; i < roundqueue.size; i++) { - UINT16 mapnum = roundqueue.entries[i].mapnum; - UINT32 val = 0; // no good default, will all-but-guarantee bad save - if (mapnum < nummapheaders && mapheaderinfo[mapnum] != NULL) - val = mapheaderinfo[mapnum]->lumpnamehash; + mapnum = roundqueue.entries[i].mapnum; - WRITEUINT32(save->p, val); + if (mapnum < nummapheaders && mapheaderinfo[mapnum] != NULL) + { + WRITEUINT8(save->p, roundqueue.entries[i].overridden); + + if (roundqueue.entries[i].overridden == true) + { + WRITESTRINGL(save->p, mapheaderinfo[mapnum]->lumpname, MAXMAPLUMPNAME); + } + else + { + WRITEUINT32(save->p, mapheaderinfo[mapnum]->lumpnamehash); + } + } + else + { + // eh, not our problem. provide something that'll almost certainly fail on load + WRITEUINT8(save->p, false); + WRITEUINT32(save->p, 0); + } } // Rank information { - WRITEUINT8(save->p, grandprixinfo.rank.numPlayers); - WRITEUINT8(save->p, grandprixinfo.rank.totalPlayers); + const gpRank_t *rank = &grandprixinfo.rank; - WRITEUINT8(save->p, grandprixinfo.rank.position); - WRITEUINT8(save->p, grandprixinfo.rank.skin); + WRITEUINT8(save->p, rank->numPlayers); + WRITEUINT8(save->p, rank->totalPlayers); - WRITEUINT32(save->p, grandprixinfo.rank.winPoints); - WRITEUINT32(save->p, grandprixinfo.rank.totalPoints); + WRITEUINT8(save->p, rank->position); + WRITEUINT8(save->p, rank->skin); - WRITEUINT32(save->p, grandprixinfo.rank.laps); - WRITEUINT32(save->p, grandprixinfo.rank.totalLaps); + WRITEUINT32(save->p, rank->winPoints); + WRITEUINT32(save->p, rank->totalPoints); - WRITEUINT32(save->p, (grandprixinfo.rank.continuesUsed + 1)); + WRITEUINT32(save->p, rank->laps); + WRITEUINT32(save->p, rank->totalLaps); - WRITEUINT32(save->p, grandprixinfo.rank.prisons); - WRITEUINT32(save->p, grandprixinfo.rank.totalPrisons); + WRITEUINT32(save->p, (rank->continuesUsed + 1)); - WRITEUINT32(save->p, grandprixinfo.rank.rings); - WRITEUINT32(save->p, grandprixinfo.rank.totalRings); + WRITEUINT32(save->p, rank->prisons); + WRITEUINT32(save->p, rank->totalPrisons); - WRITEUINT8(save->p, (UINT8)grandprixinfo.rank.specialWon); + WRITEUINT32(save->p, rank->rings); + WRITEUINT32(save->p, rank->totalRings); - /* - WRITEUINT8(save->p, grandprixinfo.rank.numLevels); + WRITEUINT8(save->p, (UINT8)rank->specialWon); - for (i = 0; i < grandprixinfo.rank.stages; i++) + WRITEUINT8(save->p, rank->numLevels); + + for (i = 0; i < rank->numLevels; i++) { - UINT8 j; - for (j = 0; j < grandprixinfo.rank.numPlayers; j++) + const gpRank_level_t *lvl = &rank->levels[i]; + + UINT32 mapHash = 0; // no good default, will all-but-guarantee bad save + UINT16 id = lvl->id-1; // GAMEMAP BASED AAAGH + if (id < nummapheaders && mapheaderinfo[id] != NULL) { - + mapHash = mapheaderinfo[id]->lumpnamehash; + //CONS_Printf("wrote map \"%s\" from rank in %u/%u\n", mapheaderinfo[id]->lumpname, i, rank->numLevels); + } + WRITEUINT32(save->p, mapHash); + + WRITEINT32(save->p, lvl->event); + WRITEUINT32(save->p, lvl->time); + WRITEUINT16(save->p, lvl->totalLapPoints); + WRITEUINT16(save->p, lvl->totalPrisons); + + UINT8 j; + for (j = 0; j < rank->numPlayers; j++) + { + const gpRank_level_perplayer_t *plr = &lvl->perPlayer[j]; + + WRITEUINT8(save->p, plr->position); + WRITEUINT8(save->p, plr->rings); + WRITEUINT16(save->p, plr->lapPoints); + WRITEUINT16(save->p, plr->prisons); + WRITEUINT8(save->p, (UINT8)plr->gotSpecialPrize); + WRITESINT8(save->p, (SINT8)plr->grade); } } - */ } // Marathon information @@ -6042,56 +6083,141 @@ static boolean P_UnArchiveSPGame(savebuffer_t *save) if (roundqueue.size != size) { - CONS_Alert(CONS_ERROR, "P_UnArchiveSPGame: Cup \"%s\"'s level composition has changed between game launches (differs in level count).\n", cupname); + CONS_Alert(CONS_ERROR, "P_UnArchiveSPGame: Cup \"%s\"'s level composition has changed between game launches (%u expected, got %u).\n", cupname, roundqueue.size, size); return false; } if (roundqueue.position == 0 || roundqueue.position > size) { - CONS_Alert(CONS_ERROR, "P_UnArchiveSPGame: Position in the round queue is invalid.\n"); + CONS_Alert(CONS_ERROR, "P_UnArchiveSPGame: Position %u/%d in the round queue is invalid.\n", roundqueue.position, size); return false; } - UINT8 i; + UINT8 i, j; + UINT16 mapnum; for (i = 0; i < roundqueue.size; i++) { - UINT32 val = READUINT32(save->p); - UINT16 mapnum = roundqueue.entries[i].mapnum; - - if (mapnum < nummapheaders && mapheaderinfo[mapnum] != NULL) + roundqueue.entries[i].overridden = (boolean)READUINT8(save->p); + if (roundqueue.entries[i].overridden == true) { - if (mapheaderinfo[mapnum]->lumpnamehash == val) + if (i >= roundqueue.position) + { + CONS_Alert(CONS_ERROR, "P_UnArchiveSPGame: Cup \"%s\"'s level composition is invalid (has been overridden at entry %u/%u, ahead of the queue head %u).\n", cupname, i, roundqueue.size, roundqueue.position-1); + return false; + } + + char mapname[MAXMAPLUMPNAME]; + + READSTRINGL(save->p, mapname, MAXMAPLUMPNAME); + mapnum = G_MapNumber(mapname); + + if (mapnum < nummapheaders) + { + roundqueue.entries[i].mapnum = mapnum; continue; + } + } + else + { + UINT32 val = READUINT32(save->p); + + mapnum = roundqueue.entries[i].mapnum; + if (mapnum < nummapheaders && mapheaderinfo[mapnum] != NULL) + { + if (mapheaderinfo[mapnum]->lumpnamehash == val) + continue; + } } - CONS_Alert(CONS_ERROR, "P_UnArchiveSPGame: Cup \"%s\"'s level composition has changed between game launches (differs at level %u).\n", cupname, i); + CONS_Alert(CONS_ERROR, "P_UnArchiveSPGame: Cup \"%s\"'s level composition has changed between game launches (differs at queue entry %u/%u).\n", cupname, i, roundqueue.size); return false; } // Rank information { - grandprixinfo.rank.numPlayers = READUINT8(save->p); - grandprixinfo.rank.totalPlayers = READUINT8(save->p); + gpRank_t *const rank = &grandprixinfo.rank; - grandprixinfo.rank.position = READUINT8(save->p); - grandprixinfo.rank.skin = READUINT8(save->p); + rank->numPlayers = READUINT8(save->p); + rank->totalPlayers = READUINT8(save->p); - grandprixinfo.rank.winPoints = READUINT32(save->p); - grandprixinfo.rank.totalPoints = READUINT32(save->p); + rank->position = READUINT8(save->p); + rank->skin = READUINT8(save->p); - grandprixinfo.rank.laps = READUINT32(save->p); - grandprixinfo.rank.totalLaps = READUINT32(save->p); + rank->winPoints = READUINT32(save->p); + rank->totalPoints = READUINT32(save->p); - grandprixinfo.rank.continuesUsed = READUINT32(save->p); + rank->laps = READUINT32(save->p); + rank->totalLaps = READUINT32(save->p); - grandprixinfo.rank.prisons = READUINT32(save->p); - grandprixinfo.rank.totalPrisons = READUINT32(save->p); + rank->continuesUsed = READUINT32(save->p); - grandprixinfo.rank.rings = READUINT32(save->p); - grandprixinfo.rank.totalRings = READUINT32(save->p); + rank->prisons = READUINT32(save->p); + rank->totalPrisons = READUINT32(save->p); - grandprixinfo.rank.specialWon = (boolean)READUINT8(save->p); + rank->rings = READUINT32(save->p); + rank->totalRings = READUINT32(save->p); + + rank->specialWon = (boolean)READUINT8(save->p); + + rank->numLevels = READUINT8(save->p); + + if (rank->numLevels > roundqueue.size) + { + CONS_Alert(CONS_ERROR, "P_UnArchiveSPGame: Cup \"%s\"'s level composition has changed between game launches (%u levels ranked VS %u).\n", cupname, rank->numLevels, roundqueue.size); + return false; + } + + boolean seeninqueue[ROUNDQUEUE_MAX]; + memset(seeninqueue, 0, sizeof (boolean) * roundqueue.size); + + for (i = 0; i < rank->numLevels; i++) + { + gpRank_level_t *const lvl = &rank->levels[i]; + + UINT32 mapHash = READUINT32(save->p); + + // Hidden Palace can adjust cup composition, and this level stuff is + // purely visual anyway, so don't be as strict as the earlier check. + for (j = 0; j < roundqueue.size; j++) + { + // Simple handling to accomodate collisions + if (seeninqueue[j] == true) + continue; + + UINT16 id = roundqueue.entries[j].mapnum; + + if (mapheaderinfo[id]->lumpnamehash != mapHash) + continue; + + lvl->id = id+1; + seeninqueue[j] = true; + break; + } + + if (j == roundqueue.size) + { + CONS_Alert(CONS_ERROR, "P_UnArchiveSPGame: Cup \"%s\"'s level composition has changed between game launches (ranked level %u/%u not found in queue).\n", cupname, i, rank->numLevels); + return false; + } + + lvl->event = READINT32(save->p); + lvl->time = READUINT32(save->p); + lvl->totalLapPoints = READUINT16(save->p); + lvl->totalPrisons = READUINT16(save->p); + + for (j = 0; j < rank->numPlayers; j++) + { + gpRank_level_perplayer_t *const plr = &lvl->perPlayer[j]; + + plr->position = READUINT8(save->p); + plr->rings = READUINT8(save->p); + plr->lapPoints = READUINT16(save->p); + plr->prisons = READUINT16(save->p); + plr->gotSpecialPrize = (boolean)READUINT8(save->p); + plr->grade = (gp_rank_e)READSINT8(save->p); + } + } } // Marathon information diff --git a/src/p_saveg.h b/src/p_saveg.h index 8657ee9d2..d73cb9a8b 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -23,7 +23,8 @@ extern "C" { #endif // 1024 bytes is plenty for a savegame -#define SAVEGAMESIZE (1024) +// ...but we'll be accomodating of a heavily replaced Round Queue. +#define SAVEGAMESIZE (2048) // For netgames #define NETSAVEGAMESIZE (768*1024) diff --git a/src/st_stuff.c b/src/st_stuff.c index ac670d5c6..82be792c5 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -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 diff --git a/src/st_stuff.h b/src/st_stuff.h index 27ef903be..a48eaf213 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -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; diff --git a/src/y_inter.c b/src/y_inter.c index 5da755835..2650ac526 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -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); @@ -1773,14 +1747,16 @@ void Y_Ticker(void) } // Animation sounds for roundqueue, see Y_RoundQueueDrawer - if (roundqueue.size != 0 + if (roundqueue.size > 1 && roundqueue.position != 0 && (timer - 1) <= 2*TICRATE) { const INT32 through = ((2*TICRATE) - (timer - 1)); + UINT8 workingqueuesize = roundqueue.size - 1; + if (data.showrank == true - && roundqueue.position == roundqueue.size-1) + && roundqueue.position == workingqueuesize) { // Handle special entry on the end if (through == data.linemeter && timer > 2) @@ -1793,11 +1769,20 @@ void Y_Ticker(void) S_StartSound(NULL, sfx_gpmetr); } } - else if (through == 9 - && roundqueue.position < roundqueue.size) + else { - // Impactful landing - S_StartSound(NULL, sfx_kc50); + if (data.showrank == false + && roundqueue.entries[workingqueuesize].rankrestricted == true) + { + workingqueuesize--; + } + + if (through == 9 + && roundqueue.position <= workingqueuesize) + { + // Impactful landing + S_StartSound(NULL, sfx_kc50); + } } } diff --git a/src/y_inter.h b/src/y_inter.h index a85017409..c1ffd7936 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -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);