From 1bdd4cf641a1116097c7081f365962c80b8bf3a3 Mon Sep 17 00:00:00 2001
From: Inuyasha <MattWCSTRFAN@gmail.com>
Date: Tue, 9 Feb 2016 02:39:16 -0800
Subject: [PATCH 1/7] backport state-animations from internal master to public
 next

most other code in the branch did not come along for the ride.
---
 src/dehacked.c    | 614 +++--------------------------------
 src/info.c        | 802 ++++++++--------------------------------------
 src/info.h        | 613 +++--------------------------------
 src/lua_mobjlib.c |   8 +
 src/p_local.h     |   1 +
 src/p_mobj.c      | 159 +++++----
 src/p_mobj.h      |   4 +-
 src/p_pspr.h      |   6 +-
 src/p_saveg.c     |  11 +
 src/p_tick.c      |   2 +
 10 files changed, 341 insertions(+), 1879 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index 44ef998ac..a29f3875e 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -4588,30 +4588,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_MSSHIELD_F12",
 
 	// Ring
-	"S_RING1",
-	"S_RING2",
-	"S_RING3",
-	"S_RING4",
-	"S_RING5",
-	"S_RING6",
-	"S_RING7",
-	"S_RING8",
-	"S_RING9",
-	"S_RING10",
-	"S_RING11",
-	"S_RING12",
-	"S_RING13",
-	"S_RING14",
-	"S_RING15",
-	"S_RING16",
-	"S_RING17",
-	"S_RING18",
-	"S_RING19",
-	"S_RING20",
-	"S_RING21",
-	"S_RING22",
-	"S_RING23",
-	"S_RING24",
+	"S_RING",
 
 	// Blue Sphere for special stages
 	"S_BLUEBALL",
@@ -4627,39 +4604,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_GRAVWELLRED3",
 
 	// Individual Team Rings
-	"S_TEAMRING1",
-	"S_TEAMRING2",
-	"S_TEAMRING3",
-	"S_TEAMRING4",
-	"S_TEAMRING5",
-	"S_TEAMRING6",
-	"S_TEAMRING7",
-	"S_TEAMRING8",
-	"S_TEAMRING9",
-	"S_TEAMRING10",
-	"S_TEAMRING11",
-	"S_TEAMRING12",
-	"S_TEAMRING13",
-	"S_TEAMRING14",
-	"S_TEAMRING15",
-	"S_TEAMRING16",
-	"S_TEAMRING17",
-	"S_TEAMRING18",
-	"S_TEAMRING19",
-	"S_TEAMRING20",
-	"S_TEAMRING21",
-	"S_TEAMRING22",
-	"S_TEAMRING23",
-	"S_TEAMRING24",
+	"S_TEAMRING",
 
 	// Special Stage Token
-	"S_EMMY1",
-	"S_EMMY2",
-	"S_EMMY3",
-	"S_EMMY4",
-	"S_EMMY5",
-	"S_EMMY6",
-	"S_EMMY7",
+	"S_EMMY",
 
 	// Special Stage Token
 	"S_TOKEN",
@@ -4813,40 +4761,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_SPIKED2",
 
 	// Starpost
-	"S_STARPOST1",
-	"S_STARPOST2",
-	"S_STARPOST3",
-	"S_STARPOST4",
-	"S_STARPOST5",
-	"S_STARPOST6",
-	"S_STARPOST7",
-	"S_STARPOST8",
-	"S_STARPOST9",
-	"S_STARPOST10",
-	"S_STARPOST11",
-	"S_STARPOST12",
-	"S_STARPOST13",
-	"S_STARPOST14",
-	"S_STARPOST15",
-	"S_STARPOST16",
-	"S_STARPOST17",
-	"S_STARPOST18",
-	"S_STARPOST19",
-	"S_STARPOST20",
-	"S_STARPOST21",
-	"S_STARPOST22",
-	"S_STARPOST23",
-	"S_STARPOST24",
-	"S_STARPOST25",
-	"S_STARPOST26",
-	"S_STARPOST27",
-	"S_STARPOST28",
-	"S_STARPOST29",
-	"S_STARPOST30",
-	"S_STARPOST31",
-	"S_STARPOST32",
-	"S_STARPOST33",
-	"S_STARPOST34",
+	"S_STARPOST_IDLE",
+	"S_STARPOST_FLASH",
+	"S_STARPOST_SPIN",
 
 	// Big floating mine
 	"S_BIGMINE1",
@@ -5454,38 +5371,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_PITY10",
 
 	// Invincibility Sparkles
-	"S_IVSP1",
-	"S_IVSP2",
-	"S_IVSP3",
-	"S_IVSP4",
-	"S_IVSP5",
-	"S_IVSP6",
-	"S_IVSP7",
-	"S_IVSP8",
-	"S_IVSP9",
-	"S_IVSP10",
-	"S_IVSP11",
-	"S_IVSP12",
-	"S_IVSP13",
-	"S_IVSP14",
-	"S_IVSP15",
-	"S_IVSP16",
-	"S_IVSP17",
-	"S_IVSP18",
-	"S_IVSP19",
-	"S_IVSP20",
-	"S_IVSP21",
-	"S_IVSP22",
-	"S_IVSP23",
-	"S_IVSP24",
-	"S_IVSP25",
-	"S_IVSP26",
-	"S_IVSP27",
-	"S_IVSP28",
-	"S_IVSP29",
-	"S_IVSP30",
-	"S_IVSP31",
-	"S_IVSP32",
+	"S_IVSP",
 
 	// Super Sonic Spark
 	"S_SSPK1",
@@ -5672,283 +5558,17 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_RRNG6",
 	"S_RRNG7",
 
-	// Bounce Ring
-	"S_BOUNCERING1",
-	"S_BOUNCERING2",
-	"S_BOUNCERING3",
-	"S_BOUNCERING4",
-	"S_BOUNCERING5",
-	"S_BOUNCERING6",
-	"S_BOUNCERING7",
-	"S_BOUNCERING8",
-	"S_BOUNCERING9",
-	"S_BOUNCERING10",
-	"S_BOUNCERING11",
-	"S_BOUNCERING12",
-	"S_BOUNCERING13",
-	"S_BOUNCERING14",
-	"S_BOUNCERING15",
-	"S_BOUNCERING16",
-	"S_BOUNCERING17",
-	"S_BOUNCERING18",
-	"S_BOUNCERING19",
-	"S_BOUNCERING20",
-	"S_BOUNCERING21",
-	"S_BOUNCERING22",
-	"S_BOUNCERING23",
-	"S_BOUNCERING24",
-	"S_BOUNCERING25",
-	"S_BOUNCERING26",
-	"S_BOUNCERING27",
-	"S_BOUNCERING28",
-	"S_BOUNCERING29",
-	"S_BOUNCERING30",
-	"S_BOUNCERING31",
-	"S_BOUNCERING32",
-	"S_BOUNCERING33",
-	"S_BOUNCERING34",
-	"S_BOUNCERING35",
-
-	// Rail Ring
-	"S_RAILRING1",
-	"S_RAILRING2",
-	"S_RAILRING3",
-	"S_RAILRING4",
-	"S_RAILRING5",
-	"S_RAILRING6",
-	"S_RAILRING7",
-	"S_RAILRING8",
-	"S_RAILRING9",
-	"S_RAILRING10",
-	"S_RAILRING11",
-	"S_RAILRING12",
-	"S_RAILRING13",
-	"S_RAILRING14",
-	"S_RAILRING15",
-	"S_RAILRING16",
-	"S_RAILRING17",
-	"S_RAILRING18",
-	"S_RAILRING19",
-	"S_RAILRING20",
-	"S_RAILRING21",
-	"S_RAILRING22",
-	"S_RAILRING23",
-	"S_RAILRING24",
-	"S_RAILRING25",
-	"S_RAILRING26",
-	"S_RAILRING27",
-	"S_RAILRING28",
-	"S_RAILRING29",
-	"S_RAILRING30",
-	"S_RAILRING31",
-	"S_RAILRING32",
-	"S_RAILRING33",
-	"S_RAILRING34",
-	"S_RAILRING35",
-
-	// Infinity ring
-	"S_INFINITYRING1",
-	"S_INFINITYRING2",
-	"S_INFINITYRING3",
-	"S_INFINITYRING4",
-	"S_INFINITYRING5",
-	"S_INFINITYRING6",
-	"S_INFINITYRING7",
-	"S_INFINITYRING8",
-	"S_INFINITYRING9",
-	"S_INFINITYRING10",
-	"S_INFINITYRING11",
-	"S_INFINITYRING12",
-	"S_INFINITYRING13",
-	"S_INFINITYRING14",
-	"S_INFINITYRING15",
-	"S_INFINITYRING16",
-	"S_INFINITYRING17",
-	"S_INFINITYRING18",
-	"S_INFINITYRING19",
-	"S_INFINITYRING20",
-	"S_INFINITYRING21",
-	"S_INFINITYRING22",
-	"S_INFINITYRING23",
-	"S_INFINITYRING24",
-	"S_INFINITYRING25",
-	"S_INFINITYRING26",
-	"S_INFINITYRING27",
-	"S_INFINITYRING28",
-	"S_INFINITYRING29",
-	"S_INFINITYRING30",
-	"S_INFINITYRING31",
-	"S_INFINITYRING32",
-	"S_INFINITYRING33",
-	"S_INFINITYRING34",
-	"S_INFINITYRING35",
-
-	// Automatic Ring
-	"S_AUTOMATICRING1",
-	"S_AUTOMATICRING2",
-	"S_AUTOMATICRING3",
-	"S_AUTOMATICRING4",
-	"S_AUTOMATICRING5",
-	"S_AUTOMATICRING6",
-	"S_AUTOMATICRING7",
-	"S_AUTOMATICRING8",
-	"S_AUTOMATICRING9",
-	"S_AUTOMATICRING10",
-	"S_AUTOMATICRING11",
-	"S_AUTOMATICRING12",
-	"S_AUTOMATICRING13",
-	"S_AUTOMATICRING14",
-	"S_AUTOMATICRING15",
-	"S_AUTOMATICRING16",
-	"S_AUTOMATICRING17",
-	"S_AUTOMATICRING18",
-	"S_AUTOMATICRING19",
-	"S_AUTOMATICRING20",
-	"S_AUTOMATICRING21",
-	"S_AUTOMATICRING22",
-	"S_AUTOMATICRING23",
-	"S_AUTOMATICRING24",
-	"S_AUTOMATICRING25",
-	"S_AUTOMATICRING26",
-	"S_AUTOMATICRING27",
-	"S_AUTOMATICRING28",
-	"S_AUTOMATICRING29",
-	"S_AUTOMATICRING30",
-	"S_AUTOMATICRING31",
-	"S_AUTOMATICRING32",
-	"S_AUTOMATICRING33",
-	"S_AUTOMATICRING34",
-	"S_AUTOMATICRING35",
-
-	// Explosion Ring
-	"S_EXPLOSIONRING1",
-	"S_EXPLOSIONRING2",
-	"S_EXPLOSIONRING3",
-	"S_EXPLOSIONRING4",
-	"S_EXPLOSIONRING5",
-	"S_EXPLOSIONRING6",
-	"S_EXPLOSIONRING7",
-	"S_EXPLOSIONRING8",
-	"S_EXPLOSIONRING9",
-	"S_EXPLOSIONRING10",
-	"S_EXPLOSIONRING11",
-	"S_EXPLOSIONRING12",
-	"S_EXPLOSIONRING13",
-	"S_EXPLOSIONRING14",
-	"S_EXPLOSIONRING15",
-	"S_EXPLOSIONRING16",
-	"S_EXPLOSIONRING17",
-	"S_EXPLOSIONRING18",
-	"S_EXPLOSIONRING19",
-	"S_EXPLOSIONRING20",
-	"S_EXPLOSIONRING21",
-	"S_EXPLOSIONRING22",
-	"S_EXPLOSIONRING23",
-	"S_EXPLOSIONRING24",
-	"S_EXPLOSIONRING25",
-	"S_EXPLOSIONRING26",
-	"S_EXPLOSIONRING27",
-	"S_EXPLOSIONRING28",
-	"S_EXPLOSIONRING29",
-	"S_EXPLOSIONRING30",
-	"S_EXPLOSIONRING31",
-	"S_EXPLOSIONRING32",
-	"S_EXPLOSIONRING33",
-	"S_EXPLOSIONRING34",
-	"S_EXPLOSIONRING35",
-
-	// Scatter Ring
-	"S_SCATTERRING1",
-	"S_SCATTERRING2",
-	"S_SCATTERRING3",
-	"S_SCATTERRING4",
-	"S_SCATTERRING5",
-	"S_SCATTERRING6",
-	"S_SCATTERRING7",
-	"S_SCATTERRING8",
-	"S_SCATTERRING9",
-	"S_SCATTERRING10",
-	"S_SCATTERRING11",
-	"S_SCATTERRING12",
-	"S_SCATTERRING13",
-	"S_SCATTERRING14",
-	"S_SCATTERRING15",
-	"S_SCATTERRING16",
-	"S_SCATTERRING17",
-	"S_SCATTERRING18",
-	"S_SCATTERRING19",
-	"S_SCATTERRING20",
-	"S_SCATTERRING21",
-	"S_SCATTERRING22",
-	"S_SCATTERRING23",
-	"S_SCATTERRING24",
-	"S_SCATTERRING25",
-	"S_SCATTERRING26",
-	"S_SCATTERRING27",
-	"S_SCATTERRING28",
-	"S_SCATTERRING29",
-	"S_SCATTERRING30",
-	"S_SCATTERRING31",
-	"S_SCATTERRING32",
-	"S_SCATTERRING33",
-	"S_SCATTERRING34",
-	"S_SCATTERRING35",
-
-	// Grenade Ring
-	"S_GRENADERING1",
-	"S_GRENADERING2",
-	"S_GRENADERING3",
-	"S_GRENADERING4",
-	"S_GRENADERING5",
-	"S_GRENADERING6",
-	"S_GRENADERING7",
-	"S_GRENADERING8",
-	"S_GRENADERING9",
-	"S_GRENADERING10",
-	"S_GRENADERING11",
-	"S_GRENADERING12",
-	"S_GRENADERING13",
-	"S_GRENADERING14",
-	"S_GRENADERING15",
-	"S_GRENADERING16",
-	"S_GRENADERING17",
-	"S_GRENADERING18",
-	"S_GRENADERING19",
-	"S_GRENADERING20",
-	"S_GRENADERING21",
-	"S_GRENADERING22",
-	"S_GRENADERING23",
-	"S_GRENADERING24",
-	"S_GRENADERING25",
-	"S_GRENADERING26",
-	"S_GRENADERING27",
-	"S_GRENADERING28",
-	"S_GRENADERING29",
-	"S_GRENADERING30",
-	"S_GRENADERING31",
-	"S_GRENADERING32",
-	"S_GRENADERING33",
-	"S_GRENADERING34",
-	"S_GRENADERING35",
+	// Weapon Ring Ammo
+	"S_BOUNCERINGAMMO",
+	"S_RAILRINGAMMO",
+	"S_INFINITYRINGAMMO",
+	"S_AUTOMATICRINGAMMO",
+	"S_EXPLOSIONRINGAMMO",
+	"S_SCATTERRINGAMMO",
+	"S_GRENADERINGAMMO",
 
 	// Weapon pickup
-	"S_BOUNCEPICKUP1",
-	"S_BOUNCEPICKUP2",
-	"S_BOUNCEPICKUP3",
-	"S_BOUNCEPICKUP4",
-	"S_BOUNCEPICKUP5",
-	"S_BOUNCEPICKUP6",
-	"S_BOUNCEPICKUP7",
-	"S_BOUNCEPICKUP8",
-	"S_BOUNCEPICKUP9",
-	"S_BOUNCEPICKUP10",
-	"S_BOUNCEPICKUP11",
-	"S_BOUNCEPICKUP12",
-	"S_BOUNCEPICKUP13",
-	"S_BOUNCEPICKUP14",
-	"S_BOUNCEPICKUP15",
-	"S_BOUNCEPICKUP16",
-
+	"S_BOUNCEPICKUP",
 	"S_BOUNCEPICKUPFADE1",
 	"S_BOUNCEPICKUPFADE2",
 	"S_BOUNCEPICKUPFADE3",
@@ -5958,23 +5578,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_BOUNCEPICKUPFADE7",
 	"S_BOUNCEPICKUPFADE8",
 
-	"S_RAILPICKUP1",
-	"S_RAILPICKUP2",
-	"S_RAILPICKUP3",
-	"S_RAILPICKUP4",
-	"S_RAILPICKUP5",
-	"S_RAILPICKUP6",
-	"S_RAILPICKUP7",
-	"S_RAILPICKUP8",
-	"S_RAILPICKUP9",
-	"S_RAILPICKUP10",
-	"S_RAILPICKUP11",
-	"S_RAILPICKUP12",
-	"S_RAILPICKUP13",
-	"S_RAILPICKUP14",
-	"S_RAILPICKUP15",
-	"S_RAILPICKUP16",
-
+	"S_RAILPICKUP",
 	"S_RAILPICKUPFADE1",
 	"S_RAILPICKUPFADE2",
 	"S_RAILPICKUPFADE3",
@@ -5984,23 +5588,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_RAILPICKUPFADE7",
 	"S_RAILPICKUPFADE8",
 
-	"S_AUTOPICKUP1",
-	"S_AUTOPICKUP2",
-	"S_AUTOPICKUP3",
-	"S_AUTOPICKUP4",
-	"S_AUTOPICKUP5",
-	"S_AUTOPICKUP6",
-	"S_AUTOPICKUP7",
-	"S_AUTOPICKUP8",
-	"S_AUTOPICKUP9",
-	"S_AUTOPICKUP10",
-	"S_AUTOPICKUP11",
-	"S_AUTOPICKUP12",
-	"S_AUTOPICKUP13",
-	"S_AUTOPICKUP14",
-	"S_AUTOPICKUP15",
-	"S_AUTOPICKUP16",
-
+	"S_AUTOPICKUP",
 	"S_AUTOPICKUPFADE1",
 	"S_AUTOPICKUPFADE2",
 	"S_AUTOPICKUPFADE3",
@@ -6010,23 +5598,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_AUTOPICKUPFADE7",
 	"S_AUTOPICKUPFADE8",
 
-	"S_EXPLODEPICKUP1",
-	"S_EXPLODEPICKUP2",
-	"S_EXPLODEPICKUP3",
-	"S_EXPLODEPICKUP4",
-	"S_EXPLODEPICKUP5",
-	"S_EXPLODEPICKUP6",
-	"S_EXPLODEPICKUP7",
-	"S_EXPLODEPICKUP8",
-	"S_EXPLODEPICKUP9",
-	"S_EXPLODEPICKUP10",
-	"S_EXPLODEPICKUP11",
-	"S_EXPLODEPICKUP12",
-	"S_EXPLODEPICKUP13",
-	"S_EXPLODEPICKUP14",
-	"S_EXPLODEPICKUP15",
-	"S_EXPLODEPICKUP16",
-
+	"S_EXPLODEPICKUP",
 	"S_EXPLODEPICKUPFADE1",
 	"S_EXPLODEPICKUPFADE2",
 	"S_EXPLODEPICKUPFADE3",
@@ -6036,23 +5608,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_EXPLODEPICKUPFADE7",
 	"S_EXPLODEPICKUPFADE8",
 
-	"S_SCATTERPICKUP1",
-	"S_SCATTERPICKUP2",
-	"S_SCATTERPICKUP3",
-	"S_SCATTERPICKUP4",
-	"S_SCATTERPICKUP5",
-	"S_SCATTERPICKUP6",
-	"S_SCATTERPICKUP7",
-	"S_SCATTERPICKUP8",
-	"S_SCATTERPICKUP9",
-	"S_SCATTERPICKUP10",
-	"S_SCATTERPICKUP11",
-	"S_SCATTERPICKUP12",
-	"S_SCATTERPICKUP13",
-	"S_SCATTERPICKUP14",
-	"S_SCATTERPICKUP15",
-	"S_SCATTERPICKUP16",
-
+	"S_SCATTERPICKUP",
 	"S_SCATTERPICKUPFADE1",
 	"S_SCATTERPICKUPFADE2",
 	"S_SCATTERPICKUPFADE3",
@@ -6062,23 +5618,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_SCATTERPICKUPFADE7",
 	"S_SCATTERPICKUPFADE8",
 
-	"S_GRENADEPICKUP1",
-	"S_GRENADEPICKUP2",
-	"S_GRENADEPICKUP3",
-	"S_GRENADEPICKUP4",
-	"S_GRENADEPICKUP5",
-	"S_GRENADEPICKUP6",
-	"S_GRENADEPICKUP7",
-	"S_GRENADEPICKUP8",
-	"S_GRENADEPICKUP9",
-	"S_GRENADEPICKUP10",
-	"S_GRENADEPICKUP11",
-	"S_GRENADEPICKUP12",
-	"S_GRENADEPICKUP13",
-	"S_GRENADEPICKUP14",
-	"S_GRENADEPICKUP15",
-	"S_GRENADEPICKUP16",
-
+	"S_GRENADEPICKUP",
 	"S_GRENADEPICKUPFADE1",
 	"S_GRENADEPICKUPFADE2",
 	"S_GRENADEPICKUPFADE3",
@@ -6459,101 +5999,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 
 	"S_ROCKSPAWN",
 
