diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg
index cf81b56ddb1d853e53a38c31bfd787930634d5e0..a08c6146377c29928fe5c81abe1c88a89417584b 100644
--- a/extras/conf/udb/Includes/SRB222_linedefs.cfg
+++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg
@@ -2944,6 +2944,41 @@ udmf
 	{
 		title = "Linedef Executor (player/object)";
 
+		412
+		{
+			title = "Teleporter";
+			prefix = "(412)";
+			arg0
+			{
+				title = "Destination tag";
+				type = 14;
+			}
+			arg1
+			{
+				title = "Flags";
+				type = 12;
+				enum
+				{
+					1 = "Silent";
+					2 = "Keep angle";
+					4 = "Keep momentum";
+					8 = "Relative silent";
+				}
+			}
+			arg2
+			{
+				title = "X offset";
+			}
+			arg3
+			{
+				title = "Y offset";
+			}
+			arg4
+			{
+				title = "Z offset";
+			}
+		}
+
 		425
 		{
 			title = "Change Object State";
diff --git a/src/p_setup.c b/src/p_setup.c
index 8e9d73e4b3f02ad5abc87263ce2946fc03344de9..879f2fb1761d47711ad80f5432fd56ff024bce79 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -3747,6 +3747,20 @@ static void P_ConvertBinaryMap(void)
 		case 411: //Stop plane movement
 			lines[i].args[0] = tag;
 			break;
+		case 412: //Teleporter
+			lines[i].args[0] = tag;
+			if (lines[i].flags & ML_BLOCKMONSTERS)
+				lines[i].args[1] |= TMT_SILENT;
+			if (lines[i].flags & ML_NOCLIMB)
+				lines[i].args[1] |= TMT_KEEPANGLE;
+			if (lines[i].flags & ML_EFFECT4)
+				lines[i].args[1] |= TMT_KEEPMOMENTUM;
+			if (lines[i].flags & ML_EFFECT3)
+				lines[i].args[1] |= TMT_RELATIVE;
+			lines[i].args[2] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS;
+			lines[i].args[3] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS;
+			lines[i].args[4] = lines[i].frontsector->ceilingheight >> FRACBITS;
+			break;
 		case 414: //Play sound effect
 			lines[i].args[2] = tag;
 			if (tag != 0)
diff --git a/src/p_spec.c b/src/p_spec.c
index 57f9237dcf8d202374bbfbc91e76bcf71934cfb6..bf6e05b7f7af6a949751539c35862b9d1496f6ff 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -2238,7 +2238,6 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 {
 	INT32 secnum = -1;
 	mobj_t *bot = NULL;
-	mtag_t tag = Tag_FGet(&line->tags);
 
 	I_Assert(!mo || !P_MobjWasRemoved(mo)); // If mo is there, mo must be valid!
 
@@ -2403,13 +2402,13 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				if (!mo) // nothing to teleport
 					return;
 
-				if (line->flags & ML_EFFECT3) // Relative silent teleport
+				if (line->args[1] & TMT_RELATIVE) // Relative silent teleport
 				{
 					fixed_t x, y, z;
 
-					x = sides[line->sidenum[0]].textureoffset;
-					y = sides[line->sidenum[0]].rowoffset;
-					z = line->frontsector->ceilingheight;
+					x = line->args[2] << FRACBITS;
+					y = line->args[3] << FRACBITS;
+					z = line->args[4] << FRACBITS;
 
 					P_UnsetThingPosition(mo);
 					mo->x += x;
@@ -2439,23 +2438,22 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				}
 				else
 				{
-					if ((secnum = Tag_Iterate_Sectors(tag, 0)) < 0)
-						return;
+					angle_t angle;
+					boolean silent, keepmomentum;
 
-					dest = P_GetObjectTypeInSectorNum(MT_TELEPORTMAN, secnum);
+					dest = P_FindObjectTypeFromTag(MT_TELEPORTMAN, line->args[0]);
 					if (!dest)
 						return;
 
+					angle = (line->args[1] & TMT_KEEPANGLE) ? mo->angle : dest->angle;
+					silent = !!(line->args[1] & TMT_SILENT);
+					keepmomentum = !!(line->args[1] & TMT_KEEPMOMENTUM);
+
 					if (bot)
-						P_Teleport(bot, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ?  mo->angle : dest->angle, (line->flags & ML_BLOCKMONSTERS) == 0, (line->flags & ML_EFFECT4) == ML_EFFECT4);
-					if (line->flags & ML_BLOCKMONSTERS)
-						P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ?  mo->angle : dest->angle, false, (line->flags & ML_EFFECT4) == ML_EFFECT4);
-					else
-					{
-						P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ?  mo->angle : dest->angle, true, (line->flags & ML_EFFECT4) == ML_EFFECT4);
-						// Play the 'bowrwoosh!' sound
-						S_StartSound(dest, sfx_mixup);
-					}
+						P_Teleport(bot, dest->x, dest->y, dest->z, angle, !silent, keepmomentum);
+					P_Teleport(mo, dest->x, dest->y, dest->z, angle, !silent, keepmomentum);
+					if (!silent)
+						S_StartSound(dest, sfx_mixup); // Play the 'bowrwoosh!' sound
 				}
 			}
 			break;
diff --git a/src/p_spec.h b/src/p_spec.h
index 09a14d9a12c35edd18acd0797aba920d036d85c0..c5c1c616253ae636fc026f55cf1f0e6b06c3685d 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -119,6 +119,14 @@ typedef enum
 	TMT_REPLACEFIRST = 2,
 } textmaptagoptions_t;
 
+typedef enum
+{
+	TMT_SILENT       = 1,
+	TMT_KEEPANGLE    = 1<<1,
+	TMT_KEEPMOMENTUM = 1<<2,
+	TMT_RELATIVE     = 1<<3,
+} textmapteleportflags_t;
+
 typedef enum
 {
 	TMSS_TRIGGERMOBJ   = 0,