diff --git a/src/p_spec.c b/src/p_spec.c
index 6e0ac7486a743569fbfe74d6c8b18ccba3ccf761..5afa38dd37ca4186382e962b80b24a4e1c1c2c79 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -108,6 +108,7 @@ static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinker
 static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec);
 static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer);
 static void P_AddSpikeThinker(sector_t *sec, INT32 referrer);
+static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee)
 
 
 //SoM: 3/7/2000: New sturcture without limits.
@@ -5762,6 +5763,19 @@ void P_SpawnSpecials(INT32 fromnetsave)
 					P_AddBridgeThinker(&lines[i], &sectors[s]);*/
 				break;
 
+			case 66: // Displace floor by front sector
+				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+					P_AddPlaneDisplaceThinker(pd_floor, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s);
+				break;
+			case 67: // Displace ceiling by front sector
+				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+					P_AddPlaneDisplaceThinker(pd_ceiling, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s);
+				break;
+			case 68: // Displace both floor AND ceiling by front sector
+				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+					P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s);
+				break;
+
 			case 100: // FOF (solid, opaque, shadows)
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
 				break;
diff --git a/src/p_spec.h b/src/p_spec.h
index a8f9ac492988ba927ff4ad4cc5d4c7bb996fe552..6e173eec5bf61fb8669f83ba0e71431f26cbcb61 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -448,6 +448,26 @@ void T_Disappear(disappear_t *d);
 void T_Pusher(pusher_t *p);
 mobj_t *P_GetPushThing(UINT32 s);
 
+// Plane displacement
+typedef struct
+{
+	thinker_t thinker;   ///< Thinker structure for plane displacement effect.
+	INT32 affectee;      ///< Number of affected sector.
+	INT32 control;       ///< Control sector used to control plane positions.
+	fixed_t last_height; ///< Last known height of control sector.
+	fixed_t speed;       ///< Plane movement speed.
+	/** Types of plane displacement effects.
+	*/
+	enum
+	{
+		pd_floor,        ///< Displace floor.
+		pd_ceiling,      ///< Displace ceiling.
+		pd_both,         ///< Displace both floor AND ceiling.
+	} type;
+} planedisplace_t;
+
+void T_PlaneDisplace(planedisplace_t *pd);
+
 void P_CalcHeight(player_t *player);
 
 sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo);