diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg
index 51332522585a9571f63fe03d9640f1b38b72040c..166836ca6f35d787a464ac238cebfb442f251106 100644
--- a/extras/conf/udb/Includes/SRB222_linedefs.cfg
+++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg
@@ -1737,6 +1737,31 @@ udmf
 				type = 13;
 			}
 		}
+
+		465
+		{
+			title = "Set Linedef Executor Delay";
+			prefix = "(465)";
+			arg0
+			{
+				title = "Linedef tag";
+				type = 15;
+			}
+			arg1
+			{
+				title = "Value";
+			}
+			arg2
+			{
+				title = "Set/add?";
+				type = 11;
+				enum
+				{
+					0 = "Set";
+					1 = "Add";
+				}
+			}
+		}
 	}
 
 	light
diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg
index bf8768d2aab41506ed407abe2a9b82733f7c8907..68629149e1b1bccb71e7d3752af271c3441031a7 100644
--- a/extras/conf/udb/Includes/SRB222_misc.cfg
+++ b/extras/conf/udb/Includes/SRB222_misc.cfg
@@ -242,6 +242,11 @@ universalfields
 			type = 2;
 			default = "";
 		}
+		executordelay
+		{
+			type = 0;
+			default = 0;
+		}
 	}
 
 	sidedef
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index 07fd7324b30bfd5f884cdcba3cf5bf928d7e759d..3e17e2ae17ba1671d93df267254724d1a7e5a5cf 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -91,6 +91,7 @@ enum line_e {
 	line_frontside,
 	line_backside,
 	line_alpha,
+	line_executordelay,
 	line_slopetype,
 	line_frontsector,
 	line_backsector,
@@ -115,6 +116,7 @@ static const char *const line_opt[] = {
 	"frontside",
 	"backside",
 	"alpha",
+	"executordelay",
 	"slopetype",
 	"frontsector",
 	"backsector",
@@ -792,6 +794,9 @@ static int line_get(lua_State *L)
 	case line_alpha:
 		lua_pushfixed(L, line->alpha);
 		return 1;
+	case line_executordelay:
+		lua_pushinteger(L, line->executordelay);
+		return 1;
 	case line_slopetype:
 		switch(line->slopetype)
 		{
diff --git a/src/p_saveg.c b/src/p_saveg.c
index b5a44b5d2476344f615284ea3cb5766e2d7afaf9..f40fd17fc396ae956e478b620c6c4da1cf578dda 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -755,12 +755,13 @@ static void P_NetUnArchiveColormaps(void)
 #define LD_DIFF2    0x80
 
 // diff2 flags
-#define LD_S2TEXOFF   0x01
-#define LD_S2TOPTEX   0x02
-#define LD_S2BOTTEX   0x04
-#define LD_S2MIDTEX   0x08
-#define LD_ARGS       0x10
-#define LD_STRINGARGS 0x20
+#define LD_S2TEXOFF      0x01
+#define LD_S2TOPTEX      0x02
+#define LD_S2BOTTEX      0x04
+#define LD_S2MIDTEX      0x08
+#define LD_ARGS          0x10
+#define LD_STRINGARGS    0x20
+#define LD_EXECUTORDELAY 0x40
 
 static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli)
 {
@@ -1086,6 +1087,9 @@ static void ArchiveLines(void)
 		if (!P_AreStringArgsEqual(li, spawnli))
 			diff2 |= LD_STRINGARGS;
 
+		if (li->executordelay != spawnli->executordelay)
+			diff2 |= LD_EXECUTORDELAY;
+
 		if (li->sidenum[0] != 0xffff)
 		{
 			si = &sides[li->sidenum[0]];
@@ -1174,6 +1178,8 @@ static void ArchiveLines(void)
 						WRITECHAR(save_p, li->stringargs[j][k]);
 				}
 			}
+			if (diff2 & LD_EXECUTORDELAY)
+				WRITEINT32(save_p, li->executordelay);
 		}
 	}
 	WRITEUINT16(save_p, 0xffff);
@@ -1256,6 +1262,9 @@ static void UnArchiveLines(void)
 				li->stringargs[j][len] = '\0';
 			}
 		}
+		if (diff2 & LD_EXECUTORDELAY)
+			li->executordelay = READINT32(save_p);
+
 	}
 }
 
diff --git a/src/p_setup.c b/src/p_setup.c
index 4ff9e61179bd05a0ac998bbfa9ebf8b2f0fceebe..06ccc6d4098a4c588edbb0b2f6e7c38d87e0d4bf 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1034,6 +1034,7 @@ static void P_LoadLinedefs(UINT8 *data)
 		memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
 		memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
 		ld->alpha = FRACUNIT;
+		ld->executordelay = 0;
 		P_SetLinedefV1(i, SHORT(mld->v1));
 		P_SetLinedefV2(i, SHORT(mld->v2));
 
