// 2.1 Eggscalibur - Ported from 2.1.25

freeslot(
	// Sprites
	"SPR_21EP",
	// Objects
	"MT_21EGGMOBILE4",
	"MT_21EGGMOBILE4_MACE",
	// States
	"S_21EGGMOBILE4_STND",
	"S_21EGGMOBILE4_LATK1",
	"S_21EGGMOBILE4_LATK2",
	"S_21EGGMOBILE4_LATK3",
	"S_21EGGMOBILE4_LATK4",
	"S_21EGGMOBILE4_LATK5",
	"S_21EGGMOBILE4_LATK6",
	"S_21EGGMOBILE4_RATK1",
	"S_21EGGMOBILE4_RATK2",
	"S_21EGGMOBILE4_RATK3",
	"S_21EGGMOBILE4_RATK4",
	"S_21EGGMOBILE4_RATK5",
	"S_21EGGMOBILE4_RATK6",
	"S_21EGGMOBILE4_RAISE1",
	"S_21EGGMOBILE4_RAISE2",
	"S_21EGGMOBILE4_RAISE3",
	"S_21EGGMOBILE4_RAISE4",
	"S_21EGGMOBILE4_RAISE5",
	"S_21EGGMOBILE4_RAISE6",
	"S_21EGGMOBILE4_RAISE7",
	"S_21EGGMOBILE4_RAISE8",
	"S_21EGGMOBILE4_RAISE9",
	"S_21EGGMOBILE4_RAISE10",
	"S_21EGGMOBILE4_PAIN",
	"S_21EGGMOBILE4_DIE1",
	"S_21EGGMOBILE4_DIE2",
	"S_21EGGMOBILE4_DIE3",
	"S_21EGGMOBILE4_DIE4",
	"S_21EGGMOBILE4_FLEE1",
	"S_21EGGMOBILE4_FLEE2",
	"S_21EGGMOBILE4_MACE"
)

// 2.1 Eggscalibur

// P_Boss4MoveCage ported from 2.1.25
local function P_21Boss4MoveCage(delta)
	local tag = 65534
	//local tag = -2
	//local snum
	
	for sector in sectors.iterate
		if sector.tag != tag
			continue
		end
		sector.floorheight = $+delta
		sector.ceilingheight = $+delta
	end
	
	for sector in sectors.iterate
		if sector.tag == tag
			return #sector
		end
	end
	
	return false
end

// P_Boss4MoveSpikeballs ported from 2.1.25
local function P_21Boss4MoveSpikeballs(mobj, angle, fz)
	local s
	local base = mobj
	local seg
	local dist = mobj.watertop+(16*(2^FRACBITS))
	local bz = mobj.watertop+(16*(2^FRACBITS))
	base = base.tracer
	while base do
		seg = base
		dist = 172*FRACUNIT
		s = 8
		while seg do
			s = $-1
			P_TeleportMove(seg, mobj.x + P_ReturnThrustX(mobj, angle, dist), mobj.y + P_ReturnThrustY(mobj, angle, dist), bz + FixedMul(fz, FixedDiv(s*(2^FRACBITS), 9*(2^FRACBITS))))
			seg = seg.hnext
			dist = $+(124*FRACUNIT)
		end
		angle = $+(ANG60*2) // Replacement for ANGLE_MAX/3 since ANGLE_MAX = -1 in Lua
		base = base.tracer
	end
end

// P_Boss4PinchSpikeballs ported from 2.1.25
local function P_21Boss4PinchSpikeballs(mobj, angle, fz)
	local s
	local base = mobj
	local seg
	local dist = mobj.watertop+(16*(2^FRACBITS))
	local bz = mobj.watertop+(16*(2^FRACBITS))
	base = base.tracer
	while base do
		seg = base
		dist = 112*FRACUNIT
		s = 10
		while seg do
			s = $-1
			P_TeleportMove(seg, seg.x, seg.y, bz + FixedMul(fz, FixedDiv(s*(2^FRACBITS), 9*(2^FRACBITS))))
			P_TryMove(seg, mobj.x + P_ReturnThrustX(mobj, angle, dist), mobj.y + P_ReturnThrustY(mobj, angle, dist), true)
			seg = seg.hnext
			dist = $+(132*FRACUNIT)
		end
		angle = $+(ANG60*2)
		base = base.tracer
	end
end

