--=============================OMEGA METROID BOSS==============================================
--The Omega Metroid custom boss, animated with a bunch of connected sprites to make it look 3D.
--=============================================================================================

local function DoMetroidGhost(s, color) --Metroid version of P_SpawnGhostMobj
if not color
color = SKINCOLOR_WHITE
end
		s.ghs = P_SpawnGhostMobj(s)
		if s.ghs and s.ghs.valid
			s.ghs.rollangle = s.rollangle
			s.ghs.tics = 12
			s.ghs.scalespeed = $*P_RandomRange(1,3)
			s.ghs.destscale = $*5
			s.ghs.color = color
			s.ghs.colorized = true
		end
end
local function DoMetroidQuake(s, o, noquake, quakestrength, rocknum) --Metroid Quake! Spawns rocks and quakes!	
		if not noquake --No quaking!		
			for z in players.iterate
				if z.mo
					if (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 4000*FRACUNIT)
						if quakestrength
						A_samquake(z.mo, quakestrength*FRACUNIT, 1, 8)
						else
						A_samquake(z.mo, 22*FRACUNIT, 1, 8)
						end
					end
				end
			end
		end
		if not rocknum
		rocknum = 1
		end
		for d = 1,rocknum
			s.satanrock = P_SpawnMobj(s.x+(P_RandomRange(-2100, 2100)*FRACUNIT), s.y+(P_RandomRange(-2100, 2100)*FRACUNIT), s.ceilingz-20*FRACUNIT, MT_METROIDDROOL)
			if s.satanrock and s.satanrock.valid
				s.satanrock.state = S_ROCKCRUMBLEA
				s.satanrock.scale = FRACUNIT*3/(P_RandomRange(1,6))
				s.satanrock.tics = 130
				s.satanrock.health = 1
				s.satanrock.momz = FRACUNIT
				s.satanrock.flags = MF_PAIN|MF_SHOOTABLE --They have tiny hitboxes, but stiiiill!
				s.satanrock.omgrock = true
				s.satanrock = nil
			end
		end
end
local function DoMetroidRocks(s, o, rocknum, doquake) --Metroid Rock Riser! Practically the same thing, but rises rocks insteads
		if not rocknum
		rocknum = 1
		end
		if doquake --Do a quake!		
			for z in players.iterate
				if z.mo
					if (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 4000*FRACUNIT)
					A_samquake(z.mo, 22*FRACUNIT, 1, 8)
					end
				end
			end
		end		
		for d = 1,rocknum
			s.satanrock = P_SpawnMobj(s.x+(P_RandomRange(-100, 100)*FRACUNIT), s.y+(P_RandomRange(-100, 100)*FRACUNIT), s.floorz+10*FRACUNIT, MT_METROIDDROOL)
			if s.satanrock and s.satanrock.valid
				s.satanrock.state = S_ROCKCRUMBLEA
				s.satanrock.scale = 105355/(P_RandomRange(2,6))
				s.satanrock.tics = 130
				s.satanrock.health = 1
				s.satanrock.angle = R_PointToAngle2(s.x, s.y, o.x, o.y)
				P_InstaThrust(s.satanrock, s.satanrock.angle, P_RandomRange(-7,-2)*FRACUNIT)
				s.satanrock.momz = FRACUNIT*P_RandomRange(3,6)
				s.satanrock.flags = MF_SHOOTABLE --Don't need to make these hurt.
				s.satanrock.omgrock = true
				s.satanrock.nosfx = true
				s.satanrock = nil
			end
		end
end
local function DoMetroidCrash(s, o, noquake) --Metroid wall crash effect! Rocks everywhere.
		if not noquake --Do a quake!		
			for z in players.iterate
				if z.mo
					if (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 4000*FRACUNIT)
					A_samquake(z.mo, 82*FRACUNIT, 1, 22)
					end
				end
			end
		end
		for d = -5,5
			s.satanrock = P_SpawnMobj(s.x, s.y, s.z+s.height, MT_METROIDDROOL)
			if s.satanrock and s.satanrock.valid
				s.satanrock.state = S_ROCKCRUMBLEA
				s.satanrock.scale = 205355/(P_RandomRange(2,5))
				s.satanrock.tics = 130
				s.satanrock.health = 1
				if (d <= 0)
				P_InstaThrust(s.satanrock, o.angle-ANGLE_90, (8*d)*FRACUNIT)
				else
				P_InstaThrust(s.satanrock, o.angle+ANGLE_90, (8*d)*FRACUNIT)
				end
				s.satanrock.momz = (8*FRACUNIT)*d
				s.satanrock.flags = MF_PAIN|MF_SHOOTABLE --Don't need to make these hurt.
				s.satanrock.omgrock = true
				s.satanrock = nil
			end
		end
end
local function DoMetroidLegStomp(s, o, time) --Leg Stomp
if not time
time = 4
end
		o.slowdown = time
		S_StartSound(s, sfx_mtrdof)
		DoMetroidRocks(s, o, 3)
					if o.omegacharge
						if (o.omegacharge > 45)
						DoMetroidQuake(s, o, nil, 50, 1)
						DoMetroidRocks(s, o, 1)							
						elseif (o.omegacharge > 40)
						S_StartSound(s, sfx_mtrdof)
						DoMetroidQuake(s, o, nil, 60, 1)
						DoMetroidRocks(s, o, 2)						
						else
						S_StartSound(s, sfx_mtrdof)
						S_StartSound(s, sfx_mtrdop)
						DoMetroidQuake(s, o, nil, 80, 1)
						DoMetroidRocks(s, o, 3)
						end
					end
					for d = 0,7
					s.stomp = P_SpawnMobj(s.x, s.y, s.z+8*FRACUNIT, MT_PARTICLE)
					s.stomp.momz = FRACUNIT*3
					s.stomp.tics = 18
					s.stomp.destscale = FRACUNIT*30
					s.stomp.frame = $|TR_TRANS60
					P_InstaThrust(s.stomp, ANGLE_45*d, 10*FRACUNIT)
						if o.omegacharge
						s.stomp.scale = FRACUNIT*3
						end
					end
end

--Leg thinker! They're the same for both sides, but inverted.
local function DoMetroidLeg(s, o)
	if s.angleoffset
	s.angle = o.angle+s.angleoffset
	else
	s.angle = o.angle
	end
	s.scale = o.scale
		if s.footset == nil
		s.footset = true
		elseif s.footset --Wait 1 tic, then set
		s.zoffsetdefault = s.zoffset	
		s.footset = false
		elseif o.omgspeed != nil --Okay, movement thinker goooo!!
		--There seems to be a delay in starting this atm.
			--Vertical calculations
			if s.legupdown == nil
			s.legupdown = 2
			end
			if s.legbackforth == nil
			s.legbackforth = 2
			end			
			
			if not (s.zoffset > 50*FRACUNIT) // and s.omgspeed --Don't move legs while standing still.
			and ((s.hoffset > -30*FRACUNIT) and (s.hoffset < 30*FRACUNIT))
				if s.legbackforth == -2
				s.legupdown = 1
				else
				s.legupdown = 2
				end
			else
				s.legupdown = -2
			end
			if not ((s.zoffset <= 0) and (s.legupdown < 0))
			s.zoffset = $+((o.omgspeed/3)*s.legupdown) --The faster you go, the more rapid your legs move
				
				if (s.zoffset <= 0) and (s.z < s.floorz+30*FRACUNIT) and not (s.legupdown and s.legupdown >= 1)
				and not o.deathanim and not o.knockback and not o.flamethrower
				DoMetroidLegStomp(s, o, 4)
				end
			end
			
			--Horizontal calculations
			if s.hoffset > 85*FRACUNIT
				s.legbackforth = -2
			elseif s.hoffset <= -85*FRACUNIT
				s.legbackforth = 2
			end			
			s.hoffset = $+((o.omgspeed/3)*s.legbackforth)	
			
		end
		if not o.deathanim
			if o.flamethrower
			s.zoffset = 0
			s.rollangle = 0
			elseif o.knockback 
			s.rollangle = 0
			s.zoffset = 0
				if (s.z < s.floorz+30*FRACUNIT)
				DoMetroidRocks(s, o, 3)
				end
			end
		end
	--TeleportMove is the main driver moving the legs.
	P_MoveOrigin(s, 
	o.x+FixedMul((67*FRACUNIT), cos(o.angle+(ANGLE_90*s.legd)))+FixedMul(10*FRACUNIT+(s.hoffset*s.legd),cos(o.angle)),
	o.y+FixedMul((67*FRACUNIT), sin(o.angle+(ANGLE_90*s.legd)))+FixedMul(10*FRACUNIT+(s.hoffset*s.legd),sin(o.angle)),
	o.z+(o.height/-2)+s.zoffset)	
