diff --git a/doomsday/plugins/common/include/p_saveg.h b/doomsday/plugins/common/include/p_saveg.h index cdd23158e6..bf83d7221f 100644 --- a/doomsday/plugins/common/include/p_saveg.h +++ b/doomsday/plugins/common/include/p_saveg.h @@ -119,6 +119,23 @@ mobj_t *SV_GetArchiveThing(ThingSerialId thingid, void *address); */ void SV_TranslateLegacyMobjFlags(mobj_t *mo, int ver); +typedef struct playerheader_s { + int numPowers; + int numKeys; + int numFrags; + int numWeapons; + int numAmmoTypes; + int numPSprites; +#if __JDOOM64__ || __JHERETIC__ || __JHEXEN__ + int numInvItemTypes; +#endif +#if __JHEXEN__ + int numArmorTypes; +#endif +} playerheader_t; + +playerheader_t *SV_GetPlayerHeader(void); + #if __JHEXEN__ void SV_HxSaveHubMap(void); void SV_HxLoadHubMap(void); diff --git a/doomsday/plugins/common/include/player.h b/doomsday/plugins/common/include/player.h index b6675d768e..76f9b72b65 100644 --- a/doomsday/plugins/common/include/player.h +++ b/doomsday/plugins/common/include/player.h @@ -71,7 +71,7 @@ weapontype_t P_WeaponSlotCycle(weapontype_t type, dd_bool prev); * * @return Number of the given player. */ -int P_GetPlayerNum(player_t *plr); +int P_GetPlayerNum(player_t const *plr); /** * Return a bit field for the current player's cheats. diff --git a/doomsday/plugins/common/src/p_saveg.cpp b/doomsday/plugins/common/src/p_saveg.cpp index 32e173a180..c7503c7f0d 100644 --- a/doomsday/plugins/common/src/p_saveg.cpp +++ b/doomsday/plugins/common/src/p_saveg.cpp @@ -23,49 +23,30 @@ #include "d_net.h" #include "dmu_lib.h" +#include "g_common.h" #if __JHERETIC__ || __JHEXEN__ # include "hu_inventory.h" #endif -#include "mobj.h" #include "p_actor.h" -#include "p_map.h" -#include "p_mapsetup.h" +#include "p_map.h" // P_TelefragMobjsTouchingPlayers +#include "p_mapsetup.h" // P_SpawnAllMaterialOriginScrollers #include "p_inventory.h" -#include "p_tick.h" -#include "r_common.h" -#include "p_savedef.h" +#include "p_tick.h" // mapTime #include "p_saveio.h" #include "polyobjs.h" #include "mapstatereader.h" #include "mapstatewriter.h" +#include "r_common.h" // R_UpdateConsoleView #include #include #include #include #include -using namespace dmu_lib; - -struct playerheader_t -{ - int numPowers; - int numKeys; - int numFrags; - int numWeapons; - int numAmmoTypes; - int numPSprites; -#if __JDOOM64__ || __JHERETIC__ || __JHEXEN__ - int numInvItemTypes; -#endif -#if __JHEXEN__ - int numArmorTypes; -#endif -}; - static bool inited = false; -SaveSlots ss(NUMSAVESLOTS); -SaveSlots *saveSlots = &ss; +static SaveSlots sslots(NUMSAVESLOTS); +SaveSlots *saveSlots = &sslots; static SaveInfo const *curInfo; @@ -408,447 +389,12 @@ mobj_t *SV_GetArchiveThing(ThingSerialId thingId, void *address) return thingArchive[thingId]; } -static playerheader_t *getPlayerHeader() +playerheader_t *SV_GetPlayerHeader() { DENG_ASSERT(playerHeaderOK); return &playerHeader; } -/** - * Writes the given player's data (not including the ID number). - */ -static void SV_WritePlayer(int playernum, Writer *writer) -{ - int i, numPSprites = getPlayerHeader()->numPSprites; - player_t temp, *p = &temp; - ddplayer_t ddtemp, *dp = &ddtemp; - - // Make a copy of the player. - std::memcpy(p, &players[playernum], sizeof(temp)); - std::memcpy(dp, players[playernum].plr, sizeof(ddtemp)); - temp.plr = &ddtemp; - - // Convert the psprite states. - for(i = 0; i < numPSprites; ++i) - { - pspdef_t *pspDef = &temp.pSprites[i]; - - if(pspDef->state) - { - pspDef->state = (state_t *) (pspDef->state - STATES); - } - } - - // Version number. Increase when you make changes to the player data - // segment format. - Writer_WriteByte(writer, 6); - -#if __JHEXEN__ - // Class. - Writer_WriteByte(writer, cfg.playerClass[playernum]); -#endif - - Writer_WriteInt32(writer, p->playerState); -#if __JHEXEN__ - Writer_WriteInt32(writer, p->class_); // 2nd class...? -#endif - Writer_WriteInt32(writer, FLT2FIX(p->viewZ)); - Writer_WriteInt32(writer, FLT2FIX(p->viewHeight)); - Writer_WriteInt32(writer, FLT2FIX(p->viewHeightDelta)); -#if !__JHEXEN__ - Writer_WriteFloat(writer, dp->lookDir); -#endif - Writer_WriteInt32(writer, FLT2FIX(p->bob)); -#if __JHEXEN__ - Writer_WriteInt32(writer, p->flyHeight); - Writer_WriteFloat(writer, dp->lookDir); - Writer_WriteInt32(writer, p->centering); -#endif - Writer_WriteInt32(writer, p->health); - -#if __JHEXEN__ - for(i = 0; i < getPlayerHeader()->numArmorTypes; ++i) - { - Writer_WriteInt32(writer, p->armorPoints[i]); - } -#else - Writer_WriteInt32(writer, p->armorPoints); - Writer_WriteInt32(writer, p->armorType); -#endif - -#if __JDOOM64__ || __JHEXEN__ - for(i = 0; i < getPlayerHeader()->numInvItemTypes; ++i) - { - inventoryitemtype_t type = inventoryitemtype_t(IIT_FIRST + i); - - Writer_WriteInt32(writer, type); - Writer_WriteInt32(writer, P_InventoryCount(playernum, type)); - } - Writer_WriteInt32(writer, P_InventoryReadyItem(playernum)); -#endif - - for(i = 0; i < getPlayerHeader()->numPowers; ++i) - { - Writer_WriteInt32(writer, p->powers[i]); - } - -#if __JHEXEN__ - Writer_WriteInt32(writer, p->keys); -#else - for(i = 0; i < getPlayerHeader()->numKeys; ++i) - { - Writer_WriteInt32(writer, p->keys[i]); - } -#endif - -#if __JHEXEN__ - Writer_WriteInt32(writer, p->pieces); -#else - Writer_WriteInt32(writer, p->backpack); -#endif - - for(i = 0; i < getPlayerHeader()->numFrags; ++i) - { - Writer_WriteInt32(writer, p->frags[i]); - } - - Writer_WriteInt32(writer, p->readyWeapon); - Writer_WriteInt32(writer, p->pendingWeapon); - - for(i = 0; i < getPlayerHeader()->numWeapons; ++i) - { - Writer_WriteInt32(writer, p->weapons[i].owned); - } - - for(i = 0; i < getPlayerHeader()->numAmmoTypes; ++i) - { - Writer_WriteInt32(writer, p->ammo[i].owned); -#if !__JHEXEN__ - Writer_WriteInt32(writer, p->ammo[i].max); -#endif - } - - Writer_WriteInt32(writer, p->attackDown); - Writer_WriteInt32(writer, p->useDown); - - Writer_WriteInt32(writer, p->cheats); - - Writer_WriteInt32(writer, p->refire); - - Writer_WriteInt32(writer, p->killCount); - Writer_WriteInt32(writer, p->itemCount); - Writer_WriteInt32(writer, p->secretCount); - - Writer_WriteInt32(writer, p->damageCount); - Writer_WriteInt32(writer, p->bonusCount); -#if __JHEXEN__ - Writer_WriteInt32(writer, p->poisonCount); -#endif - - Writer_WriteInt32(writer, dp->extraLight); - Writer_WriteInt32(writer, dp->fixedColorMap); - Writer_WriteInt32(writer, p->colorMap); - - for(i = 0; i < numPSprites; ++i) - { - pspdef_t *psp = &p->pSprites[i]; - - Writer_WriteInt32(writer, PTR2INT(psp->state)); - Writer_WriteInt32(writer, psp->tics); - Writer_WriteInt32(writer, FLT2FIX(psp->pos[VX])); - Writer_WriteInt32(writer, FLT2FIX(psp->pos[VY])); - } - -#if !__JHEXEN__ - Writer_WriteInt32(writer, p->didSecret); - - // Added in ver 2 with __JDOOM__ - Writer_WriteInt32(writer, p->flyHeight); -#endif - -#if __JHERETIC__ - for(i = 0; i < getPlayerHeader()->numInvItemTypes; ++i) - { - inventoryitemtype_t type = inventoryitemtype_t(IIT_FIRST + i); - - Writer_WriteInt32(writer, type); - Writer_WriteInt32(writer, P_InventoryCount(playernum, type)); - } - Writer_WriteInt32(writer, P_InventoryReadyItem(playernum)); - Writer_WriteInt32(writer, p->chickenPeck); -#endif - -#if __JHERETIC__ || __JHEXEN__ - Writer_WriteInt32(writer, p->morphTics); -#endif - - Writer_WriteInt32(writer, p->airCounter); - -#if __JHEXEN__ - Writer_WriteInt32(writer, p->jumpTics); - Writer_WriteInt32(writer, p->worldTimer); -#elif __JHERETIC__ - Writer_WriteInt32(writer, p->flameCount); - - // Added in ver 2 - Writer_WriteByte(writer, p->class_); -#endif -} - -/** - * Reads a player's data (not including the ID number). - */ -static void SV_ReadPlayer(player_t *p, Reader *reader) -{ - int plrnum = p - players; - int numPSprites = getPlayerHeader()->numPSprites; - ddplayer_t *dp = p->plr; - - byte ver = Reader_ReadByte(reader); - -#if __JHEXEN__ - cfg.playerClass[plrnum] = playerclass_t(Reader_ReadByte(reader)); - - de::zapPtr(p); // Force everything NULL, - p->plr = dp; // but restore the ddplayer pointer. -#endif - - p->playerState = playerstate_t(Reader_ReadInt32(reader)); -#if __JHEXEN__ - p->class_ = playerclass_t(Reader_ReadInt32(reader)); // 2nd class?? (ask Raven...) -#endif - - p->viewZ = FIX2FLT(Reader_ReadInt32(reader)); - p->viewHeight = FIX2FLT(Reader_ReadInt32(reader)); - p->viewHeightDelta = FIX2FLT(Reader_ReadInt32(reader)); -#if !__JHEXEN__ - dp->lookDir = Reader_ReadFloat(reader); -#endif - p->bob = FIX2FLT(Reader_ReadInt32(reader)); -#if __JHEXEN__ - p->flyHeight = Reader_ReadInt32(reader); - dp->lookDir = Reader_ReadFloat(reader); - p->centering = Reader_ReadInt32(reader); -#endif - - p->health = Reader_ReadInt32(reader); - -#if __JHEXEN__ - for(int i = 0; i < getPlayerHeader()->numArmorTypes; ++i) - { - p->armorPoints[i] = Reader_ReadInt32(reader); - } -#else - p->armorPoints = Reader_ReadInt32(reader); - p->armorType = Reader_ReadInt32(reader); -#endif - -#if __JDOOM64__ || __JHEXEN__ - P_InventoryEmpty(plrnum); - for(int i = 0; i < getPlayerHeader()->numInvItemTypes; ++i) - { - inventoryitemtype_t type = inventoryitemtype_t(Reader_ReadInt32(reader)); - int count = Reader_ReadInt32(reader); - - for(int k = 0; k < count; ++k) - { - P_InventoryGive(plrnum, type, true); - } - } - - P_InventorySetReadyItem(plrnum, inventoryitemtype_t(Reader_ReadInt32(reader))); -# if __JHEXEN__ - Hu_InventorySelect(plrnum, P_InventoryReadyItem(plrnum)); - if(ver < 5) - { - /*pl->artifactCount =*/ Reader_ReadInt32(reader); - } - if(ver < 6) - { - /*p->inventorySlotNum =*/ Reader_ReadInt32(reader); - } -# endif -#endif - - for(int i = 0; i < getPlayerHeader()->numPowers; ++i) - { - p->powers[i] = Reader_ReadInt32(reader); - } - if(p->powers[PT_ALLMAP]) - { - ST_RevealAutomap(plrnum, true); - } - -#if __JHEXEN__ - p->keys = Reader_ReadInt32(reader); -#else - for(int i = 0; i < getPlayerHeader()->numKeys; ++i) - { - p->keys[i] = Reader_ReadInt32(reader); - } -#endif - -#if __JHEXEN__ - p->pieces = Reader_ReadInt32(reader); -#else - p->backpack = Reader_ReadInt32(reader); -#endif - - for(int i = 0; i < getPlayerHeader()->numFrags; ++i) - { - p->frags[i] = Reader_ReadInt32(reader); - } - - p->readyWeapon = weapontype_t(Reader_ReadInt32(reader)); -#if __JHEXEN__ - if(ver < 5) - p->pendingWeapon = WT_NOCHANGE; - else -#endif - p->pendingWeapon = weapontype_t(Reader_ReadInt32(reader)); - - for(int i = 0; i < getPlayerHeader()->numWeapons; ++i) - { - p->weapons[i].owned = (Reader_ReadInt32(reader)? true : false); - } - - for(int i = 0; i < getPlayerHeader()->numAmmoTypes; ++i) - { - p->ammo[i].owned = Reader_ReadInt32(reader); - -#if !__JHEXEN__ - p->ammo[i].max = Reader_ReadInt32(reader); -#endif - } - - p->attackDown = Reader_ReadInt32(reader); - p->useDown = Reader_ReadInt32(reader); - p->cheats = Reader_ReadInt32(reader); - p->refire = Reader_ReadInt32(reader); - p->killCount = Reader_ReadInt32(reader); - p->itemCount = Reader_ReadInt32(reader); - p->secretCount = Reader_ReadInt32(reader); - -#if __JHEXEN__ - if(ver <= 1) - { - /*p->messageTics =*/ Reader_ReadInt32(reader); - /*p->ultimateMessage =*/ Reader_ReadInt32(reader); - /*p->yellowMessage =*/ Reader_ReadInt32(reader); - } -#endif - - p->damageCount = Reader_ReadInt32(reader); - p->bonusCount = Reader_ReadInt32(reader); -#if __JHEXEN__ - p->poisonCount = Reader_ReadInt32(reader); -#endif - - dp->extraLight = Reader_ReadInt32(reader); - dp->fixedColorMap = Reader_ReadInt32(reader); - - p->colorMap = Reader_ReadInt32(reader); - - for(int i = 0; i < numPSprites; ++i) - { - pspdef_t *psp = &p->pSprites[i]; - - psp->state = INT2PTR(state_t, Reader_ReadInt32(reader)); - psp->tics = Reader_ReadInt32(reader); - psp->pos[VX] = FIX2FLT(Reader_ReadInt32(reader)); - psp->pos[VY] = FIX2FLT(Reader_ReadInt32(reader)); - } - -#if !__JHEXEN__ - p->didSecret = Reader_ReadInt32(reader); - -# if __JDOOM__ || __JDOOM64__ - if(ver == 2) - { - /*p->messageTics =*/ Reader_ReadInt32(reader); - } - - if(ver >= 2) - { - p->flyHeight = Reader_ReadInt32(reader); - } - -# elif __JHERETIC__ - if(ver < 3) - { - /*p->messageTics =*/ Reader_ReadInt32(reader); - } - - p->flyHeight = Reader_ReadInt32(reader); - - P_InventoryEmpty(plrnum); - for(int i = 0; i < getPlayerHeader()->numInvItemTypes; ++i) - { - inventoryitemtype_t type = inventoryitemtype_t(Reader_ReadInt32(reader)); - int count = Reader_ReadInt32(reader); - - for(int k = 0; k < count; ++k) - { - P_InventoryGive(plrnum, type, true); - } - } - - P_InventorySetReadyItem(plrnum, (inventoryitemtype_t) Reader_ReadInt32(reader)); - Hu_InventorySelect(plrnum, P_InventoryReadyItem(plrnum)); - if(ver < 5) - { - Reader_ReadInt32(reader); // Current inventory item count? - } - if(ver < 6) - { - /*p->inventorySlotNum =*/ Reader_ReadInt32(reader); - } - - p->chickenPeck = Reader_ReadInt32(reader); -# endif -#endif - -#if __JHERETIC__ || __JHEXEN__ - p->morphTics = Reader_ReadInt32(reader); -#endif - - if(ver >= 2) - { - p->airCounter = Reader_ReadInt32(reader); - } - -#if __JHEXEN__ - p->jumpTics = Reader_ReadInt32(reader); - p->worldTimer = Reader_ReadInt32(reader); -#elif __JHERETIC__ - p->flameCount = Reader_ReadInt32(reader); - - if(ver >= 2) - { - p->class_ = playerclass_t(Reader_ReadByte(reader)); - } -#endif - -#if !__JHEXEN__ - // Will be set when unarc thinker. - p->plr->mo = 0; - p->attacker = 0; -#endif - - // Demangle it. - for(int i = 0; i < numPSprites; ++i) - { - if(p->pSprites[i].state) - { - p->pSprites[i].state = &STATES[PTR2INT(p->pSprites[i].state)]; - } - } - - // Mark the player for fixpos and fixangles. - dp->flags |= DDPF_FIXORIGIN | DDPF_FIXANGLES | DDPF_FIXMOM; - p->update |= PSF_REBORN; -} - #if !__JDOOM64__ void SV_TranslateLegacyMobjFlags(mobj_t *mo, int ver) { @@ -1030,11 +576,12 @@ static void writePlayers(Writer *writer) for(int i = 0; i < MAXPLAYERS; ++i) { - if(!players[i].plr->inGame) + player_t *plr = players + i; + if(!plr->plr->inGame) continue; Writer_WriteInt32(writer, Net_GetPlayerID(i)); - SV_WritePlayer(i, writer); + plr->write(writer); } } SV_EndSegment(); @@ -1099,7 +646,7 @@ static void readPlayers(SaveInfo &info, dd_bool *infile, dd_bool *loaded, Reader } // Read the data. - SV_ReadPlayer(player, reader); + player->read(reader); } } SV_AssertSegment(ASEG_END); @@ -2072,7 +1619,7 @@ void SV_SaveGameClient(uint sessionId) Writer_WriteFloat(writer, pl->plr->lookDir); /* $unifiedangles */ writePlayerHeader(writer); - SV_WritePlayer(CONSOLEPLAYER, writer); + players[CONSOLEPLAYER].write(writer); MapStateWriter(thingArchiveExcludePlayers).write(writer); /// @todo No consistency bytes in client saves? @@ -2146,7 +1693,7 @@ void SV_LoadGameClient(uint sessionId) cpl->plr->lookDir = Reader_ReadFloat(reader); /* $unifiedangles */ readPlayerHeader(reader, info->version()); - SV_ReadPlayer(cpl, reader); + cpl->read(reader); MapStateReader(info->version()).read(reader); diff --git a/doomsday/plugins/common/src/player.cpp b/doomsday/plugins/common/src/player.cpp index 40ebdd4be9..333c5d418d 100644 --- a/doomsday/plugins/common/src/player.cpp +++ b/doomsday/plugins/common/src/player.cpp @@ -21,13 +21,18 @@ #include "common.h" #include "player.h" -#include "dmu_lib.h" #include "d_netsv.h" #include "d_net.h" -#include "hu_log.h" -#include "p_map.h" +#include "dmu_lib.h" #include "g_common.h" +#include "hu_log.h" +#if __JHERETIC__ || __JHEXEN__ +# include "hu_inventory.h" +#endif #include "p_actor.h" +#include "p_inventory.h" +#include "p_map.h" +#include "p_saveg.h" #include "p_start.h" #include #include @@ -217,7 +222,7 @@ void P_InitPlayerClassInfo() } #endif -int P_GetPlayerNum(player_t *player) +int P_GetPlayerNum(player_t const *player) { for(int i = 0; i < MAXPLAYERS; ++i) { @@ -1204,3 +1209,442 @@ angle_t Player_ViewYawAngle(int playerNum) return ang; } + +void player_s::write(Writer *writer) const +{ +#if __JDOOM64__ || __JHERETIC__ || __JHEXEN__ + int const plrnum = P_GetPlayerNum(this); +#endif + playerheader_t const &plrHdr = *SV_GetPlayerHeader(); + + int i, numPSprites = plrHdr.numPSprites; + + player_t temp, *p = &temp; + ddplayer_t ddtemp, *dp = &ddtemp; + + // Make a copy of the player. + std::memcpy(p, this, sizeof(temp)); + std::memcpy(dp, plr, sizeof(ddtemp)); + temp.plr = &ddtemp; + + // Convert the psprite states. + for(i = 0; i < numPSprites; ++i) + { + pspdef_t *pspDef = &temp.pSprites[i]; + + if(pspDef->state) + { + pspDef->state = (state_t *) (pspDef->state - STATES); + } + } + + // Version number. Increase when you make changes to the player data + // segment format. + Writer_WriteByte(writer, 6); + +#if __JHEXEN__ + // Class. + Writer_WriteByte(writer, cfg.playerClass[plrnum]); +#endif + + Writer_WriteInt32(writer, p->playerState); +#if __JHEXEN__ + Writer_WriteInt32(writer, p->class_); // 2nd class...? +#endif + Writer_WriteInt32(writer, FLT2FIX(p->viewZ)); + Writer_WriteInt32(writer, FLT2FIX(p->viewHeight)); + Writer_WriteInt32(writer, FLT2FIX(p->viewHeightDelta)); +#if !__JHEXEN__ + Writer_WriteFloat(writer, dp->lookDir); +#endif + Writer_WriteInt32(writer, FLT2FIX(p->bob)); +#if __JHEXEN__ + Writer_WriteInt32(writer, p->flyHeight); + Writer_WriteFloat(writer, dp->lookDir); + Writer_WriteInt32(writer, p->centering); +#endif + Writer_WriteInt32(writer, p->health); + +#if __JHEXEN__ + for(i = 0; i < plrHdr.numArmorTypes; ++i) + { + Writer_WriteInt32(writer, p->armorPoints[i]); + } +#else + Writer_WriteInt32(writer, p->armorPoints); + Writer_WriteInt32(writer, p->armorType); +#endif + +#if __JDOOM64__ || __JHEXEN__ + for(i = 0; i < plrHdr.numInvItemTypes; ++i) + { + inventoryitemtype_t type = inventoryitemtype_t(IIT_FIRST + i); + + Writer_WriteInt32(writer, type); + Writer_WriteInt32(writer, P_InventoryCount(plrnum, type)); + } + Writer_WriteInt32(writer, P_InventoryReadyItem(plrnum)); +#endif + + for(i = 0; i < plrHdr.numPowers; ++i) + { + Writer_WriteInt32(writer, p->powers[i]); + } + +#if __JHEXEN__ + Writer_WriteInt32(writer, p->keys); +#else + for(i = 0; i < plrHdr.numKeys; ++i) + { + Writer_WriteInt32(writer, p->keys[i]); + } +#endif + +#if __JHEXEN__ + Writer_WriteInt32(writer, p->pieces); +#else + Writer_WriteInt32(writer, p->backpack); +#endif + + for(i = 0; i < plrHdr.numFrags; ++i) + { + Writer_WriteInt32(writer, p->frags[i]); + } + + Writer_WriteInt32(writer, p->readyWeapon); + Writer_WriteInt32(writer, p->pendingWeapon); + + for(i = 0; i < plrHdr.numWeapons; ++i) + { + Writer_WriteInt32(writer, p->weapons[i].owned); + } + + for(i = 0; i < plrHdr.numAmmoTypes; ++i) + { + Writer_WriteInt32(writer, p->ammo[i].owned); +#if !__JHEXEN__ + Writer_WriteInt32(writer, p->ammo[i].max); +#endif + } + + Writer_WriteInt32(writer, p->attackDown); + Writer_WriteInt32(writer, p->useDown); + + Writer_WriteInt32(writer, p->cheats); + + Writer_WriteInt32(writer, p->refire); + + Writer_WriteInt32(writer, p->killCount); + Writer_WriteInt32(writer, p->itemCount); + Writer_WriteInt32(writer, p->secretCount); + + Writer_WriteInt32(writer, p->damageCount); + Writer_WriteInt32(writer, p->bonusCount); +#if __JHEXEN__ + Writer_WriteInt32(writer, p->poisonCount); +#endif + + Writer_WriteInt32(writer, dp->extraLight); + Writer_WriteInt32(writer, dp->fixedColorMap); + Writer_WriteInt32(writer, p->colorMap); + + for(i = 0; i < numPSprites; ++i) + { + pspdef_t *psp = &p->pSprites[i]; + + Writer_WriteInt32(writer, PTR2INT(psp->state)); + Writer_WriteInt32(writer, psp->tics); + Writer_WriteInt32(writer, FLT2FIX(psp->pos[VX])); + Writer_WriteInt32(writer, FLT2FIX(psp->pos[VY])); + } + +#if !__JHEXEN__ + Writer_WriteInt32(writer, p->didSecret); + + // Added in ver 2 with __JDOOM__ + Writer_WriteInt32(writer, p->flyHeight); +#endif + +#if __JHERETIC__ + for(i = 0; i < plrHdr.numInvItemTypes; ++i) + { + inventoryitemtype_t type = inventoryitemtype_t(IIT_FIRST + i); + + Writer_WriteInt32(writer, type); + Writer_WriteInt32(writer, P_InventoryCount(plrnum, type)); + } + Writer_WriteInt32(writer, P_InventoryReadyItem(plrnum)); + Writer_WriteInt32(writer, p->chickenPeck); +#endif + +#if __JHERETIC__ || __JHEXEN__ + Writer_WriteInt32(writer, p->morphTics); +#endif + + Writer_WriteInt32(writer, p->airCounter); + +#if __JHEXEN__ + Writer_WriteInt32(writer, p->jumpTics); + Writer_WriteInt32(writer, p->worldTimer); +#elif __JHERETIC__ + Writer_WriteInt32(writer, p->flameCount); + + // Added in ver 2 + Writer_WriteByte(writer, p->class_); +#endif +} + +void player_s::read(Reader *reader) +{ + int const plrnum = P_GetPlayerNum(this); + + byte ver = Reader_ReadByte(reader); + +#if __JHEXEN__ + cfg.playerClass[plrnum] = playerclass_t(Reader_ReadByte(reader)); +#endif + + playerheader_t const &plrHdr = *SV_GetPlayerHeader(); + ddplayer_t *dp = plr; + +#if __JHEXEN__ + de::zapPtr(this); // Force everything NULL, + plr = dp; // but restore the ddplayer pointer. +#endif + + playerState = playerstate_t(Reader_ReadInt32(reader)); +#if __JHEXEN__ + class_ = playerclass_t(Reader_ReadInt32(reader)); // 2nd class?? (ask Raven...) +#endif + + viewZ = FIX2FLT(Reader_ReadInt32(reader)); + viewHeight = FIX2FLT(Reader_ReadInt32(reader)); + viewHeightDelta = FIX2FLT(Reader_ReadInt32(reader)); +#if !__JHEXEN__ + dp->lookDir = Reader_ReadFloat(reader); +#endif + bob = FIX2FLT(Reader_ReadInt32(reader)); +#if __JHEXEN__ + flyHeight = Reader_ReadInt32(reader); + + dp->lookDir = Reader_ReadFloat(reader); + + centering = Reader_ReadInt32(reader); +#endif + health = Reader_ReadInt32(reader); + +#if __JHEXEN__ + for(int i = 0; i < plrHdr.numArmorTypes; ++i) + { + armorPoints[i] = Reader_ReadInt32(reader); + } +#else + armorPoints = Reader_ReadInt32(reader); + armorType = Reader_ReadInt32(reader); +#endif + +#if __JDOOM64__ || __JHEXEN__ + P_InventoryEmpty(plrnum); + for(int i = 0; i < plrHdr.numInvItemTypes; ++i) + { + inventoryitemtype_t type = inventoryitemtype_t(Reader_ReadInt32(reader)); + int count = Reader_ReadInt32(reader); + + for(int k = 0; k < count; ++k) + { + P_InventoryGive(plrnum, type, true); + } + } + + P_InventorySetReadyItem(plrnum, inventoryitemtype_t(Reader_ReadInt32(reader))); +# if __JHEXEN__ + Hu_InventorySelect(plrnum, P_InventoryReadyItem(plrnum)); + if(ver < 5) + { + /*artifactCount =*/ Reader_ReadInt32(reader); + } + if(ver < 6) + { + /*inventorySlotNum =*/ Reader_ReadInt32(reader); + } +# endif +#endif + + for(int i = 0; i < plrHdr.numPowers; ++i) + { + powers[i] = Reader_ReadInt32(reader); + } + if(powers[PT_ALLMAP]) + { + ST_RevealAutomap(plrnum, true); + } + +#if __JHEXEN__ + keys = Reader_ReadInt32(reader); +#else + for(int i = 0; i < plrHdr.numKeys; ++i) + { + keys[i] = Reader_ReadInt32(reader); + } +#endif + +#if __JHEXEN__ + pieces = Reader_ReadInt32(reader); +#else + backpack = Reader_ReadInt32(reader); +#endif + + for(int i = 0; i < plrHdr.numFrags; ++i) + { + frags[i] = Reader_ReadInt32(reader); + } + + readyWeapon = weapontype_t(Reader_ReadInt32(reader)); +#if __JHEXEN__ + if(ver < 5) + pendingWeapon = WT_NOCHANGE; + else +#endif + pendingWeapon = weapontype_t(Reader_ReadInt32(reader)); + + for(int i = 0; i < plrHdr.numWeapons; ++i) + { + weapons[i].owned = (Reader_ReadInt32(reader)? true : false); + } + + for(int i = 0; i < plrHdr.numAmmoTypes; ++i) + { + ammo[i].owned = Reader_ReadInt32(reader); + +#if !__JHEXEN__ + ammo[i].max = Reader_ReadInt32(reader); +#endif + } + + attackDown = Reader_ReadInt32(reader); + useDown = Reader_ReadInt32(reader); + cheats = Reader_ReadInt32(reader); + refire = Reader_ReadInt32(reader); + killCount = Reader_ReadInt32(reader); + itemCount = Reader_ReadInt32(reader); + secretCount = Reader_ReadInt32(reader); + +#if __JHEXEN__ + if(ver <= 1) + { + /*messageTics =*/ Reader_ReadInt32(reader); + /*ultimateMessage =*/ Reader_ReadInt32(reader); + /*yellowMessage =*/ Reader_ReadInt32(reader); + } +#endif + + damageCount = Reader_ReadInt32(reader); + bonusCount = Reader_ReadInt32(reader); +#if __JHEXEN__ + poisonCount = Reader_ReadInt32(reader); +#endif + + dp->extraLight = Reader_ReadInt32(reader); + dp->fixedColorMap = Reader_ReadInt32(reader); + + colorMap = Reader_ReadInt32(reader); + + for(int i = 0; i < plrHdr.numPSprites; ++i) + { + pspdef_t *psp = &pSprites[i]; + + psp->state = INT2PTR(state_t, Reader_ReadInt32(reader)); + psp->tics = Reader_ReadInt32(reader); + psp->pos[VX] = FIX2FLT(Reader_ReadInt32(reader)); + psp->pos[VY] = FIX2FLT(Reader_ReadInt32(reader)); + } + +#if !__JHEXEN__ + didSecret = Reader_ReadInt32(reader); + +# if __JDOOM__ || __JDOOM64__ + if(ver == 2) + { + /*messageTics =*/ Reader_ReadInt32(reader); + } + + if(ver >= 2) + { + flyHeight = Reader_ReadInt32(reader); + } + +# elif __JHERETIC__ + if(ver < 3) + { + /*messageTics =*/ Reader_ReadInt32(reader); + } + + flyHeight = Reader_ReadInt32(reader); + + P_InventoryEmpty(plrnum); + for(int i = 0; i < plrHdr.numInvItemTypes; ++i) + { + inventoryitemtype_t type = inventoryitemtype_t(Reader_ReadInt32(reader)); + int count = Reader_ReadInt32(reader); + + for(int k = 0; k < count; ++k) + { + P_InventoryGive(plrnum, type, true); + } + } + + P_InventorySetReadyItem(plrnum, (inventoryitemtype_t) Reader_ReadInt32(reader)); + Hu_InventorySelect(plrnum, P_InventoryReadyItem(plrnum)); + if(ver < 5) + { + Reader_ReadInt32(reader); // Current inventory item count? + } + if(ver < 6) + { + /*inventorySlotNum =*/ Reader_ReadInt32(reader); + } + + chickenPeck = Reader_ReadInt32(reader); +# endif +#endif + +#if __JHERETIC__ || __JHEXEN__ + morphTics = Reader_ReadInt32(reader); +#endif + + if(ver >= 2) + { + airCounter = Reader_ReadInt32(reader); + } + +#if __JHEXEN__ + jumpTics = Reader_ReadInt32(reader); + worldTimer = Reader_ReadInt32(reader); +#elif __JHERETIC__ + flameCount = Reader_ReadInt32(reader); + + if(ver >= 2) + { + class_ = playerclass_t(Reader_ReadByte(reader)); + } +#endif + +#if !__JHEXEN__ + // Will be set when unarc thinker. + plr->mo = 0; + attacker = 0; +#endif + + // Demangle it. + for(int i = 0; i < plrHdr.numPSprites; ++i) + { + if(pSprites[i].state) + { + pSprites[i].state = &STATES[PTR2INT(pSprites[i].state)]; + } + } + + // Mark the player for fixpos and fixangles. + dp->flags |= DDPF_FIXORIGIN | DDPF_FIXANGLES | DDPF_FIXMOM; + update |= PSF_REBORN; +} diff --git a/doomsday/plugins/common/src/polyobjs.cpp b/doomsday/plugins/common/src/polyobjs.cpp index 0c11fe6fe6..9b153d45e0 100644 --- a/doomsday/plugins/common/src/polyobjs.cpp +++ b/doomsday/plugins/common/src/polyobjs.cpp @@ -1,7 +1,7 @@ /** @file polyobjs.h Polyobject thinkers and management. * * @authors Copyright © 2003-2013 Jaakko Keränen - * @authors Copyright © 2006-2013 Daniel Swanson + * @authors Copyright © 2005-2013 Daniel Swanson * @authors Copyright © 1999 Activision * * @par License diff --git a/doomsday/plugins/doom/include/d_player.h b/doomsday/plugins/doom/include/d_player.h index 25d4d36693..6a2ea4d6a5 100644 --- a/doomsday/plugins/doom/include/d_player.h +++ b/doomsday/plugins/doom/include/d_player.h @@ -115,6 +115,11 @@ typedef struct player_s { // Target view to a mobj (NULL=disabled): mobj_t* viewLock; // $democam int lockFull; + +#ifdef __cplusplus + void write(Writer *writer) const; + void read(Reader *reader); +#endif } player_t; // diff --git a/doomsday/plugins/doom64/include/d_player.h b/doomsday/plugins/doom64/include/d_player.h index 0b7a477fa3..93c6d9a2a3 100644 --- a/doomsday/plugins/doom64/include/d_player.h +++ b/doomsday/plugins/doom64/include/d_player.h @@ -140,6 +140,11 @@ typedef struct player_s { int lockFull; int flyHeight; + +#ifdef __cplusplus + void write(Writer *writer) const; + void read(Reader *reader); +#endif } player_t; // diff --git a/doomsday/plugins/heretic/include/h_player.h b/doomsday/plugins/heretic/include/h_player.h index 8f491d1bf2..59f64de33f 100644 --- a/doomsday/plugins/heretic/include/h_player.h +++ b/doomsday/plugins/heretic/include/h_player.h @@ -159,6 +159,11 @@ typedef struct player_s { int chickenPeck; // chicken peck countdown. mobj_t* rain1; // Active rain maker 1. mobj_t* rain2; // Active rain maker 2. + +#ifdef __cplusplus + void write(Writer *writer) const; + void read(Reader *reader); +#endif } player_t; // diff --git a/doomsday/plugins/hexen/include/x_player.h b/doomsday/plugins/hexen/include/x_player.h index bb47d83a65..e916e321cf 100644 --- a/doomsday/plugins/hexen/include/x_player.h +++ b/doomsday/plugins/hexen/include/x_player.h @@ -123,6 +123,11 @@ typedef struct player_s { // Target view to a mobj (NULL=disabled). mobj_t* viewLock; // $democam int lockFull; + +#ifdef __cplusplus + void write(Writer *writer) const; + void read(Reader *reader); +#endif } player_t; #endif