diff --git a/src/p_floor.c b/src/p_floor.c
index d9b404155a1e6e399374f3ba7940e2441c901673..a88555f9b921a7a11e885fcba0e2cc75b89ba7d6 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -972,7 +972,7 @@ void T_StartCrumble(elevator_t *elevator)
 		}
 		else if (++elevator->distance == 0) // Reposition back to original spot
 		{
-			for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+			for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->args[0], i)) >= 0 ;)
 			{
 				sector = &sectors[i];
 
@@ -1003,7 +1003,7 @@ void T_StartCrumble(elevator_t *elevator)
 		// Flash to indicate that the platform is about to return.
 		if (elevator->distance > -224 && (leveltime % ((abs(elevator->distance)/8) + 1) == 0))
 		{
-			for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+			for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->args[0], i)) >= 0 ;)
 			{
 				sector = &sectors[i];
 
@@ -1099,7 +1099,7 @@ void T_StartCrumble(elevator_t *elevator)
 		P_RemoveThinker(&elevator->thinker);
 	}
 
-	for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->args[0], i)) >= 0 ;)
 	{
 		sector = &sectors[i];
 		sector->moved = true;
@@ -2423,7 +2423,7 @@ void T_RaiseSector(levelspecthink_t *raise)
 	if (raise->sector->crumblestate >= 3 || raise->sector->ceilingdata)
 		return;
 
-	for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->args[0], i)) >= 0 ;)
 	{
 		sector = &sectors[i];
 
@@ -2616,7 +2616,7 @@ void T_RaiseSector(levelspecthink_t *raise)
 	raise->sector->ceilspeed = 42;
 	raise->sector->floorspeed = raise->vars[3]*raise->vars[8];
 
-	for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->args[0], i)) >= 0 ;)
 		P_RecalcPrecipInSector(&sectors[i]);
 }
 
@@ -3335,7 +3335,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
 
 	elevator->sector->crumblestate = 2;
 
-	for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->args[0], i)) >= 0 ;)
 	{
 		foundsec = &sectors[i];
 
diff --git a/src/p_setup.c b/src/p_setup.c
index 1af4803d6c4c1a6ab411dde9ac6e6b6c68ba0520..6b7f5932781064b2d7d8d8215fe4d6d707d71f18 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -2920,6 +2920,34 @@ static void P_ConvertBinaryMap(void)
 
 			lines[i].special = 100;
 			break;
+		case 170: //FOF: Crumbling, respawn
+		case 171: //FOF: Crumbling, no respawn
+		case 172: //FOF: Crumbling, respawn, intangible from bottom
+		case 173: //FOF: Crumbling, no respawn, intangible from bottom
+		case 174: //FOF: Crumbling, respawn, intangible from bottom, translucent
+		case 175: //FOF: Crumbling, no respawn, intangible from bottom, translucent
+		case 176: //FOF: Crumbling, respawn, floating, bobbing
+		case 177: //FOF: Crumbling, no respawn, floating, bobbing
+		case 178: //FOF: Crumbling, respawn, floating
+		case 179: //FOF: Crumbling, no respawn, floating
+		case 180: //FOF: Crumbling, respawn, air bobbing
+			lines[i].args[0] = lines[i].tag;
+			if (lines[i].special >= 172 && lines[i].special <= 175)
+			{
+				lines[i].args[1] |= 2; //Intangible from below
+				if (lines[i].flags & ML_NOCLIMB)
+					lines[i].args[2] |= 2; //Don't cast shadow
+			}
+			if (lines[i].special >= 174 && lines[i].special <= 175)
+				lines[i].args[2] |= 1; //Translucent
+			if (lines[i].special % 2 == 1)
+				lines[i].args[2] |= 4; //Don't respawn
+			if (lines[i].special == 176 || lines[i].special == 177 || lines[i].special == 180)
+				lines[i].args[2] |= 8; //Air bobbing
+			if (lines[i].special >= 176 && lines[i].special <= 179)
+				lines[i].args[2] |= 16; //Float on water
+			lines[i].special = 170;
+			break;
 		case 200: //FOF: Light block
 		case 201: //FOF: Half light block
 			lines[i].args[0] = lines[i].tag;
diff --git a/src/p_spec.c b/src/p_spec.c
index 1a1cb89903b4fa70e3afaea4abd89aa0b7355477..57e9c22aa72e8c6932e84d5379fc84f36ccdbdc6 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6093,7 +6093,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
 	raise->sourceline = sourceline;
 }
 
