diff --git a/src/d_main.c b/src/d_main.c index 1507b3668021c3c61bddaa945b0778731d3ee9ab..4d740cca340b60cc7074a345f9500d31c3d09ea3 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -997,6 +997,7 @@ void D_StartTitle(void) gameaction = ga_nothing; displayplayer = consoleplayer = 0; + gametype = -1; G_SetGametype(GT_COOP); paused = false; advancedemo = false; diff --git a/src/deh_soc.c b/src/deh_soc.c index 30b2b42b84ad90306b4d71aa0f2d100b07328419..b6dfdb7ca6515388fbe4f422ad3f5409002231cf 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1611,6 +1611,14 @@ void readlevelheader(MYFILE *f, INT32 num) mapheaderinfo[num-1]->marathonnext = (INT16)i; } + else if (fastcmp(word, "HUBLEVEL")) + { + // Convert to map number + if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0') + i = M_MapNumber(word2[0], word2[1]); + + mapheaderinfo[num-1]->hublevel = (INT16)i; + } else if (fastcmp(word, "TYPEOFLEVEL")) { if (i) // it's just a number diff --git a/src/doomstat.h b/src/doomstat.h index 4b1ab80d7191a4ffd501c25ca53f1ee5bde1f4f5..74e3e52b9472fcc7dbfe3e686812d0689bfd086d 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -306,6 +306,7 @@ typedef struct UINT32 typeoflevel; ///< Combination of typeoflevel flags. INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI. + INT16 hublevel; ///< Map number of the hub associated with this level. char keywords[32+1]; ///< Keywords separated by space to search for. 32 characters. char musname[6+1]; ///< Music track to play. "" for no music. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. diff --git a/src/g_game.c b/src/g_game.c index 75f40c8ee238fd98d1af7078d630ff096cc5d0cb..a61202b4cdbf785767645e1ec35b4469b4b04073 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3477,16 +3477,16 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = // // Sets a new gametype, also setting gametype rules accordingly. // -void G_SetGametype(INT16 gtype) +void G_SetGametype(INT16 newgametype) { - if (gametype != gtype) + if (newgametype >= 0 && newgametype < gametypecount && gametype != newgametype) { if (gametype == -1) - lastgametype = gtype; + lastgametype = newgametype; else lastgametype = gametype; - gametype = gtype; + gametype = newgametype; gametyperules = gametypedefaultrules[gametype]; } } @@ -3888,6 +3888,21 @@ boolean G_IsHubAvailable(void) return G_IsHubMapValid(currenthubmap); } +// Updates the current hub map. Reading the function explains the function. +void G_UpdateCurrentHubMap(void) +{ + if (maptol & TOL_HUB) + { + if (!M_MapLocked(gamemap, serverGamedata)) + currenthubmap = gamemap; + } + else if (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->hublevel) + { + if (!M_MapLocked(mapheaderinfo[gamemap-1]->hublevel, serverGamedata)) + currenthubmap = mapheaderinfo[gamemap-1]->hublevel; + } +} + /** Get the typeoflevel flag needed to indicate support of a gametype. * In single-player, this always returns TOL_SP. * \param gametype The gametype for which support is desired. @@ -4086,6 +4101,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) { INT32 i; INT16 newmapnum; + INT16 gametype_to_use; boolean spec = G_IsSpecialStage(gamemap); // go to next level @@ -4117,8 +4133,6 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) newmapnum = 1100-1; // No infinite loop for you } - INT16 gametype_to_use; - if (nextgametype >= 0 && nextgametype < gametypecount) gametype_to_use = nextgametype; else @@ -4139,7 +4153,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) memset(visitedmap, 0, sizeof (visitedmap)); // Allow warping to non-hub levels if in a hub level. - if (gametype_to_use == GT_HUB && lastgametype != -1) + if (gametype_to_use == GT_HUB) tolflag |= G_TOLFlag(lastgametype); // Allow warping to hub levels if in a non-hub level. else if (gametype_to_use != GT_HUB) @@ -5219,6 +5233,8 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean maptol = mapheaderinfo[gamemap-1]->typeoflevel; globalweather = mapheaderinfo[gamemap-1]->weather; + G_UpdateCurrentHubMap(); + // Don't carry over custom music change to another map. mapmusflags |= MUSIC_RELOADRESET; diff --git a/src/g_game.h b/src/g_game.h index 890fcd71e1b475e8059eda6ba76413ad1739347f..3c0878858f5b1298045c20ad7582076a99f16e45 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -184,6 +184,7 @@ void G_PreLevelTitleCard(void); boolean G_IsTitleCardAvailable(void); boolean G_IsHubAvailable(void); +void G_UpdateCurrentHubMap(void); // Can be called by the startup code or M_Responder, calls P_SetupLevel. void G_LoadGame(UINT32 slot, INT16 mapoverride); @@ -198,7 +199,7 @@ extern UINT32 gametypedefaultrules[NUMGAMETYPES]; extern UINT32 gametypetol[NUMGAMETYPES]; extern INT16 gametyperankings[NUMGAMETYPES]; -void G_SetGametype(INT16 gametype); +void G_SetGametype(INT16 newgametype); INT16 G_AddGametype(UINT32 rules); void G_AddGametypeConstant(INT16 gtype, const char *newgtconst); void G_UpdateGametypeSelections(void); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7f2560bcc4adc2f398d87aa8066119ee9ec3b455..c4f8697c476027755ca3b8735bfc4b91caf28e0f 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2536,8 +2536,7 @@ static void HU_DrawRankings(void) UINT32 whiteplayer; // draw the current gametype in the lower right - if (gametype >= 0 && gametype < gametypecount) - V_DrawString(4, splitscreen ? 184 : 192, 0, Gametype_Names[gametype]); + V_DrawString(4, splitscreen ? 184 : 192, 0, Gametype_Names[gametype]); if (gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT)) { diff --git a/src/lua_maplib.c b/src/lua_maplib.c index c946b10ce220fd28e2415d46f68233fad4bc7f0b..3c4f899faccbbe1651f472198e633523ae6a821b 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -2801,6 +2801,7 @@ enum mapheaderinfo_e mapheaderinfo_typeoflevel, mapheaderinfo_nextlevel, mapheaderinfo_marathonnext, + mapheaderinfo_hublevel, mapheaderinfo_keywords, mapheaderinfo_musname, mapheaderinfo_mustrack, @@ -2849,6 +2850,7 @@ static const char *const mapheaderinfo_opt[] = { "typeoflevel", "nextlevel", "marathonnext", + "hublevel", "keywords", "musname", "mustrack", @@ -2919,6 +2921,9 @@ static int mapheaderinfo_get(lua_State *L) case mapheaderinfo_marathonnext: lua_pushinteger(L, header->marathonnext); break; + case mapheaderinfo_hublevel: + lua_pushinteger(L, header->hublevel); + break; case mapheaderinfo_keywords: lua_pushstring(L, header->keywords); break; diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 6702e2591254349a9bd3dde6d08b7fa86ef7fb29..5f7ad68140c2c22d3eff07a68920fc6396385a95 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -815,6 +815,7 @@ void SV_StartSinglePlayerServer(void) server = true; netgame = false; multiplayer = false; + gametype = -1; G_SetGametype(GT_COOP); // no more tic the game with this settings! diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 4b44aaa9af4a3530b83086a403c13deed66e7ca9..897e6dc27ce04cf8fef86b8eec99f8fa1a671c5c 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -1741,9 +1741,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese newgametype = GT_HUB; } // Change gametype back to the previous one if warping out of a hub level - else if ((maptol & TOL_HUB) - && lastgametype != -1 - && (mapheaderinfo[mapnum-1]->typeoflevel & TOL_HUB) == 0) + else if ((maptol & TOL_HUB) && (mapheaderinfo[mapnum-1]->typeoflevel & TOL_HUB) == 0) { newgametype = lastgametype; } @@ -2086,6 +2084,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) INT32 resetplayer = 1; UINT8 skipprecutscene, FLS; INT16 mapnumber; + UINT8 newgametype; if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { @@ -2105,12 +2104,9 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) ultimatemode = false; resetplayer = ((flags & (1<<1)) == 0); - gametype = READUINT8(*cp); + newgametype = READUINT8(*cp); - if (gametype < 0 || gametype >= gametypecount) - gametype = lastgametype; - else - G_SetGametype(gametype); + G_SetGametype(newgametype); if (gametype != lastgametype) D_GameTypeChanged(); @@ -4257,7 +4253,7 @@ static void TimeLimit_OnChange(void) */ void D_GameTypeChanged(void) { - if (netgame && lastgametype != -1) + if (netgame) { CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), Gametype_Names[lastgametype], Gametype_Names[gametype]); } diff --git a/src/p_setup.c b/src/p_setup.c index 36d7d48d28d21b012d57b2477f4ff954ddb35101..cac70b703e8503577c3a6eda5e2455d47a88cee0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -355,6 +355,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->actnum = 0; mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->nextlevel = (INT16)(i + 1); + mapheaderinfo[num]->hublevel = 0; mapheaderinfo[num]->marathonnext = 0; mapheaderinfo[num]->startrings = 0; mapheaderinfo[num]->sstimer = 90; @@ -7853,10 +7854,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) maptol = mapheaderinfo[gamemap-1]->typeoflevel; gametyperules = gametypedefaultrules[gametype]; - // Set the current hub map if it was unlocked - if ((maptol & TOL_HUB) && !M_MapLocked(gamemap, serverGamedata)) - currenthubmap = gamemap; - // clear the target on map change, since the object will be invalidated P_SetTarget(&ticcmd_ztargetfocus[0], NULL); P_SetTarget(&ticcmd_ztargetfocus[1], NULL);