--==============BEAMS, BOMBS, PROJECTILES==================
--If it destroys enemies or monitors, it's probably here!
--=========================================================

local function shatterfof(s,sectorsam)
	for fof in sectorsam.ffloors()
		if (fof.flags & FF_EXISTS) and (((fof.flags & FF_BUSTUP) or (fof.flags & FF_SPINBUST)) and not ((fof.flags & FF_STRONGBUST) and not s.pworsm))
		and not (s.z-150*FRACUNIT >= fof.topheight)
		and not (s.z+150*FRACUNIT+s.height < fof.bottomheight)
		EV_CrumbleChain(sectorsam, fof)
		end
	end
end
local function MonitorBreaker(s, t, scale)
	if s.valid and t and t.valid
		s.ghs = P_SpawnMobj(s.x, s.y, s.z, MT_SAMMONBREAKER)
		if s.ghs and s.ghs.valid
		s.ghs.target = t
			if scale
			s.ghs.scale = scale
			end
			s.ghs.momx = 1 s.ghs.momy = 1 s.ghs.momz = -1
		end
	end
end
--For the Power Bomb.
local function WindStorm(p)
	if leveltime % 2 == 0
	return
	end
	for d = 1,929,57
		local rng = P_RandomRange(-30,30)	
			local ghs = P_SpawnMobj(
			p.x+FixedMul(((10+d)*FRACUNIT),cos(d*(ANG1+9909))),
			p.y+FixedMul(((10+d)*FRACUNIT),sin(d*(ANG1+9909))),
			p.z+(10*FRACUNIT)+(rng*FRACUNIT*2), MT_SAMWINDLINE)
			P_SetObjectMomZ(ghs, (rng+30)*30000)
			P_InstaThrust(ghs, R_PointToAngle2(p.x, p.y, ghs.x, ghs.y)+rng, 74*FRACUNIT)
			ghs.destscale = $*99
			ghs.spriteyscale = $/2
			ghs.tics = $*2
			ghs.renderflags = $|RF_PAPERSPRITE|RF_NOCOLORMAPS|RF_FULLBRIGHT
			ghs.angle = R_PointToAngle2(ghs.x, ghs.y, ghs.x+ghs.momx, ghs.y+ghs.momy)
			if (p.eflags & MFE_UNDERWATER)
				ghs.fuse = 7
				if leveltime % 2 == 0
					ghs.state = S_MEDIUMBUBBLE
				else
					ghs.state = S_SMALLBUBBLE
				end
			end	
			if d % 2 == 0
				ghs.flags2 = $|MF2_SHADOW
				ghs.scale = $*2
				ghs.blendmode = AST_ADD
				ghs.spritexscale = $*2
			else
				ghs.spritexscale = $*3
			end
	end
end

local FlashMobjC={SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERORANGE5,SKINCOLOR_RED, SKINCOLOR_WHITE, SKINCOLOR_SUPERGOLD3}
addHook("MobjThinker", function(s)
	if s.health and s.samusshot
		local ghs = P_SpawnGhostMobj(s)
		ghs.scalespeed = $*2
		ghs.destscale = ghs.scalespeed+1
		ghs.blendmode = AST_ADD
	end
	s.samusshot = true
	if (s.state >= S_PBXP1) and not s.saldsalf
	--	SamusShotImpact(s)
		local ghs = P_SpawnMobjFromMobj(s,0,0,0, MT_THOK)
		ghs.flags2 = $|MF2_DONTDRAW ghs.tics = 55
		S_StartSound(ghs, sfx_pbxp)	
		ghs = nil
		
		ghs = SamusBulletHole(s, s.scale/10, SKINCOLOR_SUPERGOLD4)	
		if ghs and ghs.valid
			ghs.flags2 = $|MF2_SHADOW
			ghs.fuse = 6
			ghs.scalespeed = $/2
			ghs.destscale = $*99
		end
		s.saldsalf = true
	end
end, MT_PBSHOT)

addHook("MobjThinker", function(s)
	if s.saldsalf
	or not s.target
	return
	end
	s.samusshot = true
	if ((s.state == S_PBCHARGESHOT1) or (s.state == S_PBCHARGESHOT2))
		P_SpawnMobj(s.x+FixedMul(-15*FRACUNIT, cos(s.angle)), s.y+FixedMul(-15*FRACUNIT, sin (s.angle)), s.z, MT_PBCHARGESHOTT)
	elseif (s.state == S_PBCHARGESHOTE)
		if s.wallclipped and s.target and not s.saldsalf
			local t = s.target
			P_Thrust(t, t.angle, -6*FRACUNIT)
			P_MoveOrigin(s, t.x, t.y, t.z+(t.height/2))
		end		
		A_SAMUSEXPLOSIONS(s, 7, MT_SAMEXPLODE2, false, 1000, SKINCOLOR_ORANGE)
		A_SAMUSEXPLOSIONS(s, 7, MT_SAMMISSILESMOKE, 25*FRACUNIT, 430000)
		A_SAMUSEXPLOSIONS(s, 18, MT_SAMMISSILESMOKE, false, 80000)	
			for z in players.iterate
				if z.mo
					if (FixedHypot(FixedHypot(s.x-z.mo.x, s.y-z.mo.y), s.z-z.mo.z) < 620*FRACUNIT)
					A_samquake(z.mo, 11*FRACUNIT, 7, 1)
					end
				end
			end				
			if G_GametypeHasSpectators()
			A_Samuskillstuff(s, 275*FRACUNIT, 155*FRACUNIT, s.target, true)
			else
			A_Samuskillstuff(s, 345*FRACUNIT, 315*FRACUNIT, s.target, true)
			end
			SamFaceReflect(s, 250*FRACUNIT)
	s.saldsalf = true
	S_StartSound(s, sfx_pbchae)
	end
end, MT_PBCHARGESHOT)

addHook("MobjThinker", function(s)
	if not s.saldsalf and (s.state == S_PBCHARGESHOTT2)
		s.scale = s.scale*6
		s.saldsalf = true
	elseif not s.saldsalf2 and (s.state == S_PBCHARGESHOTT3)
		s.scale = s.scale/2
		s.saldsalf2 = true
	end
end, MT_PBCHARGESHOTT)

addHook("MobjThinker", function(s)
	if s.target
	local t = s.target
		if s.ret2sign and t and t.valid and t.player
		local p = t.player
		local zet = 8
			if (p.speed > 8*FRACUNIT)
			zet = 5
		end
			
		P_MoveOrigin(s, t.x+FixedMul(t.radius*5/2, cos(t.angle-(ANG2*2))), t.y+FixedMul(t.radius*5/2, sin(t.angle-(ANG2*2))), t.z+(t.height*4/zet))
		s.z = $+(FixedMul(FixedMul(50*FRACUNIT, t.scale), sin(p.aiming)))
			if s.dontstateme
			return
			end
			if (s.tics > 10)
			s.frame = Z|FF_FULLBRIGHT|TR_TRANS20
			elseif (s.tics < 11) and (s.tics >= 5)
			s.frame = Z|FF_FULLBRIGHT|TR_TRANS50
			elseif (s.tics < 5)
			s.frame = Z|FF_FULLBRIGHT|TR_TRANS70
			end
		elseif s.ret2bomb and t and t.valid
			P_MoveOrigin(s, t.x, t.y, t.z)
			if s.dontstateme
			return
			end			
			if (s.tics > 10)
			s.frame = Z|FF_FULLBRIGHT|TR_TRANS20
			elseif (s.tics < 11) and (s.tics >= 5)
			s.frame = Z|FF_FULLBRIGHT|TR_TRANS50
			s.color = SKINCOLOR_VARIASUIT
			elseif (s.tics < 5)
			s.frame = Z|FF_FULLBRIGHT|TR_TRANS70
			s.color = SKINCOLOR_RED
			end
		elseif s.ret2spring
			if (s.tics > 10)
			s.frame = L|TR_TRANS40
			elseif (s.tics >= 8)
			s.frame = M|TR_TRANS50
			elseif (s.tics >= 6)
			s.frame = N|TR_TRANS60
			elseif (s.tics >= 4)
			s.frame = O|TR_TRANS70
			elseif (s.tics >= 2)
			s.frame = P|TR_TRANS80
			else
			s.frame = Q|TR_TRANS90
			end
		else
		s.momz = t.momz+(2*FRACUNIT*(P_MobjFlip(s)) )
		end
	end
end, MT_SAMCHARGEGFX)

addHook("MobjThinker", function(s)
	if not s.saldsalf
	s.color = SKINCOLOR_GREEN
	s.samusshot = true
		if ((s.state == S_SPSHOT1) or (s.state == S_SPSHOT2))
			if not (s.wave4 or s.wave5) or (s.ghoster and (s.wave4 or s.wave5)) or twodlevel or (s.target and s.target.valid and (s.target.flags2 & MF2_TWOD))
				local ghs = P_SpawnGhostMobj(s)
				ghs.scalespeed = $*2
				ghs.destscale = ghs.scalespeed+1
				ghs.blendmode = AST_ADD
			elseif (s.wave4 or s.wave5)
				s.ghoster = true
			end
			if s.wave2
				A_SAMPARTICLE(s, MT_MPR4, 2, 10, -4, 7, s.color, P_RandomRange(25355, 48355), true)
			end
		elseif (s.state == S_SPXP1)
			MonitorBreaker(s, s.target, s.scale*2)
			s.saldsalf = true
		end
	end
end, MT_SPSHOT)

addHook("MobjThinker", function(s)
		if not s.brakandco
		s.color = SKINCOLOR_GREEN
		end
	s.samusshot = true
		if s.weakertic == nil
		s.weakertic = 0
		s.spazerdist = 0
		else
			s.weakertic = $+1
			if (s.weakertic >= 4) and not (s.spazerdist and (s.spazerdist >= 25))
			s.weakertic = 0
			s.spazerdist = $+1
			end
		end
		if s.meleeshot
		s.meleeshot = $-1
		elseif s.meleeshot == nil and not s.brakandco
		s.meleeshot = 2
		end
		if ((s.state == S_SPSHOT1) or (s.state == S_SPSHOT2))
		local ghs = P_SpawnGhostMobj(s)	
		ghs.destscale = ghs.scalespeed+1
		ghs.blendmode = AST_ADD
		   if s.magicaltic
			if s.wave2
			A_SAMPARTICLE(s, MT_MPR4, 5, 14, -4, 8, s.color, P_RandomRange(45355, 68355))	
				if not s.saldsalf and not s.brakandco

				local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_SPCHARGESHOT)
				ghs.target = s.target
				ghs.meleeshot = 1
				ghs.blendmode = AST_ADD
				ghs.eflags = s.eflags ghs.flags2 = s.flags2
				ghs.scale = s.scale ghs.angle = s.angle+(ANG2*1)
				ghs.momz = s.momz
				P_Thrust(ghs, s.angle+(ANG2*1), FixedMul(ghs.info.speed, s.target.scale))

				ghs = P_SpawnMobj(s.x, s.y, s.z, MT_SPCHARGESHOT)
				ghs.target = s.target
				ghs.meleeshot = 1
				ghs.blendmode = AST_ADD
				ghs.eflags = s.eflags ghs.flags2 = s.flags2
				ghs.scale = s.scale ghs.angle = s.angle+(ANG2*3)
				ghs.momz = s.momz
				P_Thrust(ghs, s.angle+(ANG2*3), FixedMul(ghs.info.speed, s.target.scale))

				ghs = P_SpawnMobj(s.x, s.y, s.z, MT_SPCHARGESHOT)
				ghs.target = s.target
				ghs.meleeshot = 1
				ghs.blendmode = AST_ADD
				ghs.eflags = s.eflags ghs.flags2 = s.flags2
				ghs.scale = s.scale ghs.angle = s.angle+(ANG2*5)
				ghs.momz = s.momz
				P_Thrust(ghs, s.angle+(ANG2*5), FixedMul(ghs.info.speed, s.target.scale))

				ghs = P_SpawnMobj(s.x, s.y, s.z, MT_SPCHARGESHOT)
				ghs.target = s.target
				ghs.meleeshot = 1
				ghs.blendmode = AST_ADD
				ghs.eflags = s.eflags ghs.flags2 = s.flags2
				ghs.scale = s.scale ghs.angle = s.angle-(ANG2*3)
				ghs.momz = s.momz
				P_Thrust(ghs, s.angle-(ANG2*3), FixedMul(ghs.info.speed, s.target.scale))

				ghs = P_SpawnMobj(s.x, s.y, s.z, MT_SPCHARGESHOT)
				ghs.target = s.target
				ghs.meleeshot = 1
				ghs.blendmode = AST_ADD
				ghs.eflags = s.eflags ghs.flags2 = s.flags2
				ghs.scale = s.scale ghs.angle = s.angle-(ANG2*5)
				ghs.momz = s.momz
				P_Thrust(ghs, s.angle-(ANG2*5), FixedMul(ghs.info.speed, s.target.scale))

				ghs = P_SpawnMobj(s.x, s.y, s.z, MT_SPCHARGESHOT)
				ghs.target = s.target
				ghs.meleeshot = 1
				ghs.blendmode = AST_ADD
				ghs.eflags = s.eflags ghs.flags2 = s.flags2
				ghs.scale = s.scale ghs.angle = s.angle-(ANG2*7)
				ghs.momz = s.momz
				P_Thrust(ghs, s.angle-(ANG2*7), FixedMul(ghs.info.speed, s.target.scale))

				s.saldsalf = true
				end
			end
		   else
		   s.magicaltic = true
		   s.destscale = $*3
		   s.plshottimer = 45
		   s.blendmode = AST_ADD
		   end
	   	   if s.plshottimer
	   	   s.plshottimer = $-1
	   	   	   if s.plshottimer == 25
		  	   s.destscale = 5
	   	   	   end
		   end
		   if s.valid and (s.scale < 100)
		   s.state = S_NULL
		   end
		end
end, MT_SPCHARGESHOT)

addHook("MobjThinker", function(s)
	if not s.brakandco
		s.color = SKINCOLOR_GREEN
	end
	s.samusshot = true
		if (s.momz < 0) and (s.z < s.floorz+28*FRACUNIT)
		or (s.momz > 0) and (s.z+s.height > s.ceilingz-28*FRACUNIT)
			s.momz = 0
			s.destscale = 5
		end
		if (s.momz == 0) and (s.z < s.floorz+28*FRACUNIT)
			s.momz = 0
			P_MoveOrigin(s, s.x, s.y, s.floorz+28*FRACUNIT)
		end
		if (s.momz == 0) and (s.z > s.ceilingz-28*FRACUNIT)
			s.momz = 0
			P_MoveOrigin(s, s.x, s.y, s.ceilingz-28*FRACUNIT)
		end
		if s.valid and ((s.state == S_SPXP1) or (s.state == S_SPXP2)) and not s.boombear and not s.noshatter
			A_Samuskillstuff(s, 375*FRACUNIT, 322*FRACUNIT, s.target, true)
			A_SAMUSEXPLOSIONS(s, 8, MT_SAMSHATTERFOF, false, 9000, true)
			A_SAMPARTICLE(s, MT_MPR4, 9, 14, -4, 8, s.color, P_RandomRange(45355, 64355)*9)	
			s.boombear = true
			s.blendmode = AST_ADD
		end
		if s.health
		local tsh = P_SpawnGhostMobj(s)
		tsh.blendmode = AST_ADD
		if leveltime % 2 == 0
			tsh.destscale = $*2
		else
			tsh.destscale = tsh.scalespeed+1
		end
		   if not s.noshatter
		  	 A_Samuskillstuff(s, 344*FRACUNIT, 210*FRACUNIT, s.target, true, "combowave")
		   end
		   if (leveltime % 6 == 0) and not s.noshatter
		local ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
		ghs.sprite = SPR_MXP4
		ghs.frame = V|FF_FULLBRIGHT|TR_TRANS60
		ghs.blendmode = AST_ADD
		ghs.scale = FRACUNIT
		ghs.tics = 99
		ghs.fuse = 36
		ghs.destscale = $*99		
		   		A_SAMUSEXPLOSIONS(s, 2, MT_SAMSHATTERFOF, false, 9000)
		 		A_SAMPARTICLE(s, MT_MPR4, 15, 18, -7, 12, s.color, P_RandomRange(24355, 65353)*4)
		   elseif not s.noshatter
		   		A_SAMPARTICLE(s, MT_MPR4, 11, 14, -5, 9, SKINCOLOR_WHITE, P_RandomRange(44355, 65353)*4)
		   end
		   if (s.tics > 1)
		   		s.tics = $-1
		   end
		   if (s.state == S_MPR9G) and (s.tics < 3)
		   		s.state =S_MPR9A
		   end
		   if s.magicaltic and not s.noshatter
		   		A_SAMUSEXPLOSIONS(s, 5, MT_SAMSHATTERFOF, false, 144000)	

				if not s.saldsalf

				local ghs = P_SpawnMobj(s.x+FixedMul(s.radius*8, cos(s.angle-(ANG2*16))), s.y+FixedMul(s.radius*8, sin(s.angle-(ANG2*16))), s.z+((s.height/4)*(P_MobjFlip(s))), MT_SPCHARGECOMBO)
				ghs.target = s.target
				ghs.noshatter = true
				ghs.blendmode = AST_ADD
				ghs.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE
				ghs.eflags = s.eflags ghs.flags2 = s.flags2
				ghs.scale = s.scale/2 ghs.angle = s.angle
				ghs.momz = s.momz
				P_Thrust(ghs, s.angle-(ANG2*2), FixedMul(ghs.info.speed, s.target.scale))

				ghs = P_SpawnMobj(s.x+FixedMul(s.radius*4, cos(s.angle+(ANG2*8))), s.y+FixedMul(s.radius*4, sin(s.angle+(ANG2*8))), s.z+((s.height/4)*(P_MobjFlip(s))), MT_SPCHARGECOMBO)
				ghs.target = s.target
				ghs.noshatter = true
				ghs.blendmode = AST_ADD
				ghs.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE
				ghs.eflags = s.eflags ghs.flags2 = s.flags2
				ghs.scale = s.scale/2 ghs.angle = s.angle
				ghs.momz = s.momz
				P_Thrust(ghs, s.angle+(ANG2*1), FixedMul(ghs.info.speed, s.target.scale))

				s.saldsalf = true
				end

		   elseif not s.magicaltic
		   s.magicaltic = true
		   s.destscale = $*6
		   s.plshottimer = 40
		   end
	   	   if s.plshottimer
	   	   		s.plshottimer = $-1
				if s.noshatter
	   	   	   		if s.plshottimer == 25
		  	   		s.destscale = 5
	   	   	   		end
				elseif (s.flags & MF_BOUNCE)
					s.flags = $ & ~MF_BOUNCE & ~MF_GRENADEBOUNCE
				end
		   end
		   if s.valid and (s.scale < 20000)
		   		s.state = S_NULL
		   end
		end
end, MT_SPCHARGECOMBO)

