// 2.0 Egg Mobile - Ported from 2.0.7
// PLEASE LOAD LUA_CMMN, LUA_OJTF AND LUA_EMCM BEFORE THIS

freeslot(
	// Objects
	"MT_20EGGMOBILE",
	//"MT_20ROCKET",
	// States
	"S_20EGGMOBILE_STND",
	"S_20EGGMOBILE_LATK1",
	"S_20EGGMOBILE_LATK2",
	"S_20EGGMOBILE_LATK3",
	"S_20EGGMOBILE_LATK4",
	"S_20EGGMOBILE_LATK5",
	"S_20EGGMOBILE_LATK6",
	"S_20EGGMOBILE_LATK7",
	"S_20EGGMOBILE_LATK8",
	"S_20EGGMOBILE_LATK9",
	"S_20EGGMOBILE_LATK10",
	"S_20EGGMOBILE_RATK1",
	"S_20EGGMOBILE_RATK2",
	"S_20EGGMOBILE_RATK3",
	"S_20EGGMOBILE_RATK4",
	"S_20EGGMOBILE_RATK5",
	"S_20EGGMOBILE_RATK6",
	"S_20EGGMOBILE_RATK7",
	"S_20EGGMOBILE_RATK8",
	"S_20EGGMOBILE_RATK9",
	"S_20EGGMOBILE_RATK10",
	"S_20EGGMOBILE_PANIC1",
	"S_20EGGMOBILE_PANIC2",
	"S_20EGGMOBILE_PAIN",
	"S_20EGGMOBILE_PAIN2"
)

// 2.0 Eggmobile

local function nomissile(actor)
	if not (actor and actor.valid) then return end
	
	// possibly choose another target
	if multiplayer and P_RandomByte() < 2
		if P_LookForPlayers(actor, 0, true, false)
			return // got a new target
		end
	end
	
	//chase towards player
	actor.movecount = $-1
	if actor.movecount < 0 or not P_Move(actor, actor.info.speed)
		P_NewChaseDir(actor)
	end
end

function A_FDBoss1Chase(actor, var1, var2)
	if not (actor and actor.valid) then return end
	
	local delta
	
	if actor.reactiontime then actor.reactiontime = $-1 end
	
	// Use the 2.0 variant if var1 is not 0
	if var1 ~= 0 then
		if actor.z < actor.floorz+33*FRACUNIT then
			actor.z = actor.floorz+33*FRACUNIT
		end
	end
	
	// turn towards movement direction if not there yet
	if actor.movedir < NUMDIRS then // NUMDIRS should be 8
		actor.angle = $ & (7 * (2^29))
		delta = actor.angle - (actor.movedir * (2^29))
		
		if delta > 0 then
			actor.angle = $-ANGLE_45
		elseif delta < 0 then
			actor.angle = $+ANGLE_45
		end
	end
	
	// do not attack twice in a row
	if (actor.flags2 & MF2_JUSTATTACKED) then
		actor.flags2 = $ & ~MF2_JUSTATTACKED
		P_NewChaseDir(actor)
		return
	end
	
	if actor.movecount then
		nomissile(actor)
		return
	end
	
	if not P_CheckMissileRange(actor) then
		nomissile(actor)
		return
	end
	
	if actor.reactiontime <= 0 then
		if actor.health > actor.info.damage then
			if (P_RandomByte() & 1) then
				actor.state = actor.info.missilestate
			else
				actor.state = actor.info.meleestate
			end
		else
			actor.state = actor.info.raisestate
		end
		
		actor.flags2 = $|MF2_JUSTATTACKED
		actor.reactiontime = 2*TICRATE
		return
	end
end

