From e4bd5d085d05d6e3464294cfd962e66d714e8624 Mon Sep 17 00:00:00 2001 From: danij Date: Thu, 30 Oct 2008 06:43:30 +0000 Subject: [PATCH] Fixed various issues with save games. * jHexen - After map load the current weapon would lower and then raise again. (pendingWeapon was never saved and instead was set to currentWeapon in SV_ReadPlayer). * jHexen - player_t->airCounter was only added in player seg ver 2 (fail alignment check). * jHexen - Texture archive ver 0 support was broken. * jHexen - Removed the requirement that polyobjs be saved in the order as found by the original algorithm used to locate them in the map data. Instead wait till the tag has been read and select the associated polyobj using it. * All Games - Interpretation of the old ML_MAPPED flag was broken. --- doomsday/plugins/common/include/p_svtexarc.h | 2 +- doomsday/plugins/common/src/p_saveg.c | 46 ++++++++++-------- doomsday/plugins/common/src/p_svtexarc.c | 51 +++++++++++++------- doomsday/plugins/common/src/p_xgsave.c | 2 +- 4 files changed, 62 insertions(+), 39 deletions(-) diff --git a/doomsday/plugins/common/include/p_svtexarc.h b/doomsday/plugins/common/include/p_svtexarc.h index 3408463338..908d6b6ed2 100644 --- a/doomsday/plugins/common/include/p_svtexarc.h +++ b/doomsday/plugins/common/include/p_svtexarc.h @@ -32,7 +32,7 @@ void SV_InitMaterialArchives(void); unsigned short SV_MaterialArchiveNum(materialnum_t num); -materialnum_t SV_GetArchiveMaterial(int archiveID); +materialnum_t SV_GetArchiveMaterial(int archiveID, int group); void SV_WriteMaterialArchive(void); void SV_ReadMaterialArchive(int version); diff --git a/doomsday/plugins/common/src/p_saveg.c b/doomsday/plugins/common/src/p_saveg.c index 0272df55cb..bc7c036b17 100644 --- a/doomsday/plugins/common/src/p_saveg.c +++ b/doomsday/plugins/common/src/p_saveg.c @@ -1095,9 +1095,8 @@ static void SV_WritePlayer(int playernum) } SV_WriteLong(p->readyWeapon); -#if !__JHEXEN__ SV_WriteLong(p->pendingWeapon); -#endif + for(i = 0; i < GetPlayerHeader()->numWeapons; ++i) { SV_WriteLong(p->weapons[i].owned); @@ -1269,12 +1268,13 @@ static void SV_ReadPlayer(player_t *p) p->frags[i] = SV_ReadLong(); } -#if __JHEXEN__ - p->pendingWeapon = p->readyWeapon = SV_ReadLong(); -#else p->readyWeapon = SV_ReadLong(); - p->pendingWeapon = SV_ReadLong(); +#if __JHEXEN__ + if(ver < 5) + p->pendingWeapon = WT_NOCHANGE; + else #endif + p->pendingWeapon = SV_ReadLong(); for(i = 0; i < GetPlayerHeader()->numWeapons; ++i) { @@ -1366,7 +1366,8 @@ static void SV_ReadPlayer(player_t *p) p->morphTics = SV_ReadLong(); #endif - p->airCounter = SV_ReadLong(); + if(ver >= 2) + p->airCounter = SV_ReadLong(); #if __JHEXEN__ p->jumpTics = SV_ReadLong(); @@ -2322,8 +2323,8 @@ static void SV_ReadSector(sector_t *sec) #endif { // The flat numbers are actually archive numbers. - floorMaterial = SV_GetArchiveMaterial(SV_ReadShort()); - ceilingMaterial = SV_GetArchiveMaterial(SV_ReadShort()); + floorMaterial = SV_GetArchiveMaterial(SV_ReadShort(), 0); + ceilingMaterial = SV_GetArchiveMaterial(SV_ReadShort(), 0); } P_SetIntp(sec, DMU_FLOOR_MATERIAL, floorMaterial); @@ -2519,10 +2520,12 @@ static void SV_ReadLine(linedef_t *li) flags = SV_ReadShort(); if(ver < 3 && (flags & 0x0100)) // the old ML_MAPPED flag { + uint lineIDX = P_ToIndex(li); + // Set line as having been seen by all players.. - memset(&xli->mapped, 1, sizeof(&xli->mapped)); + memset(xli->mapped, 0, sizeof(xli->mapped)); for(i = 0; i < MAXPLAYERS; ++i) - AM_UpdateLinedef(i, P_ToIndex(li), true); + AM_UpdateLinedef(i, lineIDX, true); flags &= ~0x0100; // remove the old flag. } xli->flags = flags; @@ -2548,14 +2551,15 @@ static void SV_ReadLine(linedef_t *li) // For each side for(i = 0; i < 2; ++i) { - sidedef_t *si = P_GetPtrp(li, (i? DMU_SIDEDEF1:DMU_SIDEDEF0)); + sidedef_t* si = P_GetPtrp(li, (i? DMU_SIDEDEF1:DMU_SIDEDEF0)); + if(!si) continue; // Versions latter than 2 store per surface texture offsets. if(ver >= 2) { - float offset[2]; + float offset[2]; offset[VX] = (float) SV_ReadShort(); offset[VY] = (float) SV_ReadShort(); @@ -2586,9 +2590,9 @@ static void SV_ReadLine(linedef_t *li) #endif { // The texture numbers are archive numbers. - topMaterial = SV_GetArchiveMaterial(SV_ReadShort()); - bottomMaterial = SV_GetArchiveMaterial(SV_ReadShort()); - middleMaterial = SV_GetArchiveMaterial(SV_ReadShort()); + topMaterial = SV_GetArchiveMaterial(SV_ReadShort(), 1); + bottomMaterial = SV_GetArchiveMaterial(SV_ReadShort(), 1); + middleMaterial = SV_GetArchiveMaterial(SV_ReadShort(), 1); } P_SetIntp(si, DMU_TOP_MATERIAL, topMaterial); @@ -2636,17 +2640,19 @@ static void SV_WritePolyObj(polyobj_t* po) SV_WriteLong(FLT2FIX(po->startSpot.pos[VY])); } -static int SV_ReadPolyObj(polyobj_t* po) +static int SV_ReadPolyObj(void) { int ver; float deltaX; float deltaY; angle_t angle; + polyobj_t* po; if(saveVersion >= 3) ver = SV_ReadByte(); - if(SV_ReadLong() != po->tag) + po = PO_GetPolyobj(SV_ReadLong()); // Get polyobj by tag. + if(!po) Con_Error("UnarchivePolyobjs: Invalid polyobj tag"); angle = (angle_t) SV_ReadLong(); @@ -2722,7 +2728,7 @@ static void P_UnArchiveWorld(void) Con_Error("UnarchivePolyobjs: Bad polyobj count"); for(i = 0; i < numpolyobjs; ++i) - SV_ReadPolyObj(PO_GetPolyobj(i | 0x80000000)); + SV_ReadPolyObj(); #endif } @@ -2983,7 +2989,7 @@ static int SV_ReadFloor(floor_t* floor) floor->newSpecial = SV_ReadLong(); if(ver >= 2) - floor->material = SV_GetArchiveMaterial(SV_ReadShort()); + floor->material = SV_GetArchiveMaterial(SV_ReadShort(), 0); else floor->material = R_MaterialNumForName(W_LumpName(SV_ReadShort()), MAT_FLAT); diff --git a/doomsday/plugins/common/src/p_svtexarc.c b/doomsday/plugins/common/src/p_svtexarc.c index 0487063fb4..ef19908cae 100644 --- a/doomsday/plugins/common/src/p_svtexarc.c +++ b/doomsday/plugins/common/src/p_svtexarc.c @@ -59,14 +59,14 @@ // TYPES ------------------------------------------------------------------- typedef struct { - char name[9]; - materialtype_t type; + char name[9]; + materialgroup_t group; } materialentry_t; typedef struct { //// \todo Remove fixed limit. - materialentry_t table[MAX_ARCHIVED_MATERIALS]; - int count; + materialentry_t table[MAX_ARCHIVED_MATERIALS]; + int count, version; } materialarchive_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- @@ -83,6 +83,8 @@ materialarchive_t matArchive; // PRIVATE DATA DEFINITIONS ------------------------------------------------ +static int numFlats; // Used with older versions. + // CODE -------------------------------------------------------------------- /** @@ -106,7 +108,7 @@ void SV_PrepareMaterial(materialnum_t num, materialarchive_t* arc) // Has this already been registered? for(c = 0; c < arc->count; c++) { - if(arc->table[c].type == info.type && + if(arc->table[c].group == info.group && !stricmp(arc->table[c].name, name)) { break;// Yes, skip it... @@ -116,7 +118,7 @@ void SV_PrepareMaterial(materialnum_t num, materialarchive_t* arc) if(c == arc->count) { strcpy(arc->table[arc->count++].name, name); - arc->table[arc->count - 1].type = info.type; + arc->table[arc->count - 1].group = info.group; } } @@ -173,13 +175,26 @@ unsigned short SV_MaterialArchiveNum(materialnum_t num) return SV_SearchArchive(&matArchive, name); } -materialnum_t SV_GetArchiveMaterial(int archivenum) +materialnum_t SV_GetArchiveMaterial(int archivenum, int group) { + if(matArchive.version < 1 && group == 1) + { + archivenum += numFlats; + } + + if(!(archivenum < matArchive.count)) + { +#if _DEBUG + Con_Error("SV_GetArchiveMaterial: Bad archivenum %i.", archivenum); +#endif + return 0; + } + if(!strncmp(matArchive.table[archivenum].name, BADTEXNAME, 8)) return 0; else return R_MaterialNumForName(matArchive.table[archivenum].name, - matArchive.table[archivenum].type); + matArchive.table[archivenum].group); return 0; } @@ -191,12 +206,11 @@ void SV_WriteMaterialArchive(void) for(i = 0; i < matArchive.count; ++i) { SV_Write(matArchive.table[i].name, 8); - SV_WriteByte(matArchive.table[i].type); + SV_WriteByte(matArchive.table[i].group); } } -static void readMatArchive(materialarchive_t *arc, int version, - materialtype_t defaultType) +static void readMatArchive(materialarchive_t* arc, materialgroup_t defaultGroup) { int i, num; @@ -205,10 +219,10 @@ static void readMatArchive(materialarchive_t *arc, int version, { SV_Read(arc->table[i].name, 8); arc->table[i].name[8] = 0; - if(version >= 1) - arc->table[i].type = SV_ReadByte(); + if(arc->version >= 1) + arc->table[i].group = SV_ReadByte(); else - arc->table[i].type = defaultType; + arc->table[i].group = defaultGroup; } arc->count += num; @@ -217,10 +231,13 @@ static void readMatArchive(materialarchive_t *arc, int version, void SV_ReadMaterialArchive(int version) { matArchive.count = 0; - readMatArchive(&matArchive, version, MAT_FLAT); + matArchive.version = version; + readMatArchive(&matArchive, MAT_FLAT); - if(version == 0) + if(matArchive.version == 0) { // The old format saved textures and flats in seperate blocks. - readMatArchive(&matArchive, version, MAT_TEXTURE); + numFlats = matArchive.count; + + readMatArchive(&matArchive, MAT_TEXTURE); } } diff --git a/doomsday/plugins/common/src/p_xgsave.c b/doomsday/plugins/common/src/p_xgsave.c index a2a9c6670a..f165aece73 100644 --- a/doomsday/plugins/common/src/p_xgsave.c +++ b/doomsday/plugins/common/src/p_xgsave.c @@ -267,7 +267,7 @@ int SV_ReadXGPlaneMover(xgplanemover_t* mov) mov->crushSpeed = FIX2FLT(SV_ReadLong()); num = SV_ReadLong(); if(ver >= 3) - mov->setMaterial = SV_GetArchiveMaterial(num); + mov->setMaterial = SV_GetArchiveMaterial(num, 0); else mov->setMaterial = R_MaterialNumForName(W_LumpName(num), MAT_FLAT); mov->setSectorType = SV_ReadLong();