diff --git a/src/d_player.h b/src/d_player.h index def13cc71..8360714be 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -316,8 +316,8 @@ typedef enum k_stealingtimer, // You are stealing an item, this is your timer k_stolentimer, // You are being stolen from, this is your timer k_superring, // Spawn rings on top of you every tic! - k_sneakertimer, // Duration of the Sneaker Boost itself - k_levelbooster, // Duration of a level booster's boost (same as sneaker, but separated for boost stacking) + k_sneakertimer, // Duration of a Sneaker Boost (from Sneakers or level boosters) + k_numsneakers, // Number of stacked sneaker effects k_growshrinktimer, // > 0 = Big, < 0 = small k_squishedtimer, // Squished frame timer k_rocketsneakertimer, // Rocket Sneaker duration timer @@ -391,9 +391,6 @@ typedef enum NUMKARTHUD } karthudtype_t; -// QUICKLY GET EITHER SNEAKER OR LEVEL BOOSTER SINCE THEY ARE FUNCTIONALLY IDENTICAL -#define EITHERSNEAKER(p) (p->kartstuff[k_sneakertimer] || p->kartstuff[k_levelbooster]) - // QUICKLY GET RING TOTAL, INCLUDING RINGS CURRENTLY IN THE PICKUP ANIMATION #define RINGTOTAL(p) (p->kartstuff[k_rings] + p->kartstuff[k_pickuprings]) diff --git a/src/dehacked.c b/src/dehacked.c index 369be7a5c..8564e52db 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8389,7 +8389,7 @@ static const char *const KARTSTUFF_LIST[] = { "STOLENTIMER", "SUPERRING", "SNEAKERTIMER", - "LEVELBOOSTER", + "NUMSNEAKERS", "GROWSHRINKTIMER", "SQUISHEDTIMER", "ROCKETSNEAKERTIMER", diff --git a/src/g_game.c b/src/g_game.c index cca6c50ed..ebbf60e3d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1430,7 +1430,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { // forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward. axis = JoyAxis(AXISMOVE, ssplayer); - if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || EITHERSNEAKER(player)) + if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_sneakertimer]) { cmd->buttons |= BT_ACCELERATE; forward = forwardmove[1]; // 50 @@ -5104,7 +5104,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) || (players[displayplayers[0]].respawn.state != RESPAWNST_NONE) // Respawning || (players[displayplayers[0]].spectator || objectplacing)) // Not a physical player && !(players[displayplayers[0]].kartstuff[k_spinouttimer] - && (players[displayplayers[0]].kartstuff[k_sneakertimer] || players[displayplayers[0]].kartstuff[k_levelbooster]))) // Spinning and boosting cancels out spinout + && players[displayplayers[0]].kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout localangle[0] += (cmd->angleturn<<16); if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) diff --git a/src/k_kart.c b/src/k_kart.c index c24e8aeff..7d341d5c5 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -78,6 +78,48 @@ player_t *K_GetItemBoxPlayer(mobj_t *mobj) return player; } +// Angle reflection used by springs & speed pads +angle_t K_ReflectAngle(angle_t yourangle, angle_t theirangle, fixed_t yourspeed, fixed_t theirspeed) +{ + INT32 angoffset; + boolean subtract = false; + + angoffset = yourangle - theirangle; + + if ((angle_t)angoffset > ANGLE_180) + { + // Flip on wrong side + angoffset = InvAngle((angle_t)angoffset); + subtract = !subtract; + } + + // Fix going directly against the spring's angle sending you the wrong way + if ((angle_t)angoffset > ANGLE_90) + { + angoffset = ANGLE_180 - angoffset; + } + + // Offset is reduced to cap it (90 / 2 = max of 45 degrees) + angoffset /= 2; + + // Reduce further based on how slow your speed is compared to the spring's speed + // (set both to 0 to ignore this) + if (theirspeed != 0 && yourspeed != 0) + { + if (theirspeed > yourspeed) + { + angoffset = FixedDiv(angoffset, FixedDiv(theirspeed, yourspeed)); + } + } + + if (subtract) + angoffset = (signed)(theirangle) - angoffset; + else + angoffset = (signed)(theirangle) + angoffset; + + return (angle_t)angoffset; +} + //{ SRB2kart Net Variables void K_RegisterKartStuff(void) @@ -1883,7 +1925,7 @@ void K_MomentumToFacing(player_t *player) boolean K_ApplyOffroad(player_t *player) { - if (player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || EITHERSNEAKER(player)) + if (player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || player->kartstuff[k_sneakertimer]) return false; return true; } @@ -1920,29 +1962,44 @@ static void K_GetKartBoostPower(player_t *player) accelboost += (a) / numboosts; \ } - if (player->kartstuff[k_levelbooster]) // Level boosters - ADDBOOST(FRACUNIT/2, 8*FRACUNIT); // + 50% top speed, + 800% acceleration - if (player->kartstuff[k_sneakertimer]) // Sneaker - ADDBOOST(FRACUNIT/2, 8*FRACUNIT); // + 50% top speed, + 800% acceleration + { + UINT8 i; + for (i = 0; i < player->kartstuff[k_numsneakers]; i++) + { + ADDBOOST(FRACUNIT/2, 8*FRACUNIT); // + 50% top speed, + 800% acceleration + } + } if (player->kartstuff[k_invincibilitytimer]) // Invincibility - ADDBOOST((3*FRACUNIT)/8, 3*FRACUNIT); // + 37.5% top speed, + 300% acceleration + { + ADDBOOST(3*FRACUNIT/8, 3*FRACUNIT); // + 37.5% top speed, + 300% acceleration + } if (player->kartstuff[k_flamedash]) // Flame Shield dash + { ADDBOOST(K_FlameShieldDashVar(player->kartstuff[k_flamedash]), 3*FRACUNIT); // + infinite top speed, + 300% acceleration + } if (player->kartstuff[k_startboost]) // Startup Boost + { ADDBOOST(FRACUNIT/4, 6*FRACUNIT); // + 25% top speed, + 600% acceleration + } if (player->kartstuff[k_driftboost]) // Drift Boost + { ADDBOOST(FRACUNIT/4, 4*FRACUNIT); // + 25% top speed, + 400% acceleration + } if (player->kartstuff[k_ringboost]) // Ring Boost + { ADDBOOST(FRACUNIT/5, 4*FRACUNIT); // + 20% top speed, + 400% acceleration + } if (player->kartstuff[k_eggmanexplode]) // Ready-to-explode - ADDBOOST(FRACUNIT/5, FRACUNIT); // + 20% top speed, + 100% acceleration + { + ADDBOOST(3*FRACUNIT/20, FRACUNIT); // + 15% top speed, + 100% acceleration + } if (player->kartstuff[k_draftpower] > 0) // Drafting { @@ -1955,9 +2012,13 @@ static void K_GetKartBoostPower(player_t *player) // value smoothing if (speedboost > player->kartstuff[k_speedboost]) + { player->kartstuff[k_speedboost] = speedboost; + } else + { player->kartstuff[k_speedboost] += (speedboost - player->kartstuff[k_speedboost]) / (TICRATE/2); + } player->kartstuff[k_accelboost] = accelboost; player->kartstuff[k_numboosts] = numboosts; @@ -2080,7 +2141,7 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove // 0 with no gas, and // -25 when only braking. - if (EITHERSNEAKER(player)) + if (player->kartstuff[k_sneakertimer]) forwardmove = 50; finalspeed *= forwardmove/25; @@ -2164,7 +2225,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto K_PlayHitEmSound(source); player->kartstuff[k_sneakertimer] = 0; - //player->kartstuff[k_levelbooster] = 0; + player->kartstuff[k_numsneakers] = 0; player->kartstuff[k_driftboost] = 0; player->kartstuff[k_ringboost] = 0; @@ -2311,7 +2372,7 @@ void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor) #endif player->kartstuff[k_sneakertimer] = 0; - player->kartstuff[k_levelbooster] = 0; + player->kartstuff[k_numsneakers] = 0; player->kartstuff[k_driftboost] = 0; player->kartstuff[k_ringboost] = 0; @@ -2438,7 +2499,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b player->mo->momx = player->mo->momy = 0; player->kartstuff[k_sneakertimer] = 0; - player->kartstuff[k_levelbooster] = 0; + player->kartstuff[k_numsneakers] = 0; player->kartstuff[k_driftboost] = 0; player->kartstuff[k_ringboost] = 0; @@ -3863,13 +3924,28 @@ void K_DoSneaker(player_t *player, INT32 type) if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) { - S_StartSound(player->mo, sfx_cdfm01); + const sfxenum_t normalsfx = sfx_cdfm01; + const sfxenum_t smallsfx = sfx_cdfm40; + sfxenum_t sfx = normalsfx; + + if (player->kartstuff[k_numsneakers]) + { + // Use a less annoying sound when stacking sneakers. + sfx = smallsfx; + } + + S_StopSoundByID(player->mo, normalsfx); + S_StopSoundByID(player->mo, smallsfx); + S_StartSound(player->mo, sfx); + K_SpawnDashDustRelease(player); if (intendedboost > player->kartstuff[k_speedboost]) player->karthud[khud_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->kartstuff[k_speedboost]), intendedboost)); + + player->kartstuff[k_numsneakers]++; } - if (!EITHERSNEAKER(player)) + if (!player->kartstuff[k_sneakertimer]) { if (type == 2) { @@ -3903,10 +3979,10 @@ void K_DoSneaker(player_t *player, INT32 type) { player->pflags |= PF_ATTACKDOWN; K_PlayBoostTaunt(player->mo); - player->kartstuff[k_sneakertimer] = sneakertime; + } - else - player->kartstuff[k_levelbooster] = sneakertime; + + player->kartstuff[k_sneakertimer] = sneakertime; // set angle for spun out players: player->kartstuff[k_boostangle] = (INT32)player->mo->angle; @@ -4012,7 +4088,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) thrust = 72<player->kartstuff[k_pogospring] != 2) { - if (EITHERSNEAKER(mo->player)) + if (mo->player->kartstuff[k_sneakertimer]) thrust = FixedMul(thrust, (5*FRACUNIT)/4); else if (mo->player->kartstuff[k_invincibilitytimer]) thrust = FixedMul(thrust, (9*FRACUNIT)/8); @@ -5215,7 +5291,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->speed > 0) { // Speed lines - if (EITHERSNEAKER(player) || player->kartstuff[k_ringboost] + if (player->kartstuff[k_sneakertimer] || player->kartstuff[k_ringboost] || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost] || player->kartstuff[k_eggmanexplode]) { @@ -5431,7 +5507,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { if ((P_IsObjectOnGround(player->mo) || (player->kartstuff[k_spinouttype] != 0)) - && (!EITHERSNEAKER(player))) + && (!player->kartstuff[k_sneakertimer])) { player->kartstuff[k_spinouttimer]--; if (player->kartstuff[k_wipeoutslow] > 1) @@ -5470,15 +5546,19 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->kartstuff[k_ringboost]--; if (player->kartstuff[k_sneakertimer]) + { player->kartstuff[k_sneakertimer]--; - if (player->kartstuff[k_levelbooster]) - player->kartstuff[k_levelbooster]--; + if (player->kartstuff[k_sneakertimer] <= 0) + { + player->kartstuff[k_numsneakers] = 0; + } + } if (player->kartstuff[k_flamedash]) player->kartstuff[k_flamedash]--; - if (EITHERSNEAKER(player) && player->kartstuff[k_wipeoutslow] > 0 && player->kartstuff[k_wipeoutslow] < wipeoutslowtime+1) + if (player->kartstuff[k_sneakertimer] && player->kartstuff[k_wipeoutslow] > 0 && player->kartstuff[k_wipeoutslow] < wipeoutslowtime+1) player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1; if (player->kartstuff[k_floorboost]) @@ -6171,7 +6251,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) return turnvalue; } - if (EITHERSNEAKER(player) || player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_growshrinktimer] > 0) + if (player->kartstuff[k_sneakertimer] || player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_growshrinktimer] > 0) { turnvalue = 5*turnvalue/4; } @@ -6410,7 +6490,7 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_driftend] = 0; } - if ((!EITHERSNEAKER(player)) + if ((!player->kartstuff[k_sneakertimer]) || (!player->cmd.driftturn) || (!player->kartstuff[k_aizdriftstrat]) || (player->cmd.driftturn > 0) != (player->kartstuff[k_aizdriftstrat] > 0)) @@ -6706,7 +6786,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { K_DoSneaker(player, 2); K_PlayBoostTaunt(player->mo); - player->kartstuff[k_rocketsneakertimer] -= 2*TICRATE; + player->kartstuff[k_rocketsneakertimer] -= 3*TICRATE; if (player->kartstuff[k_rocketsneakertimer] < 1) player->kartstuff[k_rocketsneakertimer] = 1; } diff --git a/src/k_kart.h b/src/k_kart.h index 7a3a3581c..af247029d 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -13,6 +13,7 @@ #define KART_FULLTURN 800 player_t *K_GetItemBoxPlayer(mobj_t *mobj); +angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed); void K_RegisterKartStuff(void); diff --git a/src/p_inter.c b/src/p_inter.c index 49d3546ce..916f11383 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3153,6 +3153,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da || inflictor->type == MT_SMK_THWOMP || inflictor->player)) { player->kartstuff[k_sneakertimer] = 0; + player->kartstuff[k_numsneakers] = 0; K_SpinPlayer(player, source, 1, inflictor, false); K_KartPainEnergyFling(player); diff --git a/src/p_map.c b/src/p_map.c index 00d93efe7..4ef258ebb 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -324,39 +324,10 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) // This makes it a bit more interesting & unique than just being a speed boost in a pre-defined direction if (savemomx || savemomy) { - angle_t momang; - INT32 angoffset; - boolean subtract = false; - - momang = R_PointToAngle2(0, 0, savemomx, savemomy); - - angoffset = momang; - angoffset -= spring->angle; // Subtract - - // Flip on wrong side - if ((angle_t)angoffset > ANGLE_180) - { - angoffset = InvAngle((angle_t)angoffset); - subtract = !subtract; - } - - // Fix going directly against the spring's angle sending you the wrong way - if ((spring->angle - momang) > ANGLE_90) - angoffset = ANGLE_180 - angoffset; - - // Offset is reduced to cap it (90 / 2 = max of 45 degrees) - angoffset /= 2; - - // Reduce further based on how slow your speed is compared to the spring's speed - if (finalSpeed > objectSpeed) - angoffset = FixedDiv(angoffset, FixedDiv(finalSpeed, objectSpeed)); - - if (subtract) - angoffset = (signed)(spring->angle) - angoffset; - else - angoffset = (signed)(spring->angle) + angoffset; - - finalAngle = angoffset; + finalAngle = K_ReflectAngle( + R_PointToAngle2(0, 0, savemomx, savemomy), finalAngle, + objectSpeed, finalSpeed + ); } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 935ecb14a..4754172f6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8348,10 +8348,9 @@ void P_MobjThinker(mobj_t *mobj) if (p) { - if (p->kartstuff[k_sneakertimer] > mobj->movecount - || p->kartstuff[k_levelbooster] > mobj->movecount) + if (p->kartstuff[k_sneakertimer] > mobj->movecount) P_SetMobjState(mobj, S_BOOSTFLAME); - mobj->movecount = max(p->kartstuff[k_sneakertimer], p->kartstuff[k_levelbooster]); + mobj->movecount = p->kartstuff[k_sneakertimer]; } } diff --git a/src/p_spec.c b/src/p_spec.c index 03c08fdee..aa5d52927 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4052,52 +4052,38 @@ DoneSection2: case 5: // Speed pad w/o spin case 6: // Speed pad w/ spin - if (player->kartstuff[k_dashpadcooldown] != 0) + if (player->kartstuff[k_floorboost] != 0) + { + player->kartstuff[k_floorboost] = 2; break; + } i = P_FindSpecialLineFromTag(4, sector->tag, -1); if (i != -1) { - angle_t lineangle; - fixed_t linespeed; - - lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); - linespeed = P_AproxDistance(lines[i].v2->x-lines[i].v1->x, lines[i].v2->y-lines[i].v1->y); + angle_t lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); + fixed_t linespeed = P_AproxDistance(lines[i].v2->x-lines[i].v1->x, lines[i].v2->y-lines[i].v1->y); + fixed_t playerspeed = P_AproxDistance(player->mo->momx, player->mo->momy); // SRB2Kart: Scale the speed you get from them! // This is scaled differently from other horizontal speed boosts from stuff like springs, because of how this is used for some ramp jumps. if (player->mo->scale > mapobjectscale) - linespeed = FixedMul(linespeed, mapobjectscale + (player->mo->scale - mapobjectscale)); - - if (!(lines[i].flags & ML_EFFECT4)) { - P_UnsetThingPosition(player->mo); - if (roversector) // make FOF speed pads work - { - player->mo->x = roversector->soundorg.x; - player->mo->y = roversector->soundorg.y; - } - else - { - player->mo->x = sector->soundorg.x; - player->mo->y = sector->soundorg.y; - } - P_SetThingPosition(player->mo); + linespeed = FixedMul(linespeed, mapobjectscale + (player->mo->scale - mapobjectscale)); } - P_InstaThrust(player->mo, lineangle, linespeed); + lineangle = K_ReflectAngle( + R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy), lineangle, + playerspeed, linespeed + ); + + P_InstaThrust(player->mo, lineangle, max(linespeed, 2*playerspeed)); player->kartstuff[k_dashpadcooldown] = TICRATE/3; player->kartstuff[k_pogospring] = 0; - S_StartSound(player->mo, sfx_spdpad); - - { - sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons - if (cv_kartvoices.value) - S_StartSound(player->mo, sfx_kbost1+pick); - //K_TauntVoiceTimers(player); - } + player->kartstuff[k_floorboost] = 2; + S_StartSound(player->mo, sfx_cdfm62); } break; diff --git a/src/p_user.c b/src/p_user.c index cc98d46ee..ed31c1d11 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -6251,7 +6251,7 @@ static void P_MovePlayer(player_t *player) //////////////////////////// // SRB2kart - Drifting smoke and fire - if ((EITHERSNEAKER(player) || player->kartstuff[k_flamedash]) + if ((player->kartstuff[k_sneakertimer] || player->kartstuff[k_flamedash]) && onground && (leveltime & 1)) K_SpawnBoostTrail(player);