Special Mode Time Attack swag to unwind

- Play O_SSTAR3
- Special darkened background
- Imagery to replace the minimap, since Special Mode maps generally don't have them as a rule
    - Sealed Stars:
        - Star Within The Seal, from the standard Evaluation
    - Versus:
        - The DeviantArt SignatuRes
- Fix messed-up transitions between Time Attack main menu and Replay, Guests, and Ghosts submenus
    - Special Mode specifically:
        - Forced unexpected wipes
    - All modes:
        - Don't slide away the minimap (or replacement imagery) when going between these menus
        - Fix music not being correctly attached
- Correctly center minimaps in Time Attack view
This commit is contained in:
toaster 2023-12-05 21:23:58 +00:00
parent 9d24a4cb6d
commit 60e6445fd2
5 changed files with 175 additions and 40 deletions

View file

@ -259,6 +259,8 @@ typedef enum
ta_start, ta_start,
} ta_e; } ta_e;
// If you add another Time Attach submenu, remember to catch level-select.c's music/bgroutine update
extern menuitem_t PLAY_TAReplay[]; extern menuitem_t PLAY_TAReplay[];
extern menu_t PLAY_TAReplayDef; extern menu_t PLAY_TAReplayDef;
@ -1184,6 +1186,7 @@ boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, UINT8 spr2, UINT8 ro
void M_DrawCup(cupheader_t *cup, fixed_t x, fixed_t y, INT32 lockedTic, boolean isTrophy, UINT8 placement); void M_DrawCup(cupheader_t *cup, fixed_t x, fixed_t y, INT32 lockedTic, boolean isTrophy, UINT8 placement);
void M_DrawCupSelect(void); void M_DrawCupSelect(void);
void M_DrawLevelSelect(void); void M_DrawLevelSelect(void);
void M_DrawSealedBack(void);
void M_DrawTimeAttack(void); void M_DrawTimeAttack(void);
void M_DrawRaceDifficulty(void); void M_DrawRaceDifficulty(void);

View file

