diff --git a/src/dehacked.c b/src/dehacked.c
index 8057f26d8eccd24485bc1f21de404e99bf6ae7bb..4673f2799ab7e3b75120ff64e3fc80a85b7df382 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -6654,6 +6654,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 
 	"S_LOCKON1",
 	"S_LOCKON2",
+	"S_LOCKON3",
+	"S_LOCKON4",
+	"S_LOCKONINF1",
+	"S_LOCKONINF2",
+	"S_LOCKONINF3",
+	"S_LOCKONINF4",
 
 	// Tag Sign
 	"S_TTAG",
@@ -7732,6 +7738,7 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_DROWNNUMBERS", // Drowning Timer
 	"MT_GOTEMERALD", // Chaos Emerald (intangible)
 	"MT_LOCKON", // Target
+	"MT_LOCKONINF", // In-level Target
 	"MT_TAG", // Tag Sign
 	"MT_GOTFLAG", // Got Flag sign
 
diff --git a/src/doomdef.h b/src/doomdef.h
index 475328918ab57a54c013e9f7c6ea965583450e61..7bcc533c2ecda2f63fb1eda960d4d9bd80987c1a 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -384,7 +384,7 @@ enum {
 	LE_PINCHPHASE      =    -2, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!)
 	LE_ALLBOSSESDEAD   =    -3, // All bosses in the map are dead (Egg capsule raise)
 	LE_BOSSDEAD        =    -4, // A boss in the map died (Chaos mode boss tally)
-	LE_BOSS4DROP       =    -5, // CEZ boss dropped its cage
+	LE_BOSS4DROP       =    -5, // CEZ boss dropped its cage (also subtract the number of hitpoints it's lost)
 	LE_BRAKVILEATACK   =    -6, // Brak's doing his LOS attack, oh noes
 	LE_TURRET          = 32000, // THZ turret
 	LE_BRAKPLATFORM    =  4200, // v2.0 Black Eggman destroys platform