addHook("MobjThinker", function(s)
		if s.customcolor
		s.color = s.customcolor
		elseif s.hypered
			if s.wavebeamtimer != nil
				if (s.wavebeamtimer > 16)
				s.color = SKINCOLOR_SKY
				elseif (s.wavebeamtimer > 14)
				s.color = SKINCOLOR_BLUE
				elseif (s.wavebeamtimer > 12)
				s.color = SKINCOLOR_MAGENTA
				elseif (s.wavebeamtimer > 10)
				s.color = SKINCOLOR_PINK
				elseif (s.wavebeamtimer > 8)
				s.color = SKINCOLOR_CLOUDY
				elseif (s.wavebeamtimer > 6)
				s.color = SKINCOLOR_GOLD
				elseif (s.wavebeamtimer > 4)
				s.color = 29
				elseif (s.wavebeamtimer > 2)
				s.color = 32
				else
				s.color = SKINCOLOR_EMERALD
				end
			end
			if not s.wavebeamtimer
			s.wavebeamtimer = 18
			else
			s.wavebeamtimer = $-1
			end
		else
		s.color = SKINCOLOR_GREEN
		end
	s.samusshot = true
		if s.rocket and s.rocket.valid 
		local t = s.rocket
			if s.samdrollangle == nil
			s.samdrollspeed = ((P_RandomRange(1,60))*ANG1)
			s.samdrollangle = P_RandomRange(-1,1)
			s.blendmode = AST_ADD
				if not s.samdrollangle
				s.samdrollangle = 1
				end
			end
			if s.screamsound == nil
			s.screamsound = true
				if t.player
				--Scream for me, bois.
					if t.skin == "werehog"
						if P_RandomRange(0,1) --Stack the crap out of this
						S_StartSound(t, sfx_rsaaa1)
						else
						S_StartSound(t, sfx_rsaaa2)
						end
						s.screamsound = nil
					elseif t.skin == "duke" and not S_SoundPlaying(t, sfx_dnpn03)
					S_StartSound(t, sfx_dnpn03) S_StartSound(t, sfx_dnpn03)
					elseif t.skin == "sms" and not S_SoundPlaying(t, sfx_smscr2) and not t.player.hypermysticsonic
					S_StartSound(t, sfx_smscr2) S_StartSound(t, sfx_smscr2)
					elseif t.skin == "silver" and not S_SoundPlaying(t, sfx_silrip)
					S_StartSound(t, sfx_silrip) S_StartSound(t, sfx_silrip)
					elseif (t.skin == "eggman" or t.skin == "brakeggman") and not S_SoundPlaying(t, sfx_eggahh)
					S_StartSound(t, sfx_eggahh)
					elseif (t.skin == "shadow")
						if ((leveltime % 20 == 0) or ((leveltime % 10 == 0) and P_RandomRange(0,1)))
						S_StartSound(t, sfx_damnit) S_StartSound(t, sfx_damnit)
						end
					s.screamsound = nil
					end		
				end
				if s.hypered
				S_StartSound(t, sfx_shnuke)
				end
			end
			
			
			--waaaaa
			if not (t.superbrak and not s.hypered)
			s.samvrollangle = s.samvrollangle and $+(s.samdrollspeed*s.samdrollangle) or s.samdrollspeed*s.samdrollangle
				if MODVERSION
				t.rollangle = s.samvrollangle
				end
			end
			if t.player and not t.player.sam_sensitive
			t.player.viewrollangle = s.samvrollangle
			end
			if t.superbrak and not t.superbrakquickfret
				if s.hypered
				t.superbrakquickfret2 = true
				end
				t.superbrakquickfret = true
			elseif G_GametypeHasSpectators() and t and not t.health and P_CheckDeathPitCollide(t)
			and t.player and s.target and s.target.player and s.target != t
				if not t.gavespdeathscore
				P_AddPlayerScore(s.target.player, 64)
				t.gavespdeathscore = true
				end
				t.spazershocked = nil
				t.barocket = nil
				t.spcombod = nil
				if s.rocket.player s.rocket.player.viewrollangle = 0 end s.rocket.rollangle = 0 s.rocket = nil
				return
			elseif (t and t.valid and ((t.type == MT_POPUPTURRET) or t.type == MT_METROIDPART or t.type == MT_PZBOSS or t.type == MT_PTERABYTE or t.type == MT_DRAGONBOMBER) and t.health)
				t.spazershocked = nil
				t.barocket = nil
				t.spcombod = nil
				P_DamageMobj(t, s, s, 2)
				if s.rocket.player s.rocket.player.viewrollangle = 0 end s.rocket.rollangle = 0 s.rocket = nil
				return
			elseif (t.info.mass == 2006) or (t.barocket and (t.barocket > 250)) or (t.superbrak and (t.flags2 & MF2_FRET))
			or (s.target and t == s.target) or (t.player and (t.player.hbimmune or t.player.hypermysticsonic))
			or ( t.player and G_GametypeHasTeams() and s.target and s.target.player and (t.player.ctfteam == s.target.player.ctfteam) )
				t.spazershocked = nil
				t.barocket = nil
				t.spcombod = nil
				if s.rocket.player s.rocket.player.viewrollangle = 0 end s.rocket.rollangle = 0 s.rocket = nil
				return
			end
			
			if (t.type == MT_METROID) or (t.type == MT_SUPERMETROID)
				if s.hypered and (t.type == MT_METROID)
				P_KillMobj(t)
				else
				t.spazershocked = nil
				t.barocket = nil
				t.spcombod = nil
				if s.rocket.player s.rocket.player.viewrollangle = 0 end s.rocket.rollangle = 0 s.rocket = nil
				return
				end
			elseif ( (t.type == MT_EGGMOBILE3) or (t.type == MT_EGGMOBILE4) or (t.type == MT_BLACKEGGMAN)
			or (t.type == MT_METALSONIC_BATTLE) or (t.info.doomednum == 1555) ) and t.health and (t.health > 2)
			
				if not s.target
					if s.hypered and not (t.type == MT_PZBOSS)
					P_DamageMobj(t, nil, nil, 6)
					elseif t.spcombod
					P_DamageMobj(t, nil, nil, 2)
					else
					P_DamageMobj(t, nil, nil, 2)
					end
				elseif s.target
					if s.hypered and not (t.type == MT_PZBOSS)
					P_DamageMobj(t, s, s.target, 6)
					elseif t.spcombod
					P_DamageMobj(t, s, s.target, 2)
					else
					P_DamageMobj(t, s, s.target, 2)
					end
				end
				P_SpawnMobj(t.x, t.y, t.z, MT_SONIC3KBOSSEXPLODE)
				S_StartSound(t, sfx_brakrx)
				t.spazershocked = nil
					if not t.player and s.ogflags
					t.flags = s.ogflags
					end
				t.spcombod = nil
				if s.rocket.player s.rocket.player.viewrollangle = 0 end s.rocket.rollangle = 0 s.rocket = nil
				return
			end

			if t.barocket == nil
				if t.spazershocked and (t.type >= MT_EGGMOBILE) and (t.type <= MT_EGGMOBILE4)
				and (t.spcombod or s.hypered)
				and not (t.flags2 & MF2_FRET)
				S_StartSound(t, sfx_eggahh) //Squeal for me, stache boy
				end
				t.barocket = 0
			else 
				t.barocket = $+1
			end

			if t.flags
				if t.player and t.player.powers[pw_flashing] and (t.player.powers[pw_flashing] < 3)
				t.player.powers[pw_flashing] = 3
				end
				if t.player and t.health and not (t.state == S_PLAY_PAIN) and not P_IsObjectOnGround(t)
					if t.player.powers[pw_super]
					t.state = S_PLAY_STUN
					else
					t.state = S_PLAY_PAIN
					end
				elseif not t.player
					if not s.ogflags
					s.ogflags = t.flags
					t.flags = $ & ~(MF_FLOAT|MF_NOGRAVITY|MF_SLIDEME|MF_SHOOTABLE)
					end
					t.target = t
				end
			end

			if s.upm == nil
				if s.hypered
					P_MoveOrigin(s, t.x, t.y, t.z)
					s.momx = t.momx
					s.momy = t.momy
					s.momz = t.momz
				end

				if not (t.barocket and (t.barocket > 8))
					if s.target and s.target.player and s.target.player.aiming and not t.spcombod and not s.hypered
						s.upm = 11+s.target.player.aiming/(400*FRACUNIT)
						s.momx = s.target.momx
						s.momy = s.target.momy
						s.momz = s.target.momz/2
					else
						s.upm = 11
						if s.target
						s.momx = s.target.momx
						s.momy = s.target.momy
						s.momz = s.target.momz/2
						end
					end
				end
			else
			s.upm = $-1
				if (s.upm <= 1) and s.downm == nil
				s.downm = 0
				end
			end
			if s.downm != nil
			s.downm = $-1
			end
			if t.rocketangledirection == nil t.rocketangledirection = P_RandomRange(-1, 1) end
			if t.rocketanglespeed == nil t.rocketanglespeed = (P_RandomRange(6, 40))*ANG1 end

			if t.rocketangle == nil
			t.rocketangle = t.angle
				if t.player
				P_SamFP(t.player, PAL_RECYCLE, 4)
				P_PlayRinglossSound(t)
				end
			else
			t.rocketangle = $+(t.rocketanglespeed*t.rocketangledirection)
			end
			
			if not (t.player and not t.spcombod)
			t.angle = t.rocketangle
			end
			if s.hypered
				if t.superbrak 
				t.flags = $|MF_BOUNCE
					if s.superbrakbigjump or s.superbrakjump
					s.superbrakbigjump = 0
					s.superbrakjump = 0
					end
				else
					local ghs = P_SpawnGhostMobj(t)
					ghs.scale = $*2
					ghs.blendmode = AST_ADD
					ghs.colorized = true
					ghs.fuse = 12
					ghs.tics = 13
					ghs.rollangle = t.rollangle-ANGLE_45
					if leveltime % 2 == 0
					ghs.color = SKINCOLOR_SUPERSKY4
					else
					ghs.color = SKINCOLOR_SUPERSILVER1
					end
					ghs.scalespeed = $*2
					ghs.destscale = ghs.scalespeed+1
				end
			end
			if (leveltime % 2 == 0)
				if t.specialexpangle
				P_InstaThrust(t, t.specialexpangle, -88*FRACUNIT)
				else
				P_InstaThrust(t, s.angle, 88*FRACUNIT)
				end
				
				if s.upm
				P_SetObjectMomZ(t, s.upm*FRACUNIT)
				elseif s.downm
				P_SetObjectMomZ(t, s.downm*FRACUNIT)
				end
				
				if s.preimage == nil
				s.preimage = 6
				end
				if s.preimage
					local ghs = P_SpawnGhostMobj(t)
					ghs.rollangle = t.rollangle
					ghs.colorized = true
					ghs.scale = ($*5)/s.preimage
					if t.hypered
						if s.preimage % 2 == 0
							ghs.color = SKINCOLOR_PINK
						else
							ghs.color = SKINCOLOR_SUPERGOLD5
						end
					else
						if s.preimage % 2 == 0
							ghs.color = SKINCOLOR_SUPERSILVER1
						else
							ghs.color = SKINCOLOR_SUPERGOLD2
						end
					end					
				s.preimage = $-1
				end
				
			elseif (t.barocket and t.barocket > 3)
				if ((t.momx < 4*FRACUNIT and t.momx > -4*FRACUNIT) and (t.momy < 4*FRACUNIT and t.momy > -4*FRACUNIT))
				or (t.eflags & MFE_JUSTHITFLOOR) or (t.eflags & MFE_GOOWATER)
				or ((t.barocket > 35) and (P_IsObjectOnGround(t) or (t.z <= t.floorz)))
					if t.player and t.player.powers[pw_super]
					P_GivePlayerRings(t.player, -30)
					end
					if s.hypered and s.target
						if not t.player
							t.flags = $|(s.ogflags or 0)
						elseif t.player
							t.player.hbimmune = 45
						end
						
					   t.spazershocked = nil
					   t.barocket = nil
					   s.hyperedboom = P_SpawnMobj(t.x, t.y, t.z, MT_HBSHOT)
					   s.hyperedboom.target = s.target
					   s.hyperedboom.lasthyper = t
					   S_StartSound(s.hyperedboom, sfx_smexp)
					   S_StartSound(s.hyperedboom, sfx_hbsh)
					   S_StartSound(s.hyperedboom, sfx_brakrx)
					   P_ExplodeMissile(s.hyperedboom)
					   
					   	if not (t.player and t.player.powers[pw_flashing])
							if t.superbrak
								if (t.health > 6)
								P_DamageMobj(t, s, s.target, 6)
								elseif t.hyperbeampanic and (t.health <= 6)
								P_KillMobj(t, s, s.target)
								else
								P_DamageMobj(t, s, s.target)
								end
							else
							P_DamageMobj(t, s, s.target, 6)
							end
					   	end
						
					   if s.rocket.player s.rocket.player.viewrollangle = 0 end s.rocket.rollangle = 0 s.rocket = nil
					   return

					elseif t and t.valid and t.health
					
					S_StartSound(t, sfx_brakrx)
					local ghs = P_SpawnMobj(t.x, t.y, t.z, MT_CYBRAKDEMON_VILE_EXPLOSION)
						S_StartSound(t, sfx_brakrx) S_StartSound(t, sfx_s1b9)
						local angle = s.angle+ANGLE_180				
						if t.specialexpangle
							angle = t.specialexpangle+ANGLE_180
						end
						for d = -3,3 --Rocks!
							local debris = P_SpawnMobjFromMobj(t, 0, 0, 0, MT_MPR8)
							if debris and debris.valid
								local rng = P_RandomRange(7,44)
								debris.spriteyscale = $/(rng/7)
								debris.spritexscale = $/(rng/7)
								debris.flags = MF_BOUNCE|MF_GRENADEBOUNCE|MF_SOLID|MF_NOCLIPTHING //& ~MF_NOCLIPHEIGHT & ~MF_NOGRAVITY & ~MF_NOCLIP
								debris.sprite = SPR_ROIA
								debris.rollspeed = rng*ANG1
								debris.frame = A
								debris.tics = 24
								debris.fuse = 24
								debris.rollangle = (rng*5)*ANG1
								P_InstaThrust(debris, angle+(d*ANG20), 24*FRACUNIT+(rng*FRACUNIT))
								P_SetObjectMomZ(debris, P_RandomRange(-10,10)*FRACUNIT, false)
							end
						end						
					
						if not t.player
						t.flags = $|(s.ogflags or 0)
						end

						if s.target
							if t.superbrak and (t.health > 5) and t.spcombod
							P_DamageMobj(t, s, s.target, 4)
							elseif t.superbrak and (t.health > 3)
							P_DamageMobj(t, s, s.target, 3)
							elseif not (t.superbrak and (t.health < 3) and not t.hyperbeampanic)
							P_DamageMobj(t, s, s.target, 2)
							end
						elseif t.spcombod
							if t.superbrak and (t.health > 5)
							P_DamageMobj(t, s, s, 4)
							elseif not (t.superbrak and (t.health < 3) and not t.hyperbeampanic)
							P_DamageMobj(t, s, s, 2)
							end
						end
						if t and t.valid
						t.spazershocked = nil
						t.barocket = nil
						t.spcombod = nil
						end
						
						if s.rocket and s.rocket.valid
							if s.rocket.player
							s.rocket.player.viewrollangle = 0
							end
					
							s.rocket.rollangle = 0 
							s.rocket = nil
							end
						end
					return						
				end
			end

			if (s.state == S_MPR9G) and (s.tics < 2)
				s.state = S_SAMSPAWNITEM2
			end
			if (s.state == S_SAMSPAWNITEM2)
				s.tics = 77
			end
		elseif (s.state == S_SAMSPAWNITEM2)
			P_KillMobj(s)
			return
		end
end, MT_SPAZERSHOCK)

addHook("MobjThinker", function(s)
	s.color = SKINCOLOR_MAGENTA
	s.samusshot = true
		if not s.wavetwodcheck and (twodlevel or (s.target and s.target.valid and (s.target.flags2 & MF2_TWOD)))
		s.wavetwodcheck = true
		s.wavetwod = true
			if s.wave2
				if s.target and s.target.valid
				s.z = $+(s.target.height/2)
				end
			end
		elseif not s.wavetwodcheck
		s.wavetwodcheck = true
		end
		if ((s.state == S_WVSHOT1) or (s.state == S_WVSHOT2))


--Experimental code

			if (leveltime % 16 == 0) and not s.charged and (s.target and s.target.player)
			s.spindz = 0
			s.spinaxisz = 0
			s.spinaxis = 0
			s.verticalangle = R_PointToAngle2(0, 0, R_PointToDist2(0, 0, s.momx, s.momy), s.momz)
			local ang = leveltime*ANG10
				local ghs = P_SpawnMobjFromMobj(s,0,0,0,MT_SAMLIGHTLINE)
				ghs.target = s
				ghs.scale = (s.scale*5)/10
				ghs.blendmode = AST_ADD
				ghs.tics = 22
				ghs.spriteyoffset = -12*FRACUNIT
				ghs.frame = A|FF_FULLBRIGHT|TR_TRANS20
				ghs.destscale = ghs.scalespeed+1
				ghs.color = SKINCOLOR_PURPLE
				ghs.tashu = s.target.player
			end
		
		
--Back to normal
		
		s.rollangle = leveltime*ANG20 --speen
		
			if s.wavebeamtimer or (s.wavebeamtimer == 0)
				if s.wave2
					if (s.wavebeamtimer > 5)
						if s.wavetwod
						P_SetObjectMomZ(s, 365355, true)
						else
						P_Thrust(s, s.angle+ANGLE_90, FRACUNIT)
						end
					else
						if s.wavetwod
						P_SetObjectMomZ(s, -365355, true)
						else
						P_Thrust(s, s.angle-ANGLE_90, FRACUNIT)
						end
					end
				else
					if (s.wavebeamtimer > 5)
						if s.wavetwod
						P_SetObjectMomZ(s, -365355, true)
						else
						P_Thrust(s, s.angle-ANGLE_90, FRACUNIT)
						end
					else
						if s.wavetwod
						P_SetObjectMomZ(s, 365355, true)
						else
						P_Thrust(s, s.angle+ANGLE_90, FRACUNIT)
						end
					end
				end
			end
			if not s.wavebeamtimer
				s.wavebeamtimer = 10
			else
				s.wavebeamtimer = $-1
			end
			if (leveltime % 2 == 0)
				s.spriteyscale = 49355
				s.spritexscale = 55355
			else
				s.spriteyscale = FRACUNIT
				s.spritexscale = FRACUNIT			
			end
			if (s.state == S_WVSHOT1)
				if not s.wavenope
					A_SAMPARTICLE(s, MT_MPR1, 4, 5, -4, 4, s.color, P_RandomRange(9355, 34355))
				end
				local ghs = P_SpawnGhostMobj(s)
				ghs.blendmode = AST_ADD
				ghs.destscale = ghs.scalespeed+1
				ghs.rollangle = leveltime*ANG20
				ghs.colorized = true
				if leveltime % 2  == 0
					ghs.color = SKINCOLOR_SUPERGOLD5
				else
					ghs.color = SKINCOLOR_GRAVITYSUIT			
				end
			end				
		elseif (s.state == S_WVXP1) and not s.saldsalf
			s.spriteyscale = FRACUNIT
			s.spritexscale = FRACUNIT
			s.destscale = s.scale*10
			MonitorBreaker(s, s.target)
			s.scalespeed = $*3
			s.saldsalf = true
		end
		if not s.plshottimer
			if (s.momx < 0)
			s.oldwavespeedx = s.momx*-1
			else
			s.oldwavespeedx = s.momx
			end
			if (s.momy < 0)
			s.oldwavespeedy = s.momy*-1
			else
			s.oldwavespeedy = s.momy
			end
			s.oldwavespeed = ((s.oldwavespeedx+s.oldwavespeedy)/2)/FRACUNIT
			s.oldwavespeedz = s.momz
			s.plshottimer = 120
			return
		elseif s.valid and ((s.plshottimer == 1) or (s.floorz == s.ceilingz))
			s.state = S_NULL
			return
		else
		s.plshottimer = $-1
			if (s.momx < 0)	
			s.wavespeedx = s.momx*-1
			else
			s.wavespeedx = s.momx
			end
			if (s.momy < 0)	
			s.wavespeedy = s.momy*-1
			else
			s.wavespeedy = s.momy
			end
			s.wavespeed = ((s.wavespeedx+s.wavespeedy)/2)/FRACUNIT
				if s and (s.flags & MF_BOUNCE)
				and ( (s.wavespeed < s.oldwavespeed-5) or (s.momz != s.oldwavespeedz))
				s.flags = $ & ~MF_BOUNCE & ~MF_GRENADEBOUNCE
					for d = 1,3
					s.missilelight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_MINECARTSPARK)
					local t = s.missilelight
					t.scale = s.scale/15
					t.fuse = 23
					P_InstaThrust(t, P_RandomRange(1,359)*ANG1, P_RandomRange(8,18)*FRACUNIT)
					t.momz = s.momz/2
					end	
				end
		end
end, MT_WVSHOT)

