diff --git a/src/p_map.c b/src/p_map.c index 93c8852413b1f4652e18f79e66970db2eb185633..10f048e77d749e11114e52254a0e071f80a3ddf3 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -58,6 +58,8 @@ mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) ffloor_t *tmfloorrover, *tmceilingrover; pslope_t *tmfloorslope, *tmceilingslope; +static fixed_t tmfloorstep; +static fixed_t tmceilingstep; // keep track of the line that lowers the ceiling, // so missiles don't explode against sky hack walls @@ -1618,6 +1620,8 @@ static boolean PIT_CheckCameraLine(line_t *ld) // static boolean PIT_CheckLine(line_t *ld) { + const fixed_t thingtop = tmthing->z + tmthing->height; + if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID)) return true; @@ -1704,6 +1708,11 @@ static boolean PIT_CheckLine(line_t *ld) ceilingline = ld; tmceilingrover = openceilingrover; tmceilingslope = opentopslope; + tmceilingstep = openceilingstep; + if (thingtop == tmthing->ceilingz) + { + tmthing->ceilingdrop = openceilingdrop; + } } if (openbottom > tmfloorz) @@ -1711,6 +1720,11 @@ static boolean PIT_CheckLine(line_t *ld) tmfloorz = openbottom; tmfloorrover = openfloorrover; tmfloorslope = openbottomslope; + tmfloorstep = openfloorstep; + if (tmthing->z == tmthing->floorz) + { + tmthing->floordrop = openfloordrop; + } } if (highceiling > tmdrpoffceilz) @@ -1765,6 +1779,7 @@ static boolean PIT_CheckLine(line_t *ld) // boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { + INT32 thingtop = thing->z + thing->height; INT32 xl, xh, yl, yh, bx, by; subsector_t *newsubsec; boolean blockval = true; @@ -1800,12 +1815,24 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmfloorslope = newsubsec->sector->f_slope; tmceilingslope = newsubsec->sector->c_slope; + tmfloorstep = 0; + tmceilingstep = 0; + + if (thingtop < thing->ceilingz) + { + thing->ceilingdrop = 0; + } + + if (thing->z > thing->floorz) + { + thing->floordrop = 0; + } + // Check list of fake floors and see if tmfloorz/tmceilingz need to be altered. if (newsubsec->sector->ffloors) { ffloor_t *rover; fixed_t delta1, delta2; - INT32 thingtop = thing->z + thing->height; for (rover = newsubsec->sector->ffloors; rover; rover = rover->next) { @@ -1937,7 +1964,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) if (po->validcount != validcount) // if polyobj hasn't been checked { sector_t *polysec; - fixed_t delta1, delta2, thingtop; + fixed_t delta1, delta2; fixed_t polytop, polybottom; po->validcount = validcount; @@ -1963,7 +1990,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) polybottom = INT32_MIN; } - thingtop = thing->z + thing->height; delta1 = thing->z - (polybottom + ((polytop - polybottom)/2)); delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); @@ -2511,26 +2537,28 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->eflags & MFE_VERTICALFLIP) { - if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep) + if (thingtop == thing->ceilingz && tmceilingz > thingtop && thing->ceilingdrop <= maxstep) { thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; thing->ceilingrover = tmceilingrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; + thing->ceilingdrop = 0; } - else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep) + else if (tmceilingz < thingtop && tmceilingstep <= maxstep) { thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; thing->ceilingrover = tmceilingrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } } - else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep) + else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->floordrop <= maxstep) { thing->z = thing->floorz = tmfloorz; thing->floorrover = tmfloorrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; + thing->floordrop = 0; } - else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) + else if (tmfloorz > thing->z && tmfloorstep <= maxstep) { thing->z = thing->floorz = tmfloorz; thing->floorrover = tmfloorrover; diff --git a/src/p_maputl.c b/src/p_maputl.c index de6feb143bacbd8b8e95eb2f1540173ae4e64eff..ee1fb5a42112fb5c3b49e69a045e324dc12929ae 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -279,6 +279,10 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1) 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; // P_CameraLineOpening // P_LineOpening, but for camera @@ -423,7 +427,18 @@ void P_CameraLineOpening(line_t *linedef) void P_LineOpening(line_t *linedef, mobj_t *mobj) { + enum { FRONT, BACK }; + sector_t *front, *back; + fixed_t thingtop = 0; + vertex_t cross; + + /* these init to shut compiler up */ + fixed_t topedge[2] = {0}; + fixed_t botedge[2] = {0}; + + int hi = 0; + int lo = 0; if (linedef->sidenum[1] == 0xffff) { @@ -432,6 +447,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) return; } + P_ClosestPointOnLine(tmx, tmy, linedef, &cross); + // Treat polyobjects kind of like 3D Floors if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { @@ -447,6 +464,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) I_Assert(front != NULL); I_Assert(back != NULL); + if (mobj) + { + thingtop = mobj->z + mobj->height; + } + openfloorrover = openceilingrover = NULL; if (linedef->polyobj) { @@ -456,48 +478,57 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) highceiling = INT32_MIN; lowfloor = INT32_MAX; opentopslope = openbottomslope = NULL; + openceilingstep = 0; + openceilingdrop = 0; + openfloorstep = 0; + openfloordrop = 0; } else { // Set open and high/low values here - fixed_t frontheight, backheight; + fixed_t height[2]; + const sector_t * sector[2] = { front, back }; - frontheight = P_GetCeilingZ(mobj, front, tmx, tmy, linedef); - backheight = P_GetCeilingZ(mobj, back, tmx, tmy, linedef); + height[FRONT] = P_GetCeilingZ(mobj, front, tmx, tmy, linedef); + height[BACK] = P_GetCeilingZ(mobj, back, tmx, tmy, linedef); - if (frontheight < backheight) - { - opentop = frontheight; - highceiling = backheight; - opentopslope = front->c_slope; - } - else - { - opentop = backheight; - highceiling = frontheight; - opentopslope = back->c_slope; - } + hi = ( height[0] < height[1] ); + lo = ! hi; - frontheight = P_GetFloorZ(mobj, front, tmx, tmy, linedef); - backheight = P_GetFloorZ(mobj, back, tmx, tmy, linedef); + opentop = height[lo]; + highceiling = height[hi]; + opentopslope = sector[lo]->c_slope; - if (frontheight > backheight) + if (mobj) { - openbottom = frontheight; - lowfloor = backheight; - openbottomslope = front->f_slope; + topedge[FRONT] = P_GetSectorCeilingZAt(front, cross.x, cross.y); + topedge[BACK] = P_GetSectorCeilingZAt(back, cross.x, cross.y); + + openceilingstep = ( thingtop - topedge[lo] ); + openceilingdrop = ( topedge[hi] - topedge[lo] ); } - else + + height[FRONT] = P_GetFloorZ(mobj, front, tmx, tmy, linedef); + height[BACK] = P_GetFloorZ(mobj, back, tmx, tmy, linedef); + + hi = ( height[0] < height[1] ); + lo = ! hi; + + openbottom = height[hi]; + lowfloor = height[lo]; + openbottomslope = sector[hi]->f_slope; + + if (mobj) { - openbottom = backheight; - lowfloor = frontheight; - openbottomslope = back->f_slope; + botedge[FRONT] = P_GetSectorFloorZAt(front, cross.x, cross.y); + botedge[BACK] = P_GetSectorFloorZAt(back, cross.x, cross.y); + + openfloorstep = ( botedge[hi] - mobj->z ); + openfloordrop = ( botedge[hi] - botedge[lo] ); } } if (mobj) { - fixed_t thingtop = mobj->z + mobj->height; - // Check for collision with front side's midtexture if Effect 4 is set if (linedef->flags & ML_EFFECT4 && !linedef->polyobj // don't do anything for polyobjects! ...for now @@ -548,10 +579,22 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 > delta2) { // Below if (opentop > texbottom) + { + topedge[lo] -= ( opentop - texbottom ); + opentop = texbottom; + openceilingstep = ( thingtop - topedge[lo] ); + openceilingdrop = ( topedge[hi] - topedge[lo] ); + } } else { // Above if (openbottom < textop) + { + botedge[hi] += ( textop - openbottom ); + openbottom = textop; + openfloorstep = ( botedge[hi] - mobj->z ); + openfloordrop = ( botedge[hi] - botedge[lo] ); + } } } } @@ -579,14 +622,22 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) delta2 = abs(thingtop - (polybottom + ((polytop - polybottom)/2))); if (polybottom < opentop && delta1 >= delta2) + { opentop = polybottom; + } else if (polybottom < highceiling && delta1 >= delta2) + { highceiling = polybottom; + } if (polytop > openbottom && delta1 < delta2) + { openbottom = polytop; + } else if (polytop > lowfloor && delta1 < delta2) + { lowfloor = polytop; + } } // otherwise don't do anything special, pretend there's nothing else there } @@ -598,6 +649,21 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) ffloor_t *rover; fixed_t delta1, delta2; + /* yuck */ + struct + { + fixed_t top; + fixed_t bottom; + ffloor_t * ceilingrover; + ffloor_t * floorrover; + } open[2] = { + { INT32_MAX, INT32_MIN, NULL, NULL }, + { INT32_MAX, INT32_MIN, NULL, NULL }, + }; + + const fixed_t oldopentop = opentop; + const fixed_t oldopenbottom = openbottom; + // Check for frontsector's fake floors for (rover = front->ffloors; rover; rover = rover->next) { @@ -619,10 +685,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF { - if (bottomheight < opentop) { - opentop = bottomheight; + if (bottomheight < open[FRONT].top) { + open[FRONT].top = bottomheight; opentopslope = *rover->b_slope; - openceilingrover = rover; + open[FRONT].ceilingrover = rover; } else if (bottomheight < highceiling) highceiling = bottomheight; @@ -630,10 +696,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF { - if (topheight > openbottom) { - openbottom = topheight; + if (topheight > open[FRONT].bottom) { + open[FRONT].bottom = topheight; openbottomslope = *rover->t_slope; - openfloorrover = rover; + open[FRONT].floorrover = rover; } else if (topheight > lowfloor) lowfloor = topheight; @@ -661,10 +727,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF { - if (bottomheight < opentop) { - opentop = bottomheight; + if (bottomheight < open[BACK].top) { + open[BACK].top = bottomheight; opentopslope = *rover->b_slope; - openceilingrover = rover; + open[BACK].ceilingrover = rover; } else if (bottomheight < highceiling) highceiling = bottomheight; @@ -672,15 +738,53 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF { - if (topheight > openbottom) { - openbottom = topheight; + if (topheight > open[BACK].bottom) { + open[BACK].bottom = topheight; openbottomslope = *rover->t_slope; - openfloorrover = rover; + open[BACK].floorrover = rover; } else if (topheight > lowfloor) lowfloor = topheight; } } + + lo = ( open[0].top > open[1].top ); + + if (open[lo].top <= oldopentop) + { + hi = ! lo; + + topedge[lo] = P_GetFFloorBottomZAt(open[lo].ceilingrover, cross.x, cross.y); + + if (open[hi].top < oldopentop) + { + topedge[hi] = P_GetFFloorBottomZAt(open[hi].ceilingrover, cross.x, cross.y); + } + + opentop = open[lo].top; + openceilingrover = open[lo].ceilingrover; + openceilingstep = ( thingtop - topedge[lo] ); + openceilingdrop = ( topedge[hi] - topedge[lo] ); + } + + hi = ( open[0].bottom < open[1].bottom ); + + if (open[hi].bottom >= oldopenbottom) + { + lo = ! hi; + + botedge[hi] = P_GetFFloorTopZAt(open[hi].floorrover, cross.x, cross.y); + + if (open[lo].bottom > oldopenbottom) + { + botedge[lo] = P_GetFFloorTopZAt(open[lo].floorrover, cross.x, cross.y); + } + + openbottom = open[hi].bottom; + openfloorrover = open[hi].floorrover; + openfloorstep = ( botedge[hi] - mobj->z ); + openfloordrop = ( botedge[hi] - botedge[lo] ); + } } } } diff --git a/src/p_maputl.h b/src/p_maputl.h index 1c071c2cdc77d2fdae9a613b905a6eba3f15aa5e..9349d0e53c95c75a344432d093cfe19251c09db2 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -58,6 +58,10 @@ void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_ extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling; extern pslope_t *opentopslope, *openbottomslope; extern ffloor_t *openfloorrover, *openceilingrover; +extern fixed_t openceilingstep; +extern fixed_t openceilingdrop; +extern fixed_t openfloorstep; +extern fixed_t openfloordrop; void P_LineOpening(line_t *plinedef, mobj_t *mobj); diff --git a/src/p_mobj.h b/src/p_mobj.h index eaf97c44152dcb40e4ebef5c03f84879ba9546a4..cd0cc3bc74f4ecd2c18207287071eb55ded4625b 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -326,6 +326,8 @@ typedef struct mobj_s fixed_t ceilingz; // Nearest ceiling above. struct ffloor_s *floorrover; // FOF referred by floorz struct ffloor_s *ceilingrover; // FOF referred by ceilingz + fixed_t floordrop; + fixed_t ceilingdrop; // For movement checking. fixed_t radius;