local function P_21Boss4DestroyCage()
	local tag = 65534
	//local tag = -2
	local snum, nextt
	local a
	local sector, rsec
	local rover
	
	// This will be the final iteration of sector tag
	// We'll destroy the tag list as we go.
	for sector in sectors.iterate
		if sector.tag == tag
			nextt = #sector
			break
		end
	end
	
	// Destroy the FOFs.
	for sector in sectors.iterate
		for rover in sector.ffloors()
			if (rover.flags & FF_EXISTS) and rover.sector.tag == tag
				if (rover.flags & FF_RENDERALL) // checking for FF_RENDERANY.
					EV_CrumbleChain(sector, rover) // This FOF is visible to some extent? Crumble it.
				else // Completely invisible FOF
					// no longer exists (can't collide with again)
					rover.flags = $ & ~FF_EXISTS
				end
			end
		end
	end
end

local function P_21Boss4PopSpikeballs(mobj)
	local base = mobj.tracer
	local seg, nextt
	mobj.tracer = nil
	while base do
		nextt = base.tracer
		base.tracer = nil
		seg = base
		while seg do
			if seg.health
				P_KillMobj(seg, nil, nil)
			end
			seg = seg.hnext
		end
		base = nextt
	end
end

addHook("BossThinker", function(mobj)
	if mobj.state == mobj.info.spawnstate
		if mobj.health > mobj.info.damage or mobj.movedir == 4
			mobj.flags2 = $ & ~MF2_FRET
		end
		mobj.reactiontime = 0 // Drop the cage immediately.
	end
	
	// Oh no, we dead? D:
	if not mobj.health
		if mobj.tracer // need to clean up!
			P_21Boss4DestroyCage() // Just in case pinch phase was skipped
			P_21Boss4PopSpikeballs(mobj)
		end
		return true
	end
	
	// movedir == battle stage:
	//   0: initialization
	//   1: phase 1 forward
	//   2: phase 1 reverse
	//   3: pinch rise
	//   4: pinch phase
	// WELCOME to your DOOM!
	if mobj.movedir == 0
		// For this stage only:
		// movecount == cage height
		// threshold == cage momz
		if mobj.movecount == 0 // Initialize stage!
			local z
			local i, arm
			local seg = mobj
			local base = mobj
			// First frame init, spawn all the things.
			mobj.watertop = mobj.z
			z = mobj.z + mobj.height/2 - mobjinfo[MT_21EGGMOBILE4_MACE].height/2
			for arm = 0, 2, 1 do
				seg = P_SpawnMobj(mobj.x, mobj.y, z, MT_21EGGMOBILE4_MACE)
				base.tracer = seg
				base = seg
				seg.target = mobj
				for i = 0, 8, 1 do
					seg.hnext = P_SpawnMobj(mobj.x, mobj.y, z, MT_21EGGMOBILE4_MACE)
					seg.hnext.hprev = seg
					seg = seg.hnext
				end
			end
			// Move the cage up to the sky.
			mobj.movecount = 800*FRACUNIT
			if not P_21Boss4MoveCage(mobj.movecount)
				mobj.movecount = 0
				mobj.threshold = 3*TICRATE
				mobj.extravalue1 = 1
				mobj.movedir = $+1 // We don't have a cage, just continue
			else
				P_21Boss4MoveSpikeballs(mobj, 0, mobj.movecount)
			end
		else // Cage slams down over Eggman's head!
			local oldz = mobj.movecount
			mobj.threshold = $-(5*FRACUNIT)
			mobj.movecount = $+mobj.threshold
			if mobj.movecount < 0
				mobj.movecount = 0
			end
			P_21Boss4MoveCage(mobj.movecount - oldz)
			P_21Boss4MoveSpikeballs(mobj, 0, mobj.movecount)
			if mobj.movecount == 0
				mobj.threshold = 3*TICRATE
				mobj.extravalue1 = 1
				P_LinedefExecute(LE_BOSS4DROP, mobj, nil)
				mobj.movedir = $+1 // Initialization complete, next phase!
			end
		end
		return true
	// Normal operation
	elseif mobj.movedir == 1 or mobj.movedir == 2
		//print("do nothing")
	// Pinch phase init!
	elseif mobj.movedir == 3
		local z
		if mobj.z < mobj.watertop+(512*(2^FRACBITS))
			mobj.momz = 8*FRACUNIT
		else
			mobj.momz = 0
			mobj.movedir = $+1
		end
		mobj.movecount = $+(400*(FRACBITS / 2))
		mobj.movecount = $%(360*FRACUNIT)
		z = mobj.z - mobj.watertop - mobjinfo[MT_21EGGMOBILE4_MACE].height - mobj.height/2
		if z < 0 // We haven't risen high enough to pull the spikeballs along yet
			P_21Boss4MoveSpikeballs(mobj, FixedAngle(mobj.movecount), 0) // So don't pull the spikeballs along yet.
		else
			P_21Boss4PinchSpikeballs(mobj, FixedAngle(mobj.movecount), z)
		end
		return true
	// Pinch phase!
	elseif mobj.movedir == 4
		if mobj.z < (mobj.watertop + ((512+128*(mobj.info.damage-mobj.health))*(2^FRACBITS)))
			mobj.momz = 8*FRACUNIT
		else
			mobj.momz = 0
		end
		mobj.movecount = $+((800+800*(mobj.info.damage-mobj.health)) * (2 ^ (FRACBITS / 2)))
		mobj.movecount = $%(360*FRACUNIT)
		P_21Boss4PinchSpikeballs(mobj, FixedAngle(mobj.movecount), mobj.z - mobj.watertop - mobjinfo[MT_21EGGMOBILE4_MACE].height - mobj.height/2)
		
		if not mobj.target or not mobj.target.health
			P_SupermanLook4Players(mobj)
		end
		A_FaceTarget(mobj)
		return true
	else // ?????
		return true
	end
	
	// Haahahahahaaa, and let the FUN.. BEGIN!
	// movedir   == arms direction
	// movecount == arms angle
	// threshold == countdown to next attack
	// reactiontime == cage raise, speed burst
	// movefactor == cage z
	// friction == turns until helm lift

	// Raise the cage!
	if mobj.reactiontime == 1
		local oldz = mobj.movefactor
		mobj.movefactor = $+(8*FRACUNIT)
		if mobj.movefactor > 128*FRACUNIT
			mobj.movefactor = 128*FRACUNIT
		end
		P_21Boss4MoveCage(mobj.movefactor - oldz)
	// Drop the cage!
	elseif mobj.movefactor
		local oldz = mobj.movefactor
		mobj.movefactor = $-(4*FRACUNIT)
		if mobj.movefactor < 0
			mobj.movefactor = 0
		end
		P_21Boss4MoveCage(mobj.movefactor - oldz)
		if not mobj.movefactor
			if mobj.health <= mobj.info.damage
				// Proceed to pinch phase!
				P_21Boss4DestroyCage()
				mobj.movedir = 3
				P_LinedefExecute(LE_PINCHPHASE, mobj, nil)
				return true
			end
			P_LinedefExecute(LE_BOSS4DROP, mobj, nil)
		end
	end
	
		local movespeed = 170 * (2 ^ (FRACBITS / 2))
		if mobj.reactiontime == 2
			movespeed = $*3
		end
		if mobj.movedir == 2
			mobj.movecount = $-movespeed
		else
			mobj.movecount = $+movespeed
		end
		
	mobj.movecount = $%(360*FRACUNIT)
	P_21Boss4MoveSpikeballs(mobj, FixedAngle(mobj.movecount), mobj.movefactor)
	
	local extravalue1Set = false
	
	// Check for attacks, always tick the timer even while animating!!
	if not (mobj.flags2 & MF2_FRET) // but pause for pain so we don't interrupt pinch phase, eep!
	and mobj.threshold <= 0 // Make sure this code still runs in the rare case that mobj.threshold goes below 0
		// 5 -> 2.5 second timer
		mobj.threshold = 5*TICRATE-(TICRATE/2)*(mobj.info.spawnhealth-mobj.health)
		if mobj.threshold < 1
			mobj.threshold = 1
		end
		
		if mobj.extravalue1 == 0
			mobj.state = mobj.info.raisestate
			mobj.extravalue1 = 3
			extravalue1Set = true
		else
			if mobj.reactiontime == 1 // Cage is raised?
				mobj.reactiontime = 0 // Drop it!
			end
			local randomValue = P_RandomKey(10)
			// Telegraph Right (Speed Up!!)
			if randomValue == 1
			or randomValue == 3
			or randomValue == 4
			or randomValue == 5
			or randomValue == 6
				mobj.state = mobj.info.missilestate
			// Telegraph left (Reverse Direction)
			else
				mobj.state = mobj.info.meleestate
			end
		end
		if not extravalue1Set
			mobj.extravalue1 = $-1
		end
	end
	mobj.threshold = $-1
	
	// Leave if animating.
	if mobj.state != mobj.info.spawnstate
		return true
	end
	
	// Map allows us to get killed despite cage being down?
	if mobj.health <= mobj.info.damage
	// Proceed to pinch phase!
		P_21Boss4DestroyCage()
		// spawn jet's flame now you're flying upwards
		// tracer is already used, so if this ever gets reached again we've got problems
		A_21BossJetFume(mobj, 3, 0)
		mobj.movedir = 3
		P_LinedefExecute(LE_PINCHPHASE, mobj, nil)
		return true
	end
	
	mobj.reactiontime = 0 // Drop the cage if it hasn't been dropped already.
	if not mobj.target or not mobj.target.health
		P_SupermanLook4Players(mobj)
	end
	A_FaceTarget(mobj)
	
	return true // Do not use the GenericBossThinker
end, MT_21EGGMOBILE4)

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

