diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5a3351cf2e..02252b94da 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,10 @@ +July 5, 2008 +- Added a check to G_DoSaveGame() to prevent saving when you're not actually + in a level. +- Fixed: Serialized player data must always be loaded, even if it's simply to + be discarded, so that anything serialized after the players will load from + the correct position in the file when revisiting a hub map. + July 5, 2008 (Changes by Graf Zahl) - Changed: AInventory::Tick now only calls the super method if the item is not owned. Having owned inventory items interact with the world is not supposed @@ -16,7 +23,7 @@ July 5, 2008 (Changes by Graf Zahl) July 4, 2008 - Fixed: Screenwipes now pause sounds, since there can be sounds playing - during it. + during them. - UI sounds are now omitted from savegames. - Fixed: Menu sounds had been restricted to one at a time again. - Moved the P_SerializeSounds() call to the end of G_SerializeLevel() so that diff --git a/src/g_game.cpp b/src/g_game.cpp index 938a289918..dab6b5f4c0 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1989,6 +1989,13 @@ static void PutSavePic (FILE *file, int width, int height) void G_DoSaveGame (bool okForQuicksave, FString filename, const char *description) { + // Do not even try, if we're not in a level. (Can happen after + // a demo finishes playback.) + if (lines == NULL || sectors == NULL) + { + return; + } + if (demoplayback) { filename = G_BuildSaveName ("demosave.zds", -1); diff --git a/src/g_level.cpp b/src/g_level.cpp index 657faff5ca..7befda5035 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -2860,10 +2860,7 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) FCanvasTextureInfo::Serialize (arc); AM_SerializeMarkers(arc); - if (!hubLoad) - { - P_SerializePlayers (arc); - } + P_SerializePlayers (arc, hubLoad); P_SerializeSounds (arc); } diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 682d6963f9..596b1367ea 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -48,14 +48,14 @@ #include "r_interpolate.h" static void CopyPlayer (player_t *dst, player_t *src, const char *name); -static void ReadOnePlayer (FArchive &arc); -static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNow); +static void ReadOnePlayer (FArchive &arc, bool skipload); +static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNow, bool skipload); static void SpawnExtraPlayers (); // // P_ArchivePlayers // -void P_SerializePlayers (FArchive &arc) +void P_SerializePlayers (FArchive &arc, bool skipload) { BYTE numPlayers, numPlayersNow; int i; @@ -92,20 +92,20 @@ void P_SerializePlayers (FArchive &arc) // first player present, no matter what their name. if (numPlayers == 1) { - ReadOnePlayer (arc); + ReadOnePlayer (arc, skipload); } else { - ReadMultiplePlayers (arc, numPlayers, numPlayersNow); + ReadMultiplePlayers (arc, numPlayers, numPlayersNow, skipload); } - if (numPlayersNow > numPlayers) + if (!skipload && numPlayersNow > numPlayers) { SpawnExtraPlayers (); } } } -static void ReadOnePlayer (FArchive &arc) +static void ReadOnePlayer (FArchive &arc, bool skipload) { int i; char *name = NULL; @@ -122,7 +122,10 @@ static void ReadOnePlayer (FArchive &arc) didIt = true; player_t playerTemp; playerTemp.Serialize (arc); - CopyPlayer (&players[i], &playerTemp, name); + if (!skipload) + { + CopyPlayer (&players[i], &playerTemp, name); + } } else { @@ -137,7 +140,7 @@ static void ReadOnePlayer (FArchive &arc) delete[] name; } -static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNow) +static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNow, bool skipload) { // For two or more players, read each player into a temporary array. int i, j; @@ -158,36 +161,19 @@ static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNo playerUsed[i] = playeringame[i] ? 0 : 2; } - // Now try to match players from the savegame with players present - // based on their names. If two players in the savegame have the - // same name, then they are assigned to players in the current game - // on a first-come, first-served basis. - for (i = 0; i < numPlayers; ++i) + if (!skipload) { - for (j = 0; j < MAXPLAYERS; ++j) - { - if (playerUsed[j] == 0 && stricmp(players[j].userinfo.netname, nametemp[i]) == 0) - { // Found a match, so copy our temp player to the real player - Printf ("Found player %d (%s) at %d\n", i, nametemp[i], j); - CopyPlayer (&players[j], &playertemp[i], nametemp[i]); - playerUsed[j] = 1; - tempPlayerUsed[i] = 1; - break; - } - } - } - - // Any players that didn't have matching names are assigned to existing - // players on a first-come, first-served basis. - for (i = 0; i < numPlayers; ++i) - { - if (tempPlayerUsed[i] == 0) + // Now try to match players from the savegame with players present + // based on their names. If two players in the savegame have the + // same name, then they are assigned to players in the current game + // on a first-come, first-served basis. + for (i = 0; i < numPlayers; ++i) { for (j = 0; j < MAXPLAYERS; ++j) { - if (playerUsed[j] == 0) - { - Printf ("Assigned player %d (%s) to %d (%s)\n", i, nametemp[i], j, players[j].userinfo.netname); + if (playerUsed[j] == 0 && stricmp(players[j].userinfo.netname, nametemp[i]) == 0) + { // Found a match, so copy our temp player to the real player + Printf ("Found player %d (%s) at %d\n", i, nametemp[i], j); CopyPlayer (&players[j], &playertemp[i], nametemp[i]); playerUsed[j] = 1; tempPlayerUsed[i] = 1; @@ -195,17 +181,37 @@ static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNo } } } - } - // Make sure any extra players don't have actors spawned yet. - for (j = 0; j < MAXPLAYERS; ++j) - { - if (playerUsed[j] == 0) + // Any players that didn't have matching names are assigned to existing + // players on a first-come, first-served basis. + for (i = 0; i < numPlayers; ++i) { - if (players[j].mo != NULL) + if (tempPlayerUsed[i] == 0) { - players[j].mo->Destroy(); - players[j].mo = NULL; + for (j = 0; j < MAXPLAYERS; ++j) + { + if (playerUsed[j] == 0) + { + Printf ("Assigned player %d (%s) to %d (%s)\n", i, nametemp[i], j, players[j].userinfo.netname); + CopyPlayer (&players[j], &playertemp[i], nametemp[i]); + playerUsed[j] = 1; + tempPlayerUsed[i] = 1; + break; + } + } + } + } + + // Make sure any extra players don't have actors spawned yet. + for (j = 0; j < MAXPLAYERS; ++j) + { + if (playerUsed[j] == 0) + { + if (players[j].mo != NULL) + { + players[j].mo->Destroy(); + players[j].mo = NULL; + } } } } diff --git a/src/p_saveg.h b/src/p_saveg.h index edb73e67ee..09f5f28e21 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -39,7 +39,7 @@ // Persistent storage/archiving. // These are the load / save game routines. // Also see farchive.(h|cpp) -void P_SerializePlayers (FArchive &arc); +void P_SerializePlayers (FArchive &arc, bool fakeload); void P_SerializeWorld (FArchive &arc); void P_SerializeThinkers (FArchive &arc, bool); void P_SerializePolyobjs (FArchive &arc);