diff --git a/src/d_main.c b/src/d_main.c index c69850aa8..87057a22f 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -939,14 +939,16 @@ void D_StartTitle(void) if (netgame) { - if (gametyperules & GTR_CAMPAIGN) - { - G_SetGamestate(GS_WAITINGPLAYERS); // hack to prevent a command repeat + G_SetGamestate(GS_WAITINGPLAYERS); // hack to prevent a command repeat - if (server) - { - COM_BufAddText(va("map %s\n", G_BuildMapName(spstage_start))); - } + if (server) + { + INT16 mapnum = G_GetFirstMapOfGametype(gametype)+1; + + if (i > nummapheaders) + I_Error("D_StartTitle: No valid map ID found!?"); + + COM_BufAddText(va("map %s\n", G_BuildMapName(mapnum))); } return; diff --git a/src/deh_lua.c b/src/deh_lua.c index 8e6e88360..9c407dbda 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -475,18 +475,6 @@ static inline int lib_getenum(lua_State *L) } return luaL_error(L, "skincolor '%s' could not be found.\n", word); } - else if (fastncmp("GRADE_",word,6)) - { - p = word+6; - for (i = 0; NIGHTSGRADE_LIST[i]; i++) - if (*p == NIGHTSGRADE_LIST[i]) - { - lua_pushinteger(L, i); - return 1; - } - if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word); - return 0; - } else if (fastncmp("PRECIP_",word,7)) { p = word+7; for (i = 0; i < MAXPRECIP; i++) diff --git a/src/deh_soc.c b/src/deh_soc.c index 596926287..103579cb1 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -157,12 +157,9 @@ void clear_levels(void) Z_Free(mapheaderinfo[nummapheaders]->customopts); P_DeleteFlickies(nummapheaders); - P_DeleteGrades(nummapheaders); Patch_Free(mapheaderinfo[nummapheaders]->thumbnailPic); Patch_Free(mapheaderinfo[nummapheaders]->minimapPic); - Z_Free(mapheaderinfo[nummapheaders]->nextlevel); - Z_Free(mapheaderinfo[nummapheaders]->marathonnext); Z_Free(mapheaderinfo[nummapheaders]->lumpname); @@ -1155,7 +1152,6 @@ void readlevelheader(MYFILE *f, char * name) { deh_strlcpy(mapheaderinfo[num]->lvlttl, word2, sizeof(mapheaderinfo[num]->lvlttl), va("Level header %d: levelname", num)); - strlcpy(mapheaderinfo[num]->selectheading, word2, sizeof(mapheaderinfo[num]->selectheading)); // not deh_ so only complains once continue; } // CHEAP HACK: move this over here for lowercase subtitles @@ -1283,14 +1279,6 @@ void readlevelheader(MYFILE *f, char * name) } // Strings that can be truncated - else if (fastcmp(word, "NEXTLEVEL")) - { - mapheaderinfo[num]->nextlevel = Z_StrDup(word2); - } - else if (fastcmp(word, "MARATHONNEXT")) - { - mapheaderinfo[num]->marathonnext = Z_StrDup(word2); - } else if (fastcmp(word, "ZONETITLE")) { deh_strlcpy(mapheaderinfo[num]->zonttl, word2, @@ -1459,12 +1447,12 @@ void readlevelheader(MYFILE *f, char * name) else mapheaderinfo[num]->menuflags &= ~LF2_HIDEINSTATS; } - else if (fastcmp(word, "TIMEATTACK") || fastcmp(word, "RECORDATTACK")) + else if (fastcmp(word, "NOTIMEATTACK") || fastcmp(word, "NORECORDATTACK")) { // RECORDATTACK is an accepted alias if (i || word2[0] == 'T' || word2[0] == 'Y') - mapheaderinfo[num]->menuflags &= ~LF2_NOTIMEATTACK; - else mapheaderinfo[num]->menuflags |= LF2_NOTIMEATTACK; + else + mapheaderinfo[num]->menuflags &= ~LF2_NOTIMEATTACK; } else if (fastcmp(word, "VISITNEEDED")) { @@ -4060,19 +4048,6 @@ static fixed_t find_const(const char **rword) free(word); return 0; } - else if (fastncmp("GRADE_",word,6)) - { - char *p = word+6; - for (i = 0; NIGHTSGRADE_LIST[i]; i++) - if (*p == NIGHTSGRADE_LIST[i]) - { - free(word); - return i; - } - const_warning("NiGHTS grade",word); - free(word); - return 0; - } for (i = 0; INT_CONST[i].n; i++) if (fastcmp(word,INT_CONST[i].n)) { free(word); diff --git a/src/deh_tables.c b/src/deh_tables.c index 5fe950e9e..dc8c29e29 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -32,17 +32,6 @@ char *FREE_MOBJS[NUMMOBJFREESLOTS]; char *FREE_SKINCOLORS[NUMCOLORFREESLOTS]; UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway. -const char NIGHTSGRADE_LIST[] = { - 'F', // GRADE_F - 'E', // GRADE_E - 'D', // GRADE_D - 'C', // GRADE_C - 'B', // GRADE_B - 'A', // GRADE_A - 'S', // GRADE_S - '\0' -}; - struct flickytypes_s FLICKYTYPES[] = { {"BLUEBIRD", MT_FLICKY_01}, // Flicky (Flicky) {"RABBIT", MT_FLICKY_02}, // Pocky (1) diff --git a/src/deh_tables.h b/src/deh_tables.h index 294e6452a..05fb38d67 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -53,7 +53,6 @@ struct int_const_s { lua_Integer v; }; -extern const char NIGHTSGRADE_LIST[]; extern struct flickytypes_s FLICKYTYPES[]; extern actionpointer_t actionpointers[]; // Array mapping action names to action functions. extern const char *const STATE_LIST[]; diff --git a/src/doomstat.h b/src/doomstat.h index f99797abc..b47f9a4d2 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -322,12 +322,6 @@ extern struct quake fixed_t radius, intensity; } quake; -// NiGHTS grades -typedef struct -{ - UINT32 grade[6]; // D, C, B, A, S, X (F: failed to reach any of these) -} nightsgrades_t; - // Custom Lua values // (This is not ifdeffed so the map header structure can stay identical, just in case.) typedef struct @@ -355,9 +349,6 @@ typedef struct UINT32 typeoflevel; ///< Combination of typeoflevel flags. - char * nextlevel; ///< Map name of next level. - char * marathonnext; ///< See nextlevel, but for Marathon mode. - char keywords[33]; ///< Keywords separated by space to search for. 32 characters. char musname[7]; ///< Music track to play. "" for no music. @@ -391,46 +382,22 @@ typedef struct SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? - SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) - SINT8 maxbonuslives; ///< How many bonus lives to award at Intermission? (-1 for unlimited.) - UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below UINT16 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus - char selectheading[22]; ///< Level select heading. Allows for controllable grouping. UINT16 startrings; ///< Number of rings players start with. INT32 sstimer; ///< Timer for special stages. UINT32 ssspheres; ///< Sphere requirement in special stages. fixed_t gravity; ///< Map-wide gravity. - // Title card. - char ltzzpatch[8]; ///< Zig zag patch. - char ltzztext[8]; ///< Zig zag text. - char ltactdiamond[8]; ///< Act diamond. - // 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. - // NiGHTS stuff. - UINT8 numGradedMares; ///< Internal. For grade support. - nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. - UINT8 light_contrast; ///< Range of wall lighting. 0 is no lighting. boolean use_light_angle; ///< When false, wall lighting is evenly distributed. When true, wall lighting is directional. angle_t light_angle; ///< Angle of directional wall lighting. - // Music stuff. - UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds - char musintername[7]; ///< Intermission screen music. - - char muspostbossname[7]; ///< Post-bossdeath music. - UINT16 muspostbosstrack; ///< Post-bossdeath track. - UINT32 muspostbosspos; ///< Post-bossdeath position - UINT32 muspostbossfadein; ///< Post-bossdeath fade-in milliseconds. - - SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on) - // SRB2kart fixed_t mobj_scale; ///< Replacement for TOL_ERZ3 fixed_t default_waypoint_radius; ///< 0 is a special value for DEFAULT_WAYPOINT_RADIUS, but scaled with mobjscale @@ -606,26 +573,6 @@ typedef struct //UINT16 rings; ///< Rings when the level was finished. } recorddata_t; -/** Setup for one NiGHTS map. - * These are dynamically allocated because I am insane - */ -#define GRADE_F 0 -#define GRADE_E 1 -#define GRADE_D 2 -#define GRADE_C 3 -#define GRADE_B 4 -#define GRADE_A 5 -#define GRADE_S 6 - -/*typedef struct -{ - // 8 mares, 1 overall (0) - UINT8 nummares; - UINT32 score[9]; - UINT8 grade[9]; - tic_t time[9]; -} nightsdata_t;*/ - //extern nightsdata_t *nightsrecords[NUMMAPS]; extern recorddata_t *mainrecords[NUMMAPS]; diff --git a/src/f_finale.c b/src/f_finale.c index 3a77e3ec5..05457f5dd 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2416,7 +2416,7 @@ void F_EndCutScene(void) F_StartGameEvaluation(); else if (cutnum == introtoplay-1) D_StartTitle(); - else if (nextmap < 1100-1) + else if (nextmap < NEXTMAP_SPECIAL) G_NextLevel(); else G_EndGame(); diff --git a/src/g_game.c b/src/g_game.c index fbfc3512a..027a96011 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -663,7 +663,9 @@ const char *G_BuildMapName(INT32 map) */ INT32 G_MapNumber(const char * name) { +#ifdef NEXTMAPINSOC if (strncasecmp("NEXTMAP_", name, 8) != 0) +#endif { INT32 map; @@ -678,6 +680,7 @@ INT32 G_MapNumber(const char * name) return map; } +#ifdef NEXTMAPINSOC name += 8; if (strcasecmp("EVALUATION", name) == 0) @@ -688,6 +691,7 @@ INT32 G_MapNumber(const char * name) return NEXTMAP_CEREMONY; //if (strcasecmp("TITLE", name) == 0) return NEXTMAP_TITLE; +#endif } /** Clips the console player's mouse aiming to the current view. @@ -2994,7 +2998,7 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Race - GTR_CIRCUIT|GTR_BOTS, + GTR_CAMPAIGN|GTR_CIRCUIT|GTR_BOTS, // Battle GTR_SPHERES|GTR_BUMPERS|GTR_PAPERITEMS|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME }; @@ -3378,20 +3382,54 @@ UINT32 G_TOLFlag(INT32 pgametype) return gametypetol[pgametype]; } -static INT32 TOLMaps(UINT32 tolflags) +INT16 G_GetFirstMapOfGametype(UINT8 pgametype) +{ + INT16 mapnum = nummapheaders; + + if ((gametypedefaultrules[pgametype] & GTR_CAMPAIGN) && kartcupheaders) + { + mapnum = G_MapNumber(kartcupheaders->levellist[0]); + } + + if (mapnum >= nummapheaders) + { + UINT32 tolflag = G_TOLFlag(pgametype); + for (mapnum = 0; mapnum < nummapheaders; mapnum++) + { + if (!mapheaderinfo[mapnum]) + continue; + if (mapheaderinfo[mapnum]->lumpnum == LUMPERROR) + continue; + if (!(mapheaderinfo[mapnum]->typeoflevel & tolflag)) + continue; + if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) + continue; + break; + } + } + + return mapnum; +} + +static INT32 TOLMaps(UINT8 pgametype) { INT32 num = 0; INT32 i; - // Find all the maps that are ok and and put them in an array. + UINT32 tolflag = G_TOLFlag(pgametype); + + // Find all the maps that are ok for (i = 0; i < nummapheaders; i++) { if (!mapheaderinfo[i]) continue; + if (mapheaderinfo[i]->lumpnum == LUMPERROR) + continue; + if (!(mapheaderinfo[i]->typeoflevel & tolflag)) + continue; if (mapheaderinfo[i]->menuflags & LF2_HIDEINMENU) // Don't include Map Hell continue; - if ((mapheaderinfo[i]->typeoflevel & tolflags) == tolflags) - num++; + num++; } return num; @@ -3546,7 +3584,7 @@ tryagain: void G_AddMapToBuffer(INT16 map) { INT16 bufx; - INT16 refreshnum = (TOLMaps(G_TOLFlag(gametype)))-3; + INT16 refreshnum = (TOLMaps(gametype))-3; if (refreshnum < 0) refreshnum = 3; @@ -3612,7 +3650,7 @@ static boolean CanSaveLevel(INT32 mapnum) static void G_HandleSaveLevel(void) { // do this before running the intermission or custom cutscene, mostly for the sake of marathon mode but it also massively reduces redundant file save events in f_finale.c - if (nextmap >= 1100-1) + if (nextmap >= NEXTMAP_SPECIAL) { if (!gamecomplete) gamecomplete = 2; // special temporary mode to prevent using SP level select in pause menu until the intermission is over without restricting it in every intermission @@ -3635,6 +3673,167 @@ static void G_HandleSaveLevel(void) G_SaveGame((UINT32)cursaveslot, lastmap+1); // not nextmap+1 to route around special stages } +static void G_GetNextMap(void) +{ + INT32 i; + + // go to next level + // nextmap is 0-based, unlike gamemap + if (nextmapoverride != 0) + { + nextmap = (INT16)(nextmapoverride-1); + } + else if (grandprixinfo.gp == true) + { + if (grandprixinfo.roundnum == 0 || grandprixinfo.cup == NULL) // Single session + { + nextmap = prevmap; // Same map + } + else + { + if (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels) // On final map + { + nextmap = NEXTMAP_CEREMONY; // ceremonymap + } + else + { + // Proceed to next map + const INT32 cupLevelNum = G_MapNumber(grandprixinfo.cup->levellist[grandprixinfo.roundnum]); + + if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum]) + { + nextmap = cupLevelNum; + } + else + { + nextmap = prevmap; // Prevent uninitialised use + } + + grandprixinfo.roundnum++; + } + } + } + else if (bossinfo.boss == true) + { + nextmap = NEXTMAP_TITLE; // temporary + } + else + { + UINT32 tolflag = G_TOLFlag(gametype); + + if (gametyperules & GTR_CAMPAIGN) + { + register INT16 cm; + cupheader_t *cup = kartcupheaders; + UINT8 gettingresult = 0; + + // While this can't produce an infinite loop IN THE ITERATION, it + // is technically possible for you to keep cycling inside a lousy + // cul-de-sac of the same maps over and over while marathonning + // them all, if the same map is present in the cup list multiple + // times. There is no good solution. Don't dupe maps between cups! + while (cup) + { + for (i = 0; i < cup->numlevels; i++) + { + cm = G_MapNumber(cup->levellist[i]); + + // Not valid? + if (cm >= nummapheaders + || !mapheaderinfo[cm] + || mapheaderinfo[cm]->lumpnum == LUMPERROR + || !(mapheaderinfo[cm]->typeoflevel & tolflag)) + continue; + + // Grab the first valid after the map you're on + if (gettingresult) + { + nextmap = cm; + gettingresult = 2; + break; + } + + // Not the map you're on? + if (cm != prevmap) + { + continue; + } + + // Ok, this is the current map, time to get the next + gettingresult = 1; + } + + // We have a good nextmap? + if (gettingresult == 2) + { + break; + } + + // Ok, iterate to the next + cup = cup->next; + } + + // Didn't get a nextmap before reaching the end? + if (gettingresult != 2) + { + if (marathonmode) + { + nextmap = NEXTMAP_CEREMONY; // ceremonymap + } + else + { + nextmap = NEXTMAP_TITLE; + } + } + } + else + { + i = prevmap; + if (++i >= nummapheaders) + i = 0; + + while (i != prevmap) + { + if (!mapheaderinfo[i] + || mapheaderinfo[i]->lumpnum == LUMPERROR + || !(mapheaderinfo[i]->typeoflevel & tolflag) + || (mapheaderinfo[i]->menuflags & LF2_HIDEINMENU)) + { + if (++i >= nummapheaders) + i = 0; + continue; + } + + break; + } + + nextmap = i; + } + + if (!marathonmode) + { + if (cv_advancemap.value == 0) // Stay on same map. + { + nextmap = prevmap; + } + else if (cv_advancemap.value == 2) // Go to random map. + { + nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, 0, 0, false, NULL); + } + else if (nextmap >= NEXTMAP_SPECIAL) // Loop back around + { + nextmap = G_GetFirstMapOfGametype(gametype); + } + } + } + + // We are committed to this map now. + // We may as well allocate its header if it doesn't exist + // (That is, if it's a real map) + if (nextmap < NEXTMAP_SPECIAL && (nextmap >= nummapheaders || !mapheaderinfo[nextmap] || mapheaderinfo[nextmap]->lumpnum == LUMPERROR)) + I_Error("G_GetNextMap: Internal map ID %d not found (nummapheaders = %d)\n", nextmap, nummapheaders); +} + // // G_DoCompleted // @@ -3696,154 +3895,17 @@ static void G_DoCompleted(void) prevmap = (INT16)(gamemap-1); - if (demo.playback) goto demointermission; - - // go to next level - // nextmap is 0-based, unlike gamemap - if (nextmapoverride != 0) + if (!demo.playback) { - nextmap = (INT16)(nextmapoverride-1); + G_GetNextMap(); + + // Remember last map for when you come out of the special stage. + if (!spec) + lastmap = nextmap; + + // Set up power level gametype scrambles + K_SetPowerLevelScrambles(powertype); } - else if (marathonmode && mapheaderinfo[gamemap-1]->marathonnext) - { - const INT32 mNextNum = G_MapNumber(mapheaderinfo[gamemap-1]->marathonnext); - - if (mapheaderinfo[mNextNum]) - { - nextmap = (INT16)mNextNum; - } - } - else if (grandprixinfo.gp == true) - { - if (grandprixinfo.roundnum == 0 || grandprixinfo.cup == NULL) // Single session - { - nextmap = prevmap; // Same map - } - else - { - if (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels) // On final map - { - nextmap = NEXTMAP_CEREMONY; // ceremonymap - } - else - { - // Proceed to next map - const INT32 cupLevelNum = G_MapNumber(grandprixinfo.cup->levellist[grandprixinfo.roundnum]); - - if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum]) - { - nextmap = cupLevelNum; - } - else - { - nextmap = prevmap; // Prevent uninitialised use - } - - grandprixinfo.roundnum++; - } - } - } - else - { - const INT32 nextNum = G_MapNumber(mapheaderinfo[gamemap-1]->nextlevel); - - if (mapheaderinfo[nextNum]) - { - nextmap = (INT16)nextNum; - if (marathonmode && nextmap == spmarathon_start-1) - nextmap = NEXTMAP_TITLE; // No infinite loop for you - } - } - - // Remember last map for when you come out of the special stage. - if (!spec) - lastmap = nextmap; - - // If nextmap is actually going to get used, make sure it points to - // a map of the proper gametype -- skip levels that don't support - // the current gametype. (Helps avoid playing boss levels in Race, - // for instance). - if (K_CanChangeRules()) - { - if (cv_advancemap.value == 0) // Stay on same map. - { - nextmap = prevmap; - } - else if (cv_advancemap.value == 2) // Go to random map. - { - nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, 0, 0, false, NULL); - } - else if (nextmap < NEXTMAP_SPECIAL) - { - register INT16 cm = nextmap; - UINT32 tolflag = G_TOLFlag(gametype); - UINT8* visitedmap; - - visitedmap = Z_Calloc(((nummapheaders+7)/8)*sizeof(UINT8), PU_STATIC, NULL); - - while (!mapheaderinfo[cm] || mapheaderinfo[cm]->lumpnum == LUMPERROR || !(mapheaderinfo[cm]->typeoflevel & tolflag)) - { - visitedmap[cm/8] |= (1<<(cm&7)); - if (!mapheaderinfo[cm]) - cm = -1; // guarantee error execution - else if (marathonmode && mapheaderinfo[cm]->marathonnext) - { - cm = G_MapNumber(mapheaderinfo[cm]->marathonnext); - } - else - { - cm = G_MapNumber(mapheaderinfo[cm]->nextlevel); - } - - if (cm >= nummapheaders) // out of range (either NEXTMAP_SPECIAL or error) - { - cm = nextmap; //Start the loop again so that the error checking below is executed. - - //Make sure the map actually exists before you try to go to it! - if (cm >= nummapheaders || mapheaderinfo[cm]->lumpnum == LUMPERROR) - { - CONS_Alert(CONS_ERROR, M_GetText("Next map given (ID %d) doesn't exist! Reverting to id 0.\n"), cm+1); - cm = 0; - break; - } - } - - if (visitedmap[cm/8] & (1<<(cm&7))) // smells familiar - { - // We got stuck in a loop, came back to the map we started on - // without finding one supporting the current gametype. - // Thus, print a warning, and just use this map anyways. - CONS_Alert(CONS_WARNING, M_GetText("Can't find a compatible map after ID %d; using ID %d anyway\n"), prevmap, cm); - break; - } - } - Z_Free(visitedmap); - nextmap = cm; - } - // wrap around - else if (!(gametyperules & GTR_CAMPAIGN)) - nextmap = (INT16)(spstage_start-1); - - if (cv_advancemap.value == 0) // Stay on same map. - { - nextmap = prevmap; - } - else if (cv_advancemap.value == 2) // Go to random map. - { - nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, 0, 0, false, NULL); - } - } - - // We are committed to this map now. - // We may as well allocate its header if it doesn't exist - // (That is, if it's a real map) - if (nextmap < NEXTMAP_SPECIAL && (nextmap >= nummapheaders || !mapheaderinfo[nextmap] || mapheaderinfo[nextmap]->lumpnum == LUMPERROR)) - I_Error("G_DoCompleted: Internal map ID %d not found (nummapheaders = %d)\n", nextmap, nummapheaders); - - // Set up power level gametype scrambles - K_SetPowerLevelScrambles(powertype); - -demointermission: // If the current gametype has no intermission screen set, then don't start it. Y_DetermineIntermissionType(); @@ -3866,17 +3928,10 @@ demointermission: // See also F_EndCutscene, the only other place which handles intra-map/ending transitions void G_AfterIntermission(void) { - if (modeattacking) - { - M_EndModeAttackRun(); - return; - } - if (gamecomplete == 2) // special temporary mode to prevent using SP level select in pause menu until the intermission is over without restricting it in every intermission gamecomplete = 1; HU_ClearCEcho(); - //G_NextLevel(); if (demo.playback) { @@ -3900,8 +3955,8 @@ void G_AfterIntermission(void) return; } - if ((gametyperules & GTR_CAMPAIGN) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1 && (gamecomplete || !(marathonmode & MA_NOCUTSCENES))) // Start a custom cutscene. - F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); + if ((gametyperules & GTR_CAMPAIGN) && mapheaderinfo[prevmap]->cutscenenum && !modeattacking && skipstats <= 1 && (gamecomplete || !(marathonmode & MA_NOCUTSCENES))) // Start a custom cutscene. + F_StartCustomCutscene(mapheaderinfo[prevmap]->cutscenenum-1, false, false); else { if (nextmap < NEXTMAP_SPECIAL) @@ -4045,12 +4100,12 @@ void G_EndGame(void) if (demo.recording && (modeattacking || demo.savemode != DSM_NOTSAVING)) G_SaveDemo(); - // Only do evaluation and credits in coop games. - if (gametyperules & GTR_CAMPAIGN) + // Only do evaluation and credits in singleplayer contexts + if (!netgame && (gametyperules & GTR_CAMPAIGN)) { - if (nextmap == NEXTMAP_CEREMONY) // end game with ending + if (nextmap == NEXTMAP_CEREMONY) // end game with ceremony { - F_StartEnding(); + D_StartTitle(); //F_StartEnding(); -- temporary return; } if (nextmap == NEXTMAP_CREDITS) // end game with credits @@ -4065,7 +4120,7 @@ void G_EndGame(void) } } - // 1100 or competitive multiplayer, so go back to title screen. + // direct or competitive multiplayer, so go back to title screen. D_StartTitle(); } diff --git a/src/g_game.h b/src/g_game.h index 18ef96ad8..b0a0e7320 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -256,6 +256,7 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics); // Don't split up TOL handling UINT32 G_TOLFlag(INT32 pgametype); +INT16 G_GetFirstMapOfGametype(UINT8 pgametype); INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, UINT8 ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer); void G_AddMapToBuffer(INT16 map); diff --git a/src/k_menufunc.c b/src/k_menufunc.c index f930b1dfa..c119cfe7d 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -3178,6 +3178,8 @@ void M_SetupDifficultySelect(INT32 choice) // boolean M_CanShowLevelInList(INT16 mapnum, UINT8 gt) { + UINT32 tolflag = G_TOLFlag(gt); + // Does the map exist? if (!mapheaderinfo[mapnum]) return false; @@ -3186,21 +3188,26 @@ boolean M_CanShowLevelInList(INT16 mapnum, UINT8 gt) if (!mapheaderinfo[mapnum]->lvlttl[0]) return false; + // Does the map have a LUMP? + if (mapheaderinfo[mapnum]->lumpnum == LUMPERROR) + return false; + if (M_MapLocked(mapnum+1)) return false; // not unlocked + // Check for TOL + if (!(mapheaderinfo[mapnum]->typeoflevel & tolflag)) + return false; + // Should the map be hidden? - if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU /*&& mapnum+1 != gamemap*/) + if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) return false; // I don't know why, but some may have exceptions. if (levellist.timeattack && (mapheaderinfo[mapnum]->menuflags & LF2_NOTIMEATTACK)) return false; - if (gt == GT_BATTLE && (mapheaderinfo[mapnum]->typeoflevel & TOL_BATTLE)) - return true; - - if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) + if (gametypedefaultrules[gt] & GTR_CAMPAIGN) { if (levellist.selectedcup && levellist.selectedcup->numlevels) { @@ -3217,12 +3224,10 @@ boolean M_CanShowLevelInList(INT16 mapnum, UINT8 gt) if (i == levellist.selectedcup->numlevels) return false; } - - return true; } - // Hmm? Couldn't decide? - return false; + // Survived our checks. + return true; } INT16 M_CountLevelsToShowInList(UINT8 gt) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 863821a9b..b1bc68236 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -2127,10 +2127,6 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->actnum); else if (fastcmp(field,"typeoflevel")) lua_pushinteger(L, header->typeoflevel); - else if (fastcmp(field,"nextlevel")) - lua_pushstring(L, header->nextlevel); - else if (fastcmp(field,"marathonnext")) - lua_pushstring(L, header->marathonnext); else if (fastcmp(field,"keywords")) lua_pushstring(L, header->keywords); else if (fastcmp(field,"musname")) @@ -2139,20 +2135,6 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->mustrack); else if (fastcmp(field,"muspos")) lua_pushinteger(L, header->muspos); - else if (fastcmp(field,"musinterfadeout")) - lua_pushinteger(L, header->musinterfadeout); - else if (fastcmp(field,"musintername")) - lua_pushstring(L, header->musintername); - else if (fastcmp(field,"muspostbossname")) - lua_pushstring(L, header->muspostbossname); - else if (fastcmp(field,"muspostbosstrack")) - lua_pushinteger(L, header->muspostbosstrack); - else if (fastcmp(field,"muspostbosspos")) - lua_pushinteger(L, header->muspostbosspos); - else if (fastcmp(field,"muspostbossfadein")) - lua_pushinteger(L, header->muspostbossfadein); - else if (fastcmp(field,"musforcereset")) - lua_pushinteger(L, header->musforcereset); else if (fastcmp(field,"forcecharacter")) lua_pushstring(L, header->forcecharacter); else if (fastcmp(field,"weather")) @@ -2188,16 +2170,6 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->unlockrequired); else if (fastcmp(field,"levelselect")) lua_pushinteger(L, header->levelselect); - else if (fastcmp(field,"bonustype")) - lua_pushinteger(L, header->bonustype); - else if (fastcmp(field,"ltzzpatch")) - lua_pushstring(L, header->ltzzpatch); - else if (fastcmp(field,"ltzztext")) - lua_pushstring(L, header->ltzztext); - else if (fastcmp(field,"ltactdiamond")) - lua_pushstring(L, header->ltactdiamond); - else if (fastcmp(field,"maxbonuslives")) - lua_pushinteger(L, header->maxbonuslives); else if (fastcmp(field,"levelflags")) lua_pushinteger(L, header->levelflags); else if (fastcmp(field,"menuflags")) @@ -2212,7 +2184,6 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->ssspheres); else if (fastcmp(field, "gravity")) lua_pushfixed(L, header->gravity); - // TODO add support for reading numGradedMares and grades else { // Read custom vars now // (note: don't include the "LUA." in your lua scripts!) diff --git a/src/p_enemy.c b/src/p_enemy.c index d5f999624..2963cbae9 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3460,28 +3460,6 @@ void A_BossDeath(mobj_t *mo) EV_DoElevator(&junk, elevateUp, false); Tag_FSet(&junk.tags, LE_CAPSULE2); EV_DoElevator(&junk, elevateHighest, false); - - if (mapheaderinfo[gamemap-1]->muspostbossname[0] && - S_MusicExists(mapheaderinfo[gamemap-1]->muspostbossname)) - { - // Touching the egg trap button calls P_DoPlayerExit, which calls P_RestoreMusic. - // So just park ourselves in the mapmus variables. - // But don't change the mapmus variables if they were modified from their level header values (e.g., TUNES). - boolean changed = strnicmp(mapheaderinfo[gamemap-1]->musname, S_MusicName(), 7); - if (!strnicmp(mapheaderinfo[gamemap-1]->musname, mapmusname, 7)) - { - strncpy(mapmusname, mapheaderinfo[gamemap-1]->muspostbossname, 7); - mapmusname[6] = 0; - mapmusflags = (mapheaderinfo[gamemap-1]->muspostbosstrack & MUSIC_TRACKMASK) | MUSIC_RELOADRESET; - mapmusposition = mapheaderinfo[gamemap-1]->muspostbosspos; - } - - // don't change if we're in another tune - // but in case we're in jingle, use our parked mapmus variables so the correct track restores - if (!changed) - S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, (1*MUSICRATE)+(MUSICRATE/2), - mapheaderinfo[gamemap-1]->muspostbossfadein); - } } bossjustdie: diff --git a/src/p_setup.c b/src/p_setup.c index 30f4d61cc..3aefd4e1a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -363,19 +363,9 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) { const INT16 num = (INT16)(i-1); - Z_Free(mapheaderinfo[num]->nextlevel); - mapheaderinfo[num]->nextlevel = NULL; - - Z_Free(mapheaderinfo[num]->marathonnext); - mapheaderinfo[num]->marathonnext = NULL; - mapheaderinfo[num]->lvlttl[0] = '\0'; - mapheaderinfo[num]->selectheading[0] = '\0'; mapheaderinfo[num]->subttl[0] = '\0'; mapheaderinfo[num]->zonttl[0] = '\0'; - mapheaderinfo[num]->ltzzpatch[0] = '\0'; - mapheaderinfo[num]->ltzztext[0] = '\0'; - mapheaderinfo[num]->ltactdiamond[0] = '\0'; mapheaderinfo[num]->actnum = 0; mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->startrings = 0; @@ -387,13 +377,6 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->musname[6] = 0; mapheaderinfo[num]->mustrack = 0; mapheaderinfo[num]->muspos = 0; - mapheaderinfo[num]->musinterfadeout = 0; - mapheaderinfo[num]->musintername[0] = 0; - mapheaderinfo[num]->muspostbossname[0] = 0; - mapheaderinfo[num]->muspostbosstrack = 0; - mapheaderinfo[num]->muspostbosspos = 0; - mapheaderinfo[num]->muspostbossfadein = 0; - mapheaderinfo[num]->musforcereset = -1; mapheaderinfo[num]->forcecharacter[0] = '\0'; mapheaderinfo[num]->weather = PRECIP_NONE; snprintf(mapheaderinfo[num]->skytexture, 5, "SKY1"); @@ -412,8 +395,6 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->numlaps = NUMLAPS_DEFAULT; mapheaderinfo[num]->unlockrequired = -1; mapheaderinfo[num]->levelselect = 0; - mapheaderinfo[num]->bonustype = 0; - mapheaderinfo[num]->maxbonuslives = -1; mapheaderinfo[num]->levelflags = 0; mapheaderinfo[num]->menuflags = 0; mapheaderinfo[num]->mobj_scale = FRACUNIT; @@ -426,7 +407,6 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) #else // equivalent to "FlickyList = NONE" P_DeleteFlickies(num); #endif - P_DeleteGrades(num); mapheaderinfo[num]->customopts = NULL; mapheaderinfo[num]->numCustomOptions = 0; @@ -445,112 +425,12 @@ void P_AllocMapHeader(INT16 i) mapheaderinfo[i]->lumpname = NULL; mapheaderinfo[i]->thumbnailPic = NULL; mapheaderinfo[i]->minimapPic = NULL; - mapheaderinfo[i]->nextlevel = NULL; - mapheaderinfo[i]->marathonnext = NULL; mapheaderinfo[i]->flickies = NULL; - mapheaderinfo[i]->grades = NULL; nummapheaders++; } P_ClearSingleMapHeaderInfo(i + 1); } -/** NiGHTS Grades are a special structure, - * we initialize them here. - * - * \param i Index of header to allocate grades for - * \param mare The mare we're adding grades for - * \param grades the string from DeHackEd, we work with it ourselves - */ -void P_AddGradesForMare(INT16 i, UINT8 mare, char *gtext) -{ - INT32 g; - char *spos = gtext; - - CONS_Debug(DBG_SETUP, "Map %d Mare %d: ", i+1, (UINT16)mare+1); - - if (mapheaderinfo[i]->numGradedMares < mare+1) - { - mapheaderinfo[i]->numGradedMares = mare+1; - mapheaderinfo[i]->grades = Z_Realloc(mapheaderinfo[i]->grades, sizeof(nightsgrades_t) * mapheaderinfo[i]->numGradedMares, PU_STATIC, NULL); - } - - for (g = 0; g < 6; ++g) - { - // Allow "partial" grading systems - if (spos != NULL) - { - mapheaderinfo[i]->grades[mare].grade[g] = atoi(spos); - CONS_Debug(DBG_SETUP, "%u ", atoi(spos)); - // Grab next comma - spos = strchr(spos, ','); - if (spos) - ++spos; - } - else - { - // Grade not reachable - mapheaderinfo[i]->grades[mare].grade[g] = UINT32_MAX; - } - } - - CONS_Debug(DBG_SETUP, "\n"); -} - -/** And this removes the grades safely. - * - * \param i The header to remove grades from - */ -void P_DeleteGrades(INT16 i) -{ - if (mapheaderinfo[i]->grades) - Z_Free(mapheaderinfo[i]->grades); - - mapheaderinfo[i]->grades = NULL; - mapheaderinfo[i]->numGradedMares = 0; -} - -/** And this fetches the grades - * - * \param pscore The player's score. - * \param map The game map. - * \param mare The mare to test. - */ -UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare) -{ - INT32 i; - - // Determining the grade - if (mapheaderinfo[map-1] && mapheaderinfo[map-1]->grades && mapheaderinfo[map-1]->numGradedMares >= mare + 1) - { - INT32 pgrade = 0; - for (i = 0; i < 6; ++i) - { - if (pscore >= mapheaderinfo[map-1]->grades[mare].grade[i]) - ++pgrade; - } - return (UINT8)pgrade; - } - return 0; -} - -UINT8 P_HasGrades(INT16 map, UINT8 mare) -{ - // Determining the grade - // Mare 0 is treated as overall and is true if ANY grades exist - if (mapheaderinfo[map-1] && mapheaderinfo[map-1]->grades - && (mare == 0 || mapheaderinfo[map-1]->numGradedMares >= mare)) - return true; - return false; -} - -UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade) -{ - // Get the score for the grade... if it exists - if (grade == GRADE_F || grade > GRADE_S || !P_HasGrades(map, mare)) return 0; - - return mapheaderinfo[map-1]->grades[mare].grade[grade-1]; -} - // // levelflats // diff --git a/src/p_setup.h b/src/p_setup.h index 4eaf46105..3db26a7ba 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -125,10 +125,5 @@ void P_DeleteFlickies(INT16 i); // Needed for NiGHTS void P_ReloadRings(void); -void P_DeleteGrades(INT16 i); -void P_AddGradesForMare(INT16 i, UINT8 mare, char *gtext); -UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare); -UINT8 P_HasGrades(INT16 map, UINT8 mare); -UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade); #endif diff --git a/src/p_user.c b/src/p_user.c index 1e1cfcbcb..5ec02733a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4265,14 +4265,7 @@ void P_PlayerThink(player_t *player) if (!player->spectator) P_PlayerInSpecialSector(player); - else if ( -#else - if (player->spectator && #endif - (gametyperules & GTR_LIVES)) - { - /*P_ConsiderAllGone()*/; - } if (player->playerstate == PST_DEAD) {