diff --git a/src/d_main.c b/src/d_main.c
index 61255e2722574bc6e28a6acd2fa461913c4fd67b..3918d8118c0c1cfd242c70b7f04148b26612f8c8 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -96,6 +96,10 @@ int	snprintf(char *str, size_t n, const char *fmt, ...);
 #include "hardware/hw3sound.h"
 #endif
 
+#ifdef HAVE_BLUA
+#include "lua_script.h"
+#endif
+
 // platform independant focus loss
 UINT8 window_notinfocus = false;
 
@@ -634,6 +638,10 @@ void D_SRB2Loop(void)
 #ifdef HW3SOUND
 		HW3S_EndFrameUpdate();
 #endif
+
+#ifdef HAVE_BLUA
+		LUA_Step();
+#endif
 	}
 }
 
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 52c218000cf51458eeebd7dad4b1bbc50157f7ab..0415d23e61acfe98705ec8855846b06297fcdf02 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -204,7 +204,6 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return hooked;
 }
 
@@ -238,7 +237,6 @@ boolean LUAh_PlayerHook(player_t *plr, enum hook which)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return hooked;
 }
 
@@ -262,7 +260,6 @@ void LUAh_MapChange(void)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 }
 
 // Hook for map load
@@ -285,7 +282,6 @@ void LUAh_MapLoad(void)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 }
 
 // Hook for Got_AddPlayer
@@ -308,7 +304,6 @@ void LUAh_PlayerJoin(int playernum)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCCOLLECT, 0);
 }
 
 // Hook for frame (after mobj and player thinkers)
@@ -330,8 +325,6 @@ void LUAh_ThinkFrame(void)
 				hookp->error = true;
 			}
 		}
-
-	lua_gc(gL, LUA_GCSTEP, 1);
 }
 
 // Hook for mobj collisions
@@ -375,7 +368,6 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return shouldCollide;
 }
 
@@ -415,7 +407,6 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return hooked;
 }
 
@@ -464,7 +455,6 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return shouldDamage;
 }
 
@@ -508,7 +498,6 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return hooked;
 }
 
@@ -550,7 +539,6 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return hooked;
 }
 
@@ -589,7 +577,6 @@ boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return hooked;
 }
 
@@ -651,7 +638,6 @@ boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return hooked;
 }
 
@@ -685,7 +671,6 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return hooked;
 }
 
@@ -739,7 +724,6 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return hooked;
 }
 
@@ -781,7 +765,6 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source)
 		}
 
 	lua_settop(gL, 0);
-	lua_gc(gL, LUA_GCSTEP, 1);
 	return hooked;
 }
 
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 86ff11337a6fcd02e763da75ee612eb5ee789d1d..5a83d95b56a6a3a39cf7d0364c39a2866964dd26 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -674,8 +674,6 @@ void LUAh_GameHUD(player_t *stplayr)
 		LUA_Call(gL, 3);
 	}
 	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCCOLLECT, 0);
-
 	hud_running = false;
 }
 
@@ -701,8 +699,6 @@ void LUAh_ScoresHUD(void)
 		LUA_Call(gL, 1);
 	}
 	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCCOLLECT, 0);
-
 	hud_running = false;
 }
 
diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index 2dc14d6fc7dcfdb6975481df2b22d786186a52b5..0fddebabae628703c87f4efec7330489bfffc7cf 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -137,8 +137,6 @@ static void A_Lua(mobj_t *actor)
 		--superstack;
 		superactions[superstack] = NULL;
 	}
-
-	lua_gc(gL, LUA_GCSTEP, 1);
 }
 
 // Arbitrary states[] table index -> state_t *
diff --git a/src/lua_script.c b/src/lua_script.c
index a5b56bf715d02284100c61bc20d517995b317e6e..145104d9aac8c0c147bde29259377f8848512d81 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -939,6 +939,14 @@ static void NetArchiveHook(lua_CFunction archFunc)
 	lua_pop(gL, 2);
 }
 
+void LUA_Step(void)
+{
+	if (!gL)
+		return;
+	lua_settop(gL, 0);
+	lua_gc(gL, LUA_GCSTEP, 1);
+}
+
 void LUA_Archive(void)
 {
 	INT32 i;
diff --git a/src/lua_script.h b/src/lua_script.h
index 8437045ec9a9a519cdf9a587f9c617ff71897e2c..292160a0b5356e2494d6557207dfe20c2167d993 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -48,6 +48,7 @@ void LUA_InvalidateUserdata(void *data);
 void LUA_InvalidateLevel(void);
 void LUA_InvalidateMapthings(void);
 void LUA_InvalidatePlayer(player_t *player);
+void LUA_Step(void);
 void LUA_Archive(void);
 void LUA_UnArchive(void);
 void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c