diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 556d8638433dfe9b83580630dfcff9ce8726dbe5..01e94485d85696736fa334ecbe40225ba77b66da 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -513,6 +513,10 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
 	rsp->currentweapon = LONG(players[i].currentweapon);
 	rsp->ringweapons = LONG(players[i].ringweapons);
 
+	rsp->ammoremoval = (UINT16)SHORT(players[i].ammoremoval);
+	rsp->ammoremovaltimer = (tic_t)LONG(players[i].ammoremovaltimer);
+	rsp->ammoremovalweapon = LONG(players[i].ammoremovalweapon);
+
 	for (j = 0; j < NUMPOWERS; ++j)
 		rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]);
 
@@ -644,6 +648,10 @@ static void resynch_read_player(resynch_pak *rsp)
 	players[i].currentweapon = LONG(rsp->currentweapon);
 	players[i].ringweapons = LONG(rsp->ringweapons);
 
+	players[i].ammoremoval = (UINT16)SHORT(rsp->ammoremoval);
+	players[i].ammoremovaltimer = (tic_t)LONG(rsp->ammoremovaltimer);
+	players[i].ammoremovalweapon = LONG(rsp->ammoremovalweapon);
+
 	for (j = 0; j < NUMPOWERS; ++j)
 		players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]);
 
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index a6783fb3d120982ae61477f1f86f1b1cc5f57a6f..a2f140f330a2fad15e362cb7deb632f87ba667f6 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -164,6 +164,9 @@ typedef struct
 	angle_t aiming;
 	INT32 currentweapon;
 	INT32 ringweapons;
+	UINT16 ammoremoval;
+	tic_t ammoremovaltimer;
+	INT32 ammoremovalweapon;
 	UINT16 powers[NUMPOWERS];
 
 	// Score is resynched in the confirm resync packet
