diff --git a/src/p_mobj.c b/src/p_mobj.c index 38e88da90..a819883ad 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2121,16 +2121,6 @@ void P_XYMovement(mobj_t *mo) if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) && !(mo->eflags & MFE_SPRUNG)) { -#ifdef ESLOPE - pslope_t *transferslope = 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 - { - transferslope = ((mo->standingslope) ? mo->standingslope : oldslope); - transfermomz = P_PrepareSlopeToWallTransfer(mo, transferslope); // This isn't the end of it; momz will be scaled based upon the angle of movement after collision, and then it'll be applied. - } -#endif - // blocked move moved = false; @@ -2188,18 +2178,35 @@ void P_XYMovement(mobj_t *mo) } else if (player || mo->flags & (MF_SLIDEME|MF_PUSHABLE)) { // try to slide along it +#ifdef ESLOPE + // Wall transfer part 1. + pslope_t *transferslope = 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 + { + transferslope = ((mo->standingslope) ? mo->standingslope : oldslope); + transfermomz = P_GetWallTransferMomZ(mo, transferslope); + } +#endif + P_SlideMove(mo); xmove = ymove = 0; + #ifdef ESLOPE - if (transfermomz && transferslope) // Scale transfer momentum based on how head-on it is to the slope. + // Wall transfer part 2. + if (transfermomz && transferslope) // Are we "transferring onto the wall" (really just a disguised vertical launch)? { - angle_t relation = (transferslope->xydirection - R_PointToAngle2(0, 0, mo->momx, mo->momy)); - fixed_t scalefactor = abs(FINESINE((relation >> ANGLETOFINESHIFT) & FINEMASK)); - transfermomz = FixedMul(transfermomz, scalefactor); - if ((P_MobjFlip(mo)*(transfermomz - mo->momz)) > 2*FRACUNIT) // Do the actual launch! + 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); + else // Give it for free, I guess. + relation = ANGLE_90; + transfermomz = FixedMul(transfermomz, + abs(FINESINE((relation >> ANGLETOFINESHIFT) & FINEMASK))); + if (P_MobjFlip(mo)*(transfermomz - mo->momz) > 2*FRACUNIT) // Do the actual launch! { - mo->standingslope = NULL; mo->momz = transfermomz; + mo->standingslope = NULL; } } #endif diff --git a/src/p_slopes.c b/src/p_slopes.c index 3afd51cba..f480b6e4f 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -805,10 +805,12 @@ void P_SlopeLaunch(mobj_t *mo) } // -// P_SlopeToWallTransfer +// P_GetWallTransferMomZ // -// Handles slope-to-wall transfer for objects. -fixed_t P_PrepareSlopeToWallTransfer(mobj_t *mo, pslope_t *slope) +// 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) { vector3_t slopemom, axis; angle_t ang; diff --git a/src/p_slopes.h b/src/p_slopes.h index ab102fcc0..f59c5b767 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -37,7 +37,7 @@ fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y); void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_SlopeLaunch(mobj_t *mo); -fixed_t P_PrepareSlopeToWallTransfer(mobj_t *mo, pslope_t *slope); +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);