diff --git a/src/p_map.c b/src/p_map.c index e0d73721ddb7eb4907fe4b6d1f3230883f6c8c2b..d6514f8fc1925916d5c751b411c149c32bc40cdd 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1921,7 +1921,7 @@ static boolean PIT_CheckLine(line_t *ld) || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) return true; - if (P_BoxOnLineSide(tmbbox, ld) != -1) + if (P_CircleOnLineSide(tmx, tmy, tmthing->radius, ld) != -1) return true; if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag. @@ -1933,13 +1933,6 @@ static boolean PIT_CheckLine(line_t *ld) == P_PointOnLineSide(tmx + cosradius, tmy + sinradius, ld)) return true; // the line doesn't cross between collider's start or end } - else - { - vertex_t closestpoint; - P_ClosestPointOnLine(tmthing->x, tmthing->y, ld, &closestpoint); - if (abs(R_PointToDist2(closestpoint.x, closestpoint.y, tmthing->x, tmthing->y)) >= tmthing->radius) - return true; // close enough for corners of square bounding boxes to touch, but not close enough for cylindrical collision - } // A line has been hit @@ -3223,13 +3216,26 @@ isblocking: // // PTR_SlideTraverse // -static boolean PTR_SlideTraverse(intercept_t *in) +static boolean PTR_SlideTraverse(line_t *li) { - line_t *li; + fixed_t mmomx, mmomy, x, y; + // Kludgy redo of previous work, should optimize later + if (slidemo->player) + { + mmomx = slidemo->player->rmomx = slidemo->momx - slidemo->player->cmomx; + mmomy = slidemo->player->rmomy = slidemo->momy - slidemo->player->cmomy; + } + else + { + mmomx = slidemo->momx; + mmomy = slidemo->momy; + } - I_Assert(in->isaline); + x = slidemo->x + mmomx; + y = slidemo->y + mmomy; - li = in->d.line; +// if (P_CircleOnLineSide(x, y, slidemo->radius, li) != -1) +// return true; // Not inside the line, non-blocking // one-sided linedefs are always solid to sliding movement. // one-sided linedef @@ -3273,15 +3279,20 @@ isblocking: P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector); } - if (in->frac < bestslidefrac) + vertex_t closestpoint; + P_ClosestPointOnLineWithinLine(x, y, li, &closestpoint); + fixed_t dist = abs(R_PointToDist2(closestpoint.x, closestpoint.y, x, y)); + + + if (dist < bestslidefrac) { secondslidefrac = bestslidefrac; secondslideline = bestslideline; - bestslidefrac = in->frac; + bestslidefrac = dist; bestslideline = li; } - return false; // stop + return true; } // @@ -3394,7 +3405,12 @@ stairstep: // void P_SlideMove(mobj_t *mo, boolean forceslide) { - fixed_t leadx, leady, trailx, traily, newx, newy; + fixed_t leadx, leady, newx, newy; + fixed_t leftx, lefty, lefttracerx, lefttracery; + fixed_t rightx, righty, righttracerx, righttracery; + fixed_t mmomx, mmomy; + fixed_t maxslidefrac; + angle_t momang; INT16 hitcount = 0; boolean success = false; @@ -3437,37 +3453,21 @@ retry: if (++hitcount == 3) goto stairstep; // don't loop forever - // trace along the three leading corners - if (mo->momx > 0) + if (mo->player) { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; + mmomx = mo->player->rmomx = mo->momx - mo->player->cmomx; + mmomy = mo->player->rmomy = mo->momy - mo->player->cmomy; } else { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; + mmomx = mo->momx; + mmomy = mo->momy; } - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } + maxslidefrac = mo->radius + FixedHypot(mmomx, mmomy); + bestslidefrac = maxslidefrac; - bestslidefrac = FRACUNIT+1; - - P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(trailx, leady, trailx + mo->momx, leady + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); + P_RadiusLinesCheck(mo->radius, mo->x + mmomx, mo->y + mmomy, PTR_SlideTraverse); // Some walls are bouncy even if you're not if (!forceslide && bestslideline && !(bestslideline->flags & ML_BOUNCY)) // SRB2kart - All walls are bouncy unless specified otherwise @@ -3477,7 +3477,7 @@ retry: } // move up to the wall - if (bestslidefrac == FRACUNIT+1) + if (bestslidefrac == maxslidefrac) { // the move must have hit the middle, so stairstep stairstep: @@ -3562,10 +3562,13 @@ stairstep: void P_BouncePlayerMove(mobj_t *mo) { + angle_t momang; fixed_t leadx, leady; - fixed_t trailx, traily; + fixed_t leftx, lefty, lefttracerx, lefttracery; + fixed_t rightx, righty, righttracerx, righttracery; fixed_t mmomx = 0, mmomy = 0; fixed_t oldmomx = mo->momx, oldmomy = mo->momy; + fixed_t maxslidefrac; if (!mo->player) return; @@ -3585,38 +3588,14 @@ void P_BouncePlayerMove(mobj_t *mo) mo->player->kartstuff[k_driftcharge] = 0; mo->player->kartstuff[k_pogospring] = 0; - // trace along the three leading corners - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; - } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } - - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } - - bestslidefrac = FRACUNIT + 1; + maxslidefrac = mo->radius + FixedHypot(mmomx, mmomy); + bestslidefrac = maxslidefrac; - P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse); + P_RadiusLinesCheck(mo->radius, mo->x + mmomx, mo->y + mmomy, PTR_SlideTraverse); // Now continue along the wall. // First calculate remainder. - bestslidefrac = FRACUNIT - bestslidefrac; + bestslidefrac = maxslidefrac - bestslidefrac; if (bestslidefrac > FRACUNIT) bestslidefrac = FRACUNIT; @@ -3671,6 +3650,7 @@ void P_BounceMove(mobj_t *mo) fixed_t newx, newy; INT32 hitcount; fixed_t mmomx = 0, mmomy = 0; + fixed_t maxslidefrac; if (mo->player) { @@ -3694,37 +3674,12 @@ retry: mmomx = mo->momx; mmomy = mo->momy; - // trace along the three leading corners - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; - } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } - - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } - - bestslidefrac = FRACUNIT + 1; - - P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse); + maxslidefrac = mo->radius + FixedHypot(mmomx, mmomy); + bestslidefrac = maxslidefrac; + P_RadiusLinesCheck(mo->radius, mo->x + mmomx, mo->y + mmomy, PTR_SlideTraverse); // move up to the wall - if (bestslidefrac == FRACUNIT + 1) + if (bestslidefrac == maxslidefrac) { // the move must have hit the middle, so bounce straight back bounceback: @@ -4405,7 +4360,7 @@ static inline boolean PIT_GetSectors(line_t *ld) tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) return true; - if (P_BoxOnLineSide(tmbbox, ld) != -1) + if (P_CircleOnLineSide(tmx, tmy, tmthing->radius, ld) != -1) return true; if (ld->polyobj) // line belongs to a polyobject, don't add it @@ -4432,6 +4387,7 @@ static inline boolean PIT_GetSectors(line_t *ld) } // Tails 08-25-2002 +// Precipitation can stay square for hitboxes, because I would normally use tmx and tmy for P_CircleOnLineSide, but those don't seem to be set for tmprecipthing static inline boolean PIT_GetPrecipSectors(line_t *ld) { if (preciptmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || @@ -4440,7 +4396,7 @@ static inline boolean PIT_GetPrecipSectors(line_t *ld) preciptmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) return true; - if (P_BoxOnLineSide(preciptmbbox, ld) != -1) + if (P_CircleOnLineSide(tmx, tmy, tmprecipthing->radius, ld) != -1) return true; if (ld->polyobj) // line belongs to a polyobject, don't add it @@ -4468,7 +4424,6 @@ static inline boolean PIT_GetPrecipSectors(line_t *ld) // P_CreateSecNodeList alters/creates the sector_list that shows what sectors // the object resides in. - void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y) { INT32 xl, xh, yl, yh, bx, by; @@ -4558,6 +4513,7 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y) INT32 xl, xh, yl, yh, bx, by; mprecipsecnode_t *node = precipsector_list; precipmobj_t *saved_tmthing = tmprecipthing; /* cph - see comment at func end */ + fixed_t saved_tmx = tmx, saved_tmy = tmy; /* ditto */ // First, clear out the existing m_thing fields. As each node is // added or verified as needed, m_thing will be set properly. When @@ -4572,6 +4528,9 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y) tmprecipthing = thing; + tmx = x; + tmy = y; + preciptmbbox[BOXTOP] = y + 2*FRACUNIT; preciptmbbox[BOXBOTTOM] = y - 2*FRACUNIT; preciptmbbox[BOXRIGHT] = x + 2*FRACUNIT; @@ -4617,6 +4576,7 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y) * Fun. We restore its previous value unless we're in a Boom/MBF demo. */ tmprecipthing = saved_tmthing; + tmx = saved_tmx, tmy = saved_tmy; } /* cphipps 2004/08/30 - diff --git a/src/p_maputl.c b/src/p_maputl.c index 17df33a917256bdff71cb3e9dea03b4739bf22a0..826d02cf30296965d13c90694cc3db891d635490 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -26,6 +26,7 @@ // // P_ClosestPointOnLine // Finds the closest point on a given line to the supplied point +// Considers line length to be infinite, and can return results outside of the actual line // void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result) { @@ -65,6 +66,27 @@ void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result) return; } +// +// P_ClosestPointOnLineWithinLine +// Finds the closest point on a given line to the supplied point +// Like P_ClosestPointOnLine, except the result is constrained within the actual line +// +void P_ClosestPointOnLineWithinLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result) +{ + P_ClosestPointOnLine(x, y, line, result); + + // Determine max and min bounds of the line + fixed_t maxx = max(line->v1->x, line->v2->x); + fixed_t maxy = max(line->v1->y, line->v2->y); + fixed_t minx = min(line->v1->x, line->v2->x); + fixed_t miny = min(line->v1->y, line->v2->y); + + // Constrain result to line by ensuring x and y don't go beyond the maximums + result->x = min(max(result->x, minx),maxx); + result->y = min(max(result->y, miny),maxy); + return; +} + // // P_ClosestPointOnLine3D // Finds the closest point on a given line to the supplied point IN 3D!!! @@ -216,6 +238,23 @@ INT32 P_BoxOnLineSide(fixed_t *tmbox, line_t *ld) return -1; } +// +// P_CircleOnLineSide +// Considers the line to be infinite +// Returns side 0 or 1, -1 if circle crosses the line. +// Man, circles are easier than boxes +// +INT32 P_CircleOnLineSide(fixed_t x, fixed_t y, fixed_t radius, line_t *ld) +{ + vertex_t closestpoint; + P_ClosestPointOnLine(x, y, ld, &closestpoint); + + if (abs(R_PointToDist2(closestpoint.x, closestpoint.y, x, y)) < radius) + return -1; // Inside circle + else + return P_PointOnLineSide(x, y, ld); // Not inside so just return this instead +} + // // P_PointOnDivlineSide // Returns 0 or 1. @@ -1340,7 +1379,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, } } // Go through the sorted list - return P_TraverseIntercepts(trav, FRACUNIT); + return P_TraverseIntercepts(trav, 256*FRACUNIT); } @@ -1353,13 +1392,12 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, // returns FALSE if the loop exited early after a false return // value from your user function -//abandoned, maybe I'll need it someday.. -/* boolean P_RadiusLinesCheck(fixed_t radius, fixed_t x, fixed_t y, boolean (*func)(line_t *)) { INT32 xl, xh, yl, yh; INT32 bx, by; + boolean blockval = true; tmbbox[BOXTOP] = y + radius; tmbbox[BOXBOTTOM] = y - radius; @@ -1372,10 +1410,14 @@ boolean P_RadiusLinesCheck(fixed_t radius, fixed_t x, fixed_t y, yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + BMBOUNDFIX(xl, xh, yl, yh); + + validcount++; + for (bx = xl; bx <= xh; bx++) for (by = yl; by <= yh; by++) if (!P_BlockLinesIterator(bx, by, func)) - return false; - return true; -} -*/ + blockval = false; + + return blockval; +} \ No newline at end of file diff --git a/src/p_maputl.h b/src/p_maputl.h index ec4a4aa3357d739f7e19957fe3246b27ee92c283..b1791cba4e0a461dfd0ec4d1ce9d0f568296cf63 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -43,12 +43,14 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, #define P_AproxDistance(dx, dy) FixedHypot(dx, dy) void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result); +void P_ClosestPointOnLineWithinLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result); void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result); INT32 P_PointOnLineSide(fixed_t x, fixed_t y, line_t *line); void P_MakeDivline(line_t *li, divline_t *dl); void P_CameraLineOpening(line_t *plinedef); fixed_t P_InterceptVector(divline_t *v2, divline_t *v1); INT32 P_BoxOnLineSide(fixed_t *tmbox, line_t *ld); +INT32 P_CircleOnLineSide(fixed_t x, fixed_t y, fixed_t radius, line_t *ld); void P_UnsetPrecipThingPosition(precipmobj_t *thing); void P_SetPrecipitationThingPosition(precipmobj_t *thing); void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y); @@ -72,6 +74,6 @@ extern fixed_t tmbbox[4]; // p_map.c // call your user function for each line of the blockmap in the // bbox defined by the radius -//boolean P_RadiusLinesCheck(fixed_t radius, fixed_t x, fixed_t y, -// boolean (*func)(line_t *)); +boolean P_RadiusLinesCheck(fixed_t radius, fixed_t x, fixed_t y, + boolean (*func)(line_t *)); #endif // __P_MAPUTL__ diff --git a/src/p_mobj.c b/src/p_mobj.c index 7978d0f3c90b0814156b3dc62edef29509db28d6..7f895d4066f1e321f61a025f5bfc264c4298a511 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -659,136 +659,66 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover) return true; } -// P_GetFloorZ (and its ceiling counterpart) -// Gets the floor height (or ceiling height) of the mobj's contact point in sector, assuming object's center if moved to [x, y] -// If line is supplied, it's a divider line on the sector. Set it to NULL if you're not checking for collision with a line -// Supply boundsec ONLY when checking for specials! It should be the "in-level" sector, and sector the control sector (if separate). -// If set, then this function will iterate through boundsec's linedefs to find the highest contact point on the slope. Non-special-checking -// usage will handle that later. static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line, pslope_t *slope, boolean actuallylowest) { // Alright, so we're sitting on a line that contains our slope sector, and need to figure out the highest point we're touching... - // The solution is simple! Get the line's vertices, and pull each one in along its line until it touches the object's bounding box - // (assuming it isn't already inside), then test each point's slope Z and return the higher of the two. - vertex_t v1, v2; - v1.x = line->v1->x; - v1.y = line->v1->y; - v2.x = line->v2->x; - v2.y = line->v2->y; - - /*CONS_Printf("BEFORE: v1 = %f %f %f\n", - FIXED_TO_FLOAT(v1.x), - FIXED_TO_FLOAT(v1.y), - FIXED_TO_FLOAT(P_GetZAt(slope, v1.x, v1.y)) - ); - CONS_Printf(" v2 = %f %f %f\n", - FIXED_TO_FLOAT(v2.x), - FIXED_TO_FLOAT(v2.y), - FIXED_TO_FLOAT(P_GetZAt(slope, v2.x, v2.y)) - );*/ - - if (abs(v1.x-x) > radius) { - // v1's x is out of range, so rein it in - fixed_t diff = abs(v1.x-x) - radius; - - if (v1.x < x) { // Moving right - v1.x += diff; - v1.y += FixedMul(diff, FixedDiv(line->dy, line->dx)); - } else { // Moving left - v1.x -= diff; - v1.y -= FixedMul(diff, FixedDiv(line->dy, line->dx)); - } - } - - if (abs(v1.y-y) > radius) { - // v1's y is out of range, so rein it in - fixed_t diff = abs(v1.y-y) - radius; - - if (v1.y < y) { // Moving up - v1.y += diff; - v1.x += FixedMul(diff, FixedDiv(line->dx, line->dy)); - } else { // Moving down - v1.y -= diff; - v1.x -= FixedMul(diff, FixedDiv(line->dx, line->dy)); - } - } - - if (abs(v2.x-x) > radius) { - // v1's x is out of range, so rein it in - fixed_t diff = abs(v2.x-x) - radius; - - if (v2.x < x) { // Moving right - v2.x += diff; - v2.y += FixedMul(diff, FixedDiv(line->dy, line->dx)); - } else { // Moving left - v2.x -= diff; - v2.y -= FixedMul(diff, FixedDiv(line->dy, line->dx)); - } - } - - if (abs(v2.y-y) > radius) { - // v2's y is out of range, so rein it in - fixed_t diff = abs(v2.y-y) - radius; - - if (v2.y < y) { // Moving up - v2.y += diff; - v2.x += FixedMul(diff, FixedDiv(line->dx, line->dy)); - } else { // Moving down - v2.y -= diff; - v2.x -= FixedMul(diff, FixedDiv(line->dx, line->dy)); - } - } - - /*CONS_Printf("AFTER: v1 = %f %f %f\n", - FIXED_TO_FLOAT(v1.x), - FIXED_TO_FLOAT(v1.y), - FIXED_TO_FLOAT(P_GetZAt(slope, v1.x, v1.y)) - ); - CONS_Printf(" v2 = %f %f %f\n", - FIXED_TO_FLOAT(v2.x), - FIXED_TO_FLOAT(v2.y), - FIXED_TO_FLOAT(P_GetZAt(slope, v2.x, v2.y)) - );*/ + // https://stackoverflow.com/questions/25203613/find-intersection-of-circle-and-line because I can't be arsed to re-learn linear algebra + + vertex_t closestvertex; + vector2_t n, closestpoint, offset, i1, i2; + fixed_t dist, distsquared, radiussquared; + n.x = line->dx; + n.y = line->dy; + FV2_Normalize(&n); // fixed it + P_ClosestPointOnLine(x, y, line, &closestvertex); + closestpoint.x = closestvertex.x; + closestpoint.y = closestvertex.y; + dist = FixedHypot(x - closestpoint.x, y - closestpoint.y); + distsquared = FixedMul(dist, dist); + radiussquared = FixedMul(radius, radius); + offset = *FV2_Mul(&n, FixedSqrt(radiussquared - distsquared)); + i1 = *FV2_Add(&closestpoint, &offset); + i2 = *FV2_Sub(&closestpoint, &offset); // Return the higher of the two points if (actuallylowest) return min( - P_GetZAt(slope, v1.x, v1.y), - P_GetZAt(slope, v2.x, v2.y) + P_GetZAt(slope, i1.x, i1.y), + P_GetZAt(slope, i2.x, i2.y) ); else return max( - P_GetZAt(slope, v1.x, v1.y), - P_GetZAt(slope, v2.x, v2.y) + P_GetZAt(slope, i1.x, i1.y), + P_GetZAt(slope, i2.x, i2.y) ); } +// P_GetFloorZ (and its ceiling counterpart) +// Gets the floor height (or ceiling height) of the mobj's contact point in sector, assuming object's center if moved to [x, y] +// If line is supplied, it's a divider line on the sector. Set it to NULL if you're not checking for collision with a line +// Supply boundsec ONLY when checking for specials! It should be the "in-level" sector, and sector the control sector (if separate). +// If set, then this function will iterate through boundsec's linedefs to find the highest contact point on the slope. Non-special-checking +// usage will handle that later. fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) { I_Assert(mobj != NULL); I_Assert(sector != NULL); if (sector->f_slope) { - fixed_t testx, testy; + fixed_t testx = x; + fixed_t testy = y; + angle_t angleuphill; pslope_t *slope = sector->f_slope; - // Get the corner of the object that should be the highest on the slope - if (slope->d.x < 0) - testx = mobj->radius; - else - testx = -mobj->radius; - - if (slope->d.y < 0) - testy = mobj->radius; - else - testy = -mobj->radius; - + angleuphill = (INT32)slope->zangle >= 0 ? slope->xydirection : slope->xydirection+ANGLE_180; + if ((slope->zdelta > 0) ^ !!(lowest)) { - testx = -testx; - testy = -testy; + testx -= P_ReturnThrustX(mobj, angleuphill, mobj->radius); + testy -= P_ReturnThrustY(mobj, angleuphill, mobj->radius); + } + else { + testx += P_ReturnThrustX(mobj, angleuphill, mobj->radius); + testy += P_ReturnThrustY(mobj, angleuphill, mobj->radius); } - - testx += x; - testy += y; // If the highest point is in the sector, then we have it easy! Just get the Z at that point if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector)) @@ -806,6 +736,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t else finalheight = INT32_MIN; + //bbox calc is still probably faster/less calculations than P_CircleOnLineSide, so we leave it for performance bbox[BOXLEFT] = x-mobj->radius; bbox[BOXRIGHT] = x+mobj->radius; bbox[BOXTOP] = y+mobj->radius; @@ -817,7 +748,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t || bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) continue; - if (P_BoxOnLineSide(bbox, ld) != -1) + if (P_CircleOnLineSide(x, y, mobj->radius, ld) != -1) continue; if (lowest) @@ -834,6 +765,9 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t if (line == NULL) return P_GetZAt(slope, x, y); + if (mobj->player) { + CONS_Printf(""); + } return HighestOnLine(mobj->radius, x, y, line, slope, lowest); } else // Well, that makes it easy. Just get the floor height return sector->floorheight; @@ -844,27 +778,21 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed I_Assert(mobj != NULL); I_Assert(sector != NULL); if (sector->c_slope) { - fixed_t testx, testy; + fixed_t testx = x; + fixed_t testy = y; + angle_t angleuphill; pslope_t *slope = sector->c_slope; - // Get the corner of the object that should be the highest on the slope - if (slope->d.x < 0) - testx = mobj->radius; - else - testx = -mobj->radius; - - if (slope->d.y < 0) - testy = mobj->radius; - else - testy = -mobj->radius; + angleuphill = (INT32)slope->zangle >= 0 ? slope->xydirection : slope->xydirection+ANGLE_180; if ((slope->zdelta > 0) ^ !!(lowest)) { - testx = -testx; - testy = -testy; + testx -= P_ReturnThrustX(mobj, angleuphill, mobj->radius); + testy -= P_ReturnThrustY(mobj, angleuphill, mobj->radius); + } + else { + testx += P_ReturnThrustX(mobj, angleuphill, mobj->radius); + testy += P_ReturnThrustY(mobj, angleuphill, mobj->radius); } - - testx += x; - testy += y; // If the highest point is in the sector, then we have it easy! Just get the Z at that point if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector)) @@ -893,7 +821,7 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed || bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) continue; - if (P_BoxOnLineSide(bbox, ld) != -1) + if (P_CircleOnLineSide(x, y, mobj->radius, ld) != -1) continue; if (lowest) @@ -1525,6 +1453,26 @@ void P_XYMovement(mobj_t *mo) } } + //{ SRB2kart - Ballhogs + if (mo->type == MT_BALLHOG) + { + if (mo->health) + { + mo->health--; + if (mo->health == 0) + mo->destscale = 1; + } + else + { + if (mo->scale < mapobjectscale/16) + { + P_RemoveMobj(mo); + return; + } + } + } + //} + player = mo->player; //valid only if player avatar xmove = mo->momx; @@ -1559,25 +1507,6 @@ void P_XYMovement(mobj_t *mo) if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE) P_PushableCheckBustables(mo); - //{ SRB2kart - Ballhogs - if (mo->type == MT_BALLHOG) - { - if (mo->health) - { - mo->health--; - if (mo->health == 0) - mo->destscale = 1; - } - else - { - if (mo->scale < mapobjectscale/16) - { - P_RemoveMobj(mo); - return; - } - } - } - //} if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) && !(mo->eflags & MFE_SPRUNG)) { // blocked move @@ -1956,12 +1885,20 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp && !(rover->flags & FF_REVERSEPLATFORM) && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) // In reverse gravity, only clip for FOFs that are intangible from their bottom (the "top" you're falling through) if you're coming from above ("below" in your frame of reference) { + if (mo->player) + { + CONS_Printf(""); // debugger conditional + } mo->floorz = topheight; } if (bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) && !(rover->flags & FF_PLATFORM) && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below { + if (mo->player) + { + CONS_Printf(""); // debugger conditional + } mo->ceilingz = bottomheight; } } diff --git a/src/p_polyobj.c b/src/p_polyobj.c index fa98ad9a547dfed428020eeaba0e9da65af6ba23..fed8d46eca329205b74447636edff84dfd2b5689 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -177,17 +177,11 @@ boolean P_PointInsidePolyobj(polyobj_t *po, fixed_t x, fixed_t y) // boolean P_MobjTouchingPolyobj(polyobj_t *po, mobj_t *mo) { - fixed_t mbbox[4]; size_t i; - mbbox[BOXTOP] = mo->y + mo->radius; - mbbox[BOXBOTTOM] = mo->y - mo->radius; - mbbox[BOXRIGHT] = mo->x + mo->radius; - mbbox[BOXLEFT] = mo->x - mo->radius; - for (i = 0; i < po->numLines; i++) { - if (P_BoxOnLineSide(mbbox, po->lines[i]) == -1) + if (P_CircleOnLineSide(mo->x, mo->y, mo->radius, po->lines[i]) == -1) return true; } @@ -201,17 +195,11 @@ boolean P_MobjTouchingPolyobj(polyobj_t *po, mobj_t *mo) // boolean P_MobjInsidePolyobj(polyobj_t *po, mobj_t *mo) { - fixed_t mbbox[4]; size_t i; - mbbox[BOXTOP] = mo->y + mo->radius; - mbbox[BOXBOTTOM] = mo->y - mo->radius; - mbbox[BOXRIGHT] = mo->x + mo->radius; - mbbox[BOXLEFT] = mo->x - mo->radius; - for (i = 0; i < po->numLines; i++) { - if (P_BoxOnLineSide(mbbox, po->lines[i]) == 0) + if (P_CircleOnLineSide(mo->x, mo->y, mo->radius, po->lines[i]) == 0) return false; }