addHook("MobjThinker", function(s)
	s.color = SKINCOLOR_MAGENTA
	s.samusshot = true
		if s.bufferguard and s.health
		s.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE|MF_NOCLIPHEIGHT
			if s.target == nil or s.target and not s.target.health or s.target and not s.target.wavebuffering
				if s.valid and s.health
				s.bufferguard = false
				s.flags = $ & ~MF_BOUNCE & ~MF_GRENADEBOUNCE & ~MF_NOCLIPHEIGHT
				P_ExplodeMissile(s)
				return
				end	
			end
		elseif not s.bufferguard and (s.flags & MF_BOUNCE)
		s.flags = $ & ~MF_BOUNCE & ~MF_GRENADEBOUNCE & ~MF_NOCLIPHEIGHT
		end
		if ((s.state == S_WVSHOT1) or (s.state == S_WVSHOT2))
			if s.wavebeamtimer or (s.wavebeamtimer == 0)
				if (s.wavebeamtimer > 5)
				P_Thrust(s, s.angle+ANGLE_90, FRACUNIT*2)
				else
				P_Thrust(s, s.angle-ANGLE_90, FRACUNIT*2)
				end
			end
			if (s.wavebeamtimer == nil)
			s.wavebeamtimer = 8
			elseif not s.wavebeamtimer
			s.wavebeamtimer = 11
			else
			s.wavebeamtimer = $-1
			end
			if (s.state == S_WVSHOT1) and not (s.flags2 & MF2_DONTDRAW)
				s.ghs = P_SpawnGhostMobj(s)
				s.ghs.blendmode = AST_ADD
				s.ghs.destscale = s.ghs.scalespeed+1
				s.ghs.rollangle = leveltime*ANG1
				if leveltime % 2 == 0
					s.ghs.color = SKINCOLOR_SUPERGOLD5
					s.ghs.colorized = true
					s.ghs.tics = 16
				end
				
					if not s.bufferguard or (leveltime % 3 == 0)
						if (s.eflags & MFE_VERTICALFLIP)
						s.plexpand = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_PBEXPANDW)
						else
						s.plexpand = P_SpawnMobj(s.x, s.y, s.z, MT_PBEXPANDW)
						end
						if s.plexpand
							s.plexpand.blendmode = AST_ADD
							s.plexpand.scale = $*P_RandomRange(1,2)
							s.plexpand.scalespeed = $*P_RandomRange(1, 4)
							s.plexpand.destscale = $*20
						end
					end
					if not s.bufferguard
					A_SAMPARTICLE(s, MT_MPR1, 4, 5, -4, 4, s.color, P_RandomRange(29355, 54355))
					end
			end			
		elseif not s.saldsalf and (s.state == S_WVXP1) and not (s.flags2 & MF2_DONTDRAW)
		
		--The Wave Charge Shot explodes into tons of smaller shot, some which home into foes/monitors, some which are randomly scattered.
		
		A_SAMPARTICLE(s, MT_WVSHOT, 1, 40, -30, 30, 17, 50000)
		A_SAMPARTICLE(s, MT_WVSHOT, 1, 40, -30, 30, 17, 40000)
		A_SAMPARTICLE(s, MT_WVSHOT, 1, 30, -30, 30, 17, 45000)
		A_SAMPARTICLE(s, MT_WVSHOT, 1, 40, -30, 30, 17, 47000)
		A_SAMPARTICLE(s, MT_WVSHOT, 1, 30, -3, 3, 17, 60000)
		A_SAMPARTICLE(s, MT_WVSHOT, 1, 40, -15, 15, 17, 43000)
		A_SAMPARTICLE(s, MT_WVSHOT, 1, 30, -20, 20, 17, 42000)
		A_SAMPARTICLE(s, MT_WVSHOT, 1, 30, -20, 20, 17, 48000)
		A_SAMPARTICLE(s, MT_WVSHOT, 1, 40, -1, 1, 17, 54000)
		A_SAMPARTICLE(s, MT_WVSHOT, 1, 40, -5, 5, 17, 59000)
		s.destscale = s.scale*10
		s.scalespeed = $*3
		s.saldsalf = true
		
		--Fire off 1 homing bullet. Does not home onto players.
		
		s.shottarget = nil
		s.shottarget2 = nil
		local lastdist
		local lastdist2
		searchBlockmap("objects", function(s, m)
			if m and m.health
			and ((m.flags & MF_ENEMY) or (m.flags & MF_BOSS) or (m.flags & MF_MONITOR))  --Anything around?
			and P_CheckSight(s, m)
				if not ( m.subsector == s.subsector and (m.z < (s.floorz-5*s.scale)) )
					if not s.shottarget or s.shottarget2
						if lastdist == nil
						or (R_PointToDist2(s.x, s.y, m.x, m.y) < lastdist)
							if m != s.shottarget2
							s.shottarget = m
							lastdist = R_PointToDist2(s.x, s.y, m.x, m.y)
							end
						end
					else 
						if lastdist2 == nil
						or (R_PointToDist2(s.x, s.y, m.x, m.y) < lastdist2)
							if m != s.shottarget
							s.shottarget2 = m
							lastdist2 = R_PointToDist2(s.x, s.y, m.x, m.y)
							end	
						end
					end
				end
			end
  		end, s, s.x-2200*FRACUNIT, s.x+2200*FRACUNIT, s.y-2200*FRACUNIT, s.y+2200*FRACUNIT)	
		
  		if s.shottarget2 and s.shottarget2.valid
			local wvhome = P_SpawnMissile(s, s.shottarget2, MT_WVSHOT)
			if wvhome and wvhome.valid
			wvhome.target = s.target
			end
		end
  		if s.shottarget and s.shottarget.valid
			local wvhome = P_SpawnMissile(s, s.shottarget, MT_WVSHOT)
			if wvhome and wvhome.valid
			wvhome.target = s.target
			end
		else --Nothing found, then do old behaviour.
			A_SAMPARTICLE(s, MT_WVSHOT, 1, 30, -30, 30, 17, P_RandomRange(40000, 57000))
			A_SAMPARTICLE(s, MT_WVSHOT, 1, 40, -10, 10, 17, P_RandomRange(40000, 57000))
		end
		
		--Shiny explosion graphic.
		local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_THOK)
			ghs.color = SKINCOLOR_PURPLE
			ghs.sprite = SPR_MBOM
			ghs.frame = R|TR_TRANS30|FF_FULLBRIGHT
			ghs.blendmode = AST_ADD
			ghs.renderflags = $|RF_FULLBRIGHT
			ghs.fuse = 13 ghs.tics = 99 P_SetObjectMomZ(ghs, 4*FRACUNIT)
			ghs.scalespeed = $*3 ghs.destscale = FRACUNIT*99
			ghs = nil
			if (gametype == GT_COOP)
			P_RadiusAttack(s, s, 50*FRACUNIT)
			end
		ghs = P_SpawnMobjFromMobj(s,0,0,0, MT_THOK)
		ghs.flags2 = $|MF2_DONTDRAW ghs.tics = 99
		S_StartSound(ghs, sfx_wvxpz)
		S_StartSound(ghs, sfx_wvxpz)
		
				for d = 1,6
					s.missilelight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_MINECARTSPARK)
					local t = s.missilelight
					t.blendmode = AST_ADD
					t.scale = s.scale/15
					t.fuse = 30
					P_InstaThrust(t, P_RandomRange(1,359)*ANG1, P_RandomRange(8,24)*FRACUNIT)
					t.momz = P_RandomRange(2,7)*FRACUNIT
				end	
					
				s.missilelight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_SAMMISSILELIGHT)
				local t = s.missilelight
				t.blendmode = AST_ADD
				t.scale = s.scale/70
				t.color = SKINCOLOR_SUPERGOLD5
				t.layers = 1
				
		end
end, MT_WVCHARGESHOT)

addHook("MobjThinker", function(s)
		if s.dietime == nil
		s.dietime = 149
		else
		s.dietime = $-1
		end
		if s.target and s.target.health
		local t = s.target
		
			if s.spazerstunner --Technically not a stunner, but....
				s.spazerstunner = $-1
				if not s.spazerstunnersetup
					if t.spazerdirect == nil or t.spazerdirect == 1
					t.spazerdirect = -1
					else
					t.spazerdirect = 1
					end
					s.spazerstunnersetup = true
					s.spazerstunnera = t.angle
				end
				if s.spazerstunang != nil
					if not (t.flags2 & MF2_FRET)			
					t.tics = $+1
					end
				t.momx = 0 t.momy = 0
				P_InstaThrust(t, s.spazerstunang, s.spazerstunner*95355)
					if (t.flags & MF_NOGRAVITY)
					s.spazerroll = s.spazerroll and $+(((ANG30/2)*(t.spazerdirect*2))) or ((ANG30/2)*(t.spazerdirect*2))
					end
					s.spazerstunnera = $+((ANGLE_45)*t.spazerdirect)
					t.angle = s.spazerstunnera
					if (s.z < s.floorz+60*FRACUNIT)
					S_StartSound(t, sfx_s3k7e)
					s.ghs = P_SpawnMobj(t.x+FixedMul(32*FRACUNIT, cos(t.angle+ANGLE_90)),t.y+FixedMul(32*FRACUNIT, sin(t.angle+ANGLE_90)), t.z, MT_SPINDUST)
					s.ghs.frame = P_RandomRange(0,2)
					s.ghs = P_SpawnMobj(s.x+FixedMul(32*FRACUNIT, cos(t.angle-ANGLE_90)), t.y+FixedMul(32*FRACUNIT, sin(t.angle-ANGLE_90)), t.z, MT_SPINDUST)
					s.ghs.frame = P_RandomRange(0,2)
					end
				end
				if (s.spazerstunner > 6) and (s.tics > 6)
				t.waverstunned = true
					if not (t.type > 53) --Lazy.
					t.color = SKINCOLOR_GREEN
					t.colorized = true
					s.icolorizedthem = true
					end
				else
				t.waverstunned = nil
					if s.icolorizedthem
					s.icolorizedthem = false
					t.color = SKINCOLOR_NONE
					t.colorized = false
					end
				end				
				if not s.spazerstunner
					if t and t.valid
						if s.spazerroll != nil
						s.rollangle = 0
						end
					t.waverstunned = nil
					end
					s.state = S_NULL
					return
				end
				
				return
			else
			
				local ghs = P_SpawnGhostMobj(t)
				ghs.tics = 11
				ghs.blendmode = AST_ADD
				ghs.scalespeed = $/10*P_RandomRange(5,8)
				ghs.destscale = $*50
				ghs.colorized = true
				ghs.momx = P_RandomRange(-3,3)*FRACUNIT ghs.momy = P_RandomRange(-3,3)*FRACUNIT
				ghs.momz = P_RandomRange(0,2)*FRACUNIT*P_MobjFlip(t)
					if s.dietime % 4 == 0
						if not NoPushList(t)
						t.angle = $-ANG20
						end
					A_SAMPARTICLE(t, MT_MPR1, 4, 4, -2, 6, SKINCOLOR_GOLD, P_RandomRange(9355, 30355))
					A_SAMPARTICLE(t, MT_MPR1, 5, 3, -3, 6, SKINCOLOR_MAGENTA, P_RandomRange(35355, 65354))					
					P_TryMove (t, s.x+P_RandomRange(-9,9)*FRACUNIT, s.y+P_RandomRange(-9,9)*FRACUNIT, true)
					ghs.color = P_RandomRange(SKINCOLOR_SUPERPURPLE1, SKINCOLOR_SUPERPURPLE5)
					else
					t.angle = $+ANG10
					ghs.color = SKINCOLOR_GRAVITYSUIT
					end
			
				if (s.dietime % 30 == 0)
				S_StartSound(t, sfx_wvbc)
					if t.samusHP and (t.samusHP > 1) --Wittle down the HP
					t.samusHP = $-1
					end
					local ghs = P_SpawnGhostMobj(t)
					ghs.tics = 20
					ghs.scalespeed = $*4
					ghs.destscale = $*50
					ghs.color = SKINCOLOR_SUPERGOLD5
					ghs.colorized = true
					P_TryMove (t, s.x+P_RandomRange(-22,22)*FRACUNIT, s.y+P_RandomRange(-22,22)*FRACUNIT, true)
					if not NoPushList(t)
						if P_RandomRange(0,1)
						t.angle = $+(ANG30*3)
						else
						t.angle = $-(ANG30*3)
						end
					end
					local ghs = P_SpawnMobj(t.x, t.y, t.z, MT_SAMUSZAP)
					ghs.scale = s.scale*2
				 	ghs.color = SKINCOLOR_SUPERGOLD4
				 	ghs.morning = 4
				end

				if not (t.flags2 & MF2_FRET)			
				t.tics = $+1
				end
				t.momx = 0
				t.momy = 0
				s.z = t.z+(t.height/2)

				if (s.tics > 6)
				t.waverstunned = true
					if not (t.type > 53) --Lazy.
					t.color = SKINCOLOR_GRAVITYSUIT
					t.colorized = true
					s.icolorizedthem = true
					end
				else
				t.waverstunned = nil
					if s.icolorizedthem
					s.icolorizedthem = false
					t.color = SKINCOLOR_NONE
					t.colorized = false
					end
				end
			end
		elseif s.valid
			if s.target and s.target.valid --Is there REALLY no target???
			s.target.waverstunned = nil
			end
		s.state = S_NULL
		return
		end
		if s.valid and ((s.dietime and s.dietime == 1) or s.tics == 1)
			if s.target and s.target.valid
			s.target.waverstunned = nil
			end
		s.state = S_NULL
		return
		end
end, MT_WAVESTUNNER)

addHook("MobjThinker", function(s)
	s.color = SKINCOLOR_CLOUDY
	s.samusshot = true
		if ((s.state == S_ICSHOT1) or (s.state == S_ICSHOT2))
		
			A_SAMPARTICLE(s, MT_MPR6, 1, 1, -2, 1, s.color, 58000)
			if (s.state == S_ICSHOT1)
				A_SAMPARTICLE(s, MT_MPR7, 3, 1, -2, 1, s.color, 85000)
			end
			
		elseif (s.state == S_ICXP1) and not s.saldsalf

	--	A_SAMPARTICLE(s, object, coord, momentum, minuszmomentum, zmomentum, color, scale, spazer)

		A_Samuskillstuff(s, 138*FRACUNIT, 90*FRACUNIT, s.target, false, false, true)
		A_SAMPARTICLE(s, MT_MPR7, 11, 7, -2, 3, s.color, (P_RandomRange(1, 3))*35355)
		A_SAMPARTICLE(s, MT_MPR7, 11, 7, -3, 3, s.color, (P_RandomRange(1, 3))*35355)
		A_SAMPARTICLE(s, MT_MPR7, 11, 6, -2, 3, s.color, (P_RandomRange(1, 3))*35355)
		A_SAMPARTICLE(s, MT_MPR7, 12, 7, -3, 4, s.color, (P_RandomRange(1, 3))*35355)
		A_SAMPARTICLE(s, MT_MPR7, 11, 6, -2, 3, s.color, (P_RandomRange(1, 3))*35355)
		s.saldsalf = true
		s.blendmode = AST_ADD

			if s.z > s.ceilingz-55*FRACUNIT
			or s.z < s.floorz+55*FRACUNIT
				local ghs = SamShinySplat(s,SKINCOLOR_SUPERSILVER5, 10)
				ghs.scale = $/3
				ghs.destscale = $*99
				ghs.frame = A|TR_TRANS80|FF_FULLBRIGHT
			end

		elseif (s.state == S_ICXP4) and not s.saldsalf2
		
			s.destscale = s.scale*10
			s.saldsalf2 = true		
			s.blendmode = AST_ADD
			P_SetObjectMomZ(s, FRACUNIT)
		end
end, MT_ICSHOT)

addHook("MobjThinker", function(s)
	if not P_IsObjectOnGround(s)
		if s.rollspeed != nil
		s.rollnewangle = s.rollnewangle and $+s.rollspeed or 1
		s.rollangle = s.rollnewangle
		end
	else
		if s.sprite == SPR_ROIA
			P_SetObjectMomZ(s, 5*FRACUNIT)
			s.rollangle = $-ANGLE_45
		else
			s.momx = 0
			s.momy = 0
			s.momz = 0
			s.flags = $ & ~MF_BOUNCE & ~MF_GRENADEBOUNCE
		end
	end
end, MT_MPR8)

addHook("MobjThinker", function(s)
	if not s.saldsalf3
		if not s.combograce
			s.destscale = $*4
		end
		s.color = SKINCOLOR_CLOUDY
		s.blendmode = AST_ADD
		s.samusshot = true			
		s.saldsalf3 = true
	end
	if ((s.state == S_ICSHOT1) or (s.state == S_ICSHOT2))
		A_SAMPARTICLE(s, MT_MPR6, 1, 1, -2, 1, s.color, 90000)
		P_SetObjectMomZ(s, 9900, true)
		if (s.state == S_ICSHOT1)
			A_SAMPARTICLE(s, MT_MPR7, 3, 1, -2, 1, s.color, 96000)
			local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_PBEXPANDI)
			ghs.scalespeed = $*P_RandomRange(3, 9)
			ghs.destscale = $*25
			ghs.blendmode = AST_ADD
		end
				
	elseif (s.state == S_ICXP1) and not s.saldsalf and not s.combograce
		
		local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_ICBRSOUND)
		S_StartSound(ghs, sfx_icbr)
		s.saldsalf = true

			if s.z > s.ceilingz-55*FRACUNIT
			or s.z < s.floorz+55*FRACUNIT
			local ghs = SamShinySplat(s,SKINCOLOR_ICY, 11)
			ghs.frame = A|TR_TRANS40|FF_FULLBRIGHT
			ghs.scalespeed = $*2 ghs.destscale = FRACUNIT*99
			end
		
			if G_GametypeHasSpectators()
				A_Samuskillstuff(s, 305*FRACUNIT, 160*FRACUNIT, s.target, true)
			else
				A_Samuskillstuff(s, 370*FRACUNIT, 180*FRACUNIT, s.target, false, false, true)
			end	
			if not s.icesummon
				for z in players.iterate
					if z.mo
						if (FixedHypot(FixedHypot(s.x-z.mo.x, s.y-z.mo.y), s.z-z.mo.z) < 750*FRACUNIT)
						A_samquake(z.mo, 18*FRACUNIT, 10, 1)
						end
					end
				end	
				for d = 1,12
				A_SAMPARTICLE(s, MT_MPR7, P_RandomRange(8,d*2), d*3, -2, P_RandomRange(2,8), P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY5), (P_RandomRange(5, 7))*FRACUNIT)
					if d % 2 == 0 and s.sparker and s.sparker.valid
					s.sparker.colorized = true
					end
				end
			else
				A_SAMPARTICLE(s, MT_MPR7, 9, 9, -2, 6, P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY5), 4*FRACUNIT)	
			end
			
	elseif (s.state == S_ICXP4) and not s.saldsalf2
		
		s.destscale = s.scale*10
		s.saldsalf2 = true		
		if not s.icesummon
			if s.wallclipped and s.target
				local t = s.target
				P_Thrust(t, t.angle, -6*FRACUNIT)
				P_MoveOrigin(s, t.x, t.y, t.z+(t.height/2))
			end			
			SamFaceReflect(s, 210*FRACUNIT)
			for d = 1,8
				A_SAMPARTICLE(s, MT_MPR6, 8, d*4, -2, d*2, P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY5), (P_RandomRange(3, 11))*FRACUNIT)
			end
		else
			A_SAMPARTICLE(s, MT_MPR6, 7, 11, -2, 6, P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY5), 7*FRACUNIT)	
		end
	end
		
	if s.combograce
		s.combograce = $-1
		s.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE|MF_NOCLIPHEIGHT
		if (s.combograce == 1)
			s.flags = $ & ~MF_BOUNCE & ~MF_GRENADEBOUNCE & ~MF_NOCLIPHEIGHT
			s.combograce = 0
		end
	end
	if s.romio and s.romio.valid
		s.flags = $|MF_NOGRAVITY
		if not s.romio.health
			s.state = S_NULL
		end
	end
end, MT_ICCHARGESHOT)