mobjinfo[MT_21EGGMOBILE4] = {
	//$Name 2.1 Eggscalibur
	//$Sprite 21EPA1
	//$Category Bosses
	doomednum = 4043,
	spawnstate = S_21EGGMOBILE4_STND,
	spawnhealth = 8,
	painstate = S_21EGGMOBILE4_PAIN,
	painsound = sfx_odmpai,
	meleestate = S_21EGGMOBILE4_LATK1,
	missilestate = S_21EGGMOBILE4_RATK1,
	deathstate = S_21EGGMOBILE4_DIE1,
	xdeathstate = S_21EGGMOBILE4_FLEE1,
	deathsound = sfx_cybdth,
	radius = 24*FRACUNIT,
	height = 76*FRACUNIT,
	damage = 3,
	flags = MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY|MF_BOSS|MF_NOCLIPHEIGHT,
	raisestate = S_21EGGMOBILE4_RAISE1
}

states[S_21EGGMOBILE4_STND] = {
	sprite = SPR_21EP,
	frame = A,
	tics = -1
}

states[S_21EGGMOBILE4_LATK1] = {
	sprite = SPR_21EP,
	frame = B,
	tics = 3,
	nextstate = S_21EGGMOBILE4_LATK2
}

states[S_21EGGMOBILE4_LATK2] = {
	sprite = SPR_21EP,
	frame = C,
	tics = 15,
	nextstate = S_21EGGMOBILE4_LATK3
}

