diff --git a/src/p_local.h b/src/p_local.h index 9644e7a24..062289f93 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -308,21 +308,19 @@ void P_PushableThinker(mobj_t *mobj); void P_SceneryThinker(mobj_t *mobj); -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); -fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); -#define P_GetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(mobj, sector, NULL, x, y, line, false, false) -#define P_GetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(mobj, sector, NULL, x, y, line, true, false) -#define P_GetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(mobj, sectors + fof->secnum, sector, x, y, line, false, false) -#define P_GetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(mobj, sectors + fof->secnum, sector, x, y, line, true, false) -#define P_GetSpecialBottomZ(mobj, src, bound) P_MobjFloorZ(mobj, src, bound, mobj->x, mobj->y, NULL, src != bound, true) -#define P_GetSpecialTopZ(mobj, src, bound) P_MobjCeilingZ(mobj, src, bound, mobj->x, mobj->y, NULL, src == bound, true) +fixed_t P_MobjFloorZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect); +fixed_t P_MobjCeilingZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect); +#define P_GetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(sector, NULL, x, y, mobj->radius, line, false, false) +#define P_GetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(sector, NULL, x, y, mobj->radius, line, true, false) +#define P_GetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, false, false) +#define P_GetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, true, false) +#define P_GetSpecialBottomZ(mobj, src, bound) P_MobjFloorZ(src, bound, mobj->x, mobj->y, mobj->radius, NULL, src != bound, true) +#define P_GetSpecialTopZ(mobj, src, bound) P_MobjCeilingZ(src, bound, mobj->x, mobj->y, mobj->radius, NULL, src == bound, true) -fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); -fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); -#define P_CameraGetFloorZ(mobj, sector, x, y, line) P_CameraFloorZ(mobj, sector, NULL, x, y, line, false, false) -#define P_CameraGetCeilingZ(mobj, sector, x, y, line) P_CameraCeilingZ(mobj, sector, NULL, x, y, line, true, false) -#define P_CameraGetFOFTopZ(mobj, sector, fof, x, y, line) P_CameraCeilingZ(mobj, sectors + fof->secnum, sector, x, y, line, false, false) -#define P_CameraGetFOFBottomZ(mobj, sector, fof, x, y, line) P_CameraFloorZ(mobj, sectors + fof->secnum, sector, x, y, line, true, false) +#define P_CameraGetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(sector, NULL, x, y, mobj->radius, line, false, false) +#define P_CameraGetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(sector, NULL, x, y, mobj->radius, line, true, false) +#define P_CameraGetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, false, false) +#define P_CameraGetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, true, false) boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover); boolean P_CheckDeathPitCollide(mobj_t *mo); diff --git a/src/p_mobj.c b/src/p_mobj.c index 16ca0c634..d4a1fa981 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1092,9 +1092,8 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line, ); } -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) +fixed_t P_MobjFloorZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect) { - I_Assert(mobj != NULL); I_Assert(sector != NULL); if (sector->f_slope) { @@ -1103,14 +1102,14 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t // Get the corner of the object that should be the highest on the slope if (slope->d.x < 0) - testx = mobj->radius; + testx = radius; else - testx = -mobj->radius; + testx = -radius; if (slope->d.y < 0) - testy = mobj->radius; + testy = radius; else - testy = -mobj->radius; + testy = -radius; if ((slope->zdelta > 0) ^ !!(lowest)) { testx = -testx; @@ -1136,10 +1135,10 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t else finalheight = INT32_MIN; - bbox[BOXLEFT] = x-mobj->radius; - bbox[BOXRIGHT] = x+mobj->radius; - bbox[BOXTOP] = y+mobj->radius; - bbox[BOXBOTTOM] = y-mobj->radius; + bbox[BOXLEFT] = x-radius; + bbox[BOXRIGHT] = x+radius; + bbox[BOXTOP] = y+radius; + bbox[BOXBOTTOM] = y-radius; for (i = 0; i < boundsec->linecount; i++) { ld = boundsec->lines[i]; @@ -1151,9 +1150,9 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t continue; if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); + finalheight = min(finalheight, HighestOnLine(radius, x, y, ld, slope, true)); else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); + finalheight = max(finalheight, HighestOnLine(radius, x, y, ld, slope, false)); } return finalheight; @@ -1164,14 +1163,13 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t if (line == NULL) return P_GetSlopeZAt(slope, x, y); - return HighestOnLine(mobj->radius, x, y, line, slope, lowest); + return HighestOnLine(radius, x, y, line, slope, lowest); } else // Well, that makes it easy. Just get the floor height return sector->floorheight; } -fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) +fixed_t P_MobjCeilingZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect) { - I_Assert(mobj != NULL); I_Assert(sector != NULL); if (sector->c_slope) { @@ -1180,14 +1178,14 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed // Get the corner of the object that should be the highest on the slope if (slope->d.x < 0) - testx = mobj->radius; + testx = radius; else - testx = -mobj->radius; + testx = -radius; if (slope->d.y < 0) - testy = mobj->radius; + testy = radius; else - testy = -mobj->radius; + testy = -radius; if ((slope->zdelta > 0) ^ !!(lowest)) { testx = -testx; @@ -1213,10 +1211,10 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed else finalheight = INT32_MIN; - bbox[BOXLEFT] = x-mobj->radius; - bbox[BOXRIGHT] = x+mobj->radius; - bbox[BOXTOP] = y+mobj->radius; - bbox[BOXBOTTOM] = y-mobj->radius; + bbox[BOXLEFT] = x-radius; + bbox[BOXRIGHT] = x+radius; + bbox[BOXTOP] = y+radius; + bbox[BOXBOTTOM] = y-radius; for (i = 0; i < boundsec->linecount; i++) { ld = boundsec->lines[i]; @@ -1228,9 +1226,9 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed continue; if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); + finalheight = min(finalheight, HighestOnLine(radius, x, y, ld, slope, true)); else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); + finalheight = max(finalheight, HighestOnLine(radius, x, y, ld, slope, false)); } return finalheight; @@ -1241,165 +1239,11 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed if (line == NULL) return P_GetSlopeZAt(slope, x, y); - return HighestOnLine(mobj->radius, x, y, line, slope, lowest); + return HighestOnLine(radius, x, y, line, slope, lowest); } else // Well, that makes it easy. Just get the ceiling height return sector->ceilingheight; } -// Now do the same as all above, but for cameras because apparently cameras are special? -fixed_t P_CameraFloorZ(camera_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; - 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; - - if ((slope->zdelta > 0) ^ !!(lowest)) { - testx = -testx; - testy = -testy; - } - - 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_IsPointInSector(boundsec ? boundsec : sector, testx, testy)) - return P_GetSlopeZAt(slope, testx, testy); - - // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point - if (perfect) { - size_t i; - line_t *ld; - fixed_t bbox[4]; - fixed_t finalheight; - - if (lowest) - finalheight = INT32_MAX; - else - finalheight = INT32_MIN; - - bbox[BOXLEFT] = x-mobj->radius; - bbox[BOXRIGHT] = x+mobj->radius; - bbox[BOXTOP] = y+mobj->radius; - bbox[BOXBOTTOM] = y-mobj->radius; - for (i = 0; i < boundsec->linecount; i++) { - ld = boundsec->lines[i]; - - if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) - continue; - - if (P_BoxOnLineSide(bbox, ld) != -1) - continue; - - if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); - else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); - } - - return finalheight; - } - - // If we're just testing for base sector location (no collision line), just go for the center's spot... - // It'll get fixed when we test for collision anyway, and the final result can't be lower than this - if (line == NULL) - return P_GetSlopeZAt(slope, x, y); - - return HighestOnLine(mobj->radius, x, y, line, slope, lowest); - } else // Well, that makes it easy. Just get the floor height - return sector->floorheight; -} - -fixed_t P_CameraCeilingZ(camera_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->c_slope) { - fixed_t testx, testy; - 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; - - if ((slope->zdelta > 0) ^ !!(lowest)) { - testx = -testx; - testy = -testy; - } - - 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_IsPointInSector(boundsec ? boundsec : sector, testx, testy)) - return P_GetSlopeZAt(slope, testx, testy); - - // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point - if (perfect) { - size_t i; - line_t *ld; - fixed_t bbox[4]; - fixed_t finalheight; - - if (lowest) - finalheight = INT32_MAX; - else - finalheight = INT32_MIN; - - bbox[BOXLEFT] = x-mobj->radius; - bbox[BOXRIGHT] = x+mobj->radius; - bbox[BOXTOP] = y+mobj->radius; - bbox[BOXBOTTOM] = y-mobj->radius; - for (i = 0; i < boundsec->linecount; i++) { - ld = boundsec->lines[i]; - - if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) - continue; - - if (P_BoxOnLineSide(bbox, ld) != -1) - continue; - - if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); - else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); - } - - return finalheight; - } - - // If we're just testing for base sector location (no collision line), just go for the center's spot... - // It'll get fixed when we test for collision anyway, and the final result can't be lower than this - if (line == NULL) - return P_GetSlopeZAt(slope, x, y); - - return HighestOnLine(mobj->radius, x, y, line, slope, lowest); - } else // Well, that makes it easy. Just get the ceiling height - return sector->ceilingheight; -} static void P_PlayerFlip(mobj_t *mo) { if (!mo->player) @@ -2329,8 +2173,8 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) if (mo->player && mo->player->pflags & PF_GODMODE) return false; - fixed_t sectorFloor = P_GetSectorFloorZAt(mo->subsector->sector, mo->x, mo->y); - fixed_t sectorCeiling = P_GetSectorCeilingZAt(mo->subsector->sector, mo->x, mo->y); + fixed_t sectorFloor = P_MobjFloorZ(mo->subsector->sector, mo->subsector->sector, mo->x, mo->y, mo->radius, NULL, false, true); + fixed_t sectorCeiling = P_MobjCeilingZ(mo->subsector->sector, mo->subsector->sector, mo->x, mo->y, mo->radius, NULL, true, true); if (((mo->z <= sectorFloor && ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_FLOOR))