From e67e225ff2f796ba8cb78c9bacc5c91f052d5271 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 19 May 2024 20:40:40 -0300 Subject: [PATCH 1/6] Improve slope physics on solid middle textures --- src/p_local.h | 1 + src/p_map.c | 27 ++++++++-- src/p_maputl.c | 5 ++ src/p_maputl.h | 1 + src/p_mobj.c | 31 ++++++++---- src/p_mobj.h | 4 +- src/p_saveg.c | 9 +++- src/p_slopes.c | 130 +++++++++++++++++++++++++++++++++++++++++++------ src/p_slopes.h | 10 +++- src/p_user.c | 6 +-- 10 files changed, 189 insertions(+), 35 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 249c3cd4b..6a4aa241c 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -399,6 +399,7 @@ extern camera_t *mapcampointer; extern fixed_t tmx; extern fixed_t tmy; extern pslope_t *tmfloorslope, *tmceilingslope; +extern line_t *tmfloorline, *tmceilingline; /* cphipps 2004/08/30 */ extern void P_MapStart(void); diff --git a/src/p_map.c b/src/p_map.c index f97ddfa3c..aeeeda056 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -55,6 +55,7 @@ mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) ffloor_t *tmfloorrover, *tmceilingrover; pslope_t *tmfloorslope, *tmceilingslope; +line_t *tmfloorline, *tmceilingline; // keep track of the line that lowers the ceiling, // so missiles don't explode against sky hack walls @@ -1760,6 +1761,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmfloorz = thing->z + thing->height; tmfloorrover = NULL; tmfloorslope = NULL; + tmfloorline = NULL; } return CHECKTHING_COLLIDE; } @@ -1779,6 +1781,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmfloorz = tmceilingz = topz; // block while in air tmceilingrover = NULL; tmceilingslope = NULL; + tmceilingline = NULL; tmfloorthing = thing; // needed for side collision collide = CHECKTHING_COLLIDE; @@ -1788,6 +1791,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmceilingz = topz; tmceilingrover = NULL; tmceilingslope = NULL; + tmceilingline = NULL; tmfloorthing = thing; // thing we may stand on collide = CHECKTHING_COLLIDE; @@ -1805,6 +1809,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmceilingz = thing->z; tmceilingrover = NULL; tmceilingslope = NULL; + tmceilingline = NULL; } return CHECKTHING_COLLIDE; } @@ -1824,6 +1829,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmfloorz = tmceilingz = topz; // block while in air tmfloorrover = NULL; tmfloorslope = NULL; + tmfloorline = NULL; tmfloorthing = thing; // needed for side collision collide = CHECKTHING_COLLIDE; @@ -1833,6 +1839,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmfloorz = topz; tmfloorrover = NULL; tmfloorslope = NULL; + tmfloorline = NULL; tmfloorthing = thing; // thing we may stand on collide = CHECKTHING_COLLIDE; @@ -2000,6 +2007,7 @@ static boolean PIT_CheckLine(line_t *ld) ceilingline = ld; tmceilingrover = openceilingrover; tmceilingslope = opentopslope; + tmceilingline = opentopline; } if (openbottom > tmfloorz) @@ -2007,6 +2015,7 @@ static boolean PIT_CheckLine(line_t *ld) tmfloorz = openbottom; tmfloorrover = openfloorrover; tmfloorslope = openbottomslope; + tmfloorline = openbottomline; } if (highceiling > tmdrpoffceilz) @@ -2057,6 +2066,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; tmfloorrover = NULL; tmceilingrover = NULL; + tmfloorline = NULL; + tmceilingline = NULL; tmfloorslope = newsubsec->sector->f_slope; tmceilingslope = newsubsec->sector->c_slope; @@ -2642,6 +2653,8 @@ boolean PIT_PushableMoved(mobj_t *thing) ffloor_t *oldceilrover = tmceilingrover; pslope_t *oldfslope = tmfloorslope; pslope_t *oldcslope = tmceilingslope; + line_t *oldfline = tmfloorline; + line_t *oldcline = tmceilingline; // Move the player P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true); @@ -2658,6 +2671,8 @@ boolean PIT_PushableMoved(mobj_t *thing) tmceilingrover = oldceilrover; tmfloorslope = oldfslope; tmceilingslope = oldcslope; + tmfloorline = oldfline; + tmceilingline = oldcline; thing->momz = stand->momz; } else @@ -2899,11 +2914,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) // Assign thing's standingslope if needed if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) { if (!startingonground && tmfloorslope) - P_HandleSlopeLanding(thing, tmfloorslope); + P_HandleSlopeLanding(thing, tmfloorslope, tmfloorline); if (thing->momz <= 0) { thing->standingslope = tmfloorslope; + thing->standingline = tmfloorline; P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) @@ -2912,11 +2928,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) } else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) { if (!startingonground && tmceilingslope) - P_HandleSlopeLanding(thing, tmceilingslope); + P_HandleSlopeLanding(thing, tmceilingslope, tmceilingline); if (thing->momz >= 0) { thing->standingslope = tmceilingslope; + thing->standingline = tmceilingline; P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) @@ -2924,8 +2941,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) } } } - else // don't set standingslope if you're not going to clip against it + else + { + // don't set standingslope or standingline if you're not going to clip against them thing->standingslope = NULL; + thing->standingline = NULL; + } thing->x = x; thing->y = y; diff --git a/src/p_maputl.c b/src/p_maputl.c index 18a15a928..7de5b5369 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -280,6 +280,7 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1) fixed_t opentop, openbottom, openrange, lowfloor, highceiling; pslope_t *opentopslope, *openbottomslope; ffloor_t *openfloorrover, *openceilingrover; +line_t *opentopline, *openbottomline; // P_CameraLineOpening // P_LineOpening, but for camera @@ -440,6 +441,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) I_Assert(back != NULL); openfloorrover = openceilingrover = NULL; + opentopline = openbottomline = NULL; + if (linedef->polyobj) { // set these defaults so that polyobjects don't interfere with collision above or below them @@ -544,6 +547,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if ((linedef->flags & ML_MIDPEG) != 0) { opentopslope = openbottomslope; } + opentopline = linedef; } } else { // Above if (openbottom < textop) { @@ -551,6 +555,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if ((linedef->flags & ML_MIDPEG) == 0) { openbottomslope = opentopslope; } + openbottomline = linedef; } } } diff --git a/src/p_maputl.h b/src/p_maputl.h index e894c08a2..ca29fc203 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -57,6 +57,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y); extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling; extern pslope_t *opentopslope, *openbottomslope; extern ffloor_t *openfloorrover, *openceilingrover; +extern line_t *opentopline, *openbottomline; void P_LineOpening(line_t *plinedef, mobj_t *mobj); diff --git a/src/p_mobj.c b/src/p_mobj.c index 9cdd2628d..221149f70 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1672,6 +1672,7 @@ void P_XYMovement(mobj_t *mo) fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls boolean moved; pslope_t *oldslope = NULL; + line_t *oldstandingline = NULL; vector3_t slopemom = {0,0,0}; fixed_t predictedz = 0; @@ -1704,7 +1705,10 @@ void P_XYMovement(mobj_t *mo) oldy = mo->y; if (mo->flags & MF_NOCLIPHEIGHT) + { mo->standingslope = NULL; + mo->standingline = NULL; + } // adjust various things based on slope if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) { @@ -1716,7 +1720,7 @@ void P_XYMovement(mobj_t *mo) slopemom.x = xmove; slopemom.y = ymove; slopemom.z = 0; - P_QuantizeMomentumToSlope(&slopemom, mo->standingslope); + P_QuantizeObjectMomentumToSlope(mo, &slopemom); xmove = slopemom.x; ymove = slopemom.y; @@ -1724,6 +1728,7 @@ void P_XYMovement(mobj_t *mo) predictedz = mo->z + slopemom.z; // We'll use this later... oldslope = mo->standingslope; + oldstandingline = mo->standingline; } } else if (P_IsObjectOnGround(mo) && !mo->momz) predictedz = mo->z; @@ -1799,12 +1804,16 @@ void P_XYMovement(mobj_t *mo) { // try to slide along it // Wall transfer part 1. pslope_t *transferslope = NULL; + line_t *transferline = NULL; fixed_t transfermomz = 0; if (oldslope && (P_MobjFlip(mo)*(predictedz - mo->z) > 0)) // Only for moving up (relative to gravity), otherwise there's a failed launch when going down slopes and hitting walls { + angle_t zangle; transferslope = ((mo->standingslope) ? mo->standingslope : oldslope); - if (((transferslope->zangle < ANGLE_180) ? transferslope->zangle : InvAngle(transferslope->zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes. - transfermomz = P_GetWallTransferMomZ(mo, transferslope); + transferline = ((mo->standingline) ? mo->standingline : oldstandingline); + zangle = P_GetStandingSlopeZAngle(transferslope, transferline); + if (((zangle < ANGLE_180) ? zangle : InvAngle(zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes. + transfermomz = P_GetWallTransferMomZ(mo, transferslope, transferline); } P_SlideMove(mo); @@ -1817,7 +1826,7 @@ void P_XYMovement(mobj_t *mo) { angle_t relation; // Scale transfer momentum based on how head-on it is to the slope. if (mo->momx || mo->momy) // "Guess" the angle of the wall you hit using new momentum - relation = transferslope->xydirection - R_PointToAngle2(0, 0, mo->momx, mo->momy); + relation = P_GetStandingSlopeDirection(transferslope, transferline) - R_PointToAngle2(0, 0, mo->momx, mo->momy); else // Give it for free, I guess. relation = ANGLE_90; transfermomz = FixedMul(transfermomz, @@ -1826,6 +1835,7 @@ void P_XYMovement(mobj_t *mo) { mo->momz = transfermomz; mo->standingslope = NULL; + mo->standingline = NULL; if (player) { player->powers[pw_justlaunched] = 2; @@ -1875,7 +1885,7 @@ void P_XYMovement(mobj_t *mo) oldangle = FixedMul((signed)oldslope->zangle, FINECOSINE((moveangle - oldslope->xydirection) >> ANGLETOFINESHIFT)); if (mo->standingslope) - newangle = FixedMul((signed)mo->standingslope->zangle, FINECOSINE((moveangle - mo->standingslope->xydirection) >> ANGLETOFINESHIFT)); + newangle = FixedMul((signed)P_GetObjectStandingSlopeZAngle(mo), FINECOSINE((moveangle - P_GetObjectStandingSlopeDirection(mo)) >> ANGLETOFINESHIFT)); else newangle = 0; @@ -1899,7 +1909,7 @@ void P_XYMovement(mobj_t *mo) } } else if (moved && mo->standingslope && predictedz) { angle_t moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy); - angle_t newangle = FixedMul((signed)mo->standingslope->zangle, FINECOSINE((moveangle - mo->standingslope->xydirection) >> ANGLETOFINESHIFT)); + angle_t newangle = FixedMul((signed)P_GetObjectStandingSlopeZAngle(mo), FINECOSINE((moveangle - P_GetObjectStandingSlopeDirection(mo)) >> ANGLETOFINESHIFT)); /*CONS_Printf("flat to angle %f - predicted z of %f\n", FIXED_TO_FLOAT(AngleFixed(ANGLE_MAX-newangle)), @@ -2432,8 +2442,9 @@ boolean P_ZMovement(mobj_t *mo) if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) { mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; + mo->standingline = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingline : tmfloorline; P_SetPitchRollFromSlope(mo, mo->standingslope); - P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); + P_ReverseQuantizeObjectMomentumToSlope(mo, &mom); } // hit the floor @@ -2579,7 +2590,7 @@ boolean P_ZMovement(mobj_t *mo) mom.z = tmfloorthing->momz; if (mo->standingslope) { // MT_STEAM will never have a standingslope, see above. - P_QuantizeMomentumToSlope(&mom, mo->standingslope); + P_QuantizeObjectMomentumToSlope(mo, &mom); } mo->momx = mom.x; @@ -2825,7 +2836,9 @@ void P_PlayerZMovement(mobj_t *mo) if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) { // Handle landing on slope during Z movement - P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)); + P_HandleSlopeLanding(mo, + (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope), + (mo->eflags & MFE_VERTICALFLIP ? tmceilingline : tmfloorline)); } if (P_MobjFlip(mo)*mo->momz < 0) // falling diff --git a/src/p_mobj.h b/src/p_mobj.h index 2f013a2f3..ae4c5a51d 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -412,7 +412,9 @@ typedef struct mobj_s INT32 cusval; INT32 cvmem; - struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) + struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) (it does) + + struct line_s *standingline; // The line that the object is standing on boolean resetinterp; // if true, some fields should not be interpolated (see R_InterpolateMobjState implementation) boolean colorized; // Whether the mobj uses the rainbow colormap diff --git a/src/p_saveg.c b/src/p_saveg.c index 5e4d6d076..675d68acd 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1746,7 +1746,8 @@ typedef enum MD2_DISPOFFSET = 1<<23, MD2_DRAWONLYFORPLAYER = 1<<24, MD2_DONTDRAWFORVIEWMOBJ = 1<<25, - MD2_TRANSLATION = 1<<26 + MD2_TRANSLATION = 1<<26, + MD2_STANDINGLINE = 1<<27 } mobj_diff2_t; typedef enum @@ -1953,6 +1954,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_CEILINGROVER; if (mobj->standingslope) diff2 |= MD2_SLOPE; + if (mobj->standingline) + diff2 |= MD2_STANDINGLINE; if (mobj->colorized) diff2 |= MD2_COLORIZED; if (mobj->mirrored) @@ -2125,6 +2128,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, mobj->hprev->mobjnum); if (diff2 & MD2_SLOPE) WRITEUINT16(save_p, mobj->standingslope->id); + if (diff2 & MD2_STANDINGLINE) + WRITEUINT32(save_p, SaveLine(mobj->standingline)); if (diff2 & MD2_COLORIZED) WRITEUINT8(save_p, mobj->colorized); if (diff2 & MD2_MIRRORED) @@ -3181,6 +3186,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); if (diff2 & MD2_SLOPE) mobj->standingslope = P_SlopeById(READUINT16(save_p)); + if (diff2 & MD2_STANDINGLINE) + mobj->standingline = LoadLine(READUINT32(save_p)); if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); if (diff2 & MD2_MIRRORED) diff --git a/src/p_slopes.c b/src/p_slopes.c index e75d36ede..745be2eac 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -859,11 +859,10 @@ fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y) // When given a vector, rotates it and aligns it to a slope void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) { - vector3_t axis; // Fuck you, C90. - if (slope->flags & SL_NOPHYSICS) return; // No physics, no quantizing. + vector3_t axis; axis.x = -slope->d.y; axis.y = slope->d.x; axis.z = 0; @@ -877,9 +876,91 @@ void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) // When given a vector, rotates and aligns it to a flat surface (from being relative to a given slope) void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) { - slope->zangle = InvAngle(slope->zangle); - P_QuantizeMomentumToSlope(momentum, slope); - slope->zangle = InvAngle(slope->zangle); + if (slope->flags & SL_NOPHYSICS) + return; // No physics, no quantizing. + + vector3_t axis; + axis.x = -slope->d.y; + axis.y = slope->d.x; + axis.z = 0; + + FV3_Rotate(momentum, &axis, InvAngle(slope->zangle) >> ANGLETOFINESHIFT); +} + +angle_t P_GetStandingSlopeZAngle(pslope_t *slope, line_t *line) +{ + angle_t zangle = slope->zangle; + + if (line) + { + zangle = R_PointToAngle2(0, P_GetSlopeZAt(slope, line->v1->x, line->v1->y), + R_PointToDist2(line->v1->x, line->v1->y, line->v2->x, line->v2->y), P_GetSlopeZAt(slope, line->v2->x, line->v2->y)); + } + + return zangle; +} + +angle_t P_GetStandingSlopeDirection(pslope_t *slope, line_t *line) +{ + angle_t xydirection = slope->xydirection; + + if (line) + { + xydirection = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); + } + + return xydirection; +} + +angle_t P_GetObjectStandingSlopeZAngle(mobj_t *mo) +{ + return P_GetStandingSlopeZAngle(mo->standingslope, mo->standingline); +} + +angle_t P_GetObjectStandingSlopeDirection(mobj_t *mo) +{ + return P_GetStandingSlopeDirection(mo->standingslope, mo->standingline); +} + +static void QuantizeMomentumToSlope(pslope_t *slope, line_t *line, vector3_t *momentum, boolean reverse) +{ + if (!slope || slope->flags & SL_NOPHYSICS) + return; + + angle_t zangle = P_GetStandingSlopeZAngle(slope, line); + + if (reverse) + zangle = InvAngle(zangle); + + vector3_t axis; + axis.z = 0; + + if (line) + { + fixed_t len = R_PointToDist2(0, 0, line->dx, line->dy); + axis.x = FixedDiv(line->dy, len); + axis.y = -FixedDiv(line->dx, len); + } + else + { + axis.x = -slope->d.y; + axis.y = slope->d.x; + } + + FV3_Rotate(momentum, &axis, zangle >> ANGLETOFINESHIFT); +} + +// Given a vector of the object's momentum, rotates it and aligns it to the slope the object is standing on +void P_QuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum) +{ + QuantizeMomentumToSlope(mo->standingslope, mo->standingline, momentum, false); +} + +// Given a vector of the object's momentum, rotates and aligns it to a flat surface +// (from being relative to the slope the object is standing on) +void P_ReverseQuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum) +{ + QuantizeMomentumToSlope(mo->standingslope, mo->standingline, momentum, true); } // @@ -899,7 +980,7 @@ void P_SlopeLaunch(mobj_t *mo) slopemom.x = mo->momx; slopemom.y = mo->momy; slopemom.z = mo->momz*2; - P_QuantizeMomentumToSlope(&slopemom, mo->standingslope); + P_QuantizeObjectMomentumToSlope(mo, &slopemom); mo->momx = slopemom.x; mo->momy = slopemom.y; @@ -919,7 +1000,7 @@ void P_SlopeLaunch(mobj_t *mo) // It would be nice to have a single function that does everything necessary for slope-to-wall transfer. // However, it needs to be seperated out in P_XYMovement to take into account momentum before and after hitting the wall. // This just performs the necessary calculations for getting the base vertical momentum; the horizontal is already reasonably calculated by P_SlideMove. -fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) +fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope, line_t *line) { vector3_t slopemom, axis; angle_t ang; @@ -927,18 +1008,30 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) if (slope->flags & SL_NOPHYSICS) return 0; + angle_t zangle = P_GetStandingSlopeZAngle(slope, line); + // If there's physics, time for launching. // Doesn't kill the vertical momentum as much as P_SlopeLaunch does. - ang = slope->zangle + ANG15*((slope->zangle > 0) ? 1 : -1); + ang = zangle + ANG15*((zangle > 0) ? 1 : -1); if (ang > ANGLE_90 && ang < ANGLE_180) - ang = ((slope->zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards + ang = ((zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards slopemom.x = mo->momx; slopemom.y = mo->momy; slopemom.z = 3*(mo->momz/2); - axis.x = -slope->d.y; - axis.y = slope->d.x; + if (line) + { + fixed_t len = R_PointToDist2(0, 0, line->dx, line->dy); + axis.x = FixedDiv(line->dy, len); + axis.y = -FixedDiv(line->dx, len); + } + else + { + axis.x = -slope->d.y; + axis.y = slope->d.x; + } + axis.z = 0; FV3_Rotate(&slopemom, &axis, ang >> ANGLETOFINESHIFT); @@ -947,7 +1040,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) } // Function to help handle landing on slopes -void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) +void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line) { vector3_t mom; // Ditto. if (slope->flags & SL_NOPHYSICS || (slope->normal.x == 0 && slope->normal.y == 0)) { // No physics, no need to make anything complicated. @@ -966,12 +1059,13 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) mom.y = thing->momy; mom.z = thing->momz*2; - P_ReverseQuantizeMomentumToSlope(&mom, slope); + QuantizeMomentumToSlope(slope, line, &mom, true); if (P_MobjFlip(thing)*mom.z < 0) { // falling, land on slope thing->momx = mom.x; thing->momy = mom.y; thing->standingslope = slope; + thing->standingline = line; P_SetPitchRollFromSlope(thing, slope); if (!thing->player || !(thing->player->pflags & PF_BOUNCING)) thing->momz = -P_MobjFlip(thing); @@ -983,6 +1077,7 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) void P_ButteredSlope(mobj_t *mo) { fixed_t thrust; + angle_t zangle, xydirection; if (!mo->standingslope) return; @@ -1001,12 +1096,15 @@ void P_ButteredSlope(mobj_t *mo) return; // Allow the player to stand still on slopes below a certain steepness } - thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 3 / 2 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); + zangle = P_GetStandingSlopeZAngle(mo->standingslope, mo->standingline); + xydirection = P_GetStandingSlopeDirection(mo->standingslope, mo->standingline); + + thrust = FINESINE(zangle>>ANGLETOFINESHIFT) * 3 / 2 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); if (mo->player && (mo->player->pflags & PF_SPINNING)) { fixed_t mult = 0; if (mo->momx || mo->momy) { - angle_t angle = R_PointToAngle2(0, 0, mo->momx, mo->momy) - mo->standingslope->xydirection; + angle_t angle = R_PointToAngle2(0, 0, mo->momx, mo->momy) - xydirection; if (P_MobjFlip(mo) * mo->standingslope->zdelta < 0) angle ^= ANGLE_180; @@ -1027,5 +1125,5 @@ void P_ButteredSlope(mobj_t *mo) // ... and its friction against the ground for good measure (divided by original friction to keep behaviour for normal slopes the same). thrust = FixedMul(thrust, FixedDiv(mo->friction, ORIG_FRICTION)); - P_Thrust(mo, mo->standingslope->xydirection, thrust); + P_Thrust(mo, xydirection, thrust); } diff --git a/src/p_slopes.h b/src/p_slopes.h index fdc07f67e..f33053ac1 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -84,9 +84,15 @@ fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y); // Lots of physics-based bullshit void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); +void P_QuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum); +void P_ReverseQuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum); +angle_t P_GetStandingSlopeZAngle(pslope_t *slope, line_t *line); +angle_t P_GetStandingSlopeDirection(pslope_t *slope, line_t *line); +angle_t P_GetObjectStandingSlopeZAngle(mobj_t *mo); +angle_t P_GetObjectStandingSlopeDirection(mobj_t *mo); void P_SlopeLaunch(mobj_t *mo); -fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope); -void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope); +fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope, line_t *line); +void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line); void P_ButteredSlope(mobj_t *mo); pslope_t *P_MakeSlopeViaEquationConstants(const double a, const double b, const double c, const double d); diff --git a/src/p_user.c b/src/p_user.c index 7cd128cf0..1782c5386 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -6257,15 +6257,15 @@ static void P_3dMovement(player_t *player) && player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) > FRACUNIT/2) { // Factor thrust to slope, but only for the part pushing up it! // The rest is unaffected. - angle_t thrustangle = R_PointToAngle2(0, 0, totalthrust.x, totalthrust.y)-player->mo->standingslope->xydirection; + angle_t thrustangle = R_PointToAngle2(0, 0, totalthrust.x, totalthrust.y)-P_GetObjectStandingSlopeDirection(player->mo); if (player->mo->standingslope->zdelta < 0) { // Direction goes down, so thrustangle needs to face toward if (thrustangle < ANGLE_90 || thrustangle > ANGLE_270) { - P_QuantizeMomentumToSlope(&totalthrust, player->mo->standingslope); + P_QuantizeObjectMomentumToSlope(player->mo, &totalthrust); } } else { // Direction goes up, so thrustangle needs to face away if (thrustangle > ANGLE_90 && thrustangle < ANGLE_270) { - P_QuantizeMomentumToSlope(&totalthrust, player->mo->standingslope); + P_QuantizeObjectMomentumToSlope(player->mo, &totalthrust); } } } From 3a09c475c71462f923a6a1c500901e450fa027b7 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 19 May 2024 22:53:00 -0300 Subject: [PATCH 2/6] Add comments --- src/p_slopes.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index 745be2eac..1d53bfcf4 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -852,7 +852,6 @@ fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y) return light->slope ? P_GetSlopeZAt(light->slope, x, y) : light->height; } - // // P_QuantizeMomentumToSlope // @@ -887,6 +886,8 @@ void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) FV3_Rotate(momentum, &axis, InvAngle(slope->zangle) >> ANGLETOFINESHIFT); } +// Returns the angle of the slope plane. +// If line is provided, a new calculation is performed as if the slope were on the top or bottom of a solid midtexture. angle_t P_GetStandingSlopeZAngle(pslope_t *slope, line_t *line) { angle_t zangle = slope->zangle; @@ -900,28 +901,23 @@ angle_t P_GetStandingSlopeZAngle(pslope_t *slope, line_t *line) return zangle; } +// Returns the angle of the projected normal of slope plane. +// If line is provided, this simply returns the line's angle. angle_t P_GetStandingSlopeDirection(pslope_t *slope, line_t *line) { angle_t xydirection = slope->xydirection; if (line) { - xydirection = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); + xydirection = line->angle; } return xydirection; } -angle_t P_GetObjectStandingSlopeZAngle(mobj_t *mo) -{ - return P_GetStandingSlopeZAngle(mo->standingslope, mo->standingline); -} - -angle_t P_GetObjectStandingSlopeDirection(mobj_t *mo) -{ - return P_GetStandingSlopeDirection(mo->standingslope, mo->standingline); -} - +// When given a vector, rotates it and aligns it to either a slope, or a flat surface relative to the slope. +// If line is provided, this calculation is performed as if the slope were on the top or bottom of a solid midtexture. +// See also: P_QuantizeMomentumToSlope static void QuantizeMomentumToSlope(pslope_t *slope, line_t *line, vector3_t *momentum, boolean reverse) { if (!slope || slope->flags & SL_NOPHYSICS) @@ -963,6 +959,18 @@ void P_ReverseQuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum) QuantizeMomentumToSlope(mo->standingslope, mo->standingline, momentum, true); } +// Wrapper for P_GetStandingSlopeZAngle. +angle_t P_GetObjectStandingSlopeZAngle(mobj_t *mo) +{ + return P_GetStandingSlopeZAngle(mo->standingslope, mo->standingline); +} + +// Wrapper for P_GetObjectStandingSlopeDirection. +angle_t P_GetObjectStandingSlopeDirection(mobj_t *mo) +{ + return P_GetStandingSlopeDirection(mo->standingslope, mo->standingline); +} + // // P_SlopeLaunch // @@ -1042,7 +1050,6 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope, line_t *line) // Function to help handle landing on slopes void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line) { - vector3_t mom; // Ditto. if (slope->flags & SL_NOPHYSICS || (slope->normal.x == 0 && slope->normal.y == 0)) { // No physics, no need to make anything complicated. if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope { @@ -1055,6 +1062,7 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line) return; } + vector3_t mom; mom.x = thing->momx; mom.y = thing->momy; mom.z = thing->momz*2; From 6bf58ce8705111b1c7456edcf269e22e8ed6f1ee Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Mon, 20 May 2024 20:10:25 -0300 Subject: [PATCH 3/6] Revert "Add comments" This reverts commit 3a09c475c71462f923a6a1c500901e450fa027b7. --- src/p_slopes.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index 1d53bfcf4..745be2eac 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -852,6 +852,7 @@ fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y) return light->slope ? P_GetSlopeZAt(light->slope, x, y) : light->height; } + // // P_QuantizeMomentumToSlope // @@ -886,8 +887,6 @@ void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) FV3_Rotate(momentum, &axis, InvAngle(slope->zangle) >> ANGLETOFINESHIFT); } -// Returns the angle of the slope plane. -// If line is provided, a new calculation is performed as if the slope were on the top or bottom of a solid midtexture. angle_t P_GetStandingSlopeZAngle(pslope_t *slope, line_t *line) { angle_t zangle = slope->zangle; @@ -901,23 +900,28 @@ angle_t P_GetStandingSlopeZAngle(pslope_t *slope, line_t *line) return zangle; } -// Returns the angle of the projected normal of slope plane. -// If line is provided, this simply returns the line's angle. angle_t P_GetStandingSlopeDirection(pslope_t *slope, line_t *line) { angle_t xydirection = slope->xydirection; if (line) { - xydirection = line->angle; + xydirection = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); } return xydirection; } -// When given a vector, rotates it and aligns it to either a slope, or a flat surface relative to the slope. -// If line is provided, this calculation is performed as if the slope were on the top or bottom of a solid midtexture. -// See also: P_QuantizeMomentumToSlope +angle_t P_GetObjectStandingSlopeZAngle(mobj_t *mo) +{ + return P_GetStandingSlopeZAngle(mo->standingslope, mo->standingline); +} + +angle_t P_GetObjectStandingSlopeDirection(mobj_t *mo) +{ + return P_GetStandingSlopeDirection(mo->standingslope, mo->standingline); +} + static void QuantizeMomentumToSlope(pslope_t *slope, line_t *line, vector3_t *momentum, boolean reverse) { if (!slope || slope->flags & SL_NOPHYSICS) @@ -959,18 +963,6 @@ void P_ReverseQuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum) QuantizeMomentumToSlope(mo->standingslope, mo->standingline, momentum, true); } -// Wrapper for P_GetStandingSlopeZAngle. -angle_t P_GetObjectStandingSlopeZAngle(mobj_t *mo) -{ - return P_GetStandingSlopeZAngle(mo->standingslope, mo->standingline); -} - -// Wrapper for P_GetObjectStandingSlopeDirection. -angle_t P_GetObjectStandingSlopeDirection(mobj_t *mo) -{ - return P_GetStandingSlopeDirection(mo->standingslope, mo->standingline); -} - // // P_SlopeLaunch // @@ -1050,6 +1042,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope, line_t *line) // Function to help handle landing on slopes void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line) { + vector3_t mom; // Ditto. if (slope->flags & SL_NOPHYSICS || (slope->normal.x == 0 && slope->normal.y == 0)) { // No physics, no need to make anything complicated. if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope { @@ -1062,7 +1055,6 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line) return; } - vector3_t mom; mom.x = thing->momx; mom.y = thing->momy; mom.z = thing->momz*2; From 3d4c9eedf841dda8ad50b0d8fc028b3db89fdcc4 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Mon, 20 May 2024 20:10:34 -0300 Subject: [PATCH 4/6] Revert "Improve slope physics on solid middle textures" This reverts commit e67e225ff2f796ba8cb78c9bacc5c91f052d5271. --- src/p_local.h | 1 - src/p_map.c | 27 ++-------- src/p_maputl.c | 5 -- src/p_maputl.h | 1 - src/p_mobj.c | 31 ++++-------- src/p_mobj.h | 4 +- src/p_saveg.c | 9 +--- src/p_slopes.c | 130 ++++++------------------------------------------- src/p_slopes.h | 10 +--- src/p_user.c | 6 +-- 10 files changed, 35 insertions(+), 189 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 6a4aa241c..249c3cd4b 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -399,7 +399,6 @@ extern camera_t *mapcampointer; extern fixed_t tmx; extern fixed_t tmy; extern pslope_t *tmfloorslope, *tmceilingslope; -extern line_t *tmfloorline, *tmceilingline; /* cphipps 2004/08/30 */ extern void P_MapStart(void); diff --git a/src/p_map.c b/src/p_map.c index aeeeda056..f97ddfa3c 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -55,7 +55,6 @@ mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) ffloor_t *tmfloorrover, *tmceilingrover; pslope_t *tmfloorslope, *tmceilingslope; -line_t *tmfloorline, *tmceilingline; // keep track of the line that lowers the ceiling, // so missiles don't explode against sky hack walls @@ -1761,7 +1760,6 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmfloorz = thing->z + thing->height; tmfloorrover = NULL; tmfloorslope = NULL; - tmfloorline = NULL; } return CHECKTHING_COLLIDE; } @@ -1781,7 +1779,6 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmfloorz = tmceilingz = topz; // block while in air tmceilingrover = NULL; tmceilingslope = NULL; - tmceilingline = NULL; tmfloorthing = thing; // needed for side collision collide = CHECKTHING_COLLIDE; @@ -1791,7 +1788,6 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmceilingz = topz; tmceilingrover = NULL; tmceilingslope = NULL; - tmceilingline = NULL; tmfloorthing = thing; // thing we may stand on collide = CHECKTHING_COLLIDE; @@ -1809,7 +1805,6 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmceilingz = thing->z; tmceilingrover = NULL; tmceilingslope = NULL; - tmceilingline = NULL; } return CHECKTHING_COLLIDE; } @@ -1829,7 +1824,6 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmfloorz = tmceilingz = topz; // block while in air tmfloorrover = NULL; tmfloorslope = NULL; - tmfloorline = NULL; tmfloorthing = thing; // needed for side collision collide = CHECKTHING_COLLIDE; @@ -1839,7 +1833,6 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) tmfloorz = topz; tmfloorrover = NULL; tmfloorslope = NULL; - tmfloorline = NULL; tmfloorthing = thing; // thing we may stand on collide = CHECKTHING_COLLIDE; @@ -2007,7 +2000,6 @@ static boolean PIT_CheckLine(line_t *ld) ceilingline = ld; tmceilingrover = openceilingrover; tmceilingslope = opentopslope; - tmceilingline = opentopline; } if (openbottom > tmfloorz) @@ -2015,7 +2007,6 @@ static boolean PIT_CheckLine(line_t *ld) tmfloorz = openbottom; tmfloorrover = openfloorrover; tmfloorslope = openbottomslope; - tmfloorline = openbottomline; } if (highceiling > tmdrpoffceilz) @@ -2066,8 +2057,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; tmfloorrover = NULL; tmceilingrover = NULL; - tmfloorline = NULL; - tmceilingline = NULL; tmfloorslope = newsubsec->sector->f_slope; tmceilingslope = newsubsec->sector->c_slope; @@ -2653,8 +2642,6 @@ boolean PIT_PushableMoved(mobj_t *thing) ffloor_t *oldceilrover = tmceilingrover; pslope_t *oldfslope = tmfloorslope; pslope_t *oldcslope = tmceilingslope; - line_t *oldfline = tmfloorline; - line_t *oldcline = tmceilingline; // Move the player P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true); @@ -2671,8 +2658,6 @@ boolean PIT_PushableMoved(mobj_t *thing) tmceilingrover = oldceilrover; tmfloorslope = oldfslope; tmceilingslope = oldcslope; - tmfloorline = oldfline; - tmceilingline = oldcline; thing->momz = stand->momz; } else @@ -2914,12 +2899,11 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) // Assign thing's standingslope if needed if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) { if (!startingonground && tmfloorslope) - P_HandleSlopeLanding(thing, tmfloorslope, tmfloorline); + P_HandleSlopeLanding(thing, tmfloorslope); if (thing->momz <= 0) { thing->standingslope = tmfloorslope; - thing->standingline = tmfloorline; P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) @@ -2928,12 +2912,11 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) } else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) { if (!startingonground && tmceilingslope) - P_HandleSlopeLanding(thing, tmceilingslope, tmceilingline); + P_HandleSlopeLanding(thing, tmceilingslope); if (thing->momz >= 0) { thing->standingslope = tmceilingslope; - thing->standingline = tmceilingline; P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) @@ -2941,12 +2924,8 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) } } } - else - { - // don't set standingslope or standingline if you're not going to clip against them + else // don't set standingslope if you're not going to clip against it thing->standingslope = NULL; - thing->standingline = NULL; - } thing->x = x; thing->y = y; diff --git a/src/p_maputl.c b/src/p_maputl.c index 7de5b5369..18a15a928 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -280,7 +280,6 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1) fixed_t opentop, openbottom, openrange, lowfloor, highceiling; pslope_t *opentopslope, *openbottomslope; ffloor_t *openfloorrover, *openceilingrover; -line_t *opentopline, *openbottomline; // P_CameraLineOpening // P_LineOpening, but for camera @@ -441,8 +440,6 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) I_Assert(back != NULL); openfloorrover = openceilingrover = NULL; - opentopline = openbottomline = NULL; - if (linedef->polyobj) { // set these defaults so that polyobjects don't interfere with collision above or below them @@ -547,7 +544,6 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if ((linedef->flags & ML_MIDPEG) != 0) { opentopslope = openbottomslope; } - opentopline = linedef; } } else { // Above if (openbottom < textop) { @@ -555,7 +551,6 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if ((linedef->flags & ML_MIDPEG) == 0) { openbottomslope = opentopslope; } - openbottomline = linedef; } } } diff --git a/src/p_maputl.h b/src/p_maputl.h index ca29fc203..e894c08a2 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -57,7 +57,6 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y); extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling; extern pslope_t *opentopslope, *openbottomslope; extern ffloor_t *openfloorrover, *openceilingrover; -extern line_t *opentopline, *openbottomline; void P_LineOpening(line_t *plinedef, mobj_t *mobj); diff --git a/src/p_mobj.c b/src/p_mobj.c index 221149f70..9cdd2628d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1672,7 +1672,6 @@ void P_XYMovement(mobj_t *mo) fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls boolean moved; pslope_t *oldslope = NULL; - line_t *oldstandingline = NULL; vector3_t slopemom = {0,0,0}; fixed_t predictedz = 0; @@ -1705,10 +1704,7 @@ void P_XYMovement(mobj_t *mo) oldy = mo->y; if (mo->flags & MF_NOCLIPHEIGHT) - { mo->standingslope = NULL; - mo->standingline = NULL; - } // adjust various things based on slope if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) { @@ -1720,7 +1716,7 @@ void P_XYMovement(mobj_t *mo) slopemom.x = xmove; slopemom.y = ymove; slopemom.z = 0; - P_QuantizeObjectMomentumToSlope(mo, &slopemom); + P_QuantizeMomentumToSlope(&slopemom, mo->standingslope); xmove = slopemom.x; ymove = slopemom.y; @@ -1728,7 +1724,6 @@ void P_XYMovement(mobj_t *mo) predictedz = mo->z + slopemom.z; // We'll use this later... oldslope = mo->standingslope; - oldstandingline = mo->standingline; } } else if (P_IsObjectOnGround(mo) && !mo->momz) predictedz = mo->z; @@ -1804,16 +1799,12 @@ void P_XYMovement(mobj_t *mo) { // try to slide along it // Wall transfer part 1. pslope_t *transferslope = NULL; - line_t *transferline = NULL; fixed_t transfermomz = 0; if (oldslope && (P_MobjFlip(mo)*(predictedz - mo->z) > 0)) // Only for moving up (relative to gravity), otherwise there's a failed launch when going down slopes and hitting walls { - angle_t zangle; transferslope = ((mo->standingslope) ? mo->standingslope : oldslope); - transferline = ((mo->standingline) ? mo->standingline : oldstandingline); - zangle = P_GetStandingSlopeZAngle(transferslope, transferline); - if (((zangle < ANGLE_180) ? zangle : InvAngle(zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes. - transfermomz = P_GetWallTransferMomZ(mo, transferslope, transferline); + if (((transferslope->zangle < ANGLE_180) ? transferslope->zangle : InvAngle(transferslope->zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes. + transfermomz = P_GetWallTransferMomZ(mo, transferslope); } P_SlideMove(mo); @@ -1826,7 +1817,7 @@ void P_XYMovement(mobj_t *mo) { angle_t relation; // Scale transfer momentum based on how head-on it is to the slope. if (mo->momx || mo->momy) // "Guess" the angle of the wall you hit using new momentum - relation = P_GetStandingSlopeDirection(transferslope, transferline) - R_PointToAngle2(0, 0, mo->momx, mo->momy); + relation = transferslope->xydirection - R_PointToAngle2(0, 0, mo->momx, mo->momy); else // Give it for free, I guess. relation = ANGLE_90; transfermomz = FixedMul(transfermomz, @@ -1835,7 +1826,6 @@ void P_XYMovement(mobj_t *mo) { mo->momz = transfermomz; mo->standingslope = NULL; - mo->standingline = NULL; if (player) { player->powers[pw_justlaunched] = 2; @@ -1885,7 +1875,7 @@ void P_XYMovement(mobj_t *mo) oldangle = FixedMul((signed)oldslope->zangle, FINECOSINE((moveangle - oldslope->xydirection) >> ANGLETOFINESHIFT)); if (mo->standingslope) - newangle = FixedMul((signed)P_GetObjectStandingSlopeZAngle(mo), FINECOSINE((moveangle - P_GetObjectStandingSlopeDirection(mo)) >> ANGLETOFINESHIFT)); + newangle = FixedMul((signed)mo->standingslope->zangle, FINECOSINE((moveangle - mo->standingslope->xydirection) >> ANGLETOFINESHIFT)); else newangle = 0; @@ -1909,7 +1899,7 @@ void P_XYMovement(mobj_t *mo) } } else if (moved && mo->standingslope && predictedz) { angle_t moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy); - angle_t newangle = FixedMul((signed)P_GetObjectStandingSlopeZAngle(mo), FINECOSINE((moveangle - P_GetObjectStandingSlopeDirection(mo)) >> ANGLETOFINESHIFT)); + angle_t newangle = FixedMul((signed)mo->standingslope->zangle, FINECOSINE((moveangle - mo->standingslope->xydirection) >> ANGLETOFINESHIFT)); /*CONS_Printf("flat to angle %f - predicted z of %f\n", FIXED_TO_FLOAT(AngleFixed(ANGLE_MAX-newangle)), @@ -2442,9 +2432,8 @@ boolean P_ZMovement(mobj_t *mo) if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) { mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; - mo->standingline = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingline : tmfloorline; P_SetPitchRollFromSlope(mo, mo->standingslope); - P_ReverseQuantizeObjectMomentumToSlope(mo, &mom); + P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); } // hit the floor @@ -2590,7 +2579,7 @@ boolean P_ZMovement(mobj_t *mo) mom.z = tmfloorthing->momz; if (mo->standingslope) { // MT_STEAM will never have a standingslope, see above. - P_QuantizeObjectMomentumToSlope(mo, &mom); + P_QuantizeMomentumToSlope(&mom, mo->standingslope); } mo->momx = mom.x; @@ -2836,9 +2825,7 @@ void P_PlayerZMovement(mobj_t *mo) if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) { // Handle landing on slope during Z movement - P_HandleSlopeLanding(mo, - (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope), - (mo->eflags & MFE_VERTICALFLIP ? tmceilingline : tmfloorline)); + P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)); } if (P_MobjFlip(mo)*mo->momz < 0) // falling diff --git a/src/p_mobj.h b/src/p_mobj.h index ae4c5a51d..2f013a2f3 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -412,9 +412,7 @@ typedef struct mobj_s INT32 cusval; INT32 cvmem; - struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) (it does) - - struct line_s *standingline; // The line that the object is standing on + struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) boolean resetinterp; // if true, some fields should not be interpolated (see R_InterpolateMobjState implementation) boolean colorized; // Whether the mobj uses the rainbow colormap diff --git a/src/p_saveg.c b/src/p_saveg.c index 675d68acd..5e4d6d076 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1746,8 +1746,7 @@ typedef enum MD2_DISPOFFSET = 1<<23, MD2_DRAWONLYFORPLAYER = 1<<24, MD2_DONTDRAWFORVIEWMOBJ = 1<<25, - MD2_TRANSLATION = 1<<26, - MD2_STANDINGLINE = 1<<27 + MD2_TRANSLATION = 1<<26 } mobj_diff2_t; typedef enum @@ -1954,8 +1953,6 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_CEILINGROVER; if (mobj->standingslope) diff2 |= MD2_SLOPE; - if (mobj->standingline) - diff2 |= MD2_STANDINGLINE; if (mobj->colorized) diff2 |= MD2_COLORIZED; if (mobj->mirrored) @@ -2128,8 +2125,6 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, mobj->hprev->mobjnum); if (diff2 & MD2_SLOPE) WRITEUINT16(save_p, mobj->standingslope->id); - if (diff2 & MD2_STANDINGLINE) - WRITEUINT32(save_p, SaveLine(mobj->standingline)); if (diff2 & MD2_COLORIZED) WRITEUINT8(save_p, mobj->colorized); if (diff2 & MD2_MIRRORED) @@ -3186,8 +3181,6 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); if (diff2 & MD2_SLOPE) mobj->standingslope = P_SlopeById(READUINT16(save_p)); - if (diff2 & MD2_STANDINGLINE) - mobj->standingline = LoadLine(READUINT32(save_p)); if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); if (diff2 & MD2_MIRRORED) diff --git a/src/p_slopes.c b/src/p_slopes.c index 745be2eac..e75d36ede 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -859,10 +859,11 @@ fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y) // When given a vector, rotates it and aligns it to a slope void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) { + vector3_t axis; // Fuck you, C90. + if (slope->flags & SL_NOPHYSICS) return; // No physics, no quantizing. - vector3_t axis; axis.x = -slope->d.y; axis.y = slope->d.x; axis.z = 0; @@ -876,91 +877,9 @@ void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) // When given a vector, rotates and aligns it to a flat surface (from being relative to a given slope) void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) { - if (slope->flags & SL_NOPHYSICS) - return; // No physics, no quantizing. - - vector3_t axis; - axis.x = -slope->d.y; - axis.y = slope->d.x; - axis.z = 0; - - FV3_Rotate(momentum, &axis, InvAngle(slope->zangle) >> ANGLETOFINESHIFT); -} - -angle_t P_GetStandingSlopeZAngle(pslope_t *slope, line_t *line) -{ - angle_t zangle = slope->zangle; - - if (line) - { - zangle = R_PointToAngle2(0, P_GetSlopeZAt(slope, line->v1->x, line->v1->y), - R_PointToDist2(line->v1->x, line->v1->y, line->v2->x, line->v2->y), P_GetSlopeZAt(slope, line->v2->x, line->v2->y)); - } - - return zangle; -} - -angle_t P_GetStandingSlopeDirection(pslope_t *slope, line_t *line) -{ - angle_t xydirection = slope->xydirection; - - if (line) - { - xydirection = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); - } - - return xydirection; -} - -angle_t P_GetObjectStandingSlopeZAngle(mobj_t *mo) -{ - return P_GetStandingSlopeZAngle(mo->standingslope, mo->standingline); -} - -angle_t P_GetObjectStandingSlopeDirection(mobj_t *mo) -{ - return P_GetStandingSlopeDirection(mo->standingslope, mo->standingline); -} - -static void QuantizeMomentumToSlope(pslope_t *slope, line_t *line, vector3_t *momentum, boolean reverse) -{ - if (!slope || slope->flags & SL_NOPHYSICS) - return; - - angle_t zangle = P_GetStandingSlopeZAngle(slope, line); - - if (reverse) - zangle = InvAngle(zangle); - - vector3_t axis; - axis.z = 0; - - if (line) - { - fixed_t len = R_PointToDist2(0, 0, line->dx, line->dy); - axis.x = FixedDiv(line->dy, len); - axis.y = -FixedDiv(line->dx, len); - } - else - { - axis.x = -slope->d.y; - axis.y = slope->d.x; - } - - FV3_Rotate(momentum, &axis, zangle >> ANGLETOFINESHIFT); -} - -// Given a vector of the object's momentum, rotates it and aligns it to the slope the object is standing on -void P_QuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum) -{ - QuantizeMomentumToSlope(mo->standingslope, mo->standingline, momentum, false); -} - -// Given a vector of the object's momentum, rotates and aligns it to a flat surface -// (from being relative to the slope the object is standing on) -void P_ReverseQuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum) -{ - QuantizeMomentumToSlope(mo->standingslope, mo->standingline, momentum, true); + slope->zangle = InvAngle(slope->zangle); + P_QuantizeMomentumToSlope(momentum, slope); + slope->zangle = InvAngle(slope->zangle); } // @@ -980,7 +899,7 @@ void P_SlopeLaunch(mobj_t *mo) slopemom.x = mo->momx; slopemom.y = mo->momy; slopemom.z = mo->momz*2; - P_QuantizeObjectMomentumToSlope(mo, &slopemom); + P_QuantizeMomentumToSlope(&slopemom, mo->standingslope); mo->momx = slopemom.x; mo->momy = slopemom.y; @@ -1000,7 +919,7 @@ void P_SlopeLaunch(mobj_t *mo) // It would be nice to have a single function that does everything necessary for slope-to-wall transfer. // However, it needs to be seperated out in P_XYMovement to take into account momentum before and after hitting the wall. // This just performs the necessary calculations for getting the base vertical momentum; the horizontal is already reasonably calculated by P_SlideMove. -fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope, line_t *line) +fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) { vector3_t slopemom, axis; angle_t ang; @@ -1008,30 +927,18 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope, line_t *line) if (slope->flags & SL_NOPHYSICS) return 0; - angle_t zangle = P_GetStandingSlopeZAngle(slope, line); - // If there's physics, time for launching. // Doesn't kill the vertical momentum as much as P_SlopeLaunch does. - ang = zangle + ANG15*((zangle > 0) ? 1 : -1); + ang = slope->zangle + ANG15*((slope->zangle > 0) ? 1 : -1); if (ang > ANGLE_90 && ang < ANGLE_180) - ang = ((zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards + ang = ((slope->zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards slopemom.x = mo->momx; slopemom.y = mo->momy; slopemom.z = 3*(mo->momz/2); - if (line) - { - fixed_t len = R_PointToDist2(0, 0, line->dx, line->dy); - axis.x = FixedDiv(line->dy, len); - axis.y = -FixedDiv(line->dx, len); - } - else - { - axis.x = -slope->d.y; - axis.y = slope->d.x; - } - + axis.x = -slope->d.y; + axis.y = slope->d.x; axis.z = 0; FV3_Rotate(&slopemom, &axis, ang >> ANGLETOFINESHIFT); @@ -1040,7 +947,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope, line_t *line) } // Function to help handle landing on slopes -void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line) +void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) { vector3_t mom; // Ditto. if (slope->flags & SL_NOPHYSICS || (slope->normal.x == 0 && slope->normal.y == 0)) { // No physics, no need to make anything complicated. @@ -1059,13 +966,12 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line) mom.y = thing->momy; mom.z = thing->momz*2; - QuantizeMomentumToSlope(slope, line, &mom, true); + P_ReverseQuantizeMomentumToSlope(&mom, slope); if (P_MobjFlip(thing)*mom.z < 0) { // falling, land on slope thing->momx = mom.x; thing->momy = mom.y; thing->standingslope = slope; - thing->standingline = line; P_SetPitchRollFromSlope(thing, slope); if (!thing->player || !(thing->player->pflags & PF_BOUNCING)) thing->momz = -P_MobjFlip(thing); @@ -1077,7 +983,6 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line) void P_ButteredSlope(mobj_t *mo) { fixed_t thrust; - angle_t zangle, xydirection; if (!mo->standingslope) return; @@ -1096,15 +1001,12 @@ void P_ButteredSlope(mobj_t *mo) return; // Allow the player to stand still on slopes below a certain steepness } - zangle = P_GetStandingSlopeZAngle(mo->standingslope, mo->standingline); - xydirection = P_GetStandingSlopeDirection(mo->standingslope, mo->standingline); - - thrust = FINESINE(zangle>>ANGLETOFINESHIFT) * 3 / 2 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); + thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 3 / 2 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); if (mo->player && (mo->player->pflags & PF_SPINNING)) { fixed_t mult = 0; if (mo->momx || mo->momy) { - angle_t angle = R_PointToAngle2(0, 0, mo->momx, mo->momy) - xydirection; + angle_t angle = R_PointToAngle2(0, 0, mo->momx, mo->momy) - mo->standingslope->xydirection; if (P_MobjFlip(mo) * mo->standingslope->zdelta < 0) angle ^= ANGLE_180; @@ -1125,5 +1027,5 @@ void P_ButteredSlope(mobj_t *mo) // ... and its friction against the ground for good measure (divided by original friction to keep behaviour for normal slopes the same). thrust = FixedMul(thrust, FixedDiv(mo->friction, ORIG_FRICTION)); - P_Thrust(mo, xydirection, thrust); + P_Thrust(mo, mo->standingslope->xydirection, thrust); } diff --git a/src/p_slopes.h b/src/p_slopes.h index f33053ac1..fdc07f67e 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -84,15 +84,9 @@ fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y); // Lots of physics-based bullshit void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); -void P_QuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum); -void P_ReverseQuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum); -angle_t P_GetStandingSlopeZAngle(pslope_t *slope, line_t *line); -angle_t P_GetStandingSlopeDirection(pslope_t *slope, line_t *line); -angle_t P_GetObjectStandingSlopeZAngle(mobj_t *mo); -angle_t P_GetObjectStandingSlopeDirection(mobj_t *mo); void P_SlopeLaunch(mobj_t *mo); -fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope, line_t *line); -void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line); +fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope); +void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope); void P_ButteredSlope(mobj_t *mo); pslope_t *P_MakeSlopeViaEquationConstants(const double a, const double b, const double c, const double d); diff --git a/src/p_user.c b/src/p_user.c index 1782c5386..7cd128cf0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -6257,15 +6257,15 @@ static void P_3dMovement(player_t *player) && player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) > FRACUNIT/2) { // Factor thrust to slope, but only for the part pushing up it! // The rest is unaffected. - angle_t thrustangle = R_PointToAngle2(0, 0, totalthrust.x, totalthrust.y)-P_GetObjectStandingSlopeDirection(player->mo); + angle_t thrustangle = R_PointToAngle2(0, 0, totalthrust.x, totalthrust.y)-player->mo->standingslope->xydirection; if (player->mo->standingslope->zdelta < 0) { // Direction goes down, so thrustangle needs to face toward if (thrustangle < ANGLE_90 || thrustangle > ANGLE_270) { - P_QuantizeObjectMomentumToSlope(player->mo, &totalthrust); + P_QuantizeMomentumToSlope(&totalthrust, player->mo->standingslope); } } else { // Direction goes up, so thrustangle needs to face away if (thrustangle > ANGLE_90 && thrustangle < ANGLE_270) { - P_QuantizeObjectMomentumToSlope(player->mo, &totalthrust); + P_QuantizeMomentumToSlope(&totalthrust, player->mo->standingslope); } } } From 3fb5907effb3814c77f39dd9b2c6e1f9b2a1dd2b Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Mon, 20 May 2024 20:08:47 -0300 Subject: [PATCH 5/6] Add slope data to lines --- src/p_maputl.c | 14 +++--- src/p_setup.c | 2 + src/p_slopes.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++- src/r_defs.h | 2 + 4 files changed, 137 insertions(+), 8 deletions(-) diff --git a/src/p_maputl.c b/src/p_maputl.c index 18a15a928..3373a40c4 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -541,16 +541,18 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 > delta2) { // Below if (opentop > texbottom) { opentop = texbottom; - if ((linedef->flags & ML_MIDPEG) != 0) { - opentopslope = openbottomslope; - } + if (linedef->flags & ML_NOSKEW) + opentopslope = NULL; + else + opentopslope = linedef->midtexslope; } } else { // Above if (openbottom < textop) { openbottom = textop; - if ((linedef->flags & ML_MIDPEG) == 0) { - openbottomslope = opentopslope; - } + if (linedef->flags & ML_NOSKEW) + openbottomslope = NULL; + else + openbottomslope = linedef->midtexslope; } } } diff --git a/src/p_setup.c b/src/p_setup.c index 41487d702..3dd3d942c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1113,6 +1113,8 @@ static void P_InitializeLinedef(line_t *ld) ld->callcount = 0; ld->secportal = UINT32_MAX; + ld->midtexslope = NULL; + // cph 2006/09/30 - fix sidedef errors right away. // cph 2002/07/20 - these errors are fatal if not fixed, so apply them for (j = 0; j < 2; j++) diff --git a/src/p_slopes.c b/src/p_slopes.c index e75d36ede..d941c71f9 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -28,6 +28,8 @@ pslope_t *slopelist = NULL; UINT16 slopecount = 0; +static void P_UpdateMidtextureSlopesForSector(sector_t *sector); + // Calculate line normal void P_CalculateSlopeNormal(pslope_t *slope) { @@ -212,6 +214,9 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th) slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta); slope->moved = true; P_CalculateSlopeNormal(slope); + P_UpdateMidtextureSlopesForSector(srcline->frontsector); + if (srcline->backsector) + P_UpdateMidtextureSlopesForSector(srcline->backsector); } } @@ -232,6 +237,12 @@ void T_DynamicSlopeVert (dynvertexplanethink_t* th) } ReconfigureViaVertexes(th->slope, th->vex[0], th->vex[1], th->vex[2]); + + for (i = 0; i < 3; i++) + { + if (th->secs[i]) + P_UpdateMidtextureSlopesForSector(th->secs[i]); + } } static inline void P_AddDynLineSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent) @@ -758,6 +769,111 @@ pslope_t *P_MakeSlopeViaEquationConstants(const double a, const double b, const return ret; } +static pslope_t *P_GetReferenceSlopeForMidtexture(line_t *line) +{ + if (line->flags & ML_MIDPEG) + { + // Line has ML_MIDPEG, so use the floor slope + fixed_t frontheight = P_GetSectorFloorZAt(line->frontsector, line->v1->x, line->v1->y); + fixed_t backheight = P_GetSectorFloorZAt(line->backsector, line->v1->x, line->v1->y); + + if (frontheight > backheight) + { + return line->frontsector->f_slope; + } + else + { + return line->backsector->f_slope; + } + } + else + { + // Line does not have ML_MIDPEG, so use the ceiling slope + fixed_t frontheight = P_GetSectorCeilingZAt(line->frontsector, line->v1->x, line->v1->y); + fixed_t backheight = P_GetSectorCeilingZAt(line->backsector, line->v1->x, line->v1->y); + + if (frontheight < backheight) + { + return line->frontsector->c_slope; + } + else + { + return line->backsector->c_slope; + } + } + + return NULL; +} + +// Updates a slope for a solid midtexture based on the slope of the sector it's in. +static void P_UpdateSolidMidtextureSlope(line_t *line, pslope_t *ref) +{ + pslope_t *slope = line->midtexslope; + + if (ref == NULL) + return; + + // Set origin + vector3_t origin; + origin.x = line->v1->x; + origin.y = line->v1->y; + origin.z = P_GetSlopeZAt(ref, origin.x, origin.y); + FV3_Copy(&slope->o, &origin); + + // Get where the line ends + vector3_t point; + point.x = line->v2->x; + point.y = line->v2->y; + point.z = P_GetSlopeZAt(ref, point.x, point.y); + + // Get length of the line + fixed_t extent = R_PointToDist2(0, 0, line->dx, line->dy); + + // Precalculate variables + slope->zdelta = FixedDiv(origin.z - point.z, extent); + slope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); + slope->xydirection = line->angle; + + // Precalculate the direction + vector2_t dir; + dir.x = FixedMul(FINECOSINE(slope->zangle >> ANGLETOFINESHIFT), FINECOSINE((slope->xydirection+ANGLE_180) >> ANGLETOFINESHIFT)); + dir.y = FixedMul(FINECOSINE(slope->zangle >> ANGLETOFINESHIFT), FINESINE((slope->xydirection+ANGLE_180) >> ANGLETOFINESHIFT)); + FV2_Copy(&slope->d, &dir); + + P_CalculateSlopeNormal(slope); + + // Calling P_CalculateSlopeVectors is not necessary. + slope->moved = true; +} + +// Goes through every line in the sector and updates the midtexture slope if it is present +static void P_UpdateMidtextureSlopesForSector(sector_t *sector) +{ + for (size_t i = 0; i < sector->linecount; i++) + { + if (sector->lines[i]->midtexslope != NULL) + P_UpdateSolidMidtextureSlope(sector->lines[i], P_GetReferenceSlopeForMidtexture(sector->lines[i])); + } +} + +// Creates a solid midtexture slope for the line if possible +static void P_CreateSolidMidtextureSlope(line_t *line) +{ + if (line->backsector == NULL) // Ignore single-sided lines (of course) + return; + + if ((line->flags & ML_MIDSOLID) == 0) // Ignore if the midtexture is not solid + return; + + pslope_t *ref = P_GetReferenceSlopeForMidtexture(line); + if (ref) + { + line->midtexslope = Slope_Add(0); + + P_UpdateSolidMidtextureSlope(line, ref); + } +} + /// Initializes and reads the slopes from the map data. void P_SpawnSlopes(const boolean fromsave) { size_t i; @@ -785,14 +901,21 @@ void P_SpawnSlopes(const boolean fromsave) { /// Copies slopes from tagged sectors via line specials. /// \note Doesn't actually copy, but instead they share the same pointers. + // Also, creates midtexture slopes. for (i = 0; i < numlines; i++) - switch (lines[i].special) + { + line_t *line = &lines[i]; + + switch (line->special) { case 720: - P_CopySectorSlope(&lines[i]); + P_CopySectorSlope(line); default: break; } + + P_CreateSolidMidtextureSlope(line); + } } /// Initializes slopes. diff --git a/src/r_defs.h b/src/r_defs.h index da4dd2d70..7a6f518ee 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -612,6 +612,8 @@ typedef struct line_s INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0 UINT32 secportal; // transferred sector portal + + struct pslope_s *midtexslope; } line_t; typedef struct From 36395bfaac4b247234aa85c1f85780547d649bf0 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Mon, 20 May 2024 20:25:42 -0300 Subject: [PATCH 6/6] Copy the flags of the reference slope --- src/p_slopes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index d941c71f9..11327506e 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -868,7 +868,7 @@ static void P_CreateSolidMidtextureSlope(line_t *line) pslope_t *ref = P_GetReferenceSlopeForMidtexture(line); if (ref) { - line->midtexslope = Slope_Add(0); + line->midtexslope = Slope_Add(ref->flags & SL_NOPHYSICS); P_UpdateSolidMidtextureSlope(line, ref); }