diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 7ad288f2508f43cd6556bd7c2a11dc1adf3ec135..6becfd0c3820b036ff675c2ab8f85eda7ab8c046 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -1038,6 +1038,7 @@ void D_RegisterClientCommands(void)
 	for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 	{
 		CV_RegisterVar(&cv_kickstartaccel[i]);
+		CV_RegisterVar(&cv_autoroulette[i]);
 		CV_RegisterVar(&cv_shrinkme[i]);
 		CV_RegisterVar(&cv_deadzone[i]);
 		CV_RegisterVar(&cv_rumble[i]);
@@ -1783,6 +1784,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
 enum {
 	WP_KICKSTARTACCEL = 1<<0,
 	WP_SHRINKME = 1<<1,
+	WP_AUTOROULETTE = 1<<2,
 };
 
 void WeaponPref_Send(UINT8 ssplayer)
@@ -1792,6 +1794,9 @@ void WeaponPref_Send(UINT8 ssplayer)
 	if (cv_kickstartaccel[ssplayer].value)
 		prefs |= WP_KICKSTARTACCEL;
 
+	if (cv_autoroulette[ssplayer].value)
+		prefs |= WP_AUTOROULETTE;
+
 	if (cv_shrinkme[ssplayer].value)
 		prefs |= WP_SHRINKME;
 
@@ -1807,6 +1812,9 @@ void WeaponPref_Save(UINT8 **cp, INT32 playernum)
 	if (player->pflags & PF_KICKSTARTACCEL)
 		prefs |= WP_KICKSTARTACCEL;
 
+	if (player->pflags & PF_AUTOROULETTE)
+		prefs |= WP_AUTOROULETTE;
+
 	if (player->pflags & PF_SHRINKME)
 		prefs |= WP_SHRINKME;
 
@@ -1819,11 +1827,14 @@ void WeaponPref_Parse(UINT8 **cp, INT32 playernum)
 
 	UINT8 prefs = READUINT8(*cp);
 
-	player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME);
+	player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME|PF_AUTOROULETTE);
 
 	if (prefs & WP_KICKSTARTACCEL)
 		player->pflags |= PF_KICKSTARTACCEL;
 
+	if (prefs & WP_AUTOROULETTE)
+		player->pflags |= PF_AUTOROULETTE;
+
 	if (prefs & WP_SHRINKME)
 		player->pflags |= PF_SHRINKME;
 
diff --git a/src/d_player.h b/src/d_player.h
index 6d6e887d18c7d51c755fd02637e3c5777cc2e0c1..292ec12f4ef2d4781b813d884d622f18ed3899fe 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -64,7 +64,9 @@ typedef enum
 {
 	PF_GODMODE			= 1<<0, // Immortal. No lightsnake from pits either
 
-	// free: 1<<1 and 1<<2
+	// free: 1<<1
+
+	PF_AUTOROULETTE		= 1<<2, // Accessibility: Non-deterministic item box, no manual stop.
 
 	// Look back VFX has been spawned
 	// TODO: Is there a better way to track this?
@@ -437,6 +439,7 @@ struct itemroulette_t
 
 	boolean eggman;
 	boolean ringbox;
+	boolean autoroulette;
 };
 
 // enum for bot item priorities