@ -3080,6 +3080,47 @@ void M_DrawLevelSelect(void)
M_DrawCupTitle(tay, &levellist.levelsearch); M_DrawCupTitle(tay, &levellist.levelsearch);
} }
static boolean M_LevelSelectToTimeAttackTransitionHelper(void)
{
if (menutransition.tics == 0)
return false;
return \
(
menutransition.startmenu == &PLAY_LevelSelectDef
&& menutransition.endmenu == &PLAY_TimeAttackDef
) || (
menutransition.endmenu == &PLAY_LevelSelectDef
&& menutransition.startmenu == &PLAY_TimeAttackDef
);
}
void M_DrawSealedBack(void)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
if (currentMenu != &PLAY_LevelSelectDef
&& currentMenu != &PLAY_CupSelectDef)
return;
INT32 translucencylevel = 7;
if (M_LevelSelectToTimeAttackTransitionHelper())
{
translucencylevel += menutransition.tics/3;
if (translucencylevel >= 10)
return;
}
V_DrawFixedPatch(
0, 0,
FRACUNIT,
translucencylevel << V_ALPHASHIFT,
W_CachePatchName("MENUI008", PU_CACHE),
R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_BLACK, GTC_CACHE)
);
}
void M_DrawTimeAttack(void) void M_DrawTimeAttack(void)
{ {
UINT16 map = levellist.choosemap; UINT16 map = levellist.choosemap;
@ -3088,27 +3129,95 @@ void M_DrawTimeAttack(void)
INT16 rightedge = 149+t+155; INT16 rightedge = 149+t+155;
INT16 opty = 140; INT16 opty = 140;
INT32 w; INT32 w;
patch_t *minimap = NULL;
UINT8 i; UINT8 i;
M_DrawLevelSelectBlock(0, 2, map, true, false);
//V_DrawFill(24-t, 82, 100, 100, 36); // size test
V_DrawScaledPatch(149+t, 70, 0, W_CachePatchName("BESTTIME", PU_CACHE)); V_DrawScaledPatch(149+t, 70, 0, W_CachePatchName("BESTTIME", PU_CACHE));
if (currentMenu == &PLAY_TimeAttackDef && mapheaderinfo[map]) if (!mapheaderinfo[map])
{ {
tic_t timerec = 0; V_DrawRightAlignedString(rightedge-12, opty, 0, "No map!?");
tic_t laprec = 0; return;
}
{
patch_t *minimap = NULL;
INT32 minimapx = 76, minimapy = 130;
if (M_LevelSelectToTimeAttackTransitionHelper())
minimapx -= t;
if (levellist.newgametype == GT_SPECIAL)
{
// Star Within The Seal
#define SEAL_PULSELEN ((6*TICRATE)/5) // The rate of O_SSTAR3
INT32 crossfade = (timeattackmenu.ticker % (2*SEAL_PULSELEN)) - SEAL_PULSELEN;
if (crossfade < 0)
crossfade = -crossfade;
crossfade = (crossfade * 10)/SEAL_PULSELEN;
#undef SEAL_PULSELEN
if (crossfade != 10)
{
minimap = W_CachePatchName(
"K_FINB05",
PU_CACHE
);
V_DrawScaledPatch(
minimapx, minimapy,
0, minimap
);
}
if (crossfade != 0)
{
minimap = W_CachePatchName(
"K_FINB04",
PU_CACHE
);
V_DrawScaledPatch(
minimapx, minimapy,
(10-crossfade)<<V_ALPHASHIFT,
minimap
);
}
}
else if (levellist.newgametype == GT_VERSUS)
{
const INT32 teaserh = 56;
minimapy -= 1; // tiny adjustment
V_DrawScaledPatch(
minimapx, minimapy - teaserh,
V_TRANSLUCENT, W_CachePatchName("K_TEASR2", PU_CACHE)
);
V_DrawScaledPatch(
minimapx, minimapy + teaserh,
V_TRANSLUCENT, W_CachePatchName("K_TEASR4", PU_CACHE)
);
V_DrawScaledPatch(
minimapx, minimapy,
0, W_CachePatchName("K_TEASR3", PU_CACHE)
);
}
else if ((minimap = mapheaderinfo[map]->minimapPic))
{
V_DrawScaledPatch(
minimapx - (SHORT(minimap->width)/2),
minimapy - (SHORT(minimap->height)/2),
0, minimap
);
}
}
if (currentMenu == &PLAY_TimeAttackDef)
{
tic_t timerec = mapheaderinfo[map]->records.time;
tic_t laprec = mapheaderinfo[map]->records.lap;
UINT32 timeheight = 82; UINT32 timeheight = 82;
if ((minimap = mapheaderinfo[map]->minimapPic))
V_DrawScaledPatch(24-t, 82, 0, minimap);
timerec = mapheaderinfo[map]->records.time;
laprec = mapheaderinfo[map]->records.lap;
if ((gametypes[levellist.newgametype]->rules & GTR_CIRCUIT) if ((gametypes[levellist.newgametype]->rules & GTR_CIRCUIT)
&& (mapheaderinfo[map]->numlaps != 1)) && (mapheaderinfo[map]->numlaps != 1))
{ {
@ -3142,6 +3251,9 @@ void M_DrawTimeAttack(void)
else else
opty = 80; opty = 80;
// Done after to overlay material
M_DrawLevelSelectBlock(0, 2, map, true, false);
for (i = 0; i < currentMenu->numitems; i++) for (i = 0; i < currentMenu->numitems; i++)
{ {
UINT32 f = (i == itemOn) ? highlightflags : 0; UINT32 f = (i == itemOn) ? highlightflags : 0;

View file

@ -121,7 +121,7 @@ menu_t PLAY_TAReplayDef = {
2, 5, 2, 5,
M_DrawTimeAttack, M_DrawTimeAttack,
NULL, NULL,
NULL, M_TimeAttackTick,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -167,7 +167,7 @@ menu_t PLAY_TAReplayGuestDef = {
2, 5, 2, 5,
M_DrawTimeAttack, M_DrawTimeAttack,
NULL, NULL,
NULL, M_TimeAttackTick,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -208,7 +208,7 @@ menu_t PLAY_TAGhostsDef = {
2, 5, 2, 5,
M_DrawTimeAttack, M_DrawTimeAttack,
NULL, NULL,
NULL, M_TimeAttackTick,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -219,6 +219,8 @@ void M_PrepareTimeAttack(INT32 choice)
{ {
(void) choice; (void) choice;
timeattackmenu.ticker = 0;
// Gametype guess // Gametype guess
if (levellist.guessgt != MAXGAMETYPES) if (levellist.guessgt != MAXGAMETYPES)
{ {

View file

@ -276,11 +276,13 @@ void M_CupSelectHandler(INT32 choice)
} }
else if (count == 1 && levellist.levelsearch.timeattack == true) else if (count == 1 && levellist.levelsearch.timeattack == true)
{ {
PLAY_TimeAttackDef.transitionID = currentMenu->transitionID+1; currentMenu->transitionID = PLAY_TimeAttackDef.transitionID+1;
M_LevelSelected(0); M_LevelSelected(0);
} }
else else
{ {
currentMenu->transitionID = PLAY_LevelSelectDef.transitionID;
// Keep cursor position if you select the same cup again, reset if it's a different cup // Keep cursor position if you select the same cup again, reset if it's a different cup
if (oldcup != newcup || levellist.cursor >= count) if (oldcup != newcup || levellist.cursor >= count)
{ {

View file

@ -18,17 +18,6 @@ menuitem_t PLAY_LevelSelect[] =
{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_LevelSelectHandler}, 0, 0}, {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, {.routine = M_LevelSelectHandler}, 0, 0},
}; };
static void M_DrawLevelSelectBack(void)
{
if (!levellist.levelsearch.tutorial)
{
M_DrawMenuBackground();
return;
}
M_DrawExtrasBack();
}
menu_t PLAY_LevelSelectDef = { menu_t PLAY_LevelSelectDef = {
sizeof(PLAY_LevelSelect) / sizeof(menuitem_t), sizeof(PLAY_LevelSelect) / sizeof(menuitem_t),
&PLAY_CupSelectDef, &PLAY_CupSelectDef,
@ -40,7 +29,7 @@ menu_t PLAY_LevelSelectDef = {
NULL, NULL,
2, 5, 2, 5,
M_DrawLevelSelect, M_DrawLevelSelect,
M_DrawLevelSelectBack, NULL,
M_LevelSelectTick, M_LevelSelectTick,
NULL, NULL,
NULL, NULL,
@ -293,16 +282,43 @@ boolean M_LevelListFromGametype(INT16 gt)
CV_SetValue(&cv_dummyspbattack, 0); CV_SetValue(&cv_dummyspbattack, 0);
} }
PLAY_CupSelectDef.music = \
PLAY_LevelSelectDef.music = \
PLAY_TimeAttackDef.music = \
currentMenu->music;
if (gamestate == GS_MENU) if (gamestate == GS_MENU)
{ {
PLAY_CupSelectDef.menuitems[0].patch = \ const char *music;
PLAY_LevelSelectDef.menuitems[0].patch = \ void (*bgroutine)(void);
currentMenu->menuitems[itemOn].patch;
if (gt == GT_SPECIAL)
{
music = "SSTAR3";
bgroutine = M_DrawSealedBack;
}
else
{
music = currentMenu->music;
bgroutine = currentMenu->bgroutine;
// Not for the time attack ones
PLAY_CupSelectDef.menuitems[0].patch = \
PLAY_LevelSelectDef.menuitems[0].patch = \
currentMenu->menuitems[itemOn].patch;
}
menu_t *remap_menus[] = {
&PLAY_CupSelectDef,
&PLAY_LevelSelectDef,
&PLAY_TimeAttackDef,
&PLAY_TAReplayDef,
&PLAY_TAReplayGuestDef,
&PLAY_TAGhostsDef,
NULL
};
size_t i;
for (i = 0; remap_menus[i]; i++)
{
remap_menus[i]->music = music;
remap_menus[i]->bgroutine = bgroutine;
}
} }
} }
@ -311,6 +327,8 @@ boolean M_LevelListFromGametype(INT16 gt)
if (levellist.levelsearch.cupmode) if (levellist.levelsearch.cupmode)
{ {
PLAY_CupSelectDef.transitionID = PLAY_LevelSelectDef.transitionID;
const boolean secondrowlocked = M_CupSecondRowLocked(); const boolean secondrowlocked = M_CupSecondRowLocked();
if (cupgrid.cache_secondrowlocked != secondrowlocked) if (cupgrid.cache_secondrowlocked != secondrowlocked)
{ {
@ -786,8 +804,6 @@ void M_LevelSelectHandler(INT32 choice)
if (M_MenuConfirmPressed(pid) /*|| M_MenuButtonPressed(pid, MBT_START)*/) if (M_MenuConfirmPressed(pid) /*|| M_MenuButtonPressed(pid, MBT_START)*/)
{ {
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
PLAY_TimeAttackDef.transitionID = currentMenu->transitionID;
M_LevelSelected(levellist.cursor); M_LevelSelected(levellist.cursor);
} }
else if (M_MenuBackPressed(pid)) else if (M_MenuBackPressed(pid))