diff --git a/src/d_main.c b/src/d_main.c
index 22a6762554663a182f473efc2c7354ef824feee6..a48e94e7af44b0ddc4b2d635469ba1755a5e0b07 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1626,6 +1626,14 @@ void D_SRB2Main(void)
 		autostart = true;
 	}
 
+	// Set default singleplayer skin
+	if (!dedicated)
+	{
+		pickedchar = R_SkinAvailable(cv_defaultskin.string);
+		if (pickedchar == -1)
+			pickedchar = 0;
+	}
+
 	// user settings come before "+" parameters.
 	if (dedicated)
 		COM_ImmedExecute(va("exec \"%s"PATHSEP"adedserv.cfg\"\n", srb2home));
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index d022514c6a67b7d3a0a67042b2daebdacf7b8e04..369118dcce95d7833c90b9284a4b48d54442e538 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -1274,25 +1274,22 @@ static void SendNameAndColor(void)
 			players[consoleplayer].mo->color = P_GetPlayerColor(&players[consoleplayer]);
 
 		if (metalrecording)
-		{ // Starring Metal Sonic as themselves, obviously.
+		{
+			// Starring Metal Sonic as themselves, obviously.
 			SetPlayerSkinByNum(consoleplayer, 5);
-			CV_StealthSet(&cv_skin, skins[5].name);
 		}
-		else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin))
+		else if (splitscreen)
 		{
-			cv_skin.value = foundskin;
-
-			SetPlayerSkin(consoleplayer, cv_skin.string);
-			CV_StealthSet(&cv_skin, skins[cv_skin.value].name);
+			if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin))
+				SetPlayerSkin(consoleplayer, cv_skin.string);
+			else
+			{
+				// will always be same as current
+				SetPlayerSkin(consoleplayer, cv_skin.string);
+			}
 		}
 		else
-		{
-			cv_skin.value = players[consoleplayer].skin;
-			CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
-			// will always be same as current
-			SetPlayerSkin(consoleplayer, cv_skin.string);
-		}
-
+			SetPlayerSkinByNum(consoleplayer, pickedchar);
 		return;
 	}
 
@@ -1365,7 +1362,6 @@ static void SendNameAndColor2(void)
 	if (!Playing())
 		return;
 
-	// If you're not in a netgame, merely update the skin, color, and name.
 	if (botingame)
 	{
 		players[secondplaya].skincolor = botcolor;
@@ -1377,6 +1373,7 @@ static void SendNameAndColor2(void)
 	}
 	else if (!netgame)
 	{
+		// If you're not in a netgame, merely update the skin, color, and name.
 		INT32 foundskin;
 
 		CleanupPlayerName(secondplaya, cv_playername2.zstring);
@@ -1387,7 +1384,7 @@ static void SendNameAndColor2(void)
 		if (players[secondplaya].mo && !players[secondplaya].powers[pw_dye])
 			players[secondplaya].mo->color = P_GetPlayerColor(&players[secondplaya]);
 
-		if (cv_forceskin.value >= 0 && (netgame || multiplayer)) // Server wants everyone to use the same player
+		if (cv_forceskin.value >= 0 && multiplayer) // Server wants everyone to use the same player
 		{
 			const INT32 forcedskin = cv_forceskin.value;
 
@@ -1395,16 +1392,9 @@ static void SendNameAndColor2(void)
 			CV_StealthSet(&cv_skin2, skins[forcedskin].name);
 		}
 		else if ((foundskin = R_SkinAvailable(cv_skin2.string)) != -1 && R_SkinUsable(secondplaya, foundskin))
-		{
-			cv_skin2.value = foundskin;
-
 			SetPlayerSkin(secondplaya, cv_skin2.string);
-			CV_StealthSet(&cv_skin2, skins[cv_skin2.value].name);
-		}
-		else
+		else if (splitscreen)
 		{
-			cv_skin2.value = players[secondplaya].skin;
-			CV_StealthSet(&cv_skin2, skins[players[secondplaya].skin].name);
 			// will always be same as current
 			SetPlayerSkin(secondplaya, cv_skin2.string);
 		}
@@ -2094,7 +2084,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
 	{
 		SetPlayerSkinByNum(0, cv_chooseskin.value-1);
 		players[0].skincolor = skins[players[0].skin].prefcolor;
-		CV_StealthSetValue(&cv_playercolor, players[0].skincolor);
 	}
 
 	mapnumber = M_MapNumber(mapname[3], mapname[4]);
diff --git a/src/g_demo.c b/src/g_demo.c
index 4b9ff56e80f5711faabd18b53a9474f2c0a60c5e..e3377ab13825e72dace0ecf0ccd777b2db1a8ca6 100644
--- a/src/g_demo.c
+++ b/src/g_demo.c
@@ -1500,8 +1500,12 @@ void G_BeginRecording(void)
 	demo_p += 16;
 
 	// Color
-	for (i = 0; i < MAXCOLORNAME && cv_playercolor.string[i]; i++)
-		name[i] = cv_playercolor.string[i];
+	UINT16 skincolor = players[0].skincolor;
+	if (skincolor >= numskincolors)
+		skincolor = SKINCOLOR_NONE;
+	const char *skincolor_name = skincolors[skincolor].name;
+	for (i = 0; i < MAXCOLORNAME && skincolor_name[i]; i++)
+		name[i] = skincolor_name[i];
 	for (; i < MAXCOLORNAME; i++)
 		name[i] = '\0';
 	M_Memcpy(demo_p,name,MAXCOLORNAME);
@@ -2263,7 +2267,6 @@ void G_DoPlayDemo(char *defdemoname)
 			players[0].skincolor = i;
 			break;
 		}