// Make the 2.0 Egg Mobile spawn 33 FRACUNITS off the ground if its z-position hasn't been set
addHook("MapThingSpawn", function(mobj, mapthing)
	if not (mobj and mobj.valid
	and mapthing and mapthing.valid) then
		return
	end
	
	local offset
	
	if mapthing.z ~= 0 then
		offset = mapthing.z
	else
		offset = 33*FRACUNIT
	end
	
	if (mapthing.options & MTF_OBJECTFLIP) then
		if offset ~= 0 then
			mobj.z = mobj.z - offset
		else
			mobj.z = mobj.ceilingz
		end
	else
		if offset ~= 0 then
			mobj.z = mobj.z + offset
		else
			mobj.z = mobj.floorz
		end
	end
	
	// Spawn a spike ball shield if the ambush flag is set
	if (mapthing.options & MTF_AMBUSH) then
		local spikemobj
		for i = 0, 3, 1 do
			spikemobj = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_SPIKEBALL)
			spikemobj.target = mobj
			if i == 0 then
				spikemobj.angle = 0
			elseif i == 1 then
				spikemobj.angle = ANGLE_90
			elseif i == 2 then
				spikemobj.angle = ANGLE_180
			elseif i == 3 then
				spikemobj.angle = ANGLE_270
			end
		end
	end
end, MT_20EGGMOBILE)

// The Egg Mobile originally bounced off of players instead of going through them in "SKULLFLY" mode
addHook("MobjMoveCollide", function(tmthing, thing)
	if not (tmthing and tmthing.valid
	and thing and thing.valid) then
		return
	end
	
	// Only bounce off of objects if the 2.0 Egg Mobile is in "SKULLFLY" mode
	if not (tmthing.flags2 & MF2_SKULLFLY) then return end
	
	tmthing.momx = -$
	tmthing.momy = -$
	tmthing.momz = -$
	return false
end, MT_20EGGMOBILE)

// Prevents the 2.0 Egg Mobile from bouncing off of the walls in "SKULLFLY" mode
addHook("MobjMoveBlocked", function(mobj)
	mobj.flags2 = $ & ~MF2_SKULLFLY
	mobj.momx = 0
	mobj.momy = 0
	mobj.momz = 0
	return true
end, MT_20EGGMOBILE)

// Prevents the 2.0 Egg Mobile from being hit-spammed
addHook("MobjDamage", function(target, inflictor, source)
	if not (target and target.valid) then return end
	if (target.flags2 & MF2_SKULLFLY) then target.flags2 = $ & ~MF2_SKULLFLY end
end, MT_20EGGMOBILE)

// Makes the spikeball rotate around its target (only for the 2.0 Egg Mobile)
addHook("MobjThinker", function(mobj)
	if not (mobj and mobj.valid) then return end
	
	if mobj.target and mobj.target.valid and mobj.target.type == MT_20EGGMOBILE then
		local radius = FixedMul(12*mobj.info.speed, mobj.scale)
		
		mobj.angle = $ + FixedAngle(mobj.info.speed)
		P_MoveOrigin(
			mobj,
			mobj.target.x + FixedMul(cos(mobj.angle), radius),
			mobj.target.y + FixedMul(sin(mobj.angle), radius),
			mobj.target.z + mobj.target.height/2
		)
	end
end, MT_SPIKEBALL)

// Override the vanilla boss death function
addHook("BossDeath", function(mobj)
	if not (mobj and mobj.valid) then return end
	A_21BossDeath(mobj, 0, 0)
	return true
end, MT_20EGGMOBILE)

