diff --git a/src/dehacked.c b/src/dehacked.c
index e9d029be0b38ba2879291d0f9721f0d748c80850..c05a8f4441b0b47d0fe0c9575eec18a91614a90d 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1863,6 +1863,10 @@ static void readlevelheader(MYFILE *f, INT32 num)
 			}
 			else if (fastcmp(word, "STARTRINGS"))
 				mapheaderinfo[num-1]->startrings = (UINT16)i;
+			else if (fastcmp(word, "SPECIALSTAGETIME"))
+				mapheaderinfo[num-1]->sstimer = i;
+			else if (fastcmp(word, "SPECIALSTAGESPHERES"))
+				mapheaderinfo[num-1]->ssspheres = i;
 			else
 				deh_warning("Level header %d: unknown word '%s'", num, word);
 		}
diff --git a/src/doomstat.h b/src/doomstat.h
index aedb120ff27ac13e7c3a4c03d347230d638093e1..e6a227a4226f16c6789467bc39497d558dc1e647 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -319,6 +319,8 @@ typedef struct
 
 	char selectheading[22]; ///< Level select heading. Allows for controllable grouping.
 	UINT16 startrings;      ///< Number of rings players start with.
+	INT32 sstimer;          ///< Timer for special stages.
+	UINT32 ssspheres;        ///< Sphere requirement in special stages.
 
 	// Title card.
 	char ltzzpatch[8];      ///< Zig zag patch.
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index d851c820e5a4c9ee280e2b180ba82415470fc494..1737216e3791dc0b3aa8a3ce2a190c992ec8d07f 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -2082,6 +2082,10 @@ static int mapheaderinfo_get(lua_State *L)
 		lua_pushinteger(L, header->menuflags);
 	else if (fastcmp(field,"startrings"))
 		lua_pushinteger(L, header->startrings);
+	else if (fastcmp(field, "sstimer"))
+		lua_pushinteger(L, header->sstimer);
+	else if (fastcmp(field, "ssspheres"))
+		lua_pushinteger(L, header->ssspheres);
 	// TODO add support for reading numGradedMares and grades
 	else {
 		// Read custom vars now
diff --git a/src/p_setup.c b/src/p_setup.c
index b3b618e51827fcaecc2fefe4b4af669e0f0551fb..1d1826a5393e024a3dbac5a39ba32abdea5c1d51 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -218,6 +218,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
 	mapheaderinfo[num]->typeoflevel = 0;
 	mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
 	mapheaderinfo[num]->startrings = 0;
+	mapheaderinfo[num]->sstimer = 90;
+	mapheaderinfo[num]->ssspheres = 1;
 	mapheaderinfo[num]->keywords[0] = '\0';
 	snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
 	mapheaderinfo[num]->musname[6] = 0;
diff --git a/src/p_spec.c b/src/p_spec.c
index c93846438d808394bf7dcc287794d88d2d7a8d2a..fafe2cdf3b485636bb4e761df5a328b7d81a6bb6 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6249,8 +6249,8 @@ void P_InitSpecials(void)
 	gravity = FRACUNIT/2;
 
 	// Defaults in case levels don't have them set.
-	sstimer = 90*TICRATE + 6;
-	ssspheres = 1;
+	sstimer = mapheaderinfo[gamemap-1]->sstimer*TICRATE + 6;
+	ssspheres = mapheaderinfo[gamemap-1]->ssspheres;
 
 	CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false;