diff --git a/src/deh_tables.c b/src/deh_tables.c
index f20d45ee7f20310602823159d285721ac5d473bf..c90855a42147bed0a378c4576de751e0a1af6d96 100644
--- a/src/deh_tables.c
+++ b/src/deh_tables.c
@@ -5914,7 +5914,7 @@ const char *const PLAYERFLAG_LIST[] = {
 
 	// free: 1<<1 and 1<<2 (name un-matchable)
 	"\x01",
-	"\x01",
+	"AUTOROULETTE", // Item box accessibility
 
 	// Look back VFX has been spawned
 	// TODO: Is there a better way to track this?
diff --git a/src/g_demo.c b/src/g_demo.c
index de15625c0d7a097ae59d07d7b421f470ef11bf7e..7bb98fdbc3ddfcf02fd9e923196ac84a87859775 100644
--- a/src/g_demo.c
+++ b/src/g_demo.c
@@ -133,10 +133,11 @@ demoghost *ghosts = NULL;
 #define DF_ENCORE       0x40
 #define DF_MULTIPLAYER  0x80 // This demo was recorded in multiplayer mode!
 
-#define DEMO_SPECTATOR	0x01
-#define DEMO_KICKSTART	0x02
-#define DEMO_SHRINKME	0x04
-#define DEMO_BOT		0x08
+#define DEMO_SPECTATOR		0x01
+#define DEMO_KICKSTART		0x02
+#define DEMO_SHRINKME		0x04
+#define DEMO_BOT			0x08
+#define DEMO_AUTOROULETTE	0x10
 
 // For demos
 #define ZT_FWD		0x0001
@@ -2474,6 +2475,8 @@ void G_BeginRecording(void)
 				i |= DEMO_SPECTATOR;
 			if (player->pflags & PF_KICKSTARTACCEL)
 				i |= DEMO_KICKSTART;
+			if (player->pflags & PF_AUTOROULETTE)
+				i |= DEMO_AUTOROULETTE;
 			if (player->pflags & PF_SHRINKME)
 				i |= DEMO_SHRINKME;
 			if (player->bot == true)
@@ -3436,6 +3439,11 @@ void G_DoPlayDemo(const char *defdemoname)
 		else
 			players[p].pflags &= ~PF_KICKSTARTACCEL;
 
+		if (flags & DEMO_AUTOROULETTE)
+			players[p].pflags |= PF_AUTOROULETTE;
+		else
+			players[p].pflags &= ~PF_AUTOROULETTE;
+
 		if (flags & DEMO_SHRINKME)
 			players[p].pflags |= PF_SHRINKME;
 		else
diff --git a/src/g_game.c b/src/g_game.c
index e26f13a48563614f9b3bcf92a4f2947479e1acc0..1ef8faee14dd0f92598ead5caa70e22e8a073b9f 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -405,6 +405,13 @@ consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS] = {
 	CVAR_INIT ("kickstartaccel4", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange4)
 };
 
+consvar_t cv_autoroulette[MAXSPLITSCREENPLAYERS] = {
+	CVAR_INIT ("autoroulette", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange),
+	CVAR_INIT ("autoroulette2", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange2),
+	CVAR_INIT ("autoroulette3", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange3),
+	CVAR_INIT ("autoroulette4", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange4)
+};
+
 consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS] = {
 	CVAR_INIT ("shrinkme", "Off", CV_CALL, CV_OnOff, weaponPrefChange),
 	CVAR_INIT ("shrinkme2", "Off", CV_CALL, CV_OnOff, weaponPrefChange2),
@@ -2212,7 +2219,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
 	totalring = players[player].totalring;
 	xtralife = players[player].xtralife;
 
-	pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE));
+	pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_AUTOROULETTE));
 
 	// SRB2kart
 	memcpy(&itemRoulette, &players[player].itemRoulette, sizeof (itemRoulette));
diff --git a/src/g_game.h b/src/g_game.h
index e781f17ee34ebf70d00b8babe56d97940806576d..84dc5f4acf42cd10840cfe07f1bf16f7741e16ac 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -95,6 +95,7 @@ extern consvar_t cv_songcredits;
 extern consvar_t cv_pauseifunfocused;
 
 extern consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS];
+extern consvar_t cv_autoroulette[MAXSPLITSCREENPLAYERS];
 extern consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS];
 
 extern consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS];
diff --git a/src/k_hud.c b/src/k_hud.c
index 5693044852946aceb522393bd16d0f18de0dd01d..af15b474a6f592cff777f2d1f844ffbc3d242e91 100644
--- a/src/k_hud.c
+++ b/src/k_hud.c
@@ -193,6 +193,8 @@ static patch_t *kp_bossret[4];
 
 static patch_t *kp_trickcool[2];
 
+patch_t *kp_autoroulette;
+
 patch_t *kp_capsuletarget_arrow[2][2];
 patch_t *kp_capsuletarget_icon[2];
 patch_t *kp_capsuletarget_far[2];
@@ -710,6 +712,8 @@ void K_LoadKartHUDGraphics(void)
 	HU_UpdatePatch(&kp_trickcool[0], "K_COOL1");
 	HU_UpdatePatch(&kp_trickcool[1], "K_COOL2");
 
