- untested partial refactoring of P_CheckPosition.

(This is just a safety commit before doing some more extensive behind-the-scenes refactoring.)

Notable changes here:

 * use the same logic for determining whether a 3D floor is 'below' or 'above' the actor as all the other functions.
 * removed the broken code which tried to detect whether an actor was touching a steep slope. Better use P_LineOpening to find the correct planes and store the results.
 * improved detection whether the slopes on both sides of a plane are identical, using the same data as for steep slope detection.
This commit is contained in:
Christoph Oelckers 2016-02-21 16:56:21 +01:00
parent abcc6049b9
commit 98c7fabb89
6 changed files with 125 additions and 128 deletions

View file

@ -776,6 +776,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
int highestfloorterrain = -1; int highestfloorterrain = -1;
FTextureID lowestceilingpic; FTextureID lowestceilingpic;
sector_t *lowestceilingsec = NULL, *highestfloorsec = NULL; sector_t *lowestceilingsec = NULL, *highestfloorsec = NULL;
secplane_t *highestfloorplanes[2] = { NULL, NULL };
highestfloorpic.SetInvalid(); highestfloorpic.SetInvalid();
lowestceilingpic.SetInvalid(); lowestceilingpic.SetInvalid();
@ -808,6 +809,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
highestfloorpic = *rover->top.texture; highestfloorpic = *rover->top.texture;
highestfloorterrain = rover->model->GetTerrain(rover->top.isceiling); highestfloorterrain = rover->model->GetTerrain(rover->top.isceiling);
highestfloorsec = j == 0 ? linedef->frontsector : linedef->backsector; highestfloorsec = j == 0 ? linedef->frontsector : linedef->backsector;
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;
} }
@ -826,6 +828,16 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
open.top = lowestceiling; open.top = lowestceiling;
open.ceilingpic = lowestceilingpic; open.ceilingpic = lowestceilingpic;
open.topsec = lowestceilingsec; open.topsec = lowestceilingsec;
if (highestfloorplanes[0])
{
open.frontfloorplane = *highestfloorplanes[0];
if (open.frontfloorplane.c < 0) open.frontfloorplane.FlipVert();
}
if (highestfloorplanes[1])
{
open.backfloorplane = *highestfloorplanes[1];
if (open.backfloorplane.c < 0) open.backfloorplane.FlipVert();
}
} }
open.lowfloor = MIN(lowestfloor[0], lowestfloor[1]); open.lowfloor = MIN(lowestfloor[0], lowestfloor[1]);

View file

@ -294,7 +294,9 @@ bool P_LineOpening_3dMidtex(AActor *thing, const line_t *linedef, FLineOpening &
open.abovemidtex = true; open.abovemidtex = true;
open.floorpic = linedef->sidedef[0]->GetTexture(side_t::mid); open.floorpic = linedef->sidedef[0]->GetTexture(side_t::mid);
open.floorterrain = TerrainTypes[open.floorpic]; open.floorterrain = TerrainTypes[open.floorpic];
open.frontfloorplane.SetAtHeight(tt, sector_t::floor);
open.backfloorplane.SetAtHeight(tt, sector_t::floor);
} }
// returns true if it touches the midtexture // returns true if it touches the midtexture
return (abs(thing->Z() - tt) <= thing->MaxStepHeight); return (abs(thing->Z() - tt) <= thing->MaxStepHeight);

View file