// Ported BossThinker behavior for 2.0 Eggmobile from 2.0.7
addHook("BossThinker", function(mobj)
	if not (mobj and mobj.valid) then return end
	
	if mobj.health < mobj.info.damage+1 and (leveltime & 1) and mobj.health > 0 then
		P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_SMOKE) // Replace MT_SMOKE with MT_21SMOKE if necessary
	end
	if mobj.flags2 & MF2_SKULLFLY then
		P_SpawnGhostMobj(mobj)
		
		/*
		// Use this for pre-2.0 era Eggman
		
		local spawnmobj
		spawnmobj = P_SpawnMobj(mobj.x, mobj.y, mobj.z, mobj.info.painchance)
		spawnmobj.target = mobj
		spawnmobj.color = SKINCOLOR_GREY
		*/
	end
	
	if states[mobj.state].nextstate == mobj.info.spawnstate and mobj.tics == 1 then
		mobj.flags2 = $ & ~MF2_FRET
		if not (mobj.flags2 & MF2_SKULLFLY) then
			mobj.momx = 0
			mobj.momy = 0
			mobj.momz = 0
		end
	end
	
	if not mobj.tracer then A_OldBossJetFumes(mobj, 0, 0) end
	
	if not (mobj.target and mobj.target.valid and (mobj.target.flags & MF_SHOOTABLE)) then
		if mobj.health <= 0 then
			if P_LookForPlayers(mobj, 0, true) and mobj.info.mass then // Bid farewell!
				S_StartSound(mobj, mobj.info.mass)
			end
			return true
		end
		
		// look for a new target
		if P_LookForPlayers(mobj, 0, true) and mobj.info.seesound then
			S_StartSound(mobj, mobj.info.seesound)
		end
		
		return true
	end
	
	if mobj.state == mobj.info.spawnstate then A_FDBoss1Chase(mobj, 1, 0) end
	
	if mobj.state == mobj.info.meleestate
	or (mobj.state == mobj.info.missilestate and mobj.health > mobj.info.damage) then
		mobj.angle = R_PointToAngle2(mobj.x, mobj.y, mobj.target.x, mobj.target.y)
	end
	
	return true
end, MT_20EGGMOBILE)

mobjinfo[MT_20EGGMOBILE] = {
	//$Name 2.0 Eggmobile
	//$Sprite 21EMA1
	//$Category Bosses
	//$Flags4Text End level on death
	//$Flags8Text Spawn w/ Spikeball Shield
	doomednum = 4054,
	spawnstate = S_20EGGMOBILE_STND,
	spawnhealth = 8,
	seestate = S_20EGGMOBILE_STND,
	reactiontime = 8,
	painstate = S_20EGGMOBILE_PAIN,
	painchance = MT_THOK,
	painsound = sfx_dmpain,
	meleestate = S_20EGGMOBILE_LATK1,
	missilestate = S_20EGGMOBILE_RATK1,
	deathstate = S_21EGGMOBILE_DIE1,
	xdeathstate = S_21EGGMOBILE_FLEE1,
	deathsound = sfx_cybdth,
	speed = 4,
	radius = 24*FRACUNIT,
	height = 52*FRACUNIT,
	damage = 2,
	activesound = sfx_telept,
	flags = MF_SPECIAL|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_BOSS,
	raisestate = S_20EGGMOBILE_PANIC1
}

states[S_20EGGMOBILE_STND] =	{SPR_21EM,	A,	1,	nil,	0,	0,	S_20EGGMOBILE_STND}

states[S_20EGGMOBILE_LATK1] =	{SPR_21EM,	B,	3,	nil,			0,			0,	S_20EGGMOBILE_LATK2}
states[S_20EGGMOBILE_LATK2] =	{SPR_21EM,	C,	30,	nil,			0,			0,	S_20EGGMOBILE_LATK3}
states[S_20EGGMOBILE_LATK3] =	{SPR_21EM,	D,	2,	nil,			0,			0,	S_20EGGMOBILE_LATK4}
states[S_20EGGMOBILE_LATK4] =	{SPR_21EM,	E,	1,	nil,			0,			0,	S_20EGGMOBILE_LATK5}
states[S_20EGGMOBILE_LATK5] =	{SPR_21EM,	F,	1,	nil,			0,			0,	S_20EGGMOBILE_LATK6}
states[S_20EGGMOBILE_LATK6] =	{SPR_21EM,	G,	1,	nil,			0,			0,	S_20EGGMOBILE_LATK7}
states[S_20EGGMOBILE_LATK7] =	{SPR_21EM,	H,	1,	nil,			0,			0,	S_20EGGMOBILE_LATK8}
// Replace A_BossFireShot with A_21BossFireShot if it changes in the future
// Replace MT_ROCKET with MT_20ROCKET if it changes in the future
states[S_20EGGMOBILE_LATK8] =	{SPR_21EM,	I,	15,	A_BossFireShot,	MT_ROCKET,	0,	S_20EGGMOBILE_LATK9}
states[S_20EGGMOBILE_LATK9] =	{SPR_21EM,	J,	10,	nil,			0,			0,	S_20EGGMOBILE_LATK10}
states[S_20EGGMOBILE_LATK10] =	{SPR_21EM,	K,	2,	nil,			0,			0,	S_20EGGMOBILE_STND}

