// 2.1 Sea Egg - Ported from 2.1.25

freeslot(
	// Sprites
	"SPR_OEGO",
	"SPR_OFAK",
	"SPR_OTRP",
	// Sounds
	// Objects
	"MT_21EGGMOBILE3",
	"MT_OLDPROPELLER",
	"MT_OLDFAKEMOBILE",
	"MT_OLDTORPEDO",
	"MT_OLDTORPEDO2",
	// States
	"S_21EGGMOBILE3_STND",
	"S_21EGGMOBILE3_ATK1",
	"S_21EGGMOBILE3_ATK2",
	"S_21EGGMOBILE3_ATK3A",
	"S_21EGGMOBILE3_ATK3B",
	"S_21EGGMOBILE3_ATK3C",
	"S_21EGGMOBILE3_ATK3D",
	"S_21EGGMOBILE3_ATK4",
	"S_21EGGMOBILE3_ATK5",
	"S_21EGGMOBILE3_LAUGH1",
	"S_21EGGMOBILE3_LAUGH2",
	"S_21EGGMOBILE3_LAUGH3",
	"S_21EGGMOBILE3_LAUGH4",
	"S_21EGGMOBILE3_LAUGH5",
	"S_21EGGMOBILE3_LAUGH6",
	"S_21EGGMOBILE3_LAUGH7",
	"S_21EGGMOBILE3_LAUGH8",
	"S_21EGGMOBILE3_LAUGH9",
	"S_21EGGMOBILE3_LAUGH10",
	"S_21EGGMOBILE3_LAUGH11",
	"S_21EGGMOBILE3_LAUGH12",
	"S_21EGGMOBILE3_LAUGH13",
	"S_21EGGMOBILE3_LAUGH14",
	"S_21EGGMOBILE3_LAUGH15",
	"S_21EGGMOBILE3_LAUGH16",
	"S_21EGGMOBILE3_LAUGH17",
	"S_21EGGMOBILE3_LAUGH18",
	"S_21EGGMOBILE3_LAUGH19",
	"S_21EGGMOBILE3_LAUGH20",
	"S_21EGGMOBILE3_PAIN",
	"S_21EGGMOBILE3_PAIN2",
	"S_21EGGMOBILE3_DIE1",
	"S_21EGGMOBILE3_DIE2",
	"S_21EGGMOBILE3_DIE3",
	"S_21EGGMOBILE3_DIE4",
	"S_21EGGMOBILE3_FLEE1",
	"S_21EGGMOBILE3_FLEE2",
	"S_OLDFAKEMOBILE_INIT",
	"S_OLDFAKEMOBILE",
	"S_OLDFAKEMOBILE_ATK1",
	"S_OLDFAKEMOBILE_ATK2",
	"S_OLDFAKEMOBILE_ATK3A",
	"S_OLDFAKEMOBILE_ATK3B",
	"S_OLDFAKEMOBILE_ATK3C",
	"S_OLDFAKEMOBILE_ATK3D",
	"S_OLDFAKEMOBILE_ATK4",
	"S_OLDFAKEMOBILE_ATK5",
	"S_OLDTORPEDO"
)

// Relevant ported functions

// A_Boss3TakeDamage ported from 2.1.25's p_enemy.c
function A_21Boss3TakeDamage(actor, var1, var2)
	actor.movecount = var1
	
	if actor.target and actor.target.spawnpoint
		actor.threshold = actor.target.spawnpoint.extrainfo
	end
end