-	"S_ROCKCRUMBLEA1",
-	"S_ROCKCRUMBLEA2",
-	"S_ROCKCRUMBLEA3",
-	"S_ROCKCRUMBLEA4",
-	"S_ROCKCRUMBLEA5",
-
-	"S_ROCKCRUMBLEB1",
-	"S_ROCKCRUMBLEB2",
-	"S_ROCKCRUMBLEB3",
-	"S_ROCKCRUMBLEB4",
-	"S_ROCKCRUMBLEB5",
-
-	"S_ROCKCRUMBLEC1",
-	"S_ROCKCRUMBLEC2",
-	"S_ROCKCRUMBLEC3",
-	"S_ROCKCRUMBLEC4",
-	"S_ROCKCRUMBLEC5",
-
-	"S_ROCKCRUMBLED1",
-	"S_ROCKCRUMBLED2",
-	"S_ROCKCRUMBLED3",
-	"S_ROCKCRUMBLED4",
-	"S_ROCKCRUMBLED5",
-
-	"S_ROCKCRUMBLEE1",
-	"S_ROCKCRUMBLEE2",
-	"S_ROCKCRUMBLEE3",
-	"S_ROCKCRUMBLEE4",
-	"S_ROCKCRUMBLEE5",
-
-	"S_ROCKCRUMBLEF1",
-	"S_ROCKCRUMBLEF2",
-	"S_ROCKCRUMBLEF3",
-	"S_ROCKCRUMBLEF4",
-	"S_ROCKCRUMBLEF5",
-
-	"S_ROCKCRUMBLEG1",
-	"S_ROCKCRUMBLEG2",
-	"S_ROCKCRUMBLEG3",
-	"S_ROCKCRUMBLEG4",
-	"S_ROCKCRUMBLEG5",
-
-	"S_ROCKCRUMBLEH1",
-	"S_ROCKCRUMBLEH2",
-	"S_ROCKCRUMBLEH3",
-	"S_ROCKCRUMBLEH4",
-	"S_ROCKCRUMBLEH5",
-
-	"S_ROCKCRUMBLEI1",
-	"S_ROCKCRUMBLEI2",
-	"S_ROCKCRUMBLEI3",
-	"S_ROCKCRUMBLEI4",
-	"S_ROCKCRUMBLEI5",
-
-	"S_ROCKCRUMBLEJ1",
-	"S_ROCKCRUMBLEJ2",
-	"S_ROCKCRUMBLEJ3",
-	"S_ROCKCRUMBLEJ4",
-	"S_ROCKCRUMBLEJ5",
-
-	"S_ROCKCRUMBLEK1",
-	"S_ROCKCRUMBLEK2",
-	"S_ROCKCRUMBLEK3",
-	"S_ROCKCRUMBLEK4",
-	"S_ROCKCRUMBLEK5",
-
-	"S_ROCKCRUMBLEL1",
-	"S_ROCKCRUMBLEL2",
-	"S_ROCKCRUMBLEL3",
-	"S_ROCKCRUMBLEL4",
-	"S_ROCKCRUMBLEL5",
-
-	"S_ROCKCRUMBLEM1",
-	"S_ROCKCRUMBLEM2",
-	"S_ROCKCRUMBLEM3",
-	"S_ROCKCRUMBLEM4",
-	"S_ROCKCRUMBLEM5",
-
-	"S_ROCKCRUMBLEN1",
-	"S_ROCKCRUMBLEN2",
-	"S_ROCKCRUMBLEN3",
-	"S_ROCKCRUMBLEN4",
-	"S_ROCKCRUMBLEN5",
-
-	"S_ROCKCRUMBLEO1",
-	"S_ROCKCRUMBLEO2",
-	"S_ROCKCRUMBLEO3",
-	"S_ROCKCRUMBLEO4",
-	"S_ROCKCRUMBLEO5",
-
-	"S_ROCKCRUMBLEP1",
-	"S_ROCKCRUMBLEP2",
-	"S_ROCKCRUMBLEP3",
-	"S_ROCKCRUMBLEP4",
-	"S_ROCKCRUMBLEP5",
+	"S_ROCKCRUMBLEA",
+	"S_ROCKCRUMBLEB",
+	"S_ROCKCRUMBLEC",
+	"S_ROCKCRUMBLED",
+	"S_ROCKCRUMBLEE",
+	"S_ROCKCRUMBLEF",
+	"S_ROCKCRUMBLEG",
+	"S_ROCKCRUMBLEH",
+	"S_ROCKCRUMBLEI",
+	"S_ROCKCRUMBLEJ",
+	"S_ROCKCRUMBLEK",
+	"S_ROCKCRUMBLEL",
+	"S_ROCKCRUMBLEM",
+	"S_ROCKCRUMBLEN",
+	"S_ROCKCRUMBLEO",
+	"S_ROCKCRUMBLEP",
 
 	"S_SRB1_CRAWLA1",
 	"S_SRB1_CRAWLA2",
