diff --git a/src/d_main.c b/src/d_main.c
index 4904b6909c1b8b52e1e048a0e21293e410cc6fab..2405b01365ba8c47f4e54036839e7e704b6aaa4b 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -983,7 +983,7 @@ void D_StartTitle(void)
 	emeralds = 0;
 	memset(&luabanks, 0, sizeof(luabanks));
 	lastmaploaded = 0;
-	pickedchar = R_SkinAvailable(cv_defaultskin.string);
+	pickedchar = R_SkinAvailable(cv_skin.string);
 
 	// In case someone exits out at the same time they start a time attack run,
 	// reset modeattacking
diff --git a/src/g_game.c b/src/g_game.c
index 8d19c9e7cb68df142e68e7d0277b2425153f9206..de95e9be3d7c37f28edd121171b9d1f4fca79f75 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -1363,11 +1363,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 	axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL);
 	if (PLAYERINPUTDOWN(ssplayer, GC_FIRENORMAL) || (usejoystick && axis > 0))
 		cmd->buttons |= BT_FIRENORMAL;
-	
+
 	// Toss flag button
 	if (PLAYERINPUTDOWN(ssplayer, GC_TOSSFLAG))
 		cmd->buttons |= BT_TOSSFLAG;
-	
+
 	// Shield button
 	axis = PlayerJoyAxis(ssplayer, JA_SHIELD);
 	if (PLAYERINPUTDOWN(ssplayer, GC_SHIELD) || (usejoystick && axis > 0))
@@ -4018,7 +4018,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent)
 	INT32 i;
 	INT16 newmapnum;
 	boolean spec = G_IsSpecialStage(gamemap);
-	
+
 	// go to next level
 	// newmapnum is 0-based, unlike gamemap
 	if (nextmapoverride != 0)
@@ -4122,7 +4122,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent)
 
 	if (spec && (!gottoken || ignoretokens) && !nextmapoverride)
 		newmapnum = lastmap; // Exiting from a special stage? Go back to the game. Tails 08-11-2001
-	
+
 	if (!(gametyperules & GTR_CAMPAIGN))
 	{
 		if (cv_advancemap.value == 0) // Stay on same map.
@@ -4130,7 +4130,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent)
 		else if (cv_advancemap.value == 2) // Go to random map.
 			newmapnum = RandMap(G_TOLFlag(gametype_to_use), prevmap);
 	}
-	
+
 	return newmapnum;
 }
 
@@ -4140,7 +4140,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent)
 static void G_DoCompleted(void)
 {
 	INT32 i;
-	
+
 	tokenlist = 0; // Reset the list
 
 	if (modeattacking && pausedelay)
@@ -4168,7 +4168,7 @@ static void G_DoCompleted(void)
 	//Get and set prevmap/nextmap
 	prevmap = (INT16)(gamemap-1);
 	nextmap = G_GetNextMap(false, false);
-	
+
 	automapactive = false;
 
 	// We are committed to this map now.
diff --git a/src/m_menu.c b/src/m_menu.c
index 7ba5fa12f5f88a891d6c3ae5e44e7bea21cf8ecb..e0c240fecc773d2ef9f0931205f05a02315a74c2 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -7000,7 +7000,10 @@ static void M_LevelSelectWarp(INT32 choice)
 	if (currentMenu == &SP_LevelSelectDef || currentMenu == &SP_PauseLevelSelectDef)
 	{
 		if (cursaveslot > 0) // do we have a save slot to load?
+		{
+			CV_StealthSet(&cv_skin, DEFAULTSKIN); // already handled by loadgame so we don't want this
 			G_LoadGame((UINT32)cursaveslot, startmap); // reload from SP save data: this is needed to keep score/lives/continues from reverting to defaults
+		}
 		else // no save slot, start new game but keep the current skin
 		{
 			M_ClearMenus(true);
@@ -8649,9 +8652,14 @@ static void M_LoadSelect(INT32 choice)
 		M_NewGame();
 	}
 	else if (savegameinfo[saveSlotSelected-1].gamemap & 8192) // Completed
+	{
 		M_LoadGameLevelSelect(0);
+	}
 	else
+	{
+		CV_StealthSet(&cv_skin, DEFAULTSKIN); // already handled by loadgame so we don't want this
 		G_LoadGame((UINT32)saveSlotSelected, 0);
+	}
 
 	cursaveslot = saveSlotSelected;
 }
@@ -9510,6 +9518,8 @@ static void M_ChoosePlayer(INT32 choice)
 	//lastmapsaved = 0;
 	gamecomplete = 0;
 
+	CV_StealthSet(&cv_skin, skins[skinnum]->name);
+
 	G_DeferedInitNew(ultmode, G_BuildMapName(startmap), skinnum, false, fromlevelselect);
 	COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this
 
diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c
index 91635cf308529ebf17d8a99bc3e2ebd6a9afcd7e..f7b98c4dbaff55d58481b5c439623a92fcd4e4c4 100644
--- a/src/netcode/d_netcmd.c
+++ b/src/netcode/d_netcmd.c
@@ -1309,7 +1309,7 @@ static void SendNameAndColor(void)
 
 		SetColorLocal(consoleplayer, cv_playercolor.value);
 
-		if (splitscreen)
+		if (splitscreen || (!pickedchar && stricmp(cv_skin.string, skins[consoleplayer]->name) != 0))
 			SetSkinLocal(consoleplayer, R_SkinAvailable(cv_skin.string));
 		else
 			SetSkinLocal(consoleplayer, pickedchar);
@@ -4609,7 +4609,7 @@ static void Command_ExitLevel_f(void)
 			SendNetXCmd(XD_EXITLEVEL, NULL, 0);
 			return;
 		}
-		
+
 		// Allow exiting without cheating if at least one player beat the level
 		// Consistent with just setting playersforexit to one
 		if (splitscreen || multiplayer)
@@ -4623,7 +4623,7 @@ static void Command_ExitLevel_f(void)
 					continue;
 				if (players[i].lives <= 0)
 					continue;
-		
+
 				if ((players[i].pflags & PF_FINISHED) || players[i].exiting)
 				{
 					SendNetXCmd(XD_EXITLEVEL, NULL, 0);
@@ -4631,7 +4631,7 @@ static void Command_ExitLevel_f(void)
 				}
 			}
 		}
-		
+
 		// Only consider it a cheat if we're not allowed to go to the next map
 		if (M_CampaignWarpIsCheat(gametype, G_GetNextMap(true, true) + 1, serverGamedata))
 			CONS_Alert(CONS_NOTICE, M_GetText("Cheats must be enabled to force exit to a locked level!\n"));
@@ -4770,7 +4770,7 @@ static void Command_Cheats_f(void)
 			G_SetUsedCheats(false);
 		return;
 	}
-	
+
 	if (usedCheats)
 		CONS_Printf(M_GetText("Cheats are enabled, the game cannot be saved.\n"));
 	else
@@ -4942,6 +4942,8 @@ static boolean Skin2_CanChange(const char *valstr)
   */
 static void Skin_OnChange(void)
 {
+	pickedchar = R_SkinAvailable(cv_skin.string);
+
 	if (!Playing())
 		return;