diff --git a/src/d_netfil.c b/src/d_netfil.c
index db9fa12e4957c86be3bd0579907bb9ea33af8230..ed2d11138ad267f51353c29673f15783b4a97061 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -745,9 +745,12 @@ void Got_Filetxpak(void)
 {
 	INT32 filenum = netbuffer->u.filetxpak.fileid;
 	fileneeded_t *file = &fileneeded[filenum];
-	char *filename = file->filename;
+	char *filename;
 	static INT32 filetime = 0;
 
+	filename = va("%s", file->filename);
+	nameonly(filename);
+
 	if (!(strcmp(filename, "srb2.pk3")
 		&& strcmp(filename, "srb2.srb")
 		&& strcmp(filename, "srb2.wad")
@@ -758,6 +761,8 @@ void Got_Filetxpak(void)
 		))
 		I_Error("Tried to download \"%s\"", filename);
 
+	filename = file->filename;
+
 	if (filenum >= fileneedednum)
 	{
 		DEBFILE(va("fileframent not needed %d>%d\n", filenum, fileneedednum));
diff --git a/src/d_player.h b/src/d_player.h
index c133af7039cac5b02ef609be63b8f1fadbc19453..5860cf1de4b05f86b7567c4d87c3699475513c71 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -333,6 +333,10 @@ typedef struct player_s
 	INT32 currentweapon; // current weapon selected.
 	INT32 ringweapons; // weapons currently obtained.
 
+	UINT16 ammoremoval; // amount of ammo removed for the current weapon.
+	tic_t  ammoremovaltimer; // flashing counter for ammo used.
+	INT32  ammoremovalweapon; // weapon from which the ammo was removed.
+
 	// Power ups. invinc and invis are tic counters.
 	UINT16 powers[NUMPOWERS];
 
diff --git a/src/dehacked.c b/src/dehacked.c
index 2f28a74cf8e7787db06cddb7b6882f1278b8a02c..5db61a5b5ea22eb508d097d1a6683d52bd5c3517 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -3347,6 +3347,10 @@ static void readmaincfg(MYFILE *f)
 			{
 				gameovertics = get_number(word2);
 			}
+			else if (fastcmp(word, "AMMOREMOVALTICS"))
+			{
+				ammoremovaltics = get_number(word2);
+			}
 			else if (fastcmp(word, "INTROTOPLAY"))
 			{
 				introtoplay = (UINT8)get_number(word2);
@@ -4616,25 +4620,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_EGGMOBILE_PANIC5",
 	"S_EGGMOBILE_PANIC6",
 	"S_EGGMOBILE_PANIC7",
-	"S_EGGMOBILE_PANIC8",
-	"S_EGGMOBILE_PANIC9",
-	"S_EGGMOBILE_PANIC10",
 	"S_EGGMOBILE_PAIN",
 	"S_EGGMOBILE_PAIN2",
 	"S_EGGMOBILE_DIE1",
 	"S_EGGMOBILE_DIE2",
 	"S_EGGMOBILE_DIE3",
 	"S_EGGMOBILE_DIE4",
-	"S_EGGMOBILE_DIE5",
-	"S_EGGMOBILE_DIE6",
-	"S_EGGMOBILE_DIE7",
-	"S_EGGMOBILE_DIE8",
-	"S_EGGMOBILE_DIE9",
-	"S_EGGMOBILE_DIE10",
-	"S_EGGMOBILE_DIE11",
-	"S_EGGMOBILE_DIE12",
-	"S_EGGMOBILE_DIE13",
-	"S_EGGMOBILE_DIE14",
 	"S_EGGMOBILE_FLEE1",
 	"S_EGGMOBILE_FLEE2",
 	"S_EGGMOBILE_BALL",
@@ -4655,16 +4646,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_EGGMOBILE2_DIE2",
 	"S_EGGMOBILE2_DIE3",
 	"S_EGGMOBILE2_DIE4",
-	"S_EGGMOBILE2_DIE5",
-	"S_EGGMOBILE2_DIE6",
-	"S_EGGMOBILE2_DIE7",
-	"S_EGGMOBILE2_DIE8",
-	"S_EGGMOBILE2_DIE9",
-	"S_EGGMOBILE2_DIE10",
-	"S_EGGMOBILE2_DIE11",
-	"S_EGGMOBILE2_DIE12",
-	"S_EGGMOBILE2_DIE13",
-	"S_EGGMOBILE2_DIE14",
 	"S_EGGMOBILE2_FLEE1",
 	"S_EGGMOBILE2_FLEE2",
 
@@ -4714,16 +4695,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_EGGMOBILE3_DIE2",
 	"S_EGGMOBILE3_DIE3",
 	"S_EGGMOBILE3_DIE4",
-	"S_EGGMOBILE3_DIE5",
-	"S_EGGMOBILE3_DIE6",
-	"S_EGGMOBILE3_DIE7",
-	"S_EGGMOBILE3_DIE8",
-	"S_EGGMOBILE3_DIE9",
-	"S_EGGMOBILE3_DIE10",
-	"S_EGGMOBILE3_DIE11",
-	"S_EGGMOBILE3_DIE12",
-	"S_EGGMOBILE3_DIE13",
-	"S_EGGMOBILE3_DIE14",
 	"S_EGGMOBILE3_FLEE1",
 	"S_EGGMOBILE3_FLEE2",
 
@@ -4770,16 +4741,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_EGGMOBILE4_DIE2",
 	"S_EGGMOBILE4_DIE3",
 	"S_EGGMOBILE4_DIE4",
-	"S_EGGMOBILE4_DIE5",
-	"S_EGGMOBILE4_DIE6",
-	"S_EGGMOBILE4_DIE7",
-	"S_EGGMOBILE4_DIE8",
-	"S_EGGMOBILE4_DIE9",
-	"S_EGGMOBILE4_DIE10",
-	"S_EGGMOBILE4_DIE11",
-	"S_EGGMOBILE4_DIE12",
-	"S_EGGMOBILE4_DIE13",
-	"S_EGGMOBILE4_DIE14",
 	"S_EGGMOBILE4_FLEE1",
 	"S_EGGMOBILE4_FLEE2",
 	"S_EGGMOBILE4_MACE",
@@ -4835,6 +4796,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_FANG_FIRE3",
 	"S_FANG_FIRE4",
 	"S_FANG_FIREREPEAT",
+	"S_FANG_LOBSHOT0",
 	"S_FANG_LOBSHOT1",
 	"S_FANG_LOBSHOT2",
 	"S_FANG_WAIT1",
@@ -4851,6 +4813,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_FANG_PINCHFALL2",
 	"S_FANG_PINCHSKID1",
 	"S_FANG_PINCHSKID2",
+	"S_FANG_PINCHLOBSHOT0",
 	"S_FANG_PINCHLOBSHOT1",
 	"S_FANG_PINCHLOBSHOT2",
 	"S_FANG_PINCHLOBSHOT3",
@@ -5156,8 +5119,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_METALSONIC_DEATH4",
 	"S_METALSONIC_FLEE1",
 	"S_METALSONIC_FLEE2",
-	"S_METALSONIC_FLEE3",
-	"S_METALSONIC_FLEE4",
 
 	"S_MSSHIELD_F1",
 	"S_MSSHIELD_F2",
diff --git a/src/g_game.c b/src/g_game.c
index e70241269b6db950346e492b91d012fb54f544ae..d5faf68468cc2b1b0f01a09083210a6cb7dd2da6 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -217,6 +217,8 @@ UINT16 nightslinktics = 2*TICRATE;
 
 INT32 gameovertics = 15*TICRATE;
 
+UINT8 ammoremovaltics = 2*TICRATE;
+
 UINT8 use1upSound = 0;
 UINT8 maxXtraLife = 2; // Max extra lives from rings
 
@@ -3285,9 +3287,11 @@ void G_LoadGameSettings(void)
 {
 	// defaults
 	spstage_start = 1;
-	sstage_start = smpstage_start = 50;
-	sstage_end = smpstage_end = 56; // 7 special stages in vanilla SRB2
+	sstage_start = 50;
+	sstage_end = 56; // 7 special stages in vanilla SRB2
 	sstage_end++; // plus one weirdo
+	smpstage_start = 60;
+	smpstage_end = 66; // 7 multiplayer special stages too
 
 	// initialize free sfx slots for skin sounds
 	S_InitRuntimeSounds();
diff --git a/src/g_game.h b/src/g_game.h
index 4b63bc180afcb0908e5ffeefddb907cb07d098a7..e161bc8ed4a7cf11eefe93bbf6715825426b582c 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -51,6 +51,7 @@ extern tic_t levelstarttic;
 // for modding?
 extern INT16 prevmap, nextmap;
 extern INT32 gameovertics;
+extern UINT8 ammoremovaltics;
 extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
 extern INT16 rw_maximums[NUM_WEAPONS];
 extern INT32 pausedelay;
diff --git a/src/info.c b/src/info.c
index 9aed563c7a4316ae707c4ddbb82194372977f6f8..18f0e838abca1dead9f6f37a7196d2e332f95335 100644
--- a/src/info.c
+++ b/src/info.c
@@ -1043,8 +1043,8 @@ state_t states[NUMSTATES] =
 	{SPR_CBFS, 7,  1, {A_FaceStabHurl},                   6, S_FACESTABBER_CHARGE4, S_FACESTABBER_CHARGE3}, // S_FACESTABBER_CHARGE3
 	{SPR_CBFS, 7,  1, {A_FaceStabMiss}, 0,   S_FACESTABBER_STND1, S_FACESTABBER_CHARGE4}, // S_FACESTABBER_CHARGE4
 	{SPR_CBFS, 0, 35,         {A_Pain}, 0,                     0, S_FACESTABBER_STND1}, // S_FACESTABBER_PAIN
-	{SPR_CBFS, 0,  2,   {A_BossScream}, 1, MT_SONIC3KBOSSEXPLODE, S_FACESTABBER_DIE2},  // S_FACESTABBER_DIE1
-	{SPR_NULL, 0,  2,   {A_BossScream}, 1, MT_SONIC3KBOSSEXPLODE, S_FACESTABBER_DIE3},  // S_FACESTABBER_DIE2
+	{SPR_CBFS, 0,  2,   {A_BossScream}, 1, 0, S_FACESTABBER_DIE2},  // S_FACESTABBER_DIE1
+	{SPR_NULL, 0,  2,   {A_BossScream}, 1, 0, S_FACESTABBER_DIE3},  // S_FACESTABBER_DIE2
 	{SPR_NULL, 0,  0,       {A_Repeat}, 7, S_FACESTABBER_DIE1,    S_XPLD_FLICKY},       // S_FACESTABBER_DIE3
 
 	{SPR_STAB, FF_PAPERSPRITE|FF_TRANS50|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_FACESTABBERSPEAR
@@ -1205,33 +1205,20 @@ state_t states[NUMSTATES] =
 	{SPR_EGGM, 19,  10, {NULL},                    0, 0, S_EGGMOBILE_RATK10}, // S_EGGMOBILE_RATK9
 	{SPR_EGGM, 20,   2, {NULL},                    0, 0, S_EGGMOBILE_STND},   // S_EGGMOBILE_RATK10
 	{SPR_EGGM,  3,  12, {NULL},                    0, 0, S_EGGMOBILE_PANIC2}, // S_EGGMOBILE_PANIC1
-	{SPR_EGGM,  4,   4, {A_Boss1Spikeballs},       0, 4, S_EGGMOBILE_PANIC3}, // S_EGGMOBILE_PANIC2
+	{SPR_EGGM,  4,  45, {A_Boss1Laser},       MT_LASER, 2, S_EGGMOBILE_PANIC3}, // S_EGGMOBILE_PANIC2
 	{SPR_EGGM,  3,   8, {NULL},                    0, 0, S_EGGMOBILE_PANIC4}, // S_EGGMOBILE_PANIC3
-	{SPR_EGGM,  4,   4, {A_Boss1Spikeballs},       1, 4, S_EGGMOBILE_PANIC5}, // S_EGGMOBILE_PANIC4
-	{SPR_EGGM,  3,   8, {NULL},                    0, 0, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5
-	{SPR_EGGM,  4,   4, {A_Boss1Spikeballs},       2, 4, S_EGGMOBILE_PANIC7}, // S_EGGMOBILE_PANIC6
-	{SPR_EGGM,  3,   8, {NULL},                    0, 0, S_EGGMOBILE_PANIC8}, // S_EGGMOBILE_PANIC7
-	{SPR_EGGM,  4,   4, {A_Boss1Spikeballs},       3, 4, S_EGGMOBILE_PANIC9}, // S_EGGMOBILE_PANIC8
-	{SPR_EGGM,  3,   8, {NULL},                    0, 0, S_EGGMOBILE_PANIC10},// S_EGGMOBILE_PANIC9
-	{SPR_EGGM,  0,  35, {A_SkullAttack},           0, 0, S_EGGMOBILE_STND},   // S_EGGMOBILE_PANIC10
+	{SPR_EGGM,  4,  45, {A_Boss1Laser},       MT_LASER, 2, S_EGGMOBILE_PANIC5 }, // S_EGGMOBILE_PANIC4
+	{SPR_EGGM,  3,  8,  {NULL},                    0, 0, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5
+	{SPR_EGGM,  4,  45, {A_Boss1Laser},       MT_LASER, 2, S_EGGMOBILE_PANIC7 }, // S_EGGMOBILE_PANIC6
+	{SPR_EGGM,  0,  35,	{NULL},					0, 0, S_EGGMOBILE_STND },   // S_EGGMOBILE_PANIC7
 	{SPR_EGGM, 21,  24, {A_Pain},                  0, 0, S_EGGMOBILE_PAIN2},  // S_EGGMOBILE_PAIN
 	{SPR_EGGM, 21,  16, {A_SkullAttack},           1, 1, S_EGGMOBILE_STND},   // S_EGGMOBILE_PAIN2
-	{SPR_EGGM, 22,  8, {A_Fall},                   0, 0, S_EGGMOBILE_DIE2},   // S_EGGMOBILE_DIE1
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE3},   // S_EGGMOBILE_DIE2
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE4},   // S_EGGMOBILE_DIE3
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE5},   // S_EGGMOBILE_DIE4
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE6},   // S_EGGMOBILE_DIE5
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE7},   // S_EGGMOBILE_DIE6
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE8},   // S_EGGMOBILE_DIE7
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE9},   // S_EGGMOBILE_DIE8
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE10},  // S_EGGMOBILE_DIE9
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE11},  // S_EGGMOBILE_DIE10
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE12},  // S_EGGMOBILE_DIE11
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE13},  // S_EGGMOBILE_DIE12
-	{SPR_EGGM, 22,  8, {A_BossScream},             0, 0, S_EGGMOBILE_DIE14},  // S_EGGMOBILE_DIE13
-	{SPR_EGGM, 22,  -1, {A_BossDeath},             0, 0, S_NULL},             // S_EGGMOBILE_DIE14
-	{SPR_EGGM, 23,  5, {NULL},                     0, 0, S_EGGMOBILE_FLEE2},  // S_EGGMOBILE_FLEE1
-	{SPR_EGGM, 24,  5, {NULL},                     0, 0, S_EGGMOBILE_FLEE1},  // S_EGGMOBILE_FLEE2
+	{SPR_EGGM, 22,  2, {A_Fall},                   0, 0, S_EGGMOBILE_DIE2},   // S_EGGMOBILE_DIE1
+	{SPR_EGGM, 22,  2, {A_BossScream},             0, 0, S_EGGMOBILE_DIE3},   // S_EGGMOBILE_DIE2
+	{SPR_EGGM, 22,  0, {A_Repeat}, 17, S_EGGMOBILE_DIE2, S_EGGMOBILE_DIE4},   // S_EGGMOBILE_DIE3
+	{SPR_EGGM, 22,  -1, {A_BossDeath},             0, 0, S_NULL},             // S_EGGMOBILE_DIE4
+	{SPR_EGGM, 23,  2, {A_BossScream},             0, 0, S_EGGMOBILE_FLEE2},  // S_EGGMOBILE_FLEE1
+	{SPR_EGGM, 24,  2, {A_BossScream},             0, 0, S_EGGMOBILE_FLEE1},  // S_EGGMOBILE_FLEE2
 	{SPR_UNID,  1,  1, {A_UnidusBall},             2, 0, S_EGGMOBILE_BALL},   // S_EGGMOBILE_BALL
 	{SPR_NULL,  0,  1, {A_FocusTarget},            0, 0, S_EGGMOBILE_TARGET}, // S_EGGMOBILE_TARGET
 
@@ -1246,22 +1233,12 @@ state_t states[NUMSTATES] =
 	{SPR_EGGN, 1, 2,               {NULL},           0,          0, S_EGGMOBILE2_POGO4}, // S_EGGMOBILE2_POGO7
 	{SPR_EGGN, 3, 24, {A_Boss2TakeDamage},  24+TICRATE,          0, S_EGGMOBILE2_STND},  // S_EGGMOBILE2_PAIN
 	{SPR_EGGN, 4, 24, {A_Boss2TakeDamage},  24+TICRATE,          0, S_EGGMOBILE2_POGO4}, // S_EGGMOBILE2_PAIN2
