Save gclient_t::resp.coop_respawn.*weapon to fix coop savegames

This fixed bug #357 - the problem was that
client->resp.coop_respawn.weapon and .lastweapon (pointers to gitem)
were not properly initialized when loading a savegame.
Now those fields are saved (=> we had to bump the savegame version)
and for old savegames client->resp.coop_rewspawn is initialized
from client->pers, as a hack for backwards-compatibility.
This commit is contained in:
Daniel Gibson 2019-02-03 19:01:03 +01:00
parent 29bb6e5c6c
commit b44fd32572
4 changed files with 39 additions and 6 deletions

View File

@ -573,6 +573,7 @@ typedef struct
int ofs; int ofs;
fieldtype_t type; fieldtype_t type;
int flags; int flags;
short save_ver; // currently only used by clientfields[]
} field_t; } field_t;
extern field_t fields[]; extern field_t fields[];

View File

@ -71,7 +71,7 @@
* load older savegames. This should be bumped if the files * load older savegames. This should be bumped if the files
* in tables/ are changed, otherwise strange things may happen. * in tables/ are changed, otherwise strange things may happen.
*/ */
#define SAVEGAMEVER "YQ2-2" #define SAVEGAMEVER "YQ2-3"
#ifndef BUILD_DATE #ifndef BUILD_DATE
#define BUILD_DATE __DATE__ #define BUILD_DATE __DATE__
@ -733,7 +733,7 @@ WriteClient(FILE *f, gclient_t *client)
* Read the client struct from a file * Read the client struct from a file
*/ */
void void
ReadClient(FILE *f, gclient_t *client) ReadClient(FILE *f, gclient_t *client, short save_ver)
{ {
field_t *field; field_t *field;
@ -741,7 +741,14 @@ ReadClient(FILE *f, gclient_t *client)
for (field = clientfields; field->name; field++) for (field = clientfields; field->name; field++)
{ {
ReadField(f, field, (byte *)client); if(field->save_ver <= save_ver)
{
ReadField(f, field, (byte *)client);
}
}
if(save_ver < 3)
{
InitClientResp(client);
} }
} }
@ -822,6 +829,8 @@ ReadGame(const char *filename)
char str_os[32]; char str_os[32];
char str_arch[32]; char str_arch[32];
short save_ver = 0;
gi.FreeTags(TAG_GAME); gi.FreeTags(TAG_GAME);
f = Q_fopen(filename, "rb"); f = Q_fopen(filename, "rb");
@ -839,6 +848,26 @@ ReadGame(const char *filename)
if (!strcmp(str_ver, SAVEGAMEVER)) if (!strcmp(str_ver, SAVEGAMEVER))
{ {
save_ver = 3;
if (strcmp(str_game, GAMEVERSION))
{
fclose(f);
gi.error("Savegame from another game.so.\n");
}
else if (strcmp(str_os, YQ2OSTYPE))
{
fclose(f);
gi.error("Savegame from another os.\n");
}
else if (strcmp(str_arch, YQ2ARCH))
{
fclose(f);
gi.error("Savegame from another architecture.\n");
}
}
else if (!strcmp(str_ver, "YQ2-2"))
{
save_ver = 2;
if (strcmp(str_game, GAMEVERSION)) if (strcmp(str_game, GAMEVERSION))
{ {
fclose(f); fclose(f);
@ -857,6 +886,7 @@ ReadGame(const char *filename)
} }
else if (!strcmp(str_ver, "YQ2-1")) else if (!strcmp(str_ver, "YQ2-1"))
{ {
save_ver = 1;
if (strcmp(str_game, GAMEVERSION)) if (strcmp(str_game, GAMEVERSION))
{ {
fclose(f); fclose(f);
@ -901,7 +931,7 @@ ReadGame(const char *filename)
for (i = 0; i < game.maxclients; i++) for (i = 0; i < game.maxclients; i++)
{ {
ReadClient(f, &game.clients[i]); ReadClient(f, &game.clients[i], save_ver);
} }
fclose(f); fclose(f);

View File

@ -28,4 +28,6 @@
{"pers.weapon", CLOFS(pers.weapon), F_ITEM}, {"pers.weapon", CLOFS(pers.weapon), F_ITEM},
{"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM}, {"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM},
{"newweapon", CLOFS(newweapon), F_ITEM}, {"newweapon", CLOFS(newweapon), F_ITEM},
{NULL, 0, F_INT} {"resp.coop_respawn.weapon", CLOFS(resp.coop_respawn.weapon), F_ITEM, 0, 3},
{"resp.coop_respawn.lastweapon", CLOFS(resp.coop_respawn.lastweapon), F_ITEM, 0, 3},
{NULL, 0, F_INT, 0}

View File

@ -33,7 +33,7 @@ extern void WriteLevelLocals ( FILE * f ) ;
extern void WriteEdict ( FILE * f , edict_t * ent ) ; extern void WriteEdict ( FILE * f , edict_t * ent ) ;
extern void ReadGame ( const char * filename ) ; extern void ReadGame ( const char * filename ) ;
extern void WriteGame ( const char * filename , qboolean autosave ) ; extern void WriteGame ( const char * filename , qboolean autosave ) ;
extern void ReadClient ( FILE * f , gclient_t * client ) ; extern void ReadClient ( FILE * f , gclient_t * client, short save_ver ) ;
extern void WriteClient ( FILE * f , gclient_t * client ) ; extern void WriteClient ( FILE * f , gclient_t * client ) ;
extern void ReadField ( FILE * f , field_t * field , byte * base ) ; extern void ReadField ( FILE * f , field_t * field , byte * base ) ;
extern void WriteField2 ( FILE * f , field_t * field , byte * base ) ; extern void WriteField2 ( FILE * f , field_t * field , byte * base ) ;