diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg
index 8b8d1555ba9ac06ad62eadeb792fba4860385727..17b772f358ee6d9af53da65840e34b9a0d722d5d 100644
--- a/extras/conf/udb/Includes/SRB222_linedefs.cfg
+++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg
@@ -2553,6 +2553,28 @@ udmf
 			}
 		}
 
+		314
+		{
+			title = "Number of Pushables";
+			prefix = "(314)";
+			arg0
+			{
+				title = "Trigger type";
+				type = 11;
+				enum = "triggertype";
+			}
+			arg1
+			{
+				title = "Pushables";
+			}
+			arg2
+			{
+				title = "Comparison";
+				type = 11;
+				enum = "comparison";
+			}
+		}
+
 		323
 		{
 			title = "NiGHTSerize";
diff --git a/src/p_setup.c b/src/p_setup.c
index ef568b578c0d869ec1240ac08b1c7cad1ccd8892..c2fee35b6dde7a7e4018265ff9e39d44815e78c2 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -3740,6 +3740,18 @@ static void P_ConvertBinaryMap(void)
 		case 313: //No more enemies - once
 			lines[i].args[0] = tag;
 			break;
+		case 314: //Number of pushables - Continuous
+		case 315: //Number of pushables - Once
+			lines[i].args[0] = (lines[i].special == 315) ? TMT_ONCE : TMT_CONTINUOUS;
+			lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS;
+			if (lines[i].flags & ML_NOCLIMB)
+				lines[i].args[2] = TMC_GTE;
+			else if (lines[i].flags & ML_EFFECT4)
+				lines[i].args[2] = TMC_GTE;
+			else
+				lines[i].args[2] = TMC_EQUAL;
+			lines[i].special = 314;
+			break;
 		case 323: //NiGHTSerize - Each time
 		case 324: //NiGHTSerize - Once
 		case 325: //DeNiGHTSerize - Each time
diff --git a/src/p_spec.c b/src/p_spec.c
index 631f61a4a2dcc0ecf4955b5a7ee5d251dd57d257..0e552f688866974f287c6bc2abe4fe7f0a8705ea 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1559,11 +1559,12 @@ static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor)
 	}
 }
 
-static boolean P_CheckPushables(line_t *triggerline, sector_t *caller, INT32 targetpushables)
+static boolean P_CheckPushables(line_t *triggerline, sector_t *caller)
 {
 	msecnode_t *node;
 	mobj_t *mo;
 	INT32 numpushables = 0;
+	INT32 targetpushables = triggerline->args[1];
 
 	if (!caller)
 		return false; // we need a calling sector to find pushables in, silly!
@@ -1576,13 +1577,16 @@ static boolean P_CheckPushables(line_t *triggerline, sector_t *caller, INT32 tar
 			numpushables++;
 	}
 
-	if (triggerline->flags & ML_NOCLIMB)
-		return numpushables >= targetpushables;
-
-	if (triggerline->flags & ML_EFFECT4)
-		return numpushables <= targetpushables;
-
-	return numpushables == targetpushables;
+	switch (triggerline->args[2])
+	{
+		case TMC_EQUAL:
+		default:
+			return numpushables == targetpushables;
+		case TMC_GTE:
+			return numpushables >= targetpushables;
+		case TMC_LTE:
+			return numpushables <= targetpushables;
+	}
 }
 
 static void P_ActivateLinedefExecutor(line_t *line, mobj_t *actor, sector_t *caller)
@@ -1760,9 +1764,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 			if (!(actor && actor->player && actor->player->ctfteam == 2))
 				return false;
 			break;
-		case 314: // continuous
-		case 315: // once
-			if (!P_CheckPushables(triggerline, caller, dist))
+		case 314:
+			if (!P_CheckPushables(triggerline, caller))
 				return false;
 			break;
 		case 317: // continuous
@@ -1851,7 +1854,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 	 || specialtype == 307  // Character ability - Once
 	 || specialtype == 308  // Race only - Once
 	 || specialtype == 313  // No More Enemies - Once
-	 || specialtype == 315  // No of pushables - Once
+	 || (specialtype == 314 && triggerline->args[0] == TMT_ONCE)  // No of pushables
 	 || specialtype == 318  // Unlockable trigger - Once
 	 || specialtype == 320  // Unlockable - Once
 	 || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time
@@ -6663,6 +6666,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 300: // Trigger linedef executor
 			case 303: // Count rings
+			case 314: // Pushable linedef executors (count # of pushables)
 				if (lines[i].args[0] > TMT_EACHTIMEMASK)
 					P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT);
 				break;
@@ -6698,11 +6702,6 @@ void P_SpawnSpecials(boolean fromnetsave)
 				P_AddNoEnemiesThinker(&lines[i]);
 				break;
 
-			// Pushable linedef executors (count # of pushables)
-			case 314:
-			case 315:
-				break;
-
 			// Unlock trigger executors
 			case 317:
 			case 318: