diff --git a/src/actor.h b/src/actor.h index 35afef397..47f6ef44b 100644 --- a/src/actor.h +++ b/src/actor.h @@ -742,6 +742,7 @@ public: bool IsHostile (AActor *other); inline bool IsNoClip2() const; + void CheckPortalTransition(); // What species am I? virtual FName GetSpecies(); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7228ffbff..73683824b 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3288,6 +3288,43 @@ void AActor::SetRoll(angle_t r, bool interpolate) } } + +void AActor::CheckPortalTransition() +{ + if (!Sector->PortalBlocksMovement(sector_t::ceiling)) + { + AActor *port = Sector->SkyBoxes[sector_t::ceiling]; + if (Z() > port->threshold) + { + fixedvec3 oldpos = Pos(); + UnlinkFromWorld(); + SetXYZ(PosRelative(port->Sector)); + PrevX += X() - oldpos.x; + PrevY += Y() - oldpos.y; + PrevZ += Z() - oldpos.z; + LinkToWorld(); + if (player) Printf("Transitioned upwards to sector %d\n", Sector->sectornum); + return; + } + } + if (!Sector->PortalBlocksMovement(sector_t::floor)) + { + AActor *port = Sector->SkyBoxes[sector_t::floor]; + if (Z() < port->threshold && floorz < port->threshold) + { + fixedvec3 oldpos = Pos(); + UnlinkFromWorld(); + SetXYZ(PosRelative(port->Sector)); + PrevX += X() - oldpos.x; + PrevY += Y() - oldpos.y; + PrevZ += Z() - oldpos.z; + LinkToWorld(); + if (player) Printf("Transitioned downwards to sector %d\n", Sector->sectornum); + return; + } + } +} + // // P_MobjThinker // @@ -3355,6 +3392,7 @@ void AActor::Tick () UnlinkFromWorld (); flags |= MF_NOBLOCKMAP; SetXYZ(Vec3Offset(velx, vely, velz)); + CheckPortalTransition(); SetMovement(velx, vely, velz); LinkToWorld (); } @@ -3822,6 +3860,8 @@ void AActor::Tick () Crash(); } + CheckPortalTransition(); + UpdateWaterLevel (oldz); // [RH] Don't advance if predicting a player diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 10a39ba57..60a415d80 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -581,8 +581,11 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi iview->oviewpitch = iview->nviewpitch; iview->oviewangle = iview->nviewangle; } - viewx = iview->oviewx + FixedMul (frac, iview->nviewx - iview->oviewx); - viewy = iview->oviewy + FixedMul (frac, iview->nviewy - iview->oviewy); + int oldgroup = R_PointInSubsector(iview->oviewx, iview->oviewy)->sector->PortalGroup; + int newgroup = R_PointInSubsector(iview->nviewx, iview->nviewy)->sector->PortalGroup; + fixedvec2 disp = Displacements(oldgroup, newgroup); + viewx = iview->oviewx + FixedMul (frac, iview->nviewx - iview->oviewx - disp.x); + viewy = iview->oviewy + FixedMul (frac, iview->nviewy - iview->oviewy - disp.y); viewz = iview->oviewz + FixedMul (frac, iview->nviewz - iview->oviewz); if (player != NULL && !(player->cheats & CF_INTERPVIEW) && @@ -637,6 +640,26 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi // Due to interpolation this is not necessarily the same as the sector the camera is in. viewsector = R_PointInSubsector(viewx, viewy)->sector; + if (!viewsector->PortalBlocksMovement(sector_t::ceiling)) + { + AActor *point = viewsector->SkyBoxes[sector_t::ceiling]; + if (viewz > point->threshold) + { + viewx += point->scaleX; + viewy += point->scaleY; + viewsector = R_PointInSubsector(viewx, viewy)->sector; + } + } + if (!viewsector->PortalBlocksMovement(sector_t::floor)) + { + AActor *point = viewsector->SkyBoxes[sector_t::floor]; + if (viewz < point->threshold) + { + viewx += point->scaleX; + viewy += point->scaleY; + viewsector = R_PointInSubsector(viewx, viewy)->sector; + } + } } //==========================================================================