end

--Arm thinker! They're the same for both sides, but inverted
local function DoMetroidArm(s, o) 
	if s.angleoffset
	s.angle = o.angle+s.angleoffset
	else
	s.angle = o.angle
	end
	if o.knockback
	s.zoffset = 33*FRACUNIT
	s.hoffset = 0
	elseif s.armswipe
		DoMetroidGhost(s, SKINCOLOR_SUPERSKY5)
		s.armswipe = $-1	
		
		if (s.armswipe % 2 == 0)
		s.color = SKINCOLOR_SUPERSKY2
		s.colorized = true
		else
		s.color = SKINCOLOR_NONE
		s.colorized = false
		end
		
		if (s.armswipe < 6)
		s.zoffset = (s.armswipe*(-2*FRACUNIT)) --Swipe down arm	
			s.orollangle = $+(ANG20*s.armd)
			s.rollangle = s.orollangle
			
			if (s.armswipe == 3)
				if o and o.target
				s.slash = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_METROIDSLASH)
					if s.slash and s.slash.valid
					s.slash.scale = 5*FRACUNIT
					s.slash.color = SKINCOLOR_WHITE
					if s.armswipe1slash
					s.slash.singleslash = true
					end
					s.slash.target = o
					s.slash.angle = R_PointToAngle2(s.x, s.y, o.target.x, o.target.y)
					s.slash.sendto = o.target
					end
					s.armswipe1slash = false
				S_StartSound(s, sfx_cblade)
				end
			end
		elseif (s.armswipe > 5 and s.armswipe < 13)
			s.zoffset = (s.armswipe*(-2*FRACUNIT)) --Swipe down arm	
			s.orollangle = $-((ANG2*4)*s.armd)
			s.rollangle = s.orollangle	
		end
		if not s.armswipe --Reset yourself at the end.
		s.color = SKINCOLOR_NONE
		s.colorized = false
		s.orollangle = 0
		s.rollangle = 0
		end
	elseif o.omegacharge
		if s.fakehoffset == nil
		s.fakehoffset = 0
		s.hoffsetd = 1
		s.hoffset = 0
		s.zoffset = 0
		end
		if s.fakehoffset <= -12*FRACUNIT
		s.hoffsetd = 1
		elseif s.fakehoffset >= 12*FRACUNIT
		s.hoffsetd = -1
		end
		s.fakehoffset = $+(12*FRACUNIT*s.hoffsetd)
		s.hoffset = s.fakehoffset*s.armd
		s.zoffset = (s.hoffset-(23*FRACUNIT))*s.armd
	else
		if s.fakehoffset
		s.fakehoffset = nil
		s.hoffset = 0
		s.zoffset = 0
		end
		if (s.zoffset <= 0)
		s.armmove = 1	
		elseif (s.zoffset > 12*FRACUNIT)
		s.armmove = -1
		end
		if o.deathanim
		s.zoffset = $+644000*(s.armmove)
		s.rollangle = ANG1*P_RandomRange(-50,50)
		else
		s.zoffset = $+44000*(s.armmove)	
		end
	end	
	
	
	s.scale = o.scale
	P_MoveOrigin(s, 
	o.x+FixedMul((89*FRACUNIT+(s.hoffset*s.armd)), cos(o.angle+(ANGLE_90*s.armd)))+FixedMul(105*FRACUNIT,cos(o.angle)),
	o.y+FixedMul((89*FRACUNIT+(s.hoffset*s.armd)), sin(o.angle+(ANGLE_90*s.armd)))+FixedMul(105*FRACUNIT,sin(o.angle)),
	o.z+(o.height*10/43)+s.zoffset*s.armd)
end

local function DoMetroidHead(s, o) --Head Thinker! Drooling and flaming....
	if s.angleoffset
	s.angle = o.angle+s.angleoffset
	else
	s.angle = o.angle
	end
	
	s.scale = o.scale
	P_MoveOrigin(s, 
	o.x+FixedMul(135*FRACUNIT,cos(o.angle))+FixedMul(s.hoffset,cos(o.angle)),
	o.y+FixedMul(135*FRACUNIT,sin(o.angle))+FixedMul(s.hoffset,cos(o.angle)),
	o.z+(o.height*20/29)+s.zoffset)
	if o.deathanim
		if o.deathanim % 5 == 0
			s.rollangle = P_RandomRange(-30, 30)*ANG1
			s.angleoffset = (P_RandomRange(-90, 90)*ANG1)
		end
		return
	end
	if o.knockback
		s.zoffset = 10*FRACUNIT	
		s.rollangle = ANGLE_45
		s.angle = o.angle+ANGLE_90
	elseif s.flamethrower --Do a sweeping motion with your head and put the ground on fire!
		s.flamethrower = $-1
		s.orollangle = 0
		s.rollangle = 0
		s.hoffset = 0
		s.zoffset = 20*FRACUNIT
		if (s.flamethrower < 31)
			if (s.flamethrower == 30)
			S_StartSound(s, sfx_mtrdos)
			end
		s.flameangle = $+((ANG2*3)*s.ftdirect)
		s.angle = s.flameangle
			
			s.flm = P_SpawnMobj(s.x, s.y, s.z, MT_METROIDSLASH)
			s.flm.omegaflame = true
			s.flm.scale = o.scale*10/P_RandomRange(9,12)
			s.flm.destscale = $*6
			s.flm.scalespeed = $*2
			s.flm.angle = s.angle
			s.flm.momz = -P_RandomRange(11,13)*FRACUNIT
			s.flm.flags = $ & ~MF_NOCLIPHEIGHT
			P_InstaThrust(s.flm, s.angle, P_RandomRange(30,40)*FRACUNIT)
				if P_RandomRange(0,1)
				s.flm.frame = L|FF_FULLBRIGHT|TR_TRANS30
				else
				s.flm.frame = L|FF_FULLBRIGHT
				end
			s.flm.tics = -1
			s.flm.fuse = P_RandomRange(20,30)
			if not s.flamethrower --Is it over?
			s.angle = o.angle
			end
		end
	elseif o.omegacharge		
		if s.hoffset < -20*FRACUNIT or s.hoffsetd == nil or s.hoffsetspeed == nil
		s.hoffsetd = 1
		s.hoffsetspeed = P_RandomRange(10, 20)*FRACUNIT
		elseif s.hoffset > 20*FRACUNIT
		s.hoffsetd = -1
		s.hoffsetspeed = P_RandomRange(10, 20)*FRACUNIT
		end
		s.hoffset = $+(s.hoffsetspeed*s.hoffsetd)
		s.zoffset = (s.hoffset/8)-40*FRACUNIT		
	else
		s.hoffset = 0
		if (s.zoffset <= 0)
		s.headmove = 1	
		elseif (s.zoffset > 24*FRACUNIT)
		s.headmove = -1
		end
		s.zoffset = $+48000*(s.headmove)
	end
	if s.orolld == nil or (s.orollangle <= (-14*ANG1))
	s.orolld = 1 
	elseif (s.orollangle >= (14*ANG1))
	s.orolld = -1
	end
	if o.omegacharge
	s.orollangle = 0
	s.rollangle = 0
	else
		s.orollangle = $+(ANG1*s.orolld)
		s.rollangle = s.orollangle
	end
	
	
	if leveltime % 16 == 0 --Eww, drool...
	P_SpawnMobj( 
	s.x+FixedMul((P_RandomRange(-50, 50)*FRACUNIT), cos(s.angle+(ANGLE_90)))+FixedMul(45*FRACUNIT,cos(s.angle)),
	s.y+FixedMul((P_RandomRange(-50, 50)*FRACUNIT), sin(s.angle+(ANGLE_90)))+FixedMul(45*FRACUNIT,sin(s.angle)),
	s.z+(s.height/(P_RandomRange(4,6))), MT_METROIDDROOL)
	end
	
--	if (leveltime > 100) --Eww, rock drool.
--		DoMetroidQuake(s, o, nil)
--	end	
end

local function DoMetroidTail(s, o) --Tail Thinker. Weird movement here!
	if s.angleoffset != nil
		if s.tailee
		s.angle = s.tailee.angle+s.angleoffset		
		else
		s.angle = o.angle+s.angleoffset
		end
	else
	s.angleoffset = 0
		if s.tailee
		s.angle = s.tailee.angle
		else
		s.angle = o.angle
		end
	end	
	s.scale = o.scale
	s.height = 5*FRACUNIT --Smaller hitbox for this.
	s.radius = 5*FRACUNIT
	--Tailsway, vertical
		if s.tailee --Skip the calculations and just copy your friend's homework
			s.zoffset = s.tailee.zoffset*20/17 --But get it SLIGHTLY off so nobody suspects a thing!
			s.tailz = s.tailee.tailz
		else
			if (s.zoffset > 7*FRACUNIT) or s.tailz == nil
			s.tailz = -1
			s.tailzspeed = P_RandomRange(8355,60355)
			elseif (s.zoffset <= -7*FRACUNIT)
			s.tailz = 1
			s.tailzspeed = P_RandomRange(8355,60355)
			end
			s.zoffset = $+(s.tailzspeed*s.tailz)
		end
	--Tailsway, horizontal	
		if s.tailee
			s.angleoffset = s.tailee.angleoffset
			s.taild = s.tailee.taild
		else
			if (s.angleoffset > 8*ANG1) or s.taild == nil
				s.taild = -1
				s.tailspeed = P_RandomRange(1,10)
			elseif (s.angleoffset < -8*ANG1)
				s.taild = 1
				s.tailspeed = P_RandomRange(1,10)
			end
			s.angleoffset = $+(ANG1/s.tailspeed*s.taild)
		end
		
	--Actual tail position calculations. The first piece is tailseg 0, the rest counting up to 5.
	if s.tailee
		local lt = s.tailee
		P_MoveOrigin(s,
		o.x+FixedMul(-86*FRACUNIT+(-30*FRACUNIT*s.tailseg),cos(lt.angle)),
		o.y+FixedMul(-86*FRACUNIT+(-30*FRACUNIT*s.tailseg),sin(lt.angle)),
		o.z+o.height/11+((s.zoffset*s.tailseg)+9*FRACUNIT) )
	else		
	
		P_MoveOrigin(s,
		o.x+FixedMul(-86*FRACUNIT+(-30*FRACUNIT*s.tailseg),cos(o.angle)),
		o.y+FixedMul(-86*FRACUNIT+(-30*FRACUNIT*s.tailseg),sin(o.angle)),
		o.z+o.height/11+((s.zoffset)+9*FRACUNIT) )
	end
end

local function DoMetroidHitBox(s, o) --Hitbox thinker! The body parts are invincible, so aim for this!
	if not s.lasthealth or s.lasthealth != s.health --Debug function.
	and (s.health)
	s.lasthealth = s.health
	end
	if s.invincible
	s.invincible = $-1
	end
	s.flags2 = 0
	P_MoveOrigin(s, o.x+FixedMul(90*FRACUNIT,cos(o.angle)), o.y+FixedMul(90*FRACUNIT,sin(o.angle)), o.z+(o.height/5))
	s.scale = 155000
	s.momx = 0 s.momy = 0 s.momz = 0
	s.flags = MF_SHOOTABLE|MF_ENEMY|MF_NOCLIPHEIGHT|MF_NOGRAVITY
	s.state = S_THOK
	s.sprite = SPR_NULL
	s.tics = -1
end

local function DoMetroidSetup(s) --Spawn all the Metroid body parts!
		s.scale = FRACUNIT*4
		if s.z < s.floorz+80*FRACUNIT
		s.z = s.floorz+80*FRACUNIT
		end
		//Spawn the left leg
		
		s.leftleg = P_SpawnMobj(s.x, s.y, s.z, MT_METROIDPART)
		if not (s.leftleg and s.leftleg.valid)
		return 
		else
		s.leftleg.leftleg = true
		s.leftleg.legd = 1
		s.leftleg.omega = s
		s.leftleg.scale = s.scale
		s.leftleg.orollangle = 0	
		s.leftleg.hoffset = 0
		s.leftleg.zoffset = 0		
		s.leftleg.flags = MF_PAIN|MF_NOCLIPHEIGHT|MF_NOGRAVITY
		s.leftleg.state = S_THOK
		s.leftleg.sprite = SPR_OMGM
		s.leftleg.frame = F
		s.leftleg.tics = -1			
		end
		
		//Spawn the right leg
		s.rightleg = P_SpawnMobj(s.x, s.y, s.z, MT_METROIDPART)
		if not (s.rightleg and s.rightleg.valid)
		return 
		else
		s.rightleg.rightleg = true
		s.rightleg.legd = -1		
		s.rightleg.omega = s
		s.rightleg.scale = s.scale
		s.rightleg.orollangle = 0
		s.rightleg.hoffset = 0
		s.rightleg.zoffset = 0	
		s.rightleg.flags = MF_PAIN|MF_NOCLIPHEIGHT|MF_NOGRAVITY
		s.rightleg.state = S_THOK
		s.rightleg.sprite = SPR_OMGM
		s.rightleg.frame = E
		s.rightleg.tics = -1				
		end
		
		//Spawn the LEFT arm
		s.leftarm = P_SpawnMobj(s.x, s.y, s.z, MT_METROIDPART)
		if not (s.leftarm and s.leftarm.valid)
		return
		else
		s.leftarm.leftarm = true
		s.leftarm.armd = 1		
		s.leftarm.omega = s
		s.leftarm.scale = s.scale
		s.leftarm.orollangle = 0	
		s.leftarm.hoffset = 0
		s.leftarm.zoffset = 0		
		s.leftarm.flags = MF_PAIN|MF_NOCLIPHEIGHT|MF_NOGRAVITY
		s.leftarm.state = S_THOK
		s.leftarm.sprite = SPR_OMGM
		s.leftarm.frame = D		
		s.leftarm.tics = -1			
		end

		//Spawn the RIGHT arm
		s.rightarm = P_SpawnMobj(s.x, s.y, s.z, MT_METROIDPART)
		if not (s.rightarm and s.rightarm.valid)
		return
		else
		s.rightarm.rightarm = true
		s.rightarm.armd = -1	
		s.rightarm.omega = s
		s.rightarm.scale = s.scale
		s.rightarm.orollangle = 0
		s.rightarm.hoffset = 0
		s.rightarm.zoffset = 0		
		s.rightarm.flags = MF_PAIN|MF_NOCLIPHEIGHT|MF_NOGRAVITY
		s.rightarm.state = S_THOK
		s.rightarm.sprite = SPR_OMGM
		s.rightarm.frame = C
		s.rightarm.tics = -1			
		end
		
		//Spawn the head of the operation
		s.head = P_SpawnMobj(s.x, s.y, s.z, MT_METROIDPART)
		if not (s.head and s.head.valid)
		return
		else
		s.head.head = true
		s.head.headd = 1	
		s.head.omega = s
		s.head.scale = s.scale
		s.head.orollangle = 0
		s.head.hoffset = 0
		s.head.zoffset = 0		
		s.head.flags = MF_PAIN|MF_NOCLIPHEIGHT|MF_NOGRAVITY
		s.head.state = S_THOK
		s.head.sprite = SPR_OMGM
		s.head.frame = B
		s.head.tics = -1		
		end
		
		//Spawn the interesting looking tail!
		for d = 0,5
			if d != 0 and s.tail and s.tail.valid
			s.lasttail = s.tail
			end
			s.tail = P_SpawnMobj(s.x, s.y, s.z, MT_METROIDPART)
			if not (s.tail and s.tail.valid)
			return
			else
			s.tail.tail = true
			s.tail.taild = 1	
			s.tail.omega = s
			s.tail.scale = s.scale
			s.tail.orollangle = 0
			s.tail.hoffset = 0
			s.tail.zoffset = 0		
			s.tail.flags = MF_PAIN|MF_NOCLIPHEIGHT|MF_NOGRAVITY
			s.tail.state = S_THOK
			s.tail.sprite = SPR_OMGM
			s.tail.tailspeed = 2
			s.tail.tailzspeed = 35355
			s.tail.frame = G
			s.tail.tics = -1
			s.tail.tailseg = d
				if d != 0 and s.lasttail and s.lasttail.valid
				s.tail.tailee = s.lasttail --Tailee is the tail's tail.
				s.lasttail = nil
				end
			end
		end
		
		s.hitbox = P_SpawnMobj(s.x, s.y, s.z, MT_METROIDPART)
		if not (s.hitbox and s.hitbox.valid)
		return
		else
		s.hitbox.hitbox = true
		s.hitbox.omega = s
		s.hitbox.scale = 155000
		s.hitbox.nosamuspushpls = true //Don't push me
		s.hitbox.flags = MF_SHOOTABLE|MF_ENEMY|MF_NOCLIPHEIGHT|MF_NOGRAVITY
		s.hitbox.health = 13
		s.hitbox.color = SKINCOLOR_PURPLE
		s.hitbox.samusHP = 20
		s.hitbox.samusHPmax = 20
		s.hitbox.state = S_THOK
		s.hitbox.tics = -1
		end			
		
		s.setup = true --Successfully spawned everything! Let the main body know!
