--=============================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
	color = (color) or SKINCOLOR_WHITE
	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!		
		quakestrength = (quakestrength) or 22
		A_samquake(s, quakestrength<<16, 1, 4000<<16)
	end
	rocknum = (rocknum) or 1
	local ghs
	for d = 1,rocknum
		ghs = P_SpawnMobj(
		s.x+(P_RandomRange(-2100, 2100)<<16), 
		s.y+(P_RandomRange(-2100, 2100)<<16), s.ceilingz-20<<16, MT_METROIDDROOL)
		if ghs and ghs.valid
			ghs.shadowscale = FRACUNIT
			ghs.state = S_ROCKCRUMBLEA
			ghs.scale = 3<<16/(P_RandomRange(1,6))
			ghs.tics = 130
			ghs.health = 1
			ghs.momz = FRACUNIT
			ghs.flags = MF_PAIN|MF_SHOOTABLE --They have tiny hitboxes, but stiiiill!
			ghs.omgrock = true
			ghs = nil
		end
	end
end
local function DoMetroidRocks(s, o, rocknum, doquake) --Metroid Rock Riser! Practically the same thing, but rises rocks insteads
	rocknum = (rocknum) or 1
	if doquake --Do a quake!
		A_samquake(s, 22<<16, 1, 4000<<16)
	end
	local ghs
	for d = 1,rocknum
		ghs = P_SpawnMobj(s.x+(P_RandomRange(-100, 100)<<16), s.y+(P_RandomRange(-100, 100)<<16), s.floorz+10<<16, MT_METROIDDROOL)
		if ghs and ghs.valid
			ghs.shadowscale = FRACUNIT
			ghs.state = S_ROCKCRUMBLEA
			ghs.scale = 105355/(P_RandomRange(2,6))
			ghs.tics = 130
			ghs.health = 1
			ghs.angle = R_PointToAngle2(s.x, s.y, o.x, o.y)
			P_InstaThrust(ghs, ghs.angle, P_RandomRange(-7,-2)<<16)
			ghs.momz = P_RandomRange(3,6)<<16
			ghs.flags = MF_SHOOTABLE --Don't need to make these hurt.
			ghs.omgrock = true
			ghs.nosfx = true
			ghs = nil
		end
	end
end
local function DoMetroidCrash(s, o, noquake) --Metroid wall crash effect! Rocks everywhere.
	if not noquake --Do a quake!
		A_samquake(s, 82<<16, 1, 4000<<16)
	end
	local ghs
	for d = -5,5
		ghs = P_SpawnMobj(s.x, s.y, s.z+s.height, MT_METROIDDROOL)
		if ghs and ghs.valid
			ghs.state = S_ROCKCRUMBLEA
			ghs.shadowscale = FRACUNIT
			ghs.scale = 205355/(P_RandomRange(2,5))
			ghs.tics = 130
			ghs.health = 1
			P_InstaThrust(ghs, o.angle+((d <= 0) and -ANGLE_90 or ANGLE_90), (8*d)<<16)
			ghs.momz = (8<<16)*d
			ghs.flags = MF_PAIN|MF_SHOOTABLE --Don't need to make these hurt.
			ghs.omgrock = true
		end
	end
end
local function DoMetroidLegStomp(s, o, time) --Leg Stomp
	time = (time) or 4
	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
	local ghs
	for d = 0,7
		ghs = P_SpawnMobj(s.x, s.y, s.z+8<<16, MT_PARTICLE)
		ghs.momz = 3<<16
		ghs.tics = 18
		ghs.destscale = 30<<16
		ghs.frame = $|FF_TRANS60
		P_InstaThrust(ghs, ANGLE_45*d, 10<<16)
		if o.omegacharge
			ghs.scale = 3<<16
		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<<16) // and s.omgspeed --Don't move legs while standing still.
		and ((s.hoffset > -30<<16) and (s.hoffset < 30<<16))
			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<<16) 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<<16
			s.legbackforth = -2
		elseif s.hoffset <= -85<<16
			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<<16)
				DoMetroidRocks(s, o, 3)
			end
		end
	end
	--TeleportMove is the main driver moving the legs.
	P_MoveOrigin(s, 
	o.x+FixedMul((67<<16), cos(o.angle+(ANGLE_90*s.legd)))+FixedMul(10<<16+(s.hoffset*s.legd),cos(o.angle)),
	o.y+FixedMul((67<<16), sin(o.angle+(ANGLE_90*s.legd)))+FixedMul(10<<16+(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<<16
		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<<16)) --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<<16
						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<<16)) --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<<16
			s.hoffsetd = 1
		elseif s.fakehoffset >= 12<<16
			s.hoffsetd = -1
		end
		s.fakehoffset = $+(12<<16*s.hoffsetd)
		s.hoffset = s.fakehoffset*s.armd
		s.zoffset = (s.hoffset-(23<<16))*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<<16)
			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<<16+(s.hoffset*s.armd)), cos(o.angle+(ANGLE_90*s.armd)))+FixedMul(105<<16,cos(o.angle)),
	o.y+FixedMul((89<<16+(s.hoffset*s.armd)), sin(o.angle+(ANGLE_90*s.armd)))+FixedMul(105<<16,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<<16,cos(o.angle))+FixedMul(s.hoffset,cos(o.angle)),
	o.y+FixedMul(135<<16,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<<16	
		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<<16
		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)<<16
			s.flm.flags = $ & ~MF_NOCLIPHEIGHT
			P_InstaThrust(s.flm, s.angle, P_RandomRange(30,40)<<16)
				if P_RandomRange(0,1)
				s.flm.frame = L|FF_FULLBRIGHT|FF_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<<16 or s.hoffsetd == nil or s.hoffsetspeed == nil
		s.hoffsetd = 1
		s.hoffsetspeed = P_RandomRange(10, 20)<<16
		elseif s.hoffset > 20<<16
		s.hoffsetd = -1
		s.hoffsetspeed = P_RandomRange(10, 20)<<16
		end
		s.hoffset = $+(s.hoffsetspeed*s.hoffsetd)
		s.zoffset = (s.hoffset/8)-40<<16		
	else
		s.hoffset = 0
		if (s.zoffset <= 0)
		s.headmove = 1	
		elseif (s.zoffset > 24<<16)
		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)<<16), cos(s.angle+(ANGLE_90)))+FixedMul(45<<16,cos(s.angle)),
	s.y+FixedMul((P_RandomRange(-50, 50)<<16), sin(s.angle+(ANGLE_90)))+FixedMul(45<<16,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<<16 --Smaller hitbox for this.
	s.radius = 5<<16
	--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<<16) or s.tailz == nil
			s.tailz = -1
			s.tailzspeed = P_RandomRange(8355,60355)
			elseif (s.zoffset <= -7<<16)
			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<<16+(-30<<16*s.tailseg),cos(lt.angle)),
		o.y+FixedMul(-86<<16+(-30<<16*s.tailseg),sin(lt.angle)),
		o.z+o.height/11+((s.zoffset*s.tailseg)+9<<16) )
	else		
	
		P_MoveOrigin(s,
		o.x+FixedMul(-86<<16+(-30<<16*s.tailseg),cos(o.angle)),
		o.y+FixedMul(-86<<16+(-30<<16*s.tailseg),sin(o.angle)),
		o.z+o.height/11+((s.zoffset)+9<<16) )
	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<<16,cos(o.angle)), o.y+FixedMul(90<<16,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 = 4<<16
		if s.z < s.floorz+80<<16
		s.z = s.floorz+80<<16
		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!
	
		local DIFFICULTY = SAMUSDIFFICULTY
		
		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<<16)
			s.z = s.floorz+86<<16 --Well, this is just awkward, teleport up!
			s.momz = 0		
		elseif (s.z < s.floorz+86<<16) --Main body must hover over the ground!
		s.z = s.z+FRACUNIT
		s.momz = 0
		elseif (s.z > s.floorz+88<<16)
		s.momz = $-2<<16
			if (s.z <= s.floorz+88<<16) --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)<<16, s.y+P_RandomRange(-450, 450)<<16, s.z+P_RandomRange(-250, 250)<<16, MT_THOK)
			s.bmb.scale = P_RandomRange(3,5)<<16
			s.bmb.state = S_MINIEXP1
			s.bmb.color = SKINCOLOR_FLAME
			end
			if (s.deathanim < 40)
				if (s.deathanim < 18)
				s.frame = $|FF_TRANS80 & ~FF_TRANS50
				else
				s.frame = $|FF_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 = $|FF_TRANS50
					s.plexpand.scale = 7<<16
					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)<<16, s.y+P_RandomRange(-450,450)<<16, s.z+P_RandomRange(0,100)<<16, 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<<16)
				if (s.z < s.floorz+100<<16)
					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 DIFFICULTY != 0
					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<<16)
				if (s.omegaleap > 39)
					SpaceJumpGFX(s, SKINCOLOR_MOSS, 1, L|FF_TRANS40)
				end
			elseif (s.omegaleap > 33)
				s.momz = 4<<16
			else
				s.momz = $-5<<16
			end
			
			if s.omegaleapd == 5
			P_InstaThrust(s, s.angle, -38<<16)
			else
			A_FaceTarget(s)
			P_InstaThrust(s, s.angle+ANGLE_90*s.omegaleapd, 38<<16)
			end
			
			if (s.omegaleap < 34) and ((s.z < s.floorz+100<<16) 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<<16
				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<<16, 12) 	
				S_StartSound(s, sfx_befall) S_StartSound(s, sfx_dmpain) S_StartSound(s, sfx_rocks2)
				s.omegacharge = 0
				s.momx,s.momy = 0,0
				--Okay, now give the player some breathing room.
				if DIFFICULTY == 2
					s.actiontimer = 100
				elseif DIFFICULTY != 0
					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 DIFFICULTY == 2
					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 DIFFICULTY == 2 --Fusion Mode.
						s.actiontimer = P_RandomRange(4,62)
					elseif DIFFICULTY != 0 --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<<16)
						end
					else
						if s.slowdown
						s.slowdown = $-1
						s.momx = $/2
						s.momy = $/2
						else
						P_InstaThrust(s, s.angle, 18<<16)
						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<<16 --GET UNSTUCK MANUEVRES!!
						for d = 1,36
							P_TryMove(s, s.x+FixedMul(30<<16, cos(s.angle+(ANG10*d))), s.y+FixedMul(30<<16, sin (s.angle+(ANG10*d))), false)
						end
					end						
					
					if DIFFICULTY == 2 --Fusion Mode.
						s.actiontimer = P_RandomRange(70, 80)
					elseif DIFFICULTY != 0 --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 DIFFICULTY == 2 --Fusion Mode.
						s.actiontimer = P_RandomRange(60, 80)
					elseif DIFFICULTY != 0 --normal mode
						s.actiontimer = P_RandomRange(68, 86)
					else --casual
						s.actiontimer = P_RandomRange(94, 139)
					end
					if DIFFICULTY != 0
						s.rightarm.armswipe = 22
						s.leftarm.armswipe = 40
					else
						s.leftarm.armswipe = 22
					end
				elseif s.omegarng == 5 --Flamethrower
					if DIFFICULTY == 2 --Fusion Mode.
						s.actiontimer = P_RandomRange(47, 70)
					elseif DIFFICULTY != 0 --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<<16)
						s.actiontimer = 2 --Uhh, nevermind, you're in the air, don't jump.
					else
						if DIFFICULTY != 0
							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 DIFFICULTY == 2 --Fusion Mode.
							s.actiontimer = P_RandomRange(44, 55)
						elseif DIFFICULTY != 0 --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<<16)
					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|FF_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<<16)
						else
						s.ghosttime = 2
						P_InstaThrust(s, s.angle, 65<<16)
						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
			
			local ghs = P_SpawnGhostMobj(s)
			ghs.destscale = s.scale*6
			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 = ($ & ~FF_TRANSMASK)|FF_TRANS80
		 	elseif (o.deathanim < 35)
				s.frame = ($ & ~FF_TRANSMASK)|FF_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 = $|FF_TRANS40
				s.tics = 16
				if not s.nosfx
					s.momz = P_RandomRange(8,15)<<16
					S_StartSound(s, (P_RandomRange(sfx_rocks1, sfx_rocks4)))
				else
				s.tics = 8
				s.momz = P_RandomRange(1,3)<<16
				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)<<16)
				s.momz = P_RandomRange(6,18)<<16
				s.flags = $ & ~MF_PAIN & ~MF_SHOOTABLE		
				s.scale = 10<<16/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 = $|FF_TRANS40
				s.tics = 12
				s.momz = P_RandomRange(2,5)<<16
				S_StartSound(s, sfx_wbreak)
				s.dripped = true
			end
		else
			if not s.setup
			s.sprite = SPR_OMGM
			s.frame = H|FF_TRANS40
			s.scale = FRACUNIT/2
			s.destscale = 3<<16
			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<<16)
						A_samquake(z.mo, 80<<16, 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<<16)
						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<<16, MT_FLINGRING)
						if s.flingring.valid
						P_InstaThrust(s.flingring, P_RandomRange(0,359)*ANG1, 5<<16)
						s.flingring.fuse = 350
						end
					end
					s.invincible = 18
					i.state = S_PLAY_SPRING
					P_InstaThrust(i, s.angle, 45<<16)
					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)<<16), s.y+(P_RandomRange(-phazond, phazond)<<16), s.z+(P_RandomRange(-phazond/12, phazond/12)<<16), 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)<<16 
				s.pspawn.sprite = SPR_MPR1
					if P_RandomRange(0,1)
					s.pspawn.frame = Q|FF_FULLBRIGHT|FF_TRANS40
					else
					s.pspawn.frame = P|FF_FULLBRIGHT|FF_TRANS40					
					end
			end
	
	else
		s.pspawn = P_SpawnMobj(s.x+(P_RandomRange(-300, 300)<<16), s.y+(P_RandomRange(-300, 300)<<16), s.z+(P_RandomRange(-10, 10)<<16), MT_SAMUSEPARTICLE)
			if s.pspawn and s.pspawn.valid
				s.pspawn.leafpt = true
				s.pspawn.tics = 1050
				s.pspawn.scale = P_RandomRange(1,5)<<16
				s.pspawn.flags = 0
				s.pspawn.momx = P_RandomRange(-20, 20)<<16 
				s.pspawn.momy = P_RandomRange(-20, 20)<<16 
				s.pspawn.sprite = SPR_MPR1
				if green
				s.pspawn.frame = Y
				s.pspawn.z = $+350<<16
				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)<<16), s.y+(P_RandomRange(-220, 220)<<16), s.z+(P_RandomRange(-10, 10)<<16), 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)<<16 
				s.pspawn.sprite = SPR_MPR1
					if P_RandomRange(0,1)
					s.pspawn.frame = Q|FF_FULLBRIGHT|FF_TRANS40
					else
					s.pspawn.frame = P|FF_FULLBRIGHT|FF_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 = $|FF_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 = $|FF_TRANS60 & ~FF_TRANS40
			elseif (s.tics == 10)
			s.frame = $|FF_TRANS80 & ~FF_TRANS40 & ~FF_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<<16)	
						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.valid
		if not s.omegaflame
			if not s.scaleup
				s.scaleup = true
				P_InstaThrust(s, s.angle, 50<<16)		
				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)<<16
						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 = 10<<16
				P_InstaThrust(s, s.angle, 70<<16)				
			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|FF_TRANS30
			elseif (s.tics < 23)
				s.frame = K|FF_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|FF_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|FF_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<<16/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<<16) --Give Superform dudes a hard time
			m.momz = 12<<16
			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 = $|FF_TRANS50
					s.plexpand.scale = 3<<16
					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 = 20<<16
			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)