diff --git a/src/d_player.h b/src/d_player.h index c029097cc..a7787ef0e 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -730,6 +730,7 @@ struct player_t UINT16 maxinvincibilitytime; // (Alternate) Initial time for Invincibility, used for the item bar. UINT16 invincibilitybottleneck; // (Alternate) Prevents breakaways by gradienting towards a heavier decrement. INT16 invincibilitycancel; // (Alternate) Duration of Invincibility canceling. + UINT8 invincibilitywarning; // (Alternate) "Timer warning" boolean to signal Alt. Invin. is running out. UINT8 eggmanexplode; // Fake item recieved, explode in a few seconds SINT8 eggmanblame; // (-1 to 15) - Fake item recieved, who set this fake diff --git a/src/k_kart.c b/src/k_kart.c index 44e50a570..5637410a2 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7137,31 +7137,64 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->invincibilitytimer) { INT16 invinfac = 1; - if ((K_GetKartInvinType() == KARTINVIN_ALTERN) && ((INT16)(player->invincibilitybottleneck) != -1) && (player->invincibilitytimer > 2)) + if ((K_GetKartInvinType() == KARTINVIN_ALTERN) && (player->invincibilitytimer > 2)) { UINT32 invindist = INVINDIST >> 2; - if (player->distancefromcluster < invindist) + + // Value to subtract from the Invincibility timer during bottlenecking. + INT16 invin_subtrahend = 1; + + if ((INT16)(player->invincibilitybottleneck) != -1) { - player->invincibilitybottleneck = min(256, player->invincibilitybottleneck + 4); - invinfac = FixedMul(8, max(min(FRACUNIT, FRACUNIT - (player->distancefromcluster / (INVINDIST >> 2))), 0)); - } - else - { - player->invincibilitybottleneck = max(0, (INT32)(player->invincibilitybottleneck) - 2); + if (player->distancefromcluster < invindist) + { + player->invincibilitybottleneck = + min(256, player->invincibilitybottleneck + 4); + invinfac = FixedMul( + 8, + max(min(FRACUNIT, + FRACUNIT - (player->distancefromcluster / + (INVINDIST >> 2))), + 0)); + } + else + { + player->invincibilitybottleneck = + max(0, (INT32)(player->invincibilitybottleneck) - 2); + } + + invin_subtrahend = + max(1, + FixedMul((UINT16)invinfac, + max(0, player->invincibilitybottleneck) << 8)); } - player->invincibilitytimer = (UINT16)(max(2, (INT32)(player->invincibilitytimer) - max(1, FixedMul((UINT16)invinfac, player->invincibilitybottleneck << 8)))); + player->invincibilitytimer = (UINT16)(max( + 2, (INT32)(player->invincibilitytimer) - invin_subtrahend)); + + if ((K_InvincibilityGradient(player->invincibilitytimer) < + (FRACHALF * invin_subtrahend)) && + (player->maxinvincibilitytime >= (BASEINVINTIME - TICRATE))) + { + if (!player->invincibilitywarning) + { + S_StartSound(player->mo, sfx_cdfm79); + player->invincibilitywarning = 1; + } + } } else { player->invincibilitytimer--; player->invincibilitybottleneck = 0; + player->invincibilitywarning = 0; } - } + } else { - player->invincibilitybottleneck = 0; // No need for bottlenecking. + player->invincibilitybottleneck = 0; // No need for bottlenecking. player->maxinvincibilitytime = 0; + player->invincibilitywarning = 0; player->invincibilitycancel = -1; } @@ -9803,6 +9836,7 @@ void K_StripOther(player_t *player) player->roulettetype = KROULETTETYPE_NORMAL; player->invincibilitytimer = 0; + player->invincibilitywarning = 0; player->invincibilitycancel = -1; if (player->growshrinktimer) diff --git a/src/m_fixed.h b/src/m_fixed.h index 5f2aa864d..3190d0f1a 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -32,7 +32,7 @@ extern "C" { \brief units of the fraction */ #define FRACUNIT (1<>1)) +#define FRACHALF (1<<(FRACBITS-1)) #define FRACMASK (FRACUNIT -1) /** \brief Redefinition of INT32 as fixed_t unit used as fixed_t diff --git a/src/p_saveg.c b/src/p_saveg.c index 34230d2f3..68d825df2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -689,6 +689,7 @@ static void P_NetSyncPlayers(savebuffer_t *save) SYNC(players[i].maxinvincibilitytime); SYNC(players[i].invincibilitybottleneck); SYNC(players[i].invincibilitycancel); + SYNC(players[i].invincibilitywarning); SYNC(players[i].eggmanexplode); SYNC(players[i].eggmanblame);