From 3350b02cc846b5d9274a1b6f33a262c1d005e953 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 5 Feb 2025 17:46:21 -0500 Subject: [PATCH] Long Map Names Port pt 1. --- src/acs/call-funcs.cpp | 9 +-- src/d_main.cpp | 37 ++--------- src/d_netcmd.c | 13 ++-- src/deh_soc.c | 144 +++++++++-------------------------------- src/deh_soc.h | 2 +- src/dehacked.c | 24 +++---- src/doomstat.h | 6 +- src/g_demo.c | 2 +- src/g_game.c | 129 ++++++++++++++++++------------------ src/g_game.h | 6 +- src/lua_baselib.c | 25 ++++--- src/m_menu.c | 7 +- src/m_misc.cpp | 26 -------- src/m_misc.h | 2 - src/p_saveg.c | 2 +- src/p_setup.c | 94 ++++++++++++++++----------- src/p_setup.h | 4 ++ src/w_wad.c | 10 +-- 18 files changed, 207 insertions(+), 335 deletions(-) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index b84b3126b..b2e9c9e72 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -3075,13 +3075,10 @@ bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Wor { CONS_Alert(CONS_WARNING, "MapWarp level name was not provided.\n"); } - - if (levelName[0] == 'M' && levelName[1] == 'A' && levelName[2] == 'P' && levelName[5]=='\0') - { - levelName = va("MAP%d",M_MapNumber(levelName[3], levelName[4])); - } - if (nextmap >= NUMMAPS) + nextmap = G_MapNumber(levelName); + + if (nextmap == NUMMAPS) { CONS_Alert(CONS_WARNING, "MapWarp level %s is not valid or loaded.\n", levelName); return false; diff --git a/src/d_main.cpp b/src/d_main.cpp index ed76adc8c..cc481504a 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -988,13 +988,7 @@ void D_StartTitle(void) if (server) { - char mapname[6]; - - strlcpy(mapname, G_BuildMapName(spstage_start), sizeof (mapname)); - strlwr(mapname); - mapname[5] = '\0'; - - COM_BufAddText(va("map %s\n", mapname)); + COM_BufAddText(va("map %s\n", G_BuildMapName(spstage_start))); } } @@ -1515,31 +1509,8 @@ void D_SRB2Main(void) // conversion sometimes needs the palette V_ReloadPalette(); - // - // search for maps - // - for (wadnum = 0; wadnum <= mainwads; wadnum++) - { - lumpinfo = wadfiles[wadnum]->lumpinfo; - for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lumpinfo++) - { - name = lumpinfo->name; - - if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers - { - INT16 num; - if (name[5] != '\0') - continue; - num = (INT16)M_MapNumber(name[3], name[4]); - - // we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant - if (num <= NUMMAPS && mapheaderinfo[num - 1]) - { - mapheaderinfo[num - 1]->alreadyExists = true; - } - } - } - } + P_InitMapData(); + basenummapheaders = nummapheaders; CON_SetLoadingProgress(LOADED_IWAD); @@ -1614,7 +1585,7 @@ void D_SRB2Main(void) INT16 num; if (name[5] != '\0') continue; - num = (INT16)M_MapNumber(name[3], name[4]); + num = (INT16)G_MapNumber(name); // we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant if (num <= NUMMAPS && mapheaderinfo[num - 1]) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 70337b60f..ef7861c2a 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2571,8 +2571,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r if (delay != 2) { UINT8 flags = 0; - const char *mapname = G_BuildMapName(mapnum); - I_Assert(W_CheckNumForName(mapname) != LUMPERROR); + //I_Assert(W_CheckNumForName(mapname) != LUMPERROR); buf_p = buf; if (pencoremode) flags |= 1; @@ -2587,7 +2586,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r // new gametype value WRITEUINT8(buf_p, newgametype); - WRITESTRINGN(buf_p, mapname, MAX_WADPATH); + WRITEINT16(buf_p, mapnum); } if (delay == 1) @@ -3044,11 +3043,11 @@ static void Command_Map_f(void) */ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) { - char mapname[MAX_WADPATH+1]; UINT8 flags; INT32 resetplayer = 1, lastgametype; UINT8 skipprecutscene, FLS; boolean pencoremode; + INT16 mapnumber; forceresetplayers = deferencoremode = false; @@ -3085,7 +3084,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) FLS = ((flags & (1<<3)) != 0); - READSTRINGN(*cp, mapname, MAX_WADPATH); + mapnumber = READINT16(*cp); if (netgame) P_SetRandSeed(READUINT32(*cp)); @@ -3093,7 +3092,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) if (!skipprecutscene) { DEBFILE(va("Warping to %s [resetplayer=%d lastgametype=%d gametype=%d cpnd=%d]\n", - mapname, resetplayer, lastgametype, gametype, chmappending)); + G_BuildMapName(mapnumber), resetplayer, lastgametype, gametype, chmappending)); CON_LogMessage(M_GetText("Speeding off to level...\n")); } @@ -3109,7 +3108,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) demo.savemode = (cv_recordmultiplayerdemos.value == 2) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING; demo.savebutton = 0; - G_InitNew(pencoremode, mapname, resetplayer, skipprecutscene, FLS); + G_InitNew(pencoremode, mapnumber, resetplayer, skipprecutscene, FLS); if (demo.playback && !demo.timing) precache = true; if (demo.timing) diff --git a/src/deh_soc.c b/src/deh_soc.c index 6509e2f62..5b4466e0e 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1058,7 +1058,7 @@ static mapheader_lighting_t *usemaplighting(INT32 mapnum, const char *word) } } -void readlevelheader(MYFILE *f, INT32 num) +void readlevelheader(MYFILE *f, char * name) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *word; @@ -1066,10 +1066,24 @@ void readlevelheader(MYFILE *f, INT32 num) //char *word3; // Non-uppercase version of word2 char *tmp; INT32 i; + const INT32 num = G_MapNumber(name); + + if (num > NUMMAPS) + { + I_Error("Too many maps!"); + } + + if (mapheaderinfo[num-1]) + G_SetGameModified(multiplayer, true); // only mark as a major mod if it replaces an already-existing mapheaderinfo // Reset all previous map header information P_AllocMapHeader((INT16)(num-1)); + if (mapheaderinfo[num-1]->lumpname == NULL) + { + mapheaderinfo[num-1]->lumpname = Z_StrDup(name); + } + do { if (myfgets(s, MAXLINELEN, f)) @@ -1267,12 +1281,8 @@ void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word2, "CREDITS")) i = 1102; else if (fastcmp(word2, "ENDING")) i = 1103; else - // Support using the actual map name, - // i.e., Nextlevel = AB, Nextlevel = FZ, etc. - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0') - i = M_MapNumber(word2[0], word2[1]); + i = G_MapNumber(word2); mapheaderinfo[num-1]->nextlevel = (INT16)i; } @@ -1283,12 +1293,8 @@ void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word2, "CREDITS")) i = 1102; else if (fastcmp(word2, "ENDING")) i = 1103; else - // Support using the actual map name, - // i.e., MarathonNext = AB, MarathonNext = FZ, etc. - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0') - i = M_MapNumber(word2[0], word2[1]); + i = G_MapNumber(word2); mapheaderinfo[num-1]->marathonnext = (INT16)i; } @@ -2557,14 +2563,7 @@ void reademblemdata(MYFILE *f, INT32 num) emblemlocations[num-1].tag = (INT16)value; else if (fastcmp(word, "MAPNUM")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. - - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - value = M_MapNumber(word2[0], word2[1]); - - emblemlocations[num-1].level = (INT16)value; + emblemlocations[num-1].level = (INT16)G_MapNumber(word2); } else if (fastcmp(word, "SPRITE")) { @@ -2785,14 +2784,7 @@ void readunlockable(MYFILE *f, INT32 num) } else if (fastcmp(word, "VAR")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. - - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - i = M_MapNumber(word2[0], word2[1]); - - unlockables[num].variable = (INT16)i; + unlockables[num].variable = (INT16)G_MapNumber(word2); } else deh_warning("Unlockable %d: unknown word '%s'", num+1, word); @@ -2872,10 +2864,7 @@ static void readcondition(UINT8 set, UINT32 id, char *word2) ty = UC_MAPVISITED + offset; // Convert to map number if it appears to be one - if (params[1][0] >= 'A' && params[1][0] <= 'Z') - re = M_MapNumber(params[1][0], params[1][1]); - else - re = atoi(params[1]); + re = G_MapNumber(params[1]); if (re < 0 || re >= NUMMAPS) { @@ -2890,10 +2879,7 @@ static void readcondition(UINT8 set, UINT32 id, char *word2) re = atoi(params[2]); // Convert to map number if it appears to be one - if (params[1][0] >= 'A' && params[1][0] <= 'Z') - x1 = (INT16)M_MapNumber(params[1][0], params[1][1]); - else - x1 = (INT16)atoi(params[1]); + x1 = (INT16)G_MapNumber(params[1]); if (x1 < 0 || x1 >= NUMMAPS) { @@ -3096,56 +3082,20 @@ void readmaincfg(MYFILE *f) else if (fastcmp(word, "SPSTAGE_START")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. - - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - value = M_MapNumber(word2[0], word2[1]); - else - value = get_number(word2); - - spstage_start = spmarathon_start = (INT16)value; + spstage_start = (INT16)G_MapNumber(word2); } else if (fastcmp(word, "SPMARATHON_START")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. - - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - value = M_MapNumber(word2[0], word2[1]); - else - value = get_number(word2); - - spmarathon_start = (INT16)value; + spmarathon_start = (INT16)G_MapNumber(word2); } else if (fastcmp(word, "SSTAGE_START")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. - - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - value = M_MapNumber(word2[0], word2[1]); - else - value = get_number(word2); - - sstage_start = (INT16)value; + sstage_start = (INT16)G_MapNumber(word2); sstage_end = (INT16)(sstage_start+7); // 7 special stages total plus one weirdo } else if (fastcmp(word, "SMPSTAGE_START")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. - - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - value = M_MapNumber(word2[0], word2[1]); - else - value = get_number(word2); - - smpstage_start = (INT16)value; + smpstage_start = (INT16)G_MapNumber(word2); smpstage_end = (INT16)(smpstage_start+6); // 7 special stages total } else if (fastcmp(word, "REDTEAM")) @@ -3230,16 +3180,7 @@ void readmaincfg(MYFILE *f) } else if (fastcmp(word, "TITLEMAP")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. - - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - value = M_MapNumber(word2[0], word2[1]); - else - value = get_number(word2); - - titlemap = (INT16)value; + titlemap = (INT16)G_MapNumber(word2); titlechanged = true; } else if (fastcmp(word, "HIDETITLEPICS") || fastcmp(word, "TITLEPICSHIDE")) @@ -3365,30 +3306,12 @@ void readmaincfg(MYFILE *f) } else if (fastcmp(word, "BOOTMAP")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. - - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - value = M_MapNumber(word2[0], word2[1]); - else - value = get_number(word2); - - bootmap = (INT16)value; + bootmap = (INT16)G_MapNumber(word2); //titlechanged = true; } else if (fastcmp(word, "TUTORIALMAP")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. - - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - value = M_MapNumber(word2[0], word2[1]); - else - value = get_number(word2); - - tutorialmap = (INT16)value; + tutorialmap = (INT16)G_MapNumber(word2); } else deh_warning("Maincfg: unknown word '%s'", word); @@ -3613,9 +3536,6 @@ void readcupheader(MYFILE *f, cupheader_t *cup) do { INT32 map = atoi(tmp); - if (tmp[0] >= 'A' && tmp[0] <= 'Z' && tmp[2] == '\0') - map = M_MapNumber(tmp[0], tmp[1]); - if (!map) break; @@ -3631,16 +3551,12 @@ void readcupheader(MYFILE *f, cupheader_t *cup) } else if (fastcmp(word, "BONUSGAME")) { - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0') - i = M_MapNumber(word2[0], word2[1]); + i = (INT16)G_MapNumber(word2); cup->bonusgame = (INT16)i - 1; } else if (fastcmp(word, "SPECIALSTAGE")) { - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0') - i = M_MapNumber(word2[0], word2[1]); + i = (INT16)G_MapNumber(word2); cup->specialstage = (INT16)i - 1; } else if (fastcmp(word, "EMERALDNUM")) diff --git a/src/deh_soc.h b/src/deh_soc.h index d8a652579..cb24db595 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -73,7 +73,7 @@ void readhuditem(MYFILE *f, INT32 num); void readmenu(MYFILE *f, INT32 num); void readtextprompt(MYFILE *f, INT32 num); void readcutscene(MYFILE *f, INT32 num); -void readlevelheader(MYFILE *f, INT32 num); +void readlevelheader(MYFILE *f, char * name); void readgametype(MYFILE *f, char *gtname); void readsprite2(MYFILE *f, INT32 num); #ifdef HWRENDER diff --git a/src/dehacked.c b/src/dehacked.c index 211223ec0..6943c5c47 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -368,25 +368,19 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) #endif else if (fastcmp(word, "LEVEL")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. - - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - i = M_MapNumber(word2[0], word2[1]); - - if (i > 0 && i <= NUMMAPS) + size_t len = strlen(word2); + if (len <= MAXMAPLUMPNAME-1) { - if (mapheaderinfo[i]) - { - G_SetGameModified(multiplayer, true); // Only a major mod if editing stuff that isn't your own! - } - - readlevelheader(f, i); + if (len == 1) + readlevelheader(f, va("MAP0%s",word2)); + else if (len == 2) + readlevelheader(f, va("MAP%s",word2)); + else + readlevelheader(f, word2); } else { - deh_warning("Level number %d out of range (1 - %d)", i, NUMMAPS); + deh_warning("Map header's lumpname %s is too long (%s characters VS %d max)", word2, sizeu1(len), (MAXMAPLUMPNAME-1)); ignorelines(f); } } diff --git a/src/doomstat.h b/src/doomstat.h index 6031355ae..338958693 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -348,7 +348,8 @@ struct mapheader_lighting_t */ struct mapheader_t { - // The original eight, plus one. + char * lumpname; ///< Lump name can be really long + lumpnum_t lumpnum; ///< Lump number for the map char lvlttl[22]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway) char subttl[33]; ///< Subtitle for level char zonttl[22]; ///< "ZONE" replacement name @@ -449,6 +450,9 @@ struct mapheader_t #define LF2_VISITNEEDED (1<<3) ///< Not available in Time Attack modes until you visit the level extern mapheader_t* mapheaderinfo[NUMMAPS]; +extern INT32 nummapheaders,basenummapheaders; + +#define MAXMAPLUMPNAME 64 // includes \0, for cleaner savedata // This could support more, but is that a good idea? // Keep in mind that it may encourage people making overly long cups just because they "can", and would be a waste of memory. diff --git a/src/g_demo.c b/src/g_demo.c index 2e2a05149..52a29d27c 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3225,7 +3225,7 @@ void G_DoPlayDemo(char *defdemoname) R_ExecuteSetViewSize(); P_SetRandSeed(randseed); - G_InitNew(demoflags & DF_ENCORE, G_BuildMapName(gamemap), true, true, false); // Doesn't matter whether you reset or not here, given changes to resetplayer. + G_InitNew(demoflags & DF_ENCORE, gamemap, true, true, false); // Doesn't matter whether you reset or not here, given changes to resetplayer. for (i = 0; i < MAXPLAYERS; i++) { diff --git a/src/g_game.c b/src/g_game.c index 2b8bbd3f7..9baec3b6b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -183,6 +183,8 @@ struct quake quake; // Map Header Information mapheader_t* mapheaderinfo[NUMMAPS] = {NULL}; +INT32 nummapheaders = 0; +INT32 basenummapheaders = 0; // Kart cup definitions cupheader_t *kartcupheaders = NULL; @@ -685,18 +687,13 @@ void G_SetGameModified(boolean silent, boolean major) } /** Builds an original game map name from a map number. - * The complexity is due to MAPA0-MAPZZ. * * \param map Map number. * \return Pointer to a static buffer containing the desired map name. - * \sa M_MapNumber + * \sa G_MapNumber */ const char *G_BuildMapName(INT32 map) { - static char mapname[10] = "MAPXX"; // internal map name (wad resource name) - - I_Assert(map >= 0); - I_Assert(map <= NUMMAPS); if (map == 0) // hack??? { @@ -709,19 +706,35 @@ const char *G_BuildMapName(INT32 map) map = G_RandMap(G_TOLFlag(cv_newgametype.value), map, 0, 0, false, NULL)+1; } - if (map < 100) - sprintf(&mapname[3], "%.2d", map); + if (map > 0 && map <= NUMMAPS && mapheaderinfo[map - 1] != NULL) + { + return mapheaderinfo[map - 1]->lumpname; + } else { - mapname[3] = (char)('A' + (char)((map - 100) / 36)); - if ((map - 100) % 36 < 10) - mapname[4] = (char)('0' + (char)((map - 100) % 36)); - else - mapname[4] = (char)('A' + (char)((map - 100) % 36) - 10); - mapname[5] = '\0'; + return NULL; + } +} + +/** Returns the map number for map lump name. + * + * \param name Map name; + * \return Map number. + * \sa G_BuildMapName + */ +INT32 G_MapNumber(const char * name) +{ + INT32 map; + + for (map = 0; map < nummapheaders; ++map) + { + if (strcasecmp(mapheaderinfo[map]->lumpname, name) == 0) + { + break; + } } - return mapname; + return map + 1; } /** Clips the console player's mouse aiming to the current view. @@ -4629,7 +4642,7 @@ cleanup: // Can be called by the startup code or the menu task, // consoleplayer, displayplayers[], playeringame[] should be set. // -void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar, UINT8 ssplayers, boolean FLS) +void G_DeferedInitNew(boolean pencoremode, INT32 map, INT32 pickedchar, UINT8 ssplayers, boolean FLS) { INT32 i; UINT16 color = SKINCOLOR_NONE; @@ -4661,18 +4674,17 @@ void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar CV_StealthSetValue(&cv_playercolor[0], color); } - if (mapname) - { - D_MapChange(M_MapNumber(mapname[3], mapname[4]), gametype, pencoremode, true, 1, false, FLS); - } + D_MapChange(map, gametype, pencoremode, true, 1, false, FLS); } // // This is the map command interpretation something like Command_Map_f // // called at: map cmd execution, doloadgame, doplaydemo -void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, boolean skipprecutscene, boolean FLS) +void G_InitNew(UINT8 pencoremode, INT32 map, boolean resetplayer, boolean skipprecutscene, boolean FLS) { + const char * mapname = G_BuildMapName(map); + INT32 i; (void)FLS; @@ -4723,14 +4735,14 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool // internal game map // well this check is useless because it is done before (d_netcmd.c::command_map_f) // but in case of for demos.... - if (W_CheckNumForName(mapname) == LUMPERROR) + if (W_CheckNumForName(mapheaderinfo[gamemap-1]->lumpname) == LUMPERROR) { I_Error("Internal game map '%s' not found\n", mapname); Command_ExitGame_f(); return; } - gamemap = (INT16)M_MapNumber(mapname[3], mapname[4]); // get xx out of MAPxx + gamemap = map; // gamemap changed; we assume that its map header is always valid, // so make it so @@ -4758,7 +4770,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool { char *title = G_BuildMapTitle(gamemap); - CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap))); + CON_LogMessage(va(M_GetText("Map is now \"%s"), mapname)); if (title) { CON_LogMessage(va(": %s", title)); @@ -4873,21 +4885,17 @@ INT32 G_FindMap(const char *mapname, char **foundmapnamep, mapnamelen = strlen(mapname); - /* Count available maps; how ugly. */ - for (i = 0, freqc = 0; i < NUMMAPS; ++i) - { - if (mapheaderinfo[i]) - freqc++; - } - - freq = ZZ_Calloc(freqc * sizeof (mapsearchfreq_t)); + freq = ZZ_Calloc(nummapheaders * sizeof (mapsearchfreq_t)); wanttable = !!( freqp ); freqc = 0; - for (i = 0, mapnum = 1; i < NUMMAPS; ++i, ++mapnum) - if (mapheaderinfo[i]) + + for (i = 0, mapnum = 1; i < nummapheaders; ++i, ++mapnum) { + if (!mapheaderinfo[i] || mapheaderinfo[i]->lumpnum == LUMPERROR) + continue; + if (!( realmapname = G_BuildMapTitle(mapnum) )) continue; @@ -4996,8 +5004,6 @@ void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc) INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep) { - boolean usemapcode = false; - INT32 newmapnum; size_t mapnamelen; @@ -5006,45 +5012,44 @@ INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep) mapnamelen = strlen(mapname); - if (mapnamelen == 2)/* maybe two digit code */ + if (mapnamelen == 1) { - if (( newmapnum = M_MapNumber(mapname[0], mapname[1]) )) - usemapcode = true; - } - else if (mapnamelen == 5 && strnicmp(mapname, "MAP", 3) == 0) - { - if (( newmapnum = M_MapNumber(mapname[3], mapname[4]) )) - usemapcode = true; - } - - if (!usemapcode) - { - /* Now detect map number in base 10, which no one asked for. */ - newmapnum = strtol(mapname, &p, 10); - if (*p == '\0')/* we got it */ + if (mapname[0] == '*') // current map + return gamemap; + else if (mapname[0] == '+' && mapheaderinfo[gamemap-1]) // next map { + newmapnum = mapheaderinfo[gamemap-1]->nextlevel; if (newmapnum < 1 || newmapnum > NUMMAPS) { - CONS_Alert(CONS_ERROR, M_GetText("Invalid map number %d.\n"), newmapnum); + CONS_Alert(CONS_ERROR, M_GetText("NextLevel (%d) is not a valid map.\n"), newmapnum); return 0; } - usemapcode = true; - } - else - { - newmapnum = G_FindMap(mapname, realmapnamep, NULL, NULL); + else + return newmapnum; } } - if (usemapcode) + /* Now detect map number in base 10, which no one asked for. */ + newmapnum = strtol(mapname, &p, 10); + + if (*p == '\0')/* we got it */ { - /* we can't check mapheaderinfo for this hahahaha */ - if (W_CheckNumForName(G_BuildMapName(newmapnum)) == LUMPERROR) + if (newmapnum < 1 || newmapnum > nummapheaders) return 0; - if (realmapnamep) - (*realmapnamep) = G_BuildMapTitle(newmapnum); + if (!mapheaderinfo[newmapnum-1] || mapheaderinfo[newmapnum-1]->lumpnum == LUMPERROR) + return 0; } + else + { + newmapnum = G_MapNumber(mapname); + + if (newmapnum > nummapheaders) + return G_FindMap(mapname, realmapnamep, NULL, NULL); + } + + if (realmapnamep) + (*realmapnamep) = G_BuildMapTitle(newmapnum); return newmapnum; } diff --git a/src/g_game.h b/src/g_game.h index 091e162ff..3352ce069 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -93,8 +93,8 @@ void weaponPrefChange4(void); #define MAXPLMOVE (50) #define SLOWTURNTICS (cv_turnsmooth.value * 3) -// build an internal map name MAPxx from map number const char *G_BuildMapName(INT32 map); +INT32 G_MapNumber(const char *mapname); void G_ResetAnglePrediction(player_t *player); void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer); @@ -136,7 +136,7 @@ extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but sig void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo); void G_DoReborn(INT32 playernum); void G_PlayerReborn(INT32 player, boolean betweenmaps); -void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, +void G_InitNew(UINT8 pencoremode, INT32 map, boolean resetplayer, boolean skipprecutscene, boolean FLS); char *G_BuildMapTitle(INT32 mapnum); @@ -173,7 +173,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost); // Can be called by the startup code or M_Responder. // A normal game starts at map 1, but a warp test can start elsewhere -void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar, +void G_DeferedInitNew(boolean pencoremode, INT32 map, INT32 pickedchar, UINT8 ssplayers, boolean FLS); void G_DoLoadLevel(boolean resetplayer); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 020a6dcf8..0ff37d383 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -34,7 +34,6 @@ #include "k_hud.h" #include "d_netcmd.h" // IsPlayerAdmin #include "m_menu.h" // Player Setup menu color stuff -#include "m_misc.h" // M_MapNumber #include "p_spec.h" // P_StartQuake #include "i_system.h" // I_GetPreciseTime, I_GetPrecisePrecision @@ -390,18 +389,18 @@ static int lib_pGetColorAfter(lua_State *L) // M_MISC ////////////// -static int lib_mMapNumber(lua_State *L) +static int lib_gMapNumber(lua_State *L) { const char *arg = luaL_checkstring(L, 1); - size_t len = strlen(arg); - if (len == 2 || len == 5) { - char first = arg[len-2]; - char second = arg[len-1]; - lua_pushinteger(L, M_MapNumber(first, second)); - } else { - lua_pushinteger(L, 0); - } - return 1; + INT32 map; + + map = G_MapNumber(arg); + + if (map == INT32_MAX) + return 0; + + + return map; } // M_RANDOM @@ -3968,9 +3967,6 @@ static luaL_Reg lib[] = { {"M_GetColorAfter",lib_pGetColorAfter}, {"M_GetColorBefore",lib_pGetColorBefore}, - // m_misc - {"M_MapNumber",lib_mMapNumber}, - // m_random {"P_RandomFixed",lib_pRandomFixed}, {"P_RandomByte",lib_pRandomByte}, @@ -4173,6 +4169,7 @@ static luaL_Reg lib[] = { // g_game {"G_AddGametype", lib_gAddGametype}, {"G_BuildMapName",lib_gBuildMapName}, + {"G_MapNumber",lib_gMapNumber}, {"G_BuildMapTitle",lib_gBuildMapTitle}, {"G_FindMap",lib_gFindMap}, {"G_FindMapByNameOrCode",lib_gFindMapByNameOrCode}, diff --git a/src/m_menu.c b/src/m_menu.c index 720a0fdb9..c5837fe5c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6252,12 +6252,11 @@ static boolean M_ExitPandorasBox(void) static void M_ChangeLevel(INT32 choice) { - char mapname[6]; + char mapname[MAXMAPLUMPNAME-1]; (void)choice; strlcpy(mapname, G_BuildMapName(cv_nextmap.value), sizeof (mapname)); strlwr(mapname); - mapname[5] = '\0'; M_ClearMenus(true); COM_BufAddText(va("map %s -gametype \"%s\"\n", mapname, cv_newgametype.string)); @@ -7837,7 +7836,7 @@ static void M_StartGrandPrix(INT32 choice) G_DeferedInitNew( false, - G_BuildMapName(grandprixinfo.cup->levellist[0] + 1), + grandprixinfo.cup->levellist[0] + 1, (UINT8)(cv_chooseskin.value - 1), (UINT8)(cv_splitplayers.value - 1), false @@ -8134,7 +8133,7 @@ static void M_ChooseTimeAttack(INT32 choice) else G_RecordDemo(nameofdemo); - G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), (UINT8)(cv_chooseskin.value-1), 0, false); + G_DeferedInitNew(false, cv_nextmap.value, (UINT8)(cv_chooseskin.value-1), 0, false); } static void M_HandleStaffReplay(INT32 choice) diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 63859293f..b4da15099 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -182,32 +182,6 @@ boolean takescreenshot = false; // Take a screenshot this tic moviemode_t moviemode = MM_OFF; -/** Returns the map number for a map identified by the last two characters in - * its name. - * - * \param first The first character after MAP. - * \param second The second character after MAP. - * \return The map number, or 0 if no map corresponds to these characters. - * \sa G_BuildMapName - */ -INT32 M_MapNumber(char first, char second) -{ - if (isdigit(first)) - { - if (isdigit(second)) - return ((INT32)first - '0') * 10 + ((INT32)second - '0'); - return 0; - } - - if (!isalpha(first)) - return 0; - if (!isalnum(second)) - return 0; - - return 100 + ((INT32)tolower(first) - 'a') * 36 + (isdigit(second) ? ((INT32)second - '0') : - ((INT32)tolower(second) - 'a') + 10); -} - // ========================================================================== // FILE INPUT / OUTPUT // ========================================================================== diff --git a/src/m_misc.h b/src/m_misc.h index f3a464fc7..a11a384c6 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -46,8 +46,6 @@ void M_StopMovie(void); // the file where game vars and settings are saved #define CONFIGFILENAME "kartconfig.cfg" -INT32 M_MapNumber(char first, char second); - boolean FIL_WriteFile(char const *name, const void *source, size_t length); size_t FIL_ReadFileTag(char const *name, UINT8 **buffer, INT32 tag); #define FIL_ReadFile(n, b) FIL_ReadFileTag(n, b, PU_STATIC) diff --git a/src/p_saveg.c b/src/p_saveg.c index e9470b148..9dba5ea7d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5350,7 +5350,7 @@ boolean P_LoadGame(savebuffer_t *save, INT16 mapoverride) return false; // Only do this after confirming savegame is ok - G_DeferedInitNew(false, G_BuildMapName(gamemap), savedata.skin, 0, true); + G_DeferedInitNew(false, gamemap, savedata.skin, 0, true); COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this return true; diff --git a/src/p_setup.c b/src/p_setup.c index 0d5f95c2b..0791b6ffd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -469,8 +469,10 @@ void P_AllocMapHeader(INT16 i) if (!mapheaderinfo[i]) { mapheaderinfo[i] = Z_Malloc(sizeof(mapheader_t), PU_STATIC, NULL); + mapheaderinfo[i]->lumpname = NULL; mapheaderinfo[i]->flickies = NULL; mapheaderinfo[i]->grades = NULL; + nummapheaders++; } P_ClearSingleMapHeaderInfo(i + 1); } @@ -8713,6 +8715,51 @@ static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, l return lumpinfo; } +// Initialising map data... +UINT8 P_InitMapData(void) +{ + UINT8 ret = 0; + INT32 i; + lumpnum_t maplump; + char *name; + + for (i = 0; i < nummapheaders; ++i) + { + name = mapheaderinfo[i]->lumpname; + maplump = W_CheckNumForMap(name); + + // Doesn't exist? + if (maplump == INT16_MAX) + continue; + + // No change? + if (mapheaderinfo[i]->lumpnum == maplump) + continue; + + // Okay, it does... + { + ret |= MAPRET_ADDED; + + if (basenummapheaders) + { + CONS_Printf("%s\n", name); + + if (mapheaderinfo[i]->lumpnum != LUMPERROR) + { + G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you + + //If you replaced the map you're on, end the level when done. + if (i == gamemap - 1) + ret |= MAPRET_CURRENTREPLACED; + } + } + mapheaderinfo[i]->lumpnum = maplump; + } + } + + return ret; +} + // // Add a wadfile to the active wad files, // replace sounds, musics, patches, textures, sprites and maps @@ -8738,7 +8785,6 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, wadcompat_t compat) UINT16 numlumps, wadnum; char *name; lumpinfo_t *lumpinfo; - boolean mapsadded = false; // Vars to help us with the position start and amount of each resource type. // Useful for PK3s since they use folders. @@ -8894,41 +8940,6 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, wadcompat_t compat) // R_LoadSpriteInfoLumps(wadnum, numlumps); - // - // search for maps - // - lumpinfo = wadfiles[wadnum]->lumpinfo; - for (i = 0; i < numlumps; i++, lumpinfo++) - { - name = lumpinfo->name; - if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers - { - INT16 num; - if (name[5]!='\0') - continue; - num = (INT16)M_MapNumber(name[3], name[4]); - - // we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant - if (num <= NUMMAPS && mapheaderinfo[num-1]) - { - if (mapheaderinfo[num - 1]->alreadyExists != false) - { - G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you - } - mapheaderinfo[num - 1]->alreadyExists = true; - } - - if (num == gamemap) - partadd_replacescurrentmap = true; - - CONS_Printf("%s\n", name); - mapsadded = true; - } - } - - if (!mapsadded) - CONS_Printf(M_GetText("No maps added\n")); - refreshdirmenu &= ~REFRESHDIR_GAMEDATA; // Under usual circumstances we'd wait for REFRESHDIR_ flags to disappear the next frame, but this one's a bit too dangerous for that... partadd_stage = 0; return wadnum; @@ -8992,9 +9003,16 @@ boolean P_MultiSetupWadFiles(boolean fullsetup) if (partadd_stage == 2) { - if (partadd_replacescurrentmap && gamestate == GS_LEVEL && (netgame || multiplayer)) + UINT8 mapsadded = P_InitMapData(); + + if (!mapsadded) + CONS_Printf(M_GetText("No maps added\n")); + + if ((mapsadded & MAPRET_CURRENTREPLACED) + && (gamestate == GS_LEVEL) + && (netgame || multiplayer)) { - CONS_Printf(M_GetText("Current map %d replaced, ending the level to ensure consistency.\n"), gamemap); + CONS_Printf(M_GetText("Current map %s replaced by added file, ending the level to ensure consistency.\n"), mapheaderinfo[gamemap-1]->lumpname); if (server) SendNetXCmd(XD_EXITLEVEL, NULL, 0); } diff --git a/src/p_setup.h b/src/p_setup.h index 2e72c626a..c7ddb7aa3 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -114,6 +114,10 @@ void HWR_LoadLevel(void); #endif boolean P_AddWadFile(const char *wadfilename, wadcompat_t compat); +#define MAPRET_ADDED (1) +#define MAPRET_CURRENTREPLACED (1<<1) +UINT8 P_InitMapData(void); + // WARNING: The following functions should be grouped as follows: // any amount of PartialAdds followed by MultiSetups until returned true, // as soon as possible. diff --git a/src/w_wad.c b/src/w_wad.c index 6271664a4..8567e0c6b 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -67,8 +67,7 @@ #ifdef SCANTHINGS #include "p_setup.h" // P_ScanThings #endif -#include "m_misc.h" // M_MapNumber -#include "g_game.h" // G_SetGameModified +#include "g_game.h" // G_MapNumber #include "k_terrain.h" @@ -281,11 +280,8 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum, boolean mainfile) for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++) { const char *name = lump_p->name; - if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P' && name[5]=='\0') - { - INT16 mapnum = (INT16)M_MapNumber(name[3], name[4]); - P_ScanThings(mapnum, wadnum, lump + ML_THINGS); - } + INT16 mapnum = (INT16)G_MapNumber(name); + P_ScanThings(mapnum, wadnum, lump + ML_THINGS); } } #endif