Tumble when not landing upright on slopes

This commit is contained in:
Sally Coolatta 2022-03-28 17:10:27 -04:00
parent 2f3064c225
commit f3bb8833a1
6 changed files with 109 additions and 10 deletions

View file

@ -3407,6 +3407,89 @@ void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source)
P_StartQuake(64<<FRACBITS, 10);
}
static angle_t K_TumbleSlope(mobj_t *mobj, angle_t pitch, angle_t roll)
{
fixed_t pitchMul = -FINESINE(mobj->angle >> ANGLETOFINESHIFT);
fixed_t rollMul = FINECOSINE(mobj->angle >> ANGLETOFINESHIFT);
return FixedMul(pitch, pitchMul) + FixedMul(roll, rollMul);
}
#define STEEP_VAL (ANG60)
void K_CheckSlopeTumble(player_t *player, angle_t oldPitch, angle_t oldRoll)
{
fixed_t gravityadjust;
angle_t oldSlope, newSlope;
angle_t slopeDelta;
angle_t oldSteepness;
// If you don't land upright on a slope, then you tumble,
// kinda like Kirby Air Ride
if (player->tumbleBounces)
{
// Already tumbling.
return;
}
oldSlope = K_TumbleSlope(player->mo, oldPitch, oldRoll);
oldSteepness = oldSlope;
if (oldSteepness > ANGLE_180)
{
oldSteepness = InvAngle(oldSteepness);
}
if (oldSteepness <= STEEP_VAL)
{
// Transferring from flat ground to a steep slope
// is a free action. (The other way around isn't, though.)
return;
}
newSlope = K_TumbleSlope(player->mo, player->mo->pitch, player->mo->roll);
slopeDelta = AngleDelta(oldSlope, newSlope);
if (slopeDelta <= STEEP_VAL)
{
// Needs to be VERY steep before we'll punish this.
return;
}
// Oh jeez, you landed on your side.
// You get to tumble.
#if 0
// Single, medium bounce
player->tumbleBounces = TUMBLEBOUNCES;
player->tumbleHeight = 30;
#else
// Two small bounces
player->tumbleBounces = TUMBLEBOUNCES-1;
player->tumbleHeight = 20;
#endif
player->pflags &= ~PF_TUMBLESOUND;
S_StartSound(player->mo, sfx_s3k9b);
gravityadjust = P_GetMobjGravity(player->mo)/2; // so we'll halve it for our calculations.
if (player->mo->eflags & MFE_UNDERWATER)
gravityadjust /= 2; // halve "gravity" underwater
// and then modulate momz like that...
player->mo->momz = -gravityadjust * player->tumbleHeight;
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
if (P_IsDisplayPlayer(player))
P_StartQuake(64<<FRACBITS, 10);
// Reset slope.
player->mo->pitch = player->mo->roll = 0;
}
static boolean K_LastTumbleBounceCondition(player_t *player)
{
return (player->tumbleBounces > TUMBLEBOUNCES && player->tumbleHeight < 60);

View file

@ -70,6 +70,7 @@ void K_DoInstashield(player_t *player);
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved);
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type);
void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_CheckSlopeTumble(player_t *player, angle_t oldPitch, angle_t oldRoll);
INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_DebtStingPlayer(player_t *player, mobj_t *source);
void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers);

View file

@ -169,7 +169,7 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec);
boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec); // SRB2Kart
#define P_IsObjectFlipped(o) ((o)->eflags & MFE_VERTICALFLIP)
boolean P_InQuicksand(mobj_t *mo);
boolean P_PlayerHitFloor(player_t *player, boolean fromAir);
boolean P_PlayerHitFloor(player_t *player, boolean fromAir, angle_t oldPitch, angle_t oldRoll);
void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative);
void P_RestoreMusic(player_t *player);

View file

