diff --git a/bin/Mingw/Release/srb2kart_new-spb.exe.debug.txt.gz b/bin/Mingw/Release/srb2kart_new-spb.exe.debug.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..f5f6e770b06c3a6a65df22801d929e60d2887a76
Binary files /dev/null and b/bin/Mingw/Release/srb2kart_new-spb.exe.debug.txt.gz differ
diff --git a/src/d_player.h b/src/d_player.h
index 02f7f45ec23d94e9ec0d74b4e14975283acbb0f9..8600d61d33e108eae74355babd6515d6d28ddf76 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -327,7 +327,6 @@ typedef enum
 	k_squishedtimer,		// Squished frame timer
 	k_rocketsneakertimer,	// Rocket Sneaker duration timer
 	k_invincibilitytimer,	// Invincibility timer
-	k_deathsentence,		// 30 seconds to live... (SPB murder timer (not actually 30 sec, I just couldn't help the FF reference :p))
 	k_eggmanheld,			// Eggman monitor held, separate from k_itemheld so it doesn't stop you from getting items
 	k_eggmanexplode,		// Fake item recieved, explode in a few seconds
 	k_eggmanblame,			// Fake item recieved, who set this fake
diff --git a/src/dehacked.c b/src/dehacked.c
index 4a7599b9d90646199d06e707b28d57bef08ed34d..7ef3203cc0b0bd8f5b8233e0973237dfe9e6ed54 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1835,6 +1835,7 @@ static actionpointer_t actionpointers[] =
 	{{A_ItemPop},              "A_ITEMPOP"},       // SRB2kart
 	{{A_JawzChase},            "A_JAWZCHASE"}, // SRB2kart
 	{{A_JawzExplode},          "A_JAWZEXPLODE"}, // SRB2kart
+	{{A_SPBChase},             "A_SPBCHASE"}, // SRB2kart
 	{{A_MineExplode},          "A_MINEEXPLODE"}, // SRB2kart
 	{{A_BallhogExplode},       "A_BALLHOGEXPLODE"}, // SRB2kart
 	{{A_LightningFollowPlayer}, "A_LIGHTNINGFOLLOWPLAYER"},	//SRB2kart
@@ -6467,17 +6468,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_BALLHOGBOOM16",
 
 	// Self-Propelled Bomb - just an explosion for now...
-	"S_BLUELIGHTNING1",
-	"S_BLUELIGHTNING2",
-	"S_BLUELIGHTNING3",
-	"S_BLUELIGHTNING4",
-	"S_BLUEEXPLODE",
-
-	// Grow/shrink beams
-	"S_LIGHTNING1",
-	"S_LIGHTNING2",
-	"S_LIGHTNING3",
-	"S_LIGHTNING4",
+	"S_SPB",
+	"S_SPB_DEAD",
 
 	// Thunder Shield
 	"S_THUNDERSHIELD1",
@@ -7321,9 +7313,8 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_BALLHOG", // Ballhog
 	"MT_BALLHOGBOOM",
 
-	"MT_BLUELIGHTNING", // Grow/shrink stuff
-	"MT_BLUEEXPLOSION",
-	"MT_LIGHTNING",
+	"MT_SPB", // Self-Propelled Bomb
+	"MT_SPBEXPLOSION",
 
 	"MT_THUNDERSHIELD", // Thunder Shield stuff
 
@@ -7787,7 +7778,6 @@ static const char *const KARTSTUFF_LIST[] = {
 	"SQUISHEDTIMER",
 	"ROCKETSNEAKERTIMER",
 	"INVINCIBILITYTIMER",
-	"DEATHSENTENCE",
 	"EGGMANHELD",
 	"EGGMANEXPLODE",
 	"EGGMANBLAME",
diff --git a/src/doomstat.h b/src/doomstat.h
index 8e26d1001547c685ebf0bd9241f564ee3420ef4a..a8155812abae45b6e978bd82c9ac5bf09f03c46d 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -458,8 +458,6 @@ extern boolean comeback;
 extern SINT8 battlewanted[4];
 extern tic_t wantedcalcdelay;
 extern tic_t indirectitemcooldown;
-extern tic_t spbincoming;
-extern UINT8 spbplayer;
 extern tic_t mapreset;
 
 extern boolean legitimateexit;
diff --git a/src/g_game.c b/src/g_game.c
index ee1ee053a1db9c0b21b84f3fd7082c8fbb7f9e00..22265b1fac137a15e662d1aac0337558cfd7c92d 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -264,8 +264,6 @@ SINT8 pickedvote; // What vote the host rolls
 SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
 tic_t wantedcalcdelay; // Time before it recalculates WANTED
 tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded
-tic_t spbincoming; // Timer before SPB hits, can switch targets at this point
-UINT8 spbplayer; // Player num that used the last SPB
 tic_t mapreset; // Map reset delay when enough players have joined an empty game
 
 // Client-sided, unsynched variables (NEVER use in anything that needs to be synced with other players)
diff --git a/src/info.c b/src/info.c
index 932ff21a77b7f3721d210cc37f410b0a10872ab7..0b4e03beb428ac15f5fd9e06fb2b3e6999432e53 100644
--- a/src/info.c
+++ b/src/info.c
@@ -57,11 +57,11 @@ char sprnames[NUMSPRITES + 1][5] =
 	//SRB2kart Sprites
 	"SPRG","BSPR","RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE",
 	"KINV","KINF","WIPD","DRIF","DUST","FITM","BANA","ORBN","JAWZ","SSMN",
-	"KRBM","BHOG","BHBM","BLIG","LIGH","THNS","SINK","SITR","KBLN","DEZL",
-	"POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO",
-	"CRAB","SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO",
-	"ITEM","ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK","LZI1",
-	"LZI2","KLIT","VIEW"
+	"KRBM","BHOG","BHBM","SPBM","THNS","SINK","SITR","KBLN","DEZL","POKE",
+	"AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB",
+	"SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM",
+	"ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK","LZI1","LZI2",
+	"KLIT","VIEW"
 };
 
 // Doesn't work with g++, needs actionf_p1 (don't modify this comment)
@@ -2772,16 +2772,8 @@ state_t states[NUMSTATES] =
 	{SPR_BHBM, FF_FULLBRIGHT|14, 1, {NULL}, 0, 0, S_BALLHOGBOOM16},			// S_BALLHOGBOOM15
 	{SPR_BHBM, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_NULL},					// S_BALLHOGBOOM16
 
-	{SPR_BLIG, 0,  2, {NULL}, 0, 0, S_BLUELIGHTNING2},             // S_BLUELIGHTNING1
-	{SPR_BLIG, 1,  2, {NULL}, 0, 0, S_BLUELIGHTNING3},             // S_BLUELIGHTNING2
-	{SPR_BLIG, 2,  2, {NULL}, 0, 0, S_BLUELIGHTNING4},             // S_BLUELIGHTNING3
-	{SPR_BLIG, 3,  2, {NULL}, 0, 0, S_NULL},                       // S_BLUELIGHTNING4
-	{SPR_SSMN, 0,  1, {A_MineExplode}, MT_BLUEEXPLOSION, 0, S_NULL}, // S_BLUEEXPLODE
-
-	{SPR_LIGH, 0,  2, {NULL}, 0, 0, S_LIGHTNING2}, // S_LIGHTNING1
-	{SPR_LIGH, 1,  2, {NULL}, 0, 0, S_LIGHTNING3}, // S_LIGHTNING2
-	{SPR_LIGH, 2,  2, {NULL}, 0, 0, S_LIGHTNING4}, // S_LIGHTNING3
-	{SPR_LIGH, 3,  2, {NULL}, 0, 0, S_NULL},       // S_LIGHTNING4
+	{SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB}, // S_SPB
+	{SPR_SPBM, 0, 175, {NULL}, 0, 0, S_NULL}, // S_SPB_DEAD
 
 	{SPR_THNS, FF_FULLBRIGHT|9,  2, {NULL}, 0, 0, S_THUNDERSHIELD2},		// S_THUNDERSHIELD1
 	{SPR_THNS, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_THUNDERSHIELD3},		// S_THUNDERSHIELD2
@@ -15109,7 +15101,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
-		320*FRACUNIT,   // painchance
+		288*FRACUNIT,   // painchance
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
@@ -15316,34 +15308,34 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
-	{           // MT_BLUELIGHTNING
+	{           // MT_SPB
 		-1,             // doomednum
-		S_BLUELIGHTNING1, // spawnstate
-		1000,           // spawnhealth
+		S_SPB,          // spawnstate
+		1,              // spawnhealth
 		S_NULL,         // seestate
-		sfx_None,       // seesound
+		sfx_tossed,     // seesound
 		8,              // reactiontime
-		sfx_None,       // attacksound
+		sfx_kc57,       // attacksound
 		S_NULL,         // painstate
 		0,              // painchance
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_NULL,         // deathstate
+		S_SPB_DEAD,     // deathstate
 		S_NULL,         // xdeathstate
-		sfx_None,       // deathsound
-		8,              // speed
-		64*FRACUNIT,    // radius
-		64*FRACUNIT,    // height
+		sfx_s3k5d,      // deathsound
+		64*FRACUNIT,    // speed
+		16*FRACUNIT,    // radius
+		32*FRACUNIT,    // height
 		0,              // display offset
-		16,              // mass
-		0,              // damage
-		sfx_None,       // activesound
-		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
+		100,            // mass
+		1,              // damage
+		sfx_kc64,       // activesound
+		MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
 		S_NULL          // raisestate
 	},
 
-	{           // MT_BLUEEXPLOSION
+	{           // MT_SPBEXPLOSION
 		-1,             // doomednum
 		S_INVISIBLE,    // spawnstate
 		1,              // spawnhealth
@@ -15352,7 +15344,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
-		256*FRACUNIT,   // painchance
+		288*FRACUNIT,   // painchance
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
@@ -15370,33 +15362,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
-	{           // MT_LIGHTNING
-		-1,             // doomednum
-		S_LIGHTNING1,   // spawnstate
-		1000,           // spawnhealth
-		S_NULL,         // seestate
-		sfx_None,       // seesound
-		8,              // reactiontime
-		sfx_None,       // attacksound
-		S_NULL,         // painstate
-		0,              // painchance
-		sfx_None,       // painsound
-		S_NULL,         // meleestate
-		S_NULL,         // missilestate
-		S_NULL,         // deathstate
-		S_NULL,         // xdeathstate
-		sfx_None,       // deathsound
-		8,              // speed
-		64*FRACUNIT,    // radius
-		64*FRACUNIT,    // height
-		0,              // display offset
-		16,             // mass
-		0,              // damage
-		sfx_None,       // activesound
-		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
-		S_NULL          // raisestate
-	},
-
 	{           // MT_THUNDERSHIELD
 		-1,             // doomednum
 		S_THUNDERSHIELD1, // spawnstate
diff --git a/src/info.h b/src/info.h
index 9241363e65731f8979b61d00214913776549c911..70c91a6c82a96cf5fbeda8a46d3bd63fddcd9daa 100644
--- a/src/info.h
+++ b/src/info.h
@@ -166,6 +166,7 @@ void A_ToggleFlameJet();
 void A_ItemPop(); // SRB2kart
 void A_JawzChase(); // SRB2kart
 void A_JawzExplode(); // SRB2kart
+void A_SPBChase(); // SRB2kart
 void A_MineExplode(); // SRB2kart
 void A_BallhogExplode(); // SRB2kart
 void A_LightningFollowPlayer();	// SRB2kart: Lightning shield effect player chasing
@@ -604,8 +605,7 @@ typedef enum sprite
 	SPR_KRBM, // SS Mine BOOM
 	SPR_BHOG, // Ballhog
 	SPR_BHBM, // Ballhog BOOM
-	SPR_BLIG, // Self-Propelled Bomb
-	SPR_LIGH, // Grow/shrink beams (Metallic Maddness)
+	SPR_SPBM, // Self-Propelled Bomb
 	SPR_THNS, // Thunder Shield
 	SPR_SINK, // Kitchen Sink
 	SPR_SITR, // Kitchen Sink Trail
@@ -3310,18 +3310,9 @@ typedef enum state
 	S_BALLHOGBOOM15,
 	S_BALLHOGBOOM16,
 
-	// Self-Propelled Bomb - just an explosion for now...
-	S_BLUELIGHTNING1,
-	S_BLUELIGHTNING2,
-	S_BLUELIGHTNING3,
-	S_BLUELIGHTNING4,
-	S_BLUEEXPLODE,
-
-	// Grow/Shrink
-	S_LIGHTNING1,
-	S_LIGHTNING2,
-	S_LIGHTNING3,
-	S_LIGHTNING4,
+	// Self-Propelled Bomb
+	S_SPB,
+	S_SPB_DEAD,
 
 	// Thunder Shield
 	S_THUNDERSHIELD1,
@@ -4182,9 +4173,8 @@ typedef enum mobj_type
 	MT_BALLHOG, // Ballhog
 	MT_BALLHOGBOOM,
 
-	MT_BLUELIGHTNING, // Grow/shrink stuff
-	MT_BLUEEXPLOSION,
-	MT_LIGHTNING,
+	MT_SPB, // SPB stuff
+	MT_SPBEXPLOSION,
 
 	MT_THUNDERSHIELD, // Thunder Shield stuff
 
diff --git a/src/k_kart.c b/src/k_kart.c
index fccb68674de9575ce9e3923934cbb22cf4298efb..927db1f1efec7941eb8c8b6c24f38556786abc10 100644
--- a/src/k_kart.c
+++ b/src/k_kart.c
@@ -28,8 +28,6 @@
 // comeback is Battle Mode's karma comeback, also bool
 // battlewanted is an array of the WANTED player nums, -1 for no player in that slot
 // indirectitemcooldown is timer before anyone's allowed another Shrink/SPB
-// spbincoming is the timer before k_deathsentence is cast on the player in 1st
-// spbplayer is the last player who fired a SPB
 // mapreset is set when enough players fill an empty server
 
 
@@ -2190,7 +2188,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color)
 	height = source->height>>FRACBITS;
 
 	if (!color)
-		color = SKINCOLOR_RED;
+		color = SKINCOLOR_KETCHUP;
 
 	for (i = 0; i < 32; i++)
 	{
@@ -2733,7 +2731,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map
 		}
 		else
 		{
-			if (dir == -1)
+			if (dir == -1 && mapthing != MT_SPB)
 			{
 				// Shoot backward
 				mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/4);
@@ -3016,38 +3014,6 @@ static void K_DoShrink(player_t *player)
 	}
 }
 
-static void K_DoSPB(player_t *victim)
-{
-	//INT32 i;
-	S_StartSound(victim->mo, sfx_bkpoof); // Sound the BANG!
-
-	/*for (i = 0; i < MAXPLAYERS; i++)
-	{
-		if (playeringame[i])
-			P_FlashPal(&players[i], PAL_NUKE, 10);
-	}*/
-
-	if (!victim->mo || !victim->mo->health || victim->spectator)
-		return;
-
-	{
-		mobj_t *spbexplode;
-
-		if (!victim->kartstuff[k_invincibilitytimer] && !victim->kartstuff[k_growshrinktimer])
-		{
-			K_DropHnextList(victim);
-			K_StripItems(victim);
-
-			victim->powers[pw_flashing] = 0;
-		}
-
-		spbexplode = P_SpawnMobj(victim->mo->x, victim->mo->y, victim->mo->z, MT_BLUEEXPLOSION);
-
-		if (playeringame[spbplayer] && !players[spbplayer].spectator && players[spbplayer].mo)
-			P_SetTarget(&spbexplode->target, players[spbplayer].mo);
-	}
-}
-
 void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound)
 {
 	const fixed_t vscale = mapheaderinfo[gamemap-1]->mobj_scale + (mo->scale - mapheaderinfo[gamemap-1]->mobj_scale);
@@ -3923,13 +3889,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
 	if (player->kartstuff[k_justbumped])
 		player->kartstuff[k_justbumped]--;
 
-	if (player->kartstuff[k_deathsentence])
-	{
-		if (player->kartstuff[k_deathsentence] == 1)
-			K_DoSPB(player);
-		player->kartstuff[k_deathsentence]--;
-	}
-
 	if (player->kartstuff[k_lapanimation])
 		player->kartstuff[k_lapanimation]--;
 
@@ -3991,7 +3950,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
 			{
 				mobj_t *eggsexplode;
 				player->powers[pw_flashing] = 0;
-				eggsexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUEEXPLOSION);
+				eggsexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SPBEXPLOSION);
 				if (player->kartstuff[k_eggmanblame] >= 0
 				&& player->kartstuff[k_eggmanblame] < MAXPLAYERS
 				&& playeringame[player->kartstuff[k_eggmanblame]]
@@ -4799,45 +4758,14 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
 					{
 						player->kartstuff[k_itemamount]--;
 						K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0);
-						S_StartSound(player->mo, sfx_mario7);
 						K_PlayAttackTaunt(player->mo);
 					}
 					break;
 				case KITEM_SPB:
 					if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
 					{
-						UINT8 ploop;
-						UINT8 bestrank = 0;
-						fixed_t dist = 0;
-
-						for (ploop = 0; ploop < MAXPLAYERS; ploop++)
-						{
-							fixed_t thisdist;
-							if (!playeringame[ploop] || players[ploop].spectator)
-								continue;
-							if (&players[ploop] == player)
-								continue;
-							if (!players[ploop].mo)
-								continue;
-							if (players[ploop].exiting)
-								continue;
-							thisdist = R_PointToDist2(player->mo->x, player->mo->y, players[ploop].mo->x, players[ploop].mo->y);
-							if (bestrank == 0 || players[ploop].kartstuff[k_position] < bestrank)
-							{
-								bestrank = players[ploop].kartstuff[k_position];
-								dist = thisdist;
-							}
-						}
-
-						if (dist == 0)
-							spbincoming = 6*TICRATE; // If you couldn't find anyone, just set an abritary timer
-						else
-							spbincoming = (tic_t)max(1, FixedDiv(dist, 64*FRACUNIT)/FRACUNIT);
-
-						spbplayer = player-players;
-
 						player->kartstuff[k_itemamount]--;
-
+						K_ThrowKartItem(player, true, MT_SPB, 1, 0);
 						K_PlayAttackTaunt(player->mo);
 					}
 					break;
@@ -4949,9 +4877,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
 
 		if (player->kartstuff[k_itemtype] == KITEM_SPB
 			|| player->kartstuff[k_itemtype] == KITEM_SHRINK
-			|| player->kartstuff[k_growshrinktimer] < 0
-			|| spbincoming)
-			indirectitemcooldown = 20*TICRATE;
+			|| player->kartstuff[k_growshrinktimer] < 0)
+			indirectitemcooldown = 30*TICRATE;
 
 		if (player->kartstuff[k_hyudorotimer] > 0)
 		{
@@ -5436,7 +5363,6 @@ static patch_t *kp_sadface[2];
 
 static patch_t *kp_check[6];
 
-static patch_t *kp_spbwarning[2];
 static patch_t *kp_eggnum[4];
 
 static patch_t *kp_fpview[3];
@@ -5593,10 +5519,6 @@ void K_LoadKartHUDGraphics(void)
 		kp_check[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
 	}
 
-	// SPB warning
-	kp_spbwarning[0] = 			W_CachePatchName("K_SPBW1", PU_HUDGFX);
-	kp_spbwarning[1] = 			W_CachePatchName("K_SPBW2", PU_HUDGFX);
-
 	// Eggman warning numbers
 	sprintf(buffer, "K_EGGNx");
 	for (i = 0; i < 4; i++)
@@ -5718,7 +5640,6 @@ INT32 FACE_X, FACE_Y;	// Top-four Faces
 INT32 STCD_X, STCD_Y;	// Starting countdown
 INT32 CHEK_Y;			// CHECK graphic
 INT32 MINI_X, MINI_Y;	// Minimap
-INT32 SPBW_X, SPBW_Y;	// SPB warning
 INT32 WANT_X, WANT_Y;	// Battle WANTED poster
 
 static void K_initKartHUD(void)
@@ -5784,9 +5705,6 @@ static void K_initKartHUD(void)
 	// Minimap
 	MINI_X = BASEVIDWIDTH - 50;		// 270
 	MINI_Y = (BASEVIDHEIGHT/2)-16; //  84
-	// Blue Shell warning
-	SPBW_X = BASEVIDWIDTH/2;		// 270
-	SPBW_Y = BASEVIDHEIGHT- 24;		// 176
 	// Battle WANTED poster
 	WANT_X = BASEVIDWIDTH - 55;		// 270
 	WANT_Y = BASEVIDHEIGHT- 71;		// 176
@@ -5804,8 +5722,6 @@ static void K_initKartHUD(void)
 
 		MINI_Y = (BASEVIDHEIGHT/2);
 
-		SPBW_Y = (BASEVIDHEIGHT/2)-8;
-
 		WANT_X = BASEVIDWIDTH-8;
 		WANT_Y = (BASEVIDHEIGHT/2)-12;
 
@@ -5824,8 +5740,6 @@ static void K_initKartHUD(void)
 			MINI_X = (3*BASEVIDWIDTH/4);
 			MINI_Y = (3*BASEVIDHEIGHT/4);
 
-			SPBW_X = BASEVIDWIDTH/4;
-
 			WANT_X = (BASEVIDWIDTH/2)-8;
 
 			if (splitscreen > 2) // 4P-only
@@ -6449,23 +6363,6 @@ static void K_drawKartBumpersOrKarma(void)
 	}
 }
 
-static void K_drawSPBWarning(void)
-{
-	patch_t *localpatch = kp_nodraw;
-	INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM);
-
-	if (!(stplyr->kartstuff[k_deathsentence] > 0
-		|| (spbincoming > 0 && spbincoming < 2*TICRATE && stplyr->kartstuff[k_position] == 1)))
-		return;
-
-	if (leveltime % 8 > 3)
-		localpatch = kp_spbwarning[1];
-	else
-		localpatch = kp_spbwarning[0];
-
-	V_DrawScaledPatch(SPBW_X, SPBW_Y, splitflags, localpatch);
-}
-
 fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my)
 {
 	fixed_t dist, x;
@@ -7504,9 +7401,6 @@ void K_drawKartHUD(void)
 				// Draw the input UI
 				K_drawInput();
 			}
-
-			// You're about to DIEEEEE
-			K_drawSPBWarning();
 		}
 		else if (G_BattleGametype()) // Battle-only
 		{
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 37dd589981255f2284403e83e7c57e04c7b219ce..f9bc638e6c6e66434ec3814d21edaeafc81708b8 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -190,6 +190,7 @@ void A_ToggleFlameJet(mobj_t *actor);
 void A_ItemPop(mobj_t *actor); // SRB2kart
 void A_JawzChase(mobj_t *actor); // SRB2kart
 void A_JawzExplode(mobj_t *actor); // SRB2kart
+void A_SPBChase(mobj_t *actor); // SRB2kart
 void A_MineExplode(mobj_t *actor); // SRB2kart
 void A_BallhogExplode(mobj_t *actor); // SRB2kart
 void A_LightningFollowPlayer(mobj_t *actor);	// SRB2kart
@@ -4053,7 +4054,7 @@ void A_MineExplode(mobj_t *actor)
 	if (actor->target && actor->target->player)
 		K_SpawnMineExplosion(actor, actor->target->player->skincolor);
 	else
-		K_SpawnMineExplosion(actor, SKINCOLOR_RED);
+		K_SpawnMineExplosion(actor, SKINCOLOR_KETCHUP);
 
 	P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINEEXPLOSIONSOUND);
 }
@@ -8173,7 +8174,7 @@ void A_ToggleFlameJet(mobj_t* actor)
 	}
 }
 
-//{ SRB2kart - A_ItemPop, A_JawzChase, A_JawzExplode, A_MineExplode, and A_BallhogExplode
+//{ SRB2kart - A_ItemPop, A_JawzChase, A_JawzExplode, A_SPBChase, A_MineExplode, and A_BallhogExplode
 void A_ItemPop(mobj_t *actor)
 {
 	mobj_t *remains;
@@ -8293,7 +8294,7 @@ void A_JawzExplode(mobj_t *actor)
 
 	truc = P_SpawnMobj(actor->x, actor->y, actor->z, MT_BOOMEXPLODE);
 	truc->scale = actor->scale*2;
-	truc->color = SKINCOLOR_RED;
+	truc->color = SKINCOLOR_KETCHUP;
 
 	while (shrapnel)
 	{
@@ -8311,7 +8312,7 @@ void A_JawzExplode(mobj_t *actor)
 		speed2 = FixedMul(15*FRACUNIT, actor->scale)>>FRACBITS;
 		truc->momz = P_RandomRange(speed, speed2)*FRACUNIT;
 		truc->tics = TICRATE*2;
-		truc->color = SKINCOLOR_RED;
+		truc->color = SKINCOLOR_KETCHUP;
 
 		shrapnel--;
 	}
@@ -8319,65 +8320,99 @@ void A_JawzExplode(mobj_t *actor)
 	return;
 }
 
-/* old A_MineExplode - see elsewhere in the file
-void A_MineExplode(mobj_t *actor)
+void A_SPBChase(mobj_t *actor)
 {
-	mobj_t *mo2;
-	thinker_t *th;
-	INT32 d;
-	INT32 locvar1 = var1;
-	mobjtype_t type;
-	fixed_t range;
+	player_t *player = NULL;
+	UINT8 i;
+	UINT8 bestrank = UINT8_MAX;
+	fixed_t dist;
+	angle_t hang, vang;
 #ifdef HAVE_BLUA
-	if (LUA_CallAction("A_MineExplode", actor))
+	if (LUA_CallAction("A_SPBChase", actor))
 		return;
 #endif
 
-	type = (mobjtype_t)locvar1;
-	range = FixedMul(actor->info->painchance, mapheaderinfo[gamemap-1]->mobj_scale);
+	if (actor->threshold)
+	{
+		P_InstaThrust(actor, actor->angle, actor->info->speed);
+		return;
+	}
 
-	for (th = thinkercap.next; th != &thinkercap; th = th->next)
+	if (actor->extravalue1)
 	{
-		if (P_MobjWasRemoved(actor))
-			return; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
+		if (actor->tracer && actor->tracer->health && actor->tracer->player)
+		{
+			fixed_t maxspeed = K_GetKartSpeed(actor->tracer->player, false) - (actor->tracer->scale);
 
-		if (th->function.acp1 != (actionf_p1)P_MobjThinker)
-			continue;
+			if (!S_SoundPlaying(actor, actor->info->activesound))
+				S_StartSound(actor, actor->info->activesound);
 
-		mo2 = (mobj_t *)th;
+			dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z);
 
-		if (mo2 == actor || mo2->type == MT_MINEEXPLOSIONSOUND) // Don't explode yourself! Endless loop!
-			continue;
+			hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y);
+			vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z);
 
-		if (!(mo2->flags & MF_SHOOTABLE) || (mo2->flags & MF_SCENERY))
-			continue;
+			actor->momx = FixedMul(FixedMul(maxspeed, FINECOSINE(hang>>ANGLETOFINESHIFT)), FINECOSINE(vang>>ANGLETOFINESHIFT));
+			actor->momy = FixedMul(FixedMul(maxspeed, FINESINE(hang>>ANGLETOFINESHIFT)), FINECOSINE(vang>>ANGLETOFINESHIFT));
+			actor->momz = FixedMul(maxspeed, FINESINE(vang>>ANGLETOFINESHIFT));
 
-		if (G_BattleGametype() && actor->target && actor->target->player && actor->target->player->kartstuff[k_bumper] <= 0 && mo2 == actor->target)
+			actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
+			return;
+		}
+		else
+		{
+			P_SetTarget(&actor->tracer, NULL);
+			actor->extravalue1 = 0;
+		}
+	}
+
+	for (i = 0; i < MAXPLAYERS; i++)
+	{
+		if (!playeringame[i])
 			continue;
 
-		if (P_AproxDistance(P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y), mo2->z - actor->z) > range)
+		if (players[i].spectator)
 			continue;
 
-		actor->flags2 |= MF2_DEBRIS;
+		if (players[i].exiting)
+			continue; // exiting
 
-		if (mo2->player) // Looks like we're going to have to need a seperate function for this too
-			K_ExplodePlayer(mo2->player, actor->target);
-		else
-			P_DamageMobj(mo2, actor, actor->target, 1);
+		if (!players[i].mo)
+			continue; // no mobj
+
+		if (players[i].mo->health <= 0)
+			continue; // dead
+
+		if (players[i].kartstuff[k_position] < bestrank)
+		{
+			bestrank = players[i].kartstuff[k_position];
+			player = &players[i];
+		}
 	}
 
-	for (d = 0; d < 16; d++)
-		K_SpawnKartExplosion(actor->x, actor->y, actor->z, range + 32*mapheaderinfo[gamemap-1]->mobj_scale, 32, type, d*(ANGLE_45/4), true, false, actor->target); // 32 <-> 64
+	if (player != NULL && player->mo)
+	{
+		P_SetTarget(&actor->tracer, player->mo);
 
-	if (actor->target && actor->target->player)
-		K_SpawnMineExplosion(actor, actor->target->player->skincolor);
-	else
-		K_SpawnMineExplosion(actor, SKINCOLOR_RED);
+		dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z);
+		hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y);
+		vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z);
 
-	P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINEEXPLOSIONSOUND);
+		actor->momx = FixedMul(FixedMul(actor->info->speed, FINECOSINE(hang>>ANGLETOFINESHIFT)), FINECOSINE(vang>>ANGLETOFINESHIFT));
+		actor->momy = FixedMul(FixedMul(actor->info->speed, FINESINE(hang>>ANGLETOFINESHIFT)), FINECOSINE(vang>>ANGLETOFINESHIFT));
+		actor->momz = FixedMul(actor->info->speed, FINESINE(vang>>ANGLETOFINESHIFT));
+
+		actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
+
+		if (dist <= RING_DIST && (actor->z > actor->floorz && actor->z+actor->height < actor->ceilingz))
+		{
+			S_StartSound(actor, actor->info->attacksound);
+			actor->extravalue1 = 1;
+		}
+	}
 
 	return;
-}*/
+}
 
 void A_BallhogExplode(mobj_t *actor)
 {
diff --git a/src/p_inter.c b/src/p_inter.c
index cd0ed8938e3a0854e2758e546e333b88ea866698..6342c0334457b78eb5571d7fbad3674cb2a4ea52 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -490,7 +490,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 					if (special->target->color)
 						boom->color = special->target->color;
 					else
-						boom->color = SKINCOLOR_RED;
+						boom->color = SKINCOLOR_KETCHUP;
 					S_StartSound(boom, special->info->attacksound);
 
 					if (player->kartstuff[k_bumper] == 1) // If you have only one bumper left, and see if it's a 1v1
@@ -583,6 +583,36 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 				special->target->player->kartstuff[k_eggmanblame] = -1;
 			}
 			return;
