Post-roundqueue updates
Was just going to fix some bugs, but you know me... * `map +` works again (now yields the calculated nextmap, ignoring advancemap) * `showmap` prints the correct map title when previewing * Roundqueue no longer trips ASan (aww, just one byte short!) * Added NEXTMAP_RANDOM so the intermission drawer can now be smart, and not just go off of cv_advancemap but actually show where you're going!
This commit is contained in:
parent
0b7fbbbb62
commit
2eaa0cd39c
5 changed files with 236 additions and 216 deletions
|
|
@ -3366,7 +3366,7 @@ INT32 mapchangepending = 0;
|
|||
*/
|
||||
void D_MapChange(mapnum_t mapnum, INT32 newgametype, boolean pencoremode, boolean presetplayers, INT32 delay, boolean skipprecutscene, boolean pforcespecialstage)
|
||||
{
|
||||
static char buf[1+1+1+1+1+2+4];
|
||||
static char buf[1+1+1+1+2+2+4];
|
||||
static char *buf_p = buf;
|
||||
// The supplied data are assumed to be good.
|
||||
I_Assert(delay >= 0 && delay <= 2);
|
||||
|
|
@ -6790,19 +6790,13 @@ static void Command_Showmap_f(void)
|
|||
{
|
||||
char *title = G_BuildMapTitle(printmap + 1);
|
||||
|
||||
if (mapheaderinfo[gamemap-1]->zonttl[0] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
|
||||
/* if (mapheaderinfo[printmap]->menuttl[0])
|
||||
{
|
||||
if (mapheaderinfo[gamemap-1]->actnum[0])
|
||||
CONS_Printf("%s (%d): %s %s %s", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl, mapheaderinfo[gamemap-1]->actnum);
|
||||
else
|
||||
CONS_Printf("%s (%d): %s %s\n", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl);
|
||||
CONS_Printf("%s (%d): %s / %s\n", G_BuildMapName(printmap + 1), printmap, title, mapheaderinfo[printmap]->menuttl);
|
||||
}
|
||||
else
|
||||
else */
|
||||
{
|
||||
if (mapheaderinfo[gamemap-1]->actnum[0])
|
||||
CONS_Printf("%s (%d): %s %s\n", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum);
|
||||
else
|
||||
CONS_Printf("%s (%d): %s\n", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl);
|
||||
CONS_Printf("%s (%d): %s\n", G_BuildMapName(printmap + 1), printmap, title);
|
||||
}
|
||||
|
||||
Z_Free(title);
|
||||
|
|
|
|||
412
src/g_game.c
412
src/g_game.c
|
|
@ -4913,12 +4913,197 @@ void G_GPCupIntoRoundQueue(cupheader_t *cup, UINT8 setgametype, boolean setencor
|
|||
}
|
||||
}
|
||||
|
||||
static UINT8 G_GetRoundQueuePosition(void)
|
||||
{
|
||||
UINT8 position = roundqueue.position;
|
||||
boolean permitrank = false;
|
||||
/*if (grandprixinfo.gp == true
|
||||
&& grandprixinfo.gamespeed >= KARTSPEED_NORMAL)
|
||||
{
|
||||
// On A rank pace? Then you get a chance for S rank!
|
||||
permitrank = (K_CalculateGPPercent(&grandprixinfo.rank) >= K_SealedStarEntryRequirement(&grandprixinfo.rank));
|
||||
|
||||
// If you're on Master, a win floats you to rank-restricted levels for free.
|
||||
// (This is a different class of challenge!)
|
||||
if (grandprixinfo.masterbots && grandprixinfo.rank.position <= 1)
|
||||
permitrank = true;
|
||||
}*/
|
||||
|
||||
while (position < roundqueue.size
|
||||
&& (roundqueue.entries[position].mapnum >= nummapheaders
|
||||
|| mapheaderinfo[roundqueue.entries[position].mapnum] == NULL
|
||||
|| (permitrank == false && roundqueue.entries[position].rankrestricted == true)))
|
||||
{
|
||||
// Skip all restricted queue entries.
|
||||
position++;
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
// gets the nextmap number WITHOUT ANY GODDAMN SIDE EFFECTS!
|
||||
// any gametype changes or roundqueue updates should happen in G_GetNextMap or elsewhere
|
||||
mapnum_t G_CheckNextMap(boolean noadvancemap)
|
||||
{
|
||||
mapnum_t currentmap = G_GamestateUsesLevel() ? gamemap-1 : prevmap;
|
||||
//boolean spec = G_IsSpecialStage(currentmap);
|
||||
INT32 i;
|
||||
|
||||
if (nextmapoverride != 0)
|
||||
{
|
||||
return nextmapoverride-1;
|
||||
}
|
||||
else if (roundqueue.size > 0)
|
||||
{
|
||||
UINT8 position = G_GetRoundQueuePosition();
|
||||
if (position < roundqueue.size)
|
||||
{
|
||||
// The next entry in the queue is valid; set it as nextmap!
|
||||
return roundqueue.entries[position].mapnum;
|
||||
}
|
||||
else if (grandprixinfo.gp == true)
|
||||
{
|
||||
// In GP, we're now ready to go to the ceremony.
|
||||
return NEXTMAP_CEREMONY;
|
||||
}
|
||||
}
|
||||
else if (grandprixinfo.gp == true)
|
||||
{
|
||||
// Fast And Rapid Testing
|
||||
// this codepath is exclusively accessible through console/command line
|
||||
return currentmap;
|
||||
}
|
||||
|
||||
// no special cases? time to cycle maps!
|
||||
mapnum_t newmap = NEXTMAP_INVALID;
|
||||
UINT32 tolflag = G_TOLFlag(gametype);
|
||||
mapnum_t cm;
|
||||
|
||||
if (true/*!(gametyperules & GTR_NOCUPSELECT)*/)
|
||||
{
|
||||
cupheader_t *cup = mapheaderinfo[gamemap-1]->cup;
|
||||
UINT8 gettingresult = 0;
|
||||
|
||||
while (cup)
|
||||
{
|
||||
// Not unlocked? Grab the next result afterwards
|
||||
/*if (!marathonmode && M_CupLocked(cup))
|
||||
{
|
||||
cup = cup->next;
|
||||
gettingresult = 1;
|
||||
continue;
|
||||
}*/
|
||||
|
||||
for (i = 0; i < cup->numlevels; i++)
|
||||
{
|
||||
cm = cup->cachedlevels[i];
|
||||
|
||||
// Not valid?
|
||||
if (cm >= nummapheaders
|
||||
|| !mapheaderinfo[cm]
|
||||
|| mapheaderinfo[cm]->lumpnum == LUMPERROR
|
||||
|| !(mapheaderinfo[cm]->typeoflevel & tolflag)
|
||||
|| (!marathonmode && M_MapLocked(cm+1)))
|
||||
continue;
|
||||
|
||||
// If the map is in multiple cups, only consider the first one valid.
|
||||
if (mapheaderinfo[cm]->cup != cup)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Grab the first valid after the map you're on
|
||||
if (gettingresult)
|
||||
{
|
||||
newmap = cm;
|
||||
gettingresult = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Not the map you're on?
|
||||
if (cm != currentmap)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok, this is the current map, time to get the next
|
||||
gettingresult = 1;
|
||||
}
|
||||
|
||||
// We have a good nextmap?
|
||||
if (gettingresult == 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Ok, iterate to the next
|
||||
cup = cup->next;
|
||||
}
|
||||
}
|
||||
|
||||
// still nothing? just go through maps sequentially...
|
||||
if (newmap == NEXTMAP_INVALID)
|
||||
{
|
||||
cm = currentmap;
|
||||
|
||||
do
|
||||
{
|
||||
if (++cm >= nummapheaders)
|
||||
cm = 0;
|
||||
|
||||
if (!mapheaderinfo[cm]
|
||||
|| mapheaderinfo[cm]->lumpnum == LUMPERROR
|
||||
|| !(mapheaderinfo[cm]->typeoflevel & tolflag)
|
||||
|| (mapheaderinfo[cm]->menuflags & LF2_HIDEINMENU))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (M_MapLocked(cm + 1) == true)
|
||||
{
|
||||
// We haven't earned this one.
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
} while (cm != currentmap);
|
||||
|
||||
newmap = cm;
|
||||
}
|
||||
|
||||
if (!noadvancemap && K_CanChangeRules(true))
|
||||
{
|
||||
switch (cv_advancemap.value)
|
||||
{
|
||||
case 0: // Stay on same map.
|
||||
return currentmap;
|
||||
case 3: // Voting screen.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (players[i].spectator)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (i != MAXPLAYERS)
|
||||
return NEXTMAP_VOTING;
|
||||
/* FALLTHRU */
|
||||
case 2: // Go to random map.
|
||||
return NEXTMAP_RANDOM;
|
||||
default:
|
||||
// Loop back around
|
||||
return newmap < NEXTMAP_SPECIAL ? newmap : G_GetFirstMapOfGametype(gametype);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return newmap;
|
||||
}
|
||||
}
|
||||
|
||||
void G_GetNextMap(void)
|
||||
{
|
||||
//boolean spec = G_IsSpecialStage(prevmap+1);
|
||||
INT32 i;
|
||||
boolean setalready = false;
|
||||
|
||||
if (!server)
|
||||
{
|
||||
// Server is authoriative, not you
|
||||
|
|
@ -4945,11 +5130,10 @@ void G_GetNextMap(void)
|
|||
|
||||
// go to next level
|
||||
// nextmap is 0-based, unlike gamemap
|
||||
nextmap = G_CheckNextMap(false);
|
||||
|
||||
if (nextmapoverride != 0)
|
||||
{
|
||||
nextmap = (nextmapoverride-1);
|
||||
setalready = true;
|
||||
|
||||
if (nextmap < nummapheaders && mapheaderinfo[nextmap])
|
||||
{
|
||||
if ((mapheaderinfo[nextmap]->typeoflevel & G_TOLFlag(gametype)) == 0)
|
||||
|
|
@ -4987,73 +5171,43 @@ void G_GetNextMap(void)
|
|||
}
|
||||
else if (roundqueue.size > 0)
|
||||
{
|
||||
boolean permitrank = false;
|
||||
/*if (grandprixinfo.gp == true
|
||||
&& grandprixinfo.gamespeed >= KARTSPEED_NORMAL)
|
||||
UINT8 position = G_GetRoundQueuePosition();
|
||||
|
||||
if (position < roundqueue.size)
|
||||
{
|
||||
// On A rank pace? Then you get a chance for S rank!
|
||||
permitrank = (K_CalculateGPPercent(&grandprixinfo.rank) >= K_SealedStarEntryRequirement(&grandprixinfo.rank));
|
||||
deferencoremode = roundqueue.entries[position].encore;
|
||||
|
||||
// If you're on Master, a win floats you to rank-restricted levels for free.
|
||||
// (This is a different class of challenge!)
|
||||
if (grandprixinfo.masterbots && grandprixinfo.rank.position <= 1)
|
||||
permitrank = true;
|
||||
}*/
|
||||
|
||||
while (roundqueue.position < roundqueue.size
|
||||
&& (roundqueue.entries[roundqueue.position].mapnum >= nummapheaders
|
||||
|| mapheaderinfo[roundqueue.entries[roundqueue.position].mapnum] == NULL
|
||||
|| (permitrank == false && roundqueue.entries[roundqueue.position].rankrestricted == true)))
|
||||
{
|
||||
// Skip all restricted queue entries.
|
||||
roundqueue.position++;
|
||||
}
|
||||
|
||||
if (roundqueue.position < roundqueue.size)
|
||||
{
|
||||
// The next entry in the queue is valid; set it as nextmap!
|
||||
nextmap = roundqueue.entries[roundqueue.position].mapnum;
|
||||
deferencoremode = roundqueue.entries[roundqueue.position].encore;
|
||||
|
||||
// And we handle gametype changes, too.
|
||||
if (roundqueue.entries[roundqueue.position].gametype != gametype)
|
||||
// Handle gametype changes.
|
||||
if (roundqueue.entries[position].gametype != gametype)
|
||||
{
|
||||
INT32 lastgametype = gametype;
|
||||
G_SetGametype(roundqueue.entries[roundqueue.position].gametype);
|
||||
G_SetGametype(roundqueue.entries[position].gametype);
|
||||
D_GameTypeChanged(lastgametype);
|
||||
}
|
||||
|
||||
// Is this special..?
|
||||
forcespecialstage = roundqueue.entries[roundqueue.position].rankrestricted;
|
||||
forcespecialstage = roundqueue.entries[position].rankrestricted;
|
||||
|
||||
// On entering roundqueue mode, kill the non-PWR between-round scores.
|
||||
// This makes it viable as a future tournament mode base.
|
||||
if (roundqueue.position == 0)
|
||||
if (position == 0)
|
||||
{
|
||||
forceresetplayers = true;
|
||||
}
|
||||
|
||||
// Handle primary queue position update.
|
||||
roundqueue.position++;
|
||||
roundqueue.position = position + 1;
|
||||
if (grandprixinfo.gp == false || gametype == GT_RACE) // roundqueue.entries[0].gametype
|
||||
{
|
||||
roundqueue.roundnum++;
|
||||
}
|
||||
|
||||
setalready = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wipe the queue info.
|
||||
memset(&roundqueue, 0, sizeof(struct roundqueue));
|
||||
|
||||
if (grandprixinfo.gp == true)
|
||||
{
|
||||
// In GP, we're now ready to go to the ceremony.
|
||||
nextmap = NEXTMAP_CEREMONY;
|
||||
setalready = true;
|
||||
}
|
||||
else
|
||||
if (grandprixinfo.gp == false)
|
||||
{
|
||||
// On exiting roundqueue mode, kill the non-PWR between-round scores.
|
||||
// This prevents future tournament winners from carrying their wins out.
|
||||
|
|
@ -5064,151 +5218,6 @@ void G_GetNextMap(void)
|
|||
// Make sure the next D_MapChange sends updated roundqueue state.
|
||||
roundqueue.netcommunicate = true;
|
||||
}
|
||||
else if (grandprixinfo.gp == true)
|
||||
{
|
||||
// Fast And Rapid Testing
|
||||
// this codepath is exclusively accessible through console/command line
|
||||
nextmap = prevmap;
|
||||
setalready = true;
|
||||
}
|
||||
|
||||
if (setalready == false)
|
||||
{
|
||||
UINT32 tolflag = G_TOLFlag(gametype);
|
||||
register INT16 cm;
|
||||
|
||||
if (true/*!(gametyperules & GTR_NOCUPSELECT)*/)
|
||||
{
|
||||
cupheader_t *cup = mapheaderinfo[gamemap-1]->cup;
|
||||
UINT8 gettingresult = 0;
|
||||
|
||||
while (cup)
|
||||
{
|
||||
// Not unlocked? Grab the next result afterwards
|
||||
/*if (!marathonmode && M_CupLocked(cup))
|
||||
{
|
||||
cup = cup->next;
|
||||
gettingresult = 1;
|
||||
continue;
|
||||
}*/
|
||||
|
||||
for (i = 0; i < cup->numlevels; i++)
|
||||
{
|
||||
cm = cup->cachedlevels[i];
|
||||
|
||||
// Not valid?
|
||||
if (cm >= nummapheaders
|
||||
|| !mapheaderinfo[cm]
|
||||
|| mapheaderinfo[cm]->lumpnum == LUMPERROR
|
||||
|| !(mapheaderinfo[cm]->typeoflevel & tolflag)
|
||||
|| (!marathonmode && M_MapLocked(cm+1)))
|
||||
continue;
|
||||
|
||||
// If the map is in multiple cups, only consider the first one valid.
|
||||
if (mapheaderinfo[cm]->cup != cup)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Grab the first valid after the map you're on
|
||||
if (gettingresult)
|
||||
{
|
||||
nextmap = cm;
|
||||
gettingresult = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Not the map you're on?
|
||||
if (cm != prevmap)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok, this is the current map, time to get the next
|
||||
gettingresult = 1;
|
||||
}
|
||||
|
||||
// We have a good nextmap?
|
||||
if (gettingresult == 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Ok, iterate to the next
|
||||
cup = cup->next;
|
||||
}
|
||||
|
||||
// Didn't get a nextmap before reaching the end?
|
||||
if (gettingresult != 2)
|
||||
{
|
||||
nextmap = NEXTMAP_CEREMONY; // ceremonymap
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cm = prevmap;
|
||||
|
||||
do
|
||||
{
|
||||
if (++cm >= nummapheaders)
|
||||
cm = 0;
|
||||
|
||||
if (!mapheaderinfo[cm]
|
||||
|| mapheaderinfo[cm]->lumpnum == LUMPERROR
|
||||
|| !(mapheaderinfo[cm]->typeoflevel & tolflag)
|
||||
|| (mapheaderinfo[cm]->menuflags & LF2_HIDEINMENU))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (M_MapLocked(cm + 1) == true)
|
||||
{
|
||||
// We haven't earned this one.
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
} while (cm != prevmap);
|
||||
|
||||
nextmap = cm;
|
||||
}
|
||||
|
||||
if (K_CanChangeRules(true))
|
||||
{
|
||||
switch (cv_advancemap.value)
|
||||
{
|
||||
case 0: // Stay on same map.
|
||||
nextmap = prevmap;
|
||||
break;
|
||||
case 3: // Voting screen.
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (players[i].spectator)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (i != MAXPLAYERS)
|
||||
{
|
||||
nextmap = NEXTMAP_VOTING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case 2: // Go to random map.
|
||||
nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, false, 0, false, NULL);
|
||||
break;
|
||||
default:
|
||||
if (nextmap >= NEXTMAP_SPECIAL) // Loop back around
|
||||
{
|
||||
nextmap = G_GetFirstMapOfGametype(gametype);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We are committed to this map now.
|
||||
if (nextmap == NEXTMAP_INVALID || (nextmap < NEXTMAP_SPECIAL && (nextmap >= nummapheaders || !mapheaderinfo[nextmap] || mapheaderinfo[nextmap]->lumpnum == LUMPERROR)))
|
||||
|
|
@ -5359,7 +5368,11 @@ void G_AfterIntermission(void)
|
|||
//
|
||||
void G_NextLevel(void)
|
||||
{
|
||||
if (nextmap >= NEXTMAP_SPECIAL)
|
||||
if (nextmap == NEXTMAP_RANDOM)
|
||||
{
|
||||
nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, false, 0, false, NULL);
|
||||
}
|
||||
else if (nextmap >= NEXTMAP_SPECIAL)
|
||||
{
|
||||
G_EndGame();
|
||||
return;
|
||||
|
|
@ -6553,16 +6566,9 @@ mapnum_t G_FindMapByNameOrCode(const char *mapname, char **realmapnamep)
|
|||
return gamemap;
|
||||
else if (mapname[0] == '+') // next map
|
||||
{
|
||||
//TODO: FIXME
|
||||
// THIS CURRENTLY ALWAYS RETURNS ZERO. FIGURE OUT WHY.
|
||||
G_GetNextMap();
|
||||
|
||||
if (nextmap < NEXTMAP_INVALID)
|
||||
return nextmap;
|
||||
else
|
||||
return 0;
|
||||
newmapnum = G_CheckNextMap(true);
|
||||
return newmapnum >= NEXTMAP_SPECIAL ? 0 : newmapnum+1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Now detect map number in base 10, which no one asked for. */
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ UINT8 G_GetGametypeColor(INT16 gt);
|
|||
void G_BeginLevelExit(void);
|
||||
void G_FinishExitLevel(void);
|
||||
void G_NextLevel(void);
|
||||
mapnum_t G_CheckNextMap(boolean noadvancemap);
|
||||
void G_GetNextMap(void);
|
||||
void G_Continue(void);
|
||||
void G_UseContinue(void);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ typedef enum
|
|||
NEXTMAP_CREDITS = UINT16_MAX-3,
|
||||
NEXTMAP_CEREMONY = UINT16_MAX-4,
|
||||
NEXTMAP_VOTING = UINT16_MAX-5,
|
||||
NEXTMAP_INVALID = UINT16_MAX-6, // Always last
|
||||
NEXTMAP_RANDOM = UINT16_MAX-6,
|
||||
NEXTMAP_INVALID = UINT16_MAX-7, // Always last
|
||||
NEXTMAP_SPECIAL = NEXTMAP_INVALID
|
||||
} ATTRPACK mapnum_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -759,7 +759,25 @@ skiptallydrawer:
|
|||
else if (modeattacking != ATTACKING_NONE)
|
||||
string = va("Exiting in %d", tickdown);
|
||||
else
|
||||
string = va("%s starts in %d", cv_advancemap.string, tickdown);
|
||||
{
|
||||
mapnum_t next = G_CheckNextMap(false);
|
||||
switch (next)
|
||||
{
|
||||
case NEXTMAP_VOTING:
|
||||
string = "Vote";
|
||||
break;
|
||||
case NEXTMAP_CEREMONY:
|
||||
string = "Ceremony";
|
||||
break;
|
||||
case NEXTMAP_RANDOM:
|
||||
string = "Random";
|
||||
break;
|
||||
default:
|
||||
string = next == prevmap ? "Same" : "Next";
|
||||
break;
|
||||
}
|
||||
string = va("%s starts in %d", string, tickdown);
|
||||
}
|
||||
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 188, hilicol,
|
||||
string);
|
||||
|
|
|
|||
Loading…
Reference in a new issue