diff --git a/src/lua_hook.h b/src/lua_hook.h
index c22309eaaea94a43c054f44d4cf9f57e003567b5..3a5ba3afd4af2be4a79eeed06a354a0b5c10b47a 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -111,7 +111,7 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnM
 boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following
 UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage
 void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player quitting
-void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
+void LUAh_IntermissionThinker(boolean stagefailed); // Hook for Y_Ticker
 boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh....
 UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode
 boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 3715aae049b6c85201813ea7f43a07526163be9c..5dca0d7a0435f85743a9c1f1c2a2036168abb810 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -1633,7 +1633,7 @@ void LUAh_PlayerQuit(player_t *plr, kickreason_t reason)
 }
 
 // Hook for Y_Ticker
-void LUAh_IntermissionThinker(void)
+void LUAh_IntermissionThinker(boolean failedstage)
 {
 	hook_p hookp;
 	if (!gL || !(hooksAvailable[hook_IntermissionThinker/8] & (1<<(hook_IntermissionThinker%8))))
@@ -1646,8 +1646,11 @@ void LUAh_IntermissionThinker(void)
 		if (hookp->type != hook_IntermissionThinker)
 			continue;
 
+		lua_pushboolean(gL, failedstage); // stagefailed
+
 		PushHook(gL, hookp);
-		if (lua_pcall(gL, 0, 0, 1)) {
+		lua_pushvalue(gL, -2); // stagefailed
+		if (lua_pcall(gL, 1, 0, 1)) {
 			if (!hookp->error || cv_debug & DBG_LUA)
 				CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
 			lua_pop(gL, 1);
diff --git a/src/lua_hud.h b/src/lua_hud.h
index a7b1a4cf58a6159fc9eacb811770dc9dd0761d62..d2f5bceca6f0d56745d2a40c3826ea1e594b9718 100644
--- a/src/lua_hud.h
+++ b/src/lua_hud.h
@@ -37,7 +37,9 @@ enum hud {
 	hud_tabemblems,
 	// Intermission
 	hud_intermissiontally,
+	hud_intermissiontitletext,
 	hud_intermissionmessages,
+	hud_intermissionemeralds,
 	hud_MAX
 };
 
@@ -49,4 +51,4 @@ void LUAh_GameHUD(player_t *stplyr);
 void LUAh_ScoresHUD(void);
 void LUAh_TitleHUD(void);
 void LUAh_TitleCardHUD(player_t *stplayr);
-void LUAh_IntermissionHUD(void);
+void LUAh_IntermissionHUD(boolean failedstage);
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index b0548c3212931e8ce4f377dddd5a7ff68f97551b..9a3e676d5fd6168fd64bfaaa44466a5e85e8949c 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -63,7 +63,9 @@ static const char *const hud_disable_options[] = {
 	"tabemblems",
 
 	"intermissiontally",
+	"intermissiontitletext",
 	"intermissionmessages",
+	"intermissionemeralds",
 	NULL};
 
 enum hudinfo {
@@ -857,6 +859,26 @@ static int libd_drawScaledNameTag(lua_State *L)
 	return 0;
 }
 
+static int libd_drawLevelTitle(lua_State *L)
+{
+	INT32 x;
+	INT32 y;
+	const char *str;
+	INT32 flags;
+
+	HUDONLY
+
+	x = luaL_checkinteger(L, 1);
+	y = luaL_checkinteger(L, 2);
+	str = luaL_checkstring(L, 3);
+	flags = luaL_optinteger(L, 4, 0);
+
+	flags &= ~V_PARAMMASK; // Don't let crashes happen.
+
+	V_DrawLevelTitle(x, y, flags, str);
+	return 0;
+}
+
 static int libd_stringWidth(lua_State *L)
 {
 	const char *str = luaL_checkstring(L, 1);
@@ -886,6 +908,20 @@ static int libd_nameTagWidth(lua_State *L)
 	return 1;
 }
 
+static int libd_levelTitleWidth(lua_State *L)
+{
+	HUDONLY
+	lua_pushinteger(L, V_LevelNameWidth(luaL_checkstring(L, 1)));
+	return 1;
+}
+
+static int libd_levelTitleHeight(lua_State *L)
+{
+	HUDONLY
+	lua_pushinteger(L, V_LevelNameHeight(luaL_checkstring(L, 1)));
+	return 1;
+}
+
 static int libd_getColormap(lua_State *L)
 {
 	INT32 skinnum = TC_DEFAULT;
@@ -1091,10 +1127,13 @@ static luaL_Reg lib_draw[] = {
 	{"drawString", libd_drawString},
 	{"drawNameTag", libd_drawNameTag},
 	{"drawScaledNameTag", libd_drawScaledNameTag},
+	{"drawLevelTitle", libd_drawLevelTitle},
 	{"fadeScreen", libd_fadeScreen},
 	// misc
 	{"stringWidth", libd_stringWidth},
 	{"nameTagWidth", libd_nameTagWidth},
+	{"levelTitleWidth", libd_levelTitleWidth},
+	{"levelTitleHeight", libd_levelTitleHeight},
 	// m_random
 	{"RandomFixed",libd_RandomFixed},
 	{"RandomByte",libd_RandomByte},
@@ -1384,7 +1423,7 @@ void LUAh_TitleCardHUD(player_t *stplayr)
 	hud_running = false;
 }
 
-void LUAh_IntermissionHUD(void)
+void LUAh_IntermissionHUD(boolean failedstage)
 {
 	if (!gL || !(hudAvailable & (1<<hudhook_intermission)))
 		return;
@@ -1402,10 +1441,14 @@ void LUAh_IntermissionHUD(void)
 	lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
 	I_Assert(lua_istable(gL, -1));
 	lua_remove(gL, -3); // pop HUD
+
+	lua_pushboolean(gL, failedstage); // stagefailed
 	lua_pushnil(gL);
-	while (lua_next(gL, -3) != 0) {
-		lua_pushvalue(gL, -3); // graphics library (HUD[1])
-		LUA_Call(gL, 1, 0, 1);
+
+	while (lua_next(gL, -4) != 0) {
+		lua_pushvalue(gL, -4); // graphics library (HUD[1])
+		lua_pushvalue(gL, -4); // stagefailed
+		LUA_Call(gL, 2, 0, 1);
 	}
 	lua_settop(gL, 0);
 	hud_running = false;
diff --git a/src/y_inter.c b/src/y_inter.c
index 6d807c63f4eb9f2620decfcb98619d64b3145077..6d3ec2cb50ecfab1e70280acd2330c163587f740 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -430,7 +430,7 @@ void Y_IntermissionDrawer(void)
 	else if (bgtile)
 		V_DrawPatchFill(bgtile);
 
-	LUAh_IntermissionHUD();
+	LUAh_IntermissionHUD(intertype == int_spec && stagefailed);
 	if (!LUA_HudEnabled(hud_intermissiontally))
 		goto skiptallydrawer;
 
@@ -471,14 +471,17 @@ void Y_IntermissionDrawer(void)
 			}
 		}
 
-		// draw the "got through act" lines and act number
-		V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1);
+		if (LUA_HudEnabled(hud_intermissiontitletext))
 		{
-			INT32 h = V_LevelNameHeight(data.coop.passed2);
-			V_DrawLevelTitle(data.coop.passedx2, 49+h+2, 0, data.coop.passed2);
+			// draw the "got through act" lines and act number
+			V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1);
+			{
+				INT32 h = V_LevelNameHeight(data.coop.passed2);
+				V_DrawLevelTitle(data.coop.passedx2, 49+h+2, 0, data.coop.passed2);
 
-			if (data.coop.actnum)
-				V_DrawLevelActNum(244, 42+h, 0, data.coop.actnum);
+				if (data.coop.actnum)
+					V_DrawLevelActNum(244, 42+h, 0, data.coop.actnum);
+			}
 		}
 
 		bonusy = 150;
@@ -562,37 +565,44 @@ void Y_IntermissionDrawer(void)
 
 		if (drawsection == 1)
 		{
-			const char *ringtext = "\x82" "50 rings, no shield";
-			const char *tut1text = "\x82" "press " "\x80" "spin";
-			const char *tut2text = "\x82" "mid-" "\x80" "jump";
-			ttheight = 8;
-			V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1);
-			ttheight += V_LevelNameHeight(data.spec.passed3) + 2;
-			V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3);
-			ttheight += V_LevelNameHeight(data.spec.passed4) + 2;
-			V_DrawLevelTitle(data.spec.passedx4 + xoffset3, ttheight, 0, data.spec.passed4);
-
-			ttheight = 108;
-			V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset4 - (V_LevelNameWidth(ringtext)/2), ttheight, 0, ringtext);
-			ttheight += V_LevelNameHeight(tut1text) + 2;
-			V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset5 - (V_LevelNameWidth(tut1text)/2), ttheight, 0, tut1text);
-			ttheight += V_LevelNameHeight(tut2text) + 2;
-			V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset6 - (V_LevelNameWidth(tut2text)/2), ttheight, 0, tut2text);
+			if (LUA_HudEnabled(hud_intermissiontitletext))
+			{
+				const char *ringtext = "\x82" "50 rings, no shield";
+				const char *tut1text = "\x82" "press " "\x80" "spin";
+				const char *tut2text = "\x82" "mid-" "\x80" "jump";
+				ttheight = 8;
+				V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1);
+				ttheight += V_LevelNameHeight(data.spec.passed3) + 2;
+				V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3);
+				ttheight += V_LevelNameHeight(data.spec.passed4) + 2;
+				V_DrawLevelTitle(data.spec.passedx4 + xoffset3, ttheight, 0, data.spec.passed4);
+
+				ttheight = 108;
+				V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset4 - (V_LevelNameWidth(ringtext)/2), ttheight, 0, ringtext);
+				ttheight += V_LevelNameHeight(tut1text) + 2;
+				V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset5 - (V_LevelNameWidth(tut1text)/2), ttheight, 0, tut1text);
+				ttheight += V_LevelNameHeight(tut2text) + 2;
+				V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset6 - (V_LevelNameWidth(tut2text)/2), ttheight, 0, tut2text);
+			}
 		}
 		else
 		{
 			INT32 yoffset = 0;
-			if (data.spec.passed1[0] != '\0')
-			{
-				ttheight = 24;
-				V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1);
-				ttheight += V_LevelNameHeight(data.spec.passed2) + 2;
-				V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2);
-			}
-			else
+
+			if (LUA_HudEnabled(hud_intermissiontitletext))
 			{
-				ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2;
-				V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2);
+				if (data.spec.passed1[0] != '\0')
+				{
+					ttheight = 24;
+					V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1);
+					ttheight += V_LevelNameHeight(data.spec.passed2) + 2;
+					V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2);
+				}
+				else
+				{
+					ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2;
+					V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2);
+				}
 			}
 
 			V_DrawScaledPatch(152 + xoffset3, 108, 0, data.spec.bonuspatches[0]);
@@ -638,6 +648,7 @@ void Y_IntermissionDrawer(void)
 
 		// draw the emeralds
 		//if (intertic & 1)
+		if (LUA_HudEnabled(hud_intermissionemeralds))
 		{
 			boolean drawthistic = !(ALL7EMERALDS(emeralds) && (intertic & 1));
 			INT32 emeraldx = 152 - 3*28;
@@ -1010,7 +1021,7 @@ void Y_Ticker(void)
 	if (paused || P_AutoPause())
 		return;
 
-	LUAh_IntermissionThinker();
+	LUAh_IntermissionThinker(intertype == int_spec && stagefailed);
 
 	intertic++;