+		case MT_SPB:
+			if ((special->target == toucher || special->target == toucher->target) && (special->threshold > 0))
+				return;
+
+			if (special->health <= 0 || toucher->health <= 0)
+				return;
+
+			if (!player->mo || player->spectator)
+				return;
+
+			if (special->tracer && toucher == special->tracer)
+			{
+				mobj_t *spbexplode;
+
+				if (!player->kartstuff[k_invincibilitytimer] && !player->kartstuff[k_growshrinktimer])
+				{
+					K_DropHnextList(player);
+					K_StripItems(player);
+					player->powers[pw_flashing] = 0;
+				}
+
+				spbexplode = P_SpawnMobj(toucher->x, toucher->y, toucher->z, MT_SPBEXPLOSION);
+				P_SetTarget(&spbexplode->target, special->target);
+
+				P_RemoveMobj(special);
+			}
+			else
+				K_SpinPlayer(player, special, 0, false);
+
+			return;
 
 // ***************************************** //
 // Rings, coins, spheres, weapon panels, etc //
@@ -2201,7 +2231,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
 		 || target->type == MT_JAWZ || target->type == MT_JAWZ_DUD || target->type == MT_JAWZ_SHIELD
 		 || target->type == MT_BANANA || target->type == MT_BANANA_SHIELD
 		 || target->type == MT_FAKEITEM || target->type == MT_FAKESHIELD
-		 || target->type == MT_BALLHOG)) // kart dead items
+		 || target->type == MT_BALLHOG || target->type == MT_SPB)) // kart dead items
 		target->flags |= MF_NOGRAVITY; // Don't drop Tails 03-08-2000
 	else
 		target->flags &= ~MF_NOGRAVITY; // lose it if you for whatever reason have it, I'm looking at you shields
@@ -3355,8 +3385,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 				player->kartstuff[k_growshrinktimer] = 2;
 			}
 			player->kartstuff[k_sneakertimer] = 0;
-			// Invincible or not, we still need this.
-			//P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_LIGHTNING);
 			S_StartSound(player->mo, sfx_kc59);
 			return true;
 		}
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 32ac65502203e51ed661e9d9510de98019454d6c..0fe3534ea2e2fd2f00ac1e761e940e8fb3cc5099 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -7413,6 +7413,7 @@ void P_MobjThinker(mobj_t *mobj)
 		case MT_ORBINAUT:
 		case MT_BANANA:
 		case MT_FAKEITEM:
