From 67e63442da2d629d7e9c13250fc15d3f4c6e20fa Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 4 Oct 2019 00:18:34 -0400 Subject: [PATCH] Start on Cup/Level selects --- src/d_main.c | 2 +- src/hu_stuff.c | 19 +++- src/hu_stuff.h | 1 + src/k_menu.h | 61 +++++++++-- src/k_menudef.c | 89 ++++++++++++---- src/k_menudraw.c | 250 ++++++++++++++++++++++++++++++++++++------- src/k_menufunc.c | 270 ++++++++++++++++++++++++++++++++++++++++++++--- src/v_video.c | 188 +++++++++++++++++++++++++++++++++ src/v_video.h | 8 ++ 9 files changed, 800 insertions(+), 88 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 1758c4a16..1beff2292 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -318,7 +318,7 @@ static void D_Display(void) F_WipeStartScreen(); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); F_WipeEndScreen(); - F_RunWipe(wipedefs[wipedefindex], gamestate != GS_MENU, "FADEMAP0", false); + F_RunWipe(wipedefs[wipedefindex], gamestate != GS_MENU, "FADEMAP0", false, false); } if (gamestate != GS_LEVEL && rendermode != render_none) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 3be1d6473..455d90394 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -72,6 +72,8 @@ patch_t *nightsnum[10]; // 0-9 patch_t *kart_font[KART_FONTSIZE]; // SRB2kart patch_t *gamemode_font[AZ_FONTSIZE]; patch_t *file_font[AZ_FONTSIZE]; +patch_t *title_font_high[LT_FONTSIZE]; +patch_t *title_font_low[LT_FONTSIZE]; // Level title and credits fonts patch_t *lt_font[LT_FONTSIZE]; @@ -261,15 +263,26 @@ void HU_LoadGraphics(void) // j = LT_FONTSTART; - for (i = 0; i < LT_FONTSIZE; i++) + for (i = 0; i < LT_FONTSIZE; i++, j++) { sprintf(buffer, "LTFNT%.3d", j); - j++; - if (W_CheckNumForName(buffer) == LUMPERROR) lt_font[i] = NULL; else lt_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); + + // Level select title fonts + sprintf(buffer, "THIFN%.3d", j); + if (W_CheckNumForName(buffer) == LUMPERROR) + title_font_high[i] = NULL; + else + title_font_high[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); + + sprintf(buffer, "TLWFN%.3d", j); + if (W_CheckNumForName(buffer) == LUMPERROR) + title_font_low[i] = NULL; + else + title_font_low[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); } // cache the credits font for entire game execution (why not?) diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 9c9206f83..0df283b29 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -86,6 +86,7 @@ extern boolean chat_on; extern patch_t *hu_font[HU_FONTSIZE], *tny_font[HU_FONTSIZE]; extern patch_t *kart_font[KART_FONTSIZE]; // SRB2kart extern patch_t *gamemode_font[AZ_FONTSIZE], *file_font[AZ_FONTSIZE]; +extern patch_t *title_font_high[LT_FONTSIZE], *title_font_low[LT_FONTSIZE]; extern patch_t *tallnum[10]; extern patch_t *pingnum[10]; extern patch_t *pinggfx[5]; diff --git a/src/k_menu.h b/src/k_menu.h index d57618a4a..20b9e778d 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -108,8 +108,8 @@ typedef struct menu_s INT16 lastOn; // last item user was on in menu menuitem_t *menuitems; // menu items INT16 x, y; // x, y of menu - INT16 transitionInTics; // tics for transitions in - INT16 transitionOutTics; // tics for transitions out + INT16 transitionID; // only transition if IDs match + INT16 transitionTics; // tics for transitions out void (*drawroutine)(void); // draw routine void (*tickroutine)(void); // ticker routine boolean (*quitroutine)(void); // called before quit a menu return true if we can @@ -139,18 +139,27 @@ typedef enum quitkart } main_e; -extern menuitem_t PLAY_MainMenu[]; -extern menu_t PLAY_MainDef; - extern menuitem_t PLAY_CharSelect[]; extern menu_t PLAY_CharSelectDef; +extern menuitem_t PLAY_MainMenu[]; +extern menu_t PLAY_MainDef; + extern menuitem_t PLAY_Gamemodes[]; extern menu_t PLAY_GamemodesDef; extern menuitem_t PLAY_RaceGamemodesMenu[]; extern menu_t PLAY_RaceGamemodesDef; +extern menuitem_t PLAY_CupSelect[]; +extern menu_t PLAY_CupSelectDef; + +extern menuitem_t PLAY_LevelSelect[]; +extern menu_t PLAY_LevelSelectDef; + +extern menuitem_t PLAY_BattleGamemodesMenu[]; +extern menu_t PLAY_BattleGamemodesDef; + extern menuitem_t PAUSE_PlaybackMenu[]; extern menu_t PAUSE_PlaybackMenuDef; @@ -171,11 +180,9 @@ typedef enum playback_quit } playback_e; - // K_MENUFUNC.C extern menu_t *currentMenu; - extern char dummystaffname[22]; extern INT16 itemOn; // menu item skull is on, Hack by Tails 09-18-2002 @@ -248,13 +255,13 @@ typedef struct setup_player_s extern setup_player_t setup_player[MAXSPLITSCREENPLAYERS]; extern UINT8 setup_numplayers; -extern UINT16 setup_animcounter; +extern tic_t setup_animcounter; + +#define CSROTATETICS 6 // The selection spawns 3 explosions in 4 directions, and there's 4 players -- 3 * 4 * 4 = 48 #define CSEXPLOSIONS 48 -#define CSROTATETICS 6 - extern struct setup_explosions_s { UINT8 x, y; UINT8 tics; @@ -275,6 +282,35 @@ void M_CharacterSelectHandler(INT32 choice); void M_CharacterSelectTick(void); boolean M_CharacterSelectQuit(void); +#define CUPS_COLUMNS 7 +#define CUPS_ROWS 2 +#define CUPS_MAPSPERCUP 5 +#define CUPS_MAX (NUMMAPS / CUPS_MAPSPERCUP) +#define CUPS_PAGES (CUPS_MAX / (CUPS_COLUMNS * CUPS_ROWS)) + +extern struct levellist_cupgrid_s { + UINT8 numcups; + SINT8 x, y; + SINT8 pageno; + tic_t previewanim; +} levellist_cupgrid; + +extern struct levellist_scroll_s { + SINT8 cupid; + SINT8 cursor; + UINT16 y; + UINT16 dest; +} levellist_scroll; + +boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); +void M_LevelSelectInit(INT32 choice); + +void M_CupSelectHandler(INT32 choice); +void M_CupSelectTick(void); + +void M_LevelSelectHandler(INT32 choice); +void M_LevelSelectTick(void); + void M_EndModeAttackRun(void); void M_SetPlaybackMenuPointer(void); void M_PlaybackRewind(INT32 choice); @@ -298,6 +334,9 @@ void M_DrawImageDef(void); void M_DrawCharacterSelect(void); +void M_DrawCupSelect(void); +void M_DrawLevelSelect(void); + void M_DrawPlaybackMenu(void); // These defines make it a little easier to make menus @@ -322,7 +361,7 @@ void M_DrawPlaybackMenu(void); 0,\ source,\ 0, 0,\ - 10, 10,\ + 1, 10,\ M_DrawKartGamemodeMenu,\ NULL,\ NULL\ diff --git a/src/k_menudef.c b/src/k_menudef.c index 5dc155fd0..3030340ba 100644 --- a/src/k_menudef.c +++ b/src/k_menudef.c @@ -19,16 +19,16 @@ menuitem_t MainMenu[] = { {IT_STRING | IT_CALL, "Play", "Cut to the chase and start the race!", - NULL, M_CharacterSelectInit, 48, 0}, + NULL, M_CharacterSelectInit, 0, 0}, {IT_STRING, "Extra", "Check out some bonus features.", - NULL, NULL, 80, 0}, + NULL, NULL, 0, 0}, {IT_STRING, "Option", "Configure your controls, settings, and preferences.", - NULL, NULL, 112, 0}, + NULL, NULL, 0, 0}, {IT_STRING | IT_CALL, "Quit", "Exit SRB2Kart.", - NULL, M_QuitSRB2, 160, 0}, + NULL, M_QuitSRB2, 0, 0}, }; menu_t MainDef = KARTGAMEMODEMENU(MainMenu, NULL); @@ -57,45 +57,96 @@ menu_t PLAY_CharSelectDef = { menuitem_t PLAY_MainMenu[] = { {IT_STRING | IT_SUBMENU, "Local Play", "Play only on this computer.", - NULL, &PLAY_GamemodesDef, 64, 0}, + NULL, &PLAY_GamemodesDef, 0, 0}, {IT_STRING, "Online", "Connect to other computers.", - NULL, NULL, 96, 0}, + NULL, NULL, 0, 0}, - {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 160, 0}, + {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 0, 0}, }; menu_t PLAY_MainDef = KARTGAMEMODEMENU(PLAY_MainMenu, &PLAY_CharSelectDef); menuitem_t PLAY_GamemodesMenu[] = { - {IT_STRING | IT_SUBMENU, "Race", "A competition for the best time!", - NULL, &PLAY_RaceGamemodesDef, 64, 0}, + {IT_STRING | IT_SUBMENU, "Race", "A contest to see who's the fastest of them all!", + NULL, &PLAY_RaceGamemodesDef, 0, 0}, - {IT_STRING, "Battle", "Clash against other players in a survival match!", - NULL, NULL, 96, 0}, + {IT_STRING | IT_SUBMENU, "Battle", "Sharpen your item usage in these special Battle zones!", + NULL, &PLAY_BattleGamemodesDef, 0, 0}, - {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 160, 0}, + {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 0, 0}, }; menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef); +// RACE + menuitem_t PLAY_RaceGamemodesMenu[] = { - {IT_STRING, "Grand Prix", "Compete for the best rank over five races!", - NULL, NULL, 48, 0}, + {IT_STRING | IT_CALL, "Grand Prix", "Compete for the best rank over five races!", + NULL, M_LevelSelectInit, 0, 0}, - {IT_STRING, "Match Race", "Pick your own settings in a specialized single race.", - NULL, NULL, 80, 0}, + {IT_STRING | IT_CALL, "Match Race", "Play by your own rules in a specialized, single race!", + NULL, M_LevelSelectInit, 1, 0}, - {IT_STRING, "Time Attack", "Race against ghosts for the best time, no fluff.", - NULL, NULL, 112, 0}, + {IT_STRING | IT_CALL, "Time Attack", "Record your best time on any track!", + NULL, M_LevelSelectInit, 2, 0}, - {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 160, 0}, + {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 0, 0}, }; menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_GamemodesDef); +menuitem_t PLAY_CupSelect[] = +{ + {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_CupSelectHandler, 0, 0}, +}; + +menu_t PLAY_CupSelectDef = { + sizeof(PLAY_CupSelect) / sizeof(menuitem_t), + &PLAY_RaceGamemodesDef, + 0, + PLAY_CupSelect, + 0, 0, + 2, 10, + M_DrawCupSelect, + M_CupSelectTick, + NULL +}; + +menuitem_t PLAY_LevelSelect[] = +{ + {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_LevelSelectHandler, 0, 0}, +}; + +menu_t PLAY_LevelSelectDef = { + sizeof(PLAY_LevelSelect) / sizeof(menuitem_t), + &PLAY_CupSelectDef, + 0, + PLAY_LevelSelect, + 0, 0, + 2, 10, + M_DrawLevelSelect, + M_LevelSelectTick, + NULL +}; + +// BATTLE + +menuitem_t PLAY_BattleGamemodesMenu[] = +{ + {IT_STRING | IT_CALL, "Survival", "It's last hedgehog standing in this free-for-all!", + NULL, M_LevelSelectInit, 3, 0}, + + {IT_STRING | IT_CALL, "Time Attack", "Bust up all of the capsules in record time!", + NULL, M_LevelSelectInit, 4, 0}, + + {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 0, 0}, +}; + +menu_t PLAY_BattleGamemodesDef = KARTGAMEMODEMENU(PLAY_BattleGamemodesMenu, &PLAY_GamemodesDef); + // ------------------- // In-game/pause menus // ------------------- diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 8c433c5d5..b9f271615 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -135,7 +135,7 @@ void M_Drawer(void) if (menuwipe) { F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_menu_final], false, "FADEMAP0", true); + F_RunWipe(wipedefs[wipe_menu_final], false, "FADEMAP0", true, false); menuwipe = false; } @@ -380,6 +380,7 @@ void M_DrawGenericMenu(void) void M_DrawKartGamemodeMenu(void) { INT16 i, x = 170; + UINT8 n = currentMenu->numitems-1; M_DrawMenuTooltips(); M_DrawMenuPreviews(); @@ -389,10 +390,17 @@ void M_DrawKartGamemodeMenu(void) for (i = 0; i < currentMenu->numitems; i++) { + INT16 y; + + if (i == n) + y = 160; + else + y = 80 - (16 * (n-1)) + (32 * i); + switch (currentMenu->menuitems[i].status & IT_DISPLAY) { case IT_STRING: - V_DrawRightAlignedGamemodeString(x, currentMenu->menuitems[i].mvar1, 0, currentMenu->menuitems[i].text, + V_DrawRightAlignedGamemodeString(x, y, 0, currentMenu->menuitems[i].text, (i == itemOn) ? SKINCOLOR_PLAGUE : SKINCOLOR_PIGEON); break; } @@ -724,9 +732,8 @@ static void M_DrawCharSelectExplosions(void) #define IDLELEN 8 #define SELECTLEN (8 + IDLELEN + 7 + IDLELEN) -static void M_DrawCharSelectCursors(void) +static void M_DrawCharSelectCursor(UINT8 num) { - UINT8 i; static const char *idleframes[IDLELEN] = { "CHHOV1", "CHHOV1", "CHHOV1", "CHHOV2", "CHHOV1", "CHHOV3", "CHHOV1", "CHHOV2" }; @@ -743,40 +750,37 @@ static void M_DrawCharSelectCursors(void) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - for (i = 0; i < setup_numplayers; i++) + setup_player_t *p = &setup_player[num]; + char letter = 'A' + num; + UINT8 *colormap; + INT16 x, y; + INT16 quadx, quady; + + quadx = 4 * (p->gridx / 3); + quady = 4 * (p->gridy / 3); + + x = 82 + (p->gridx*16) + quadx - 13, + y = 22 + (p->gridy*16) + quady - 12, + + colormap = R_GetTranslationColormap(TC_DEFAULT, (p->color != SKINCOLOR_NONE ? p->color : SKINCOLOR_GREY), GTC_MENUCACHE); + + if (p->mdepth >= CSSTEP_READY) { - setup_player_t *p = &setup_player[i]; - char letter = 'A' + i; - UINT8 *colormap; - INT16 x, y; - INT16 quadx, quady; - - quadx = 4 * (p->gridx / 3); - quady = 4 * (p->gridy / 3); - - x = 82 + (p->gridx*16) + quadx - 13, - y = 22 + (p->gridy*16) + quady - 12, - - colormap = R_GetTranslationColormap(TC_DEFAULT, (p->color != SKINCOLOR_NONE ? p->color : SKINCOLOR_GREY), GTC_MENUCACHE); - - if (p->mdepth >= CSSTEP_READY) - { - V_DrawMappedPatch(x, y, 0, W_CachePatchName("CHCNFRM0", PU_CACHE), colormap); - } - else if (p->mdepth > CSSTEP_CHARS) - { - V_DrawMappedPatch(x, y, 0, W_CachePatchName(selectframesa[setup_animcounter % SELECTLEN], PU_CACHE), colormap); - if (selectframesb[(setup_animcounter-1) % SELECTLEN] != NULL) - V_DrawMappedPatch(x, y, V_TRANSLUCENT, W_CachePatchName(selectframesb[(setup_animcounter-1) % SELECTLEN], PU_CACHE), colormap); - } - else - { - V_DrawMappedPatch(x, y, 0, W_CachePatchName(idleframes[setup_animcounter % IDLELEN], PU_CACHE), colormap); - } - - if (p->mdepth < CSSTEP_READY) - V_DrawMappedPatch(x, y, 0, W_CachePatchName(va("CSELH%c", letter), PU_CACHE), colormap); + V_DrawMappedPatch(x, y, 0, W_CachePatchName("CHCNFRM0", PU_CACHE), colormap); } + else if (p->mdepth > CSSTEP_CHARS) + { + V_DrawMappedPatch(x, y, 0, W_CachePatchName(selectframesa[setup_animcounter % SELECTLEN], PU_CACHE), colormap); + if (selectframesb[(setup_animcounter-1) % SELECTLEN] != NULL) + V_DrawMappedPatch(x, y, V_TRANSLUCENT, W_CachePatchName(selectframesb[(setup_animcounter-1) % SELECTLEN], PU_CACHE), colormap); + } + else + { + V_DrawMappedPatch(x, y, 0, W_CachePatchName(idleframes[setup_animcounter % IDLELEN], PU_CACHE), colormap); + } + + if (p->mdepth < CSSTEP_READY) + V_DrawMappedPatch(x, y, 0, W_CachePatchName(va("CSELH%c", letter), PU_CACHE), colormap); } #undef IDLE @@ -786,6 +790,7 @@ static void M_DrawCharSelectCursors(void) void M_DrawCharacterSelect(void) { UINT8 i, j, k; + UINT8 priority = setup_animcounter % setup_numplayers; INT16 quadx, quady; SINT8 skin; @@ -851,12 +856,177 @@ void M_DrawCharacterSelect(void) // Explosions when you've made your final selection M_DrawCharSelectExplosions(); - // Draw the cursors - M_DrawCharSelectCursors(); - - // Draw a preview for each player for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + // Draw a preview for each player M_DrawCharSelectPreview(i); + + if (i >= setup_numplayers) + continue; + + // Draw the cursors + if (i != priority) + M_DrawCharSelectCursor(i); + } + + // Draw the priority player over the other ones + M_DrawCharSelectCursor(priority); +} + +// LEVEL SELECT + +static void M_DrawCupPreview(INT16 y, UINT8 cupnum) +{ + UINT8 i; + INT16 x = -(levellist_cupgrid.previewanim % 82); + + V_DrawFill(0, y, BASEVIDWIDTH, 54, 31); + + for (i = 0; i < 5; i++) + { + lumpnum_t lumpnum; + patch_t *PictureOfLevel; + UINT8 lvloff = (i + (levellist_cupgrid.previewanim / 82)) % 5; + + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(1 + (cupnum * 5) + lvloff))); + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + V_DrawSmallScaledPatch(x + 1 + (i*82), y+2, 0, PictureOfLevel); + } +} + +void M_DrawCupSelect(void) +{ + UINT8 i, j; + + for (i = 0; i < CUPS_COLUMNS; i++) + { + for (j = 0; j < CUPS_ROWS; j++) + { + V_DrawFill(14 + (i*42), 22 + (j*40) - (15*menutransition.tics), 39, 38, 31); + } + } + + V_DrawScaledPatch(14 + (levellist_cupgrid.x*42) - 4, + 22 + (levellist_cupgrid.y*40) - 4 - (12*menutransition.tics), + 0, W_CachePatchName("CUPCURS", PU_CACHE) + ); + + V_DrawScaledPatch(0, 120 - (12*menutransition.tics), 0, W_CachePatchName("MENUHINT", PU_CACHE)); + M_DrawCupPreview(146 + (12*menutransition.tics), levellist_cupgrid.x + (levellist_cupgrid.y * CUPS_COLUMNS)); + + V_DrawCenteredLSTitleLowString(BASEVIDWIDTH/2, 126 - (12*menutransition.tics), 0, "SNEAKER CUP"); +} + +static void M_DrawHighLowLevelTitle(INT16 x, INT16 y, INT16 map) +{ + static char word1[21]; + static char word2[21]; + UINT8 word1len = 0; + UINT8 word2len = 0; + INT16 x2 = x; + UINT8 i; + + if (!mapheaderinfo[map]->lvlttl[0]) + return; + + if (mapheaderinfo[map]->zonttl[0]) + { + strcpy(word1, mapheaderinfo[map]->lvlttl); + strcpy(word2, mapheaderinfo[map]->zonttl); + } + else + { + boolean donewithone = false; + + for (i = 0; i < 21; i++) + { + if (!mapheaderinfo[map]->lvlttl[i]) + { + if (donewithone) + word2[word2len] = '\0'; + else + word1[word1len] = '\0'; + break; + } + + if (mapheaderinfo[map]->lvlttl[i] == ' ') + { + if (!donewithone) + { + word1[word1len] = '\0'; + donewithone = true; + continue; + } + } + + if (donewithone) + { + word2[word2len] = mapheaderinfo[map]->lvlttl[i]; + word2len++; + } + else + { + word1[word1len] = mapheaderinfo[map]->lvlttl[i]; + word1len++; + } + } + } + + for (i = 0; i < 2; i++) + { + INT32 c; + if (i >= word1len) + break; + c = toupper(word1[i]) - LT_FONTSTART; + x2 += SHORT(title_font_high[c]->width) - 4; + } + + if (word1len) + V_DrawLSTitleHighString(x, y, 0, word1); + if (word2len) + V_DrawLSTitleLowString(x2, y+28, 0, word2); +} + +void M_DrawLevelSelect(void) +{ + UINT8 i; + INT16 t = (32*menutransition.tics); + INT16 y = 80 - (12 * levellist_scroll.y); + + for (i = 0; i < 5; i++) + { + lumpnum_t lumpnum; + patch_t *PictureOfLevel; + UINT8 *colormap = NULL; + INT16 map = 1 + (levellist_scroll.cupid * 5) + i; + + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(map))); + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + if (i == levellist_scroll.cursor && ((skullAnimCounter / 4) & 1)) + V_DrawScaledPatch(3+t, y, 0, W_CachePatchName("LVLSEL2", PU_CACHE)); + else + V_DrawScaledPatch(3+t, y, 0, W_CachePatchName("LVLSEL", PU_CACHE)); + + if (i != levellist_scroll.cursor) + colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GREY, GTC_MENUCACHE); + + V_DrawSmallMappedPatch(9+t, y+6, 0, PictureOfLevel, colormap); + + M_DrawHighLowLevelTitle(98+t, y+8, map-1); + + y += 72; + } + + V_DrawScaledPatch(0, 0, 0, W_CachePatchName("MENUHINT", PU_CACHE)); + V_DrawCenteredLSTitleLowString(BASEVIDWIDTH/2, 6, 0, "SNEAKER CUP"); } // diff --git a/src/k_menufunc.c b/src/k_menufunc.c index e13d87b5c..74b563dc0 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -171,8 +171,8 @@ static consvar_t cv_dummystaff = {"dummystaff", "0", CV_HIDDEN|CV_CALL, dummysta // ========================================================================== // (there's only a couple anyway) -// Prototypes #if 0 +// Prototypes static INT32 M_FindFirstMap(INT32 gtype); static INT32 M_GetFirstLevelInList(void); #endif @@ -180,6 +180,7 @@ static INT32 M_GetFirstLevelInList(void); // Nextmap. Used for Time Attack. static void Nextmap_OnChange(void) { +#if 0 char *leveltitle; // Update the string in the consvar. @@ -187,7 +188,7 @@ static void Nextmap_OnChange(void) leveltitle = G_BuildMapTitle(cv_nextmap.value); cv_nextmap.string = cv_nextmap.zstring = leveltitle ? leveltitle : Z_StrDup(G_BuildMapName(cv_nextmap.value)); -#if 0 + if (currentMenu == &SP_TimeAttackDef) { // see also p_setup.c's P_LoadRecordGhosts @@ -272,6 +273,7 @@ static void Nextmap_OnChange(void) #endif } + static void Dummymenuplayer_OnChange(void) { if (cv_dummymenuplayer.value < 1) @@ -346,6 +348,7 @@ static void Newgametype_OnChange(void) #endif } + void Screenshot_option_Onchange(void) { #if 0 @@ -1174,10 +1177,11 @@ void M_SetupNextMenu(menu_t *menudef, boolean notransition) if (!notransition) { - if (currentMenu->transitionOutTics) + if (currentMenu->transitionID == menudef->transitionID + && currentMenu->transitionTics) { menutransition.tics = 0; - menutransition.dest = currentMenu->transitionOutTics; + menutransition.dest = currentMenu->transitionTics; menutransition.in = false; menutransition.newmenu = menudef; return; // Don't change menu yet, the transition will call this again @@ -1188,7 +1192,7 @@ void M_SetupNextMenu(menu_t *menudef, boolean notransition) F_WipeStartScreen(); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_menu_toblack], false, "FADEMAP0", false); + F_RunWipe(wipedefs[wipe_menu_toblack], false, "FADEMAP0", false, false); } } @@ -1243,6 +1247,8 @@ void M_GoBack(INT32 choice) } else M_ClearMenus(true); + + S_StartSound(NULL, sfx_s3k5b); } // @@ -1263,14 +1269,12 @@ void M_Ticker(void) // If dest is zero, we're mid-transition and want to end it if (menutransition.tics == menutransition.dest && menutransition.newmenu != NULL) { - M_SetupNextMenu(menutransition.newmenu, true); - - if (menutransition.newmenu->transitionInTics) + if (currentMenu->transitionID == menutransition.newmenu->transitionID + && menutransition.newmenu->transitionTics) { - menutransition.tics = currentMenu->transitionOutTics; + menutransition.tics = menutransition.newmenu->transitionTics; menutransition.dest = 0; menutransition.in = true; - menutransition.newmenu = NULL; } else if (gamestate == GS_MENU) { @@ -1280,8 +1284,11 @@ void M_Ticker(void) F_WipeStartScreen(); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_menu_toblack], false, "FADEMAP0", false); + F_RunWipe(wipedefs[wipe_menu_toblack], false, "FADEMAP0", false, false); } + + M_SetupNextMenu(menutransition.newmenu, true); + menutransition.newmenu = NULL; } } else @@ -1629,7 +1636,7 @@ setup_player_t setup_player[MAXSPLITSCREENPLAYERS]; struct setup_explosions_s setup_explosions[48]; UINT8 setup_numplayers = 0; -UINT16 setup_animcounter = 0; +tic_t setup_animcounter = 0; consvar_t *setup_playercvars[MAXSPLITSCREENPLAYERS][SPLITCV_MAX]; @@ -1781,7 +1788,7 @@ static void M_HandleCharacterGrid(INT32 choice, setup_player_t *p, UINT8 num) else p->mdepth = CSSTEP_ALTS; - S_StartSound(NULL, sfx_s3k5b); + S_StartSound(NULL, sfx_s3k63); } break; case KEY_ESCAPE: @@ -1824,7 +1831,7 @@ static void M_HandleCharRotate(INT32 choice, setup_player_t *p) break; case KEY_ENTER: p->mdepth = CSSTEP_COLORS; - S_StartSound(NULL, sfx_s3k5b); + S_StartSound(NULL, sfx_s3k63); break; case KEY_ESCAPE: p->mdepth = CSSTEP_CHARS; @@ -1996,6 +2003,241 @@ boolean M_CharacterSelectQuit(void) return true; } +// LEVEL SELECT + +#if 0 +// Call before showing any level-select menus +static void M_PrepareLevelSelect(void) +{ + if (levellistmode != LLM_CREATESERVER) + CV_SetValue(&cv_nextmap, M_GetFirstLevelInList()); + else + Newgametype_OnChange(); // Make sure to start on an appropriate map if wads have been added +} + +// +// M_CanShowLevelInList +// +// Determines whether to show a given map in the various level-select lists. +// Set gt = -1 to ignore gametype. +// +boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) +{ + // Does the map exist? + if (!mapheaderinfo[mapnum]) + return false; + + // Does the map have a name? + if (!mapheaderinfo[mapnum]->lvlttl[0]) + return false; + + if (M_MapLocked(mapnum+1)) + return false; // not unlocked + + // Should the map be hidden? + if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU && mapnum+1 != gamemap) + return false; + + if (gt == GT_MATCH && (mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH)) + return true; + + if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) + { + if (levellist_cup != -1) + { + if (mapnum < (1 + ((levellist_cup-1) * 5)) + || mapnum > (6 + ((levellist_cup-1) * 5)) + return false; + } + + return true; + } + + // Hmm? Couldn't decide? + return false; +} + +static INT32 M_CountLevelsToShowInList(void) +{ + INT32 mapnum, count = 0; + + for (mapnum = 0; mapnum < NUMMAPS; mapnum++) + if (M_CanShowLevelInList(mapnum, -1)) + count++; + + return count; +} + +static INT32 M_GetFirstLevelInList(void) +{ + INT32 mapnum; + + for (mapnum = 0; mapnum < NUMMAPS; mapnum++) + if (M_CanShowLevelInList(mapnum, -1)) + return mapnum + 1; + + return 1; +} +#endif + +struct levellist_cupgrid_s levellist_cupgrid; +struct levellist_scroll_s levellist_scroll; + +static void M_LevelSelectScrollDest(void) +{ + levellist_scroll.dest = (6*levellist_scroll.cursor); + + if (levellist_scroll.dest < 3) + levellist_scroll.dest = 3; + + if (levellist_scroll.dest > (6*4)-3) + levellist_scroll.dest = (6*4)-3; +} + +void M_LevelSelectInit(INT32 choice) +{ + UINT8 selecttype = currentMenu->menuitems[itemOn].mvar1; + + (void)choice; + + switch (selecttype) + { + case 2: + CV_StealthSetValue(&cv_newgametype, GT_RACE); + break; + default: + break; + } + + PLAY_CupSelectDef.prevMenu = currentMenu; + + if (cv_newgametype.value != GT_RACE) + { + PLAY_LevelSelectDef.prevMenu = currentMenu; + M_SetupNextMenu(&PLAY_LevelSelectDef, false); + } + else + { + PLAY_LevelSelectDef.prevMenu = &PLAY_CupSelectDef; + M_SetupNextMenu(&PLAY_CupSelectDef, false); + } +} + +void M_CupSelectHandler(INT32 choice) +{ + UINT8 selcup = levellist_cupgrid.x + (levellist_cupgrid.y * CUPS_COLUMNS); + + switch (choice) + { + case KEY_RIGHTARROW: + levellist_cupgrid.x++; + if (levellist_cupgrid.x >= CUPS_COLUMNS) + { + levellist_cupgrid.x = 0; + //levellist_cupgrid.pageno++; + } + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_LEFTARROW: + levellist_cupgrid.x--; + if (levellist_cupgrid.x < 0) + { + levellist_cupgrid.x = CUPS_COLUMNS-1; + //levellist_cupgrid.pageno--; + } + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_UPARROW: + levellist_cupgrid.y++; + if (levellist_cupgrid.y >= CUPS_ROWS) + { + levellist_cupgrid.y = 0; + //levellist_cupgrid.pageno++; + } + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_DOWNARROW: + levellist_cupgrid.y--; + if (levellist_cupgrid.y < 0) + { + levellist_cupgrid.y = CUPS_ROWS-1; + //levellist_cupgrid.pageno--; + } + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_ENTER: + if (levellist_scroll.cupid != selcup) // Keep cursor position if you select the same cup again + { + levellist_scroll.cursor = 0; + levellist_scroll.cupid = selcup; + } + + M_LevelSelectScrollDest(); + levellist_scroll.y = levellist_scroll.dest; + + M_SetupNextMenu(&PLAY_LevelSelectDef, false); + S_StartSound(NULL, sfx_s3k63); + break; + case KEY_ESCAPE: + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu, false); + else + M_ClearMenus(true); + break; + default: + break; + } +} + +void M_CupSelectTick(void) +{ + levellist_cupgrid.previewanim++; +} + +void M_LevelSelectHandler(INT32 choice) +{ + if (levellist_scroll.y != levellist_scroll.dest) + return; + + switch (choice) + { + case KEY_UPARROW: + levellist_scroll.cursor--; + if (levellist_scroll.cursor < 0) + levellist_scroll.cursor = 4; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_DOWNARROW: + levellist_scroll.cursor++; + if (levellist_scroll.cursor > 4) + levellist_scroll.cursor = 0; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_ENTER: + //M_SetupNextMenu(&PLAY_TimeAttack, false); + S_StartSound(NULL, sfx_s3k63); + break; + case KEY_ESCAPE: + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu, false); + else + M_ClearMenus(true); + break; + default: + break; + } + + M_LevelSelectScrollDest(); +} + +void M_LevelSelectTick(void) +{ + if (levellist_scroll.y > levellist_scroll.dest) + levellist_scroll.y--; + else if (levellist_scroll.y < levellist_scroll.dest) + levellist_scroll.y++; +} + // ===================== // PAUSE / IN-GAME MENUS // ===================== diff --git a/src/v_video.c b/src/v_video.c index f5c912296..42f503e32 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1935,6 +1935,150 @@ void V_DrawRightAlignedFileString(INT32 x, INT32 y, INT32 option, const char *st x -= V_FileStringWidth(string, option); V_DrawFileString(x, y, option, string); } + +void V_DrawLSTitleHighString(INT32 x, INT32 y, INT32 option, const char *string) +{ + INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; + INT32 spacewidth = 16; + const char *ch = string; + + option &= ~V_FLIP; + + if (option & V_NOSCALESTART) + { + dupx = vid.dupx; + dupy = vid.dupy; + scrwidth = vid.width; + } + else + { + dupx = dupy = 1; + scrwidth = vid.width/vid.dupx; + left = (scrwidth - BASEVIDWIDTH)/2; + } + + for (;;ch++) + { + if (!*ch) + break; + + if (*ch == '\n') + { + cx = x; + cy += 14*dupy; + + continue; + } + + c = toupper(*ch) - LT_FONTSTART; + + // character does not exist or is a space + if (c < 0 || c >= LT_FONTSIZE || !title_font_high[c]) + { + cx += spacewidth * dupx; + continue; + } + + w = (SHORT(title_font_high[c]->width) - 4) * dupx; + + if (cx > scrwidth) + break; + + if (cx+left + w < 0) //left boundary check + { + cx += w; + continue; + } + + V_DrawFixedPatch(cx<= LT_FONTSIZE || !title_font_low[c]) + { + cx += spacewidth * dupx; + continue; + } + + w = (SHORT(title_font_low[c]->width) - 4) * dupx; + + if (cx > scrwidth) + break; + + if (cx+left + w < 0) //left boundary check + { + cx += w; + continue; + } + + V_DrawFixedPatch(cx<= LT_FONTSIZE || !title_font_high[c]) + w += spacewidth; + else + w += SHORT(title_font_high[c]->width) - 4; + } + + return w; +} + +INT32 V_LSTitleLowStringWidth(const char *string, INT32 option) +{ + INT32 c, w = 0; + INT32 spacewidth = 16; + size_t i; + + (void)option; + + for (i = 0; i < strlen(string); i++) + { + c = string[i]; + c = toupper(c) - LT_FONTSTART; + + if (c < 0 || c >= LT_FONTSIZE || !title_font_low[c]) + w += spacewidth; + else + w += SHORT(title_font_low[c]->width) - 4; + } + + return w; +} + boolean *heatshifter = NULL; INT32 lastheight = 0; INT32 heatindex[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; diff --git a/src/v_video.h b/src/v_video.h index fe8e2b019..52dbc90b5 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -187,6 +187,12 @@ void V_DrawRightAlignedGamemodeString(INT32 x, INT32 y, INT32 option, const char void V_DrawFileString(INT32 x, INT32 y, INT32 option, const char *string); void V_DrawCenteredFileString(INT32 x, INT32 y, INT32 option, const char *string); void V_DrawRightAlignedFileString(INT32 x, INT32 y, INT32 option, const char *string); +void V_DrawLSTitleHighString(INT32 x, INT32 y, INT32 option, const char *string); +void V_DrawCenteredLSTitleHighString(INT32 x, INT32 y, INT32 option, const char *string); +void V_DrawRightAlignedLSTitleHighString(INT32 x, INT32 y, INT32 option, const char *string); +void V_DrawLSTitleLowString(INT32 x, INT32 y, INT32 option, const char *string); +void V_DrawCenteredLSTitleLowString(INT32 x, INT32 y, INT32 option, const char *string); +void V_DrawRightAlignedLSTitleLowString(INT32 x, INT32 y, INT32 option, const char *string); // draw a string using the hu_font, 0.5x scale void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string); @@ -224,6 +230,8 @@ INT32 V_ThinStringWidth(const char *string, INT32 option); // SRB2Kart INT32 V_GamemodeStringWidth(const char *string, INT32 option); INT32 V_FileStringWidth(const char *string, INT32 option); +INT32 V_LSTitleHighStringWidth(const char *string, INT32 option); +INT32 V_LSTitleLowStringWidth(const char *string, INT32 option); void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param);