-	{SPR_EGGN, 5, 8,             {A_Fall},           0,          0, S_EGGMOBILE2_DIE2},  // S_EGGMOBILE2_DIE1
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE3},  // S_EGGMOBILE2_DIE2
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE4},  // S_EGGMOBILE2_DIE3
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE5},  // S_EGGMOBILE2_DIE4
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE6},  // S_EGGMOBILE2_DIE5
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE7},  // S_EGGMOBILE2_DIE6
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE8},  // S_EGGMOBILE2_DIE7
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE9},  // S_EGGMOBILE2_DIE8
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE10}, // S_EGGMOBILE2_DIE9
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE11}, // S_EGGMOBILE2_DIE10
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE12}, // S_EGGMOBILE2_DIE11
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE13}, // S_EGGMOBILE2_DIE12
-	{SPR_EGGN, 5, 8,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE14}, // S_EGGMOBILE2_DIE13
-	{SPR_EGGN, 5, -1,       {A_BossDeath},           0,          0, S_NULL},             // S_EGGMOBILE2_DIE14
-	{SPR_EGGN, 6, 5,               {NULL},           0,          0, S_EGGMOBILE2_FLEE2}, // S_EGGMOBILE2_FLEE1
-	{SPR_EGGN, 7, 5,               {NULL},           0,          0, S_EGGMOBILE2_FLEE1}, // S_EGGMOBILE2_FLEE2
+	{SPR_EGGN, 5, 2,             {A_Fall},           0,          0, S_EGGMOBILE2_DIE2},  // S_EGGMOBILE2_DIE1
+	{SPR_EGGN, 5, 2,       {A_BossScream},           0,          0, S_EGGMOBILE2_DIE3},  // S_EGGMOBILE2_DIE2
+	{SPR_EGGN, 5, 0,       {A_Repeat}, 17, S_EGGMOBILE2_DIE2, S_EGGMOBILE2_DIE4},  // S_EGGMOBILE2_DIE3
+	{SPR_EGGN, 5, -1,       {A_BossDeath},           0,          0, S_NULL},             // S_EGGMOBILE2_DIE4
+	{SPR_EGGN, 6, 2,       {A_BossScream},           0,          0, S_EGGMOBILE2_FLEE2}, // S_EGGMOBILE2_FLEE1
+	{SPR_EGGN, 7, 2,       {A_BossScream},           0,          0, S_EGGMOBILE2_FLEE1}, // S_EGGMOBILE2_FLEE2
 
 	{SPR_TNKA, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK1
 	{SPR_TNKB, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK2
@@ -1305,22 +1282,12 @@ state_t states[NUMSTATES] =
 	{SPR_EGGO,  7,   4, {NULL},                    0, 0, S_EGGMOBILE3_STND},    // S_EGGMOBILE3_LAUGH20
 	{SPR_EGGO,  8,   1, {A_Boss3TakeDamage},       0, 0, S_EGGMOBILE3_PAIN2},   // S_EGGMOBILE3_PAIN
 	{SPR_EGGO,  8,  23, {A_Pain},                  0, 0, S_EGGMOBILE3_STND},    // S_EGGMOBILE3_PAIN2
-	{SPR_EGGO,  9,   8, {A_Fall},                  0, 0, S_EGGMOBILE3_DIE2},    // S_EGGMOBILE3_DIE1
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE3},    // S_EGGMOBILE3_DIE2
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE4},    // S_EGGMOBILE3_DIE3
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE5},    // S_EGGMOBILE3_DIE4
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE6},    // S_EGGMOBILE3_DIE5
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE7},    // S_EGGMOBILE3_DIE6
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE8},    // S_EGGMOBILE3_DIE7
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE9},    // S_EGGMOBILE3_DIE8
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE10},   // S_EGGMOBILE3_DIE9
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE11},   // S_EGGMOBILE3_DIE10
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE12},   // S_EGGMOBILE3_DIE11
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE13},   // S_EGGMOBILE3_DIE12
-	{SPR_EGGO,  9,   8, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE14},   // S_EGGMOBILE3_DIE13
-	{SPR_EGGO,  9,  -1, {A_BossDeath},             0, 0, S_NULL},               // S_EGGMOBILE3_DIE14
-	{SPR_EGGO, 10,   5, {NULL},                    0, 0, S_EGGMOBILE3_FLEE2},   // S_EGGMOBILE3_FLEE1
-	{SPR_EGGO, 11,   5, {NULL},                    0, 0, S_EGGMOBILE3_FLEE1},   // S_EGGMOBILE3_FLEE2
+	{SPR_EGGO,  9,   2, {A_Fall},                  0, 0, S_EGGMOBILE3_DIE2},    // S_EGGMOBILE3_DIE1
+	{SPR_EGGO,  9,   2, {A_BossScream},            0, 0, S_EGGMOBILE3_DIE3},    // S_EGGMOBILE3_DIE2
+	{SPR_EGGO,  9,   0, {A_Repeat}, 17, S_EGGMOBILE3_DIE2, S_EGGMOBILE3_DIE4},  // S_EGGMOBILE3_DIE3
+	{SPR_EGGO,  9,  -1, {A_BossDeath},             0, 0, S_NULL},               // S_EGGMOBILE3_DIE4
+	{SPR_EGGO, 10,   2, {A_BossScream},            0, 0, S_EGGMOBILE3_FLEE2},   // S_EGGMOBILE3_FLEE1
+	{SPR_EGGO, 11,   2, {A_BossScream},            0, 0, S_EGGMOBILE3_FLEE1},   // S_EGGMOBILE3_FLEE2
 
 	// Boss 3 Propeller
 	{SPR_PRPL, 0, 1, {NULL}, 0, 0, S_PROPELLER2}, // S_PROPELLER1
@@ -1361,26 +1328,16 @@ state_t states[NUMSTATES] =
 	{SPR_EGGP,13|FF_ANIMATE, -1, {NULL},        1,        10, S_NULL},             // S_EGGMOBILE4_RAISE2
 	{SPR_EGGP,11,  0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2}, // S_EGGMOBILE4_PAIN1
 	{SPR_EGGP,11, 24, {A_Pain},                 0,         0, S_EGGMOBILE4_STND},  // S_EGGMOBILE4_PAIN2
-	{SPR_EGGP,12,  8, {A_Fall},         0,          0, S_EGGMOBILE4_DIE2},   // S_EGGMOBILE4_DIE1
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE3},   // S_EGGMOBILE4_DIE2
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE4},   // S_EGGMOBILE4_DIE3
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE5},   // S_EGGMOBILE4_DIE4
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE6},   // S_EGGMOBILE4_DIE5
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE7},   // S_EGGMOBILE4_DIE6
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE8},   // S_EGGMOBILE4_DIE7
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE9},   // S_EGGMOBILE4_DIE8
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE10},  // S_EGGMOBILE4_DIE9
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE11},  // S_EGGMOBILE4_DIE10
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE12},  // S_EGGMOBILE4_DIE11
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE13},  // S_EGGMOBILE4_DIE12
-	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE14},  // S_EGGMOBILE4_DIE13
-	{SPR_EGGP,12, -1, {A_BossDeath},    0,          0, S_NULL},              // S_EGGMOBILE4_DIE14
-	{SPR_EGGP,13,  5, {NULL},           0,          0, S_EGGMOBILE4_FLEE2},  // S_EGGMOBILE4_FLEE1
-	{SPR_EGGP,14,  5, {NULL},           0,          0, S_EGGMOBILE4_FLEE1},  // S_EGGMOBILE4_FLEE2
+	{SPR_EGGP,12,  2, {A_Fall},         0,          0, S_EGGMOBILE4_DIE2},   // S_EGGMOBILE4_DIE1
+	{SPR_EGGP,12,  2, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE3},   // S_EGGMOBILE4_DIE2
+	{SPR_EGGP,12,  0, {A_Repeat},   17, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE4},   // S_EGGMOBILE4_DIE3
+	{SPR_EGGP,12, -1, {A_BossDeath},    0,          0, S_NULL},              // S_EGGMOBILE4_DIE4
+	{SPR_EGGP,13,  2, {A_BossScream},   0,          0, S_EGGMOBILE4_FLEE2},  // S_EGGMOBILE4_FLEE1
+	{SPR_EGGP,14,  2, {A_BossScream},   0,          0, S_EGGMOBILE4_FLEE1},  // S_EGGMOBILE4_FLEE2
 	{SPR_BMCE, 0, -1, {NULL},           0,          0, S_NULL},              // S_EGGMOBILE4_MACE
