static int SV_ReadGlow(glow_t *glow) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes Sector *sector; int minLight; int maxLight; int direction; } v13_glow_t; */ // Padding at the start (an old thinker_t struct) Reader_Read(svReader, NULL, SIZEOF_V13_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. glow->sector = P_ToPtr(DMU_SECTOR, Reader_ReadInt32(svReader)); if(!glow->sector) Con_Error("tc_glow: bad sector number\n"); glow->minLight = (float) Reader_ReadInt32(svReader) / 255.0f; glow->maxLight = (float) Reader_ReadInt32(svReader) / 255.0f; glow->direction = Reader_ReadInt32(svReader); glow->thinker.function = (thinkfunc_t) T_Glow; return true; // Add this thinker. }
void SaveInfo_Read(SaveInfo *info, Reader *reader) { saveheader_t *hdr; DENG_ASSERT(info != 0); hdr = &info->header; hdr->magic = Reader_ReadInt32(reader); hdr->version = Reader_ReadInt32(reader); hdr->gameMode = (gamemode_t)Reader_ReadInt32(reader); if(hdr->version >= 10) { Str_Read(&info->name, reader); } else { // Older formats use a fixed-length name (24 characters). #define OLD_NAME_LENGTH 24 char buf[OLD_NAME_LENGTH]; Reader_Read(reader, buf, OLD_NAME_LENGTH); Str_Set(&info->name, buf); #undef OLD_NAME_LENGTH } hdr->skill = Reader_ReadByte(reader); hdr->episode = Reader_ReadByte(reader); hdr->map = Reader_ReadByte(reader); hdr->deathmatch = Reader_ReadByte(reader); hdr->noMonsters = Reader_ReadByte(reader); #if __JHEXEN__ hdr->randomClasses = Reader_ReadByte(reader); #endif #if !__JHEXEN__ hdr->respawnMonsters = Reader_ReadByte(reader); // Older formats serialize the unpacked saveheader_t struct; skip the junk values (alignment). if(hdr->version < 10) SV_Seek(2); hdr->mapTime = Reader_ReadInt32(reader); { int i; for(i = 0; i < MAXPLAYERS; ++i) { hdr->players[i] = Reader_ReadByte(reader); }} #endif info->gameId = Reader_ReadInt32(reader); #if __JDOOM__ || __JHERETIC__ // Translate gameMode identifiers from older save versions. translateLegacyGameMode(&hdr->gameMode, hdr->version); #endif }
/** * T_FireFlicker was added to save games in ver5, therefore we don't have * an old format to support. */ int fireflicker_s::read(MapStateReader *msr) { Reader1 *reader = msr->reader(); /*int ver =*/ Reader_ReadByte(reader); // version byte. // Note: the thinker class byte has already been read. sector = (Sector*)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); maxLight = (float) Reader_ReadInt32(reader) / 255.0f; minLight = (float) Reader_ReadInt32(reader) / 255.0f; thinker.function = (thinkfunc_t) T_FireFlicker; return true; // Add this thinker. }
static int SV_ReadStrobe(strobe_t *strobe) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes Sector *sector; int count; int minLight; int maxLight; int darkTime; int brightTime; } v13_strobe_t; */ // Padding at the start (an old thinker_t struct) Reader_Read(svReader, NULL, SIZEOF_V13_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. strobe->sector = P_ToPtr(DMU_SECTOR, Reader_ReadInt32(svReader)); if(!strobe->sector) Con_Error("tc_strobe: bad sector number\n"); strobe->count = Reader_ReadInt32(svReader); strobe->minLight = (float) Reader_ReadInt32(svReader) / 255.0f; strobe->maxLight = (float) Reader_ReadInt32(svReader) / 255.0f; strobe->darkTime = Reader_ReadInt32(svReader); strobe->brightTime = Reader_ReadInt32(svReader); strobe->thinker.function = (thinkfunc_t) T_StrobeFlash; return true; // Add this thinker. }
static int SV_ReadCeiling(ceiling_t *ceiling) { /* Original Heretic format: typedef struct { thinker_t thinker; ///< 12 bytes ceilingtype_e type; ///< 32bit int Sector* sector; fixed_t bottomheight, topheight; fixed_t speed; boolean crush; int direction; /// 1= up, 0= waiting, -1= down int tag' int olddirection; } v13_ceiling_t; */ byte temp[SIZEOF_V13_THINKER_T]; // Padding at the start (an old thinker_t struct) Reader_Read(svReader, &temp, SIZEOF_V13_THINKER_T); // Start of used data members. ceiling->type = Reader_ReadInt32(svReader); // A 32bit pointer to sector, serialized. ceiling->sector = P_ToPtr(DMU_SECTOR, Reader_ReadInt32(svReader)); if(!ceiling->sector) Con_Error("tc_ceiling: bad sector number\n"); ceiling->bottomHeight = FIX2FLT(Reader_ReadInt32(svReader)); ceiling->topHeight = FIX2FLT(Reader_ReadInt32(svReader)); ceiling->speed = FIX2FLT(Reader_ReadInt32(svReader)); ceiling->crush = Reader_ReadInt32(svReader); ceiling->state = (Reader_ReadInt32(svReader) == -1? CS_DOWN : CS_UP); ceiling->tag = Reader_ReadInt32(svReader); ceiling->oldState = (Reader_ReadInt32(svReader) == -1? CS_DOWN : CS_UP); ceiling->thinker.function = T_MoveCeiling; if(!(temp + V13_THINKER_T_FUNC_OFFSET)) Thinker_SetStasis(&ceiling->thinker, true); P_ToXSector(ceiling->sector)->specialData = T_MoveCeiling; return true; // Add this thinker. }
static int SV_ReadFloor(floor_t *floor) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes floortype_e type; // was 32bit int boolean crush; Sector *sector; int direction; int newspecial; short texture; fixed_t floordestheight; fixed_t speed; } v13_floormove_t; */ Uri *newTextureUrn; // Padding at the start (an old thinker_t struct) Reader_Read(svReader, NULL, SIZEOF_V13_THINKER_T); // Start of used data members. floor->type = Reader_ReadInt32(svReader); floor->crush = Reader_ReadInt32(svReader); // A 32bit pointer to sector, serialized. floor->sector = P_ToPtr(DMU_SECTOR, Reader_ReadInt32(svReader)); if(!floor->sector) Con_Error("tc_floor: bad sector number\n"); floor->state = (int) Reader_ReadInt32(svReader); floor->newSpecial = Reader_ReadInt32(svReader); newTextureUrn = readTextureUrn(svReader, "Flats"); floor->material = DD_MaterialForTextureUri(newTextureUrn); Uri_Delete(newTextureUrn); floor->floorDestHeight = FIX2FLT(Reader_ReadInt32(svReader)); floor->speed = FIX2FLT(Reader_ReadInt32(svReader)); floor->thinker.function = T_MoveFloor; P_ToXSector(floor->sector)->specialData = T_MoveFloor; return true; // Add this thinker. }
int glow_s::read(MapStateReader *msr) { Reader1 *reader = msr->reader(); int mapVersion = msr->mapVersion(); if(mapVersion >= 5) { // Note: the thinker class byte has already been read. /*int ver =*/ Reader_ReadByte(reader); // version byte. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); maxLight = (float) Reader_ReadInt32(reader) / 255.0f; minLight = (float) Reader_ReadInt32(reader) / 255.0f; direction = Reader_ReadInt32(reader); } else { // Its in the old pre V5 format which serialized strobe_t // Padding at the start (an old thinker_t struct) byte junk[16]; // sizeof thinker_t Reader_Read(reader, junk, 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); minLight = (float) Reader_ReadInt32(reader) / 255.0f; maxLight = (float) Reader_ReadInt32(reader) / 255.0f; direction = Reader_ReadInt32(reader); } thinker.function = (thinkfunc_t) T_Glow; return true; // Add this thinker. }
static int SV_ReadDoor(door_t *door) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes doortype_e type; // was 32bit int Sector *sector; fixed_t topheight; fixed_t speed; int direction; // 1 = up, 0 = waiting at top, -1 = down int topwait; // tics to wait at the top // (keep in case a door going down is reset) int topcountdown; // when it reaches 0, start going down } v13_vldoor_t; */ // Padding at the start (an old thinker_t struct) Reader_Read(svReader, NULL, SIZEOF_V13_THINKER_T); // Start of used data members. door->type = Reader_ReadInt32(svReader); // A 32bit pointer to sector, serialized. door->sector = P_ToPtr(DMU_SECTOR, Reader_ReadInt32(svReader)); if(!door->sector) Con_Error("tc_door: bad sector number\n"); door->topHeight = FIX2FLT(Reader_ReadInt32(svReader)); door->speed = FIX2FLT(Reader_ReadInt32(svReader)); door->state = Reader_ReadInt32(svReader); door->topWait = Reader_ReadInt32(svReader); door->topCountDown = Reader_ReadInt32(svReader); door->thinker.function = T_Door; P_ToXSector(door->sector)->specialData = T_Door; return true; // Add this thinker. }
static int SV_ReadPlat(plat_t *plat) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes Sector *sector; fixed_t speed; fixed_t low; fixed_t high; int wait; int count; platstate_e status; // was 32bit int platstate_e oldStatus; // was 32bit int boolean crush; int tag; plattype_e type; // was 32bit int } v13_plat_t; */ byte temp[SIZEOF_V13_THINKER_T]; // Padding at the start (an old thinker_t struct) Reader_Read(svReader, &temp, SIZEOF_V13_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. plat->sector = P_ToPtr(DMU_SECTOR, Reader_ReadInt32(svReader)); if(!plat->sector) Con_Error("tc_plat: bad sector number\n"); plat->speed = FIX2FLT(Reader_ReadInt32(svReader)); plat->low = FIX2FLT(Reader_ReadInt32(svReader)); plat->high = FIX2FLT(Reader_ReadInt32(svReader)); plat->wait = Reader_ReadInt32(svReader); plat->count = Reader_ReadInt32(svReader); plat->state = Reader_ReadInt32(svReader); plat->oldState = Reader_ReadInt32(svReader); plat->crush = Reader_ReadInt32(svReader); plat->tag = Reader_ReadInt32(svReader); plat->type = Reader_ReadInt32(svReader); plat->thinker.function = T_PlatRaise; if(!(temp + V13_THINKER_T_FUNC_OFFSET)) Thinker_SetStasis(&plat->thinker, true); P_ToXSector(plat->sector)->specialData = T_PlatRaise; return true; // Add this thinker. }
static void SV_v13_ReadMobj(void) { coord_t pos[3], mom[3], floorz, ceilingz, radius, height; int frame, valid, type, ddflags = 0; spritenum_t sprite; mobjinfo_t* info; angle_t angle; mobj_t* mo; // The thinker was 3 ints long. Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); pos[VX] = FIX2FLT(Reader_ReadInt32(svReader)); pos[VY] = FIX2FLT(Reader_ReadInt32(svReader)); pos[VZ] = FIX2FLT(Reader_ReadInt32(svReader)); // Sector links. Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); angle = (angle_t) (ANG45 * (Reader_ReadInt32(svReader) / 45)); sprite = Reader_ReadInt32(svReader); frame = Reader_ReadInt32(svReader); frame &= ~FF_FRAMEMASK; // not used anymore. // Block links. Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); // BspLeaf. Reader_ReadInt32(svReader); floorz = FIX2FLT(Reader_ReadInt32(svReader)); ceilingz = FIX2FLT(Reader_ReadInt32(svReader)); radius = FIX2FLT(Reader_ReadInt32(svReader)); height = FIX2FLT(Reader_ReadInt32(svReader)); mom[MX] = FIX2FLT(Reader_ReadInt32(svReader)); mom[MY] = FIX2FLT(Reader_ReadInt32(svReader)); mom[MZ] = FIX2FLT(Reader_ReadInt32(svReader)); valid = Reader_ReadInt32(svReader); type = Reader_ReadInt32(svReader); info = &MOBJINFO[type]; if(info->flags & MF_SOLID) ddflags |= DDMF_SOLID; if(info->flags2 & MF2_DONTDRAW) ddflags |= DDMF_DONTDRAW; /** * We now have all the information we need to create the mobj. */ mo = P_MobjCreateXYZ(P_MobjThinker, pos[VX], pos[VY], pos[VZ], angle, radius, height, ddflags); mo->sprite = sprite; mo->frame = frame; mo->floorZ = floorz; mo->ceilingZ = ceilingz; mo->mom[MX] = mom[MX]; mo->mom[MY] = mom[MY]; mo->mom[MZ] = mom[MZ]; mo->valid = valid; mo->type = type; mo->moveDir = DI_NODIR; /** * Continue reading the mobj data. */ Reader_ReadInt32(svReader); // info mo->tics = Reader_ReadInt32(svReader); mo->state = INT2PTR(state_t, Reader_ReadInt32(svReader)); mo->damage = Reader_ReadInt32(svReader); mo->flags = Reader_ReadInt32(svReader); mo->flags2 = Reader_ReadInt32(svReader); mo->special1 = Reader_ReadInt32(svReader); mo->special2 = Reader_ReadInt32(svReader); mo->health = Reader_ReadInt32(svReader); // Fix a bunch of kludges in the original Heretic. switch(mo->type) { case MT_MACEFX1: case MT_MACEFX2: case MT_MACEFX3: case MT_HORNRODFX2: case MT_HEADFX3: case MT_WHIRLWIND: case MT_TELEGLITTER: case MT_TELEGLITTER2: mo->special3 = mo->health; mo->health = info->spawnHealth; break; default: break; } mo->moveDir = Reader_ReadInt32(svReader); mo->moveCount = Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); // target mo->reactionTime = Reader_ReadInt32(svReader); mo->threshold = Reader_ReadInt32(svReader); mo->player = INT2PTR(player_t, Reader_ReadInt32(svReader)); mo->lastLook = Reader_ReadInt32(svReader); mo->spawnSpot.origin[VX] = (coord_t) Reader_ReadInt32(svReader); mo->spawnSpot.origin[VY] = (coord_t) Reader_ReadInt32(svReader); mo->spawnSpot.origin[VZ] = 0; // Initialize with "something". mo->spawnSpot.angle = (angle_t) (ANG45 * (Reader_ReadInt32(svReader) / 45)); /*mo->spawnSpot.type = (int)*/ Reader_ReadInt32(svReader); { int spawnFlags = ((int) Reader_ReadInt32(svReader)) & ~MASK_UNKNOWN_MSF_FLAGS; // Spawn on the floor by default unless the mobjtype flags override. spawnFlags |= MSF_Z_FLOOR; mo->spawnSpot.flags = spawnFlags; } mo->info = info; SV_TranslateLegacyMobjFlags(mo, 0); mo->state = &STATES[PTR2INT(mo->state)]; mo->target = NULL; if(mo->player) { mo->player = &players[PTR2INT(mo->player) - 1]; mo->player->plr->mo = mo; mo->player->plr->mo->dPlayer = mo->player->plr; } P_MobjSetOrigin(mo); mo->floorZ = P_GetDoublep(mo->bspLeaf, DMU_FLOOR_HEIGHT); mo->ceilingZ = P_GetDoublep(mo->bspLeaf, DMU_CEILING_HEIGHT); }
int waggle_s::read(MapStateReader *msr) { Reader1 *reader = msr->reader(); int mapVersion = msr->mapVersion(); if(mapVersion >= 4) { /*int ver =*/ Reader_ReadByte(reader); // version byte. // Start of used data members. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); originalHeight = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); accumulator = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); accDelta = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); targetScale = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); scale = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); scaleDelta = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); ticker = Reader_ReadInt32(reader); state = wagglestate_e(Reader_ReadInt32(reader)); } else { // Its in the old pre V4 format which serialized waggle_t // Padding at the start (an old thinker_t struct) byte junk[16]; // sizeof thinker_t Reader_Read(reader, junk, 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); originalHeight = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); accumulator = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); accDelta = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); targetScale = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); scale = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); scaleDelta = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); ticker = Reader_ReadInt32(reader); state = wagglestate_e(Reader_ReadInt32(reader)); } thinker.function = (thinkfunc_t) T_FloorWaggle; P_ToXSector(sector)->specialData = this; return true; // Add this thinker. }
static void SV_v13_ReadPlayer(player_t* pl) { int i, plrnum = pl - players; ddplayer_t* ddpl = pl->plr; byte temp[12]; Reader_ReadInt32(svReader); // mo pl->playerState = Reader_ReadInt32(svReader); Reader_Read(svReader, temp, 10); // ticcmd_t pl->viewZ = FIX2FLT(Reader_ReadInt32(svReader)); pl->viewHeight = FIX2FLT(Reader_ReadInt32(svReader)); pl->viewHeightDelta = FIX2FLT(Reader_ReadInt32(svReader)); pl->bob = FIX2FLT(Reader_ReadInt32(svReader)); pl->flyHeight = Reader_ReadInt32(svReader); ddpl->lookDir = Reader_ReadInt32(svReader); pl->centering = Reader_ReadInt32(svReader); pl->health = Reader_ReadInt32(svReader); pl->armorPoints = Reader_ReadInt32(svReader); pl->armorType = Reader_ReadInt32(svReader); P_InventoryEmpty(plrnum); for(i = 0; i < 14; ++i) { inventoryitemtype_t type = Reader_ReadInt32(svReader); int j, count = Reader_ReadInt32(svReader); for(j = 0; j < count; ++j) P_InventoryGive(plrnum, type, true); } P_InventorySetReadyItem(plrnum, (inventoryitemtype_t) Reader_ReadInt32(svReader)); Hu_InventorySelect(plrnum, P_InventoryReadyItem(plrnum)); Reader_ReadInt32(svReader); // current inventory item count? /*pl->inventorySlotNum =*/ Reader_ReadInt32(svReader); memset(pl->powers, 0, sizeof(pl->powers)); pl->powers[PT_INVULNERABILITY] = !!Reader_ReadInt32(svReader); pl->powers[PT_INVISIBILITY] = !!Reader_ReadInt32(svReader); pl->powers[PT_ALLMAP] = !!Reader_ReadInt32(svReader); if(pl->powers[PT_ALLMAP]) { ST_RevealAutomap(pl - players, true); } pl->powers[PT_INFRARED] = !!Reader_ReadInt32(svReader); pl->powers[PT_WEAPONLEVEL2] = !!Reader_ReadInt32(svReader); pl->powers[PT_FLIGHT] = !!Reader_ReadInt32(svReader); pl->powers[PT_SHIELD] = !!Reader_ReadInt32(svReader); pl->powers[PT_HEALTH2] = !!Reader_ReadInt32(svReader); memset(pl->keys, 0, sizeof(pl->keys)); pl->keys[KT_YELLOW] = !!Reader_ReadInt32(svReader); pl->keys[KT_GREEN] = !!Reader_ReadInt32(svReader); pl->keys[KT_BLUE] = !!Reader_ReadInt32(svReader); pl->backpack = Reader_ReadInt32(svReader); memset(pl->frags, 0, sizeof(pl->frags)); pl->frags[0] = Reader_ReadInt32(svReader); pl->frags[1] = Reader_ReadInt32(svReader); pl->frags[2] = Reader_ReadInt32(svReader); pl->frags[3] = Reader_ReadInt32(svReader); pl->readyWeapon = Reader_ReadInt32(svReader); pl->pendingWeapon = Reader_ReadInt32(svReader); // Owned weapons. memset(pl->weapons, 0, sizeof(pl->weapons)); pl->weapons[WT_FIRST ].owned = !!Reader_ReadInt32(svReader); pl->weapons[WT_SECOND ].owned = !!Reader_ReadInt32(svReader); pl->weapons[WT_THIRD ].owned = !!Reader_ReadInt32(svReader); pl->weapons[WT_FOURTH ].owned = !!Reader_ReadInt32(svReader); pl->weapons[WT_FIFTH ].owned = !!Reader_ReadInt32(svReader); pl->weapons[WT_SIXTH ].owned = !!Reader_ReadInt32(svReader); pl->weapons[WT_SEVENTH].owned = !!Reader_ReadInt32(svReader); pl->weapons[WT_EIGHTH ].owned = !!Reader_ReadInt32(svReader); memset(pl->ammo, 0, sizeof(pl->ammo)); pl->ammo[AT_CRYSTAL].owned = Reader_ReadInt32(svReader); pl->ammo[AT_ARROW ].owned = Reader_ReadInt32(svReader); pl->ammo[AT_ORB ].owned = Reader_ReadInt32(svReader); pl->ammo[AT_RUNE ].owned = Reader_ReadInt32(svReader); pl->ammo[AT_FIREORB].owned = Reader_ReadInt32(svReader); pl->ammo[AT_MSPHERE].owned = Reader_ReadInt32(svReader); pl->ammo[AT_CRYSTAL].max = Reader_ReadInt32(svReader); pl->ammo[AT_ARROW ].max = Reader_ReadInt32(svReader); pl->ammo[AT_ORB ].max = Reader_ReadInt32(svReader); pl->ammo[AT_RUNE ].max = Reader_ReadInt32(svReader); pl->ammo[AT_FIREORB].max = Reader_ReadInt32(svReader); pl->ammo[AT_MSPHERE].max = Reader_ReadInt32(svReader); pl->attackDown = Reader_ReadInt32(svReader); pl->useDown = Reader_ReadInt32(svReader); pl->cheats = Reader_ReadInt32(svReader); pl->refire = Reader_ReadInt32(svReader); pl->killCount = Reader_ReadInt32(svReader); pl->itemCount = Reader_ReadInt32(svReader); pl->secretCount = Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); // message, char* pl->damageCount = Reader_ReadInt32(svReader); pl->bonusCount = Reader_ReadInt32(svReader); pl->flameCount = Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); // attacker ddpl->extraLight = Reader_ReadInt32(svReader); ddpl->fixedColorMap = Reader_ReadInt32(svReader); pl->colorMap = Reader_ReadInt32(svReader); for(i = 0; i < 2; ++i) { pspdef_t* psp = &pl->pSprites[i]; psp->state = INT2PTR(state_t, Reader_ReadInt32(svReader)); psp->pos[VX] = Reader_ReadInt32(svReader); psp->pos[VY] = Reader_ReadInt32(svReader); psp->tics = Reader_ReadInt32(svReader); } pl->didSecret = Reader_ReadInt32(svReader); pl->morphTics = Reader_ReadInt32(svReader); pl->chickenPeck = Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); // rain1 Reader_ReadInt32(svReader); // rain2 }
void SV_LoadGameClient(uint /*sessionId*/) { throw de::Error("SV_LoadGameClient", "Not currently implemented"); #if 0 #if !__JHEXEN__ // unsupported in libhexen player_t *cpl = players + CONSOLEPLAYER; mobj_t *mo = cpl->plr->mo; if(!IS_CLIENT || !mo) return; de::game::GameStateFolder *session = new de::game::GameStateFolder(saveNameForClientSessionId(sessionId)); de::game::GameStateMetadata *metadata = new de::game::GameStateMetadata; //G_ReadLegacySessionMetadata(metadata, reader); metadata->set("sessionId", sessionId); session->replaceMetadata(metadata); de::Path path = de::String("/savegame") / "client" / session->path(); if(!SV_OpenFileForRead(path)) { delete session; App_Log(DE2_RES_WARNING, "SV_LoadGameClient: Failed opening \"%s\" for reading", path.toString().toLatin1().constData()); return; } if((*metadata)["magic"].value().asNumber() != MY_CLIENT_SAVE_MAGIC) { SV_CloseFile(); delete session; App_Log(DE2_RES_ERROR, "Client save file format not recognized"); return; } Reader1 *reader = SV_NewReader(); int const saveVersion = (*metadata)["version"].value().asNumber(); Uri *mapUri = Uri_NewWithPath2((*metadata)["mapUri"].value().asText().toUtf8().constData(), RC_NULL); GameRules *rules = 0; if(metadata->hasSubrecord("gameRules")) { rules = GameRules::fromRecord(metadata->subrecord("gameRules")); } // Do we need to change the map? if(gfw_Session()->mapUri() != *reinterpret_cast<de::Uri *>(mapUri)) { gfw_Session()->begin(*mapUri, 0/*default*/, *rules); } else if(rules) { gfw_Session()->rules() = *rules; } delete rules; rules = 0; Uri_Delete(mapUri); mapUri = 0; mapTime = (*metadata)["mapTime"].value().asNumber(); P_MobjUnlink(mo); mo->origin[VX] = FIX2FLT(Reader_ReadInt32(reader)); mo->origin[VY] = FIX2FLT(Reader_ReadInt32(reader)); mo->origin[VZ] = FIX2FLT(Reader_ReadInt32(reader)); P_MobjLink(mo); mo->floorZ = FIX2FLT(Reader_ReadInt32(reader)); mo->ceilingZ = FIX2FLT(Reader_ReadInt32(reader)); mo->angle = Reader_ReadInt32(reader); /* $unifiedangles */ cpl->plr->lookDir = Reader_ReadFloat(reader); /* $unifiedangles */ #if __JHEXEN__ if(saveVersion >= 4) #else if(saveVersion >= 5) #endif { SV_AssertSegment(ASEG_PLAYER_HEADER); } playerheader_t plrHdr; plrHdr.read(reader, saveVersion); cpl->read(reader, plrHdr); MapStateReader(*session).read(Str_Text(Uri_Resolved(mapUri))); SV_CloseFile(); Reader_Delete(reader); delete session; #else DENG2_UNUSED(sessionId); #endif #endif }
/** * Reads all versions of archived lines. * Including the old Ver1. */ void SV_ReadLine(Line *li, MapStateReader *msr) { xline_t *xli = P_ToXLine(li); Reader1 *reader = msr->reader(); int mapVersion = msr->mapVersion(); bool xgDataFollows = false; #if __JHEXEN__ if(mapVersion >= 4) #else if(mapVersion >= 2) #endif { xgDataFollows = Reader_ReadByte(reader) == 1; } #ifdef __JHEXEN__ DENG2_UNUSED(xgDataFollows); #endif // A version byte? int ver = 1; #if __JHEXEN__ if(mapVersion >= 3) #else if(mapVersion >= 5) #endif { ver = (int) Reader_ReadByte(reader); } if(ver >= 4) { P_SetIntp(li, DMU_FLAGS, Reader_ReadInt16(reader)); } int flags = Reader_ReadInt16(reader); if(xli->flags & ML_TWOSIDED) { flags |= ML_TWOSIDED; } if(ver < 4) { // Translate old line flags. int ddLineFlags = 0; if(flags & 0x0001) // old ML_BLOCKING flag { ddLineFlags |= DDLF_BLOCKING; flags &= ~0x0001; } if(flags & 0x0008) // old ML_DONTPEGTOP flag { ddLineFlags |= DDLF_DONTPEGTOP; flags &= ~0x0008; } if(flags & 0x0010) // old ML_DONTPEGBOTTOM flag { ddLineFlags |= DDLF_DONTPEGBOTTOM; flags &= ~0x0010; } P_SetIntp(li, DMU_FLAGS, ddLineFlags); } if(ver < 3) { if(flags & ML_MAPPED) { int lineIDX = P_ToIndex(li); // Set line as having been seen by all players.. de::zap(xli->mapped); for(int i = 0; i < MAXPLAYERS; ++i) { P_SetLineAutomapVisibility(i, lineIDX, true); } } } xli->flags = flags; if(ver >= 3) { for(int i = 0; i < MAXPLAYERS; ++i) { xli->mapped[i] = Reader_ReadByte(reader); } } #if __JHEXEN__ xli->special = Reader_ReadByte(reader); xli->arg1 = Reader_ReadByte(reader); xli->arg2 = Reader_ReadByte(reader); xli->arg3 = Reader_ReadByte(reader); xli->arg4 = Reader_ReadByte(reader); xli->arg5 = Reader_ReadByte(reader); #else xli->special = Reader_ReadInt16(reader); /*xli->tag =*/ Reader_ReadInt16(reader); #endif // For each side for(int i = 0; i < 2; ++i) { Side *si = (Side *)P_GetPtrp(li, (i? DMU_BACK:DMU_FRONT)); if(!si) continue; // Versions latter than 2 store per surface texture offsets. if(ver >= 2) { float offset[2]; offset[VX] = (float) Reader_ReadInt16(reader); offset[VY] = (float) Reader_ReadInt16(reader); P_SetFloatpv(si, DMU_TOP_MATERIAL_OFFSET_XY, offset); offset[VX] = (float) Reader_ReadInt16(reader); offset[VY] = (float) Reader_ReadInt16(reader); P_SetFloatpv(si, DMU_MIDDLE_MATERIAL_OFFSET_XY, offset); offset[VX] = (float) Reader_ReadInt16(reader); offset[VY] = (float) Reader_ReadInt16(reader); P_SetFloatpv(si, DMU_BOTTOM_MATERIAL_OFFSET_XY, offset); } else { float offset[2]; offset[VX] = (float) Reader_ReadInt16(reader); offset[VY] = (float) Reader_ReadInt16(reader); P_SetFloatpv(si, DMU_TOP_MATERIAL_OFFSET_XY, offset); P_SetFloatpv(si, DMU_MIDDLE_MATERIAL_OFFSET_XY, offset); P_SetFloatpv(si, DMU_BOTTOM_MATERIAL_OFFSET_XY, offset); } if(ver >= 3) { P_SetIntp(si, DMU_TOP_FLAGS, Reader_ReadInt16(reader)); P_SetIntp(si, DMU_MIDDLE_FLAGS, Reader_ReadInt16(reader)); P_SetIntp(si, DMU_BOTTOM_FLAGS, Reader_ReadInt16(reader)); } world_Material *topMaterial = 0, *bottomMaterial = 0, *middleMaterial = 0; #if !__JHEXEN__ if(mapVersion >= 4) #endif { topMaterial = msr->material(Reader_ReadInt16(reader), 1); bottomMaterial = msr->material(Reader_ReadInt16(reader), 1); middleMaterial = msr->material(Reader_ReadInt16(reader), 1); } P_SetPtrp(si, DMU_TOP_MATERIAL, topMaterial); P_SetPtrp(si, DMU_BOTTOM_MATERIAL, bottomMaterial); P_SetPtrp(si, DMU_MIDDLE_MATERIAL, middleMaterial); // Ver2 includes surface colours if(ver >= 2) { float rgba[4]; int flags; for(int k = 0; k < 3; ++k) rgba[k] = (float) Reader_ReadByte(reader) / 255.f; rgba[3] = 1; P_SetFloatpv(si, DMU_TOP_COLOR, rgba); for(int k = 0; k < 3; ++k) rgba[k] = (float) Reader_ReadByte(reader) / 255.f; rgba[3] = 1; P_SetFloatpv(si, DMU_BOTTOM_COLOR, rgba); for(int k = 0; k < 4; ++k) rgba[k] = (float) Reader_ReadByte(reader) / 255.f; P_SetFloatpv(si, DMU_MIDDLE_COLOR, rgba); P_SetIntp(si, DMU_MIDDLE_BLENDMODE, Reader_ReadInt32(reader)); flags = Reader_ReadInt16(reader); if(mapVersion < 12) { if(P_GetIntp(si, DMU_FLAGS) & SDF_SUPPRESS_BACK_SECTOR) flags |= SDF_SUPPRESS_BACK_SECTOR; } P_SetIntp(si, DMU_FLAGS, flags); } } #if !__JHEXEN__ if(xgDataFollows) { SV_ReadXGLine(li, msr); } #endif }
void playerheader_s::read(Reader1 *reader, int saveVersion) { #if __JHEXEN__ if(saveVersion >= 4) #else if(saveVersion >= 5) #endif { int ver = Reader_ReadByte(reader); #if !__JHERETIC__ DENG2_UNUSED(ver); #endif numPowers = Reader_ReadInt32(reader); numKeys = Reader_ReadInt32(reader); numFrags = Reader_ReadInt32(reader); numWeapons = Reader_ReadInt32(reader); numAmmoTypes = Reader_ReadInt32(reader); numPSprites = Reader_ReadInt32(reader); #if __JHERETIC__ if(ver >= 2) numInvItemTypes = Reader_ReadInt32(reader); else numInvItemTypes = NUM_INVENTORYITEM_TYPES; #endif #if __JHEXEN__ || __JDOOM64__ numInvItemTypes = Reader_ReadInt32(reader); #endif #if __JHEXEN__ numArmorTypes = Reader_ReadInt32(reader); #endif } else // The old format didn't save the counts. { #if __JHEXEN__ numPowers = 9; numKeys = 11; numFrags = 8; numWeapons = 4; numAmmoTypes = 2; numPSprites = 2; numInvItemTypes = 33; numArmorTypes = 4; #elif __JDOOM__ || __JDOOM64__ numPowers = 6; numKeys = 6; numFrags = 4; // Why was this only 4? numWeapons = 9; numAmmoTypes = 4; numPSprites = 2; # if __JDOOM64__ numInvItemTypes = 3; # endif #elif __JHERETIC__ numPowers = 9; numKeys = 3; numFrags = 4; // ? numWeapons = 8; numInvItemTypes = 14; numAmmoTypes = 6; numPSprites = 2; #endif } }
int light_s::read(MapStateReader *msr) { Reader1 *reader = msr->reader(); int mapVersion = msr->mapVersion(); if(mapVersion >= 4) { /*int ver =*/ Reader_ReadByte(reader); // version byte. type = (lighttype_t) Reader_ReadByte(reader); sector = (Sector *)P_ToPtr(DMU_SECTOR, Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); value1 = (float) Reader_ReadInt32(reader) / 255.0f; value2 = (float) Reader_ReadInt32(reader) / 255.0f; tics1 = Reader_ReadInt32(reader); tics2 = Reader_ReadInt32(reader); count = Reader_ReadInt32(reader); } else { // Its in the old pre V4 format which serialized light_t // Padding at the start (an old thinker_t struct) byte junk[16]; // sizeof thinker_t Reader_Read(reader, junk, 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); type = lighttype_t(Reader_ReadInt32(reader)); value1 = (float) Reader_ReadInt32(reader) / 255.0f; value2 = (float) Reader_ReadInt32(reader) / 255.0f; tics1 = Reader_ReadInt32(reader); tics2 = Reader_ReadInt32(reader); count = Reader_ReadInt32(reader); } thinker.function = (thinkfunc_t) T_Light; return true; // Add this thinker. }
int mobj_s::read(MapStateReader *msr) { #define FF_FULLBRIGHT 0x8000 ///< Used to be a flag in thing->frame. #define FF_FRAMEMASK 0x7fff Reader1 *reader = msr->reader(); int ver = Reader_ReadByte(reader); #if !__JHEXEN__ if(ver >= 2) // Version 2 has mobj archive numbers. { msr->addMobjToThingArchive(this, Reader_ReadInt16(reader)); } #endif #if !__JHEXEN__ target = 0; if(ver >= 2) { target = INT2PTR(mobj_t, Reader_ReadInt16(reader)); } #endif #if __JDOOM__ || __JDOOM64__ tracer = 0; if(ver >= 5) { tracer = INT2PTR(mobj_t, Reader_ReadInt16(reader)); } #endif onMobj = 0; #if __JHEXEN__ if(ver >= 8) #else if(ver >= 5) #endif { onMobj = INT2PTR(mobj_t, Reader_ReadInt16(reader)); } origin[VX] = FIX2FLT(Reader_ReadInt32(reader)); origin[VY] = FIX2FLT(Reader_ReadInt32(reader)); origin[VZ] = FIX2FLT(Reader_ReadInt32(reader)); angle = Reader_ReadInt32(reader); sprite = Reader_ReadInt32(reader); frame = Reader_ReadInt32(reader); // might be ORed with FF_FULLBRIGHT if(frame & FF_FULLBRIGHT) frame &= FF_FRAMEMASK; // not used anymore. #if __JHEXEN__ if(ver < 6) { /*floorflat =*/ Reader_ReadInt32(reader); } #else floorZ = FIX2FLT(Reader_ReadInt32(reader)); ceilingZ = FIX2FLT(Reader_ReadInt32(reader)); #endif radius = FIX2FLT(Reader_ReadInt32(reader)); height = FIX2FLT(Reader_ReadInt32(reader)); mom[MX] = FIX2FLT(Reader_ReadInt32(reader)); mom[MY] = FIX2FLT(Reader_ReadInt32(reader)); mom[MZ] = FIX2FLT(Reader_ReadInt32(reader)); valid = Reader_ReadInt32(reader); type = Reader_ReadInt32(reader); #if __JHEXEN__ if(ver < 7) { /*info = (mobjinfo_t *)*/ Reader_ReadInt32(reader); } #endif info = &MOBJINFO[type]; if(info->flags2 & MF2_FLOATBOB) mom[MZ] = 0; if(info->flags & MF_SOLID) ddFlags |= DDMF_SOLID; if(info->flags2 & MF2_DONTDRAW) ddFlags |= DDMF_DONTDRAW; tics = Reader_ReadInt32(reader); state = INT2PTR(state_t, Reader_ReadInt32(reader)); #if __JHEXEN__ damage = Reader_ReadInt32(reader); #endif flags = Reader_ReadInt32(reader); #if __JHEXEN__ flags2 = Reader_ReadInt32(reader); if(ver >= 5) { flags3 = Reader_ReadInt32(reader); } special1 = Reader_ReadInt32(reader); special2 = Reader_ReadInt32(reader); #endif health = Reader_ReadInt32(reader); #if __JHERETIC__ if(ver < 8) { // Fix a bunch of kludges in the original Heretic. switch(type) { case MT_MACEFX1: case MT_MACEFX2: case MT_MACEFX3: case MT_HORNRODFX2: case MT_HEADFX3: case MT_WHIRLWIND: case MT_TELEGLITTER: case MT_TELEGLITTER2: special3 = health; if(type == MT_HORNRODFX2 && special3 > 16) special3 = 16; health = MOBJINFO[type].spawnHealth; break; default: break; } } #endif moveDir = Reader_ReadInt32(reader); moveCount = Reader_ReadInt32(reader); #if __JHEXEN__ target = INT2PTR(mobj_t, Reader_ReadInt32(reader)); #endif reactionTime = Reader_ReadInt32(reader); threshold = Reader_ReadInt32(reader); player = INT2PTR(player_t, Reader_ReadInt32(reader)); lastLook = Reader_ReadInt32(reader); #if __JHEXEN__ floorClip = FIX2FLT(Reader_ReadInt32(reader)); msr->addMobjToThingArchive(this, Reader_ReadInt32(reader)); tid = Reader_ReadInt32(reader); #else // For nightmare respawn. if(ver >= 6) { spawnSpot.origin[VX] = FIX2FLT(Reader_ReadInt32(reader)); spawnSpot.origin[VY] = FIX2FLT(Reader_ReadInt32(reader)); spawnSpot.origin[VZ] = FIX2FLT(Reader_ReadInt32(reader)); spawnSpot.angle = Reader_ReadInt32(reader); if(ver < 10) { /*spawnSpot.type =*/ Reader_ReadInt32(reader); } spawnSpot.flags = Reader_ReadInt32(reader); } else { spawnSpot.origin[VX] = (float) Reader_ReadInt16(reader); spawnSpot.origin[VY] = (float) Reader_ReadInt16(reader); spawnSpot.origin[VZ] = 0; // Initialize with "something". spawnSpot.angle = (angle_t) (ANG45 * (Reader_ReadInt16(reader) / 45)); /*spawnSpot.type = (int)*/ Reader_ReadInt16(reader); spawnSpot.flags = (int) Reader_ReadInt16(reader); } # if __JDOOM__ || __JDOOM64__ if(ver >= 3) # elif __JHERETIC__ if(ver >= 5) # endif { intFlags = Reader_ReadInt32(reader); dropOffZ = FIX2FLT(Reader_ReadInt32(reader)); gear = Reader_ReadInt32(reader); } # if __JDOOM__ || __JDOOM64__ if(ver >= 6) { damage = Reader_ReadInt32(reader); flags2 = Reader_ReadInt32(reader); } else // flags2 will be applied from the defs. { damage = DDMAXINT; // Use the value set in mo->info->damage } # elif __JHERETIC__ damage = Reader_ReadInt32(reader); flags2 = Reader_ReadInt32(reader); # endif if(ver >= 7) { flags3 = Reader_ReadInt32(reader); } // Else flags3 will be applied from the defs. #endif #if __JHEXEN__ special = Reader_ReadInt32(reader); Reader_Read(reader, args, 1 * 5); #elif __JHERETIC__ special1 = Reader_ReadInt32(reader); special2 = Reader_ReadInt32(reader); if(ver >= 8) { special3 = Reader_ReadInt32(reader); } #endif #if __JHEXEN__ if(ver >= 2) #else if(ver >= 4) #endif { translucency = Reader_ReadByte(reader); } #if __JHEXEN__ if(ver >= 3) #else if(ver >= 5) #endif { visTarget = (short) (Reader_ReadByte(reader)) -1; } #if __JHEXEN__ if(ver >= 4) { tracer = INT2PTR(mobj_t, Reader_ReadInt32(reader)); } if(ver >= 4) { lastEnemy = INT2PTR(mobj_t, Reader_ReadInt32(reader)); } #else if(ver >= 5) { floorClip = FIX2FLT(Reader_ReadInt32(reader)); } #endif #if __JHERETIC__ if(ver >= 7) { generator = INT2PTR(mobj_t, Reader_ReadInt16(reader)); } else { generator = 0; } #endif /* * Restore! (unmangle) */ info = &MOBJINFO[type]; Mobj_SetState(this, PTR2INT(state)); #if __JHEXEN__ if(flags2 & MF2_DORMANT) { tics = -1; } #endif if(player) { // The player number translation table is used to find out the // *current* (actual) player number of the referenced player. player = msr->player(PTR2INT(player)); #if __JHEXEN__ if(!player) { // This saved player does not exist in the current game! // Destroy this mobj. Mobj_Destroy(this); return false; } #endif dPlayer = player->plr; dPlayer->mo = this; //dPlayer->clAngle = angle; /* $unifiedangles */ dPlayer->lookDir = 0; /* $unifiedangles */ } visAngle = angle >> 16; #if !__JHEXEN__ if(dPlayer && !dPlayer->inGame) { dPlayer->mo = 0; Mobj_Destroy(this); return false; } #endif #if !__JDOOM64__ // Do we need to update this mobj's flag values? if(ver < MOBJ_SAVEVERSION) { SV_TranslateLegacyMobjFlags(this, ver); } #endif P_MobjLink(this); floorZ = P_GetDoublep(Mobj_Sector(this), DMU_FLOOR_HEIGHT); ceilingZ = P_GetDoublep(Mobj_Sector(this), DMU_CEILING_HEIGHT); return false; #undef FF_FRAMEMASK #undef FF_FULLBRIGHT }
int pillar_s::read(MapStateReader *msr) { Reader1 *reader = msr->reader(); int mapVersion = msr->mapVersion(); if(mapVersion >= 4) { // Note: the thinker class byte has already been read. /*int ver =*/ Reader_ReadByte(reader); // version byte. // Start of used data members. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); ceilingSpeed = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); floorSpeed = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); floorDest = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); ceilingDest = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); direction = Reader_ReadInt32(reader); crush = Reader_ReadInt32(reader); } else { // Its in the old pre V4 format which serialized pillar_t // Padding at the start (an old thinker_t struct) byte junk[16]; // sizeof thinker_t Reader_Read(reader, junk, 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); ceilingSpeed = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); floorSpeed = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); floorDest = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); ceilingDest = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); direction = Reader_ReadInt32(reader); crush = Reader_ReadInt32(reader); } thinker.function = (thinkfunc_t) T_BuildPillar; P_ToXSector(sector)->specialData = this; return true; // Add this thinker. }
int plat_t::read(MapStateReader *msr) { Reader *reader = msr->reader(); int mapVersion = msr->mapVersion(); #if __JHEXEN__ if(mapVersion >= 4) #else if(mapVersion >= 5) #endif { // Note: the thinker class byte has already been read. /*int ver =*/ Reader_ReadByte(reader); // version byte. thinker.function = T_PlatRaise; #if !__JHEXEN__ // Should we put this into stasis? if(mapVersion == 5) { if(!Reader_ReadByte(reader)) Thinker_SetStasis(&thinker, true); } #endif type = plattype_e(Reader_ReadByte(reader)); sector = (Sector *)P_ToPtr(DMU_SECTOR, Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); speed = FIX2FLT(Reader_ReadInt32(reader)); low = (float) Reader_ReadInt16(reader); high = (float) Reader_ReadInt16(reader); wait = Reader_ReadInt32(reader); count = Reader_ReadInt32(reader); state = platstate_e(Reader_ReadByte(reader)); oldState = platstate_e(Reader_ReadByte(reader)); crush = (dd_bool) Reader_ReadByte(reader); tag = Reader_ReadInt32(reader); } else { // Its in the old format which serialized plat_t // Padding at the start (an old thinker_t struct) int32_t junk[4]; // sizeof thinker_t Reader_Read(reader, (byte *)junk, 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); speed = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); low = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); high = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); wait = Reader_ReadInt32(reader); count = Reader_ReadInt32(reader); state = platstate_e(Reader_ReadInt32(reader)); oldState = platstate_e(Reader_ReadInt32(reader)); crush = Reader_ReadInt32(reader); tag = Reader_ReadInt32(reader); type = plattype_e(Reader_ReadInt32(reader)); thinker.function = T_PlatRaise; #if !__JHEXEN__ if(junk[2] == 0) { Thinker_SetStasis(&thinker, true); } #endif } P_ToXSector(sector)->specialData = this; return true; // Add this thinker. }