+	HU_UpdatePatch(&kp_autoroulette, "A11YITEM");
+
 	sprintf(buffer, "K_BOSB0x");
 	for (i = 0; i < 8; i++)
 	{
@@ -2743,70 +2747,92 @@ static void K_drawRingCounter(boolean gametypeinfoshown)
 
 static void K_drawKartAccessibilityIcons(boolean gametypeinfoshown, INT32 fx)
 {
-	INT32 fy = LAPS_Y-14;
-	INT32 splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN;
-	//INT32 step = 1; -- if there's ever more than one accessibility icon
-
-	fx += LAPS_X;
-
-	if (r_splitscreen < 2) // adjust to speedometer height
-	{
-		if (gametypeinfoshown)
-		{
-			fy -= 11;
-
-			if ((gametyperules & (GTR_BUMPERS|GTR_CIRCUIT)) == GTR_BUMPERS)
-				fy -= 4;
-		}
-		else
-		{
-			fy += 9;
-		}
-	}
-	else
-	{
-		fx = LAPS_X+43;
-		fy = LAPS_Y;
-		if (!(stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]))	// If we are not P1 or P3...
-		{
-			splitflags ^= (V_SNAPTOLEFT|V_SNAPTORIGHT);
-			fx = (BASEVIDWIDTH/2) - (fx + 10);
-			//step = -step;
-		}
-	}
-
-	if (stplyr->pflags & PF_KICKSTARTACCEL) // just KICKSTARTACCEL right now, maybe more later
-	{
-		SINT8 col = 0, wid, fil, ofs;
-		UINT8 i = 7;
-		ofs = (stplyr->kickstartaccel == ACCEL_KICKSTART) ? 1 : 0;
-		fil = i-(stplyr->kickstartaccel*i)/ACCEL_KICKSTART;
-
-		V_DrawFill(fx+4, fy+ofs-1, 2, 1, 31|V_SLIDEIN|splitflags);
-		V_DrawFill(fx, (fy+ofs-1)+8, 10, 1, 31|V_SLIDEIN|splitflags);
-
-		while (i--)
-		{
-			wid = (i/2)+1;
-			V_DrawFill(fx+4-wid, fy+ofs+i, 2+(wid*2), 1, 31|V_SLIDEIN|splitflags);
-			if (fil > 0)
-			{
-				if (i < fil)
-					col = 23;
-				else if (i == fil)
-					col = 3;
-				else
-					col = 5 + (i-fil)*2;
-			}
-			else if ((leveltime % 7) == i)
-				col = 0;
-			else
-				col = 3;
-			V_DrawFill(fx+5-wid, fy+ofs+i, (wid*2), 1, col|V_SLIDEIN|splitflags);
-		}
-
-		//fx += step*12;
-	}
+    INT32 fy = LAPS_Y-14;
+    INT32 splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN;
+ 
+    boolean mirror = false;
+ 
+    fx += LAPS_X;
+ 
+    if (r_splitscreen < 2) // adjust to speedometer height
+    {
+        if (gametypeinfoshown)
+        {
+            fy -= 11;
+ 
+            if ((gametyperules & (GTR_BUMPERS|GTR_CIRCUIT)) == GTR_BUMPERS)
+                fy -= 4;
+        }
+        else
+        {
+            fy += 9;
+        }
+    }
+    else
+    {
+        fx = LAPS_X+44;
+        fy = LAPS_Y;
+        if (!(stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]))  // If we are not P1 or P3...
+        {
+            splitflags ^= (V_SNAPTOLEFT|V_SNAPTORIGHT);
+            fx = (BASEVIDWIDTH/2) - fx;
+            mirror = true;
+        }
+    }
+ 
+    // Kickstart Accel
+    if (stplyr->pflags & PF_KICKSTARTACCEL)
+    {
+        if (mirror)
+            fx -= 10;
+ 
+        SINT8 col = 0, wid, fil, ofs;
+        UINT8 i = 7;
+        ofs = (stplyr->kickstartaccel == ACCEL_KICKSTART) ? 1 : 0;
+        fil = i-(stplyr->kickstartaccel*i)/ACCEL_KICKSTART;
+ 
+        V_DrawFill(fx+4, fy+ofs-1, 2, 1, 31|V_SLIDEIN|splitflags);
+        V_DrawFill(fx, (fy+ofs-1)+8, 10, 1, 31|V_SLIDEIN|splitflags);
+ 
+        while (i--)
+        {
+            wid = (i/2)+1;
+            V_DrawFill(fx+4-wid, fy+ofs+i, 2+(wid*2), 1, 31|V_SLIDEIN|splitflags);
+            if (fil > 0)
+            {
+                if (i < fil)
+                    col = 23;
+                else if (i == fil)
+                    col = 3;
+                else
+                    col = 5 + (i-fil)*2;
+            }
+            else if ((leveltime % 7) == i)
+                col = 0;
+            else
+                col = 3;
+            V_DrawFill(fx+5-wid, fy+ofs+i, (wid*2), 1, col|V_SLIDEIN|splitflags);
+        }
+ 
+        if (mirror)
+            fx--;
+        else
+            fx += 10 + 1;
+    }
+ 
+    // Auto Roulette
+    if (stplyr->pflags & PF_AUTOROULETTE)
+    {
+        if (mirror)
+            fx -= 12;
+ 
+        V_DrawScaledPatch(fx, fy-1, V_SLIDEIN|splitflags, kp_autoroulette);
+ 
+        if (mirror)
+            fx--;
+        else
+            fx += 12 + 1;
+    }
 }
 
 static void K_drawKartSpeedometer(boolean gametypeinfoshown)
