--=================================DARK PZ BOSS=============================================
--ACZ4's boss! The mastermind who brought the Metroids and turns the Black Rock's goo into Phazon!
--They are referred to as DarkPZ alot in the code, but that doesn't mean it's spoiler-free.
--==========================================================================================

local function DoPZGhost(s, color) --PZ version of P_SpawnGhostMobj
	color = (color) or SKINCOLOR_SUPERSKY3
	local ghs = P_SpawnGhostMobj(s)
	if ghs and ghs.valid
		ghs.rollangle = s.rollangle
		ghs.tics = 12
		ghs.blendmode = AST_ADD
		ghs.scalespeed = $*P_RandomRange(1,3)
		ghs.destscale = $*5
		ghs.color = color
		ghs.colorized = true
	end
end
local function DoPZBarrier(s, color, tics, stomp, rotatedist) --PZ Barrier!
	color = (color) or SKINCOLOR_SUPERSKY3
	tics = (tics) or 12
	rotatedist = (rotatedist) or 45
	local ghs
	if stomp and stomp == "special" --Reflector variant.
		for d = 0,5
			local cal = (ANG60*d)
			ghs = P_SpawnMobj(s.x+FixedMul(30*cos(s.angle+cal), s.scale), s.y+FixedMul(30*sin(s.angle+cal), s.scale), s.z, MT_THOK)
			ghs.renderflags = RF_NOCOLORMAPS|RF_FULLBRIGHT
			ghs.scale = FRACUNIT
			ghs.momz = FRACUNIT*P_RandomRange(5,40)
			ghs.tics = tics*P_RandomRange(2,4)
			ghs.destscale = FRACUNIT*30
			ghs.blendmode = AST_ADD
			ghs.sprite = SPR_PHAZ
			if d < 3
				ghs.frame = J|FF_TRANS20
				ghs.color = SKINCOLOR_SUPERSKY3			
			else
				if (leveltime % 2 == 0)
					ghs.frame = J|FF_TRANS30
					ghs.color = SKINCOLOR_COBALT
				else
					ghs.color = SKINCOLOR_BLACK
					ghs.frame = J|FF_TRANS50
				end
			end
			P_InstaThrust(ghs, ANGLE_45*d, P_RandomRange(4,6)<<16)
		end		
	
	elseif stomp --Stomp variant.
		for d = 0,5
			local cal = (ANG60*d)
			ghs = P_SpawnMobj(s.x+FixedMul(rotatedist*cos(s.angle+cal), s.scale), s.y+FixedMul(rotatedist*sin(s.angle+cal), s.scale), s.z, MT_THOK)
			ghs.renderflags = RF_NOCOLORMAPS|RF_FULLBRIGHT
			ghs.scale = 3<<16
			ghs.momz = 10<<16
			ghs.tics = tics*2
			ghs.destscale = 30<<16
			ghs.sprite = SPR_PHAZ
			if (leveltime % 2 == 0)
				ghs.frame = J|FF_TRANS30
				ghs.color = color
			else
				ghs.color = SKINCOLOR_WHITE
				ghs.frame = J|FF_TRANS50
			end
		//	P_InstaThrust(ghs, R_PointToAngle2(ghs.x, ghs.y, s.x, s.y), -20<<16)
			P_InstaThrust(ghs, ANGLE_45*d, P_RandomRange(8,12)<<16)
		end	
		
	else
		ghs = P_SpawnMobj(s.x, s.y, s.z, MT_THOK)
		ghs.renderflags = RF_NOCOLORMAPS|RF_FULLBRIGHT
		ghs.scale = P_RandomRange(9,12)<<16
		ghs.sprite = SPR_PHAZ
		ghs.color = color
		ghs.colorized = true			
		if P_RandomRange(0,1)
			ghs.frame = J|FF_TRANS50
			ghs.tics = tics
			ghs.color = color
		else
			ghs.tics = tics
			ghs.frame = J|FF_TRANS70
			ghs.color = (P_RandomRange(0,1)) and color or SKINCOLOR_JET
		end	
		ghs.scalespeed = $*2/P_RandomRange(1,7)
		ghs.destscale = s.scalespeed+1
		ghs.momz = (P_RandomRange(38,54))<<16			
	end
end


addHook("MobjThinker", function(s) if not s.valid return end --
	if not s.setup --Similar size to Samus
		s.scale = 110000
		s.shadowscale = 50000
		s.setup = true
		s.superstrongfoe = true
	end
	--These flashing frames don't take massive priority exactly.
	if s.painfred --Flash pain colors.
		if (s.painfred % 2 == 0)
			s.color = SKINCOLOR_RED
			s.colorized = true
		else
			s.colorized = false
			s.color = SKINCOLOR_NONE
		end
		s.painfred = $-1			
	elseif s.painfyellow
		if (s.painfyellow % 2 == 0)
			s.color = SKINCOLOR_YELLOW
			s.colorized = true
		else
			s.colorized = false
			s.color = SKINCOLOR_NONE
		end
		s.painfyellow = $-1			
	end
	
	local DIFFICULTY = SAMUSDIFFICULTY
	
	--DYING....DRAMATICALLY.	
	if s.pzdeathanim
		s.flags = $|MF_NOCLIPHEIGHT & ~(MF_PAIN|MF_SHOOTABLE)
		if s.pzclone or (leveltime % 8 == 0) --Clones don't get a dramatic death.
			local ghs
			for d = 1,12
				ghs = P_SpawnMobj(s.x+P_RandomRange(200,200)<<16, s.y+P_RandomRange(200,200)<<16, s.z+P_RandomRange(1,80)<<16, MT_THOK)
				ghs.tics = 24
				ghs.momx = P_RandomRange(-30,30)<<16
				ghs.momy = P_RandomRange(-30,30)<<16
				ghs.momz = P_RandomRange(-10,10)<<16						
				ghs.sprite = SPR_MPR1
				ghs.color = SKINCOLOR_RED
				ghs.blendmode = AST_ADD
				ghs.colorized = true
				if P_RandomRange(0,1)
					ghs.frame = Q|FF_FULLBRIGHT|FF_TRANS30
				else
					ghs.frame = P|FF_FULLBRIGHT|FF_TRANS20	
				end
			end
			if s.pzclone
			ghs = P_SpawnGhostMobj(s)
			ghs.scale = $*3
			ghs.destscale = ghs.scalespeed+1
			ghs.tics = 35
			ghs.colorized = true
			ghs.color = SKINCOLOR_RED
			S_StartSound(ghs, sfx_pztele)
				if s.target and s.target.player
				and (s.target.player.sammissiles != nil and (s.target.player.sammissiles < 6))
					P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_MPKU) 
				end
				if s.valid
					s.state = S_NULL return --
				end
			else
			local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_SAMUSZAP)
				if ghs.valid
				ghs.scale = s.scale*2
				ghs.momx = s.momx
				ghs.momy = s.momy
				ghs.momz = s.momz
				ghs.eflags = s.eflags
				ghs.blendmode = AST_ADD
				ghs.color = P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY5)
				ghs.morning = 4
					if ghs.valid
						LeafSpawn(s, nil, true, 90)
						LeafSpawn(s, nil, true, 300)
						ghs = P_SpawnMobj(s.x, s.y, s.z+((s.height/6)*P_MobjFlip(s)), MT_SAMUSZAP)
						ghs.color = P_RandomRange(SKINCOLOR_SUPERRED1, SKINCOLOR_SUPERRED5)
						ghs.morning = 4
					end
				end
			end
		end
		
		if not s.pzclone --Commence dramatic doom.
			if (s.pzdeathanim == 139)
				A_FaceTarget(s)
				s.scalespeed = $/4
				s.destscale = s.scale*3
				P_MoveOrigin(s, s.x+FixedMul(255<<16, cos(s.angle)), s.y+FixedMul(255<<16, sin(s.angle)), s.floorz+50<<16)
					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
					P_SamFP(z, PAL_RECYCLE, 12)
					end
				P_LinedefExecute(11111) --Stop the music.
			end
			
			s.state = S_PZ_PAIN
			s.pzdeathanim = $-1
			s.momx,s.momy,s.momz = 0,0,FRACUNIT
			
			if s.pzdeathanim % 4 == 0
				DoPZGhost(s)
				S_StartSound(s, sfx_mtrdb)
				s.bmb = P_SpawnMobj(s.x+P_RandomRange(-250,250)<<16, s.y+P_RandomRange(-250, 250)<<16, s.z+P_RandomRange(-150, 150)<<16, MT_THOK)
				s.bmb.scale = FRACUNIT*P_RandomRange(3,5)
				s.bmb.state = S_MINIEXP1
				s.bmb.color = SKINCOLOR_FLAME
				s.bmb.blendmode = AST_ADD
			end
			
			if (s.pzdeathanim < 40)
				if (s.pzdeathanim < 18)
				s.sprite = SPR_PHAZ
				s.frame = I|FF_TRANS80
				else
				s.sprite = SPR_PHAZ
				s.frame = I|FF_TRANS40
				end
				
				if (s.pzdeathanim == 1)
				
					DoPZBarrier(s, nil, nil, true, 40)
					DoPZBarrier(s, P_RandomRange(SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERSILVER5))
					
					local ghs
					for d = 1,30
					LeafSpawn(s, nil, true, 350)
					ghs = P_SpawnMobj(s.x+P_RandomRange(-100,100)<<16, s.y+P_RandomRange(-100,100)<<16, s.z+P_RandomRange(1,80)<<16, MT_THOK)
					ghs.tics = 105
					ghs.momx = P_RandomRange(-30,30)<<16
					ghs.momy = P_RandomRange(-30,30)<<16
					ghs.momz = P_RandomRange(-10,30)<<16						
					ghs.sprite = SPR_MPR1
						if P_RandomRange(0,1)
						ghs.color = SKINCOLOR_COBALT
						ghs.colorized = true
						end
						if P_RandomRange(0,1)
						ghs.frame = Q|FF_FULLBRIGHT|FF_TRANS30
						else
						ghs.frame = P|FF_FULLBRIGHT|FF_TRANS20					
						end						
					end
				s.plexpand = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_PBEXPAND)
					if s.plexpand
					s.plexpand.blendmode = AST_ADD
					s.plexpand.frame = $|FF_TRANS50
					s.plexpand.scale = FRACUNIT*7
					s.plexpand.scalespeed = $*10
					s.plexpand.destscale = $*40
					end	
					P_LinedefExecute(11112)
					P_LinedefExecute(11113)
					P_LinedefExecute(111)
					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_NRGB
						elseif s.item == 6
						s.item = MT_NRGD
						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
		end
	-- Ambush sequence				
	elseif s.pzambush
		s.pzambush = $-1
		if (s.pzambush > 100)
			if s.pzambush == 101
				for z in players.iterate
					if z.mo
					z.mo.rdeathmsg = true 
					end
				end
			end
		s.frame = A|FF_TRANS70
		elseif (s.pzambush > 25)
		s.momz = 2<<16
			if (s.pzambush > 60)
			s.flags2 = $ & ~MF2_DONTDRAW
			s.frame = A|FF_TRANS60|FF_FULLBRIGHT
			elseif (s.pzambush > 50)
			s.frame = D|FF_TRANS40|FF_FULLBRIGHT
				if (s.pzambush == 60)
				S_StartSound(s, sfx_pzlaug)
				end
			elseif (s.pzambush == 50)
				S_StartSound(s, sfx_cmcha)
				s.frame = D|FF_FULLBRIGHT
				if s.target
				local t = s.target
				t.omegarushpanic = 30
				s.pzreticule2 = P_SpawnMobj(t.x, t.y, t.z+t.height*2, MT_PZTARGET)
					if s.pzreticule2 and s.pzreticule2.valid
					s.pzreticule2.target = t
					s.pzreticule2.fuse = 51
					end
				end
			end
		elseif (s.pzambush < 26)
			s.momz = 0
			if (s.pzambush == 25)
				s.frame = D|FF_FULLBRIGHT
				s.momz = 0
				if s.pzreticule2 and s.pzreticule2.valid -- Got a target? FIRE!!!
					s.flags = $|MF_NOCLIP & ~ MF_ENEMY & ~MF_SHOOTABLE & ~MF_BOSS
					s.pzmissile = P_SpawnMissile(s, s.pzreticule2, MT_HBSHOT)
					if s.pzmissile and s.pzmissile.valid
						local f = s.pzmissile
						f.darkhyper = true --We give both types this
						f.flags2 = $|MF2_SUPERFIRE			
						for z in players.iterate
							if z.mo
								if (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 3000<<16)
									A_samquake(z.mo, 80<<16, 28, 28)
									SAM_COM_BufInsertText(z, "tunes DARKPZ")
									P_SamFP(z, PAL_MIXUP, 6)
									z.mo.omegarushpanic = 12
								end
							end
						end
						S_StartSound(nil, sfx_hbsh) S_StartSound(s, sfx_hbsh)
						s.flags = $|MF_ENEMY|MF_SHOOTABLE|MF_BOSS & ~MF_NOCLIP --This game is an asshole.				
					end
				end
			end
		end
	-- Super knockback!! Nice!		
	elseif s.pzsuperknockback
		s.pzsuperknockback = $-1
			if s.pzknockbackangle != nil
				s.painfred = $+1
				A_SAMPARTICLE(s, MT_MPR5, 6, 8, -2, 6, SKINCOLOR_COBALT, P_RandomRange(44355, 58355))
				P_InstaThrust(s, s.pzknockbackangle, -68<<16)
				s.momz = 11<<16
				s.state = S_PZ_PAIN
				s.pzrollangle = s.pzrollangle and $+ANG30 or ANG30
				s.rollangle = s.pzrollangle
				if s.target and s.target.valid
					s.target.angle = R_PointToAngle2(s.target.x, s.target.y, s.x, s.y)
				end
			end
			
			if P_IsObjectOnGround(s) or (s.blockframes > 5) or (s.pzsuperknockback == 1) or s.pzknockbackangle == nil
				S_StopSound(s)
				s.rollangle = 0
				S_StartSound(nil, sfx_brakrx)
				S_StartSound(nil, sfx_smexp)
				for z in players.iterate
					if z.mo and (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 3000<<16)
						A_samquake(z.mo, 80<<16, 9, 9)
						P_SamFP(z, PAL_MIXUP, 4)
						if not S_SoundPlaying(z.mo, sfx_pzouch)
							S_StartSound(z.mo, sfx_pzouch, z)
						end
					end
				end
				for d = 0,2
					S_StartSound(nil, sfx_brakrx)
					s.plexpand = P_SpawnMobj(s.x, s.y, s.z+s.height/4, MT_PBEXPANDW)
					if s.plexpand and s.plexpand.valid
						s.plexpand.scale = $*P_RandomRange(5,8)
						s.plexpand.scalespeed = $*P_RandomRange(20,35)
						s.plexpand.destscale = $*60
						s.plexpand.tics = $*5/3
						s.plexpand.color = SKINCOLOR_COBALT+d
						s.plexpand.colorized = true
					end
				end
				P_DamageMobj(s, nil, nil, 3) --Inflict all the damage!
				s.pzsuperknockback = 0					
			end
			
			if (leveltime % 3 == 0)
				A_BossScream(s, 0, MT_CYBRAKDEMON_VILE_EXPLOSION)
			else
				S_StartSound(s, sfx_s3kb4)
				P_SpawnMobj(s.x+P_RandomRange(-100,100)<<16, s.y+P_RandomRange(-100,100)<<16, s.z+P_RandomRange(-70,70)<<16, MT_SONIC3KBOSSEXPLODE)
			end
	--Phazon Barrier!			
	elseif s.pzreflecttime
	
		s.pzreflecttime = $-1
		s.state = S_PZ_FLOAT
		s.momx = 0 s.momy = 0 s.momz = 0
		s.angle = $+(ANG20*2)
		
		LeafSpawn(s, nil, true, 90)
		DoPZGhost(s)
				
		if (s.pzreflecttime % 2 == 0) and (s.pzreflecttime > 25)
				s.invincible = 3
				DoPZBarrier(s, nil, nil, "special", 40)
					
				for d = 1,4
					LeafSpawn(s, nil, true, 350)
					s.ghs = P_SpawnMobj(s.x+P_RandomRange(-200,200)<<16, s.y+P_RandomRange(-200,200)<<16, s.z+P_RandomRange(1,80)<<16, MT_IVSP)
					s.ghs.tics = P_RandomRange(50,80)
					s.ghs.angle = R_PointToAngle2(s.ghs.x, s.ghs.y, s.x, s.y)
					P_InstaThrust(s.ghs, s.ghs.angle, (P_RandomRange(3,20))*-FRACUNIT)						
					s.ghs.scale = $*P_RandomRange(1,3)
					s.ghs.momz = P_RandomRange(2,15)<<16
					
					if P_RandomRange(0,1)
						s.ghs.color = SKINCOLOR_SUPERGOLD1
						s.ghs.colorized = true
					end				
				end
		end
		
		if (s.pzreflecttime % 20 == 0)
		S_StartSound(s, sfx_s3k79)
		S_StartSound(s, sfx_cmol)
		end
		LeafSpawn(s, nil, true, 200)
		LeafSpawn(s, nil, true, 600)
		
		if s.actiontimer and (s.actiontimer < 3)
		s.actiontimer = 3 --Extend timer.
		end
		
		if not s.pzreflecttime
		A_FaceTarget(s)
		s.colorized = false
		end
		
	--THE PHAZON SCREW ATTACK DIVE!	

	elseif s.phazoncooldown
		s.phazoncooldown = $-1
		s.state = S_PZ_FLOAT
		s.momx = 0 s.momy = 0
		
		if not (s.z < s.floorz+3<<16)
			s.momz = -20<<16
		else
			s.momz = 0
		end
		
		LeafSpawn(s, nil, true, 200)
		LeafSpawn(s, nil, true, 600)
		
		if s.actiontimer and (s.actiontimer < 3)
			s.actiontimer = 3 --Extend timer.
		end
	elseif s.phazondive
		if not P_IsObjectOnGround(s)
			if (leveltime % 3 == 0)
				local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_SAMUSZAP)
				if ghs.valid
					ghs.scale = s.scale*2
					ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
					ghs.momx,ghs.momy,ghs.momz = s.momx,s.momy,s.momz
					ghs.eflags = s.eflags
					ghs.color = P_RandomRange(SKINCOLOR_SUPERGOLD1, SKINCOLOR_SUPERGOLD5)
					ghs.morning = 4
					if (s.phazondive < 40) and ghs.valid
						DoPZGhost(s, P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY5))
						LeafSpawn(s, nil, true, 90)
						LeafSpawn(s, nil, true, 300)
						LeafSpawn(s, nil, true, 600)
						ghs = P_SpawnMobj(s.x, s.y, s.z+((s.height/6)*P_MobjFlip(s)), MT_SAMUSZAP)
						ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
						ghs.color = s.color
						ghs.scale = $*3
						ghs.morning = 4
					end
				end
			end
		end
		
		s.phazondive = $-1
		s.state = S_PZ_ROLL
		if (leveltime % 3 == 0)
			s.colorized = false
			s.color = SKINCOLOR_NONE
		else
			s.colorized = true
			s.color = SKINCOLOR_SUPERSILVER1
		end
		
		if (s.phazondive >= 89)
			for d = 0,7
				local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_PARTICLE)
				ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
				ghs.momz = FRACUNIT*3
				ghs.tics = 12
				ghs.scale = FRACUNIT*3
				ghs.destscale = FRACUNIT*30
				ghs.frame = $|FF_TRANS60
				P_InstaThrust(ghs, ANGLE_45*d, 15<<16)
			end
			s.momz = (s.phazondive*10/23)<<16
			s.momx = $/2
			s.momy = $/2
			P_Thrust(s, s.angle, -2<<16)
		elseif (s.phazondive >= 40)
			s.momz = 0 s.momx = 0 s.momy = 0
		elseif (s.phazondive < 40)
			if s.pzreticule4 and s.pzreticule4.valid
				s.angle = R_PointToAngle2(s.x, s.y, s.pzreticule4.x, s.pzreticule4.y) 
			end
			
			if s.phazondive == 39
				for z in players.iterate
					if z.mo
					and (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 2000<<16)
						A_samquake(z.mo, 40<<16, 8, 8)
						P_SamFP(z, PAL_MIXUP, 4)
						z.mo.omegarushpanic = 6
					end
				end
				s.blockframes = 0
				A_FaceTarget(s)
				S_StartSound(nil, sfx_satkf)
				S_StartSound(nil, sfx_pbchae)
			end
			
			P_InstaThrust(s, s.angle, 60<<16)
			s.momz = -30<<16
			
			if P_IsObjectOnGround(s) or (s.blockframes > 5)
				S_StartSound(nil, sfx_bexpld)
				S_StartSound(nil, sfx_bgxpld)
				S_StartSound(nil, sfx_brakrx)
				A_SAMUSEXPLOSIONS(s, 5, MT_SAMEXPLODE1, 5<<16, 144000, true)
				A_SAMUSEXPLOSIONS(s, 7, MT_SAMMISSILESMOKE, 50<<16, 650000)
				A_SAMUSEXPLOSIONS(s, 12, MT_SAMEXPLODE1, false, 1001, true)
				A_SAMUSEXPLOSIONS(s, 20, MT_SAMMISSILESMOKE, false, 9001)
				for z in players.iterate
					if z.mo
						z.mo.omegarushpanic = 0
						if (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 3000<<16)
							A_samquake(z.mo, 75<<16, 20, 20)
							P_SamFP(z, PAL_MIXUP, 4)
							
							if (FixedHypot(FixedHypot(s.x-z.mo.x, s.y-z.mo.y), s.z-z.mo.z) < 200<<16) and z.mo.health
								P_DamageMobj(z.mo, s, s)
								P_SamFP(z, PAL_NUKE, 20)
								P_InstaThrust(z.mo, R_PointToAngle2(z.mo.x, z.mo.y, s.x, s.y), 70<<16)
								z.mo.momz = $-4<<16
								z.mo.angle = R_PointToAngle2(z.mo.x, z.mo.y, s.x, s.y)
							end
						end
					end
				end
				s.colorized = false
				s.phazondive = 0
				s.phazoncooldown = 45 --Invincibiliiiityyyy
				s.pzreflector2 = 20
				s.pzreflector = 45 
			end
			
			if s.phazondive == 1 --Never landed?? Just cancel, I guess..
				s.phazondive = 0
				s.colorized = false
				s.momz = 0
				s.state = S_PZ_FLOAT
			end				
		end
	--PHAZON GATTLING ACTION		
	elseif s.phazongattling
		s.phazongattling = $-1
		s.momx = 0 s.momy = 0 s.momz = 0
		s.state = S_PZ_SHOOT
		A_FaceTarget(s)
		if (s.phazongattling >= 89)
			s.momz = (s.phazongattling/3)<<16	
		elseif (s.phazongattling < 89)
			if (s.phazongattling % 4 == 0) and s.pzreticule3 and s.pzreticule3.valid and not (s.state == S_PZ_PAIN)
				S_StartSound(s, sfx_plcm) S_StartSound(s, sfx_plcm)
				s.flags = $|MF_NOCLIP & ~(MF_ENEMY|MF_SHOOTABLE|MF_BOSS) --Don't clip into yourself	before you can even assign a target. 
				s.pzgattle = P_SpawnMissile(s, s.pzreticule3, MT_PLSHOT)
				s.colorized = true
				s.color = SKINCOLOR_SKY				
				if s.pzgattle and s.pzgattle.valid
					s.pzgattle.darkhyper = true
					s.pzgattle.flags2 = $|MF2_SUPERFIRE|MF2_EXPLOSION
					s.pzgattle.color = SKINCOLOR_SUPERSKY2
					s.pzgattle.colorized = true
				end
				s.flags = $|MF_ENEMY|MF_SHOOTABLE|MF_BOSS & ~MF_NOCLIP					
			else
				s.color = SKINCOLOR_NONE
				s.colorized = true
			end
			if (s.phazongattling == 1)
				s.colorized = false
				S_StartSound(s, sfx_fizzle)
				s.phazongattling = 0
				s.state = S_PZ_FLOAT
				s.momz = -20<<16
			end
		end
	--SLIDEBACK SHOT! Gives player room to dodge an incoming Phazon Missile or Hyper Beam!
	elseif s.slideback
		s.slideback = $-1
		s.frame = A|FF_FULLBRIGHT
		if s.hyperfire --Beam warning!!
			local ZHEIGHT = (s.eflags & MFE_VERTICALFLIP) and s.height*10/13 or s.height/4
			local ghs = P_SpawnMobj(s.x, s.y, s.z+ZHEIGHT, MT_SAMUSZAP)
			if ghs.valid
				ghs.scale = s.scale*30/41
				ghs.momx = s.momx/2
				ghs.momy = s.momy/2
				ghs.momz = s.momz/2
				ghs.eflags = s.eflags
				ghs.color = SKINCOLOR_COBALT
				ghs.morning = 4
			end
		end
	DoPZGhost(s, P_RandomRange(SKINCOLOR_WHITE, SKINCOLOR_JET))
		if (s.slideback == 29 or s.slideback == 49)
		S_StartSound(s, sfx_iceb) S_StartSound(s, sfx_s3k47)
			for d = 0,7
				local ghs = P_SpawnMobj(s.x, s.y, s.z+8<<16, MT_PARTICLE)
				ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
				ghs.momz = FRACUNIT*3
				ghs.tics = 18
				ghs.destscale = FRACUNIT*30
				ghs.frame = $|FF_TRANS60
				P_InstaThrust(ghs, ANGLE_45*d, 10<<16)
				ghs.scale = FRACUNIT*3
			end
		end
		if s.z < s.floorz+130<<16
			P_SpawnMobj(s.x, s.y, s.floorz, MT_EXPLODE)
		end	
		if (s.slideback > 15) --Tick down faster
			s.slideback = $-1
		end
		
		A_FaceTarget(s)			
		s.momz = FRACUNIT*8/s.slideback
		P_InstaThrust(s, s.angle, (s.slideback*(-2<<16))+9<<16)
		if s.slideback == 1
			s.momx = 0
			s.momy = 0
			s.momz = 0
			s.state = S_PZ_SHOOT
		 	if s.pzreticule2 and s.pzreticule2.valid -- Got a target? FIRE!!!
			s.flags = $|MF_NOCLIP & ~ MF_ENEMY & ~MF_SHOOTABLE & ~MF_BOSS
				s.pzmissile = P_SpawnMissile(s, s.pzreticule2, (s.hyperfire) and MT_HBSHOT or MT_SAMSUPERMISSILE)
				if s.pzmissile and s.pzmissile.valid
					local f = s.pzmissile
					f.darkhyper = true --We give both types this
					f.flags2 = $|MF2_SUPERFIRE				
					if f.type == MT_SAMSUPERMISSILE
						S_StartSound(nil, sfx_smsh)
						f.momx = $*10/13 f.momy = $*10/13 f.momz = $*10/13 --Slow down a lot!
						f.pzbarrier = P_SpawnMobj(f.x, f.y, f.z, MT_PZBARRIER)
						if f.pzbarrier and f.pzbarrier.valid
							local b = f.pzbarrier
							if f.target
								b.target = f.target
							end
							b.darkpz = s
							b.borigin = f --cling to origin
							b.scale = FRACUNIT*10
						end
					else -- This is the Hyper Beam...
						for z in players.iterate
							if z.mo
								if (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 3000<<16)
									A_samquake(z.mo, 80<<16, 28, 28)
									P_SamFP(z, PAL_MIXUP, 6)
									z.mo.omegarushpanic = 12
								end
							end
						end
						S_StartSound(nil, sfx_hbsh) S_StartSound(s, sfx_hbsh) S_StartSound(s, sfx_hbsh)
					end
					s.flags = $|MF_ENEMY|MF_SHOOTABLE|MF_BOSS & ~MF_NOCLIP --This game is an asshole.				
				end
			end
			s.pzmissile = nil
			s.hyperfire = nil --Discard useless data...
			s.pzreticule2 = nil
			s.slideback = 0			
		end
		
	--BASIC FLOATING AND RANDOM ACTIONS SETUP!
	
	elseif s.target and s.target.valid and s.target.health and s.target.player
		local t = s.target
	
		if t.crystalflashtime
			t.crystalflashtune = 1
		end
		if s.floattransition
			s.floattransition = $-1
		end
		--I give up, MAKE the damn music play.
		if (leveltime % 105 == 0) and s.health and not s.pzclone
			for z in players.iterate
				SAM_COM_BufInsertText(z, "tunes DARKPZ")
			end
		end
		if t.pzpaintime and DIFFICULTY != 2
		and s.actiontimer and (s.actiontimer < 60)
			s.pzbossrngset = true
			s.pzbossrng = 10 --Spam barriers to give players time to get back on the platform and catch their breath.
		end
		if not s.actiontimer --Set up a cooldown before an action!
			if s.pzclone
				s.actiontimer = P_RandomRange(100,150)
			elseif DIFFICULTY == 2 --Fusion Mode.
				s.actiontimer = P_RandomRange(12,42)
			elseif DIFFICULTY != 0 --normal mode
				s.actiontimer = P_RandomRange(40,62)
			else --casual
				s.actiontimer = P_RandomRange(55,95)
			end
		else
			if s.pzclone --Clones always spam the Wave Homer, sometimes attacking with the
			s.health = 1
			s.flags = $|MF_SHOOTABLE|MF_BOSS|MF_NOGRAVITY & ~MF_NOCLIP
				if s.originalpz and s.originalpz.valid
				elseif s and s.valid
					P_SpawnGhostMobj(s)
					s.pzdeathanim = 10
					return --
				end
				if not (s.pzbossrng and s.pzbossrng >= 8)
					s.pzbossrng = 1
					s.pzbossrngset = true
				end
			end
			if not (s.actiontimer  < 3 and (s.state == S_PZ_PAIN)) --Don't get stunlocked without retaliating at least!
				s.actiontimer = $-1
			end
		end
		
		--All the magic gets decided when the actiontimer hits 1!	
		
		if s.actiontimer == 1
			if s.pzbossrngset --Looks like your attack was predetermined this time!
				s.pzbossrngset = false
			else	
			
				-- 1/2/3 = Wave Homers, 3 shots that slowly stalk and pressure a player while you can keep moving.
				-- 4 Phazon Dive. A modified screw attack with a bigger explosion and reflect radius, but not as strong as the real deal.
				-- 5 Phazon Missile. A modified SM with reflect barrier and concentrated explosion. Reflectable with your Screw Attack.
				-- 6 Phazon Vortex. A modified Gattling Vortex. Slower traveling, but does damage over-time if it hits at all!
				-- 7 Hyper Beam. Only available below 6 health, otherwise becomes Phazon Missile. Slow tracking, but EXTREMELY dangerous!
				-- 8/9 Dimensional Shift. Phases itself above you and dashes backwards. Nothin' personal, huntress.
				-- Clones - Appear at 8 and 3 remaining health respectively. Real Dark Samus has more afterimages and uses other attacks.
				-- As a Metroid, it's DNA rejects the Ice Beam. Fortunately you didn't have the Spazer Beam when it copied Samus.
			
				if DIFFICULTY == 2
					s.pzbossrng = P_RandomRange(1,9)
				else
					s.pzbossrng = P_RandomRange(1,10) --Let's decrease the odds of Dark Samus becoming a one-note clown spamming the same attack
				end
				if s.lastpzbossrng and ((s.pzbossrng == s.lastpzbossrng) or (s.pzbossrng < 4 and s.lastpzbossrng < 4))
					if (s.pzbossrng <= 3) --Don't spam Wave Homers, we don't need this to become Touhou.
						s.pzbossrng = P_RandomRange(4,8)
					elseif (s.pzbossrng == 4) -- Never spam phazon dives! That'd be both obnoxious and exploitable.
						if P_RandomRange(0,1)
							s.pzbossrng = $+1
						else
							s.pzbossrng = $-1
						end
					elseif (s.pzbossrng == 7) and not (s.health > 8) and DIFFICULTY != 0
						s.pzbossrng = 5 --Too soon to bring out the Hyper Beam, use the Phazon Missile instead!
					else
						s.pzbossrng = P_RandomRange(1,9) --Reroll! If you STILL get the same one, fine....
					end
				end
				s.lastpzbossrng = s.pzbossrng
			end
			
			if s.pzbossrng <= 3 or s.pzclone --Spawn 3 wave homers, which then target targets which chase your target.
				A_FaceTarget(s)
				S_StartSound(s, sfx_wvchsh)
				if not s.pzclone --God, please don't cause seizures.
					S_StartSound(s, sfx_wvcm)
					S_StartSound(s, sfx_wvcm2)			
					for z in players.iterate
						if z.mo
							if (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 3000<<16)
								A_samquake(z.mo, 50<<16, 1, 12)
								P_SamFP(z, PAL_MIXUP, 4)
							end
						end
					end	
				end
				for d = -1,1
					if d == 0 or s.pzclone
						s.wavehomer = P_SpawnMobj(s.x, s.y, s.z+280<<16, MT_PZWAVEHOMER)
					else					
						s.wavehomer = P_SpawnMobj(
						s.x+FixedMul((290<<16), cos(s.angle+((ANG1*80)*d))),
						s.y+FixedMul((290<<16), sin(s.angle+((ANG1*80)*d))),	
						s.z+180<<16, MT_PZWAVEHOMER)
					end
					s.pzreticule = P_SpawnMobj(
					t.x+FixedMul((350<<16), cos(t.angle+(ANGLE_90*d))),
					t.y+FixedMul((350<<16), sin(t.angle+(ANGLE_90*d))),	
					t.z+t.height, MT_PZTARGET)
					
					if s.wavehomer and s.wavehomer.valid
						s.wavehomer.target = s
						s.wavehomer.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
						s.wavehomer.flags2 = $|MF2_SUPERFIRE
						if s.pzreticule and s.pzreticule.valid
							s.pzreticule.target = t
							s.pzreticule.wavehomertarget = true 
							s.pzreticule.angside = d
							s.wavehomer.pztarget = s.pzreticule
						elseif t.valid
							s.wavehomer.pztarget = t
						end
						s.pzreticule = nil
					end
					if s.pzclone --Only spawn 1 Wave Homer if you are a clone.
						break
					end
				end
			
				if DIFFICULTY == 2 --Fusion Mode.
					s.actiontimer = P_RandomRange(8, 40)
				elseif DIFFICULTY != 0 --normal mode
					s.actiontimer = P_RandomRange(40, 89)
				else --casual
					s.actiontimer = P_RandomRange(65, 145)
				end					
			elseif s.pzbossrng == 4 -- Use the Phazon Dive!!
				if DIFFICULTY == 2 --Fusion Mode.
					s.actiontimer = P_RandomRange(100, 100)
				elseif DIFFICULTY != 0 --normal mode
					s.actiontimer = P_RandomRange(100, 100)
				else --casual
					s.actiontimer = P_RandomRange(100, 145)
				end
				s.phazondive = 100
				S_StartSound(s, sfx_sprnp)
				S_StartSound(s, sfx_mtrdol)
				S_StartSound(nil, sfx_satkc)
				s.pzbarrier = P_SpawnMobj(s.x, s.y, s.z, MT_PZBARRIER)
				if s.pzbarrier and s.pzbarrier.valid
					local b = s.pzbarrier
					b.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
					b.target = s
					b.darkpz = s
					b.borigin = s --cling to origin
					b.scale = FRACUNIT*10
				end	
				s.pzreticule4 = P_SpawnMobj(t.x, t.y, t.z+t.height*2, MT_PZTARGET)					
				if s.pzreticule4 and s.pzreticule4.valid
					s.pzreticule4.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
					s.pzreticule4.target = t
					s.pzreticule4.scale = FRACUNIT*2 --Bigger scale = Faster chasing speed
					s.pzreticule4.fuse = 101
				end						
			
			elseif (s.pzbossrng == 5 or s.pzbossrng == 7) --Fire a Phazon Super Missile!
				if DIFFICULTY == 2 --Fusion Mode.
					s.actiontimer = P_RandomRange(66, 80)
				elseif DIFFICULTY != 0 --normal mode
					s.actiontimer = P_RandomRange(70, 95)
				else --casual
					s.actiontimer = P_RandomRange(100, 140)
				end
				S_StartSound(nil, sfx_rail1)
				S_StartSound(nil, sfx_iceb)
				S_StartSound(nil, sfx_s3k47)
				A_FaceTarget(s)
					if s.pzbossrng == 7 // --Shoot the almighty Hyper Beam!
					and not (s.health > 8) and DIFFICULTY != 0					
						s.slideback = 50
						S_StartSound(nil, sfx_cmcha)
						s.hyperfire = true						
						for z in players.iterate
							if z.mo
								if (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 2500<<16)
									A_samquake(z.mo, 70<<16, 5, 5)
									z.mo.omegarushpanic = 55
								end
							end
						end
					else
						S_StartSound(s, sfx_mread) S_StartSound(s, sfx_mread)
						s.slideback = 30
					end
					s.pzreticule2 = P_SpawnMobj(t.x, t.y, t.z+t.height*2, MT_PZTARGET)					
					if s.pzreticule2 and s.pzreticule2.valid
						s.pzreticule2.target = t
						s.pzreticule2.fuse = 51
					end
					s.plexpand = P_SpawnMobj(s.x, s.y, s.z+s.height/4, MT_PBEXPANDW)
					if s.plexpand and s.plexpand.valid
						s.plexpand.scale = $*8
						s.plexpand.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
						s.plexpand.scalespeed = $*P_RandomRange(30,50)
						s.plexpand.destscale = $*60
						s.plexpand.tics = $*5/3
						s.plexpand.color = SKINCOLOR_COBALT
						s.plexpand.colorized = true
					end						
			elseif s.pzbossrng == 6 --Barrage Samus with a Phazon Vortex!
			
				if DIFFICULTY == 2 --Fusion Mode.
					s.actiontimer = P_RandomRange(100, 102)
				elseif DIFFICULTY != 0 --normal mode
					s.actiontimer = P_RandomRange(110, 150)
				else --casual
					s.actiontimer = P_RandomRange(135, 200)
				end	
			
				S_StartSound(nil, sfx_s3k82)
				S_StartSound(nil, sfx_s3kb6)
				s.phazongattling = 99
				A_FaceTarget(s)
				s.pzreticule3 = P_SpawnMobj(t.x, t.y, t.z+t.height*2, MT_PZTARGET)					
					if s.pzreticule3 and s.pzreticule3.valid
					s.pzreticule3.target = t
					s.pzreticule3.scale = FRACUNIT*2 --Bigger scale = Faster chasing speed
					s.pzreticule3.fuse = 101
				end
				s.plexpand = P_SpawnMobj(s.x, s.y, s.z, MT_PBEXPAND)
				if s.plexpand and s.plexpand.valid
					s.plexpand.color = SKINCOLOR_SUPERGOLD3
					s.plexpand.scale = $*3
					s.plexpand.scalespeed = $*4
					s.plexpand.destscale = $*26
				end
			elseif s.pzbossrng == 10 --Phazon Barrier! Mainly to make the fight more slow-paced in Zero and Hyper mode.
				s.pzbarrier = P_SpawnMobj(s.x, s.y, s.z, MT_PZBARRIER)
				if s.pzbarrier and s.pzbarrier.valid
					local b = s.pzbarrier
					b.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
					b.target = s
					b.darkpz = s
					b.borigin = s --cling to origin
					b.scale = FRACUNIT*10
				end	
				S_StartSound(nil, sfx_s3k82)
				S_StartSound(nil, sfx_s3kb6)
				S_StartSound(s, sfx_mtrdos)
				s.pzreflecttime = 75
				s.lastpzbossrng = 10
				
				if DIFFICULTY != 0 --normal mode
					s.actiontimer = 100
				else --casual
					s.actiontimer = 120
				end				
				
			elseif s.pzbossrng >= 8 --Teleport, Mario!
				s.lastpzbossrng = 6 --Never use a Phazon Vortex after this!
				if DIFFICULTY == 2 --Fusion Mode.
					s.actiontimer = P_RandomRange(15, 30)
				elseif DIFFICULTY != 0 --normal mode
					s.actiontimer = P_RandomRange(30, 60)
				else --casual
					s.actiontimer = P_RandomRange(70, 100)
				end
				s.frame = A|FF_FULLBRIGHT
				s.ghs = P_SpawnGhostMobj(s)
				s.ghs.scale = $*2
				s.ghs.destscale = s.ghs.scalespeed+1
				s.ghs.tics = 16
				s.ghs.colorized = true
				s.ghs.color = SKINCOLOR_LAVENDER
				S_StartSound(nil, sfx_pztele)
				for d = 1,12
					s.ghs = P_SpawnMobj(s.x+P_RandomRange(200,200)<<16, s.y+P_RandomRange(200,200)<<16, s.z+P_RandomRange(1,80)<<16, MT_THOK)
					s.ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
					s.ghs.tics = 24
					s.ghs.momx = P_RandomRange(-30,30)<<16
					s.ghs.momy = P_RandomRange(-30,30)<<16
					s.ghs.momz = P_RandomRange(-10,10)<<16						
					s.ghs.sprite = SPR_MPR1
					if P_RandomRange(0,1)
						s.ghs.frame = Q|FF_FULLBRIGHT|FF_TRANS40
					else
						s.ghs.frame = P|FF_FULLBRIGHT|FF_TRANS40					
					end
				end
				
				if t.sam_automob and t.sam_automob.valid and t.sam_automob == s
					t.sam_faillock = true --release lock on
					t.sam_automob = nil
				end
								
				s.teleportdash = 12
				s.teleportdashangle = t.angle
				P_MoveOrigin(s, t.x, t.y, t.z+t.momz+200<<16)
				if not (P_TryMove(s, s.x, s.y, true))
					for d = 1,18
						P_TryMove(s, s.x+FixedMul(-70<<16, cos(ANG20*d)), s.y+FixedMul(-70<<16, sin (ANG20*d)), true)
					end
				end
			end
		else
			if not ((s.state == S_PZ_SHOOT)) --Basic floating around. Shoot me, Samus-chan!
				if not s.floattime or not s.floatdirect or not s.floatdirectf
					
					s.floatdirect = P_RandomRange(0,1) and 1 or -1 --Float right or left?
					s.floatdirectf = P_RandomRange(0,2) and 1 or -1 --Favor approaching the player
					s.momx = 0 s.momy = 0 s.rollangle = 0
					if s.lastfloatdirect and (s.floatdirect == s.lastfloatdirect)
						s.floattime = P_RandomRange(8, 20)
						s.floatspeed = $+2
					else
						s.floatspeed = 1 --Transition your speed a bit more slowly!
						s.floattime = P_RandomRange(18, 30)
						s.floattransition = 5
					end
					s.lastfloatdirect = s.floatdirect
				end
				s.state = S_PZ_FLOAT
				A_FaceTarget(s) -- Always face target or this won't work right.
				if (leveltime % 2 == 0) and not s.pzclone --Spawn Phazon and fancy ghost effects, pls
					LeafSpawn(s, nil, true, 90)
					DoPZGhost(s)
				elseif s.pzclone and (leveltime % 6 == 0)
					DoPZGhost(s, SKINCOLOR_SKY)
				end
				if s.floattransition
					s.frame = A|FF_FULLBRIGHT
				elseif (s.floatdirect == -1)
					s.frame = B|FF_FULLBRIGHT
				else
					s.frame = C|FF_FULLBRIGHT
				end		
			
				--Sideways and front movement.
				if not (s.floatspeed > 17)
					s.floatspeed = $+1			
					if s.waverstunned
						s.floatspeed = 4 --Wave Beam slows PZ down
					end
				end
				if s.floattime
					s.floattime = $-1
				end
				P_InstaThrust(s, s.angle+(ANGLE_90*s.floatdirect), s.floatspeed<<16)
				if s.pzclone and s.floatdirectf == 1
					P_Thrust(s, s.angle, FRACUNIT*P_RandomRange(2,5)) --Close in slower, will you?
				elseif s.floatdirectf == 1 and s.target and s.target.valid
				and (FixedHypot(s.x-s.target.x, s.y-s.target.y) > 1200<<16)
					P_Thrust(s, s.angle, FRACUNIT*P_RandomRange(20,25)) --Let's close the distance a bit.
				else
					P_Thrust(s, s.angle, FRACUNIT*(P_RandomRange(7,10)*s.floatdirectf)) --InstaThrust MUST be before this!
				end
			
				--Adjust height according to target
				if (s.z < t.z+18<<16) or (s.z < s.floorz+5<<16)
					s.momz = $+7355
				elseif (s.z > t.z+13<<16)
					if s.momz > 0
						s.momz = 0
					else
						s.momz = $-10355
					end
				else
					s.momz = 0
				end
			elseif s.pzambush --Ambush a player with the Hyper Beam! This is instant death at 0%, do NOT get hit!
				if s.pzambush and s.target and s.target.valid
					s.pzambush = $-1
					s.state = S_PZ_HIDE
				end
				if not s.pzambush --Okay, let's fight, boys!
					s.state = S_PZ_LOOK
				end
			else
				if (s.tics < 9)
					s.frame = A|FF_FULLBRIGHT
				end
			end			
		end			
	end
	if not (s and s.valid) --Superlazy check....
		return --
	end
	//Perform these actions regardless of an acquired target!
//	s.color = SKINCOLOR_JET
//	s.colorized = true
	if s.blockframes
		s.blockframes = $-1
	end
	if s.invincible
		s.invincible = $-1
	end
	if s.health
		s.pzlasthealth = s.health
	end
	if s.negatecrusher
		s.negatecrusher = $-1
		if s.target and s.target.valid
			P_MoveOrigin(s, s.target.x, s.target.y, s.target.z+230<<16)
		end
	end
	if s.pzreflector -- Spam barrier function.
		s.pzreflector = $-1
		if (s.pzreflector > 39)
			DoPZBarrier(s, P_RandomRange(SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERSILVER5))
		elseif P_RandomRange(0,1)
			DoPZBarrier(s, P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY5))
		else
			DoPZBarrier(s, SKINCOLOR_COBALT)
		end
	end
	if s.pzreflector2 -- Spam secondary barrier function. This one only happens after the Phazon Dive.
		s.pzreflector2 = $-1
		DoPZBarrier(s, nil, nil, true, s.pzreflector2*5)
	end
	if not s.pzdeathanim
		if (s.flags2 & MF2_FRET) --Never do this. Only villains do that.
			s.flags2 = $ & ~MF2_FRET
			s.flags2 = MF_SHOOTABLE|MF_BOSS|MF_NOGRAVITY
		end
		if s.teleportdash --Lock angle and dash back!
			s.teleportdash = $-1
			s.frame = A|FF_FULLBRIGHT
			if s.teleportdashangle
				s.angle = s.teleportdashangle 
			end
			P_InstaThrust(s, s.angle, -35<<16)
			DoPZGhost(s, P_RandomRange(SKINCOLOR_SUPERPURPLE1, SKINCOLOR_SUPERPURPLE5))
		end			
		if s.pzknockback and not s.pzdeathanim
			s.pzknockback = $-1
			if s.pzknockbackforce != nil and s.pzknockbackangle != nil
			P_InstaThrust(s, s.pzknockbackangle, -s.pzknockbackforce*2<<16)
				s.spinrundust = P_SpawnMobj(s.x+FixedMul(24<<16, cos(s.angle+ANGLE_90)),s.y+FixedMul(24<<16, sin(s.angle+ANGLE_90)), s.z, MT_SPINDUST)
				s.spinrundust.scale = FRACUNIT*3
				s.spinrundust.frame = P_RandomRange(0,2)
				s.spinrundust = P_SpawnMobj(s.x+FixedMul(24<<16, cos(s.angle-ANGLE_90)),s.y+FixedMul(24<<16, sin(s.angle-ANGLE_90)), s.z, MT_SPINDUST)
				s.spinrundust.frame = P_RandomRange(0,2)
				s.spinrundust.scale = FRACUNIT*3
				S_StartSound(s, sfx_s3k79)
			end
			if s.state == S_PZ_FLOAT
				s.frame = J
			end
		end
		if s.pzclone
			s.frame = $|FF_TRANS40|FF_FULLBRIGHT
			if s.justcloned
				s.justcloned = $-1
				if s.originalpz and s.originalpz.valid
					P_InstaThrust(s, R_PointToAngle2(s.x, s.y, s.originalpz.x, s.originalpz.y), -30<<16)
				end
			end
		end
	end