@@ -7484,6 +6945,7 @@ struct {
 
 	// Frame settings
 	{"FF_FRAMEMASK",FF_FRAMEMASK},
+	{"FF_ANIMATE",FF_ANIMATE},
 	{"FF_FULLBRIGHT",FF_FULLBRIGHT},
 	{"FF_TRANSMASK",FF_TRANSMASK},
 	{"FF_TRANSSHIFT",FF_TRANSSHIFT},
diff --git a/src/info.c b/src/info.c
index 9e04b4e34..9f75f188d 100644
--- a/src/info.c
+++ b/src/info.c
@@ -60,6 +60,7 @@ char sprnames[NUMSPRITES + 1][5] =
 state_t states[NUMSTATES] =
 {
 	// frame is masked through FF_FRAMEMASK
+	// FF_ANIMATE (0x4000) makes simple state animations (var1 #frames, var2 tic delay)
 	// FF_FULLBRIGHT (0x8000) activates the fullbright colormap
 	// use FF_TRANS10 - FF_TRANS90 for easy translucency
 	// (or tr_trans10<<FF_TRANSSHIFT if you want to make it hard on yourself)
@@ -924,30 +925,7 @@ state_t states[NUMSTATES] =
 	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|11, 1, {NULL}, 0, 0, S_MSSHIELD_F1},  // S_MSSHIELD_F12
 
 	// Ring
-	{SPR_RING,  0, 1, {NULL}, 0, 0, S_RING2},  // S_RING1
-	{SPR_RING,  1, 1, {NULL}, 0, 0, S_RING3},  // S_RING2
-	{SPR_RING,  2, 1, {NULL}, 0, 0, S_RING4},  // S_RING3
-	{SPR_RING,  3, 1, {NULL}, 0, 0, S_RING5},  // S_RING4
-	{SPR_RING,  4, 1, {NULL}, 0, 0, S_RING6},  // S_RING5
-	{SPR_RING,  5, 1, {NULL}, 0, 0, S_RING7},  // S_RING6
-	{SPR_RING,  6, 1, {NULL}, 0, 0, S_RING8},  // S_RING7
-	{SPR_RING,  7, 1, {NULL}, 0, 0, S_RING9},  // S_RING8
-	{SPR_RING,  8, 1, {NULL}, 0, 0, S_RING10}, // S_RING9
-	{SPR_RING,  9, 1, {NULL}, 0, 0, S_RING11}, // S_RING10
-	{SPR_RING, 10, 1, {NULL}, 0, 0, S_RING12}, // S_RING11
-	{SPR_RING, 11, 1, {NULL}, 0, 0, S_RING13}, // S_RING12
-	{SPR_RING, 12, 1, {NULL}, 0, 0, S_RING14}, // S_RING13
-	{SPR_RING, 13, 1, {NULL}, 0, 0, S_RING15}, // S_RING14
-	{SPR_RING, 14, 1, {NULL}, 0, 0, S_RING16}, // S_RING15
-	{SPR_RING, 15, 1, {NULL}, 0, 0, S_RING17}, // S_RING16
-	{SPR_RING, 16, 1, {NULL}, 0, 0, S_RING18}, // S_RING17
-	{SPR_RING, 17, 1, {NULL}, 0, 0, S_RING19}, // S_RING18
-	{SPR_RING, 18, 1, {NULL}, 0, 0, S_RING20}, // S_RING19
-	{SPR_RING, 19, 1, {NULL}, 0, 0, S_RING21}, // S_RING20
-	{SPR_RING, 20, 1, {NULL}, 0, 0, S_RING22}, // S_RING21
-	{SPR_RING, 21, 1, {NULL}, 0, 0, S_RING23}, // S_RING22
-	{SPR_RING, 22, 1, {NULL}, 0, 0, S_RING24}, // S_RING23
-	{SPR_RING, 23, 1, {NULL}, 0, 0, S_RING1},  // S_RING24
+	{SPR_RING, FF_ANIMATE, -1, {NULL}, 23, 1, S_RING}, // S_RING
 
 	// Blue Sphere Replacement for special stages
 	{SPR_BBAL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEBALL
@@ -963,39 +941,10 @@ state_t states[NUMSTATES] =
 	{SPR_GWLR, 2, 1, {NULL}, 0, 0, S_GRAVWELLRED},    // S_GRAVWELLRED3
 
 	// Individual Team Rings (now with shield attracting action! =P)
-	{SPR_TRNG,  0, 1, {NULL}, 0, 0, S_TEAMRING2},  // S_TEAMRING1
-	{SPR_TRNG,  1, 1, {NULL}, 0, 0, S_TEAMRING3},  // S_TEAMRING2
-	{SPR_TRNG,  2, 1, {NULL}, 0, 0, S_TEAMRING4},  // S_TEAMRING3
-	{SPR_TRNG,  3, 1, {NULL}, 0, 0, S_TEAMRING5},  // S_TEAMRING4
-	{SPR_TRNG,  4, 1, {NULL}, 0, 0, S_TEAMRING6},  // S_TEAMRING5
-	{SPR_TRNG,  5, 1, {NULL}, 0, 0, S_TEAMRING7},  // S_TEAMRING6
-	{SPR_TRNG,  6, 1, {NULL}, 0, 0, S_TEAMRING8},  // S_TEAMRING7
-	{SPR_TRNG,  7, 1, {NULL}, 0, 0, S_TEAMRING9},  // S_TEAMRING8
-	{SPR_TRNG,  8, 1, {NULL}, 0, 0, S_TEAMRING10}, // S_TEAMRING9
-	{SPR_TRNG,  9, 1, {NULL}, 0, 0, S_TEAMRING11}, // S_TEAMRING10
-	{SPR_TRNG, 10, 1, {NULL}, 0, 0, S_TEAMRING12}, // S_TEAMRING11
-	{SPR_TRNG, 11, 1, {NULL}, 0, 0, S_TEAMRING13}, // S_TEAMRING12
-	{SPR_TRNG, 12, 1, {NULL}, 0, 0, S_TEAMRING14}, // S_TEAMRING13
-	{SPR_TRNG, 13, 1, {NULL}, 0, 0, S_TEAMRING15}, // S_TEAMRING14
-	{SPR_TRNG, 14, 1, {NULL}, 0, 0, S_TEAMRING16}, // S_TEAMRING15
-	{SPR_TRNG, 15, 1, {NULL}, 0, 0, S_TEAMRING17}, // S_TEAMRING16
-	{SPR_TRNG, 16, 1, {NULL}, 0, 0, S_TEAMRING18}, // S_TEAMRING17
-	{SPR_TRNG, 17, 1, {NULL}, 0, 0, S_TEAMRING19}, // S_TEAMRING18
-	{SPR_TRNG, 18, 1, {NULL}, 0, 0, S_TEAMRING20}, // S_TEAMRING19
-	{SPR_TRNG, 19, 1, {NULL}, 0, 0, S_TEAMRING21}, // S_TEAMRING20
-	{SPR_TRNG, 20, 1, {NULL}, 0, 0, S_TEAMRING22}, // S_TEAMRING21
-	{SPR_TRNG, 21, 1, {NULL}, 0, 0, S_TEAMRING23}, // S_TEAMRING22
-	{SPR_TRNG, 22, 1, {NULL}, 0, 0, S_TEAMRING24}, // S_TEAMRING23
-	{SPR_TRNG, 23, 1, {NULL}, 0, 0, S_TEAMRING1},  // S_TEAMRING24
+	{SPR_TRNG, FF_ANIMATE, -1, {NULL}, 23, 1, S_TEAMRING},  // S_TEAMRING1
 
 	// Special Stage Token
-	{SPR_EMMY, FF_FULLBRIGHT,   2, {NULL}, 0, 0, S_EMMY2}, // S_EMMY1
-	{SPR_EMMY, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_EMMY3}, // S_EMMY2
-	{SPR_EMMY, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_EMMY4}, // S_EMMY3
-	{SPR_EMMY, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_EMMY5}, // S_EMMY4
-	{SPR_EMMY, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_EMMY6}, // S_EMMY5
-	{SPR_EMMY, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_EMMY7}, // S_EMMY6
-	{SPR_EMMY, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_EMMY1}, // S_EMMY7
+	{SPR_EMMY, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 6, 2, S_EMMY}, // S_EMMY
 
 	// Special Stage Token
 	{SPR_TOKE, FF_TRANS50|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_TOKEN
@@ -1150,40 +1099,9 @@ state_t states[NUMSTATES] =
 	{SPR_USPK, 2,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2
 
 	// Starpost
-	{SPR_STPT, 0, -1, {NULL}, 0, 0, S_NULL},       // S_STARPOST1
-	{SPR_STPT, 0, 2, {NULL}, 0, 0, S_STARPOST3},   // S_STARPOST2
-	{SPR_STPT, 1, 2, {NULL}, 0, 0, S_STARPOST2},   // S_STARPOST3
-	{SPR_STPT, 2, 1, {NULL}, 0, 0, S_STARPOST5},   // S_STARPOST4
-	{SPR_STPT, 3, 1, {NULL}, 0, 0, S_STARPOST6},   // S_STARPOST5
-	{SPR_STPT, 4, 1, {NULL}, 0, 0, S_STARPOST7},   // S_STARPOST6
-	{SPR_STPT, 5, 1, {NULL}, 0, 0, S_STARPOST8},   // S_STARPOST7
-	{SPR_STPT, 6, 1, {NULL}, 0, 0, S_STARPOST9},   // S_STARPOST8
-	{SPR_STPT, 7, 1, {NULL}, 0, 0, S_STARPOST10},  // S_STARPOST9
-	{SPR_STPT, 8, 1, {NULL}, 0, 0, S_STARPOST11},  // S_STARPOST10
-	{SPR_STPT, 9, 1, {NULL}, 0, 0, S_STARPOST12},  // S_STARPOST11
-	{SPR_STPT, 10, 1, {NULL}, 0, 0, S_STARPOST13}, // S_STARPOST12
-	{SPR_STPT, 11, 1, {NULL}, 0, 0, S_STARPOST14}, // S_STARPOST13
-	{SPR_STPT, 12, 1, {NULL}, 0, 0, S_STARPOST15}, // S_STARPOST14
-	{SPR_STPT, 13, 1, {NULL}, 0, 0, S_STARPOST16}, // S_STARPOST15
-	{SPR_STPT, 14, 1, {NULL}, 0, 0, S_STARPOST17}, // S_STARPOST16
-	{SPR_STPT, 15, 1, {NULL}, 0, 0, S_STARPOST18}, // S_STARPOST17
-	{SPR_STPT, 16, 1, {NULL}, 0, 0, S_STARPOST19}, // S_STARPOST18
-	{SPR_STPT, 0, 1, {NULL}, 0, 0, S_STARPOST20},  // S_STARPOST19
-	{SPR_STPT, 2, 1, {NULL}, 0, 0, S_STARPOST21},  // S_STARPOST20
-	{SPR_STPT, 3, 1, {NULL}, 0, 0, S_STARPOST22},  // S_STARPOST21
-	{SPR_STPT, 4, 1, {NULL}, 0, 0, S_STARPOST23},  // S_STARPOST22
-	{SPR_STPT, 5, 1, {NULL}, 0, 0, S_STARPOST24},  // S_STARPOST23
-	{SPR_STPT, 6, 1, {NULL}, 0, 0, S_STARPOST25},  // S_STARPOST24
-	{SPR_STPT, 7, 1, {NULL}, 0, 0, S_STARPOST26},  // S_STARPOST25
-	{SPR_STPT, 8, 1, {NULL}, 0, 0, S_STARPOST27},  // S_STARPOST26
-	{SPR_STPT, 9, 1, {NULL}, 0, 0, S_STARPOST28},  // S_STARPOST27
-	{SPR_STPT, 10, 1, {NULL}, 0, 0, S_STARPOST29}, // S_STARPOST28
-	{SPR_STPT, 11, 1, {NULL}, 0, 0, S_STARPOST30}, // S_STARPOST29
-	{SPR_STPT, 12, 1, {NULL}, 0, 0, S_STARPOST31}, // S_STARPOST30
-	{SPR_STPT, 13, 1, {NULL}, 0, 0, S_STARPOST32}, // S_STARPOST31
-	{SPR_STPT, 14, 1, {NULL}, 0, 0, S_STARPOST33}, // S_STARPOST32
-	{SPR_STPT, 15, 1, {NULL}, 0, 0, S_STARPOST34}, // S_STARPOST33
-	{SPR_STPT, 16, 1, {NULL}, 0, 0, S_STARPOST2},  // S_STARPOST34
+	{SPR_STPT, 0           , -1, {NULL},  0, 0, S_NULL},           // S_STARPOST_IDLE
+	{SPR_STPT, FF_ANIMATE  , -1, {NULL},  1, 2, S_NULL},           // S_STARPOST_FLASH
+	{SPR_STPT, FF_ANIMATE|2, 31, {NULL}, 15, 1, S_STARPOST_FLASH}, // S_STARPOST_SPIN
 
 	// Big floating mine
 	{SPR_BMNE, 0, 5, {NULL}, 0, 0, S_BIGMINE2},    // S_BIGMINE1
@@ -1801,38 +1719,7 @@ state_t states[NUMSTATES] =
 	{SPR_PITY, FF_TRANS20|5, 1, {NULL}, 0, 0, S_PITY1 }, // S_PITY10
 
 	// Invincibility Sparkles
-	{SPR_IVSP, 0, 1, {NULL}, 0, 0, S_IVSP2},   // S_IVSP1
-	{SPR_IVSP, 1, 1, {NULL}, 0, 0, S_IVSP3},   // S_IVSP2
-	{SPR_IVSP, 2, 1, {NULL}, 0, 0, S_IVSP4},   // S_IVSP3
-	{SPR_IVSP, 3, 1, {NULL}, 0, 0, S_IVSP5},   // S_IVSP4
-	{SPR_IVSP, 4, 1, {NULL}, 0, 0, S_IVSP6},   // S_IVSP5
-	{SPR_IVSP, 5, 1, {NULL}, 0, 0, S_IVSP7},   // S_IVSP6
-	{SPR_IVSP, 6, 1, {NULL}, 0, 0, S_IVSP8},   // S_IVSP7
-	{SPR_IVSP, 7, 1, {NULL}, 0, 0, S_IVSP9},   // S_IVSP8
-	{SPR_IVSP, 8, 1, {NULL}, 0, 0, S_IVSP10},  // S_IVSP9
-	{SPR_IVSP, 9, 1, {NULL}, 0, 0, S_IVSP11},  // S_IVSP10
-	{SPR_IVSP, 10, 1, {NULL}, 0, 0, S_IVSP12}, // S_IVSP11
-	{SPR_IVSP, 11, 1, {NULL}, 0, 0, S_IVSP13}, // S_IVSP12
-	{SPR_IVSP, 12, 1, {NULL}, 0, 0, S_IVSP14}, // S_IVSP13
-	{SPR_IVSP, 13, 1, {NULL}, 0, 0, S_IVSP15}, // S_IVSP14
-	{SPR_IVSP, 14, 1, {NULL}, 0, 0, S_IVSP16}, // S_IVSP15
-	{SPR_IVSP, 15, 1, {NULL}, 0, 0, S_IVSP17}, // S_IVSP16
-	{SPR_IVSP, 16, 1, {NULL}, 0, 0, S_IVSP18}, // S_IVSP17
-	{SPR_IVSP, 17, 1, {NULL}, 0, 0, S_IVSP19}, // S_IVSP18
-	{SPR_IVSP, 18, 1, {NULL}, 0, 0, S_IVSP20}, // S_IVSP19
-	{SPR_IVSP, 19, 1, {NULL}, 0, 0, S_IVSP21}, // S_IVSP20
-	{SPR_IVSP, 20, 1, {NULL}, 0, 0, S_IVSP22}, // S_IVSP21
-	{SPR_IVSP, 21, 1, {NULL}, 0, 0, S_IVSP23}, // S_IVSP22
-	{SPR_IVSP, 22, 1, {NULL}, 0, 0, S_IVSP24}, // S_IVSP23
-	{SPR_IVSP, 23, 1, {NULL}, 0, 0, S_IVSP25}, // S_IVSP24
-	{SPR_IVSP, 24, 1, {NULL}, 0, 0, S_IVSP26}, // S_IVSP25
-	{SPR_IVSP, 25, 1, {NULL}, 0, 0, S_IVSP27}, // S_IVSP26
-	{SPR_IVSP, 26, 1, {NULL}, 0, 0, S_IVSP28}, // S_IVSP27
-	{SPR_IVSP, 27, 1, {NULL}, 0, 0, S_IVSP29}, // S_IVSP28
-	{SPR_IVSP, 28, 1, {NULL}, 0, 0, S_IVSP30}, // S_IVSP29
-	{SPR_IVSP, 29, 1, {NULL}, 0, 0, S_IVSP31}, // S_IVSP30
-	{SPR_IVSP, 30, 1, {NULL}, 0, 0, S_IVSP32}, // S_IVSP31
-	{SPR_IVSP, 31, 1, {NULL}, 0, 0, S_NULL},   // S_IVSP32
+	{SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL},   // S_IVSP
 
 	// Super Sonic Spark
 	{SPR_SSPK, 0, 2, {NULL}, 0, 0, S_SSPK2}, // S_SSPK1
@@ -2024,284 +1911,18 @@ state_t states[NUMSTATES] =
 	{SPR_RRNG, FF_FULLBRIGHT|5, 1, {A_ThrownRing}, 0, 0, S_RRNG7}, // S_RRNG6
 	{SPR_RRNG, FF_FULLBRIGHT|6, 1, {A_ThrownRing}, 0, 0, S_RRNG1}, // S_RRNG7
 
-	// Bounce Ring
-	{SPR_RNGB, 0, 1, {NULL}, 0, 0, S_BOUNCERING2},   // S_BOUNCERING1
-	{SPR_RNGB, 1, 1, {NULL}, 0, 0, S_BOUNCERING3},   // S_BOUNCERING2
-	{SPR_RNGB, 2, 1, {NULL}, 0, 0, S_BOUNCERING4},   // S_BOUNCERING3
-	{SPR_RNGB, 3, 1, {NULL}, 0, 0, S_BOUNCERING5},   // S_BOUNCERING4
-	{SPR_RNGB, 4, 1, {NULL}, 0, 0, S_BOUNCERING6},   // S_BOUNCERING5
-	{SPR_RNGB, 5, 1, {NULL}, 0, 0, S_BOUNCERING7},   // S_BOUNCERING6
-	{SPR_RNGB, 6, 1, {NULL}, 0, 0, S_BOUNCERING8},   // S_BOUNCERING7
-	{SPR_RNGB, 7, 1, {NULL}, 0, 0, S_BOUNCERING9},   // S_BOUNCERING8
-	{SPR_RNGB, 8, 1, {NULL}, 0, 0, S_BOUNCERING10},  // S_BOUNCERING9
-	{SPR_RNGB, 9, 1, {NULL}, 0, 0, S_BOUNCERING11},  // S_BOUNCERING10
-	{SPR_RNGB, 10, 1, {NULL}, 0, 0, S_BOUNCERING12}, // S_BOUNCERING11
-	{SPR_RNGB, 11, 1, {NULL}, 0, 0, S_BOUNCERING13}, // S_BOUNCERING12
-	{SPR_RNGB, 12, 1, {NULL}, 0, 0, S_BOUNCERING14}, // S_BOUNCERING13
-	{SPR_RNGB, 13, 1, {NULL}, 0, 0, S_BOUNCERING15}, // S_BOUNCERING14
-	{SPR_RNGB, 14, 1, {NULL}, 0, 0, S_BOUNCERING16}, // S_BOUNCERING15
-	{SPR_RNGB, 15, 1, {NULL}, 0, 0, S_BOUNCERING17}, // S_BOUNCERING16
-	{SPR_RNGB, 16, 1, {NULL}, 0, 0, S_BOUNCERING18}, // S_BOUNCERING17
-	{SPR_RNGB, 17, 1, {NULL}, 0, 0, S_BOUNCERING19}, // S_BOUNCERING18
-	{SPR_RNGB, 18, 1, {NULL}, 0, 0, S_BOUNCERING20}, // S_BOUNCERING19
-	{SPR_RNGB, 19, 1, {NULL}, 0, 0, S_BOUNCERING21}, // S_BOUNCERING20
-	{SPR_RNGB, 20, 1, {NULL}, 0, 0, S_BOUNCERING22}, // S_BOUNCERING21
-	{SPR_RNGB, 21, 1, {NULL}, 0, 0, S_BOUNCERING23}, // S_BOUNCERING22
-	{SPR_RNGB, 22, 1, {NULL}, 0, 0, S_BOUNCERING24}, // S_BOUNCERING23
-	{SPR_RNGB, 23, 1, {NULL}, 0, 0, S_BOUNCERING25}, // S_BOUNCERING24
-	{SPR_RNGB, 24, 1, {NULL}, 0, 0, S_BOUNCERING26}, // S_BOUNCERING25
-	{SPR_RNGB, 25, 1, {NULL}, 0, 0, S_BOUNCERING27}, // S_BOUNCERING26
-	{SPR_RNGB, 26, 1, {NULL}, 0, 0, S_BOUNCERING28}, // S_BOUNCERING27
-	{SPR_RNGB, 27, 1, {NULL}, 0, 0, S_BOUNCERING29}, // S_BOUNCERING28
-	{SPR_RNGB, 28, 1, {NULL}, 0, 0, S_BOUNCERING30}, // S_BOUNCERING29
-	{SPR_RNGB, 29, 1, {NULL}, 0, 0, S_BOUNCERING31}, // S_BOUNCERING30
-	{SPR_RNGB, 30, 1, {NULL}, 0, 0, S_BOUNCERING32}, // S_BOUNCERING31
-	{SPR_RNGB, 31, 1, {NULL}, 0, 0, S_BOUNCERING33}, // S_BOUNCERING32
-	{SPR_RNGB, 32, 1, {NULL}, 0, 0, S_BOUNCERING34}, // S_BOUNCERING33
-	{SPR_RNGB, 33, 1, {NULL}, 0, 0, S_BOUNCERING35}, // S_BOUNCERING34
-	{SPR_RNGB, 34, 1, {NULL}, 0, 0, S_BOUNCERING1},  // S_BOUNCERING35
-
-	// Rail Ring
-	{SPR_RNGR, 0, 1, {NULL}, 0, 0, S_RAILRING2},   // S_RAILRING1
-	{SPR_RNGR, 1, 1, {NULL}, 0, 0, S_RAILRING3},   // S_RAILRING2
-	{SPR_RNGR, 2, 1, {NULL}, 0, 0, S_RAILRING4},   // S_RAILRING3
-	{SPR_RNGR, 3, 1, {NULL}, 0, 0, S_RAILRING5},   // S_RAILRING4
-	{SPR_RNGR, 4, 1, {NULL}, 0, 0, S_RAILRING6},   // S_RAILRING5
-	{SPR_RNGR, 5, 1, {NULL}, 0, 0, S_RAILRING7},   // S_RAILRING6
-	{SPR_RNGR, 6, 1, {NULL}, 0, 0, S_RAILRING8},   // S_RAILRING7
-	{SPR_RNGR, 7, 1, {NULL}, 0, 0, S_RAILRING9},   // S_RAILRING8
-	{SPR_RNGR, 8, 1, {NULL}, 0, 0, S_RAILRING10},  // S_RAILRING9
-	{SPR_RNGR, 9, 1, {NULL}, 0, 0, S_RAILRING11},  // S_RAILRING10
-	{SPR_RNGR, 10, 1, {NULL}, 0, 0, S_RAILRING12}, // S_RAILRING11
-	{SPR_RNGR, 11, 1, {NULL}, 0, 0, S_RAILRING13}, // S_RAILRING12
-	{SPR_RNGR, 12, 1, {NULL}, 0, 0, S_RAILRING14}, // S_RAILRING13
-	{SPR_RNGR, 13, 1, {NULL}, 0, 0, S_RAILRING15}, // S_RAILRING14
-	{SPR_RNGR, 14, 1, {NULL}, 0, 0, S_RAILRING16}, // S_RAILRING15
-	{SPR_RNGR, 15, 1, {NULL}, 0, 0, S_RAILRING17}, // S_RAILRING16
-	{SPR_RNGR, 16, 1, {NULL}, 0, 0, S_RAILRING18}, // S_RAILRING17
-	{SPR_RNGR, 17, 1, {NULL}, 0, 0, S_RAILRING19}, // S_RAILRING18
-	{SPR_RNGR, 18, 1, {NULL}, 0, 0, S_RAILRING20}, // S_RAILRING19
-	{SPR_RNGR, 19, 1, {NULL}, 0, 0, S_RAILRING21}, // S_RAILRING20
-	{SPR_RNGR, 20, 1, {NULL}, 0, 0, S_RAILRING22}, // S_RAILRING21
-	{SPR_RNGR, 21, 1, {NULL}, 0, 0, S_RAILRING23}, // S_RAILRING22
-	{SPR_RNGR, 22, 1, {NULL}, 0, 0, S_RAILRING24}, // S_RAILRING23
-	{SPR_RNGR, 23, 1, {NULL}, 0, 0, S_RAILRING25}, // S_RAILRING24
-	{SPR_RNGR, 24, 1, {NULL}, 0, 0, S_RAILRING26}, // S_RAILRING25
-	{SPR_RNGR, 25, 1, {NULL}, 0, 0, S_RAILRING27}, // S_RAILRING26
-	{SPR_RNGR, 26, 1, {NULL}, 0, 0, S_RAILRING28}, // S_RAILRING27
-	{SPR_RNGR, 27, 1, {NULL}, 0, 0, S_RAILRING29}, // S_RAILRING28
-	{SPR_RNGR, 28, 1, {NULL}, 0, 0, S_RAILRING30}, // S_RAILRING29
-	{SPR_RNGR, 29, 1, {NULL}, 0, 0, S_RAILRING31}, // S_RAILRING30
-	{SPR_RNGR, 30, 1, {NULL}, 0, 0, S_RAILRING32}, // S_RAILRING31
-	{SPR_RNGR, 31, 1, {NULL}, 0, 0, S_RAILRING33}, // S_RAILRING32
-	{SPR_RNGR, 32, 1, {NULL}, 0, 0, S_RAILRING34}, // S_RAILRING33
-	{SPR_RNGR, 33, 1, {NULL}, 0, 0, S_RAILRING35}, // S_RAILRING34
-	{SPR_RNGR, 34, 1, {NULL}, 0, 0, S_RAILRING1},  // S_RAILRING35
-
-	// Infinity Ring
-	{SPR_RNGI, 0, 1, {NULL}, 0, 0, S_INFINITYRING2},   // S_INFINITYRING1
-	{SPR_RNGI, 1, 1, {NULL}, 0, 0, S_INFINITYRING3},   // S_INFINITYRING2
-	{SPR_RNGI, 2, 1, {NULL}, 0, 0, S_INFINITYRING4},   // S_INFINITYRING3
-	{SPR_RNGI, 3, 1, {NULL}, 0, 0, S_INFINITYRING5},   // S_INFINITYRING4
-	{SPR_RNGI, 4, 1, {NULL}, 0, 0, S_INFINITYRING6},   // S_INFINITYRING5
-	{SPR_RNGI, 5, 1, {NULL}, 0, 0, S_INFINITYRING7},   // S_INFINITYRING6
-	{SPR_RNGI, 6, 1, {NULL}, 0, 0, S_INFINITYRING8},   // S_INFINITYRING7
-	{SPR_RNGI, 7, 1, {NULL}, 0, 0, S_INFINITYRING9},   // S_INFINITYRING8
-	{SPR_RNGI, 8, 1, {NULL}, 0, 0, S_INFINITYRING10},  // S_INFINITYRING9
-	{SPR_RNGI, 9, 1, {NULL}, 0, 0, S_INFINITYRING11},  // S_INFINITYRING10
-	{SPR_RNGI, 10, 1, {NULL}, 0, 0, S_INFINITYRING12}, // S_INFINITYRING11
-	{SPR_RNGI, 11, 1, {NULL}, 0, 0, S_INFINITYRING13}, // S_INFINITYRING12
-	{SPR_RNGI, 12, 1, {NULL}, 0, 0, S_INFINITYRING14}, // S_INFINITYRING13
-	{SPR_RNGI, 13, 1, {NULL}, 0, 0, S_INFINITYRING15}, // S_INFINITYRING14
-	{SPR_RNGI, 14, 1, {NULL}, 0, 0, S_INFINITYRING16}, // S_INFINITYRING15
-	{SPR_RNGI, 15, 1, {NULL}, 0, 0, S_INFINITYRING17}, // S_INFINITYRING16
-	{SPR_RNGI, 16, 1, {NULL}, 0, 0, S_INFINITYRING18}, // S_INFINITYRING17
-	{SPR_RNGI, 17, 1, {NULL}, 0, 0, S_INFINITYRING19}, // S_INFINITYRING18
-	{SPR_RNGI, 18, 1, {NULL}, 0, 0, S_INFINITYRING20}, // S_INFINITYRING19
-	{SPR_RNGI, 19, 1, {NULL}, 0, 0, S_INFINITYRING21}, // S_INFINITYRING20
-	{SPR_RNGI, 20, 1, {NULL}, 0, 0, S_INFINITYRING22}, // S_INFINITYRING21
-	{SPR_RNGI, 21, 1, {NULL}, 0, 0, S_INFINITYRING23}, // S_INFINITYRING22
-	{SPR_RNGI, 22, 1, {NULL}, 0, 0, S_INFINITYRING24}, // S_INFINITYRING23
-	{SPR_RNGI, 23, 1, {NULL}, 0, 0, S_INFINITYRING25}, // S_INFINITYRING24
-	{SPR_RNGI, 24, 1, {NULL}, 0, 0, S_INFINITYRING26}, // S_INFINITYRING25
-	{SPR_RNGI, 25, 1, {NULL}, 0, 0, S_INFINITYRING27}, // S_INFINITYRING26
-	{SPR_RNGI, 26, 1, {NULL}, 0, 0, S_INFINITYRING28}, // S_INFINITYRING27
-	{SPR_RNGI, 27, 1, {NULL}, 0, 0, S_INFINITYRING29}, // S_INFINITYRING28
-	{SPR_RNGI, 28, 1, {NULL}, 0, 0, S_INFINITYRING30}, // S_INFINITYRING29
-	{SPR_RNGI, 29, 1, {NULL}, 0, 0, S_INFINITYRING31}, // S_INFINITYRING30
-	{SPR_RNGI, 30, 1, {NULL}, 0, 0, S_INFINITYRING32}, // S_INFINITYRING31
-	{SPR_RNGI, 31, 1, {NULL}, 0, 0, S_INFINITYRING33}, // S_INFINITYRING32
-	{SPR_RNGI, 32, 1, {NULL}, 0, 0, S_INFINITYRING34}, // S_INFINITYRING33
-	{SPR_RNGI, 33, 1, {NULL}, 0, 0, S_INFINITYRING35}, // S_INFINITYRING34
-	{SPR_RNGI, 34, 1, {NULL}, 0, 0, S_INFINITYRING1},  // S_INFINITYRING35
-
-	// Automatic Ring
-	{SPR_RNGA, 0, 1, {NULL}, 0, 0, S_AUTOMATICRING2},   // S_AUTOMATICRING1
-	{SPR_RNGA, 1, 1, {NULL}, 0, 0, S_AUTOMATICRING3},   // S_AUTOMATICRING2
-	{SPR_RNGA, 2, 1, {NULL}, 0, 0, S_AUTOMATICRING4},   // S_AUTOMATICRING3
-	{SPR_RNGA, 3, 1, {NULL}, 0, 0, S_AUTOMATICRING5},   // S_AUTOMATICRING4
-	{SPR_RNGA, 4, 1, {NULL}, 0, 0, S_AUTOMATICRING6},   // S_AUTOMATICRING5
-	{SPR_RNGA, 5, 1, {NULL}, 0, 0, S_AUTOMATICRING7},   // S_AUTOMATICRING6
-	{SPR_RNGA, 6, 1, {NULL}, 0, 0, S_AUTOMATICRING8},   // S_AUTOMATICRING7
-	{SPR_RNGA, 7, 1, {NULL}, 0, 0, S_AUTOMATICRING9},   // S_AUTOMATICRING8
-	{SPR_RNGA, 8, 1, {NULL}, 0, 0, S_AUTOMATICRING10},  // S_AUTOMATICRING9
-	{SPR_RNGA, 9, 1, {NULL}, 0, 0, S_AUTOMATICRING11},  // S_AUTOMATICRING10
-	{SPR_RNGA, 10, 1, {NULL}, 0, 0, S_AUTOMATICRING12}, // S_AUTOMATICRING11
-	{SPR_RNGA, 11, 1, {NULL}, 0, 0, S_AUTOMATICRING13}, // S_AUTOMATICRING12
-	{SPR_RNGA, 12, 1, {NULL}, 0, 0, S_AUTOMATICRING14}, // S_AUTOMATICRING13
-	{SPR_RNGA, 13, 1, {NULL}, 0, 0, S_AUTOMATICRING15}, // S_AUTOMATICRING14
-	{SPR_RNGA, 14, 1, {NULL}, 0, 0, S_AUTOMATICRING16}, // S_AUTOMATICRING15
-	{SPR_RNGA, 15, 1, {NULL}, 0, 0, S_AUTOMATICRING17}, // S_AUTOMATICRING16
-	{SPR_RNGA, 16, 1, {NULL}, 0, 0, S_AUTOMATICRING18}, // S_AUTOMATICRING17
-	{SPR_RNGA, 17, 1, {NULL}, 0, 0, S_AUTOMATICRING19}, // S_AUTOMATICRING18
-	{SPR_RNGA, 18, 1, {NULL}, 0, 0, S_AUTOMATICRING20}, // S_AUTOMATICRING19
-	{SPR_RNGA, 19, 1, {NULL}, 0, 0, S_AUTOMATICRING21}, // S_AUTOMATICRING20
-	{SPR_RNGA, 20, 1, {NULL}, 0, 0, S_AUTOMATICRING22}, // S_AUTOMATICRING21
-	{SPR_RNGA, 21, 1, {NULL}, 0, 0, S_AUTOMATICRING23}, // S_AUTOMATICRING22
-	{SPR_RNGA, 22, 1, {NULL}, 0, 0, S_AUTOMATICRING24}, // S_AUTOMATICRING23
-	{SPR_RNGA, 23, 1, {NULL}, 0, 0, S_AUTOMATICRING25}, // S_AUTOMATICRING24
-	{SPR_RNGA, 24, 1, {NULL}, 0, 0, S_AUTOMATICRING26}, // S_AUTOMATICRING25
-	{SPR_RNGA, 25, 1, {NULL}, 0, 0, S_AUTOMATICRING27}, // S_AUTOMATICRING26
-	{SPR_RNGA, 26, 1, {NULL}, 0, 0, S_AUTOMATICRING28}, // S_AUTOMATICRING27
-	{SPR_RNGA, 27, 1, {NULL}, 0, 0, S_AUTOMATICRING29}, // S_AUTOMATICRING28
-	{SPR_RNGA, 28, 1, {NULL}, 0, 0, S_AUTOMATICRING30}, // S_AUTOMATICRING29
-	{SPR_RNGA, 29, 1, {NULL}, 0, 0, S_AUTOMATICRING31}, // S_AUTOMATICRING30
-	{SPR_RNGA, 30, 1, {NULL}, 0, 0, S_AUTOMATICRING32}, // S_AUTOMATICRING31
-	{SPR_RNGA, 31, 1, {NULL}, 0, 0, S_AUTOMATICRING33}, // S_AUTOMATICRING32
-	{SPR_RNGA, 32, 1, {NULL}, 0, 0, S_AUTOMATICRING34}, // S_AUTOMATICRING33
-	{SPR_RNGA, 33, 1, {NULL}, 0, 0, S_AUTOMATICRING35}, // S_AUTOMATICRING34
-	{SPR_RNGA, 34, 1, {NULL}, 0, 0, S_AUTOMATICRING1},  // S_AUTOMATICRING35
-
-	// Explosion Ring
-	{SPR_RNGE, 0, 1, {NULL}, 0, 0, S_EXPLOSIONRING2},   // S_EXPLOSIONRING1
-	{SPR_RNGE, 1, 1, {NULL}, 0, 0, S_EXPLOSIONRING3},   // S_EXPLOSIONRING2
-	{SPR_RNGE, 2, 1, {NULL}, 0, 0, S_EXPLOSIONRING4},   // S_EXPLOSIONRING3
-	{SPR_RNGE, 3, 1, {NULL}, 0, 0, S_EXPLOSIONRING5},   // S_EXPLOSIONRING4
-	{SPR_RNGE, 4, 1, {NULL}, 0, 0, S_EXPLOSIONRING6},   // S_EXPLOSIONRING5
-	{SPR_RNGE, 5, 1, {NULL}, 0, 0, S_EXPLOSIONRING7},   // S_EXPLOSIONRING6
-	{SPR_RNGE, 6, 1, {NULL}, 0, 0, S_EXPLOSIONRING8},   // S_EXPLOSIONRING7
-	{SPR_RNGE, 7, 1, {NULL}, 0, 0, S_EXPLOSIONRING9},   // S_EXPLOSIONRING8
-	{SPR_RNGE, 8, 1, {NULL}, 0, 0, S_EXPLOSIONRING10},  // S_EXPLOSIONRING9
-	{SPR_RNGE, 9, 1, {NULL}, 0, 0, S_EXPLOSIONRING11},  // S_EXPLOSIONRING10
-	{SPR_RNGE, 10, 1, {NULL}, 0, 0, S_EXPLOSIONRING12}, // S_EXPLOSIONRING11
-	{SPR_RNGE, 11, 1, {NULL}, 0, 0, S_EXPLOSIONRING13}, // S_EXPLOSIONRING12
-	{SPR_RNGE, 12, 1, {NULL}, 0, 0, S_EXPLOSIONRING14}, // S_EXPLOSIONRING13
-	{SPR_RNGE, 13, 1, {NULL}, 0, 0, S_EXPLOSIONRING15}, // S_EXPLOSIONRING14
-	{SPR_RNGE, 14, 1, {NULL}, 0, 0, S_EXPLOSIONRING16}, // S_EXPLOSIONRING15
-	{SPR_RNGE, 15, 1, {NULL}, 0, 0, S_EXPLOSIONRING17}, // S_EXPLOSIONRING16
-	{SPR_RNGE, 16, 1, {NULL}, 0, 0, S_EXPLOSIONRING18}, // S_EXPLOSIONRING17
-	{SPR_RNGE, 17, 1, {NULL}, 0, 0, S_EXPLOSIONRING19}, // S_EXPLOSIONRING18
-	{SPR_RNGE, 18, 1, {NULL}, 0, 0, S_EXPLOSIONRING20}, // S_EXPLOSIONRING19
-	{SPR_RNGE, 19, 1, {NULL}, 0, 0, S_EXPLOSIONRING21}, // S_EXPLOSIONRING20
-	{SPR_RNGE, 20, 1, {NULL}, 0, 0, S_EXPLOSIONRING22}, // S_EXPLOSIONRING21
-	{SPR_RNGE, 21, 1, {NULL}, 0, 0, S_EXPLOSIONRING23}, // S_EXPLOSIONRING22
-	{SPR_RNGE, 22, 1, {NULL}, 0, 0, S_EXPLOSIONRING24}, // S_EXPLOSIONRING23
-	{SPR_RNGE, 23, 1, {NULL}, 0, 0, S_EXPLOSIONRING25}, // S_EXPLOSIONRING24
-	{SPR_RNGE, 24, 1, {NULL}, 0, 0, S_EXPLOSIONRING26}, // S_EXPLOSIONRING25
-	{SPR_RNGE, 25, 1, {NULL}, 0, 0, S_EXPLOSIONRING27}, // S_EXPLOSIONRING26
-	{SPR_RNGE, 26, 1, {NULL}, 0, 0, S_EXPLOSIONRING28}, // S_EXPLOSIONRING27
-	{SPR_RNGE, 27, 1, {NULL}, 0, 0, S_EXPLOSIONRING29}, // S_EXPLOSIONRING28
-	{SPR_RNGE, 28, 1, {NULL}, 0, 0, S_EXPLOSIONRING30}, // S_EXPLOSIONRING29
-	{SPR_RNGE, 29, 1, {NULL}, 0, 0, S_EXPLOSIONRING31}, // S_EXPLOSIONRING30
-	{SPR_RNGE, 30, 1, {NULL}, 0, 0, S_EXPLOSIONRING32}, // S_EXPLOSIONRING31
-	{SPR_RNGE, 31, 1, {NULL}, 0, 0, S_EXPLOSIONRING33}, // S_EXPLOSIONRING32
-	{SPR_RNGE, 32, 1, {NULL}, 0, 0, S_EXPLOSIONRING34}, // S_EXPLOSIONRING33
-	{SPR_RNGE, 33, 1, {NULL}, 0, 0, S_EXPLOSIONRING35}, // S_EXPLOSIONRING34
-	{SPR_RNGE, 34, 1, {NULL}, 0, 0, S_EXPLOSIONRING1},  // S_EXPLOSIONRING35
-
-	// Scatter Ring
-	{SPR_RNGS, 0, 1, {NULL}, 0, 0, S_SCATTERRING2},   // S_SCATTERRING1
-	{SPR_RNGS, 1, 1, {NULL}, 0, 0, S_SCATTERRING3},   // S_SCATTERRING2
-	{SPR_RNGS, 2, 1, {NULL}, 0, 0, S_SCATTERRING4},   // S_SCATTERRING3
-	{SPR_RNGS, 3, 1, {NULL}, 0, 0, S_SCATTERRING5},   // S_SCATTERRING4
-	{SPR_RNGS, 4, 1, {NULL}, 0, 0, S_SCATTERRING6},   // S_SCATTERRING5
-	{SPR_RNGS, 5, 1, {NULL}, 0, 0, S_SCATTERRING7},   // S_SCATTERRING6
-	{SPR_RNGS, 6, 1, {NULL}, 0, 0, S_SCATTERRING8},   // S_SCATTERRING7
-	{SPR_RNGS, 7, 1, {NULL}, 0, 0, S_SCATTERRING9},   // S_SCATTERRING8
-	{SPR_RNGS, 8, 1, {NULL}, 0, 0, S_SCATTERRING10},  // S_SCATTERRING9
-	{SPR_RNGS, 9, 1, {NULL}, 0, 0, S_SCATTERRING11},  // S_SCATTERRING10
-	{SPR_RNGS, 10, 1, {NULL}, 0, 0, S_SCATTERRING12}, // S_SCATTERRING11
-	{SPR_RNGS, 11, 1, {NULL}, 0, 0, S_SCATTERRING13}, // S_SCATTERRING12
-	{SPR_RNGS, 12, 1, {NULL}, 0, 0, S_SCATTERRING14}, // S_SCATTERRING13
-	{SPR_RNGS, 13, 1, {NULL}, 0, 0, S_SCATTERRING15}, // S_SCATTERRING14
-	{SPR_RNGS, 14, 1, {NULL}, 0, 0, S_SCATTERRING16}, // S_SCATTERRING15
-	{SPR_RNGS, 15, 1, {NULL}, 0, 0, S_SCATTERRING17}, // S_SCATTERRING16
-	{SPR_RNGS, 16, 1, {NULL}, 0, 0, S_SCATTERRING18}, // S_SCATTERRING17
-	{SPR_RNGS, 17, 1, {NULL}, 0, 0, S_SCATTERRING19}, // S_SCATTERRING18
-	{SPR_RNGS, 18, 1, {NULL}, 0, 0, S_SCATTERRING20}, // S_SCATTERRING19
-	{SPR_RNGS, 19, 1, {NULL}, 0, 0, S_SCATTERRING21}, // S_SCATTERRING20
-	{SPR_RNGS, 20, 1, {NULL}, 0, 0, S_SCATTERRING22}, // S_SCATTERRING21
-	{SPR_RNGS, 21, 1, {NULL}, 0, 0, S_SCATTERRING23}, // S_SCATTERRING22
-	{SPR_RNGS, 22, 1, {NULL}, 0, 0, S_SCATTERRING24}, // S_SCATTERRING23
-	{SPR_RNGS, 23, 1, {NULL}, 0, 0, S_SCATTERRING25}, // S_SCATTERRING24
-	{SPR_RNGS, 24, 1, {NULL}, 0, 0, S_SCATTERRING26}, // S_SCATTERRING25
-	{SPR_RNGS, 25, 1, {NULL}, 0, 0, S_SCATTERRING27}, // S_SCATTERRING26
-	{SPR_RNGS, 26, 1, {NULL}, 0, 0, S_SCATTERRING28}, // S_SCATTERRING27
-	{SPR_RNGS, 27, 1, {NULL}, 0, 0, S_SCATTERRING29}, // S_SCATTERRING28
-	{SPR_RNGS, 28, 1, {NULL}, 0, 0, S_SCATTERRING30}, // S_SCATTERRING29
-	{SPR_RNGS, 29, 1, {NULL}, 0, 0, S_SCATTERRING31}, // S_SCATTERRING30
-	{SPR_RNGS, 30, 1, {NULL}, 0, 0, S_SCATTERRING32}, // S_SCATTERRING31
-	{SPR_RNGS, 31, 1, {NULL}, 0, 0, S_SCATTERRING33}, // S_SCATTERRING32
-	{SPR_RNGS, 32, 1, {NULL}, 0, 0, S_SCATTERRING34}, // S_SCATTERRING33
-	{SPR_RNGS, 33, 1, {NULL}, 0, 0, S_SCATTERRING35}, // S_SCATTERRING34
-	{SPR_RNGS, 34, 1, {NULL}, 0, 0, S_SCATTERRING1},  // S_SCATTERRING35
-
-	// Grenade Ring
-	{SPR_RNGG, 0, 1, {NULL}, 0, 0, S_GRENADERING2},   // S_GRENADERING1
-	{SPR_RNGG, 1, 1, {NULL}, 0, 0, S_GRENADERING3},   // S_GRENADERING2
-	{SPR_RNGG, 2, 1, {NULL}, 0, 0, S_GRENADERING4},   // S_GRENADERING3
-	{SPR_RNGG, 3, 1, {NULL}, 0, 0, S_GRENADERING5},   // S_GRENADERING4
-	{SPR_RNGG, 4, 1, {NULL}, 0, 0, S_GRENADERING6},   // S_GRENADERING5
-	{SPR_RNGG, 5, 1, {NULL}, 0, 0, S_GRENADERING7},   // S_GRENADERING6
-	{SPR_RNGG, 6, 1, {NULL}, 0, 0, S_GRENADERING8},   // S_GRENADERING7
-	{SPR_RNGG, 7, 1, {NULL}, 0, 0, S_GRENADERING9},   // S_GRENADERING8
-	{SPR_RNGG, 8, 1, {NULL}, 0, 0, S_GRENADERING10},  // S_GRENADERING9
-	{SPR_RNGG, 9, 1, {NULL}, 0, 0, S_GRENADERING11},  // S_GRENADERING10
-	{SPR_RNGG, 10, 1, {NULL}, 0, 0, S_GRENADERING12}, // S_GRENADERING11
-	{SPR_RNGG, 11, 1, {NULL}, 0, 0, S_GRENADERING13}, // S_GRENADERING12
-	{SPR_RNGG, 12, 1, {NULL}, 0, 0, S_GRENADERING14}, // S_GRENADERING13
-	{SPR_RNGG, 13, 1, {NULL}, 0, 0, S_GRENADERING15}, // S_GRENADERING14
-	{SPR_RNGG, 14, 1, {NULL}, 0, 0, S_GRENADERING16}, // S_GRENADERING15
-	{SPR_RNGG, 15, 1, {NULL}, 0, 0, S_GRENADERING17}, // S_GRENADERING16
-	{SPR_RNGG, 16, 1, {NULL}, 0, 0, S_GRENADERING18}, // S_GRENADERING17
-	{SPR_RNGG, 17, 1, {NULL}, 0, 0, S_GRENADERING19}, // S_GRENADERING18
-	{SPR_RNGG, 18, 1, {NULL}, 0, 0, S_GRENADERING20}, // S_GRENADERING19
-	{SPR_RNGG, 19, 1, {NULL}, 0, 0, S_GRENADERING21}, // S_GRENADERING20
-	{SPR_RNGG, 20, 1, {NULL}, 0, 0, S_GRENADERING22}, // S_GRENADERING21
-	{SPR_RNGG, 21, 1, {NULL}, 0, 0, S_GRENADERING23}, // S_GRENADERING22
-	{SPR_RNGG, 22, 1, {NULL}, 0, 0, S_GRENADERING24}, // S_GRENADERING23
-	{SPR_RNGG, 23, 1, {NULL}, 0, 0, S_GRENADERING25}, // S_GRENADERING24
-	{SPR_RNGG, 24, 1, {NULL}, 0, 0, S_GRENADERING26}, // S_GRENADERING25
-	{SPR_RNGG, 25, 1, {NULL}, 0, 0, S_GRENADERING27}, // S_GRENADERING26
-	{SPR_RNGG, 26, 1, {NULL}, 0, 0, S_GRENADERING28}, // S_GRENADERING27
-	{SPR_RNGG, 27, 1, {NULL}, 0, 0, S_GRENADERING29}, // S_GRENADERING28
-	{SPR_RNGG, 28, 1, {NULL}, 0, 0, S_GRENADERING30}, // S_GRENADERING29
-	{SPR_RNGG, 29, 1, {NULL}, 0, 0, S_GRENADERING31}, // S_GRENADERING30
-	{SPR_RNGG, 30, 1, {NULL}, 0, 0, S_GRENADERING32}, // S_GRENADERING31
-	{SPR_RNGG, 31, 1, {NULL}, 0, 0, S_GRENADERING33}, // S_GRENADERING32
-	{SPR_RNGG, 32, 1, {NULL}, 0, 0, S_GRENADERING34}, // S_GRENADERING33
-	{SPR_RNGG, 33, 1, {NULL}, 0, 0, S_GRENADERING35}, // S_GRENADERING34
-	{SPR_RNGG, 34, 1, {NULL}, 0, 0, S_GRENADERING1},  // S_GRENADERING35
+	// Weapon Ring Ammo
+	{SPR_RNGB, FF_ANIMATE, -1, {NULL}, 34, 1, S_BOUNCERINGAMMO},    // S_BOUNCERINGAMMO
+	{SPR_RNGR, FF_ANIMATE, -1, {NULL}, 34, 1, S_RAILRINGAMMO},      // S_RAILRINGAMMO
+	{SPR_RNGI, FF_ANIMATE, -1, {NULL}, 34, 1, S_INFINITYRINGAMMO},  // S_INFINITYRINGAMMO
+	{SPR_RNGA, FF_ANIMATE, -1, {NULL}, 34, 1, S_AUTOMATICRINGAMMO}, // S_AUTOMATICRINGAMMO
+	{SPR_RNGE, FF_ANIMATE, -1, {NULL}, 34, 1, S_EXPLOSIONRINGAMMO}, // S_EXPLOSIONRINGAMMO
+	{SPR_RNGS, FF_ANIMATE, -1, {NULL}, 34, 1, S_SCATTERRINGAMMO},   // S_SCATTERRINGAMMO
+	{SPR_RNGG, FF_ANIMATE, -1, {NULL}, 34, 1, S_GRENADERINGAMMO},   // S_GRENADERINGAMMO
 
 	// Bounce Ring Pickup
-	{SPR_PIKB,  0, 1, {NULL}, 0, 0, S_BOUNCEPICKUP2},  // S_BOUNCEPICKUP1
-	{SPR_PIKB,  1, 1, {NULL}, 0, 0, S_BOUNCEPICKUP3},  // S_BOUNCEPICKUP2
-	{SPR_PIKB,  2, 1, {NULL}, 0, 0, S_BOUNCEPICKUP4},  // S_BOUNCEPICKUP3
-	{SPR_PIKB,  3, 1, {NULL}, 0, 0, S_BOUNCEPICKUP5},  // S_BOUNCEPICKUP4
-	{SPR_PIKB,  4, 1, {NULL}, 0, 0, S_BOUNCEPICKUP6},  // S_BOUNCEPICKUP5
-	{SPR_PIKB,  5, 1, {NULL}, 0, 0, S_BOUNCEPICKUP7},  // S_BOUNCEPICKUP6
-	{SPR_PIKB,  6, 1, {NULL}, 0, 0, S_BOUNCEPICKUP8},  // S_BOUNCEPICKUP7
-	{SPR_PIKB,  7, 1, {NULL}, 0, 0, S_BOUNCEPICKUP9},  // S_BOUNCEPICKUP8
-	{SPR_PIKB,  8, 1, {NULL}, 0, 0, S_BOUNCEPICKUP10}, // S_BOUNCEPICKUP9
-	{SPR_PIKB,  9, 1, {NULL}, 0, 0, S_BOUNCEPICKUP11}, // S_BOUNCEPICKUP10
-	{SPR_PIKB, 10, 1, {NULL}, 0, 0, S_BOUNCEPICKUP12}, // S_BOUNCEPICKUP11
-	{SPR_PIKB, 11, 1, {NULL}, 0, 0, S_BOUNCEPICKUP13}, // S_BOUNCEPICKUP12
-	{SPR_PIKB, 12, 1, {NULL}, 0, 0, S_BOUNCEPICKUP14}, // S_BOUNCEPICKUP13
-	{SPR_PIKB, 13, 1, {NULL}, 0, 0, S_BOUNCEPICKUP15}, // S_BOUNCEPICKUP14
-	{SPR_PIKB, 14, 1, {NULL}, 0, 0, S_BOUNCEPICKUP16}, // S_BOUNCEPICKUP15
-	{SPR_PIKB, 15, 1, {NULL}, 0, 0, S_BOUNCEPICKUP1},  // S_BOUNCEPICKUP16
+	{SPR_PIKB, FF_ANIMATE, -1, {NULL}, 15, 1, S_BOUNCEPICKUP},  // S_BOUNCEPICKUP
 
-	// Bounce Ring Pickup Fade
 	{SPR_PIKB,  0, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE2}, // S_BOUNCEPICKUPFADE1
 	{SPR_PIKB,  2, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE3}, // S_BOUNCEPICKUPFADE2
 	{SPR_PIKB,  4, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE4}, // S_BOUNCEPICKUPFADE3
@@ -2312,24 +1933,8 @@ state_t states[NUMSTATES] =
 	{SPR_PIKB, 14, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE1}, // S_BOUNCEPICKUPFADE8
 
 	// Rail Ring Pickup
-	{SPR_PIKR,  0, 1, {NULL}, 0, 0, S_RAILPICKUP2},  // S_RAILPICKUP1
-	{SPR_PIKR,  1, 1, {NULL}, 0, 0, S_RAILPICKUP3},  // S_RAILPICKUP2
-	{SPR_PIKR,  2, 1, {NULL}, 0, 0, S_RAILPICKUP4},  // S_RAILPICKUP3
-	{SPR_PIKR,  3, 1, {NULL}, 0, 0, S_RAILPICKUP5},  // S_RAILPICKUP4
-	{SPR_PIKR,  4, 1, {NULL}, 0, 0, S_RAILPICKUP6},  // S_RAILPICKUP5
-	{SPR_PIKR,  5, 1, {NULL}, 0, 0, S_RAILPICKUP7},  // S_RAILPICKUP6
-	{SPR_PIKR,  6, 1, {NULL}, 0, 0, S_RAILPICKUP8},  // S_RAILPICKUP7
-	{SPR_PIKR,  7, 1, {NULL}, 0, 0, S_RAILPICKUP9},  // S_RAILPICKUP8
-	{SPR_PIKR,  8, 1, {NULL}, 0, 0, S_RAILPICKUP10}, // S_RAILPICKUP9
-	{SPR_PIKR,  9, 1, {NULL}, 0, 0, S_RAILPICKUP11}, // S_RAILPICKUP10
-	{SPR_PIKR, 10, 1, {NULL}, 0, 0, S_RAILPICKUP12}, // S_RAILPICKUP11
-	{SPR_PIKR, 11, 1, {NULL}, 0, 0, S_RAILPICKUP13}, // S_RAILPICKUP12
-	{SPR_PIKR, 12, 1, {NULL}, 0, 0, S_RAILPICKUP14}, // S_RAILPICKUP13
-	{SPR_PIKR, 13, 1, {NULL}, 0, 0, S_RAILPICKUP15}, // S_RAILPICKUP14
-	{SPR_PIKR, 14, 1, {NULL}, 0, 0, S_RAILPICKUP16}, // S_RAILPICKUP15
-	{SPR_PIKR, 15, 1, {NULL}, 0, 0, S_RAILPICKUP1},  // S_RAILPICKUP16
+	{SPR_PIKR, FF_ANIMATE, -1, {NULL}, 15, 1, S_RAILPICKUP},  // S_RAILPICKUP
 
-	// Rail Ring Pickup Fade
 	{SPR_PIKR,  0, 1, {NULL}, 0, 0, S_RAILPICKUPFADE2}, // S_RAILPICKUPFADE1
 	{SPR_PIKR,  2, 1, {NULL}, 0, 0, S_RAILPICKUPFADE3}, // S_RAILPICKUPFADE2
 	{SPR_PIKR,  4, 1, {NULL}, 0, 0, S_RAILPICKUPFADE4}, // S_RAILPICKUPFADE3
@@ -2340,22 +1945,7 @@ state_t states[NUMSTATES] =
 	{SPR_PIKR, 14, 1, {NULL}, 0, 0, S_RAILPICKUPFADE1}, // S_RAILPICKUPFADE8
 
 	// Auto Ring Pickup
-	{SPR_PIKA,  0, 1, {NULL}, 0, 0, S_AUTOPICKUP2},  // S_AUTOPICKUP1
-	{SPR_PIKA,  1, 1, {NULL}, 0, 0, S_AUTOPICKUP3},  // S_AUTOPICKUP2
-	{SPR_PIKA,  2, 1, {NULL}, 0, 0, S_AUTOPICKUP4},  // S_AUTOPICKUP3
-	{SPR_PIKA,  3, 1, {NULL}, 0, 0, S_AUTOPICKUP5},  // S_AUTOPICKUP4
-	{SPR_PIKA,  4, 1, {NULL}, 0, 0, S_AUTOPICKUP6},  // S_AUTOPICKUP5
-	{SPR_PIKA,  5, 1, {NULL}, 0, 0, S_AUTOPICKUP7},  // S_AUTOPICKUP6
-	{SPR_PIKA,  6, 1, {NULL}, 0, 0, S_AUTOPICKUP8},  // S_AUTOPICKUP7
-	{SPR_PIKA,  7, 1, {NULL}, 0, 0, S_AUTOPICKUP9},  // S_AUTOPICKUP8
-	{SPR_PIKA,  8, 1, {NULL}, 0, 0, S_AUTOPICKUP10}, // S_AUTOPICKUP9
-	{SPR_PIKA,  9, 1, {NULL}, 0, 0, S_AUTOPICKUP11}, // S_AUTOPICKUP10
-	{SPR_PIKA, 10, 1, {NULL}, 0, 0, S_AUTOPICKUP12}, // S_AUTOPICKUP11
-	{SPR_PIKA, 11, 1, {NULL}, 0, 0, S_AUTOPICKUP13}, // S_AUTOPICKUP12
-	{SPR_PIKA, 12, 1, {NULL}, 0, 0, S_AUTOPICKUP14}, // S_AUTOPICKUP13
-	{SPR_PIKA, 13, 1, {NULL}, 0, 0, S_AUTOPICKUP15}, // S_AUTOPICKUP14
-	{SPR_PIKA, 14, 1, {NULL}, 0, 0, S_AUTOPICKUP16}, // S_AUTOPICKUP15
-	{SPR_PIKA, 15, 1, {NULL}, 0, 0, S_AUTOPICKUP1},  // S_AUTOPICKUP16
+	{SPR_PIKA, FF_ANIMATE, -1, {NULL}, 15, 1, S_AUTOPICKUP},  // S_AUTOPICKUP
 
 	{SPR_PIKA,  0, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE2}, // S_AUTOPICKUPFADE1
 	{SPR_PIKA,  2, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE3}, // S_AUTOPICKUPFADE2
@@ -2367,22 +1957,7 @@ state_t states[NUMSTATES] =
 	{SPR_PIKA, 14, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE1}, // S_AUTOPICKUPFADE8
 
 	// Explode Ring Pickup
-	{SPR_PIKE,  0, 1, {NULL}, 0, 0, S_EXPLODEPICKUP2},  // S_EXPLODEPICKUP1
-	{SPR_PIKE,  1, 1, {NULL}, 0, 0, S_EXPLODEPICKUP3},  // S_EXPLODEPICKUP2
-	{SPR_PIKE,  2, 1, {NULL}, 0, 0, S_EXPLODEPICKUP4},  // S_EXPLODEPICKUP3
-	{SPR_PIKE,  3, 1, {NULL}, 0, 0, S_EXPLODEPICKUP5},  // S_EXPLODEPICKUP4
-	{SPR_PIKE,  4, 1, {NULL}, 0, 0, S_EXPLODEPICKUP6},  // S_EXPLODEPICKUP5
-	{SPR_PIKE,  5, 1, {NULL}, 0, 0, S_EXPLODEPICKUP7},  // S_EXPLODEPICKUP6
-	{SPR_PIKE,  6, 1, {NULL}, 0, 0, S_EXPLODEPICKUP8},  // S_EXPLODEPICKUP7
-	{SPR_PIKE,  7, 1, {NULL}, 0, 0, S_EXPLODEPICKUP9},  // S_EXPLODEPICKUP8
-	{SPR_PIKE,  8, 1, {NULL}, 0, 0, S_EXPLODEPICKUP10}, // S_EXPLODEPICKUP9
-	{SPR_PIKE,  9, 1, {NULL}, 0, 0, S_EXPLODEPICKUP11}, // S_EXPLODEPICKUP10
-	{SPR_PIKE, 10, 1, {NULL}, 0, 0, S_EXPLODEPICKUP12}, // S_EXPLODEPICKUP11
-	{SPR_PIKE, 11, 1, {NULL}, 0, 0, S_EXPLODEPICKUP13}, // S_EXPLODEPICKUP12
-	{SPR_PIKE, 12, 1, {NULL}, 0, 0, S_EXPLODEPICKUP14}, // S_EXPLODEPICKUP13
-	{SPR_PIKE, 13, 1, {NULL}, 0, 0, S_EXPLODEPICKUP15}, // S_EXPLODEPICKUP14
-	{SPR_PIKE, 14, 1, {NULL}, 0, 0, S_EXPLODEPICKUP16}, // S_EXPLODEPICKUP15
-	{SPR_PIKE, 15, 1, {NULL}, 0, 0, S_EXPLODEPICKUP1},  // S_EXPLODEPICKUP16
+	{SPR_PIKE, FF_ANIMATE, -1, {NULL}, 15, 1, S_EXPLODEPICKUP},  // S_EXPLODEPICKUP
 
 	{SPR_PIKE,  0, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE2}, // S_EXPLODEPICKUPFADE1
 	{SPR_PIKE,  2, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE3}, // S_EXPLODEPICKUPFADE2
@@ -2394,22 +1969,7 @@ state_t states[NUMSTATES] =
 	{SPR_PIKE, 14, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE1}, // S_EXPLODEPICKUPFADE8
 
 	// Scatter Ring Pickup
-	{SPR_PIKS,  0, 1, {NULL}, 0, 0, S_SCATTERPICKUP2},  // S_SCATTERPICKUP1
-	{SPR_PIKS,  1, 1, {NULL}, 0, 0, S_SCATTERPICKUP3},  // S_SCATTERPICKUP2
-	{SPR_PIKS,  2, 1, {NULL}, 0, 0, S_SCATTERPICKUP4},  // S_SCATTERPICKUP3
-	{SPR_PIKS,  3, 1, {NULL}, 0, 0, S_SCATTERPICKUP5},  // S_SCATTERPICKUP4
-	{SPR_PIKS,  4, 1, {NULL}, 0, 0, S_SCATTERPICKUP6},  // S_SCATTERPICKUP5
-	{SPR_PIKS,  5, 1, {NULL}, 0, 0, S_SCATTERPICKUP7},  // S_SCATTERPICKUP6
-	{SPR_PIKS,  6, 1, {NULL}, 0, 0, S_SCATTERPICKUP8},  // S_SCATTERPICKUP7
-	{SPR_PIKS,  7, 1, {NULL}, 0, 0, S_SCATTERPICKUP9},  // S_SCATTERPICKUP8
-	{SPR_PIKS,  8, 1, {NULL}, 0, 0, S_SCATTERPICKUP10}, // S_SCATTERPICKUP9
-	{SPR_PIKS,  9, 1, {NULL}, 0, 0, S_SCATTERPICKUP11}, // S_SCATTERPICKUP10
-	{SPR_PIKS, 10, 1, {NULL}, 0, 0, S_SCATTERPICKUP12}, // S_SCATTERPICKUP11
-	{SPR_PIKS, 11, 1, {NULL}, 0, 0, S_SCATTERPICKUP13}, // S_SCATTERPICKUP12
-	{SPR_PIKS, 12, 1, {NULL}, 0, 0, S_SCATTERPICKUP14}, // S_SCATTERPICKUP13
-	{SPR_PIKS, 13, 1, {NULL}, 0, 0, S_SCATTERPICKUP15}, // S_SCATTERPICKUP14
-	{SPR_PIKS, 14, 1, {NULL}, 0, 0, S_SCATTERPICKUP16}, // S_SCATTERPICKUP15
-	{SPR_PIKS, 15, 1, {NULL}, 0, 0, S_SCATTERPICKUP1},  // S_SCATTERPICKUP16
+	{SPR_PIKS,  FF_ANIMATE, -1, {NULL}, 15, 1, S_SCATTERPICKUP},  // S_SCATTERPICKUP
 
 	{SPR_PIKS,  0, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE2}, // S_SCATTERPICKUPFADE1
 	{SPR_PIKS,  2, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE3}, // S_SCATTERPICKUPFADE2
@@ -2421,22 +1981,7 @@ state_t states[NUMSTATES] =
 	{SPR_PIKS, 14, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE1}, // S_SCATTERPICKUPFADE8
 
 	// Grenade Ring Pickup
-	{SPR_PIKG,  0, 1, {NULL}, 0, 0, S_GRENADEPICKUP2},  // S_GRENADEPICKUP1
-	{SPR_PIKG,  1, 1, {NULL}, 0, 0, S_GRENADEPICKUP3},  // S_GRENADEPICKUP2
-	{SPR_PIKG,  2, 1, {NULL}, 0, 0, S_GRENADEPICKUP4},  // S_GRENADEPICKUP3
-	{SPR_PIKG,  3, 1, {NULL}, 0, 0, S_GRENADEPICKUP5},  // S_GRENADEPICKUP4
-	{SPR_PIKG,  4, 1, {NULL}, 0, 0, S_GRENADEPICKUP6},  // S_GRENADEPICKUP5
-	{SPR_PIKG,  5, 1, {NULL}, 0, 0, S_GRENADEPICKUP7},  // S_GRENADEPICKUP6
-	{SPR_PIKG,  6, 1, {NULL}, 0, 0, S_GRENADEPICKUP8},  // S_GRENADEPICKUP7
-	{SPR_PIKG,  7, 1, {NULL}, 0, 0, S_GRENADEPICKUP9},  // S_GRENADEPICKUP8
-	{SPR_PIKG,  8, 1, {NULL}, 0, 0, S_GRENADEPICKUP10}, // S_GRENADEPICKUP9
-	{SPR_PIKG,  9, 1, {NULL}, 0, 0, S_GRENADEPICKUP11}, // S_GRENADEPICKUP10
-	{SPR_PIKG, 10, 1, {NULL}, 0, 0, S_GRENADEPICKUP12}, // S_GRENADEPICKUP11
-	{SPR_PIKG, 11, 1, {NULL}, 0, 0, S_GRENADEPICKUP13}, // S_GRENADEPICKUP12
-	{SPR_PIKG, 12, 1, {NULL}, 0, 0, S_GRENADEPICKUP14}, // S_GRENADEPICKUP13
-	{SPR_PIKG, 13, 1, {NULL}, 0, 0, S_GRENADEPICKUP15}, // S_GRENADEPICKUP14
-	{SPR_PIKG, 14, 1, {NULL}, 0, 0, S_GRENADEPICKUP16}, // S_GRENADEPICKUP15
-	{SPR_PIKG, 15, 1, {NULL}, 0, 0, S_GRENADEPICKUP1},  // S_GRENADEPICKUP16
+	{SPR_PIKG,  FF_ANIMATE, -1, {NULL}, 15, 1, S_GRENADEPICKUP},  // S_GRENADEPICKUP
 
 	{SPR_PIKG,  0, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE2}, // S_GRENADEPICKUPFADE1
 	{SPR_PIKG,  2, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE3}, // S_GRENADEPICKUPFADE2
@@ -2448,58 +1993,58 @@ state_t states[NUMSTATES] =
 	{SPR_PIKG, 14, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE1}, // S_GRENADEPICKUPFADE8
 
 	// Thrown Weapon Rings
-	{SPR_RNGB, 32768, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE2}, // S_THROWNBOUNCE1
-	{SPR_RNGB, 32773, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE3}, // S_THROWNBOUNCE2
-	{SPR_RNGB, 32778, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE4}, // S_THROWNBOUNCE3
-	{SPR_RNGB, 32783, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE5}, // S_THROWNBOUNCE4
-	{SPR_RNGB, 32788, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE6}, // S_THROWNBOUNCE5
-	{SPR_RNGB, 32793, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE7}, // S_THROWNBOUNCE6
-	{SPR_RNGB, 32798, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE1}, // S_THROWNBOUNCE7
+	{SPR_RNGB, FF_FULLBRIGHT   , 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE2}, // S_THROWNBOUNCE1
+	{SPR_RNGB, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE3}, // S_THROWNBOUNCE2
+	{SPR_RNGB, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE4}, // S_THROWNBOUNCE3
+	{SPR_RNGB, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE5}, // S_THROWNBOUNCE4
+	{SPR_RNGB, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE6}, // S_THROWNBOUNCE5
+	{SPR_RNGB, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE7}, // S_THROWNBOUNCE6
+	{SPR_RNGB, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE1}, // S_THROWNBOUNCE7
 
-	{SPR_RNGI, 32768, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY2}, // S_THROWNINFINITY1
-	{SPR_RNGI, 32773, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY3}, // S_THROWNINFINITY2
-	{SPR_RNGI, 32778, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY4}, // S_THROWNINFINITY3
-	{SPR_RNGI, 32783, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY5}, // S_THROWNINFINITY4
-	{SPR_RNGI, 32788, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY6}, // S_THROWNINFINITY5
-	{SPR_RNGI, 32793, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY7}, // S_THROWNINFINITY6
-	{SPR_RNGI, 32798, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY1}, // S_THROWNINFINITY7
+	{SPR_RNGI, FF_FULLBRIGHT   , 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY2}, // S_THROWNINFINITY1
+	{SPR_RNGI, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY3}, // S_THROWNINFINITY2
+	{SPR_RNGI, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY4}, // S_THROWNINFINITY3
+	{SPR_RNGI, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY5}, // S_THROWNINFINITY4
+	{SPR_RNGI, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY6}, // S_THROWNINFINITY5
+	{SPR_RNGI, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY7}, // S_THROWNINFINITY6
+	{SPR_RNGI, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY1}, // S_THROWNINFINITY7
 
-	{SPR_TAUT, 32768, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC2}, // S_THROWNAUTOMATIC1
-	{SPR_TAUT, 32769, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC3}, // S_THROWNAUTOMATIC2
-	{SPR_TAUT, 32770, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC4}, // S_THROWNAUTOMATIC3
-	{SPR_TAUT, 32771, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC5}, // S_THROWNAUTOMATIC4
-	{SPR_TAUT, 32772, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC6}, // S_THROWNAUTOMATIC5
-	{SPR_TAUT, 32773, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC7}, // S_THROWNAUTOMATIC6
-	{SPR_TAUT, 32774, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC1}, // S_THROWNAUTOMATIC7
+	{SPR_TAUT, FF_FULLBRIGHT  , 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC2}, // S_THROWNAUTOMATIC1
+	{SPR_TAUT, FF_FULLBRIGHT|1, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC3}, // S_THROWNAUTOMATIC2
+	{SPR_TAUT, FF_FULLBRIGHT|2, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC4}, // S_THROWNAUTOMATIC3
+	{SPR_TAUT, FF_FULLBRIGHT|3, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC5}, // S_THROWNAUTOMATIC4
+	{SPR_TAUT, FF_FULLBRIGHT|4, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC6}, // S_THROWNAUTOMATIC5
+	{SPR_TAUT, FF_FULLBRIGHT|5, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC7}, // S_THROWNAUTOMATIC6
+	{SPR_TAUT, FF_FULLBRIGHT|6, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC1}, // S_THROWNAUTOMATIC7
 
-	{SPR_RNGE, 32768, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION2}, // S_THROWNEXPLOSION1
-	{SPR_RNGE, 32773, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION3}, // S_THROWNEXPLOSION2
-	{SPR_RNGE, 32778, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION4}, // S_THROWNEXPLOSION3
-	{SPR_RNGE, 32783, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION5}, // S_THROWNEXPLOSION4
-	{SPR_RNGE, 32788, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION6}, // S_THROWNEXPLOSION5
-	{SPR_RNGE, 32793, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION7}, // S_THROWNEXPLOSION6
-	{SPR_RNGE, 32798, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION1}, // S_THROWNEXPLOSION7
+	{SPR_RNGE, FF_FULLBRIGHT   , 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION2}, // S_THROWNEXPLOSION1
+	{SPR_RNGE, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION3}, // S_THROWNEXPLOSION2
+	{SPR_RNGE, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION4}, // S_THROWNEXPLOSION3
+	{SPR_RNGE, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION5}, // S_THROWNEXPLOSION4
+	{SPR_RNGE, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION6}, // S_THROWNEXPLOSION5
+	{SPR_RNGE, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION7}, // S_THROWNEXPLOSION6
+	{SPR_RNGE, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION1}, // S_THROWNEXPLOSION7
 
-	{SPR_TGRE, 32768, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE2},  // S_THROWNGRENADE1
-	{SPR_TGRE, 32769, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE3},  // S_THROWNGRENADE2
-	{SPR_TGRE, 32770, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE4},  // S_THROWNGRENADE3
-	{SPR_TGRE, 32771, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE5},  // S_THROWNGRENADE4
-	{SPR_TGRE, 32772, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE6},  // S_THROWNGRENADE5
-	{SPR_TGRE, 32773, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE7},  // S_THROWNGRENADE6
-	{SPR_TGRE, 32774, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE8},  // S_THROWNGRENADE7
-	{SPR_TGRE, 32775, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE9},  // S_THROWNGRENADE8
-	{SPR_TGRE, 32776, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE10}, // S_THROWNGRENADE9
-	{SPR_TGRE, 32777, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE11}, // S_THROWNGRENADE10
-	{SPR_TGRE, 32778, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE12}, // S_THROWNGRENADE11
-	{SPR_TGRE, 32779, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE13}, // S_THROWNGRENADE12
-	{SPR_TGRE, 32780, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE14}, // S_THROWNGRENADE13
-	{SPR_TGRE, 32781, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE15}, // S_THROWNGRENADE14
-	{SPR_TGRE, 32782, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE16}, // S_THROWNGRENADE15
-	{SPR_TGRE, 32783, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE17}, // S_THROWNGRENADE16
-	{SPR_TGRE, 32784, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE18}, // S_THROWNGRENADE17
-	{SPR_TGRE, 32785, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE1},  // S_THROWNGRENADE18
+	{SPR_TGRE, FF_FULLBRIGHT   , 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE2},  // S_THROWNGRENADE1
+	{SPR_TGRE, FF_FULLBRIGHT| 1, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE3},  // S_THROWNGRENADE2
+	{SPR_TGRE, FF_FULLBRIGHT| 2, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE4},  // S_THROWNGRENADE3
+	{SPR_TGRE, FF_FULLBRIGHT| 3, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE5},  // S_THROWNGRENADE4
+	{SPR_TGRE, FF_FULLBRIGHT| 4, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE6},  // S_THROWNGRENADE5
+	{SPR_TGRE, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE7},  // S_THROWNGRENADE6
+	{SPR_TGRE, FF_FULLBRIGHT| 6, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE8},  // S_THROWNGRENADE7
+	{SPR_TGRE, FF_FULLBRIGHT| 7, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE9},  // S_THROWNGRENADE8
+	{SPR_TGRE, FF_FULLBRIGHT| 8, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE10}, // S_THROWNGRENADE9
+	{SPR_TGRE, FF_FULLBRIGHT| 9, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE11}, // S_THROWNGRENADE10
+	{SPR_TGRE, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE12}, // S_THROWNGRENADE11
+	{SPR_TGRE, FF_FULLBRIGHT|11, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE13}, // S_THROWNGRENADE12
+	{SPR_TGRE, FF_FULLBRIGHT|12, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE14}, // S_THROWNGRENADE13
+	{SPR_TGRE, FF_FULLBRIGHT|13, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE15}, // S_THROWNGRENADE14
+	{SPR_TGRE, FF_FULLBRIGHT|14, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE16}, // S_THROWNGRENADE15
+	{SPR_TGRE, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE17}, // S_THROWNGRENADE16
+	{SPR_TGRE, FF_FULLBRIGHT|16, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE18}, // S_THROWNGRENADE17
+	{SPR_TGRE, FF_FULLBRIGHT|17, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE1},  // S_THROWNGRENADE18
 
-	{SPR_TSCR, 0, 1, {A_ThrownRing}, 0, 0, S_THROWNSCATTER}, // S_THROWNSCATTER
+	{SPR_TSCR, FF_FULLBRIGHT, 1, {A_ThrownRing}, 0, 0, S_THROWNSCATTER}, // S_THROWNSCATTER
 
 	{SPR_NULL, 0, 1, {A_RingExplode}, 0, 0, S_XPLD1}, // S_RINGEXPLODE
 
@@ -2813,15 +2358,15 @@ state_t states[NUMSTATES] =
 	{SPR_NULL, 0, 35, {NULL}, 0, 0, S_CRUMBLE2},  // S_CRUMBLE1
 	{SPR_NULL, 0, 105, {A_Scream}, 0, 0, S_NULL}, // S_CRUMBLE2
 
-	{SPR_SUPT, 0,     4, {A_Scream}, 0, 0,  S_SUPERTRANS2}, // S_SUPERTRANS1
-	{SPR_SUPT, 1,     4, {NULL}, 0, 0,  S_SUPERTRANS3}, // S_SUPERTRANS2
-	{SPR_SUPT, 32770, 4, {NULL}, 0, 0,  S_SUPERTRANS4}, // S_SUPERTRANS3
-	{SPR_SUPT, 3,     3, {NULL}, 0, 0,  S_SUPERTRANS5}, // S_SUPERTRANS4
-	{SPR_SUPT, 4,     3, {NULL}, 0, 0,  S_SUPERTRANS6}, // S_SUPERTRANS5
-	{SPR_SUPT, 5,     3, {NULL}, 0, 0,  S_SUPERTRANS7}, // S_SUPERTRANS6
-	{SPR_SUPT, 6,     3, {NULL}, 0, 0,  S_SUPERTRANS8}, // S_SUPERTRANS7
-	{SPR_SUPT, 7,     3, {NULL}, 0, 0,  S_SUPERTRANS9}, // S_SUPERTRANS8
-	{SPR_SUPT, 8,    16, {NULL}, 0, 0, S_NIGHTSDRONE1}, // S_SUPERTRANS9
+	{SPR_SUPT,               0,  4, {A_Scream}, 0, 0,  S_SUPERTRANS2}, // S_SUPERTRANS1
+	{SPR_SUPT,               1,  4, {NULL}, 0, 0,  S_SUPERTRANS3}, // S_SUPERTRANS2
+	{SPR_SUPT, FF_FULLBRIGHT|2,  4, {NULL}, 0, 0,  S_SUPERTRANS4}, // S_SUPERTRANS3
+	{SPR_SUPT,               3,  3, {NULL}, 0, 0,  S_SUPERTRANS5}, // S_SUPERTRANS4
+	{SPR_SUPT,               4,  3, {NULL}, 0, 0,  S_SUPERTRANS6}, // S_SUPERTRANS5
+	{SPR_SUPT,               5,  3, {NULL}, 0, 0,  S_SUPERTRANS7}, // S_SUPERTRANS6
+	{SPR_SUPT,               6,  3, {NULL}, 0, 0,  S_SUPERTRANS8}, // S_SUPERTRANS7
+	{SPR_SUPT,               7,  3, {NULL}, 0, 0,  S_SUPERTRANS9}, // S_SUPERTRANS8
+	{SPR_SUPT,               8, 16, {NULL}, 0, 0, S_NIGHTSDRONE1}, // S_SUPERTRANS9
 
 	// Spark
 	{SPR_SPRK, FF_TRANS40  , 1, {NULL}, 0, 0, S_SPRK2},  // S_SPRK1
@@ -2857,101 +2402,22 @@ state_t states[NUMSTATES] =
 
 	{SPR_NULL, 0, 1, {A_RockSpawn}, 0, 0, S_ROCKSPAWN}, // S_ROCKSPAWN
 
-	{SPR_ROIA, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEA2}, // S_ROCKCRUMBLEA1
-	{SPR_ROIA, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEA3}, // S_ROCKCRUMBLEA2
-	{SPR_ROIA, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEA4}, // S_ROCKCRUMBLEA3
-	{SPR_ROIA, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEA5}, // S_ROCKCRUMBLEA4
-	{SPR_ROIA, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEA1}, // S_ROCKCRUMBLEA5
-
-	{SPR_ROIB, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEB2}, // S_ROCKCRUMBLEB1
-	{SPR_ROIB, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEB3}, // S_ROCKCRUMBLEB2
-	{SPR_ROIB, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEB4}, // S_ROCKCRUMBLEB3
-	{SPR_ROIB, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEB5}, // S_ROCKCRUMBLEB4
-	{SPR_ROIB, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEB1}, // S_ROCKCRUMBLEB5
-
-	{SPR_ROIC, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEC2}, // S_ROCKCRUMBLEC1
-	{SPR_ROIC, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEC3}, // S_ROCKCRUMBLEC2
-	{SPR_ROIC, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEC4}, // S_ROCKCRUMBLEC3
-	{SPR_ROIC, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEC5}, // S_ROCKCRUMBLEC4
-	{SPR_ROIC, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEC1}, // S_ROCKCRUMBLEC5
-
-	{SPR_ROID, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLED2}, // S_ROCKCRUMBLED1
-	{SPR_ROID, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLED3}, // S_ROCKCRUMBLED2
-	{SPR_ROID, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLED4}, // S_ROCKCRUMBLED3
-	{SPR_ROID, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLED5}, // S_ROCKCRUMBLED4
-	{SPR_ROID, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLED1}, // S_ROCKCRUMBLED5
-
-	{SPR_ROIE, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEE2}, // S_ROCKCRUMBLEE1
-	{SPR_ROIE, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEE3}, // S_ROCKCRUMBLEE2
-	{SPR_ROIE, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEE4}, // S_ROCKCRUMBLEE3
-	{SPR_ROIE, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEE5}, // S_ROCKCRUMBLEE4
-	{SPR_ROIE, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEE1}, // S_ROCKCRUMBLEE5
-
-	{SPR_ROIF, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEF2}, // S_ROCKCRUMBLEF1
-	{SPR_ROIF, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEF3}, // S_ROCKCRUMBLEF2
-	{SPR_ROIF, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEF4}, // S_ROCKCRUMBLEF3
-	{SPR_ROIF, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEF5}, // S_ROCKCRUMBLEF4
-	{SPR_ROIF, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEF1}, // S_ROCKCRUMBLEF5
-
-	{SPR_ROIG, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEG2}, // S_ROCKCRUMBLEG1
-	{SPR_ROIG, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEG3}, // S_ROCKCRUMBLEG2
-	{SPR_ROIG, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEG4}, // S_ROCKCRUMBLEG3
-	{SPR_ROIG, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEG5}, // S_ROCKCRUMBLEG4
-	{SPR_ROIG, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEG1}, // S_ROCKCRUMBLEG5
-
-	{SPR_ROIH, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEH2}, // S_ROCKCRUMBLEH1
-	{SPR_ROIH, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEH3}, // S_ROCKCRUMBLEH2
-	{SPR_ROIH, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEH4}, // S_ROCKCRUMBLEH3
-	{SPR_ROIH, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEH5}, // S_ROCKCRUMBLEH4
-	{SPR_ROIH, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEH1}, // S_ROCKCRUMBLEH5
-
-	{SPR_ROII, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEI2}, // S_ROCKCRUMBLEI1
-	{SPR_ROII, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEI3}, // S_ROCKCRUMBLEI2
-	{SPR_ROII, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEI4}, // S_ROCKCRUMBLEI3
-	{SPR_ROII, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEI5}, // S_ROCKCRUMBLEI4
-	{SPR_ROII, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEI1}, // S_ROCKCRUMBLEI5
-
-	{SPR_ROIJ, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEJ2}, // S_ROCKCRUMBLEJ1
-	{SPR_ROIJ, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEJ3}, // S_ROCKCRUMBLEJ2
-	{SPR_ROIJ, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEJ4}, // S_ROCKCRUMBLEJ3
-	{SPR_ROIJ, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEJ5}, // S_ROCKCRUMBLEJ4
-	{SPR_ROIJ, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEJ1}, // S_ROCKCRUMBLEJ5
-
-	{SPR_ROIK, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEK2}, // S_ROCKCRUMBLEK1
-	{SPR_ROIK, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEK3}, // S_ROCKCRUMBLEK2
-	{SPR_ROIK, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEK4}, // S_ROCKCRUMBLEK3
-	{SPR_ROIK, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEK5}, // S_ROCKCRUMBLEK4
-	{SPR_ROIK, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEK1}, // S_ROCKCRUMBLEK5
-
-	{SPR_ROIL, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEL2}, // S_ROCKCRUMBLEL1
-	{SPR_ROIL, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEL3}, // S_ROCKCRUMBLEL2
-	{SPR_ROIL, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEL4}, // S_ROCKCRUMBLEL3
-	{SPR_ROIL, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEL5}, // S_ROCKCRUMBLEL4
-	{SPR_ROIL, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEL1}, // S_ROCKCRUMBLEL5
-
-	{SPR_ROIM, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEM2}, // S_ROCKCRUMBLEM1
-	{SPR_ROIM, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEM3}, // S_ROCKCRUMBLEM2
-	{SPR_ROIM, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEM4}, // S_ROCKCRUMBLEM3
-	{SPR_ROIM, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEM5}, // S_ROCKCRUMBLEM4
-	{SPR_ROIM, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEM1}, // S_ROCKCRUMBLEM5
-
-	{SPR_ROIN, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEN2}, // S_ROCKCRUMBLEN1
-	{SPR_ROIN, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEN3}, // S_ROCKCRUMBLEN2
-	{SPR_ROIN, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEN4}, // S_ROCKCRUMBLEN3
-	{SPR_ROIN, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEN5}, // S_ROCKCRUMBLEN4
-	{SPR_ROIN, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEN1}, // S_ROCKCRUMBLEN5
-
-	{SPR_ROIO, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEO2}, // S_ROCKCRUMBLEO1
-	{SPR_ROIO, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEO3}, // S_ROCKCRUMBLEO2
-	{SPR_ROIO, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEO4}, // S_ROCKCRUMBLEO3
-	{SPR_ROIO, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEO5}, // S_ROCKCRUMBLEO4
-	{SPR_ROIO, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEO1}, // S_ROCKCRUMBLEO5
-
-	{SPR_ROIP, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEP2}, // S_ROCKCRUMBLEP1
-	{SPR_ROIP, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEP3}, // S_ROCKCRUMBLEP2
-	{SPR_ROIP, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEP4}, // S_ROCKCRUMBLEP3
-	{SPR_ROIP, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEP5}, // S_ROCKCRUMBLEP4
-	{SPR_ROIP, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEP1}, // S_ROCKCRUMBLEP5
+	{SPR_ROIA, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEA}, // S_ROCKCRUMBLEA
+	{SPR_ROIB, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEB}, // S_ROCKCRUMBLEB
+	{SPR_ROIC, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEC}, // S_ROCKCRUMBLEC
+	{SPR_ROID, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLED}, // S_ROCKCRUMBLED
+	{SPR_ROIE, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEE}, // S_ROCKCRUMBLEE
+	{SPR_ROIF, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEF}, // S_ROCKCRUMBLEF
+	{SPR_ROIG, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEG}, // S_ROCKCRUMBLEG
+	{SPR_ROIH, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEH}, // S_ROCKCRUMBLEH
+	{SPR_ROII, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEI}, // S_ROCKCRUMBLEI
+	{SPR_ROIJ, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEJ}, // S_ROCKCRUMBLEJ
+	{SPR_ROIK, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEK}, // S_ROCKCRUMBLEK
+	{SPR_ROIL, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEL}, // S_ROCKCRUMBLEL
+	{SPR_ROIM, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEM}, // S_ROCKCRUMBLEM
+	{SPR_ROIN, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEN}, // S_ROCKCRUMBLEN
+	{SPR_ROIO, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEO}, // S_ROCKCRUMBLEO
+	{SPR_ROIP, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEP}, // S_ROCKCRUMBLEP
 
 	{SPR_SRBA, 0, 5, {A_Look}, 0, 0, S_SRB1_CRAWLA1}, // S_SRB1_CRAWLA1
 	{SPR_SRBA, 0, 3, {A_Chase}, 0, 0, S_SRB1_CRAWLA3}, // S_SRB1_CRAWLA2
@@ -5051,7 +4517,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_RING
 		300,            // doomednum
-		S_RING1,        // spawnstate
+		S_RING,         // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -5078,7 +4544,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_FLINGRING
 		-1,             // doomednum
-		S_RING1,        // spawnstate
+		S_RING,         // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -5134,7 +4600,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_REDTEAMRING
 		308,            // doomednum
-		S_TEAMRING1,    // spawnstate
+		S_TEAMRING,     // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -5161,7 +4627,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_BLUETEAMRING
 		309,            // doomednum
-		S_TEAMRING1,    // spawnstate
+		S_TEAMRING,     // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -5188,7 +4654,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_EMMY
 		312,            // doomednum
-		S_EMMY1,        // spawnstate
+		S_EMMY,         // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -5938,13 +5404,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_STARPOST
 		502,            // doomednum
-		S_STARPOST1,    // spawnstate
+		S_STARPOST_IDLE, // spawnstate
 		1,              // spawnhealth
-		S_STARPOST2,    // seestate
+		S_STARPOST_FLASH, // seestate
 		sfx_None,       // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
-		S_STARPOST4,    // painstate
+		S_STARPOST_SPIN, // painstate
 		0,              // painchance
 		sfx_strpst,     // painsound
 		S_NULL,         // meleestate
@@ -10481,7 +9947,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_IVSP
 		-1,             // doomednum
-		S_IVSP1,        // spawnstate
+		S_IVSP,         // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11463,7 +10929,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 // Ring ammo: Health = amount given
 	{           // MT_BOUNCERING
 		301,            // doomednum
-		S_BOUNCERING1,  // spawnstate
+		S_BOUNCERINGAMMO, // spawnstate
 		10,             // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11490,7 +10956,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_RAILRING
 		302,            // doomednum
-		S_RAILRING1,    // spawnstate
+		S_RAILRINGAMMO, // spawnstate
 		5,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11517,7 +10983,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_INFINITYRING
 		303,            // doomednum
-		S_INFINITYRING1,// spawnstate
+		S_INFINITYRINGAMMO,// spawnstate
 		80,             // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11544,7 +11010,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_AUTOMATICRING
 		304,            // doomednum
-		S_AUTOMATICRING1, // spawnstate
+		S_AUTOMATICRINGAMMO, // spawnstate
 		40,             // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11571,7 +11037,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_EXPLOSIONRING
 		305,            // doomednum
-		S_EXPLOSIONRING1, // spawnstate
+		S_EXPLOSIONRINGAMMO, // spawnstate
 		5,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11598,7 +11064,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_SCATTERRING
 		306,            // doomednum
-		S_SCATTERRING1, // spawnstate
+		S_SCATTERRINGAMMO, // spawnstate
 		5,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11625,7 +11091,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_GRENADERING
 		307,            // doomednum
-		S_GRENADERING1, // spawnstate
+		S_GRENADERINGAMMO, // spawnstate
 		10,             // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11653,7 +11119,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 // Ring panels: Reactiontime = amount given
 	{           // MT_BOUNCEPICKUP
 		330,            // doomednum
-		S_BOUNCEPICKUP1,// spawnstate
+		S_BOUNCEPICKUP, // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11680,7 +11146,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_RAILPICKUP
 		331,            // doomednum
-		S_RAILPICKUP1,  // spawnstate
+		S_RAILPICKUP,   // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11707,7 +11173,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_AUTOPICKUP
 		332,            // doomednum
-		S_AUTOPICKUP1,  // spawnstate
+		S_AUTOPICKUP,   // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11734,7 +11200,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_EXPLODEPICKUP
 		333,            // doomednum
-		S_EXPLODEPICKUP1,// spawnstate
+		S_EXPLODEPICKUP,// spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11761,7 +11227,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_SCATTERPICKUP
 		334,            // doomednum
-		S_SCATTERPICKUP1,// spawnstate
+		S_SCATTERPICKUP,// spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11788,7 +11254,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_GRENADEPICKUP
 		335,            // doomednum
-		S_GRENADEPICKUP1,// spawnstate
+		S_GRENADEPICKUP,// spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -12740,7 +12206,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // painstate
 		0,              // painchance
 		sfx_itemup,     // painsound
-		S_RING1,        // meleestate
+		S_RING,         // meleestate
 		S_NULL,         // missilestate
 		S_SPRK1,        // deathstate
 		S_NULL,         // xdeathstate
@@ -13383,7 +12849,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_FALLINGROCK
 		-1,             // doomednum
-		S_ROCKCRUMBLEA1,// spawnstate
+		S_ROCKCRUMBLEA, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13410,7 +12876,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE1
 		-1,             // doomednum
-		S_ROCKCRUMBLEA1,// spawnstate
+		S_ROCKCRUMBLEA, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13437,7 +12903,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE2
 		-1,             // doomednum
-		S_ROCKCRUMBLEB1, // spawnstate
+		S_ROCKCRUMBLEB, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13464,7 +12930,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE3
 		-1,             // doomednum
-		S_ROCKCRUMBLEC1,// spawnstate
+		S_ROCKCRUMBLEC, //spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13491,7 +12957,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE4
 		-1,             // doomednum
-		S_ROCKCRUMBLED1,// spawnstate
+		S_ROCKCRUMBLED, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13518,7 +12984,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE5
 		-1,             // doomednum
-		S_ROCKCRUMBLEE1,// spawnstate
+		S_ROCKCRUMBLEE, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13545,7 +13011,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE6
 		-1,             // doomednum
-		S_ROCKCRUMBLEF1,// spawnstate
+		S_ROCKCRUMBLEF, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13572,7 +13038,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE7
 		-1,             // doomednum
-		S_ROCKCRUMBLEG1,// spawnstate
+		S_ROCKCRUMBLEG, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13599,7 +13065,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE8
 		-1,             // doomednum
-		S_ROCKCRUMBLEH1,// spawnstate
+		S_ROCKCRUMBLEH, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13626,7 +13092,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE9
 		-1,             // doomednum
-		S_ROCKCRUMBLEI1,// spawnstate
+		S_ROCKCRUMBLEI, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13653,7 +13119,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE10
 		-1,             // doomednum
-		S_ROCKCRUMBLEJ1,// spawnstate
+		S_ROCKCRUMBLEJ, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13680,7 +13146,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE11
 		-1,             // doomednum
-		S_ROCKCRUMBLEK1,// spawnstate
+		S_ROCKCRUMBLEK, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13707,7 +13173,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE12
 		-1,             // doomednum
-		S_ROCKCRUMBLEL1,// spawnstate
+		S_ROCKCRUMBLEL, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13734,7 +13200,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE13
 		-1,             // doomednum
-		S_ROCKCRUMBLEM1,// spawnstate
+		S_ROCKCRUMBLEM, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13761,7 +13227,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE14
 		-1,             // doomednum
-		S_ROCKCRUMBLEN1,// spawnstate
+		S_ROCKCRUMBLEN, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13788,7 +13254,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE15
 		-1,             // doomednum
-		S_ROCKCRUMBLEO1,// spawnstate
+		S_ROCKCRUMBLEO, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13815,7 +13281,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE16
 		-1,             // doomednum
-		S_ROCKCRUMBLEP1,// spawnstate
+		S_ROCKCRUMBLEP, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
diff --git a/src/info.h b/src/info.h
index 03726260b..9596f0384 100644
--- a/src/info.h
+++ b/src/info.h
@@ -1433,30 +1433,7 @@ typedef enum state
 	S_MSSHIELD_F12,
 
 	// Ring
-	S_RING1,
-	S_RING2,
-	S_RING3,
-	S_RING4,
-	S_RING5,
-	S_RING6,
-	S_RING7,
-	S_RING8,
-	S_RING9,
-	S_RING10,
-	S_RING11,
-	S_RING12,
-	S_RING13,
-	S_RING14,
-	S_RING15,
-	S_RING16,
-	S_RING17,
-	S_RING18,
-	S_RING19,
-	S_RING20,
-	S_RING21,
-	S_RING22,
-	S_RING23,
-	S_RING24,
+	S_RING,
 
 	// Blue Sphere for special stages
 	S_BLUEBALL,
@@ -1472,39 +1449,10 @@ typedef enum state
 	S_GRAVWELLRED3,
 
 	// Individual Team Rings
-	S_TEAMRING1,
-	S_TEAMRING2,
-	S_TEAMRING3,
-	S_TEAMRING4,
-	S_TEAMRING5,
-	S_TEAMRING6,
-	S_TEAMRING7,
-	S_TEAMRING8,
-	S_TEAMRING9,
-	S_TEAMRING10,
-	S_TEAMRING11,
-	S_TEAMRING12,
-	S_TEAMRING13,
-	S_TEAMRING14,
-	S_TEAMRING15,
-	S_TEAMRING16,
-	S_TEAMRING17,
-	S_TEAMRING18,
-	S_TEAMRING19,
-	S_TEAMRING20,
-	S_TEAMRING21,
-	S_TEAMRING22,
-	S_TEAMRING23,
-	S_TEAMRING24,
+	S_TEAMRING,
 
 	// Special Stage Token
-	S_EMMY1,
-	S_EMMY2,
-	S_EMMY3,
-	S_EMMY4,
-	S_EMMY5,
-	S_EMMY6,
-	S_EMMY7,
+	S_EMMY,
 
 	// Special Stage Token
 	S_TOKEN,
@@ -1658,40 +1606,9 @@ typedef enum state
 	S_SPIKED2,
 
 	// Starpost
-	S_STARPOST1,
-	S_STARPOST2,
-	S_STARPOST3,
-	S_STARPOST4,
-	S_STARPOST5,
-	S_STARPOST6,
-	S_STARPOST7,
-	S_STARPOST8,
-	S_STARPOST9,
-	S_STARPOST10,
-	S_STARPOST11,
-	S_STARPOST12,
-	S_STARPOST13,
-	S_STARPOST14,
-	S_STARPOST15,
-	S_STARPOST16,
-	S_STARPOST17,
-	S_STARPOST18,
-	S_STARPOST19,
-	S_STARPOST20,
-	S_STARPOST21,
-	S_STARPOST22,
-	S_STARPOST23,
-	S_STARPOST24,
-	S_STARPOST25,
-	S_STARPOST26,
-	S_STARPOST27,
-	S_STARPOST28,
-	S_STARPOST29,
-	S_STARPOST30,
-	S_STARPOST31,
-	S_STARPOST32,
-	S_STARPOST33,
-	S_STARPOST34,
+	S_STARPOST_IDLE,
+	S_STARPOST_FLASH,
+	S_STARPOST_SPIN,
 
 	// Big floating mine
 	S_BIGMINE1,
@@ -2299,38 +2216,7 @@ typedef enum state
 	S_PITY10,
 
 	// Invincibility Sparkles
-	S_IVSP1,
-	S_IVSP2,
-	S_IVSP3,
-	S_IVSP4,
-	S_IVSP5,
-	S_IVSP6,
-	S_IVSP7,
-	S_IVSP8,
-	S_IVSP9,
-	S_IVSP10,
-	S_IVSP11,
-	S_IVSP12,
-	S_IVSP13,
-	S_IVSP14,
-	S_IVSP15,
-	S_IVSP16,
-	S_IVSP17,
-	S_IVSP18,
-	S_IVSP19,
-	S_IVSP20,
-	S_IVSP21,
-	S_IVSP22,
-	S_IVSP23,
-	S_IVSP24,
-	S_IVSP25,
-	S_IVSP26,
-	S_IVSP27,
-	S_IVSP28,
-	S_IVSP29,
-	S_IVSP30,
-	S_IVSP31,
-	S_IVSP32,
+	S_IVSP,
 
 	// Super Sonic Spark
 	S_SSPK1,
@@ -2517,283 +2403,17 @@ typedef enum state
 	S_RRNG6,
 	S_RRNG7,
 
-	// Bounce Ring
-	S_BOUNCERING1,
-	S_BOUNCERING2,
-	S_BOUNCERING3,
-	S_BOUNCERING4,
-	S_BOUNCERING5,
-	S_BOUNCERING6,
-	S_BOUNCERING7,
-	S_BOUNCERING8,
-	S_BOUNCERING9,
-	S_BOUNCERING10,
-	S_BOUNCERING11,
-	S_BOUNCERING12,
-	S_BOUNCERING13,
-	S_BOUNCERING14,
-	S_BOUNCERING15,
-	S_BOUNCERING16,
-	S_BOUNCERING17,
-	S_BOUNCERING18,
-	S_BOUNCERING19,
-	S_BOUNCERING20,
-	S_BOUNCERING21,
-	S_BOUNCERING22,
-	S_BOUNCERING23,
-	S_BOUNCERING24,
-	S_BOUNCERING25,
-	S_BOUNCERING26,
-	S_BOUNCERING27,
-	S_BOUNCERING28,
-	S_BOUNCERING29,
-	S_BOUNCERING30,
-	S_BOUNCERING31,
-	S_BOUNCERING32,
-	S_BOUNCERING33,
-	S_BOUNCERING34,
-	S_BOUNCERING35,
-
-	// Rail Ring
-	S_RAILRING1,
-	S_RAILRING2,
-	S_RAILRING3,
-	S_RAILRING4,
-	S_RAILRING5,
-	S_RAILRING6,
-	S_RAILRING7,
-	S_RAILRING8,
-	S_RAILRING9,
-	S_RAILRING10,
-	S_RAILRING11,
-	S_RAILRING12,
-	S_RAILRING13,
-	S_RAILRING14,
-	S_RAILRING15,
-	S_RAILRING16,
-	S_RAILRING17,
-	S_RAILRING18,
-	S_RAILRING19,
-	S_RAILRING20,
-	S_RAILRING21,
-	S_RAILRING22,
-	S_RAILRING23,
-	S_RAILRING24,
-	S_RAILRING25,
-	S_RAILRING26,
-	S_RAILRING27,
-	S_RAILRING28,
-	S_RAILRING29,
-	S_RAILRING30,
-	S_RAILRING31,
-	S_RAILRING32,
-	S_RAILRING33,
-	S_RAILRING34,
-	S_RAILRING35,
-
-	// Infinity Ring
-	S_INFINITYRING1,
-	S_INFINITYRING2,
-	S_INFINITYRING3,
-	S_INFINITYRING4,
-	S_INFINITYRING5,
-	S_INFINITYRING6,
-	S_INFINITYRING7,
-	S_INFINITYRING8,
-	S_INFINITYRING9,
-	S_INFINITYRING10,
-	S_INFINITYRING11,
-	S_INFINITYRING12,
-	S_INFINITYRING13,
-	S_INFINITYRING14,
-	S_INFINITYRING15,
-	S_INFINITYRING16,
-	S_INFINITYRING17,
-	S_INFINITYRING18,
-	S_INFINITYRING19,
-	S_INFINITYRING20,
-	S_INFINITYRING21,
-	S_INFINITYRING22,
-	S_INFINITYRING23,
-	S_INFINITYRING24,
-	S_INFINITYRING25,
-	S_INFINITYRING26,
-	S_INFINITYRING27,
-	S_INFINITYRING28,
-	S_INFINITYRING29,
-	S_INFINITYRING30,
-	S_INFINITYRING31,
-	S_INFINITYRING32,
-	S_INFINITYRING33,
-	S_INFINITYRING34,
-	S_INFINITYRING35,
-
-	// Automatic Ring
-	S_AUTOMATICRING1,
-	S_AUTOMATICRING2,
-	S_AUTOMATICRING3,
-	S_AUTOMATICRING4,
-	S_AUTOMATICRING5,
-	S_AUTOMATICRING6,
-	S_AUTOMATICRING7,
-	S_AUTOMATICRING8,
-	S_AUTOMATICRING9,
-	S_AUTOMATICRING10,
-	S_AUTOMATICRING11,
-	S_AUTOMATICRING12,
-	S_AUTOMATICRING13,
-	S_AUTOMATICRING14,
-	S_AUTOMATICRING15,
-	S_AUTOMATICRING16,
-	S_AUTOMATICRING17,
-	S_AUTOMATICRING18,
-	S_AUTOMATICRING19,
-	S_AUTOMATICRING20,
-	S_AUTOMATICRING21,
-	S_AUTOMATICRING22,
-	S_AUTOMATICRING23,
-	S_AUTOMATICRING24,
-	S_AUTOMATICRING25,
-	S_AUTOMATICRING26,
-	S_AUTOMATICRING27,
-	S_AUTOMATICRING28,
-	S_AUTOMATICRING29,
-	S_AUTOMATICRING30,
-	S_AUTOMATICRING31,
-	S_AUTOMATICRING32,
-	S_AUTOMATICRING33,
-	S_AUTOMATICRING34,
-	S_AUTOMATICRING35,
-
-	// Explosion Ring
-	S_EXPLOSIONRING1,
-	S_EXPLOSIONRING2,
-	S_EXPLOSIONRING3,
-	S_EXPLOSIONRING4,
-	S_EXPLOSIONRING5,
-	S_EXPLOSIONRING6,
-	S_EXPLOSIONRING7,
-	S_EXPLOSIONRING8,
-	S_EXPLOSIONRING9,
-	S_EXPLOSIONRING10,
-	S_EXPLOSIONRING11,
-	S_EXPLOSIONRING12,
-	S_EXPLOSIONRING13,
-	S_EXPLOSIONRING14,
-	S_EXPLOSIONRING15,
-	S_EXPLOSIONRING16,
-	S_EXPLOSIONRING17,
-	S_EXPLOSIONRING18,
-	S_EXPLOSIONRING19,
-	S_EXPLOSIONRING20,
-	S_EXPLOSIONRING21,
-	S_EXPLOSIONRING22,
-	S_EXPLOSIONRING23,
-	S_EXPLOSIONRING24,
-	S_EXPLOSIONRING25,
-	S_EXPLOSIONRING26,
-	S_EXPLOSIONRING27,
-	S_EXPLOSIONRING28,
-	S_EXPLOSIONRING29,
-	S_EXPLOSIONRING30,
-	S_EXPLOSIONRING31,
-	S_EXPLOSIONRING32,
-	S_EXPLOSIONRING33,
-	S_EXPLOSIONRING34,
-	S_EXPLOSIONRING35,
-
-	// Scatter Ring
-	S_SCATTERRING1,
-	S_SCATTERRING2,
-	S_SCATTERRING3,
-	S_SCATTERRING4,
-	S_SCATTERRING5,
-	S_SCATTERRING6,
-	S_SCATTERRING7,
-	S_SCATTERRING8,
-	S_SCATTERRING9,
-	S_SCATTERRING10,
-	S_SCATTERRING11,
-	S_SCATTERRING12,
-	S_SCATTERRING13,
-	S_SCATTERRING14,
-	S_SCATTERRING15,
-	S_SCATTERRING16,
-	S_SCATTERRING17,
-	S_SCATTERRING18,
-	S_SCATTERRING19,
-	S_SCATTERRING20,
-	S_SCATTERRING21,
-	S_SCATTERRING22,
-	S_SCATTERRING23,
-	S_SCATTERRING24,
-	S_SCATTERRING25,
-	S_SCATTERRING26,
-	S_SCATTERRING27,
-	S_SCATTERRING28,
-	S_SCATTERRING29,
-	S_SCATTERRING30,
-	S_SCATTERRING31,
-	S_SCATTERRING32,
-	S_SCATTERRING33,
-	S_SCATTERRING34,
-	S_SCATTERRING35,
-
-	// Grenade Ring
-	S_GRENADERING1,
-	S_GRENADERING2,
-	S_GRENADERING3,
-	S_GRENADERING4,
-	S_GRENADERING5,
-	S_GRENADERING6,
-	S_GRENADERING7,
-	S_GRENADERING8,
-	S_GRENADERING9,
-	S_GRENADERING10,
-	S_GRENADERING11,
-	S_GRENADERING12,
-	S_GRENADERING13,
-	S_GRENADERING14,
-	S_GRENADERING15,
-	S_GRENADERING16,
-	S_GRENADERING17,
-	S_GRENADERING18,
-	S_GRENADERING19,
-	S_GRENADERING20,
-	S_GRENADERING21,
-	S_GRENADERING22,
-	S_GRENADERING23,
-	S_GRENADERING24,
-	S_GRENADERING25,
-	S_GRENADERING26,
-	S_GRENADERING27,
-	S_GRENADERING28,
-	S_GRENADERING29,
-	S_GRENADERING30,
-	S_GRENADERING31,
-	S_GRENADERING32,
-	S_GRENADERING33,
-	S_GRENADERING34,
-	S_GRENADERING35,
+	// Weapon Ring Ammo
+	S_BOUNCERINGAMMO,
+	S_RAILRINGAMMO,
+	S_INFINITYRINGAMMO,
+	S_AUTOMATICRINGAMMO,
+	S_EXPLOSIONRINGAMMO,
+	S_SCATTERRINGAMMO,
+	S_GRENADERINGAMMO,
 
 	// Weapon pickup
-	S_BOUNCEPICKUP1,
-	S_BOUNCEPICKUP2,
-	S_BOUNCEPICKUP3,
-	S_BOUNCEPICKUP4,
-	S_BOUNCEPICKUP5,
-	S_BOUNCEPICKUP6,
-	S_BOUNCEPICKUP7,
-	S_BOUNCEPICKUP8,
-	S_BOUNCEPICKUP9,
-	S_BOUNCEPICKUP10,
-	S_BOUNCEPICKUP11,
-	S_BOUNCEPICKUP12,
-	S_BOUNCEPICKUP13,
-	S_BOUNCEPICKUP14,
-	S_BOUNCEPICKUP15,
-	S_BOUNCEPICKUP16,
-
+	S_BOUNCEPICKUP,
 	S_BOUNCEPICKUPFADE1,
 	S_BOUNCEPICKUPFADE2,
 	S_BOUNCEPICKUPFADE3,
@@ -2803,23 +2423,7 @@ typedef enum state
 	S_BOUNCEPICKUPFADE7,
 	S_BOUNCEPICKUPFADE8,
 
-	S_RAILPICKUP1,
-	S_RAILPICKUP2,
-	S_RAILPICKUP3,
-	S_RAILPICKUP4,
-	S_RAILPICKUP5,
-	S_RAILPICKUP6,
-	S_RAILPICKUP7,
-	S_RAILPICKUP8,
-	S_RAILPICKUP9,
-	S_RAILPICKUP10,
-	S_RAILPICKUP11,
-	S_RAILPICKUP12,
-	S_RAILPICKUP13,
-	S_RAILPICKUP14,
-	S_RAILPICKUP15,
-	S_RAILPICKUP16,
-
+	S_RAILPICKUP,
 	S_RAILPICKUPFADE1,
 	S_RAILPICKUPFADE2,
 	S_RAILPICKUPFADE3,
@@ -2829,23 +2433,7 @@ typedef enum state
 	S_RAILPICKUPFADE7,
 	S_RAILPICKUPFADE8,
 
-	S_AUTOPICKUP1,
-	S_AUTOPICKUP2,
-	S_AUTOPICKUP3,
-	S_AUTOPICKUP4,
-	S_AUTOPICKUP5,
-	S_AUTOPICKUP6,
-	S_AUTOPICKUP7,
-	S_AUTOPICKUP8,
-	S_AUTOPICKUP9,
-	S_AUTOPICKUP10,
-	S_AUTOPICKUP11,
-	S_AUTOPICKUP12,
-	S_AUTOPICKUP13,
-	S_AUTOPICKUP14,
-	S_AUTOPICKUP15,
-	S_AUTOPICKUP16,
-
+	S_AUTOPICKUP,
 	S_AUTOPICKUPFADE1,
 	S_AUTOPICKUPFADE2,
 	S_AUTOPICKUPFADE3,
@@ -2855,23 +2443,7 @@ typedef enum state
 	S_AUTOPICKUPFADE7,
 	S_AUTOPICKUPFADE8,
 
-	S_EXPLODEPICKUP1,
-	S_EXPLODEPICKUP2,
-	S_EXPLODEPICKUP3,
-	S_EXPLODEPICKUP4,
-	S_EXPLODEPICKUP5,
-	S_EXPLODEPICKUP6,
-	S_EXPLODEPICKUP7,
-	S_EXPLODEPICKUP8,
-	S_EXPLODEPICKUP9,
-	S_EXPLODEPICKUP10,
-	S_EXPLODEPICKUP11,
-	S_EXPLODEPICKUP12,
-	S_EXPLODEPICKUP13,
-	S_EXPLODEPICKUP14,
-	S_EXPLODEPICKUP15,
-	S_EXPLODEPICKUP16,
-
+	S_EXPLODEPICKUP,
 	S_EXPLODEPICKUPFADE1,
 	S_EXPLODEPICKUPFADE2,
 	S_EXPLODEPICKUPFADE3,
@@ -2881,23 +2453,7 @@ typedef enum state
 	S_EXPLODEPICKUPFADE7,
 	S_EXPLODEPICKUPFADE8,
 
-	S_SCATTERPICKUP1,
-	S_SCATTERPICKUP2,
-	S_SCATTERPICKUP3,
-	S_SCATTERPICKUP4,
-	S_SCATTERPICKUP5,
-	S_SCATTERPICKUP6,
-	S_SCATTERPICKUP7,
-	S_SCATTERPICKUP8,
-	S_SCATTERPICKUP9,
-	S_SCATTERPICKUP10,
-	S_SCATTERPICKUP11,
-	S_SCATTERPICKUP12,
-	S_SCATTERPICKUP13,
-	S_SCATTERPICKUP14,
-	S_SCATTERPICKUP15,
-	S_SCATTERPICKUP16,
-
+	S_SCATTERPICKUP,
 	S_SCATTERPICKUPFADE1,
 	S_SCATTERPICKUPFADE2,
 	S_SCATTERPICKUPFADE3,
@@ -2907,23 +2463,7 @@ typedef enum state
 	S_SCATTERPICKUPFADE7,
 	S_SCATTERPICKUPFADE8,
 
-	S_GRENADEPICKUP1,
-	S_GRENADEPICKUP2,
-	S_GRENADEPICKUP3,
-	S_GRENADEPICKUP4,
-	S_GRENADEPICKUP5,
-	S_GRENADEPICKUP6,
-	S_GRENADEPICKUP7,
-	S_GRENADEPICKUP8,
-	S_GRENADEPICKUP9,
-	S_GRENADEPICKUP10,
-	S_GRENADEPICKUP11,
-	S_GRENADEPICKUP12,
-	S_GRENADEPICKUP13,
-	S_GRENADEPICKUP14,
-	S_GRENADEPICKUP15,
-	S_GRENADEPICKUP16,
-
+	S_GRENADEPICKUP,
 	S_GRENADEPICKUPFADE1,
 	S_GRENADEPICKUPFADE2,
 	S_GRENADEPICKUPFADE3,
@@ -3304,101 +2844,22 @@ typedef enum state
 
 	S_ROCKSPAWN,
 
-	S_ROCKCRUMBLEA1,
-	S_ROCKCRUMBLEA2,
-	S_ROCKCRUMBLEA3,
-	S_ROCKCRUMBLEA4,
-	S_ROCKCRUMBLEA5,
-
-	S_ROCKCRUMBLEB1,
-	S_ROCKCRUMBLEB2,
-	S_ROCKCRUMBLEB3,
-	S_ROCKCRUMBLEB4,
-	S_ROCKCRUMBLEB5,
-
-	S_ROCKCRUMBLEC1,
-	S_ROCKCRUMBLEC2,
-	S_ROCKCRUMBLEC3,
-	S_ROCKCRUMBLEC4,
-	S_ROCKCRUMBLEC5,
-
-	S_ROCKCRUMBLED1,
-	S_ROCKCRUMBLED2,
-	S_ROCKCRUMBLED3,
-	S_ROCKCRUMBLED4,
-	S_ROCKCRUMBLED5,
-
-	S_ROCKCRUMBLEE1,
-	S_ROCKCRUMBLEE2,
-	S_ROCKCRUMBLEE3,
-	S_ROCKCRUMBLEE4,
-	S_ROCKCRUMBLEE5,
-
-	S_ROCKCRUMBLEF1,
-	S_ROCKCRUMBLEF2,
-	S_ROCKCRUMBLEF3,
-	S_ROCKCRUMBLEF4,
-	S_ROCKCRUMBLEF5,
-
-	S_ROCKCRUMBLEG1,
-	S_ROCKCRUMBLEG2,
-	S_ROCKCRUMBLEG3,
-	S_ROCKCRUMBLEG4,
-	S_ROCKCRUMBLEG5,
-
-	S_ROCKCRUMBLEH1,
-	S_ROCKCRUMBLEH2,
-	S_ROCKCRUMBLEH3,
-	S_ROCKCRUMBLEH4,
-	S_ROCKCRUMBLEH5,
-
-	S_ROCKCRUMBLEI1,
-	S_ROCKCRUMBLEI2,
-	S_ROCKCRUMBLEI3,
-	S_ROCKCRUMBLEI4,
-	S_ROCKCRUMBLEI5,
-
-	S_ROCKCRUMBLEJ1,
-	S_ROCKCRUMBLEJ2,
-	S_ROCKCRUMBLEJ3,
-	S_ROCKCRUMBLEJ4,
-	S_ROCKCRUMBLEJ5,
-
-	S_ROCKCRUMBLEK1,
-	S_ROCKCRUMBLEK2,
-	S_ROCKCRUMBLEK3,
-	S_ROCKCRUMBLEK4,
-	S_ROCKCRUMBLEK5,
-
-	S_ROCKCRUMBLEL1,
-	S_ROCKCRUMBLEL2,
-	S_ROCKCRUMBLEL3,
-	S_ROCKCRUMBLEL4,
-	S_ROCKCRUMBLEL5,
-
-	S_ROCKCRUMBLEM1,
-	S_ROCKCRUMBLEM2,
-	S_ROCKCRUMBLEM3,
-	S_ROCKCRUMBLEM4,
-	S_ROCKCRUMBLEM5,
-
-	S_ROCKCRUMBLEN1,
-	S_ROCKCRUMBLEN2,
-	S_ROCKCRUMBLEN3,
-	S_ROCKCRUMBLEN4,
-	S_ROCKCRUMBLEN5,
-
-	S_ROCKCRUMBLEO1,
-	S_ROCKCRUMBLEO2,
-	S_ROCKCRUMBLEO3,
-	S_ROCKCRUMBLEO4,
-	S_ROCKCRUMBLEO5,
-
-	S_ROCKCRUMBLEP1,
-	S_ROCKCRUMBLEP2,
-	S_ROCKCRUMBLEP3,
-	S_ROCKCRUMBLEP4,
-	S_ROCKCRUMBLEP5,
+	S_ROCKCRUMBLEA,
+	S_ROCKCRUMBLEB,
+	S_ROCKCRUMBLEC,
+	S_ROCKCRUMBLED,
+	S_ROCKCRUMBLEE,
+	S_ROCKCRUMBLEF,
+	S_ROCKCRUMBLEG,
+	S_ROCKCRUMBLEH,
+	S_ROCKCRUMBLEI,
+	S_ROCKCRUMBLEJ,
+	S_ROCKCRUMBLEK,
+	S_ROCKCRUMBLEL,
+	S_ROCKCRUMBLEM,
+	S_ROCKCRUMBLEN,
+	S_ROCKCRUMBLEO,
+	S_ROCKCRUMBLEP,
 
 	S_SRB1_CRAWLA1,
 	S_SRB1_CRAWLA2,
diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c
index 83e7039e4..bf4ee0b28 100644
--- a/src/lua_mobjlib.c
+++ b/src/lua_mobjlib.c
@@ -34,6 +34,7 @@ enum mobj_e {
 	mobj_angle,
 	mobj_sprite,
 	mobj_frame,
+	mobj_anim_duration,
 	mobj_touching_sectorlist,
 	mobj_subsector,
 	mobj_floorz,
@@ -92,6 +93,7 @@ static const char *const mobj_opt[] = {
 	"angle",
 	"sprite",
 	"frame",
+	"anim_duration",
 	"touching_sectorlist",
 	"subsector",
 	"floorz",
@@ -187,6 +189,9 @@ static int mobj_get(lua_State *L)
 	case mobj_frame:
 		lua_pushinteger(L, mo->frame);
 		break;
+	case mobj_anim_duration:
+		lua_pushinteger(L, mo->anim_duration);
+		break;
 	case mobj_touching_sectorlist:
 		return UNIMPLEMENTED;
 	case mobj_subsector:
@@ -406,6 +411,9 @@ static int mobj_set(lua_State *L)
 	case mobj_frame:
 		mo->frame = (UINT32)luaL_checkinteger(L, 3);
 		break;
+	case mobj_anim_duration:
+		mo->anim_duration = (UINT16)luaL_checkinteger(L, 3);
+		break;
 	case mobj_touching_sectorlist:
 		return UNIMPLEMENTED;
 	case mobj_subsector:
diff --git a/src/p_local.h b/src/p_local.h
index 97b8865d4..d035925c8 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -212,6 +212,7 @@ void P_RemoveSavegameMobj(mobj_t *th);
 boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state);
 boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
 void P_RunShields(void);
+void P_RunOverlays(void);
 void P_MobjThinker(mobj_t *mobj);
 boolean P_RailThinker(mobj_t *mobj);
 void P_PushableThinker(mobj_t *mobj);
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 25ae8815a..323e5ce95 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -79,11 +79,33 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum)
 	actioncachehead.prev = newaction;
 }
 
+//
+// P_CycleStateAnimation
+//
+FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj)
+{
+	// var2 determines delay between animation frames
+	if (!(mobj->frame & FF_ANIMATE) || --mobj->anim_duration != 0)
+		return;
+	mobj->anim_duration = (UINT16)mobj->state->var2;
+
+	// compare the current sprite frame to the one we started from
+	// if more than var1 away from it, swap back to the original
+	// else just advance by one
+	if ((mobj->frame & FF_FRAMEMASK) - (mobj->state->frame & FF_FRAMEMASK) < (UINT32)mobj->state->var1)
+		++mobj->frame;
+	else
+		mobj->frame = (mobj->state->frame & FF_FRAMEMASK) | (mobj->frame & ~FF_FRAMEMASK);
+}
+
 //
 // P_CycleMobjState
 //
 static void P_CycleMobjState(mobj_t *mobj)
 {
+	// state animations
+	P_CycleStateAnimation(mobj);
+
 	// cycle through states,
 	// calling action functions at transitions
 	if (mobj->tics != -1)
@@ -102,6 +124,9 @@ static void P_CycleMobjState(mobj_t *mobj)
 //
 static void P_CyclePlayerMobjState(mobj_t *mobj)
 {
+	// state animations
+	P_CycleStateAnimation(mobj);
+
 	// cycle through states,
 	// calling action functions at transitions
 	if (mobj->tics != -1)
@@ -279,6 +304,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 
 		mobj->sprite = st->sprite;
 		mobj->frame = st->frame;
+		mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
 
 		// Modified handling.
 		// Call action functions when the state is set
@@ -346,6 +372,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
 		mobj->tics = st->tics;
 		mobj->sprite = st->sprite;
 		mobj->frame = st->frame;
+		mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
 
 		// Modified handling.
 		// Call action functions when the state is set
@@ -399,6 +426,8 @@ boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state)
 	mobj->tics = st->tics;
 	mobj->sprite = st->sprite;
 	mobj->frame = st->frame;
+	mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
+
 	return true;
 }
 
@@ -416,6 +445,8 @@ static boolean P_SetPrecipMobjState(precipmobj_t *mobj, statenum_t state)
 	mobj->tics = st->tics;
 	mobj->sprite = st->sprite;
 	mobj->frame = st->frame;
+	mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
+
 	return true;
 }
 
@@ -3716,6 +3747,8 @@ void P_NullPrecipThinker(precipmobj_t *mobj)
 
 void P_SnowThinker(precipmobj_t *mobj)
 {
+	P_CycleStateAnimation((mobj_t *)mobj);
+
 	// adjust height
 	if ((mobj->z += mobj->momz) <= mobj->floorz)
 		mobj->z = mobj->ceilingz;
@@ -3723,6 +3756,8 @@ void P_SnowThinker(precipmobj_t *mobj)
 
 void P_RainThinker(precipmobj_t *mobj)
 {
+	P_CycleStateAnimation((mobj_t *)mobj);
+
 	if (mobj->state != &states[S_RAIN1])
 	{
 		// cycle through states,
@@ -5833,8 +5868,6 @@ INT32 numshields = 0;
 void P_RunShields(void)
 {
 	INT32 i;
-	mobj_t *mo, *next;
-	fixed_t destx,desty,zoffs;
 
 	// run shields
 	for (i = 0; i < numshields; i++)
@@ -5843,60 +5876,6 @@ void P_RunShields(void)
 		P_SetTarget(&shields[i], NULL);
 	}
 	numshields = 0;
-
-	// run overlays
-	next = NULL;
-	for (mo = overlaycap; mo; mo = next)
-	{
-		I_Assert(!P_MobjWasRemoved(mo));
-
-		// grab next in chain, then unset the chain target
-		next = mo->hnext;
-		P_SetTarget(&mo->hnext, NULL);
-
-		if (!mo->target)
-			continue;
-		if (!splitscreen /*&& rendermode != render_soft*/)
-		{
-			angle_t viewingangle;
-
-			if (players[displayplayer].awayviewtics)
-				viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y);
-			else if (!camera.chase && players[displayplayer].mo)
-				viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y);
-			else
-				viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, camera.x, camera.y);
-
-			if (mo->state->var1)
-				viewingangle += ANGLE_180;
-			destx = mo->target->x + P_ReturnThrustX(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
-			desty = mo->target->y + P_ReturnThrustY(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
-		}
-		else
-		{
-			destx = mo->target->x;
-			desty = mo->target->y;
-		}
-
-		mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
-		mo->scale = mo->destscale = mo->target->scale;
-		zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);
-		mo->angle = mo->target->angle;
-
-		P_UnsetThingPosition(mo);
-		mo->x = destx;
-		mo->y = desty;
-		if (mo->eflags & MFE_VERTICALFLIP)
-			mo->z = (mo->target->z + mo->target->height - mo->height) - zoffs;
-		else
-			mo->z = mo->target->z + zoffs;
-		if (mo->state->var1)
-			P_SetUnderlayPosition(mo);
-		else
-			P_SetThingPosition(mo);
-		P_CheckPosition(mo, mo->x, mo->y);
-	}
-	P_SetTarget(&overlaycap, NULL);
 }
 
 static boolean P_AddShield(mobj_t *thing)
@@ -5933,6 +5912,71 @@ static boolean P_AddShield(mobj_t *thing)
 	return true;
 }
 
+void P_RunOverlays(void)
+{
+	// run overlays
+	mobj_t *mo, *next = NULL;
+	fixed_t destx,desty,zoffs;
+
+	for (mo = overlaycap; mo; mo = next)
+	{
+		I_Assert(!P_MobjWasRemoved(mo));
+
+		// grab next in chain, then unset the chain target
+		next = mo->hnext;
+		P_SetTarget(&mo->hnext, NULL);
+
+		if (!mo->target)
+			continue;
+		if (!splitscreen /*&& rendermode != render_soft*/)
+		{
+			angle_t viewingangle;
+
+			if (players[displayplayer].awayviewtics)
+				viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y);
+			else if (!camera.chase && players[displayplayer].mo)
+				viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y);
+			else
+				viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, camera.x, camera.y);
+
+			if (!(mo->state->frame & FF_ANIMATE) && mo->state->var1)
+				viewingangle += ANGLE_180;
+			destx = mo->target->x + P_ReturnThrustX(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
+			desty = mo->target->y + P_ReturnThrustY(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
+		}
+		else
+		{
+			destx = mo->target->x;
+			desty = mo->target->y;
+		}
+
+		mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
+		mo->scale = mo->destscale = mo->target->scale;
+		mo->angle = mo->target->angle;
+
+		if (!(mo->state->frame & FF_ANIMATE))
+			zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);
+		// if you're using FF_ANIMATE on an overlay,
+		// then you're on your own.
+		else
+			zoffs = 0;
+
+		P_UnsetThingPosition(mo);
+		mo->x = destx;
+		mo->y = desty;
+		if (mo->eflags & MFE_VERTICALFLIP)
+			mo->z = (mo->target->z + mo->target->height - mo->height) - zoffs;
+		else
+			mo->z = mo->target->z + zoffs;
+		if (mo->state->var1)
+			P_SetUnderlayPosition(mo);
+		else
+			P_SetThingPosition(mo);
+		P_CheckPosition(mo, mo->x, mo->y);
+	}
+	P_SetTarget(&overlaycap, NULL);
+}
+
 // Called only when MT_OVERLAY thinks.
 static void P_AddOverlay(mobj_t *thing)
 {
@@ -7502,6 +7546,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 	mobj->tics = st->tics;
 	mobj->sprite = st->sprite;
 	mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits..
+	mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
+
 	mobj->friction = ORIG_FRICTION;
 
 	mobj->movefactor = ORIG_FRICTION_FACTOR;
@@ -7727,6 +7773,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
 	mobj->tics = st->tics;
 	mobj->sprite = st->sprite;
 	mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits..
+	mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
 
 	// set subsector and/or block links
 	P_SetPrecipitationThingPosition(mobj);
diff --git a/src/p_mobj.h b/src/p_mobj.h
index 224a8ca5b..6198f5bec 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -270,6 +270,7 @@ typedef struct mobj_s
 	angle_t angle;  // orientation
 	spritenum_t sprite; // used to find patch_t and flip value
 	UINT32 frame; // frame number, plus bits see p_pspr.h
+	UINT16 anim_duration; // for FF_ANIMATE states
 
 	struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
 
@@ -383,7 +384,8 @@ typedef struct precipmobj_s
 	// More drawing info: to determine current sprite.
 	angle_t angle;  // orientation
 	spritenum_t sprite; // used to find patch_t and flip value
-	INT32 frame; // frame number, plus bits see p_pspr.h
+	UINT32 frame; // frame number, plus bits see p_pspr.h
+	UINT16 anim_duration; // for FF_ANIMATE states
 
 	struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
 
diff --git a/src/p_pspr.h b/src/p_pspr.h
index e0b57675c..53ad30abd 100644
--- a/src/p_pspr.h
+++ b/src/p_pspr.h
@@ -36,9 +36,11 @@
 #endif
 
 /// \brief Frame flags: only the frame number
-#define FF_FRAMEMASK 0x7fff
+#define FF_FRAMEMASK 0x3fff
+/// \brief Frame flags: Simple stateless animation
+#define FF_ANIMATE 0x4000
 /// \brief Frame flags: frame always appears full bright
-#define FF_FULLBRIGHT 0x8000  //
+#define FF_FULLBRIGHT 0x8000
 /// \brief Frame flags: 0 = no trans(opaque), 1-15 = transl. table
 #define FF_TRANSMASK 0xf0000
 /// \brief shift for FF_TRANSMASK
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 61f51e497..565ff0bd0 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1058,6 +1058,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		diff |= MD_SPRITE;
 	if (mobj->frame != mobj->state->frame)
 		diff |= MD_FRAME;
+	if (mobj->anim_duration != (UINT16)mobj->state->var2)
+		diff |= MD_FRAME;
 	if (mobj->eflags)
 		diff |= MD_EFLAGS;
 	if (mobj->player)
@@ -1178,7 +1180,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 	if (diff & MD_SPRITE)
 		WRITEUINT16(save_p, mobj->sprite);
 	if (diff & MD_FRAME)
+	{
 		WRITEUINT32(save_p, mobj->frame);
+		WRITEUINT16(save_p, mobj->anim_duration);
+	}
 	if (diff & MD_EFLAGS)
 		WRITEUINT16(save_p, mobj->eflags);
 	if (diff & MD_PLAYER)
@@ -2004,9 +2009,15 @@ static void LoadMobjThinker(actionf_p1 thinker)
 	else
 		mobj->sprite = mobj->state->sprite;
 	if (diff & MD_FRAME)
+	{
 		mobj->frame = READUINT32(save_p);
+		mobj->anim_duration = READUINT16(save_p);
+	}
 	else
+	{
 		mobj->frame = mobj->state->frame;
+		mobj->anim_duration = (UINT16)mobj->state->var2;
+	}
 	if (diff & MD_EFLAGS)
 		mobj->eflags = READUINT16(save_p);
 	if (diff & MD_PLAYER)
diff --git a/src/p_tick.c b/src/p_tick.c
index 2973505f3..c72ab5b67 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -631,6 +631,7 @@ void P_Ticker(boolean run)
 
 	// Run shield positioning
 	P_RunShields();
+	P_RunOverlays();
 
 	P_UpdateSpecials();
 	P_RespawnSpecials();
@@ -742,6 +743,7 @@ void P_PreTicker(INT32 frames)
 
 		// Run shield positioning
 		P_RunShields();
+		P_RunOverlays();
 
 		P_UpdateSpecials();
 		P_RespawnSpecials();

From 58e685353a3575e71869f691de6a2e793cb1ec1e Mon Sep 17 00:00:00 2001
From: Inuyasha <MattWCSTRFAN@gmail.com>
Date: Tue, 5 Jan 2016 05:03:00 -0800
Subject: [PATCH 2/7] Attempt 2 at special stage fades. More basic in
 execution.

---
 src/dehacked.c | 12 ++++++++++--
 src/f_finale.h |  3 ++-
 src/f_wipe.c   |  1 +
 src/p_setup.c  | 51 +++++++++++++++++++++++++++++++++++++-------------
 4 files changed, 51 insertions(+), 16 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index 44ef998ac..f7ec8ed51 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -3187,6 +3187,12 @@ static void readwipes(MYFILE *f)
 				else if (fastcmp(pword, "FINAL"))
 					wipeoffset = wipe_gameend_final;
 			}
