From 4a68f191c8d4e1197b30dbcf2060d10e97987c8f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 26 Jan 2017 19:14:52 +0000 Subject: [PATCH 01/29] Mostly-complete structural work, very much incomplete rendering work. --- src/dehacked.c | 6 + src/doomstat.h | 2 + src/m_menu.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++-- src/m_menu.h | 17 +++ src/p_setup.c | 2 + 5 files changed, 320 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index c71c55ac1..e5d08fdb0 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1211,6 +1211,12 @@ static void readlevelheader(MYFILE *f, INT32 num) { deh_strlcpy(mapheaderinfo[num-1]->lvlttl, word2, sizeof(mapheaderinfo[num-1]->lvlttl), va("Level header %d: levelname", num)); + strlcpy(mapheaderinfo[num-1]->selectheading, word2, sizeof(mapheaderinfo[num-1]->selectheading)); // not deh_ so only complains once + } + else if (fastcmp(word, "SELECTHEADING")) + { + deh_strlcpy(mapheaderinfo[num-1]->selectheading, word2, + sizeof(mapheaderinfo[num-1]->selectheading), va("Level header %d: selectheading", num)); } else if (fastcmp(word, "SCRIPTNAME")) { diff --git a/src/doomstat.h b/src/doomstat.h index f1b7d2169..a3b95c95b 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -241,6 +241,8 @@ typedef struct UINT8 levelflags; ///< LF_flags: merged eight booleans into one UINT8 for space, see below UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus + char selectheading[22+5]; ///< Level select heading. Allows for controllable grouping. + // Freed animals stuff. UINT8 numFlickies; ///< Internal. For freed flicky support. mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. diff --git a/src/m_menu.c b/src/m_menu.c index f682cd1b5..36e5c9e1a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -53,6 +53,7 @@ #include "byteptr.h" #include "st_stuff.h" #include "i_sound.h" +#include "fastcmp.h" // Condition Sets #include "m_cond.h" @@ -346,6 +347,7 @@ static void M_HandleLevelStats(INT32 choice); static void M_HandleConnectIP(INT32 choice); #endif static void M_HandleSetupMultiPlayer(INT32 choice); +static void M_HandleNewLevelSelect(INT32 choice); #ifdef HWRENDER static void M_HandleFogColor(INT32 choice); #endif @@ -642,9 +644,10 @@ static menuitem_t SR_MainMenu[] = static menuitem_t SR_LevelSelectMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleNewLevelSelect, '\0'}, // dummy menuitem for the control func +/* {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120},*/ }; static menuitem_t SR_UnlockChecklistMenu[] = @@ -3438,6 +3441,281 @@ static void M_PatchSkinNameTable(void) return; } +// Handle Level Select +static levelselect_t levelselect = {0, NULL}; +static UINT8 levelselectselect[2]; + +#define lsrow levelselectselect[0] +#define lscol levelselectselect[1] + +// +// M_CanShowLevelInNewList +// +// Determines whether to show a given map in the various level-select lists. +// Set gt = -1 to ignore gametype. +// +boolean M_CanShowLevelInNewList(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; + + switch (levellistmode) + { + case LLM_CREATESERVER: + // Should the map be hidden? + if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) + return false; + + /*if (M_MapLocked(mapnum+1)) + return false; // not unlocked*/ + + if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP)) + return true; + + if (gt == GT_COMPETITION && (mapheaderinfo[mapnum]->typeoflevel & TOL_COMPETITION)) + return true; + + if (gt == GT_CTF && (mapheaderinfo[mapnum]->typeoflevel & TOL_CTF)) + return true; + + if ((gt == GT_MATCH || gt == GT_TEAMMATCH) && (mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH)) + return true; + + if ((gt == GT_TAG || gt == GT_HIDEANDSEEK) && (mapheaderinfo[mapnum]->typeoflevel & TOL_TAG)) + return true; + + if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) + return true; + + return false; + + case LLM_LEVELSELECT: + if (mapheaderinfo[mapnum]->levelselect != maplistoption) + return false; + + /*if (M_MapLocked(mapnum+1)) + return false; // not unlocked*/ + + return true; + case LLM_RECORDATTACK: + if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) + return false; + + /*if (M_MapLocked(mapnum+1)) + return false; // not unlocked*/ + + if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + return true; + + /*if (!mapvisited[mapnum]) + return false;*/ + + return true; + case LLM_NIGHTSATTACK: + if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK)) + return false; + + /*if (M_MapLocked(mapnum+1)) + return false; // not unlocked*/ + + if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + return true; + + /*if (!mapvisited[mapnum]) + return false;*/ + + return true; + } + + // Hmm? Couldn't decide? + return false; +} + +/*static INT32 M_CountLevelsToShowInNewList(INT32 gt) +{ + INT32 mapnum, count = 0; + + for (mapnum = 0; mapnum < NUMMAPS; mapnum++) + if (M_CanShowLevelInList(mapnum, gt)) + count++; + + return count; +}*/ + +static INT32 M_CountRowsToShowInNewList(INT32 gt) +{ + INT32 mapnum, prevmapnum, col = 0, rows = 0; + + for (mapnum = 0; mapnum < NUMMAPS; mapnum++) + { + if (M_CanShowLevelInNewList(mapnum, gt)) + { + if (rows == 0) + rows++; + else + { + if (col == 2 + || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[prevmapnum]->selectheading))) + { + col = 0; + rows++; + } + else + col++; + } + prevmapnum = mapnum; + } + } + + return rows; +} + +static boolean M_PrepareNewLevelSelect(INT32 gt) +{ + INT32 numrows = M_CountRowsToShowInNewList(gt); + INT32 mapnum, col = 0, row = 0; + + if (!numrows) + return false; + + if (levelselect.rows) + Z_Free(levelselect.rows); + levelselect.rows = NULL; + + levelselect.numrows = numrows; + levelselect.rows = Z_Realloc(levelselect.rows, numrows*sizeof(levelselectrow_t), PU_STATIC, NULL); + if (!levelselect.rows) + I_Error("Insufficient memory to prepare level select platter"); + + for (mapnum = 0; mapnum < NUMMAPS; mapnum++) + { + if (M_CanShowLevelInNewList(mapnum, gt)) + { + const INT32 actnum = mapheaderinfo[mapnum]->actnum; + + // preparing next position to drop mapnum into + if (levelselect.rows[0].maplist[0]) + { + if (col == 2 // no more space on the row? + || (levelselect.rows[row].maplist[0] && !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row].maplist[0]-1]->selectheading)))) // a new heading is starting? + { + col = 0; + row++; + } + else + col++; + } + + levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter + levelselect.rows[row].mapavailable[col] = true; /*(!M_MapLocked(mapnum+1) + && (mapvisited[mapnum] || mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED));*/ + + // individual map name + if (!levelselect.rows[row].mapavailable[col]) + sprintf(levelselect.rows[row].mapnames[col], "???"); + else if (actnum) + sprintf(levelselect.rows[row].mapnames[col], "ACT %d", actnum); + else + { + sprintf(levelselect.rows[row].mapnames[col], "%s", mapheaderinfo[mapnum]->lvlttl); + } + + // creating header text + if (!col && (!row || (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row].maplist[0]-1]->selectheading)))) + { + if (!levelselect.rows[row].mapavailable[col]) + sprintf(levelselect.rows[row].header, "???"); + else + { + sprintf(levelselect.rows[row].header, "%s", mapheaderinfo[mapnum]->selectheading); + if (!(mapheaderinfo[mapnum]->levelflags & LF_NOZONE) && (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[mapnum]->lvlttl))) + { + sprintf(levelselect.rows[row].header + strlen(levelselect.rows[row].header), " ZONE"); + } + } + } + } + } + + lsrow = lscol = 0; + + return true; +} + +static void M_HandleNewLevelSelect(INT32 choice) +{ + boolean exitmenu = false; // exit to previous menu + INT32 selectval; + + switch (choice) + { + case KEY_DOWNARROW: + lsrow++; + if (lsrow == levelselect.numrows) + lsrow = 0; + S_StartSound(NULL,sfx_s3kb7); + break; + + case KEY_UPARROW: + lsrow--; + if (lsrow == UINT8_MAX) + lsrow = levelselect.numrows-1; + S_StartSound(NULL,sfx_s3kb7); + break; + + case KEY_LEFTARROW: + if (lscol > 0) + { + lscol--; + S_StartSound(NULL,sfx_s3kb7); + } + break; + + case KEY_RIGHTARROW: + if (lscol < 2) + { + lscol++; + S_StartSound(NULL,sfx_s3kb7); + } + break; + + case KEY_ENTER: + selectval = levelselect.rows[lsrow].maplist[lscol]; + if (selectval && levelselect.rows[lsrow].mapavailable[lscol]) + { + CV_SetValue(&cv_nextmap, selectval); + M_LevelSelectWarp(0); + S_StartSound(NULL,sfx_s3kb7); + } + else + S_StartSound(NULL,sfx_s3kb2); + break; + + case KEY_ESCAPE: + exitmenu = true; + break; + + default: + break; + } + + if (exitmenu) + { + if (currentMenu->prevMenu) + M_SetupNextMenu (currentMenu->prevMenu); + else + M_ClearMenus(true); + } +} + +#undef lsrow +#undef lscol + // Call before showing any level-select menus static void M_PrepareLevelSelect(void) { @@ -4089,7 +4367,16 @@ static void M_DrawLevelSelectMenu(void) { M_DrawGenericMenu(); - if (cv_nextmap.value) + V_DrawCenteredString(160, 40, V_YELLOWMAP, levelselect.rows[levelselectselect[0]].header); + V_DrawCenteredString(160, 48, 0, levelselect.rows[levelselectselect[0]].mapnames[levelselectselect[1]]); + + /*if (levelselect.rows[levelselectselect[0]].maplist[levelselectselect[1]]) + V_DrawCenteredString(160, 48, V_YELLOWMAP, + va("%s\n", G_BuildMapTitle(levelselect.rows[levelselectselect[0]].maplist[levelselectselect[1]]))); + else + V_DrawCenteredString(160, 48, V_YELLOWMAP, + va("none\n"));*/ + /*if (cv_nextmap.value) { lumpnum_t lumpnum; patch_t *PictureOfLevel; @@ -4103,7 +4390,7 @@ static void M_DrawLevelSelectMenu(void) PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); V_DrawSmallScaledPatch(200, 110, 0, PictureOfLevel); - } + }*/ } static void M_DrawSkyRoom(void) @@ -4288,13 +4575,12 @@ static void M_CustomLevelSelect(INT32 choice) SR_LevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; maplistoption = (UINT8)(unlockables[ul].variable); - if (M_CountLevelsToShowInList() == 0) + if (!M_PrepareNewLevelSelect(-1)) { M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); return; } - M_PrepareLevelSelect(); M_SetupNextMenu(&SR_LevelSelectDef); } @@ -7474,4 +7760,4 @@ static void M_HandleFogColor(INT32 choice) M_ClearMenus(true); } } -#endif +#endif \ No newline at end of file diff --git a/src/m_menu.h b/src/m_menu.h index 9cac52ed5..76eabd729 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -68,6 +68,7 @@ void M_QuitResponse(INT32 ch); // Determines whether to show a level in the list boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); +boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt); // flags for items in the menu @@ -182,6 +183,22 @@ typedef struct UINT8 next; } description_t; +// experimental level select -- remember to use M_HandleSetupMultiPlayer +typedef struct +{ + char header[22+5]; // mapheader_t lvltttl max length + " ZONE" + INT32 maplist[3]; + char mapnames[3][22]; + boolean mapavailable[3]; +} levelselectrow_t; + +typedef struct +{ + UINT8 numrows; + levelselectrow_t *rows; +} levelselect_t; +// experimental level select end + // mode descriptions for video mode menu typedef struct { diff --git a/src/p_setup.c b/src/p_setup.c index 6df103255..5004ebdfa 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -199,6 +199,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) const INT16 num = (INT16)(i-1); DEH_WriteUndoline("LEVELNAME", mapheaderinfo[num]->lvlttl, UNDO_NONE); mapheaderinfo[num]->lvlttl[0] = '\0'; + DEH_WriteUndoline("SELECTHEADING", mapheaderinfo[num]->selectheading, UNDO_NONE); + mapheaderinfo[num]->selectheading[0] = '\0'; DEH_WriteUndoline("SUBTITLE", mapheaderinfo[num]->subttl, UNDO_NONE); mapheaderinfo[num]->subttl[0] = '\0'; DEH_WriteUndoline("ACT", va("%d", mapheaderinfo[num]->actnum), UNDO_NONE); From 521ab3ca1a96d0077ce0ef30d077205e7fc8b048 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 27 Jan 2017 00:02:47 +0000 Subject: [PATCH 02/29] The visuals now work nicely. Future work involves porting this with minimal code repetition to the other sections of the game that use the old level select system. --- src/doomstat.h | 2 +- src/m_menu.c | 196 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 146 insertions(+), 52 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index a3b95c95b..391f57a14 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -241,7 +241,7 @@ typedef struct UINT8 levelflags; ///< LF_flags: merged eight booleans into one UINT8 for space, see below UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus - char selectheading[22+5]; ///< Level select heading. Allows for controllable grouping. + char selectheading[22]; ///< Level select heading. Allows for controllable grouping. // Freed animals stuff. UINT8 numFlickies; ///< Internal. For freed flicky support. diff --git a/src/m_menu.c b/src/m_menu.c index 36e5c9e1a..072c29e84 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3443,10 +3443,49 @@ static void M_PatchSkinNameTable(void) // Handle Level Select static levelselect_t levelselect = {0, NULL}; -static UINT8 levelselectselect[2]; +static UINT8 levelselectselect[3]; +static patch_t *levselp[4]; +static INT32 lsoffs[2]; #define lsrow levelselectselect[0] #define lscol levelselectselect[1] +#define lstic levelselectselect[2] + +#define hseperation 101 +#define vseperation 82 + +static boolean M_LevelUnlockedInNewList(INT32 mapnum) +{ + if (M_MapLocked(mapnum+1)) + return false; // not unlocked + + switch (levellistmode) + { + case LLM_CREATESERVER: + return true; + + case LLM_LEVELSELECT: + return true; + + case LLM_RECORDATTACK: + if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + return true; + + if (!mapvisited[mapnum]) + return false; + + return true; + case LLM_NIGHTSATTACK: + if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + return true; + + if (!mapvisited[mapnum]) + return false; + + return true; + } + return true; +} // // M_CanShowLevelInNewList @@ -3464,6 +3503,9 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) if (!mapheaderinfo[mapnum]->lvlttl[0]) return false; + /*if (M_MapLocked(mapnum+1)) + return false; // not unlocked*/ + switch (levellistmode) { case LLM_CREATESERVER: @@ -3471,9 +3513,6 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) return false; - /*if (M_MapLocked(mapnum+1)) - return false; // not unlocked*/ - if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP)) return true; @@ -3498,21 +3537,15 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) if (mapheaderinfo[mapnum]->levelselect != maplistoption) return false; - /*if (M_MapLocked(mapnum+1)) - return false; // not unlocked*/ - return true; case LLM_RECORDATTACK: if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) return false; - /*if (M_MapLocked(mapnum+1)) - return false; // not unlocked*/ - - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + /*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) return true; - /*if (!mapvisited[mapnum]) + if (!mapvisited[mapnum]) return false;*/ return true; @@ -3520,13 +3553,10 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK)) return false; - /*if (M_MapLocked(mapnum+1)) - return false; // not unlocked*/ - - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + /*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) return true; - /*if (!mapvisited[mapnum]) + if (!mapvisited[mapnum]) return false;*/ return true; @@ -3612,8 +3642,7 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) } levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter - levelselect.rows[row].mapavailable[col] = true; /*(!M_MapLocked(mapnum+1) - && (mapvisited[mapnum] || mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED));*/ + levelselect.rows[row].mapavailable[col] = M_LevelUnlockedInNewList(mapnum); // individual map name if (!levelselect.rows[row].mapavailable[col]) @@ -3642,7 +3671,20 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) } } - lsrow = lscol = 0; + lsrow = lscol = lstic = lsoffs[0] = lsoffs[1] = 0; + + if (levselp[0]) // never going to have some provided but not all, saves individually checking + { + W_UnlockCachedPatch(levselp[0]); + W_UnlockCachedPatch(levselp[1]); + W_UnlockCachedPatch(levselp[2]); + W_UnlockCachedPatch(levselp[3]); + } + + levselp[0] = W_CachePatchName("SLCT1LVL", PU_STATIC); + levselp[1] = W_CachePatchName("SLCT2LVL", PU_STATIC); + levselp[2] = W_CachePatchName("BLANKLVL", PU_STATIC); + levselp[3] = W_CachePatchName("STATCLVL", PU_STATIC); return true; } @@ -3658,6 +3700,7 @@ static void M_HandleNewLevelSelect(INT32 choice) lsrow++; if (lsrow == levelselect.numrows) lsrow = 0; + lsoffs[0] = vseperation; S_StartSound(NULL,sfx_s3kb7); break; @@ -3665,6 +3708,7 @@ static void M_HandleNewLevelSelect(INT32 choice) lsrow--; if (lsrow == UINT8_MAX) lsrow = levelselect.numrows-1; + lsoffs[0] = -vseperation; S_StartSound(NULL,sfx_s3kb7); break; @@ -3672,6 +3716,7 @@ static void M_HandleNewLevelSelect(INT32 choice) if (lscol > 0) { lscol--; + lsoffs[1] = hseperation; S_StartSound(NULL,sfx_s3kb7); } break; @@ -3680,6 +3725,7 @@ static void M_HandleNewLevelSelect(INT32 choice) if (lscol < 2) { lscol++; + lsoffs[1] = -hseperation; S_StartSound(NULL,sfx_s3kb7); } break; @@ -3690,10 +3736,13 @@ static void M_HandleNewLevelSelect(INT32 choice) { CV_SetValue(&cv_nextmap, selectval); M_LevelSelectWarp(0); - S_StartSound(NULL,sfx_s3kb7); + S_StartSound(NULL,sfx_menu1); } else + { + lsoffs[0] = -8; S_StartSound(NULL,sfx_s3kb2); + } break; case KEY_ESCAPE: @@ -3713,6 +3762,81 @@ static void M_HandleNewLevelSelect(INT32 choice) } } +static void M_DrawLevelSelectRow(UINT8 row, INT32 y) +{ + UINT8 col; + const boolean highlight = (row == lsrow); + y -= 16; + if (levelselect.rows[row].header[0]) + { + V_DrawString(19, y-4, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].header); + if ((y > 0) && (y < 200)) + { + V_DrawFill(19, y+5, 282, 2, 26); + V_DrawFill(19, y+5, 281, 1, (highlight ? yellowmap[3] : 3)); + } + } + y += 8; + for (col = 0; col < 3; col++) + { + INT32 x = 19+(col*hseperation); + patch_t *patch; + + INT32 map = levelselect.rows[row].maplist[col]; + if (!map) + continue; + + // A 160x100 image of the level as entry MAPxxP + if (!(levelselect.rows[row].mapavailable[col])) + patch = ((lstic & 1) ? levselp[2] : levselp[3]); // static - make secret maps look ENTICING + else if (W_CheckNumForName(va("%sP", G_BuildMapName(map))) != LUMPERROR) + patch = W_CachePatchName(va("%sP", G_BuildMapName(map)), PU_CACHE); + else + patch = levselp[2]; // don't flash to indicate that it's just a normal level + + V_DrawSmallScaledPatch(x, y, 0, patch); + W_UnlockCachedPatch(patch); + + if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "EGG ROCK CORE" + V_DrawThinString(x, y+50, ((highlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); + else // "ACT 19" + V_DrawString(x, y+50, ((highlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); + } +} + +static void M_DrawLevelSelectMenu(void) +{ + UINT8 prev = ((lsrow == 0) ? levelselect.numrows-1 : lsrow-1); + UINT8 next = ((lsrow == levelselect.numrows-1) ? 0 : lsrow+1); + + if (++lstic == 32) + lstic = 0; + + M_DrawLevelSelectRow(prev, lsoffs[0]); + M_DrawLevelSelectRow(lsrow, vseperation + lsoffs[0]); + M_DrawLevelSelectRow(next, 2*vseperation + lsoffs[0]); + + if (lsoffs[0] > vseperation/3) + M_DrawLevelSelectRow( ((prev == 0) ? levelselect.numrows-1 : prev-1), -vseperation + lsoffs[0]); + else if (lsoffs[0] < -vseperation/3) + M_DrawLevelSelectRow( ((next == levelselect.numrows-1) ? 0 : next+1), 3*vseperation + lsoffs[0]); + + if (abs(lsoffs[0]) > 1) + lsoffs[0] = 2*lsoffs[0]/3; + else + lsoffs[0] = 0; + + if (abs(lsoffs[1]) > 1) + lsoffs[1] >>= 2; + else + lsoffs[1] = 0; + + V_DrawSmallScaledPatch(19+(lscol*hseperation) + lsoffs[1], vseperation-8, 0, ((lstic & 8) ? levselp[0] : levselp[1])); +} + +#undef hseperation +#undef vseperation + #undef lsrow #undef lscol @@ -4363,36 +4487,6 @@ static void M_DrawEmblemHints(void) M_DrawGenericMenu(); } -static void M_DrawLevelSelectMenu(void) -{ - M_DrawGenericMenu(); - - V_DrawCenteredString(160, 40, V_YELLOWMAP, levelselect.rows[levelselectselect[0]].header); - V_DrawCenteredString(160, 48, 0, levelselect.rows[levelselectselect[0]].mapnames[levelselectselect[1]]); - - /*if (levelselect.rows[levelselectselect[0]].maplist[levelselectselect[1]]) - V_DrawCenteredString(160, 48, V_YELLOWMAP, - va("%s\n", G_BuildMapTitle(levelselect.rows[levelselectselect[0]].maplist[levelselectselect[1]]))); - else - V_DrawCenteredString(160, 48, V_YELLOWMAP, - va("none\n"));*/ - /*if (cv_nextmap.value) - { - lumpnum_t lumpnum; - patch_t *PictureOfLevel; - - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - V_DrawSmallScaledPatch(200, 110, 0, PictureOfLevel); - }*/ -} - static void M_DrawSkyRoom(void) { INT32 i, y = 0; From 7178ae5916afdf233127096a3696ddb412be03e0 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 27 Jan 2017 14:42:57 +0000 Subject: [PATCH 03/29] Hefty refactor. * Named all the new functions/etc "Platter" instead of "NewList", to make maintenence easier and also because it sounds delicious. * The code, as a whole, is much cleaner. * Allows for multiple items under the same heading now, with highlights and spacing consistently handled. * Allows for picking up where you left off between menus now (assuming the same map is available on multiple screens). * Defined M_CanShowLevelInList in terms of the two compartmentalised functions cleaved from it, in order to ensure consistency and prevent code duplication. --- src/m_menu.c | 309 ++++++++++++++++++++++++--------------------------- src/m_menu.h | 3 +- 2 files changed, 146 insertions(+), 166 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 072c29e84..97f396207 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -309,7 +309,7 @@ static void M_DrawChecklist(void); static void M_DrawEmblemHints(void); static void M_DrawPauseMenu(void); static void M_DrawServerMenu(void); -static void M_DrawLevelSelectMenu(void); +static void M_DrawLevelPlatterMenu(void); static void M_DrawImageDef(void); static void M_DrawLoad(void); static void M_DrawLevelStats(void); @@ -338,6 +338,7 @@ static boolean M_CancelConnect(void); #endif static boolean M_ExitPandorasBox(void); static boolean M_QuitMultiPlayerMenu(void); +static void M_HandleLevelPlatter(INT32 choice); static void M_HandleSoundTest(INT32 choice); static void M_HandleImageDef(INT32 choice); static void M_HandleLoadSave(INT32 choice); @@ -347,7 +348,6 @@ static void M_HandleLevelStats(INT32 choice); static void M_HandleConnectIP(INT32 choice); #endif static void M_HandleSetupMultiPlayer(INT32 choice); -static void M_HandleNewLevelSelect(INT32 choice); #ifdef HWRENDER static void M_HandleFogColor(INT32 choice); #endif @@ -644,7 +644,7 @@ static menuitem_t SR_MainMenu[] = static menuitem_t SR_LevelSelectMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleNewLevelSelect, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func /* {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120},*/ @@ -1437,7 +1437,7 @@ menu_t SR_LevelSelectDef = sizeof (SR_LevelSelectMenu)/sizeof (menuitem_t), &SR_MainDef, SR_LevelSelectMenu, - M_DrawLevelSelectMenu, + M_DrawLevelPlatterMenu, 40, 40, 0, NULL @@ -3443,38 +3443,36 @@ static void M_PatchSkinNameTable(void) // Handle Level Select static levelselect_t levelselect = {0, NULL}; -static UINT8 levelselectselect[3]; +static UINT8 levelselectselect[4]; static patch_t *levselp[4]; static INT32 lsoffs[2]; #define lsrow levelselectselect[0] #define lscol levelselectselect[1] #define lstic levelselectselect[2] +#define lshli levelselectselect[3] #define hseperation 101 -#define vseperation 82 +#define basevseperation 62 +#define headingheight 16 +#define getheadingoffset(row) (levelselect.rows[row].header[0] ? headingheight : 0) +#define vseperation(row) basevseperation + getheadingoffset(row) -static boolean M_LevelUnlockedInNewList(INT32 mapnum) +// +// M_LevelAvailableOnPlatter +// +// Okay, you know that the level SHOULD show up on the platter already. +// The only question is whether it should be as a question mark, +// (hinting as to its existence), or as its pure, unfettered self. +// +static boolean M_LevelAvailableOnPlatter(INT32 mapnum) { if (M_MapLocked(mapnum+1)) return false; // not unlocked switch (levellistmode) { - case LLM_CREATESERVER: - return true; - - case LLM_LEVELSELECT: - return true; - case LLM_RECORDATTACK: - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false; - - return true; case LLM_NIGHTSATTACK: if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) return true; @@ -3482,18 +3480,22 @@ static boolean M_LevelUnlockedInNewList(INT32 mapnum) if (!mapvisited[mapnum]) return false; + // intentional fallthrough + case LLM_CREATESERVER: + case LLM_LEVELSELECT: + default: return true; } return true; } // -// M_CanShowLevelInNewList +// M_CanShowLevelOnPlatter // // Determines whether to show a given map in the various level-select lists. // Set gt = -1 to ignore gametype. // -boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) +static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) { // Does the map exist? if (!mapheaderinfo[mapnum]) @@ -3542,23 +3544,11 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) return false; - /*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false;*/ - return true; case LLM_NIGHTSATTACK: if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK)) return false; - /*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false;*/ - return true; } @@ -3566,24 +3556,24 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) return false; } -/*static INT32 M_CountLevelsToShowInNewList(INT32 gt) +/*static INT32 M_CountLevelsToShowOnPlatter(INT32 gt) { INT32 mapnum, count = 0; for (mapnum = 0; mapnum < NUMMAPS; mapnum++) - if (M_CanShowLevelInList(mapnum, gt)) + if (M_CanShowLevelInPlatter(mapnum, gt)) count++; return count; }*/ -static INT32 M_CountRowsToShowInNewList(INT32 gt) +static INT32 M_CountRowsToShowOnPlatter(INT32 gt) { INT32 mapnum, prevmapnum, col = 0, rows = 0; for (mapnum = 0; mapnum < NUMMAPS; mapnum++) { - if (M_CanShowLevelInNewList(mapnum, gt)) + if (M_CanShowLevelOnPlatter(mapnum, gt)) { if (rows == 0) rows++; @@ -3605,9 +3595,9 @@ static INT32 M_CountRowsToShowInNewList(INT32 gt) return rows; } -static boolean M_PrepareNewLevelSelect(INT32 gt) +static boolean M_PrepareLevelPlatter(INT32 gt) { - INT32 numrows = M_CountRowsToShowInNewList(gt); + INT32 numrows = M_CountRowsToShowOnPlatter(gt); INT32 mapnum, col = 0, row = 0; if (!numrows) @@ -3620,13 +3610,17 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) levelselect.numrows = numrows; levelselect.rows = Z_Realloc(levelselect.rows, numrows*sizeof(levelselectrow_t), PU_STATIC, NULL); if (!levelselect.rows) - I_Error("Insufficient memory to prepare level select platter"); + I_Error("Insufficient memory to prepare level platter"); + + // done here so lsrow and lscol can be set if cv_nextmap is on the platter + lsrow = lscol = lstic = lshli = lsoffs[0] = lsoffs[1] = 0; for (mapnum = 0; mapnum < NUMMAPS; mapnum++) { - if (M_CanShowLevelInNewList(mapnum, gt)) + if (M_CanShowLevelOnPlatter(mapnum, gt)) { const INT32 actnum = mapheaderinfo[mapnum]->actnum; + const boolean headingisname = (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[mapnum]->lvlttl)); // preparing next position to drop mapnum into if (levelselect.rows[0].maplist[0]) @@ -3642,27 +3636,33 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) } levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter - levelselect.rows[row].mapavailable[col] = M_LevelUnlockedInNewList(mapnum); + levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(mapnum); + + if (cv_nextmap.value == mapnum+1) // A little quality of life improvement. + { + lsrow = row; + lscol = col; + } // individual map name if (!levelselect.rows[row].mapavailable[col]) sprintf(levelselect.rows[row].mapnames[col], "???"); else if (actnum) sprintf(levelselect.rows[row].mapnames[col], "ACT %d", actnum); + else if (headingisname) + sprintf(levelselect.rows[row].mapnames[col], "THE ACT", actnum); else - { sprintf(levelselect.rows[row].mapnames[col], "%s", mapheaderinfo[mapnum]->lvlttl); - } // creating header text - if (!col && (!row || (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row].maplist[0]-1]->selectheading)))) + if (!col && (!row || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row-1].maplist[0]-1]->selectheading)))) { if (!levelselect.rows[row].mapavailable[col]) sprintf(levelselect.rows[row].header, "???"); else { sprintf(levelselect.rows[row].header, "%s", mapheaderinfo[mapnum]->selectheading); - if (!(mapheaderinfo[mapnum]->levelflags & LF_NOZONE) && (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[mapnum]->lvlttl))) + if (!(mapheaderinfo[mapnum]->levelflags & LF_NOZONE) && headingisname) { sprintf(levelselect.rows[row].header + strlen(levelselect.rows[row].header), " ZONE"); } @@ -3671,8 +3671,6 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) } } - lsrow = lscol = lstic = lsoffs[0] = lsoffs[1] = 0; - if (levselp[0]) // never going to have some provided but not all, saves individually checking { W_UnlockCachedPatch(levselp[0]); @@ -3689,7 +3687,14 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) return true; } -static void M_HandleNewLevelSelect(INT32 choice) +#define selectvalnextmapnobrace(column) selectval = levelselect.rows[lsrow].maplist[column];\ + if (selectval && levelselect.rows[lsrow].mapavailable[column])\ + {\ + CV_SetValue(&cv_nextmap, selectval); + +#define selectvalnextmap(column) selectvalnextmapnobrace(column)} + +static void M_HandleLevelPlatter(INT32 choice) { boolean exitmenu = false; // exit to previous menu INT32 selectval; @@ -3700,24 +3705,50 @@ static void M_HandleNewLevelSelect(INT32 choice) lsrow++; if (lsrow == levelselect.numrows) lsrow = 0; - lsoffs[0] = vseperation; + + lsoffs[0] = vseperation(lsrow); + + if (levelselect.rows[lsrow].header[0]) + lshli = lsrow; + // no else needed - headerless lines associate upwards, so moving down to a row without a header is identity + S_StartSound(NULL,sfx_s3kb7); + + selectvalnextmap(lscol) else selectvalnextmap(0) break; case KEY_UPARROW: + lsoffs[0] = -vseperation(lsrow); + lsrow--; if (lsrow == UINT8_MAX) lsrow = levelselect.numrows-1; - lsoffs[0] = -vseperation; + + if (levelselect.rows[lsrow].header[0]) + lshli = lsrow; + else + { + UINT8 iter = lsrow; + do + iter = ((iter == 0) ? levelselect.numrows-1 : iter-1); + while ((iter != lsrow) && !(levelselect.rows[iter].header[0])); + lshli = iter; + } + S_StartSound(NULL,sfx_s3kb7); + + selectvalnextmap(lscol) else selectvalnextmap(0) break; case KEY_LEFTARROW: if (lscol > 0) { lscol--; + lsoffs[1] = hseperation; S_StartSound(NULL,sfx_s3kb7); + + selectvalnextmap(lscol) else selectvalnextmap(0) } break; @@ -3725,20 +3756,23 @@ static void M_HandleNewLevelSelect(INT32 choice) if (lscol < 2) { lscol++; + lsoffs[1] = -hseperation; S_StartSound(NULL,sfx_s3kb7); + + selectvalnextmap(lscol) else selectvalnextmap(0) } break; case KEY_ENTER: - selectval = levelselect.rows[lsrow].maplist[lscol]; - if (selectval && levelselect.rows[lsrow].mapavailable[lscol]) - { - CV_SetValue(&cv_nextmap, selectval); + selectvalnextmapnobrace(lscol) + M_LevelSelectWarp(0); + + lsoffs[0] = lsoffs[1] = 0; S_StartSound(NULL,sfx_menu1); } - else + else if (!lsoffs[0]) // prevent sound spam { lsoffs[0] = -8; S_StartSound(NULL,sfx_s3kb2); @@ -3762,21 +3796,29 @@ static void M_HandleNewLevelSelect(INT32 choice) } } -static void M_DrawLevelSelectRow(UINT8 row, INT32 y) +static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) { UINT8 col; - const boolean highlight = (row == lsrow); - y -= 16; + const boolean rowhighlight = (row == lsrow); if (levelselect.rows[row].header[0]) { - V_DrawString(19, y-4, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].header); - if ((y > 0) && (y < 200)) + const boolean headerhighlight = (rowhighlight || (row == lshli)); + + y += headingheight - 12; + V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0), levelselect.rows[row].header); + y += 9; + if ((y >= 0) && (y < 200)) { - V_DrawFill(19, y+5, 282, 2, 26); - V_DrawFill(19, y+5, 281, 1, (highlight ? yellowmap[3] : 3)); + V_DrawFill(19, y, 281, 1, (headerhighlight ? yellowmap[3] : 3)); + V_DrawFill(300, y, 1, 1, 26); } + y++; + if ((y >= 0) && (y < 200)) + { + V_DrawFill(19, y, 282, 1, 26); + } + y += 2; } - y += 8; for (col = 0; col < 3; col++) { INT32 x = 19+(col*hseperation); @@ -3795,50 +3837,66 @@ static void M_DrawLevelSelectRow(UINT8 row, INT32 y) patch = levselp[2]; // don't flash to indicate that it's just a normal level V_DrawSmallScaledPatch(x, y, 0, patch); - W_UnlockCachedPatch(patch); - if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "EGG ROCK CORE" - V_DrawThinString(x, y+50, ((highlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); - else // "ACT 19" - V_DrawString(x, y+50, ((highlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); + if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed + V_DrawThinString(x, y+50, ((rowhighlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); + else + V_DrawString(x, y+50, ((rowhighlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); } } -static void M_DrawLevelSelectMenu(void) +#define basey 59+headingheight + +static void M_DrawLevelPlatterMenu(void) { - UINT8 prev = ((lsrow == 0) ? levelselect.numrows-1 : lsrow-1); - UINT8 next = ((lsrow == levelselect.numrows-1) ? 0 : lsrow+1); + UINT8 iter = lsrow; + INT32 y = basey + lsoffs[0] - getheadingoffset(lsrow); if (++lstic == 32) lstic = 0; - M_DrawLevelSelectRow(prev, lsoffs[0]); - M_DrawLevelSelectRow(lsrow, vseperation + lsoffs[0]); - M_DrawLevelSelectRow(next, 2*vseperation + lsoffs[0]); + // finds row at top of the screen + while (y > 0) + { + iter = ((iter == 0) ? levelselect.numrows-1 : iter-1); + y -= vseperation(iter); + } - if (lsoffs[0] > vseperation/3) - M_DrawLevelSelectRow( ((prev == 0) ? levelselect.numrows-1 : prev-1), -vseperation + lsoffs[0]); - else if (lsoffs[0] < -vseperation/3) - M_DrawLevelSelectRow( ((next == levelselect.numrows-1) ? 0 : next+1), 3*vseperation + lsoffs[0]); + // draw from top to bottom + while (y < 200) + { + M_DrawLevelPlatterRow(iter, y); + y += vseperation(iter); + iter = ((iter == levelselect.numrows-1) ? 0 : iter+1); + } + // handle movement of cursor box if (abs(lsoffs[0]) > 1) lsoffs[0] = 2*lsoffs[0]/3; else lsoffs[0] = 0; if (abs(lsoffs[1]) > 1) - lsoffs[1] >>= 2; + lsoffs[1] = 2*lsoffs[1]/3; else lsoffs[1] = 0; - V_DrawSmallScaledPatch(19+(lscol*hseperation) + lsoffs[1], vseperation-8, 0, ((lstic & 8) ? levselp[0] : levselp[1])); + // draw cursor box + V_DrawSmallScaledPatch(19+(lscol*hseperation) + lsoffs[1], basey, 0, ((lstic & 8) ? levselp[0] : levselp[1])); } -#undef hseperation -#undef vseperation +#undef basey #undef lsrow #undef lscol +#undef lstic +#undef lshli + +#undef hseperation +#undef basevseperation +#undef headingheight +#undef getheadingoffset +#undef vseperation // Call before showing any level-select menus static void M_PrepareLevelSelect(void) @@ -3852,89 +3910,12 @@ static void M_PrepareLevelSelect(void) // // M_CanShowLevelInList // -// Determines whether to show a given map in the various level-select lists. +// Determines whether to show a given map in level-select lists where you don't want to see locked levels. // 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; - - switch (levellistmode) - { - case LLM_CREATESERVER: - // Should the map be hidden? - if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP)) - return true; - - if (gt == GT_COMPETITION && (mapheaderinfo[mapnum]->typeoflevel & TOL_COMPETITION)) - return true; - - if (gt == GT_CTF && (mapheaderinfo[mapnum]->typeoflevel & TOL_CTF)) - return true; - - if ((gt == GT_MATCH || gt == GT_TEAMMATCH) && (mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH)) - return true; - - if ((gt == GT_TAG || gt == GT_HIDEANDSEEK) && (mapheaderinfo[mapnum]->typeoflevel & TOL_TAG)) - return true; - - if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) - return true; - - return false; - - case LLM_LEVELSELECT: - if (mapheaderinfo[mapnum]->levelselect != maplistoption) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - return true; - case LLM_RECORDATTACK: - if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false; - - return true; - case LLM_NIGHTSATTACK: - if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK)) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false; - - return true; - } - - // Hmm? Couldn't decide? - return false; + return (M_CanShowLevelOnPlatter(mapnum, gt) && M_LevelAvailableOnPlatter(mapnum)); } static INT32 M_CountLevelsToShowInList(void) @@ -4669,7 +4650,7 @@ static void M_CustomLevelSelect(INT32 choice) SR_LevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; maplistoption = (UINT8)(unlockables[ul].variable); - if (!M_PrepareNewLevelSelect(-1)) + if (!M_PrepareLevelPlatter(-1)) { M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); return; diff --git a/src/m_menu.h b/src/m_menu.h index 76eabd729..5c07d8ae8 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -66,9 +66,8 @@ void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtyp // Called by linux_x/i_video_xshm.c void M_QuitResponse(INT32 ch); -// Determines whether to show a level in the list +// Determines whether to show a level in the list (platter version does not need to be exposed) boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); -boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt); // flags for items in the menu From 2737d08107bcee1a536c063e27b1e43c70090d2f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 27 Jan 2017 23:16:35 +0000 Subject: [PATCH 04/29] * Singleplayer save-complete level select now following new system. * More comprehensive "pick up where you left off" system. * Made individual map name selection actually take into account the map name AND the act number if the heading isn't the zone name. --- src/m_menu.c | 77 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 97f396207..4c37bb3af 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -645,9 +645,6 @@ static menuitem_t SR_MainMenu[] = static menuitem_t SR_LevelSelectMenu[] = { {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func -/* {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120},*/ }; static menuitem_t SR_UnlockChecklistMenu[] = @@ -692,9 +689,7 @@ static menuitem_t SP_LoadGameMenu[] = // Single Player Level Select static menuitem_t SP_LevelSelectMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func }; // Single Player Time Attack @@ -1433,12 +1428,12 @@ menu_t SR_MainDef = }; menu_t SR_LevelSelectDef = { - 0, + NULL, sizeof (SR_LevelSelectMenu)/sizeof (menuitem_t), &SR_MainDef, SR_LevelSelectMenu, M_DrawLevelPlatterMenu, - 40, 40, + 0, 0, 0, NULL }; @@ -1478,7 +1473,18 @@ menu_t SP_LoadDef = 0, NULL }; -menu_t SP_LevelSelectDef = MAPICONMENUSTYLE(NULL, SP_LevelSelectMenu, &SP_LoadDef); + +menu_t SP_LevelSelectDef = +{ + NULL, + sizeof (SP_LevelSelectMenu)/sizeof (menuitem_t), + &SP_LoadDef, + SP_LevelSelectMenu, + M_DrawLevelPlatterMenu, + 0, 0, + 0, + NULL +}; menu_t SP_GameStatsDef = { @@ -3556,22 +3562,24 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) return false; } -/*static INT32 M_CountLevelsToShowOnPlatter(INT32 gt) +#if 0 +static INT32 M_CountLevelsToShowOnPlatter(INT32 gt) { INT32 mapnum, count = 0; for (mapnum = 0; mapnum < NUMMAPS; mapnum++) - if (M_CanShowLevelInPlatter(mapnum, gt)) + if (M_CanShowLevelOnPlatter(mapnum, gt)) count++; return count; -}*/ +} +#endif static INT32 M_CountRowsToShowOnPlatter(INT32 gt) { - INT32 mapnum, prevmapnum, col = 0, rows = 0; + INT32 mapnum = 0, prevmapnum = 0, col = 0, rows = 0; - for (mapnum = 0; mapnum < NUMMAPS; mapnum++) + while (mapnum < NUMMAPS) { if (M_CanShowLevelOnPlatter(mapnum, gt)) { @@ -3590,6 +3598,7 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) } prevmapnum = mapnum; } + mapnum++; } return rows; @@ -3598,7 +3607,7 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) static boolean M_PrepareLevelPlatter(INT32 gt) { INT32 numrows = M_CountRowsToShowOnPlatter(gt); - INT32 mapnum, col = 0, row = 0; + INT32 mapnum, desiredmap, col = 0, row = 0; if (!numrows) return false; @@ -3615,6 +3624,8 @@ static boolean M_PrepareLevelPlatter(INT32 gt) // done here so lsrow and lscol can be set if cv_nextmap is on the platter lsrow = lscol = lstic = lshli = lsoffs[0] = lsoffs[1] = 0; + desiredmap = ((Playing()) ? gamemap: cv_nextmap.value); + for (mapnum = 0; mapnum < NUMMAPS; mapnum++) { if (M_CanShowLevelOnPlatter(mapnum, gt)) @@ -3638,21 +3649,32 @@ static boolean M_PrepareLevelPlatter(INT32 gt) levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(mapnum); - if (cv_nextmap.value == mapnum+1) // A little quality of life improvement. + if (desiredmap == mapnum+1) // A little quality of life improvement. { lsrow = row; lscol = col; } // individual map name - if (!levelselect.rows[row].mapavailable[col]) - sprintf(levelselect.rows[row].mapnames[col], "???"); - else if (actnum) - sprintf(levelselect.rows[row].mapnames[col], "ACT %d", actnum); - else if (headingisname) - sprintf(levelselect.rows[row].mapnames[col], "THE ACT", actnum); + if (levelselect.rows[row].mapavailable[col]) + { + if (headingisname) + { + if (actnum) + sprintf(levelselect.rows[row].mapnames[col], "ACT %d", actnum); + else + sprintf(levelselect.rows[row].mapnames[col], "THE ACT"); + } + else + { + if (actnum) + sprintf(levelselect.rows[row].mapnames[col], "%s %d", mapheaderinfo[mapnum]->lvlttl, actnum); + else + sprintf(levelselect.rows[row].mapnames[col], "%s", mapheaderinfo[mapnum]->lvlttl); + } + } else - sprintf(levelselect.rows[row].mapnames[col], "%s", mapheaderinfo[mapnum]->lvlttl); + sprintf(levelselect.rows[row].mapnames[col], "???"); // creating header text if (!col && (!row || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row-1].maplist[0]-1]->selectheading)))) @@ -4650,6 +4672,7 @@ static void M_CustomLevelSelect(INT32 choice) SR_LevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; maplistoption = (UINT8)(unlockables[ul].variable); + if (!M_PrepareLevelPlatter(-1)) { M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); @@ -4677,17 +4700,17 @@ static void M_SinglePlayerMenu(INT32 choice) static void M_LoadGameLevelSelect(INT32 choice) { (void)choice; + + SP_LevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; maplistoption = 1; - if (M_CountLevelsToShowInList() == 0) + + if (!M_PrepareLevelPlatter(-1)) { M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); return; } - SP_LevelSelectDef.prevMenu = currentMenu; - - M_PrepareLevelSelect(); M_SetupNextMenu(&SP_LevelSelectDef); } From 70068c664d40bf7ff144c57c29112be885dee82c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 28 Jan 2017 00:56:28 +0000 Subject: [PATCH 05/29] * Dark blue background behind text underneath map icons. * Traditional menu cursor now added. --- src/m_menu.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 4c37bb3af..d2751cf9d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3841,6 +3841,7 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) } y += 2; } + for (col = 0; col < 3; col++) { INT32 x = 19+(col*hseperation); @@ -3860,6 +3861,21 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) V_DrawSmallScaledPatch(x, y, 0, patch); + if ((y+50) < 200) + { + INT32 topy = (y+50), h = 8; + + if (topy < 0) + { + h += topy; + topy = 0; + } + else if (topy + h >= 200) + h = 200 - y; + if (h > 0) + V_DrawFill(x, topy, 80, h, 159); + } + if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed V_DrawThinString(x, y+50, ((rowhighlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); else @@ -3873,6 +3889,7 @@ static void M_DrawLevelPlatterMenu(void) { UINT8 iter = lsrow; INT32 y = basey + lsoffs[0] - getheadingoffset(lsrow); + const UINT32 cursorx = 19+(lscol*hseperation); if (++lstic == 32) lstic = 0; @@ -3892,6 +3909,12 @@ static void M_DrawLevelPlatterMenu(void) iter = ((iter == levelselect.numrows-1) ? 0 : iter+1); } + // draw cursor box + V_DrawSmallScaledPatch(cursorx + lsoffs[1], basey, 0, ((lstic & 8) ? levselp[0] : levselp[1])); + + if (levelselect.rows[lsrow].maplist[lscol]) + V_DrawScaledPatch(cursorx-17, basey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE)); + // handle movement of cursor box if (abs(lsoffs[0]) > 1) lsoffs[0] = 2*lsoffs[0]/3; @@ -3902,9 +3925,6 @@ static void M_DrawLevelPlatterMenu(void) lsoffs[1] = 2*lsoffs[1]/3; else lsoffs[1] = 0; - - // draw cursor box - V_DrawSmallScaledPatch(19+(lscol*hseperation) + lsoffs[1], basey, 0, ((lstic & 8) ? levselp[0] : levselp[1])); } #undef basey From 3574b598d62bf074493dba81af4beb2f20bc273a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 28 Jan 2017 10:34:58 +0000 Subject: [PATCH 06/29] * Make unlockable levels (as opposed to ones which are part of the main campaign) have a different coloured (dark orange) text background. * Better comments. --- src/m_menu.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index d2751cf9d..c9d8d0ca9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3604,6 +3604,12 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) return rows; } +// +// M_PrepareLevelPlatter +// +// Prepares a tasty dish of zones and acts! +// Call before any attempt to access a level platter. +// static boolean M_PrepareLevelPlatter(INT32 gt) { INT32 numrows = M_CountRowsToShowOnPlatter(gt); @@ -3716,6 +3722,11 @@ static boolean M_PrepareLevelPlatter(INT32 gt) #define selectvalnextmap(column) selectvalnextmapnobrace(column)} +// +// M_HandleLevelPlatter +// +// Reacts to your key inputs. Basically a mini menu thinker. +// static void M_HandleLevelPlatter(INT32 choice) { boolean exitmenu = false; // exit to previous menu @@ -3772,6 +3783,11 @@ static void M_HandleLevelPlatter(INT32 choice) selectvalnextmap(lscol) else selectvalnextmap(0) } + else if (!lsoffs[1]) // prevent sound spam + { + lsoffs[1] = -8; + S_StartSound(NULL,sfx_s3kb7); + } break; case KEY_RIGHTARROW: @@ -3784,6 +3800,11 @@ static void M_HandleLevelPlatter(INT32 choice) selectvalnextmap(lscol) else selectvalnextmap(0) } + else if (!lsoffs[1]) // prevent sound spam + { + lsoffs[1] = 8; + S_StartSound(NULL,sfx_s3kb7); + } break; case KEY_ENTER: @@ -3873,7 +3894,9 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) else if (topy + h >= 200) h = 200 - y; if (h > 0) - V_DrawFill(x, topy, 80, h, 159); + V_DrawFill(x, topy, 80, h, + ((mapheaderinfo[map-1]->unlockrequired < 0) + ? 159 : 63)); } if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed @@ -3940,7 +3963,7 @@ static void M_DrawLevelPlatterMenu(void) #undef getheadingoffset #undef vseperation -// Call before showing any level-select menus +// Call before showing any level-select menus (Not necessary for platter-based ones) static void M_PrepareLevelSelect(void) { if (levellistmode != LLM_CREATESERVER) From a23da9ae43a903538853b67c6017a030d1bb8b02 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 28 Jan 2017 13:13:03 +0000 Subject: [PATCH 07/29] * Level Platter system added to Record/NiGHTS Attack modes. * Made quality-of-life improvement for starting the player off on the "right" map more reliable. --- src/d_netcmd.c | 2 + src/m_menu.c | 218 ++++++++++++++++++++++++++++++++++++-------- src/sdl/i_video.c | 2 +- src/sdl12/i_video.c | 2 +- src/win32/win_vid.c | 2 +- 5 files changed, 183 insertions(+), 43 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 55a3b30f9..1cc1adf8b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1532,6 +1532,8 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese // The supplied data are assumed to be good. I_Assert(delay >= 0 && delay <= 2); + CV_SetValue(&cv_nextmap, mapnum); + CONS_Debug(DBG_GAMELOGIC, "Map change: mapnum=%d gametype=%d ultmode=%d resetplayers=%d delay=%d skipprecutscene=%d\n", mapnum, newgametype, pultmode, resetplayers, delay, skipprecutscene); diff --git a/src/m_menu.c b/src/m_menu.c index c9d8d0ca9..6895f674f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -238,7 +238,9 @@ menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef; // Single Player static void M_LoadGame(INT32 choice); +static void M_TimeAttackLevelSelect(INT32 choice); static void M_TimeAttack(INT32 choice); +static void M_NightsAttackLevelSelect(INT32 choice); static void M_NightsAttack(INT32 choice); static void M_Statistics(INT32 choice); static void M_ReplayTimeAttack(INT32 choice); @@ -354,6 +356,7 @@ static void M_HandleFogColor(INT32 choice); static void M_HandleVideoMode(INT32 choice); // Consvar onchange functions +static boolean M_SetNextMapOnPlatter(void); static void Nextmap_OnChange(void); static void Newgametype_OnChange(void); static void Dummymares_OnChange(void); @@ -666,10 +669,10 @@ static menuitem_t SR_EmblemHintMenu[] = // Single Player Main static menuitem_t SP_MainMenu[] = { - {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 92}, - {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 100}, - {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 108}, - {IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 116}, + {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 92}, + {IT_SECRET, NULL, "Record Attack", M_TimeAttackLevelSelect, 100}, + {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttackLevelSelect, 108}, + {IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 116}, }; enum @@ -692,6 +695,12 @@ static menuitem_t SP_LevelSelectMenu[] = {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func }; +// Single Player Time Attack Level Select +static menuitem_t SP_TimeAttackLevelSelectMenu[] = +{ + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func +}; + // Single Player Time Attack static menuitem_t SP_TimeAttackMenu[] = { @@ -784,6 +793,12 @@ static menuitem_t SP_NightsGhostMenu[] = {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_NightsAttackDef, 50} }; +// Single Player Nights Attack Level Select +static menuitem_t SP_NightsAttackLevelSelectMenu[] = +{ + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func +}; + // Single Player Nights Attack static menuitem_t SP_NightsAttackMenu[] = { @@ -1478,7 +1493,7 @@ menu_t SP_LevelSelectDef = { NULL, sizeof (SP_LevelSelectMenu)/sizeof (menuitem_t), - &SP_LoadDef, + &MainDef, // Doesn't matter. SP_LevelSelectMenu, M_DrawLevelPlatterMenu, 0, 0, @@ -1509,6 +1524,17 @@ menu_t SP_LevelStatsDef = NULL }; +menu_t SP_TimeAttackLevelSelectDef = +{ + "M_ATTACK", + sizeof (SP_TimeAttackLevelSelectMenu)/sizeof (menuitem_t), + &MainDef, // Doesn't matter. + SP_TimeAttackLevelSelectMenu, + M_DrawLevelPlatterMenu, + 0, 0, + 0, + NULL +}; static menu_t SP_TimeAttackDef = { "M_ATTACK", @@ -1518,7 +1544,7 @@ static menu_t SP_TimeAttackDef = M_DrawTimeAttackMenu, 32, 40, 0, - NULL + M_SetNextMapOnPlatter }; static menu_t SP_ReplayDef = { @@ -1554,6 +1580,17 @@ static menu_t SP_GhostDef = NULL }; +menu_t SP_NightsAttackLevelSelectDef = +{ + "M_NIGHTS", // HAMALAYAN + sizeof (SP_NightsAttackLevelSelectMenu)/sizeof (menuitem_t), + &MainDef, // Doesn't matter. + SP_NightsAttackLevelSelectMenu, + M_DrawLevelPlatterMenu, + 0, 0, + 0, + NULL +}; static menu_t SP_NightsAttackDef = { "M_NIGHTS", @@ -1563,7 +1600,7 @@ static menu_t SP_NightsAttackDef = M_DrawNightsAttackMenu, 32, 40, 0, - NULL + M_SetNextMapOnPlatter }; static menu_t SP_NightsReplayDef = { @@ -1775,6 +1812,7 @@ static void Nextmap_OnChange(void) if (currentMenu == &SP_NightsAttackDef) { + M_SetNextMapOnPlatter(); CV_StealthSetValue(&cv_dummymares, 0); // Hide the record changing CVAR if only one mare is available. if (!nightsrecords[cv_nextmap.value-1] || nightsrecords[cv_nextmap.value-1]->nummares < 2) @@ -2414,7 +2452,7 @@ boolean M_Responder(event_t *ev) multiplayer = false; } - if (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef) + if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef)) { // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. menuactive = false; @@ -3604,6 +3642,27 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) return rows; } +static boolean M_SetNextMapOnPlatter(void) +{ + INT32 row, col = 0; + while (col < 3) + { + row = 0; + while (row < levelselect.numrows) + { + if (levelselect.rows[row].maplist[col] == cv_nextmap.value) + { + lsrow = row; + lscol = col; + return true; + } + row++; + } + col++; + } + return true; +} + // // M_PrepareLevelPlatter // @@ -3613,7 +3672,7 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) static boolean M_PrepareLevelPlatter(INT32 gt) { INT32 numrows = M_CountRowsToShowOnPlatter(gt); - INT32 mapnum, desiredmap, col = 0, row = 0; + INT32 mapnum, col = 0, row = 0; if (!numrows) return false; @@ -3630,8 +3689,6 @@ static boolean M_PrepareLevelPlatter(INT32 gt) // done here so lsrow and lscol can be set if cv_nextmap is on the platter lsrow = lscol = lstic = lshli = lsoffs[0] = lsoffs[1] = 0; - desiredmap = ((Playing()) ? gamemap: cv_nextmap.value); - for (mapnum = 0; mapnum < NUMMAPS; mapnum++) { if (M_CanShowLevelOnPlatter(mapnum, gt)) @@ -3655,7 +3712,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt) levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(mapnum); - if (desiredmap == mapnum+1) // A little quality of life improvement. + if (cv_nextmap.value == mapnum+1) // A little quality of life improvement. { lsrow = row; lscol = col; @@ -3810,10 +3867,17 @@ static void M_HandleLevelPlatter(INT32 choice) case KEY_ENTER: selectvalnextmapnobrace(lscol) - M_LevelSelectWarp(0); - lsoffs[0] = lsoffs[1] = 0; S_StartSound(NULL,sfx_menu1); + if (gamestate == GS_TIMEATTACK) + { + if (currentMenu == &SP_TimeAttackLevelSelectDef) + M_TimeAttack(-1); + else + M_NightsAttack(-1); + } + else + M_LevelSelectWarp(0); } else if (!lsoffs[0]) // prevent sound spam { @@ -3833,7 +3897,16 @@ static void M_HandleLevelPlatter(INT32 choice) if (exitmenu) { if (currentMenu->prevMenu) - M_SetupNextMenu (currentMenu->prevMenu); + { + if (gamestate == GS_TIMEATTACK) + { + // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. + menuactive = false; + D_StartTitle(); + } + else + M_SetupNextMenu (currentMenu->prevMenu); + } else M_ClearMenus(true); } @@ -3917,6 +3990,9 @@ static void M_DrawLevelPlatterMenu(void) if (++lstic == 32) lstic = 0; + if (gamestate == GS_TIMEATTACK) + V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); + // finds row at top of the screen while (y > 0) { @@ -3948,6 +4024,8 @@ static void M_DrawLevelPlatterMenu(void) lsoffs[1] = 2*lsoffs[1]/3; else lsoffs[1] = 0; + + M_DrawMenuTitle(); } #undef basey @@ -5825,33 +5903,63 @@ void M_DrawTimeAttackMenu(void) } } -// Going to Time Attack menu... -static void M_TimeAttack(INT32 choice) +static void M_TimeAttackLevelSelect(INT32 choice) { (void)choice; + levellistmode = LLM_RECORDATTACK; - memset(skins_cons_t, 0, sizeof (skins_cons_t)); - - levellistmode = LLM_RECORDATTACK; // Don't be dependent on cv_newgametype - - if (M_CountLevelsToShowInList() == 0) + if (!M_PrepareLevelPlatter(-1)) { M_StartMessage(M_GetText("No record-attackable levels found.\n"),NULL,MM_NOTHING); return; } + memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); - M_PrepareLevelSelect(); - M_SetupNextMenu(&SP_TimeAttackDef); - Nextmap_OnChange(); - - itemOn = tastart; // "Start" is selected. + M_SetupNextMenu(&SP_TimeAttackLevelSelectDef); G_SetGamestate(GS_TIMEATTACK); S_ChangeMusicInternal("_inter", true); } +// Going to Time Attack menu... +static void M_TimeAttack(INT32 choice) +{ + const boolean direct = (choice != -1); // Are we coming from SP_TimeAtttackLevelSelect? + + if (direct) + { + SP_TimeAttackDef.prevMenu = &MainDef; + levellistmode = LLM_RECORDATTACK; // Don't be dependent on cv_newgametype + + if (M_CountLevelsToShowInList() == 0) + { + M_StartMessage(M_GetText("No record-attackable levels found.\n"),NULL,MM_NOTHING); + return; + } + + memset(skins_cons_t, 0, sizeof (skins_cons_t)); + M_PatchSkinNameTable(); + + M_PrepareLevelSelect(); + } + else + SP_TimeAttackDef.prevMenu = currentMenu; + + M_SetupNextMenu(&SP_TimeAttackDef); + + if (direct) + { + Nextmap_OnChange(); + + G_SetGamestate(GS_TIMEATTACK); + S_ChangeMusicInternal("_inter", true); + } + + itemOn = tastart; // "Start" is selected. +} + // Drawing function for Nights Attack void M_DrawNightsAttackMenu(void) { @@ -5957,34 +6065,64 @@ void M_DrawNightsAttackMenu(void) } } -// Going to Nights Attack menu... -static void M_NightsAttack(INT32 choice) +static void M_NightsAttackLevelSelect(INT32 choice) { (void)choice; + levellistmode = LLM_NIGHTSATTACK; - memset(skins_cons_t, 0, sizeof (skins_cons_t)); - - levellistmode = LLM_NIGHTSATTACK; // Don't be dependent on cv_newgametype - - if (M_CountLevelsToShowInList() == 0) + if (!M_PrepareLevelPlatter(-1)) { M_StartMessage(M_GetText("No NiGHTS-attackable levels found.\n"),NULL,MM_NOTHING); return; } - // This is really just to make sure Sonic is the played character, just in case + memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); - M_PrepareLevelSelect(); - M_SetupNextMenu(&SP_NightsAttackDef); - Nextmap_OnChange(); - - itemOn = nastart; // "Start" is selected. + M_SetupNextMenu(&SP_NightsAttackLevelSelectDef); G_SetGamestate(GS_TIMEATTACK); S_ChangeMusicInternal("_inter", true); } +// Going to Nights Attack menu... +static void M_NightsAttack(INT32 choice) +{ + const boolean direct = (choice != -1); // Are we coming from SP_TimeAtttackLevelSelect? + + if (direct) + { + SP_NightsAttackDef.prevMenu = &MainDef; + levellistmode = LLM_NIGHTSATTACK; // Don't be dependent on cv_newgametype + + if (M_CountLevelsToShowInList() == 0) + { + M_StartMessage(M_GetText("No NiGHTS-attackable levels found.\n"),NULL,MM_NOTHING); + return; + } + + // This is really just to make sure Sonic is the played character, just in case + memset(skins_cons_t, 0, sizeof (skins_cons_t)); + M_PatchSkinNameTable(); + + M_PrepareLevelSelect(); + } + else + SP_NightsAttackDef.prevMenu = currentMenu; + + M_SetupNextMenu(&SP_NightsAttackDef); + + if (direct) + { + Nextmap_OnChange(); + + G_SetGamestate(GS_TIMEATTACK); + S_ChangeMusicInternal("_inter", true); + } + + itemOn = nastart; // "Start" is selected. +} + // Player has selected the "START" from the nights attack screen static void M_ChooseNightsAttack(INT32 choice) { diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index aa572e6e0..7d33f2554 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -909,7 +909,7 @@ static inline boolean I_SkipFrame(void) case GS_LEVEL: if (!paused) return false; - case GS_TIMEATTACK: + //case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible case GS_WAITINGPLAYERS: return skip; // Skip odd frames default: diff --git a/src/sdl12/i_video.c b/src/sdl12/i_video.c index 197924eda..1fa80e7d4 100644 --- a/src/sdl12/i_video.c +++ b/src/sdl12/i_video.c @@ -1311,7 +1311,7 @@ static inline boolean I_SkipFrame(void) case GS_LEVEL: if (!paused) return false; - case GS_TIMEATTACK: + //case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible case GS_WAITINGPLAYERS: return skip; // Skip odd frames default: diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index 0960bb6dd..31d1b8120 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -322,7 +322,7 @@ static inline boolean I_SkipFrame(void) case GS_LEVEL: if (!paused) return false; - case GS_TIMEATTACK: + //case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible #ifndef CLIENT_LOADINGSCREEN case GS_WAITINGPLAYERS: #endif From df3ba302634c32553b59530dd3d27abd077a3e4f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 29 Jan 2017 19:25:43 +0000 Subject: [PATCH 08/29] * Revamped Time and Nights attack. Still need to figure out the way to sort pressing esc on reselect level sending you back to the title screen. This will need further whittling before I can call this a solved section and move onto MP stuff. --- src/m_menu.c | 469 +++++++++++++++++++++++++++------------------------ 1 file changed, 247 insertions(+), 222 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 6895f674f..d2406b655 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -188,6 +188,7 @@ static INT32 vidm_column_size; // PROTOTYPES // +static void M_GoBack(INT32 choice); static void M_StopMessage(INT32 choice); #ifndef NONET @@ -205,6 +206,23 @@ menu_t MessageDef; menu_t SPauseDef; +// Level Select +static levelselect_t levelselect = {0, NULL}; +static UINT8 levelselectselect[4]; +static patch_t *levselp[4]; +static INT32 lsoffs[2]; + +#define lsrow levelselectselect[0] +#define lscol levelselectselect[1] +#define lstic levelselectselect[2] +#define lshli levelselectselect[3] + +#define lshseperation 101 +#define lsbasevseperation 62 +#define lsheadingheight 16 +#define getheadingoffset(row) (levelselect.rows[row].header[0] ? lsheadingheight : 0) +#define lsvseperation(row) lsbasevseperation + getheadingoffset(row) + // Sky Room static void M_CustomLevelSelect(INT32 choice); static void M_CustomWarp(INT32 choice); @@ -356,7 +374,6 @@ static void M_HandleFogColor(INT32 choice); static void M_HandleVideoMode(INT32 choice); // Consvar onchange functions -static boolean M_SetNextMapOnPlatter(void); static void Nextmap_OnChange(void); static void Newgametype_OnChange(void); static void Dummymares_OnChange(void); @@ -704,18 +721,18 @@ static menuitem_t SP_TimeAttackLevelSelectMenu[] = // Single Player Time Attack static menuitem_t SP_TimeAttackMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 52}, - {IT_STRING|IT_CVAR, NULL, "Player", &cv_chooseskin, 62}, + {IT_STRING|IT_CALL, NULL, "Reselect Level", &M_GoBack, 52}, + {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 62}, {IT_DISABLED, NULL, "Guest Option...", &SP_GuestReplayDef, 100}, - {IT_DISABLED, NULL, "Replay...", &SP_ReplayDef, 110}, - {IT_DISABLED, NULL, "Ghosts...", &SP_GhostDef, 120}, + {IT_DISABLED, NULL, "Replay...", &SP_ReplayDef, 110}, + {IT_DISABLED, NULL, "Ghosts...", &SP_GhostDef, 120}, {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseTimeAttack, 130}, }; enum { - talevel, + talevelback, taplayer, taguest, @@ -802,18 +819,18 @@ static menuitem_t SP_NightsAttackLevelSelectMenu[] = // Single Player Nights Attack static menuitem_t SP_NightsAttackMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 44}, - {IT_STRING|IT_CVAR, NULL, "Show Records For", &cv_dummymares, 54}, + {IT_STRING|IT_CALL, NULL, "Reselect Level", &M_GoBack, 52}, + {IT_STRING|IT_CVAR, NULL, "Show Records For", &cv_dummymares, 62}, - {IT_DISABLED, NULL, "Guest Option...", &SP_NightsGuestReplayDef, 108}, - {IT_DISABLED, NULL, "Replay...", &SP_NightsReplayDef, 118}, - {IT_DISABLED, NULL, "Ghosts...", &SP_NightsGhostDef, 128}, - {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseNightsAttack, 138}, + {IT_DISABLED, NULL, "Guest Option...", &SP_NightsGuestReplayDef, 100}, + {IT_DISABLED, NULL, "Replay...", &SP_NightsReplayDef, 110}, + {IT_DISABLED, NULL, "Ghosts...", &SP_NightsGhostDef, 120}, + {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseNightsAttack, 130}, }; enum { - nalevel, + nalevelback, narecords, naguest, @@ -1544,7 +1561,7 @@ static menu_t SP_TimeAttackDef = M_DrawTimeAttackMenu, 32, 40, 0, - M_SetNextMapOnPlatter + NULL }; static menu_t SP_ReplayDef = { @@ -1600,7 +1617,7 @@ static menu_t SP_NightsAttackDef = M_DrawNightsAttackMenu, 32, 40, 0, - M_SetNextMapOnPlatter + NULL }; static menu_t SP_NightsReplayDef = { @@ -1812,7 +1829,6 @@ static void Nextmap_OnChange(void) if (currentMenu == &SP_NightsAttackDef) { - M_SetNextMapOnPlatter(); CV_StealthSetValue(&cv_dummymares, 0); // Hide the record changing CVAR if only one mare is available. if (!nightsrecords[cv_nextmap.value-1] || nightsrecords[cv_nextmap.value-1]->nummares < 2) @@ -2023,6 +2039,34 @@ menu_t *currentMenu = &MainDef; // BASIC MENU HANDLING // ========================================================================= +static void M_GoBack(INT32 choice) +{ + (void)choice; + + if (currentMenu->prevMenu) + { + //If we entered the game search menu, but didn't enter a game, + //make sure the game doesn't still think we're in a netgame. + if (!Playing() && netgame && multiplayer) + { + MSCloseUDPSocket(); // Clean up so we can re-open the connection later. + netgame = false; + multiplayer = false; + } + + if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef)) + { + // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. + menuactive = false; + D_StartTitle(); + } + else + M_SetupNextMenu(currentMenu->prevMenu); + } + else + M_ClearMenus(true); +} + static void M_ChangeCvar(INT32 choice) { consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; @@ -2441,28 +2485,8 @@ boolean M_Responder(event_t *ev) case KEY_ESCAPE: noFurtherInput = true; currentMenu->lastOn = itemOn; - if (currentMenu->prevMenu) - { - //If we entered the game search menu, but didn't enter a game, - //make sure the game doesn't still think we're in a netgame. - if (!Playing() && netgame && multiplayer) - { - MSCloseUDPSocket(); // Clean up so we can re-open the connection later. - netgame = false; - multiplayer = false; - } - if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef)) - { - // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. - menuactive = false; - D_StartTitle(); - } - else - M_SetupNextMenu(currentMenu->prevMenu); - } - else - M_ClearMenus(true); + M_GoBack(0); return true; @@ -3485,23 +3509,6 @@ static void M_PatchSkinNameTable(void) return; } -// Handle Level Select -static levelselect_t levelselect = {0, NULL}; -static UINT8 levelselectselect[4]; -static patch_t *levselp[4]; -static INT32 lsoffs[2]; - -#define lsrow levelselectselect[0] -#define lscol levelselectselect[1] -#define lstic levelselectselect[2] -#define lshli levelselectselect[3] - -#define hseperation 101 -#define basevseperation 62 -#define headingheight 16 -#define getheadingoffset(row) (levelselect.rows[row].header[0] ? headingheight : 0) -#define vseperation(row) basevseperation + getheadingoffset(row) - // // M_LevelAvailableOnPlatter // @@ -3642,6 +3649,7 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) return rows; } +#if 0 static boolean M_SetNextMapOnPlatter(void) { INT32 row, col = 0; @@ -3662,6 +3670,7 @@ static boolean M_SetNextMapOnPlatter(void) } return true; } +#endif // // M_PrepareLevelPlatter @@ -3796,7 +3805,7 @@ static void M_HandleLevelPlatter(INT32 choice) if (lsrow == levelselect.numrows) lsrow = 0; - lsoffs[0] = vseperation(lsrow); + lsoffs[0] = lsvseperation(lsrow); if (levelselect.rows[lsrow].header[0]) lshli = lsrow; @@ -3808,7 +3817,7 @@ static void M_HandleLevelPlatter(INT32 choice) break; case KEY_UPARROW: - lsoffs[0] = -vseperation(lsrow); + lsoffs[0] = -lsvseperation(lsrow); lsrow--; if (lsrow == UINT8_MAX) @@ -3835,7 +3844,7 @@ static void M_HandleLevelPlatter(INT32 choice) { lscol--; - lsoffs[1] = hseperation; + lsoffs[1] = lshseperation; S_StartSound(NULL,sfx_s3kb7); selectvalnextmap(lscol) else selectvalnextmap(0) @@ -3852,7 +3861,7 @@ static void M_HandleLevelPlatter(INT32 choice) { lscol++; - lsoffs[1] = -hseperation; + lsoffs[1] = -lshseperation; S_StartSound(NULL,sfx_s3kb7); selectvalnextmap(lscol) else selectvalnextmap(0) @@ -3912,80 +3921,86 @@ static void M_HandleLevelPlatter(INT32 choice) } } +static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight) +{ + y += lsheadingheight - 12; + V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0), header); + y += 9; + if ((y >= 0) && (y < 200)) + { + V_DrawFill(19, y, 281, 1, (headerhighlight ? yellowmap[3] : 3)); + V_DrawFill(300, y, 1, 1, 26); + } + y++; + if ((y >= 0) && (y < 200)) + { + V_DrawFill(19, y, 282, 1, 26); + } + y += 2; +} + +static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolean highlight) +{ + patch_t *patch; + + INT32 map = levelselect.rows[row].maplist[col]; + if (!map) + return; + + // A 160x100 image of the level as entry MAPxxP + if (!(levelselect.rows[row].mapavailable[col])) + patch = ((lstic & 1) ? levselp[2] : levselp[3]); // static - make secret maps look ENTICING + else if (W_CheckNumForName(va("%sP", G_BuildMapName(map))) != LUMPERROR) + patch = W_CachePatchName(va("%sP", G_BuildMapName(map)), PU_CACHE); + else + patch = levselp[2]; // don't flash to indicate that it's just a normal level + + V_DrawSmallScaledPatch(x, y, 0, patch); + + if ((y+50) < 200) + { + INT32 topy = (y+50), h = 8; + + if (topy < 0) + { + h += topy; + topy = 0; + } + else if (topy + h >= 200) + h = 200 - y; + if (h > 0) + V_DrawFill(x, topy, 80, h, + ((mapheaderinfo[map-1]->unlockrequired < 0) + ? 159 : 63)); + } + + if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed + V_DrawThinString(x, y+50, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); + else + V_DrawString(x, y+50, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); +} + static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) { UINT8 col; const boolean rowhighlight = (row == lsrow); if (levelselect.rows[row].header[0]) { - const boolean headerhighlight = (rowhighlight || (row == lshli)); - - y += headingheight - 12; - V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0), levelselect.rows[row].header); - y += 9; - if ((y >= 0) && (y < 200)) - { - V_DrawFill(19, y, 281, 1, (headerhighlight ? yellowmap[3] : 3)); - V_DrawFill(300, y, 1, 1, 26); - } - y++; - if ((y >= 0) && (y < 200)) - { - V_DrawFill(19, y, 282, 1, 26); - } - y += 2; + M_DrawLevelPlatterHeader(y, levelselect.rows[row].header, (rowhighlight || (row == lshli))); + y += lsheadingheight; } for (col = 0; col < 3; col++) - { - INT32 x = 19+(col*hseperation); - patch_t *patch; - - INT32 map = levelselect.rows[row].maplist[col]; - if (!map) - continue; - - // A 160x100 image of the level as entry MAPxxP - if (!(levelselect.rows[row].mapavailable[col])) - patch = ((lstic & 1) ? levselp[2] : levselp[3]); // static - make secret maps look ENTICING - else if (W_CheckNumForName(va("%sP", G_BuildMapName(map))) != LUMPERROR) - patch = W_CachePatchName(va("%sP", G_BuildMapName(map)), PU_CACHE); - else - patch = levselp[2]; // don't flash to indicate that it's just a normal level - - V_DrawSmallScaledPatch(x, y, 0, patch); - - if ((y+50) < 200) - { - INT32 topy = (y+50), h = 8; - - if (topy < 0) - { - h += topy; - topy = 0; - } - else if (topy + h >= 200) - h = 200 - y; - if (h > 0) - V_DrawFill(x, topy, 80, h, - ((mapheaderinfo[map-1]->unlockrequired < 0) - ? 159 : 63)); - } - - if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed - V_DrawThinString(x, y+50, ((rowhighlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); - else - V_DrawString(x, y+50, ((rowhighlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); - } + M_DrawLevelPlatterMap(row, col, 19+(col*lshseperation), y, (rowhighlight && col == lscol)); } -#define basey 59+headingheight +#define lsbasey 59+lsheadingheight static void M_DrawLevelPlatterMenu(void) { UINT8 iter = lsrow; - INT32 y = basey + lsoffs[0] - getheadingoffset(lsrow); - const UINT32 cursorx = 19+(lscol*hseperation); + INT32 y = lsbasey + lsoffs[0] - getheadingoffset(lsrow); + const UINT32 cursorx = 19+(lscol*lshseperation); if (++lstic == 32) lstic = 0; @@ -3997,22 +4012,22 @@ static void M_DrawLevelPlatterMenu(void) while (y > 0) { iter = ((iter == 0) ? levelselect.numrows-1 : iter-1); - y -= vseperation(iter); + y -= lsvseperation(iter); } // draw from top to bottom while (y < 200) { M_DrawLevelPlatterRow(iter, y); - y += vseperation(iter); + y += lsvseperation(iter); iter = ((iter == levelselect.numrows-1) ? 0 : iter+1); } // draw cursor box - V_DrawSmallScaledPatch(cursorx + lsoffs[1], basey, 0, ((lstic & 8) ? levselp[0] : levselp[1])); + V_DrawSmallScaledPatch(cursorx + lsoffs[1], lsbasey, 0, ((lstic & 8) ? levselp[0] : levselp[1])); if (levelselect.rows[lsrow].maplist[lscol]) - V_DrawScaledPatch(cursorx-17, basey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawScaledPatch(cursorx-17, lsbasey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE)); // handle movement of cursor box if (abs(lsoffs[0]) > 1) @@ -4028,18 +4043,7 @@ static void M_DrawLevelPlatterMenu(void) M_DrawMenuTitle(); } -#undef basey - -#undef lsrow -#undef lscol -#undef lstic -#undef lshli - -#undef hseperation -#undef basevseperation -#undef headingheight -#undef getheadingoffset -#undef vseperation +#undef lsbasey // Call before showing any level-select menus (Not necessary for platter-based ones) static void M_PrepareLevelSelect(void) @@ -5814,7 +5818,7 @@ void M_DrawTimeAttackMenu(void) else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - V_DrawSmallScaledPatch(208, 32, 0, PictureOfLevel); + V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); // Character face! if (W_CheckNumForName(skins[cv_chooseskin.value-1].charsel) != LUMPERROR) @@ -5832,15 +5836,17 @@ void M_DrawTimeAttackMenu(void) emblem_t *em; INT32 yHeight; - V_DrawCenteredString(104, 32, 0, "* LEVEL RECORDS *"); + M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true); + + V_DrawCenteredString(104, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) sprintf(beststr, "(none)"); else sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score); - V_DrawString(104-72, 48, V_YELLOWMAP, "SCORE:"); - V_DrawRightAlignedString(104+72, 48, V_ALLOWLOWERCASE, beststr); + V_DrawString(104-72, 48+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); + V_DrawRightAlignedString(104+72, 48+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) sprintf(beststr, "(none)"); @@ -5849,16 +5855,16 @@ void M_DrawTimeAttackMenu(void) G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); - V_DrawString(104-72, 58, V_YELLOWMAP, "TIME:"); - V_DrawRightAlignedString(104+72, 58, V_ALLOWLOWERCASE, beststr); + V_DrawString(104-72, 58+lsheadingheight/2, V_YELLOWMAP, "TIME:"); + V_DrawRightAlignedString(104+72, 58+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->rings) sprintf(beststr, "(none)"); else sprintf(beststr, "%hu", mainrecords[cv_nextmap.value-1]->rings); - V_DrawString(104-72, 68, V_YELLOWMAP, "RINGS:"); - V_DrawRightAlignedString(104+72, 68, V_ALLOWLOWERCASE, beststr); + V_DrawString(104-72, 68+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); + V_DrawRightAlignedString(104+72, 68+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); // Draw record emblems. em = M_GetLevelEmblems(cv_nextmap.value); @@ -5874,17 +5880,17 @@ void M_DrawTimeAttackMenu(void) } if (em->collected) - V_DrawSmallMappedPatch(104+76, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), + V_DrawSmallMappedPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else - V_DrawSmallScaledPatch(104+76, yHeight, 0, W_CachePatchName("NEEDIT", PU_CACHE)); + V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); skipThisOne: em = M_GetLevelEmblems(-1); } } - // ALWAYS DRAW level name and skin even when not on this menu! + // ALWAYS DRAW level and skin even when not on this menu! if (currentMenu != &SP_TimeAttackDef) { consvar_t *ncv; @@ -5892,14 +5898,11 @@ void M_DrawTimeAttackMenu(void) x = SP_TimeAttackDef.x; y = SP_TimeAttackDef.y; - for (i = 0; i < 2; ++i) - { - ncv = (consvar_t *)SP_TimeAttackMenu[i].itemaction; + V_DrawString(x, y + SP_TimeAttackMenu[talevelback].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[talevelback].text); - V_DrawString(x, y + SP_TimeAttackMenu[i].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[i].text); - V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), - y + SP_TimeAttackMenu[i].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string); - } + ncv = (consvar_t *)SP_TimeAttackMenu[taplayer].itemaction; + V_DrawString(x, y + SP_TimeAttackMenu[taplayer].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[taplayer].text); + V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), y + SP_TimeAttackMenu[taplayer].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string); } } @@ -5914,7 +5917,6 @@ static void M_TimeAttackLevelSelect(INT32 choice) return; } - memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); M_SetupNextMenu(&SP_TimeAttackLevelSelectDef); @@ -5939,7 +5941,6 @@ static void M_TimeAttack(INT32 choice) return; } - memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); M_PrepareLevelSelect(); @@ -5948,11 +5949,10 @@ static void M_TimeAttack(INT32 choice) SP_TimeAttackDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_TimeAttackDef); + Nextmap_OnChange(); if (direct) { - Nextmap_OnChange(); - G_SetGamestate(GS_TIMEATTACK); S_ChangeMusicInternal("_inter", true); } @@ -5963,6 +5963,8 @@ static void M_TimeAttack(INT32 choice) // Drawing function for Nights Attack void M_DrawNightsAttackMenu(void) { + INT32 i, x, y, cursory = 0; + UINT16 dispstatus; patch_t *PictureOfLevel; lumpnum_t lumpnum; char beststr[40]; @@ -5971,8 +5973,43 @@ void M_DrawNightsAttackMenu(void) V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); + M_DrawMenuTitle(); + // draw menu (everything else goes on top of it) - M_DrawGenericMenu(); + // Sadly we can't just use generic mode menus because we need some extra hacks + x = currentMenu->x; + y = currentMenu->y; + + for (i = 0; i < currentMenu->numitems; ++i) + { + dispstatus = (currentMenu->menuitems[i].status & IT_DISPLAY); + if (dispstatus != IT_STRING && dispstatus != IT_WHITESTRING) + continue; + + y = currentMenu->y+currentMenu->menuitems[i].alphaKey; + if (i == itemOn) + cursory = y; + + V_DrawString(x, y, (dispstatus == IT_WHITESTRING) ? V_YELLOWMAP : 0 , currentMenu->menuitems[i].text); + + // Cvar specific handling + if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_CVAR) + { + consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + INT32 soffset = 0; + + // hack to keep the menu from overlapping the overall grade icon + if (currentMenu != &SP_NightsAttackDef) + soffset = 80; + + // Should see nothing but strings + V_DrawString(BASEVIDWIDTH - x - soffset - V_StringWidth(cv->string, 0), y, V_YELLOWMAP, cv->string); + } + } + + // DRAW THE SKULL CURSOR + V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); // A 160x100 image of the level as entry MAPxxP lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); @@ -5982,7 +6019,7 @@ void M_DrawNightsAttackMenu(void) else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - V_DrawSmallScaledPatch(90, 28, 0, PictureOfLevel); + V_DrawSmallScaledPatch(208, 32+lsheadingheight/2, 0, PictureOfLevel); // Level record list if (cv_nextmap.value) @@ -5995,74 +6032,65 @@ void M_DrawNightsAttackMenu(void) UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value); tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value); + M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true); + if (P_HasGrades(cv_nextmap.value, 0)) - V_DrawScaledPatch(200, 28 + 8, 0, ngradeletters[bestoverall]); + V_DrawScaledPatch(224, 120, 0, ngradeletters[bestoverall]); - if (currentMenu == &SP_NightsAttackDef) - { - if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) + if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) { - V_DrawString(160-88, 112, V_YELLOWMAP, "BEST GRADE:"); - V_DrawSmallScaledPatch(160 + 86 - (ngradeletters[bestgrade]->width/2), - 112 + 8 - (ngradeletters[bestgrade]->height/2), - 0, ngradeletters[bestgrade]); - } - - if (!bestscore) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%u", bestscore); - - V_DrawString(160 - 88, 122, V_YELLOWMAP, "BEST SCORE:"); - V_DrawRightAlignedString(160 + 88, 122, V_ALLOWLOWERCASE, beststr); - - if (besttime == UINT32_MAX) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(besttime, true), - G_TicsToSeconds(besttime), - G_TicsToCentiseconds(besttime)); - - V_DrawString(160-88, 132, V_YELLOWMAP, "BEST TIME:"); - V_DrawRightAlignedString(160+88, 132, V_ALLOWLOWERCASE, beststr); - - if (cv_dummymares.value == 0) { - // Draw record emblems. - em = M_GetLevelEmblems(cv_nextmap.value); - while (em) - { - switch (em->type) - { - case ET_NGRADE: yHeight = 112; break; - case ET_NTIME: yHeight = 132; break; - default: - goto skipThisOne; - } - - if (em->collected) - V_DrawSmallMappedPatch(160+88, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); - else - V_DrawSmallScaledPatch(160+88, yHeight, 0, W_CachePatchName("NEEDIT", PU_CACHE)); - - skipThisOne: - em = M_GetLevelEmblems(-1); - } - } + V_DrawString(104 - 72, 48+lsheadingheight/2, V_YELLOWMAP, "BEST GRADE:"); + V_DrawSmallScaledPatch(104 + 72 - (ngradeletters[bestgrade]->width/2), + 48+lsheadingheight/2 + 8 - (ngradeletters[bestgrade]->height/2), + 0, ngradeletters[bestgrade]); } - // ALWAYS DRAW level name even when not on this menu! - else - { - consvar_t *ncv; - INT32 x = SP_NightsAttackDef.x; - INT32 y = SP_NightsAttackDef.y; - ncv = (consvar_t *)SP_NightsAttackMenu[0].itemaction; - V_DrawString(x, y + SP_NightsAttackMenu[0].alphaKey, V_TRANSLUCENT, SP_NightsAttackMenu[0].text); - V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), - y + SP_NightsAttackMenu[0].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string); + if (!bestscore) + sprintf(beststr, "(none)"); + else + sprintf(beststr, "%u", bestscore); + + V_DrawString(104 - 72, 58+lsheadingheight/2, V_YELLOWMAP, "BEST SCORE:"); + V_DrawRightAlignedString(104 + 72, 58+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + + if (besttime == UINT32_MAX) + sprintf(beststr, "(none)"); + else + sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(besttime, true), + G_TicsToSeconds(besttime), + G_TicsToCentiseconds(besttime)); + + V_DrawString(104 - 72, 68+lsheadingheight/2, V_YELLOWMAP, "BEST TIME:"); + V_DrawRightAlignedString(104 + 72, 68+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + + if (cv_dummymares.value == 0) { + // Draw record emblems. + em = M_GetLevelEmblems(cv_nextmap.value); + while (em) + { + switch (em->type) + { + case ET_NGRADE: yHeight = 48; break; + case ET_NTIME: yHeight = 68; break; + default: + goto skipThisOne; + } + + if (em->collected) + V_DrawSmallMappedPatch(104+76, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), + R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); + else + V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); + + skipThisOne: + em = M_GetLevelEmblems(-1); + } } } + + // ALWAYS DRAW level even when not on this menu! + if (currentMenu != &SP_NightsAttackDef) + V_DrawString(SP_TimeAttackDef.x, SP_TimeAttackDef.y + SP_TimeAttackMenu[nalevelback].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[nalevelback].text); } static void M_NightsAttackLevelSelect(INT32 choice) @@ -6076,7 +6104,6 @@ static void M_NightsAttackLevelSelect(INT32 choice) return; } - memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); M_SetupNextMenu(&SP_NightsAttackLevelSelectDef); @@ -6102,7 +6129,6 @@ static void M_NightsAttack(INT32 choice) } // This is really just to make sure Sonic is the played character, just in case - memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); M_PrepareLevelSelect(); @@ -6111,11 +6137,10 @@ static void M_NightsAttack(INT32 choice) SP_NightsAttackDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_NightsAttackDef); + Nextmap_OnChange(); if (direct) { - Nextmap_OnChange(); - G_SetGamestate(GS_TIMEATTACK); S_ChangeMusicInternal("_inter", true); } From 8d3804a2016429dd65a9dd7f6063e48ca1a43afe Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 29 Jan 2017 22:00:07 +0000 Subject: [PATCH 09/29] * Renamed the confusing "Reselect Level" to "Back to Level Select". * Updated layout of NiGHTS attack page to match Records attack. * Improved code. --- src/m_menu.c | 69 +++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index d2406b655..40a729906 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -721,7 +721,7 @@ static menuitem_t SP_TimeAttackLevelSelectMenu[] = // Single Player Time Attack static menuitem_t SP_TimeAttackMenu[] = { - {IT_STRING|IT_CALL, NULL, "Reselect Level", &M_GoBack, 52}, + {IT_STRING|IT_CALL, NULL, "Back to Level Select", &M_GoBack, 52}, {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 62}, {IT_DISABLED, NULL, "Guest Option...", &SP_GuestReplayDef, 100}, @@ -819,13 +819,13 @@ static menuitem_t SP_NightsAttackLevelSelectMenu[] = // Single Player Nights Attack static menuitem_t SP_NightsAttackMenu[] = { - {IT_STRING|IT_CALL, NULL, "Reselect Level", &M_GoBack, 52}, + {IT_STRING|IT_CALL, NULL, "Back to Level Select", &M_GoBack, 52}, {IT_STRING|IT_CVAR, NULL, "Show Records For", &cv_dummymares, 62}, {IT_DISABLED, NULL, "Guest Option...", &SP_NightsGuestReplayDef, 100}, {IT_DISABLED, NULL, "Replay...", &SP_NightsReplayDef, 110}, {IT_DISABLED, NULL, "Ghosts...", &SP_NightsGhostDef, 120}, - {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseNightsAttack, 130}, + {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseNightsAttack, 130}, }; enum @@ -5764,9 +5764,7 @@ void M_DrawTimeAttackMenu(void) { INT32 i, x, y, cursory = 0; UINT16 dispstatus; - patch_t *PictureOfLevel, *PictureOfUrFace; - lumpnum_t lumpnum; - char beststr[40]; + patch_t *PictureOfUrFace; S_ChangeMusicInternal("_inter", true); // Eww, but needed for when user hits escape during demo playback @@ -5810,16 +5808,6 @@ void M_DrawTimeAttackMenu(void) V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); - // Character face! if (W_CheckNumForName(skins[cv_chooseskin.value-1].charsel) != LUMPERROR) { @@ -5835,9 +5823,22 @@ void M_DrawTimeAttackMenu(void) { emblem_t *em; INT32 yHeight; + patch_t *PictureOfLevel; + lumpnum_t lumpnum; + char beststr[40]; M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true); + // A 160x100 image of the level as entry MAPxxP + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); + V_DrawCenteredString(104, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) @@ -5965,9 +5966,6 @@ void M_DrawNightsAttackMenu(void) { INT32 i, x, y, cursory = 0; UINT16 dispstatus; - patch_t *PictureOfLevel; - lumpnum_t lumpnum; - char beststr[40]; S_ChangeMusicInternal("_inter", true); // Eww, but needed for when user hits escape during demo playback @@ -6011,21 +6009,14 @@ void M_DrawNightsAttackMenu(void) V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - V_DrawSmallScaledPatch(208, 32+lsheadingheight/2, 0, PictureOfLevel); - // Level record list if (cv_nextmap.value) { emblem_t *em; INT32 yHeight; + patch_t *PictureOfLevel; + lumpnum_t lumpnum; + char beststr[40]; UINT8 bestoverall = G_GetBestNightsGrade(cv_nextmap.value, 0); UINT8 bestgrade = G_GetBestNightsGrade(cv_nextmap.value, cv_dummymares.value); @@ -6034,14 +6025,26 @@ void M_DrawNightsAttackMenu(void) M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true); + // A 160x100 image of the level as entry MAPxxP + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); + + V_DrawCenteredString(104, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); + if (P_HasGrades(cv_nextmap.value, 0)) - V_DrawScaledPatch(224, 120, 0, ngradeletters[bestoverall]); + V_DrawScaledPatch(235, 135, 0, ngradeletters[bestoverall]); if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) { V_DrawString(104 - 72, 48+lsheadingheight/2, V_YELLOWMAP, "BEST GRADE:"); - V_DrawSmallScaledPatch(104 + 72 - (ngradeletters[bestgrade]->width/2), - 48+lsheadingheight/2 + 8 - (ngradeletters[bestgrade]->height/2), + V_DrawTinyScaledPatch(104 + 72 - (ngradeletters[bestgrade]->width/4) - 1, + 48+lsheadingheight/2 - 1, 0, ngradeletters[bestgrade]); } @@ -6090,7 +6093,7 @@ void M_DrawNightsAttackMenu(void) // ALWAYS DRAW level even when not on this menu! if (currentMenu != &SP_NightsAttackDef) - V_DrawString(SP_TimeAttackDef.x, SP_TimeAttackDef.y + SP_TimeAttackMenu[nalevelback].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[nalevelback].text); + V_DrawString(SP_NightsAttackDef.x, SP_NightsAttackDef.y + SP_TimeAttackMenu[nalevelback].alphaKey, V_TRANSLUCENT, SP_NightsAttackMenu[nalevelback].text); } static void M_NightsAttackLevelSelect(INT32 choice) From f56f76692c0c4b5639b44be2e596d9617472db36 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 30 Jan 2017 20:55:31 +0000 Subject: [PATCH 10/29] Put size of BEST GRADE back to 2.1 levels. To make space for it, I left-aligned * LEVEL RECORDS *. http://imgur.com/a/3i7GT --- src/m_menu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 40a729906..705882659 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5839,7 +5839,7 @@ void M_DrawTimeAttackMenu(void) V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); - V_DrawCenteredString(104, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); + V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) sprintf(beststr, "(none)"); @@ -6035,16 +6035,16 @@ void M_DrawNightsAttackMenu(void) V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); - V_DrawCenteredString(104, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); + V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); if (P_HasGrades(cv_nextmap.value, 0)) V_DrawScaledPatch(235, 135, 0, ngradeletters[bestoverall]); if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) - { + {//make bigger again V_DrawString(104 - 72, 48+lsheadingheight/2, V_YELLOWMAP, "BEST GRADE:"); - V_DrawTinyScaledPatch(104 + 72 - (ngradeletters[bestgrade]->width/4) - 1, - 48+lsheadingheight/2 - 1, + V_DrawSmallScaledPatch(104 + 72 - (ngradeletters[bestgrade]->width/2), + 48+lsheadingheight/2 + 8 - (ngradeletters[bestgrade]->height/2), 0, ngradeletters[bestgrade]); } From b5fef5f46a57eb70fe37e3bdd34f30120fb3373c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 31 Jan 2017 11:04:50 +0000 Subject: [PATCH 11/29] Forgot to vertically align collected emblems on nights page --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 705882659..1322d93b5 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6080,7 +6080,7 @@ void M_DrawNightsAttackMenu(void) } if (em->collected) - V_DrawSmallMappedPatch(104+76, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), + V_DrawSmallMappedPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); From 3cb2f178c6d89d2312623b5d194d2b0e7b5c2189 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 31 Jan 2017 18:48:50 +0000 Subject: [PATCH 12/29] Getting closer to done. Updated the mid-game gametype/level select menu! Just need to combine it with the server creation menu, and then I'll be ready to make a merge request... --- src/doomstat.h | 2 +- src/m_menu.c | 97 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 80 insertions(+), 19 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 391f57a14..801e79edd 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -313,7 +313,7 @@ enum GameType NUMGAMETYPES }; -// If you alter this list, update gametype_cons_t in m_menu.c +// If you alter this list, update dehacked.c, and gametype_cons_t and MISC_ChangeGameTypeMenu in m_menu.c extern tic_t totalplaytime; diff --git a/src/m_menu.c b/src/m_menu.c index 1322d93b5..90b5d4901 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -242,6 +242,7 @@ static void M_Options(INT32 choice); static void M_SelectableClearMenus(INT32 choice); static void M_Retry(INT32 choice); static void M_EndGame(INT32 choice); +static void M_GameTypeChange(INT32 choice); static void M_MapChange(INT32 choice); static void M_ChangeLevel(INT32 choice); static void M_ConfirmSpectate(INT32 choice); @@ -328,6 +329,7 @@ static void M_DrawSkyRoom(void); static void M_DrawChecklist(void); static void M_DrawEmblemHints(void); static void M_DrawPauseMenu(void); +static void M_DrawGameTypeMenu(void); static void M_DrawServerMenu(void); static void M_DrawLevelPlatterMenu(void); static void M_DrawImageDef(void); @@ -392,7 +394,7 @@ static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}}; consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL}; // This gametype list is integral for many different reasons. -// When you add gametypes here, don't forget to update them in CV_AddValue! +// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! CV_PossibleValue_t gametype_cons_t[] = { {GT_COOP, "Co-op"}, @@ -505,7 +507,7 @@ typedef enum static menuitem_t MPauseMenu[] = { {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, - {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24}, + {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_GameTypeChange, 24}, {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40}, {IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen @@ -586,11 +588,25 @@ static menuitem_t MISC_ChangeTeamMenu[] = {IT_WHITESTRING|IT_CALL, NULL, "Confirm", M_ConfirmTeamChange, 90}, }; +static menuitem_t MISC_ChangeGameTypeMenu[] = +{ + {IT_STRING|IT_CALL, NULL, "Co-op", M_MapChange, 0}, + + {IT_STRING|IT_CALL, NULL, "Competition", M_MapChange, 12}, + {IT_STRING|IT_CALL, NULL, "Race", M_MapChange, 20}, + + {IT_STRING|IT_CALL, NULL, "Match", M_MapChange, 32}, + {IT_STRING|IT_CALL, NULL, "Team Match", M_MapChange, 40}, + + {IT_STRING|IT_CALL, NULL, "Tag", M_MapChange, 52}, + {IT_STRING|IT_CALL, NULL, "Hide and Seek", M_MapChange, 60}, + + {IT_STRING|IT_CALL, NULL, "Capture the Flag", M_MapChange, 72}, +}; + static menuitem_t MISC_ChangeLevelMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 30}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - {IT_WHITESTRING|IT_CALL, NULL, "Change Level", M_ChangeLevel, 120}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, 0}, // dummy menuitem for the control func }; static menuitem_t MISC_HelpMenu[] = @@ -664,7 +680,7 @@ static menuitem_t SR_MainMenu[] = static menuitem_t SR_LevelSelectMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, 0}, // dummy menuitem for the control func }; static menuitem_t SR_UnlockChecklistMenu[] = @@ -703,19 +719,19 @@ enum // Single Player Load Game static menuitem_t SP_LoadGameMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLoadSave, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLoadSave, 0}, // dummy menuitem for the control func }; // Single Player Level Select static menuitem_t SP_LevelSelectMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, 0}, // dummy menuitem for the control func }; // Single Player Time Attack Level Select static menuitem_t SP_TimeAttackLevelSelectMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, 0}, // dummy menuitem for the control func }; // Single Player Time Attack @@ -813,7 +829,7 @@ static menuitem_t SP_NightsGhostMenu[] = // Single Player Nights Attack Level Select static menuitem_t SP_NightsAttackLevelSelectMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, 0}, // dummy menuitem for the control func }; // Single Player Nights Attack @@ -842,12 +858,12 @@ enum // Statistics static menuitem_t SP_GameStatsMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleGameStats, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleGameStats, 0}, // dummy menuitem for the control func }; static menuitem_t SP_LevelStatsMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelStats, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelStats, 0}, // dummy menuitem for the control func }; // A rare case. @@ -1199,7 +1215,7 @@ static menuitem_t OP_VideoOptionsMenu[] = static menuitem_t OP_VideoModeMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleVideoMode, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleVideoMode, 0}, // dummy menuitem for the control func }; #ifdef HWRENDER @@ -1432,7 +1448,31 @@ menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); // Misc Main Menu menu_t MISC_ScrambleTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ScrambleTeamMenu, &MPauseDef, 27, 40); menu_t MISC_ChangeTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ChangeTeamMenu, &MPauseDef, 27, 40); -menu_t MISC_ChangeLevelDef = MAPICONMENUSTYLE(NULL, MISC_ChangeLevelMenu, &MPauseDef); + +// MP Gametype and map change menu +menu_t MISC_ChangeGameTypeDef = +{ + NULL, + sizeof (MISC_ChangeGameTypeMenu)/sizeof (menuitem_t), + &MainDef, // Doesn't matter. + MISC_ChangeGameTypeMenu, + M_DrawGameTypeMenu, + 30, 104 - ((80 - lsheadingheight/2)/2), // vertically centering + 0, + NULL +}; +menu_t MISC_ChangeLevelDef = +{ + NULL, + sizeof (MISC_ChangeLevelMenu)/sizeof (menuitem_t), + &MISC_ChangeGameTypeDef, + MISC_ChangeLevelMenu, + M_DrawLevelPlatterMenu, + 0, 0, + 0, + NULL +}; + menu_t MISC_HelpDef = IMAGEDEF(MISC_HelpMenu); // Sky Room @@ -3885,6 +3925,8 @@ static void M_HandleLevelPlatter(INT32 choice) else M_NightsAttack(-1); } + else if (currentMenu == &MISC_ChangeLevelDef) + M_ChangeLevel(0); else M_LevelSelectWarp(0); } @@ -6845,16 +6887,35 @@ static void M_DrawServerMenu(void) V_DrawSmallScaledPatch((BASEVIDWIDTH*3/4)-(SHORT(PictureOfLevel->width)/4), ((BASEVIDHEIGHT*3/4)-(SHORT(PictureOfLevel->height)/4)+10), 0, PictureOfLevel); } -static void M_MapChange(INT32 choice) +static void M_GameTypeChange(INT32 choice) { (void)choice; + MISC_ChangeGameTypeDef.prevMenu = currentMenu; + M_SetupNextMenu(&MISC_ChangeGameTypeDef); + itemOn = gametype; +} + +// Drawing function for Nights Attack +void M_DrawGameTypeMenu(void) +{ + M_DrawGenericMenu(); + M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight, "SELECT GAMETYPE", true); +} + +static void M_MapChange(INT32 choice) +{ + MISC_ChangeLevelDef.prevMenu = currentMenu; levellistmode = LLM_CREATESERVER; - CV_SetValue(&cv_newgametype, gametype); - CV_SetValue(&cv_nextmap, gamemap); + CV_SetValue(&cv_newgametype, choice); + + if (!M_PrepareLevelPlatter(choice)) + { + M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); + return; + } - M_PrepareLevelSelect(); M_SetupNextMenu(&MISC_ChangeLevelDef); } From 873e768a446d6cb73a272c078e7dccbd37ea5803 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 31 Jan 2017 23:56:09 +0000 Subject: [PATCH 13/29] Server page (and splitscreen server page) started. http://i.imgur.com/jJ3YZUd.png Will be discussing what to do with the space freed under "server options" the heading on IRC tomorrow. (MI, if you're looking - the mistake was that I set up an IT_CALL menu line as IT_CVAR by mistake, which of course caused a crash when trying to get ((consvar_t *)M_GameTypeChange)->string. ;P ) --- src/m_menu.c | 139 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 51 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 90b5d4901..fc2b894fe 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -406,7 +406,7 @@ CV_PossibleValue_t gametype_cons_t[] = {GT_TEAMMATCH, "Team Match"}, {GT_TAG, "Tag"}, - {GT_HIDEANDSEEK, "Hide and Seek"}, + {GT_HIDEANDSEEK, "Hide & Seek"}, {GT_CTF, "CTF"}, {0, NULL} @@ -506,21 +506,21 @@ typedef enum // --------------------- static menuitem_t MPauseMenu[] = { - {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, - {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_GameTypeChange, 24}, + {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, + {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 24}, - {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40}, - {IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen - {IT_CALL | IT_STRING, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen + {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40}, + {IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen + {IT_CALL | IT_STRING, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen - {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48}, - {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48}, - {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48}, - {IT_CALL | IT_STRING, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone - {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64}, + {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48}, + {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48}, + {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48}, + {IT_CALL | IT_STRING, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone + {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64}, - {IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80}, - {IT_CALL | IT_STRING, NULL, "Quit Game", M_QuitSRB2, 88}, + {IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80}, + {IT_CALL | IT_STRING, NULL, "Quit Game", M_QuitSRB2, 88}, }; typedef enum @@ -599,7 +599,7 @@ static menuitem_t MISC_ChangeGameTypeMenu[] = {IT_STRING|IT_CALL, NULL, "Team Match", M_MapChange, 40}, {IT_STRING|IT_CALL, NULL, "Tag", M_MapChange, 52}, - {IT_STRING|IT_CALL, NULL, "Hide and Seek", M_MapChange, 60}, + {IT_STRING|IT_CALL, NULL, "Hide & Seek", M_MapChange, 60}, {IT_STRING|IT_CALL, NULL, "Capture the Flag", M_MapChange, 72}, }; @@ -924,28 +924,33 @@ static menuitem_t MP_MainMenu[] = static menuitem_t MP_ServerMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 10}, + {IT_DISABLED|IT_NOTHING, NULL, "", NULL, 0}, #ifndef NONET - {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 20}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 30}, + {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, #endif - - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 80}, - - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, + {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 90}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, }; enum { - mp_server_gametype = 0, + mp_server_dummy = 0, // exists solely so numbering is consistent between NONET and not NONET #ifndef NONET mp_server_room, mp_server_name, #endif - mp_server_level, + mp_server_levelgt, mp_server_start }; +// Separated splitscreen and normal servers. +static menuitem_t MP_SplitServerMenu[] = +{ + {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 90}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, +}; + #ifndef NONET static menuitem_t MP_ConnectMenu[] = { @@ -1004,14 +1009,6 @@ static menuitem_t MP_ConnectIPMenu[] = }; #endif -// Separated splitscreen and normal servers. -static menuitem_t MP_SplitServerMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 10}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 80}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, -}; - static menuitem_t MP_PlayerSetupMenu[] = { {IT_KEYHANDLER | IT_STRING, NULL, "Your name", M_HandleSetupMultiPlayer, 0}, @@ -1708,7 +1705,31 @@ menu_t SP_PlayerDef = // Multiplayer menu_t MP_MainDef = DEFAULTMENUSTYLE("M_MULTI", MP_MainMenu, &MainDef, 60, 40); -menu_t MP_ServerDef = MAPICONMENUSTYLE("M_MULTI", MP_ServerMenu, &MP_MainDef); + +menu_t MP_ServerDef = +{ + "M_MULTI", + sizeof (MP_ServerMenu)/sizeof (menuitem_t), + &MP_MainDef, + MP_ServerMenu, + M_DrawServerMenu, + 27, 40, + 0, + NULL +}; + +menu_t MP_SplitServerDef = +{ + "M_MULTI", + sizeof (MP_SplitServerMenu)/sizeof (menuitem_t), + &MP_MainDef, + MP_SplitServerMenu, + M_DrawServerMenu, + 27, 40, + 0, + NULL +}; + #ifndef NONET menu_t MP_ConnectDef = { @@ -1744,7 +1765,7 @@ menu_t MP_RoomDef = NULL }; #endif -menu_t MP_SplitServerDef = MAPICONMENUSTYLE("M_MULTI", MP_SplitServerMenu, &MP_MainDef); + menu_t MP_PlayerSetupDef = { "M_SPLAYR", @@ -3926,7 +3947,12 @@ static void M_HandleLevelPlatter(INT32 choice) M_NightsAttack(-1); } else if (currentMenu == &MISC_ChangeLevelDef) - M_ChangeLevel(0); + { + if (currentMenu->prevMenu && currentMenu->prevMenu->prevMenu != &MPauseDef) + M_SetupNextMenu(currentMenu->prevMenu->prevMenu); + else + M_ChangeLevel(0); + } else M_LevelSelectWarp(0); } @@ -3956,7 +3982,7 @@ static void M_HandleLevelPlatter(INT32 choice) D_StartTitle(); } else - M_SetupNextMenu (currentMenu->prevMenu); + M_SetupNextMenu(currentMenu->prevMenu); } else M_ClearMenus(true); @@ -6858,11 +6884,10 @@ static void M_StartServer(INT32 choice) static void M_DrawServerMenu(void) { - lumpnum_t lumpnum; - patch_t *PictureOfLevel; - M_DrawGenericMenu(); + M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true); + #ifndef NONET // Room name if (currentMenu == &MP_ServerDef) @@ -6876,15 +6901,26 @@ static void M_DrawServerMenu(void) } #endif - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + if (cv_nextmap.value) + { + patch_t *PictureOfLevel; + lumpnum_t lumpnum; + char headerstr[40]; - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + sprintf(headerstr, "%s - %s", cv_newgametype.string, cv_nextmap.string); - V_DrawSmallScaledPatch((BASEVIDWIDTH*3/4)-(SHORT(PictureOfLevel->width)/4), ((BASEVIDHEIGHT*3/4)-(SHORT(PictureOfLevel->height)/4)+10), 0, PictureOfLevel); + M_DrawLevelPlatterHeader(currentMenu->y + 80 - lsheadingheight/2, (const char *)headerstr, true); + + // A 160x100 image of the level as entry MAPxxP + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + 90, 0, PictureOfLevel); + } } static void M_GameTypeChange(INT32 choice) @@ -6893,14 +6929,14 @@ static void M_GameTypeChange(INT32 choice) MISC_ChangeGameTypeDef.prevMenu = currentMenu; M_SetupNextMenu(&MISC_ChangeGameTypeDef); - itemOn = gametype; + if (Playing()) + itemOn = gametype; } -// Drawing function for Nights Attack void M_DrawGameTypeMenu(void) { M_DrawGenericMenu(); - M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight, "SELECT GAMETYPE", true); + M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight, "Select Gametype", true); } static void M_MapChange(INT32 choice) @@ -6923,7 +6959,7 @@ static void M_StartSplitServerMenu(INT32 choice) { (void)choice; levellistmode = LLM_CREATESERVER; - M_PrepareLevelSelect(); + Newgametype_OnChange(); M_SetupNextMenu(&MP_SplitServerDef); } @@ -6931,10 +6967,11 @@ static void M_StartSplitServerMenu(INT32 choice) static void M_StartServerMenu(INT32 choice) { (void)choice; - levellistmode = LLM_CREATESERVER; - M_PrepareLevelSelect(); ms_RoomId = -1; + levellistmode = LLM_CREATESERVER; + Newgametype_OnChange(); M_SetupNextMenu(&MP_ServerDef); + itemOn = 1; } From 4efeb029783006b3841f5ed4455561a76ed863aa Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 1 Feb 2017 17:21:04 +0000 Subject: [PATCH 14/29] Added some useful options to the Server setup menu, including a jump-link to the relevant Options screen. Think it should be a little smarter designed, though, but I'd rather commit what I have then let it languish. --- src/m_menu.c | 52 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index fc2b894fe..bfc6b15b0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -281,6 +281,7 @@ static void M_ConnectIPMenu(INT32 choice); #endif static void M_StartSplitServerMenu(INT32 choice); static void M_StartServer(INT32 choice); +static void M_ServerOptions(INT32 choice); #ifndef NONET static void M_Refresh(INT32 choice); static void M_Connect(INT32 choice); @@ -926,29 +927,36 @@ static menuitem_t MP_ServerMenu[] = { {IT_DISABLED|IT_NOTHING, NULL, "", NULL, 0}, #ifndef NONET - {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, + {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, + {IT_STRING|IT_CVAR, NULL, "Max Players", &cv_maxplayers, 46}, + {IT_STRING|IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 56}, #endif - {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 90}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, + {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 100}, + {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140}, }; enum { - mp_server_dummy = 0, // exists solely so numbering is consistent between NONET and not NONET + mp_server_dummy = 0, // exists solely so zero-indexed in both NONET and not NONET #ifndef NONET mp_server_room, mp_server_name, + mp_server_maxpl, + mp_server_waddl, #endif mp_server_levelgt, + mp_server_options, mp_server_start }; // Separated splitscreen and normal servers. static menuitem_t MP_SplitServerMenu[] = { - {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 90}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, + {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 100}, + {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140}, }; #ifndef NONET @@ -1022,14 +1030,14 @@ static menuitem_t MP_PlayerSetupMenu[] = // Prefix: OP_ static menuitem_t OP_MainMenu[] = { - {IT_SUBMENU | IT_STRING, NULL, "Setup Controls...", &OP_ControlsDef, 10}, + {IT_SUBMENU | IT_STRING, NULL, "Setup Controls...", &OP_ControlsDef, 10}, - {IT_SUBMENU | IT_STRING, NULL, "Video Options...", &OP_VideoOptionsDef, 30}, - {IT_SUBMENU | IT_STRING, NULL, "Sound Options...", &OP_SoundOptionsDef, 40}, - {IT_SUBMENU | IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 50}, + {IT_SUBMENU | IT_STRING, NULL, "Video Options...", &OP_VideoOptionsDef, 30}, + {IT_SUBMENU | IT_STRING, NULL, "Sound Options...", &OP_SoundOptionsDef, 40}, + {IT_SUBMENU | IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 50}, - {IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70}, - {IT_SUBMENU | IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 80}, + {IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70}, + {IT_CALL | IT_STRING, NULL, "Server Options...", M_ServerOptions, 80}, }; static menuitem_t OP_ControlsMenu[] = @@ -1713,7 +1721,7 @@ menu_t MP_ServerDef = &MP_MainDef, MP_ServerMenu, M_DrawServerMenu, - 27, 40, + 27, 30, 0, NULL }; @@ -1725,7 +1733,7 @@ menu_t MP_SplitServerDef = &MP_MainDef, MP_SplitServerMenu, M_DrawServerMenu, - 27, 40, + 27, 30, 0, NULL }; @@ -4507,7 +4515,7 @@ static void M_Options(INT32 choice) (void)choice; // if the player is not admin or server, disable server options - OP_MainMenu[5].status = (Playing() && !(server || adminplayer == consoleplayer)) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + OP_MainMenu[5].status = (Playing() && !(server || adminplayer == consoleplayer)) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); // if the player is playing _at all_, disable the erase data options OP_DataOptionsMenu[1].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); @@ -6909,7 +6917,7 @@ static void M_DrawServerMenu(void) sprintf(headerstr, "%s - %s", cv_newgametype.string, cv_nextmap.string); - M_DrawLevelPlatterHeader(currentMenu->y + 80 - lsheadingheight/2, (const char *)headerstr, true); + M_DrawLevelPlatterHeader(currentMenu->y + MP_ServerMenu[mp_server_levelgt].alphaKey - 10 - lsheadingheight/2, (const char *)headerstr, true); // A 160x100 image of the level as entry MAPxxP lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); @@ -6919,7 +6927,7 @@ static void M_DrawServerMenu(void) else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + 90, 0, PictureOfLevel); + V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + MP_ServerMenu[mp_server_levelgt].alphaKey, 0, PictureOfLevel); } } @@ -6963,6 +6971,14 @@ static void M_StartSplitServerMenu(INT32 choice) M_SetupNextMenu(&MP_SplitServerDef); } +static void M_ServerOptions(INT32 choice) +{ + (void)choice; + + OP_ServerOptionsDef.prevMenu = currentMenu; + M_SetupNextMenu(&OP_ServerOptionsDef); +} + #ifndef NONET static void M_StartServerMenu(INT32 choice) { From 8ebb4a3c3f3c3a69b3366641ee055b07c0dc660a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 1 Feb 2017 17:36:19 +0000 Subject: [PATCH 15/29] Making things nicer for the server creation menus of 2P mode and NONET executables. --- src/m_menu.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index bfc6b15b0..03f97d750 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1721,7 +1721,11 @@ menu_t MP_ServerDef = &MP_MainDef, MP_ServerMenu, M_DrawServerMenu, - 27, 30, + 27, 30 +#ifdef NONET + - 50 +#endif + , 0, NULL }; @@ -1733,7 +1737,7 @@ menu_t MP_SplitServerDef = &MP_MainDef, MP_SplitServerMenu, M_DrawServerMenu, - 27, 30, + 27, 30 - 50, 0, NULL }; @@ -6894,12 +6898,11 @@ static void M_DrawServerMenu(void) { M_DrawGenericMenu(); - M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true); - #ifndef NONET // Room name if (currentMenu == &MP_ServerDef) { + M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true); if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, V_YELLOWMAP, (itemOn == mp_server_room) ? "