-static void P_AddAirbob(sector_t *sec, line_t *sourceline, boolean noadjust, boolean dynamic)
+static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean raise, boolean dynamic, boolean spindash)
 {
 	levelspecthink_t *airbob;
 
@@ -6106,26 +6106,18 @@ static void P_AddAirbob(sector_t *sec, line_t *sourceline, boolean noadjust, boo
 	airbob->sector = sec;
 
 	// Require a spindash to activate
-	if (sourceline->flags & ML_NOCLIMB)
-		airbob->vars[1] = 1;
-	else
-		airbob->vars[1] = 0;
+	airbob->vars[1] = spindash ? 1 : 0;
 
 	airbob->vars[2] = FRACUNIT;
 
-	if (noadjust)
-		airbob->vars[7] = airbob->sector->ceilingheight-16*FRACUNIT;
-	else
-		airbob->vars[7] = airbob->sector->ceilingheight - P_AproxDistance(sourceline->dx, sourceline->dy);
+	airbob->vars[7] = airbob->sector->ceilingheight - dist;
+
 	airbob->vars[6] = airbob->vars[7]
 		- (sec->ceilingheight - sec->floorheight);
 
 	airbob->vars[3] = airbob->vars[2];
 
-	if (sourceline->flags & ML_BLOCKMONSTERS)
-		airbob->vars[0] = 1;
-	else
-		airbob->vars[0] = 0;
+	airbob->vars[0] = raise ? 0 : 1;
 
 	airbob->vars[5] = sec->ceilingheight;
 	airbob->vars[4] = airbob->vars[5]
@@ -6817,18 +6809,19 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 150: // Air bobbing platform
 			case 151: // Adjustable air bobbing platform
+			{
+				fixed_t dist = (lines[i].special == 151) ? P_AproxDistance(lines[i].dx, lines[i].dy) : 16*FRACUNIT;
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				lines[i].flags |= ML_BLOCKMONSTERS;
-				P_AddAirbob(lines[i].frontsector, lines + i, (lines[i].special != 151), false);
+				P_AddAirbob(lines[i].frontsector, lines + i, dist, false, false, !!(lines[i].flags & ML_NOCLIMB));
 				break;
+			}
 			case 152: // Adjustable air bobbing platform in reverse
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				P_AddAirbob(lines[i].frontsector, lines + i, true, false);
+				P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), true, false, !!(lines[i].flags & ML_NOCLIMB));
 				break;
 			case 153: // Dynamic Sinking Platform
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				lines[i].flags |= ML_BLOCKMONSTERS;
-				P_AddAirbob(lines[i].frontsector, lines + i, false, true);
+				P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), false, true, !!(lines[i].flags & ML_NOCLIMB));
 				break;
 
 			case 160: // Float/bob platform
@@ -6836,71 +6829,46 @@ void P_SpawnSpecials(boolean fromnetsave)
 				break;
 
 			case 170: // Crumbling platform
-				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE, secthinkers);
-				break;
-
-			case 171: // Crumbling platform that will not return
-				P_AddFakeFloorsByLine(i,
-					FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_NORETURN, secthinkers);
-				break;
-
-			case 172: // "Platform" that crumbles and returns
-				ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_CRUMBLE|FF_BOTHPLANES|FF_ALLSIDES;
-				if (lines[i].flags & ML_NOCLIMB) // shade it unless no-climb
-					ffloorflags |= FF_NOSHADE;
-
-				P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
-				break;
-
-			case 173: // "Platform" that crumbles and doesn't return
-				ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_CRUMBLE|FF_NORETURN|FF_BOTHPLANES|FF_ALLSIDES;
-				if (lines[i].flags & ML_NOCLIMB) // shade it unless no-climb
-					ffloorflags |= FF_NOSHADE;
+				ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE;
 
