diff --git a/src/d_main.c b/src/d_main.c index d75a4d5013d9a92e7abccad7211721b3fa1f00b5..40d9319fd867bb2b57443c0817b825910e369019 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1377,6 +1377,9 @@ void D_SRB2Main(void) CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n"); Z_Init(); + gametype = -1; + G_SetGametype(GT_COOP); + clientGamedata = M_NewGameDataStruct(); serverGamedata = M_NewGameDataStruct(); @@ -1728,9 +1731,8 @@ void D_SRB2Main(void) if (newgametype != -1) { - j = gametype; G_SetGametype(newgametype); - D_GameTypeChanged(j); + D_GameTypeChanged(); } } diff --git a/src/doomstat.h b/src/doomstat.h index b5b2984407cc7cf03d213de8cb70f3bab720fc88..d05620582a06256dce0af266764c71e8941f992b 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -96,7 +96,7 @@ extern boolean addedtogame; // true after the server has added you // Only true if >1 player. netgame => multiplayer but not (multiplayer=>netgame) extern boolean multiplayer; -extern INT16 gametype; +extern INT16 gametype, lastgametype; extern UINT32 gametyperules; extern INT16 gametypecount; @@ -407,6 +407,8 @@ enum GameType GT_CTF, // capture the flag + GT_HUB, + GT_FIRSTFREESLOT, GT_LASTFREESLOT = GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1, NUMGAMETYPES @@ -474,7 +476,7 @@ enum TypeOfLevel TOL_CTF = 0x40, ///< Capture the Flag // CTF default = 64 - // 0x80 was here + TOL_HUB = 0x80, ///< Hub TOL_2D = 0x0100, ///< 2D TOL_MARIO = 0x0200, ///< Mario diff --git a/src/g_game.c b/src/g_game.c index 1c186ae03149780b254c72f5243ed3d551350e52..ea29d3091618195a3a11538cc12187d522c9663b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2353,7 +2353,7 @@ void G_Ticker(boolean run) memset(&luabanks, 0, sizeof(luabanks)); } - else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES) + else if (G_CanLoseLivesInGametype() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES) players[consoleplayer].lives -= 1; G_DoReborn(consoleplayer); @@ -3133,7 +3133,7 @@ void G_DoReborn(INT32 playernum) return; //Exit function to avoid proccing other SP related mechanics } - if (countdowntimeup || (!(netgame || multiplayer) && (gametyperules & GTR_CAMPAIGN))) + if (countdowntimeup || (!(netgame || multiplayer) && ((gametyperules & GTR_CAMPAIGN) || (maptol & TOL_HUB)))) resetlevel = true; else if ((G_GametypeUsesCoopLives() || G_GametypeUsesCoopStarposts()) && (netgame || multiplayer) && !G_IsSpecialStage(gamemap)) { @@ -3420,23 +3420,27 @@ const char *Gametype_Names[NUMGAMETYPES] = "Tag", // GT_TAG "Hide & Seek", // GT_HIDEANDSEEK - "CTF" // GT_CTF + "CTF", // GT_CTF + + "Hub" // GT_HUB }; // For dehacked const char *Gametype_ConstantNames[NUMGAMETYPES] = { - "GT_COOP", // GT_COOP - "GT_COMPETITION", // GT_COMPETITION - "GT_RACE", // GT_RACE + "GT_COOP", + "GT_COMPETITION", + "GT_RACE", + + "GT_MATCH", + "GT_TEAMMATCH", - "GT_MATCH", // GT_MATCH - "GT_TEAMMATCH", // GT_TEAMMATCH + "GT_TAG", + "GT_HIDEANDSEEK", - "GT_TAG", // GT_TAG - "GT_HIDEANDSEEK", // GT_HIDEANDSEEK + "GT_CTF", - "GT_CTF" // GT_CTF + "GT_HUB" }; // Gametype rules @@ -3461,15 +3465,26 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = // CTF GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, + + // Hub + GTR_LIVES|GTR_FRIENDLY|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_CUTSCENES }; // -// Sets a new gametype. +// Sets a new gametype, also setting gametype rules accordingly. // void G_SetGametype(INT16 gtype) { - gametype = gtype; - gametyperules = gametypedefaultrules[gametype]; + if (gametype != gtype) + { + if (gametype == -1) + lastgametype = gtype; + else + lastgametype = gametype; + + gametype = gtype; + gametyperules = gametypedefaultrules[gametype]; + } } // @@ -3627,6 +3642,8 @@ UINT32 gametypetol[NUMGAMETYPES] = TOL_TAG, // Hide and Seek TOL_CTF, // CTF + + TOL_HUB // Hub }; tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = { @@ -3645,6 +3662,8 @@ tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = { {"TAG",TOL_TAG}, {"CTF",TOL_CTF}, + {"HUB",TOL_HUB}, + {"2D",TOL_2D}, {"MARIO",TOL_MARIO}, {"NIGHTS",TOL_NIGHTS}, @@ -3736,6 +3755,20 @@ boolean G_GametypeUsesLives(void) return false; } +// +// G_CanLoseLivesInGametype +// +// Returns true if player can lose lives in +// the current gametype. False otherwise. +// +boolean G_CanLoseLivesInGametype(void) +{ + if (maptol & TOL_HUB) + return false; + + return G_GametypeUsesLives(); +} + // // G_GametypeUsesCoopLives // @@ -3840,7 +3873,11 @@ boolean G_CompetitionGametype(void) UINT32 G_TOLFlag(INT32 pgametype) { if (!multiplayer) - return TOL_SP; + { + if (pgametype != GT_HUB) + return TOL_SP; + } + return gametypetol[pgametype]; } @@ -4051,6 +4088,13 @@ 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) + tolflag |= G_TOLFlag(lastgametype); + // Allow warping to hub levels if in a non-hub level. + else if (gametype_to_use != GT_HUB) + tolflag |= G_TOLFlag(GT_HUB); + while (!mapheaderinfo[cm] || !(mapheaderinfo[cm]->typeoflevel & tolflag)) { visitedmap[cm/8] |= (1<<(cm&7)); diff --git a/src/g_game.h b/src/g_game.h index f72ea6b41b1b29b4b263b9039c0ad588bc78de17..d9436b69ce013791f230dc863130f70ca553ddeb 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -206,6 +206,7 @@ void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolo INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); +boolean G_CanLoseLivesInGametype(void); boolean G_GametypeUsesCoopLives(void); boolean G_GametypeUsesCoopStarposts(void); boolean G_GametypeHasTeams(void); diff --git a/src/m_menu.c b/src/m_menu.c index 37d191a0df84158e31d0d782d6f4b2d6b819eadc..3e597682c5686aeb02e8409a4fa7f526e1790b21 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -646,6 +646,7 @@ gtdesc_t gametypedesc[NUMGAMETYPES] = {{123, 123}, "Whoever's IT has to hunt down everyone else. If you get caught, you have to turn on your former friends!"}, {{150, 150}, "Try and find a good hiding place in these maps - we dare you."}, {{ 37, 153}, "Steal the flag from the enemy's base and bring it back to your own, but watch out - they could just as easily steal yours!"}, + {{182, 182}, "Walk through a selection of levels."} }; static menuitem_t MISC_ChangeLevelMenu[] = @@ -5089,24 +5090,6 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) if (G_IsSpecialStage(mapnum+1)) return false; - 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; - if (gt >= 0 && gt < gametypecount && (mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt])) return true; @@ -9567,7 +9550,9 @@ static void M_Statistics(INT32 choice) if (!mapheaderinfo[i] || mapheaderinfo[i]->lvlttl[0] == '\0') continue; - if (!(mapheaderinfo[i]->typeoflevel & TOL_SP) || (mapheaderinfo[i]->menuflags & LF2_HIDEINSTATS)) + if (!(mapheaderinfo[i]->typeoflevel & TOL_SP) + || (mapheaderinfo[i]->typeoflevel & TOL_HUB) + || (mapheaderinfo[i]->menuflags & LF2_HIDEINSTATS)) continue; if (!(clientGamedata->mapvisited[i] & MV_MAX)) diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 94170fa0df401064f5c1a2f9569cfceb0b0c490e..4214425c454a183b3ceddc0360b2aef4ecd7330b 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -406,9 +406,10 @@ boolean timedemo_csv; char timedemo_csv_id[256]; boolean timedemo_quit; -INT16 gametype = GT_COOP; +INT16 gametype = -1; +INT16 lastgametype = -1; UINT32 gametyperules = 0; -INT16 gametypecount = (GT_CTF + 1); +INT16 gametypecount = (GT_HUB + 1); boolean splitscreen = false; boolean circuitmap = false; @@ -1731,6 +1732,22 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese SendNameAndColor2(); } } + + if (gametype == newgametype && mapheaderinfo[mapnum-1]) + { + // Change gametype to Hub if warping into a hub level + if ((gametyperules & GTR_CAMPAIGN) && (mapheaderinfo[mapnum-1]->typeoflevel & TOL_HUB)) + { + 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) + { + newgametype = lastgametype; + } + } } 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); @@ -1838,6 +1855,8 @@ static void Command_Map_f(void) INT32 newgametype = gametype; + UINT32 tolflags; + INT32 d; if (client && !IsPlayerAdmin(consoleplayer)) @@ -1965,15 +1984,35 @@ static void Command_Map_f(void) // don't use a gametype the map doesn't support // G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer + tolflags = G_TOLFlag(newgametype); + + // Allow warping to non-hub levels if in a hub level. + if (newgametype == GT_HUB && lastgametype != -1) + tolflags |= G_TOLFlag(lastgametype); + // Allow warping to hub levels if in a non-hub level. + else if (newgametype != GT_HUB) + tolflags |= G_TOLFlag(GT_HUB); + if (!( mapheaderinfo[newmapnum-1] && - mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype) + mapheaderinfo[newmapnum-1]->typeoflevel & tolflags )) { if (prevent_cheat && !cv_skipmapcheck.value) { - CONS_Alert(CONS_WARNING, M_GetText("%s (%s) doesn't support %s mode!\n(Use -force to override)\n"), realmapname, G_BuildMapName(newmapnum), - (multiplayer ? gametype_cons_t[newgametype].strvalue : "Single Player")); + const char *gametype_name; + + if (!multiplayer && newgametype == GT_COOP) + { + gametype_name = M_GetText("Single Player"); + } + else + { + gametype_name = Gametype_Names[newgametype]; + } + + CONS_Alert(CONS_WARNING, M_GetText("%s (%s) doesn't support %s mode!\n(Use -force to override)\n"), + realmapname, G_BuildMapName(newmapnum), gametype_name); Z_Free(realmapname); Z_Free(mapname); return; @@ -2044,7 +2083,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) { char mapname[MAX_WADPATH+1]; UINT8 flags; - INT32 resetplayer = 1, lastgametype; + INT32 resetplayer = 1; UINT8 skipprecutscene, FLS; INT16 mapnumber; @@ -2076,7 +2115,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) G_SetGametype(gametype); if (gametype != lastgametype) - D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype + D_GameTypeChanged(); skipprecutscene = ((flags & (1<<2)) != 0); @@ -3955,22 +3994,13 @@ static void Command_ModDetails_f(void) // static void Command_ShowGametype_f(void) { - const char *gametypestr = NULL; - - if (!(netgame || multiplayer)) // print "Single player" instead of "Co-op" + if (!(netgame || multiplayer) && gametype == GT_COOP) // print "Single player" instead of "Co-op" { - CONS_Printf(M_GetText("Current gametype is %s\n"), M_GetText("Single player")); + CONS_Printf(M_GetText("Current gametype is %s\n"), M_GetText("Single Player")); return; } - // get name string for current gametype - if (gametype >= 0 && gametype < gametypecount) - gametypestr = Gametype_Names[gametype]; - - if (gametypestr) - CONS_Printf(M_GetText("Current gametype is %s\n"), gametypestr); - else // string for current gametype was not found above (should never happen) - CONS_Printf(M_GetText("Unknown gametype set (%d)\n"), gametype); + CONS_Printf(M_GetText("Current gametype is %s\n"), Gametype_Names[gametype]); } /** Plays the intro. @@ -4210,7 +4240,14 @@ static void TimeLimit_OnChange(void) // Some people might like to use them together. It works. } else if (netgame || multiplayer) - CONS_Printf(M_GetText("Time limit disabled\n")); + { + if (timelimitintics != 0) + { + CONS_Printf(M_GetText("Time limit disabled\n")); + } + + timelimitintics = 0; + } } /** Adjusts certain settings to match a changed gametype. @@ -4220,20 +4257,13 @@ static void TimeLimit_OnChange(void) * \author Graue <graue@oceanbase.org> * \todo Get rid of the hardcoded stuff, ugly stuff, etc. */ -void D_GameTypeChanged(INT32 lastgametype) +void D_GameTypeChanged(void) { - if (netgame) + if (netgame && lastgametype != -1) { - const char *oldgt = NULL, *newgt = NULL; - - if (lastgametype >= 0 && lastgametype < gametypecount) - oldgt = Gametype_Names[lastgametype]; - if (gametype >= 0 && lastgametype < gametypecount) - newgt = Gametype_Names[gametype]; - - if (oldgt && newgt) - CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), oldgt, newgt); + CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), Gametype_Names[lastgametype], Gametype_Names[gametype]); } + // Only do the following as the server, not as remote admin. // There will always be a server, and this only needs to be done once. if (server && (multiplayer || netgame)) @@ -4293,10 +4323,6 @@ void D_GameTypeChanged(INT32 lastgametype) break; } } - else if (!multiplayer && !netgame) - { - G_SetGametype(GT_COOP); - } // reset timelimit and pointlimit in race/coop, prevent stupid cheats if (server) diff --git a/src/netcode/d_netcmd.h b/src/netcode/d_netcmd.h index c11575575fc025bcce4ad755651e3b77493233db..a9a91d8b22c3bbe2c7e5cec7ee05eb85e666b002 100644 --- a/src/netcode/d_netcmd.h +++ b/src/netcode/d_netcmd.h @@ -203,7 +203,7 @@ boolean EnsurePlayerNameIsGood(char *name, INT32 playernum); void D_SendPlayerConfig(void); void Command_ExitGame_f(void); void Command_Retry_f(void); -void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore +void D_GameTypeChanged(void); void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pultmode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect); boolean IsPlayerAdmin(INT32 playernum); void SetAdminPlayer(INT32 playernum); diff --git a/src/p_inter.c b/src/p_inter.c index 27e612154dc87c1b88fec2e42e890af0d27c382e..06884beef63a4e88321a0e3e9c90d409a3ec6597 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2691,7 +2691,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if ((target->player->lives <= 1) && (netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value == 0)) ; else if ((!target->player->bot || target->player->bot == BOT_MPAI) && !target->player->spectator && (target->player->lives != INFLIVES) - && G_GametypeUsesLives()) + && G_CanLoseLivesInGametype()) { if (!(target->player->pflags & PF_FINISHED)) target->player->lives -= 1; // Lose a life Tails 03-11-2000 diff --git a/src/st_stuff.c b/src/st_stuff.c index 4fdacd51ada1871c4a711f91749e0d9b39872796..4541b0adb3e590c096a85e8b730775dad51a116e 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -968,7 +968,7 @@ static void ST_drawLivesArea(void) } else { - if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1)) && !(stplyr->pflags & PF_FINISHED)) + if (G_CanLoseLivesInGametype() && stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1)) && !(stplyr->pflags & PF_FINISHED)) livescount++; if (livescount > 99) livescount = 99; diff --git a/src/y_inter.c b/src/y_inter.c index d7e644567eb14030e1bbb569434e1db460d8b56c..e2343b530dc1d1b81aadf48a542cef7ba1fd70d2 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -165,7 +165,22 @@ static INT32 tallydonetic = -1; static INT32 endtic = -1; intertype_t intertype = int_none; -intertype_t intermissiontypes[NUMGAMETYPES]; +intertype_t intermissiontypes[NUMGAMETYPES] = +{ + int_coop, // GT_COOP + int_comp, // GT_COMPETITION + int_race, // GT_RACE + + int_match, // GT_MATCH + int_teammatch, // GT_TEAMMATCH + + int_match, // GT_TAG + int_match, // GT_HIDEANDSEEK + + int_ctf, // GT_CTF + + int_none // GT_HUB +}; static huddrawlist_h luahuddrawlist_intermission; @@ -1275,25 +1290,11 @@ void Y_Ticker(void) // void Y_DetermineIntermissionType(void) { - // set to int_none initially - intertype = int_none; + intertype = intermissiontypes[gametype]; - if (intermissiontypes[gametype] != int_none) - intertype = intermissiontypes[gametype]; - else if (gametype == GT_COOP) - intertype = (G_IsSpecialStage(gamemap)) ? int_spec : int_coop; - else if (gametype == GT_TEAMMATCH) - intertype = int_teammatch; - else if (gametype == GT_MATCH - || gametype == GT_TAG - || gametype == GT_HIDEANDSEEK) - intertype = int_match; - else if (gametype == GT_RACE) - intertype = int_race; - else if (gametype == GT_COMPETITION) - intertype = int_comp; - else if (gametype == GT_CTF) - intertype = int_ctf; + // Special case for special stages + if (intertype == int_coop && G_IsSpecialStage(gamemap)) + intertype = int_spec; } //