+			else if (fastncmp(word, "SPECLEVEL_", 10))
+			{
+				pword = word + 10;
+				if (fastcmp(pword, "TOWHITE"))
+					wipeoffset = wipe_speclevel_towhite;
+			}
 
 			if (wipeoffset < 0)
 			{
@@ -3194,9 +3200,11 @@ static void readwipes(MYFILE *f)
 				continue;
 			}
 
-			if (value == UINT8_MAX // Cannot disable non-toblack wipes (or the level toblack wipe)
-			 && (wipeoffset <= wipe_level_toblack || wipeoffset >= wipe_level_final))
+			if (value == UINT8_MAX
+			 && (wipeoffset <= wipe_level_toblack || wipeoffset >= wipe_speclevel_towhite))
 			{
+				 // Cannot disable non-toblack wipes
+				 // (or the level toblack wipe, or the special towhite wipe)
 				deh_warning("Wipes: can't disable wipe of type '%s'", word);
 				continue;
 			}
diff --git a/src/f_finale.h b/src/f_finale.h
index 97a26f4c4..e263a3797 100644
--- a/src/f_finale.h
+++ b/src/f_finale.h
@@ -90,6 +90,7 @@ enum
 	// custom intermissions
 	wipe_specinter_toblack,
 	wipe_multinter_toblack,
