mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2025-02-05 07:51:13 +00:00
Add P_GetFloorZ and P_GetCeilingZ as boilerplate to facilitate better slope collision
I have not used this anywhere in the code yet.
This commit is contained in:
parent
0c477c685d
commit
58dd6d42af
2 changed files with 215 additions and 33 deletions
|
@ -232,6 +232,9 @@ boolean P_RailThinker(mobj_t *mobj);
|
||||||
void P_PushableThinker(mobj_t *mobj);
|
void P_PushableThinker(mobj_t *mobj);
|
||||||
void P_SceneryThinker(mobj_t *mobj);
|
void P_SceneryThinker(mobj_t *mobj);
|
||||||
|
|
||||||
|
fixed_t P_GetFloorZ(mobj_t *mobj, sector_t *sector, fixed_t x, fixed_t y, line_t *line);
|
||||||
|
fixed_t P_GetCeilingZ(mobj_t *mobj, sector_t *sector, fixed_t x, fixed_t y, line_t *line);
|
||||||
|
|
||||||
boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover);
|
boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover);
|
||||||
boolean P_CheckDeathPitCollide(mobj_t *mo);
|
boolean P_CheckDeathPitCollide(mobj_t *mo);
|
||||||
boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover);
|
boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover);
|
||||||
|
|
245
src/p_mobj.c
245
src/p_mobj.c
|
@ -722,52 +722,231 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fixed_t P_GetMobjZAtSecF(mobj_t *mobj, sector_t *sector) // SRB2CBTODO: This needs to be over all the code
|
// 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
|
||||||
|
fixed_t P_GetFloorZ(mobj_t *mobj, sector_t *sector, fixed_t x, fixed_t y, line_t *line) // SRB2CBTODO: This needs to be over all the code
|
||||||
{
|
{
|
||||||
I_Assert(mobj != NULL);
|
I_Assert(mobj != NULL);
|
||||||
|
I_Assert(sector != NULL);
|
||||||
#ifdef ESLOPE
|
#ifdef ESLOPE
|
||||||
if (sector->f_slope)
|
if (sector->f_slope) {
|
||||||
return P_GetZAt(sector->f_slope, mobj->x, mobj->y);
|
fixed_t testx, testy;
|
||||||
else
|
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) {
|
||||||
|
testx = -testx;
|
||||||
|
testx = -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_PointInSubsector(testx, testy)->sector == sector
|
||||||
|
// The following line is a hack to fix a bug where an object pops down on the frame its highest corner re-enters the sloped sector.
|
||||||
|
|| R_PointInSubsector(testx+mobj->momx, testy+mobj->momy)->sector == sector
|
||||||
|
)
|
||||||
|
return P_GetZAt(slope, testx, testy);
|
||||||
|
|
||||||
|
// 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_GetZAt(slope, x, y);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
if (abs(v1.x-x) > mobj->radius) {
|
||||||
|
// v1's x is out of range, so rein it in
|
||||||
|
fixed_t diff = abs(v1.x-x) - mobj->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) > mobj->radius) {
|
||||||
|
// v1's y is out of range, so rein it in
|
||||||
|
fixed_t diff = abs(v1.y-y) - mobj->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) > mobj->radius) {
|
||||||
|
// v1's x is out of range, so rein it in
|
||||||
|
fixed_t diff = abs(v2.x-x) - mobj->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) > mobj->radius) {
|
||||||
|
// v2's y is out of range, so rein it in
|
||||||
|
fixed_t diff = abs(v2.y-y) - mobj->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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the higher of the two points
|
||||||
|
return max(
|
||||||
|
P_GetZAt(slope, v1.x, v1.y),
|
||||||
|
P_GetZAt(slope, v2.x, v2.y)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else // Well, that makes it easy. Just get the floor height
|
||||||
#endif
|
#endif
|
||||||
return sector->floorheight;
|
return sector->floorheight;
|
||||||
}
|
}
|
||||||
|
|
||||||
fixed_t P_GetMobjZAtF(mobj_t *mobj) // SRB2CBTODO: This needs to be over all the code
|
fixed_t P_GetCeilingZ(mobj_t *mobj, sector_t *sector, fixed_t x, fixed_t y, line_t *line) // SRB2CBTODO: This needs to be over all the code
|
||||||
{
|
{
|
||||||
I_Assert(mobj != NULL);
|
I_Assert(mobj != NULL);
|
||||||
sector_t *sector;
|
I_Assert(sector != NULL);
|
||||||
sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
|
|
||||||
|
|
||||||
#ifdef ESLOPE
|
#ifdef ESLOPE
|
||||||
if (sector->f_slope)
|
if (sector->c_slope) {
|
||||||
return P_GetZAt(sector->f_slope, mobj->x, mobj->y);
|
fixed_t testx, testy;
|
||||||
else
|
pslope_t *slope = sector->c_slope;
|
||||||
#endif
|
|
||||||
return sector->floorheight;
|
|
||||||
}
|
|
||||||
|
|
||||||
fixed_t P_GetMobjZAtSecC(mobj_t *mobj, sector_t *sector) // SRB2CBTODO: This needs to be over all the code
|
// Get the corner of the object that should be the lowest on the slope
|
||||||
{
|
if (slope->d.x < 0)
|
||||||
I_Assert(mobj != NULL);
|
testx = mobj->radius;
|
||||||
#ifdef ESLOPE
|
else
|
||||||
if (sector->c_slope)
|
testx = -mobj->radius;
|
||||||
return P_GetZAt(sector->c_slope, mobj->x, mobj->y);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
return sector->ceilingheight;
|
|
||||||
}
|
|
||||||
|
|
||||||
fixed_t P_GetMobjZAtC(mobj_t *mobj) // SRB2CBTODO: This needs to be over all the code
|
if (slope->d.y < 0)
|
||||||
{
|
testy = mobj->radius;
|
||||||
I_Assert(mobj != NULL);
|
else
|
||||||
sector_t *sector;
|
testy = -mobj->radius;
|
||||||
sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
|
|
||||||
|
|
||||||
#ifdef ESLOPE
|
if (slope->zdelta < 0) {
|
||||||
if (sector->c_slope)
|
testx = -testx;
|
||||||
return P_GetZAt(sector->c_slope, mobj->x, mobj->y);
|
testx = -testy;
|
||||||
else
|
}
|
||||||
|
|
||||||
|
testx += x;
|
||||||
|
testy += y;
|
||||||
|
|
||||||
|
// If the lowest point is in the sector, then we have it easy! Just get the Z at that point
|
||||||
|
if (R_PointInSubsector(testx, testy)->sector == sector
|
||||||
|
// The following line is a hack to fix a bug where an object pops down on the frame its highest corner re-enters the sloped sector.
|
||||||
|
|| R_PointInSubsector(testx+mobj->momx, testy+mobj->momy)->sector == sector
|
||||||
|
)
|
||||||
|
return P_GetZAt(slope, testx, testy);
|
||||||
|
|
||||||
|
// 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 higher than this
|
||||||
|
if (line == NULL)
|
||||||
|
return P_GetZAt(slope, x, y);
|
||||||
|
|
||||||
|
// 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 lower 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;
|
||||||
|
|
||||||
|
if (abs(v1.x-x) > mobj->radius) {
|
||||||
|
// v1's x is out of range, so rein it in
|
||||||
|
fixed_t diff = abs(v1.x-x) - mobj->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) > mobj->radius) {
|
||||||
|
// v1's y is out of range, so rein it in
|
||||||
|
fixed_t diff = abs(v1.y-y) - mobj->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) > mobj->radius) {
|
||||||
|
// v1's x is out of range, so rein it in
|
||||||
|
fixed_t diff = abs(v2.x-x) - mobj->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) > mobj->radius) {
|
||||||
|
// v2's y is out of range, so rein it in
|
||||||
|
fixed_t diff = abs(v2.y-y) - mobj->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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the lower of the two points
|
||||||
|
return min(
|
||||||
|
P_GetZAt(slope, v1.x, v1.y),
|
||||||
|
P_GetZAt(slope, v2.x, v2.y)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else // Well, that makes it easy. Just get the ceiling height
|
||||||
#endif
|
#endif
|
||||||
return sector->ceilingheight;
|
return sector->ceilingheight;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue