diff --git a/src/f_finale.h b/src/f_finale.h
index c0c6360c316186698c1c78b200d56b3399f121f8..29e9b4d8c8676a827b58afc786b53b11ef68bd8f 100644
--- a/src/f_finale.h
+++ b/src/f_finale.h
@@ -82,7 +82,6 @@ typedef enum
 
 // Current menu parameters
 
-extern UINT8 titlemapinaction;
 extern mobj_t *titlemapcameraref;
 extern char curbgname[8];
 extern SINT8 curfadevalue;
diff --git a/src/g_state.h b/src/g_state.h
index 76c9bd16f1e63e76cdd5b60c9d14fed560f765f1..7ee0cfb6347ad5dabe6759eb53052faa1c1e6332 100644
--- a/src/g_state.h
+++ b/src/g_state.h
@@ -50,6 +50,7 @@ typedef enum
 } gameaction_t;
 
 extern gamestate_t gamestate;
+extern UINT8 titlemapinaction;
 extern UINT8 ultimatemode; // was sk_insane
 extern gameaction_t gameaction;
 
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 767ab2dd32bdbcd19ac15f4e4c7c3ff017245a0e..7d3ab2140c30417120f4f093ff4b465d91e76c53 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -33,8 +33,6 @@
 
 #define NOHUD if (hud_running)\
 return luaL_error(L, "HUD rendering code should not call this function!");
-#define INLEVEL if (gamestate != GS_LEVEL)\
-return luaL_error(L, "This function can only be used in a level!");
 
 boolean luaL_checkboolean(lua_State *L, int narg) {
 	luaL_checktype(L, narg, LUA_TBOOLEAN);
diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c
index 98d18d8db06713c4eed15cc9b5364d858956589d..c6856b426224b17f29f7fd26b122865ad0d51b51 100644
--- a/src/lua_consolelib.c
+++ b/src/lua_consolelib.c
@@ -28,9 +28,6 @@ return luaL_error(L, "HUD rendering code should not call this function!");
 // for functions not allowed in hooks or coroutines (supercedes above)
 #define NOHOOK if (!lua_lumploading)\
 		return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
-// for functions only allowed within a level
-#define INLEVEL if (gamestate != GS_LEVEL)\
-return luaL_error(L, "This function can only be used in a level!");
 
 static const char *cvname = NULL;
 
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index ded90daf08a8b5f76293f65c0af150fb455835d3..82843db4ee768a129f23e82e728d00964ffdcdde 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -333,8 +333,7 @@ static int lib_iterateSectorThinglist(lua_State *L)
 	mobj_t *state = NULL;
 	mobj_t *thing = NULL;
 
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 
 	if (lua_gettop(L) < 2)
 		return luaL_error(L, "Don't call sector.thinglist() directly, use it as 'for rover in sector.thinglist do <block> end'.");
@@ -369,8 +368,7 @@ static int lib_iterateSectorFFloors(lua_State *L)
 	ffloor_t *state = NULL;
 	ffloor_t *ffloor = NULL;
 
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 
 	if (lua_gettop(L) < 2)
 		return luaL_error(L, "Don't call sector.ffloors() directly, use it as 'for rover in sector.ffloors do <block> end'.");
@@ -1251,8 +1249,7 @@ static int bbox_get(lua_State *L)
 static int lib_iterateSectors(lua_State *L)
 {
 	size_t i = 0;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 	if (lua_gettop(L) < 2)
 		return luaL_error(L, "Don't call sectors.iterate() directly, use it as 'for sector in sectors.iterate do <block> end'.");
 	lua_settop(L, 2);
@@ -1270,8 +1267,7 @@ static int lib_iterateSectors(lua_State *L)
 static int lib_getSector(lua_State *L)
 {
 	int field;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "You cannot access this outside of a level!");
+	INLEVEL
 	lua_settop(L, 2);
 	lua_remove(L, 1); // dummy userdata table is unused.
 	if (lua_isnumber(L, 1))
@@ -1305,8 +1301,7 @@ static int lib_numsectors(lua_State *L)
 static int lib_iterateSubsectors(lua_State *L)
 {
 	size_t i = 0;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 	if (lua_gettop(L) < 2)
 		return luaL_error(L, "Don't call subsectors.iterate() directly, use it as 'for subsector in subsectors.iterate do <block> end'.");
 	lua_settop(L, 2);
@@ -1324,8 +1319,7 @@ static int lib_iterateSubsectors(lua_State *L)
 static int lib_getSubsector(lua_State *L)
 {
 	int field;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "You cannot access this outside of a level!");
+	INLEVEL
 	lua_settop(L, 2);
 	lua_remove(L, 1); // dummy userdata table is unused.
 	if (lua_isnumber(L, 1))
@@ -1359,8 +1353,7 @@ static int lib_numsubsectors(lua_State *L)
 static int lib_iterateLines(lua_State *L)
 {
 	size_t i = 0;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 	if (lua_gettop(L) < 2)
 		return luaL_error(L, "Don't call lines.iterate() directly, use it as 'for line in lines.iterate do <block> end'.");
 	lua_settop(L, 2);
@@ -1378,8 +1371,7 @@ static int lib_iterateLines(lua_State *L)
 static int lib_getLine(lua_State *L)
 {
 	int field;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "You cannot access this outside of a level!");
+	INLEVEL
 	lua_settop(L, 2);
 	lua_remove(L, 1); // dummy userdata table is unused.
 	if (lua_isnumber(L, 1))
@@ -1413,8 +1405,7 @@ static int lib_numlines(lua_State *L)
 static int lib_iterateSides(lua_State *L)
 {
 	size_t i = 0;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 	if (lua_gettop(L) < 2)
 		return luaL_error(L, "Don't call sides.iterate() directly, use it as 'for side in sides.iterate do <block> end'.");
 	lua_settop(L, 2);
@@ -1432,8 +1423,7 @@ static int lib_iterateSides(lua_State *L)
 static int lib_getSide(lua_State *L)
 {
 	int field;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "You cannot access this outside of a level!");
+	INLEVEL
 	lua_settop(L, 2);
 	lua_remove(L, 1); // dummy userdata table is unused.
 	if (lua_isnumber(L, 1))
@@ -1467,8 +1457,7 @@ static int lib_numsides(lua_State *L)
 static int lib_iterateVertexes(lua_State *L)
 {
 	size_t i = 0;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 	if (lua_gettop(L) < 2)
 		return luaL_error(L, "Don't call vertexes.iterate() directly, use it as 'for vertex in vertexes.iterate do <block> end'.");
 	lua_settop(L, 2);
@@ -1486,8 +1475,7 @@ static int lib_iterateVertexes(lua_State *L)
 static int lib_getVertex(lua_State *L)
 {
 	int field;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "You cannot access this outside of a level!");
+	INLEVEL
 	lua_settop(L, 2);
 	lua_remove(L, 1); // dummy userdata table is unused.
 	if (lua_isnumber(L, 1))
@@ -1523,8 +1511,7 @@ static int lib_numvertexes(lua_State *L)
 static int lib_iterateSegs(lua_State *L)
 {
 	size_t i = 0;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 	if (lua_gettop(L) < 2)
 		return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do <block> end'.");
 	lua_settop(L, 2);
@@ -1542,8 +1529,7 @@ static int lib_iterateSegs(lua_State *L)
 static int lib_getSeg(lua_State *L)
 {
 	int field;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "You cannot access this outside of a level!");
+	INLEVEL
 	lua_settop(L, 2);
 	lua_remove(L, 1); // dummy userdata table is unused.
 	if (lua_isnumber(L, 1))
@@ -1577,8 +1563,7 @@ static int lib_numsegs(lua_State *L)
 static int lib_iterateNodes(lua_State *L)
 {
 	size_t i = 0;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 	if (lua_gettop(L) < 2)
 		return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do <block> end'.");
 	lua_settop(L, 2);
@@ -1596,8 +1581,7 @@ static int lib_iterateNodes(lua_State *L)
 static int lib_getNode(lua_State *L)
 {
 	int field;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "You cannot access this outside of a level!");
+	INLEVEL
 	lua_settop(L, 2);
 	lua_remove(L, 1); // dummy userdata table is unused.
 	if (lua_isnumber(L, 1))
diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c
index 8bbbebe1d4c1340e974bd4df7e3d9b29d8ddaa1a..de1b854f6234a9b6d1f5ec2a0e3e7bebfbb1f1d6 100644
--- a/src/lua_mobjlib.c
+++ b/src/lua_mobjlib.c
@@ -816,8 +816,7 @@ static int mapthing_set(lua_State *L)
 static int lib_iterateMapthings(lua_State *L)
 {
 	size_t i = 0;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 	if (lua_gettop(L) < 2)
 		return luaL_error(L, "Don't call mapthings.iterate() directly, use it as 'for mapthing in mapthings.iterate do <block> end'.");
 	lua_settop(L, 2);
@@ -835,8 +834,7 @@ static int lib_iterateMapthings(lua_State *L)
 static int lib_getMapthing(lua_State *L)
 {
 	int field;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "You cannot access this outside of a level!");
+	INLEVEL
 	lua_settop(L, 2);
 	lua_remove(L, 1); // dummy userdata table is unused.
 	if (lua_isnumber(L, 1))
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index 700dab21100acb79d222be025ae3ca4b728ab8a0..b7bdaa1be87a078974490fe569e171c15906b319 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -25,8 +25,7 @@
 static int lib_iteratePlayers(lua_State *L)
 {
 	INT32 i = -1;
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 	if (lua_gettop(L) < 2)
 	{
 		//return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'.");
@@ -53,8 +52,7 @@ static int lib_getPlayer(lua_State *L)
 {
 	const char *field;
 	// i -> players[i]
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "You cannot access this outside of a level!");
+	INLEVEL
 	if (lua_type(L, 2) == LUA_TNUMBER)
 	{
 		lua_Integer i = luaL_checkinteger(L, 2);
diff --git a/src/lua_script.h b/src/lua_script.h
index b690e4fa7577e6f0076a7f6d7b878bde9d01581d..fcbca29379e0acd50aeeab20250696ee16a3233d 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -15,6 +15,7 @@
 #include "m_fixed.h"
 #include "doomtype.h"
 #include "d_player.h"
+#include "g_state.h"
 
 #include "blua/lua.h"
 #include "blua/lualib.h"
@@ -97,4 +98,7 @@ void COM_Lua_f(void);
 // uncomment if you want seg_t/node_t in Lua
 // #define HAVE_LUA_SEGS
 
+#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\
+return luaL_error(L, "This can only be used in a level!");
+
 #endif
diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c
index 63eb15846b29a2b465b26a662144dcf5d757d92d..877294898e1483541b12d093adf70b9accb9cd35 100644
--- a/src/lua_thinkerlib.c
+++ b/src/lua_thinkerlib.c
@@ -56,8 +56,7 @@ static int lib_iterateThinkers(lua_State *L)
 	thinker_t *th = NULL, *next = NULL;
 	struct iterationState *it;
 
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 
 	it = luaL_checkudata(L, 1, META_ITERATIONSTATE);
 
@@ -112,8 +111,7 @@ static int lib_startIterate(lua_State *L)
 {
 	struct iterationState *it;
 
-	if (gamestate != GS_LEVEL)
-		return luaL_error(L, "This function can only be used in a level!");
+	INLEVEL
 
 	lua_pushvalue(L, lua_upvalueindex(1));
 	it = lua_newuserdata(L, sizeof(struct iterationState));