Fast falling

E-Brake in the air for x4 gravity, at the cost of a tiny bounce on landing.
This commit is contained in:
Sally Coolatta 2022-09-04 21:21:25 -04:00
parent 1e9b95e546
commit bc538a066f
11 changed files with 180 additions and 71 deletions

View file

@ -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

View file

@ -9025,8 +9025,12 @@ 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
@ -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

View file

@ -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"))

View file

@ -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;
}

View file

@ -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",
/*
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
);
*/
}
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",
/*
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) {
);
*/
if (ANGLE_MAX-newangle > ANG30 && newangle > ANGLE_180)
{
mo->momz = P_MobjFlip(mo)*FRACUNIT/2;
mo->z = predictedz + P_MobjFlip(mo);
mo->standingslope = NULL;

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);
}
}

View file

@ -1112,6 +1112,8 @@ sfxinfo_t S_sfx[NUMSFX] =
// SRB2kart - Grow/invinc clash
{"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
{"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""},

View file

@ -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,