#include "a_doomglobal.h" #include "a_hexenglobal.h" #include "a_strifeglobal.h" #include "ravenshared.h" #include "a_weaponpiece.h" #include "d_dehacked.h" // For NULL states, which aren't owned by any actor, the owner // is recorded as AActor with the following state. AActor should // never actually have this many states of its own, so this // is (relatively) safe. #define NULL_STATE_INDEX 127 // These are special tokens found in the data stream of an archive. // Whenever a new object is encountered, it gets created using new and // is then asked to serialize itself before processing of the previous // object continues. This can result in some very deep recursion if // you aren't careful about how you organize your data. #define NEW_OBJ ((BYTE)1) // Data for a new object follows #define NEW_CLS_OBJ ((BYTE)2) // Data for a new class and object follows #define OLD_OBJ ((BYTE)3) // Reference to an old object follows #define NULL_OBJ ((BYTE)4) // Load as NULL #define M1_OBJ ((BYTE)44) // Load as (DObject*)-1 #define NEW_PLYR_OBJ ((BYTE)5) // Data for a new player follows #define NEW_PLYR_CLS_OBJ ((BYTE)6) // Data for a new class and player follows #define NEW_NAME ((BYTE)27) // A new name follows #define OLD_NAME ((BYTE)28) // Reference to an old name follows #define NIL_NAME ((BYTE)33) // Load as NULL #define NEW_SPRITE ((BYTE)11) // A new sprite name follows #define OLD_SPRITE ((BYTE)12) // Reference to an old sprite name follows #if 0 // still needed as reference. FCrap &FCrap::ReadObject(DObject* &obj, PClass *wanttype) { BYTE objHead; const PClass *type; BYTE playerNum; DWORD index; DObject *newobj; operator<< (objHead); switch (objHead) { case NULL_OBJ: obj = NULL; break; case M1_OBJ: obj = (DObject *)~0; break; case OLD_OBJ: index = ReadCount(); if (index >= ArchiveToObject.Size()) { I_Error("Object reference too high (%u; max is %u)\n", index, ArchiveToObject.Size()); } obj = ArchiveToObject[index]; break; case NEW_PLYR_CLS_OBJ: operator<< (playerNum); if (m_HubTravel) { // If travelling inside a hub, use the existing player actor type = ReadClass(wanttype); // Printf ("New player class: %s (%u)\n", type->Name, m_File->Tell()); obj = players[playerNum].mo; // But also create a new one so that we can get past the one // stored in the archive. AActor *tempobj = static_cast(type->CreateNew()); MapObject(obj != NULL ? obj : tempobj); tempobj->SerializeUserVars(*this); tempobj->Serialize(*this); tempobj->CheckIfSerialized(); // If this player is not present anymore, keep the new body // around just so that the load will succeed. if (obj != NULL) { // When the temporary player's inventory items were loaded, // they became owned by the real player. Undo that now. for (AInventory *item = tempobj->Inventory; item != NULL; item = item->Inventory) { item->Owner = tempobj; } tempobj->Destroy(); } else { obj = tempobj; players[playerNum].mo = static_cast(obj); } break; } /* fallthrough when not travelling to a previous level */ case NEW_CLS_OBJ: type = ReadClass(wanttype); // Printf ("New class: %s (%u)\n", type->Name, m_File->Tell()); newobj = obj = type->CreateNew(); MapObject(obj); newobj->SerializeUserVars(*this); newobj->Serialize(*this); newobj->CheckIfSerialized(); break; case NEW_PLYR_OBJ: operator<< (playerNum); if (m_HubTravel) { type = ReadStoredClass(wanttype); // Printf ("Use player class: %s (%u)\n", type->Name, m_File->Tell()); obj = players[playerNum].mo; AActor *tempobj = static_cast(type->CreateNew()); MapObject(obj != NULL ? obj : tempobj); tempobj->SerializeUserVars(*this); tempobj->Serialize(*this); tempobj->CheckIfSerialized(); if (obj != NULL) { for (AInventory *item = tempobj->Inventory; item != NULL; item = item->Inventory) { item->Owner = tempobj; } tempobj->Destroy(); } else { obj = tempobj; players[playerNum].mo = static_cast(obj); } break; } /* fallthrough when not travelling to a previous level */ case NEW_OBJ: type = ReadStoredClass(wanttype); // Printf ("Use class: %s (%u)\n", type->Name, m_File->Tell()); obj = type->CreateNew(); MapObject(obj); obj->SerializeUserVars(*this); obj->Serialize(*this); obj->CheckIfSerialized(); break; default: I_Error("Unknown object code (%d) in archive\n", objHead); } return *this; } #endif #if 0 void DThinker::SerializeAll(FArchive &arc, bool hubLoad) { DThinker *thinker; BYTE stat; int statcount; int i; if (arc.IsStoring()) { } else { try { arc << statcount; while (statcount > 0) { arc << stat << thinker; while (thinker != NULL) { // This may be a player stored in their ancillary list. Remove // them first before inserting them into the new list. if (thinker->NextThinker != NULL) { thinker->Remove(); } // Thinkers with the OF_JustSpawned flag set go in the FreshThinkers // list. Anything else goes in the regular Thinkers list. if (thinker->ObjectFlags & OF_EuthanizeMe) { // This thinker was destroyed during the loading process. Do // not link it in to any list. } else if (thinker->ObjectFlags & OF_JustSpawned) { FreshThinkers[stat].AddTail(thinker); } else { Thinkers[stat].AddTail(thinker); } arc << thinker; } statcount--; } } catch (class CDoomError &) { DestroyAllThinkers(); throw; } } } #endif