+	wipe_speclevel_towhite,
 
 	wipe_level_final,
 	wipe_intermission_final,
@@ -108,7 +109,7 @@ enum
 
 	NUMWIPEDEFS
 };
-#define WIPEFINALSHIFT 12
+#define WIPEFINALSHIFT 13
 extern UINT8 wipedefs[NUMWIPEDEFS];
 
 #endif
diff --git a/src/f_wipe.c b/src/f_wipe.c
index 6f14e577a..e0578949e 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -58,6 +58,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
 
 	0,  // wipe_specinter_toblack
 	0,  // wipe_multinter_toblack
+	0,  // wipe_speclevel_towhite
 
 	0,  // wipe_level_final
 	0,  // wipe_intermission_final
diff --git a/src/p_setup.c b/src/p_setup.c
index 3491669c7..dc0e4ffd5 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -2369,7 +2369,7 @@ boolean P_SetupLevel(boolean skipprecip)
 	// use gamemap to get map number.
 	// 99% of the things already did, so.
 	// Map header should always be in place at this point
-	INT32 i, loadprecip = 1;
+	INT32 i, loadprecip = 1, ranspecialwipe = 0;
 	INT32 loademblems = 1;
 	INT32 fromnetsave = 0;
 	boolean loadedbm = false;
@@ -2442,6 +2442,28 @@ boolean P_SetupLevel(boolean skipprecip)
 	// will be set by player think.
 	players[consoleplayer].viewz = 1;
 
