Improved compatibility of blocking lines handling

Only the first blocking line changes contact state during line iteration
This reverts 3b818171d5

https://forum.zdoom.org/viewtopic.php?t=57870
This commit is contained in:
alexey.lysiuk 2017-12-31 11:34:12 +02:00
parent a5ded11994
commit 40fd816d54

View file

@ -856,7 +856,7 @@ static int LineIsBelow(line_t *line, AActor *actor)
//========================================================================== //==========================================================================
static // killough 3/26/98: make static static // killough 3/26/98: make static
bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::CheckResult &cres, const FBoundingBox &box, FCheckPosition &tm) bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::CheckResult &cres, const FBoundingBox &box, FCheckPosition &tm, const bool wasfit)
{ {
line_t *ld = cres.line; line_t *ld = cres.line;
bool rail = false; bool rail = false;
@ -902,12 +902,15 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
double portz = cres.line->frontsector->GetPortalPlaneZ(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) if (tm.thing->Z() < portz && tm.thing->Z() + tm.thing->MaxStepHeight >= portz && tm.floorz < portz)
{ {
tm.floorz = portz; if (wasfit)
tm.floorsector = cres.line->frontsector; {
tm.floorpic = cres.line->sidedef[0]->GetTexture(side_t::mid); tm.floorz = portz;
tm.floorterrain = 0; tm.floorsector = cres.line->frontsector;
tm.portalstep = true; tm.floorpic = cres.line->sidedef[0]->GetTexture(side_t::mid);
tm.portalgroup = cres.line->frontsector->GetOppositePortalGroup(sector_t::ceiling); tm.floorterrain = 0;
tm.portalstep = true;
tm.portalgroup = cres.line->frontsector->GetOppositePortalGroup(sector_t::ceiling);
}
return true; return true;
} }
} }
@ -916,7 +919,10 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
{ {
P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee);
} }
tm.thing->BlockingLine = ld; if (wasfit)
{
tm.thing->BlockingLine = ld;
}
CheckForPushSpecial(ld, 0, tm.thing); CheckForPushSpecial(ld, 0, tm.thing);
return false; return false;
} }
@ -948,12 +954,15 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
if (state == -1) return true; if (state == -1) return true;
if (state == 1) if (state == 1)
{ {
// the line should not block but we should set the ceilingz to the portal boundary so that we can't float up into that line. if (wasfit)
double portalz = cres.line->frontsector->GetPortalPlaneZ(sector_t::floor);
if (portalz < tm.ceilingz)
{ {
tm.ceilingz = portalz; // the line should not block but we should set the ceilingz to the portal boundary so that we can't float up into that line.
tm.ceilingsector = cres.line->frontsector; double portalz = cres.line->frontsector->GetPortalPlaneZ(sector_t::floor);
if (portalz < tm.ceilingz)
{
tm.ceilingz = portalz;
tm.ceilingsector = cres.line->frontsector;
}
} }
return true; return true;
} }
@ -965,12 +974,15 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
if (state == -1) return true; if (state == -1) return true;
if (state == 1) if (state == 1)
{ {
double portalz = cres.line->frontsector->GetPortalPlaneZ(sector_t::ceiling); if (wasfit)
if (portalz > tm.floorz)
{ {
tm.floorz = portalz; double portalz = cres.line->frontsector->GetPortalPlaneZ(sector_t::ceiling);
tm.floorsector = cres.line->frontsector; if (portalz > tm.floorz)
tm.floorterrain = 0; {
tm.floorz = portalz;
tm.floorsector = cres.line->frontsector;
tm.floorterrain = 0;
}
} }
return true; return true;
} }
@ -981,7 +993,10 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
{ {
P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee); P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee);
} }
tm.thing->BlockingLine = ld; if (wasfit)
{
tm.thing->BlockingLine = ld;
}
// Calculate line side based on the actor's original position, not the new one. // Calculate line side based on the actor's original position, not the new one.
CheckForPushSpecial(ld, P_PointOnLineSide(cres.Position, ld), tm.thing); CheckForPushSpecial(ld, P_PointOnLineSide(cres.Position, ld), tm.thing);
return false; return false;
@ -1000,9 +1015,12 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
double portz = tm.thing->Sector->GetPortalPlaneZ(sector_t::ceiling); double portz = tm.thing->Sector->GetPortalPlaneZ(sector_t::ceiling);
if (tm.thing->Z() < portz && tm.thing->Z() + tm.thing->MaxStepHeight >= portz && tm.floorz < portz) if (tm.thing->Z() < portz && tm.thing->Z() + tm.thing->MaxStepHeight >= portz && tm.floorz < portz)
{ {
// Actor is stepping through a portal. if (wasfit)
tm.portalstep = true; {
tm.portalgroup = tm.thing->Sector->GetOppositePortalGroup(sector_t::ceiling); // Actor is stepping through a portal.
tm.portalstep = true;
tm.portalgroup = tm.thing->Sector->GetOppositePortalGroup(sector_t::ceiling);
}
return true; return true;
} }
} }
@ -1042,41 +1060,44 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
open.bottom += 32; open.bottom += 32;
} }
// adjust floor / ceiling heights if (wasfit)
if (!(cres.portalflags & FFCF_NOCEILING))
{ {
if (open.top < tm.ceilingz) // adjust floor / ceiling heights
if (!(cres.portalflags & FFCF_NOCEILING))
{ {
tm.ceilingz = open.top; if (open.top < tm.ceilingz)
tm.ceilingsector = open.topsec; {
tm.ceilingpic = open.ceilingpic; tm.ceilingz = open.top;
tm.ceilingline = ld; tm.ceilingsector = open.topsec;
tm.thing->BlockingLine = ld; tm.ceilingpic = open.ceilingpic;
} tm.ceilingline = ld;
} tm.thing->BlockingLine = ld;
}
// If we are stepping through a portal the line's opening must be checked, regardless of the NOFLOOR flag
if (!(cres.portalflags & FFCF_NOFLOOR) || (tm.portalstep && open.bottomsec->PortalGroup == tm.portalgroup))
{
if (open.bottom > tm.floorz)
{
tm.floorz = open.bottom;
tm.floorsector = open.bottomsec;
tm.floorpic = open.floorpic;
tm.floorterrain = open.floorterrain;
tm.touchmidtex = open.touchmidtex;
tm.abovemidtex = open.abovemidtex;
tm.thing->BlockingLine = ld;
}
else if (open.bottom == tm.floorz)
{
tm.touchmidtex |= open.touchmidtex;
tm.abovemidtex |= open.abovemidtex;
} }
if (open.lowfloor < tm.dropoffz) // If we are stepping through a portal the line's opening must be checked, regardless of the NOFLOOR flag
if (!(cres.portalflags & FFCF_NOFLOOR) || (tm.portalstep && open.bottomsec->PortalGroup == tm.portalgroup))
{ {
tm.dropoffz = open.lowfloor; if (open.bottom > tm.floorz)
{
tm.floorz = open.bottom;
tm.floorsector = open.bottomsec;
tm.floorpic = open.floorpic;
tm.floorterrain = open.floorterrain;
tm.touchmidtex = open.touchmidtex;
tm.abovemidtex = open.abovemidtex;
tm.thing->BlockingLine = ld;
}
else if (open.bottom == tm.floorz)
{
tm.touchmidtex |= open.touchmidtex;
tm.abovemidtex |= open.abovemidtex;
}
if (open.lowfloor < tm.dropoffz)
{
tm.dropoffz = open.lowfloor;
}
} }
} }
@ -1881,7 +1902,7 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo
while (it.Next(&lcres)) while (it.Next(&lcres))
{ {
bool thisresult = PIT_CheckLine(it, lcres, it.Box(), tm); bool thisresult = PIT_CheckLine(it, lcres, it.Box(), tm, good);
good &= thisresult; good &= thisresult;
if (thisresult) if (thisresult)
{ {
@ -5920,10 +5941,7 @@ bool P_AdjustFloorCeil(AActor *thing, FChangePosition *cpos)
} }
bool isgood = P_CheckPosition(thing, thing->Pos(), tm); bool isgood = P_CheckPosition(thing, thing->Pos(), tm);
if (!(thing->flags4 & MF4_ACTLIKEBRIDGE))
// This is essentially utterly broken because it even uses the return from a failed P_CheckPosition but the entire logic will break down if that isn't done.
// However, if tm.floorz is greater than tm.ceilingz we have a real problem that needs to be dealt with exolicitly.
if (!(thing->flags4 & MF4_ACTLIKEBRIDGE) && tm.floorz <= tm.ceilingz)
{ {
thing->floorz = tm.floorz; thing->floorz = tm.floorz;
thing->ceilingz = tm.ceilingz; thing->ceilingz = tm.ceilingz;