Second row of cups is invisible if none of them are unlocked

- Controlled by M_CupSecondRowLocked
    - Looks for any Cup with associated unlockable that's on the second row
    - Cached on load for both relevant menus - Cupgrid and Challenges
- Custom cups will be stretched out onto more pages
    - Side incentive of unlocking more material: Less annoying interactions with custom material
- Pages with nothing unlocked are completely skipped over

Also moves a bunch of minor things which previously used magic numbers to the CUPMENU_COLUMNS/CUPMENU_ROWS defines, for sanity
This commit is contained in:
toaster 2023-11-20 21:09:33 +00:00
parent b8c18ce39f
commit 382119b8fb
8 changed files with 122 additions and 19 deletions

View file

@ -53,6 +53,9 @@ extern UINT32 maptol;
extern INT32 cursaveslot;
extern UINT8 gamecomplete;
#define CUPMENU_COLUMNS 7
#define CUPMENU_ROWS 2
// Extra abilities/settings for skins (combinable stuff)
typedef enum
{

View file

@ -752,8 +752,6 @@ void M_SetupPlayMenu(INT32 choice);
void M_SetupGametypeMenu(INT32 choice);
void M_SetupRaceMenu(INT32 choice);
#define CUPMENU_COLUMNS 7
#define CUPMENU_ROWS 2
#define CUPMENU_CURSORID (cupgrid.x + (cupgrid.y * CUPMENU_COLUMNS) + (cupgrid.pageno * (CUPMENU_COLUMNS * CUPMENU_ROWS)))
extern struct cupgrid_s {
@ -764,6 +762,7 @@ extern struct cupgrid_s {
size_t cappages;
tic_t previewanim;
boolean grandprix; // Setup grand prix server after picking
boolean cache_secondrowlocked;
} cupgrid;
typedef struct levelsearch_s {
@ -1274,6 +1273,8 @@ extern struct challengesmenu_s {
UINT16 unlockcount[CMC_MAX];
UINT8 fade;
boolean cache_secondrowlocked;
} challengesmenu;
menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu);

View file

@ -2712,7 +2712,9 @@ void M_DrawCupSelect(void)
for (i = 0; i < CUPMENU_COLUMNS; i++)
{
for (j = 0; j < CUPMENU_ROWS; j++)
x = 14 + (i*42);
for (j = 0; j < (cupgrid.cache_secondrowlocked ? 1 : CUPMENU_ROWS); j++)
{
size_t id = (i + (j * CUPMENU_COLUMNS)) + (cupgrid.pageno * (CUPMENU_COLUMNS * CUPMENU_ROWS));
@ -2721,8 +2723,9 @@ void M_DrawCupSelect(void)
templevelsearch.cup = cupgrid.builtgrid[id];
x = 14 + (i*42);
y = 20 + (j*44) - (30*menutransition.tics);
if (cupgrid.cache_secondrowlocked == true)
y += 28;
const boolean isGP = (cupgrid.grandprix && (cv_dummygpdifficulty.value >= 0 && cv_dummygpdifficulty.value < KARTGP_MAX));
if (isGP)
@ -2745,11 +2748,23 @@ void M_DrawCupSelect(void)
V_DrawScaledPatch(x + 32, y + 32, 0, W_CachePatchName("CUPBKUP1", PU_CACHE));
}
// used to be 8 + (j*100) - (30*menutransition.tics)
// but one-row mode means y has to be changed
// this is the difference between y and that
if (j == 0)
{
y -= 12; // (8) - (20)
}
else
{
y += 44; //(8 + 100) - (20 + 44)
}
if (windata && windata->best_placement != 0)
{
M_DrawCupWinData(
x,
8 + (j*100) - (30*menutransition.tics),
y,
templevelsearch.cup,
cv_dummygpdifficulty.value,
(cupgrid.previewanim & 1),
@ -2761,6 +2776,8 @@ void M_DrawCupSelect(void)
x = 14 + (cupgrid.x*42);
y = 20 + (cupgrid.y*44) - (30*menutransition.tics);
if (cupgrid.cache_secondrowlocked == true)
y += 28;
V_DrawScaledPatch(x - 4, y - 1, 0, W_CachePatchName("CUPCURS", PU_CACHE));
@ -5686,40 +5703,56 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
M_DrawCupPreview(146, &templevelsearch);
maxid = id = (temp->id % 14);
maxid = id = (temp->id % (CUPMENU_COLUMNS * CUPMENU_ROWS));
offset = (temp->id - id) * 2;
while (temp && maxid < 14)
while (temp && maxid < (CUPMENU_COLUMNS * CUPMENU_ROWS))
{
maxid++;
temp = temp->next;
}
V_DrawFadeFill(4, (BASEVIDHEIGHT-(4+16)), 28 + offset, 16, 0, 31, challengetransparentstrength);
y = (BASEVIDHEIGHT-(4+16));
if (challengesmenu.cache_secondrowlocked == true)
y += 8;
V_DrawFadeFill(
4,
y,
28 + offset,
(challengesmenu.cache_secondrowlocked ? 8 : 16),
0,
31,
challengetransparentstrength
);
for (i = 0; i < offset; i += 4)
{
V_DrawFill(4+1 + i, (BASEVIDHEIGHT-(4+16))+3, 2, 2, 15);
V_DrawFill(4+1 + i, (BASEVIDHEIGHT-(4+16))+8+3, 2, 2, 15);
V_DrawFill(4+1 + i, y+3, 2, 2, 15);
if (challengesmenu.cache_secondrowlocked == false)
V_DrawFill(4+1 + i, y+8+3, 2, 2, 15);
}
for (i = 0; i < 7; i++)
for (i = 0; i < CUPMENU_COLUMNS; i++)
{
if (templevelsearch.cup && id == i)
{
V_DrawFill(offset + 4 + (i*4), (BASEVIDHEIGHT-(4+16)), 4, 8, 0);
V_DrawFill(offset + 4 + (i*4), y, 4, 8, 0);
}
else if (i < maxid)
{
V_DrawFill(offset + 4+1 + (i*4), (BASEVIDHEIGHT-(4+16))+3, 2, 2, 0);
V_DrawFill(offset + 4+1 + (i*4), y+3, 2, 2, 0);
}
if (templevelsearch.cup && (templevelsearch.cup->id % 14) == i+7)
if (templevelsearch.cup && id == i+CUPMENU_COLUMNS)
{
V_DrawFill(offset + 4 + (i*4), (BASEVIDHEIGHT-(4+16))+8, 4, 8, 0);
V_DrawFill(offset + 4 + (i*4), y+8, 4, 8, 0);
}
else if (i+7 < maxid)
else if (challengesmenu.cache_secondrowlocked == true)
;
else if (i+CUPMENU_COLUMNS < maxid)
{
V_DrawFill(offset + 4+1 + (i*4), (BASEVIDHEIGHT-(4+16))+8+3, 2, 2, 0);
V_DrawFill(offset + 4+1 + (i*4), y+8+3, 2, 2, 0);
}
}

View file

@ -3190,6 +3190,33 @@ boolean M_CupLocked(cupheader_t *cup)
return false;
}
boolean M_CupSecondRowLocked(void)
{
// The following was pre-optimised for cached behaviour.
// It would need a refactor if the cache system were to
// change, maybe to iterate over unlockable_t instead.
cupheader_t *cup;
for (cup = kartcupheaders; cup; cup = cup->next)
{
// Only important for the second row.
if ((cup->id % (CUPMENU_COLUMNS * CUPMENU_ROWS)) < CUPMENU_COLUMNS)
continue;
// Only important for ones that can be locked.
if (cup->cache_cuplock == MAXUNLOCKABLES)
continue;
// If it's NOT unlocked, can't be used as proof of unlock.
if (!M_CheckNetUnlockByID(cup->cache_cuplock))
continue;
// Okay, at least one cup on the second row is unlocked!
return false;
}
return true;
}
boolean M_MapLocked(UINT16 mapnum)
{
// Don't lock maps in dedicated servers.

View file

@ -437,6 +437,7 @@ UINT16 M_CompletionEmblems(void);
boolean M_CheckNetUnlockByID(UINT16 unlockid);
boolean M_SecretUnlocked(INT32 type, boolean local);
boolean M_CupLocked(cupheader_t *cup);
boolean M_CupSecondRowLocked(void);
boolean M_MapLocked(UINT16 mapnum);
INT32 M_CountMedals(boolean all, boolean extraonly);

View file

@ -58,6 +58,8 @@ static void M_UpdateChallengeGridVisuals(void)
{
UINT16 i;
challengesmenu.cache_secondrowlocked = M_CupSecondRowLocked();
challengesmenu.unlockcount[CMC_UNLOCKED] = 0;
challengesmenu.unlockcount[CMC_TOTAL] = 0;

View file

@ -214,7 +214,9 @@ void M_CupSelectHandler(INT32 choice)
M_SetMenuDelay(pid);
}
if (menucmd[pid].dpad_ud > 0)
if (cupgrid.cache_secondrowlocked == true)
; // No up/down for you!
else if (menucmd[pid].dpad_ud > 0)
{
cupgrid.y++;
if (cupgrid.y >= CUPMENU_ROWS)

View file

@ -299,10 +299,21 @@ boolean M_LevelListFromGametype(INT16 gt)
if (levellist.levelsearch.cupmode)
{
const boolean secondrowlocked = M_CupSecondRowLocked();
if (cupgrid.cache_secondrowlocked != secondrowlocked)
{
cupgrid.cache_secondrowlocked = secondrowlocked;
if (cupgrid.y || cupgrid.pageno)
{
// Prevent softlock, reset to start
cupgrid.x = cupgrid.y = cupgrid.pageno = 0;
}
}
levelsearch_t templevelsearch = levellist.levelsearch; // full copy
size_t currentid = 0, highestunlockedid = 0;
const size_t pagelen = sizeof(cupheader_t*) * (CUPMENU_COLUMNS * CUPMENU_ROWS);
boolean foundany = false, currentvalid = false;
boolean foundany = false, foundanythispage = false, currentvalid = false;
G_GetBackupCupData(
cupgrid.grandprix == true
@ -374,6 +385,7 @@ boolean M_LevelListFromGametype(INT16 gt)
templevelsearch.checklocked = true;
if (M_GetFirstLevelInList(&temp, &templevelsearch) != NEXTMAP_INVALID)
{
foundanythispage = true;
highestunlockedid = currentid;
if (Playing()
@ -386,6 +398,28 @@ boolean M_LevelListFromGametype(INT16 gt)
}
currentid++;
// If the second row is locked and you've reached it, skip onward.
if (secondrowlocked == true)
{
size_t deltaid = currentid % (CUPMENU_COLUMNS * CUPMENU_ROWS);
if (deltaid >= CUPMENU_COLUMNS)
{
currentid += (CUPMENU_COLUMNS * CUPMENU_ROWS) - deltaid;
}
}
// If you've gone a full page without anything valid, compress it down!
if ((currentid % (CUPMENU_COLUMNS * CUPMENU_ROWS)) == 0)
{
if (foundanythispage == false)
{
currentid -= (CUPMENU_COLUMNS * CUPMENU_ROWS);
memset(&cupgrid.builtgrid[currentid], 0, pagelen);
}
foundanythispage = false;
}
templevelsearch.cup = templevelsearch.cup->next;
}