diff --git a/src/actor.h b/src/actor.h index 9e9d71237..1993a92f0 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1167,7 +1167,7 @@ private: bool FixMapthingPos(); public: - void LinkToWorld (bool spawningmapthing=false, FPortalGroupArray *groups = NULL, sector_t *sector = NULL); + void LinkToWorld (bool spawningmapthing=false, sector_t *sector = NULL); void UnlinkFromWorld (); void AdjustFloorClip (); virtual void SetOrigin (fixed_t x, fixed_t y, fixed_t z, bool moving = false); diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index e1a86b8fc..8c456517e 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2505,9 +2505,9 @@ static bool DoDehPatch() { if (PatchFile[25] < '3') { + Printf (PRINT_BOLD, "\"%s\" is an old and unsupported DeHackEd patch\n", PatchName); delete[] PatchName; delete[] PatchFile; - Printf (PRINT_BOLD, "\"%s\" is an old and unsupported DeHackEd patch\n", PatchFile); return false; } // fix for broken WolfenDoom patches which contain \0 characters in some places. diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 68020dcec..1fc63e03d 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -381,13 +381,15 @@ int FIWadManager::CheckIWAD (const char *doomwaddir, WadStuff *wads) // //========================================================================== +static bool havepicked = false; + int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, const char *zdoom_wad) { TArray wads; TArray foundwads; const char *iwadparm = Args->CheckValue ("-iwad"); - size_t numwads; int pickwad; + size_t numwads; size_t i; bool iwadparmfound = false; FString custwad; @@ -536,26 +538,29 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, { for (i = 0; i < numwads; ++i) { - FString basename = ExtractFileBase (wads[i].Path); - if (stricmp (basename, defaultiwad) == 0) + FString basename = ExtractFileBase(wads[i].Path); + if (stricmp(basename, defaultiwad) == 0) { defiwad = (int)i; break; } } } - pickwad = I_PickIWad (&wads[0], (int)numwads, queryiwad, defiwad); - if (pickwad >= 0) + if (!havepicked) // just use the first IWAD if the restart doesn't have a -iwad parameter. We cannot open the picker in fullscreen mode. { - // The newly selected IWAD becomes the new default - FString basename = ExtractFileBase (wads[pickwad].Path); - defaultiwad = basename; + pickwad = I_PickIWad(&wads[0], (int)numwads, queryiwad, defiwad); + if (pickwad >= 0) + { + // The newly selected IWAD becomes the new default + FString basename = ExtractFileBase(wads[pickwad].Path); + defaultiwad = basename; + } + if (pickwad < 0) + exit(0); + havepicked = true; } } - if (pickwad < 0) - exit (0); - // zdoom.pk3 must always be the first file loaded and the IWAD second. wadfiles.Clear(); D_AddFile (wadfiles, zdoom_wad); diff --git a/src/p_map.cpp b/src/p_map.cpp index e3ab370d0..8174d8e77 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -5250,7 +5250,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo double bombdistancefloat = 1.f / (double)(bombdistance - fulldamagedistance); double bombdamagefloat = (double)bombdamage; - FPortalGroupArray grouplist; + FPortalGroupArray grouplist(FPortalGroupArray::PGA_Full3d); FMultiBlockThingsIterator it(grouplist, bombspot->X(), bombspot->Y(), bombspot->Z() - bombdistfix, bombspot->height + bombdistfix*2, bombdistfix); FMultiBlockThingsIterator::CheckResult cres; diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 20fe996a5..b9d682e6e 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -435,7 +435,7 @@ bool AActor::FixMapthingPos() // //========================================================================== -void AActor::LinkToWorld (bool spawningmapthing, FPortalGroupArray *groups, sector_t *sector) +void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector) { if (spawningmapthing && (flags4 & MF4_FIXMAPTHINGPOS) && sector == NULL) { @@ -457,7 +457,7 @@ void AActor::LinkToWorld (bool spawningmapthing, FPortalGroupArray *groups, sect Sector = sector; subsector = R_PointInSubsector(X(), Y()); // this is from the rendering nodes, not the gameplay nodes! - if ( !(flags & MF_NOSECTOR) ) + if (!(flags & MF_NOSECTOR)) { // invisible things don't go into the sector links // killough 8/11/98: simpler scheme using pointer-to-pointer prev @@ -482,51 +482,60 @@ void AActor::LinkToWorld (bool spawningmapthing, FPortalGroupArray *groups, sect // When a node is deleted, its sector links (the links starting // at sector_t->touching_thinglist) are broken. When a node is // added, new sector links are created. - P_CreateSecNodeList (this, X(), Y()); + P_CreateSecNodeList(this, X(), Y()); touching_sectorlist = sector_list; // Attach to thing sector_list = NULL; // clear for next time - } + } + - // link into blockmap (inert things don't need to be in the blockmap) - if ( !(flags & MF_NOBLOCKMAP) ) + if (!(flags & MF_NOBLOCKMAP)) { - int x1 = GetSafeBlockX(X() - radius - bmaporgx); - int x2 = GetSafeBlockX(X() + radius - bmaporgx); - int y1 = GetSafeBlockY(Y() - radius - bmaporgy); - int y2 = GetSafeBlockY(Y() + radius - bmaporgy); + FPortalGroupArray check(FPortalGroupArray::PGA_NoSectorPortals); - if (x1 >= bmapwidth || x2 < 0 || y1 >= bmapheight || y2 < 0) - { // thing is off the map - BlockNode = NULL; - } - else - { // [RH] Link into every block this actor touches, not just the center one - FBlockNode **alink = &this->BlockNode; - x1 = MAX (0, x1); - y1 = MAX (0, y1); - x2 = MIN (bmapwidth - 1, x2); - y2 = MIN (bmapheight - 1, y2); - for (int y = y1; y <= y2; ++y) - { - for (int x = x1; x <= x2; ++x) + P_CollectConnectedGroups(Sector->PortalGroup, Pos(), Top(), radius, check); + + for (int i = -1; i < (int)check.Size(); i++) + { + fixedvec3 pos = i==-1? Pos() : PosRelative(check[i]); + + int x1 = GetSafeBlockX(pos.x - radius - bmaporgx); + int x2 = GetSafeBlockX(pos.x + radius - bmaporgx); + int y1 = GetSafeBlockY(pos.y - radius - bmaporgy); + int y2 = GetSafeBlockY(pos.y + radius - bmaporgy); + + if (x1 >= bmapwidth || x2 < 0 || y1 >= bmapheight || y2 < 0) + { // thing is off the map + BlockNode = NULL; + } + else + { // [RH] Link into every block this actor touches, not just the center one + FBlockNode **alink = &this->BlockNode; + x1 = MAX(0, x1); + y1 = MAX(0, y1); + x2 = MIN(bmapwidth - 1, x2); + y2 = MIN(bmapheight - 1, y2); + for (int y = y1; y <= y2; ++y) { - FBlockNode **link = &blocklinks[y*bmapwidth + x]; - FBlockNode *node = FBlockNode::Create (this, x, y, this->Sector->PortalGroup); - - // Link in to block - if ((node->NextActor = *link) != NULL) + for (int x = x1; x <= x2; ++x) { - (*link)->PrevActor = &node->NextActor; - } - node->PrevActor = link; - *link = node; + FBlockNode **link = &blocklinks[y*bmapwidth + x]; + FBlockNode *node = FBlockNode::Create(this, x, y, this->Sector->PortalGroup); - // Link in to actor - node->PrevBlock = alink; - node->NextBlock = NULL; - (*alink) = node; - alink = &node->NextBlock; + // Link in to block + if ((node->NextActor = *link) != NULL) + { + (*link)->PrevActor = &node->NextActor; + } + node->PrevActor = link; + *link = node; + + // Link in to actor + node->PrevBlock = alink; + node->NextBlock = NULL; + (*alink) = node; + alink = &node->NextBlock; + } } } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a9e23c2a8..87fe34837 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -456,7 +456,7 @@ void AActor::Serialize (FArchive &arc) if (arc.IsLoading ()) { touching_sectorlist = NULL; - LinkToWorld (false, NULL, Sector); + LinkToWorld (false, Sector); AddToHash (); SetShade (fillcolor); if (player) diff --git a/src/portal.cpp b/src/portal.cpp index a6446a82b..63dfeafe6 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -1107,7 +1107,25 @@ void P_CreateLinkedPortals() } } } - //BuildBlockmap(); + if (linkedPortals.Size() > 0) + { + // We need to relink all actors that may touch a linked line portal + TThinkerIterator it; + AActor *actor; + while ((actor = it.Next())) + { + if (!(actor->flags & MF_NOBLOCKMAP)) + { + FPortalGroupArray check(FPortalGroupArray::PGA_NoSectorPortals); + P_CollectConnectedGroups(actor->Sector->PortalGroup, actor->Pos(), actor->Top(), actor->radius, check); + if (check.Size() > 0) + { + actor->UnlinkFromWorld(); + actor->LinkToWorld(); + } + } + } + } } @@ -1208,7 +1226,7 @@ bool P_CollectConnectedGroups(int startgroup, const fixedvec3 &position, fixed_t wsec = P_PointInSector(dx, dy); // get lower sector at the exact spot we want to check and repeat retval = true; } - if (out.method == FPortalGroupArray::PGA_Full3d) + if (out.method == FPortalGroupArray::PGA_Full3d && PortalBlockmap.hasLinkedSectorPortals) { groupsToCheck.Clear(); groupsToCheck.Push(startgroup); diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 4cdf31747..072059901 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -5024,9 +5024,7 @@ void A_Weave(AActor *self, int xyspeed, int zspeed, fixed_t xydist, fixed_t zdis { self->UnlinkFromWorld (); self->flags |= MF_NOBLOCKMAP; - // the following 4 lines are for future-proofing this for both interpolation overhaul and line portals. - // For portals we need to calculate the destination including the portal offset - // and for interpolation we need to set the performed movement explicitly, because SetXY cannot do that. + // We need to do portal offsetting here explicitly, because SetXY cannot do that. newX -= self->X(); newY -= self->Y(); self->SetXY(self->Vec2Offset(newX, newY));