-	{SPR_BMCE, 0,  2, {A_BossScream},   1, MT_SONIC3KBOSSEXPLODE, S_EGGMOBILE4_MACE_DIE2},  // S_EGGMOBILE4_MACE_DIE1
-	{SPR_NULL, 0,  2, {A_BossScream},   1, MT_SONIC3KBOSSEXPLODE, S_EGGMOBILE4_MACE_DIE3},  // S_EGGMOBILE4_MACE_DIE2
-	{SPR_NULL, 0,  0, {A_Repeat},       7, S_EGGMOBILE4_MACE_DIE1,    S_BOSSEXPLODE},       // S_EGGMOBILE4_MACE_DIE3
+	{SPR_BMCE, 0,  2, {A_BossScream},   1, 0, S_EGGMOBILE4_MACE_DIE2},  // S_EGGMOBILE4_MACE_DIE1
+	{SPR_NULL, 0,  2, {A_BossScream},   1, 0, S_EGGMOBILE4_MACE_DIE3},  // S_EGGMOBILE4_MACE_DIE2
+	{SPR_NULL, 0,  0, {A_Repeat},       7, S_EGGMOBILE4_MACE_DIE1, S_SONIC3KBOSSEXPLOSION1}, // S_EGGMOBILE4_MACE_DIE3
 
 	// Boss 4 jet flame
 	{SPR_EFIR, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_JETFLAME
@@ -1430,7 +1387,7 @@ state_t states[NUMSTATES] =
 	{SPR_FANG,  4,  1, {A_DoNPCSkid}, S_FANG_SKID3, 0, S_FANG_SKID2}, // S_FANG_SKID2
 	{SPR_FANG,  4, 10, {NULL}, 0, 0, S_FANG_CHOOSEATTACK}, // S_FANG_SKID3
 
-	{SPR_FANG,  0, 0, {A_RandomState}, S_FANG_LOBSHOT1, S_FANG_FIRESTART1, S_NULL}, // S_FANG_CHOOSEATTACK
+	{SPR_FANG,  0, 0, {A_RandomState}, S_FANG_LOBSHOT0, S_FANG_FIRESTART1, S_NULL}, // S_FANG_CHOOSEATTACK
 
 	{SPR_FANG,  5,  0, {A_PrepareRepeat}, 3, 0, S_FANG_FIRESTART2}, // S_FANG_FIRESTART1 // Reset loop
 	{SPR_FANG,  5, 18, {A_LookForBetter}, 1, 0, S_FANG_FIRE1}, // S_FANG_FIRESTART2
@@ -1440,7 +1397,8 @@ state_t states[NUMSTATES] =
 	{SPR_FANG,  5,  5, {NULL}, 2, 0, S_FANG_FIREREPEAT}, // S_FANG_FIRE4
 	{SPR_FANG,  5,  0, {A_Repeat}, 3, S_FANG_FIRE1, S_FANG_WAIT1}, // S_FANG_FIREREPEAT // End of loop
 
-	{SPR_FANG, 19, 18, {A_LookForBetter}, 1, 0, S_FANG_LOBSHOT2}, // S_FANG_LOBSHOT1
+	{SPR_FANG, 18, 16, {A_LookForBetter}, 1, 0, S_FANG_LOBSHOT1}, // S_FANG_LOBSHOT0
+	{SPR_FANG, 19,  2, {A_LookForBetter}, 1, 0, S_FANG_LOBSHOT2}, // S_FANG_LOBSHOT1
 	{SPR_FANG, 20, 18, {A_BrakLobShot}, MT_FBOMB, 32+(1<<16), S_FANG_WAIT1}, // S_FANG_LOBSHOT2
 
 	{SPR_FANG, FF_ANIMATE|15, 70, {NULL}, 1, 5, S_FANG_WAIT2}, // S_FANG_WAIT1
@@ -1458,17 +1416,18 @@ state_t states[NUMSTATES] =
 	{SPR_FANG, 12,  1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL2}, // S_FANG_PINCHFALL1
 	{SPR_FANG, 13,  1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL2
 	{SPR_FANG,  4,  0, {A_PlayAttackSound}, 0, 0, S_FANG_PINCHSKID2}, // S_FANG_PINCHSKID1
-	{SPR_FANG,  4,  1, {A_DoNPCSkid}, S_FANG_PINCHLOBSHOT1, 0, S_FANG_PINCHSKID2}, // S_FANG_PINCHSKID2
-	{SPR_FANG, 19, 18, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT2}, // S_FANG_PINCHLOBSHOT1
+	{SPR_FANG,  4,  1, {A_DoNPCSkid}, S_FANG_PINCHLOBSHOT0, 0, S_FANG_PINCHSKID2}, // S_FANG_PINCHSKID2
+	{SPR_FANG, 18, 16, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT1}, // S_FANG_PINCHLOBSHOT0
+	{SPR_FANG, 19,  2, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT2}, // S_FANG_PINCHLOBSHOT1
 	{SPR_FANG, 20, 30, {A_Boss5MakeItRain}, MT_FBOMB, -16, S_FANG_PINCHLOBSHOT3}, // S_FANG_PINCHLOBSHOT2
-	{SPR_FANG, 19, 18, {A_LinedefExecute}, LE_BOSS4DROP, 0, S_FANG_PINCHLOBSHOT4}, // S_FANG_PINCHLOBSHOT3
-	{SPR_FANG, 19,  0, {A_Boss5Calm}, 0, 0, S_FANG_PATHINGSTART1}, // S_FANG_PINCHLOBSHOT4
+	{SPR_FANG, 20, 18, {A_LinedefExecute}, LE_BOSS4DROP, 0, S_FANG_PINCHLOBSHOT4}, // S_FANG_PINCHLOBSHOT3
+	{SPR_FANG,  0,  0, {A_Boss5Calm}, 0, 0, S_FANG_PATHINGSTART1}, // S_FANG_PINCHLOBSHOT4
 
-	{SPR_FANG, 14, 0, {A_DoNPCPain}, 0, 0, S_FANG_DIE2}, // S_FANG_DIE1
-	{SPR_FANG, 14, 1, {A_Boss5CheckOnGround}, S_FANG_DIE3, 0, S_FANG_DIE2}, // S_FANG_DIE2
+	{SPR_FANG, 21, 0, {A_DoNPCPain},                    0, 0, S_FANG_DIE2}, // S_FANG_DIE1
+	{SPR_FANG, 21, 1, {A_Boss5CheckOnGround}, S_FANG_DIE3, 0, S_FANG_DIE2}, // S_FANG_DIE2
 
-	{SPR_FANG, 17,   0, {A_Scream}, 0, 0, S_FANG_DIE4}, // S_FANG_DIE3
-	{SPR_FANG, 17, 104, {NULL}, 0, 0, S_FANG_DIE5}, // S_FANG_DIE4
+	{SPR_FANG, 22,   0, {A_Scream}, 0, 0, S_FANG_DIE4}, // S_FANG_DIE3
+	{SPR_FANG, 22, 104, {NULL},     0, 0, S_FANG_DIE5}, // S_FANG_DIE4
 
 	{SPR_FANG, 11, 0, {A_PlaySound}, sfx_jump, 0, S_FANG_DIE6}, // S_FANG_DIE5
 	{SPR_FANG, 11, 1, {A_ZThrust}, 6, (1<<16)|1, S_FANG_DIE7}, // S_FANG_DIE6
@@ -1480,7 +1439,7 @@ state_t states[NUMSTATES] =
 	{SPR_FANG,  9,  2, {NULL}, 0, 0, S_FANG_FLEEBOUNCE2}, // S_FANG_FLEEBOUNCE1
 	{SPR_FANG, 10, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_FANG_FLEEBOUNCE2
 
-	{SPR_FANG, 18, 7*TICRATE, {NULL}, 0, 0, S_NULL}, // S_FANG_KO
+	{SPR_FANG, 17, 7*TICRATE, {NULL}, 0, 0, S_NULL}, // S_FANG_KO
 
 	{SPR_FBOM, 0, 1, {A_GhostMe}, 0, 0, S_FBOMB2}, // S_FBOMB1
 	{SPR_FBOM, 1, 1, {A_GhostMe}, 0, 0, S_FBOMB1}, // S_FBOMB2
@@ -1621,7 +1580,7 @@ state_t states[NUMSTATES] =
 	{SPR_BRAK, 18, 0, {A_CheckHealth}, 3, S_CYBRAKDEMON_PAIN3, S_CYBRAKDEMON_CHOOSE_ATTACK1}, // S_CYBRAKDEMON_PAIN2
 	{SPR_BRAK, 18, 0, {A_LinedefExecute}, LE_PINCHPHASE, 0, S_CYBRAKDEMON_CHOOSE_ATTACK1}, // S_CYBRAKDEMON_PAIN3
 	{SPR_BRAK, 18, 1, {A_Repeat}, 1, S_CYBRAKDEMON_DIE1, S_CYBRAKDEMON_DIE2}, // S_CYBRAKDEMON_DIE1
-	{SPR_BRAK, 18, 2, {A_BossScream}, 0, MT_SONIC3KBOSSEXPLODE, S_CYBRAKDEMON_DIE3}, // S_CYBRAKDEMON_DIE2
+	{SPR_BRAK, 18, 2, {A_BossScream}, 0, 0, S_CYBRAKDEMON_DIE3}, // S_CYBRAKDEMON_DIE2
 	{SPR_BRAK, 18, 0, {A_Repeat}, 52, S_CYBRAKDEMON_DIE2, S_CYBRAKDEMON_DIE4}, // S_CYBRAKDEMON_DIE3
 	{SPR_BRAK, 13, 14, {A_PlaySound}, sfx_bedie2, 0, S_CYBRAKDEMON_DIE5}, // S_CYBRAKDEMON_DIE4
 	{SPR_BRAK, 14, 7, {NULL}, 0, 0, S_CYBRAKDEMON_DIE6}, // S_CYBRAKDEMON_DIE5
@@ -1737,7 +1696,7 @@ state_t states[NUMSTATES] =
 
 	{SPR_NULL, 0, 1, {A_SetFuse}, TICRATE, 0, S_CYBRAKDEMONVILEEXPLOSION2}, //S_CYBRAKDEMONVILEEXPLOSION1,
 	{SPR_NULL, 0, 0, {A_ScoreRise}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION3}, //S_CYBRAKDEMONVILEEXPLOSION2,
-	{SPR_NULL, 0, 1, {A_BossScream}, 0, MT_SONIC3KBOSSEXPLODE, S_CYBRAKDEMONVILEEXPLOSION1}, //S_CYBRAKDEMONVILEEXPLOSION3,
+	{SPR_NULL, 0, 1, {A_BossScream}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION1}, //S_CYBRAKDEMONVILEEXPLOSION3,
 
 	// Metal Sonic
 	{SPR_METL,  0, 35, {NULL}, 0, 0, S_METALSONIC_WAIT1}, // S_METALSONIC_STAND
@@ -1766,14 +1725,12 @@ state_t states[NUMSTATES] =
 	{SPR_METL, 16, -1, {NULL},         0, 0, S_NULL},             // S_METALSONIC_BADBOUNCE
 	{SPR_METL, 13, -1, {NULL},         0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT
 	{SPR_METL, 11, 40, {A_Pain},       0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN
-	{SPR_METL, 13,  8, {A_Fall},       0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1
-	{SPR_METL, 13,  8, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2
-	{SPR_METL, 13, 0, {A_Repeat}, 11, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3
+	{SPR_METL, 13,  2, {A_Fall},       0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1
+	{SPR_METL, 13,  4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2
+	{SPR_METL, 13,  0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3
 	{SPR_METL, 13, -1, {A_BossDeath},  0, 0, S_NULL},             // S_METALSONIC_DEATH4
-	{SPR_METL, 11,  4, {NULL},         0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
-	{SPR_METL, 11,  4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2
-	{SPR_METL, 11,  4, {NULL},         0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3
-	{SPR_METL, 11,  4, {NULL},         0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4
+	{SPR_METL, 11,  1, {A_BossScream},         0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
+	{SPR_METL, 11,  7, {NULL},                 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2
 
 	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2},  // S_MSSHIELD_F1
 	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3},  // S_MSSHIELD_F2
@@ -3736,8 +3693,8 @@ state_t states[NUMSTATES] =
 	{SPR_HIVE, 2,  2, {NULL}, 0, 0, S_HIVEELEMENTAL_DORMANT}, // S_HIVEELEMENTAL_SHOOT2
 	{SPR_HIVE, 0,  5, {A_ParentTriesToSleep}, S_HIVEELEMENTAL_PREPARE1, 0, S_HIVEELEMENTAL_DORMANT}, // S_HIVEELEMENTAL_DORMANT
 	{SPR_HIVE, 3, 35, {A_Pain}, 0, 0, S_HIVEELEMENTAL_LOOK}, // S_HIVEELEMENTAL_PAIN
-	{SPR_HIVE, 3,  2, {A_BossScream}, 1, MT_SONIC3KBOSSEXPLODE, S_HIVEELEMENTAL_DIE2}, // S_HIVEELEMENTAL_DIE1
-	{SPR_NULL, 0,  2, {A_BossScream}, 1, MT_SONIC3KBOSSEXPLODE, S_HIVEELEMENTAL_DIE3}, // S_HIVEELEMENTAL_DIE2
+	{SPR_HIVE, 3,  2, {A_BossScream}, 1, 0, S_HIVEELEMENTAL_DIE2}, // S_HIVEELEMENTAL_DIE1
+	{SPR_NULL, 0,  2, {A_BossScream}, 1, 0, S_HIVEELEMENTAL_DIE3}, // S_HIVEELEMENTAL_DIE2
 	{SPR_NULL, 0,  0, {A_Repeat}, 7, S_HIVEELEMENTAL_DIE1, S_XPLD_FLICKY}, // S_HIVEELEMENTAL_DIE3
 
 	{SPR_BUMB, 1, 10, {NULL}, 0, 0, S_BUMBLEBORE_LOOK1}, // S_BUMBLEBORE_SPAWN
@@ -4635,7 +4592,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_FACESTABBER_CHARGE1, // missilestate
 		S_FACESTABBER_DIE1, // deathstate
 		S_NULL,         // xdeathstate
-		sfx_cybdth,     // deathsound
+		sfx_s3kb4,      // deathsound
 		3,              // speed
 		32*FRACUNIT,    // radius
 		72*FRACUNIT,    // height
@@ -5202,7 +5159,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_EGGMOBILE_RATK1, // missilestate
 		S_EGGMOBILE_DIE1,  // deathstate
 		S_EGGMOBILE_FLEE1, // xdeathstate
-		sfx_cybdth,        // deathsound
+		sfx_s3kb4,         // deathsound
 		4,                 // speed
 		24*FRACUNIT,       // radius
 		76*FRACUNIT,       // height
@@ -5337,7 +5294,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		(statenum_t)MT_EGGMOBILE2_POGO, // missilestate
 		S_EGGMOBILE2_DIE1, // deathstate
 		S_EGGMOBILE2_FLEE1,// xdeathstate
-		sfx_cybdth,        // deathsound
+		sfx_s3kb4,         // deathsound
 		2*FRACUNIT,        // speed
 		24*FRACUNIT,       // radius
 		76*FRACUNIT,       // height
@@ -5399,7 +5356,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		100,            // mass
 		1,              // damage
 		sfx_None,       // activesound
-		MF_NOBLOCKMAP,  // flags
+		MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags
 		S_NULL          // raisestate
 	},
 
@@ -5426,7 +5383,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		100,            // mass
 		1,              // damage
 		sfx_None,       // activesound
-		MF_NOBLOCKMAP,  // flags
+		MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags
 		S_NULL          // raisestate
 	},
 
@@ -5453,7 +5410,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		100,            // mass
 		1,              // damage
 		sfx_None,       // activesound
-		MF_NOBLOCKMAP,  // flags
+		MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags
 		S_NULL          // raisestate
 	},
 
@@ -5526,7 +5483,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_EGGMOBILE3_LAUGH1,// missilestate
 		S_EGGMOBILE3_DIE1,  // deathstate
 		S_EGGMOBILE3_FLEE1, // xdeathstate
-		sfx_cybdth,         // deathsound
+		sfx_s3kb4,          // deathsound
 		8*FRACUNIT,         // speed
 		32*FRACUNIT,        // radius
 		116*FRACUNIT,       // height
@@ -5634,7 +5591,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_EGGMOBILE4_RATK1,// missilestate
 		S_EGGMOBILE4_DIE1, // deathstate
 		S_EGGMOBILE4_FLEE1,// xdeathstate
-		sfx_cybdth,        // deathsound
+		sfx_s3kb4,         // deathsound
 		0,                 // speed
 		24*FRACUNIT,       // radius
 		76*FRACUNIT,       // height
@@ -6363,7 +6320,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_METALSONIC_SHOOT, // missilestate
 		S_METALSONIC_DEATH1,// deathstate
 		S_METALSONIC_FLEE1, // xdeathstate
-		sfx_s3k6e,          // deathsound
+		sfx_s3kb4,          // deathsound
 		MT_ENERGYBALL,      // speed
 		16*FRACUNIT,        // radius
 		48*FRACUNIT,        // height
@@ -6550,7 +6507,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_BOSSEXPLODE,  // deathstate
+		S_SONIC3KBOSSEXPLOSION1, // deathstate
 		S_NULL,         // xdeathstate
 		sfx_cybdth,     // deathsound
 		38*FRACUNIT,    // speed
@@ -18979,7 +18936,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // missilestate
 		S_HIVEELEMENTAL_DIE1, // deathstate
 		S_NULL,         // xdeathstate
-		sfx_cybdth,     // deathsound
+		sfx_s3kb4,      // deathsound
 		6*FRACUNIT,     // speed
 		30*FRACUNIT,    // radius
 		80*FRACUNIT,    // height
diff --git a/src/info.h b/src/info.h
index bb27ac3e3b299681495fbd4f8bfad07324be61e9..593c1fb7cdd60c372162e3de51e1fad444367c3b 100644
--- a/src/info.h
+++ b/src/info.h
@@ -1364,25 +1364,12 @@ typedef enum state
 	S_EGGMOBILE_PANIC5,
 	S_EGGMOBILE_PANIC6,
 	S_EGGMOBILE_PANIC7,
-	S_EGGMOBILE_PANIC8,
-	S_EGGMOBILE_PANIC9,
-	S_EGGMOBILE_PANIC10,
 	S_EGGMOBILE_PAIN,
 	S_EGGMOBILE_PAIN2,
 	S_EGGMOBILE_DIE1,
 	S_EGGMOBILE_DIE2,
 	S_EGGMOBILE_DIE3,
 	S_EGGMOBILE_DIE4,
-	S_EGGMOBILE_DIE5,
-	S_EGGMOBILE_DIE6,
-	S_EGGMOBILE_DIE7,
-	S_EGGMOBILE_DIE8,
-	S_EGGMOBILE_DIE9,
-	S_EGGMOBILE_DIE10,
-	S_EGGMOBILE_DIE11,
-	S_EGGMOBILE_DIE12,
-	S_EGGMOBILE_DIE13,
-	S_EGGMOBILE_DIE14,
 	S_EGGMOBILE_FLEE1,
 	S_EGGMOBILE_FLEE2,
 	S_EGGMOBILE_BALL,
@@ -1403,16 +1390,6 @@ typedef enum state
 	S_EGGMOBILE2_DIE2,
 	S_EGGMOBILE2_DIE3,
 	S_EGGMOBILE2_DIE4,
-	S_EGGMOBILE2_DIE5,
-	S_EGGMOBILE2_DIE6,
-	S_EGGMOBILE2_DIE7,
-	S_EGGMOBILE2_DIE8,
-	S_EGGMOBILE2_DIE9,
-	S_EGGMOBILE2_DIE10,
-	S_EGGMOBILE2_DIE11,
-	S_EGGMOBILE2_DIE12,
-	S_EGGMOBILE2_DIE13,
-	S_EGGMOBILE2_DIE14,
 	S_EGGMOBILE2_FLEE1,
 	S_EGGMOBILE2_FLEE2,
 
@@ -1462,16 +1439,6 @@ typedef enum state
 	S_EGGMOBILE3_DIE2,
 	S_EGGMOBILE3_DIE3,
 	S_EGGMOBILE3_DIE4,
-	S_EGGMOBILE3_DIE5,
-	S_EGGMOBILE3_DIE6,
-	S_EGGMOBILE3_DIE7,
-	S_EGGMOBILE3_DIE8,
-	S_EGGMOBILE3_DIE9,
-	S_EGGMOBILE3_DIE10,
-	S_EGGMOBILE3_DIE11,
-	S_EGGMOBILE3_DIE12,
-	S_EGGMOBILE3_DIE13,
-	S_EGGMOBILE3_DIE14,
 	S_EGGMOBILE3_FLEE1,
 	S_EGGMOBILE3_FLEE2,
 
@@ -1518,16 +1485,6 @@ typedef enum state
 	S_EGGMOBILE4_DIE2,
 	S_EGGMOBILE4_DIE3,
 	S_EGGMOBILE4_DIE4,
-	S_EGGMOBILE4_DIE5,
-	S_EGGMOBILE4_DIE6,
-	S_EGGMOBILE4_DIE7,
-	S_EGGMOBILE4_DIE8,
-	S_EGGMOBILE4_DIE9,
-	S_EGGMOBILE4_DIE10,
-	S_EGGMOBILE4_DIE11,
-	S_EGGMOBILE4_DIE12,
-	S_EGGMOBILE4_DIE13,
-	S_EGGMOBILE4_DIE14,
 	S_EGGMOBILE4_FLEE1,
 	S_EGGMOBILE4_FLEE2,
 	S_EGGMOBILE4_MACE,
@@ -1583,6 +1540,7 @@ typedef enum state
 	S_FANG_FIRE3,
 	S_FANG_FIRE4,
 	S_FANG_FIREREPEAT,
+	S_FANG_LOBSHOT0,
 	S_FANG_LOBSHOT1,
 	S_FANG_LOBSHOT2,
 	S_FANG_WAIT1,
@@ -1599,6 +1557,7 @@ typedef enum state
 	S_FANG_PINCHFALL2,
 	S_FANG_PINCHSKID1,
 	S_FANG_PINCHSKID2,
+	S_FANG_PINCHLOBSHOT0,
 	S_FANG_PINCHLOBSHOT1,
 	S_FANG_PINCHLOBSHOT2,
 	S_FANG_PINCHLOBSHOT3,
@@ -1904,8 +1863,6 @@ typedef enum state
 	S_METALSONIC_DEATH4,
 	S_METALSONIC_FLEE1,
 	S_METALSONIC_FLEE2,
-	S_METALSONIC_FLEE3,
-	S_METALSONIC_FLEE4,
 
 	S_MSSHIELD_F1,
 	S_MSSHIELD_F2,
diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c
index c6856b426224b17f29f7fd26b122865ad0d51b51..9e74dac76ce05b746e88e3bb7081b5219d7dfc35 100644
--- a/src/lua_consolelib.c
+++ b/src/lua_consolelib.c
@@ -308,6 +308,8 @@ static int lib_cvRegisterVar(lua_State *L)
 #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("CV_RegisterVar") " (%s)", e);
 #define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1)))
 
+	memset(cvar, 0x00, sizeof(consvar_t)); // zero everything by default
+
 	lua_pushnil(L);
 	while (lua_next(L, 1)) {
 		// stack: cvar table, cvar userdata, key/index, value
@@ -395,6 +397,13 @@ static int lib_cvRegisterVar(lua_State *L)
 #undef FIELDERROR
 #undef TYPEERROR
 
+	if (!cvar->name)
+		return luaL_error(L, M_GetText("Variable has no name!\n"));
+	if ((cvar->flags & CV_NOINIT) && !(cvar->flags & CV_CALL))
+		return luaL_error(L, M_GetText("Variable %s has CV_NOINIT without CV_CALL\n"), cvar->name);
+	if ((cvar->flags & CV_CALL) && !cvar->func)
+		return luaL_error(L, M_GetText("Variable %s has CV_CALL without a function\n"), cvar->name);
+
 	// stack: cvar table, cvar userdata
 	lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars");
 	I_Assert(lua_istable(L, 3));
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index b7bdaa1be87a078974490fe569e171c15906b319..addd707e16da8e86254cedb7393788091678744f 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -136,6 +136,12 @@ static int player_get(lua_State *L)
 		lua_pushinteger(L, plr->currentweapon);
 	else if (fastcmp(field,"ringweapons"))
 		lua_pushinteger(L, plr->ringweapons);
+	else if (fastcmp(field,"ammoremoval"))
+		lua_pushinteger(L, plr->ammoremoval);
+	else if (fastcmp(field,"ammoremovaltimer"))
+		lua_pushinteger(L, plr->ammoremovaltimer);
+	else if (fastcmp(field,"ammoremovalweapon"))
+		lua_pushinteger(L, plr->ammoremovalweapon);
 	else if (fastcmp(field,"powers"))
 		LUA_PushUserdata(L, plr->powers, META_POWERS);
 	else if (fastcmp(field,"pflags"))
@@ -428,6 +434,12 @@ static int player_set(lua_State *L)
 		plr->currentweapon = (INT32)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"ringweapons"))
 		plr->ringweapons = (INT32)luaL_checkinteger(L, 3);
+	else if (fastcmp(field,"ammoremoval"))
+		plr->ammoremoval = (UINT16)luaL_checkinteger(L, 3);
+	else if (fastcmp(field,"ammoremovaltimer"))
+		plr->ammoremovaltimer = (tic_t)luaL_checkinteger(L, 3);
+	else if (fastcmp(field,"ammoremovalweapon"))
+		plr->ammoremovalweapon = (INT32)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"powers"))
 		return NOSET;
 	else if (fastcmp(field,"pflags"))
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 7bc9c14b74c3192f46bb762c2e36c4f182b92db7..e3f169784d8e2f2bc255dc416cd4f5cd028bf14b 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -3002,6 +3002,8 @@ void A_Boss7FireMissiles(mobj_t *actor)
 // var2:
 //		0 - Boss 1 Left side
 //		1 - Boss 1 Right side
+//		2 - Triple laser
+//		>3 - Boss 1 Middle
 //
 void A_Boss1Laser(mobj_t *actor)
 {
@@ -3037,6 +3039,15 @@ void A_Boss1Laser(mobj_t *actor)
 			else
 				z = actor->z + FixedMul(56*FRACUNIT, actor->scale);
 			break;
+		case 2:
+			var2 = 3; // Fire middle laser
+			A_Boss1Laser(actor);
+			var2 = 0; // Fire left laser
+			A_Boss1Laser(actor);
+			var2 = 1; // Fire right laser
+			A_Boss1Laser(actor);
+			return;
+			break;
 		default:
 			x = actor->x;
 			y = actor->y;
@@ -3044,7 +3055,7 @@ void A_Boss1Laser(mobj_t *actor)
 			break;
 	}
 
-	if (!(actor->flags2 & MF2_FIRING))
+	if (!(actor->flags2 & MF2_FIRING) && actor->tics > 1)
 	{
 		actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);
 		if (mobjinfo[locvar1].seesound)
@@ -3066,6 +3077,7 @@ void A_Boss1Laser(mobj_t *actor)
 		angle = FixedAngle(FixedDiv(actor->tics*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT);
 	else
 		angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y));
+
 	point = P_SpawnMobj(x, y, z, locvar1);
 	P_SetTarget(&point->target, actor);
 	point->angle = actor->angle;
@@ -3337,7 +3349,7 @@ void A_BossZoom(mobj_t *actor)
 // var1:
 //		0 - Use movecount to spawn explosions evenly
 //		1 - Use P_Random to spawn explosions at complete random
-// var2 = Object to spawn. Default is MT_BOSSEXPLODE.
+// var2 = Object to spawn. Default is MT_SONIC3KBOSSEXPLODE.
 //
 void A_BossScream(mobj_t *actor)
 {
@@ -3369,7 +3381,7 @@ void A_BossScream(mobj_t *actor)
 
 	// Determine what mobj to spawn. If undefined or invalid, use MT_BOSSEXPLODE as default.
 	if (locvar2 <= 0 || locvar2 >= NUMMOBJTYPES)
-		explodetype = MT_BOSSEXPLODE;
+		explodetype = MT_SONIC3KBOSSEXPLODE; //MT_BOSSEXPLODE; -- piss to you, sonic 2
 	else
 		explodetype = (mobjtype_t)locvar2;
 
@@ -3936,14 +3948,24 @@ bossjustdie:
 			mo->flags |= MF_NOGRAVITY|MF_NOCLIP;
 			mo->flags |= MF_NOCLIPHEIGHT;
 
+			mo->movedir = 0;
+			mo->extravalue1 = 35;
+			mo->flags2 |= MF2_BOSSFLEE;
+			mo->momz = 2*mo->scale;
+
 			if (mo->target)
 			{
-				mo->angle = R_PointToAngle2(mo->x, mo->y, mo->target->x, mo->target->y);
-				mo->flags2 |= MF2_BOSSFLEE;
-				mo->momz = FixedMul(FixedDiv(mo->target->z - mo->z, P_AproxDistance(mo->x-mo->target->x,mo->y-mo->target->y)), FixedMul(2*FRACUNIT, mo->scale));
+				angle_t diff = R_PointToAngle2(mo->x, mo->y, mo->target->x, mo->target->y) - mo->angle;
+				if (diff)
+				{
+					if (diff > ANGLE_180)
+						diff = InvAngle(InvAngle(diff)/mo->extravalue1);
+					else
+						diff /= mo->extravalue1;
+					mo->movedir = diff;
+				}
 			}
-			else
-				mo->momz = FixedMul(2*FRACUNIT, mo->scale);
+
 			break;
 		}
 	}
@@ -11992,7 +12014,7 @@ void A_MineExplode(mobj_t *actor)
 	{
 #define dist 64
 		UINT8 i;
-		mobjtype_t type = ((actor->eflags & MFE_UNDERWATER) ? MT_UWEXPLODE : MT_BOSSEXPLODE);
+		mobjtype_t type = ((actor->eflags & MFE_UNDERWATER) ? MT_UWEXPLODE : MT_SONIC3KBOSSEXPLODE);
 		S_StartSound(actor, ((actor->eflags & MFE_UNDERWATER) ? sfx_s3k57 : sfx_s3k4e));
 		P_SpawnMobj(actor->x, actor->y, actor->z, type);
 		for (i = 0; i < 16; i++)
diff --git a/src/p_inter.c b/src/p_inter.c
index cbf5ce54a829505e31f0fbfee7aa22fcadebc90a..0030e8e58e5a827ea57efe595680f86e9da9c25d 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -428,7 +428,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 					  || special->state == &states[S_FANG_BOUNCE4]
 					  || special->state == &states[S_FANG_PINCHBOUNCE3]
 					  || special->state == &states[S_FANG_PINCHBOUNCE4])
-					&& P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > 0)
+					&& P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > -(special->height/4))
 					{
 						P_DamageMobj(toucher, special, special, 1, 0);
 						P_SetTarget(&special->tracer, toucher);
diff --git a/src/p_map.c b/src/p_map.c
index cc9209ea8b8e0951a46e091801f39869765c18fd..15fa97c8f1481423193abbccd011273712331218 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -285,6 +285,9 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
 
 	if (spring->info->painchance != 2)
 	{
+		if (object->player)
+			object->player->pflags &= ~PF_APPLYAUTOBRAKE;
+
 		if ((horizspeed && vertispeed) || (object->player && object->player->homing)) // Mimic SA
 		{
 			object->momx = object->momy = 0;
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 5482f1a5df31dc8c9b61076d6543df5db693900a..1ee90d250acff6f79da69a528b303e25eba03948 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -4236,12 +4236,7 @@ static void P_GenericBossThinker(mobj_t *mobj)
 	if (!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))
 	{
 		if (mobj->health <= 0)
-		{
-			// look for a new target
-			if (P_BossTargetPlayer(mobj, false) && mobj->info->mass) // Bid farewell!
-				S_StartSound(mobj, mobj->info->mass);
 			return;
-		}
 
 		// look for a new target
 		if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound)
@@ -4263,7 +4258,7 @@ static void P_GenericBossThinker(mobj_t *mobj)
 // AI for the first boss.
 static void P_Boss1Thinker(mobj_t *mobj)
 {
-	if (mobj->flags2 & MF2_FRET && (statenum_t)(mobj->state-states) == mobj->info->spawnstate) {
+	if (mobj->flags2 & MF2_FRET && mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1) {
 		mobj->flags2 &= ~(MF2_FRET|MF2_SKULLFLY);
 		mobj->momx = mobj->momy = mobj->momz = 0;
 	}
@@ -4281,11 +4276,7 @@ static void P_Boss1Thinker(mobj_t *mobj)
 			return; // It's okay, then.
 
 		if (mobj->health <= 0)
-		{
-			if (P_BossTargetPlayer(mobj, false) && mobj->info->mass) // Bid farewell!
-				S_StartSound(mobj, mobj->info->mass);
 			return;
-		}
 
 		// look for a new target
 		if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound)
@@ -4332,12 +4323,7 @@ static void P_Boss2Thinker(mobj_t *mobj)
 	if (mobj->health <= mobj->info->damage && (!mobj->target || !(mobj->target->flags & MF_SHOOTABLE)))
 	{
 		if (mobj->health <= 0)
-		{
-			// look for a new target
-			if (P_BossTargetPlayer(mobj, false) && mobj->info->mass) // Bid farewell!
-				S_StartSound(mobj, mobj->info->mass);
 			return;
-		}
 
 		// look for a new target
 		if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound)
@@ -7107,6 +7093,11 @@ void P_MobjThinker(mobj_t *mobj)
 
 		switch (mobj->type)
 		{
+			case MT_BOSSTANK1:
+			case MT_BOSSTANK2:
+			case MT_BOSSSPIGOT:
+				mobj->flags2 ^= MF2_DONTDRAW;
+				break;
 			case MT_MACEPOINT:
 			case MT_CHAINMACEPOINT:
 			case MT_SPRINGBALLPOINT:
@@ -7730,7 +7721,25 @@ void P_MobjThinker(mobj_t *mobj)
 				break;
 		}
 		if (mobj->flags2 & MF2_BOSSFLEE)
-			P_InstaThrust(mobj, mobj->angle, FixedMul(12*FRACUNIT, mobj->scale));
+		{
+			if (mobj->extravalue1)
+			{
+				if (!(--mobj->extravalue1))
+				{
+					if (mobj->target)
+					{
+						mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, P_AproxDistance(mobj->x-mobj->target->x,mobj->y-mobj->target->y)), mobj->scale<<1);
+						mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
+					}
+					else
+						mobj->momz = 8*mobj->scale;
+				}
+				else
+					mobj->angle += mobj->movedir;
+			}
+			else if (mobj->target)
+				P_InstaThrust(mobj, mobj->angle, FixedMul(12*FRACUNIT, mobj->scale));
+		}
 	}
 	else if (mobj->health <= 0) // Dead things think differently than the living.
 		switch (mobj->type)
@@ -7842,8 +7851,8 @@ void P_MobjThinker(mobj_t *mobj)
 						mobj->x + (P_RandomRange(r, -r) << FRACBITS),
 						mobj->y + (P_RandomRange(r, -r) << FRACBITS),
 						mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS),
-						MT_BOSSEXPLODE);
-					S_StartSound(explosion, sfx_cybdth);
+						MT_SONIC3KBOSSEXPLODE);
+					S_StartSound(explosion, sfx_s3kb4);
 				}
 				if (mobj->movedir == DMG_DROWNED)
 					P_SetObjectMomZ(mobj, -FRACUNIT / 2, true); // slower fall from drowning
diff --git a/src/p_saveg.c b/src/p_saveg.c
index ea998b445e40c90135d0454ce412367373fc42d8..7c073b1514762b74ab6d352d2cdbebb755670ff1 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -125,6 +125,10 @@ static void P_NetArchivePlayers(void)
 		WRITEINT32(save_p, players[i].currentweapon);
 		WRITEINT32(save_p, players[i].ringweapons);
 
+		WRITEUINT16(save_p, players[i].ammoremoval);
+		WRITEUINT32(save_p, players[i].ammoremovaltimer);
+		WRITEINT32(save_p, players[i].ammoremovaltimer);
+
 		for (j = 0; j < NUMPOWERS; j++)
 			WRITEUINT16(save_p, players[i].powers[j]);
 
@@ -329,6 +333,10 @@ static void P_NetUnArchivePlayers(void)
 		players[i].currentweapon = READINT32(save_p);
 		players[i].ringweapons = READINT32(save_p);
 
+		players[i].ammoremoval = READUINT16(save_p);
+		players[i].ammoremovaltimer = READUINT32(save_p);
+		players[i].ammoremovalweapon = READINT32(save_p);
+
 		for (j = 0; j < NUMPOWERS; j++)
 			players[i].powers[j] = READUINT16(save_p);
 
diff --git a/src/p_user.c b/src/p_user.c
index fc1d97e49d8d3d4aa03275562e52a1a01825a2ae..a69bd5b9372063b2ba4cea98eb5920283a010399 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1051,6 +1051,8 @@ void P_ResetPlayer(player_t *player)
 //
 boolean P_PlayerCanDamage(player_t *player, mobj_t *thing)
 {
+	fixed_t bottomheight, topheight;
+
 	if (!player->mo || player->spectator || !thing || P_MobjWasRemoved(thing))
 		return false;
 
@@ -1090,13 +1092,26 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing)
 		return true;
 
 	// From the top/bottom.
-	if (P_MobjFlip(player->mo)*(player->mo->z - (thing->z + thing->height/2)) > 0)
+	bottomheight = player->mo->z;
+	topheight = player->mo->z + player->mo->height;
+
+	if (player->mo->eflags & MFE_VERTICALFLIP)
 	{
-		if ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(player->mo)*player->mo->momz < 0))
+		fixed_t swap = bottomheight;
+		bottomheight = topheight;
+		topheight = swap;
+	}
+
+	if (P_MobjFlip(player->mo)*(bottomheight - (thing->z + thing->height/2)) > 0)
+	{
+		if ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) < 0))
+			return true;
+	}
+	else if (P_MobjFlip(player->mo)*(topheight - (thing->z + thing->height/2)) < 0)
+	{
+		if (player->charability == CA_FLY && player->panim == PA_ABILITY && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0))
 			return true;
 	}
