From fab38d092b5b1cc736aa2916523a12cd5823da16 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 27 Apr 2016 02:13:35 +0200 Subject: [PATCH] - fixed: P_LineOpening could miss a 3D floor if an actor was centered right against its side. - restored the original 3D floor code to retrieve the current floor in P_CheckPosition. The portal aware version was a bit too strict and could place the actor on the wrong side when moving at high speeds. --- src/p_3dfloors.cpp | 2 +- src/p_map.cpp | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index 8da672513..5e2117b9b 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -790,7 +790,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li lowestceilingsec = j == 0 ? linedef->frontsector : linedef->backsector; } - if(ff_top > highestfloor && delta1 < delta2 && (!restrict || thing->Z() >= ff_top)) + if(ff_top > highestfloor && delta1 <= delta2 && (!restrict || thing->Z() >= ff_top)) { highestfloor = ff_top; highestfloorpic = *rover->top.texture; diff --git a/src/p_map.cpp b/src/p_map.cpp index 3d04c6889..bd442fa61 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1514,7 +1514,45 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo // Any contacted lines the step closer together will adjust them. if (!thing->IsNoClip2()) { - P_GetFloorCeilingZ(tm, FFCF_SAMESECTOR); + if (!newsec->PortalBlocksMovement(sector_t::ceiling) || !newsec->PortalBlocksMovement(sector_t::floor)) + { + // Use P_GetFloorCeilingZ only if there's portals to consider. Its logic is subtly different than what is needed here for 3D floors. + P_GetFloorCeilingZ(tm, FFCF_SAMESECTOR); + } + else + { + tm.floorz = tm.dropoffz = newsec->floorplane.ZatPoint(pos); + tm.floorpic = newsec->GetTexture(sector_t::floor); + tm.ceilingz = newsec->ceilingplane.ZatPoint(pos); + tm.ceilingpic = newsec->GetTexture(sector_t::ceiling); + tm.floorsector = tm.ceilingsector = newsec; + } + + F3DFloor* rover; + double thingtop = thing->Height > 0 ? thing->Top() : thing->Z() + 1; + + for (unsigned i = 0; ie->XFloor.ffloors.Size(); i++) + { + rover = newsec->e->XFloor.ffloors[i]; + if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; + + double ff_bottom = rover->bottom.plane->ZatPoint(pos); + double ff_top = rover->top.plane->ZatPoint(pos); + + double delta1 = thing->Z() - (ff_bottom + ((ff_top - ff_bottom) / 2)); + double delta2 = thingtop - (ff_bottom + ((ff_top - ff_bottom) / 2)); + + if (ff_top > tm.floorz && fabs(delta1) < fabs(delta2)) + { + tm.floorz = tm.dropoffz = ff_top; + tm.floorpic = *rover->top.texture; + } + if (ff_bottom < tm.ceilingz && abs(delta1) >= abs(delta2)) + { + tm.ceilingz = ff_bottom; + tm.ceilingpic = *rover->bottom.texture; + } + } } else {