end


--Main Omega thinker, thinking from the body!
addHook("MobjThinker", function(s)
	if not s.setup
		DoMetroidSetup(s)
		return
	else --Okay, all setup, now lets go!
		if s.reflecttic
			s.reflecttic = $-1
			s.ghs = P_SpawnGhostMobj(s)
			s.ghs.destscale = s.scale*6
			s.ghs.scalespeed = $*3
			S_StartSound(s, sfx_cdfm50) S_StartSound(s, sfx_cdfm51)
			s.color = SKINCOLOR_SUPERSILVER1
			s.colorized = true
		end	
		if s.painfyellow s.painfyellow = $-1 end if s.painfred s.painfred = $-1 end if s.painfpurple s.painfpurple = $-1 end
		if s.flamethrower and (s.flamethrower > 30)
			if (s.flamethrower % 2 == 0)
			s.color = SKINCOLOR_FLAME
			s.colorized = true
			else
			s.colorized = false
			s.color = SKINCOLOR_NONE
			end			
		elseif s.painfyellow --Flashing colors? Go in this order of priority.
			if (s.painfyellow % 2 == 0)
			s.color = SKINCOLOR_YELLOW
			s.colorized = true
			else
			s.colorized = false
			s.color = SKINCOLOR_NONE
			end
		elseif s.painfpurple
			if (s.painfpurple % 2 == 0)
			s.color = SKINCOLOR_PURPLE
			s.colorized = true
			else
			s.colorized = false
			s.color = SKINCOLOR_NONE
			end		
		elseif s.painfred
			if (s.painfred % 2 == 0)
			s.color = SKINCOLOR_RED
			s.colorized = true
			else
			s.colorized = false
			s.color = SKINCOLOR_NONE
			end			
		elseif s.colorized
		s.color = SKINCOLOR_NONE
		s.colorized = false
		end
	
		--The legs will dictate where in vertical space we wanna be!
		if (s.z < s.floorz+30*FRACUNIT)
			s.z = s.floorz+86*FRACUNIT --Well, this is just awkward, teleport up!
			s.momz = 0		
		elseif (s.z < s.floorz+86*FRACUNIT) --Main body must hover over the ground!
		s.z = s.z+FRACUNIT
		s.momz = 0
		elseif (s.z > s.floorz+88*FRACUNIT)
		s.momz = $-FRACUNIT*2
			if (s.z <= s.floorz+88*FRACUNIT) --Ahh, you just touched ze floor
			DoMetroidRocks(s, s, 9)
			DoMetroidQuake(s, o, nil, 60, 15)
			S_StartSound(s, sfx_mtrdop)		
			end
		end
		if s.omgspeed == nil
		s.omgspeed = 1
		end
		if s.momx < 0
		s.omgmomx = s.momx*-1 else s.omgmomx = s.momx
		end
		if s.momy < 0
		s.omgmomy = s.momy*-1 else s.omgmomy = s.momy
		end
		s.omgspeed = s.omgmomy+s.omgmomx --This is the speed the Metroid's moving at
		if s.rammedwall
		s.rammedwall = $-1 --For charges!
		end
		if s.angleturn
		s.angleturn = $-1
		end
		if s.ghosttime
		s.ghosttime = $-1
		DoMetroidGhost(s)
		end
		if s.flamethrower
		s.flamethrower = $-1
		s.momy = 0
		s.momx = 0
		end
		if s.deathanim
			if s.deathanim == 138
			S_StartSound(nil, sfx_mtrdow)
			DoMetroidRocks(s, s, 8)
				for z in players.iterate
					if z.mo and z.mo.valid
					z.mo.crystalflashtune = 0
						if z.mo.crystalflashtime
						z.mo.nocftunechange = true
						end
					end
				end
			P_LinedefExecute(15678)	
			end
			DoMetroidQuake(s, s, nil, 40, 1)
			s.flags = $|MF_NOCLIP|MF_NOCLIPHEIGHT & ~MF_PAIN & ~MF_SHOOTABLE
			s.deathanim = $-1
			s.momx = 0
			s.momy = 0
			if s.deathanim % 8 == 0
			S_StartSound(s, sfx_mtrdb)
			s.bmb = P_SpawnMobj(s.x+P_RandomRange(-450,450)*FRACUNIT, s.y+P_RandomRange(-450, 450)*FRACUNIT, s.z+P_RandomRange(-250, 250)*FRACUNIT, MT_THOK)
			s.bmb.scale = FRACUNIT*P_RandomRange(3,5)
			s.bmb.state = S_MINIEXP1
			s.bmb.color = SKINCOLOR_FLAME
			end
			if (s.deathanim < 40)
				if (s.deathanim < 18)
				s.frame = $|TR_TRANS80 & ~TR_TRANS50
				else
				s.frame = $|TR_TRANS50
				end
				if (s.deathanim == 1)
				P_LinedefExecute(15677)
				DoMetroidRocks(s, s, 8)
				s.plexpand = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_PBEXPAND)
					if s.plexpand
					s.plexpand.frame = $|TR_TRANS50
					s.plexpand.scale = FRACUNIT*7
					s.plexpand.scalespeed = $*10
					s.plexpand.destscale = $*40
					end	
					
					S_StartSound(nil, sfx_mtrdd)			
					
					for d = 1,5
						s.itemrng = P_RandomRange(1,8)
						if s.itemrng == 1
						s.item = MT_PBOM
						elseif s.itemrng == 2
						s.item = MT_BMPKU
						elseif s.itemrng < 5
						s.item = MT_NRGD
						elseif s.item == 6
						s.item = MT_NRGB
						else
						s.item = MT_SPKU
						end
						P_SpawnMobj(s.x+P_RandomRange(-450,450)*FRACUNIT, s.y+P_RandomRange(-450,450)*FRACUNIT, s.z+P_RandomRange(0,100)*FRACUNIT, s.item)
					end
				end
			end
		elseif s.knockback --Seriously powerful hits can push even Omega Metroids back
			s.leftarm.armswipe = 0
			s.rightarm.armswipe = 0
			s.leftarm.armswipe = 0
			s.head.flamethrower = 0
			s.flamethrower = 0
			s.omegaleap = 0
			if s.knockbackhd == nil
			s.knockbackhd = P_RandomRange(-5,5)
			end
			s.omegacharge = 0
			s.actiontimer = 0
			s.knockback = $-1
			s.angle = $+(ANG1*s.knockbackhd)
			if s.knockbackd != nil
				P_InstaThrust(s, s.knockbackd, 36*FRACUNIT)
				if (s.z < s.floorz+100*FRACUNIT)
					DoMetroidQuake(s, o, nil, 60, 1)
					if P_RandomRange(0,1)
					S_StartSound(s, sfx_cdfm42) S_StartSound(s, sfx_cdfm42)
					end
				end
				
			end
			if not s.knockback --Knockback ended. Predetermine next knockback direction and possible retalation in harder difficulties
			s.knockbackd = nil
			s.knockbackhd = P_RandomRange(-5,5)
				if s.target and s.target.valid and s.target.player and s.target.player.crazysamusmobs
					if P_RandomRange(0,1)
						--Shoot a projectile-annuling Sonic blast and CHARGE!
						s.rightarm.armswipe = 12
						s.rightarm.singleslash = true
						s.actiontimer = 2
						s.omegarng = 1
						s.omegarngset = true
					elseif P_RandomRange(0,1)
						s.rightarm.armswipe = 12
						s.rightarm.singleslash = true					
						--Jump out of the way!
					end
					if (s.hitbox and s.hitbox.valid and s.hitbox.health < 5) and (s.actiontimer > 10)
					s.actiontimer = $-10 --Go faster at low health
					end
				end
			end
		elseif s.omegaleap
		s.omegaleap = $-1
		s.ghosttime = 2
		s.head.rollangle = 0
			if (s.omegaleap > 37)
			s.momz = (s.omegaleap*FRACUNIT)
				if (s.omegaleap > 39)
				SpaceJumpGFX(s, SKINCOLOR_MOSS, 1, L|TR_TRANS40)
				end
			elseif (s.omegaleap > 33)
			s.momz = 4*FRACUNIT
			else
			s.momz = $-5*FRACUNIT
			end
			
			if s.omegaleapd == 5
			P_InstaThrust(s, s.angle, -38*FRACUNIT)
			else
			A_FaceTarget(s)
			P_InstaThrust(s, s.angle+ANGLE_90*s.omegaleapd, 38*FRACUNIT)
			end
			
			if (s.omegaleap < 34) and ((s.z < s.floorz+100*FRACUNIT) or P_IsObjectOnGround(s))
				if not (s.omegaleap == 5) and (s.actiontimer > 10)
				s.actiontimer = 9
				end
				
			s.omegaleap = 0
			s.momx = 0 s.momy = 0 s.momz = -2*FRACUNIT
				if not s.omegabreak
					local sectorz = R_PointInSubsector(s.x, s.y).sector
					if sectorz.tag == 112 or sectorz.tag == 158
					or sectorz == sectors[1552] or sectorz == sectors[1549]
					P_LinedefExecute(15679)
					s.omegabreak = true
					end
				end
				for d = 1,2
				S_StartSound(s, sfx_mtrdop) S_StartSound(s, sfx_mtrdop) S_StartSound(s, sfx_bkpoof)
				DoMetroidLegStomp(s.rightleg, s, 7) DoMetroidLegStomp(s.leftleg, s, 7)
				DoMetroidQuake(s, s, nil, 80, 16)
				end
			end
		elseif s.target and s.target.valid and s.target.health and s.target.player
		local t = s.target
			if not s.gavemessage3
				s.gavemessage3 = true
				for z in players.iterate
					if z.mo
					z.mo.rdeathmsg = true
					end
				end
			end
			if s.crystalflashtime
			s.crystalflashtune = 2
			end
			if s.rammedher
			DoMetroidRocks(s, s, 4, nil)
			DoMetroidQuake(s, s, nil, 90*FRACUNIT, 12) 	
			S_StartSound(s, sfx_befall) S_StartSound(s, sfx_dmpain) S_StartSound(s, sfx_rocks2)
			s.omegacharge = 0
			s.momx = 0
			s.momy = 0
			--Okay, now give the player some breathing room.
			if t.player.fusionmode
			s.actiontimer = 100
			elseif t.player.crazysamusmobs
			s.actiontimer = 108
			s.omegarngset = true 
			s.omegarng = 5
			s.lastomegarng = 5
			else
			s.actiontimer = 180
			s.omegarngset = true
			s.omegarng = 5	
			s.lastomegarng = 5
			end
			s.rammedher = false
			end
			if not s.ohealthset
				if t.player.fusionmode
				s.health = 16 --Slightly higher health against Fusion Mode players
				end
			s.ohealthset = true
			end
			--Oh boy, we got a target, time to eat!
			if not s.actiontimer
				if not s.actiontimerfirsttime
					s.actiontimer = 30 --Attack almost right away!
					s.lastomegarng = 5
					s.actiontimerfirsttime = true
				else
					if t.player.fusionmode --Fusion Mode.
					s.actiontimer = P_RandomRange(4,62)
					elseif t.player.crazysamusmobs --normal mode
					s.actiontimer = P_RandomRange(30,70)
					else --casual
					s.actiontimer = P_RandomRange(65,125)
					end
				s.leftarm.rollangle = 0
				s.rightarm.rollangle = 0				
				s.leftarm.armswipe = 0
				s.rightarm.armswipe = 0
				end
			else
				if s.actiontimer % 16 == 0
				s.angleturn = 6
				end
				if not s.omegacharge and not s.flamethrower
					if s.angleturn --Gradually adjust angle to face your target.
					local diff = (R_PointToAngle2(s.x, s.y, t.x, t.y) - s.angle)
						if diff != nil
							if (diff > ANGLE_180)
							diff = InvAngle(InvAngle(diff)/8)
 							else
							diff = $/8
							end
							s.angle = $+diff
            			end
						if s.slowdown
						s.slowdown = $-1
						s.momx = $/2
						s.momy = $/2
						else
						P_InstaThrust(s, s.angle, 9*FRACUNIT)
						end
					else
						if s.slowdown
						s.slowdown = $-1
						s.momx = $/2
						s.momy = $/2
						else
						P_InstaThrust(s, s.angle, 18*FRACUNIT)
						end
					end
				end
			s.actiontimer = $-1
			end
			if s.actiontimer == 1
				if s.omegarngset
				s.omegarngset = false
				else
				s.omegarng = P_RandomRange(1,6) --Let's decrease the odds of the Omega becoming a one-note clown spamming the same attack
					if s.lastomegarng and (s.omegarng == s.lastomegarng)
						if (s.omegarng == 5) --Never do a flamethrower spam!
						s.omegarng = P_RandomRange(2,3)
						elseif (s.omegarng == 6)
						s.omegarng = P_RandomRange(1,5) -- Or jumpspam.
						else
						s.omegarng = P_RandomRange(1,6) --Reroll!
						end
					end
					s.lastomegarng = s.omegarng
				end
				
				if s.omegarng <= 2 --Suddenly charge at your enemy with terrifying speeds!
					s.angleturn = 0
					S_StartSound(s, sfx_mtrdof)
					A_FaceTarget(s)
					P_SamFP(t.player, PAL_RECYCLE, 3)
					s.omegacharge = 50
						if not (P_TryMove(s, s.x, s.y, false))	
							s.z = $+5*FRACUNIT --GET UNSTUCK MANUEVRES!!
							for d = 1,36
								P_TryMove(s, s.x+FixedMul(30*FRACUNIT, cos(s.angle+(ANG10*d))), s.y+FixedMul(30*FRACUNIT, sin (s.angle+(ANG10*d))), false)
							end
						end						
					
					if t.player.fusionmode --Fusion Mode.
					s.actiontimer = P_RandomRange(70, 80)
					elseif t.player.crazysamusmobs --normal mode
					s.actiontimer = P_RandomRange(78, 85)
					else --casual
					s.actiontimer = P_RandomRange(120, 145)
					end
				elseif s.omegarng <= 4 --Sonic Boom Slash, takes down other projectiles
					if t.player.fusionmode --Fusion Mode.
					s.actiontimer = P_RandomRange(60, 80)
					elseif t.player.crazysamusmobs --normal mode
					s.actiontimer = P_RandomRange(68, 86)
					else --casual
					s.actiontimer = P_RandomRange(94, 139)
					end
					if t.player.crazysamusmobs
					s.rightarm.armswipe = 22
					s.leftarm.armswipe = 40
					else
					s.leftarm.armswipe = 22
					end
				elseif s.omegarng == 5 --Flamethrower
					if t.player.fusionmode --Fusion Mode.
					s.actiontimer = P_RandomRange(47, 70)
					elseif t.player.crazysamusmobs --normal mode
					s.actiontimer = P_RandomRange(50, 75)
					else --casual
					s.actiontimer = P_RandomRange(94, 139)
					end
						if P_RandomRange(0,1)
							s.head.ftdirect = 1
						else
							s.head.ftdirect = -1
						end
					A_FaceTarget(s)
					s.head.flameangle = (R_PointToAngle2(s.x, s.y, t.x, t.y)-(ANGLE_90*s.head.ftdirect))
					s.head.flamethrower = 45 --Go up with ANG3*2 for 30 frames, burning the floor!
					s.flamethrower = 45				
				elseif s.omegarng >= 6 --Do a mighty leap!
					if (s.z > s.floorz+100*FRACUNIT)
					s.actiontimer = 2 --Uhh, nevermind, you're in the air, don't jump.
					else
						if t.player.crazysamusmobs
						s.leftarm.armswipe = 12
						s.leftarm.singleslash = true
						end
					S_StartSound(s, sfx_mtrdol)
					s.omegaleap = 45
					A_FaceTarget(s)
						if P_RandomRange(0,1)
						s.omegaleapd = 1
						elseif P_RandomRange(0,1)				
						s.omegaleapd = -1
						else
						s.omegaleapd = 5 --backwards leap
						end
						if t.player.fusionmode --Fusion Mode.
						s.actiontimer = P_RandomRange(44, 55)
						elseif t.player.crazysamusmobs --normal mode
						s.actiontimer = P_RandomRange(55, 69)
						else --casual
						s.actiontimer = P_RandomRange(94, 129)
						end
					end
				end
				if (s.hitbox and s.hitbox.valid and s.hitbox.health < 5) and (s.actiontimer > 10)
				s.actiontimer = $-10 --Go faster at low health
				end
			else
				if s.omegacharge
				s.omegacharge = $-1
					if s.target
					s.target.omegarushpanic = 3
					end
					if (s.omegacharge > 45)
					P_InstaThrust(s, s.angle, 28*FRACUNIT)
					s.plexpand = P_SpawnMobj(s.x, s.y, s.z+s.height/4, MT_PBEXPANDW)
						if s.plexpand
						s.plexpand.scale = $*P_RandomRange(8,16)
						s.plexpand.scalespeed = $*P_RandomRange(30,50)
						s.plexpand.destscale = $*60
						s.plexpand.tics = $*5/3
							if P_RandomRange(0,1)
							s.plexpand.frame = I|FF_FULLBRIGHT|TR_TRANS90
							end
						end
						if (s.omegacharge == 46)
						S_StartSound(s, sfx_mtrdor)
						end
					else
						if (s.omegacharge > 40)
							if (leveltime % 3 == 0)
							s.ghosttime = 2
							end
							P_InstaThrust(s, s.angle, 46*FRACUNIT)
						else
						s.ghosttime = 2
						P_InstaThrust(s, s.angle, 65*FRACUNIT)
						end
						
						--Crashed into a wall? Jump back and re-position!
						if s.rammedwall and (s.rammedwall >= 3)
						s.omegacharge = 0
						s.omegaleap = 42
						s.omegaleapd = 5
						S_StartSound(s, sfx_crumbl) S_StartSound(s, sfx_bkpoof)
						s.angleturn = 0
						s.actiontimer = 50
						DoMetroidCrash(s, s, nil)
						end
					end
				end
			end
		elseif (s.state == S_OMGM2) --return to looking state
		s.state = S_OMGM1
		end
	end