+	// Special stage fade to white
+	// This is handled BEFORE sounds are stopped.
+	if (rendermode != render_none && G_IsSpecialStage(gamemap))
+	{
+		tic_t starttime = I_GetTime();
+		tic_t endtime = starttime + (3*TICRATE)/2;
+
+		S_StartSound(NULL, sfx_s3kaf);
+
+		F_WipeStartScreen();
+		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0);
+
+		F_WipeEndScreen();
+		F_RunWipe(wipedefs[wipe_speclevel_towhite], false);
+
+		// Hold on white for extra effect.
+		while (I_GetTime() < endtime)
+			I_Sleep();
+
+		ranspecialwipe = 1;
+	}
+
 	// Make sure all sounds are stopped before Z_FreeTags.
 	S_StopSounds();
 	S_ClearSfx();
@@ -2451,25 +2473,28 @@ boolean P_SetupLevel(boolean skipprecip)
 	S_Start();
 
 	// Let's fade to black here
-	if (rendermode != render_none)
+	// But only if we didn't do the special stage wipe
+	if (rendermode != render_none && !ranspecialwipe)
 	{
 		F_WipeStartScreen();
 		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
 
 		F_WipeEndScreen();
 		F_RunWipe(wipedefs[wipe_level_toblack], false);
+	}
 