@@ -1505,6 +1506,8 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
 		lines[i].sidenum[1] = atol(val);
 	else if (fastcmp(param, "alpha"))
 		lines[i].alpha = FLOAT_TO_FIXED(atof(val));
+	else if (fastcmp(param, "executordelay"))
+		lines[i].executordelay = atol(val);
 
 	// Flags
 	else if (fastcmp(param, "blocking") && fastcmp("true", val))
@@ -1740,6 +1743,7 @@ static void P_LoadTextmap(void)
 		memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
 		memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
 		ld->alpha = FRACUNIT;
+		ld->executordelay = 0;
 		ld->sidenum[0] = 0xffff;
 		ld->sidenum[1] = 0xffff;
 
@@ -3010,6 +3014,15 @@ static void P_ConvertBinaryMap(void)
 		default:
 			break;
 		}
+
+		//Linedef executor delay
+		if (lines[i].special >= 400 && lines[i].special < 500)
+		{
+			//Dummy value to indicate that this executor is delayed.
+			//The real value is taken from the back sector at runtime.
+			if (lines[i].flags & ML_DONTPEGTOP)
+				lines[i].executordelay = 1;
+		}
 	}
 
 	for (i = 0; i < nummapthings; i++)
diff --git a/src/p_spec.c b/src/p_spec.c
index f1d2c13b5c85464e909e1bb37e266b58589ab630..a68fd2b80b9646a88f0e16f629f363dc18597941 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1528,16 +1528,24 @@ void T_ExecutorDelay(executor_t *e)
 static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector)
 {
 	executor_t *e;
+	INT32 delay;
 
-	if (!line->backsector)
-		I_Error("P_AddExecutorDelay: Line has no backsector!\n");
+	if (udmf)
+		delay = line->executordelay;
+	else
+	{
+		if (!line->backsector)
+			I_Error("P_AddExecutorDelay: Line has no backsector!\n");
+
+		delay = (line->backsector->ceilingheight >> FRACBITS) + (line->backsector->floorheight >> FRACBITS);
+	}
 
 	e = Z_Calloc(sizeof (*e), PU_LEVSPEC, NULL);
 
 	e->thinker.function.acp1 = (actionf_p1)T_ExecutorDelay;
 	e->line = line;
 	e->sector = sector;
-	e->timer = (line->backsector->ceilingheight>>FRACBITS)+(line->backsector->floorheight>>FRACBITS);
+	e->timer = delay;
 	P_SetTarget(&e->caller, mobj); // Use P_SetTarget to make sure the mobj doesn't get freed while we're delaying.
 	P_AddThinker(THINK_MAIN, &e->thinker);
 }
@@ -1938,7 +1946,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 			if (ctlsector->lines[i]->special >= 400
 				&& ctlsector->lines[i]->special < 500)
 			{
-				if (ctlsector->lines[i]->flags & ML_DONTPEGTOP)
+				if (ctlsector->lines[i]->executordelay)
 					P_AddExecutorDelay(ctlsector->lines[i], actor, caller);
 				else
 					P_ProcessLineSpecial(ctlsector->lines[i], actor, caller);
@@ -2026,7 +2034,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 			if (ctlsector->lines[i]->special >= 400
 				&& ctlsector->lines[i]->special < 500)
 			{
-				if (ctlsector->lines[i]->flags & ML_DONTPEGTOP)
+				if (ctlsector->lines[i]->executordelay)
 					P_AddExecutorDelay(ctlsector->lines[i], actor, caller);
 				else
 					P_ProcessLineSpecial(ctlsector->lines[i], actor, caller);
@@ -4005,6 +4013,23 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			}
 			break;
 
+		case 465: // Set linedef executor delay
+			{
+				INT32 linenum;
+
+				if (!udmf)
+					break;
+
+				for (linenum = -1; (linenum = P_FindLineFromTag(line->args[0], linenum)) >= 0 ;)
+				{
+					if (line->args[2])
+						lines[linenum].executordelay += line->args[1];
+					else
+						lines[linenum].executordelay = line->args[1];
+				}
+			}
+			break;
+
 		case 480: // Polyobj_DoorSlide
 		case 481: // Polyobj_DoorSwing
 			PolyDoor(line);
diff --git a/src/r_defs.h b/src/r_defs.h
index 73c6d05138e56cdcc35e2ce5a3e1d7573b1cbd9d..c3b72b5c65f4f49eddbf3ec6a800eef2ac4ea4c6 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -421,6 +421,7 @@ typedef struct line_s
 	// Visual appearance: sidedefs.
 	UINT16 sidenum[2]; // sidenum[1] will be 0xffff if one-sided
 	fixed_t alpha; // translucency
+	INT32 executordelay;
 
 	fixed_t bbox[4]; // bounding box for the extent of the linedef