diff --git a/src/g_shared/p_3dfloors.cpp b/src/g_shared/p_3dfloors.cpp index 1d3e2d4c5..9ef599a69 100644 --- a/src/g_shared/p_3dfloors.cpp +++ b/src/g_shared/p_3dfloors.cpp @@ -692,6 +692,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li double lowestfloor[2] = { linedef->frontsector->floorplane.ZatPoint(x, y), linedef->backsector->floorplane.ZatPoint(x, y) }; + bool lowestfloorset[2] = { false, false }; FTextureID highestfloorpic; int highestfloorterrain = -1; FTextureID lowestceilingpic; @@ -741,7 +742,11 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li highestfloorplanes[j] = rover->top.plane; } } - if(ff_top > lowestfloor[j] && ff_top <= thing->Z() + thing->MaxStepHeight) lowestfloor[j] = ff_top; + if (ff_top > lowestfloor[j] && ff_top <= thing->Z() + thing->MaxStepHeight) + { + lowestfloor[j] = ff_top; + lowestfloorset[j] = true; + } } } @@ -771,8 +776,14 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li open.topsec = lowestceilingsec; open.topffloor = lowestceilingffloor; } - - open.lowfloor = MIN(lowestfloor[0], lowestfloor[1]); + + // Don't overwrite still valid info from portals here. + if ((open.lowfloorthroughportal & 1) && lowestfloorset[0]) open.lowfloorthroughportal &= ~1; + if ((open.lowfloorthroughportal & 2) && lowestfloorset[1]) open.lowfloorthroughportal &= ~2; + + double low1 = (open.lowfloorthroughportal & 1) ? open.lowfloor : lowestfloor[0]; + double low2 = (open.lowfloorthroughportal & 2) ? open.lowfloor : lowestfloor[1]; + open.lowfloor = MIN(low1, low2); } } } diff --git a/src/g_shared/p_checkposition.h b/src/g_shared/p_checkposition.h index c475e282d..36f3e735b 100644 --- a/src/g_shared/p_checkposition.h +++ b/src/g_shared/p_checkposition.h @@ -36,6 +36,7 @@ struct FCheckPosition TMap LastRipped; bool DoRipping; bool portalstep; + bool dropoffisportal; int portalgroup; int PushTime; diff --git a/src/p_map.cpp b/src/p_map.cpp index b33e8b133..06bd5dce1 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -280,6 +280,7 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags) tmf.ceilingz = NextHighestCeilingAt(sec, tmf.pos.X, tmf.pos.Y, tmf.pos.Z, tmf.pos.Z + tmf.thing->Height, flags, &tmf.ceilingsector, &ffc); tmf.floorz = tmf.dropoffz = NextLowestFloorAt(sec, tmf.pos.X, tmf.pos.Y, tmf.pos.Z, flags, tmf.thing->MaxStepHeight, &tmf.floorsector, &fff); + tmf.dropoffisportal = tmf.floorsector != sec; if (fff) { @@ -1018,7 +1019,12 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec if (open.lowfloor < tm.dropoffz) { - tm.dropoffz = open.lowfloor; + // Do not alter the dropoff if the previous portal layer got it solely from its own data. + if (!(cres.portalflags & FFCF_NOCEILING) || tm.dropoffisportal) + { + tm.dropoffz = open.lowfloor; + tm.dropoffisportal = open.lowfloorthroughportal; + } } } } @@ -1680,6 +1686,7 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo else { tm.floorz = tm.dropoffz = newsec->floorplane.ZatPoint(pos); + tm.dropoffisportal = false; tm.floorpic = newsec->GetTexture(sector_t::floor); tm.ceilingz = newsec->ceilingplane.ZatPoint(pos); tm.ceilingpic = newsec->GetTexture(sector_t::ceiling); @@ -1704,6 +1711,7 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo if (ff_top > tm.floorz && fabs(delta1) < fabs(delta2)) { tm.floorz = tm.dropoffz = ff_top; + tm.dropoffisportal = false; tm.floorpic = *rover->top.texture; tm.floorterrain = rover->model->GetTerrain(rover->top.isceiling); } diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 16f6a72ad..a9cd38355 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -177,12 +177,17 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, co bool usefront; + // Store portal state to avoid registering false dropoffs. + open.lowfloorthroughportal = 0; + if (ff == LINEOPEN_MIN) open.lowfloorthroughportal |= 1; + if (bf == LINEOPEN_MIN) open.lowfloorthroughportal |= 2; + // [RH] fudge a bit for actors that are moving across lines // bordering a slope/non-slope that meet on the floor. Note // that imprecisions in the plane equation mean there is a // good chance that even if a slope and non-slope look like // they line up, they won't be perfectly aligned. - if (ff == -FLT_MIN || bf == -FLT_MIN || ref == NULL || fabs (ff-bf) > 1./256) + if (ff == LINEOPEN_MIN || bf == LINEOPEN_MIN || ref == NULL || fabs (ff-bf) > 1./256) { usefront = (ff > bf); } @@ -196,6 +201,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, co usefront = !P_PointOnLineSide (*ref, linedef); } + open.lowfloorthroughportal = false; if (usefront) { open.bottom = ff; diff --git a/src/p_maputl.h b/src/p_maputl.h index 5a65c27d3..e86d363cf 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -111,6 +111,7 @@ struct FLineOpening int floorterrain; bool touchmidtex; bool abovemidtex; + uint8_t lowfloorthroughportal; F3DFloor *topffloor; F3DFloor *bottomffloor; };