@ -276,7 +276,7 @@ static bool PIT_FindFloorCeiling(FMultiBlockLinesIterator &mit, FMultiBlockLines
void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags) void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags)
{ {
sector_t *sec = (!(flags & FFCF_SAMESECTOR) || tmf.thing->Sector == NULL)? P_PointInSector(tmf.x, tmf.y) : tmf.thing->Sector; sector_t *sec = (!(flags & FFCF_SAMESECTOR) || tmf.thing->Sector == NULL)? P_PointInSector(tmf.x, tmf.y) : tmf.sector;
F3DFloor *ffc, *fff; F3DFloor *ffc, *fff;
tmf.ceilingz = sec->NextHighestCeilingAt(tmf.thing, tmf.z + tmf.thing->height, flags, &tmf.ceilingsector, &ffc); tmf.ceilingz = sec->NextHighestCeilingAt(tmf.thing, tmf.z + tmf.thing->height, flags, &tmf.ceilingsector, &ffc);
@ -316,6 +316,10 @@ void P_FindFloorCeiling(AActor *actor, int flags)
{ {
flags |= FFCF_3DRESTRICT; flags |= FFCF_3DRESTRICT;
} }
if (flags & FFCF_SAMESECTOR)
{
tmf.sector = actor->Sector;
}
P_GetFloorCeilingZ(tmf, flags); P_GetFloorCeilingZ(tmf, flags);
assert(tmf.thing->Sector != NULL); assert(tmf.thing->Sector != NULL);
@ -759,8 +763,9 @@ int P_GetMoveFactor(const AActor *mo, int *frictionp)
//========================================================================== //==========================================================================
static // killough 3/26/98: make static static // killough 3/26/98: make static
bool PIT_CheckLine(line_t *ld, const FBoundingBox &box, FCheckPosition &tm) bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::CheckResult &cres, const FBoundingBox &box, FCheckPosition &tm)
{ {
line_t *ld = cres.line;
bool rail = false; bool rail = false;
if (box.Right() <= ld->bbox[BOXLEFT] if (box.Right() <= ld->bbox[BOXLEFT]
@ -802,7 +807,6 @@ bool PIT_CheckLine(line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST) bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST)
|| ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY))); || ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY)));
fixedvec3 pos = tm.thing->PosRelative(ld);
if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE))) if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE)))
{ {
if (ld->flags & ML_RAILING) if (ld->flags & ML_RAILING)
@ -821,55 +825,33 @@ bool PIT_CheckLine(line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
} }
tm.thing->BlockingLine = ld; 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(pos.x, pos.y, ld), tm.thing, false); CheckForPushSpecial(ld, P_PointOnLineSide(cres.position.x, cres.position.y, ld), tm.thing, false);
return false; return false;
} }
} }
// [RH] Steep sectors count as dropoffs (unless already in one) fixedvec2 ref = FindRefPoint(ld, cres.position);
FLineOpening open;
P_LineOpening(open, tm.thing, ld, ref.x, ref.y, cres.position.x, cres.position.y, cres.portalflags);
// [RH] Steep sectors count as dropoffs, if the actor touches the boundary between a steep slope and something else
if (!(tm.thing->flags & MF_DROPOFF) && if (!(tm.thing->flags & MF_DROPOFF) &&
!(tm.thing->flags & (MF_NOGRAVITY | MF_NOCLIP))) !(tm.thing->flags & (MF_NOGRAVITY | MF_NOCLIP)))
{ {
secplane_t frontplane, backplane;
// Check 3D floors as well // Check 3D floors as well
frontplane = P_FindFloorPlane(ld->frontsector, pos.x, pos.y, tm.thing->floorz); if ((open.frontfloorplane.c < STEEPSLOPE) != (open.backfloorplane.c < STEEPSLOPE))
backplane = P_FindFloorPlane(ld->backsector, pos.x, pos.y, tm.thing->floorz);
if (frontplane.c < STEEPSLOPE || backplane.c < STEEPSLOPE)
{ {
const msecnode_t *node = tm.thing->touching_sectorlist; // on the boundary of a steep slope
bool allow = false; return false;
int count = 0;
while (node != NULL)
{
count++;
if (node->m_sector->floorplane.c < STEEPSLOPE)
{
allow = true;
break;
}
node = node->m_tnext;
}
if (!allow)
{
return false;
}
} }
} }
fixedvec2 rpos = { tm.x, tm.y }; // If the floor planes on both sides we should recalculate open.bottom at the actual position we are checking
fixedvec2 ref = FindRefPoint(ld, rpos); // This is to avoid bumpy movement when crossing a linedef with the same slope on both sides.
FLineOpening open; if (open.frontfloorplane == open.backfloorplane)
P_LineOpening(open, tm.thing, ld, ref.x, ref.y, tm.x, tm.y, 0);
// the floorplane on both sides is identical with the current one
// so don't mess around with the z-position.
if (ld->frontsector->floorplane == ld->backsector->floorplane &&
ld->frontsector->floorplane == tm.thing->Sector->floorplane &&
!ld->frontsector->e->XFloor.ffloors.Size() && !ld->backsector->e->XFloor.ffloors.Size() &&
!open.abovemidtex)
{ {
open.bottom = INT_MIN; open.bottom = open.frontfloorplane.ZatPoint(cres.position.x, cres.position.y);
} }
if (rail && if (rail &&
@ -1017,8 +999,9 @@ static bool CanAttackHurt(AActor *victim, AActor *shooter)
// //
//========================================================================== //==========================================================================
bool PIT_CheckThing(AActor *thing, FCheckPosition &tm) bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::CheckResult &cres, const FBoundingBox &box, FCheckPosition &tm)
{ {
AActor *thing = cres.thing;
fixed_t topz; fixed_t topz;
bool solid; bool solid;
int damage; int damage;
@ -1440,56 +1423,29 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo
tm.x = x; tm.x = x;
tm.y = y; tm.y = y;
tm.z = thing->Z();
newsec = P_PointInSector(x, y); newsec = tm.sector = P_PointInSector(x, y);
tm.ceilingline = thing->BlockingLine = NULL; tm.ceilingline = thing->BlockingLine = NULL;
// The base floor / ceiling is from the subsector that contains the point. // Retrieve the base floor / ceiling from the target location.
// Any contacted lines the step closer together will adjust them. // Any contacted lines the step closer together will adjust them.
tm.floorz = tm.dropoffz = newsec->LowestFloorAt(x, y, &tm.floorsector); if (!thing->IsNoClip2())
tm.ceilingz = newsec->HighestCeilingAt(x, y, &tm.ceilingsector);
tm.floorpic = tm.floorsector->GetTexture(sector_t::floor);
tm.floorterrain = tm.floorsector->GetTerrain(sector_t::floor);
tm.ceilingpic = tm.ceilingsector->GetTexture(sector_t::ceiling);
tm.touchmidtex = false;
tm.abovemidtex = false;
//Added by MC: Fill the tmsector.
tm.sector = newsec;
//Check 3D floors
if (!thing->IsNoClip2() && newsec->e->XFloor.ffloors.Size())
{ {
F3DFloor* rover; P_GetFloorCeilingZ(tm, FFCF_SAMESECTOR);
fixed_t delta1; }
fixed_t delta2; else
int thingtop = thing->Z() + (thing->height == 0 ? 1 : thing->height); {
// With noclip2, we must ignore 3D floors and go right to the uppermost ceiling and lowermost floor.
for (unsigned i = 0; i<newsec->e->XFloor.ffloors.Size(); i++) tm.floorz = tm.dropoffz = newsec->LowestFloorAt(x, y, &tm.floorsector);
{ tm.ceilingz = newsec->HighestCeilingAt(x, y, &tm.ceilingsector);
rover = newsec->e->XFloor.ffloors[i]; tm.floorpic = tm.floorsector->GetTexture(sector_t::floor);
if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; tm.floorterrain = tm.floorsector->GetTerrain(sector_t::floor);
tm.ceilingpic = tm.ceilingsector->GetTexture(sector_t::ceiling);
fixed_t ff_bottom = rover->bottom.plane->ZatPoint(x, y);
fixed_t ff_top = rover->top.plane->ZatPoint(x, y);
delta1 = thing->Z() - (ff_bottom + ((ff_top - ff_bottom) / 2));
delta2 = thingtop - (ff_bottom + ((ff_top - ff_bottom) / 2));
if (ff_top > tm.floorz && abs(delta1) < abs(delta2))
{
tm.floorz = tm.dropoffz = ff_top;
tm.floorpic = *rover->top.texture;
tm.floorterrain = rover->model->GetTerrain(rover->top.isceiling);
}
if (ff_bottom < tm.ceilingz && abs(delta1) >= abs(delta2))
{
tm.ceilingz = ff_bottom;
tm.ceilingpic = *rover->bottom.texture;
}
}
} }
tm.touchmidtex = false;
tm.abovemidtex = false;
validcount++; validcount++;
spechit.Clear(); spechit.Clear();
@ -1507,51 +1463,52 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo
tm.stepthing = NULL; tm.stepthing = NULL;
FBoundingBox box(x, y, thing->radius); FBoundingBox box(x, y, thing->radius);
{ FPortalGroupArray pcheck;
FBlockThingsIterator it2(box); FMultiBlockThingsIterator it2(pcheck, x, y, thing->Z(), thing->height, thing->radius);
AActor *th; FMultiBlockThingsIterator::CheckResult tcres;
while ((th = it2.Next()))
{
if (!PIT_CheckThing(th, tm))
{ // [RH] If a thing can be stepped up on, we need to continue checking
// other things in the blocks and see if we hit something that is
// definitely blocking. Otherwise, we need to check the lines, or we
// could end up stuck inside a wall.
AActor *BlockingMobj = thing->BlockingMobj;
if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ)) while ((it2.Next(&tcres)))
{ // Thing slammed into something; don't let it move now. {
thing->height = realheight; if (!PIT_CheckThing(it2, tcres, it2.Box(), tm))
return false; { // [RH] If a thing can be stepped up on, we need to continue checking
} // other things in the blocks and see if we hit something that is
else if (!BlockingMobj->player && !(thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY)) && // definitely blocking. Otherwise, we need to check the lines, or we
BlockingMobj->Top() - thing->Z() <= thing->MaxStepHeight) // could end up stuck inside a wall.
{ AActor *BlockingMobj = thing->BlockingMobj;
if (thingblocker == NULL ||
BlockingMobj->Z() > thingblocker->Z()) // If this blocks through a line portal with a vertical displacement, it will always completely block. There is no way to step up onto such an actor.
{ if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ) || tcres.zdiff != 0)
thingblocker = BlockingMobj; { // Thing slammed into something; don't let it move now.
} thing->height = realheight;
thing->BlockingMobj = NULL; return false;
} }
else if (thing->player && else if (!BlockingMobj->player && !(thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY)) &&
thing->Top() - BlockingMobj->Z() <= thing->MaxStepHeight) BlockingMobj->Top() - thing->Z() <= thing->MaxStepHeight)
{ {
if (thingblocker) if (thingblocker == NULL ||
{ // There is something to step up on. Return this thing as BlockingMobj->Z() > thingblocker->Z())
// the blocker so that we don't step up. {
thing->height = realheight; thingblocker = BlockingMobj;
return false; }
} thing->BlockingMobj = NULL;
// Nothing is blocking us, but this actor potentially could }
// if there is something else to step on. else if (thing->player &&
thing->BlockingMobj = NULL; thing->Top() - BlockingMobj->Z() <= thing->MaxStepHeight)
} {
else if (thingblocker)
{ // Definitely blocking { // There is something to step up on. Return this thing as
// the blocker so that we don't step up.
thing->height = realheight; thing->height = realheight;
return false; return false;
} }
// Nothing is blocking us, but this actor potentially could
// if there is something else to step on.
thing->BlockingMobj = NULL;
}
else
{ // Definitely blocking
thing->height = realheight;
return false;
} }
} }
} }
@ -1574,7 +1531,8 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo
if (actorsonly || (thing->flags & MF_NOCLIP)) if (actorsonly || (thing->flags & MF_NOCLIP))
return (thing->BlockingMobj = thingblocker) == NULL; return (thing->BlockingMobj = thingblocker) == NULL;
FBlockLinesIterator it(box); FMultiBlockLinesIterator it(pcheck, thing);
FMultiBlockLinesIterator::CheckResult lcres;
line_t *ld; line_t *ld;
fixed_t thingdropoffz = tm.floorz; fixed_t thingdropoffz = tm.floorz;
@ -1583,9 +1541,9 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo
bool good = true; bool good = true;
while ((ld = it.Next())) while (it.Next(&lcres))
{ {
good &= PIT_CheckLine(ld, box, tm); good &= PIT_CheckLine(it, lcres, it.Box(), tm);
} }
if (!good) if (!good)
{ {

View file

@ -229,6 +229,8 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
open.floorterrain = back->GetTerrain(sector_t::floor); open.floorterrain = back->GetTerrain(sector_t::floor);
open.lowfloor = ff; open.lowfloor = ff;
} }
open.frontfloorplane = front->floorplane;
open.backfloorplane = back->floorplane;
} }
else else
{ // Dummy stuff to have some sort of opening for the 3D checks to modify { // Dummy stuff to have some sort of opening for the 3D checks to modify
@ -240,6 +242,8 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
open.floorterrain = -1; open.floorterrain = -1;
open.bottom = FIXED_MIN; open.bottom = FIXED_MIN;
open.lowfloor = FIXED_MAX; open.lowfloor = FIXED_MAX;
open.frontfloorplane.SetAtHeight(FIXED_MIN, sector_t::floor);
open.backfloorplane.SetAtHeight(FIXED_MIN, sector_t::floor);
} }
// Check 3D floors // Check 3D floors
@ -798,6 +802,7 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
item->position.x = offset.x; item->position.x = offset.x;
item->position.y = offset.y; item->position.y = offset.y;
item->position.z = checkpoint.z; item->position.z = checkpoint.z;
item->zdiff = 0;
item->portalflags = portalflags; item->portalflags = portalflags;
return true; return true;
} }
@ -1085,6 +1090,7 @@ bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *ite
{ {
item->thing = thing; item->thing = thing;
item->position = checkpoint + Displacements(basegroup, thing->Sector->PortalGroup); item->position = checkpoint + Displacements(basegroup, thing->Sector->PortalGroup);
item->zdiff = 0;
item->portalflags = portalflags; item->portalflags = portalflags;
return true; return true;
} }