end, MT_METROIDBOSS)
addHook("MobjThinker", function(s)
	if not (s.omega and s.omega.valid) and s.valid --No Omega? Then go away.
	s.state = S_NULL
	return
	else --Give seperate local thinkers for ease of modifications...
	local o = s.omega
		s.tics = -1 
		s.color = o.color
		s.colorized = o.colorized		
		if s.reflecttic
			s.reflecttic = $-1
			s.ghs = P_SpawnGhostMobj(s)
			s.ghs.destscale = s.scale*6
			s.ghs.scalespeed = $*3
			S_StartSound(s, sfx_cdfm50) S_StartSound(s, sfx_cdfm51)
			s.color = SKINCOLOR_SUPERSILVER1
			s.colorized = true
		end
		if o.ghosttime and not s.hitbox
		DoMetroidGhost(s)
		end
		if s.rammedher
			if not o.rammedher --Transfer this to your body
			o.rammedher = true
			end
		s.rammedher = false
		end
	//Okay, now do individual thinkers!	
			if s.rightarm or s.leftarm
			DoMetroidArm(s, o)
			elseif s.leftleg or s.rightleg
			DoMetroidLeg(s, o)
			elseif s.head
			DoMetroidHead(s, o)
			elseif s.tail
			DoMetroidTail(s, o)
			elseif s.hitbox
			DoMetroidHitBox(s, o)
			else
			return
			end
			if (o and o.deathanim)
			s.flags = $|MF_NOCLIP|MF_NOCLIPHEIGHT & ~MF_PAIN & ~MF_SHOOTABLE
				if s.hitbox
					return
			 	elseif (o.deathanim < 18)
				s.frame = $|TR_TRANS80 & ~TR_TRANS50
			 	elseif (o.deathanim < 35)
			 	s.frame = $|TR_TRANS50
				end
			end
	end
end, MT_METROIDPART)