end, MT_PZBOSS)

addHook("MobjMoveBlocked", function(s, i)
	if s and s.valid 
		s.blockframes = s.blockframes and $+2 or 2
		if (s.blockframes > 4) and s.floatdirectf
		s.floatdirectf = $*-1 --Don't get stuck on walls.
			if s.floatdirect and P_RandomRange(0,1)
			s.floatdirect = $*-1
			end
		s.momz = 5<<16*P_RandomRange(-1,1)
			if (s.blockframes > 35) -- Try teleporting unstuck?
			s.blockframes = 0
			s.pzbossrng = 8
			s.pzbossrngset = true
			end		
		end
	end
end, MT_PZBOSS)

addHook("MobjThinker", function(s)
	if s and s.valid 
	s.colorized = true
		if (s.scale <= FRACUNIT/2)
				s.destscale = FRACUNIT*3
				s.scalespeed = 50000		
				S_StartSound(s, sfx_cmol)
		elseif (s.scale >= FRACUNIT*3) or not s.scalestart
				s.scalestart = true
				s.scalespeed = 10000
				s.destscale = 10001	
		end
		if leveltime % 3 == 0
			if s.color == SKINCOLOR_COBALT		
			s.color = SKINCOLOR_COBALT
			else
			s.color = SKINCOLOR_SKY
			end
		end
		if ((s.state == S_WVSHOT1) or (s.state == S_WVSHOT2))
			s.frame = $|FF_TRANS30|FF_FULLBRIGHT
			if not s.fuse --Setup.
					s.plexpand = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_PBEXPAND) --Appearance effect.
					if s.plexpand
					s.plexpand.color = SKINCOLOR_SUPERSKY3
					s.plexpand.colorized = true
					s.plexpand.frame = $|FF_TRANS50
					s.plexpand.scale = FRACUNIT*7
					s.plexpand.scalespeed = $*10
					s.plexpand.destscale = $*40
					end	
				s.fuse = 280 --Emergency timer
			end			
			if s.pztarget and s.pztarget.valid
				P_HomingAttack(s, s.pztarget) --Slowly chase your target
				if leveltime % 4 == 0
				LeafSpawn(s, nil, true, 50)
				DoPZGhost(s, P_RandomRange(SKINCOLOR_GREY, SKINCOLOR_BLACK))
				end
			end
			if (s.fuse != nil)
				if (s.fuse > 30) and not (s.pztarget and s.pztarget.valid)
					s.fuse = 30 --Target gone, cancel yourself.
				end
				if (s.fuse <= 30) --Okay, vanish.	
					s.flags = $ & ~MF_SHOOTABLE & ~MF_MISSILE			
					if (s.fuse > 15)
					s.frame = $|FF_TRANS50 & ~FF_TRANS30
					else
					s.frame = $|FF_TRANS80 & ~FF_TRANS50 & ~FF_TRANS30
						if (s.fuse == 1) and s.valid
						s.state = S_NULL
						return
						end
					end
				end
			end
		elseif (s.state == S_WVXP1) and not s.saldsalf
			for d = 0,16
			LeafSpawn(s, nil, true, 400) --Lots of Phazon particles
			end
			for z in players.iterate
				if z.mo
					if (FixedHypot(s.x-z.mo.x, s.y-z.mo.y) < 1500<<16)
						A_samquake(z.mo, 70<<16, 1, 14)
						P_Thrust(z.mo, R_PointToAngle(z.mo.x, z.mo.y, s.x, s.y), -16<<16) --Push everyone
						P_SamFP(z, PAL_NUKE, 5)
					end
				end
			end				
		S_StartSound(s, sfx_bkpoof) S_StartSound(s, sfx_smexp) S_StartSound(s, sfx_cmol)
		s.scale = s.scale*3
		s.destscale = $*10
		s.saldsalf = true
		end
	end
