More bumpcode fixing

* Players are no longer always weight 5 (blame 3bc6b89fa0)
* K_KartBouncing is now called if result.mo is set and the move succeeds,
  and the solid flag is now set based on PIT_CheckThing blocking the move
* Fixed simultaneous object + wall bumps
* Removed the remaining uses of K_KartBouncing in PIT_CheckThing
* Reverted player bumps back to BMIT_CONTINUE, since it works now
This commit is contained in:
GenericHeroGuy 2025-11-22 21:15:00 +01:00
parent d19ff35fbf
commit fd2e480ee4
5 changed files with 90 additions and 94 deletions

View file

@ -97,7 +97,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
{
// Player Damage
P_DamageMobj(t2, t1, t1->target, 1, DMG_WIPEOUT);
K_KartBouncing(t2, t1, false, false);
P_SetTarget(&g_tm.hitthing, t1);
S_StartSound(t2, sfx_s3k7b);
}
@ -754,7 +754,7 @@ boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2)
boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2)
{
if ((t2->player && (G_CompatLevel(0x0008) || !t2->player->hyudorotimer)) || t2->type == MT_FALLINGROCK)
K_KartBouncing(t2, t1, false, false);
P_SetTarget(&g_tm.hitthing, t1);
return true;
}
@ -782,7 +782,7 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2)
return true;
*/
K_KartBouncing(t2, t1, false, true);
P_SetTarget(&g_tm.hitthing, t1);
return false;
}

View file

@ -482,60 +482,49 @@ static fixed_t K_PlayerWeight(mobj_t* mobj, mobj_t* against)
if (!mobj->player)
return weight;
if (against && !P_MobjWasRemoved(against) && against->player)
if (!P_MobjWasRemoved(against) && against->player)
{
if ((!P_PlayerInPain(against->player) &&
P_PlayerInPain(mobj->player)) // You're hurt
|| (K_GetShieldFromPlayer(against->player) ==
KSHIELD_BUBBLE // They have a Bubble Shield
&& K_GetShieldFromPlayer(mobj->player) != KSHIELD_BUBBLE)) // and you don't
if ((!P_PlayerInPain(against->player) && P_PlayerInPain(mobj->player)) // You're hurt
|| (K_GetShieldFromPlayer(against->player) == KSHIELD_BUBBLE // They have a Bubble Shield
&& K_GetShieldFromPlayer(mobj->player) != KSHIELD_BUBBLE)) // and you don't
{
weight = 0; // This player does not cause any bump action
return 0; // This player does not cause any bump action
}
else if (invinisalt && against->player->invincibilitytimer)
{
// Scale Alt. Invin. weight to their power. At full power, you get shoved
// off! Might cause less shitty-feeling bumpcheck moments.
weight = max(0,
FRACUNIT - FixedMul((against->player->kartweight) * FRACUNIT,
K_InvincibilityGradient(
against->player->invincibilitytimer)));
return max(0, FRACUNIT - against->player->kartweight * K_InvincibilityGradient(against->player->invincibilitytimer));
}
}
else
// Applies rubberbanding, to prevent rubberbanding bots
// from causing super crazy bumps.
fixed_t spd = K_GetKartSpeed(mobj->player, false, true);
weight = (mobj->player->kartweight) * FRACUNIT;
if (invinisalt && mobj->player->invincibilitytimer)
{
// Applies rubberbanding, to prevent rubberbanding bots
// from causing super crazy bumps.
fixed_t spd = K_GetKartSpeed(mobj->player, false, true);
// Cap the gradient at 1.0 to prevent exaggerated nonsense.
fixed_t mygradient = min(FRACUNIT, K_InvincibilityGradient(mobj->player->invincibilitytimer));
weight = (mobj->player->kartweight) * FRACUNIT;
// Scale Alt. Invin. weight to your power. At full power, they get shoved off!
// Might cause less shitty-feeling bumpcheck moments.
weight = FixedMul(weight, mygradient);
if (invinisalt && mobj->player->invincibilitytimer)
{
// Cap the gradient at 1.0 to prevent exaggerated nonsense.
fixed_t mygradient = min(
FRACUNIT, K_InvincibilityGradient(mobj->player->invincibilitytimer));
// Scale Alt. Invin. weight to your power. At full power, they get shoved
// off! Might cause less shitty-feeling bumpcheck moments.
weight = FixedMul(weight, mygradient);
// Like the Bubble Shield, nerf bumps a good bit to make them feel less
// ridiculous. As your power depletes, this nerf gets less necessary, so
// scale it to match.
weight =
FixedMul(weight, FRACUNIT - FixedMul(INVBUMPBOTTLENECK, mygradient));
}
else if (K_GetShieldFromPlayer(mobj->player) == KSHIELD_BUBBLE &&
mobj->player->bubblecool == 0)
{
weight = max(BUBBLEMINWEIGHT, weight);
weight = FixedMul(weight, FRACUNIT / 16);
}
if (mobj->player->speed > spd)
weight += (mobj->player->speed - spd) / 8;
// Like the Bubble Shield, nerf bumps a good bit to make them feel less ridiculous.
// As your power depletes, this nerf gets less necessary, so scale it to match.
weight = FixedMul(weight, FRACUNIT - FixedMul(INVBUMPBOTTLENECK, mygradient));
}
else if (K_GetShieldFromPlayer(mobj->player) == KSHIELD_BUBBLE && mobj->player->bubblecool == 0)
{
weight = max(BUBBLEMINWEIGHT, weight);
weight = FixedMul(weight, FRACUNIT / 16);
}
if (mobj->player->speed > spd)
weight += (mobj->player->speed - spd) / 8;
return weight;
}
@ -833,8 +822,17 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean sol
return false;
}
if (bounce == true && mass2 > 0) // Perform a Goomba Bounce.
if (mobj2->health <= 0 && (mobj2->type == MT_ORBINAUT || mobj2->type == MT_ORBINAUT_SHIELD
|| mobj2->type == MT_JAWZ || mobj2->type == MT_JAWZ_SHIELD || mobj2->type == MT_JAWZ_DUD))
{
// dead orbis and jawz are supposed to have a momz of 0 here
// but K_KartBouncing now runs AFTER K_ItemDamage
mobj1->momz = 0;
}
else if (bounce == true && mass2 > 0) // Perform a Goomba Bounce.
{
mobj1->momz = -mobj1->momz;
}
else
{
fixed_t newz = mobj1->momz;

View file

@ -483,6 +483,7 @@ struct TryMoveResult_t
boolean success;
line_t *line;
mobj_t *mo;
boolean blockingmo; // set if PIT_CheckThing blocked the move (mo may still be set!)
vector2_t normal;
};

View file

@ -1204,7 +1204,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
P_SetTarget(&g_tm.hitthing, thing);
}
return BMIT_ABORT;
return BMIT_CONTINUE;
}
else if (thing->type == MT_BLUEROBRA_HEAD || thing->type == MT_BLUEROBRA_JOINT)
{
@ -1303,7 +1303,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
return BMIT_CONTINUE; // underneath
P_SetTarget(&g_tm.hitthing, thing);
return BMIT_ABORT;
return BMIT_CONTINUE;
}
else if (thing->flags & MF_SOLID)
{
@ -1644,7 +1644,8 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld)
// TODO: refactor this into one place
if (ld->frontsector == ld->backsector && !P_MidtextureIsSolid(ld, g_tm.thing))
{
// you hit a FOF or polyobject in this sector, not the non-solid midtexture...
// if you reach this point, you've hit the planes of a FOF, or perhaps a polyobject,
// but you can't hit a non-solid midtexture sharing the same front and back sectors!
}
else if (open.range < g_tm.thing->height)
{
@ -2061,6 +2062,15 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re
}
}
if (result != NULL)
{
if (result->mo == NULL) // || g_tm.hitthing != NULL) // don't bump the most distant object in multiple BMIT_CONTINUE bumps...?
{
result->mo = g_tm.hitthing;
result->blockingmo = !blockval;
}
}
validcount++;
// check lines
@ -2080,7 +2090,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re
if (result != NULL)
{
result->line = NULL;
result->mo = g_tm.hitthing;
}
else
{
@ -3090,7 +3099,6 @@ static boolean P_ThingHeightClip(mobj_t *thing)
// SLIDE MOVE
// Allows the player to slide along any angled walls.
//
static line_t *bestslideline;
static mobj_t *slidemo;
static fixed_t tmxmove, tmymove;
@ -3138,17 +3146,10 @@ static void P_PlayerHitBounceLine(line_t *ld, vector2_t* normal)
if (slidemo->player && movelen < (15*mapobjectscale))
movelen = (15*mapobjectscale);
if (!ld)
{
angle_t th = R_PointToAngle2(0, 0, tmxmove, tmymove);
normal->x = -FCOS(th);
normal->y = -FSIN(th);
}
x = FixedMul(movelen, normal->x);
y = FixedMul(movelen, normal->y);
if (ld && P_IsLineTripWire(ld))
if (P_IsLineTripWire(ld))
{
tmxmove = FixedMul(x, FRACUNIT+(FRACUNIT/2));
tmymove = FixedMul(y, FRACUNIT+(FRACUNIT/2));
@ -3319,6 +3320,7 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
//
void P_SlideMove(mobj_t *mo, TryMoveResult_t *result)
{
line_t *bestslideline;
fixed_t newx, newy;
boolean success = false;
@ -3517,8 +3519,8 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
if (mo->player == NULL)
return;
if (result == NULL || (result->line == NULL && P_MobjWasRemoved(result->mo)))
return; // don't be silly, you can't bounce off of thin air!
if (result == NULL)
return;
if (mo->player->spectator)
{
@ -3526,53 +3528,46 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
return;
}
if (!P_MobjWasRemoved(result->mo))
if (!P_MobjWasRemoved(result->mo)) // object bounce
{
boolean solid = false, bounce = false;
mobj_t *mo1 = mo, *mo2 = result->mo;
boolean bounce = false;
if (result->mo->player != NULL)
{
// The bump has to happen last
mobj_t *mo1 = mo;
mobj_t *mo2 = result->mo;
boolean zbounce = false;
if (P_IsObjectOnGround(result->mo) && mo->momz < 0)
if (P_IsObjectOnGround(mo2) && mo1->momz < 0)
{
zbounce = true;
bounce = true;
}
else if (P_IsObjectOnGround(mo1) && mo2->momz < 0)
{
bounce = true;
mo1 = result->mo;
mo2 = mo;
}
else if (P_IsObjectOnGround(mo) && result->mo->momz < 0)
{
zbounce = true;
}
K_KartBouncing(mo1, mo2, zbounce, false);
return;
}
else switch (result->mo->type)
else switch (mo2->type)
{
case MT_BLUEROBRA:
case MT_BLUEROBRA_HEAD:
case MT_SMK_PIPE:
case MT_SMK_THWOMP:
solid = true;
case MT_SMK_ICEBLOCK:
break;
default:
if (result->mo->flags & MF_SOLID)
solid = true;
// FALLTHRU
case MT_KART_LEFTOVER:
bounce = P_IsObjectOnGround(result->mo) && mo->momz < 0;
bounce = P_IsObjectOnGround(mo2) && mo1->momz < 0;
break;
}
K_KartBouncing(mo, result->mo, bounce, solid);
return;
// no more special logic! if you want a solid bounce, return BMIT_ABORT
K_KartBouncing(mo1, mo2, bounce, result->blockingmo);
}
if (result->line == NULL)
return;
mmomx = mo->player->rmomx;
mmomy = mo->player->rmomy;
@ -3606,7 +3601,6 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
}
slidemo = mo;
bestslideline = result->line;
/*if (mo->health <= 0)
{
@ -3625,7 +3619,7 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
}
if (bestslideline && P_IsLineTripWire(bestslideline))
if (P_IsLineTripWire(result->line))
{
// TRIPWIRE CANNOT BE MADE NONBOUNCY
K_ApplyTripWire(mo->player, TRIPSTATE_BLOCKED);
@ -3633,7 +3627,7 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
else
{
// Some walls aren't bouncy even if you are
if (bestslideline && (bestslideline->flags & ML_NOTBOUNCY))
if (result->line && (result->line->flags & ML_NOTBOUNCY))
{
// SRB2Kart: Non-bouncy line!
P_SlideMove(mo, result);
@ -3643,7 +3637,7 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
K_SpawnBumpEffect(mo);
}
P_PlayerHitBounceLine(bestslideline, &result->normal);
P_PlayerHitBounceLine(result->line, &result->normal);
mo->eflags |= MFE_JUSTBOUNCEDWALL;
mo->momx = tmxmove;
@ -3651,7 +3645,7 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
mo->player->cmomx = tmxmove;
mo->player->cmomy = tmymove;
if (!bestslideline || !P_IsLineTripWire(bestslideline))
if (!P_IsLineTripWire(result->line))
{
if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true, NULL))
{
@ -3684,14 +3678,13 @@ void P_BounceMove(mobj_t *mo, TryMoveResult_t *result)
return;
}
if (result->line == NULL)
return;
mmomx = mo->momx;
mmomy = mo->momy;
slidemo = mo;
bestslideline = result->line;
if (bestslideline == NULL)
return;
if (mo->type == MT_SHELL)
{
@ -3715,7 +3708,7 @@ void P_BounceMove(mobj_t *mo, TryMoveResult_t *result)
tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
}
P_HitBounceLine(bestslideline); // clip the moves
P_HitBounceLine(result->line); // clip the moves
mo->momx = tmxmove;
mo->momy = tmymove;

View file

@ -1841,6 +1841,10 @@ void P_XYMovement(mobj_t *mo)
{
// TERRAIN footstep effects.
K_HandleFootstepParticles(mo);
// we still need to bounce off objects even if the move succeeded!
if (player != NULL && !P_MobjWasRemoved(result.mo))
P_BounceMove(mo, &result);
}
if (moved && oldslope && !(mo->flags & MF_NOCLIPHEIGHT))