diff --git a/src/p_local.h b/src/p_local.h index 8eaf6b2b8..1ff20a9ac 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -167,7 +167,6 @@ extern fixed_t t_cam_dist[MAXSPLITSCREENPLAYERS], t_cam_height[MAXSPLITSCREENPLA void P_AddPlayerScore(player_t *player, UINT32 amount); void P_ResetCamera(player_t *player, camera_t *thiscam); boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); -void P_SlideCameraMove(camera_t *thiscam); void P_DemoCameraMovement(camera_t *cam, UINT8 num); void P_ToggleDemoCamera(UINT8 viewnum); boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled); diff --git a/src/p_map.c b/src/p_map.c index e0f7cb9eb..4571ab989 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3115,55 +3115,10 @@ static boolean P_ThingHeightClip(mobj_t *thing) // SLIDE MOVE // Allows the player to slide along any angled walls. // -static fixed_t bestslidefrac, secondslidefrac; static line_t *bestslideline; -static line_t *secondslideline; static mobj_t *slidemo; static fixed_t tmxmove, tmymove; -// -// P_HitCameraSlideLine -// -static void P_HitCameraSlideLine(line_t *ld, camera_t *thiscam) -{ - INT32 side; - angle_t lineangle, moveangle, deltaangle; - fixed_t movelen, newlen; - - if (ld->slopetype == ST_HORIZONTAL) - { - tmymove = 0; - return; - } - - if (ld->slopetype == ST_VERTICAL) - { - tmxmove = 0; - return; - } - - side = P_PointOnLineSide(thiscam->x, thiscam->y, ld); - lineangle = ld->angle; - - if (side == 1) - lineangle += ANGLE_180; - - moveangle = R_PointToAngle2(0, 0, tmxmove, tmymove); - deltaangle = moveangle-lineangle; - - if (deltaangle > ANGLE_180) - deltaangle += ANGLE_180; - - lineangle >>= ANGLETOFINESHIFT; - deltaangle >>= ANGLETOFINESHIFT; - - movelen = P_AproxDistance(tmxmove, tmymove); - newlen = FixedMul(movelen, FINECOSINE(deltaangle)); - - tmxmove = FixedMul(newlen, FINECOSINE(lineangle)); - tmymove = FixedMul(newlen, FINESINE(lineangle)); -} - // // P_HitSlideLine // Adjusts the xmove / ymove @@ -3271,57 +3226,6 @@ static void P_HitBounceLine(line_t *ld) deltaangle = R_PointToAngle2(0, 0, tmxmove, tmymove); } -// -// PTR_SlideCameraTraverse -// -static boolean PTR_SlideCameraTraverse(intercept_t *in) -{ - line_t *li; - opening_t open = {0}; - - I_Assert(in->isaline); - - li = in->d.line; - - // one-sided linedef - if (!li->backsector) - { - if (P_PointOnLineSide(mapcampointer->x, mapcampointer->y, li)) - return true; // don't hit the back side - goto isblocking; - } - - // set openrange, opentop, openbottom - P_CameraLineOpening(li, &open); - - if (open.range < mapcampointer->height) - goto isblocking; // doesn't fit - - if (open.ceiling - mapcampointer->z < mapcampointer->height) - goto isblocking; // mobj is too high - - if (open.floor - mapcampointer->z > 0) // We don't want to make the camera step up. - goto isblocking; // too big a step up - - // this line doesn't block movement - return true; - - // the line does block movement, - // see if it is closer than best so far -isblocking: - { - if (in->frac < bestslidefrac) - { - secondslidefrac = bestslidefrac; - secondslideline = bestslideline; - bestslidefrac = in->frac; - bestslideline = li; - } - } - - return false; // stop -} - /* static boolean PTR_LineIsBlocking(line_t *li) { @@ -3382,105 +3286,6 @@ static boolean PTR_SlideTraverse(intercept_t *in) } */ -// -// P_SlideCameraMove -// -// Tries to slide the camera along a wall. -// -void P_SlideCameraMove(camera_t *thiscam) -{ - fixed_t leadx, leady, trailx, traily, newx, newy; - INT32 hitcount = 0; - INT32 retval = 0; - - bestslideline = NULL; - -retry: - if (++hitcount == 3) - goto stairstep; // don't loop forever - - // trace along the three leading corners - if (thiscam->momx > 0) - { - leadx = thiscam->x + thiscam->radius; - trailx = thiscam->x - thiscam->radius; - } - else - { - leadx = thiscam->x - thiscam->radius; - trailx = thiscam->x + thiscam->radius; - } - - if (thiscam->momy > 0) - { - leady = thiscam->y + thiscam->radius; - traily = thiscam->y - thiscam->radius; - } - else - { - leady = thiscam->y - thiscam->radius; - traily = thiscam->y + thiscam->radius; - } - - bestslidefrac = FRACUNIT+1; - - mapcampointer = thiscam; - - P_PathTraverse(leadx, leady, leadx + thiscam->momx, leady + thiscam->momy, - PT_ADDLINES, PTR_SlideCameraTraverse); - P_PathTraverse(trailx, leady, trailx + thiscam->momx, leady + thiscam->momy, - PT_ADDLINES, PTR_SlideCameraTraverse); - P_PathTraverse(leadx, traily, leadx + thiscam->momx, traily + thiscam->momy, - PT_ADDLINES, PTR_SlideCameraTraverse); - - // move up to the wall - if (bestslidefrac == FRACUNIT+1) - { - retval = P_TryCameraMove(thiscam->x, thiscam->y + thiscam->momy, thiscam); - // the move must have hit the middle, so stairstep -stairstep: - if (!retval) // Allow things to drop off. - P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y, thiscam); - return; - } - - // fudge a bit to make sure it doesn't hit - bestslidefrac -= 0x800; - if (bestslidefrac > 0) - { - newx = FixedMul(thiscam->momx, bestslidefrac); - newy = FixedMul(thiscam->momy, bestslidefrac); - - retval = P_TryCameraMove(thiscam->x + newx, thiscam->y + newy, thiscam); - - if (!retval) - goto stairstep; - } - - // Now continue along the wall. - // First calculate remainder. - bestslidefrac = FRACUNIT - (bestslidefrac+0x800); - - if (bestslidefrac > FRACUNIT) - bestslidefrac = FRACUNIT; - - if (bestslidefrac <= 0) - return; - - tmxmove = FixedMul(thiscam->momx, bestslidefrac); - tmymove = FixedMul(thiscam->momy, bestslidefrac); - - P_HitCameraSlideLine(bestslideline, thiscam); // clip the moves - - thiscam->momx = tmxmove; - thiscam->momy = tmymove; - - retval = P_TryCameraMove(thiscam->x + tmxmove, thiscam->y + tmymove, thiscam); - - if (!retval) - goto retry; -} - static void P_CheckLavaWall(mobj_t *mo, sector_t *sec) { ffloor_t *rover; diff --git a/src/p_maputl.c b/src/p_maputl.c index 4df9de76c..bba3e9776 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -1736,10 +1736,6 @@ static boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac) boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, INT32 flags, traverser_t trav) { - fixed_t xt1, yt1, xt2, yt2; - fixed_t xstep, ystep, partialx, partialy, xintercept, yintercept; - INT32 mapx, mapy, mapxstep, mapystep, count; - validcount++; intercept_p = intercepts; @@ -1756,170 +1752,94 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, px1 -= bmaporgx; py1 -= bmaporgy; - xt1 = (unsigned)px1>>MAPBLOCKSHIFT; - yt1 = (unsigned)py1>>MAPBLOCKSHIFT; - px2 -= bmaporgx; py2 -= bmaporgy; - xt2 = (unsigned)px2>>MAPBLOCKSHIFT; - yt2 = (unsigned)py2>>MAPBLOCKSHIFT; - if (xt2 > xt1) + // blockmap traversal algorithm ported from antimony + int gridpos_x = (unsigned)px1 >> MAPBLOCKSHIFT; + int gridpos_y = (unsigned)py1 >> MAPBLOCKSHIFT; + if (flags & PT_ADDLINES) + if (!P_BlockLinesIterator(gridpos_x, gridpos_y, PIT_AddLineIntercepts)) + return false; // early out + if (flags & PT_ADDTHINGS) + if (!P_BlockThingsIterator(gridpos_x, gridpos_y, PIT_AddThingIntercepts)) + return false; // early out + + int endpos_x = (unsigned)px2 >> MAPBLOCKSHIFT; + int endpos_y = (unsigned)py2 >> MAPBLOCKSHIFT; + if (gridpos_x == endpos_x && gridpos_y == endpos_y) + return P_TraverseIntercepts(trav, FRACUNIT); + + fixed_t pos_x = px1; + fixed_t pos_y = py1; + fixed_t dist_x = px2 - px1; + fixed_t dist_y = py2 - py1; + int dir_x = dist_x < 0 ? -1 : 1; + int dir_y = dist_y < 0 ? -1 : 1; + fixed_t delta_x; + fixed_t delta_y; + // special cases for 0 to avoid crashes + if (dist_y == 0) { - mapxstep = 1; - partialx = FRACUNIT - ((px1>>MAPBTOFRAC) & FRACMASK); - ystep = FixedDiv(py2 - py1, abs(px2 - px1)); + delta_x = INT32_MAX; + delta_y = 0; } - else if (xt2 < xt1) + else if (dist_x == 0) { - mapxstep = -1; - partialx = (px1>>MAPBTOFRAC) & FRACMASK; - ystep = FixedDiv(py2 - py1, abs(px2 - px1)); + delta_x = 0; + delta_y = INT32_MAX; } else { - mapxstep = 0; - partialx = FRACUNIT; - ystep = 256*FRACUNIT; + delta_x = FixedDiv2(dist_x, abs(dist_y)); + delta_y = FixedDiv2(dist_y, abs(dist_x)); } - yintercept = (py1>>MAPBTOFRAC) + FixedMul(partialx, ystep); + while (gridpos_x >= 0 && gridpos_y >= 0 && gridpos_x < bmapwidth && gridpos_y < bmapheight) + { + fixed_t hitx_x; + if (dir_x > 0) + hitx_x = (gridpos_x+1) << MAPBLOCKSHIFT; + else + hitx_x = gridpos_x << MAPBLOCKSHIFT; - if (yt2 > yt1) - { - mapystep = 1; - partialy = FRACUNIT - ((py1>>MAPBTOFRAC) & FRACMASK); - xstep = FixedDiv(px2 - px1, abs(py2 - py1)); - } - else if (yt2 < yt1) - { - mapystep = -1; - partialy = (py1>>MAPBTOFRAC) & FRACMASK; - xstep = FixedDiv(px2 - px1, abs(py2 - py1)); - } - else - { - mapystep = 0; - partialy = FRACUNIT; - xstep = 256*FRACUNIT; - } - xintercept = (px1>>MAPBTOFRAC) + FixedMul(partialy, xstep); + fixed_t hity_y; + if (dir_y > 0) + hity_y = (gridpos_y+1) << MAPBLOCKSHIFT; + else + hity_y = gridpos_y << MAPBLOCKSHIFT; - // [RH] Fix for traces that pass only through blockmap corners. In that case, - // xintercept and yintercept can both be set ahead of mapx and mapy, so the - // for loop would never advance anywhere. - - if (abs(xstep) == FRACUNIT && abs(ystep) == FRACUNIT) - { - if (ystep < 0) + hitx_x -= pos_x; + hity_y -= pos_y; + fixed_t hitx_y = FixedMul(delta_y, abs(hitx_x)); + fixed_t hity_x = FixedMul(delta_x, abs(hity_y)); + if (FixedMul(hitx_x, hitx_x) + FixedMul(hitx_y, hitx_y) > FixedMul(hity_x, hity_x) + FixedMul(hity_y, hity_y)) { - partialx = FRACUNIT - partialx; + gridpos_y += dir_y; + pos_x += hity_x; + pos_y += hity_y; } - if (xstep < 0) + else { - partialy = FRACUNIT - partialy; + gridpos_x += dir_x; + pos_x += hitx_x; + pos_y += hitx_y; } - if (partialx == partialy) - { - xintercept = xt1 << FRACBITS; - yintercept = yt1 << FRACBITS; - } - } - // Step through map blocks. - // Count is present to prevent a round off error - // from skipping the break. - mapx = xt1; - mapy = yt1; - - for (count = 0; count < 100; count++) - { if (flags & PT_ADDLINES) - { - P_BlockLinesIterator(mapx, mapy, PIT_AddLineIntercepts); - } - + if (!P_BlockLinesIterator(gridpos_x, gridpos_y, PIT_AddLineIntercepts)) + return false; // early out if (flags & PT_ADDTHINGS) - { - P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts); - } - - // both coordinates reached the end, so end the traversing. - if ((mapxstep | mapystep) == 0) - { + if (!P_BlockThingsIterator(gridpos_x, gridpos_y, PIT_AddThingIntercepts)) + return false; // early out + if (gridpos_x == endpos_x && gridpos_y == endpos_y) break; - } - - // [RH] Handle corner cases properly instead of pretending they don't exist. - switch ( (((yintercept >> FRACBITS) == mapy) << 1) | ((xintercept >> FRACBITS) == mapx) ) - { - case 0: // neither xintercept nor yintercept match! - { - count = 100; // Stop traversing, because somebody screwed up. - break; - } - case 1: // xintercept matches - { - xintercept += xstep; - mapy += mapystep; - if (mapy == yt2) - { - mapystep = 0; - } - break; - } - case 2: // yintercept matches - { - yintercept += ystep; - mapx += mapxstep; - if (mapx == xt2) - { - mapxstep = 0; - } - break; - } - case 3: // xintercept and yintercept both match - { - // The trace is exiting a block through its corner. Not only does the block - // being entered need to be checked (which will happen when this loop - // continues), but the other two blocks adjacent to the corner also need to - // be checked. - if (flags & PT_ADDLINES) - { - P_BlockLinesIterator(mapx + mapxstep, mapy, PIT_AddLineIntercepts); - P_BlockLinesIterator(mapx, mapy + mapystep, PIT_AddLineIntercepts); - } - - if (flags & PT_ADDTHINGS) - { - P_BlockThingsIterator(mapx + mapxstep, mapy, PIT_AddThingIntercepts); - P_BlockThingsIterator(mapx, mapy + mapystep, PIT_AddThingIntercepts); - } - - xintercept += xstep; - yintercept += ystep; - - mapx += mapxstep; - mapy += mapystep; - - if (mapx == xt2) - { - mapxstep = 0; - } - if (mapy == yt2) - { - mapystep = 0; - } - break; - } - } } // Go through the sorted list return P_TraverseIntercepts(trav, FRACUNIT); } - // ========================================================================= // BLOCKMAP ITERATORS // ========================================================================= diff --git a/src/p_mobj.c b/src/p_mobj.c index 32cb9bc97..3cda3dcac 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3642,8 +3642,6 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled { fixed_t camspeed = P_AproxDistance(thiscam->momx, thiscam->momy); - P_SlideCameraMove(thiscam); - if (!resetcalled && P_AproxDistance(thiscam->momx, thiscam->momy) == camspeed) { P_ResetCamera(player, thiscam);