states[S_20EGGMOBILE_RATK1] =	{SPR_21EM,	L,	3,	nil,			0,			0,	S_20EGGMOBILE_RATK2}
states[S_20EGGMOBILE_RATK2] =	{SPR_21EM,	M,	30,	nil,			0,			0,	S_20EGGMOBILE_RATK3}
states[S_20EGGMOBILE_RATK3] =	{SPR_21EM,	N,	2,	nil,			0,			0,	S_20EGGMOBILE_RATK4}
states[S_20EGGMOBILE_RATK4] =	{SPR_21EM,	O,	1,	nil,			0,			0,	S_20EGGMOBILE_RATK5}
states[S_20EGGMOBILE_RATK5] =	{SPR_21EM,	P,	1,	nil,			0,			0,	S_20EGGMOBILE_RATK6}
states[S_20EGGMOBILE_RATK6] =	{SPR_21EM,	Q,	1,	nil,			0,			0,	S_20EGGMOBILE_RATK7}
states[S_20EGGMOBILE_RATK7] =	{SPR_21EM,	R,	1,	nil,			0,			0,	S_20EGGMOBILE_RATK8}
// Replace A_BossFireShot with A_21BossFireShot if it changes in the future
// Replace MT_ROCKET with MT_20ROCKET if it changes in the future
states[S_20EGGMOBILE_RATK8] =	{SPR_21EM,	S,	15,	A_BossFireShot,	MT_ROCKET,	1,	S_20EGGMOBILE_RATK9}
states[S_20EGGMOBILE_RATK9] =	{SPR_21EM,	T,	10,	nil,			0,			0,	S_20EGGMOBILE_RATK10}
states[S_20EGGMOBILE_RATK10] =	{SPR_21EM,	U,	2,	nil,			0,			0,	S_20EGGMOBILE_STND}

states[S_20EGGMOBILE_PANIC1] =	{SPR_21EM,	D,	35,	nil,			0,	0,	S_20EGGMOBILE_PANIC2}
states[S_20EGGMOBILE_PANIC2] =	{SPR_21EM,	A,	35,	A_SkullAttack,	0,	0,	S_20EGGMOBILE_STND}

states[S_20EGGMOBILE_PAIN] =	{SPR_21EM,	V,	24,	A_Pain,			0,	0,	S_20EGGMOBILE_PAIN2}
states[S_20EGGMOBILE_PAIN2] =	{SPR_21EM,	V,	24,	A_SkullAttack,	1,	0,	S_20EGGMOBILE_STND}

// Not needed, because the current "rocket" works just fine
/*
// 2.0 "Rocket" Laser

mobjinfo[MT_20ROCKET] = {
	doomednum = -1,
	spawnstate = S_ROCKET, // Replace this with S_20ROCKET if it changes in the future
	spawnhealth = 1000,
	seesound = sfx_rlaunc,
	reactiontime = 8,
	speed = 20*FRACUNIT,
	radius = 11*FRACUNIT,
	height = 8*FRACUNIT,
	damage = 20,
	flags = MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY
}
*/
