diff --git a/src/p_map.c b/src/p_map.c index b026e124b..bea998ebd 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1579,11 +1579,6 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) tmceilingrover = openceilingrover; tmceilingslope = opentopslope; tmceilingpic = opentoppic; - tmceilingstep = openceilingstep; - if (thingtop == tmthing->ceilingz) - { - tmthing->ceilingdrop = openceilingdrop; - } } if (openbottom > tmfloorz) @@ -1592,11 +1587,6 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) tmfloorrover = openfloorrover; tmfloorslope = openbottomslope; tmfloorpic = openbottompic; - tmfloorstep = openfloorstep; - if (tmthing->z == tmthing->floorz) - { - tmthing->floordrop = openfloordrop; - } } if (highceiling > tmdrpoffceilz) @@ -2554,15 +2544,149 @@ boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) // boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) { - fixed_t oldx = thing->x; - fixed_t oldy = thing->y; + fixed_t tryx = thing->x; + fixed_t tryy = thing->y; + fixed_t oldx = tryx; + fixed_t oldy = tryy; + fixed_t radius = thing->radius; + fixed_t thingtop = thing->z + thing->height; fixed_t startingonground = P_IsObjectOnGround(thing); - fixed_t stairjank = 0; - pslope_t *oldslope = thing->standingslope; + floatok = false; + + // reset this to 0 at the start of each trymove call as it's only used here + numspechitint = 0U; + + // This makes sure that there are no freezes from computing extremely small movements. + // Originally was MAXRADIUS/2, but that causes some inconsistencies for small players. + if (radius < mapobjectscale) + radius = mapobjectscale; + + do { + if (thing->flags & MF_NOCLIP) { + tryx = x; + tryy = y; + } else { + if (x-tryx > radius) + tryx += radius; + else if (x-tryx < -radius) + tryx -= radius; + else + tryx = x; + if (y-tryy > radius) + tryy += radius; + else if (y-tryy < -radius) + tryy -= radius; + else + tryy = y; + } + + if (!P_CheckPosition(thing, tryx, tryy)) + return false; // solid wall or thing + + // copy into the spechitint buffer from spechit + spechitint_copyinto(); + + if (!(thing->flags & MF_NOCLIP)) + { + //All things are affected by their scale. + const fixed_t maxstepmove = FixedMul(MAXSTEPMOVE, mapobjectscale); + fixed_t maxstep = maxstepmove; + + if (thing->player && thing->player->waterskip) + maxstep += maxstepmove; // Add some extra stepmove when waterskipping + + // If using type Section1:13, double the maxstep. + if (P_MobjTouchingSectorSpecial(thing, 1, 13, false)) + maxstep <<= 1; + // If using type Section1:12, no maxstep. For short walls, like Egg Zeppelin + else if (P_MobjTouchingSectorSpecial(thing, 1, 12, false)) + maxstep = 0; + + if (thing->type == MT_SKIM) + maxstep = 0; + + if (tmceilingz - tmfloorz < thing->height) + { + if (tmfloorthing) + tmhitthing = tmfloorthing; + return false; // doesn't fit + } + + floatok = true; + + if (thing->eflags & MFE_VERTICALFLIP) + { + if (thing->z < tmfloorz) + return false; // mobj must raise itself to fit + } + else if (tmceilingz < thingtop) + return false; // mobj must lower itself to fit + + // Ramp test + if ((maxstep > 0) && !(P_MobjTouchingSectorSpecial(thing, 1, 14, false))) + { + // If the floor difference is MAXSTEPMOVE or less, and the sector isn't Section1:14, ALWAYS + // step down! Formerly required a Section1:13 sector for the full MAXSTEPMOVE, but no more. + + if (thing->eflags & MFE_VERTICALFLIP) + { + if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep) + { + thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; + thing->ceilingrover = tmceilingrover; + thing->eflags |= MFE_JUSTSTEPPEDDOWN; + } + else if (tmceilingz < thingtop && thingtop - tmceilingz <= 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) + { + thing->z = thing->floorz = tmfloorz; + thing->floorrover = tmfloorrover; + thing->eflags |= MFE_JUSTSTEPPEDDOWN; + } + else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) + { + thing->z = thing->floorz = tmfloorz; + thing->floorrover = tmfloorrover; + thing->eflags |= MFE_JUSTSTEPPEDDOWN; + } + } + + if (thing->eflags & MFE_VERTICALFLIP) + { + if (thingtop - tmceilingz > maxstep) + { + if (tmfloorthing) + tmhitthing = tmfloorthing; + return false; // too big a step up + } + } + else if (tmfloorz - thing->z > maxstep) + { + if (tmfloorthing) + tmhitthing = tmfloorthing; + return false; // too big a step up + } + + if (!allowdropoff && !(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !tmfloorthing) + { + if (thing->eflags & MFE_VERTICALFLIP) + { + if (tmdrpoffceilz - tmceilingz > maxstep) + return false; + } + else if (tmfloorz - tmdropoffz > maxstep) + return false; // don't stand over a dropoff + } + } + } while (tryx != x || tryy != y); // The move is ok! - if (!increment_move(thing, x, y, allowdropoff)) - return false; // If it's a pushable object, check if anything is // standing on top and move it, too. @@ -2597,53 +2721,33 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (!(thing->flags & MF_NOCLIPHEIGHT)) { // Assign thing's standingslope if needed - if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) - { - K_UpdateMobjTerrain(thing, tmfloorpic); - + if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) { if (!startingonground && tmfloorslope) - { P_HandleSlopeLanding(thing, tmfloorslope); - } if (thing->momz <= 0) { thing->standingslope = tmfloorslope; - P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) - { P_PlayerHitFloor(thing->player, true); - } } } - else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) - { - K_UpdateMobjTerrain(thing, tmceilingpic); - + else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) { if (!startingonground && tmceilingslope) - { P_HandleSlopeLanding(thing, tmceilingslope); - } if (thing->momz >= 0) { thing->standingslope = tmceilingslope; - P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) - { P_PlayerHitFloor(thing->player, true); - } } } } - else - { - // don't set standingslope if you're not going to clip against it + else // don't set standingslope if you're not going to clip against it thing->standingslope = NULL; - thing->terrain = NULL; - } thing->x = x; thing->y = y; @@ -2670,7 +2774,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) oldside = P_PointOnLineSide(oldx, oldy, ld); if (side != oldside) { - P_CrossSpecialLine(ld, oldside, thing); + if (ld->special) + { + P_CrossSpecialLine(ld, oldside, thing); + } } } } diff --git a/src/p_maputl.c b/src/p_maputl.c index b4ae2f3ed..fc3819ca5 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -338,10 +338,6 @@ line_t * P_FindNearestLine 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 @@ -564,18 +560,7 @@ P_GetMidtextureTopBottom 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) { @@ -584,8 +569,6 @@ 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)) { @@ -601,11 +584,6 @@ 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) { @@ -616,68 +594,95 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) lowfloor = INT32_MAX; opentopslope = openbottomslope = NULL; opentoppic = openbottompic = -1; - openceilingstep = 0; - openceilingdrop = 0; - openfloorstep = 0; - openfloordrop = 0; } else { // Set open and high/low values here - fixed_t height[2]; + fixed_t frontheight, backheight; const sector_t * sector[2] = { front, back }; - height[FRONT] = P_GetCeilingZ(mobj, front, tmx, tmy, linedef); - height[BACK] = P_GetCeilingZ(mobj, back, tmx, tmy, linedef); + frontheight = P_GetCeilingZ(mobj, front, tmx, tmy, linedef); + backheight = P_GetCeilingZ(mobj, back, tmx, tmy, linedef); - hi = ( height[0] < height[1] ); - lo = ! hi; - - opentop = height[lo]; - highceiling = height[hi]; - opentopslope = sector[lo]->c_slope; - opentoppic = sector[lo]->ceilingpic; - - if (mobj) + if (frontheight < backheight) { - 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] ); + opentop = frontheight; + highceiling = backheight; + opentopslope = front->c_slope; + } + else + { + opentop = backheight; + highceiling = frontheight; + opentopslope = back->c_slope; } - height[FRONT] = P_GetFloorZ(mobj, front, tmx, tmy, linedef); - height[BACK] = P_GetFloorZ(mobj, back, tmx, tmy, linedef); + frontheight = P_GetFloorZ(mobj, front, tmx, tmy, linedef); + backheight = 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; - openbottompic = sector[hi]->floorpic; - - if (mobj) + if (frontheight > backheight) { - 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] ); + openbottom = frontheight; + lowfloor = backheight; + openbottomslope = front->f_slope; } + else + { + openbottom = backheight; + lowfloor = frontheight; + openbottomslope = back->f_slope; + } + + opentoppic = sector[!(frontheight < backheight)]->ceilingpic; + openbottompic = sector[frontheight < backheight]->floorpic; } 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 || (mobj->player && P_IsLineTripWire(linedef) && !K_TripwirePass(mobj->player))) && !linedef->polyobj // don't do anything for polyobjects! ...for now ) { - fixed_t textop, texbottom; + side_t *side = &sides[linedef->sidenum[0]]; + fixed_t textop, texbottom, texheight; fixed_t texmid, delta1, delta2; + INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid + + if (texnum) { + // Get the midtexture's height + texheight = textures[texnum]->height << FRACBITS; + + // Set texbottom and textop to the Z coordinates of the texture's boundaries +#if 0 + // don't remove this code unless solid midtextures + // on non-solid polyobjects should NEVER happen in the future + if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { + if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat + texbottom = back->floorheight + side->rowoffset; + textop = back->ceilingheight + side->rowoffset; + } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { + texbottom = back->floorheight + side->rowoffset; + textop = texbottom + texheight*(side->repeatcnt+1); + } else { + textop = back->ceilingheight + side->rowoffset; + texbottom = textop - texheight*(side->repeatcnt+1); + } + } else +#endif + { + if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat + texbottom = openbottom + side->rowoffset; + textop = opentop + side->rowoffset; + } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { + texbottom = openbottom + side->rowoffset; + textop = texbottom + texheight*(side->repeatcnt+1); + } else { + textop = opentop + side->rowoffset; + texbottom = textop - texheight*(side->repeatcnt+1); + } + } - if (P_GetMidtextureTopBottom(linedef, cross.x, cross.y, &textop, &texbottom)) - { texmid = texbottom+(textop-texbottom)/2; delta1 = abs(mobj->z - texmid); @@ -685,22 +690,10 @@ 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] ); - } } } } @@ -728,22 +721,14 @@ 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 } @@ -755,21 +740,6 @@ 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) { @@ -777,7 +747,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && P_CheckSolidFFloorSurface(mobj->player, rover)) + if (mobj->player && P_CheckSolidLava(rover)) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) @@ -791,11 +761,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF { - if (bottomheight < open[FRONT].top) { - open[FRONT].top = bottomheight; + if (bottomheight < opentop) { + opentop = bottomheight; opentopslope = *rover->b_slope; opentoppic = *rover->bottompic; - open[FRONT].ceilingrover = rover; + openceilingrover = rover; } else if (bottomheight < highceiling) highceiling = bottomheight; @@ -803,11 +773,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF { - if (topheight > open[FRONT].bottom) { - open[FRONT].bottom = topheight; + if (topheight > openbottom) { + openbottom = topheight; openbottomslope = *rover->t_slope; openbottompic = *rover->toppic; - open[FRONT].floorrover = rover; + openfloorrover = rover; } else if (topheight > lowfloor) lowfloor = topheight; @@ -821,7 +791,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && P_CheckSolidFFloorSurface(mobj->player, rover)) + if (mobj->player && P_CheckSolidLava(rover)) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) @@ -835,11 +805,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF { - if (bottomheight < open[BACK].top) { - open[BACK].top = bottomheight; + if (bottomheight < opentop) { + opentop = bottomheight; opentopslope = *rover->b_slope; opentoppic = *rover->bottompic; - open[BACK].ceilingrover = rover; + openceilingrover = rover; } else if (bottomheight < highceiling) highceiling = bottomheight; @@ -847,54 +817,16 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF { - if (topheight > open[BACK].bottom) { - open[BACK].bottom = topheight; + if (topheight > openbottom) { + openbottom = topheight; openbottomslope = *rover->t_slope; openbottompic = *rover->toppic; - open[BACK].floorrover = rover; + openfloorrover = 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 29e7d4de9..936094498 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -61,10 +61,6 @@ boolean P_GetMidtextureTopBottom(line_t *linedef, fixed_t x, fixed_t y, fixed_t 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; extern INT32 opentoppic, openbottompic; void P_LineOpening(line_t *plinedef, mobj_t *mobj);