-	else if (player->charability == CA_FLY && player->panim == PA_ABILITY)
-		return true;
 
 	// Shield stomp.
 	if (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY))
@@ -3885,6 +3900,33 @@ static void P_SetWeaponDelay(player_t *player, INT32 delay)
 	}
 }
 
+//
+// P_DrainWeaponAmmo
+//
+// Reduces rings and weapon ammo. Also penalizes the player
+// for using weapon rings with no normal rings! >:V
+//
+static void P_DrainWeaponAmmo (player_t *player, INT32 power)
+{
+	player->powers[power]--;
+
+	if (player->rings < 1)
+	{
+		player->ammoremovalweapon = player->currentweapon;
+		player->ammoremovaltimer  = ammoremovaltics;
+
+		if (player->powers[power] > 0) // can't take a ring that doesn't exist
+		{
+			player->powers[power]--;
+			player->ammoremoval = 2;
+		}
+		else
+			player->ammoremoval = 1;
+	}
+	else
+		player->rings--;
+}
+
 //
 // P_DoFiring()
 //
@@ -3923,22 +3965,12 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
 
 	player->pflags |= PF_ATTACKDOWN;
 
-#define TAKE_AMMO(player, power) \
-		player->powers[power]--; \
-		if (player->rings < 1) \
-		{ \
-			if (player->powers[power] > 0) \
-				player->powers[power]--; \
-		} \
-		else \
-			player->rings--;
-
 	if (cmd->buttons & BT_FIRENORMAL) // No powers, just a regular ring.
 		goto firenormal; //code repetition sucks.
 	// Bounce ring
 	else if (player->currentweapon == WEP_BOUNCE && player->powers[pw_bouncering])
 	{
-		TAKE_AMMO(player, pw_bouncering);
+		P_DrainWeaponAmmo(player, pw_bouncering);
 		P_SetWeaponDelay(player, TICRATE/4);
 
 		mo = P_SpawnPlayerMissile(player->mo, MT_THROWNBOUNCE, MF2_BOUNCERING);
@@ -3949,7 +3981,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
 	// Rail ring
 	else if (player->currentweapon == WEP_RAIL && player->powers[pw_railring])
 	{
-		TAKE_AMMO(player, pw_railring);
+		P_DrainWeaponAmmo(player, pw_railring);
 		P_SetWeaponDelay(player, (3*TICRATE)/2);
 
 		mo = P_SpawnPlayerMissile(player->mo, MT_REDRING, MF2_RAILRING|MF2_DONTDRAW);
@@ -3960,7 +3992,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
 	// Automatic
 	else if (player->currentweapon == WEP_AUTO && player->powers[pw_automaticring])
 	{
-		TAKE_AMMO(player, pw_automaticring);
+		P_DrainWeaponAmmo(player, pw_automaticring);
 		player->pflags &= ~PF_ATTACKDOWN;
 		P_SetWeaponDelay(player, 2);
 
@@ -3969,7 +4001,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
 	// Explosion
 	else if (player->currentweapon == WEP_EXPLODE && player->powers[pw_explosionring])
 	{
-		TAKE_AMMO(player, pw_explosionring);
+		P_DrainWeaponAmmo(player, pw_explosionring);
 		P_SetWeaponDelay(player, (3*TICRATE)/2);
 
 		mo = P_SpawnPlayerMissile(player->mo, MT_THROWNEXPLOSION, MF2_EXPLOSION);
@@ -3977,7 +4009,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
 	// Grenade
 	else if (player->currentweapon == WEP_GRENADE && player->powers[pw_grenadering])
 	{
-		TAKE_AMMO(player, pw_grenadering);
+		P_DrainWeaponAmmo(player, pw_grenadering);
 		P_SetWeaponDelay(player, TICRATE/3);
 
 		mo = P_SpawnPlayerMissile(player->mo, MT_THROWNGRENADE, MF2_EXPLOSION);
@@ -3996,7 +4028,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
 		angle_t shotangle = player->mo->angle;
 		angle_t oldaiming = player->aiming;
 
-		TAKE_AMMO(player, pw_scatterring);
+		P_DrainWeaponAmmo(player, pw_scatterring);
 		P_SetWeaponDelay(player, (2*TICRATE)/3);
 
 		// Center
@@ -4058,8 +4090,6 @@ firenormal:
 		}
 	}
 
-	#undef TAKE_AMMO
-
 	if (mo)
 	{
 		if (mo->flags & MF_MISSILE && mo->flags2 & MF2_RAILRING)
@@ -6509,12 +6539,12 @@ static void P_DoNiGHTSCapsule(player_t *player)
 					player->capsule->health = sphereresult;
 			}
 
-			// Spawn a 'pop' for every 5 tics
-			if (!((tictimer - firstpoptic) % 5))
+			// Spawn a 'pop' for every 2 tics
+			if (!((tictimer - firstpoptic) % 2))
 				S_StartSound(P_SpawnMobj(player->capsule->x + ((P_SignedRandom()/2)<<FRACBITS),
 				player->capsule->y + ((P_SignedRandom()/2)<<FRACBITS),
 				player->capsule->z + (player->capsule->height/2) + ((P_SignedRandom()/2)<<FRACBITS),
-				MT_BOSSEXPLODE),sfx_cybdth);
+				MT_SONIC3KBOSSEXPLODE),sfx_s3kb4);
 		}
 		else
 		{
@@ -11233,6 +11263,16 @@ void P_PlayerThink(player_t *player)
 
 				if (!currentlyonground)
 					acceleration /= 2;
+				// fake skidding! see P_SkidStuff for reference on conditionals
+				else if (!player->skidtime && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID) && P_AproxDistance(player->mo->momx, player->mo->momy) >= FixedMul(player->runspeed/2, player->mo->scale))
+				{
+					if (player->mo->state-states != S_PLAY_SKID)
+						P_SetPlayerMobjState(player->mo, S_PLAY_SKID);
+					player->mo->tics = player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS;
+
+					if (P_IsLocalPlayer(player)) // the sound happens way more frequently now, so give co-op players' ears a brake...
+						S_StartSound(player->mo, sfx_skid);
+				}
 
 				if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration...
 					acceleration = FixedMul(acceleration<<FRACBITS, player->mo->movefactor)>>FRACBITS;
