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_enemy.cpp b/src/p_enemy.cpp index fcc18ae55..585c292f8 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -538,15 +538,31 @@ bool P_Move (AActor *actor) tm.FromPMove = true; - try_ok = true; - for(int i=1; i < steps; i++) - { - try_ok = P_TryMove(actor, DVector2(origx + deltax * i / steps, origy + deltay * i / steps), dropoff, NULL, tm); - if (!try_ok) break; - } + DVector2 start = { origx, origy }; + DVector2 move = { deltax, deltay }; + DAngle oldangle = actor->Angles.Yaw; - // killough 3/15/98: don't jump over dropoffs: - if (try_ok) try_ok = P_TryMove (actor, DVector2(tryx, tryy), dropoff, NULL, tm); + try_ok = true; + for (int i = 1; i <= steps; i++) + { + DVector2 ptry = start + move * i / steps; + // killough 3/15/98: don't jump over dropoffs: + try_ok = P_TryMove(actor, ptry, dropoff, NULL, tm); + if (!try_ok) break; + + // Handle portal transitions just like P_XYMovement. + if (steps > 1 && actor->Pos().XY() != ptry) + { + DAngle anglediff = deltaangle(oldangle, actor->Angles.Yaw); + + if (anglediff != 0) + { + move = move.Rotated(anglediff); + oldangle = actor->Angles.Yaw; + } + start = actor->Pos() - move * i / steps; + } + } // [GrafZahl] Interpolating monster movement as it is done here just looks bad // so make it switchable 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(); diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index f20e848df..52f484afc 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -1608,6 +1608,13 @@ TArray I_GetGogPaths() result.Push(path + "/Plutonia"); } + // Look for Strife: Veteran Edition + gamepath = gogregistrypath + "\\1432899949"; + if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.GetChars(), "Path", path)) + { + result.Push(path); // directly in install folder + } + return result; }