diff --git a/src/command.c b/src/command.c
index 305a5eeeb94fe82415fc9f5e8e27a6a8dcf618eb..54406adeb95d681c4f7134a436630dbffe21ae86 100644
--- a/src/command.c
+++ b/src/command.c
@@ -28,6 +28,7 @@
 #include "byteptr.h"
 #include "p_saveg.h"
 #include "g_game.h" // for player_names
+#include "m_cond.h" // for encore mode
 #include "d_netcmd.h"
 #include "hu_stuff.h"
 #include "p_setup.h"
@@ -1373,6 +1374,12 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth)
 			return;
 		}
 
+		if (var == &cv_kartencore && !M_SecretUnlocked(SECRET_ENCORE))
+		{
+			CONS_Printf(M_GetText("You haven't unlocked Encore Mode yet!\n"));
+			return;
+		}
+
 		// Only add to netcmd buffer if in a netgame, otherwise, just change it.
 		if (netgame || multiplayer)
 		{
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index e1e0a6353a8ffda5a0b96bbcca6db6f4d157ff03..a504453e585653f77f143af2fb04e4056e5dcf71 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -352,7 +352,7 @@ static CV_PossibleValue_t kartbumpers_cons_t[] = {{1, "MIN"}, {12, "MAX"}, {0, N
 consvar_t cv_kartbumpers = {"kartbumpers", "3", CV_NETVAR|CV_CHEAT, kartbumpers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartFrantic_OnChange, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL};
 static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}};
 consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
 static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
@@ -5249,11 +5249,11 @@ static void KartEncore_OnChange(void)
 	if (G_RaceGametype())
 	{
 		if ((boolean)cv_kartencore.value != encoremode && gamestate == GS_LEVEL /*&& leveltime > starttime*/)
-			CONS_Printf(M_GetText("Encore tracks will be turned %s next round.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off"));
+			CONS_Printf(M_GetText("Encore Mode will be turned %s next round.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off"));
 		else
 		{
-			CONS_Printf(M_GetText("Encore tracks have been turned %s.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off"));
-			encoremode = (boolean)cv_kartencore.value;
+			CONS_Printf(M_GetText("Encore Mode has been turned %s.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off"));
+			//encoremode = (boolean)cv_kartencore.value;
 		}
 	}
 }
diff --git a/src/dehacked.c b/src/dehacked.c
index 8fcf597dfe15cc32009b6f586d9b224976fda1ed..15586934de2a4de22f4b0e48fdd0572e292a763a 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -2384,8 +2384,8 @@ static void readunlockable(MYFILE *f, INT32 num)
 			else if (fastcmp(word, "OBJECTIVE"))
 				deh_strlcpy(unlockables[num].objective, word2,
 					sizeof (unlockables[num].objective), va("Unlockable %d: objective", num));
-			else if (fastcmp(word, "HEIGHT"))
-				unlockables[num].height = (UINT16)i;
+			else if (fastcmp(word, "SHOWCONDITIONSET"))
+				unlockables[num].showconditionset = (UINT8)i;
 			else if (fastcmp(word, "CONDITIONSET"))
 				unlockables[num].conditionset = (UINT8)i;
 			else if (fastcmp(word, "NOCECHO"))
@@ -2416,6 +2416,8 @@ static void readunlockable(MYFILE *f, INT32 num)
 					unlockables[num].type = SECRET_WARP;
 				else if (fastcmp(word2, "SOUNDTEST"))
 					unlockables[num].type = SECRET_SOUNDTEST;
+				else if (fastcmp(word2, "ENCORE"))
+					unlockables[num].type = SECRET_ENCORE;
 				else
 					unlockables[num].type = (INT16)i;
 			}
