- fixed: It was not possible to step through a ceiling portal into the upper sector.

This commit is contained in:
Christoph Oelckers 2016-05-20 13:10:42 +02:00
parent 68c5191798
commit 428bd52295
3 changed files with 44 additions and 8 deletions

View file

@ -33,8 +33,9 @@ struct FCheckPosition
AActor *stepthing; AActor *stepthing;
// [RH] These are used by PIT_CheckThing and P_XYMovement to apply // [RH] These are used by PIT_CheckThing and P_XYMovement to apply
// ripping damage once per tic instead of once per move. // ripping damage once per tic instead of once per move.
bool DoRipping;
TMap<AActor*, bool> LastRipped; TMap<AActor*, bool> LastRipped;
bool DoRipping;
bool portalstep;
int PushTime; int PushTime;

View file

@ -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. // Since a one-sided line does not have an opening there's nothing left to do about it.
return true; 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) if (tm.thing->flags2 & MF2_BLASTED)
{ {
P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); 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; sector_t* newsec;
tm.floatok = false; tm.floatok = false;
tm.portalstep = false;
oldz = thing->Z(); oldz = thing->Z();
if (onfloor) if (onfloor)
{ {
@ -2246,6 +2263,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos,
thing->LinkToWorld(); thing->LinkToWorld();
P_FindFloorCeiling(thing); P_FindFloorCeiling(thing);
portalcrossed = true; portalcrossed = true;
tm.portalstep = false;
} }
else if (!portalcrossed) else if (!portalcrossed)
{ {
@ -2271,6 +2289,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos,
P_FindFloorCeiling(thing); P_FindFloorCeiling(thing);
thing->ClearInterpolation(); thing->ClearInterpolation();
portalcrossed = true; 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 // 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. // 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 // [RH] If changing sectors, trigger transitions
thing->CheckSectorTransition(oldsec); thing->CheckSectorTransition(oldsec);
thing->flags6 &= ~MF6_INTRYMOVE; thing->flags6 &= ~MF6_INTRYMOVE;

View file

@ -2117,21 +2117,23 @@ explode:
if (mo->Pos().XY() != ptry) if (mo->Pos().XY() != ptry)
{ {
// If the new position does not match the desired position, the player // 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 // must have gone through a teleporter or portal.
// 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.
if (mo->Vel.X == 0 && mo->Vel.Y == 0) if (mo->Vel.X == 0 && mo->Vel.Y == 0)
{ {
// Stop moving right now if it was a regular teleporter.
step = steps; step = steps;
} }
else 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); DAngle anglediff = deltaangle(oldangle, mo->Angles.Yaw);
if (anglediff != 0) if (anglediff != 0)
{ {
move = move.Rotated(anglediff); 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; start = mo->Pos() - move * step / steps;
} }
@ -3225,7 +3227,7 @@ DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec)
while (!sec->PortalBlocksMovement(sector_t::ceiling)) 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)); pos = PosRelative(sec->GetOppositePortalGroup(sector_t::ceiling));
sec = P_PointInSector(pos); sec = P_PointInSector(pos);
@ -3237,7 +3239,7 @@ DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec)
{ {
while (!sec->PortalBlocksMovement(sector_t::floor)) 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)); pos = PosRelative(sec->GetOppositePortalGroup(sector_t::floor));
sec = P_PointInSector(pos); sec = P_PointInSector(pos);
@ -3256,7 +3258,7 @@ void AActor::CheckPortalTransition(bool islinked)
bool moved = false; bool moved = false;
while (!Sector->PortalBlocksMovement(sector_t::ceiling)) while (!Sector->PortalBlocksMovement(sector_t::ceiling))
{ {
if (Z() > Sector->GetPortalPlaneZ(sector_t::ceiling)) if (Z() >= Sector->GetPortalPlaneZ(sector_t::ceiling))
{ {
DVector3 oldpos = Pos(); DVector3 oldpos = Pos();
if (islinked && !moved) UnlinkFromWorld(); if (islinked && !moved) UnlinkFromWorld();