addHook("MobjThinker", function(s) //Gross.
	if s and s.valid 
		if s.omgrock -- And now the ceiling's drooling rocks, just great!
			if P_IsObjectOnGround(s) and not s.dripped
				s.flags = $|MF_SCENERY & ~MF_PAIN & ~MF_SHOOTABLE --No lingering hitboxes!
				s.frame = $|TR_TRANS40
				s.tics = 16
				if not s.nosfx
				s.momz = P_RandomRange(8,15)*FRACUNIT
				S_StartSound(s, (P_RandomRange(sfx_rocks1, sfx_rocks4)))
				else
				s.tics = 8
				s.momz = P_RandomRange(1,3)*FRACUNIT
				end
				s.dripped = true
			end
		elseif s.omgtree
			if not s.setup
			s.sprite = SPR_OMGM
			s.frame = N
			P_InstaThrust(s, P_RandomRange(1,359)*ANG1, P_RandomRange(1,16)*FRACUNIT)
			s.momz = P_RandomRange(6,18)*FRACUNIT
			s.flags = $ & ~MF_PAIN & ~MF_SHOOTABLE		
			s.scale = FRACUNIT*10/P_RandomRange(2,11)
			s.rollangle = P_RandomRange(0,359)*ANG1
			s.tics = 140
			s.setup = true
			elseif P_IsObjectOnGround(s) and not s.dripped
				s.frame = $|TR_TRANS40
				s.tics = 12
				s.momz = P_RandomRange(2,5)*FRACUNIT
				S_StartSound(s, sfx_wbreak)
				s.dripped = true
			end
		else
			if not s.setup
			s.sprite = SPR_OMGM
			s.frame = H|TR_TRANS40
			s.scale = FRACUNIT/2
			s.destscale = FRACUNIT*3
			s.tics = 130
			s.setup = true
			
			elseif P_IsObjectOnGround(s) and not s.dripped
			
			s.dripped = true
			s.scale = FRACUNIT
			s.momx = 0 s.momy = 0 s.momz = 0
			s.state = S_SPLISH1
			S_StartSound(s, (P_RandomRange(sfx_wdrip1, sfx_wdrip8)))
			end
		end
	end
end, MT_METROIDDROOL)
addHook("MobjDeath", function(s, i, so) --Let players shoot falling rocks for health!
	if so and so.valid and YouAreSamus(so) and so.player and (so.player.sam_energy and so.player.sam_energy < 300)
		if s and s.valid and s.omgrock and (i and i.valid and (i.flags & MF_MISSILE) and not (i.type == MT_ICCHARGESHOT))
		P_SpawnMobj(s.x, s.y, s.z, MT_NRGA)
		end
	end
end, MT_METROIDDROOL)