diff --git a/src/k_hud.h b/src/k_hud.h
index 041243d5b65e9757acffea21dae943a8c9a7a73a..d982c851b03dad534f148c17745954a6f016b64f 100644
--- a/src/k_hud.h
+++ b/src/k_hud.h
@@ -61,6 +61,8 @@ extern patch_t *kp_capsuletarget_near[8];
 
 extern patch_t *kp_superflickytarget[4];
 
+extern patch_t *kp_autoroulette;
+
 extern patch_t *kp_button_a[2][2];
 extern patch_t *kp_button_b[2][2];
 extern patch_t *kp_button_c[2][2];
diff --git a/src/k_menu.h b/src/k_menu.h
index 70f6b79c3bb1034367d846a72d447cb2557ce3a7..69ec29542b6ba2592df1dbfb1bf43123c09337a0 100644
--- a/src/k_menu.h
+++ b/src/k_menu.h
@@ -981,6 +981,7 @@ extern INT16 controlleroffsets[][2];
 extern consvar_t cv_dummyprofilename;
 extern consvar_t cv_dummyprofileplayername;
 extern consvar_t cv_dummyprofilekickstart;
+extern consvar_t cv_dummyprofileautoroulette;
 extern consvar_t cv_dummyprofilerumble;
 
 void M_ResetOptions(void);
diff --git a/src/k_menufunc.c b/src/k_menufunc.c
index 8a596b6639d730bfba71de584dbc537047c14c54..54b0f26b7dd28563ae97e4f320a019f7c01cb5ee 100644
--- a/src/k_menufunc.c
+++ b/src/k_menufunc.c
@@ -1215,6 +1215,7 @@ void M_Init(void)
 	CV_RegisterVar(&cv_dummyprofilename);
 	CV_RegisterVar(&cv_dummyprofileplayername);
 	CV_RegisterVar(&cv_dummyprofilekickstart);
+	CV_RegisterVar(&cv_dummyprofileautoroulette);
 	CV_RegisterVar(&cv_dummyprofilerumble);
 
 	CV_RegisterVar(&cv_dummygpdifficulty);