addHook("MobjThinker", function(s)
	s.color = SKINCOLOR_WHITE
	s.samusshot = true
		if not s.saldsalf3
		s.destscale = FRACUNIT
		s.scalespeed = $
		s.saldsalf3 = true
		end
		if ((s.state == S_ICSHOT1) or (s.state == S_ICSHOT2))
		A_SAMPARTICLE(s, MT_MPR6, 1, 1, -2, 1, s.color, ((P_RandomRange(8500, 9935))*10))
			if (s.tics > 1)
			s.tics = $-1
			end
			if (s.state == S_ICSHOT1)
			A_SAMPARTICLE(s, MT_MPR7, 3, 1, -2, 1, s.color, ((P_RandomRange(9000, 9900))*30))
			A_SAMPARTICLE(s, MT_MPR6, 6, 10, -2, 7, s.color, (P_RandomRange(8, 16))*FRACUNIT)
			A_SAMPARTICLE(s, MT_MPR6, 8, 11, -2, 5, s.color, (P_RandomRange(4, 16))*FRACUNIT)
			A_SAMPARTICLE(s, MT_MPR6, 6, 10, -2, 6, s.color, (P_RandomRange(8, 16))*FRACUNIT)
			A_SAMPARTICLE(s, MT_MPR6, 8, 12, -2, 5, s.color, (P_RandomRange(8, 16))*FRACUNIT)
			A_SAMPARTICLE(s, MT_MPR6, 6, 11, -2, 6, s.color, (P_RandomRange(4, 16))*FRACUNIT)
			A_SAMPARTICLE(s, MT_MPR6, 8, 10, -2, 4, s.color, (P_RandomRange(8, 16))*FRACUNIT)
			A_SAMPARTICLE(s, MT_MPR6, 6, 12, -2, 5, s.color, (P_RandomRange(8, 16))*FRACUNIT)
			s.plexpand = P_SpawnMobj(s.x, s.y, s.z+(s.height*2), MT_PBEXPANDI)
			//	if s.plexpand
				s.plexpand.scale = $*P_RandomRange(2,6)
				s.plexpand.scalespeed = $*P_RandomRange(6, 10)
				s.plexpand.destscale = $*25
			//	end
			end
		end

		if s.health and not s.saldsalf and not (s.z <= s.floorz) and not (s.z > s.ceilingz-150*FRACUNIT)
			if (leveltime % 2 == 0)
			s.prevticx = s.x
			s.prevticy = s.y
			elseif not s.prevticx
			s.prevticx = s.x
			s.prevticy = s.y
			end
		s.prevticz = s.z
		end
		if s.health and not s.saldsalf
			if (s.z+s.height >= s.ceilingz-s.momz) and (P_MobjFlip(s) == 1) and not s.asfal
			s.asfal = true
			P_ExplodeMissile(s)
			end
		end
		if not s.saldsalf and ((s.state == S_ICCMXP1) or (s.state == S_ICCMXP2))
		A_Samuskillstuff(s, 370*FRACUNIT, 220*FRACUNIT, s.target, false, false, true)
		local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_ICBRSOUND)
			if s.prevticx
			P_MoveOrigin(s, s.prevticx, s.prevticy, s.prevticz)
			end
		S_StartSound(ghs, sfx_icbr)
			if s.target
			s.scale = s.target.scale*3
			else
			s.scale = 280355
			end
		A_SAMPARTICLE(s, MT_MPR7, 10, 9, -2, 7, s.color, (P_RandomRange(6, 10))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR7, 8, 8, -2, 5, s.color, (P_RandomRange(7, 10))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR7, 10, 9, -2, 6, s.color, (P_RandomRange(6, 10))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR7, 8, 8, -2, 5, s.color, (P_RandomRange(6, 10))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR7, 10, 9, -2, 6, s.color, (P_RandomRange(6, 10))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR7, 8, 8, -2, 5, s.color, (P_RandomRange(6, 10))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR7, 10, 9, -2, 5, s.color, (P_RandomRange(7, 10))*FRACUNIT)
		s.saldsalf = 1	
		P_StartQuake(10*FRACUNIT, 8, table, nil)
		S_StartSound(s, sfx_iccm2)
		S_StartSound(s, sfx_iccm2)
		
		elseif (s.state == S_ICCMXP4)
		A_SAMPARTICLE(s, MT_MPR6, 6, 15, -2, 20, s.color, (P_RandomRange(8, 16))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR6, 8, 16, -2, 18, s.color, (P_RandomRange(4, 16))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR6, 6, 15, -2, 19, s.color, (P_RandomRange(8, 16))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR6, 8, 17, -2, 18, s.color, (P_RandomRange(8, 16))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR6, 6, 16, -2, 19, s.color, (P_RandomRange(4, 16))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR6, 8, 15, -2, 17, s.color, (P_RandomRange(8, 16))*FRACUNIT)
		A_SAMPARTICLE(s, MT_MPR6, 6, 17, -2, 18, s.color, (P_RandomRange(8, 16))*FRACUNIT)
		end

//function A_SAMPARTICLE(s, object, coord, momentum, minuszmomentum, zmomentum, color, scale, spazer)

		if s.saldsalf
			s.saldsalf = $+1
			if s.addsaldsalf
			s.addsaldsalf = false
			s.saldsalf = $+100
			end
			if (s.saldsalf % 2 == 0) and s.target and (s.z+s.height >= s.ceilingz-200*FRACUNIT) and not (s.z < s.floorz+200*FRACUNIT)
				A_SAMPARTICLE(s, MT_ICCHARGESHOT, 10, 70, -22, -8, s.color, (P_RandomRange(8, 16))*FRACUNIT, "ice", s.target)
			elseif (s.saldsalf % 3 == 0) and (s.z+s.height < s.ceilingz-200*FRACUNIT) and (s.z > s.floorz+30*FRACUNIT)
				A_SAMPARTICLE(s, MT_ICCHARGESHOT, 10, 50, -4, 40, s.color, (P_RandomRange(8, 16))*FRACUNIT, "ice", s.target)
			elseif (s.saldsalf % 4 == 0) and (s.z <= s.floorz+30*FRACUNIT)
				A_SAMPARTICLE(s, MT_ICCHARGESHOT, 10, 45, 5, 45, s.color, (P_RandomRange(8, 16))*FRACUNIT, "ice", s.target)
			end
			if (s.saldsalf == 220)
			s.destscale = 5
			s.scalespeed = 2750
			s.saldsalf = 221
			
			elseif (s.saldsalf > 251)
			s.flags2 = $|MF2_SHADOW
			end
			if s.valid and ((s.saldsalf > 280) or (s.scale < 100))
			s.state = S_NULL
			return
			end
		end
end, MT_ICCHARGECOMBO)


addHook("MobjThinker", function(s)
	if (s.state == S_ICXP1)
	s.flags = $ & ~MF_SOLID
	end
end, MT_ICBLOCK)

local function RemoteFreeze(s)
	if s.tracer and s.tracer.frozenbox and s.tracer.health
		if not (s.frozencage and s.frozencage.valid)
		s.frozencage = P_SpawnMobj(s.x, s.y, s.z-s.height/3, MT_ICBLOCK)
		s.frozencage.scale = s.height/15
		s.frozenbox = true
		elseif (s.frozencage and s.frozencage.valid)
		local t = s.frozencage
			P_TryMove (s, t.x, t.y)
			t.fuse = 2
			s.momx = 0
			s.momy = 0
			s.momz = 0
			s.tics = 16
			
		end
	end 
end
local function RemoteFreezeFix(s) --Fix rare charged ice beam glitch
	if s.frozencage and s.frozencage.valid
	s.frozencage.state = S_NULL
	return
	end 
end
addHook("MobjRemoved", RemoteFreezeFix, MT_CRUSHCLAW)
addHook("MobjRemoved", RemoteFreezeFix, MT_BANPSPRING)
addHook("MobjThinker", RemoteFreeze, MT_CRUSHCLAW)
addHook("MobjThinker", RemoteFreeze, MT_BANPSPRING)

addHook("MobjThinker", function(s)
	if s.chozobox and s.chozobox.valid and s.samusshooter
		local m = s.chozobox
			if (m.frozenbox == nil) and (m.flags & (MF_ENEMY|MF_BOSS))
			and (m.flags & MF_SHOOTABLE)
				if (m.type == MT_SNAILER)
				m.lastsnailerz = m.z
				elseif (m.type == MT_DETON)
				m.state = m.info.spawnstate
				end
				if (m.health == 1)
				s.frozenboxstate = m.state
				s.frozenboxflags = m.flags
				s.frozenboxeflags = m.eflags
				s.frozenboxflags2 = m.flags2
				m.flags = MF_NOGRAVITY|MF_SCENERY
				m.momx = 0
				m.momy = 0
				m.momz = 0
				
				if m.target and m.target.player 
				and not (m.type == MT_DETON)
				and not ((m.flags == MF_BOSS|MF_SPECIAL|MF_BOUNCE) and (m.scale == 57000))
				m.target = nil
				end
				
				S_StartSound(m, sfx_icfr)
				s.frozentimer = 999
				s.frozencage = P_SpawnMobj(m.x, m.y, m.z-m.height/3, MT_ICBLOCK)
				s.frozencage.scale = m.height/15
				m.frozenbox = true
				return
				end
			elseif s.frozencage
			local t = s.frozencage
				if m and m.valid and m.frozenbox
				P_TryMove (t, m.x, m.y)
				P_SetMobjStateNF(m, s.frozenboxstate)
				t.flags = $|MF_NOCLIPHEIGHT
				t.z = m.z-m.height/3
				m.flags = MF_NOGRAVITY|MF_SCENERY
				m.momx = 0
				m.momy = 0
				m.momz = 0
				m.tics = 16
						if (m.type == MT_SNAILER) and m.lastsnailerz != nil
						m.z = m.lastsnailerz
						P_MoveOrigin(t, m.x, m.y, m.z)
						end
						if t.refreshiceblock
							t.refreshiceblock = false
							t.state = S_ICBLOCK
							t.scale = m.height/15
							s.frozentimer = 999
							S_StartSound(t, sfx_icfr)
						end
						--test3dice , no longer a test.
						for d = 1,4
							local ghs = P_SpawnMobj(t.x+FixedMul(t.radius, cos(t.angle+(ANGLE_90*d))), t.y+FixedMul(t.radius, sin(t.angle+(ANGLE_90*d))), t.z, MT_THOK)
								ghs.sprite = SPR_ICXP
								ghs.frame = F|TR_TRANS40|FF_PAPERSPRITE
								ghs.angle = (t.angle+(ANGLE_90*d))+ANGLE_90
								ghs.scale = t.scale
								ghs.tics = 2
								if d == 1
									for i = 0,1,1
										local ths = P_SpawnMobj(ghs.x-(t.radius), ghs.y-(t.radius), t.z+(t.height*i), MT_THOK)
										ths.sprite = SPR_ICXP
										ths.frame = F|TR_TRANS40
										ths.renderflags = $|RF_FLOORSPRITE|RF_NOSPLATBILLBOARD|RF_NOSPLATROLLANGLE
										ths.scale = t.scale
										ths.tics = 2							 
									end								
								end
						end
						
						if s and t and m and m.valid and (t.icethisfool or ((m.health <= 0)))
						t.flags = MF_NOGRAVITY
						t.state = S_ICXP1
						t.destscale = $*2
						t.yarhar = P_SpawnMobj(t.x, t.y, t.z, MT_ICBRSOUND)
						S_StartSound(t.yarhar, sfx_icbr)
							if (m.type == MT_DETON) --You're weird.
							m.flags = MF_SHOOTABLE
							m.state = m.info.spawnstate
							else
							m.state = s.frozenboxstate
							m.flags = s.frozenboxflags
							m.flags = $|MF_SHOOTABLE
							m.eflags = s.frozenboxeflags
							m.flags2 = s.frozenboxflags2
							end
							
							local docloserange = false
							for z in players.iterate
								if z.mo and not docloserange
									if (FixedHypot(FixedHypot(m.x-z.mo.x, m.y-z.mo.y), m.z-z.mo.z) < 1000*FRACUNIT)
										A_samquake(z.mo, 12*FRACUNIT, 10, 1)
											for d = 1,18
											local ghs = P_SpawnMobj(t.x+((P_RandomRange(-70, 70))*t.scale), t.y+((P_RandomRange(-70, 70))*t.scale), t.z+t.height/2, MT_MPR8)
											ghs.color = SKINCOLOR_SKY
											ghs.target = t 
												local rng = P_RandomRange(500, 55000)
												local angrng = P_RandomRange(-50,50)*ANG1
												P_InstaThrust(ghs, z.mo.angle+(angrng), z.speed+13*FRACUNIT)
												ghs.momz = (rng*18)+m.momz
												ghs.spriteyscale = $+(rng*3)
												ghs.spritexscale = $+(rng*3)
												ghs.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE
												ghs.frame = A+P_RandomRange(0,1)|((FRACUNIT*2)+(P_RandomRange(0,6)*FRACUNIT))
												ghs.blendmode = AST_ADD
												ghs.combograce = 6
												ghs.icesummon = s
												ghs.rollspeed = angrng
												ghs.rollnewangle = rng*ANG1
												docloserange = true
											end
									end
								end
							end
							if not docloserange
								--Ice Shatter time!
								for d = 1,16
								local ghs = P_SpawnMobj(t.x+((P_RandomRange(-70, 70))*t.scale), t.y+((P_RandomRange(-70, 70))*t.scale), t.z+t.height/2, MT_MPR8)
								ghs.color = SKINCOLOR_SKY
								ghs.target = t 
								ghs.momx = (P_RandomRange(-9, 9))*FRACUNIT+m.momx
								ghs.momy = (P_RandomRange(-9, 9))*FRACUNIT+m.momy
									local rng = P_RandomRange(500, 55000)
									ghs.momz = (rng*18)+m.momz
									ghs.spriteyscale = $+(rng*3)
									ghs.spritexscale = $+(rng*3)
									ghs.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE
									ghs.frame = A+P_RandomRange(0,1)|((FRACUNIT*2)+(P_RandomRange(0,6)*FRACUNIT))
									ghs.blendmode = AST_ADD
									ghs.combograce = 6
									ghs.icesummon = s
									ghs.rollspeed = P_RandomRange(-46,46)*ANG1
								ghs.rollnewangle = rng*ANG1	
								end
							end
						local samusrng = P_RandomRange(1, 201)
							if (samusrng < 5)
							m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+((m.height*2/3)*(P_MobjFlip(m))), MT_NRGA)
							elseif (samusrng < 8)
							m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+((m.height*2/3)*(P_MobjFlip(m))), MT_NRGB)
							elseif (samusrng < 70)
							m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+((m.height*2/3)*(P_MobjFlip(m))), MT_MPKU)
							elseif (samusrng < 72)
								if s.target and s.target.player and s.target.player.samsupermissilesmax
								m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+((m.height*2/3)*(P_MobjFlip(m))), MT_SPKU)
								end
							elseif (samusrng < 73)
								if s.target and s.target.player and s.target.player.sampwmax
								m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+((m.height*2/3)*(P_MobjFlip(m))), MT_PBOM)
								end
							end
						m.frozenbox = nil
						P_KillMobj(m, s, s.samusshooter)
						s.state = S_NULL
						return
						end
				end
			end
			if s.frozentimer
				s.frozentimer = $-1
				s.tics = 2
				s.flags2 = $|MF2_DONTDRAW --Lazy ahoy
				local ghs = P_SpawnMobjFromMobj(m, 0, 0, 0, MT_OVERLAY)		
				ghs.target = m
				if m.skin
					ghs.skin = m.skin
				end
				ghs.sprite = m.sprite
				ghs.sprite2 = m.sprite2
				ghs.frame = m.frame
				ghs.tics = 2
				ghs.rollangle = m.rollangle
				ghs.colorized = true
				ghs.color = SKINCOLOR_SKY
				
				if (s.frozentimer == 120) and s.frozencage
					s.frozencage.destscale = m.height/29
					s.frozencage.scalespeed = $/10
					s.frozencage.state = S_ICBLOCK2
				end
				
				if s.frozentimer and (s.frozentimer == 1) and m
				m.state = s.frozenboxstate
				m.flags = s.frozenboxflags
				m.flags = $|MF_SHOOTABLE
				m.eflags = s.frozenboxeflags
				m.flags2 = s.frozenboxflags2
				S_StartSound(m, sfx_icbf)
				m.frozenbox = nil
					if s.frozencage
						s.frozencage.blendmode = AST_ADD
						s.frozencage.state = S_ICXP1
					end
					if s.valid
					s.state = S_NULL
					return
					end
				end
			elseif s.valid
				s.state = S_NULL
				return
			end
	elseif s.valid
	s.state = S_NULL
	return
	end
end, MT_FREEZETRACKER)
addHook("MobjLineCollide", function(s, i)
	return false
end, MT_ICBLOCK)

addHook("MobjThinker", function(s)
		if not s.samusshot
		s.samusshot = true
		s.gvtimer = 18
			if not s.gattlingvortex and not s.darkhyper
				s.color = SKINCOLOR_RED
			end
		end
		s.flameangle = R_PointToAngle2(s.x, s.y, s.x+s.momy, s.y+s.momy)
		if s.gattlingvortex and s.health
			if (s.z+s.momz <= s.floorz+65355)
				s.momz = 0
			end
			if (s.z+s.height+s.momz > s.ceilingz-95355)
				s.momz = 0
			end			
			if not ((s.eflags & MFE_TOUCHWATER) or (s.eflags & MFE_UNDERWATER))
				if s.gattlingvortex1
					if (leveltime % 2 == 0) and s.plshottimer
					A_SAMPARTICLE(s, MT_MINIEXP, 15, 20, -15, 15, SKINCOLOR_ORANGE, P_RandomRange(38355, 59355)*3)
					end
					if (s.gvtimer > 3) and (s.z+s.momz <= s.floorz+150*FRACUNIT)
					local ghs = SamShinySplat(s,SKINCOLOR_FLAME, (s.gvtimer-3))
					ghs.frame = A|TR_TRANS70|FF_FULLBRIGHT
					end
				else			
					local sampng = P_RandomRange(1, 11)
					if (sampng < 5) and (leveltime % 2 == 0) and s.target
					A_SAMPARTICLE(s, MT_MINIFIRE, 19, 1, -195, -176, s.color, P_RandomRange(48355, 65354)*2, s.target)
					end
				end
			end
		end
		if not s.darkhyper
			if (s.state == S_PLSHOT1)		
				if (leveltime % 3 == 0) and s.gattlingvortex
					A_SAMPARTICLE(s, MT_MPR5, 6, 8, -2, 6, s.color, P_RandomRange(24355, 48355))
				else
					A_SAMPARTICLE(s, MT_MPR5, 6, 5, -2, 6, s.color, P_RandomRange(12355, 24355))
				end
				
				s.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
				s.rollangle = leveltime*ANG30

				if (s.gvtimer > 2)
					s.gvtimer = $-1	
					if (s.gvtimer > 12)
					s.spriteyscale = FRACUNIT/(s.gvtimer/4)
					s.spritexscale = FRACUNIT/(s.gvtimer/6)		
					elseif (s.gvtimer > 2)
					s.spriteyscale = FRACUNIT-(s.gvtimer*800)
					s.spritexscale = FRACUNIT-(s.gvtimer*900)
					end
					s.spriteyoffset = (8*FRACUNIT)-(s.spriteyscale*8)
				else
					s.spriteyoffset = 0
					s.spritexscale = FRACUNIT
					s.spriteyscale = FRACUNIT	
				end
				
				if not s.gattlingvortex or (s.plshottimer and s.plshottimer < 18)
				or s.gattlingvortex1 or (leveltime % 3 == 0) or (leveltime % 2 == 0)
				
					if s.ghs and s.ghs.valid --Not a local variable.
						s.ghs.blendmode = s.blendmode
						if leveltime % 3 == 0
							s.ghs.rollangle = s.rollangle+ANGLE_90
						else
							s.ghs.rollangle = s.rollangle-ANGLE_90
						end
						s.ghs.spriteyscale = s.spriteyscale
						s.ghs.spritexscale = s.spritexscale
					end
					s.ghs = P_SpawnGhostMobj(s)
					s.ghs.fuse = 10
					s.ghs.tics = 12
					s.ghs.scalespeed = $/3
					s.ghs.destscale = s.ghs.scalespeed+1
					s.ghs.spriteyscale = s.spritexscale --Intentionally reverse x and yscale
					s.ghs.spritexscale = s.spriteyscale
					s.ghs.blendmode = s.blendmode
					s.ghs.rollangle = s.rollangle
				end
			elseif not s.saldsalf and (s.state == S_PLXP1)
				local ghs = P_SpawnMobjFromMobj(s,0,0,0, MT_THOK)
				ghs.flags2 = $|MF2_DONTDRAW ghs.tics = 99
				S_StartSound(ghs, sfx_plxpz)
				S_StartSound(ghs, sfx_plxpz)
				s.destscale = s.scale*15
				MonitorBreaker(s, s.target)
				s.scalespeed = $*2
				s.saldsalf = true
		--		SamusShotImpact(s)
				SamusBulletHole(s, s.scale+9900, SKINCOLOR_RED, true)
				
				if s.flameangle != nil
					for d = -3,3
					local rng = P_RandomRange(-7,7)
					ghs = P_SpawnMobjFromMobj(s,0,0,0, MT_THOK)
					ghs.sprite = SPR_MXP4
					ghs.blendmode = AST_ADD
					ghs.tics = 99
					ghs.scale = $/3 ghs.scalespeed = $*4
					ghs.destscale = $*99
					ghs.rollangle = $+(rng*ANG20)
						if d > 0 or s.gattlingvortex
						ghs.colorized = true
						ghs.color = s.color
						end
					ghs.renderflags = $|RF_FULLBRIGHT //|RF_PAPERSPRITE
					ghs.angle = s.flameangle+ANGLE_90+(rng*(ANG10))+(ANG20*d)
					P_SetObjectMomZ(ghs, d*FRACUNIT+(2*FRACUNIT), true)
						if s.gattlingvortex
						ghs.fuse = 16
						P_InstaThrust(ghs, ghs.angle, -40*FRACUNIT)
						else
						ghs.fuse = 9
						P_InstaThrust(ghs, ghs.angle, -12*FRACUNIT)						
						end
					end
				end
				if not s.gattlingvortex  --Open monitors easier, pls.
					searchBlockmap("objects", function(ref, m)
						if (m.flags & (MF_MONITOR)) and m.health and (m.flags & (MF_SHOOTABLE))
							if not (s.x > m.x+120*FRACUNIT) and not (s.x < m.x-120*FRACUNIT)
							and not (s.y > m.y+120*FRACUNIT) and not (s.y < m.y-120*FRACUNIT)
							and not (s.z > m.z+120*FRACUNIT) and not (s.z < m.z-120*FRACUNIT)		
								A_SAMITEM(s, m)
							end
						end
					end, s, s.x-(120*FRACUNIT), s.x+(120*FRACUNIT), s.y-(120*FRACUNIT), s.y+(120*FRACUNIT))		
				end
				
				if s.gattlingvortex1
					A_Samuskillstuff(s, 90*FRACUNIT, 80*FRACUNIT, s.target, true)			
				end
			end
		else
		
			s.spriteyoffset = 0
			s.spritexscale = FRACUNIT
			s.spriteyscale = FRACUNIT
			
			if not s.colorized
				s.colorized = true
				P_Thrust(s, P_RandomRange(1,359)*ANG1, P_RandomRange(-10,10)*FRACUNIT)
				P_SetObjectMomZ(s, P_RandomRange(-5,5)*FRACUNIT, true)
			end
			LeafSpawn(s, nil, true, 200)
			local ghs = P_SpawnGhostMobj(s)
			ghs.blendmode = AST_ADD
			ghs.color = SKINCOLOR_COBALT
			P_Thrust(ghs, P_RandomRange(1,359)*ANG1, P_RandomRange(-30,30)*FRACUNIT)
			P_SetObjectMomZ(ghs, P_RandomRange(-10,10)*FRACUNIT, true)			
			ghs.destscale = $*P_RandomRange(1,6)
			if leveltime % 2 == 0
				A_SAMPARTICLE(s, MT_MPR5, 6, 8, -2, 6, SKINCOLOR_COBALT, P_RandomRange(24355, 48355))
				s.color = SKINCOLOR_JET
			else
				s.color = P_RandomRange(SKINCOLOR_SUPERSKY1, SKINCOLOR_SUPERSKY3)
			end
		end
		if not s.plshottimer
			s.plshottimer = 18
		elseif s.valid and (s.plshottimer == 1)
			s.state = S_NULL
			return
		else
			s.plshottimer = $-1
		end
end, MT_PLSHOT)