diff --git a/src/m_cond.c b/src/m_cond.c
index 7d07d00ad7cadeb2e982b0fd9a25ce59ce96a24e..63f88cb610b68ef7a3a6e3bf42d4f52f7e554eb3 100644
--- a/src/m_cond.c
+++ b/src/m_cond.c
@@ -96,12 +96,14 @@ extraemblem_t extraemblems[MAXEXTRAEMBLEMS] =
 // Default Unlockables
 unlockable_t unlockables[MAXUNLOCKABLES] =
 {
-	// Name, Objective, Menu Height, ConditionSet, Unlock Type, Variable, NoCecho, NoChecklist
-	/* 01 */ {"Egg Cup",  "", 0, 1, SECRET_NONE, 0, false, false, 0},
-	/* 02 */ {"SMK Cup",  "", 0, 2, SECRET_NONE, 0, false, false, 0},
-	/* 03 */ {"Chao Cup", "", 0, 3, SECRET_NONE, 0, false, false, 0},
+	// Name, Objective, Showing Conditionset, ConditionSet, Unlock Type, Variable, NoCecho, NoChecklist
+	/* 01 */ {"Egg Cup",  "", -1, 1, SECRET_NONE, 0, false, false, 0},
+	/* 02 */ {"SMK Cup",  "", -1, 2, SECRET_NONE, 0, false, false, 0},
+	/* 03 */ {"Chao Cup", "", -1, 3, SECRET_NONE, 0, false, false, 0},
 
-	/* 04 */ {"Record Attack", "", 0, -1, SECRET_RECORDATTACK, 0, true, true, 0},
+	/* 04 */ {"Encore Mode", "", 3, 4, SECRET_ENCORE, 0, false, false, 0},
+
+	/* 05 */ {"Record Attack", "", -1, -1, SECRET_RECORDATTACK, 0, true, true, 0},
 };
 
 // Default number of emblems and extra emblems
@@ -125,6 +127,10 @@ void M_SetupDefaultConditionSets(void)
 	M_AddRawCondition(3, 1, UC_TOTALEMBLEMS, 30, 0, 0);
 	M_AddRawCondition(3, 2, UC_MATCHESPLAYED, 50, 0, 0);
 
+	// -- 4: Collect 50 emblems OR play 150 matches
+	M_AddRawCondition(4, 1, UC_TOTALEMBLEMS, 50, 0, 0);
+	M_AddRawCondition(4, 2, UC_MATCHESPLAYED, 150, 0, 0);
+
 	// -- 10: Play 100 matches
 	M_AddRawCondition(10, 1, UC_MATCHESPLAYED, 100, 0, 0);
 }
diff --git a/src/m_cond.h b/src/m_cond.h
index 052c31f2f8af9f2eb647cb3ef5c6841027185900..5c8762ad8c0ae0ef92c55396b052b7785a589d77 100644
--- a/src/m_cond.h
+++ b/src/m_cond.h
@@ -103,7 +103,7 @@ typedef struct
 {
 	char name[64];
 	char objective[64];
-	UINT16 height; // menu height
+	UINT8 showconditionset;
 	UINT8 conditionset;
 	INT16 type;
 	INT16 variable;
@@ -112,6 +112,7 @@ typedef struct
 	UINT8 unlocked;
 } unlockable_t;
 
+// I have NO idea why these are going negative, but whatever.
 #define SECRET_NONE         -6 // Does nil.  Use with levels locked by UnlockRequired
 #define SECRET_ITEMFINDER	-5 // Enables Item Finder/Emblem Radar
 #define SECRET_EMBLEMHINTS	-4 // Enables Emblem Hints
@@ -123,6 +124,7 @@ typedef struct
 #define SECRET_WARP			 2 // Selectable warp
 #define SECRET_SOUNDTEST	 3 // Sound Test
 #define SECRET_CREDITS		 4 // Enables Credits
+#define SECRET_ENCORE        5 // Enables Encore mode cvar
 
 // If you have more secrets than these variables allow in your game,
 // you seriously need to get a life.
diff --git a/src/m_menu.c b/src/m_menu.c
index 3e12c65d799edc0a352e5aa3084f021c806e13ed..07a2a9c3cc9fd6f1f4f234f1978abbb30208662a 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -1444,7 +1444,7 @@ static menuitem_t OP_GameOptionsMenu[] =
 
 	{IT_STRING | IT_CVAR, NULL, "Game Speed",					&cv_kartspeed,			 30},
 	{IT_STRING | IT_CVAR, NULL, "Frantic Items",				&cv_kartfrantic,		 40},
