mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- 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:
parent
abcc6049b9
commit
98c7fabb89
6 changed files with 125 additions and 128 deletions
|
@ -776,6 +776,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
|
|||
int highestfloorterrain = -1;
|
||||
FTextureID lowestceilingpic;
|
||||
sector_t *lowestceilingsec = NULL, *highestfloorsec = NULL;
|
||||
secplane_t *highestfloorplanes[2] = { NULL, NULL };
|
||||
|
||||
highestfloorpic.SetInvalid();
|
||||
lowestceilingpic.SetInvalid();
|
||||
|
@ -808,6 +809,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
|
|||
highestfloorpic = *rover->top.texture;
|
||||
highestfloorterrain = rover->model->GetTerrain(rover->top.isceiling);
|
||||
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;
|
||||
}
|
||||
|
@ -826,6 +828,16 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
|
|||
open.top = lowestceiling;
|
||||
open.ceilingpic = lowestceilingpic;
|
||||
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]);
|
||||
|
|
|
@ -294,7 +294,9 @@ bool P_LineOpening_3dMidtex(AActor *thing, const line_t *linedef, FLineOpening &
|
|||
open.abovemidtex = true;
|
||||
open.floorpic = linedef->sidedef[0]->GetTexture(side_t::mid);
|
||||
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
|
||||
return (abs(thing->Z() - tt) <= thing->MaxStepHeight);
|
||||
|
|
212
src/p_map.cpp
212
src/p_map.cpp
|
@ -276,7 +276,7 @@ static bool PIT_FindFloorCeiling(FMultiBlockLinesIterator &mit, FMultiBlockLines
|
|||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
if (flags & FFCF_SAMESECTOR)
|
||||
{
|
||||
tmf.sector = actor->Sector;
|
||||
}
|
||||
P_GetFloorCeilingZ(tmf, flags);
|
||||
assert(tmf.thing->Sector != NULL);
|
||||
|
||||
|
@ -759,8 +763,9 @@ int P_GetMoveFactor(const AActor *mo, int *frictionp)
|
|||
//==========================================================================
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
|| ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY)));
|
||||
|
||||
fixedvec3 pos = tm.thing->PosRelative(ld);
|
||||
if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE)))
|
||||
{
|
||||
if (ld->flags & ML_RAILING)
|
||||
|
@ -821,55 +825,33 @@ bool PIT_CheckLine(line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
|
|||
}
|
||||
tm.thing->BlockingLine = ld;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// [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) &&
|
||||
!(tm.thing->flags & (MF_NOGRAVITY | MF_NOCLIP)))
|
||||
{
|
||||
secplane_t frontplane, backplane;
|
||||
// Check 3D floors as well
|
||||
frontplane = P_FindFloorPlane(ld->frontsector, pos.x, pos.y, tm.thing->floorz);
|
||||
backplane = P_FindFloorPlane(ld->backsector, pos.x, pos.y, tm.thing->floorz);
|
||||
if (frontplane.c < STEEPSLOPE || backplane.c < STEEPSLOPE)
|
||||
if ((open.frontfloorplane.c < STEEPSLOPE) != (open.backfloorplane.c < STEEPSLOPE))
|
||||
{
|
||||
const msecnode_t *node = tm.thing->touching_sectorlist;
|
||||
bool allow = 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;
|
||||
}
|
||||
// on the boundary of a steep slope
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fixedvec2 rpos = { tm.x, tm.y };
|
||||
fixedvec2 ref = FindRefPoint(ld, rpos);
|
||||
FLineOpening open;
|
||||
|
||||
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)
|
||||
// If the floor planes on both sides we should recalculate open.bottom at the actual position we are checking
|
||||
// This is to avoid bumpy movement when crossing a linedef with the same slope on both sides.
|
||||
if (open.frontfloorplane == open.backfloorplane)
|
||||
{
|
||||
open.bottom = INT_MIN;
|
||||
open.bottom = open.frontfloorplane.ZatPoint(cres.position.x, cres.position.y);
|
||||
}
|
||||
|
||||
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;
|
||||
bool solid;
|
||||
int damage;
|
||||
|
@ -1440,56 +1423,29 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo
|
|||
|
||||
tm.x = x;
|
||||
tm.y = y;
|
||||
tm.z = thing->Z();
|
||||
|
||||
newsec = P_PointInSector(x, y);
|
||||
newsec = tm.sector = P_PointInSector(x, y);
|
||||
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.
|
||||
tm.floorz = tm.dropoffz = newsec->LowestFloorAt(x, y, &tm.floorsector);
|
||||
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())
|
||||
if (!thing->IsNoClip2())
|
||||
{
|
||||
F3DFloor* rover;
|
||||
fixed_t delta1;
|
||||
fixed_t delta2;
|
||||
int thingtop = thing->Z() + (thing->height == 0 ? 1 : thing->height);
|
||||
|
||||
for (unsigned i = 0; i<newsec->e->XFloor.ffloors.Size(); i++)
|
||||
{
|
||||
rover = newsec->e->XFloor.ffloors[i];
|
||||
if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
P_GetFloorCeilingZ(tm, FFCF_SAMESECTOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
// With noclip2, we must ignore 3D floors and go right to the uppermost ceiling and lowermost floor.
|
||||
tm.floorz = tm.dropoffz = newsec->LowestFloorAt(x, y, &tm.floorsector);
|
||||
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;
|
||||
validcount++;
|
||||
spechit.Clear();
|
||||
|
||||
|
@ -1507,51 +1463,52 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo
|
|||
tm.stepthing = NULL;
|
||||
FBoundingBox box(x, y, thing->radius);
|
||||
|
||||
{
|
||||
FBlockThingsIterator it2(box);
|
||||
AActor *th;
|
||||
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;
|
||||
FPortalGroupArray pcheck;
|
||||
FMultiBlockThingsIterator it2(pcheck, x, y, thing->Z(), thing->height, thing->radius);
|
||||
FMultiBlockThingsIterator::CheckResult tcres;
|
||||
|
||||
if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ))
|
||||
{ // Thing slammed into something; don't let it move now.
|
||||
thing->height = realheight;
|
||||
return false;
|
||||
}
|
||||
else if (!BlockingMobj->player && !(thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY)) &&
|
||||
BlockingMobj->Top() - thing->Z() <= thing->MaxStepHeight)
|
||||
{
|
||||
if (thingblocker == NULL ||
|
||||
BlockingMobj->Z() > thingblocker->Z())
|
||||
{
|
||||
thingblocker = BlockingMobj;
|
||||
}
|
||||
thing->BlockingMobj = NULL;
|
||||
}
|
||||
else if (thing->player &&
|
||||
thing->Top() - BlockingMobj->Z() <= thing->MaxStepHeight)
|
||||
{
|
||||
if (thingblocker)
|
||||
{ // There is something to step up on. Return this thing as
|
||||
// the blocker so that we don't step up.
|
||||
thing->height = realheight;
|
||||
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
|
||||
while ((it2.Next(&tcres)))
|
||||
{
|
||||
if (!PIT_CheckThing(it2, tcres, it2.Box(), 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 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)
|
||||
{ // Thing slammed into something; don't let it move now.
|
||||
thing->height = realheight;
|
||||
return false;
|
||||
}
|
||||
else if (!BlockingMobj->player && !(thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY)) &&
|
||||
BlockingMobj->Top() - thing->Z() <= thing->MaxStepHeight)
|
||||
{
|
||||
if (thingblocker == NULL ||
|
||||
BlockingMobj->Z() > thingblocker->Z())
|
||||
{
|
||||
thingblocker = BlockingMobj;
|
||||
}
|
||||
thing->BlockingMobj = NULL;
|
||||
}
|
||||
else if (thing->player &&
|
||||
thing->Top() - BlockingMobj->Z() <= thing->MaxStepHeight)
|
||||
{
|
||||
if (thingblocker)
|
||||
{ // There is something to step up on. Return this thing as
|
||||
// the blocker so that we don't step up.
|
||||
thing->height = realheight;
|
||||
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))
|
||||
return (thing->BlockingMobj = thingblocker) == NULL;
|
||||
|
||||
FBlockLinesIterator it(box);
|
||||
FMultiBlockLinesIterator it(pcheck, thing);
|
||||
FMultiBlockLinesIterator::CheckResult lcres;
|
||||
line_t *ld;
|
||||
|
||||
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;
|
||||
|
||||
while ((ld = it.Next()))
|
||||
while (it.Next(&lcres))
|
||||
{
|
||||
good &= PIT_CheckLine(ld, box, tm);
|
||||
good &= PIT_CheckLine(it, lcres, it.Box(), tm);
|
||||
}
|
||||
if (!good)
|
||||
{
|
||||
|
|
|
@ -229,6 +229,8 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
|
|||
open.floorterrain = back->GetTerrain(sector_t::floor);
|
||||
open.lowfloor = ff;
|
||||
}
|
||||
open.frontfloorplane = front->floorplane;
|
||||
open.backfloorplane = back->floorplane;
|
||||
}
|
||||
else
|
||||
{ // 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.bottom = FIXED_MIN;
|
||||
open.lowfloor = FIXED_MAX;
|
||||
open.frontfloorplane.SetAtHeight(FIXED_MIN, sector_t::floor);
|
||||
open.backfloorplane.SetAtHeight(FIXED_MIN, sector_t::floor);
|
||||
}
|
||||
|
||||
// Check 3D floors
|
||||
|
@ -798,6 +802,7 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
|
|||
item->position.x = offset.x;
|
||||
item->position.y = offset.y;
|
||||
item->position.z = checkpoint.z;
|
||||
item->zdiff = 0;
|
||||
item->portalflags = portalflags;
|
||||
return true;
|
||||
}
|
||||
|
@ -1085,6 +1090,7 @@ bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *ite
|
|||
{
|
||||
item->thing = thing;
|
||||
item->position = checkpoint + Displacements(basegroup, thing->Sector->PortalGroup);
|
||||
item->zdiff = 0;
|
||||
item->portalflags = portalflags;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -99,6 +99,8 @@ struct FLineOpening
|
|||
sector_t *topsec;
|
||||
FTextureID ceilingpic;
|
||||
FTextureID floorpic;
|
||||
secplane_t frontfloorplane;
|
||||
secplane_t backfloorplane;
|
||||
int floorterrain;
|
||||
bool touchmidtex;
|
||||
bool abovemidtex;
|
||||
|
@ -221,6 +223,7 @@ public:
|
|||
{
|
||||
line_t *line;
|
||||
fixedvec3 position;
|
||||
fixed_t zdiff;
|
||||
int portalflags;
|
||||
};
|
||||
|
||||
|
@ -306,6 +309,7 @@ public:
|
|||
{
|
||||
AActor *thing;
|
||||
fixedvec3 position;
|
||||
fixed_t zdiff;
|
||||
int portalflags;
|
||||
};
|
||||
|
||||
|
|
15
src/r_defs.h
15
src/r_defs.h
|
@ -345,6 +345,21 @@ struct secplane_t
|
|||
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;
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue