Local P_LineOpening result + traversal leniency

P_LineOpening results are stored in a locally made struct instead of being a bunch of disorganized globals.

Waypoint traversals can go thru 1 line, if it was blocked by step-up rules, for free, similar concept to sound-blocking lines in Doom.
This commit is contained in:
Sally Coolatta 2023-05-13 00:39:36 -04:00
parent 66f0c7c9f0
commit 6fa821b2d3
5 changed files with 268 additions and 259 deletions

View file

@ -1671,6 +1671,8 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
// Adjusts tm.floorz and tm.ceilingz as lines are contacted - FOR CAMERA ONLY // Adjusts tm.floorz and tm.ceilingz as lines are contacted - FOR CAMERA ONLY
static BlockItReturn_t PIT_CheckCameraLine(line_t *ld) static BlockItReturn_t PIT_CheckCameraLine(line_t *ld)
{ {
opening_t open = {0};
if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID)) if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID))
return BMIT_CONTINUE; return BMIT_CONTINUE;
@ -1704,25 +1706,25 @@ static BlockItReturn_t PIT_CheckCameraLine(line_t *ld)
} }
// set openrange, opentop, openbottom // set openrange, opentop, openbottom
P_CameraLineOpening(ld); P_CameraLineOpening(ld, &open);
// adjust floor / ceiling heights // adjust floor / ceiling heights
if (opentop < tm.ceilingz) if (open.ceiling < tm.ceilingz)
{ {
tm.ceilingz = opentop; tm.ceilingz = open.ceiling;
tm.ceilingline = ld; tm.ceilingline = ld;
} }
if (openbottom > tm.floorz) if (open.floor > tm.floorz)
{ {
tm.floorz = openbottom; tm.floorz = open.floor;
} }
if (highceiling > tm.drpoffceilz) if (open.highceiling > tm.drpoffceilz)
tm.drpoffceilz = highceiling; tm.drpoffceilz = open.highceiling;
if (lowfloor < tm.dropoffz) if (open.lowfloor < tm.dropoffz)
tm.dropoffz = lowfloor; tm.dropoffz = open.lowfloor;
return BMIT_CONTINUE; return BMIT_CONTINUE;
} }
@ -1773,6 +1775,7 @@ boolean P_IsLineTripWire(const line_t *ld)
static BlockItReturn_t PIT_CheckLine(line_t *ld) static BlockItReturn_t PIT_CheckLine(line_t *ld)
{ {
const fixed_t thingtop = tm.thing->z + tm.thing->height; const fixed_t thingtop = tm.thing->z + tm.thing->height;
opening_t open = {0};
if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID)) if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID))
return BMIT_CONTINUE; return BMIT_CONTINUE;
@ -1845,41 +1848,41 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld)
return BMIT_ABORT; return BMIT_ABORT;
// set openrange, opentop, openbottom // set openrange, opentop, openbottom
P_LineOpening(ld, tm.thing); P_LineOpening(ld, tm.thing, &open);
// adjust floor / ceiling heights // adjust floor / ceiling heights
if (opentop < tm.ceilingz) if (open.ceiling < tm.ceilingz)
{ {
tm.ceilingz = opentop; tm.ceilingz = open.ceiling;
tm.ceilingline = ld; tm.ceilingline = ld;
tm.ceilingrover = openceilingrover; tm.ceilingrover = open.ceilingrover;
tm.ceilingslope = opentopslope; tm.ceilingslope = open.ceilingslope;
tm.ceilingpic = opentoppic; tm.ceilingpic = open.ceilingpic;
tm.ceilingstep = openceilingstep; tm.ceilingstep = open.ceilingstep;
if (thingtop == tm.thing->ceilingz) if (thingtop == tm.thing->ceilingz)
{ {
tm.thing->ceilingdrop = openceilingdrop; tm.thing->ceilingdrop = open.ceilingdrop;
} }
} }
if (openbottom > tm.floorz) if (open.floor > tm.floorz)
{ {
tm.floorz = openbottom; tm.floorz = open.floor;
tm.floorrover = openfloorrover; tm.floorrover = open.floorrover;
tm.floorslope = openbottomslope; tm.floorslope = open.floorslope;
tm.floorpic = openbottompic; tm.floorpic = open.floorpic;
tm.floorstep = openfloorstep; tm.floorstep = open.floorstep;
if (tm.thing->z == tm.thing->floorz) if (tm.thing->z == tm.thing->floorz)
{ {
tm.thing->floordrop = openfloordrop; tm.thing->floordrop = open.floordrop;
} }
} }
if (highceiling > tm.drpoffceilz) if (open.highceiling > tm.drpoffceilz)
tm.drpoffceilz = highceiling; tm.drpoffceilz = open.highceiling;
if (lowfloor < tm.dropoffz) if (open.lowfloor < tm.dropoffz)
tm.dropoffz = lowfloor; tm.dropoffz = open.lowfloor;
// we've crossed the line // we've crossed the line
if (P_SpecialIsLinedefCrossType(ld)) if (P_SpecialIsLinedefCrossType(ld))
@ -3462,6 +3465,7 @@ static void P_HitBounceLine(line_t *ld)
static boolean PTR_SlideCameraTraverse(intercept_t *in) static boolean PTR_SlideCameraTraverse(intercept_t *in)
{ {
line_t *li; line_t *li;
opening_t open = {0};
I_Assert(in->isaline); I_Assert(in->isaline);
@ -3476,15 +3480,15 @@ static boolean PTR_SlideCameraTraverse(intercept_t *in)
} }
// set openrange, opentop, openbottom // set openrange, opentop, openbottom
P_CameraLineOpening(li); P_CameraLineOpening(li, &open);
if (openrange < mapcampointer->height) if (open.range < mapcampointer->height)
goto isblocking; // doesn't fit goto isblocking; // doesn't fit
if (opentop - mapcampointer->z < mapcampointer->height) if (open.ceiling - mapcampointer->z < mapcampointer->height)
goto isblocking; // mobj is too high goto isblocking; // mobj is too high
if (openbottom - mapcampointer->z > 0) // We don't want to make the camera step up. if (open.floor - mapcampointer->z > 0) // We don't want to make the camera step up.
goto isblocking; // too big a step up goto isblocking; // too big a step up
// this line doesn't block movement // this line doesn't block movement
@ -3509,6 +3513,8 @@ isblocking:
/* /*
static boolean PTR_LineIsBlocking(line_t *li) static boolean PTR_LineIsBlocking(line_t *li)
{ {
opening_t open = {0};
// one-sided linedefs are always solid to sliding movement. // one-sided linedefs are always solid to sliding movement.
if (!li->backsector) if (!li->backsector)
return !P_PointOnLineSide(slidemo->x, slidemo->y, li); return !P_PointOnLineSide(slidemo->x, slidemo->y, li);
@ -3517,15 +3523,15 @@ static boolean PTR_LineIsBlocking(line_t *li)
return true; return true;
// set openrange, opentop, openbottom // set openrange, opentop, openbottom
P_LineOpening(li, slidemo); P_LineOpening(li, slidemo, &open);
if (openrange < slidemo->height) if (open.range < slidemo->height)
return true; // doesn't fit return true; // doesn't fit
if (opentop - slidemo->z < slidemo->height) if (open.ceiling - slidemo->z < slidemo->height)
return true; // mobj is too high return true; // mobj is too high
if (openbottom - slidemo->z > P_GetThingStepUp(slidemo, slidemo->x, slidemo->y)) if (open.floor - slidemo->z > P_GetThingStepUp(slidemo, slidemo->x, slidemo->y))
return true; // too big a step up return true; // too big a step up
return false; return false;

View file

@ -335,28 +335,24 @@ line_t * P_FindNearestLine
// Sets opentop and openbottom to the window through a two sided line. // Sets opentop and openbottom to the window through a two sided line.
// OPTIMIZE: keep this precalculated // OPTIMIZE: keep this precalculated
// //
fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
pslope_t *opentopslope, *openbottomslope;
ffloor_t *openfloorrover, *openceilingrover;
fixed_t openceilingstep;
fixed_t openceilingdrop;
fixed_t openfloorstep;
fixed_t openfloordrop;
INT32 opentoppic, openbottompic;
// P_CameraLineOpening // P_CameraLineOpening
// P_LineOpening, but for camera // P_LineOpening, but for camera
// Tails 09-29-2002 // Tails 09-29-2002
void P_CameraLineOpening(line_t *linedef) void P_CameraLineOpening(line_t *linedef, opening_t *open)
{ {
sector_t *front; sector_t *front;
sector_t *back; sector_t *back;
fixed_t frontfloor, frontceiling, backfloor, backceiling; fixed_t frontfloor, frontceiling, backfloor, backceiling;
fixed_t thingtop;
open->ceiling = open->highceiling = INT32_MAX;
open->floor = open->lowfloor = INT32_MIN;
open->range = 0;
if (linedef->sidenum[1] == 0xffff) if (linedef->sidenum[1] == 0xffff)
{ {
// single sided line // single sided line
openrange = 0;
return; return;
} }
@ -368,14 +364,14 @@ void P_CameraLineOpening(line_t *linedef)
if (front->camsec >= 0) if (front->camsec >= 0)
{ {
// SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetSectorFloorZAt (&sectors[front->camsec], camera[0].x, camera[0].y); frontfloor = P_GetSectorFloorZAt (&sectors[front->camsec], mapcampointer->x, mapcampointer->y);
frontceiling = P_GetSectorCeilingZAt(&sectors[front->camsec], camera[0].x, camera[0].y); frontceiling = P_GetSectorCeilingZAt(&sectors[front->camsec], mapcampointer->x, mapcampointer->y);
} }
else if (front->heightsec >= 0) else if (front->heightsec >= 0)
{ {
// SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
frontfloor = P_GetSectorFloorZAt (&sectors[front->heightsec], camera[0].x, camera[0].y); frontfloor = P_GetSectorFloorZAt (&sectors[front->heightsec], mapcampointer->x, mapcampointer->x);
frontceiling = P_GetSectorCeilingZAt(&sectors[front->heightsec], camera[0].x, camera[0].y); frontceiling = P_GetSectorCeilingZAt(&sectors[front->heightsec], mapcampointer->x, mapcampointer->y);
} }
else else
{ {
@ -386,14 +382,14 @@ void P_CameraLineOpening(line_t *linedef)
if (back->camsec >= 0) if (back->camsec >= 0)
{ {
// SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope)
backfloor = P_GetSectorFloorZAt (&sectors[back->camsec], camera[0].x, camera[0].y); backfloor = P_GetSectorFloorZAt (&sectors[back->camsec], mapcampointer->x, mapcampointer->y);
backceiling = P_GetSectorCeilingZAt(&sectors[back->camsec], camera[0].x, camera[0].y); backceiling = P_GetSectorCeilingZAt(&sectors[back->camsec], mapcampointer->x, mapcampointer->y);
} }
else if (back->heightsec >= 0) else if (back->heightsec >= 0)
{ {
// SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope)
backfloor = P_GetSectorFloorZAt (&sectors[back->heightsec], camera[0].x, camera[0].y); backfloor = P_GetSectorFloorZAt (&sectors[back->heightsec], mapcampointer->x, mapcampointer->y);
backceiling = P_GetSectorCeilingZAt(&sectors[back->heightsec], camera[0].x, camera[0].y); backceiling = P_GetSectorCeilingZAt(&sectors[back->heightsec], mapcampointer->x, mapcampointer->y);
} }
else else
{ {
@ -401,29 +397,28 @@ void P_CameraLineOpening(line_t *linedef)
backceiling = P_CameraGetCeilingZ(mapcampointer, back, tm.x, tm.y, linedef); backceiling = P_CameraGetCeilingZ(mapcampointer, back, tm.x, tm.y, linedef);
} }
{ thingtop = mapcampointer->z + mapcampointer->height;
fixed_t thingtop = mapcampointer->z + mapcampointer->height;
if (frontceiling < backceiling) if (frontceiling < backceiling)
{ {
opentop = frontceiling; open->ceiling = frontceiling;
highceiling = backceiling; open->highceiling = backceiling;
} }
else else
{ {
opentop = backceiling; open->ceiling = backceiling;
highceiling = frontceiling; open->highceiling = frontceiling;
} }
if (frontfloor > backfloor) if (frontfloor > backfloor)
{ {
openbottom = frontfloor; open->floor = frontfloor;
lowfloor = backfloor; open->lowfloor = backfloor;
} }
else else
{ {
openbottom = backfloor; open->floor = backfloor;
lowfloor = frontfloor; open->lowfloor = frontfloor;
} }
// Check for fake floors in the sector. // Check for fake floors in the sector.
@ -445,15 +440,15 @@ void P_CameraLineOpening(line_t *linedef)
delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
if (bottomheight < opentop && delta1 >= delta2) if (bottomheight < open->ceiling && delta1 >= delta2)
opentop = bottomheight; open->ceiling = bottomheight;
else if (bottomheight < highceiling && delta1 >= delta2) else if (bottomheight < open->highceiling && delta1 >= delta2)
highceiling = bottomheight; open->highceiling = bottomheight;
if (topheight > openbottom && delta1 < delta2) if (topheight > open->floor && delta1 < delta2)
openbottom = topheight; open->floor = topheight;
else if (topheight > lowfloor && delta1 < delta2) else if (topheight > open->lowfloor && delta1 < delta2)
lowfloor = topheight; open->lowfloor = topheight;
} }
// Check for backsectors fake floors // Check for backsectors fake floors
@ -469,20 +464,19 @@ void P_CameraLineOpening(line_t *linedef)
delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
if (bottomheight < opentop && delta1 >= delta2) if (bottomheight < open->ceiling && delta1 >= delta2)
opentop = bottomheight; open->ceiling = bottomheight;
else if (bottomheight < highceiling && delta1 >= delta2) else if (bottomheight < open->highceiling && delta1 >= delta2)
highceiling = bottomheight; open->highceiling = bottomheight;
if (topheight > openbottom && delta1 < delta2) if (topheight > open->floor && delta1 < delta2)
openbottom = topheight; open->floor = topheight;
else if (topheight > lowfloor && delta1 < delta2) else if (topheight > open->lowfloor && delta1 < delta2)
lowfloor = topheight; open->lowfloor = topheight;
} }
} }
openrange = opentop - openbottom;
return; open->range = (open->ceiling - open->floor);
}
} }
boolean boolean
@ -592,7 +586,7 @@ static boolean P_MidtextureIsSolid(line_t *linedef, mobj_t *mobj)
return ((linedef->flags & ML_MIDSOLID) == ML_MIDSOLID); return ((linedef->flags & ML_MIDSOLID) == ML_MIDSOLID);
} }
void P_LineOpening(line_t *linedef, mobj_t *mobj) void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open)
{ {
enum { FRONT, BACK }; enum { FRONT, BACK };
@ -608,15 +602,14 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
int lo = 0; int lo = 0;
// set these defaults so that polyobjects don't interfere with collision above or below them // set these defaults so that polyobjects don't interfere with collision above or below them
opentop = highceiling = INT32_MAX; open->ceiling = open->highceiling = INT32_MAX;
openbottom = lowfloor = INT32_MIN; open->floor = open->lowfloor = INT32_MIN;
openrange = 0; open->range = 0;
opentopslope = openbottomslope = NULL; open->ceilingslope = open->floorslope = NULL;
opentoppic = openbottompic = -1; open->ceilingrover = open->floorrover = NULL;
openceilingstep = 0; open->ceilingpic = open->floorpic = -1;
openceilingdrop = 0; open->ceilingstep = open->floorstep = 0;
openfloorstep = 0; open->ceilingdrop = open->floordrop = 0;
openfloordrop = 0;
if (linedef->sidenum[1] == 0xffff) if (linedef->sidenum[1] == 0xffff)
{ {
@ -646,7 +639,6 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
thingtop = mobj->z + mobj->height; thingtop = mobj->z + mobj->height;
} }
openfloorrover = openceilingrover = NULL;
if (!linedef->polyobj) if (!linedef->polyobj)
{ {
// Set open and high/low values here // Set open and high/low values here
@ -659,18 +651,18 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
hi = ( height[0] < height[1] ); hi = ( height[0] < height[1] );
lo = ! hi; lo = ! hi;
opentop = height[lo]; open->ceiling = height[lo];
highceiling = height[hi]; open->highceiling = height[hi];
opentopslope = sector[lo]->c_slope; open->ceilingslope = sector[lo]->c_slope;
opentoppic = sector[lo]->ceilingpic; open->ceilingpic = sector[lo]->ceilingpic;
if (mobj) if (mobj)
{ {
topedge[FRONT] = P_GetSectorCeilingZAt(front, cross.x, cross.y); topedge[FRONT] = P_GetSectorCeilingZAt(front, cross.x, cross.y);
topedge[BACK] = P_GetSectorCeilingZAt(back, cross.x, cross.y); topedge[BACK] = P_GetSectorCeilingZAt(back, cross.x, cross.y);
openceilingstep = ( thingtop - topedge[lo] ); open->ceilingstep = ( thingtop - topedge[lo] );
openceilingdrop = ( topedge[hi] - topedge[lo] ); open->ceilingdrop = ( topedge[hi] - topedge[lo] );
} }
height[FRONT] = P_GetFloorZ(mobj, front, tm.x, tm.y, linedef); height[FRONT] = P_GetFloorZ(mobj, front, tm.x, tm.y, linedef);
@ -679,18 +671,18 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
hi = ( height[0] < height[1] ); hi = ( height[0] < height[1] );
lo = ! hi; lo = ! hi;
openbottom = height[hi]; open->floor = height[hi];
lowfloor = height[lo]; open->lowfloor = height[lo];
openbottomslope = sector[hi]->f_slope; open->floorslope = sector[hi]->f_slope;
openbottompic = sector[hi]->floorpic; open->floorpic = sector[hi]->floorpic;
if (mobj) if (mobj)
{ {
botedge[FRONT] = P_GetSectorFloorZAt(front, cross.x, cross.y); botedge[FRONT] = P_GetSectorFloorZAt(front, cross.x, cross.y);
botedge[BACK] = P_GetSectorFloorZAt(back, cross.x, cross.y); botedge[BACK] = P_GetSectorFloorZAt(back, cross.x, cross.y);
openfloorstep = ( botedge[hi] - mobj->z ); open->floorstep = ( botedge[hi] - mobj->z );
openfloordrop = ( botedge[hi] - botedge[lo] ); open->floordrop = ( botedge[hi] - botedge[lo] );
} }
} }
@ -712,25 +704,25 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (delta1 > delta2) if (delta1 > delta2)
{ {
// Below // Below
if (opentop > texbottom) if (open->ceiling > texbottom)
{ {
topedge[lo] -= ( opentop - texbottom ); topedge[lo] -= ( open->ceiling - texbottom );
opentop = texbottom; open->ceiling = texbottom;
openceilingstep = ( thingtop - topedge[lo] ); open->ceilingstep = ( thingtop - topedge[lo] );
openceilingdrop = ( topedge[hi] - topedge[lo] ); open->ceilingdrop = ( topedge[hi] - topedge[lo] );
} }
} }
else else
{ {
// Above // Above
if (openbottom < textop) if (open->floor < textop)
{ {
botedge[hi] += ( textop - openbottom ); botedge[hi] += ( textop - open->floor );
openbottom = textop; open->floor = textop;
openfloorstep = ( botedge[hi] - mobj->z ); open->floorstep = ( botedge[hi] - mobj->z );
openfloordrop = ( botedge[hi] - botedge[lo] ); open->floordrop = ( botedge[hi] - botedge[lo] );
} }
} }
} }
@ -760,26 +752,26 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
delta1 = abs(mobj->z - polymid); delta1 = abs(mobj->z - polymid);
delta2 = abs(thingtop - polymid); delta2 = abs(thingtop - polymid);
if (delta1 >= delta2) if (delta1 > delta2)
{ {
if (polybottom < opentop) if (polybottom < open->ceiling)
{ {
opentop = polybottom; open->ceiling = polybottom;
} }
else if (polybottom < highceiling) else if (polybottom < open->highceiling)
{ {
highceiling = polybottom; open->highceiling = polybottom;
} }
} }
else else
{ {
if (polytop > openbottom) if (polytop > open->floor)
{ {
openbottom = polytop; open->floor = polytop;
} }
else if (polytop > lowfloor) else if (polytop > open->lowfloor)
{ {
lowfloor = polytop; open->lowfloor = polytop;
} }
} }
} }
@ -796,11 +788,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
/* yuck */ /* yuck */
struct struct
{ {
fixed_t top; fixed_t ceiling;
fixed_t bottom; fixed_t floor;
ffloor_t * ceilingrover; ffloor_t * ceilingrover;
ffloor_t * floorrover; ffloor_t * floorrover;
} open[2] = { } fofopen[2] = {
{ INT32_MAX, INT32_MIN, NULL, NULL }, { INT32_MAX, INT32_MIN, NULL, NULL },
{ INT32_MAX, INT32_MIN, NULL, NULL }, { INT32_MAX, INT32_MIN, NULL, NULL },
}; };
@ -831,10 +823,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
// thing is below FOF // thing is below FOF
if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM)
{ {
if (bottomheight < open[FRONT].top) if (bottomheight < fofopen[FRONT].ceiling)
{ {
open[FRONT].top = bottomheight; fofopen[FRONT].ceiling = bottomheight;
open[FRONT].ceilingrover = rover; fofopen[FRONT].ceilingrover = rover;
} }
} }
} }
@ -843,10 +835,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
// thing is above FOF // thing is above FOF
if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM)
{ {
if (topheight > open[FRONT].bottom) if (topheight > fofopen[FRONT].floor)
{ {
open[FRONT].bottom = topheight; fofopen[FRONT].floor = topheight;
open[FRONT].floorrover = rover; fofopen[FRONT].floorrover = rover;
} }
} }
} }
@ -878,10 +870,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
// thing is below FOF // thing is below FOF
if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM)
{ {
if (bottomheight < open[BACK].top) if (bottomheight < fofopen[BACK].ceiling)
{ {
open[BACK].top = bottomheight; fofopen[BACK].ceiling = bottomheight;
open[BACK].ceilingrover = rover; fofopen[BACK].ceilingrover = rover;
} }
} }
} }
@ -890,77 +882,77 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
// thing is above FOF // thing is above FOF
if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM)
{ {
if (topheight > open[BACK].bottom) if (topheight > fofopen[BACK].floor)
{ {
open[BACK].bottom = topheight; fofopen[BACK].floor = topheight;
open[BACK].floorrover = rover; fofopen[BACK].floorrover = rover;
} }
} }
} }
} }
hi = ( open[0].top < open[1].top ); hi = ( fofopen[0].ceiling < fofopen[1].ceiling );
lo = ! hi; lo = ! hi;
if (open[lo].top <= opentop) if (fofopen[lo].ceiling <= open->ceiling)
{ {
topedge[lo] = P_GetFFloorBottomZAt(open[lo].ceilingrover, cross.x, cross.y); topedge[lo] = P_GetFFloorBottomZAt(fofopen[lo].ceilingrover, cross.x, cross.y);
if (open[hi].top < opentop) if (fofopen[hi].ceiling < open->ceiling)
{ {
topedge[hi] = P_GetFFloorBottomZAt(open[hi].ceilingrover, cross.x, cross.y); topedge[hi] = P_GetFFloorBottomZAt(fofopen[hi].ceilingrover, cross.x, cross.y);
} }
opentop = open[lo].top; open->ceiling = fofopen[lo].ceiling;
openceilingrover = open[lo].ceilingrover; open->ceilingrover = fofopen[lo].ceilingrover;
opentopslope = *open[lo].ceilingrover->b_slope; open->ceilingslope = *fofopen[lo].ceilingrover->b_slope;
opentoppic = *open[lo].ceilingrover->bottompic; open->ceilingpic = *fofopen[lo].ceilingrover->bottompic;
openceilingstep = ( thingtop - topedge[lo] ); open->ceilingstep = ( thingtop - topedge[lo] );
openceilingdrop = ( topedge[hi] - topedge[lo] ); open->ceilingdrop = ( topedge[hi] - topedge[lo] );
if (open[hi].top < highceiling) if (fofopen[hi].ceiling < open->highceiling)
{ {
highceiling = open[hi].top; open->highceiling = fofopen[hi].ceiling;
} }
} }
else if (open[lo].top < highceiling) else if (fofopen[lo].ceiling < open->highceiling)
{ {
highceiling = open[lo].top; open->highceiling = fofopen[lo].ceiling;
} }
hi = ( open[0].bottom < open[1].bottom ); hi = ( fofopen[0].floor < fofopen[1].floor );
lo = ! hi; lo = ! hi;
if (open[hi].bottom >= openbottom) if (fofopen[hi].floor >= open->floor)
{ {
botedge[hi] = P_GetFFloorTopZAt(open[hi].floorrover, cross.x, cross.y); botedge[hi] = P_GetFFloorTopZAt(fofopen[hi].floorrover, cross.x, cross.y);
if (open[lo].bottom > openbottom) if (fofopen[lo].floor > open->floor)
{ {
botedge[lo] = P_GetFFloorTopZAt(open[lo].floorrover, cross.x, cross.y); botedge[lo] = P_GetFFloorTopZAt(fofopen[lo].floorrover, cross.x, cross.y);
} }
openbottom = open[hi].bottom; open->floor = fofopen[hi].floor;
openfloorrover = open[hi].floorrover; open->floorrover = fofopen[hi].floorrover;
openbottomslope = *open[hi].floorrover->t_slope; open->floorslope = *fofopen[hi].floorrover->t_slope;
openbottompic = *open[hi].floorrover->toppic; open->floorpic = *fofopen[hi].floorrover->toppic;
openfloorstep = ( botedge[hi] - mobj->z ); open->floorstep = ( botedge[hi] - mobj->z );
openfloordrop = ( botedge[hi] - botedge[lo] ); open->floordrop = ( botedge[hi] - botedge[lo] );
if (open[lo].bottom > lowfloor) if (fofopen[lo].floor > open->lowfloor)
{ {
lowfloor = open[lo].bottom; open->lowfloor = fofopen[lo].floor;
} }
} }
else if (open[hi].bottom > lowfloor) else if (fofopen[hi].floor > open->lowfloor)
{ {
lowfloor = open[hi].bottom; open->lowfloor = fofopen[hi].floor;
} }
} }
} }
} }
openrange = opentop - openbottom; open->range = (open->ceiling - open->floor);
} }

View file

@ -50,7 +50,7 @@ void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result);
void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *line, vector3_t *result); void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *line, vector3_t *result);
INT32 P_PointOnLineSide(fixed_t x, fixed_t y, line_t *line); INT32 P_PointOnLineSide(fixed_t x, fixed_t y, line_t *line);
void P_MakeDivline(line_t *li, divline_t *dl); void P_MakeDivline(line_t *li, divline_t *dl);
void P_CameraLineOpening(line_t *plinedef); void P_CameraLineOpening(line_t *plinedef, opening_t *open);
fixed_t P_InterceptVector(divline_t *v2, divline_t *v1); fixed_t P_InterceptVector(divline_t *v2, divline_t *v1);
INT32 P_BoxOnLineSide(fixed_t *tmbox, line_t *ld); INT32 P_BoxOnLineSide(fixed_t *tmbox, line_t *ld);
line_t * P_FindNearestLine(const fixed_t x, const fixed_t y, const sector_t *, const INT32 special); line_t * P_FindNearestLine(const fixed_t x, const fixed_t y, const sector_t *, const INT32 special);
@ -61,16 +61,18 @@ void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_
boolean P_GetMidtextureTopBottom(line_t *linedef, fixed_t x, fixed_t y, fixed_t *return_top, fixed_t *return_bottom); boolean P_GetMidtextureTopBottom(line_t *linedef, fixed_t x, fixed_t y, fixed_t *return_top, fixed_t *return_bottom);
extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling; struct opening_t
extern pslope_t *opentopslope, *openbottomslope; {
extern ffloor_t *openfloorrover, *openceilingrover; fixed_t ceiling, floor, range;
extern fixed_t openceilingstep; fixed_t lowfloor, highceiling;
extern fixed_t openceilingdrop; pslope_t *floorslope, *ceilingslope;
extern fixed_t openfloorstep; ffloor_t *floorrover, *ceilingrover;
extern fixed_t openfloordrop; fixed_t ceilingstep, ceilingdrop;
extern INT32 opentoppic, openbottompic; fixed_t floorstep, floordrop;
INT32 ceilingpic, floorpic;
};
void P_LineOpening(line_t *plinedef, mobj_t *mobj); void P_LineOpening(line_t *plinedef, mobj_t *mobj, opening_t *open);
typedef enum typedef enum
{ {

View file

@ -36,6 +36,7 @@ typedef struct
mobj_t *t1, *t2; mobj_t *t1, *t2;
boolean alreadyHates; // For bot traversal, for if the bot is already in a sector it doesn't want to be boolean alreadyHates; // For bot traversal, for if the bot is already in a sector it doesn't want to be
UINT8 traversed;
} los_t; } los_t;
typedef boolean (*los_init_t)(mobj_t *, mobj_t *, register los_t *); typedef boolean (*los_init_t)(mobj_t *, mobj_t *, register los_t *);
@ -51,6 +52,8 @@ typedef struct
static INT32 sightcounts[2]; static INT32 sightcounts[2];
#define TRAVERSE_MAX (2)
// //
// P_DivlineSide // P_DivlineSide
// //
@ -365,6 +368,7 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los
fixed_t frac = 0; fixed_t frac = 0;
boolean canStepUp, canDropOff; boolean canStepUp, canDropOff;
fixed_t maxstep = 0; fixed_t maxstep = 0;
opening_t open = {0};
if (P_CanTraceBlockingLine(seg, divl, los) == false) if (P_CanTraceBlockingLine(seg, divl, los) == false)
{ {
@ -380,32 +384,32 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los
tm.y = los->strace.y + FixedMul(los->strace.dy, frac); tm.y = los->strace.y + FixedMul(los->strace.dy, frac);
// set openrange, opentop, openbottom // set openrange, opentop, openbottom
P_LineOpening(line, los->t1); P_LineOpening(line, los->t1, &open);
maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y);
if (openrange < los->t1->height) if (open.range < los->t1->height)
{ {
// Can't fit // Can't fit
return false; return false;
} }
canStepUp = ((flip ? (highceiling - opentop) : (openbottom - lowfloor)) <= maxstep); // If we can step up...
canDropOff = (flip ? (los->t1->z + los->t1->height <= opentop) : (los->t1->z >= openbottom)); canStepUp = ((flip ? (open.highceiling - open.ceiling) : (open.floor - open.lowfloor)) <= maxstep);
// Or if we're on the higher side...
canDropOff = (flip ? (los->t1->z + los->t1->height <= open.ceiling) : (los->t1->z >= open.floor));
if (canStepUp || canDropOff) if (canStepUp || canDropOff)
{ {
if (los->t1->player != NULL && los->alreadyHates == false) if (los->t1->player != NULL && los->alreadyHates == false)
{ {
// Treat damage sectors like walls, if you're not already in a bad sector. // Treat damage / offroad sectors like walls.
sector_t *front, *back; UINT8 side = P_DivlineSide(los->t2x, los->t2y, divl) & 1;
sector_t *sector = (side == 1) ? seg->backsector : seg->frontsector;
front = seg->frontsector; if (K_BotHatesThisSector(los->t1->player, sector, tm.x, tm.y))
back = seg->backsector;
if (K_BotHatesThisSector(los->t1->player, front, tm.x, tm.y)
|| K_BotHatesThisSector(los->t1->player, back, tm.x, tm.y))
{ {
// This line does not block us, but we don't want to be in it. // This line does not block us, but we don't want to cross it regardless.
return false; return false;
} }
} }
@ -413,7 +417,8 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los
return true; return true;
} }
return false; los->traversed++;
return (los->traversed < TRAVERSE_MAX);
} }
static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t *los) static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t *los)
@ -423,6 +428,7 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t
fixed_t frac = 0; fixed_t frac = 0;
boolean canStepUp, canDropOff; boolean canStepUp, canDropOff;
fixed_t maxstep = 0; fixed_t maxstep = 0;
opening_t open = {0};
if (P_CanTraceBlockingLine(seg, divl, los) == false) if (P_CanTraceBlockingLine(seg, divl, los) == false)
{ {
@ -445,10 +451,10 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t
tm.y = los->strace.y + FixedMul(los->strace.dy, frac); tm.y = los->strace.y + FixedMul(los->strace.dy, frac);
// set openrange, opentop, openbottom // set openrange, opentop, openbottom
P_LineOpening(line, los->t1); P_LineOpening(line, los->t1, &open);
maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y);
#if 0 #if 1
if (los->t2->type == MT_WAYPOINT) if (los->t2->type == MT_WAYPOINT)
{ {
waypoint_t *wp = K_SearchWaypointHeapForMobj(los->t2); waypoint_t *wp = K_SearchWaypointHeapForMobj(los->t2);
@ -456,19 +462,19 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t
if (wp != NULL) if (wp != NULL)
{ {
CONS_Printf( CONS_Printf(
"========\nID: %d\nopenrange: %.2f >= %.2f\n", "========\nID: %d\nrange: %.2f >= %.2f\n",
K_GetWaypointID(wp), K_GetWaypointID(wp),
FIXED_TO_FLOAT(openrange), FIXED_TO_FLOAT(open.range),
FIXED_TO_FLOAT(los->t1->height) FIXED_TO_FLOAT(los->t1->height)
); );
if (openrange >= los->t1->height) if (open.range >= los->t1->height)
{ {
CONS_Printf( CONS_Printf(
"openbottom: %.2f\nlowfloor: %.2f\nstep: %.2f <= %.2f\n", "floor: %.2f\nlowfloor: %.2f\nstep: %.2f <= %.2f\n",
FIXED_TO_FLOAT(openbottom), FIXED_TO_FLOAT(open.floor),
FIXED_TO_FLOAT(lowfloor), FIXED_TO_FLOAT(open.lowfloor),
FIXED_TO_FLOAT(openbottom - lowfloor), FIXED_TO_FLOAT(open.floor - open.lowfloor),
FIXED_TO_FLOAT(maxstep) FIXED_TO_FLOAT(maxstep)
); );
} }
@ -476,24 +482,25 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t
} }
#endif #endif
if (openrange < los->t1->height) if (open.range < los->t1->height)
{ {
// Can't fit // Can't fit
return false; return false;
} }
// If we can step up... // If we can step up...
canStepUp = ((flip ? (highceiling - opentop) : (openbottom - lowfloor)) <= maxstep); canStepUp = ((flip ? (open.highceiling - open.ceiling) : (open.floor - open.lowfloor)) <= maxstep);
// Or if we're on the higher side... // Or if we're on the higher side...
canDropOff = (flip ? (los->t1->z + los->t1->height <= opentop) : (los->t1->z >= openbottom)); canDropOff = (flip ? (los->t1->z + los->t1->height <= open.ceiling) : (los->t1->z >= open.floor));
if (canStepUp || canDropOff) if (canStepUp || canDropOff)
{ {
return true; return true;
} }
return false; los->traversed++;
return (los->traversed < TRAVERSE_MAX);
} }
// //
@ -748,6 +755,7 @@ static boolean P_CompareMobjsAcrossLines(mobj_t *t1, mobj_t *t2, register los_fu
los.t1 = t1; los.t1 = t1;
los.t2 = t2; los.t2 = t2;
los.alreadyHates = false; los.alreadyHates = false;
los.traversed = 0;
los.topslope = los.topslope =
(los.bottomslope = t2->z - (los.sightzstart = (los.bottomslope = t2->z - (los.sightzstart =

View file

@ -265,6 +265,7 @@ TYPEDEF (BasicFF_t);
// p_maputl.h // p_maputl.h
TYPEDEF (divline_t); TYPEDEF (divline_t);
TYPEDEF (intercept_t); TYPEDEF (intercept_t);
TYPEDEF (opening_t);
// p_mobj.h // p_mobj.h
TYPEDEF (mobj_t); TYPEDEF (mobj_t);