diff --git a/src/info.c b/src/info.c
index 074e31ba2eb044476607796a58ab05f0d6c90c1e..5af1586b4c0a852039bbd9bb3cc4841cdaae7f25 100644
--- a/src/info.c
+++ b/src/info.c
@@ -1352,14 +1352,15 @@ state_t states[NUMSTATES] =
 	{SPR_EGGP,10,  2, {NULL},           0,          0, S_EGGMOBILE4_STND},   // S_EGGMOBILE4_RATK6
 	{SPR_EGGP, 0, 20, {A_Boss4Raise},   sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1
 	{SPR_EGGP,13, 10, {NULL},           0,          0, S_EGGMOBILE4_RAISE3}, // S_EGGMOBILE4_RAISE2
-	{SPR_EGGP,14, 10, {NULL},           0,          0, S_EGGMOBILE4_RAISE4}, // S_EGGMOBILE4_RAISE3
+	{SPR_EGGP,14, 10, {NULL},           0,          0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE3
 	{SPR_EGGP,13, 10, {NULL},           0,          0, S_EGGMOBILE4_RAISE5}, // S_EGGMOBILE4_RAISE4
 	{SPR_EGGP,14, 10, {NULL},           0,          0, S_EGGMOBILE4_RAISE6}, // S_EGGMOBILE4_RAISE5
 	{SPR_EGGP,13, 10, {NULL},           0,          0, S_EGGMOBILE4_RAISE7}, // S_EGGMOBILE4_RAISE6
 	{SPR_EGGP,14, 10, {NULL},           0,          0, S_EGGMOBILE4_RAISE8}, // S_EGGMOBILE4_RAISE7
 	{SPR_EGGP,13, 10, {NULL},           0,          0, S_EGGMOBILE4_RAISE9}, // S_EGGMOBILE4_RAISE8
 	{SPR_EGGP,14, 10, {NULL},           0,          0, S_EGGMOBILE4_RAISE10},// S_EGGMOBILE4_RAISE9
-	{SPR_EGGP,13, 10, {NULL},           0,          0, S_EGGMOBILE4_STND},   // S_EGGMOBILE4_RAISE10
+	// rename eventually
+	{SPR_EGGP,11,  0, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_PAIN},   // S_EGGMOBILE4_RAISE10
 	{SPR_EGGP,11, 24, {A_Pain},         0,          0, S_EGGMOBILE4_STND},   // S_EGGMOBILE4_PAIN
 	{SPR_EGGP,12,  8, {A_Fall},         0,          0, S_EGGMOBILE4_DIE2},   // S_EGGMOBILE4_DIE1
 	{SPR_EGGP,12,  8, {A_BossScream},   0,          0, S_EGGMOBILE4_DIE3},   // S_EGGMOBILE4_DIE2
@@ -3298,6 +3299,13 @@ state_t states[NUMSTATES] =
 
 	{SPR_LCKN,   FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON1
 	{SPR_LCKN, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON2
+	{SPR_LCKN, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON3
+	{SPR_LCKN, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON4
+
+	{SPR_LCKN,   FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF1
+	{SPR_LCKN, 1|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF2
+	{SPR_LCKN, 2|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF3
+	{SPR_LCKN, 3|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF4
 
 	{SPR_TTAG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_TTAG
 
@@ -5577,7 +5585,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,          // seesound
 		0,                 // reactiontime
 		sfx_None,          // attacksound
-		S_EGGMOBILE4_PAIN, // painstate
+		S_EGGMOBILE4_RAISE10, // painstate
 		0,                 // painchance
 		sfx_dmpain,        // painsound
 		S_EGGMOBILE4_LATK1,// meleestate
@@ -16529,6 +16537,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
+	{           // MT_LOCKONINF
+		1126,           // doomednum
+		S_INVISIBLE,    // spawnstate
+		1000,           // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_NULL,         // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		8,              // speed
+		16*FRACUNIT,    // radius
+		32*FRACUNIT,    // height
+		111,            // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
+		S_NULL          // raisestate
+	},
+
 	{           // MT_TAG
 		-1,             // doomednum
 		S_TTAG,         // spawnstate
diff --git a/src/info.h b/src/info.h
index 13abfa5f60249d91afd05bc0fba7b35376f41a44..75091ce1e0edbe29cc4665810818464dc3aaf725 100644
--- a/src/info.h
+++ b/src/info.h
@@ -3409,6 +3409,12 @@ typedef enum state
 
 	S_LOCKON1,
 	S_LOCKON2,
+	S_LOCKON3,
+	S_LOCKON4,
+	S_LOCKONINF1,
+	S_LOCKONINF2,
+	S_LOCKONINF3,
+	S_LOCKONINF4,
 
 	// Tag Sign
 	S_TTAG,
@@ -4507,6 +4513,7 @@ typedef enum mobj_type
 	MT_DROWNNUMBERS, // Drowning Timer
 	MT_GOTEMERALD, // Chaos Emerald (intangible)
 	MT_LOCKON, // Target
+	MT_LOCKONINF, // In-level Target
 	MT_TAG, // Tag Sign
 	MT_GOTFLAG, // Got Flag sign
 
diff --git a/src/p_enemy.c b/src/p_enemy.c
index a817ee8a6ba8db8c3c5671f8e5ce35f4bb1b460c..05915c0b34ef8e0dff85ee3a9428d1aea5091093 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -3167,8 +3167,12 @@ void A_Boss4Reverse(mobj_t *actor)
 	actor->reactiontime = 0;
 	if (actor->movedir == 1)
 		actor->movedir = 2;
-	else
+	else if (actor->movedir == 2)
 		actor->movedir = 1;
+	else if (actor->movedir == 4)
+		actor->movedir = 5;
+	else
+		actor->movedir = 4;
 }
 
 // Function: A_Boss4SpeedUp
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 4f46116caa58a395213fce7a51f4672bc0fde4a2..a3e0d7704344f768fffefcf9b51d6bac89675471 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -4660,9 +4660,9 @@ static void P_Boss3Thinker(mobj_t *mobj)
 }
 
 // Move Boss4's sectors by delta.
-static boolean P_Boss4MoveCage(fixed_t delta)
+static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta)
 {
-	const UINT16 tag = 65534;
+	const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
 	INT32 snum;
 	sector_t *sector;
 	for (snum = sectors[tag%numsectors].firsttag; snum != -1; snum = sector->nexttag)
@@ -4682,7 +4682,7 @@ static void P_Boss4MoveSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz)
 {
 	INT32 s;
 	mobj_t *base = mobj, *seg;
-	fixed_t dist, bz = mobj->watertop+(16<<FRACBITS);
+	fixed_t dist, bz = mobj->watertop+(8<<FRACBITS);
 	while ((base = base->tracer))
 	{
 		for (seg = base, dist = 172*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 124*FRACUNIT, --s)
@@ -4692,26 +4692,44 @@ static void P_Boss4MoveSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz)
 }
 
 // Pull them closer.
-static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz)
+static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz)
 {
 	INT32 s;
 	mobj_t *base = mobj, *seg;
-	fixed_t dist, bz = mobj->watertop+(16<<FRACBITS);
-	while ((base = base->tracer))
+	fixed_t originx, originy, workx, worky, dx, dy, bz = mobj->watertop+(8<<FRACBITS);
+
+	if (mobj->spawnpoint)
+	{
+		originx = mobj->spawnpoint->x << FRACBITS;
+		originy = mobj->spawnpoint->y << FRACBITS;
+	}
+	else
 	{
-		for (seg = base, dist = 112*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 132*FRACUNIT, --s)
+		originx = mobj->x;
+		originy = mobj->y;
+	}
+
+	dz /= 9;
+	
+	while ((base = base->tracer)) // there are 10 per spoke, remember that
+	{
+		dx = (originx + P_ReturnThrustX(mobj, angle, (9*132)<<FRACBITS) - mobj->x)/9;
+		dy = (originy + P_ReturnThrustY(mobj, angle, (9*132)<<FRACBITS) - mobj->y)/9;
+		workx = mobj->x + P_ReturnThrustX(mobj, angle, (112)<<FRACBITS);
+		worky = mobj->y + P_ReturnThrustY(mobj, angle, (112)<<FRACBITS);
+		for (seg = base, s = 9; seg; seg = seg->hnext, --s)
 		{
-			seg->z = bz + FixedMul(fz, FixedDiv(s<<FRACBITS, 9<<FRACBITS));
-			P_TryMove(seg, mobj->x + P_ReturnThrustX(mobj, angle, dist), mobj->y + P_ReturnThrustY(mobj, angle, dist), true);
+			seg->z = bz + (dz*(9-s));
+			P_TryMove(seg, workx + (dx*s), worky + (dy*s), true);
 		}
 		angle += ANGLE_MAX/3;
 	}
 }
 
 // Destroy cage FOFs.
-static void P_Boss4DestroyCage(void)
+static void P_Boss4DestroyCage(mobj_t *mobj)
 {
-	const UINT16 tag = 65534;
+	const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
 	INT32 snum, next;
 	size_t a;
 	sector_t *sector, *rsec;
@@ -4776,7 +4794,7 @@ static void P_Boss4Thinker(mobj_t *mobj)
 {
 	if ((statenum_t)(mobj->state-states) == mobj->info->spawnstate)
 	{
-		if (mobj->health > mobj->info->damage || mobj->movedir == 4)
+		if (mobj->flags2 & MF2_FRET && (mobj->health > mobj->info->damage || mobj->movedir == 4))
 			mobj->flags2 &= ~MF2_FRET;
 		mobj->reactiontime = 0; // Drop the cage immediately.
 	}
@@ -4786,7 +4804,7 @@ static void P_Boss4Thinker(mobj_t *mobj)
 	{
 		if (mobj->tracer) // need to clean up!
 		{
-			P_Boss4DestroyCage(); // Just in case pinch phase was skipped.
+			P_Boss4DestroyCage(mobj); // Just in case pinch phase was skipped.
 			P_Boss4PopSpikeballs(mobj);
 		}
 		return;
@@ -4813,6 +4831,7 @@ static void P_Boss4Thinker(mobj_t *mobj)
 			mobj_t *seg, *base = mobj;
 			// First frame init, spawn all the things.
 			mobj->watertop = mobj->z;
+			mobj->flags2 |= MF2_STRONGBOX; // don't perform the linedef executor at start
 			z = mobj->z + mobj->height/2 - mobjinfo[MT_EGGMOBILE4_MACE].height/2;
 			for (arm = 0; arm <3 ; arm++)
 			{
@@ -4829,10 +4848,10 @@ static void P_Boss4Thinker(mobj_t *mobj)
 			}
 			// Move the cage up to the sky.
 			mobj->movecount = 800*FRACUNIT;
-			if (!P_Boss4MoveCage(mobj->movecount))
+			if (!P_Boss4MoveCage(mobj, mobj->movecount))
 			{
 				mobj->movecount = 0;
-				mobj->threshold = 3*TICRATE;
+				//mobj->threshold = 3*TICRATE;
 				mobj->extravalue1 = 1;
 				mobj->movedir++; // We don't have a cage, just continue.
 			}
@@ -4846,13 +4865,18 @@ static void P_Boss4Thinker(mobj_t *mobj)
 			mobj->movecount += mobj->threshold;
 			if (mobj->movecount < 0)
 				mobj->movecount = 0;
-			P_Boss4MoveCage(mobj->movecount - oldz);
+			P_Boss4MoveCage(mobj, mobj->movecount - oldz);
 			P_Boss4MoveSpikeballs(mobj, 0, mobj->movecount);
 			if (mobj->movecount == 0)
 			{
-				mobj->threshold = 3*TICRATE;
+				//mobj->threshold = 3*TICRATE;
 				mobj->extravalue1 = 1;
-				P_LinedefExecute(LE_BOSS4DROP, mobj, NULL);
+				//P_LinedefExecute(LE_BOSS4DROP + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); -- oh no you don't
+				S_StartSound(NULL, sfx_doorc2);
+				quake.intensity = 10<<FRACBITS;
+				quake.radius = 512<<FRACBITS;
+				quake.time = 20;
+				quake.epicenter = NULL;
 				mobj->movedir++; // Initialization complete, next phase!
 			}
 		}
@@ -4875,10 +4899,10 @@ static void P_Boss4Thinker(mobj_t *mobj)
 			mobj->momz = 0;
 			mobj->movedir++;
 		}
-		mobj->movecount += 400<<(FRACBITS>>1);
+		mobj->movecount -= 210<<(FRACBITS>>1);
 		mobj->movecount %= 360*FRACUNIT;
 		z = mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2;
-		if (z < 0) // We haven't risen high enough to pull the spikeballs along yet
+		if (z < (8<<FRACBITS)) // We haven't risen high enough to pull the spikeballs along yet
 			P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), 0); // So don't pull the spikeballs along yet.
 		else
 			P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), z);
@@ -4886,12 +4910,19 @@ static void P_Boss4Thinker(mobj_t *mobj)
 	}
 	// Pinch phase!
 	case 4:
+	case 5:
 	{
+		fixed_t movespeed = 420<<(FRACBITS>>1);
+		movespeed += (420*(mobj->info->damage-mobj->health)<<(FRACBITS>>1));
+		if (mobj->movedir == 4)
+			mobj->movecount -= movespeed;
+		else
+			mobj->movecount += movespeed;
+
 		if (mobj->z < (mobj->watertop + ((512+128*(mobj->info->damage-mobj->health))<<FRACBITS)))
 			mobj->momz = 8*FRACUNIT;
 		else
 			mobj->momz = 0;
-		mobj->movecount += (800+800*(mobj->info->damage-mobj->health))<<(FRACBITS>>1);
 		mobj->movecount %= 360*FRACUNIT;
 		P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2);
 
@@ -4917,10 +4948,20 @@ static void P_Boss4Thinker(mobj_t *mobj)
 	if (mobj->reactiontime == 1)
 	{
 		fixed_t oldz = mobj->movefactor;
-		mobj->movefactor += 8*FRACUNIT;
-		if (mobj->movefactor > 128*FRACUNIT)
+		if (mobj->movefactor < 128*FRACUNIT)
+		{
+			mobj->movefactor += 8*FRACUNIT;
+			P_Boss4MoveCage(mobj, mobj->movefactor - oldz);
+			// 5 -> 2.5 second timer
+			mobj->threshold = 5*TICRATE-(TICRATE/2)*(mobj->info->spawnhealth-mobj->health);
+			if (mobj->threshold < 1)
+				mobj->threshold = 1;
+		}
+		else if (mobj->movefactor > 128*FRACUNIT)
+		{
 			mobj->movefactor = 128*FRACUNIT;
-		P_Boss4MoveCage(mobj->movefactor - oldz);
+			P_Boss4MoveCage(mobj, mobj->movefactor - oldz);
+		}
 	}
 	// Drop the cage!
 	else if (mobj->movefactor)
@@ -4929,24 +4970,32 @@ static void P_Boss4Thinker(mobj_t *mobj)
 		mobj->movefactor -= 4*FRACUNIT;
 		if (mobj->movefactor < 0)
 			mobj->movefactor = 0;
-		P_Boss4MoveCage(mobj->movefactor - oldz);
-		if (!mobj->movefactor)
+		P_Boss4MoveCage(mobj, mobj->movefactor - oldz);
+		if (mobj->flags2 & MF2_STRONGBOX)
+			mobj->flags2 &= ~MF2_STRONGBOX;
+		else if (!mobj->movefactor)
 		{
 			if (mobj->health <= mobj->info->damage)
 			{ // Proceed to pinch phase!
-				P_Boss4DestroyCage();
+				P_Boss4DestroyCage(mobj);
 				mobj->movedir = 3;
-				P_LinedefExecute(LE_PINCHPHASE, mobj, NULL);
+				P_LinedefExecute(LE_PINCHPHASE + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL);
 				return;
 			}
-			P_LinedefExecute(LE_BOSS4DROP, mobj, NULL);
+			P_LinedefExecute(LE_BOSS4DROP - (mobj->info->spawnhealth-mobj->health) + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL);
+			S_StartSound(NULL, sfx_doorc2);
+			quake.intensity = 10<<FRACBITS;
+			quake.radius = 512<<FRACBITS;
+			quake.time = 20;
+			quake.epicenter = NULL;
 		}
 	}
 
 	{
 		fixed_t movespeed = 170<<(FRACBITS>>1);
-		if (mobj->reactiontime == 2)
-			movespeed *= 3;
+		movespeed += ((50*(mobj->info->spawnhealth-mobj->health))<<(FRACBITS>>1));
+		if (mobj->movefactor)
+			movespeed /= 2;
 		if (mobj->movedir == 2)
 			mobj->movecount -= movespeed;
 		else
@@ -4956,37 +5005,14 @@ static void P_Boss4Thinker(mobj_t *mobj)
 	P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->movefactor);
 
 	// Check for attacks, always tick the timer even while animating!!
-	if (!(mobj->flags2 & MF2_FRET) // but pause for pain so we don't interrupt pinch phase, eep!
-	&& mobj->threshold-- == 0)
+	if (mobj->threshold)
 	{
-		// 5 -> 2.5 second timer
-		mobj->threshold = 5*TICRATE-(TICRATE/2)*(mobj->info->spawnhealth-mobj->health);
-		if (mobj->threshold < 1)
-			mobj->threshold = 1;
-
-		if (mobj->extravalue1-- == 0)
-		{
-			P_SetMobjState(mobj, mobj->info->raisestate);
-			mobj->extravalue1 = 3;
-		}
-		else
+		if (!(mobj->flags2 & MF2_FRET) && !(--mobj->threshold)) // but pause for pain so we don't interrupt pinch phase, eep!
 		{
 			if (mobj->reactiontime == 1) // Cage is raised?
+			{
+				P_SetMobjState(mobj, mobj->info->spawnstate);
 				mobj->reactiontime = 0; // Drop it!
-			switch(P_RandomKey(10))
-			{
-				// Telegraph Right (Speed Up!!)
-				case 1:
-				case 3:
-				case 4:
-				case 5:
-				case 6:
-					P_SetMobjState(mobj, mobj->info->missilestate);
-					break;
-				// Telegraph Left (Reverse Direction)
-				default:
-					P_SetMobjState(mobj, mobj->info->meleestate);
-					break;
 			}
 		}
 	}
@@ -4998,13 +5024,13 @@ static void P_Boss4Thinker(mobj_t *mobj)
 	// Map allows us to get killed despite cage being down?
 	if (mobj->health <= mobj->info->damage)
 	{ // Proceed to pinch phase!
-		P_Boss4DestroyCage();
+		P_Boss4DestroyCage(mobj);
 		// spawn jet's flame now you're flying upwards
 		// tracer is already used, so if this ever gets reached again we've got problems
 		var1 = 3;
 		A_BossJetFume(mobj);
 		mobj->movedir = 3;
-		P_LinedefExecute(LE_PINCHPHASE, mobj, NULL);
+		P_LinedefExecute(LE_PINCHPHASE + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL);
 		return;
 	}
 
@@ -7183,6 +7209,17 @@ void P_MobjThinker(mobj_t *mobj)
 				else
 					mobj->z = mobj->target->z - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale) - mobj->height;
 				break;
+			case MT_LOCKONINF:
+				if (!(mobj->flags2 & MF2_STRONGBOX))
+				{
+					mobj->threshold = mobj->z;
+					mobj->flags2 |= MF2_STRONGBOX;
+				}
+				if (!(mobj->eflags & MFE_VERTICALFLIP))
+					mobj->z = mobj->threshold + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale);
+				else
+					mobj->z = mobj->threshold - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale);
+				break;
 			case MT_DROWNNUMBERS:
 				if (!mobj->target)
 				{
@@ -9184,6 +9221,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 		case MT_ALTVIEWMAN:
 			if (titlemapinaction) mobj->flags &= ~MF_NOTHINK;
 			break;
+		case MT_LOCKONINF:
+			P_SetScale(mobj, (mobj->destscale = 3*mobj->scale));
+			break;
 		case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE:
 			mobj->fuse = mobj->info->painchance;
 			break;