diff --git a/src/d_player.h b/src/d_player.h index 2a770b316..cf7788101 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -135,11 +135,12 @@ typedef enum typedef enum { - PF2_SELFMUTE = 1<<1, - PF2_SELFDEAFEN = 1<<2, - PF2_SERVERMUTE = 1<<3, - PF2_SERVERDEAFEN = 1<<4, - PF2_STRICTFASTFALL = 1<<5, + PF2_SELFMUTE = 1<<1, + PF2_SELFDEAFEN = 1<<2, + PF2_SERVERMUTE = 1<<3, + PF2_SERVERDEAFEN = 1<<4, + PF2_STRICTFASTFALL = 1<<5, + PF2_ALWAYSDAMAGED = 1<<6, } pflags2_t; typedef enum diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 0de68598c..0392e0133 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -885,18 +885,28 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) thing = oldthing; P_SetTarget(&g_tm.thing, oldg_tm.thing);*/ + boolean hit = false; + if (K_KartBouncing(t2, t1->target) == true) { if (t2->player && t1->target && t1->target->player) { - K_PvPTouchDamage(t2, t1->target); + hit = K_PvPTouchDamage(t2, t1->target); } // Don't play from t1 else it gets cut out... for some reason. S_StartSound(t2, sfx_s3k44); } - return true; + if (hit && (gametyperules & GTR_BUMPERS)) + { + K_PopBubbleShield(t1->target->player); + return false; + } + else + { + return true; + } } if (K_BubbleShieldCanReflect(t1, t2)) @@ -1158,6 +1168,27 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) return false; } + + boolean guard1 = K_PlayerGuard(t1->player); + boolean guard2 = K_PlayerGuard(t2->player); + + // Bubble Shield physically extends past guard when inflated, + // makes some sense to suppress this behavior + if (t1->player->bubbleblowup) + guard1 = false; + if (t2->player->bubbleblowup) + guard2 = false; + + if (guard1 && guard2) + K_DoPowerClash(t1, t2); + else if (guard1) + K_DoGuardBreak(t1, t2); + else if (guard2) + K_DoGuardBreak(t2, t1); + + if (guard1 || guard2) + return false; + // Clash instead of damage if both parties have any of these conditions auto canClash = [](mobj_t *t1, mobj_t *t2) { diff --git a/src/k_kart.c b/src/k_kart.c index f09f724d6..bcf9747b8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -72,8 +72,11 @@ // comeback is Battle Mode's karma comeback, also bool // mapreset is set when enough players fill an empty server -static void K_PopBubbleShield(player_t *player) +void K_PopBubbleShield(player_t *player) { + if (player->curshield != KSHIELD_BUBBLE) + return; + S_StartSound(player->mo, sfx_kc31); K_StripItems(player); K_AddHitLag(player->mo, 4, false); @@ -1180,20 +1183,6 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2) K_SpawnBumpForObjs(mobj1, mobj2); - if (mobj1->type == MT_PLAYER && mobj2->type == MT_PLAYER - && !mobj1->player->powerupVFXTimer && !mobj2->player->powerupVFXTimer) - { - boolean guard1 = K_PlayerGuard(mobj1->player); - boolean guard2 = K_PlayerGuard(mobj2->player); - - if (guard1 && guard2) - K_DoPowerClash(mobj1, mobj2); - else if (guard1) - K_DoGuardBreak(mobj1, mobj2); - else if (guard2) - K_DoGuardBreak(mobj2, mobj1); - } - K_PlayerJustBumped(mobj1->player); K_PlayerJustBumped(mobj2->player); @@ -4565,12 +4554,16 @@ void K_DoPowerClash(mobj_t *t1, mobj_t *t2) { UINT8 lag1 = 5; UINT8 lag2 = 5; + boolean stripbubble = (gametyperules & GTR_BUMPERS); + // short-circuit instashield for vfx visibility if (t1->player) { t1->player->instashield = 1; t1->player->speedpunt += 20; lag1 -= min(lag1, t1->player->speedpunt/10); + if (stripbubble && t1->player->curshield == KSHIELD_BUBBLE) + K_PopBubbleShield(t1->player); } if (t2->player) @@ -4578,6 +4571,8 @@ void K_DoPowerClash(mobj_t *t1, mobj_t *t2) { t2->player->instashield = 1; t2->player->speedpunt += 20; lag2 -= min(lag1, t2->player->speedpunt/10); + if (stripbubble && t2->player->curshield == KSHIELD_BUBBLE) + K_PopBubbleShield(t2->player); } S_StartSound(t1, sfx_parry); @@ -4615,7 +4610,9 @@ void K_DoGuardBreak(mobj_t *t1, mobj_t *t2) { angle_t thrangle = R_PointToAngle2(t2->x, t2->y, t1->x, t1->y); P_Thrust(t1, thrangle, 7*mapobjectscale); + t1->player->pflags2 |= PF2_ALWAYSDAMAGED; P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE); + t1->player->pflags2 &= ~PF2_ALWAYSDAMAGED; clash = P_SpawnMobj((t1->x/2) + (t2->x/2), (t1->y/2) + (t2->y/2), (t1->z/2) + (t2->z/2), MT_GUARDBREAK); @@ -10380,6 +10377,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->powerupVFXTimer > 0) { player->powerupVFXTimer--; + if (player->powerupVFXTimer == 0) + player->mo->flags &= ~MF_NOCLIPTHING; } if (player->dotrickfx && !player->mo->hitlag) @@ -14722,7 +14721,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) S_StartSound(player->mo, sfx_s3k75); player->bubbleblowup++; - player->bubblecool = player->bubbleblowup*4; + player->bubblecool = player->bubbleblowup * (gametyperules & GTR_BUMPERS ? 6 : 4); if (player->bubbleblowup > bubbletime*2) { diff --git a/src/k_kart.h b/src/k_kart.h index 935ff2819..e454ec0a1 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -118,6 +118,8 @@ Make sure this matches the actual number of states angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed); +void K_PopBubbleShield(player_t *player); + boolean K_IsDuelItem(mobjtype_t type); boolean K_DuelItemAlwaysSpawns(mapthing_t *mt); boolean K_InRaceDuel(void); diff --git a/src/k_powerup.cpp b/src/k_powerup.cpp index 2efd94b84..38ece8439 100644 --- a/src/k_powerup.cpp +++ b/src/k_powerup.cpp @@ -65,9 +65,10 @@ void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time) } S_StartSound(NULL, sfx_gsha7l); - player->flashing = 2*TICRATE; + player->flashing = 3*TICRATE; player->mo->hitlag += BATTLE_POWERUP_VFX_TIME; player->powerupVFXTimer = BATTLE_POWERUP_VFX_TIME; + player->mo->flags |= MF_NOCLIPTHING; Obj_SpawnPowerUpSpinner(player->mo, powerup, BATTLE_POWERUP_VFX_TIME); g_darkness.start = leveltime; diff --git a/src/p_inter.c b/src/p_inter.c index aa53f1496..9af619404 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3104,6 +3104,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da invincible = false; } + if (player->pflags2 && PF2_ALWAYSDAMAGED) + { + invincible = false; + clash = false; + } + // TODO: doing this from P_DamageMobj limits punting to objects that damage the player. // And it may be kind of yucky. // But this is easier than accounting for every condition in PIT_CheckThing! diff --git a/src/p_user.c b/src/p_user.c index a49cd3930..80169dee6 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4564,9 +4564,7 @@ void P_PlayerThink(player_t *player) // Strength counts up to diminish fade. if (player->flashing && player->flashing < UINT16_MAX && - (player->spectator || !P_PlayerInPain(player)) && - // Battle: flashing tics do not decrease in the air - (!(gametyperules & GTR_BUMPERS) || P_IsObjectOnGround(player->mo))) + (player->spectator || !P_PlayerInPain(player))) { player->flashing--; }