// A_Boss3Path ported from 2.1.25's p_enemy.c
function A_21Boss3Path(actor, var1, var2)
	if actor.tracer and actor.tracer.health and actor.tracer.movecount
		actor.movecount = $|1
	elseif (actor.movecount & 1)
		actor.movecount = 0
	end
	
	if (actor.movecount & 2) // We've reached a firing point?
		// Wait here and pretend to be angry or something.
		actor.momx = 0
		actor.momy = 0
		actor.momz = 0
		actor.target = actor.tracer.target
		A_FaceTarget(actor, 0, 0)
		if actor.tracer.state == actor.tracer.info.missilestate
			actor.state = actor.info.missilestate
		end
		return
	elseif actor.threshold >= 0 // Traveling mode
		//local th
		//local mo2
		local dist, dist2
		local speed
		
		actor.target = nil
		
		// scan the thinkers
		// to find a point that matches
		// the number
		for th in mobjs.iterate()
			if th.type == MT_BOSS3WAYPOINT and th.spawnpoint and th.spawnpoint.angle == actor.threshold
				actor.target = th
				break
			end
		end
		
		if not actor.target // Should NEVER happen
			print("Error: Boss 3 Dummy was unable to find specified waypoint: " + actor.thresold)
			return
		end
		
		dist = FixedHypot(FixedHypot(actor.target.x - actor.x, actor.target.y - actor.y), actor.target.z - actor.z)
		
		if dist < 1
			dist = 1
		end
		
		if actor.tracer and (actor.tracer.movedir
		or actor.tracer.health <= actor.tracer.info.damage)
			speed = actor.info.speed * 2
		else
			speed = actor.info.speed
		end
		
		actor.momx = FixedMul(FixedDiv(actor.target.x - actor.x, dist), speed)
		actor.momy = FixedMul(FixedDiv(actor.target.y - actor.y, dist), speed)
		actor.momz = FixedMul(FixedDiv(actor.target.z - actor.z, dist), speed)
		
		if actor.momx != 0 or actor.momy != 0
			actor.angle = R_PointToAngle2(0, 0, actor.momx, actor.momy)
		end
		
		dist2 = FixedHypot(FixedHypot(actor.target.x - (actor.x + actor.momx), actor.target.y - (actor.y + actor.momy)), actor.target.z - (actor.z + actor.momz))
		
		if dist2 < 1
			dist2 = 1
		end
		
		if dist / (2^FRACBITS) <= dist2 / (2^FRACBITS)
			// If further away, set XYZ of mobj to waypoint location
			P_TeleportMove(actor, actor.target.x, actor.target.y, actor.target.z)
			actor.momx = 0
			actor.momy = 0
			actor.momz = 0
			
			if actor.threshold == 0
				P_RemoveMobj(actor) // Cycle completed. Dummy removed.
				return
			end
			
			// Set to next waypoint in sequence
			if actor.target.spawnpoint
				// From the center point, choose one of the five paths
				if actor.target.spawnpoint.angle == 0
					P_RemoveMobj(actor) // Cycle completed. Dummy removed.
					return
				else
					actor.threshold = actor.target.spawnpoint.extrainfo
				end
				
				// If the deaf flag is set, go into firing mode
				if (actor.target.spawnpoint.options & MTF_AMBUSH)
					actor.movecount = $|2
				end
			else // This should never happen, as well
				print("Error: Boss 3 Dummy waypoint has no spawnpoint associated with it.")
			end
		end
	end
end

// 2.1 Sea Egg

addHook("BossThinker", function(mobj)
	
	//print(mobj.target)
	if states[mobj.state] == states[mobj.info.spawnstate]
		mobj.flags2 = $ & ~MF2_FRET
	end
	
	if (mobj.flags2 & MF2_FRET)
		mobj.movedir = 1
	end
	
	if not mobj.tracer
		A_21BossJetFume(mobj, 1, 0)
	end
	
	if mobj.health <= 0
		mobj.movecount = 0
		mobj.reactiontime = 0
		
		if mobj.state < mobj.info.xdeathstate
			return true
		end
		
		if mobj.threshold == -1
			mobj.momx = 0
			mobj.momy = 0
			mobj.momz = mobj.info.speed
			return true
		end
	end
	
	if mobj.reactiontime
		local i
		
		if states[mobj.state] != states[mobj.info.spawnstate]
			mobj.state = mobj.info.spawnstate
		end
		
		mobj.reactiontime = $-1
		if not mobj.reactiontime
			local rover
			
			// Shock the water
			for player in players.iterate do
				if not player.valid or player.spectator
					continue
				end
				
				if not player.mo
					continue
				end
				
				if player.mo.health <= 0
					continue
				end
				
				if (player.mo.eflags & MFE_UNDERWATER)
					P_DamageMobj(player.mo, mobj, mobj, 1)
				end
			end
			
			// Make the water flash
			for sector in sectors.iterate do
				if not sector.ffloors()
					continue
				end
				
				for rover in sector.ffloors() do
					if not (rover.flags & FF_EXISTS)
						continue
					end
					
					if not (rover.flags & FF_SWIMMABLE)
						continue
					end
					
					P_SpawnLightningFlash(rover.master.frontsector)
					break
				end
			end
			
			if mobj.extravalue1 + TICRATE*2 < leveltime
				mobj.extravalue1 = leveltime
				S_StartSound(nil, sfx_buzz1)
			end
			
			// If in the center, check to make sure
			// none of the players are in the water
			for player in players.iterate do
				if not player.valid or player.spectator
					continue
				end
				
				if not player.mo or player.bot
					continue
				end
				
				if player.mo.health <= 0
					continue
				end
				
				if player.mo.eflags & MFE_UNDERWATER
				// Stay put
					mobj.reactiontime = 2*TICRATE
					return true
				end
			end
		end
		
		if not mobj.reactiontime and mobj.health <= mobj.info.damage
		// Spawn pinch dummies from the center when we're leaving it.
			//local th
			//local mo2
			local dummy
			local way = mobj.threshold - 1 // 0 through 4
			local way2
			
			i = 0 // reset i to 0 so we can check how many clones we've removed
			
			// scan the thinkers to make sure all the old pinch dummies are gone before making new ones
			// this can happen if the boss was hurt earlier than expected
			for th in mobjs.iterate() do
				//mo2 = th
				if th.type == mobj.info.mass and th.tracer == mobj
					P_RemoveMobj(th)
					i = $+1
				end
				if i == 2 // we've already removed 2 of these, let's stop now
					break
				end
			end
			
			way = (way + P_RandomRange(1,3)) % 5 // dummy 1 at one of the first three options after eggmobile
			dummy = P_SpawnMobj(mobj.x, mobj.y, mobj.z, mobj.info.mass)
			dummy.angle = mobj.angle
			dummy.threshold = way + 1
			dummy.tracer = mobj
			
			repeat
				way2 = (way + P_RandomRange(1,3)) % 5 // dummy 2 has to be careful,
			until not (way2 == mobj.threshold - 1) // to make sure it doesn't try to go the Eggman Way if dummy 1 rolled high.
			dummy = P_SpawnMobj(mobj.x, mobj.y, mobj.z, mobj.info.mass)
			dummy.angle = mobj.angle
			dummy.threshold = way2 + 1
			dummy.tracer = mobj
			
			//CONS_Debug(DBG_GAMELOGIC, "Eggman path %d - Dummy selected paths %d and %d\n", mobj.threshold, way + 1, dummy threshold)
			P_LinedefExecute(LE_PINCHPHASE, mobj, nil)
		end
	elseif mobj.movecount // Firing mode
		local i
		
		// Look for a new target
		P_BossTargetPlayer(mobj, false)
		
		if not mobj.target or not mobj.target.player
			return true
		end
		
		// Are there any players underwater? If so, shock them!
		for player in players.iterate do
			if not player.valid or player.spectator
				continue
			end
			
			if not player.mo or player.bot
				continue
			end
			
			if (player.mo.eflags & MFE_UNDERWATER)
				mobj.movecount = 0
				mobj.state = mobj.info.spawnstate
				return true
			end
		end
		
		// Always face your target
		A_FaceTarget(mobj)
		
		// Check if the attack animation is running. If not, play it.
		if mobj.state < mobj.info.missilestate or mobj.state > mobj.info.raisestate
			if mobj.health <= mobj.info.damage // pinch phase
				mobj.movecount = $-1 // limited number of shots before diving again
			end
			if mobj.movecount
				mobj.state = mobj.info.missilestate
			end
		end
	elseif mobj.threshold >= 0 // Traveling mode
		local th
		local mo2
		local dist, dist2
		local speed
		
		mobj.target = nil
		
		if mobj.state != mobj.info.spawnstate and mobj.health > 0
			and not(mobj.flags2 & MF2_FRET)
			mobj.state = mobj.info.spawnstate
		end
		
		// scan the thinekrs
		// to find a point that matches
		// the number
		for th in mobjs.iterate()
			/*
			if th.function.acp1 != P_MobjThinker
				continue
			end
			*/
			
			//mo2 = th
			if th.type == MT_BOSS3WAYPOINT and th.spawnpoint and th.spawnpoint.angle == mobj.threshold
				mobj.target = th
				break
			end
		end
		
		if not mobj.target // Should NEVER happen
			print("Error: Boss 3 was unable to find specified waypoint: " + mobj.threshold)
			return true
		end
		
		dist = FixedHypot(FixedHypot(mobj.target.x - mobj.x, mobj.target.y - mobj.y), mobj.target.z - mobj.z)
		
		if dist < 1
			dist = 1
		end
		
		if mobj.movedir or mobj.health <= mobj.info.damage
			speed = mobj.info.speed * 2
		else
			speed = mobj.info.speed
		end
		
		mobj.momx = FixedMul(FixedDiv(mobj.target.x - mobj.x, dist), speed)
		mobj.momy = FixedMul(FixedDiv(mobj.target.y - mobj.y, dist), speed)
		mobj.momz = FixedMul(FixedDiv(mobj.target.z - mobj.z, dist), speed)
		
		if mobj.momx != 0 or mobj.momy != 0
			mobj.angle = R_PointToAngle2(0, 0, mobj.momx, mobj.momy)
		end
		
		dist2 = FixedHypot(FixedHypot(mobj.target.x - (mobj.x + mobj.momx), mobj.target.y - (mobj.y + mobj.momy)), mobj.target.z - (mobj.z + mobj.momz))
		
		if dist2 < 1
			dist2 = 1
		end
		
		if dist / FRACUNIT <= dist2 / FRACUNIT
			P_TeleportMove(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
			
			if mobj.threshold == 0
				mobj.reactiontime = 1 // Bzzt! Shock the water!
				mobj.movedir = 0
				
				if mobj.health <= 0
					mobj.flags = $|MF_NOGRAVITY|MF_NOCLIP
					mobj.flags = $|MF_NOCLIPHEIGHT
					mobj.threshold = -1
					return true
				end
			end
			
			// Set to next waypoint in sequence
			if mobj.target.spawnpoint
				// From the center point, choose one of the five paths
				if mobj.target.spawnpoint.angle == 0
					mobj.threshold = P_RandomRange(1,5)
				else
					mobj.threshold = mobj.target.spawnpoint.extrainfo
				end
				
				// If the deaf flag is set, go into firing mode
				if (mobj.target.spawnpoint.options & MTF_AMBUSH)
					mobj.movecount = mobj.health+1
				end
			else // This should never happen, as well
				//CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 waypoint has no spawnpoint associated with it.\n")
			end
		end
	end
	
	return true
end, MT_21EGGMOBILE3)

addHook("MobjDeath", function(target)
	local i = 0 // to check how many clones we've removed
	
	// scan the thinkers to make sure all the old pinch dummies are gone on death
	// this can happen if the boss was hurt earlier than expected
	for th in mobjs.iterate()
		if th.type == target.info.mass and th.tracer == target
			P_RemoveMobj(th)
			i = $+1
		end
		if i == 2 // we've already removed 2 of these, let's stop now
			break
		end
	end
end, MT_21EGGMOBILE3)

addHook("BossDeath", function(mo)
	A_21BossDeath(mo)
	return true
end, MT_21EGGMOBILE3)

mobjinfo[MT_21EGGMOBILE3] = {
	//$Name 2.1 Sea Egg
	//$Sprite OEGOA1
	//$Category Bosses
	doomednum = 4042,
	spawnstate = S_21EGGMOBILE3_STND,
	spawnhealth = 8,
	painstate = S_21EGGMOBILE3_PAIN,
	painchance = MT_PROPELLER,
	painsound = sfx_odmpai,
	missilestate = S_21EGGMOBILE3_ATK1,
	deathstate = S_21EGGMOBILE3_DIE1,
	xdeathstate = S_21EGGMOBILE3_FLEE1,
	deathsound = sfx_cybdth,
	speed = 8*FRACUNIT,
	radius = 32*FRACUNIT,
	height = 116*FRACUNIT,
	mass = MT_OLDFAKEMOBILE,
	damage = 3,
	activesound = sfx_telept,
	flags = MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY|MF_BOSS|MF_NOCLIPHEIGHT,
	raisestate = S_21EGGMOBILE3_LAUGH20
}

states[S_21EGGMOBILE3_STND] = {
	sprite = SPR_OEGO,
	frame = A,
	tics = 1,
	nextstate = S_21EGGMOBILE3_STND
}

states[S_21EGGMOBILE3_ATK1] = {
	sprite = SPR_OEGO,
	frame = B,
	tics = 2,
	nextstate = S_21EGGMOBILE3_ATK2
}

states[S_21EGGMOBILE3_ATK2] = {
	sprite = SPR_OEGO,
	frame = C,
	tics = 2,
	nextstate = S_21EGGMOBILE3_ATK3A
}

states[S_21EGGMOBILE3_ATK3A] = {
	sprite = SPR_OEGO,
	frame = D,
	tics = 2,
	action = A_BossFireShot,
	var1 = MT_OLDTORPEDO,
	var2 = 2,
	nextstate = S_21EGGMOBILE3_ATK3B
}

states[S_21EGGMOBILE3_ATK3B] = {
	sprite = SPR_OEGO,
	frame = D,
	tics = 2,
	action = A_BossFireShot,
	var1 = MT_OLDTORPEDO,
	var2 = 4,
	nextstate = S_21EGGMOBILE3_ATK3C
}

states[S_21EGGMOBILE3_ATK3C] = {
	sprite = SPR_OEGO,
	frame = D,
	tics = 2,
	action = A_BossFireShot,
	var1 = MT_OLDTORPEDO,
	var2 = 3,
	nextstate = S_21EGGMOBILE3_ATK3D
}

states[S_21EGGMOBILE3_ATK3D] = {
	sprite = SPR_OEGO,
	frame = D,
	tics = 2,
	action = A_BossFireShot,
	var1 = MT_OLDTORPEDO,
	var2 = 5,
	nextstate = S_21EGGMOBILE3_ATK4
}

states[S_21EGGMOBILE3_ATK4] = {
	sprite = SPR_OEGO,
	frame = E,
	tics = 2,
	nextstate = S_21EGGMOBILE3_ATK5
}

states[S_21EGGMOBILE3_ATK5] = {
	sprite = SPR_OEGO,
	frame = F,
	tics = 2,
	nextstate = S_21EGGMOBILE3_LAUGH1
}

states[S_21EGGMOBILE3_LAUGH1] = {
	sprite = SPR_OEGO,
	frame = G,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH2
}

states[S_21EGGMOBILE3_LAUGH2] = {
	sprite = SPR_OEGO,
	frame = H,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH3
}

states[S_21EGGMOBILE3_LAUGH3] = {
	sprite = SPR_OEGO,
	frame = G,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH4
}

states[S_21EGGMOBILE3_LAUGH4] = {
	sprite = SPR_OEGO,
	frame = H,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH5
}

states[S_21EGGMOBILE3_LAUGH5] = {
	sprite = SPR_OEGO,
	frame = G,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH6
}

states[S_21EGGMOBILE3_LAUGH6] = {
	sprite = SPR_OEGO,
	frame = H,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH7
}

states[S_21EGGMOBILE3_LAUGH7] = {
	sprite = SPR_OEGO,
	frame = G,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH8
}

states[S_21EGGMOBILE3_LAUGH8] = {
	sprite = SPR_OEGO,
	frame = H,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH9
}

states[S_21EGGMOBILE3_LAUGH9] = {
	sprite = SPR_OEGO,
	frame = G,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH10
}

states[S_21EGGMOBILE3_LAUGH10] = {
	sprite = SPR_OEGO,
	frame = H,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH11
}

states[S_21EGGMOBILE3_LAUGH11] = {
	sprite = SPR_OEGO,
	frame = G,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH12
}

states[S_21EGGMOBILE3_LAUGH12] = {
	sprite = SPR_OEGO,
	frame = H,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH13
}

states[S_21EGGMOBILE3_LAUGH13] = {
	sprite = SPR_OEGO,
	frame = G,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH14
}

states[S_21EGGMOBILE3_LAUGH14] = {
	sprite = SPR_OEGO,
	frame = H,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH15
}

states[S_21EGGMOBILE3_LAUGH15] = {
	sprite = SPR_OEGO,
	frame = G,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH16
}

states[S_21EGGMOBILE3_LAUGH16] = {
	sprite = SPR_OEGO,
	frame = H,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH17
}

states[S_21EGGMOBILE3_LAUGH17] = {
	sprite = SPR_OEGO,
	frame = G,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH18
}

states[S_21EGGMOBILE3_LAUGH18] = {
	sprite = SPR_OEGO,
	frame = H,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH19
}

states[S_21EGGMOBILE3_LAUGH19] = {
	sprite = SPR_OEGO,
	frame = G,
	tics = 4,
	nextstate = S_21EGGMOBILE3_LAUGH20
}

states[S_21EGGMOBILE3_LAUGH20] = {
	sprite = SPR_OEGO,
	frame = H,
	tics = 4,
	nextstate = S_21EGGMOBILE3_STND
}

states[S_21EGGMOBILE3_PAIN] = {
	sprite = SPR_OEGO,
	frame = I,
	tics = 1,
	action = A_21Boss3TakeDamage, // Replace this with A_21Boss3TakeDamage if necessary
	nextstate = S_21EGGMOBILE3_PAIN2
}

states[S_21EGGMOBILE3_PAIN2] = {
	sprite = SPR_OEGO,
	frame = I,
	tics = 23,
	action = A_Pain,
	nextstate = S_21EGGMOBILE3_STND
}

states[S_21EGGMOBILE3_DIE1] = {
	sprite = SPR_OEGO,
	frame = J,
	tics = 8,
	action = A_Fall,
	nextstate = S_21EGGMOBILE3_DIE2
}

states[S_21EGGMOBILE3_DIE2] = {
	sprite = SPR_OEGO,
	frame = J,
	tics = 8,
	action = A_BossScream,
	var1 = 0,
	var2 = MT_BOSSEXPLODE,
	nextstate = S_21EGGMOBILE3_DIE3
}

states[S_21EGGMOBILE3_DIE3] = {
	sprite = SPR_OEGO,
	frame = J,
	tics = 0,
	action = A_Repeat,
	var1 = 12,
	var2 = S_21EGGMOBILE3_DIE2,
	nextstate = S_21EGGMOBILE3_DIE4
}

states[S_21EGGMOBILE3_DIE4] = {
	sprite = SPR_OEGO,
	frame = J,
	tics = -1,
	action = A_BossDeath
}

states[S_21EGGMOBILE3_FLEE1] = {
	sprite = SPR_OEGO,
	frame = K,
	tics = 5,
	nextstate = S_21EGGMOBILE3_FLEE2
}

states[S_21EGGMOBILE3_FLEE2] = {
	sprite = SPR_OEGO,
	frame = L,
	tics = 5,
	nextstate = S_21EGGMOBILE3_FLEE1
}

// 2.1 Fake Mobile

addHook("TouchSpecial", function(special, toucher)
	local touchx, touchy, touchspeed
	local angle
	
	if FixedHypot(toucher.x-special.x, toucher.y-special.y) >
		FixedHypot((toucher.x-toucher.momx)-special.x, (toucher.y-toucher.momy)-special.y)
		touchx = toucher.x + toucher.momx
		touchy = toucher.y + toucher.momy
	else
		touchx = toucher.x
		touchy = toucher.y
	end
	
	angle = R_PointToAngle2(special.x, special.y, touchx, touchy)
	touchspeed = FixedHypot(toucher.momx, toucher.momy)
	
	toucher.momx = P_ReturnThrustX(special, angle, touchspeed)
	toucher.momy = P_ReturnThrustY(special, angle, touchspeed)
	toucher.momz = -toucher.momz
	if (toucher.player.pflags & PF_GLIDING)
		toucher.player.pflags = $ & ~(PF_GLIDING|PF_JUMPED)
		toucher.state = S_PLAY_FALL
	end
	
	// Play a bounce sound?
	S_StartSound(toucher, special.info.painsound)
	
	return true
end, MT_OLDFAKEMOBILE)

mobjinfo[MT_OLDFAKEMOBILE] = {
	doomednum = -1,
	spawnstate = S_OLDFAKEMOBILE_INIT,
	spawnhealth = 1000,
	painchance = MT_PROPELLER,
	painsound = sfx_s3k7b,
	missilestate = S_OLDFAKEMOBILE_ATK1,
	deathstate = S_XPLD1, // Replace with an old explosion, if necessary
	deathsound = sfx_pop,
	speed = 8*FRACUNIT,
	radius = 32*FRACUNIT,
	height = 116*FRACUNIT,
	damage = 3,
	flags = MF_SPECIAL|MF_NOGRAVITY|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT
}

states[S_OLDFAKEMOBILE_INIT] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 1,
	action = A_21BossJetFume,
	var1 = 1,
	var2 = 0,
	nextstate = S_OLDFAKEMOBILE
}

