diff --git a/src/p_mobj.c b/src/p_mobj.c index 7d609a9dd..6a0dc4f01 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1625,7 +1625,6 @@ void P_XYMovement(mobj_t *mo) S_StartSound(mo, mo->info->activesound); //{ SRB2kart - Orbinaut, Ballhog - // Ballhog dies on contact with walls if (mo->type == MT_ORBINAUT || mo->type == MT_BALLHOG) { mobj_t *fx; @@ -1735,12 +1734,44 @@ void P_XYMovement(mobj_t *mo) return; } } - if (mo->flags & MF_SLIDEME|MF_PUSHABLE) - { + if (player || mo->flags & MF_SLIDEME|MF_PUSHABLE) + { // try to slide along it +#ifdef WALLTRANSFER + // 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); + 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); + } +#endif + + P_SlideMove(mo); if (P_MobjWasRemoved(mo)) return; xmove = ymove = 0; + +#ifdef WALLTRANSFER + // Wall transfer part 2. + if (transfermomz && transferslope) // Are we "transferring onto the wall" (really just a disguised vertical 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->momz = transfermomz; + mo->standingslope = NULL; + } + } +#endif } // } diff --git a/src/p_slopes.c b/src/p_slopes.c index bca62a54d..ffb31f21e 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1015,6 +1015,41 @@ void P_SlopeLaunch(mobj_t *mo) mo->terrain = NULL; } +#ifdef WALLTRANSFER +// +// P_GetWallTransferMomZ +// +// 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; + + if (mo->standingslope->flags & SL_NOPHYSICS) + return 0; + + // 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); + if (ang > ANGLE_90 && ang < ANGLE_180) + 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); + + axis.x = -slope->d.y; + axis.y = slope->d.x; + axis.z = 0; + + FV3_Rotate(&slopemom, &axis, ang >> ANGLETOFINESHIFT); + + return 2*(slopemom.z/3); +} +#endif + // Function to help handle landing on slopes void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) { diff --git a/src/p_slopes.h b/src/p_slopes.h index 827b32ae2..021a66ccc 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -101,6 +101,9 @@ boolean P_CanApplySlopePhysics(mobj_t *mo, pslope_t *slope); void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_SlopeLaunch(mobj_t *mo); +#ifdef WALLTRANSFER +fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope); +#endif void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope); void P_ButteredSlope(mobj_t *mo);