Adjust most player physics for Garden Top

- Auto accel
- 800% acceleration
- 110% top speed
- Infinite tether like Lightning Shield

- Resists going upward on slopes
- Less friction

- Can always turn your sprite
- Turning speed does not get weaker at high speeds
- Turning speed is normal underwater
- Keeps moving in momentum direction, regardless of how
you turn
- Releasing a drift redirects all your momentum in that
direction

- Floats over bananas, damage sectors and offroad
- No stair janking while floating

- Hold drift for extra gravity. Not only does this fast
fall (this stacks with true fast falling), it builds
momentum down slopes too!

- Parries Big Players (Grow), Invincibility, Flame Shield
and, of course, other Tops -- all except if you're
grinding
- Wipes out anyone you touch
- Infinite weight like Bubble Shield

- Does not water skip
- Does not water run while holding drift
This commit is contained in:
James R 2022-08-25 01:34:23 -07:00
parent 5063a4acf1
commit 56a5432f41
6 changed files with 135 additions and 21 deletions

View file

@ -66,17 +66,22 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
if (t1->type == MT_BANANA && t1->health > 1)
S_StartSound(t2, sfx_bsnipe);
damageitem = true;
if (t2->player->flamedash && t2->player->itemtype == KITEM_FLAMESHIELD)
{
// Melt item
S_StartSound(t2, sfx_s3k43);
}
else if (K_IsRidingFloatingTop(t2->player))
{
// Float over silly banana
damageitem = false;
}
else
{
P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL|DMG_WOMBO);
}
damageitem = true;
}
else if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD
|| t2->type == MT_ORBINAUT || t2->type == MT_ORBINAUT_SHIELD
@ -774,11 +779,13 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
// Clash instead of damage if both parties have any of these conditions
t1Condition = (K_IsBigger(t1, t2) == true)
|| (t1->player->invincibilitytimer > 0)
|| (t1->player->flamedash > 0 && t1->player->itemtype == KITEM_FLAMESHIELD);
|| (t1->player->flamedash > 0 && t1->player->itemtype == KITEM_FLAMESHIELD)
|| (t1->player->curshield == KSHIELD_TOP && !K_IsHoldingDownTop(t1->player));
t2Condition = (K_IsBigger(t2, t1) == true)
|| (t2->player->invincibilitytimer > 0)
|| (t2->player->flamedash > 0 && t2->player->itemtype == KITEM_FLAMESHIELD);
|| (t2->player->flamedash > 0 && t2->player->itemtype == KITEM_FLAMESHIELD)
|| (t2->player->curshield == KSHIELD_TOP && !K_IsHoldingDownTop(t2->player));
if (t1Condition == true && t2Condition == true)
{

View file

@ -1374,7 +1374,13 @@ static fixed_t K_PlayerWeight(mobj_t *mobj, mobj_t *against)
if (!mobj->player)
return weight;
if (against && !P_MobjWasRemoved(against) && against->player
if (against && (against->type == MT_GARDENTOP || (against->player && against->player->curshield == KSHIELD_TOP)))
{
/* Players bumping into a Top get zero weight -- the
Top rider is immovable. */
weight = 0;
}
else if (against && !P_MobjWasRemoved(against) && against->player
&& ((!P_PlayerInPain(against->player) && P_PlayerInPain(mobj->player)) // You're hurt
|| (against->player->itemtype == KITEM_BUBBLESHIELD && mobj->player->itemtype != KITEM_BUBBLESHIELD))) // They have a Bubble Shield
{
@ -1962,6 +1968,18 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur
#undef CHAOTIXBANDLEN
}
static boolean K_HasInfiniteTether(player_t *player)
{
switch (player->curshield)
{
case KSHIELD_LIGHTNING:
case KSHIELD_TOP:
return true;
}
return false;
}
/** \brief Updates the player's drafting values once per frame
\param player player object passed from K_KartPlayerThink
@ -1976,7 +1994,7 @@ static void K_UpdateDraft(player_t *player)
UINT8 leniency;
UINT8 i;
if (player->itemtype == KITEM_LIGHTNINGSHIELD)
if (K_HasInfiniteTether(player))
{
// Lightning Shield gets infinite draft distance as its (other) passive effect.
draftdistance = 0;
@ -3267,6 +3285,8 @@ boolean K_ApplyOffroad(player_t *player)
{
if (player->invincibilitytimer || player->hyudorotimer || player->sneakertimer)
return false;
if (K_IsRidingFloatingTop(player))
return false;
return true;
}
@ -3274,6 +3294,8 @@ boolean K_SlopeResistance(player_t *player)
{
if (player->invincibilitytimer || player->sneakertimer || player->tiregrease || player->flamedash)
return true;
if (player->curshield == KSHIELD_TOP)
return true;
return false;
}
@ -3320,6 +3342,9 @@ boolean K_WaterRun(player_t *player)
boolean K_WaterSkip(player_t *player)
{
if (player->curshield == KSHIELD_TOP)
return false;
if (player->speed/3 > abs(player->mo->momz)) // Going more forward than horizontal, so you can skip across the water.
return true;
@ -3531,7 +3556,7 @@ static void K_GetKartBoostPower(player_t *player)
draftspeed *= 2;
}
if (player->itemtype == KITEM_LIGHTNINGSHIELD)
if (K_HasInfiniteTether(player))
{
// infinite tether
draftspeed *= 2;
@ -3653,6 +3678,10 @@ fixed_t K_GetKartAccel(player_t *player)
if (gametype == GT_BATTLE && player->bumpers <= 0)
k_accel *= 2;
// Marble Garden Top gets 800% accel
if (player->curshield == KSHIELD_TOP)
k_accel *= 8;
return FixedMul(k_accel, (FRACUNIT + player->accelboost) / 4);
}
@ -3742,17 +3771,35 @@ SINT8 K_GetForwardMove(player_t *player)
forwardmove = MAXPLMOVE;
}
if (player->curshield == KSHIELD_TOP)
{
if (forwardmove < 0 ||
(K_GetKartButtons(player) & BT_DRIFT))
{
forwardmove = 0;
}
else
{
forwardmove = MAXPLMOVE;
}
}
return forwardmove;
}
fixed_t K_GetNewSpeed(player_t *player)
{
const fixed_t accelmax = 4000;
const fixed_t p_speed = K_GetKartSpeed(player, true, true);
fixed_t p_speed = K_GetKartSpeed(player, true, true);
fixed_t p_accel = K_GetKartAccel(player);
fixed_t newspeed, oldspeed, finalspeed;
if (player->curshield == KSHIELD_TOP)
{
p_speed = 11 * p_speed / 10;
}
if (K_PlayerUsesBotMovement(player) == true && player->botvars.rubberband > 0)
{
// Acceleration is tied to top speed...
@ -8964,13 +9011,25 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue)
if ((currentSpeed <= 0) // Not moving
&& ((K_GetKartButtons(player) & BT_EBRAKEMASK) != BT_EBRAKEMASK) // Not e-braking
&& (player->respawn.state == RESPAWNST_NONE) // Not respawning
&& (player->curshield != KSHIELD_TOP) // Not riding a Top
&& (P_IsObjectOnGround(player->mo) == true)) // On the ground
{
return 0;
}
p_maxspeed = K_GetKartSpeed(player, false, true);
p_speed = min(currentSpeed, (p_maxspeed * 2));
if (player->curshield == KSHIELD_TOP)
{
// Do not downscale turning speed with faster
// movement speed; behaves as if turning in place.
p_speed = 0;
}
else
{
p_speed = min(currentSpeed, (p_maxspeed * 2));
}
weightadjust = FixedDiv((p_maxspeed * 3) - p_speed, (p_maxspeed * 3) + (player->kartweight * FRACUNIT));
if (K_PlayerUsesBotMovement(player))
@ -8997,7 +9056,9 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue)
turnfixed = FixedMul(turnfixed, FRACUNIT + player->handleboost);
}
if ((player->mo->eflags & MFE_UNDERWATER) &&
if (player->curshield == KSHIELD_TOP)
;
else if ((player->mo->eflags & MFE_UNDERWATER) &&
player->speed > 11 * player->mo->scale)
{
turnfixed /= 2;
@ -10013,6 +10074,11 @@ void K_AdjustPlayerFriction(player_t *player)
player->mo->friction += ((FRACUNIT - prevfriction) / greasetics) * player->tiregrease;
}
if (player->curshield == KSHIELD_TOP)
{
player->mo->friction += 1024;
}
/*
if (K_PlayerEBrake(player) == true)
{

View file

@ -2850,6 +2850,11 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->terrain = NULL;
}
if (thing->player && K_IsRidingFloatingTop(thing->player))
{
stairjank = false;
}
/* FIXME: slope step down (even up) has some false
positives, so just ignore them entirely. */
if (stairjank && !oldslope && !thing->standingslope &&

View file

@ -1133,7 +1133,11 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
gravityadd = FixedMul(TUMBLEGRAVITY, gravityadd);
}
if (mo->player->fastfall != 0)
if (K_IsHoldingDownTop(mo->player))
{
gravityadd = (5*gravityadd)/2;
}
else if (mo->player->fastfall != 0)
{
// Fast falling
gravityadd *= 4;
@ -3092,13 +3096,26 @@ boolean P_CanRunOnWater(player_t *player, ffloor_t *rover)
fixed_t clip = flip ? (surfaceheight - playerbottom) : (playerbottom - surfaceheight);
fixed_t span = player->mo->watertop - player->mo->waterbottom;
return
clip > -(player->mo->height / 2) &&
span > player->mo->height &&
player->speed / 5 > abs(player->mo->momz) &&
player->speed > K_GetKartSpeed(player, false, false) &&
K_WaterRun(player) &&
(rover->flags & FF_SWIMMABLE);
if (!(rover->flags & FF_SWIMMABLE) ||
clip < -(player->mo->height / 2) ||
span < player->mo->height)
{
return false;
}
if (player->curshield == KSHIELD_TOP)
{
return (K_GetKartButtons(player) & BT_DRIFT) != BT_DRIFT;
}
if (K_WaterRun(player) &&
player->speed / 5 > abs(player->mo->momz) &&
player->speed > K_GetKartSpeed(player, false, false))
{
return true;
}
return false;
}
boolean P_CheckSolidFFloorSurface(player_t *player, ffloor_t *rover)

View file

@ -4426,7 +4426,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
switch (special)
{
case 1: // Damage (Generic)
if (roversector || P_MobjReadyToTrigger(player->mo, sector))
if (!K_IsRidingFloatingTop(player) && (roversector || P_MobjReadyToTrigger(player->mo, sector)))
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL);
break;
case 2: // Damage (Water) // SRB2kart - These three damage types are now offroad sectors
@ -4434,7 +4434,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
case 4: // Damage (Electrical)
break;
case 5: // Spikes
if (roversector || P_MobjReadyToTrigger(player->mo, sector))
if (!K_IsRidingFloatingTop(player) && (roversector || P_MobjReadyToTrigger(player->mo, sector)))
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL);
break;
case 6: // Death Pit (Camera Mod)

View file

@ -1801,7 +1801,7 @@ static void P_3dMovement(player_t *player)
// Get the old momentum; this will be needed at the end of the function! -SH
oldMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
if (player->stairjank > 8 && leveltime & 3)
if ((player->stairjank > 8 && leveltime & 3) || K_IsRidingFloatingTop(player))
{
movepushangle = K_MomentumAngle(player->mo);
}
@ -1884,6 +1884,7 @@ static void P_3dMovement(player_t *player)
if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration...
movepushforward = FixedMul(movepushforward, player->mo->movefactor);
if (player->curshield != KSHIELD_TOP)
{
INT32 a = K_GetUnderwaterTurnAdjust(player);
INT32 adj = 0;
@ -1967,6 +1968,24 @@ static void P_3dMovement(player_t *player)
player->mo->momx += totalthrust.x;
player->mo->momy += totalthrust.y;
// Releasing a drift while on the Top translates all your
// momentum (and even then some) into whichever direction
// you're facing
if (onground && player->curshield == KSHIELD_TOP && (K_GetKartButtons(player) & BT_DRIFT) != BT_DRIFT && (player->oldcmd.buttons & BT_DRIFT))
{
const fixed_t gmin = FRACUNIT/4;
const fixed_t gmax = 5*FRACUNIT/2;
const fixed_t grindfactor = (gmax - gmin) / GARDENTOP_MAXGRINDTIME;
const fixed_t grindscale = gmin + (player->topdriftheld * grindfactor);
const fixed_t speed = R_PointToDist2(0, 0, player->mo->momx, player->mo->momy);
P_InstaThrust(player->mo, player->mo->angle, FixedMul(speed, grindscale));
player->topdriftheld = 0;/* reset after release */
}
if (!onground)
{
const fixed_t airspeedcap = (50*mapobjectscale);