View file

@ -99,6 +99,8 @@ struct FLineOpening
sector_t *topsec; sector_t *topsec;
FTextureID ceilingpic; FTextureID ceilingpic;
FTextureID floorpic; FTextureID floorpic;
secplane_t frontfloorplane;
secplane_t backfloorplane;
int floorterrain; int floorterrain;
bool touchmidtex; bool touchmidtex;
bool abovemidtex; bool abovemidtex;
@ -221,6 +223,7 @@ public:
{ {
line_t *line; line_t *line;
fixedvec3 position; fixedvec3 position;
fixed_t zdiff;
int portalflags; int portalflags;
}; };
@ -306,6 +309,7 @@ public:
{ {
AActor *thing; AActor *thing;
fixedvec3 position; fixedvec3 position;
fixed_t zdiff;
int portalflags; int portalflags;
}; };

View file

@ -345,6 +345,21 @@ struct secplane_t
return -TMulScale16 (a, v->x, b, v->y, z, c); return -TMulScale16 (a, v->x, b, v->y, z, c);
} }
void SetAtHeight(fixed_t height, int ceiling)
{
a = b = 0;
if (ceiling)
{
c = ic = -FRACUNIT;
d = height;
}
else
{
c = ic = FRACUNIT;
d = -height;
}
}
bool CopyPlaneIfValid (secplane_t *dest, const secplane_t *opp) const; bool CopyPlaneIfValid (secplane_t *dest, const secplane_t *opp) const;
}; };