+	// Print "SPEEDING OFF TO [ZONE] [ACT 1]..."
+	if (rendermode != render_none)
+	{
 		// Don't include these in the fade!
-		{
-			char tx[64];
-			V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to..."));
-			snprintf(tx, 63, "%s%s%s",
-				mapheaderinfo[gamemap-1]->lvlttl,
-				(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE",
-				(mapheaderinfo[gamemap-1]->actnum > 0) ? va(", Act %d",mapheaderinfo[gamemap-1]->actnum) : "");
-			V_DrawSmallString(1, 195, V_ALLOWLOWERCASE, tx);
-			I_UpdateNoVsync();
-		}
+		char tx[64];
+		V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to..."));
+		snprintf(tx, 63, "%s%s%s",
+			mapheaderinfo[gamemap-1]->lvlttl,
+			(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE",
+			(mapheaderinfo[gamemap-1]->actnum > 0) ? va(", Act %d",mapheaderinfo[gamemap-1]->actnum) : "");
+		V_DrawSmallString(1, 195, V_ALLOWLOWERCASE, tx);
+		I_UpdateNoVsync();
 	}
 
 #ifdef HAVE_BLUA
@@ -2767,7 +2792,7 @@ boolean P_SetupLevel(boolean skipprecip)
 
 	// Remove the loading shit from the screen
 	if (rendermode != render_none)
-		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (ranspecialwipe) ? 0 : 31);
 
 	if (precache || dedicated)
 		R_PrecacheLevel();

From b7ebb8186d3555ef8f2cbd102d755e7dfba75147 Mon Sep 17 00:00:00 2001
From: Sean Ryder <sryder13@gmail.com>
Date: Tue, 9 Feb 2016 16:20:18 +0000
Subject: [PATCH 3/7] Fix MD2 interpolation for FF_ANIMATE states

---
 src/hardware/hw_md2.c | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 77795ccc0..b092ac32e 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -1195,16 +1195,37 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 			HWR_GetMappedPatch(gpatch, spr->colormap);
 		}
 
