diff --git a/src/d_player.h b/src/d_player.h index 85eec2e3e..86f4c718b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -443,6 +443,8 @@ typedef struct player_s fixed_t spindashspeed; // Spindash release speed UINT8 spindashboost; // Spindash release boost timer + fixed_t fastfall; // Fast fall momentum + UINT8 numboosts; // Count of how many boosts are being stacked, for after image spawning fixed_t boostpower; // Base boost value, for offroad fixed_t speedboost; // Boost value smoothing for max speed diff --git a/src/k_kart.c b/src/k_kart.c index 189b946cd..b31556fc4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9025,13 +9025,17 @@ static INT32 K_FlameShieldMax(player_t *player) boolean K_PlayerEBrake(player_t *player) { + if (player->fastfall != 0) + { + return true; + } + return (K_GetKartButtons(player) & BT_EBRAKEMASK) == BT_EBRAKEMASK - && P_IsObjectOnGround(player->mo) == true - && player->drift == 0 - && player->spinouttimer == 0 - && player->justbumped == 0 - && player->spindashboost == 0 - && player->nocontrol == 0; + && player->drift == 0 + && player->spinouttimer == 0 + && player->justbumped == 0 + && player->spindashboost == 0 + && player->nocontrol == 0; } SINT8 K_Sliptiding(player_t *player) @@ -9053,9 +9057,8 @@ void K_KartEbrakeVisuals(player_t *p) mobj_t *spdl; fixed_t sx, sy; - if (K_PlayerEBrake(p)) + if (K_PlayerEBrake(p) == true) { - if (p->ebrakefor % 20 == 0) { wave = P_SpawnMobj(p->mo->x, p->mo->y, p->mo->z, MT_SOFTLANDING); @@ -9092,7 +9095,6 @@ void K_KartEbrakeVisuals(player_t *p) K_FlipFromObject(p->mo->hprev, p->mo); } - if (!p->spindash) { // Spawn downwards fastline @@ -9233,6 +9235,7 @@ static void K_KartSpindashWind(mobj_t *parent) static void K_KartSpindash(player_t *player) { + const boolean onGround = P_IsObjectOnGround(player->mo); const INT16 MAXCHARGETIME = K_GetSpindashChargeTime(player); UINT16 buttons = K_GetKartButtons(player); boolean spawnWind = (leveltime % 2 == 0); @@ -9296,6 +9299,36 @@ static void K_KartSpindash(player_t *player) return; } + // Handle fast falling behaviors first. + if (onGround == false) + { + // Update fastfall. + player->fastfall = player->mo->momz; + player->spindash = 0; + return; + } + else if (player->fastfall != 0) + { + // Handle fastfall bounce. + const fixed_t maxBounce = player->mo->scale * 10; + const fixed_t minBounce = player->mo->scale * 2; + fixed_t bounce = abs(player->fastfall) / 4; + + if (bounce > maxBounce) + { + bounce = maxBounce; + } + + if (bounce > minBounce) + { + S_StartSound(player->mo, sfx_ffbonc); + player->mo->momz = bounce * P_MobjFlip(player->mo); + } + + player->fastfall = 0; + return; + } + if (player->speed == 0 && player->steering != 0 && leveltime % 8 == 0) { // Rubber burn turn sfx diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 1d5f6bee7..19b9b4463 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -274,6 +274,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->spindashspeed); else if (fastcmp(field,"spindashboost")) lua_pushinteger(L, plr->spindashboost); + else if (fastcmp(field,"fastfall")) + lua_pushfixed(L, plr->fastfall); else if (fastcmp(field,"numboosts")) lua_pushinteger(L, plr->numboosts); else if (fastcmp(field,"boostpower")) @@ -632,6 +634,8 @@ static int player_set(lua_State *L) plr->spindashspeed = luaL_checkinteger(L, 3); else if (fastcmp(field,"spindashboost")) plr->spindashboost = luaL_checkinteger(L, 3); + else if (fastcmp(field,"fastfall")) + plr->fastfall = luaL_checkfixed(L, 3); else if (fastcmp(field,"numboosts")) plr->numboosts = luaL_checkinteger(L, 3); else if (fastcmp(field,"boostpower")) diff --git a/src/p_map.c b/src/p_map.c index d667b0346..0bf029ab2 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2463,9 +2463,8 @@ fixed_t P_GetThingStepUp(mobj_t *thing) const fixed_t maxstepmove = P_BaseStepUp(); fixed_t maxstep = maxstepmove; - if (thing->type == MT_SKIM) + if (thing->player && thing->player->fastfall != 0) { - // Skim special (not needed for kart?) return 0; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 8e6e0eb2a..e6c003829 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1132,6 +1132,12 @@ fixed_t P_GetMobjGravity(mobj_t *mo) { gravityadd = FixedMul(TUMBLEGRAVITY, gravityadd); } + + if (mo->player->fastfall != 0) + { + // Fast falling + gravityadd *= 4; + } } else { @@ -1761,7 +1767,9 @@ void P_XYMovement(mobj_t *mo) if (moved && oldslope && !(mo->flags & MF_NOCLIPHEIGHT)) { // Check to see if we ran off - if (oldslope != mo->standingslope) { // First, compare different slopes + if (oldslope != mo->standingslope) + { + // First, compare different slopes angle_t oldangle, newangle; angle_t moveangle = K_MomentumAngle(mo); @@ -1773,7 +1781,9 @@ void P_XYMovement(mobj_t *mo) newangle = 0; // Now compare the Zs of the different quantizations - if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) { // Allow for a bit of sticking - this value can be adjusted later + if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) + { + // Allow for a bit of sticking - this value can be adjusted later mo->standingslope = oldslope; P_SetPitchRollFromSlope(mo, mo->standingslope); P_SlopeLaunch(mo); @@ -1781,26 +1791,37 @@ void P_XYMovement(mobj_t *mo) //CONS_Printf("launched off of slope - "); } - /*CONS_Printf("old angle %f - new angle %f = %f\n", - FIXED_TO_FLOAT(AngleFixed(oldangle)), - FIXED_TO_FLOAT(AngleFixed(newangle)), - FIXED_TO_FLOAT(AngleFixed(oldangle-newangle)) - );*/ - // Sryder 2018-11-26: Don't launch here if it's a slope without physics, we stick to those like glue anyway - } else if (predictedz-mo->z > abs(slopemom.z/2) - && !(mo->standingslope->flags & SL_NOPHYSICS)) { // Now check if we were supposed to stick to this slope + /* + CONS_Printf("old angle %f - new angle %f = %f\n", + FIXED_TO_FLOAT(AngleFixed(oldangle)), + FIXED_TO_FLOAT(AngleFixed(newangle)), + FIXED_TO_FLOAT(AngleFixed(oldangle-newangle)) + ); + */ + + } + else if (predictedz - mo->z > abs(slopemom.z/2) + && P_CanApplySlopePhysics(mo, mo->standingslope) == true) // Sryder 2018-11-26: Don't launch here if it's a slope without physics, we stick to those like glue anyway + { + // Now check if we were supposed to stick to this slope //CONS_Printf("%d-%d > %d\n", (predictedz), (mo->z), (slopemom.z/2)); P_SlopeLaunch(mo); } - } else if (moved && mo->standingslope && predictedz) { + } + else if (moved && mo->standingslope && predictedz) + { angle_t moveangle = K_MomentumAngle(mo); 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)), - FIXED_TO_FLOAT(predictedz) - );*/ - if (ANGLE_MAX-newangle > ANG30 && newangle > ANGLE_180) { + /* + CONS_Printf("flat to angle %f - predicted z of %f\n", + FIXED_TO_FLOAT(AngleFixed(ANGLE_MAX-newangle)), + FIXED_TO_FLOAT(predictedz) + ); + */ + + if (ANGLE_MAX-newangle > ANG30 && newangle > ANGLE_180) + { mo->momz = P_MobjFlip(mo)*FRACUNIT/2; mo->z = predictedz + P_MobjFlip(mo); mo->standingslope = NULL; diff --git a/src/p_saveg.c b/src/p_saveg.c index 5569f24d5..22e94a419 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -280,6 +280,8 @@ static void P_NetArchivePlayers(void) WRITEFIXED(save_p, players[i].spindashspeed); WRITEUINT8(save_p, players[i].spindashboost); + WRITEFIXED(save_p, players[i].fastfall); + WRITEUINT8(save_p, players[i].numboosts); WRITEFIXED(save_p, players[i].boostpower); WRITEFIXED(save_p, players[i].speedboost); @@ -565,6 +567,8 @@ static void P_NetUnArchivePlayers(void) players[i].spindashspeed = READFIXED(save_p); players[i].spindashboost = READUINT8(save_p); + players[i].fastfall = READFIXED(save_p); + players[i].numboosts = READUINT8(save_p); players[i].boostpower = READFIXED(save_p); players[i].speedboost = READFIXED(save_p); diff --git a/src/p_slopes.c b/src/p_slopes.c index 3c124a550..6c749506b 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -894,6 +894,40 @@ 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; } +// Returns true if we should run slope physics code on an object. +boolean P_CanApplySlopePhysics(mobj_t *mo, pslope_t *slope) +{ + if (slope == NULL || mo == NULL || P_MobjWasRemoved(mo) == true) + { + // Invalid input. + return false; + } + + if (slope->flags & SL_NOPHYSICS) + { + // Physics are turned off. + return false; + } + + if (slope->normal.x == 0 && slope->normal.y == 0) + { + // Flat slope? No such thing, man. No such thing. + return false; + } + + if (mo->player != NULL) + { + if (K_PlayerEBrake(mo->player) == true) + { + // Spindash negates slopes. + return false; + } + } + + // We can do slope physics. + return true; +} + // // P_QuantizeMomentumToSlope // @@ -923,19 +957,13 @@ void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) slope->zangle = InvAngle(slope->zangle); } -// SRB2Kart: This fixes all slope-based jumps for different scales in Kart automatically without map tweaking. -// However, they will always feel off every single time... see for yourself: https://cdn.discordapp.com/attachments/270211093761097728/484924392128774165/kart0181.gif -//#define GROWNEVERMISSES - // // P_SlopeLaunch // // Handles slope ejection for objects void P_SlopeLaunch(mobj_t *mo) { - if (!(mo->standingslope->flags & SL_NOPHYSICS) // If there's physics, time for launching. - && (mo->standingslope->normal.x != 0 - || mo->standingslope->normal.y != 0)) + if (P_CanApplySlopePhysics(mo, mo->standingslope) == true) // If there's physics, time for launching. { // Double the pre-rotation Z, then halve the post-rotation Z. This reduces the // vertical launch given from slopes while increasing the horizontal launch @@ -946,19 +974,9 @@ void P_SlopeLaunch(mobj_t *mo) slopemom.z = mo->momz; P_QuantizeMomentumToSlope(&slopemom, mo->standingslope); -#ifdef GROWNEVERMISSES - { - const fixed_t xyscale = mapobjectscale + (mapobjectscale - mo->scale); - const fixed_t zscale = mapobjectscale + (mapobjectscale - mo->scale); - mo->momx = FixedMul(slopemom.x, xyscale); - mo->momy = FixedMul(slopemom.y, xyscale); - mo->momz = FixedMul(slopemom.z, zscale); - } -#else mo->momx = slopemom.x; mo->momy = slopemom.y; mo->momz = slopemom.z; -#endif mo->eflags |= MFE_SLOPELAUNCHED; } @@ -984,14 +1002,19 @@ 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 (P_CanApplySlopePhysics(mo, mo->standingslope) == false) + { + return false; + } // 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 + { + // hard cap of directly upwards + ang = ((slope->zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); + } slopemom.x = mo->momx; slopemom.y = mo->momy; @@ -1010,13 +1033,16 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) 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. + + if (P_CanApplySlopePhysics(thing, slope) == false) // No physics, no need to make anything complicated. + { if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope { thing->standingslope = slope; P_SetPitchRollFromSlope(thing, slope); thing->momz = -P_MobjFlip(thing); } + return; } @@ -1026,7 +1052,9 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) P_ReverseQuantizeMomentumToSlope(&mom, slope); - if (P_MobjFlip(thing)*mom.z < 0) { // falling, land on slope + if (P_MobjFlip(thing)*mom.z < 0) + { + // falling, land on slope thing->momx = mom.x; thing->momy = mom.y; thing->standingslope = slope; @@ -1041,27 +1069,29 @@ void P_ButteredSlope(mobj_t *mo) { fixed_t thrust; - if (!mo->standingslope) - return; - - if (mo->standingslope->flags & SL_NOPHYSICS) - return; // No physics, no butter. - if (mo->flags & (MF_NOCLIPHEIGHT|MF_NOGRAVITY)) return; // don't slide down slopes if you can't touch them or you're not affected by gravity - if (mo->player) { - // SRB2Kart - spindash negates slopes - if (K_PlayerEBrake(mo->player)) - return; + if (P_CanApplySlopePhysics(mo, mo->standingslope) == false) + return; // No physics, no butter. - // Changed in kart to only not apply physics on very slight slopes (I think about 4 degree angles) + if (mo->player != NULL) + { if (abs(mo->standingslope->zdelta) < FRACUNIT/21) - return; // Don't slide on non-steep slopes + { + // Don't slide on non-steep slopes. + // Changed in Ring Racers to only not apply physics on very slight slopes. + // (I think about 4 degree angles.) + return; + } - // This only means you can be stopped on slopes that aren't steeper than 45 degrees - if (abs(mo->standingslope->zdelta) < FRACUNIT/2 && !(mo->player->rmomx || mo->player->rmomy)) - return; // Allow the player to stand still on slopes below a certain steepness + if (abs(mo->standingslope->zdelta) < FRACUNIT/2 + && !(mo->player->rmomx || mo->player->rmomy)) + { + // Allow the player to stand still on slopes below a certain steepness. + // 45 degree angle steep, to be exact. + return; + } } thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 5 / 4 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); diff --git a/src/p_slopes.h b/src/p_slopes.h index a72ca1776..6f9764fa9 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -82,6 +82,7 @@ fixed_t P_GetFFloorBottomZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y); fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y); // Lots of physics-based bullshit +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); diff --git a/src/p_user.c b/src/p_user.c index 4030232f7..b277dacff 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1905,17 +1905,27 @@ static void P_3dMovement(player_t *player) } if ((totalthrust.x || totalthrust.y) - && player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) > FRACUNIT/2) { + && player->mo->standingslope != NULL + && (!(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) - 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) { + 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); } - } else { // Direction goes up, so thrustangle needs to face away - if (thrustangle > ANGLE_90 && thrustangle < ANGLE_270) { + } + else + { + // Direction goes up, so thrustangle needs to face away + if (thrustangle > ANGLE_90 && thrustangle < ANGLE_270) + { P_QuantizeMomentumToSlope(&totalthrust, player->mo->standingslope); } } diff --git a/src/sounds.c b/src/sounds.c index 7cbc0e8c0..9240577fa 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1110,7 +1110,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"kdtrg3", false, 64, 80, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // High energy, SF_X2AWAYSOUND|SF_X8AWAYSOUND // SRB2kart - Grow/invinc clash - {"parry", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X8AWAYSOUND + {"parry", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X8AWAYSOUND + + {"ffbonc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SRB2Kart - Engine sounds // Engine class A diff --git a/src/sounds.h b/src/sounds.h index 6d1c51f57..c5eb638e0 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1176,6 +1176,9 @@ typedef enum // SRB2Kart - Powerup clash SFX sfx_parry, + // Fast fall bounce + sfx_ffbonc, + // Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy... // Engine class A - Low Speed, Low Weight sfx_krta00,