local function OHitBoxReaction(s, i, so)
if s.health and s.invincible
return true
end
	if (s.health <= 0) or (so and so.player and so.player.hypermysticsonic)
		if s.omega and s.omega.valid
		s.omega.deathanim = 140 --Damn, you actually won? Props!
		s.omega.fuse = 141
		s.omega.painfpurple = 140
		S_StartSound(s.omega, sfx_mtrdod) S_StartSound(s.omega, sfx_mtrdod)
		S_StartSound(s.omega, sfx_mtrdb)
			for z in players.iterate
				if z.mo
					if (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 4000*FRACUNIT)
						A_samquake(z.mo, 80*FRACUNIT, 1, 18)
						P_SamFP(z, PAL_RECYCLE, 12)
					end
				end
			end
			s.state = S_THOK
			s.tics = -1
			s.flags = $|MF_NOCLIP|MF_NOCLIPHEIGHT & ~MF_ENEMY & ~MF_BOSS & ~MF_SHOOTABLE
			s.flags2 = $|MF2_DONTDRAW
			return true
		else
			return --No linked omega? Well, just disappear, I guess.
		end
	else --No dying yet.
		if s.omega and s.omega.valid	
			if i and i.player and i.health --Melee attack?
				if YouAreSamus(i) --Samus has some special damage methods
					if i.player.sam_shinesparkfly --Is that a giant 30 foot beast? TACKLE IT!
						if (s.health > 2) --Deal a crapton of damage.
						s.health = $-2
						elseif (s.health > 1)
						s.health = $-1
						end
						s.omega.painfred = 55
						s.invincible = 18
						i.momx = 0 i.momz = 0 i.momy = 0
						i.player.sam_shinesparkstop = 12
						S_StartSound(s, sfx_mtrdop) S_StartSound(s, sfx_mtrdor) S_StartSound(s, sfx_mtrdb)
						S_StartSound(i, sfx_satkh) S_StartSound(i, sfx_bkpoof)
						P_SamFP(i.player, PAL_RECYCLE, 7)
						s.omega.knockback = 42
						s.omega.knockbackd = i.angle
						if not i.player.powers[pw_flashing]
						i.player.powers[pw_flashing] = 50 --Give invincibility
						end
					elseif i.sam_deathball
						s.omega.painfred = 40
						s.invincible = 18
						S_StartSound(s, sfx_mtrdop) S_StartSound(s, sfx_mtrdor) S_StartSound(s, sfx_mtrdb)
						s.omega.knockback = 36
						s.omega.knockbackd = R_PointToAngle2(s.x, s.y, i.x, i.y)
						if not i.player.powers[pw_flashing]
						i.player.powers[pw_flashing] = 50 --Give invincibility
						end						
					elseif i.player.sam_screwattacking --Screw attacks just bounce you off
						if not i.player.powers[pw_flashing]
							if i.player.sam_shinesparkdirect != nil
							i.player.sam_shinesparkdirect = $+ANGLE_180
							S_StartSound(s, sfx_s1bb) S_StartSound(s, sfx_s1bb)
							end
							i.player.powers[pw_flashing] = 40
							return true
						else
							return true
						end				
					end
				else --Did a Sonic hurt you?
					if i.player.powers[pw_super] or (i.player.speed > 100*FRACUNIT)
						if (s.health > 1)
						s.health = $-1 --Was it a SUPER Sonic?
						end
					s.omega.painfred = 40
					S_StartSound(s, sfx_mtrdop) S_StartSound(s, sfx_mtrdor) S_StartSound(s, sfx_mtrdb)
					S_StartSound(i, sfx_satkh) S_StartSound(i, sfx_bkpoof)
					s.omega.knockback = 38
					s.omega.knockbackd = i.angle					
					end
					for d = 1,20
						s.flingring = P_SpawnMobj(s.x, s.y, s.z+100*FRACUNIT, MT_FLINGRING)
						if s.flingring.valid
						P_InstaThrust(s.flingring, P_RandomRange(0,359)*ANG1, 5*FRACUNIT)
						s.flingring.fuse = 350
						end
					end
					s.invincible = 18
					i.state = S_PLAY_SPRING
					P_InstaThrust(i, s.angle, 45*FRACUNIT)
					S_StartSound(i, sfx_dmpain)
					if not i.player.powers[pw_flashing]
					i.player.powers[pw_flashing] = 105 
					end
				end
			elseif (i and i.type == MT_SPCHARGESHOT) and (s.samusHP > 12)
				s.omega.painfyellow = 20
				s.samusHP = $-12
				s.invincible = 6
				return true --No damage taken yet
			elseif (i and i.type == MT_SAMSUPERMISSILE or i.type == MT_SPAZERSHOCK or i.type == MT_ICCHARGECOMBO)	
				s.omega.painfred = 55
				s.omega.knockback = 28
				s.omega.knockbackd = R_PointToAngle2(i.x, i.y, s.omega.x, s.omega.y) 
				s.invincible = 28
				S_StartSound(s, sfx_mtrdop) S_StartSound(s, sfx_mtrdor) S_StartSound(s, sfx_mtrdb)
				if (i.type == MT_ICCHARGECOMBO)
				i.addsaldsalf = true
				end
			elseif (i and i.type == MT_SAMPOWERBOMB) --Powerbombs are ineffective, but core hits will still sting
				if i and not i.phase
				s.health = $+1
				s.omega.knockback = 40
				s.omega.knockbackd = R_PointToAngle2(i.x, i.y, s.omega.x, s.omega.y) 
				S_StartSound(s, sfx_mtrdop) S_StartSound(s, sfx_mtrdor) S_StartSound(s, sfx_mtrdb)
				else
				s.health = $+2
				s.omega.painfyellow = 30
				end
				s.omega.painfred = 55
				s.invincible = 45
			else --Default damage behaviour
			s.omega.painfred = 18
				if i and i.valid and (i.type == MT_ICCHARGESHOT)
				s.invincible = 21
				else
				s.invincible = 9
				end
			end	
			if i and i.target and i.target.player --You've pissed off the beast....
			s.omega.target = i
			s.target = i
			end
			s.omega.leftarm.armswipe = 0 --Get interrupted
			s.omega.rightarm.armswipe = 0
			s.omega.leftarm.rollangle = 0
			s.omega.rightarm.rollangle = 0			
			s.samusHP = 20 s.samusHPmax = 20 --Reset health to 20. Your powerbeam peashooter won't help much here....
		end
		s.flags = $|MF_NOCLIPHEIGHT|MF_BOSS|MF_SHOOTABLE|MF_ENEMY
		s.flags2 = $ & ~MF2_FRET
		return
	end
end
addHook("MobjDamage", OHitBoxReaction, MT_METROIDPART)
addHook("MobjDeath", OHitBoxReaction, MT_METROIDPART)

--Used to detect Omega Metroids charging into walls/objects
addHook("MobjMoveBlocked", function(s, i)
	if s and (s.omegacharge and (s.omegacharge < 42))
		if not s.rammedwall
		s.rammedwall = 2
		else
		s.rammedwall = $+2
		end
	end
end, MT_METROIDBOSS)

rawset(_G, "LeafSpawn", function(s, green, phazon, phazond)
	if phazon and phazond --Nvm, Phazon Particle.
		s.pspawn = P_SpawnMobj(s.x+(P_RandomRange(-phazond, phazond)*FRACUNIT), s.y+(P_RandomRange(-phazond, phazond)*FRACUNIT), s.z+(P_RandomRange(-phazond/12, phazond/12)*FRACUNIT), MT_SAMUSEPARTICLE)
			if s.pspawn and s.pspawn.valid
				s.pspawn.pzpt = true
				s.pspawn.flags = MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT
				s.pspawn.scale = 55000*P_RandomRange(1,2)
				s.pspawn.destscale = s.pspawn.scale*P_RandomRange(1,5)
				s.pspawn.tics = P_RandomRange(21, 58)
				s.pspawn.flags = MF_NOGRAVITY
				s.pspawn.momz = P_RandomRange(1, 5)*FRACUNIT 
				s.pspawn.sprite = SPR_MPR1
					if P_RandomRange(0,1)
					s.pspawn.frame = Q|FF_FULLBRIGHT|TR_TRANS40
					else
					s.pspawn.frame = P|FF_FULLBRIGHT|TR_TRANS40					
					end
			end
	
	else
		s.pspawn = P_SpawnMobj(s.x+(P_RandomRange(-300, 300)*FRACUNIT), s.y+(P_RandomRange(-300, 300)*FRACUNIT), s.z+(P_RandomRange(-10, 10)*FRACUNIT), MT_SAMUSEPARTICLE)
			if s.pspawn and s.pspawn.valid
				s.pspawn.leafpt = true
				s.pspawn.tics = 1050
				s.pspawn.scale = FRACUNIT*P_RandomRange(1,5)
				s.pspawn.flags = 0
				s.pspawn.momx = P_RandomRange(-20, 20)*FRACUNIT 
				s.pspawn.momy = P_RandomRange(-20, 20)*FRACUNIT 
				s.pspawn.sprite = SPR_MPR1
				if green
				s.pspawn.frame = Y
				s.pspawn.z = $+350*FRACUNIT
				s.pspawn.scale = $*2
				else
				s.pspawn.frame = R
				end
			end
	end
end)
//Spawns phazon and leaf particles
addHook("MobjThinker", function(s)
	if not (s.leafpt or s.pzpt)
		if not s.neutral
		s.neutral = true
		s.tics = -1 --infinityyyy
		s.flags2 = $|MF2_DONTDRAW
		end
		if s.angle == 0 -- Leaf spawner
			if (leveltime % 22 == 0)
			LeafSpawn(s)
			end
		elseif s.angle == ANGLE_90 --Phazon spawner
			if (leveltime % 7 == 0)
			s.pspawn = P_SpawnMobj(s.x+(P_RandomRange(-220, 220)*FRACUNIT), s.y+(P_RandomRange(-220, 220)*FRACUNIT), s.z+(P_RandomRange(-10, 10)*FRACUNIT), MT_SAMUSEPARTICLE)
				if s.pspawn and s.pspawn.valid
				s.pspawn.pzpt = true
				s.pspawn.flags = MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT
				s.pspawn.scale = 55000*P_RandomRange(1,2)
				s.pspawn.destscale = s.pspawn.scale*P_RandomRange(1,5)
				s.pspawn.tics = P_RandomRange(21, 58)
				s.pspawn.flags = MF_NOGRAVITY
				s.pspawn.momz = P_RandomRange(1, 5)*FRACUNIT 
				s.pspawn.sprite = SPR_MPR1
					if P_RandomRange(0,1)
					s.pspawn.frame = Q|FF_FULLBRIGHT|TR_TRANS40
					else
					s.pspawn.frame = P|FF_FULLBRIGHT|TR_TRANS40					
					end
				end
			end
		end
	else
		if s.leafpt --leaf particle
			P_Thrust(s, P_RandomRange(0,359)*ANG1, P_RandomRange(0,6000))
			if not P_RandomRange(0,2)
			s.momz = $*10/P_RandomRange(14,24)
			P_Thrust(s, P_RandomRange(0,359)*ANG1, P_RandomRange(35355,55000)*4)
			end
			if P_IsObjectOnGround(s) and not s.begone 
				s.frame = $|TR_TRANS60
				s.tics = 6
				s.destscale = $*3
				s.begone = true
			end
		elseif s.pzpt --phazon particle
			s.blendmode = AST_ADD
			if (s.tics == 20)
			s.frame = $|TR_TRANS60 & ~TR_TRANS40
			elseif (s.tics == 10)
			s.frame = $|TR_TRANS80 & ~TR_TRANS40 & ~TR_TRANS60
			end
		end
	end
end, MT_SAMUSEPARTICLE)