addHook("MobjThinker", function(s)
	if s.health
		if s.morning
		s.morning = $-1
		s.blendmode = AST_ADD
		s.samusshot = true
		end
		if (s.morning == 1) and s.valid
		P_KillMobj(s)
		return
		elseif ((s.eflags & MFE_TOUCHWATER) or (s.eflags & MFE_UNDERWATER)) and s.valid
		s.state = S_NULL
		return
		end
	end
end, MT_MINIFIRE)

local function FireCollide(s, m)
	if not (m and m.valid)
	return false
	end
	if (m.type == MT_METROIDPART or m.type == MT_METROIDBOSS or m.type == MT_METROIDSLASH)
	return false
	end
	if s.health
		if not (s.z > m.z+m.height) and not (m.z+m.height < s.z)
		and not (s.target and (s.target == m))
			if s.target and m and m.health and ( (m.flags & (MF_ENEMY|MF_BOSS)) or m.player)
				if G_GametypeHasTeams() and m.player and m.player.ctfteam and s.target.player and s.target.player.ctfteam
				and m.player.ctfteam == s.target.player.ctfteam
				else
				s.samusshot = true
				P_DamageMobj(m, s, s.target, 1)
				P_KillMobj(s, m, m)
				end
			elseif not s.target and m and m.health and ((m.flags & (MF_ENEMY|MF_BOSS)) or m.player)
			s.samusshot = true
			P_DamageMobj(m, s, s, 1)
			P_KillMobj(s, m, m)
			end
		end
	end
	return false
end
addHook("MobjCollide", FireCollide, MT_MINIFIRE)
addHook("MobjMoveCollide", FireCollide, MT_MINIFIRE)

addHook("MobjThinker", function(s)
	if s.morning
	s.morning = $-1
	s.blendmode = AST_ADD
	local samuszng = P_RandomRange(1,3)	
		if (samuszng < 2)
			if (s.state == S_SAMZAP1)
			s.state = S_SAMZAP3
			elseif (s.state == S_SAMZAP2)
			s.state = S_SAMZAP1
			elseif (s.state == S_SAMZAP3)
			s.state = S_SAMZAP2
			elseif (s.state == S_SAMZAP4)
			s.state = S_SAMZAP2
			end
		elseif (samuszng == 2)
			if (s.state == S_SAMZAP1)
			s.state = S_SAMZAP4
			elseif (s.state == S_SAMZAP2)
			s.state = S_SAMZAP3
			elseif (s.state == S_SAMZAP3)
			s.state = S_SAMZAP1
			elseif (s.state == S_SAMZAP4)
			s.state = S_SAMZAP3
			end
		else
			if (s.state == S_SAMZAP1)
			s.state = S_SAMZAP2
			elseif (s.state == S_SAMZAP2)
			s.state = S_SAMZAP4
			elseif (s.state == S_SAMZAP3)
			s.state = S_SAMZAP4
			elseif (s.state == S_SAMZAP4)
			s.state = S_SAMZAP1
			end
		end
	elseif s.valid
	s.state = S_NULL
	end
end, MT_SAMUSZAP)

addHook("MobjThinker", function(s)
		if not s.color
			s.color = SKINCOLOR_RED
		end	
		--Setup
		s.samusshot = true
		s.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
		
		--While charge shot is flying	
		if ((s.state == S_PLSHOT1) or (s.state == S_PLSHOT2))
		A_SAMPARTICLE(s, MT_MPR5, 7, 5, -2, 8, s.color, P_RandomRange(52355, 74355))		
		local ghs = P_SpawnGhostMobj(s) --Afterimages
		ghs.blendmode = AST_ADD
		ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS

			local groundcrash = false
			--Fancy groundcrashing firewaves
			if (s.z+s.momz <= s.floorz+30*FRACUNIT)
				groundcrash = true
				if (s.z+s.momz <= s.floorz+65355)
				s.momz = 0
				end
			elseif (s.z+s.height+s.momz > s.ceilingz-30*FRACUNIT)
				groundcrash = true
				if (s.z+s.height+s.momz > s.ceilingz-115355)
				s.momz = 0
				end
			end
			if groundcrash
				local ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
				ghs.angle = s.angle+ANGLE_90
				ghs.sprite = SPR_PHAZ
				ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
				ghs.spriteyscale = FRACUNIT/2
				ghs.spritexscale = 85000
				ghs.color = s.color
				ghs.colorized = true
				ghs.tics = 20
					if leveltime % 2 == 0
						ghs.fuse = 10
						ghs.frame = K|FF_PAPERSPRITE|FF_FULLBRIGHT
						ghs.scalespeed = $*P_RandomRange(1,3)
					else
						ghs.fuse = 18
						ghs.frame = J|TR_TRANS20|FF_PAPERSPRITE|FF_FULLBRIGHT
						ghs.blendmode = AST_ADD
						ghs.scalespeed = $/2
					end
				ghs.destscale = $*99
			end

			if (s.state == S_PLSHOT1)
				local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_PBEXPAND)
				if ghs
				ghs.scale = $*P_RandomRange(2,3)
				ghs.scalespeed = $*P_RandomRange(7, 11)
				ghs.destscale = $*25
				ghs.blendmode = AST_ADD
				end
			
				A_SAMPARTICLE(s, MT_MINIEXP, 15, 20, -10, 10, s.color, P_RandomRange(38355, 59355)*3)
		
				ghs = P_SpawnMobj(s.x+FixedMul(-400*FRACUNIT, cos(s.angle)), s.y+FixedMul(-400*FRACUNIT, sin (s.angle)), s.z-(s.momz*2), MT_PBEXPAND)
				if ghs
				ghs.blendmode = AST_ADD
				ghs.scale = $*P_RandomRange(1,2)
				ghs.scalespeed = $*P_RandomRange(2, 4)
				ghs.destscale = $*25
				ghs.blendmode = AST_ADD
				end
			end
		end

		--Did the shot explode?

		if (s.state == S_PLXP1) and not s.saldsalf
		SamFaceReflect(s, 110*FRACUNIT)
		SamusBulletHole(s, s.scale*3, SKINCOLOR_RED, true)
		
		s.scale = s.scale*2
		MonitorBreaker(s, s.target, s.scale*2)
		A_SAMUSEXPLOSIONS(s, 2, MT_SAMMISSILESMOKE, false, 50000, SKINCOLOR_RED)
		A_SAMPARTICLE(s, MT_MPR5, 7, 4, -2, 8, s.color, 99355)
		A_SAMPARTICLE(s, MT_MPR5, 7, 4, -2, 8, s.color, 94355)
		A_SAMPARTICLE(s, MT_MPR5, 7, 4, -2, 8, s.color, 99999)
		A_SAMPARTICLE(s, MT_MPR5, 7, 4, -2, 8, s.color, 97955)
		s.destscale = s.scale*30
		s.scalespeed = $*6
		s.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
		P_SetObjectMomZ(s, -85355)
		s.saldsalf = true

				searchBlockmap("objects", function(ref, m)
					if (m.flags & (MF_MONITOR)) and m.health and (m.flags & (MF_SHOOTABLE))
						if not (s.x > m.x+180*FRACUNIT) and not (s.x < m.x-180*FRACUNIT)
						and not (s.y > m.y+180*FRACUNIT) and not (s.y < m.y-180*FRACUNIT)
						and not (s.z > m.z+180*FRACUNIT) and not (s.z < m.z-180*FRACUNIT)		
							A_SAMITEM(s, m)
						end
					end
				end, s, s.x-(180*FRACUNIT), s.x+(180*FRACUNIT), s.y-(180*FRACUNIT), s.y+(180*FRACUNIT))		
		
		end
		
		if not s.plshottimer
			s.plshottimer = 17
		elseif s.valid and (s.plshottimer == 1)
			s.state = S_NULL
			return
		else
			s.plshottimer = $-1
		end
end, MT_PLCHARGESHOT)

--Disintegrate players and enemies to dust.
local function plasmadustspawn(s, d)
				local rng = P_RandomRange(3,12)
				local dust = P_SpawnMobj(s.dtxloc+P_RandomRange(0, s.dtradius/FRACUNIT)*3*s.dtscale, s.dtyloc+P_RandomRange(0, s.dtradius/FRACUNIT)*3*s.dtscale, s.dtzloc+P_RandomRange(0, s.dtheight/FRACUNIT)*2*s.dtscale, MT_THOK)
				dust.sprite = SPR_MPR9
				dust.renderflags = $|RF_FULLBRIGHT
				dust.shadowscale = 6000
				dust.tics = 3+rng
				dust.blendmode = AST_ADD
				dust.scale = (s.dtscale*10/rng)
				dust.frame = W|(TR_TRANS10*(rng/3))
				dust.angle = s.dtangle+ANGLE_90
				if d
				P_Thrust(dust, (((ANG1*4)*4)*d), (rng*4)*FRACUNIT)
				P_SetObjectMomZ(s, (rng*2)*s.dtscale, true)
				else
				P_Thrust(dust, dust.angle+(P_RandomRange(-40,40)*ANG1), rng*FRACUNIT)
				P_SetObjectMomZ(s, (rng-3)*s.dtscale, true)
				end
					if s.formershell and s.formershell.valid			
					local husk = s.formershell
					husk.tics = 4
						if s.plasmadust
						husk.color = SKINCOLOR_PLASMABURNED					
							--Flamey back gfx
							if (husk.fuse > 35)
								if leveltime % 3 == 0
									local rng = P_RandomRange(1,10)
									local ghs = P_SpawnMobjFromMobj(husk, 0, 0, rng*FRACUNIT, MT_THOK)
									ghs.sprite = SPR_MXP4
									ghs.frame = S|TR_TRANS30+((rng/2)*FRACUNIT)|FF_FULLBRIGHT
									ghs.dispoffset = -3
									ghs.tics = rng+3
									ghs.fuse = ghs.tics-1
									ghs.blendmode = AST_ADD
									ghs.scale = (husk.scale/15)*rng
									if rng % 3 == 0
										ghs.color = SKINCOLOR_SUPERGOLD5
										ghs.colorized = true
									elseif rng % 2 == 0
										ghs.color = SKINCOLOR_CRIMSON
										ghs.colorized = true					
									end
									ghs.rollangle = rng*ANG30
									ghs.scalespeed = $*rng
									ghs.destscale = $*99
								end
							end
						elseif s.hyperdust
						husk.color = SKINCOLOR_WHITE
						else
						husk.color = SKINCOLOR_BEIGE				
						end
					end
					if s.plasmadust
					
						if leveltime % 7 == 0 or rng == 4
						dust.color = SKINCOLOR_SUPERGOLD4
						elseif leveltime % 13 == 0
						dust.color = SKINCOLOR_CRIMSON
						else
						dust.color = SKINCOLOR_PLASMABURNED
						dust.blendmode = 0
						end
						
					elseif s.hyperdust
						dust.color = SKINCOLOR_WHITE
						dust.blendmode = AST_ADD
					else
						dust.color = SKINCOLOR_BEIGE				
					end
end

addHook("MobjThinker", function(s)

	if s.target and s.target.valid --While our target's still here....
	local t = s.target
			if t and t.valid and t.player
				if t.crystalflashanim
					if s.formershell and s.formershell.valid
					s.formershell.state = S_NULL
					end
					if s.valid --WAIT, STOP, SON
					t.flags = $ & ~MF_NOGRAVITY & ~MF_NOCLIPTHING
					s.state = S_NULL
					return
					end
				elseif S_OriginPlaying(t)
				S_StopSound(t)
				end
			end	
		t.momx = 0 t.momy = 0 t.momz = 0
		t.sprite2 = SPR2_DEAD
		t.frame = A|FF_FULLBRIGHT
		t.flags = $|MF_NOGRAVITY|MF_NOCLIPTHING
		t.flags2 = $|MF2_DONTDRAW
	end
	
	if s.dtframe != nil
	
		if s.formershell and s.formershell.valid // and s.dusttracker and (t.tics < 9)
			if s.trnset == nil
			s.trnset = 0
				if P_RandomRange(0,1)
				s.dtexplodepushd = 1
				else
				s.dtexplodepushd = -1
				end
			end
			if s.dtexplodepush
			s.dtexplodepush = $+1
			s.formershell.color = FlashMobjC[P_RandomRange(1,5)]
			s.formershell.colorized = true
			s.formershell.frame = s.selectedframe or 0
			
				--Rolling!
				s.dtrollangle = s.dtrollangle and $+(ANG30*s.dtexplodepushd) or (ANG30*s.dtexplodepushd)
				s.formershell.rollangle = s.dtrollangle
				s.formershell.angle = s.dtrollangle
				
				if (s.dtexplodepush > 12)
				P_SetObjectMomZ(s.formershell, -FRACUNIT/2, true)
				end
				if P_IsObjectOnGround(s.formershell)
				 	if not s.waitatic
					s.waitatic = true
					elseif s.formershell.valid
					s.ghs = P_SpawnMobj(s.formershell.x, s.formershell.y, s.formershell.z, MT_SONIC3KBOSSEXPLODE)
					s.ghs.scale = s.formershell.scale*3
					S_StartSound(s.ghs, sfx_mtrdb)
					s.formershell.state = S_NULL
					s.state = S_NULL
					return
					end
				end
			else
			s.formershell.frame = s.selectedframe|(s.trnset)|FF_FULLBRIGHT	
			end
			if s.superdisintegrate and (s.formershell.fuse > 82) and (s.formershell.fuse % 2 == 0)
				s.ghs3 = P_SpawnGhostMobj(s.formershell)
				s.ghs3.rollangle = P_RandomRange(1,359)*ANG1
				s.ghs3.color = SKINCOLOR_SUPERGOLD3
				s.ghs3.colorized = true
			end
			if not s.dtexplodepush and (s.formershell.fuse % 6 == 0) and not (s.trnset == TR_TRANS90)
				if not s.trnplus
				s.trnplus = true
				else
					if s.superdisintegrate and not s.scalespeeddoubled
					s.formershell.scalespeed = $*2
					s.scalespeeddoubled = true
					end				
				s.trnset = $+FRACUNIT
				end
			end
			s.dtxloc = s.formershell.x s.dtyloc = s.formershell.y s.dtzloc = s.formershell.z
			P_MoveOrigin(s, s.formershell.x, s.formershell.y, s.formershell.z)
			s.tics = s.formershell.tics
			s.fuse = s.formershell.fuse
			
			if not s.dtexplodepush --I mean, they're dead, right??
				if not s.firstdboom
					s.firstdboom = true
					for d = 1,45
					plasmadustspawn(s, d)
					end
				else
				plasmadustspawn(s)
				end
			end
		end
	end
end, MT_DUSTTRACKER)

addHook("MobjThinker", function(s)
	s.samusshot = true
	s.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
	s.flags2 = $|MF2_RAILRING
	s.blendmode = AST_ADD
		if s.darkhyper
			if leveltime % 3 == 0
			s.color = SKINCOLOR_COBALT
			else
			s.color = SKINCOLOR_SKY
			end
			s.colorized = true
		end	
		if s.truehyper
			if not s.truehyperspawn

				local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_HBSHOT)
				ghs.target = s.target
				ghs.eflags = s.eflags ghs.flags2 = s.flags2 ghs.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE ghs.thfuse = 40
				ghs.scale = s.scale ghs.angle = s.angle+(ANG2*1)
				ghs.momz = s.momz-10*FRACUNIT
				P_Thrust(ghs, s.angle+(ANG2*1), FixedMul(ghs.info.speed, s.target.scale))

				ghs = P_SpawnMobj(s.x, s.y, s.z, MT_HBSHOT)
				ghs.target = s.target
				ghs.eflags = s.eflags ghs.flags2 = s.flags2 ghs.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE ghs.thfuse = 40
				ghs.scale = s.scale ghs.angle = s.angle+(ANG2*3)
				ghs.momz = s.momz+10*FRACUNIT
				P_Thrust(ghs, s.angle+(ANG2*3), FixedMul(ghs.info.speed, s.target.scale))

				ghs = P_SpawnMobj(s.x, s.y, s.z, MT_HBSHOT)
				ghs.target = s.target
				ghs.eflags = s.eflags ghs.flags2 = s.flags2 ghs.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE ghs.thfuse = 40
				ghs.scale = s.scale ghs.angle = s.angle-(ANG2*3)
				ghs.momz = s.momz-10*FRACUNIT
				P_Thrust(ghs, s.angle-(ANG2*3), FixedMul(ghs.info.speed, s.target.scale))

				ghs = P_SpawnMobj(s.x, s.y, s.z, MT_HBSHOT)
				ghs.target = s.target
				ghs.eflags = s.eflags ghs.flags2 = s.flags2 ghs.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE ghs.thfuse = 40
				ghs.scale = s.scale ghs.angle = s.angle-(ANG2*5)
				ghs.momz = s.momz+10*FRACUNIT
				P_Thrust(ghs, s.angle-(ANG2*5), FixedMul(ghs.info.speed, s.target.scale))


			s.truehyperspawn = true
			end
		end

		if s.thfuse
		s.thfuse = $-1
			if ( ((s.thfuse == 36 or s.thfuse == 10) and not (s.flags & MF_BOUNCE)) or ((s.thfuse == 29 or s.thfuse == 17) and (s.flags & MF_BOUNCE)) )
			and s.target
			s.pwbomb2 = P_SpawnMobj(s.x, s.y, s.z, MT_SAMSUPERMISSILE)
			s.pwbomb2.target = s.target
			s.pwbomb2.smhyper = true
				if s.pwbomb2 and s.pwbomb2.health
				P_ExplodeMissile(s.pwbomb2)
				end
			end
			if s.valid and s.thfuse == 1 and s.health
			s.momx = 0 s.momy = 0 s.momz = 0
			P_KillMobj(s)
			return
			end
		end
		
		if (s.state == S_HBSHOT3) or (s.state == S_PLSHOT2) or (s.state == S_PLSHOT1)
			if (s.state == S_HBSHOT3) and not s.saldsalf2
			A_SAMPARTICLE(s, MT_MPR5, 6, 5, -2, 6, s.color,99355)
			A_SAMPARTICLE(s, MT_MPR5, 6, 5, -2, 6, s.color,99355)
			A_SAMPARTICLE(s, MT_MPR5, 6, 5, -2, 6, s.color,99355)
			A_SAMPARTICLE(s, MT_MPR5, 6, 5, -2, 6, s.color,99355)
			A_SAMPARTICLE(s, MT_MPR5, 6, 5, -2, 6, s.color,99355)
			A_SAMPARTICLE(s, MT_MPR5, 6, 5, -2, 6, s.color,99355)
			P_SpawnGhostMobj(s)
			s.saldsalf2 = true
			end		
		A_SAMPARTICLE(s, MT_MPR1, 9, 6, -2, 6, s.color, P_RandomRange(42355, 64355))
			if s.darkhyper
				local ghs = P_SpawnGhostMobj(s)
				ghs.blendmode = AST_ADD
				ghs.tics = 24
				ghs.fuse = 24
				ghs.color = P_RandomRange(SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERSILVER5)
				ghs.scale = $/P_RandomRange(1,2)
				ghs.scalespeed = $/P_RandomRange(2,8)
				ghs.destscale = s.scalespeed+1
			else
				local ghs = P_SpawnGhostMobj(s)
				ghs.blendmode = AST_ADD
				ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
			end


			if (leveltime % 2 == 0)
			
				local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_PBEXPANDW)
				if ghs
				ghs.scale = $*P_RandomRange(1,3)
				ghs.blendmode = AST_ADD
				ghs.scalespeed = $*P_RandomRange(1, 8)
				ghs.destscale = $*20
					if s.darkhyper
					ghs.colorized = true
					ghs.color = SKINCOLOR_JET
					end
				end
				local ghs = P_SpawnMobj(s.x+FixedMul(-400*FRACUNIT, cos(s.angle)), s.y+FixedMul(-400*FRACUNIT, sin (s.angle)), s.z-(s.momz*2), MT_PBEXPAND)
				if ghs
				ghs.blendmode = AST_ADD
				ghs.scale = $*P_RandomRange(1,2)
				ghs.scalespeed = $*P_RandomRange(2, 4)
				ghs.destscale = $*25
					if s.darkhyper
					ghs.colorized = true
					ghs.color = SKINCOLOR_JET
					end				
				end
			else
			local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_PBEXPANDI)
				if ghs
				ghs.blendmode = AST_ADD
				ghs.scale = $*P_RandomRange(1,3)
				ghs.scalespeed = $*P_RandomRange(3, 9)
				ghs.destscale = $*25
					if s.darkhyper
					ghs.colorized = true
					ghs.color = SKINCOLOR_SUPERSKY2
					end		
				end
			end
		elseif not s.saldsalf and (s.state == S_HBXP1) 
		s.saldsalf = true
			if s.wallclipped and s.target
			local t = s.target
			P_Thrust(t, t.angle, -9*FRACUNIT)
			P_MoveOrigin(s, t.x, t.y, t.z+(t.height/2))
			end		
			SamFaceReflect(s, 500*FRACUNIT)
			for i = -2,3
			local ghs
				if i < 0
				ghs = P_SpawnMobj(s.x, s.y, s.z, MT_THOK)
				ghs.flags = $ & ~MF_NOCLIPHEIGHT
				else
				ghs = P_SpawnMobj(s.x, s.y, s.z+(45*i)*FRACUNIT, MT_THOK)
				end
				ghs.scale = s.scale/10
				ghs.tics = 24+(i*2)
				ghs.sprite = SPR_HBXP
				ghs.frame = E|TR_TRANS60|FF_FULLBRIGHT
				if i < 1
				ghs.scalespeed = $*(-2*(i))
				else
				ghs.momz = i*(4*FRACUNIT)
				ghs.scalespeed = $/i
				ghs.frame = C|TR_TRANS80|FF_FULLBRIGHT
				end
				ghs.destscale = FRACUNIT*99
				ghs.color = P_RandomRange(SKINCOLOR_SUPERGOLD1, SKINCOLOR_SUPERPURPLE2)
			end
		
			s.missilelight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_SAMMISSILELIGHT)
			s.missilelight.scale = s.scale/10
			s.missilelight.blendmode = AST_ADD
			s.missilelight.scalespeed = $*10/7
			s.missilelight.color = s.color
			s.missilelight.layers = 4
			s.missilelight.blendmode = AST_ADD
		
			if s.darkhyper
			S_StartSound(nil, sfx_bgxpld)
			S_StartSound(nil, sfx_smexp) S_StartSound(s, sfx_smexp)
			S_StartSound(nil, sfx_brakrx)
			P_StartQuake(80*FRACUNIT, 28)
				for z in players.iterate
					if z.mo and z.mo.health
						if (FixedHypot(FixedHypot(s.x-z.mo.x, s.y-z.mo.y), s.z-z.mo.z) < 125*FRACUNIT)
						P_DamageMobj(z.mo, s, s.target) --Don't get near this thing...
						end
					end
				end
			end			
		elseif not s.saldsalf3 and (s.state == S_HBXP5)
		A_SAMUSEXPLOSIONS(s, 28, MT_SAMMISSILESMOKE, false, 1)	
		if not s.darkhyper
		P_StartQuake(10*FRACUNIT, 16)
		end
		s.destscale = s.scale*3
		s.scalespeed = $/2
			for z in players.iterate
				if z.mo
					if (FixedHypot(FixedHypot(s.x-z.mo.x, s.y-z.mo.y), s.z-z.mo.z) < 650*FRACUNIT)
					A_samquake(z.mo, 33*FRACUNIT, 23, 1)
					P_SamFP(z, PAL_RECYCLE, 4) --Ouch, too close to the flashing explosion.
					end
				end
			end
			if (s.flags & MF_BOUNCE)
			s.momx = 0 s.momy = 0 s.momz = 0
			end
			if s.truehyper and s.target
			s.pwbomb = P_SpawnMobj(s.x, s.y, s.z, MT_SAMPOWERBOMB)
			s.pwbomb.target = s.target
			s.pwbomb.thcolors = s
				if s.pwbomb and s.pwbomb.valid and s.pwbomb.health
				P_KillMobj(s.pwbomb)
				end
			end
			if not s.darkhyper
				if G_GametypeHasSpectators()
				A_Samuskillstuff(s, 550*FRACUNIT, 375*FRACUNIT, s.target, false, true)
				else
				A_Samuskillstuff(s, 650*FRACUNIT, 450*FRACUNIT, s.target, false, true)
				end
			end
		s.saldsalf3 = true
		end
		if s.valid and s.pwbomb and s.pwbomb.valid and s.pwbomb.health and s.target
		s.pwbomb.target = s.target
		P_ExplodeMissile(s.pwbomb)
		end
		if s.saldsalf
			if s.darkhyper
			LeafSpawn(s, nil, true, 550)
			else
			A_SAMPARTICLE(s, MT_MPR4, 45, 16, -1, 14, s.color, P_RandomRange(49355, 69355))
				if leveltime % 11 == 0
					if s.z > s.ceilingz-95*FRACUNIT
					or s.z < s.floorz+95*FRACUNIT
					local ghs = SamShinySplat(s,s.color, 20)
					ghs.frame = A|TR_TRANS50|FF_FULLBRIGHT
					ghs.scale = $*2 ghs.destscale = FRACUNIT*99
					end
				end
			end
		end
		if not s.darkhyper
			if s.wavebeamtimer or (s.wavebeamtimer == 0)
				if (s.wavebeamtimer > 16)
				s.color = SKINCOLOR_SKY
				elseif (s.wavebeamtimer > 14)
				s.color = SKINCOLOR_BLUE
				elseif (s.wavebeamtimer > 12)
				s.color = SKINCOLOR_MAGENTA
				elseif (s.wavebeamtimer > 10)
				s.color = SKINCOLOR_PINK
				elseif (s.wavebeamtimer > 8)
				s.color = SKINCOLOR_CLOUDY
				elseif (s.wavebeamtimer > 6)
				s.color = SKINCOLOR_GOLD
				elseif (s.wavebeamtimer > 4)
				s.color = 29
				elseif (s.wavebeamtimer > 2)
				s.color = 32
				else
				s.color = SKINCOLOR_EMERALD
				end
			end
			if not s.wavebeamtimer
			s.wavebeamtimer = 18
			else
			s.wavebeamtimer = $-1
			end
		elseif s.darkhyper
			LeafSpawn(s, nil, true, 450)
			if leveltime % 3 == 0
			s.color = SKINCOLOR_COBALT
			else
			s.color = SKINCOLOR_SKY
			end
			s.colorized = true
		end
end, MT_HBSHOT)

local function SpiderGrow(s) --Spiderball grows other objects too that mapthingspawn fucks up with.
	if s.valid
		if not s.saldsalfy
		s.scale = FRACUNIT*5/2
		s.saldsalfy = true
			for m in mobjs.iterate(mobjs)
				if m and m.valid and not m.saldsalfy
				and ((m.type == MT_VRST) or (m.type == MT_GVST) or (m.type == MT_SATK)
				or (m.type == MT_MHBM) or (m.type == MT_CHBM) or (m.type == MT_SJMP))
				m.scale = FRACUNIT*5/2
				m.saldsalfy = true
					if (m.type == MT_SJMP)
					m.scale = 43570
					end
				end
			end
		end
	end
end
local function QuickGrow(s)
	if s.valid and not s.saldsalf
	s.scale = s.scale*5/2
	s.saldsalf = true
	end
end
addHook("MobjThinker", SpiderGrow, MT_SPDRBL)
addHook("MobjSpawn", QuickGrow, MT_SPDRBL)
addHook("MobjSpawn", QuickGrow, MT_MHBM)
addHook("MobjSpawn", QuickGrow, MT_GVST)
addHook("MobjSpawn", QuickGrow, MT_VRST)
addHook("MobjSpawn", QuickGrow, MT_SATK)
addHook("MobjSpawn", function(s)
	if not s.saldsalf
		s.scale = s.scale*2
		s.saldsalf = true
	end
end, MT_SPBL)
addHook("MobjSpawn", function(s)
	if not s.saldsalf
		s.scale = 43570
		s.saldsalf = true
	end
end, MT_SJMP)
addHook("MobjSpawn", function(s)
	if not s.saldsalf
		s.scale = s.scale*3
		s.saldsalf = true
	end
end, MT_CHBM)

addHook("MobjThinker", function(s)
	if (s.state == S_SAMEXPLODE21)
		if not s.color
			s.color = SKINCOLOR_BEIGE
		elseif (s.color == SKINCOLOR_VARIASUIT)
			s.tics = 1
		end
	end
end, MT_SAMEXPLODE2)

addHook("MobjThinker", function(s)
	s.samusshot = true
		if not s.sambombgrow
		s.scale = $*3
		s.sambombgrow = true
		s.shadowscale = FRACUNIT/5
		elseif (s.state == S_SAMMORPHBOMB5) and not s.saldsalf
		s.scale = $*2
		s.shadowscale = 0
		s.blendmode = AST_ADD		
		A_SAMUSEXPLOSIONS(s, 2, MT_SAMSHATTERFOF, false, 9000)
			if s.target --bomb floors below you. It just feels right this way.
				local sectorz = R_PointInSubsector(s.x, s.y).sector
					for fof in sectorz.ffloors()
						if (fof.flags & FF_EXISTS) and ((fof.flags & FF_STRONGBUST) or (fof.flags & FF_BUSTUP))
						and not (s.z-99*FRACUNIT >= fof.topheight)
						and not (s.z+99*FRACUNIT+s.height < fof.bottomheight)
						EV_CrumbleChain(sectorz, fof)						
						end
					end
			end
		A_Samuskillstuff(s, 250*FRACUNIT, 200*FRACUNIT, s.target, false, false, true)
		s.saldsalf = true
		S_StartSound(s, sfx_mbbmbx)
		local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_SAM_AUTOSPRITE)
		ghs.sprite = SPR_MBOM
		ghs.spriteyscale = 11000
		ghs.spritexscale = 11000		
		ghs.sttspeed = 2
		ghs.sttfade = 12
		ghs.tics = 15
		ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
		ghs.blendmode = AST_ADD
		ghs.frame = J|FF_FULLBRIGHT|TR_TRANS40
		ghs.destscale = $*99
		end
end, MT_SAMMORPHBOMB)

local function SamAutoSprite(s)
	if (leveltime % s.sttspeed == 0) --sttspeed = how quick to progress frames
		s.frame = $+1
		if s.sttfade and (s.tics < s.sttfade) --If sttfade has a value, start fading when tics reaches under that value.
			s.scalespeed = $*2
			if not ((s.frame & ~FF_FULLBRIGHT & ~FF_PAPERSPRITE & ~FF_FLOORSPRITE) >= TR_TRANS90)
				s.frame = $+FRACUNIT
			end
		end		
	end
end
--Automatically advances frames and fades. Basically copied from my code for Surge, hence STT. (Surge The Tenrec)
addHook("MobjThinker",  function(s)
	SamAutoSprite(s)
end, MT_SAM_AUTOSPRITE)

addHook("MobjThinker", function(s)
	if not s.target
	s.state = S_NULL
	return
	end
		if not s.sambombgrow
			s.scale = $*4
			s.shadowscale = 28000
			s.sambombgrow = true
			s.samusshot = true
			s.pwtimer = 13
		end
		if (s.state == S_SAMMBOP8) and not s.saldsalf
			s.scale = s.scale*2
			s.pwbomb = P_SpawnMobj(s.x, s.y, s.z, MT_SAMPOWERBOMB)
			s.pwbomb.target = s.target
			S_StartSound(s.pwbomb, sfx_pwbmb)
			s.saldsalf = true
		end
		if s.pwtimer
			if s.pwtimer == 1
			local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_PBEXPANDW)
			ghs.blendmode = AST_ADD
			ghs.scale = $*P_RandomRange(1,3)
			ghs.scalespeed = $*P_RandomRange(1, 8)
			ghs.destscale = $*20
			
			ghs = P_SpawnMobj(s.x, s.y, s.z, MT_PBEXPAND)
			ghs.blendmode = AST_ADD
			ghs.scale = $*P_RandomRange(1,2)
			ghs.scalespeed = $*P_RandomRange(2, 4)
			ghs.destscale = $*25
			end
			s.pwtimer = $-1
		end
end, MT_SAMMBOP)

local function LineShatter(s, dist) --Used to make missile wall destruction feel more responsive.
	local line = {}
	searchBlockmap("lines", function(m, linedef)
		local x,y = P_ClosestPointOnLine(m.x, m.y, linedef)
		if (R_PointToDist2(m.x, m.y, x, y) < dist)
			table.insert(line, linedef)
		else
		return
		end
	end, s, s.x-dist, s.x+dist, s.y-dist, s.y+dist)
	for i = 1, #line
		if line[i].valid
			local backfront = {line[i].frontsector, line[i].backsector}
			for d = 1, #backfront
				for fof in backfront[d].ffloors()
					if fof.valid and (fof.flags & FF_BUSTUP) and (fof.flags & FF_EXISTS)
					and ((abs(s.z-fof.topheight) <= dist) or (abs(s.z-fof.bottomheight) <= dist))
					and ((s.type == MT_SAMSUPERMISSILE) or not (fof.flags & FF_STRONGBUST))
						EV_CrumbleChain(nil, fof)
            		end
        		end
			end
		end
	end
end

local function PowerCollide(s, m)
	if m and m.player
	return false
	end
end
addHook("MobjCollide", PowerCollide, MT_SAMMBOP)
addHook("MobjMoveCollide",PowerCollide, MT_SAMMBOP)
addHook("MobjCollide", PowerCollide, MT_SAMPOWERBOMB)
addHook("MobjMoveCollide", PowerCollide, MT_SAMPOWERBOMB)

addHook("MobjThinker", function(s)
	s.samusshot = true
	s.spriteyscale = 95000
	s.spritexscale = 95000
		if not ((s.state == S_SAMMISSILEE) or (s.state == S_SAMMISSILEE2))
		and not s.missiledisabled
			s.shadowscale = FRACUNIT
			s.sam_mtimer = s.sam_mtimer and $+1 or 1
			
			--Flashy line stuff! 1.3 is a bit rushed, so calculations are not 100% correct...
			if s.target and s.target.player and not s.target.player.crystalflashtime
			local t = s.target
				if s.spindz == nil
				s.spindz = 30
					if s.spinaxisz == nil
					s.spinaxisz = 60
					end
				else
					s.spinaxisz = s.spinaxisz and $+s.spindz or 1
					if s.spinaxisz > 180
					s.spinaxisz = 180
					s.spindz = -30
					elseif s.spinaxisz < -180
					s.spindz = 30
					s.spinaxisz = -180
					end				
				end
			
				if s.spinaxis and s.spinaxis <= 150
					s.spinaxis = 150
				else
					s.spinaxis = s.spinaxis and $-15 or 301
				end
			
			
				--s is the missile
		--		s.verticalangle = R_PointToAngle2(0, 0, R_PointToDist2(0, 0, s.momx, s.momy), s.momz)
				s.verticalangle = R_PointToAngle2(0, 0, R_PointToDist2(0, 0, s.momx, s.momy), s.momz)
		--		R_PointToDist2(s.x, s.y, s.x+s.momx, t.y), ((t.z+(t.height/2)) - s.z)
				--Now spawn it correctly. You can assume the spinaxis is 40.
				local ang = leveltime*ANG10
				local ghs = P_SpawnMobj(
				s.x+FixedMul(s.spinaxis*s.scale, cos(ang)),
				s.y+FixedMul(s.spinaxis*s.scale, sin(ang)),
		 		s.z+(s.spinaxisz*s.scale),
				MT_SAMLIGHTLINE)
				ghs.tashu = s.target.player
				
				ghs = P_SpawnMobj(
				s.x+FixedMul(40*s.scale, cos(ang)),
				s.y+FixedMul(40*s.scale, sin(ang)),
				s.z+(s.scale*8),
				MT_SAMLIGHTLINE)
				
				if leveltime % 2 == 0
				ghs.lvl2spawn = true
				end
				ghs.target = s
				ghs.scale = s.scale/9
				ghs.blendmode = AST_ADD
				ghs.tics = 22
				ghs.frame = A|FF_FULLBRIGHT|TR_TRANS70
				ghs.color = SKINCOLOR_WHITE		
				ghs.tashu = s.target.player
			end
			
			if (s.sam_mtimer > 8) and multiplayer
			--Missile racing sound.
				for z in players.iterate
					if SAM_displayplayer(z) and z.mo and z.mo.valid 
					and not S_SoundPlaying(s, sfx_msfrsz)				
					and not (z.mo == s.target) 
						local dist = FixedHypot(FixedHypot((s.x+s.momx)-z.mo.x, (s.y+s.momy)-z.mo.y), s.z-z.mo.z)
						if ((dist < 1000*FRACUNIT) or (s.seekermissile and (dist < 2000*FRACUNIT)))		
							S_StartSound(s, sfx_msfrsz)
						end
					end
				end
			end
			
			local ghs = P_SpawnMobj(s.x+FixedMul(-15*FRACUNIT, cos(s.angle)), s.y+FixedMul(-15*FRACUNIT, sin (s.angle)), s.z, MT_SAMMISSILESMOKE)
			if ghs and ghs.valid
				ghs.destscale = $/2
				ghs.scalespeed = $/6
				if (s.sam_mtimer > 5) 
					ghs.colorized = true
					ghs.flags2 = $|MF2_SHADOW
					ghs.color = SKINCOLOR_SKY
					ghs.blendmode = AST_ADD	
					ghs.tics = $/2
				elseif P_RandomRange(0,1)
					ghs.frame = $|FF_TRANS70
				end
			end
				
		elseif (s.state == S_SAMMISSILEE) --Initial missile explosion effect
		
			if s.wallclipped and s.target
				local t = s.target
				P_Thrust(t, t.angle, -3*FRACUNIT)
				P_MoveOrigin(s, t.x, t.y, t.z+(t.height/2))
			end
			
			SamFaceReflect(s, 210*FRACUNIT)
			s.shadowscale = 0
		//	A_SAMUSEXPLOSIONS(s, 5, MT_BOSSEXPLODE, false, 90000, SKINCOLOR_SKY)
			A_SAMUSEXPLOSIONS(s, 8, MT_SAMSHATTERFOF, false, 9000)
		//	A_SAMUSEXPLOSIONS(s, 3, MT_SAMMISSILESMOKE, 8*FRACUNIT, 180000, SKINCOLOR_SKY)

			local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_THOK)
			ghs.sprite = SPR_MXP4
			ghs.frame = Y|FF_FULLBRIGHT|TR_TRANS40
			P_SetObjectMomZ(ghs, FRACUNIT, true)
			ghs.blendmode = AST_ADD
			ghs.scale = s.scale/3
			ghs.tics = 39
			ghs.fuse = 20
			ghs.scalespeed = $*3
			ghs.destscale = $*99
			ghs.dispoffset = 3
		
			s.missilelight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_SAMMISSILELIGHT)
			s.missilelight.scale = s.scale/10
			s.missilelight.blendmode = AST_ADD
			s.missilelight.color = SKINCOLOR_SUPERSILVER1
			s.missilelight.layers = 2
			LineShatter(s, 64*FRACUNIT)
			
			if G_GametypeHasSpectators()
				A_Samuskillstuff(s, 268*FRACUNIT, 145*FRACUNIT, s.target, true)
			else
				A_Samuskillstuff(s, 310*FRACUNIT, 185*FRACUNIT, s.target, true)
			end
			
			--Splat to help with 3D explosion radius
			if s.z > s.ceilingz-70*FRACUNIT
			or s.z < s.floorz+70*FRACUNIT
				local ghs = SamShinySplat(s,SKINCOLOR_SKY, 16)
				ghs.frame = A|TR_TRANS70|FF_FULLBRIGHT
			end
			
			for z in players.iterate
				if z.mo
					if (FixedHypot(FixedHypot(s.x-z.mo.x, s.y-z.mo.y), s.z-z.mo.z) < 500*FRACUNIT)
					A_samquake(z.mo, 9*FRACUNIT, 9, 1)
					end
				end
			end
			
			S_StartSound(s, sfx_misxp2)
			s.state = S_SAMMISSILEE2
			
		elseif s.state == S_SAMMISSILEE2 and (s.tics > 18) and (leveltime % 4 == 0) --Explosion continously gives off light flicker, Prime 2 style.
		
			local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_THOK)
			ghs.sprite = SPR_MXP4
			ghs.frame = Y|FF_FULLBRIGHT|TR_TRANS10
			ghs.blendmode = AST_ADD
			ghs.scale = (s.scale*(9+(s.tics/6)))/P_RandomRange(4,11)
			ghs.rollangle = leveltime*ANG20
			P_SetObjectMomZ(ghs, -FRACUNIT, true)
			ghs.fuse = 8 ghs.tics = 99
			ghs.scalespeed = $*2
			ghs.destscale = $*99
			ghs.dispoffset = 3
			
		end
end, MT_SAMMISSILE)
//The Lightdash Orbs are truly special.

addHook("MobjThinker", function(s)
	if s.target and s.target.valid
	and (s.target.state != S_SAMMISSILEE) and (s.target.state != S_SAMSUPERMISSILEE)
	
	local t = s.target
	
		A_FaceTarget(s) --Always face missile for calculation purposes.
		
		local finang = leveltime*(ANG1*27)
			
		if not s.yuldorbspawned --Set this once.
			s.yuldorbspawned = true
			s.scalespeed = $/16
			s.destscale = $*2
		end
		
		
		if s.lvl2spawn
			P_MoveOrigin(s, t.x-t.momx+FixedMul(t.spinaxis*s.scale, cos(finang)), t.y-t.momy+FixedMul(t.spinaxis*s.scale, sin(finang)),
			t.z-t.momz+(t.height/2)+(t.spinaxisz*s.scale*-1) )
		else
			P_MoveOrigin(s, t.x-t.momx-FixedMul(t.spinaxis*s.scale, cos(finang)), t.y-t.momy-FixedMul(t.spinaxis*s.scale, sin(finang)),
			t.z-t.momz+(t.height/2)+(t.spinaxisz*s.scale) )
		end
		
		if (s.tics < 16) --Fading effect
			if not (s.frame & TR_TRANS90)
			and (s.tics % 2 == 0)
				s.frame = $+FRACUNIT
			end 
		end
				
		--Lightline! Spawn in relation to your last known x, since momx and momy don't really apply with teleportation.
		if s.valid and s.yuprevx != nil --Make sure there IS a comparison to be made.		
			local renderer
			if (t.player == consoleplayer)
				renderer = CV_FindVar("renderer").value
			end
				for d = 1,8
				
					local lightline = P_SpawnMobj(
					FixedMul((FRACUNIT-(6535*d)) , s.x)+FixedMul((6535*d) , s.yuprevx), --x position
					FixedMul((FRACUNIT-(6535*d)) , s.y)+FixedMul((6535*d) , s.yuprevy), --y position
					FixedMul((FRACUNIT-(6535*d)) , s.z)+FixedMul((6535*d) , s.yuprevz), --z position
					MT_THOK)
					lightline.blendmode = AST_ADD
					lightline.scale = s.scale/2
					lightline.scalespeed = $/12
					lightline.destscale = lightline.scalespeed+1
					lightline.color = s.color
					
					if renderer == 1
						lightline.frame = $|FF_FULLBRIGHT & ~FF_TRANSMASK
					else
						lightline.frame = $|TR_TRANS90|FF_FULLBRIGHT & ~TR_TRANS50
					end					
					if s.tashu and not SAM_displayplayer(s.tashu)
					lightline.flags2 = $|MF2_DONTDRAW
					end
				end
		end
		s.yuprevx = s.x --Where were we last?
		s.yuprevy = s.y
		s.yuprevz = s.z
		if s.tashu and not SAM_displayplayer(s.tashu)	
			s.flags2 = $|MF2_DONTDRAW
		end
		if s.yulddisengage --Are we told to fade away gracefully?
			if (leveltime % 8 == 0)
				if not (s.frame & TR_TRANS90)
					s.frame = $+FRACUNIT
				elseif s.valid
					s.state = S_NULL
				return
				end
			end
		end	
	elseif s.valid --No target. Bai, bish.
		s.state = S_NULL
	end
end, MT_SAMLIGHTLINE)

addHook("MobjThinker", function(s)
/* --Wave beam sparks
		if s.sparklight
			if not s.setup
			s.color = P_RandomRange(SKINCOLOR_SUPERGOLD1, SKINCOLOR_SUPERGOLD4)
			s.flags = MF_BOUNCE|MF_GRENADEBOUNCE
			s.frame = A|TR_TRANS20|FF_FULLBRIGHT
			s.setup = true
			end
			
			s.ghs = P_SpawnGhostMobj(s)
			s.ghs.tics = 14 s.ghs.fuse = 14
		return
		end */
--Main light
			
		if not s.setup
		s.setup = true
		s.frame = A|TR_TRANS90|FF_FULLBRIGHT
		s.tics = 13
		s.destscale = 999*FRACUNIT
		s.blendmode = AST_ADD
			if not s.mlight2
				for d = 1,(s.layers or 2)
				s.mlight2 = P_SpawnMobj(s.x, s.y, s.z, MT_SAMMISSILELIGHT)
				local t = s.mlight2
				t.setup = true
				t.secondmlight = true
				t.scale = (s.scale/2)*d
				t.scalespeed = s.scalespeed+((s.scalespeed/3)*d)
				t.tics = 13+(s.layers or 2)
				t.destscale = 999*FRACUNIT
				t.momz = t.scalespeed*30 --Otherwise it goes downwards for some reason
				t.sprite = SPR_OILF
				t.frame = A|TR_TRANS90|FF_FULLBRIGHT
					if s.crystalflashl or s.superlayered
						for z in players.iterate
							if z.sam_software and (z == consoleplayer)
							t.flags2 = $|MF2_DONTDRAW
							s.flags2 = $|MF2_DONTDRAW
							end
						end
					end					
					if s.crystalflashlt
					t.crystalflashlt = s.crystalflashlt
					end
					if s.tokenlight
						if P_RandomRange(0,10)
						t.colorized = true
						t.color = P_RandomRange(SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERTAN5)
						end
					elseif s.crystalflashl					
						if d == 6 or not (d % 2 == 0)
						t.colorized = true
						t.color = SKINCOLOR_SUPERSILVER1
						else
						t.colorized = true
						t.color = SKINCOLOR_SUPERRED3
						end
					elseif s.layers == 2
					t.frame = A|TR_TRANS70|FF_FULLBRIGHT
						if d == 2
						t.colorized = true
						t.color = SKINCOLOR_SUPERSKY1
						end
					elseif s.layers == 4 and d == 4
					t.colorized = true
					t.color = SKINCOLOR_SUPERSKY3
					end
				end
			end
		else
			if s.crystalflashlt and s.crystalflashlt.valid
			P_MoveOrigin(s, s.crystalflashlt.x, s.crystalflashlt.y, s.crystalflashlt.z+s.crystalflashlt.height/2)
			end
			if s.tics == 4 and s.secondmlight
			s.frame = A|TR_TRANS90|FF_FULLBRIGHT
			end
		end
end, MT_SAMMISSILELIGHT)



local function FofShattering(s)
	local sector = R_PointInSubsector(s.x, s.y).sector
	shatterfof(s, sector)
	if ( R_PointInSubsector(s.x+(s.momx/2), s.y+(s.momy/2)).sector != sector )
		sector = R_PointInSubsector(s.x+(s.momx/2), s.y + (s.momy/2)).sector
		shatterfof(s, sector)
	end
end
addHook("MobjThinker", FofShattering, MT_SAMEXPLODE1)
addHook("MobjThinker", FofShattering, MT_SAMSHATTERFOF)

addHook("MobjThinker", function(s)
	s.samusshot = true
	s.spriteyscale = FRACUNIT*2
	s.spritexscale = FRACUNIT*2
		if s.darkhyper --Phazon Missile
			LeafSpawn(s, nil, true, 200)		
			if leveltime % 3 == 0
				s.color = SKINCOLOR_COBALT
			else
				s.color = SKINCOLOR_SKY
			end
			s.colorized = true
		end	
		if s.stimer == nil
			s.stimer = 1
		elseif s.stimer
			s.stimer = $+1
		end
		if (s.state == S_SAMSUPERMISSILE1) and not s.missiledisabled
		s.shadowscale = FRACUNIT
			if multiplayer
				--Super Missile racing sound.
				for z in players.iterate
					if SAM_displayplayer(z) and z.mo and z.mo.valid and not (z.mo == s.target)
						if not S_SoundPlaying(s, sfx_smsh)
							S_StartSound(s, sfx_smsh)
						end
						if not S_SoundPlaying(s, sfx_msfrsz) and (s.stimer >= 5)				
							if (FixedHypot(FixedHypot((s.x+s.momx)-z.mo.x, (s.y+s.momy)-z.mo.y), s.z-z.mo.z) < 2000*FRACUNIT)
								S_StartSound(s, sfx_msfrsz)	
								S_StartSound(s, sfx_msfrsz)
							end
						end
					end
				end
			end
			if (s.stimer >= 5)
			s.ghs = P_SpawnMobj(s.x+FixedMul(-15*FRACUNIT, cos(s.angle)), s.y+FixedMul(-15*FRACUNIT, sin (s.angle)), s.z, MT_SAMMISSILESMOKE)
				if s.ghs and s.ghs.valid and (leveltime % 2 == 0)
					s.ghs.blendmode = AST_ADD
				end	
				if (s.stimer > 16)
				P_SpawnMobj(s.x+FixedMul(-52*FRACUNIT, cos(s.angle)), s.y+FixedMul(-52*FRACUNIT, sin (s.angle)), s.z, MT_SAMMISSILESMOKE)
				s.ghs = P_SpawnMobj(s.x+FixedMul(-15*FRACUNIT, cos(s.angle)), s.y+FixedMul(-15*FRACUNIT, sin (s.angle)), s.z, MT_SAMMISSILESMOKE)
					if s.ghs and s.ghs.valid
					s.ghs.blendmode = AST_ADD
					end
				end
			end
			
		s.momx = $*25/24
		s.momy = $*25/24 --Gradually speed up
		s.momz = $*25/24

			if s.target and s.target.player
			if s.spindz == nil
			s.spindz = 30
				if s.spinaxisz == nil
				s.spinaxisz = 90
				end
			else
				s.spinaxisz = s.spinaxisz and $+s.spindz or 1
				if s.spinaxisz > 180
				s.spinaxisz = 180
				s.spindz = -30
				elseif s.spinaxisz < -180
				s.spindz = 30
				s.spinaxisz = -180
				end
			end
			
			if s.spinaxis and s.spinaxis <= 150
				s.spinaxis = 150
			else
				s.spinaxis = s.spinaxis and $-15 or 301
			end
			
			
			s.verticalangle = R_PointToAngle2(0, 0, R_PointToDist2(0, 0, s.momx, s.momy), s.momz)
			local ang = leveltime*ANG10
			local ghs = P_SpawnMobj(
			s.x+FixedMul(s.spinaxis*s.scale, cos(ang)),
			s.y+FixedMul(s.spinaxis*s.scale, sin(ang)),
		 	s.z+(s.spinaxisz*s.scale),
			MT_SAMLIGHTLINE)
			ghs.tashu = s.target.player
			
				local ang = leveltime*ANG10	
				local ghs = P_SpawnMobj(
				s.x+FixedMul(40*s.scale, cos(ang)),
				s.y+FixedMul(40*s.scale, sin(ang)),
				s.z+(s.scale*8),
				MT_SAMLIGHTLINE)
				if leveltime % 2 == 0
				ghs.lvl2spawn = true
				end
				ghs.target = s
				ghs.scale = s.scale/9
				ghs.blendmode = AST_ADD
				ghs.tics = 22
				ghs.frame = A|FF_FULLBRIGHT|TR_TRANS50
				ghs.color = SKINCOLOR_SUPERGOLD5
				ghs.tashu = s.target.player
				end

		elseif (s.state == S_SAMSUPERMISSILEE)
			if s.wallclipped and s.target
			local t = s.target
			P_Thrust(t, t.angle, -9*FRACUNIT)
			P_MoveOrigin(s, t.x, t.y, t.z+(t.height/2))
			end		
		s.shadowscale = 0
		A_SAMUSEXPLOSIONS(s, 5, MT_SAMEXPLODE1, 5*FRACUNIT, 144000, true)
		A_SAMUSEXPLOSIONS(s, 7, MT_SAMMISSILESMOKE, 50*FRACUNIT, 650000)
		A_SAMUSEXPLOSIONS(s, 12, MT_SAMEXPLODE1, false, 1001, true)
		A_SAMUSEXPLOSIONS(s, 20, MT_SAMMISSILESMOKE, false, 9001)
		
		s.missilelight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_SAMMISSILELIGHT)
		s.missilelight.scale = s.scale/4
		s.missilelight.scalespeed = $*10/7
		s.missilelight.color = SKINCOLOR_SUPERSILVER1
		s.missilelight.layers = 6
		
			--Splat to help with 3D explosion radius
			if s.z > s.ceilingz-70*FRACUNIT
			or s.z < s.floorz+70*FRACUNIT

			local ghs = SamShinySplat(s, SKINCOLOR_RED, 16)
			ghs.frame = A|TR_TRANS40|FF_FULLBRIGHT
			ghs.scale = $*2
			ghs.destscale = $*99
			ghs.scalespeed = $*3
			
			end
		
			for d = 1,29
			local ghs = P_SpawnMobj(
			s.x+FixedMul((100+(d*7)*s.scale),cos(s.angle)),
			s.y+FixedMul((100+(d*7)*s.scale),sin(s.angle)),
			s.z+(d*3*s.scale), MT_THOK)
			ghs.eflags = s.eflags
			ghs.sprite = SPR_MPR9
			P_SetObjectMomZ(ghs, (30-d)*FRACUNIT)
			if d % 2 == 0
				ghs.frame = V|TR_TRANS40|FF_FULLBRIGHT
				P_SetObjectMomZ(ghs, 5*FRACUNIT)
				ghs.scale = $*2
				ghs.color = SKINCOLOR_RED
			else
				ghs.frame = W|TR_TRANS10|FF_FULLBRIGHT
				ghs.scale = $*3
				ghs.color = SKINCOLOR_SUPERGOLD3
			end
			ghs.rollangle = d*ANG20
			ghs.blendmode = AST_ADD
			ghs.destscale = $*99
			ghs.fuse = 8+d
			ghs.tics = 99		
			end
			
			for d = 1,16
				local ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
				ghs.sprite = SPR_PHAZ
				ghs.spriteyscale = FRACUNIT
				ghs.spritexscale = 95000
				ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
				ghs.blendmode = AST_ADD
				ghs.colorized = true
				ghs.tics = 99
				P_SetObjectMomZ(ghs, 5*FRACUNIT)
				P_InstaThrust(ghs, (ANGLE_45/2)*d, 36*FRACUNIT)
				ghs.angle = (R_PointToAngle2(ghs.x, ghs.y, ghs.x+ghs.momx, ghs.y+ghs.momy))+ANGLE_90
					if d % 2 == 0
						ghs.fuse = 15
						ghs.frame = K|TR_TRANS60|FF_PAPERSPRITE|FF_FULLBRIGHT
						ghs.scalespeed = $*P_RandomRange(1,3)
						ghs.color = SKINCOLOR_SUPERORANGE5
					else
					
						ghs.fuse = 21
						ghs.frame = J|TR_TRANS70|FF_PAPERSPRITE|FF_FULLBRIGHT
						ghs.scalespeed = $/2
						ghs.color = SKINCOLOR_RED
					end
				ghs.scalespeed = $*3
				ghs.destscale = $*99
			end

		SamFaceReflect(s, 500*FRACUNIT)
		LineShatter(s, 90*FRACUNIT)
		
			if not s.darkhyper
				if G_GametypeHasSpectators()
				A_Samuskillstuff(s, 520*FRACUNIT, 325*FRACUNIT, s.target, false, true)
				else
				A_Samuskillstuff(s, 750*FRACUNIT, 500*FRACUNIT, s.target, false, true)
				end
			end
			for z in players.iterate
				if z.mo
					if (FixedHypot(FixedHypot(s.x-z.mo.x, s.y-z.mo.y), s.z-z.mo.z) < 3000*FRACUNIT)
					or (s.target and z.mo == s.target) --May as well always let the shooter know if it hit.
					A_samquake(z.mo, 14*FRACUNIT, 13, 5)
						if s.darkhyper and (FixedHypot(FixedHypot(s.x-z.mo.x, s.y-z.mo.y), s.z-z.mo.z) < 235*FRACUNIT)
						P_DamageMobj(z.mo, s, s.target) --Big explosion, dodge, Samus!
						end
					end
				end
			end
		S_StartSound(s, sfx_smexp)
		s.state = S_SAMEXPLODE11
		end
end, MT_SAMSUPERMISSILE)

