From 428bd52295c1ac1b8ab4876f82ecb6a9ba1edaad Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 20 May 2016 13:10:42 +0200 Subject: [PATCH] - fixed: It was not possible to step through a ceiling portal into the upper sector. --- src/p_checkposition.h | 3 ++- src/p_map.cpp | 33 +++++++++++++++++++++++++++++++++ src/p_mobj.cpp | 16 +++++++++------- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/p_checkposition.h b/src/p_checkposition.h index d0d4a3826..98891b87c 100644 --- a/src/p_checkposition.h +++ b/src/p_checkposition.h @@ -33,8 +33,9 @@ struct FCheckPosition AActor *stepthing; // [RH] These are used by PIT_CheckThing and P_XYMovement to apply // ripping damage once per tic instead of once per move. - bool DoRipping; TMap LastRipped; + bool DoRipping; + bool portalstep; int PushTime; diff --git a/src/p_map.cpp b/src/p_map.cpp index 8fd274437..c5bf741da 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -728,6 +728,22 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec // Since a one-sided line does not have an opening there's nothing left to do about it. return true; } + + // check if the actor can step through the ceiling portal. In this case one-sided lines in the current area should not block + if (!cres.line->frontsector->PortalBlocksMovement(sector_t::ceiling)) + { + double portz = cres.line->frontsector->GetPortalPlaneZ(sector_t::ceiling); + if (tm.thing->Z() < portz && tm.thing->Z() + tm.thing->MaxStepHeight >= portz && tm.floorz < portz) + { + tm.floorz = portz; + tm.floorsector = cres.line->frontsector; + tm.floorpic = cres.line->sidedef[0]->GetTexture(side_t::mid); + tm.floorterrain = 0; + tm.portalstep = true; + return true; + } + } + if (tm.thing->flags2 & MF2_BLASTED) { P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); @@ -1974,6 +1990,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, sector_t* newsec; tm.floatok = false; + tm.portalstep = false; oldz = thing->Z(); if (onfloor) { @@ -2246,6 +2263,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, thing->LinkToWorld(); P_FindFloorCeiling(thing); portalcrossed = true; + tm.portalstep = false; } else if (!portalcrossed) { @@ -2271,6 +2289,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, P_FindFloorCeiling(thing); thing->ClearInterpolation(); portalcrossed = true; + tm.portalstep = false; } // if this is the current camera we need to store the point where the portal was crossed and the exit // so that the renderer can properly calculate an interpolated position along the movement path. @@ -2410,6 +2429,20 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, } } + // If the actor stepped through a ceiling portal we need to reacquire the actual position info after the transition + if (tm.portalstep) + { + DVector3 oldpos = thing->Pos(); + thing->UnlinkFromWorld(); + thing->SetXYZ(thing->PosRelative(thing->Sector->GetOppositePortalGroup(sector_t::ceiling))); + thing->Prev = thing->Pos() - oldpos; + thing->Sector = P_PointInSector(thing->Pos()); + thing->PrevPortalGroup = thing->Sector->PortalGroup; + thing->LinkToWorld(); + + P_FindFloorCeiling(thing); + } + // [RH] If changing sectors, trigger transitions thing->CheckSectorTransition(oldsec); thing->flags6 &= ~MF6_INTRYMOVE; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 419da0ccb..fe049bdb4 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2117,21 +2117,23 @@ explode: if (mo->Pos().XY() != ptry) { // If the new position does not match the desired position, the player - // must have gone through a teleporter, so stop moving right now if it - // was a regular teleporter. If it was a line-to-line or fogless teleporter, - // the move should continue, but start and move need to change. + // must have gone through a teleporter or portal. + if (mo->Vel.X == 0 && mo->Vel.Y == 0) { + // Stop moving right now if it was a regular teleporter. step = steps; } else { + // It was a portal, line-to-line or fogless teleporter, so the move should continue. + // For that we need to adjust the start point, and the movement vector. DAngle anglediff = deltaangle(oldangle, mo->Angles.Yaw); if (anglediff != 0) { move = move.Rotated(anglediff); - oldangle = mo->Angles.Yaw; // in case more moves are needed this needs to be updated. + oldangle = mo->Angles.Yaw; } start = mo->Pos() - move * step / steps; } @@ -3225,7 +3227,7 @@ DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec) while (!sec->PortalBlocksMovement(sector_t::ceiling)) { - if (testz > sec->GetPortalPlaneZ(sector_t::ceiling)) + if (testz >= sec->GetPortalPlaneZ(sector_t::ceiling)) { pos = PosRelative(sec->GetOppositePortalGroup(sector_t::ceiling)); sec = P_PointInSector(pos); @@ -3237,7 +3239,7 @@ DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec) { while (!sec->PortalBlocksMovement(sector_t::floor)) { - if (testz <= sec->GetPortalPlaneZ(sector_t::floor)) + if (testz < sec->GetPortalPlaneZ(sector_t::floor)) { pos = PosRelative(sec->GetOppositePortalGroup(sector_t::floor)); sec = P_PointInSector(pos); @@ -3256,7 +3258,7 @@ void AActor::CheckPortalTransition(bool islinked) bool moved = false; while (!Sector->PortalBlocksMovement(sector_t::ceiling)) { - if (Z() > Sector->GetPortalPlaneZ(sector_t::ceiling)) + if (Z() >= Sector->GetPortalPlaneZ(sector_t::ceiling)) { DVector3 oldpos = Pos(); if (islinked && !moved) UnlinkFromWorld();