local function OmegaCollide(s, m)
--Be careful where you try and shoot these guys.
if not (s and s.valid)
or (s.omega and not s.omega.valid)
return
end
	if (s.deathanim or s.omega and s.omega.deathanim)
	return false
	end
	if m and m.valid
		if ((m.type == MT_METROIDPART) or (m.type == MT_METROIDDROOL) or (m.type == MT_METROIDSLASH) or (m.type == MT_MINIFIRE)) --Don't collide with yourself.
		return false
		else
			if s and s.valid and not (s.leftarm or s.rightarm)
			and not (m.z > s.z+s.height)
			and not (s.z > m.z+m.height)
				if not m.treecut
				and ( ((m.type >= MT_GFZTREE) and (m.type <= MT_SPRINGTREE)) or (m.type == MT_PINETREE) )
					m.treecut = true
					S_StartSound(s, sfx_wbreak)
					for d = 1,10
					LeafSpawn(s, true)
					m.logfall = P_SpawnMobj(s.x, s.y, s.z+(s.height*3/d), MT_METROIDDROOL)
						if m.logfall and m.logfall.valid
						m.logfall.omgtree =  true
						end
					end
				m.state = S_NULL
				return false
				end			
				if s.hitbox and m.player and not (YouAreSamus(m))
				and ((m.player.pflags & PF_JUMPED) or (m.player.pflags & PF_SPINNING) or (m.player.pflags & PF_THOKKED))
						if not m.player.powers[pw_flashing]
						m.player.powers[pw_flashing] = 30
						end
						P_DamageMobj(s, m, m) --Force a hit
						m.state = S_PLAY_FALL
						m.momz = $*-1
						P_InstaThrust(m, m.angle, -45*FRACUNIT)	
						return false
				elseif (m.flags & MF_MISSILE) and m.health and not s.hitbox
				and m.target and m.target.player
				and not m.target.player.hypermysticsonic
				and not ((m.type == MT_SAMPOWERBOMB) or (m.type == MT_SPCHARGECOMBO))
				and (m.momx or m.momy or m.momz)
						if not s.reflecttic --Give 1 tic of leeway!
							s.reflecttic = 2
							return false
						elseif s.reflecttic == 2
							return false
						else
							m.target = s --aim carefully or you'll pay the price.
							m.momx = $*-1 m.momy = $*-1 m.momz = $*-1
						end
					return false
				end
			else
				return false
			end
		end
	end
end
addHook("MobjCollide", OmegaCollide, MT_METROIDBOSS)
addHook("MobjMoveCollide", OmegaCollide, MT_METROIDBOSS)
addHook("MobjCollide", OmegaCollide, MT_METROIDPART)
addHook("MobjMoveCollide", OmegaCollide, MT_METROIDPART)

addHook("MobjThinker", function(s)
	if s and s.valid
		if not s.omegaflame
			if not s.scaleup
			s.scaleup = true
			P_InstaThrust(s, s.angle, 50*FRACUNIT)		
				if not s.extraslashes and not s.singleslash
					if s.sendto and s.sendto.valid
						if s.sendto.z < s.z
						s.z = s.sendto.z+(s.sendto.height/2)
						s.momz = 0
						else
						s.momz = P_RandomRange(10,30)*FRACUNIT
						end
					end	
					for d = -1, 1, 2
						s.xtraslash = P_SpawnMobj(s.x, s.y, s.z, MT_METROIDSLASH)
							if s.xtraslash and s.xtraslash.valid
							local m = s.xtraslash
							m.scale = s.scale
							m.angle = s.angle+(ANG30*d)
							m.color = s.color
							m.extraslashes = true
							m.target = s.target
							m.momz = s.momz
							end							
					end
				end
			s.scalespeed = $*2
			s.destscale = FRACUNIT*10
			P_InstaThrust(s, s.angle, 70*FRACUNIT)				
			end
			if (leveltime % 2 == 0)
			s.flags2 = $|MF2_DONTDRAW
			else
			s.flags2 = $ & ~MF2_DONTDRAW
			P_SpawnGhostMobj(s)
			end
			if (s.tics < 36)
			s.frame = J|TR_TRANS30
			elseif (s.tics < 23)
			s.frame = K|TR_TRANS40
			s.momx = $*50/51 s.momy = $*50/51 s.momz = $*50/51
				if (s.tics < 17)
				s.flags = $ & ~MF_PAIN --They won't hurt anymore, to prevent players backtracking into the attack after dodging it.
				end
			elseif (s.tics < 10)
			s.frame = K|TR_TRANS50
			s.momx = $*20/21 s.momy = $*20/21 s.momz = $*20/21	
			end
		else --Oh, it's a flame!
			if leveltime % 3 == 0 --Little firesparks.
				s.flm2 = P_SpawnMobj(s.x+P_RandomRange(20,20)*s.scale, s.y+P_RandomRange(20,20)*s.scale, s.z+P_RandomRange(20,20)*s.scale, MT_THOK)
				s.flm2.scale = s.scale/P_RandomRange(1,5)
				s.flm2.sprite = SPR_OMGM
				s.flm2.blendmode = AST_ADD
				s.flm2.frame = M|FF_FULLBRIGHT|TR_TRANS30
				s.flm2.tics = 6
			end
			if not s.laidflame and s.valid and P_IsObjectOnGround(s)
				s.flm3 = P_SpawnMobj(s.x, s.y, s.floorz, MT_MINIFIRE)
				if s.flm3 and s.flm3.valid				
				s.flm3.morning = 105
				s.flm3.fuse = 106
				s.flm3.blendmode = AST_ADD
				s.flm3.scale = 5*FRACUNIT/P_RandomRange(1,3)
				s.flm3.target = s.target
				end
				s.state = S_NULL
				return
			end
		end
	end
end, MT_METROIDSLASH)

local function SlashCollide(s, m)
	if m and m.valid
	and ((m.flags & MF_MISSILE) or m.player and m.player.powers[pw_super] or (((m.type >= MT_GFZTREE) and (m.type <= MT_SPRINGTREE)) or (m.type == MT_PINETREE)))and m.health
		if s and s.valid
		and not (m.z > s.z+s.height)
		and not (s.z > m.z+m.height)
			S_StartSound(s, sfx_cbloc)
			if (((m.type >= MT_GFZTREE) and (m.type <= MT_SPRINGTREE)) or (m.type == MT_PINETREE)) and not m.treecut
			m.treecut = true
			S_StartSound(s, sfx_wbreak)
				for d = 1,10
				LeafSpawn(s, true)
				m.logfall = P_SpawnMobj(s.x, s.y, s.z+((s.height*3)/d), MT_METROIDDROOL)
					if m.logfall and m.logfall.valid
					m.logfall.omgtree =  true
					end
				end
			m.state = S_NULL
			return false
			end
			if m.player and not (m.state == S_PLAY_STUN)
			m.state = S_PLAY_STUN
			P_InstaThrust(m, s.angle, 50*FRACUNIT) --Give Superform dudes a hard time
			m.momz = 12*FRACUNIT
			m.angle = s.angle+ANGLE_180
			S_StartSound(m, sfx_cbloc)
				if not m.player.powers[pw_flashing]
				m.player.powers[pw_flashing] = 24
				end
			elseif (m.flags & MF_MISSILE)
			and not ((m.type == MT_SPCHARGECOMBO) or (m.type == MT_HBSHOT)) --Don't block beam combos.
			S_StartSound(s, sfx_cbloc) --Take down opposing projectiles with your own!!
				s.plexpand = P_SpawnMobj(m.x, m.y, m.z+m.height/2, MT_PBEXPAND)
					if s.plexpand
					s.plexpand.color = SKINCOLOR_WHITE
					s.plexpand.frame = $|TR_TRANS50
					s.plexpand.scale = FRACUNIT*3
					s.plexpand.scalespeed = $*3
					s.plexpand.destscale = $*22
					end
			m.ghs = P_SpawnGhostMobj(m)
			m.ghs.tics = 30 m.ghs.rollangle = $+ANG30
			m.ghs.scale = m.scale*2
			m.ghs.destscale = FRACUNIT*20
			m.ghs.scalespeed = $*7
			
			if m and m.valid
			m.state = S_NULL
			end
			return false
			end
		end
	end
end
addHook("MobjCollide", SlashCollide, MT_METROIDSLASH)
addHook("MobjMoveCollide", SlashCollide, MT_METROIDSLASH)

addHook("MobjLineCollide", function(s, i) --Phase through stuff
	return false
end, MT_METROIDSLASH)