addHook("MobjThinker", function(p)
	if p.target and p.target.player
	local t = p.target
		if p.srdcr == nil
		p.srdcr = 1
		p.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
		end
		if p.gravitysuitjustgot
		P_MoveOrigin(p, t.x+FixedMul(-2*FRACUNIT, cos(t.angle)), t.y+FixedMul(-2*FRACUNIT, sin (t.angle)), t.z)
		elseif (p.state >= S_SAMPOWERBOMB2) and (p.state < S_SAMPOWERBOMB5)
			WindStorm(p)		
		end
		if p.state == S_SAMPOWERBOMB1
		
			if not p.gravitysuitjustgot
			S_StartSound(p, sfx_smexp)
			SamFaceReflect(p, 900*FRACUNIT)
			end 
			S_StartSound(p, sfx_pwbmb)		
			p.scale = FRACUNIT*10
			p.flags2 = $|MF2_EXPLOSION
			p.color = SKINCOLOR_YELLOW
			
			--Splat to help with 3D explosion radius

			local ghs = SamShinySplat(p,SKINCOLOR_SUPERGOLD5, 66)
			ghs.frame = A|TR_TRANS20|FF_FULLBRIGHT
			ghs.scale = $/2
			ghs.destscale = $*99
			ghs.scalespeed = $*2
			
			if G_GametypeHasSpectators() 
				if not p.gravitysuitjustgot
				A_Samuskillstuff(p, 420*FRACUNIT, 340*FRACUNIT, t, false, true)
				end
			else
			A_Samuskillstuff(p, 500*FRACUNIT, 400*FRACUNIT, t, false, true)
			end
			p.missilelight = P_SpawnMobj(p.x, p.y, p.z+p.height, MT_SAMMISSILELIGHT)
			p.missilelight.scale = FRACUNIT/30
			p.missilelight.color = SKINCOLOR_SUPERSILVER1
			p.missilelight.layers = 8
			P_StartQuake(18*FRACUNIT, 10)
			
		elseif p.state == S_SAMPOWERBOMB1A
			p.scale = p.scale+12001
			p.blendmode = AST_ADD
			if not p.phase
				p.scale = FRACUNIT
				p.phase = 1
					for z in players.iterate
						if p.gravitysuitjustgot and z.mo and p.target == z.mo
							if (z.sam_gravitysuit == 1)
								if z.customsuitc2 and not (z.customsuitc2 > #skincolors - 1)
									z.mo.sam_flashfade = 35
									z.mo.sam_flashfadecolor = p.customsuitc2
								end	
							else
								if z.customsuitc3 and not (z.customsuitc3 > #skincolors - 1)
									z.mo.sam_flashfade = 35
									z.mo.sam_flashfadecolor = z.customsuitc3		
								end
							end				
						elseif z.mo and (FixedHypot(FixedHypot(z.mo.x-p.x, z.mo.y-p.y), z.mo.z-p.z) <= 1150*FRACUNIT)
						P_SamFP(z, PAL_MIXUP, 6)
						z.mo.sam_flashfade = 40
						z.mo.sam_flashfadecolor = SKINCOLOR_SUPERGOLD5
						end
					end
				A_SAMUSEXPLOSIONS(p, 20, MT_SPARK, 65*FRACUNIT, 6000)
				if not p.gravitysuitjustgot
				A_SAMUSEXPLOSIONS(p, 10, MT_IVSP, 75*FRACUNIT, 199000)
				A_SAMUSEXPLOSIONS(p, 17, MT_IVSP, 5*FRACUNIT, 900)
				A_SAMUSEXPLOSIONS(p, 8, MT_SAMMISSILESMOKE, 90*FRACUNIT, 192500)
				A_SAMUSEXPLOSIONS(p, 2, MT_EXPLODE, 71*FRACUNIT, 90)
				A_SAMUSEXPLOSIONS(p, 5, MT_SAMSHATTERFOF, false, 9000, true)
				A_SAMUSEXPLOSIONS(p, 4, MT_BOSSEXPLODE, 38*FRACUNIT, 292500)
				A_SAMUSEXPLOSIONS(p, 8, MT_SAMEXPLODE1, false, 1, true)
				end
				
				local ghs = P_SpawnMobjFromMobj(p, 0, 0, 0, MT_SAM_AUTOSPRITE)
				ghs.sprite = SPR_MBOM
				ghs.scale = FRACUNIT*4
				ghs.colorized = true
				ghs.spriteyscale = 12000
				ghs.spritexscale = 12000	
				ghs.sttspeed = 12
				ghs.sttfade = 15
				ghs.tics = 80
				ghs.color = SKINCOLOR_ORANGE
				ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
				ghs.blendmode = AST_ADD
				ghs.frame = J|FF_FULLBRIGHT|TR_TRANS40
				ghs.destscale = $*99
				ghs.scalespeed = $*5
			end
			
		elseif p.state == S_SAMPOWERBOMB2
			p.scale = p.scale+15500
			
			if p.phasetim == nil
			p.phasetim = 8
			else
				if p.phasetim == 1
				A_SAMUSEXPLOSIONS(p, 18, MT_SPARK, 5*FRACUNIT, 100)
				A_SAMUSEXPLOSIONS(p, 23, MT_SPARK, 30*FRACUNIT, 8000)
				A_SAMUSEXPLOSIONS(p, 16, MT_SPARK, 54*FRACUNIT, 15000)
				A_SAMUSEXPLOSIONS(p, 12, MT_SPARK, 67*FRACUNIT, 20000)
				end
				p.phasetim = $-1
			end
			if not (p.phase and p.phase >= 2)
				P_StartQuake(6*FRACUNIT, 35)
				p.color = SKINCOLOR_YELLOW
				if G_GametypeHasSpectators() 
					if not p.gravitysuitjustgot
					p.phase = 2
					A_Samuskillstuff(p, 750*FRACUNIT, 480*FRACUNIT, t, false, true)
					end
				else
				p.phase = 2
				A_Samuskillstuff(p, 800*FRACUNIT, 700*FRACUNIT, t, false, true)
				end
			end	
			
		elseif p.state == S_SAMPOWERBOMB3
			if p.thcolors
			p.color = SKINCOLOR_BLUE
			else
			p.color = SKINCOLOR_SUPERSILVER5
			end
			p.scale = p.scale+29000
			if G_GametypeHasSpectators() 
				for z in players.iterate
					if z.mo and z.mo != t and (FixedHypot(FixedHypot(z.mo.x-p.x, z.mo.y-p.y), z.mo.z-p.z) <= 3900*FRACUNIT)
						if not (G_GametypeHasTeams() and t.player.ctfteam == z.mo.player.ctfteam)
						P_Thrust(z.mo, R_PointToAngle2(p.x, p.y, z.mo.x, z.mo.y), 3*FRACUNIT)
						end
					end
				end
			end			
			if not (p.phase and p.phase >= 3)
				A_SAMUSEXPLOSIONS(p, 19, MT_SPARK, 120*FRACUNIT, 5500)
				A_SAMUSEXPLOSIONS(p, 28, MT_SPARK, 20*FRACUNIT, 20)
				if not p.gravitysuitjustgot
				A_SAMUSEXPLOSIONS(p, 25, MT_IVSP, 45*FRACUNIT, 15000)
				A_SAMUSEXPLOSIONS(p, 10, MT_BOSSEXPLODE, 98*FRACUNIT, 100)
				A_SAMUSEXPLOSIONS(p, 10, MT_SAMSHATTERFOF, false, 9000, true)
				A_SAMUSEXPLOSIONS(p, 14, MT_SAMMISSILESMOKE, 75*FRACUNIT, 100)
				A_SAMUSEXPLOSIONS(p, 14, MT_SAMEXPLODE1, false, 7000, true)
				end
			p.phase = 3
			
				local ghs = P_SpawnMobjFromMobj(p, 0, 0, 0, MT_SAM_AUTOSPRITE)
				ghs.sprite = SPR_MBOM
				ghs.scale = FRACUNIT*5
				ghs.colorized = true
				ghs.spriteyscale = 24000
				ghs.spritexscale = 24000	
				ghs.sttspeed = 6
				ghs.sttfade = 15
				ghs.tics = 40
				ghs.color = SKINCOLOR_RED
				ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
				ghs.blendmode = AST_ADD
				ghs.frame = J|FF_FULLBRIGHT|TR_TRANS80
				ghs.destscale = $*99
				ghs.scalespeed = $*5
				
				for d = 1,16
				local ghs = P_SpawnMobjFromMobj(p, 0,0,0, MT_THOK)
				ghs.sprite = SPR_PHAZ
				ghs.spriteyscale = FRACUNIT
				ghs.spritexscale = 95000
				ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
				ghs.blendmode = AST_ADD
				ghs.colorized = true
				ghs.tics = 99
				P_SetObjectMomZ(ghs, 85356)
				P_InstaThrust(ghs, (ANGLE_45/2)*d, 65*FRACUNIT)
				ghs.angle = R_PointToAngle2(ghs.x, ghs.y, ghs.x+ghs.momx, ghs.y+ghs.momy)+ANGLE_90
					if d % 2 == 0
						ghs.fuse = 20
						ghs.frame = K|TR_TRANS20|FF_PAPERSPRITE|FF_FULLBRIGHT
						ghs.scalespeed = $*P_RandomRange(1,3)
						ghs.color = SKINCOLOR_SUPERGOLD3
					else
					
						ghs.fuse = 28
						ghs.frame = J|TR_TRANS40|FF_PAPERSPRITE|FF_FULLBRIGHT
						ghs.scalespeed = $/2
						ghs.color = SKINCOLOR_SUPERGOLD5
					end
				ghs.scalespeed = $*2
				ghs.destscale = $*99
				end
			
			end
			if leveltime % 2 == 0
			for d = 1,729,43
				local ghs = P_SpawnMobj(
				p.x+FixedMul(((10+d)*FRACUNIT),cos(d*(ANG1+9909))),
				p.y+FixedMul(((10+d)*FRACUNIT),sin(d*(ANG1+9909))),
				p.z, MT_THOK)
				
				ghs.eflags = p.eflags
				ghs.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE & ~MF_NOCLIPHEIGHT
				ghs.sprite = SPR_MPR9
				local rng = P_RandomRange(-30,30)*ANG1
				P_SetObjectMomZ(ghs, d*3000)
				P_InstaThrust(ghs, R_PointToAngle2(p.x, p.y, ghs.x, ghs.y)+rng, (d/20)*FRACUNIT)
				if d % 2 == 0
					ghs.frame = V|TR_TRANS60|FF_FULLBRIGHT
					ghs.scale = $*2
					ghs.color = SKINCOLOR_SUPERGOLD3
				else
					ghs.frame = W|TR_TRANS20|FF_FULLBRIGHT
					ghs.scale = $*3
					ghs.color = SKINCOLOR_SUPERSKY3
				end
				ghs.rollangle = d*ANG2
				ghs.blendmode = AST_ADD
				ghs.destscale = $*99
				ghs.fuse = 5+(d/20)
				ghs.tics = 99
			end
			end	
		elseif p.state == S_SAMPOWERBOMB4

			if p.thcolors
			p.color = SKINCOLOR_SUPERGOLD5
			else
			p.color = SKINCOLOR_SUPERSILVER5
			end
			p.scale = p.scale+44500

			if not (p.phase and p.phase >= 4)
				if G_GametypeHasSpectators() 
					if not p.gravitysuitjustgot
					A_Samuskillstuff(p, 1830*FRACUNIT, 1150*FRACUNIT, t, false, true)
					end
				else
				A_Samuskillstuff(p, 2250*FRACUNIT, 1300*FRACUNIT, t, false, true)
				end
			p.phase = 4
			end
			if not p.gravitysuitjustgot
				SamFaceReflect(p, 950*FRACUNIT)
				if G_GametypeHasSpectators() 
					for z in players.iterate
						if z.mo and z.mo != t and (FixedHypot(FixedHypot(z.mo.x-p.x, z.mo.y-p.y), z.mo.z-p.z) <= 2300*FRACUNIT)
							if not (G_GametypeHasTeams() and t.player.ctfteam == z.mo.player.ctfteam)
								P_Thrust(z.mo, R_PointToAngle2(p.x, p.y, z.mo.x, z.mo.y), FRACUNIT)
							end
						end
					end
				end
			end

		elseif p.state == S_SAMPOWERBOMB5
		
			if p.thcolors
			p.color = SKINCOLOR_SUPERGOLD5
			else
			p.color = SKINCOLOR_SUPERSILVER5
			end
			p.phase = 6
			p.scale = p.scale+27000
			
		elseif p.state == S_SAMPOWERBOMB6
			p.scale = p.scale+16000
		end
	end
end, MT_SAMPOWERBOMB)

addHook("MobjThinker", function(s)
		if not s.samptimer
			if s.spazersummon
			s.samptimer = P_RandomRange(6, 18)
			else
			s.samptimer = P_RandomRange(10, 50)
			end
		else
		s.samptimer = $-1
		end
		if ((P_CheckDeathPitCollide(s)) or (s.samptimer == 1)) and s
		s.state = S_NULL
		return 
		end
end, MT_MPR1)

addHook("MobjThinker", function(s)
	if P_CheckDeathPitCollide(s)
		s.state = S_NULL
		return 
	end
end, MT_MPR4)

addHook("MobjThinker", function(s)
	if not s.samptimer
		s.samptimer = P_RandomRange(110, 150)
	else
		s.samptimer = $-1
	end
	if ((s.momx < FRACUNIT) and (s.momy < FRACUNIT))
		s.tics = $+1	
	end
	if ((P_CheckDeathPitCollide(s)) or (s.samptimer == 1)) and s
		s.state = S_NULL
		return 
	end
end, MT_MPR2)

addHook("MobjThinker", function(s)
	if not s.samptimer
		s.samptimer = P_RandomRange(110, 150)
	else
		s.samptimer = $-1
	end
	if ((s.momx < 25355) and (s.momy < 25355))
		s.tics = $+1	
	end
	if s.valid and ((P_CheckDeathPitCollide(s)) or (s.samptimer == 1))
		s.state = S_NULL
		return 	
	end
end, MT_MPR3)

addHook("MobjThinker", function(s)
	if not s.samptimer
		s.samptimer = P_RandomRange(18, 100)
	else
		s.samptimer = $-1
	end
	if s.valid and ((P_CheckDeathPitCollide(s)) or (s.samptimer == 1))
		s.state = S_NULL
		return 
	end
end, MT_MPR5)

addHook("MobjThinker", function(s)
	if s.deathbolt
		if s.target and s.target.valid
		P_MoveOrigin(s, s.target.x, s.target.y, s.target.z+s.target.height/2)
		end
		s.sprite = SPR_MPR9
		P_SpawnMobj(s.x+(P_RandomRange(-40, 40)*FRACUNIT), s.y+(P_RandomRange(-40, 40)*FRACUNIT), s.z+s.height/2, MT_EXPLODE)
		if leveltime % 2 == 0
		P_SpawnMobj(s.x+(P_RandomRange(-30, 30)*FRACUNIT), s.y+(P_RandomRange(-30, 30)*FRACUNIT), s.z+(P_RandomRange(45, 1)*FRACUNIT), MT_SUPERSPARK)
		else
		P_SpawnMobj(s.x+(P_RandomRange(-125, 125)*FRACUNIT), s.y+(P_RandomRange(-125, 125)*FRACUNIT), s.z+(P_RandomRange(15, -20)*FRACUNIT), MT_SPARK)
		end
		if not s.deathboltstart
		s.destscale = FRACUNIT*10
		s.scalespeed = $*2
		P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_EXPLODE)
		P_SpawnMobj(s.x, s.y, s.z-5*FRACUNIT, MT_EXPLODE)
		s.deathboltstart = true
		s.frame = 26|FF_FULLBRIGHT|TR_TRANS20
		s.tics = 2
		elseif s.frame == 26|FF_FULLBRIGHT|TR_TRANS20 and s.tics <= 1
		s.frame = 27|FF_FULLBRIGHT|TR_TRANS10

		s.tics = 5
		elseif s.frame == 27|FF_FULLBRIGHT|TR_TRANS10 and s.tics <= 1
		s.frame = 28|FF_FULLBRIGHT|TR_TRANS20
		s.tics = 4
		elseif s.frame == 28|FF_FULLBRIGHT|TR_TRANS20 and s.tics <= 1
		s.frame = 29|FF_FULLBRIGHT|TR_TRANS30
		s.tics = 3
		elseif s.frame == 29|FF_FULLBRIGHT|TR_TRANS30 and s.tics <= 1
		s.frame = 30|FF_FULLBRIGHT|TR_TRANS40
		s.tics = 2
		end
	end
end, MT_THOK)

addHook("MobjThinker", function(s)
	if s.tracer and s.tracer.valid
		if not (s.tracer.flags2 & MF2_DONTDRAW) and gamemap == 25 and ((players[0] and players[0].samworldevents) or not players[0])
		s.tracer.flags2 = $|MF2_DONTDRAW
		end
	end
end, MT_METALSONIC_RACE)

//Samus' Lights thinker. But switch to custom lights for SAMP sprites!

addHook("MobjThinker", function(s)
	if s.tracer and s.tracer.valid and s.tracer.player
		if (s.tracer.sprite == SPR_SAMU and s.tracer.frame != 0)
			s.flags2 = $|MF2_DONTDRAW
		else
			if (s.tracer.sprite != SPR_PLAY) // or not s.tracer.player.sam_gravitysuit
			s.flags2 = $|MF2_DONTDRAW
			return
			elseif (s.flags2 & MF2_DONTDRAW)
			s.flags2 = $ & ~MF2_DONTDRAW		
			end
			s.tics = 3
			s.skin = "samuslights"
			s.scale = s.tracer.scale
			s.angle = s.tracer.player.drawangle
			s.frame = s.tracer.frame
			s.sprite = s.tracer.sprite
			s.sprite2 = s.tracer.sprite2
			s.color = SKINCOLOR_SUPERSILVER1
			s.rollangle = s.tracer.rollangle
			return
		end
	end
end, MT_SAMUSLIGHTS)

addHook("MobjThinker", function(s)
  if s.target and s.target.valid and YouAreSamus(s.target) and s.target.player
local t = s.target
local p = t.player
	if t.health
		if P_IsObjectOnGround(s)
		and not (p.sam_screwattacking or t.sam_screwattackfling)
		and not p.sammorphed and not p.powers[pw_nocontrol] 
		and not p.exiting and not p.gotflag
		and p.sam_power_grip
		
			if (t.eflags & MFE_VERTICALFLIP)
			and ((t.ceilingz+40*FRACUNIT) > s.ceilingz)
			and (t.z+24*FRACUNIT > s.z)
			and (t.floorz < (s.ceilingz-20*FRACUNIT))
			and (t.z < t.ceilingz+40*FRACUNIT) 
			
			or ((t.floorz-40*FRACUNIT) < s.floorz)
			and (t.z-24*FRACUNIT < s.z)  
			and (t.ceilingz > (s.floorz+20*FRACUNIT)) 
			and (t.z > t.floorz+40*FRACUNIT) 
			
			local fofy = false
				if s.subsector and s.subsector.sector 
					for fof in s.subsector.sector.ffloors()
						if (fof.flags & FF_EXISTS)
							if ((fof.flags & FF_BLOCKOTHERS) and not (fof.flags & FF_BLOCKPLAYER))
							and (t.floorz < fof.topheight)
								if not (t.z+5*t.scale > fof.topheight)
									if not (t.eflags & MFE_VERTICALFLIP)
									and not (fof.topheight > t.z+t.height+(230*t.scale))
										return
									end
								end
							end
						end
						fofy = true
					end
				end
				if (p.samspbscharge > 125)
					t.sam_ldspeed = 80*FRACUNIT
				else
					t.sam_ldspeed = min(80*FRACUNIT, max(abs(t.momx)+abs(t.momy), 8*FRACUNIT))
				end				
				
				t.momx = 0 t.momy = 0 t.momz = 0
				if (t.eflags & MFE_VERTICALFLIP)
					t.z = s.z+10*FRACUNIT
				else
					t.z = s.z-56*FRACUNIT
				end
				
				S_StopSoundByID(s, sfx_sjmp)
				
				t.state = S_PLAY_RIDE
				t.spriteyoffset = -6*FRACUNIT
				t.spriteyscale = 72355
				t.sam_geton = 0
				A_samquake(s, 30*FRACUNIT, 2, 1)
				
				CancelScrewAttack(t,p)
				p.sams_jumpcd = 6
				p.sams_morphcd = 6
				p.sams_screwattackcd = 6
				p.sam_spacejumped = true
				
				t.sam_ldclmb = 30
				p.aiming = 1901*FRACUNIT+3
				S_StartSound(s, sfx_samclb)
				
				t.sam_ldforce = 15*FRACUNIT	
				
				local pmomz = 0
				if s.pmomz and (s.pmomz*P_MobjFlip(t) > 1)
					pmomz = s.pmomz
					if pmomz < 0
						pmomz = $/-2
					end
					t.sam_ldforce = min($+(pmomz+FRACUNIT), 10*FRACUNIT)
					t.momz = (pmomz+FRACUNIT)
				elseif t.pmomz  and (t.pmomz*P_MobjFlip(t) > 1)
					pmomz = t.pmomz
					if pmomz < 0
						pmomz = $/-2
					end	
					t.sam_ldforce = min($+(pmomz+FRACUNIT), 10*FRACUNIT)
					t.momz = (pmomz+FRACUNIT)
				end					
				
				if not (fofy and (s.subsector == t.subsector))
					t.angle = R_PointToAngle2(t.x, t.y, s.x, s.y)
					t.sam_ledgeupangle = t.angle
				end

				p.powers[pw_nocontrol] = max($,2)
				p.pflags = $|PF_JUMPED|PF_FULLSTASIS & ~PF_THOKKED & ~PF_SPINNING & ~PF_STARTJUMP & ~PF_STARTDASH
			end
		end
	end	
  elseif s.valid	
	s.state = S_NULL
  end
end, MT_PWGRPLD)