diff --git a/src/p_map.c b/src/p_map.c index 0d53074ad..4bb58790f 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1584,6 +1584,11 @@ 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,6 +1597,11 @@ 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) @@ -2553,149 +2563,15 @@ 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 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 oldx = thing->x; + fixed_t oldy = thing->y; fixed_t startingonground = P_IsObjectOnGround(thing); - 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)) - maxstep <<= 1; - // If using type Section1:12, no maxstep. For short walls, like Egg Zeppelin - else if (P_MobjTouchingSectorSpecial(thing, 1, 12)) - 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))) - { - // 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); + fixed_t stairjank = 0; + pslope_t *oldslope = thing->standingslope; // 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. @@ -2730,12 +2606,14 @@ 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)) { - + if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) + { K_UpdateMobjTerrain(thing, tmfloorpic); - + if (!startingonground && tmfloorslope) + { P_HandleSlopeLanding(thing, tmfloorslope); + } if (thing->momz <= 0) { @@ -2743,15 +2621,19 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) 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)) { - + else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) + { K_UpdateMobjTerrain(thing, tmceilingpic); if (!startingonground && tmceilingslope) + { P_HandleSlopeLanding(thing, tmceilingslope); + } if (thing->momz >= 0) { @@ -2759,15 +2641,19 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) 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; diff --git a/src/p_maputl.c b/src/p_maputl.c index 4c78c4ed4..1f91154dd 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -338,6 +338,10 @@ 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 @@ -590,7 +594,18 @@ static boolean P_MidtextureIsSolid(line_t *linedef, mobj_t *mobj) 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) { @@ -599,6 +614,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)) { @@ -614,6 +631,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) { @@ -624,78 +646,88 @@ 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 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) + hi = ( height[0] < height[1] ); + lo = ! hi; + + opentop = height[lo]; + highceiling = height[hi]; + opentopslope = sector[lo]->c_slope; + opentoppic = sector[lo]->ceilingpic; + + if (mobj) { - opentop = frontheight; - highceiling = backheight; - opentopslope = front->c_slope; - } - else - { - opentop = backheight; - highceiling = frontheight; - opentopslope = back->c_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] ); } - frontheight = P_GetFloorZ(mobj, front, tmx, tmy, linedef); - backheight = P_GetFloorZ(mobj, back, tmx, tmy, linedef); + height[FRONT] = P_GetFloorZ(mobj, front, tmx, tmy, linedef); + height[BACK] = P_GetFloorZ(mobj, back, tmx, tmy, linedef); - if (frontheight > backheight) + hi = ( height[0] < height[1] ); + lo = ! hi; + + openbottom = height[hi]; + lowfloor = height[lo]; + openbottomslope = sector[hi]->f_slope; + openbottompic = sector[hi]->floorpic; + + if (mobj) { - openbottom = frontheight; - lowfloor = backheight; - openbottomslope = front->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] ); } - 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 (P_MidtextureIsSolid(linedef, mobj) == true) { - side_t *side = &sides[linedef->sidenum[0]]; - fixed_t textop, texbottom, texheight; + fixed_t textop, texbottom; fixed_t texmid, delta1, delta2; - INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid - vertex_t cross; - if (texnum) { - // Get the midtexture's height - texheight = textures[texnum]->height << FRACBITS; - P_ClosestPointOnLine(tmx, tmy, linedef, &cross); - - if (P_GetMidtextureTopBottom(linedef, cross.x, cross.y, &textop, &texbottom)) - { - texmid = texbottom+(textop-texbottom)/2; + if (P_GetMidtextureTopBottom(linedef, cross.x, cross.y, &textop, &texbottom)) + { + texmid = texbottom+(textop-texbottom)/2; - delta1 = abs(mobj->z - texmid); - delta2 = abs(thingtop - texmid); + delta1 = abs(mobj->z - texmid); + delta2 = abs(thingtop - texmid); - if (delta1 > delta2) { // Below - if (opentop > texbottom) - opentop = texbottom; - } else { // Above - if (openbottom < textop) - openbottom = textop; + 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] ); } } } @@ -725,14 +757,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 } @@ -744,6 +784,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) { @@ -765,11 +820,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 >= delta2 && (rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) // thing is below FOF { - if (bottomheight < opentop) { - opentop = bottomheight; + if (bottomheight < open[FRONT].top) { + open[FRONT].top = bottomheight; opentopslope = *rover->b_slope; opentoppic = *rover->bottompic; - openceilingrover = rover; + open[FRONT].ceilingrover = rover; } else if (bottomheight < highceiling) highceiling = bottomheight; @@ -777,11 +832,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 < delta2 && (rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) // thing is above FOF { - if (topheight > openbottom) { - openbottom = topheight; + if (topheight > open[FRONT].bottom) { + open[FRONT].bottom = topheight; openbottomslope = *rover->t_slope; openbottompic = *rover->toppic; - openfloorrover = rover; + open[FRONT].floorrover = rover; } else if (topheight > lowfloor) lowfloor = topheight; @@ -809,11 +864,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 >= delta2 && (rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) // thing is below FOF { - if (bottomheight < opentop) { - opentop = bottomheight; + if (bottomheight < open[BACK].top) { + open[BACK].top = bottomheight; opentopslope = *rover->b_slope; opentoppic = *rover->bottompic; - openceilingrover = rover; + open[BACK].ceilingrover = rover; } else if (bottomheight < highceiling) highceiling = bottomheight; @@ -821,16 +876,54 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 < delta2 && (rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) // thing is above FOF { - if (topheight > openbottom) { - openbottom = topheight; + if (topheight > open[BACK].bottom) { + open[BACK].bottom = topheight; openbottomslope = *rover->t_slope; openbottompic = *rover->toppic; - 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 936094498..29e7d4de9 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -61,6 +61,10 @@ 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);