diff --git a/src/Sourcefile b/src/Sourcefile index 8453c55e6..87fa585b3 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -134,6 +134,7 @@ k_botitem.cpp k_botsearch.cpp k_cluster.cpp k_odds.c +k_altshrink.c k_grandprix.c k_boss.c k_hud.c diff --git a/src/command.h b/src/command.h index b6e99ebf2..1cbf3d617 100644 --- a/src/command.h +++ b/src/command.h @@ -188,7 +188,7 @@ extern CV_PossibleValue_t CV_Natural[]; #define KARTGP_MASTER 4 // Not a speed setting, gives hard speed with maxed out bots #define KARTGP_NIGHTMARE 5 // Not a speed setting, gives expert speed with maxed out bots extern CV_PossibleValue_t kartspeed_cons_t[], gpdifficulty_cons_t[]; -// Invincibility types. +// Invincibility types. FIXME: Make this a more generalized name eventually (please...) #define KARTINVIN_LEGACY 0 #define KARTINVIN_ALTERN 1 diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 79548c2ab..e7d501769 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -68,6 +68,7 @@ #include "m_perfstats.h" #include "g_party.h" #include "k_specialstage.h" +#include "k_altshrink.h" #define CV_RESTRICT CV_NETVAR @@ -167,6 +168,7 @@ static void KartItemPush_OnChange(void); static void KartAntiBump_OnChange(void); static void KartItemBreaker_OnChange(void); static void KartInvinType_OnChange(void); +static void KartShrinkType_OnChange(void); static void KartBumpSpark_OnChange(void); static void Schedule_OnChange(void); @@ -499,6 +501,10 @@ consvar_t cv_kartstacking_grow_speedboost = CVAR_INIT ("vanillaboost_grow_speedb consvar_t cv_kartstacking_grow_accelboost = CVAR_INIT ("vanillaboost_grow_accelboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_grow_stackable = CVAR_INIT ("vanillaboost_grow_stackable", "Off", CV_NETVAR|CV_GUARD, CV_OnOff, NULL); +consvar_t cv_kartstacking_altshrink_speedboost = CVAR_INIT ("vanillaboost_altshrink_speedboost", "0.56", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_altshrink_accelboost = CVAR_INIT ("vanillaboost_altshrink_accelboost", "0.15", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_altshrink_stackable = CVAR_INIT ("vanillaboost_altshrink_stackable", "On", CV_NETVAR|CV_GUARD, CV_OnOff, NULL); + consvar_t cv_kartstacking_bubble_speedboost = CVAR_INIT ("vanillaboost_bubble_speedboost", "0.35", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_bubble_accelboost = CVAR_INIT ("vanillaboost_bubble_accelboost", "8.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_bubble_stackable = CVAR_INIT ("vanillaboost_bubble_stackable", "Off", CV_NETVAR|CV_GUARD, CV_OnOff, NULL); @@ -594,9 +600,14 @@ consvar_t cv_kartspbdist = CVAR_INIT ("kartspbdist", "4432", CV_NETVAR|CV_CHEAT| consvar_t cv_kartlegacyspbdist = CVAR_INIT ("kartlegacyspbdist", "2216", CV_NETVAR|CV_CHEAT|CV_GUARD, spbdist_cons_t, NULL); #undef MAXODDSDIST -// Invincibility modifiers -static CV_PossibleValue_t invintype_cons_t[] = {{0, "Legacy"}, {1, "Alternative"}, {0, NULL}}; -consvar_t cv_kartinvintype = CVAR_INIT ("kartinvintype", "Legacy", CV_NETVAR|CV_CALL, invintype_cons_t, KartInvinType_OnChange); +// Items with alternative types +static CV_PossibleValue_t kartitemtype_cons_t[] = {{KARTINVIN_LEGACY, "Legacy"}, {KARTINVIN_ALTERN, "Alternative"}, {0, NULL}}; +consvar_t cv_kartinvintype = CVAR_INIT ("kartinvintype", "Legacy", CV_NETVAR|CV_CALL, kartitemtype_cons_t, KartInvinType_OnChange); +consvar_t cv_kartshrinktype = CVAR_INIT ("kartshrinktype", "Legacy", CV_NETVAR|CV_CALL, kartitemtype_cons_t, KartShrinkType_OnChange); + +// Time limit for Alt. Shrink +static CV_PossibleValue_t altshrinktime_cons_t[] = {{0, "MIN"}, {(INT16_MAX / TICRATE), "MAX"}, {0, NULL}}; +consvar_t cv_kartaltshrinktime = CVAR_INIT ("kartaltshrinktime", "13", CV_NETVAR|CV_CHEAT|CV_GUARD, altshrinktime_cons_t, NULL); // How far the player must be from the cluster to begin frequently rolling Invincibility. static CV_PossibleValue_t invindist_cons_t[] = {{1, "MIN"}, {32000, "MAX"}, {0, NULL}}; @@ -1271,6 +1282,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_growmusic); CV_RegisterVar(&cv_supermusic); + CV_RegisterVar(&cv_altshrinkmusic); CV_RegisterVar(&cv_songcredits); CV_RegisterVar(&cv_tutorialprompt); @@ -1337,6 +1349,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_invincmusicfade); CV_RegisterVar(&cv_growmusicfade); + CV_RegisterVar(&cv_altshrinkmusicfade); CV_RegisterVar(&cv_resetspecialmusic); @@ -7831,6 +7844,24 @@ static void KartInvinType_OnChange(void) } } +static void KartShrinkType_OnChange(void) +{ + if (K_CanChangeRules(false) == false) + { + return; + } + + if (leveltime < starttime) + { + CONS_Printf(M_GetText("Shrink type has been changed to \"%s\".\n"), cv_kartshrinktype.string); + shrinktype = (UINT8)cv_kartshrinktype.value; + } + else + { + CONS_Printf(M_GetText("Shrink type will be changed to \"%s\" next round.\n"), cv_kartshrinktype.string); + } +} + static void KartBumpSpark_OnChange(void) { if (K_CanChangeRules(false) == false) diff --git a/src/d_player.h b/src/d_player.h index 872b3dc32..afd782980 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -724,6 +724,7 @@ struct player_t fixed_t slopeaccel; // Handle slopeboost accel INT16 growshrinktimer; // > 0 = Big, < 0 = small + INT16 altshrinktimeshit; // (Alt. Shrink) How many times were you flipped over while shrunk? INT16 growcancel; // Duration of grow canceling INT16 squishedtimer; // Duration of being squished diff --git a/src/g_game.c b/src/g_game.c index e9249f005..fa0022f81 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -62,6 +62,7 @@ #include "k_specialstage.h" #include "k_bot.h" #include "k_odds.h" +#include "k_altshrink.h" #include "doomstat.h" #include "acs/interface.h" #include "k_director.h" @@ -442,11 +443,13 @@ consvar_t cv_showfreeplay = CVAR_INIT ("showfreeplay", "On", CV_SAVE, CV_OnOff, static CV_PossibleValue_t powermusic_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "SFX"}, {0, NULL}}; consvar_t cv_growmusic = CVAR_INIT ("growmusic", "On", CV_SAVE, powermusic_cons_t, NULL); consvar_t cv_supermusic = CVAR_INIT ("supermusic", "On", CV_SAVE, powermusic_cons_t, NULL); +consvar_t cv_altshrinkmusic = CVAR_INIT ("altshrinkmusic", "On", CV_SAVE, powermusic_cons_t, NULL); consvar_t cv_invertmouse = CVAR_INIT ("invertmouse", "Off", CV_SAVE, CV_OnOff, NULL); consvar_t cv_invincmusicfade = CVAR_INIT ("invincmusicfade", "300", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_growmusicfade = CVAR_INIT ("growmusicfade", "500", CV_SAVE, CV_Unsigned, NULL); +consvar_t cv_altshrinkmusicfade = CVAR_INIT ("altshrinkmusicfade", "500", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_resetspecialmusic = CVAR_INIT ("resetspecialmusic", "Yes", CV_SAVE, CV_YesNo, NULL); @@ -2864,7 +2867,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) } // Keep Shrink status, remove Grow status - if (players[player].growshrinktimer < 0) + // Alt. Shrink is a powerup, so don't keep that. + if (K_IsLegacyShrunk(&players[player])) growshrinktimer = players[player].growshrinktimer; else growshrinktimer = 0; diff --git a/src/g_game.h b/src/g_game.h index da46b853c..f61668e9a 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -71,7 +71,7 @@ extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, extern consvar_t cv_shoutname, cv_shoutcolor, cv_autoshout; extern consvar_t cv_songcredits; extern consvar_t cv_showfreeplay; -extern consvar_t cv_growmusic, cv_supermusic; +extern consvar_t cv_growmusic, cv_supermusic, cv_altshrinkmusic; extern consvar_t cv_pauseifunfocused; @@ -88,6 +88,7 @@ extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_gu extern consvar_t cv_invincmusicfade; extern consvar_t cv_growmusicfade; +extern consvar_t cv_altshrinkmusicfade; extern consvar_t cv_resetspecialmusic; diff --git a/src/k_altshrink.c b/src/k_altshrink.c new file mode 100644 index 000000000..ff94a98ab --- /dev/null +++ b/src/k_altshrink.c @@ -0,0 +1,81 @@ +// BLANKART +//----------------------------------------------------------------------------- +/// \file k_altshrink.c +/// \brief Alternative Shrink item type functions. + +#include "doomdef.h" +#include "doomtype.h" +#include "doomstat.h" + +#include "command.h" +#include "console.h" +#include "d_player.h" +#include "k_altshrink.h" +#include "k_cluster.hpp" +#include "m_fixed.h" +#include "p_local.h" + + +UINT8 shrinktype; + +void K_UpdateShrinkType(void) +{ + if (leveltime < starttime) + { + CONS_Printf(M_GetText("Shrink type has been changed to \"%s\".\n"), cv_kartshrinktype.string); + } + + shrinktype = (UINT8)cv_kartshrinktype.value; +} + +/** \brief Depending on the Shrink type set, this returns true or false if the player is shrunk. + + \param player (player_t) Player to test shrunken status for + \param legacy (boolean) Legacy shrink? + + \return void +*/ +boolean K_IsShrunkMode(player_t *player, boolean legacy) +{ + boolean shrunk = K_IsShrunk(player); + boolean legacytype = (shrinktype == KARTINVIN_LEGACY); + + if (legacy) + { + return ((shrunk) && (legacytype)); + } + + return ((shrunk) && (!legacytype)); +} + +#define ALTSHRINK_EPSILON (320 * FRACUNIT) +#define NEIGHBOR_IFRAMES (TICRATE / 2) +#define BASE_IFRAMES (2 * TICRATE) + +void K_AltShrinkIFrames(player_t *player) +{ + vector3_t tempclusterpoint; + + // Find neighbors + INT32 N = K_CountNeighboringPlayers(player, ALTSHRINK_EPSILON, &tempclusterpoint); + + // For every neighbor, add some iframes for a clean breakaway. + player->flashing = (UINT16)min((INT32)(UINT16_MAX), BASE_IFRAMES + (NEIGHBOR_IFRAMES * N)); +} + +#define PITY_SHRINKINCREASE_BASE (3) +#define PITY_SHRINKINCREASE (TICRATE / 2) + +void K_AltShrinkPityIncrease(player_t *player) +{ + // Increase your shrink timer by a little bit for every player you run into. + INT32 shrinktime = (UINT32)(K_GetShrinkTime(player)); + + fixed_t dimin = FRACUNIT; + + dimin = max(0, 5 - player->altshrinktimeshit) * FRACUNIT / 5; + + shrinktime = min(INT16_MAX, shrinktime + PITY_SHRINKINCREASE_BASE + FixedMul(PITY_SHRINKINCREASE, dimin)); + + player->growshrinktimer = ((INT16)shrinktime) * -1; +} \ No newline at end of file diff --git a/src/k_altshrink.h b/src/k_altshrink.h new file mode 100644 index 000000000..e535f94f1 --- /dev/null +++ b/src/k_altshrink.h @@ -0,0 +1,70 @@ +// BLANKART +//----------------------------------------------------------------------------- +/// \file k_altshrink.h +/// \brief Alternative Shrink item type functions. + +#ifndef __K_ALTSHRINK__ +#define __K_ALTSHRINK__ + +#include "doomdef.h" +#include "d_player.h" // Need for player_t +#include "command.h" // Need for player_t +#include "m_fixed.h" +#include "k_kart.h" + +extern consvar_t cv_kartaltshrinktime; +extern consvar_t cv_kartshrinktype; + +extern consvar_t cv_kartstacking_altshrink_speedboost; +extern consvar_t cv_kartstacking_altshrink_accelboost; +extern consvar_t cv_kartstacking_altshrink_stackable; + +extern UINT8 shrinktype; + +#define ALTSHRINKTIME CV_Get(&cv_kartaltshrinktime) + +#define SHRINKSPEEDBOOST CV_Get(&cv_kartstacking_altshrink_speedboost) +#define SHRINKACCELBOOST CV_Get(&cv_kartstacking_altshrink_accelboost) +#define SHRINKSTACKABLE CV_Get(&cv_kartstacking_altshrink_stackable) + +/** \brief Returns true or false if Alt. Shrink is active. + + \return Are we using the alternative Shrink type? +*/ +FUNCINLINE static ATTRINLINE boolean K_AltShrinkActive(void) +{ + return (shrinktype == KARTINVIN_ALTERN); +} + + +/** \brief Returns true or false if the player is shrunk. + + \param player (player_t) Player to test shrunken status for + + \return Is this player shrunk? +*/ +FUNCINLINE static ATTRINLINE boolean K_IsShrunk(player_t *player) +{ + return (player->growshrinktimer < 0); +} + +FUNCINLINE static ATTRINLINE INT16 K_GetShrinkTime(player_t *player) +{ + return (player->growshrinktimer * -1); +} + +FUNCINLINE static ATTRINLINE fixed_t K_AccomodateShrinkScaling(fixed_t x) +{ + return FixedDiv(x, SHRINK_SCALE); +} + +boolean K_IsShrunkMode(player_t *player, boolean legacy); + +#define K_IsLegacyShrunk(player) (K_IsShrunkMode(player, true)) +#define K_IsAltShrunk(player) (K_IsShrunkMode(player, false)) + +void K_UpdateShrinkType(void); +void K_AltShrinkIFrames(player_t *player); +void K_AltShrinkPityIncrease(player_t *player); + +#endif // __K_ALTSHRINK__ \ No newline at end of file diff --git a/src/k_collide.c b/src/k_collide.c index 44769c1d5..8e73ebe8b 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -2,6 +2,7 @@ /// \brief SRB2Kart item collision hooks #include "k_collide.h" +#include "k_altshrink.h" #include "k_stats.h" #include "doomstat.h" #include "doomtype.h" @@ -857,19 +858,37 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) { if (G_CompatLevel(0x0008) || !hyudoroT1) { - switch (cv_kartairsquish.value) + if ((t2->player) && (K_IsAltShrunk(t2->player)) && + (!(t1->player && t1->player->growshrinktimer > 0))) { - case 1: - P_DamageMobj(t2, t1, t1, 1, DMG_SQUISH); - return true; - break; - case 2: - P_DamageMobj(t2, t1, t1, 1, DMG_FLIPOVER); - return true; - break; - default: - return false; - break; + // Alt. Shrink: Just make the player flip over. + if (P_DamageMobj(t2, NULL, NULL, 1, DMG_FLIPOVER)) + { + K_AltShrinkPityIncrease(t2->player); + t2->player->altshrinktimeshit++; + K_PlayPainSound(t2, NULL); + } + } + if (P_IsObjectOnGround(t1) && P_IsObjectOnGround(t2)) + { + P_DamageMobj(t2, t1, t1, 1, DMG_SQUISH); + } + else + { + switch (cv_kartairsquish.value) + { + case 1: + P_DamageMobj(t2, t1, t1, 1, DMG_SQUISH); + return true; + break; + case 2: + P_DamageMobj(t2, t1, t1, 1, DMG_FLIPOVER); + return true; + break; + default: + return false; + break; + } } } } @@ -878,20 +897,39 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) if (G_CompatLevel(0x0008) || !hyudoroT2) { // shitty code duplication 🥲 - switch (cv_kartairsquish.value) + + if ((t1->player) && (K_IsAltShrunk(t1->player)) && + (!(t2->player && t2->player->growshrinktimer > 0))) { - case 1: - P_DamageMobj(t1, t2, t2, 1, DMG_SQUISH); - return true; - break; - case 2: - P_DamageMobj(t1, t2, t2, 1, DMG_FLIPOVER); - return true; - break; - default: - return false; - break; + // Alt. Shrink: Just make the player flip over. + if (P_DamageMobj(t1, NULL, NULL, 1, DMG_FLIPOVER)) + { + K_AltShrinkPityIncrease(t1->player); + t1->player->altshrinktimeshit++; + K_PlayPainSound(t1, NULL); + } } + else if (P_IsObjectOnGround(t1) && P_IsObjectOnGround(t2)) + { + P_DamageMobj(t1, t2, t2, 1, DMG_SQUISH); + } + else + { + switch (cv_kartairsquish.value) + { + case 1: + P_DamageMobj(t1, t2, t2, 1, DMG_SQUISH); + return true; + break; + case 2: + P_DamageMobj(t1, t2, t2, 1, DMG_FLIPOVER); + return true; + break; + default: + return false; + break; + } + } } return true; } diff --git a/src/k_kart.c b/src/k_kart.c index 08fb83f3a..80f3cd405 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -66,6 +66,7 @@ #include "k_cluster.hpp" #include "k_odds.h" #include "k_specialstage.h" +#include "k_altshrink.h" #include "h_timers.h" #include "blan/b_soc.h" @@ -345,6 +346,10 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartstacking_grow_accelboost); CV_RegisterVar(&cv_kartstacking_grow_stackable); + CV_RegisterVar(&cv_kartstacking_altshrink_speedboost); + CV_RegisterVar(&cv_kartstacking_altshrink_accelboost); + CV_RegisterVar(&cv_kartstacking_altshrink_stackable); + CV_RegisterVar(&cv_kartstacking_bubble_speedboost); CV_RegisterVar(&cv_kartstacking_bubble_accelboost); CV_RegisterVar(&cv_kartstacking_bubble_stackable); @@ -410,6 +415,9 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartslopeboost); + CV_RegisterVar(&cv_kartshrinktype); + CV_RegisterVar(&cv_kartaltshrinktime); + CV_RegisterVar(&cv_kartinvintype); CV_RegisterVar(&cv_kartinvindist); CV_RegisterVar(&cv_kartinvindistmul); @@ -1597,7 +1605,7 @@ static void K_RespawnChecker(player_t *player) } else if (player->respawn == 1) { - if (player->growshrinktimer < 0) + if (K_IsShrunk(player)) { player->mo->scalespeed = mapobjectscale/TICRATE; player->mo->destscale = (6*mapobjectscale)/8; @@ -2665,6 +2673,14 @@ static void K_GetKartBoostPower(player_t *player) K_DoBoost(player, GROWSPEEDBOOST, GROWACCELBOOST, GROWSTACKABLE, GROWSTACKABLE); // + 20% top speed, + 0% acceleration } + if (K_IsAltShrunk(player)) // Alt. Shrink + { + fixed_t shrinkspeed = K_AccomodateShrinkScaling(SHRINKSPEEDBOOST); + fixed_t shrinkaccel = K_AccomodateShrinkScaling(SHRINKACCELBOOST); + + K_DoBoost(player, FixedMul(shrinkspeed, GROW_SCALE), FixedMul(shrinkaccel, GROW_SCALE), SHRINKSTACKABLE, SHRINKSTACKABLE); // + 45% top speed, + 200% acceleration + } + if (player->bubbleboost) // Bubble Shield popping boost { K_DoBoost(player, BUBBLESPEEDBOOST, BUBBLEACCELBOOST, BUBBLESTACKABLE, BUBBLESTACKABLE); // + 35% top speed, + 800% acceleration @@ -3324,7 +3340,7 @@ static void K_RemoveGrowShrink(player_t *player) { if (player->growshrinktimer > 0) // Play Shrink noise S_StartSound(player->mo, sfx_kc59); - else if (player->growshrinktimer < 0) // Play Grow noise + else if (K_IsShrunk(player)) // Play Grow noise S_StartSound(player->mo, sfx_kc5a); K_KartResetPlayerColor(player); @@ -3351,8 +3367,8 @@ void K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source) player->squishedtimer = TICRATE; - // Reduce Shrink timer - if (player->growshrinktimer < 0) + // Reduce Shrink timer for Legacy Shrink + if (K_IsLegacyShrunk(player)) { player->growshrinktimer += TICRATE; if (player->growshrinktimer >= 0) @@ -5073,6 +5089,44 @@ void K_DoInvincibility(player_t *player, tic_t time) P_RestoreMusic(player); } +static void K_DoGrowShrink(player_t *player, boolean shrinking) +{ + player->mo->scalespeed = mapobjectscale/TICRATE; + player->mo->destscale = FixedMul(mapobjectscale, (shrinking) ? SHRINK_SCALE : GROW_SCALE); + + if (K_PlayerShrinkCheat(player) == true) + { + player->mo->destscale = FixedMul(player->mo->destscale, SHRINK_SCALE); + } + + if ((shrinking) && (ALTSHRINKTIME > 0)) + { + player->growshrinktimer = ALTSHRINKTIME * -TICRATE; + } + else + { + player->growshrinktimer = (gametyperules & GTR_CLOSERPLAYERS ? 8 : 12) * ((shrinking) ? -TICRATE : TICRATE); + } + + if (player->invincibilitytimer > 0) + { + ; // invincibility has priority in P_RestoreMusic, no point in starting here + } + else if (P_IsLocalPlayer(player) == true) + { + S_ChangeMusicSpecial((shrinking) ? "kshrnk" : "kgrow"); + } + else //used to be "if (P_IsDisplayPlayer(player) == false)" + { + if (!shrinking) + { + S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow)); + } + } + + P_RestoreMusic(player); +} + void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source) { mobj_t *cachenext; @@ -6366,6 +6420,7 @@ static void K_UpdateInvincibilitySounds(player_t *player) sfxnum = cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow; else if (player->invincibilitytimer > 0 && (!localplayer || cv_supermusic.value == 2)) sfxnum = cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc; + // FIXME: Does Alt. Shrink need an alarm? } if (sfxnum != sfx_None && !S_SoundPlaying(player->mo, sfxnum)) @@ -7375,7 +7430,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { if (player->growshrinktimer > 0) player->growshrinktimer--; - if (player->growshrinktimer < 0) + if (K_IsShrunk(player)) player->growshrinktimer++; // Back to normal @@ -7709,7 +7764,7 @@ void K_KartResetPlayerColor(player_t *player) if (player->growshrinktimer % 5 == 0) { player->mo->colorized = true; - player->mo->color = (player->growshrinktimer < 0 ? SKINCOLOR_CREAMSICLE : SKINCOLOR_PERIWINKLE); + player->mo->color = (K_IsShrunk(player) ? SKINCOLOR_CREAMSICLE : SKINCOLOR_PERIWINKLE); fullbright = true; goto finalise; } @@ -8984,8 +9039,11 @@ INT16 K_GetKartTurnValue(const player_t *player, INT16 turnvalue) if (K_SlipdashActive() && K_Sliptiding(player)) // slight handling boost based on weight turnvalue = FixedMul(turnvalue, FRACUNIT + (10 - player->kartweight)*FRACUNIT/48); - if (player->invincibilitytimer || player->sneakertimer || player->bubbleboost || player->growshrinktimer > 0) - turnvalue = FixedMul(turnvalue, FixedDiv(5*FRACUNIT, 4*FRACUNIT)); + if (player->invincibilitytimer || player->sneakertimer || player->bubbleboost || + player->growshrinktimer > 0 || K_IsAltShrunk(player)) + { + turnvalue = FixedMul(turnvalue, FixedDiv(5 * FRACUNIT, 4 * FRACUNIT)); + } if (player->flamedash && player->flamestore) // Reduce turning { @@ -10769,39 +10827,24 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { player->itemamount--; - if (player->growshrinktimer < 0) + if (K_IsLegacyShrunk(player)) { - // If you're shrunk, then "grow" will just make you normal again. + // If you're shrunk, then "grow" will just make you normal again... K_RemoveGrowShrink(player); } else { + // ...in Legacy mode. + // Alt. Shrink's a powerup, so Grow overrides! + if (K_IsAltShrunk(player)) + { + player->growshrinktimer = 0; // Paranoia + } + K_PlayPowerGloatSound(player->mo); - player->mo->scalespeed = mapobjectscale/TICRATE; - player->mo->destscale = FixedMul(mapobjectscale, GROW_SCALE); + K_DoGrowShrink(player, false); - if (K_PlayerShrinkCheat(player) == true) - { - player->mo->destscale = FixedMul(player->mo->destscale, SHRINK_SCALE); - } - - player->growshrinktimer = (gametyperules & GTR_CLOSERPLAYERS ? 8 : 12) * TICRATE; - - if (player->invincibilitytimer > 0) - { - ; // invincibility has priority in P_RestoreMusic, no point in starting here - } - else if (P_IsLocalPlayer(player) == true) - { - S_ChangeMusicSpecial("kgrow"); - } - else //used to be "if (P_IsDisplayPlayer(player) == false)" - { - S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow)); - } - - P_RestoreMusic(player); S_StartSound(player->mo, sfx_kc5a); } @@ -10811,7 +10854,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) case KITEM_SHRINK: if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { - K_DoShrink(player); + if (K_AltShrinkActive()) + { + K_DoGrowShrink(player, true); + K_AltShrinkIFrames(player); + + S_StartSound(player->mo, sfx_kc46); + } + else + { + K_DoShrink(player); + } + player->itemamount--; K_PlayPowerGloatSound(player->mo); K_BotResetItemConfirm(player, false); @@ -11023,12 +11077,15 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_RemoveMobj(player->shieldtracer); } + if (player->growshrinktimer == 0) + player->altshrinktimeshit = 0; + if (player->growshrinktimer <= 0) player->growcancel = -1; if (player->itemtype == KITEM_SPB || player->itemtype == KITEM_SHRINK - || player->growshrinktimer < 0) + || K_IsLegacyShrunk(player)) indirectitemcooldown = 20*TICRATE; if (player->hyudorotimer > 0) diff --git a/src/k_odds.c b/src/k_odds.c index a5f7d5747..17ea88146 100644 --- a/src/k_odds.c +++ b/src/k_odds.c @@ -33,6 +33,7 @@ #include "k_bot.h" #include "k_kart.h" #include "k_waypoint.h" +#include "k_altshrink.h" #include "k_cluster.hpp" #include "k_odds.h" @@ -120,6 +121,11 @@ static UINT8 K_KartItemOddsRace[NUMKARTRESULTS-1][MAXODDS] = { 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // Jawz x2 }; +static UINT8 altshrinkodds[MAXODDS] = + { 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0}; + //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + //B C D E F G H I J K L M N O P Q + static UINT8 K_KartItemOddsBattle[NUMKARTRESULTS][2] = { //R S @@ -203,7 +209,7 @@ tic_t ItemBGone[NUMKARTRESULTS][2] = { 10, 0 }, // Ballhog { 20, 0 }, // Self-Propelled Bomb { 3, 0 }, // Grow - { 20, 0 }, // Shrink + { 5, 0 }, // Shrink { 0, 0 }, // Thunder Shield { 20, 0 }, // Hyudoro { 0, 0 }, // Pogo Spring @@ -394,6 +400,24 @@ UINT8 K_ItemResultToAmount(SINT8 getitem) } } +/** \brief Prevent overpowered rolls while under the effects of Alt. Shrink. + + \param item the item to check + + \return Don't double for this item? +*/ +static boolean K_DontDoubleMyItems(SINT8 item) +{ + return ((item == KITEM_BALLHOG) || (item == KRITEM_TENFOLDBANANA) + || (item == KRITEM_TRIPLEORBINAUT) + || (item == KRITEM_QUADORBINAUT) || (item == KRITEM_TRIPLESNEAKER) + || (item == KRITEM_DUALJAWZ) || (item == KITEM_SPB) + || (item == KITEM_INVINCIBILITY) || (item == KITEM_GROW) + || (item == KITEM_BUBBLESHIELD) || (item == KITEM_FLAMESHIELD) + || (item == KITEM_ROCKETSNEAKER) || (item == KITEM_SHRINK) + || (item == KITEM_HYUDORO)); +} + /** \brief Item Roulette for Kart \param player player @@ -403,10 +427,11 @@ UINT8 K_ItemResultToAmount(SINT8 getitem) */ static void K_KartGetItemResult(player_t *player, SINT8 getitem) { - if (getitem == KITEM_SPB || getitem == KITEM_SHRINK) // Indirect items + if (getitem == KITEM_SPB || (getitem == KITEM_SHRINK && (!K_AltShrinkActive()))) // Indirect items + { indirectitemcooldown = 20*TICRATE; - - if (K_GetBGone(getitem, true) > 0) // Item cooldowns + } + else if (K_GetBGone(getitem, true) > 0) // Item cooldowns { K_SetBGoneToBase(getitem); } @@ -415,6 +440,12 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem) player->itemtype = K_ItemResultToType(getitem); UINT8 itemamount = K_ItemResultToAmount(getitem); + + if (K_IsAltShrunk(player) && (!K_DontDoubleMyItems(getitem))) + { + itemamount *= 2; + } + if (cv_kartdebugitem.value != KITEM_NONE && cv_kartdebugitem.value == player->itemtype && cv_kartdebugamount.value > 1) itemamount = cv_kartdebugamount.value; player->itemamount = itemamount; @@ -638,7 +669,11 @@ INT32 K_KartGetItemOdds( else if (gametyperules & GTR_RACEODDS) { I_Assert(pos < MAXODDS); // Ditto - newodds = K_KartItemOddsRace[item-1][pos]; + + if (item == KITEM_SHRINK && K_AltShrinkActive()) + newodds = altshrinkodds[pos]; // Alt. Shrink has unique odds, since it's a power item. + else + newodds = K_KartItemOddsRace[item-1][pos]; } else { @@ -820,7 +855,11 @@ INT32 K_KartGetItemOdds( case KITEM_SHRINK: cooldownOnStart = true; powerItem = true; - indirectItem = true; + + if (!K_AltShrinkActive()) + indirectItem = true; + + // "Why keep this for Alt. Shrink?" Bag. Ging. notNearEnd = true; if (pingame-1 <= pexiting) @@ -920,10 +959,17 @@ UINT8 K_FindUseodds(const player_t *player, fixed_t mashed, UINT32 pdis, UINT8 b UINT8 disttable[oddsdiv]; UINT8 distlen = 0; boolean oddsvalid[MAXODDS]; + boolean rivalodds = false; // Unused now, oops :V (void)bestbumper; + if ((player->bot && player->botvars.rival) || K_IsAltShrunk(player)) + { + // Rival bots and players using Alt. Shrink get crazier items. + rivalodds = true; + } + for (i = 0; i < MAXODDS; i++) { boolean available = false; @@ -943,7 +989,7 @@ UINT8 K_FindUseodds(const player_t *player, fixed_t mashed, UINT32 pdis, UINT8 b mashed, spbrush, player->bot, - (player->bot && player->botvars.rival), + rivalodds, K_IsPlayerLosing(player) ) > 0) { diff --git a/src/p_saveg.c b/src/p_saveg.c index 744cdc30b..92982a02b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -45,6 +45,7 @@ #include "acs/interface.h" #include "g_party.h" #include "k_waypoint.h" +#include "k_altshrink.h" #include @@ -4099,6 +4100,7 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) SYNCBOOLEAN(itempushing); SYNC(bumpsparkactive); SYNC(invintype); + SYNC(shrinktype); SYNC(antibumptime); for (i = 0; i < sizeof(votelevels)/sizeof(*votelevels); i++) diff --git a/src/p_setup.c b/src/p_setup.c index 8de8390bd..99376d695 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -109,6 +109,7 @@ #include "k_mapuser.h" #include "p_deepcopy.h" #include "k_specialstage.h" +#include "k_altshrink.h" #include "blan/b_soc.h" @@ -8072,6 +8073,7 @@ static void P_InitLevelSettings(boolean reloadinggamestate) bumpsparkactive = (UINT8)cv_kartbumpspark.value; invintype = (UINT8)cv_kartinvintype.value; + K_UpdateShrinkType(); antibumptime = (tic_t)cv_kartantibump.value * TICRATE; diff --git a/src/p_spec.c b/src/p_spec.c index c5e86ce28..e0a7f990f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -44,6 +44,7 @@ // SRB2kart #include "k_kart.h" +#include "k_altshrink.h" #include "console.h" // CON_LogMessage #include "k_terrain.h" #include "acs/interface.h" @@ -9189,7 +9190,8 @@ boolean P_AllowFriction(mobj_t *mobj) if (mobj->player->invincibilitytimer || mobj->player->hyudorotimer || mobj->player->sneakertimer - || mobj->player->growshrinktimer > 0) + || mobj->player->growshrinktimer > 0 + || K_IsAltShrunk(mobj->player)) return false; return true; diff --git a/src/p_user.c b/src/p_user.c index 315556831..13b9d038a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -62,6 +62,7 @@ #include "k_color.h" #include "k_follower.h" #include "k_odds.h" +#include "k_altshrink.h" #include "g_party.h" #include "acs/interface.h" @@ -831,6 +832,8 @@ void P_RestoreMusic(player_t *player) { wantedmus = 1; bestlocaltimer = players[p].growshrinktimer; } \ else if (players[p].invincibilitytimer > bestlocaltimer) \ { wantedmus = 2; bestlocaltimer = players[p].invincibilitytimer; } \ + else if ((K_AltShrinkActive()) && (K_GetShrinkTime(&players[p]) > bestlocaltimer)) \ + { wantedmus = 3; bestlocaltimer = K_GetShrinkTime(&players[p]); } \ } setbests(localplayertable[0]); setbests(localplayertable[1]); @@ -848,6 +851,8 @@ void P_RestoreMusic(player_t *player) wantedmus = 1; else if (player->invincibilitytimer > 1) wantedmus = 2; + else if ((K_AltShrinkActive()) && (K_GetShrinkTime(player) > 1)) + wantedmus = 3; } } @@ -864,6 +869,12 @@ void P_RestoreMusic(player_t *player) S_ChangeMusicInternal("kinvnc", true); S_SetRestoreMusicFadeInCvar(&cv_invincmusicfade); } + // Item - Shrink (Alternative) + else if ((wantedmus == 3) && cv_altshrinkmusic.value == 1) + { + S_ChangeMusicInternal("kshrnk", true); + S_SetRestoreMusicFadeInCvar(&cv_altshrinkmusicfade); + } else { #if 0