-	CV_StealthSetValue(&cv_playercolor, players[0].skincolor);
 	if (players[0].mo)
 	{
 		players[0].mo->color = players[0].skincolor;
diff --git a/src/g_game.c b/src/g_game.c
index c49b202adf4e22ca2e547d8005c6d5533971fd2c..70ff31f301105e2b75915c16da42150be7835d28 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -55,6 +55,8 @@ gameaction_t gameaction;
 gamestate_t gamestate = GS_NULL;
 UINT8 ultimatemode = false;
 
+INT32 pickedchar;
+
 boolean botingame;
 UINT8 botskin;
 UINT16 botcolor;
@@ -4770,12 +4772,9 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
 	Z_Free(savebuffer);
 	save_p = savebuffer = NULL;
 
-//	gameaction = ga_nothing;
-//	G_SetGamestate(GS_LEVEL);
 	displayplayer = consoleplayer;
 	multiplayer = splitscreen = false;
 
-//	G_DeferedInitNew(sk_medium, G_BuildMapName(1), 0, 0, 1);
 	if (setsizeneeded)
 		R_ExecuteSetViewSize();
 
@@ -4968,9 +4967,9 @@ cleanup:
 // Can be called by the startup code or the menu task,
 // consoleplayer, displayplayer, playeringame[] should be set.
 //
-void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, boolean SSSG, boolean FLS)
+void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 character, boolean SSSG, boolean FLS)
 {
-	UINT16 color = skins[pickedchar].prefcolor;
+	pickedchar = character;
 	paused = false;
 
 	if (demoplayback)
@@ -4991,10 +4990,7 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, b
 		SplitScreen_OnChange();
 	}
 
-	color = skins[pickedchar].prefcolor;
-	SetPlayerSkinByNum(consoleplayer, pickedchar);
-	CV_StealthSet(&cv_skin, skins[pickedchar].name);
-	CV_StealthSetValue(&cv_playercolor, color);
+	SetPlayerSkinByNum(consoleplayer, character);
 
 	if (mapname)
 		D_MapChange(M_MapNumber(mapname[3], mapname[4]), gametype, pultmode, true, 1, false, FLS);
diff --git a/src/g_game.h b/src/g_game.h
index a8c285f79f442b04a266f7e4ccbdd34997029833..cb38fc1d5b47afdd3741840352f0a77127121fc1 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -174,8 +174,7 @@ void G_SpawnPlayer(INT32 playernum);
 
 // Can be called by the startup code or M_Responder.
 // A normal game starts at map 1, but a warp test can start elsewhere
-void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar,
-	boolean SSSG, boolean FLS);
+void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 character, boolean SSSG, boolean FLS);
 void G_DoLoadLevel(boolean resetplayer);
 void G_StartTitleCard(void);
 void G_PreLevelTitleCard(void);
diff --git a/src/g_state.h b/src/g_state.h
index 8f97930bb6d7b2ce736382d443f9d9f89d83b03a..4b07f3d903cd1c90efd3c28a68f1c9897061f4eb 100644
--- a/src/g_state.h
+++ b/src/g_state.h
@@ -53,9 +53,11 @@ typedef enum
 
 extern gamestate_t gamestate;
 extern UINT8 titlemapinaction;
-extern UINT8 ultimatemode; // was sk_insane
+extern UINT8 ultimatemode;
 extern gameaction_t gameaction;
 
+extern INT32 pickedchar;
+
 extern boolean botingame;
 extern UINT8 botskin;
 extern UINT16 botcolor;
diff --git a/src/p_setup.c b/src/p_setup.c
index 0c8ea656ec9d24c469a355d91f1418debc4c4701..747cf6d7f9180d3c5e426abbd89c80e5667f0bdd 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -7179,19 +7179,13 @@ static void P_ForceCharacter(const char *forcecharskin)
 		{
 			SetPlayerSkin(secondarydisplayplayer, forcecharskin);
 			if ((unsigned)cv_playercolor2.value != skins[players[secondarydisplayplayer].skin].prefcolor)
-			{
-				CV_StealthSetValue(&cv_playercolor2, skins[players[secondarydisplayplayer].skin].prefcolor);
 				players[secondarydisplayplayer].skincolor = skins[players[secondarydisplayplayer].skin].prefcolor;
-			}
 		}
 
 		SetPlayerSkin(consoleplayer, forcecharskin);
 		// normal player colors in single player
 		if ((unsigned)cv_playercolor.value != skins[players[consoleplayer].skin].prefcolor)
-		{
-			CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor);
 			players[consoleplayer].skincolor = skins[players[consoleplayer].skin].prefcolor;
-		}
 	}
 }
 
diff --git a/src/r_skins.c b/src/r_skins.c
index 9443ad49b03d492e6856f4125881def0b1f463e4..8bd75e35bf7f247ae377ac0bff5f0736ccdb4357 100644
--- a/src/r_skins.c
+++ b/src/r_skins.c
@@ -346,10 +346,6 @@ static void SetSkin(player_t *player, INT32 skinnum)
 
 	if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback))
 	{
-		if (player == &players[consoleplayer])
-			CV_StealthSetValue(&cv_playercolor, skin->prefcolor);
-		else if (player == &players[secondarydisplayplayer])
-			CV_StealthSetValue(&cv_playercolor2, skin->prefcolor);
 		player->skincolor = newcolor = skin->prefcolor;
 		if (player->bot && botingame)
 		{