void P_RecalculateAttached3DFloors(sector_t * sec) { extsector_t::xfloor &x = sec->e->XFloor; for(unsigned int i=0; i<x.attached.Size(); i++) { P_Recalculate3DFloors(x.attached[i]); } P_Recalculate3DFloors(sec); }
//========================================================================== // // Spawns 3D floors // //========================================================================== void P_Spawn3DFloors (void) { static int flagvals[] = {128+512, 2+512, 512}; int i; line_t * line; for (i=0,line=lines;i<numlines;i++,line++) { switch(line->special) { case ExtraFloor_LightOnly: // Note: I am spawning both this and ZDoom's ExtraLight data // I don't want to mess with both at the same time during rendering // so inserting this into the 3D-floor table as well seemed to be // the best option. // // This does not yet handle case 0 properly! if (line->args[1] < 0 || line->args[1] > 2) line->args[1] = 0; P_Set3DFloor(line, 3, flagvals[line->args[1]], 0); break; case Sector_Set3DFloor: // The flag high-byte/line id is only needed in Hexen format. // UDMF can set both of these parameters without any restriction of the usable values. // In Doom format the translators can take full integers for the tag and the line ID always is the same as the tag. if (level.maptype == MAPTYPE_HEXEN) { if (line->args[1]&8) { tagManager.AddLineID(i, line->args[4]); } else { line->args[0]+=256*line->args[4]; line->args[4]=0; } } P_Set3DFloor(line, line->args[1]&~8, line->args[2], line->args[3]); break; default: continue; } line->special=0; line->args[0] = line->args[1] = line->args[2] = line->args[3] = line->args[4] = 0; } // kg3D - do it in software for (i = 0; i < numsectors; i++) { P_Recalculate3DFloors(§ors[i]); } }
//========================================================================== // // Spawns 3D floors // //========================================================================== void P_Spawn3DFloors (void) { static int flagvals[] = {512, 2+512, 512+1024}; int i; line_t * line; for (i=0,line=lines;i<numlines;i++,line++) { switch(line->special) { case ExtraFloor_LightOnly: if (line->args[1] < 0 || line->args[1] > 2) line->args[1] = 0; P_Set3DFloor(line, 3, flagvals[line->args[1]], 0); break; case Sector_Set3DFloor: // The flag high-byte/line id is only needed in Hexen format. // UDMF can set both of these parameters without any restriction of the usable values. // In Doom format the translators can take full integers for the tag and the line ID always is the same as the tag. if (level.maptype == MAPTYPE_HEXEN) { if (line->args[1]&8) { tagManager.AddLineID(i, line->args[4]); } else { line->args[0]+=256*line->args[4]; line->args[4]=0; } } P_Set3DFloor(line, line->args[1]&~8, line->args[2], line->args[3]); break; default: continue; } line->special=0; line->args[0] = line->args[1] = line->args[2] = line->args[3] = line->args[4] = 0; } // kg3D - do it in software for (i = 0; i < numsectors; i++) { P_Recalculate3DFloors(§ors[i]); } }
void G_SerializeLevel(FSerializer &arc, bool hubload) { int i = level.totaltime; if (arc.isWriting()) { arc.Array("checksum", level.md5, 16); } else { // prevent bad things from happening by doing a check on the size of level arrays and the map's entire checksum. // The old code happily tried to load savegames with any mismatch here, often causing meaningless errors // deep down in the deserializer or just a crash if the few insufficient safeguards were not triggered. BYTE chk[16] = { 0 }; arc.Array("checksum", chk, 16); if (arc.GetSize("linedefs") != (unsigned)numlines || arc.GetSize("sidedefs") != (unsigned)numsides || arc.GetSize("sectors") != (unsigned)numsectors || arc.GetSize("polyobjs") != (unsigned)po_NumPolyobjs || memcmp(chk, level.md5, 16)) { I_Error("Savegame is from a different level"); } } arc("saveversion", SaveVersion); Renderer->StartSerialize(arc); if (arc.isReading()) { DThinker::DestroyAllThinkers(); interpolator.ClearInterpolations(); arc.ReadObjects(hubload); } arc("level.flags", level.flags) ("level.flags2", level.flags2) ("level.fadeto", level.fadeto) ("level.found_secrets", level.found_secrets) ("level.found_items", level.found_items) ("level.killed_monsters", level.killed_monsters) ("level.total_secrets", level.total_secrets) ("level.total_items", level.total_items) ("level.total_monsters", level.total_monsters) ("level.gravity", level.gravity) ("level.aircontrol", level.aircontrol) ("level.teamdamage", level.teamdamage) ("level.maptime", level.maptime) ("level.totaltime", i) ("level.skytexture1", level.skytexture1) ("level.skytexture2", level.skytexture2); // Hub transitions must keep the current total time if (!hubload) level.totaltime = i; if (arc.isReading()) { sky1texture = level.skytexture1; sky2texture = level.skytexture2; R_InitSkyMap(); G_AirControlChanged(); } // fixme: This needs to ensure it reads from the correct place. Should be one once there's enough of this code converted to JSON FBehavior::StaticSerializeModuleStates(arc); // The order here is important: First world state, then portal state, then thinkers, and last polyobjects. arc.Array("linedefs", lines, &loadlines[0], numlines); arc.Array("sidedefs", sides, &loadsides[0], numsides); arc.Array("sectors", sectors, &loadsectors[0], numsectors); arc("zones", Zones); arc("lineportals", linePortals); arc("sectorportals", sectorPortals); if (arc.isReading()) P_CollectLinkedPortals(); DThinker::SerializeThinkers(arc, !hubload); arc.Array("polyobjs", polyobjs, po_NumPolyobjs); arc("subsectors", subsectors); StatusBar->SerializeMessages(arc); AM_SerializeMarkers(arc); FRemapTable::StaticSerializeTranslations(arc); FCanvasTextureInfo::Serialize(arc); P_SerializePlayers(arc, hubload); P_SerializeSounds(arc); if (arc.isReading()) { for (int i = 0; i < numsectors; i++) { P_Recalculate3DFloors(§ors[i]); } for (int i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i] && players[i].mo != NULL) { players[i].mo->SetupWeaponSlots(); } } } Renderer->EndSerialize(arc); }
static void PrepareTransparentDoors(sector_t * sector) { bool solidwall=false; int notextures=0; int nobtextures=0; int selfref=0; int i; sector_t * nextsec=NULL; #ifdef _DEBUG if (sector-sectors==2) { int a = 0; } #endif P_Recalculate3DFloors(sector); if (sector->subsectorcount==0) return; sector->transdoorheight=sector->GetPlaneTexZ(sector_t::floor); sector->transdoor= !(sector->e->XFloor.ffloors.Size() || sector->heightsec || sector->floorplane.isSlope()); if (sector->transdoor) { for (i=0; i<sector->linecount; i++) { if (sector->lines[i]->frontsector==sector->lines[i]->backsector) { selfref++; continue; } sector_t * sec=getNextSector(sector->lines[i], sector); if (sec==NULL) { solidwall=true; continue; } else { nextsec=sec; int side = sector->lines[i]->sidedef[0]->sector == sec; if (sector->GetPlaneTexZ(sector_t::floor)!=sec->GetPlaneTexZ(sector_t::floor)+1. || sec->floorplane.isSlope()) { sector->transdoor=false; return; } if (!sector->lines[i]->sidedef[1-side]->GetTexture(side_t::top).isValid()) notextures++; if (!sector->lines[i]->sidedef[1-side]->GetTexture(side_t::bottom).isValid()) nobtextures++; } } if (sector->GetTexture(sector_t::ceiling)==skyflatnum) { sector->transdoor=false; return; } if (selfref+nobtextures!=sector->linecount) { sector->transdoor=false; } if (selfref+notextures!=sector->linecount) { // This is a crude attempt to fix an incorrect transparent door effect I found in some // WolfenDoom maps but considering the amount of code required to handle it I left it in. // Do this only if the sector only contains one-sided walls or ones with no lower texture. if (solidwall) { if (solidwall+nobtextures+selfref==sector->linecount && nextsec) { sector->heightsec=nextsec; sector->heightsec->MoreFlags=0; } sector->transdoor=false; } } } }
void G_SerializeLevel (FArchive &arc, bool hubLoad) { int i = level.totaltime; Renderer->StartSerialize(arc); arc << level.flags << level.flags2 << level.fadeto << level.found_secrets << level.found_items << level.killed_monsters << level.gravity << level.aircontrol << level.teamdamage << level.maptime << i; if (SaveVersion >= 3313) { arc << level.nextmusic; } // Hub transitions must keep the current total time if (!hubLoad) level.totaltime = i; if (SaveVersion >= 4507) { arc << level.skytexture1 << level.skytexture2; } else { level.skytexture1 = TexMan.GetTexture(arc.ReadName(), FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); level.skytexture2 = TexMan.GetTexture(arc.ReadName(), FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); } if (arc.IsLoading()) { sky1texture = level.skytexture1; sky2texture = level.skytexture2; R_InitSkyMap(); } G_AirControlChanged (); BYTE t; // Does this level have scrollers? if (arc.IsStoring ()) { t = level.Scrolls ? 1 : 0; arc << t; } else { arc << t; if (level.Scrolls) { delete[] level.Scrolls; level.Scrolls = NULL; } if (t) { level.Scrolls = new FSectorScrollValues[numsectors]; memset (level.Scrolls, 0, sizeof(level.Scrolls)*numsectors); } } FBehavior::StaticSerializeModuleStates (arc); if (arc.IsLoading()) interpolator.ClearInterpolations(); P_SerializeThinkers (arc, hubLoad); P_SerializeWorld (arc); P_SerializePolyobjs (arc); P_SerializeSubsectors(arc); StatusBar->Serialize (arc); if (SaveVersion >= 4222) { // This must be done *after* thinkers are serialized. arc << level.DefaultSkybox; } arc << level.total_monsters << level.total_items << level.total_secrets; // Does this level have custom translations? FRemapTable *trans; WORD w; if (arc.IsStoring ()) { for (unsigned int i = 0; i < translationtables[TRANSLATION_LevelScripted].Size(); ++i) { trans = translationtables[TRANSLATION_LevelScripted][i]; if (trans != NULL && !trans->IsIdentity()) { w = WORD(i); arc << w; trans->Serialize(arc); } } w = 0xffff; arc << w; } else { while (arc << w, w != 0xffff) { trans = translationtables[TRANSLATION_LevelScripted].GetVal(w); if (trans == NULL) { trans = new FRemapTable; translationtables[TRANSLATION_LevelScripted].SetVal(w, trans); } trans->Serialize(arc); } } // This must be saved, too, of course! FCanvasTextureInfo::Serialize (arc); AM_SerializeMarkers(arc); P_SerializePlayers (arc, hubLoad); P_SerializeSounds (arc); if (arc.IsLoading()) { for (i = 0; i < numsectors; i++) { P_Recalculate3DFloors(§ors[i]); } for (i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i] && players[i].mo != NULL) { players[i].mo->SetupWeaponSlots(); } } } Renderer->EndSerialize(arc); }
void G_SerializeLevel (FArchive &arc, bool hubLoad) { int i = level.totaltime; Renderer->StartSerialize(arc); if (arc.IsLoading()) P_DestroyThinkers(hubLoad); arc << level.flags << level.flags2 << level.fadeto << level.found_secrets << level.found_items << level.killed_monsters << level.gravity << level.aircontrol << level.teamdamage << level.maptime << i; // Hub transitions must keep the current total time if (!hubLoad) level.totaltime = i; arc << level.skytexture1 << level.skytexture2; if (arc.IsLoading()) { sky1texture = level.skytexture1; sky2texture = level.skytexture2; R_InitSkyMap(); } G_AirControlChanged (); BYTE t; // Does this level have scrollers? if (arc.IsStoring ()) { t = level.Scrolls ? 1 : 0; arc << t; } else { arc << t; if (level.Scrolls) { delete[] level.Scrolls; level.Scrolls = NULL; } if (t) { level.Scrolls = new FSectorScrollValues[numsectors]; memset (level.Scrolls, 0, sizeof(level.Scrolls)*numsectors); } } FBehavior::StaticSerializeModuleStates (arc); if (arc.IsLoading()) interpolator.ClearInterpolations(); P_SerializeWorld(arc); P_SerializeThinkers (arc, hubLoad); P_SerializeWorldActors(arc); // serializing actor pointers in the world data must be done after SerializeWorld has restored the entire sector state, otherwise LinkToWorld may fail. P_SerializePolyobjs (arc); P_SerializeSubsectors(arc); StatusBar->Serialize (arc); arc << level.total_monsters << level.total_items << level.total_secrets; // Does this level have custom translations? FRemapTable *trans; WORD w; if (arc.IsStoring ()) { for (unsigned int i = 0; i < translationtables[TRANSLATION_LevelScripted].Size(); ++i) { trans = translationtables[TRANSLATION_LevelScripted][i]; if (trans != NULL && !trans->IsIdentity()) { w = WORD(i); arc << w; trans->Serialize(arc); } } w = 0xffff; arc << w; } else { while (arc << w, w != 0xffff) { trans = translationtables[TRANSLATION_LevelScripted].GetVal(w); if (trans == NULL) { trans = new FRemapTable; translationtables[TRANSLATION_LevelScripted].SetVal(w, trans); } trans->Serialize(arc); } } // This must be saved, too, of course! FCanvasTextureInfo::Serialize (arc); AM_SerializeMarkers(arc); P_SerializePlayers (arc, hubLoad); P_SerializeSounds (arc); if (arc.IsLoading()) { for (i = 0; i < numsectors; i++) { P_Recalculate3DFloors(§ors[i]); } for (i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i] && players[i].mo != NULL) { players[i].mo->SetupWeaponSlots(); } } } Renderer->EndSerialize(arc); }