+		if (spr->mobj->frame & FF_ANIMATE)
+		{
+			// set duration and tics to be the correct values for FF_ANIMATE states
+			durs = spr->mobj->state->var2;
+			tics = spr->mobj->anim_duration;
+		}
+
 		//FIXME: this is not yet correct
 		frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames;
 		buff = md2->model->glCommandBuffer;
 		curr = &md2->model->frames[frame];
-		if (cv_grmd2.value == 1
-		    && spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL
-		    && !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND]))
+		if (cv_grmd2.value == 1)
 		{
-			const INT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames;
-			next = &md2->model->frames[nextframe];
+			// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
+			if (spr->mobj->frame & FF_ANIMATE)
+			{
+				UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1;
+				if (nextframe >= (UINT32)spr->mobj->state->var1)
+					nextframe = (spr->mobj->state->frame & FF_FRAMEMASK);
+				nextframe %= md2->model->header.numFrames;
+				next = &md2->model->frames[nextframe];
+			}
+			else
+			{
+				if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL
+					&& !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND]))
+				{
+					const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames;
+					next = &md2->model->frames[nextframe];
+				}
+			}
 		}
 
 		//Hurdler: it seems there is still a small problem with mobj angle

From f10279d61bf2a79bcd031ab1f625368cd5bf6ebc Mon Sep 17 00:00:00 2001
From: Inuyasha <MattWCSTRFAN@gmail.com>
Date: Thu, 25 Feb 2016 14:35:05 -0800
Subject: [PATCH 4/7] Very minor performance improvement.

---
 src/p_mobj.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/p_mobj.c b/src/p_mobj.c
index 323e5ce95..d2454f267 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -92,9 +92,7 @@ FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj)
 	// compare the current sprite frame to the one we started from
 	// if more than var1 away from it, swap back to the original
 	// else just advance by one
-	if ((mobj->frame & FF_FRAMEMASK) - (mobj->state->frame & FF_FRAMEMASK) < (UINT32)mobj->state->var1)
-		++mobj->frame;
-	else
+	if (((++mobj->frame) & FF_FRAMEMASK) - (mobj->state->frame & FF_FRAMEMASK) > (UINT32)mobj->state->var1)
 		mobj->frame = (mobj->state->frame & FF_FRAMEMASK) | (mobj->frame & ~FF_FRAMEMASK);
 }
 

From c7ba1d15321531fe2d5ba01e6854760305e98f63 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Fri, 26 Feb 2016 18:11:12 +0000
Subject: [PATCH 5/7] Make sure target sector's lightlist is reset whenever FOF
 flags are changed.

This fixes how removing certain flags (such as FF_EXISTS) from FOFs can cause HOMs on walls bordering their target sectors. Also fixes how the force-FOF-to-vanish linedef special can leave behind the FOF's shadow
---
 src/lua_maplib.c | 6 +++++-
 src/p_spec.c     | 7 +++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index 38920c223..16d05dacd 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -1111,9 +1111,13 @@ static int ffloor_set(lua_State *L)
 	case ffloor_bottompic:
 		*ffloor->bottompic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
 		break;
-	case ffloor_flags:
+	case ffloor_flags: {
+		ffloortype_e oldflags = ffloor->flags; // store FOF's old flags
 		ffloor->flags = luaL_checkinteger(L, 3);
+		if (ffloor->flags != oldflags)
+			ffloor->target->moved = true; // reset target sector's lightlist
 		break;
+	}
 	case ffloor_alpha:
 		ffloor->alpha = (INT32)luaL_checkinteger(L, 3);
 		break;
diff --git a/src/p_spec.c b/src/p_spec.c
index 81994d46c..2c471fa9e 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -3039,6 +3039,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS);
 				sector_t *sec; // Sector that the FOF is visible (or not visible) in
 				ffloor_t *rover; // FOF to vanish/un-vanish
+				ffloortype_e oldflags; // store FOF's old flags
 
 				for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;)
 				{
@@ -3062,11 +3063,17 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 						return;
 					}
 
+					oldflags = rover->flags;
+
 					// Abracadabra!
 					if (line->flags & ML_NOCLIMB)
 						rover->flags |= FF_EXISTS;
 					else
 						rover->flags &= ~FF_EXISTS;
+
+					// if flags changed, reset sector's light list
+					if (rover->flags != oldflags)
+						sec->moved = true;
 				}
 			}
 			break;

From c3166e40b0010fa9c6748875c8e1bfc9551cbc2f Mon Sep 17 00:00:00 2001
From: wolfy852 <wolfy852@hotmail.com>
Date: Sat, 27 Feb 2016 14:27:14 -0600
Subject: [PATCH 6/7] Update names in credits

Same as the commit in internal, minus toaster's name (by request, of course.)
---
 src/f_finale.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/f_finale.c b/src/f_finale.c
index 507616f3c..2a1e5cce2 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -977,6 +977,7 @@ static const char *credits[] = {
 	"\"Monster\" Iestyn Jealous",
 	"Ronald \"Furyhunter\" Kinard", // The SDL2 port
 	"John \"JTE\" Muniz",
+	"Ehab \"Wolfy\" Saeed",
 	"\"SSNTails\"",
 	"Matthew \"Inuyasha\" Walsh",
 	"",
@@ -1020,7 +1021,7 @@ static const char *credits[] = {
 	"\"Monster\" Iestyn Jealous",
 	"Jarel \"Arrow\" Jones",
 	"Stefan \"Stuf\" Rimalia",
-	"Shane Strife",
+	"Shane Mychal Sexton",
 	"\"Spazzo\"",
 	"David \"Big Wave Dave\" Spencer Sr.",
 	"David \"Instant Sonic\" Spencer Jr.",
@@ -1069,7 +1070,7 @@ static const char *credits[] = {
 	"iD Software",
 	"Alex \"MistaED\" Fuller",
 	"FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak
-	"Randy Heit (<!>)", // For his MSPaint <!> sprite that we nicked
+	"Randi Heit (<!>)", // For their MSPaint <!> sprite that we nicked
 	"",
 	"\1Produced By",
 	"Sonic Team Junior",

From e2b3adc04f73663659afad9a8b42b87a9778055d Mon Sep 17 00:00:00 2001
From: Inuyasha <MattWCSTRFAN@gmail.com>
Date: Sun, 28 Feb 2016 18:21:37 -0800
Subject: [PATCH 7/7] Randy Heit -> Randi Heit

---
 src/f_finale.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/f_finale.c b/src/f_finale.c
index 466e208a5..9c3da5a68 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -1068,7 +1068,7 @@ static const char *credits[] = {
 	"iD Software",
 	"Alex \"MistaED\" Fuller",
 	"FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak
-	"Randy Heit (<!>)", // For his MSPaint <!> sprite that we nicked
+	"Randi Heit (<!>)", // For their MSPaint <!> sprite that we nicked
 	"",
 	"\1Produced By",
 	"Sonic Team Junior",