- 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.


SVN r1069 (trunk)
This commit is contained in:
Randy Heit 2008-07-06 03:52:53 +00:00
parent 448b8955c5
commit 87d7b3601a
5 changed files with 66 additions and 49 deletions

View file

@ -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) July 5, 2008 (Changes by Graf Zahl)
- Changed: AInventory::Tick now only calls the super method if the item is not - 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 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 July 4, 2008
- Fixed: Screenwipes now pause sounds, since there can be sounds playing - Fixed: Screenwipes now pause sounds, since there can be sounds playing
during it. during them.
- UI sounds are now omitted from savegames. - UI sounds are now omitted from savegames.
- Fixed: Menu sounds had been restricted to one at a time again. - 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 - Moved the P_SerializeSounds() call to the end of G_SerializeLevel() so that

View file

@ -1989,6 +1989,13 @@ static void PutSavePic (FILE *file, int width, int height)
void G_DoSaveGame (bool okForQuicksave, FString filename, const char *description) 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) if (demoplayback)
{ {
filename = G_BuildSaveName ("demosave.zds", -1); filename = G_BuildSaveName ("demosave.zds", -1);

View file

@ -2860,10 +2860,7 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
FCanvasTextureInfo::Serialize (arc); FCanvasTextureInfo::Serialize (arc);
AM_SerializeMarkers(arc); AM_SerializeMarkers(arc);
if (!hubLoad) P_SerializePlayers (arc, hubLoad);
{
P_SerializePlayers (arc);
}
P_SerializeSounds (arc); P_SerializeSounds (arc);
} }

View file

@ -48,14 +48,14 @@
#include "r_interpolate.h" #include "r_interpolate.h"
static void CopyPlayer (player_t *dst, player_t *src, const char *name); static void CopyPlayer (player_t *dst, player_t *src, const char *name);
static void ReadOnePlayer (FArchive &arc); static void ReadOnePlayer (FArchive &arc, bool skipload);
static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNow); static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNow, bool skipload);
static void SpawnExtraPlayers (); static void SpawnExtraPlayers ();
// //
// P_ArchivePlayers // P_ArchivePlayers
// //
void P_SerializePlayers (FArchive &arc) void P_SerializePlayers (FArchive &arc, bool skipload)
{ {
BYTE numPlayers, numPlayersNow; BYTE numPlayers, numPlayersNow;
int i; int i;
@ -92,20 +92,20 @@ void P_SerializePlayers (FArchive &arc)
// first player present, no matter what their name. // first player present, no matter what their name.
if (numPlayers == 1) if (numPlayers == 1)
{ {
ReadOnePlayer (arc); ReadOnePlayer (arc, skipload);
} }
else else
{ {
ReadMultiplePlayers (arc, numPlayers, numPlayersNow); ReadMultiplePlayers (arc, numPlayers, numPlayersNow, skipload);
} }
if (numPlayersNow > numPlayers) if (!skipload && numPlayersNow > numPlayers)
{ {
SpawnExtraPlayers (); SpawnExtraPlayers ();
} }
} }
} }
static void ReadOnePlayer (FArchive &arc) static void ReadOnePlayer (FArchive &arc, bool skipload)
{ {
int i; int i;
char *name = NULL; char *name = NULL;
@ -122,7 +122,10 @@ static void ReadOnePlayer (FArchive &arc)
didIt = true; didIt = true;
player_t playerTemp; player_t playerTemp;
playerTemp.Serialize (arc); playerTemp.Serialize (arc);
CopyPlayer (&players[i], &playerTemp, name); if (!skipload)
{
CopyPlayer (&players[i], &playerTemp, name);
}
} }
else else
{ {
@ -137,7 +140,7 @@ static void ReadOnePlayer (FArchive &arc)
delete[] name; 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. // For two or more players, read each player into a temporary array.
int i, j; int i, j;
@ -158,36 +161,19 @@ static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNo
playerUsed[i] = playeringame[i] ? 0 : 2; playerUsed[i] = playeringame[i] ? 0 : 2;
} }
// Now try to match players from the savegame with players present if (!skipload)
// 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) // Now try to match players from the savegame with players present
{ // based on their names. If two players in the savegame have the
if (playerUsed[j] == 0 && stricmp(players[j].userinfo.netname, nametemp[i]) == 0) // same name, then they are assigned to players in the current game
{ // Found a match, so copy our temp player to the real player // on a first-come, first-served basis.
Printf ("Found player %d (%s) at %d\n", i, nametemp[i], j); for (i = 0; i < numPlayers; ++i)
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)
{ {
for (j = 0; j < MAXPLAYERS; ++j) for (j = 0; j < MAXPLAYERS; ++j)
{ {
if (playerUsed[j] == 0) 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 ("Assigned player %d (%s) to %d (%s)\n", i, nametemp[i], j, players[j].userinfo.netname); Printf ("Found player %d (%s) at %d\n", i, nametemp[i], j);
CopyPlayer (&players[j], &playertemp[i], nametemp[i]); CopyPlayer (&players[j], &playertemp[i], nametemp[i]);
playerUsed[j] = 1; playerUsed[j] = 1;
tempPlayerUsed[i] = 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. // Any players that didn't have matching names are assigned to existing
for (j = 0; j < MAXPLAYERS; ++j) // players on a first-come, first-served basis.
{ for (i = 0; i < numPlayers; ++i)
if (playerUsed[j] == 0)
{ {
if (players[j].mo != NULL) if (tempPlayerUsed[i] == 0)
{ {
players[j].mo->Destroy(); for (j = 0; j < MAXPLAYERS; ++j)
players[j].mo = NULL; {
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;
}
} }
} }
} }

View file

@ -39,7 +39,7 @@
// Persistent storage/archiving. // Persistent storage/archiving.
// These are the load / save game routines. // These are the load / save game routines.
// Also see farchive.(h|cpp) // Also see farchive.(h|cpp)
void P_SerializePlayers (FArchive &arc); void P_SerializePlayers (FArchive &arc, bool fakeload);
void P_SerializeWorld (FArchive &arc); void P_SerializeWorld (FArchive &arc);
void P_SerializeThinkers (FArchive &arc, bool); void P_SerializeThinkers (FArchive &arc, bool);
void P_SerializePolyobjs (FArchive &arc); void P_SerializePolyobjs (FArchive &arc);