states[S_OLDFAKEMOBILE] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 1,
	action = A_21Boss3Path,
	nextstate = S_OLDFAKEMOBILE
}

states[S_OLDFAKEMOBILE_ATK1] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 2,
	nextstate = S_OLDFAKEMOBILE_ATK2
}

states[S_OLDFAKEMOBILE_ATK1] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 2,
	nextstate = S_OLDFAKEMOBILE_ATK2
}

states[S_OLDFAKEMOBILE_ATK2] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 2,
	nextstate = S_OLDFAKEMOBILE_ATK3A
}

states[S_OLDFAKEMOBILE_ATK3A] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 2,
	action = A_BossFireShot,
	var1 = MT_OLDTORPEDO2,
	var2 = 2,
	nextstate = S_OLDFAKEMOBILE_ATK3B
}

states[S_OLDFAKEMOBILE_ATK3B] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 2,
	action = A_BossFireShot,
	var1 = MT_OLDTORPEDO2,
	var2 = 4,
	nextstate = S_OLDFAKEMOBILE_ATK3C
}

states[S_OLDFAKEMOBILE_ATK3C] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 2,
	action = A_BossFireShot,
	var1 = MT_OLDTORPEDO2,
	var2 = 3,
	nextstate = S_OLDFAKEMOBILE_ATK3D
}

