diff --git a/src/dehacked.c b/src/dehacked.c
index 50bd5e36d9266532d8d7228cf1138a535e14323d..707cdbfbb8276e8a342b829849723a65be8bce14 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1323,6 +1323,8 @@ static void readlevelheader(MYFILE *f, INT32 num)
 				else
 					mapheaderinfo[num-1]->menuflags &= ~LF2_WIDEICON;
 			}
+			else if (fastcmp(word, "STARTRINGS"))
+				mapheaderinfo[num-1]->startrings = (UINT16)i;
 			else
 				deh_warning("Level header %d: unknown word '%s'", num, word);
 		}
diff --git a/src/doomstat.h b/src/doomstat.h
index efd347dbed6f11fa5ff843ca7461ad5094b2bdd9..06dfcca0b9a9729b60248b3b87633e35e01d0a07 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -313,6 +313,7 @@ typedef struct
 	UINT8 menuflags;      ///< LF2_flags: options that affect record attack / nights mode menus
 
 	char selectheading[22]; ///< Level select heading. Allows for controllable grouping.
+	UINT16 startrings;      ///< Number of rings players start with.
 
 	// Freed animals stuff.
 	UINT8 numFlickies;     ///< Internal. For freed flicky support.
diff --git a/src/g_game.c b/src/g_game.c
index 2ad0b12d9658076c95c7766f95ec727ed05095ae..632e33009c7b290268ff543a1597ac327e3e7ef0 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -2397,6 +2397,8 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
 
 	P_SpawnPlayer(playernum);
 
+	players[playernum].rings = mapheaderinfo[gamemap-1]->startrings;
+
 	if (starpost) //Don't even bother with looking for a place to spawn.
 	{
 		P_MovePlayerToStarpost(playernum);
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index 27b97204f2f64a073005ae22dc1a41aea86b572f..c5555009f849c8addd92c641a2db1d6414f6bba5 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -2080,6 +2080,8 @@ static int mapheaderinfo_get(lua_State *L)
 		lua_pushinteger(L, header->levelflags);
 	else if (fastcmp(field,"menuflags"))
 		lua_pushinteger(L, header->menuflags);
+	else if (fastcmp(field,"startrings"))
+		lua_pushinteger(L, header->startrings);
 	// 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 af4f1f9dd6989322f85704951b79248400b2a4a6..585da2149b1c3c4277ceb06968b47afeea41d788 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -209,6 +209,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
 	mapheaderinfo[num]->actnum = 0;
 	mapheaderinfo[num]->typeoflevel = 0;
 	mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
+	mapheaderinfo[num]->startrings = 0;
 	snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
 	mapheaderinfo[num]->musname[6] = 0;
 	mapheaderinfo[num]->mustrack = 0;
@@ -2175,7 +2176,7 @@ static void P_LevelInitStuff(void)
 	tokenbits = 0;
 	runemeraldmanager = false;
 	emeraldspawndelay = 60*TICRATE;
-	nummaprings = 0;
+	nummaprings = mapheaderinfo[gamemap-1]->startrings;
 
 	// emerald hunt
 	hunt1 = hunt2 = hunt3 = NULL;