// 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
		actor.reactiontime = $-1
	end
	
	// Use the 2.0 variant if var1 is not 0
	if var1 ~= 0
		if actor.z < actor.floorz+33*FRACUNIT
			actor.z = actor.floorz+33*FRACUNIT
		end
	end
	
	// turn towards movement direction if not there yet
	if actor.movedir < NUMDIRS // NUMDIRS should be 8
		actor.angle = $ & (7 * (2^29))
		delta = actor.angle - (actor.movedir * (2^29))
		
		if delta > 0
			actor.angle = $-ANGLE_45
		elseif delta < 0
			actor.angle = $+ANGLE_45
		end
	end
	
	// do not attack twice in a row
	if (actor.flags2 & MF2_JUSTATTACKED)
		actor.flags2 = $ & ~MF2_JUSTATTACKED
		P_NewChaseDir(actor)
		return
	end
	
	if actor.movecount
		nomissile(actor)
		return
	end
	
	if not P_CheckMissileRange(actor)
		nomissile(actor)
		return
	end
	
	if actor.reactiontime <= 0
		if actor.health > actor.info.damage
			if (P_RandomByte() & 1)
				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)
		return
	end
	
	local offset
	
	if mapthing.z ~= 0
		offset = mapthing.z
	else
		offset = 33*FRACUNIT
	end
	
	if (mapthing.options & MTF_OBJECTFLIP)
		if offset ~= 0
			mobj.z = mobj.z - offset
		else
			mobj.z = mobj.ceilingz
		end
	else
		if offset ~= 0
			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)
		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
				spikemobj.angle = 0
			elseif i == 1
				spikemobj.angle = ANGLE_90
			elseif i == 2
				spikemobj.angle = ANGLE_180
			elseif i == 3
				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)
		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)
		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
		local radius = FixedMul(12*mobj.info.speed, mobj.scale)
		
		mobj.angle = $ + FixedAngle(mobj.info.speed)
		P_TeleportMove(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)
	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 mobj.health < mobj.info.damage+1 and (leveltime & 1) and mobj.health > 0
		P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_SMOKE) // Replace MT_SMOKE with MT_21SMOKE if necessary
	end
	if mobj.flags2 & MF2_SKULLFLY
		P_SpawnGhostMobj(mobj)
		
		/*
		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
		mobj.flags2 = $ & ~MF2_FRET
		if not (mobj.flags2 & MF2_SKULLFLY)
			mobj.momx = 0
			mobj.momy = 0
			mobj.momz = 0
		end
	end
	
	if not mobj.tracer
		A_OldBossJetFumes(mobj, 0, 0)
	end
	
	if not (mobj.target and mobj.target.valid and (mobj.target.flags & MF_SHOOTABLE))
		if mobj.health <= 0
			if P_LookForPlayers(mobj, 0, true) and mobj.info.mass // 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
			S_StartSound(mobj, mobj.info.seesound)
		end
		
		return true
	end
	
	if mobj.state == mobj.info.spawnstate
		A_FDBoss1Chase(mobj, 1, 0)
	end
	
	if mobj.state == mobj.info.meleestate
	or (mobj.state == mobj.info.missilestate and mobj.health > mobj.info.damage)
		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 = 4050,
	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
}
*/