diff --git a/src/k_profiles.c b/src/k_profiles.c
index f0a0a8e8910e446c07ee20a1257fa8245cd7d919..817392d6857af48145d254961565d78a50043a7a 100644
--- a/src/k_profiles.c
+++ b/src/k_profiles.c
@@ -68,6 +68,7 @@ profile_t* PR_MakeProfile(
 	strcpy(new->follower, fname);
 	new->followercolor = fcol;
 	new->kickstartaccel = false;
+	new->autoroulette = false;
 
 	// Copy from gamecontrol directly as we'll be setting controls up directly in the profile.
 	memcpy(new->controls, controlarray, sizeof(new->controls));
@@ -84,6 +85,7 @@ profile_t* PR_MakeProfileFromPlayer(const char *prname, const char *pname, const
 
 	// Player bound cvars:
 	new->kickstartaccel = cv_kickstartaccel[pnum].value;
+	new->autoroulette = cv_autoroulette[pnum].value;
 	new->rumble = cv_rumble[pnum].value;
 
 	return new;
@@ -270,6 +272,7 @@ void PR_SaveProfiles(void)
 
 		// Consvars.
 		WRITEUINT8(save.p, profilesList[i]->kickstartaccel);
+		WRITEUINT8(save.p, profilesList[i]->autoroulette);
 		WRITEUINT8(save.p, profilesList[i]->rumble);
 
 		// Controls.
@@ -407,6 +410,18 @@ void PR_LoadProfiles(void)
 
 		// Consvars.
 		profilesList[i]->kickstartaccel = (boolean)READUINT8(save.p);
+
+		// 6->7, add autoroulette
+		if (version < 7)
+		{
+			profilesList[i]->autoroulette = false;
+			
+		}
+		else
+		{
+			profilesList[i]->autoroulette = (boolean)READUINT8(save.p);
+		}
+
 		if (version < 4)
 		{
 			profilesList[i]->rumble = true;
@@ -459,6 +474,7 @@ static void PR_ApplyProfile_Settings(profile_t *p, UINT8 playernum)
 {
 	// toggles
 	CV_StealthSetValue(&cv_kickstartaccel[playernum], p->kickstartaccel);
+	CV_StealthSetValue(&cv_autoroulette[playernum], p->autoroulette);
 
 	// set controls...
 	memcpy(&gamecontrol[playernum], p->controls, sizeof(gamecontroldefault));
diff --git a/src/k_profiles.h b/src/k_profiles.h
index d08c350be10da6ee83ebcb685b6b76125a8b4abb..8fc72212fd88a3227ab6deae9760cc8d75693097 100644
--- a/src/k_profiles.h
+++ b/src/k_profiles.h
@@ -31,7 +31,7 @@ extern "C" {
 #define SKINNAMESIZE 16
 
 #define PROFILENAMELEN 6
-#define PROFILEVER 6
+#define PROFILEVER 7
 #define MAXPROFILES 16
 #define PROFILESFILE "ringprofiles.prf"
 #define PROFILE_GUEST 0
@@ -74,6 +74,7 @@ struct profile_t
 	// Player-specific consvars.
 	// @TODO: List all of those
 	boolean kickstartaccel;				// cv_kickstartaccel
+	boolean autoroulette;					// cv_autoroulette
 	boolean rumble;						// cv_rumble
 
 	// Finally, control data itself
diff --git a/src/k_roulette.c b/src/k_roulette.c
index f54b2c9e4fa43c596e22e1cdb98fda36d891b3f5..3dce1b705abb1ca237a33c24ee0b073951ab3437 100644
--- a/src/k_roulette.c
+++ b/src/k_roulette.c
@@ -1074,6 +1074,7 @@ static void K_InitRoulette(itemroulette_t *const roulette)
 	roulette->active = true;
 	roulette->eggman = false;
 	roulette->ringbox = false;
+	roulette->autoroulette = false;
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
@@ -1235,6 +1236,12 @@ static void K_CalculateRouletteSpeed(itemroulette_t *const roulette)
 		return;
 	}
 
+	if (roulette->autoroulette == true)
+	{
+		roulette->speed = ROULETTE_SPEED_FASTEST;
+		return;
+	}
+
 	if (K_TimeAttackRules() == true)
 	{
 		// Time Attack rules; use a consistent speed.
@@ -1296,6 +1303,10 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
 	if (player != NULL)
 	{
 		roulette->baseDist = K_UndoMapScaling(player->distancetofinish);
+		
+		if (player->pflags & PF_AUTOROULETTE)
+			roulette->autoroulette = true;
+
 		K_CalculateRouletteSpeed(roulette);
 	}
 
@@ -1456,6 +1467,9 @@ void K_StartItemRoulette(player_t *const player, boolean ringbox)
 
 	K_FillItemRouletteData(player, roulette, ringbox);
 
+	if (roulette->autoroulette)
+		roulette->index = P_RandomRange(PR_AUTOROULETTE, 0, roulette->itemListLen - 1);
+
 	if (K_PlayerUsesBotMovement(player) == true)
 	{
 		K_BotPickItemPriority(player);
@@ -1581,11 +1595,16 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
 
 	if (roulette->elapsed > TICRATE>>1) // Prevent accidental immediate item confirm
 	{
-		if (roulette->elapsed > TICRATE<<4 || (roulette->eggman && roulette->elapsed > TICRATE*4))
+		if (roulette->elapsed > TICRATE<<4 || (roulette->eggman && !roulette->autoroulette && roulette->elapsed > TICRATE*4))
 		{
 			// Waited way too long, forcefully confirm the item.
 			confirmItem = true;
 		}
+		else if (roulette->autoroulette)
+		{
+			// confirmItem = (roulette->speed > 15);
+			confirmItem = (roulette->elapsed == TICRATE*2);
+		}
 		else
 		{
 			// We can stop our item when we choose.
@@ -1616,6 +1635,10 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
 		{
 			// D2 fudge factor. Roulette was originally designed and tested with this delay.
 			UINT8 fudgedDelay = (player->cmd.latency <= 2) ? 0 : player->cmd.latency - 2;
+
+			if (roulette->autoroulette)
+				fudgedDelay = 0; // We didn't manually stop this, you jackwagon
+
 			while (fudgedDelay > 0)
 			{
 				UINT8 gap = (roulette->speed - roulette->tics); // How long has the roulette been on this entry?
@@ -1671,6 +1694,11 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
 
 	roulette->elapsed++;
 
+	/*
+	if (roulette->autoroulette && (roulette->elapsed % 5 == 0) && (roulette->elapsed > TICRATE))
+		roulette->speed++;
+	*/
+
 	if (roulette->tics == 0)
 	{
 		roulette->index = (roulette->index + 1) % roulette->itemListLen;
diff --git a/src/m_random.h b/src/m_random.h
index 54d3698a866ed70070e325352735ea63ac0a2d1d..f3e81f93806c0912f9ad283fb8ba5f1dec90e5f3 100644
--- a/src/m_random.h
+++ b/src/m_random.h
@@ -78,6 +78,8 @@ typedef enum
 
 	PR_BOTS, // Bot spawning
 
+	PR_AUTOROULETTE, // Item box accessibility
+
 	PRNUMCLASS
 } pr_class_t;
 
diff --git a/src/menus/options-profiles-1.c b/src/menus/options-profiles-1.c
index 020be18588066d84e557d828bcbf64338776ca6f..b27578c75bc45833f00aa7861388d62c8f3ac9b4 100644
--- a/src/menus/options-profiles-1.c
+++ b/src/menus/options-profiles-1.c
@@ -30,6 +30,7 @@ menu_t OPTIONS_ProfilesDef = {
 consvar_t cv_dummyprofilename = CVAR_INIT ("dummyprofilename", "", CV_HIDDEN, NULL, NULL);
 consvar_t cv_dummyprofileplayername = CVAR_INIT ("dummyprofileplayername", "", CV_HIDDEN, NULL, NULL);
 consvar_t cv_dummyprofilekickstart = CVAR_INIT ("dummyprofilekickstart", "Off", CV_HIDDEN, CV_OnOff, NULL);
+consvar_t cv_dummyprofileautoroulette = CVAR_INIT ("dummyprofileautoroulette", "Off", CV_HIDDEN, CV_OnOff, NULL);
 consvar_t cv_dummyprofilerumble = CVAR_INIT ("dummyprofilerumble", "On", CV_HIDDEN, CV_OnOff, NULL);
 
 void M_ProfileSelectInit(INT32 choice)
@@ -93,6 +94,7 @@ static void M_StartEditProfile(INT32 c)
 			CV_StealthSet(&cv_dummyprofilename, optionsmenu.profile->profilename);
 			CV_StealthSet(&cv_dummyprofileplayername, optionsmenu.profile->playername);
 			CV_StealthSetValue(&cv_dummyprofilekickstart, optionsmenu.profile->kickstartaccel);
+			CV_StealthSetValue(&cv_dummyprofileautoroulette, optionsmenu.profile->autoroulette);
 			CV_StealthSetValue(&cv_dummyprofilerumble, optionsmenu.profile->rumble);
 		}
 		else
@@ -100,6 +102,7 @@ static void M_StartEditProfile(INT32 c)
 			CV_StealthSet(&cv_dummyprofilename, "");
 			CV_StealthSet(&cv_dummyprofileplayername, "");
 			CV_StealthSetValue(&cv_dummyprofilekickstart, 0);	// off
+			CV_StealthSetValue(&cv_dummyprofileautoroulette, 0); // off
 			CV_StealthSetValue(&cv_dummyprofilerumble, 1);	// on
 		}
 
diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c
index 9ef5b590f8205cb999f00f3d840f17a301ee564b..dc648abd678eed76b2a2066985e73464428a7dae 100644
--- a/src/menus/options-profiles-edit-controls.c
+++ b/src/menus/options-profiles-edit-controls.c
@@ -91,6 +91,9 @@ menuitem_t OPTIONS_ProfileControls[] = {
 	{IT_CONTROL | IT_CVAR, "KICKSTART ACCEL", "Hold A to auto-accel. Tap it to cancel.",
 		NULL, {.cvar = &cv_dummyprofilekickstart}, 0, 0},
 
+	{IT_CONTROL | IT_CVAR, "AUTO ROULETTE", "Item roulette auto-stops on a random result.",
+		NULL, {.cvar = &cv_dummyprofileautoroulette}, 0, 0},
+
 	{IT_HEADER, "EXTRA", "",
 		NULL, {NULL}, 0, 0},
 
@@ -187,6 +190,7 @@ static void M_ProfileControlSaveResponse(INT32 choice)
 		SINT8 belongsto = PR_ProfileUsedBy(optionsmenu.profile);
 		// Save the profile
 		optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value;
+		optionsmenu.profile->autoroulette = cv_dummyprofileautoroulette.value;
 		optionsmenu.profile->rumble = cv_dummyprofilerumble.value;
 		memcpy(&optionsmenu.profile->controls, optionsmenu.tempcontrols, sizeof(gamecontroldefault));
 
@@ -196,6 +200,7 @@ static void M_ProfileControlSaveResponse(INT32 choice)
 		{
 			memcpy(&gamecontrol[belongsto], optionsmenu.tempcontrols, sizeof(gamecontroldefault));
 			CV_SetValue(&cv_kickstartaccel[belongsto], cv_dummyprofilekickstart.value);
+			CV_SetValue(&cv_autoroulette[belongsto], cv_dummyprofileautoroulette.value);
 			CV_SetValue(&cv_rumble[belongsto], cv_dummyprofilerumble.value);
 		}
 
@@ -213,6 +218,7 @@ void M_ProfileControlsConfirm(INT32 choice)
 	M_ProfileControlSaveResponse(MA_YES);
 
 	optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value;		// Make sure to save kickstart accel.
+	optionsmenu.profile->autoroulette = cv_dummyprofileautoroulette.value; // We should really just rip this entire construct out at some point
 	optionsmenu.profile->rumble = cv_dummyprofilerumble.value;		// And rumble too!
 
 	// Reapply player 1's real profile.
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 580e5bf38985defe39eb5b70d9f85c982200efeb..6f4ecbacd1693faf81e9a1084c37c94f0d11341d 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -623,6 +623,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
 		WRITEUINT32(save->p, players[i].itemRoulette.elapsed);
 		WRITEUINT8(save->p, players[i].itemRoulette.eggman);
 		WRITEUINT8(save->p, players[i].itemRoulette.ringbox);
+		WRITEUINT8(save->p, players[i].itemRoulette.autoroulette);
 
 		// sonicloopsvars_t
 		WRITEFIXED(save->p, players[i].loop.radius);
@@ -1058,6 +1059,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
 		players[i].itemRoulette.elapsed = (tic_t)READUINT32(save->p);
 		players[i].itemRoulette.eggman = (boolean)READUINT8(save->p);
 		players[i].itemRoulette.ringbox = (boolean)READUINT8(save->p);
+		players[i].itemRoulette.autoroulette = (boolean)READUINT8(save->p);
 
 		// sonicloopsvars_t
 		players[i].loop.radius = READFIXED(save->p);