@@ -11317,6 +11357,12 @@ void P_PlayerThink(player_t *player)
 	// Counters, time dependent power ups.
 	// Time Bonus & Ring Bonus count settings
 
+	if (player->ammoremovaltimer)
+	{
+		if (--player->ammoremovaltimer == 0)
+			player->ammoremoval = 0;
+	}
+
 	// Strength counts up to diminish fade.
 	if (player->powers[pw_sneakers] && player->powers[pw_sneakers] < UINT16_MAX)
 		player->powers[pw_sneakers]--;
diff --git a/src/st_stuff.c b/src/st_stuff.c
index aefb4c53c70badbc2a9b85e178b4cdceb2b704dc..142cd3e61f8c261703d9b2121165b3b95960dc5e 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -1960,6 +1960,7 @@ static void ST_drawWeaponRing(powertype_t weapon, INT32 rwflag, INT32 wepflag, I
 
 static void ST_drawMatchHUD(void)
 {
+	char penaltystr[5];
 	const INT32 y = 176; // HUD_LIVES
 	INT32 offset = (BASEVIDWIDTH / 2) - (NUM_WEAPONS * 10) - 6;
 
@@ -1986,18 +1987,20 @@ static void ST_drawMatchHUD(void)
 				ST_drawWeaponSelect(offset, y);
 		}
 
-		offset += 20;
-		ST_drawWeaponRing(pw_automaticring, RW_AUTO, WEP_AUTO, offset, y, autoring);
-		offset += 20;
-		ST_drawWeaponRing(pw_bouncering, RW_BOUNCE, WEP_BOUNCE, offset, y, bouncering);
-		offset += 20;
-		ST_drawWeaponRing(pw_scatterring, RW_SCATTER, WEP_SCATTER, offset, y, scatterring);
-		offset += 20;
-		ST_drawWeaponRing(pw_grenadering, RW_GRENADE, WEP_GRENADE, offset, y, grenadering);
-		offset += 20;
-		ST_drawWeaponRing(pw_explosionring, RW_EXPLODE, WEP_EXPLODE, offset, y, explosionring);
-		offset += 20;
-		ST_drawWeaponRing(pw_railring, RW_RAIL, WEP_RAIL, offset, y, railring);
+		ST_drawWeaponRing(pw_automaticring, RW_AUTO, WEP_AUTO, offset + 20, y, autoring);
+		ST_drawWeaponRing(pw_bouncering, RW_BOUNCE, WEP_BOUNCE, offset + 40, y, bouncering);
+		ST_drawWeaponRing(pw_scatterring, RW_SCATTER, WEP_SCATTER, offset + 60, y, scatterring);
+		ST_drawWeaponRing(pw_grenadering, RW_GRENADE, WEP_GRENADE, offset + 80, y, grenadering);
+		ST_drawWeaponRing(pw_explosionring, RW_EXPLODE, WEP_EXPLODE, offset + 100, y, explosionring);
+		ST_drawWeaponRing(pw_railring, RW_RAIL, WEP_RAIL, offset + 120, y, railring);
+
+		if (stplyr->ammoremovaltimer && leveltime % 8 < 4)
+		{
+			sprintf(penaltystr, "-%d", stplyr->ammoremoval);
+			V_DrawString(offset + 8 + stplyr->ammoremovalweapon * 20, y,
+					V_REDMAP, penaltystr);
+		}
+
 	}
 }