From d3822cd7a58dec69805ee46f63cbbc06caf43c46 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 16 Mar 2024 04:02:01 +0000 Subject: [PATCH 01/11] Merge branch 'fix-map-command-ghost-crash' into 'master' Free ghosts when level data is freed Closes #1163 See merge request KartKrew/Kart!2108 --- src/p_setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_setup.c b/src/p_setup.c index dd8684ebd..bf2f42f65 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8893,6 +8893,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) HWR_ClearAllTextures(); #endif + G_FreeGhosts(); // ghosts are allocated with PU_LEVEL Patch_FreeTag(PU_PATCH_LOWPRIORITY); Patch_FreeTag(PU_PATCH_ROTATED); Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); From cebf6a6e4e6e4e1fff6b046c21a012fbe54c7f7a Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 7 Feb 2024 20:21:32 -0700 Subject: [PATCH 02/11] Fix crashes when P_DamageMobj was naively passed a removed source --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 6badd614a..6be083302 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2125,7 +2125,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (damagetype != DMG_SPECTATOR && target->player && target->player->spectator) return false; - if (source && source->player && source->player->spectator) + if (!P_MobjWasRemoved(source) && source->player && source->player->spectator) return false; switch (target->type) From 767e92f43152bdc182f7dcfdb03a1f9fb7f10a3c Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 2 Feb 2024 19:18:50 -0700 Subject: [PATCH 03/11] Validate PvPTouchDamage (crash fix) --- src/k_collide.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/k_collide.c b/src/k_collide.c index 24f9a0eaf..0b363d6b9 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -794,6 +794,10 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2) boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) { + // What the fuck is calling this with stale refs? Whatever, validation's cheap. + if (P_MobjWasRemoved(t1) || P_MobjWasRemoved(t2) || !t1->player || !t2->player) + return false; + const boolean flameT1 = ((t1->player->flamestore > 0) && (t1->player->flametimer > 0)); const boolean flameT2 = ((t2->player->flamestore > 0) && (t2->player->flametimer > 0)); const boolean hyudoroT1 = (t1->player->hyudorotimer > 0); From 5e96844c1c16d9e6f09187feeea05d462d3c3c27 Mon Sep 17 00:00:00 2001 From: Oni Date: Mon, 4 Sep 2023 00:25:59 +0000 Subject: [PATCH 04/11] Merge branch 'savedemo-titlecard-crash' into 'master' Only save demo on exit if demobuf.p is ready Closes #648 See merge request KartKrew/Kart!1459 --- src/g_demo.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/g_demo.c b/src/g_demo.c index 0e359bbd2..710d42e36 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -4366,7 +4366,10 @@ boolean G_CheckDemoStatus(void) if (demo.recording && (modeattacking || demo.savemode != DSM_NOTSAVING)) { - G_SaveDemo(); + if (demobuf.p) + { + G_SaveDemo(); + } return true; } From 6237ce51e299003aebc48d0ac4ea62b4a6910499 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 21 Aug 2023 01:40:05 -0400 Subject: [PATCH 05/11] Fix frequent legacy GL crash that Jeck is getting This uses `gl_frontsector`, which can sometimes be NULL. --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 628d7f2ad..b239cd815 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -361,7 +361,7 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, pslope_t *slope, const sector_t { INT16 finallight = lightnum; - if (slope != NULL && P_ApplyLightOffsetFine(lightnum, sector)) + if (slope != NULL && sector != NULL && P_ApplyLightOffsetFine(lightnum, sector)) { finallight += (fof ? -slope->hwLightOffset : slope->hwLightOffset); From 20794ff7a0940a1dd6def41003ab4950c3f19020 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 17 Mar 2023 01:31:53 -0400 Subject: [PATCH 06/11] Fix Sector_ToggleWaypoints crash --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index fb761b741..9c55fe6b0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4417,7 +4417,7 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha if (waypointcap == NULL) { // No point in trying at all if no waypoints exist. - break; + return false; } TAG_ITER_SECTORS(args[0], secnum) From 04e99590e1d03e54349ec14866fac7c34698b05c Mon Sep 17 00:00:00 2001 From: Oni Date: Wed, 22 Feb 2023 09:29:26 +0000 Subject: [PATCH 07/11] Merge branch 'seg-fault-on-i-error' into 'master' Generate a backtrace for I_Error; add a crash command See merge request KartKrew/Kart!947 --- src/d_main.cpp | 32 ++++++++++++++++++++++++++++++++ src/d_main.h | 2 ++ src/d_netcmd.c | 4 ++-- src/m_menu.c | 1 + src/sdl/i_system.cpp | 4 ++-- 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 03f02ac2e..e0be0e5a0 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1395,6 +1395,33 @@ D_ConvertVersionNumbers (void) #endif } +const char *D_GetFancyBranchName(void) +{ + if (!strcmp(compbranch, "")) + { + // \x8b = aqua highlight + return "\x8b" "detached HEAD" "\x80"; + } + + return compbranch; +} + +static void Command_assert(void) +{ +#if !defined(NDEBUG) || defined(PARANOIA) + CONS_Printf("Yes, assertions are enabled.\n"); +#else + CONS_Printf("No, ssertions are NOT enabled.\n"); +#endif +} + +#ifdef DEVELOP +static void Command_crash(void) +{ + I_Error("The game crashed on PURPOSE, because of the 'crash' command. (This is only enabled in DEVELOP builds.)"); +} +#endif + // // D_SRB2Main // @@ -1560,6 +1587,11 @@ void D_SRB2Main(void) // Do this up here so that WADs loaded through the command line can use ExecCfg COM_Init(); + COM_AddCommand("assert", Command_assert); +#ifdef DEVELOP + COM_AddCommand("crash", Command_crash); +#endif + // add any files specified on the command line with -file wadfile // to the wad list if (!((M_GetUrlProtocolArg() || M_CheckParm("-connect")) && !M_CheckParm("-server"))) diff --git a/src/d_main.h b/src/d_main.h index 98f06d869..f9f543d85 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -59,6 +59,8 @@ extern boolean usehome; //Alam: which path? extern const char *pandf; //Alam: how to path? extern char srb2path[256]; //Alam: SRB2's Home +const char *D_GetFancyBranchName(void); + // the infinite loop of D_SRB2Loop() called from win_main for windows version void D_SRB2Loop(void) FUNCNORETURN; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d3d69cfb4..2ec3e980b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -5298,9 +5298,9 @@ static void Command_ListDoomednums_f(void) static void Command_Version_f(void) { #ifdef DEVELOP - CONS_Printf("SRB2Kart %s-%s (%s %s)\n", compbranch, comprevision, compdate, comptime); + CONS_Printf("SRB2Kart %s-%s (%s %s)\n", D_GetFancyBranchName(), comprevision, compdate, comptime); #else - CONS_Printf("SRB2Kart %s (%s %s %s %s) ", VERSIONSTRING, compdate, comptime, comprevision, compbranch); + CONS_Printf("SRB2Kart %s (%s %s %s %s) ", VERSIONSTRING, compdate, comptime, comprevision, D_GetFancyBranchName()); #endif // Base library diff --git a/src/m_menu.c b/src/m_menu.c index 8d92d884f..3ac367d88 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2848,6 +2848,7 @@ texty -= 10*vid.dupy;\ #if defined(DEVELOP) addtext(V_ALLOWLOWERCASE|V_GREENMAP|V_TRANSLUCENT, comprevision); addtext(V_ALLOWLOWERCASE|V_YELLOWMAP|V_TRANSLUCENT, compbranch); + addtext(0, D_GetFancyBranchName()); V_DrawThinString(0, 0, V_ALLOWLOWERCASE|V_ORANGEMAP|V_TRANSLUCENT|V_SNAPTOTOP, va("%s", complast)); #else // Regular build addtext(V_ALLOWLOWERCASE|V_TRANSLUCENT, va("%s", VERSIONSTRING)); diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 5df6ddba5..fd33b0f89 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -2124,8 +2124,8 @@ FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...) W_Shutdown(); -#if defined (PARANOIA) && defined (__CYGWIN__) - *(volatile INT32 *)0 = 4; //Alam: Debug! +#if defined (PARANOIA) || defined (DEVELOP) + *(INT32 *)0 = 4; //Alam: Debug! #endif exit(-1); From 631d9b4454aa809a5ad088fcaab14244e51596a9 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 26 Dec 2022 23:07:32 +0000 Subject: [PATCH 08/11] Fix a crash in K_drawBossHealthBar exposed by the new random functions --- src/k_hud.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 93129fada..cf34ace68 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2036,7 +2036,7 @@ static void K_drawBossHealthBar(void) UINT8 i = 0, barstatus = 1, randlen = 0, darken = 0; const INT32 startx = BASEVIDWIDTH - 23; INT32 starty = BASEVIDHEIGHT - 25; - INT32 rolrand = 0; + INT32 rolrand = 0, randtemp = 0; boolean randsign = false; if (bossinfo.barlen <= 1) @@ -2082,7 +2082,9 @@ static void K_drawBossHealthBar(void) barstatus = 2; } - randlen = M_RandomKey(bossinfo.visualbar-(bossinfo.visualdiv/(2*FRACUNIT)))+1; + randtemp = bossinfo.visualbar-(bossinfo.visualdiv/(2*FRACUNIT)); + if (randtemp > 0) + randlen = M_RandomKey(randtemp)+1; randsign = M_RandomChance(FRACUNIT/2); // Right wing. @@ -2097,7 +2099,9 @@ static void K_drawBossHealthBar(void) randlen--; if (!randlen) { - randlen = M_RandomKey(bossinfo.visualbar-(bossinfo.visualdiv/(2*FRACUNIT)))+1; + randtemp = bossinfo.visualbar-(bossinfo.visualdiv/(2*FRACUNIT)); + if (randtemp > 0) + randlen = M_RandomKey(randtemp)+1; if (barstatus > 1) { rolrand = M_RandomKey(barstatus)+1; From 9a076cd88e9a2cc2a3baf0a141f8d5212f7114e4 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sun, 30 Nov 2025 15:58:15 -0500 Subject: [PATCH 09/11] Fix 2p lives icon placement if offsets are on --- src/k_hud.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index cf34ace68..64f105f97 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2665,10 +2665,11 @@ static void K_drawKartStatsnLives(void) { INT32 offsetx = 0; INT32 offsety = 0; + boolean split = r_splitscreen == 1; - if (cv_lives_xoffset.value == 0 || cv_lives_yoffset.value == 0) + if ((cv_lives_xoffset.value == 0 || cv_lives_yoffset.value == 0) || split) { - if ((cv_newspeedometer.value == 0 || cv_newspeedometer.value == 2) && !K_RingsActive()) + if ((cv_newspeedometer.value == 0 || cv_newspeedometer.value == 2) && !K_RingsActive() && !split) { offsetx = 25; offsety = 15; From 5505c02fd555b2b2e72bd200c8f2deaddea5680e Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sun, 30 Nov 2025 16:03:07 -0500 Subject: [PATCH 10/11] Fix logic oopsies in lives offset check --- src/k_hud.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_hud.c b/src/k_hud.c index 64f105f97..41eddc1b6 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2667,7 +2667,7 @@ static void K_drawKartStatsnLives(void) INT32 offsety = 0; boolean split = r_splitscreen == 1; - if ((cv_lives_xoffset.value == 0 || cv_lives_yoffset.value == 0) || split) + if ((cv_lives_xoffset.value == 0 && cv_lives_yoffset.value == 0) || split) { if ((cv_newspeedometer.value == 0 || cv_newspeedometer.value == 2) && !K_RingsActive() && !split) { From dfc1981854908c893bb9812574a428749b7deca8 Mon Sep 17 00:00:00 2001 From: yamamama Date: Sun, 30 Nov 2025 15:20:58 -0500 Subject: [PATCH 11/11] Add the "Arrow Bullet" * Toggleable QoL option for Alt. Shrink * While using Alt. Shrink, at or above a speed threshold (currently 175% the statblock's cruising speed), ignore most things that would damage you * Rewards breakaways and incentivizes going fast * Graphics are placeholder --- src/d_netcmd.c | 8 +++++++ src/d_netcmd.h | 2 ++ src/k_collide.c | 4 ++++ src/k_kart.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++-- src/k_kart.h | 3 +++ src/p_inter.c | 10 ++++++++ src/p_user.c | 5 ++++ 7 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 2ec3e980b..1657adea4 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -608,6 +608,14 @@ consvar_t cv_kartflame_fastfuel = CVAR_INIT ("kartflame_fastfuel", "Off", CV_NET // we want this to be default now apparently consvar_t cv_kartflame_offroadburn = CVAR_INIT ("kartflame_offroadburn", "On", CV_NETVAR, CV_OnOff, NULL); +// "Arrow Bullet": above a certain speed threshold, an aura in the shape of the Shrink arrow +// covers you, signaling protection from (most) items and players. +// Default threshold percentage is currently 166%. +consvar_t cv_kartaltshrink_arrowbullet = CVAR_INIT ("kart_altshrink_arrowbullet", "On", CV_NETVAR, CV_OnOff, NULL); + +static CV_PossibleValue_t altshrink_arrowbullet_threshold_cons_t[] = {{0, "MIN"}, {2 * FRACUNIT, "MAX"}, {0, NULL}}; +consvar_t cv_kartaltshrink_arrowbulletthres = CVAR_INIT ("kart_altshrink_arrowbullet_threshold", "1.66", CV_NETVAR|CV_FLOAT, altshrink_arrowbullet_threshold_cons_t, NULL); + static CV_PossibleValue_t kartairsquish_cons_t[] = {{1, "Squish"}, {2, "Flip-over"}, {0, "None"}, {0, NULL}}; consvar_t cv_kartairsquish = CVAR_INIT ("kartairsquish", "None", CV_NETVAR, kartairsquish_cons_t, NULL); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index b7cd9ad6f..5c41a3ce4 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -189,6 +189,8 @@ extern consvar_t cv_kartbubble_defense_damagerate; extern consvar_t cv_kartbubble_boost_allow; extern consvar_t cv_kartflame_fastfuel; extern consvar_t cv_kartflame_offroadburn; +extern consvar_t cv_kartaltshrink_arrowbullet; +extern consvar_t cv_kartaltshrink_arrowbulletthres; extern consvar_t cv_kartairsquish; diff --git a/src/k_collide.c b/src/k_collide.c index 0b363d6b9..d1e4c4e7f 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -856,6 +856,8 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) P_InstaThrust(t2, K_MomentumAngle(t2), K_Momentum2D(t2) / 3); K_PlayPainSound(t2, NULL); + + return true; } } if (P_IsObjectOnGround(t1) && P_IsObjectOnGround(t2)) @@ -899,6 +901,8 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) P_InstaThrust(t1, K_MomentumAngle(t1), K_Momentum2D(t1) / 3); K_PlayPainSound(t1, NULL); + + return true; } } else if (P_IsObjectOnGround(t1) && P_IsObjectOnGround(t2)) diff --git a/src/k_kart.c b/src/k_kart.c index 4f64bdf49..bc7fea8d1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -406,6 +406,8 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartbubble_boost_allow); CV_RegisterVar(&cv_kartflame_fastfuel); CV_RegisterVar(&cv_kartflame_offroadburn); + CV_RegisterVar(&cv_kartaltshrink_arrowbullet); + CV_RegisterVar(&cv_kartaltshrink_arrowbulletthres); CV_RegisterVar(&cv_kartairsquish); @@ -830,6 +832,22 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean sol return false; } + const boolean mobj1_intercepting = ((mobj1->player) && (K_InterceptArrowBullet(mobj1->player))); + const boolean mobj2_intercepting = ((mobj2->player) && (K_InterceptArrowBullet(mobj2->player))); + + // The other player is an Arrow Bullet, ignore them. + if (mobj1->player && K_AltShrinkArrowBulletCondition(mobj1->player) && (!mobj2_intercepting)) + { + mobj1->player->justbumped = bumptime; + return false; + } + + if (mobj2->player && K_AltShrinkArrowBulletCondition(mobj2->player) && (!mobj1_intercepting)) + { + mobj2->player->justbumped = bumptime; + return false; + } + mass1 = K_GetMobjWeight(mobj1, mobj2); if (solid == true && mass1 > 0) @@ -2160,7 +2178,8 @@ boolean K_TripwirePass(const player_t *player) boolean K_PlayerCanPunt(const player_t *player) { return player->invincibilitytimer > 0 || player->growshrinktimer > 0 || - (player->flamestore > 0 && K_GetShieldFromPlayer(player) == KSHIELD_FLAME); + (player->flamestore > 0 && K_GetShieldFromPlayer(player) == KSHIELD_FLAME) || + K_AltShrinkArrowBulletCondition(player); } boolean K_ItemMobjAllowedtoWaterRun(mobj_t *item) @@ -7520,7 +7539,15 @@ void K_KartResetPlayerColor(player_t *player) if (player->growshrinktimer) // Ditto, for grow/shrink { - if (player->growshrinktimer % 5 == 0) + if (K_AltShrinkArrowBulletCondition(player)) + { + // Arrow Bullet! + player->mo->colorized = true; + player->mo->color = SKINCOLOR_CREAMSICLE; + fullbright = true; + goto finalise; + } + else if (player->growshrinktimer % 5 == 0) { player->mo->colorized = true; player->mo->color = player->growshrinktimer < 0 ? SKINCOLOR_CREAMSICLE : SKINCOLOR_PERIWINKLE; @@ -8895,6 +8922,14 @@ static boolean K_AltInvinSliptideCondition(player_t *player) return (K_InvincibilityGradient(player->invincibilitytimer) > (FRACUNIT/2)); } +fixed_t K_GetSpeedPercentage(player_t *player) +{ + if (!player) + return 0; // NULL player means there's no speeed to gather. + + return (FixedDiv(player->speed, K_GetKartSpeed(player, false, false))); +} + // Sliptide conditions for Alt. Shrink static boolean K_AltShrinkSliptideCondition(player_t *player) { @@ -8910,6 +8945,28 @@ static boolean K_AltShrinkSliptideCondition(player_t *player) return (speedPercent > (3 * FRACUNIT / 4)); } +// Conditions for putting the player in "arrow bullet" mode. +boolean K_AltShrinkArrowBulletCondition(player_t *player) +{ + if (!cv_kartaltshrink_arrowbullet.value) // Not toggled on; we can't do anything + return false; + + if (!player) + return false; // NULL player means there's no way we can BE an arrow bullet. + + // Only if you're at or above the threshold percentage! + return (K_GetSpeedPercentage(player) >= cv_kartaltshrink_arrowbulletthres.value); +} + +// This player intercepts an Arrow Bullet and causes damage. +boolean K_InterceptArrowBullet(player_t *player) +{ + if (!player) + return false; + + return ((player->invincibilitytimer && !K_IsKartItemAlternate(KITEM_INVINCIBILITY)) || (player->growshrinktimer > 0) || (player->flamestore)); +} + static void K_HandleAirDriftDrag(player_t *player, boolean onground) { if (onground && player->airdriftspeed > 0) diff --git a/src/k_kart.h b/src/k_kart.h index 7cc5931d2..1892b0342 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -264,6 +264,9 @@ fixed_t K_InvincibilityGradient(UINT16 time); UINT16 K_GetInvincibilityTime(player_t *player); fixed_t K_GetInvincibilitySpeed(UINT16 time); fixed_t K_GetInvincibilityAccel(UINT16 time); +fixed_t K_GetSpeedPercentage(player_t *player); +boolean K_AltShrinkArrowBulletCondition(player_t *player); +boolean K_InterceptArrowBullet(player_t *player); void K_ResetPogoSpring(player_t *player); void K_DoInvincibility(player_t *player, tic_t time); void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source); diff --git a/src/p_inter.c b/src/p_inter.c index 6be083302..5b25a2d34 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2215,6 +2215,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da const boolean explosioncombo = type == DMG_EXPLODE // This damage type can do evil stuff like ALWAYS combo && player->bubbleboost == 0; // ...but popping a Bubble Shield protects you! + // An Arrow Bullet player ran into a player with a stronger power item. Damage them! + const boolean intercept = ((!P_MobjWasRemoved(inflictor)) && inflictor->player && K_InterceptArrowBullet(inflictor->player)); + // Check if the player is allowed to be damaged! // If not, then spawn the instashield effect instead. if (!force) @@ -2253,6 +2256,13 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; } + // Alt. Shrink: Tank non-explosion hits, as long as you're in Arrow Bullet mode. + if ((explosioncombo == false) && (intercept == false) && (K_AltShrinkArrowBulletCondition(player))) + { + K_DoInstashield(player); + return false; + } + // Bubble Shield protects you from spinout, but not knockback if (K_GetShieldFromPlayer(player) == KSHIELD_BUBBLE && explosioncombo == false && source != NULL && type != DMG_VOLTAGE diff --git a/src/p_user.c b/src/p_user.c index 6eb8d32ad..52ff68403 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2309,6 +2309,11 @@ void P_MovePlayer(player_t *player) K_SpawnSparkleTrail(player->mo); } + if (K_AltShrinkArrowBulletCondition(player)) + { + K_SpawnSparkleTrail(player->mo); + } + if (player->wipeoutslow > 1 && (leveltime & 1)) K_SpawnWipeoutTrail(player->mo, false);