@ -2667,12 +2667,15 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (thing->momz <= 0)
{
angle_t oldPitch = thing->pitch;
angle_t oldRoll = thing->roll;
thing->standingslope = tmfloorslope;
P_SetPitchRollFromSlope(thing, thing->standingslope);
if (thing->momz == 0 && thing->player && !startingonground)
if (thing->momz == 0 && thing->player)
{
P_PlayerHitFloor(thing->player, true);
P_PlayerHitFloor(thing->player, !startingonground, oldPitch, oldRoll);
}
}
}
@ -2687,12 +2690,15 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (thing->momz >= 0)
{
angle_t oldPitch = thing->pitch;
angle_t oldRoll = thing->roll;
thing->standingslope = tmceilingslope;
P_SetPitchRollFromSlope(thing, thing->standingslope);
if (thing->momz == 0 && thing->player && !startingonground)
if (thing->momz == 0 && thing->player)
{
P_PlayerHitFloor(thing->player, true);
P_PlayerHitFloor(thing->player, !startingonground, oldPitch, oldRoll);
}
}
}
@ -2983,7 +2989,7 @@ static boolean P_ThingHeightClip(mobj_t *thing)
}
if ((P_MobjFlip(thing)*(thing->z - oldz) > 0 || hitfloor) && thing->player)
P_PlayerHitFloor(thing->player, !onfloor);
P_PlayerHitFloor(thing->player, !onfloor, thing->pitch, thing->roll);
// debug: be sure it falls to the floor
thing->eflags &= ~MFE_ONGROUND;

View file

@ -2685,6 +2685,7 @@ static boolean P_PlayerPolyObjectZMovement(mobj_t *mo)
void P_PlayerZMovement(mobj_t *mo)
{
boolean onground;
angle_t oldPitch, oldRoll;
I_Assert(mo != NULL);
I_Assert(!P_MobjWasRemoved(mo));
@ -2692,6 +2693,9 @@ void P_PlayerZMovement(mobj_t *mo)
if (!mo->player)
return;
oldPitch = mo->pitch;
oldRoll = mo->roll;
// Intercept the stupid 'fall through 3dfloors' bug
if (mo->subsector->sector->ffloors)
P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
@ -2768,7 +2772,7 @@ void P_PlayerZMovement(mobj_t *mo)
mo->pmomz = 0; // We're on a new floor, don't keep doing platform movement.
mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack
clipmomz = P_PlayerHitFloor(mo->player, true);
clipmomz = P_PlayerHitFloor(mo->player, true, oldPitch, oldRoll);
P_PlayerPolyObjectZMovement(mo);
if (clipmomz)

View file

@ -1316,7 +1316,7 @@ void P_DoPlayerExit(player_t *player)
//
// Handles player hitting floor surface.
// Returns whether to clip momz.
boolean P_PlayerHitFloor(player_t *player, boolean fromAir)
boolean P_PlayerHitFloor(player_t *player, boolean fromAir, angle_t oldPitch, angle_t oldRoll)
{
boolean clipmomz;
@ -1329,6 +1329,11 @@ boolean P_PlayerHitFloor(player_t *player, boolean fromAir)
K_SpawnSplashForMobj(player->mo, abs(player->mo->momz));
}
if (player->mo->health)
{
K_CheckSlopeTumble(player, oldPitch, oldRoll);
}
return clipmomz;
}
@ -1639,7 +1644,7 @@ static void P_CheckQuicksand(player_t *player)
player->mo->z = ceilingheight - player->mo->height;
if (player->mo->momz <= 0)
P_PlayerHitFloor(player, false);
P_PlayerHitFloor(player, false, player->mo->roll, player->mo->pitch);
}
else
{
@ -1651,7 +1656,7 @@ static void P_CheckQuicksand(player_t *player)
player->mo->z = floorheight;
if (player->mo->momz >= 0)
P_PlayerHitFloor(player, false);
P_PlayerHitFloor(player, false, player->mo->roll, player->mo->pitch);
}
friction = abs(rover->master->v1->y - rover->master->v2->y)>>6;