+		case MT_SPB:
 			if (mobj->z <= mobj->floorz)
 			{
 				P_RemoveMobj(mobj);
@@ -7433,7 +7434,7 @@ void P_MobjThinker(mobj_t *mobj)
 			mobj->flags2 ^= MF2_DONTDRAW;
 			break;
 		case MT_SSMINE:
-		case MT_BLUEEXPLOSION:
+		case MT_SPBEXPLOSION:
 			if (mobj->health > -100)
 			{
 				P_SetMobjState(mobj, mobj->info->deathstate);
@@ -8168,6 +8169,7 @@ void P_MobjThinker(mobj_t *mobj)
 				mobj->threshold--;
 			break;
 		case MT_BALLHOG:
+		case MT_SPB:
 			P_SpawnGhostMobj(mobj)->fuse = 3;
 			if (mobj->threshold > 0)
 				mobj->threshold--;
@@ -8187,7 +8189,7 @@ void P_MobjThinker(mobj_t *mobj)
 			if (mobj->target && mobj->target->player)
 				mobj->color = mobj->target->player->skincolor;
 			else
-				mobj->color = SKINCOLOR_RED;
+				mobj->color = SKINCOLOR_KETCHUP;
 			if (mobj->momx || mobj->momy)
 				P_SpawnGhostMobj(mobj);
 			if (P_IsObjectOnGround(mobj))
@@ -8213,7 +8215,7 @@ void P_MobjThinker(mobj_t *mobj)
 			if (mobj->threshold > 0)
 				mobj->threshold--;
 			break;
-		case MT_BLUEEXPLOSION:
+		case MT_SPBEXPLOSION:
 			mobj->health--;
 			break;
 		case MT_MINEEXPLOSION:
@@ -9341,7 +9343,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 		case MT_JAWZ: 			case MT_JAWZ_DUD: 		case MT_JAWZ_SHIELD:
 		case MT_SSMINE: 		case MT_SSMINE_SHIELD:
 		case MT_BALLHOG: 		case MT_SINK:
-		case MT_THUNDERSHIELD:
+		case MT_THUNDERSHIELD:	case MT_SPB:
 			P_SpawnShadowMobj(mobj);
 		default:
 			break;
diff --git a/src/p_saveg.c b/src/p_saveg.c
index df76497d9cfcfca90ab6a37fa7570a9a18240cb4..6bf258dd01b406f8b74b3e07633a1f5e91c64974 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -3284,8 +3284,6 @@ static void P_NetArchiveMisc(void)
 
 	WRITEUINT32(save_p, wantedcalcdelay);
 	WRITEUINT32(save_p, indirectitemcooldown);
-	WRITEUINT32(save_p, spbincoming);
-	WRITEUINT8(save_p, spbplayer);
 	WRITEUINT32(save_p, mapreset);
 
 	// Is it paused?
@@ -3390,8 +3388,6 @@ static inline boolean P_NetUnArchiveMisc(void)
 
 	wantedcalcdelay = READUINT32(save_p);
 	indirectitemcooldown = READUINT32(save_p);
-	spbincoming = READUINT32(save_p);
-	spbplayer = READUINT8(save_p);
 	mapreset = READUINT32(save_p);
 
 	// Is it paused?
diff --git a/src/p_setup.c b/src/p_setup.c
index a606dca07a5bc00b13ef2bee980cbbdce729839d..7356dcbb3495bb64afba8db118439d331d86adc2 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -3023,8 +3023,6 @@ boolean P_SetupLevel(boolean skipprecip)
 
 	wantedcalcdelay = wantedfrequency*2;
 	indirectitemcooldown = 0;
-	spbincoming = 0;
-	spbplayer = 0;
 	mapreset = 0;
 
 	// clear special respawning que
diff --git a/src/p_tick.c b/src/p_tick.c
index 9b59e70dd82e88a08b6401938015684718327d75..e2a1bb4b607eb66ae72c0a9a9c2b6cb027b7f175 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -678,38 +678,6 @@ void P_Ticker(boolean run)
 		if (countdown2)
 			countdown2--;
 
-		if (spbincoming && --spbincoming <= 0)
-		{
-			UINT8 best = 0;
-			SINT8 hurtthisguy = -1;
-
-			spbincoming = 0;
-
-			for (i = 0; i < MAXPLAYERS; i++)
-			{
-				if (!playeringame[i] || players[i].spectator)
-					continue;
-
-				if (!players[i].mo)
-					continue;
-
-				if (players[i].exiting)
-					continue;
-
-				if (best <= 0 || players[i].kartstuff[k_position] < best)
-				{
-					best = players[i].kartstuff[k_position];
-					hurtthisguy = i;
-				}
-			}
-
-			if (hurtthisguy != -1)
-			{
-				players[hurtthisguy].kartstuff[k_deathsentence] = (2*TICRATE)+1;
-				S_StartSound(players[hurtthisguy].mo, sfx_kc57);
-			}
-		}
-
 		if (indirectitemcooldown)
 			indirectitemcooldown--;
 
diff --git a/src/p_user.c b/src/p_user.c
index 472d7c27fbd12c04b71857f8022ee44449cfa1bc..e785650f1c7b7c59240dda0bb40c73e0d6d0d20a 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -7671,7 +7671,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
 			|| mo->type == MT_ORBINAUT_SHIELD || mo->type == MT_JAWZ_SHIELD
 			|| mo->type == MT_BANANA || mo->type == MT_BANANA_SHIELD
 			|| mo->type == MT_FAKEITEM || mo->type == MT_FAKESHIELD
-			|| mo->type == MT_BALLHOG)
+			|| mo->type == MT_BALLHOG || mo->type == MT_SPB)
 		{
 			if (mo->eflags & MFE_VERTICALFLIP)
 				mo->z -= mo->height;