states[S_OLDFAKEMOBILE_ATK3D] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 2,
	action = A_BossFireShot,
	var1 = MT_OLDTORPEDO2,
	var2 = 5,
	nextstate = S_OLDFAKEMOBILE_ATK4
}

states[S_OLDFAKEMOBILE_ATK4] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 2,
	nextstate = S_OLDFAKEMOBILE_ATK5
}

states[S_OLDFAKEMOBILE_ATK5] = {
	sprite = SPR_OFAK,
	frame = A,
	tics = 2,
	nextstate = S_OLDFAKEMOBILE
}

// 2.1 Torpedo

mobjinfo[MT_OLDTORPEDO] = {
	doomednum = -1,
	spawnstate = S_OLDTORPEDO,
	spawnhealth = 1000,
	seesound = sfx_orlaun,
	reactiontime = 8,
	deathstate = S_MINE_BOOM1, // Make this a 2.1 variant if it changes in the future
	deathsound = sfx_cybdth,
	speed = 20*FRACUNIT,
	radius = 11*FRACUNIT,
	height = 8*FRACUNIT,
	mass = 100,
	damage = 20,
	flags = MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY
}

mobjinfo[MT_OLDTORPEDO2] = {
	doomednum = -1,
	spawnstate = S_OLDTORPEDO,
	spawnhealth = 1000,
	reactiontime = 8,
	deathstate = S_MINE_BOOM1, // Make this a 2.1 variant if it changes in the future
	deathsound = sfx_cybdth,
	speed = 20*FRACUNIT,
	radius = 11*FRACUNIT,
	height = 8*FRACUNIT,
	mass = 100,
	damage = 20,
	flags = MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY
}

states[S_OLDTORPEDO] = {
	sprite = SPR_OTRP,
	frame = A,
	tics = 1,
	action = A_SmokeTrailer,
	var1 = MT_SMOKE,
	var2 = 0,
	nextstate = S_OLDTORPEDO
}