end, MT_PZWAVEHOMER)
addHook("MobjLineCollide", function(s, i) --Phase through stuff
	return false
end, MT_PZWAVEHOMER)
addHook("MobjLineCollide", function(s, i) --Difference with NOCLIP is that this'll still collide with objects
	return false
end, MT_PZBARRIER)

addHook("MobjThinker", function(s)
	if s and s.valid
		if s.borigin and s.borigin.valid
		local t = s.borigin
			if (s.borigin.type == MT_PZBOSS) and (s.borigin.phazondive or s.borigin.pzreflecttime)
				P_MoveOrigin(s, t.x, t.y,	t.z+t.height/2)
				if s.valid and s.borigin.pzreflecttime
					s.flags2 = $|MF2_DONTDRAW
				elseif s.valid and (s.borigin.phazondive > 50)
					s.scale = (FRACUNIT*500)/s.borigin.phazondive
					s.colorized = true
						if (leveltime % 5 == 0)
						s.color = P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY5)
						else
						s.color = SKINCOLOR_COBALT
						end
					if (s.borigin.phazondive > 78)						
					s.frame = $|FF_TRANS90 & ~FF_TRANS60 & ~FF_TRANS50 & ~FF_TRANS40 & ~FF_TRANS70
					else
					s.frame = $|FF_TRANS70 & ~FF_TRANS60 & ~FF_TRANS50 & ~FF_TRANS80 & ~FF_TRANS90 & ~FF_TRANS40
					end
				elseif s.valid
					s.scale = FRACUNIT*10
					if (s.borigin.phazondive < 41) 
						if (leveltime % 5 == 0)
						DoPZGhost(s, P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY5))
						else
						DoPZGhost(s, SKINCOLOR_COBALT)
						end
					end
				end
				return
			elseif (s.borigin.type == MT_SAMSUPERMISSILE)
				if s.borigin.health and s.borigin.darkhyper
				and not (s.borigin.flags2 & MF2_DEBRIS)
				and not (s.borigin.state == S_SAMSUPERMISSILEE)
						if (leveltime % 4 == 0)
						DoPZGhost(s, P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY5))
						end
					P_MoveOrigin(s, t.x, t.y,	t.z+t.height/2)
					return
				elseif s and s.valid
				s.state = S_NULL
				return
				end
			elseif s and s.valid
			s.state = S_NULL
			return
			end
		elseif s and s.valid
			s.state = S_NULL
			return
		end
	end
end, MT_PZBARRIER)
addHook("MobjThinker", function(s)
	if s and s.valid
	and s.target and s.target.valid
	local t = s.target		
		if s.wavehomertarget 
			if s.angside
			P_MoveOrigin(s,
			t.x+FixedMul((350<<16), cos(t.angle+(ANGLE_90*s.angside*-1))),
			t.y+FixedMul((350<<16), sin(t.angle+(ANGLE_90*s.angside*-1))),	
			t.z+t.height)
			else
			P_MoveOrigin(s, t.x, t.y,	t.z+t.height)			
			end
		else
			P_HomingAttack(s, t)
		end
	end
end, MT_PZTARGET)

addHook("ShouldDamage", function(s, i, so, dmg, dmgtype) --Negate random crushing, pls....
	if dmgtype
		if (dmgtype == DMG_CRUSHED or dmgtype == DMG_DEATHPIT)
		return false
		end
	end
end, MT_PZBOSS)
addHook("MobjDeath", function(s, i, so, dmgtype) --Negate random crushing, pls....
	if dmgtype
		if (dmgtype == DMG_CRUSHED or dmgtype == DMG_DEATHPIT)
		s.negatecrusher = 2
			if s and s.valid and s.target and s.target.valid
			P_MoveOrigin(s, s.target.x, s.target.y, s.target.z+230<<16)
			s.pzbossrng = 8
			s.actiontimer = 2
			s.pzbossrngset = true
			end
		return true
		end
	end
end, MT_PZBOSS)

local function PZReaction(s, i, so, dmg) --Damage reactions! Not as complex as the Omega's.
	if s.negatecrusher
	s.negatecrusher = 0
	s.flags = MF_NOGRAVITY|MF_SHOOTABLE|MF_BOSS
	s.flags2 = $ & ~MF2_FRET & ~MF2_BOSSDEAD & ~MF2_BOSSFLEE
		if not s.health and s.pzlasthealth
		s.health = s.pzlasthealth
		end
		return true
	end
	if s.health and s.invincible or (s.pzambush and s.pzambush > 50)--Still invincible...
		return true
	end
	if s.pzclone and s.originalpz and (so and so == s.originalpz) --Don't fight amongst yourself, men.
	or so and so.pzclone
		return true
	end
	if i and (i.darkhyper or ((i.flags & MF_MISSILE) and i.target == s or (s.originalpz and (i.target == s.originalpz))) )
		if (i.type == MT_PLSHOT) or (i.target == s) --Don't get mauled by reflected Phazon Vortex shots or your own attacks
		return true
		end
	end
	if (so and so.valid and (so == s)) --Don't hit yourself, stupid.
		return true
	end
--Kay, let's actually do the reaction part now.	
	if (s.health <= 0) or (so and so.player and so.player.hypermysticsonic)
		if s and s.valid
		s.pzdeathanim = 140 --Initiate dramatic death animation. You earned it. Unless you were HMS, you cheating little....
		s.fuse = 141
		s.painfred = 140
		s.momx = 0 s.momy = 0 s.momz = 0
		s.pzreflector = 8
		s.pzreflector2 = 14
		s.state = S_PZ_PAIN
		s.tics = 150
			if not s.pzclone
				for m in mobjs.iterate(mobjs) --Remove excess crap, 'cause you won!
					if m and m.valid
					and ((m.pzclone and m.originalpz and m.originalpz.valid and (m.originalpz == s)) or (m.type == MT_PZWAVEHOMER))
					m.state = S_NULL
					end
				end
			s.z = s.floorz+50<<16
			P_LinedefExecute(11111)
			S_StartSound(nil, sfx_pzdead)
			S_StartSound(s, 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
			end
			return true
		else
			return --...wut?
		end
	else --We're not dying yet!
		if s and s.valid	
			if s.phazondive
				if i and i.player and i.health and (YouAreSamus(i) or i.player.powers[pw_super]) --Your cheap immitation can't defeat the real deal.
					if (i.player.sam_shinesparkfly and i.player.sam_shinesparkfly > 17)
					or (i.player.sam_screwattacking and i.player.sam_screwattacking > 23)
					or i.player.powers[pw_super]
						s.painfred = 55
						s.invincible = 25
						s.phazondive = 0
						i.momx = 0 i.momz = 0 i.momy = 0
						i.player.sam_shinesparkstop = 12
						S_StartSound(s, sfx_pzdead) S_StartSound(s, sfx_pzdead) S_StartSound(s, sfx_pzdead)
						S_StartSound(s, sfx_bkpoof) S_StartSound(nil, sfx_brakrx)
						S_StartSound(i, sfx_brakrx) S_StartSound(s, sfx_brakrx)
						s.pzsuperknockback = 105
						s.blockframes = 0
						s.actiontimer = 105
						s.pzknockbackangle = i.angle+ANGLE_180
						A_samquake(i, 80<<16, 24, 24)
						i.angle = R_PointToAngle2(i.x-i.momx, i.y-i.momy, s.x, s.y)
						return true
					end
				end
				return true --Take no damage otherwise.
			else --Default damage behaviour
				if so and so.player and so.player.powers[pw_super] --Supers do extra damage!
				dmg = $+2 
				end			
				if i and (i.type == MT_ICCHARGECOMBO)
					s.invincible = 101
					s.painfred = 101
					i.addsaldsalf = true
				elseif i and i.gattlingvortex
					s.invincible = 55
					s.painfred = 55		
				elseif i and i.valid and (i.type == MT_ICCHARGESHOT)
					s.invincible = 70
					s.painfred = 65
				elseif dmg != nil
				
					s.invincible = dmg*30
					s.painfred = dmg*30
					s.pzknockback = dmg*8 --How many tics you're send flying for.
					s.pzknockbackforce = dmg*16
					if (dmg >= 2) or s.pzclone
						S_StartSound(s, sfx_mtrdop) S_StartSound(s, sfx_mtrdb)
						S_StopSoundByID(s, sfx_pzouch)
						S_StartSound(nil, sfx_pzouch) S_StartSound(s, sfx_pzouch)
					end
					if i and i.valid
						s.pzknockbackangle = R_PointToAngle2(s.x, s.y, i.x, i.y)
						if (i.type == MT_SAMPOWERBOMB)
							s.invincible = 101
							s.painfred = 101
						end
					end
					
				else -- No damage info, so...uhh, default go?
				
				s.painfred = 24
				s.invincible = 12
				end
			end	

			
			if i and i.target and i.target.player --Switch target to whoever's attacking you.
				s.target = i
			end
			if not s.pzclone
				if (s.health < 11) and not s.darkclonephase1
				or (s.health < 6) and not s.darkclonephase2
					s.darkclonephase1 = true
					S_StartSound(nil, sfx_pztele)
					DoPZBarrier(s, SKINCOLOR_COBALT)
					DoPZBarrier(s, nil, nil, true, 70)
					for d = 1,3
						s.pzghs = P_SpawnMobj(s.x+P_RandomRange(-50,50), s.y+P_RandomRange(-50,50), s.z+100*d<<16, MT_PZBOSS)
						if s.pzghs and s.pzghs.valid
							s.pzghs.flags = $ & ~MF_SHOOTABLE
							s.pzghs.pzclone = true
							s.pzghs.originalpz = s --Remember the OG.
							s.pzghs.actiontimer = P_RandomRange(90,230)
							s.pzghs.justcloned = 19
							s.pzghs.target = s.target
							s.pzghs.state = S_PZ_FLOAT
							s.pzghs.invincible = 50
							s.pzghs.painfred = s.painfred
							if not (P_TryMove(s.pzghs, s.pzghs.x, s.pzghs.y, true))
								for d = 1,18
									P_TryMove(s.pzghs, s.pzghs.x+FixedMul(-70<<16, cos(ANG20*d)), s.pzghs.y+FixedMul(-70<<16, sin (ANG20*d)), true)
								end
							end
						end
					end
					for z in players.iterate
						P_SamFP(z, PAL_RECYCLE, 14)
					end
					if (s.health < 5) or DIFFICULTY != 0
						s.darkclonephase2 = true --One more time!!
					end
				end
			end
			s.rollangle = 0	--Just incase, reset rollangle.
			s.samusHP = 8 s.samusHPmax = 8 --Reset your SamusHP value to 8!
			s.flags = $|MF_BOSS|MF_SHOOTABLE|MF_NOGRAVITY --Just incase....
			s.flags2 = $ & ~MF2_FRET
		end
		return
	end
end
addHook("MobjDamage", PZReaction, MT_PZBOSS)
addHook("MobjDeath", PZReaction, MT_PZBOSS)

local function PZCollide(s, m)
	if not (s and s.valid)
	or not (m and m.valid)
	return
	end
	if m.player and not s.phazondive
		if YouAreSamus(m) //Only melee players during the Phazon Dive.
			return false
		elseif not s.invincible
			if (m.z > s.z+s.height+20<<16)
			or (s.z > m.z+m.height+20<<16)
			return 
			end
			if (m.player.pflags & PF_JUMPED) or (m.player.pflags & PF_SPINNING) or (m.player.pflags & PF_THOKKED)
			m.momx = $*-1 m.momy = $*-1 m.momz = $*-1
			S_StartSound(m, sfx_dmpain)
			P_DamageMobj(s, m, m)
			return false
			end
		end
	end
	if (s.phazondive or s.pzreflecttime) and (m and (m.flags & MF_MISSILE) and (m.target != s))
	SamusBeamReflect(m, s)
	return false
	end
	if (m.darkhyper and m.target and m.target == s)
	or (m.type == MT_PZBARRIER or m.type == PZ_TARGET or m.type == MT_PZBOSS)
	return false
	end
	if s.pzreflecttime and not (m and m.player)
	return false
	end
end
addHook("MobjCollide", PZCollide, MT_PZBOSS)
addHook("MobjMoveCollide", PZCollide, MT_PZBOSS)

local function SamusIsWin(line, s) --Mission Complete
	for z in players.iterate
		if z.mo 
		SamusMission(z.mo, "\x82     THE OPERATION WAS", "\x82 COMPLETED SUCCESSFULLY", nil, 3, 0, false)
		end
	end
end
addHook("LinedefExecute", SamusIsWin, "SAMISWIN")

addHook("MobjThinker", function(s)
	if s.angle == ANGLE_90 and (s.state == S_PZ_REMAINS1)
	s.state = S_PZ_REMAINS3
	elseif s.tics == 199 and (s.state == S_PZ_REMAINS1)
	s.tics = $-P_RandomRange(0,191)
	end
end, MT_DARKPZREMAINS)