-				P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
-				break;
+				//Tangibility settings
+				if (lines[i].args[1] & 1) //Intangible from top
+					ffloorflags |= FF_REVERSEPLATFORM;
+				if (lines[i].args[1] & 2) //Intangible from bottom
+					ffloorflags |= FF_PLATFORM;
+				if (lines[i].args[1] & 4) //Don't block player
+					ffloorflags &= ~FF_BLOCKPLAYER;
+				if (lines[i].args[1] & 8) //Don't block others
+					ffloorflags &= ~FF_BLOCKOTHERS;
 
-			case 174: // Translucent "platform" that crumbles and returns
-				ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_PLATFORM|FF_CRUMBLE|FF_TRANSLUCENT|FF_BOTHPLANES|FF_ALLSIDES;
-				if (lines[i].flags & ML_NOCLIMB) // shade it unless no-climb
+				//Flags
+				if (lines[i].args[2] & 1) //Translucent
+					ffloorflags |= FF_TRANSLUCENT;
+				if (lines[i].args[2] & 2) //Don't cast shadow
 					ffloorflags |= FF_NOSHADE;
+				if (lines[i].args[2] & 4) //Don't respawn
+					ffloorflags |= FF_NORETURN;
+				if (lines[i].args[2] & 16) //Float on water
+					ffloorflags |= FF_FLOATBOB;
+
+				//If translucent or player can enter it, cut inner walls
+				if ((ffloorflags & FF_TRANSLUCENT) || (lines[i].args[1] & 7))
+					ffloorflags |= FF_CUTEXTRA|FF_EXTRA;
+				else
+					ffloorflags |= FF_CUTLEVEL;
 
-				P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
-				break;
-
-			case 175: // Translucent "platform" that crumbles and doesn't return
-				ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_PLATFORM|FF_CRUMBLE|FF_NORETURN|FF_TRANSLUCENT|FF_BOTHPLANES|FF_ALLSIDES;
-				if (lines[i].flags & ML_NOCLIMB) // shade it unless no-climb
-					ffloorflags |= FF_NOSHADE;
+				//If player can enter it, render insides
+				if (lines[i].args[1] & 7)
+				{
+					if (ffloorflags & FF_RENDERPLANES)
+						ffloorflags |= FF_BOTHPLANES;
+					if (ffloorflags & FF_RENDERSIDES)
+						ffloorflags |= FF_ALLSIDES;
+				}
 
 				P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
-				break;
-
-			case 176: // Air bobbing platform that will crumble and bob on the water when it falls and hits
-				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB|FF_CRUMBLE, secthinkers);
-				lines[i].flags |= ML_BLOCKMONSTERS;
-				P_AddAirbob(lines[i].frontsector, lines + i, true, false);
-				break;
-
-			case 177: // Air bobbing platform that will crumble and bob on
-				// the water when it falls and hits, then never return
-				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB|FF_CRUMBLE|FF_NORETURN, secthinkers);
-				lines[i].flags |= ML_BLOCKMONSTERS;
-				P_AddAirbob(lines[i].frontsector, lines + i, true, false);
-				break;
-
-			case 178: // Crumbling platform that will float when it hits water
-				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE|FF_FLOATBOB, secthinkers);
-				break;
-
-			case 179: // Crumbling platform that will float when it hits water, but not return
-				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_FLOATBOB|FF_NORETURN, secthinkers);
-				break;
-
-			case 180: // Air bobbing platform that will crumble
-				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE, secthinkers);
-				lines[i].flags |= ML_BLOCKMONSTERS;
-				P_AddAirbob(lines[i].frontsector, lines + i, true, false);
+				if (lines[i].args[2] & 8) //Air bobbing
+					P_AddAirbob(lines[i].frontsector, lines + i, 16*FRACUNIT, false, false, false);
 				break;
 
 			case 190: // Rising Platform FOF (solid, opaque, shadows)