-	{IT_STRING | IT_CVAR, NULL, "Encore Mode",					&cv_kartencore,			 50},
+	{IT_SECRET,           NULL, "Encore Mode",					&cv_kartencore,			 50},
 
 	{IT_STRING | IT_CVAR, NULL, "Number of Laps",				&cv_basenumlaps,		 70},
 	{IT_STRING | IT_CVAR, NULL, "Exit Countdown Timer",			&cv_countdowntime,		 80},
@@ -4311,6 +4311,9 @@ static void M_Options(INT32 choice)
 	OP_MainMenu[7].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL);
 	OP_MainMenu[8].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU);
 
+	OP_GameOptionsMenu[3].status =
+		(M_SecretUnlocked(SECRET_ENCORE)) ? (IT_CVAR|IT_STRING) : IT_SECRET; // cv_kartencore
+
 	OP_MainDef.prevMenu = currentMenu;
 	M_SetupNextMenu(&OP_MainDef);
 }
@@ -4463,7 +4466,8 @@ static void M_DrawChecklist(void)
 	for (i = 0; i < MAXUNLOCKABLES; i++)
 	{
 		if (unlockables[i].name[0] == 0 || unlockables[i].nochecklist
-		|| !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS)
+		|| !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS
+		|| !M_Achieved(unlockables[i].showconditionset - 1))
 			continue;
 
 		++line;
diff --git a/src/p_setup.c b/src/p_setup.c
index 196eb5c72c03f07fe1461befc86771cc04eecbbb..39a26260ce277f3e3d51c30547f197a541183bfa 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -136,6 +136,8 @@ mapthing_t *playerstarts[MAXPLAYERS];
 mapthing_t *bluectfstarts[MAXPLAYERS];
 mapthing_t *redctfstarts[MAXPLAYERS];
 
+boolean prevencoremode = false;
+
 /** Logs an error about a map being corrupt, then terminate.
   * This allows reporting highly technical errors for usefulness, without
   * confusing a novice map designer who simply needs to run ZenNode.
@@ -2245,6 +2247,8 @@ static void P_LevelInitStuff(void)
 		players[i].pflags &= ~PF_TRANSFERTOCLOSEST;
 	}
 
+	prevencoremode = ((wipegamestate == GS_TITLESCREEN) ? false : encoremode);
+
 	// SRB2Kart: map load variables
 	if (modeattacking) // Just play it safe and set everything
 	{
@@ -2647,7 +2651,7 @@ boolean P_SetupLevel(boolean skipprecip)
 
 	// Encore mode fade to pink to white
 	// This is handled BEFORE sounds are stopped.
-	if (rendermode != render_none && encoremode)
+	if (rendermode != render_none && encoremode && !prevencoremode)
 	{
 		tic_t starttime, endtime, nowtime;
 
@@ -2697,14 +2701,14 @@ boolean P_SetupLevel(boolean skipprecip)
 		S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); //S_StopMusic();
 
 	// Let's fade to white here
-	// But only if we didn't do the encore wipe
+	// But only if we didn't do the encore startup wipe
 	if (rendermode != render_none && !ranspecialwipe)
 	{
 		F_WipeStartScreen();
-		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120);
+		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (encoremode ? 122 : 120));
 
 		F_WipeEndScreen();
-		F_RunWipe(wipedefs[wipe_level_toblack], false);
+		F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
 	}
 
 	// Reset the palette now all fades have been done
@@ -3045,7 +3049,7 @@ boolean P_SetupLevel(boolean skipprecip)
 
 	// Remove the loading shit from the screen
 	if (rendermode != render_none)
-		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120);
+		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (encoremode && !ranspecialwipe ? 122 : 120));
 
 	if (precache || dedicated)
 		R_PrecacheLevel();