states[S_21EGGMOBILE4_LATK3] = {
	sprite = SPR_21EP,
	frame = D,
	tics = 2,
	nextstate = S_21EGGMOBILE4_LATK4
}

states[S_21EGGMOBILE4_LATK4] = {
	sprite = SPR_21EP,
	frame = E,
	tics = 4,
	nextstate = S_21EGGMOBILE4_LATK5
}

states[S_21EGGMOBILE4_LATK5] = {
	sprite = SPR_21EP,
	frame = E,
	tics = 50,
	action = A_Boss4Reverse, // Replace this with A_21Boss4Reverse if it changes in the future
	var1 = sfx_mswing,
	var2 = 0,
	nextstate = S_21EGGMOBILE4_LATK6
}

states[S_21EGGMOBILE4_LATK6] = {
	sprite = SPR_21EP,
	frame = F,
	tics = 2,
	nextstate = S_21EGGMOBILE4_STND
}

states[S_21EGGMOBILE4_RATK1] = {
	sprite = SPR_21EP,
	frame = G,
	tics = 3,
	nextstate = S_21EGGMOBILE4_RATK2
}

states[S_21EGGMOBILE4_RATK2] = {
	sprite = SPR_21EP,
	frame = H,
	tics = 15,
	nextstate = S_21EGGMOBILE4_RATK3
}

states[S_21EGGMOBILE4_RATK3] = {
	sprite = SPR_21EP,
	frame = I,
	tics = 2,
	nextstate = S_21EGGMOBILE4_RATK4
}

states[S_21EGGMOBILE4_RATK4] = {
	sprite = SPR_21EP,
	frame = J,
	tics = 4,
	nextstate = S_21EGGMOBILE4_RATK5
}

states[S_21EGGMOBILE4_RATK5] = {
	sprite = SPR_21EP,
	frame = J,
	tics = 150,
	action = A_Boss4SpeedUp, // Replace this with A_21Boss4SpeedUp if it changes in the future
	var1 = sfx_mswing,
	var2 = 0,
	nextstate = S_21EGGMOBILE4_RATK6
}

states[S_21EGGMOBILE4_RATK6] = {
	sprite = SPR_21EP,
	frame = K,
	tics = 2,
	nextstate = S_21EGGMOBILE4_STND
}

states[S_21EGGMOBILE4_RAISE1] = {
	sprite = SPR_21EP,
	frame = A,
	tics = 20,
	action = A_Boss4Raise, // Replace this with A_21Boss4Raise if it changes in the future
	var1 = sfx_doord1,
	var2 = 0,
	nextstate = S_21EGGMOBILE4_RAISE2
}

states[S_21EGGMOBILE4_RAISE2] = {
	sprite = SPR_21EP,
	frame = N,
	tics = 10,
	nextstate = S_21EGGMOBILE4_RAISE3
}

states[S_21EGGMOBILE4_RAISE3] = {
	sprite = SPR_21EP,
	frame = O,
	tics = 10,
	nextstate = S_21EGGMOBILE4_RAISE4
}

states[S_21EGGMOBILE4_RAISE4] = {
	sprite = SPR_21EP,
	frame = N,
	tics = 10,
	nextstate = S_21EGGMOBILE4_RAISE5
}

states[S_21EGGMOBILE4_RAISE5] = {
	sprite = SPR_21EP,
	frame = O,
	tics = 10,
	nextstate = S_21EGGMOBILE4_RAISE6
}

states[S_21EGGMOBILE4_RAISE6] = {
	sprite = SPR_21EP,
	frame = N,
	tics = 10,
	nextstate = S_21EGGMOBILE4_RAISE7
}

states[S_21EGGMOBILE4_RAISE7] = {
	sprite = SPR_21EP,
	frame = O,
	tics = 10,
	nextstate = S_21EGGMOBILE4_RAISE8
}

states[S_21EGGMOBILE4_RAISE8] = {
	sprite = SPR_21EP,
	frame = N,
	tics = 10,
	nextstate = S_21EGGMOBILE4_RAISE9
}

states[S_21EGGMOBILE4_RAISE9] = {
	sprite = SPR_21EP,
	frame = O,
	tics = 10,
	nextstate = S_21EGGMOBILE4_RAISE10
}

states[S_21EGGMOBILE4_RAISE10] = {
	sprite = SPR_21EP,
	frame = N,
	tics = 10,
	nextstate = S_21EGGMOBILE4_STND
}

states[S_21EGGMOBILE4_PAIN] = {
	sprite = SPR_21EP,
	frame = L,
	tics = 24,
	action = A_Pain,
	nextstate = S_21EGGMOBILE4_STND
}

states[S_21EGGMOBILE4_DIE1] = {
	sprite = SPR_21EP,
	frame = M,
	tics = 8,
	action = A_Fall,
	nextstate = S_21EGGMOBILE4_DIE2
	}

states[S_21EGGMOBILE4_DIE2] = {
	sprite = SPR_21EP,
	frame = M,
	tics = 8,
	action = A_BossScream,
	var1 = 0,
	var2 = MT_BOSSEXPLODE,
	nextstate = S_21EGGMOBILE4_DIE3
	}

states[S_21EGGMOBILE4_DIE3] = {
	sprite = SPR_21EP,
	frame = M,
	tics = 0,
	action = A_Repeat,
	var1 = 12,
	var2 = S_21EGGMOBILE4_DIE2,
	nextstate = S_21EGGMOBILE4_DIE4
	}

states[S_21EGGMOBILE4_DIE4] = {
	sprite = SPR_21EP,
	frame = M,
	tics = -1,
	action = A_BossDeath
	}

states[S_21EGGMOBILE4_FLEE1] = {
	sprite = SPR_21EP,
	frame = N,
	tics = 5,
	nextstate = S_21EGGMOBILE4_FLEE2
}

states[S_21EGGMOBILE4_FLEE2] = {
	sprite = SPR_21EP,
	frame = O,
	tics = 5,
	nextstate = S_21EGGMOBILE4_FLEE1
}

// 2.1 Eggscalibur Mace

mobjinfo[MT_21EGGMOBILE4_MACE] = {
	doomednum = -1,
	spawnstate = S_21EGGMOBILE4_MACE,
	spawnhealth = 1000,
	reactiontime = 8,
	deathstate = S_BOSSEXPLODE,
	deathsound = sfx_cybdth,
	speed = 48*FRACUNIT,
	radius = 34*FRACUNIT,
	height = 68*FRACUNIT,
	mass = 100,
	damage = 1,
	activesound = sfx_mswing,
	flags = MF_PAIN|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY
}

states[S_21EGGMOBILE4_MACE] = {
	sprite = SPR_21MC,
	frame = D,
	tics = -1
}
