//When the time comes....DODGE!!
//SMS' dodgeroll might come in use, but you still have to be ready to time it right!

local function AtomBust(s)
	local sectorz = R_PointInSubsector(s.x, s.y).sector //Atomdive through bustable floors!
	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

addHook("MobjThinker", function(s)
if not s.player
return end
local p = s.player
	if p.cmphwarning
	p.cmphwarning = $-1
		if not P_IsObjectOnGround(s)
		and not (p.panim == PA_ROLL)
		s.state = S_PLAY_ROLL
		end
		if (p.cmd.buttons & BT_JUMP)
		and (p.cmd.buttons & BT_USE)
		and not (p.spinhold and (p.spinhold > 8))
		and not P_PlayerInPain(p)
		and not p.cmphdodge
			P_SetObjectMomZ(s, 12*FRACUNIT)
			P_SpawnMobj(s.x, s.y, s.z, MT_EXPLODE)
			p.cmphdodge = 55
			if p.smpawncher
				print("\x83"+p.name+" dodged "+p.smpawncher.name+"'s haymaker.")
				p.smpawncher = nil
			end
			s.state = S_PLAY_ROLL
			p.pflags = $|PF_JUMPED & ~PF_THOKKED
			p.secondjump = 0
			p.powers[pw_nocontrol] = $+20
			S_StartSound(s, sfx_s3kab)
			S_StartSound(s, sfx_s3kb6)
			S_StartSound(s, sfx_s3k76)
			p.powers[pw_flashing] = 35

			if (p.cmd.forwardmove > 0)
			P_InstaThrust(s, s.angle, 45*FRACUNIT)
			elseif (p.cmd.sidemove >= 0)
			P_InstaThrust(s, s.angle+ANGLE_90, -45*FRACUNIT)
			elseif (p.cmd.sidemove < 0)
			P_InstaThrust(s, s.angle-ANGLE_90, -45*FRACUNIT)
			else
			P_InstaThrust(s, s.angle, -45*FRACUNIT)
			end
		end	
	end
	if p.hmsbpunch
		s.flags = $|MF_BOUNCE
		s.angle = $+ANG30
		if not (P_PlayerInPain(p))
		p.hmsbpunch = false
		s.flags = $ & ~MF_BOUNCE
		end

	end
	if p.cmphdodge
		s.ghs = P_SpawnGhostMobj(s)
		s.ghs.rollangle = s.rollangle
		p.cmphdodge = $-1
	end
	if p.fusrodah
	p.fusrodah = $+1
		if s and not (s.state == S_PLAY_PAIN)
		p.fusrodah = 0
		end
	end
	if (s and s.skin == "sms")
		if s.sdodgecd
		s.sdodgecd = $-1
			if not s.sdodgecd and s.sdodgelvl
			s.sdodgelvl = 0
			end
		end
		if s.sideroll 
			if s.state == S_SMS_SIDEDODGE1
				if (s.tics > 4)
				s.rollangle = $+FixedAngle(6*FRACUNIT)*s.sideroll
				else
				s.rollangle = $+FixedAngle(20*FRACUNIT)*s.sideroll
				end
			else
			s.sideroll = 0
				if not s.airboostroll
				s.rollangle = 0
				end
			end
		end
		if s.smpkclosest
			s.smpkclosest = nil
		end
		if p.sms_dodging
		and ((s.state == S_PLAY_SPRING) or (p.panim == PA_FALL) or p.powers[pw_carry] or p.cmphdodge)
			p.sms_dodging = 0
		end
		if (p.cmd.buttons & BT_CUSTOM2)
			//	 if not A_HMSCheckDeathPit(s) //Let's make sure NONE of this works....
		//	if s.health
		// 	and not P_PlayerInPain(p)
				if (p.cmd.sidemove > 0 or p.cmd.sidemove < 0 or p.cmd.forwardmove > 0 or p.cmd.forwardmove < 0)
				and (P_IsObjectOnGround(s) or p.powers[pw_carry] == CR_ROPEHANG)
					if not p.hypermysticsonic //Do gods need to dodge? The real questions we need to ask in life.
					and not ((p.smsmeleebutton > 8) and (p.speed >= 3*FRACUNIT))
					and not ((p.smsmeleebutton > 849) and (p.speed < 3*FRACUNIT))
					and not p.gotflag
					and not p.sms_stompanim
					and not ((p.cmd.forwardmove > 0 or p.cmd.forwardmove < 0) and (s.flags2 & MF2_TWOD or twodlevel))
					and not (s.eflags & MFE_JUSTHITFLOOR)
					and not (s.state == S_SMSCOMETHAYMAKER2)
					and not (p.footsweep02 or p.footsweep03 or (p.footsweep01 and (p.footsweep01 < 13)))
					and not (p.sms_dodgetap > 4)
					and not (p.pflags & (PF_STASIS|PF_SLIDING)) and not p.smsblastboost
					and not (p.powers[pw_carry] and p.powers[pw_carry] != CR_ROPEHANG)
						if p.smsanalogsweep and s.truelsmsat and not (p.pflags & PF_ANALOGMODE) and s.truelsmsa != nil
						s.angle = s.truelsmsa
						s.truelsmsat = 0
						end
						s.smsboostimmune = 15
						p.sms_dodging = 15
							if (p.pflags & PF_ANALOGMODE)
								if (p.cmd.sidemove)
								s.angle = p.drawangle
								elseif (p.cmd.forwardmove < 0)
								s.angle = $+ANGLE_180
								end
							end
							if not (s.eflags & MFE_UNDERWATER)
								if s.sdodgecd
									if s.sdodgelvl
									s.sdodgelvl = $+1
									end
								else
								s.sdodgelvl = 1
								end
							s.sdodgecd = 24
							else
							s.sdodgelvl = 1						
							end
						p.sms_tapnothold = 500
						s.dodgespinslide = false
						s.forcedod = false
						A_SMSquake(s, 5*FRACUNIT, 2, 200, true)
						p.footsweep01 = 0
						p.footsweep02 = 0
						p.footsweep03 = 0
						p.sms_comethaymaker = 0
						p.pflags = $ & ~PF_SPINNING
							if p.powers[pw_carry]
							p.powers[pw_carry] = CR_NONE
							s.z = $+60*FRACUNIT
							end

							if G_GametypeHasSpectators() and not (p.mxscap > 1) and p.rings
								P_GivePlayerRings(p, -1) //Allow players to still use this at 0 rings for clutch life-saving dodges
							end
						
						if not (s.eflags & MFE_UNDERWATER)
						P_SetObjectMomZ(s, FRACUNIT*8)
						S_StartSound(s, sfx_sdodge)
						P_SpawnMobj(s.x+FixedMul(-4*FRACUNIT, cos(s.angle)), s.y+FixedMul(-4*FRACUNIT, sin(s.angle)), s.z, MT_EXPLODE)
						else
						P_SetObjectMomZ(s, FRACUNIT*3)
						S_StartSound(s, sfx_s3k42)
						P_SpawnMobj(s.x, s.y, s.z, MT_MEDIUMBUBBLE)
						P_SpawnMobj(s.x-20*FRACUNIT, s.y-20*FRACUNIT, s.z+2*FRACUNIT, MT_SMALLBUBBLE)
						P_SpawnMobj(s.x+20*FRACUNIT, s.y+20*FRACUNIT, s.z+2*FRACUNIT, MT_SMALLBUBBLE)
						end
							if (p.cmd.forwardmove > 0) //Dodge forwards!
							and not (p.cmd.sidemove > 0)
							and not (p.cmd.sidemove < 0)
							and not (s.flags2 & MF2_TWOD or twodlevel)
							s.state = S_PLAY_RUN
						//	s.frame = B
								if not (s.eflags & MFE_UNDERWATER)
								P_InstaThrust(s, s.angle, FixedMul(71*FRACUNIT, s.scale)+5*FRACUNIT)
								else
								P_InstaThrust(s, s.angle, FixedMul(32*FRACUNIT, s.scale)+5*FRACUNIT)
								end
							elseif (p.cmd.forwardmove < 0) //Dodge Backwards!
							and not (p.cmd.sidemove > 0)
							and not (p.cmd.sidemove < 0)
							and not (s.flags2 & MF2_TWOD or twodlevel)
							s.state = S_SMS_SIDEDODGE2
								if not (s.eflags & MFE_UNDERWATER)
								P_InstaThrust(s, s.angle, FixedMul(-69*FRACUNIT, s.scale)-5*FRACUNIT)
								else
								P_InstaThrust(s, s.angle, FixedMul(-31*FRACUNIT, s.scale)-5*FRACUNIT)
								end
							elseif (p.cmd.sidemove > 0)
							and not (s.flags2 & MF2_TWOD or twodlevel)
							s.state = S_SMS_SIDEDODGE1
							s.sideroll = -1 //Dodge Right!
								if not (s.eflags & MFE_UNDERWATER)
								P_InstaThrust(s, s.angle - ANGLE_90, (FixedMul(64*FRACUNIT, s.scale)+5*FRACUNIT)+cos(p.aiming))
								else
								P_InstaThrust(s, s.angle - ANGLE_90,  (FixedMul(28*FRACUNIT, s.scale)+5*FRACUNIT)+cos(p.aiming))
								end
							elseif (p.cmd.sidemove < 0)
							and not (s.flags2 & MF2_TWOD or twodlevel)
							s.state = S_SMS_SIDEDODGE1
							s.sideroll = 1 //Dodge Left!
								if not (s.eflags & MFE_UNDERWATER)
								P_InstaThrust(s, s.angle + ANGLE_90, (FixedMul(64*FRACUNIT, s.scale)+5*FRACUNIT)+cos(p.aiming))
								else
								P_InstaThrust(s, s.angle + ANGLE_90, (FixedMul(28*FRACUNIT, s.scale)+5*FRACUNIT)+cos(p.aiming))
								end
							elseif (p.cmd.sidemove > 0) or (p.cmd.sidemove < 0) //2D version
							s.state = S_SMS_SIDEDODGE1
								if (p.cmd.sidemove > 0)
								s.sideroll = -1
								else
								s.sideroll = 1
								end
								if not (s.eflags & MFE_UNDERWATER)
								P_InstaThrust(s, s.angle, FixedMul(71*FRACUNIT, s.scale)+5*FRACUNIT)
								else
								P_InstaThrust(s, s.angle, FixedMul(32*FRACUNIT, s.scale)+5*FRACUNIT)
								end
							end
					end
			end
		end
			if p.sms_dodging == 15
			p.smsmeleebutton = 850
				if s.sdodgelvl and not (s.eflags & MFE_UNDERWATER)
					if s.sdodgelvl == 2
						S_StartSound(s, sfx_s236)
						P_SpawnXYZMissile(s, s, MT_EXPLODE, s.x, s.y, s.z)
					elseif (s.sdodgelvl > 2)
						s.sdodgecd = 0
							if (p.pflags & PF_ANALOGMODE)
							s.sliderollang = p.drawangle
							else
							s.sliderollang = s.angle
							end
						s.sdodgeoh = 30
						p.sms_flamedelay = 30
						p.smsatomdivestun = s.angle
						S_StartSound(s, sfx_cdfm51)
						S_StartSound(s, sfx_s3k47)
						S_StartSound(s, sfx_s25b)
						
					//	S_StartSound(s, sfx_kc3b) Unused sound
					
						for d = 0,7
						P_SpawnParaloop(s.x, s.y, s.z, 30*FRACUNIT, 4, MT_NIGHTSPARKLE, d*(ANG20*2), S_XPLD1, true)
						end
						P_SpawnXYZMissile(s, s, MT_EXPLODE, s.x, s.y, s.z)
						s.momx = $*6/5
						s.momy = $*6/5
						s.momz = $*2 
					end
				end
				if (p.pflags & PF_DIRECTIONCHAR)
				p.drawangle = s.angle
				end
			elseif p.sms_dodging == 14
				if s.state == S_PLAY_EDGE
				or (s.state == S_PLAY_WALK)
				or (s.state == S_SMS_SIDEDODGE1)
				s.state = S_SMS_SIDEDODGE1
				elseif not (s.state == S_SMS_SIDEDODGE2)
				s.state = S_PLAY_RUN
				end
			elseif p.sms_dodging == 13
				if (s.state == S_PLAY_WALK)
				or (s.state == S_PLAY_RUN)
				s.state = S_PLAY_ROLL
				end
			elseif p.sms_dodging == 1
				p.pflags = $ & ~PF_THOKKED
				if (p.cmd.buttons & BT_CUSTOM2) and P_IsObjectOnGround(s) and not (p.cmd.buttons & BT_CUSTOM1) and not s.sdodgeoh
				and ((p.speed > 3*FRACUNIT) and (p.speed < 40*FRACUNIT))
				s.momx = $/2 s.momy = $/2 //Makes rapid-dodging easier for the button mashers.
				end
				if not P_IsObjectOnGround(s)
					if not p.powers[pw_carry]
					p.pflags = $|PF_JUMPED
					end
					if (p.pflags & PF_DIRECTIONCHAR)
					p.drawangle = s.angle
					end
				elseif (p.cmd.buttons & BT_USE) and not (p.cmd.forwardmove > 0) and not s.sdodgeoh
				p.pflags = $|PF_STARTDASH|PF_SPINNING|PF_USEDOWN & ~PF_THOKKED
				s.state = S_PLAY_ROLL
				s.momx = 0
				s.momy = 0
				elseif (p.cmd.buttons & BT_CUSTOM1) and not (p.sms_tapnothold and p.sms_tapnothold > 15)
				and (p.cmd.forwardmove or p.cmd.sidemove) and not (s.eflags & MFE_UNDERWATER)  and not s.sdodgeoh
							p.speed = 140*FRACUNIT
							s.smsboostimmune = 7
							if (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))
							p.sms_boostlevel = 65
							else
							p.sms_boostlevel = $+29
							end
						if (p.cmd.forwardmove > 0)
						P_Thrust(s, s.angle, 55*FRACUNIT)
						elseif (p.cmd.sidemove > 0)
							if not (p.pflags & (PF_DIRECTIONCHAR|PF_ANALOGMODE))
							p.drawangle = s.angle-ANGLE_90
							end
						P_Thrust(s, s.angle+ANGLE_90, -55*FRACUNIT)
						elseif (p.cmd.sidemove < 0)
							if not (p.pflags & (PF_DIRECTIONCHAR|PF_ANALOGMODE))
							p.drawangle = s.angle+ANGLE_90
							end
						P_Thrust(s, s.angle+ANGLE_90, 55*FRACUNIT)
						elseif (p.cmd.forwardmove < 0)
						P_Thrust(s, s.angle, -55*FRACUNIT)
						end
						s.ghs = P_SpawnGhostMobj(s)
						s.ghs.destscale = $*4
						s.ghs.rollangle = s.rollangle
						s.ghs.tics = 12
						s.novawave = P_SpawnMobj(s.x, s.y, s.z, MT_HMSNOVAWAVE)
						s.novawave.color = s.color
						s.novawave.followmenoz = s
						s.novawave.tics = 1
						s.novawave.destscale = $/3
						s.novawave.scale = s.scale
						S_StartSound(s, sfx_kc3c)
						S_StartSound(s, sfx_kc5b)						
						S_StartSound(s, sfx_s3k7e)
						s.smsgrboost = P_SpawnMobj(s.x, s.y, s.z, MT_SMSGROUNDBOOST)
						s.smsgrboost.tracer = s
						s.smsgrboost = P_SpawnMobj(s.x+s.momx*3, s.y+s.momy*3, s.z+s.momz*3, MT_SMSAIRBOOST)
						s.smsgrboost.tracer = s
							if G_GametypeHasSpectators() and p.rings
							P_GivePlayerRings(p, -1)
							end
				elseif (p.cmd.buttons & (BT_CUSTOM3|BT_TOSSFLAG|BT_WEAPONPREV|BT_WEAPONNEXT)) // and not (p.pflags & PF_ANALOGMODE)
				and not s.sdodgeoh
				and not (s.eflags & MFE_UNDERWATER)
					p.sweepspeed = 85*FRACUNIT
					p.footsweepanim = true
					p.sweepangle = s.angle
					p.footsweep01 = 0
					p.footsweep02 = 20
					A_SMSquake(s, 9*FRACUNIT, 2, 750, true)
					p.footsweep03 = 0
					p.smsmeleebutton = 9000
					s.state = S_SMS_FOOTSWEEP1
					P_SpawnGhostMobj(s)
					S_StartSound(s, sfx_s1c0)
					S_StartSound(s, sfx_sswip)
					S_StartSound(s, sfx_s3k64)
					if G_GametypeHasSpectators() and not (p.mxscap > 1)
						P_GivePlayerRings(p, -1)
					end
				end
			end
			if (p.sms_dodging > 2)
				p.pflags = $|PF_THOKKED
				p.drawangle = s.angle
				if (p.sms_dodging > 3)
					if s.forcedod and s.forcedodx
					s.momx = s.forcedodx
					s.momy = s.forcedody
					s.forcedod = false
						if (p.speed > 40*FRACUNIT)
						s.momx = $/2
						s.momy = $/2
						end
					end
					s.forcedodx = s.momx 
					s.forcedody = s.momy
				end
				if (p.sms_dodging > 10)
				local ghscolor = P_RandomRange(SKINCOLOR_SUPERRED1, SKINCOLOR_SUPERPERIDOT5)
					for d = 1,3
						if (d % 2 == 0)
						s.ghs = P_SpawnMobj(s.x-s.momx/2, s.y-s.momy/2, s.z-s.momz/2, MT_THOK)
						s.ghs.scale = $*10/9
						s.ghs.color = ghscolor
						s.ghs.momx = s.momx/d
						s.ghs.momy = s.momy/d
						s.ghs.momz = s.momz/d
						s.ghs.tics = 4
						s.ghs.destscale = s.ghs.scalespeed+1
						else
						s.ghs = P_SpawnGhostMobj(s)
						s.ghs.color = ghscolor
						s.ghs.tics = 3
						s.ghs.rollangle = s.rollangle
						s.ghs.momx = s.momx/((d)*-1)
						s.ghs.momy = s.momy/((d)*-1)
						s.ghs.momz = s.momz/((d)*-1)
						end
					end
				end
				if (p.cmd.buttons & BT_ATTACK) //Allow an immediate diffusion flame
				p.sms_flamebuttonhold = 3500
				end
				if (s.eflags & MFE_JUSTHITFLOOR)
				p.sms_dodging = 2
					if not s.sdodgeoh
						if (p.cmd.buttons & BT_USE) and not (p.cmd.forwardmove > 0)
						p.pflags = $|PF_STARTDASH|PF_SPINNING|PF_USEDOWN & ~PF_THOKKED
						s.state = S_PLAY_ROLL
						s.momx = 0
						s.momy = 0
						elseif (p.cmd.buttons & BT_CUSTOM1) and not (p.sms_tapnothold and p.sms_tapnothold > 15)
						and (p.cmd.forwardmove or p.cmd.sidemove) and not (s.eflags & MFE_UNDERWATER)
							p.speed = 140*FRACUNIT //Trick SRB2 for 1 frame
							s.smsboostimmune = 7
							if (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))
							p.sms_boostlevel = 65
							else
							p.sms_boostlevel = $+29
							end
						if (p.cmd.forwardmove > 0)
						P_Thrust(s, s.angle, 55*FRACUNIT)
						elseif (p.cmd.sidemove > 0)
							if not (p.pflags & (PF_DIRECTIONCHAR|PF_ANALOGMODE))
							p.drawangle = s.angle-ANGLE_90
							end
						P_Thrust(s, s.angle+ANGLE_90, -55*FRACUNIT)
						elseif (p.cmd.sidemove < 0)
							if not (p.pflags & (PF_DIRECTIONCHAR|PF_ANALOGMODE))
							p.drawangle = s.angle+ANGLE_90
							end
						P_Thrust(s, s.angle+ANGLE_90, 55*FRACUNIT)
						elseif (p.cmd.forwardmove < 0)
						P_Thrust(s, s.angle, -55*FRACUNIT)
						end
						s.ghs = P_SpawnGhostMobj(s)
						s.ghs.destscale = $*4
						s.ghs.rollangle = s.rollangle
						s.ghs.tics = 12
						p.sms_tapnothold = 30
						s.novawave = P_SpawnMobj(s.x, s.y, s.z, MT_HMSNOVAWAVE)
						s.novawave.color = s.color
						s.novawave.followmenoz = s
						s.novawave.tics = 1
						s.novawave.destscale = $/3
						s.novawave.scale = s.scale
						S_StartSound(s, sfx_kc3c)
						S_StartSound(s, sfx_kc5b)						
						S_StartSound(s, sfx_s3k7e)
						s.smsgrboost = P_SpawnMobj(s.x, s.y, s.z, MT_SMSGROUNDBOOST)
						s.smsgrboost.tracer = s
						s.smsgrboost = P_SpawnMobj(s.x+s.momx*3, s.y+s.momy*3, s.z+s.momz*3, MT_SMSAIRBOOST)
						s.smsgrboost.tracer = s
							if G_GametypeHasSpectators() and p.rings
							P_GivePlayerRings(p, -1)
							end
						elseif (p.cmd.buttons & (BT_CUSTOM3|BT_TOSSFLAG|BT_WEAPONPREV|BT_WEAPONNEXT)) // and not (p.pflags & PF_ANALOGMODE)
						and not (s.eflags & MFE_UNDERWATER)
						p.sweepspeed = 85*FRACUNIT
						p.footsweepanim = true
						p.sweepangle = s.angle
						p.footsweep01 = 0
						p.footsweep02 = 20
						A_SMSquake(s, 9*FRACUNIT, 2, 750, true)
						p.footsweep03 = 0
						p.smsmeleebutton = 9000
						s.state = S_SMS_FOOTSWEEP1
						P_SpawnGhostMobj(s)
						S_StartSound(s, sfx_s1c0)
						S_StartSound(s, sfx_sswip)
						S_StartSound(s, sfx_s3k64)
						if G_GametypeHasSpectators() and not (p.mxscap > 1)
							P_GivePlayerRings(p, -1)
						end
						end
					end
				end
			end

//Remember those flying rings jumps did in Sonic X? ...no?
//Well, here's the Ring Burst. It consumes a whole load of rings,
//but holy crap, it is ridiculously powerful

			if p.sms_ringburstfalltimer
			and not p.sms_ringburstfly
				p.sms_ringburstfalltimer = 0
			end
			if P_IsObjectOnGround(s)
			and ((((p.powers[pw_sneakers] > 2) and (G_PlatformGametype() and not s.battlemodsms)) and (p.speed > 107*FRACUNIT)) or (p.sms_boostlevel >= 64))
			and ((p.cmd.buttons & BT_CUSTOM1) or p.sms_autoboosthold)
			and not (s.eflags & MFE_UNDERWATER)
			and not (p.sms_ringburst)
			p.sms_ringburstready = 3
			end
			if (p.pflags & PF_DIRECTIONCHAR) //Let's not have directionchar screw us here.
			and (p.sms_ringburstready or p.sms_ringburst or p.sms_ringburstfly)
				p.drawangle = s.angle
			end
			if s.waitforforward
				if not (p.cmd.forwardmove > 0)
				s.waitforforward = false
				end
			end
			if p.sms_ringburstready		
			and (p.rings > 9)
			and not p.hypermysticsonic
			and not p.gotflag
				if (p.cmd.buttons & BT_CUSTOM1) and P_IsObjectOnGround(s) and not s.sms_tapnothold2
				s.sms_tapnothold2 = 10
				elseif s.sms_tapnothold2
					if not P_IsObjectOnGround(s)
					s.sms_tapnothold2 = 0
					s.ret4ringburst = false
					elseif not (p.cmd.buttons & BT_CUSTOM1)
					s.sms_tapnothold2 = $-1
					elseif (p.cmd.buttons & BT_CUSTOM1)
						if (s.sms_tapnothold2 < 10)
						s.ret4ringburst = true
						s.sms_tapnothold2 = 0
						end
					end
				end
				if (p.pflags & PF_DIRECTIONCHAR)
				p.drawangle = s.angle
				end
				if p.skidtime
				and not (twodlevel or (s.flags2 & MF2_TWOD)) 

				or (twodlevel or (s.flags2 & MF2_TWOD))
				and (p.cmd.forwardmove < 0)

					p.smsstompspawn = P_SpawnMobj(s.x, s.y, s.z, MT_EXPLODE)
					p.smsstompspawn.scale = s.scale 
					p.sms_ringburst = 43
					p.sms_ringburstfalltimer = 0
					S_StartSound(s, sfx_s3k79)
					s.state = S_SMS_RINGBURSTSLIDE
					if (twodlevel or (s.flags2 & MF2_TWOD))
					p.pflags = $ & ~PF_SPINNING  & ~PF_STARTDASH
					P_InstaThrust(s, s.angle, 0)
					p.powers[pw_nocontrol] = $+4
					else
					P_InstaThrust(s, s.angle, FixedMul(7*FRACUNIT, s.scale))
					end
				end
			elseif s.sms_tapnothold2
			s.sms_tapnothold2 = 0
			end
			if (p.sms_ringburst or s.ret4ringburst)
			or ((p.pflags & PF_SPINNING) and not (p.pflags & PF_STARTDASH) and not ((s.momz*P_MobjFlip(s) < 0) and (p.pflags & PF_JUMPED)) 
			and ((p.sms_boostlevel >= 65) or (p.powers[pw_sneakers] > 2) and (G_PlatformGametype() and not s.battlemodsms))
			and not (s.eflags & MFE_UNDERWATER) and (p.speed > 100*FRACUNIT)) //and P_IsObjectOnGround(s)
				if (p.skidtime or p.speed < 5000)
				and P_IsObjectOnGround(s)
				and not (p.pflags & (PF_STARTDASH|PF_SPINNING))
				s.state = S_SMS_RINGBURSTSLIDE
				elseif (s.state == S_PLAY_WALK) and (p.pflags & PF_SPINNING)
				s.state = S_PLAY_ROLL
				end
				if (p.sms_ringburst % 2 == 0)
				or p.sms_ringburst == 1
					s.flags2 = $ & ~MF2_DONTDRAW //Game does this naturally, buuuut....
					P_SpawnGhostMobj(s)
					p.smsstompspawn = P_SpawnMobj(s.x, s.y, s.z, MT_SPARK)
					p.smsstompspawn.scale = s.scale

				elseif not (p.sms_ringburst % 2 == 0)
					s.flags2 = $|MF2_DONTDRAW
				end

				if (p.rings > 9)
				and not (p.pflags & PF_SLIDING)
				and not p.gotflag
				and not (s.eflags & MFE_UNDERWATER)
					if (p.cmd.buttons & BT_JUMP) and not (p.sms_jumphold and p.sms_jumphold > 24)
					and ((p.cmd.buttons & BT_CUSTOM2) or (p.cmd.forwardmove < 0))
					or s.ret4ringburst
						P_DoJump(p, true)
						s.waitforforward = true
						s.ret4ringburst = false
						p.sms_boostlevel = 0
						p.sms_ringburst = 0
						p.sms_ringburstready = 0
						p.sms_ringburstfly = 1
						p.sms_ringburstdrain = 1
						if s.smssoundobj9 and s.smssoundobj9.valid
						P_KillMobj(s.smssoundobj9)
						end
						s.ringburstticket2 = 31
						s.smssoundobj9 = P_SpawnMobj(s.x, s.y, s.z, MT_SMSSOUNDOBJ)
						s.smssoundobj9.master = s
						s.smssoundobj9.health = 1
						S_StartSound(s.smssoundobj9, sfx_smsrbt)
						s.smssoundobj9.smsrbt = 1
						A_SMSquake(s, 45*FRACUNIT, 5, 1500)
						P_FlashPal(p, PAL_MIXUP, 7)
						P_NukeEnemies(s, s, FixedMul(300*FRACUNIT, s.scale))
						P_SpawnMobj(s.x, s.y, s.z, MT_SMSAIRBOOST)
						P_GivePlayerRings(p, -1)

						if not p.smsgraphix
						s.hjg1 = P_SpawnMobj(s.x, s.y, s.z-20*FRACUNIT, MT_HMSWAVEAURA)
						s.hjg1.dustwave = 1
						s.hjg1.blendmode = AST_ADD
						s.hjg1.sprite = SPR_SMMK
						s.hjg1.frame = 3
						s.hjg1.target = s
						s.hjg1.fuse = 15
						s.hjg1.scale = s.scale*2
						s.hjg1.destscale = s.scale*5
						end
						
						A_SMSSTOMPQUAKE(s, 45, 5, 5*FRACUNIT, 0, 0, 0, 7, SKINCOLOR_SUPERRED4)
						A_SMSSTOMPQUAKE(s, 85, 6, 16*FRACUNIT, 0, ANG10, 0, 22)
						A_SMSSTOMPQUAKE(s, 125, 7, 30*FRACUNIT, 0, ANG20, 0, 14)
						A_SMSSTOMPQUAKE(s, 165, 12, 40*FRACUNIT, FRACUNIT*2, ANG30, 0, 19, SKINCOLOR_SUPERSILVER4)
				
						A_SMSSTOMPQUAKE(s, 55, 5, 7*FRACUNIT, 0, ANG30, 0, 7, SKINCOLOR_RED)
						A_SMSSTOMPQUAKE(s, 75, 6, 12*FRACUNIT, 0, (ANG10*5), 0, 22)
						A_SMSSTOMPQUAKE(s, 115, 7, 25*FRACUNIT, 0, 0, 0, 14)
						A_SMSSTOMPQUAKE(s, 145, 12, 35*FRACUNIT, FRACUNIT*2, (ANG30*2), 0, 19, SKINCOLOR_SILVER)
					end
				end
			end
			if (p.sms_ringburstfly == 1)
			and p.rings
				p.charflags = $|SF_CANBUSTWALLS
				if not ((p.cmd.forwardmove > 0) and not s.waitforforward)
					if (p.sms_ringburstfalltimer and (p.sms_ringburstfalltimer == 1))
					s.state = S_SMS_VERTICALRINGBURST
					end
					if (twodlevel or (s.flags2 & MF2_TWOD))
					P_InstaThrust(s, s.angle, FixedMul(0*FRACUNIT, s.scale))
					elseif (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))
					P_InstaThrust(s, s.angle, FixedMul(135*FRACUNIT, s.scale))
					else
					P_InstaThrust(s, s.angle, FixedMul(90*FRACUNIT, s.scale))
					end
					if not ((p.sms_ringburstdrain == 1) or (p.sms_ringburstdrain == 3))
						if (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))
						P_SetObjectMomZ(s, 50*FRACUNIT)
						else
						P_SetObjectMomZ(s, 35*FRACUNIT)
						end
					end
					if (p.sms_ringburstfalltimer < 6)
					P_SpawnGhostMobj(s)
					end
					if (leveltime % 2 == 0)
					A_SMSSTOMPSMOKE(s, P_RandomRange(20, 65), MT_IVSP)
					else
					A_SMSSTOMPSMOKE(s, P_RandomRange(20, 65), MT_SUPERSPARK)
					end
					if (p.sms_ringburstfalltimer > 64)
					p.sms_ringburstfly = 0
						if (p.sms_boostlevel < 23)
						p.sms_boostlevel = 23
						end
					P_SpawnGhostMobj(s)
					s.state = S_SMS_SIDET
					p.hometrickanim = true
					s.hmscchange = true 
					p.pflags = $ & ~PF_JUMPED
					p.homingtrickcharge = 0
					s.airboostroll = 0
					s.rollangle = 0
					s.smstrickroll = true
					s.smstrickrollang = 0
					p.charability = CA_THOK
					s.momz = $*5/6
					end
				end
				if ((p.cmd.forwardmove > 0) and not s.waitforforward)
				or ((p.cmd.buttons & BT_USE) and not (p.spinhold and (p.spinhold > 1)))
					p.sms_ringburstradialboost = P_SpawnMobj(s.x, s.y, s.z+((12*FRACUNIT)*(P_MobjFlip(s))), MT_RADIALBOOST)
					p.sms_ringburstradialboost.color = 2
					p.sms_ringburstradialboost.blendmode = AST_ADD
					p.sms_ringburstfly = 2
					s.ringburstticket2 = 39
					A_SMSquake(s, 46*FRACUNIT, 4, 900)
						if s.smssoundobj9 and s.smssoundobj9.valid
						P_KillMobj(s.smssoundobj9)
						end
						s.waitforforward = false
						s.smssoundobj9 = P_SpawnMobj(s.x, s.y, s.z, MT_SMSSOUNDOBJ)
						s.smssoundobj9.master = s
						s.smssoundobj9.health = 1
						S_StartSound(s.smssoundobj9, sfx_smsrbt)
						s.smssoundobj9.smsrbt = 2
					S_StartSound(s, sfx_smsrbt)
				//	S_StartSound(s, sfx_rail2)
					p.sms_ringburstfalltimer = 0
					p.spinhold = 10
					s.state = S_SMS_HORIZONTALRINGBURST
				end
				if not (p.panim == PA_ROLL) and not s.smstrickroll
				and (p.sms_ringburstfalltimer and (p.sms_ringburstfalltimer > 6))
				s.state = S_PLAY_ROLL
				end
			elseif (p.sms_ringburstfly == 2)
			and (p.rings)
				p.charflags = $|SF_CANBUSTWALLS
				if (p.sms_ringburstfalltimer and (p.sms_ringburstfalltimer == 1))
				s.state = S_SMS_HORIZONTALRINGBURST
				end
				if not (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))
				p.smsgrboost = P_SpawnMobj(s.x, s.y, s.z+((12*FRACUNIT)*(P_MobjFlip(s))), MT_SMSGROUNDBOOST)
				p.smsgrboost.tracer = s
				p.smsgrboost.ringburst2 = true
				P_RadiusAttack(s, s, 128*FRACUNIT)
				end
				P_SetObjectMomZ(s, 0*FRACUNIT)
				if not ((p.sms_ringburstdrain == 1) or (p.sms_ringburstdrain == 3))
					if (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))
						P_InstaThrust(s, s.angle, FixedMul(225*FRACUNIT, s.scale))
					else
						P_InstaThrust(s, s.angle, FixedMul(150*FRACUNIT, s.scale))
					end
				end
				if (p.sms_ringburstfalltimer > 90)
					P_SpawnGhostMobj(s)
					s.state = S_SMS_ROLLT2
					p.hometrickanim = true
					p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED & ~PF_NOJUMPDAMAGE
					p.homingtrickcharge = 0
					p.sms_ringburstfly = 0
				end
				if ((p.sms_ringburstfly == 2) and (p.sms_ringburstfalltimer and (p.sms_ringburstfalltimer > 2)) and (p.speed < FixedMul(30*FRACUNIT, s.scale)))
					p.sms_ringburstready = 0
					p.sms_ringburstfly = 3
					p.sms_ringburstdrain = 0
					p.powers[pw_flashing] = 46
					p.sms_flamedelay = 46
					s.state = S_PLAY_ROLL
					S_StartSound(s, sfx_dmpain)
					P_InstaThrust(s, s.angle, 0)
					P_SetObjectMomZ(s, 1*FRACUNIT)
					P_FlashPal(p, PAL_MIXUP, 7)
					P_NukeEnemies(s, s, 100*FRACUNIT)
					P_SpawnMobj(s.x, s.y, s.z, MT_BURSTWAVE)
				end
			elseif (p.sms_ringburstfly == 3)
				P_SetObjectMomZ(s, 1*FRACUNIT)
				if (p.powers[pw_flashing] <= 16)
				or (p.sms_flamedelay <= 16)
					p.sms_ringburstfly = 0
					s.state = S_PLAY_FALL
				end
			end
			if p.sms_ringburstfly
			p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING
				if (leveltime % 2 == 0)	and not (p.sms_ringburstfly == 3)
				s.ringburstticket = true
				end
				if (p.cmd.buttons & BT_CUSTOM2)
				and not (p.smsmeleebutton > 1)
					P_InstaThrust(s, s.angle, 0)
					P_NukeEnemies(s, s, FixedMul(128*FRACUNIT, s.scale))
					P_SetObjectMomZ(s, FRACUNIT*-45)
					S_StartSound(s, sfx_stst)
					if not p.powers[pw_carry]
					p.pflags = $|PF_JUMPED
					end
					p.sms_ringburstfly = 0
					p.sms_stompanim = 9001

				elseif ((s.state == S_PLAY_WALK) or (s.state == S_PLAY_RUN) or (s.state == S_SMSWATERGRIND1))
				and (P_IsObjectOnGround(s) and not (p.sms_ringburstfly == 1))
				and (p.sms_ringburstfalltimer and p.sms_ringburstfalltimer > 3)
				p.sms_boostlevel = 67
				p.sms_ringburstready = 0
				p.sms_ringburstfly = 0
				
				elseif (s.state == S_PLAY_PAIN) or (s.state == S_PLAY_SPRING)
				or not s.health
				or p.hypermysticsonic
				or p.gotflag or p.powers[pw_carry]
				or (p.panim == PA_FALL)
				or ((s.eflags & MFE_JUSTHITFLOOR) and P_IsObjectOnGround(s) and not (p.sms_ringburstfly == 1))
					if not s.smstrickroll
						p.sms_ringburstready = 0
						p.sms_ringburstfly = 0
						if (s.state == S_PLAY_ROLL) and not p.powers[pw_carry]
						p.pflags = $|PF_JUMPED
						end
					end
				elseif (p.sms_ringburstfly and (p.sms_ringburstfly < 3)) and (p.rings < 2)
				or ((p.sms_ringburstfly == 2) and (p.sms_ringburstfalltimer and (p.sms_ringburstfalltimer > 2)) and (p.speed < FixedMul(30*FRACUNIT, s.scale)))
				or ((p.sms_ringburstfly == 1) and (s.momz == 0) and (p.sms_ringburstfalltimer > 2))
					p.sms_ringburstready = 0
					p.sms_ringburstfly = 3
					p.sms_ringburstdrain = 0
					p.powers[pw_flashing] = 46
					p.sms_flamedelay = 46
					s.state = S_PLAY_ROLL
					S_StartSound(s, sfx_dmpain)
					P_InstaThrust(s, s.angle, 0)
					P_SetObjectMomZ(s, 1*FRACUNIT)
					P_FlashPal(p, PAL_MIXUP, 7)
					P_NukeEnemies(s, s, 100*FRACUNIT)
					P_SpawnMobj(s.x, s.y, s.z, MT_BURSTWAVE)
				elseif not (p.sms_ringburstfly == 1)
					if ((p.cmd.buttons & BT_USE) and not (p.spinhold and (p.spinhold > 1)))
					p.sms_ringburstfly = 0
						if (p.sms_boostlevel < 31)
						p.sms_boostlevel = 31
						end
						P_SpawnGhostMobj(s)
						s.state = S_SMS_ROLLT2
						p.hometrickanim = true
						p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED & ~PF_NOJUMPDAMAGE
						p.homingtrickcharge = 0
					end
				end
			end

//One of SMS' supermoves, the Comet Haymaker. When you reach incredible
//speeds, turn your kinetic energy into one deadly punch, sending
//your enemies flying into the walls like comets.
			if p.sms_comethaymaker
			and not ((s.state == S_SMSCOMETHAYMAKER1) or (s.state == S_HMSCOMETHAYMAKER1))
			and not ((s.state == S_HMSCOMETHAYMAKER2) or (s.state == S_SMSCOMETHAYMAKER2))
				if p.hypermysticsonic
					s.state = S_HMSCOMETHAYMAKER1
				else
					s.state = S_SMSCOMETHAYMAKER1
				end
			end
			if s.smshmcheck or ((p.sms_boostlevel and p.sms_boostlevel >= 64) or (p.hypermysticsonic) or (p.sms_ringburst and not p.sms_ringburstfly)) //You need some speed going for this attack.
			and (P_IsObjectOnGround(s) or p.smseasyhaymaker or ((p.cmd.buttons & BT_CUSTOM1 and (p.cmd.forwardmove < 0) and not (p.cmd.sidemove < 0) and not (p.cmd.sidemove > 0) and ((p.hypermysticsonic) or (p.speed > FixedMul(5*FRACUNIT, s.scale))))))
			and not p.sms_dodging
				if ((p.cmd.buttons & BT_CUSTOM2) or s.smshmcheck)
				and ( s.smshmcheck or not ((p.pflags & PF_JUMPED and not ((p.hypermysticsonic) or p.smseasyhaymaker or ((p.cmd.buttons & BT_CUSTOM1) and (p.cmd.forwardmove < 0)))) ) )
				and ((p.smsmeleebutton and p.smsmeleebutton < 5 and not p.hypermysticsonic) or (p.smsmeleebutton and p.smsmeleebutton < 2 and p.hypermysticsonic)) //Don't hold the button.
				and not (p.sms_stompanim and not p.smseasyhaymaker)
				and not (p.transformdown|p.sms_comethaymaker|p.gotflag)
				and not (p.pflags & PF_SLIDING) and not p.powers[pw_carry]
				and not ((s.state == S_SMSCOMETHAYMAKER2) or ((s.state == S_HMSCOMETHAYMAKER2) and not (G_PlatformGametype() and not s.battlemodsms)))
				and not (p.cmd.buttons & BT_TOSSFLAG)
				   if not G_GametypeHasSpectators()
					if p.hypermysticsonic
				//	A_SMSFindTarget(s, 1891*FRACUNIT, 1)
					s.eymon = P_SpawnMobj(s.x+FixedMul(1100*FRACUNIT,cos(s.angle)), s.y+FixedMul(1100*FRACUNIT,sin(s.angle)), s.z-1400*FRACUNIT, MT_SMSECHECK)
						if s.eymon and s.eymon.valid
						s.eymon.cmphhms = true
						s.eymon.target = s
						s.eymon.height = 2800*FRACUNIT
						s.eymon.radius = 1300*FRACUNIT
						end
					else
					s.eymon = P_SpawnMobj(s.x+FixedMul(570*FRACUNIT,cos(s.angle)), s.y+FixedMul(570*FRACUNIT,sin(s.angle)), s.z-600*FRACUNIT, MT_SMSECHECK)
						if s.eymon and s.eymon.valid
						s.eymon.cmphsms = true
						s.eymon.target = s
						s.eymon.height = 1200*FRACUNIT
						s.eymon.radius = 660*FRACUNIT
						end
				//	A_SMSFindTarget(s, 922*FRACUNIT, 1)
					end
						if s.smshmcheck and s.target and s.cmphtarget and (s.cmphtarget == s.target) 
						and s.target.health // and ((s.target.flags & MF_ENEMY) or (s.target.flags & MF_BOSS) or (s.target.type == MT_EGGGUARD) or (s.target.type == MT_FANG) or (s.target.type == MT_PTERABYTE) )
						and not s.target.fusrodah // and (P_CheckSight(s, s.target))
						and (((FixedHypot(s.target.x-s.x, s.target.y-s.y)) < 1640*FRACUNIT) or (((FixedHypot(s.target.x-s.x, s.target.y-s.y)) < 3400*FRACUNIT) and p.hypermysticsonic))
						s.smshmcheck = 0
						s.cmphtarget = nil
						s.cmphclosest = nil
						  if (s.target.type == MT_METALSONIC_BATTLE) and s.target.health
						  s.target.flags = $|MF_BOSS|MF_SHOOTABLE & ~MF_NOCLIPTHING & ~MF_NOCLIP
						  end
						  if (s.target.type == MT_EGGGUARD) and s.target.tracer and s.target.tracer.health and (s.target.tracer.type == MT_EGGSHIELD)
						  s.target.tracer.state = S_NULL
						  s.target.flags = $|MF_SHOOTABLE|MF_ENEMY
						  end
						  
						p.pflags = $ & ~PF_JUMPED & ~PF_SPINNING
						P_HomingAttack(s, s.target) //Use the default homing attack the first tic.
						p.sms_comethaymaker = 25
						p.sms_ringburst = 0
							
								if (s.target.type == MT_MINUS)
								and not s.target.fusrodah
									s.target.state = S_MINUS_AERIAL1
									s.target.z = $+(20*FRACUNIT*(P_MobjFlip(s.target)))
									P_SetObjectMomZ(s.target, 3*FRACUNIT, true)
									s.target.flags = $|MF_SHOOTABLE|MF_ENEMY|MF_SPECIAL & ~MF_NOCLIPTHING
								end
										
								if not p.hypermysticsonic
								s.state = S_SMSCOMETHAYMAKER1
								S_StartSound(s, sfx_cmph)
								
								else

								s.state = S_HMSCOMETHAYMAKER1
								P_SpawnMobj(s.x, s.y, s.z, MT_BURSTLIGHT)
								P_FlashPal(p, 0, 3)
								S_StartSound(s, sfx_nerf)
								if not (s.target.subsector == s.subsector) 
								and P_CheckPosition(s, s.target.x+FixedMul(-65*FRACUNIT, cos(s.angle)), s.target.y+FixedMul(-65*FRACUNIT, sin(s.angle)), s.target.z)
								P_TeleportMove(s, s.target.x+FixedMul(-65*FRACUNIT, cos(s.angle)), s.target.y+FixedMul(-65*FRACUNIT, sin(s.angle)), s.target.z )
								elseif (s.target.z < s.floorz) or (s.target.z > s.ceilingz)
								P_TryMove(s, s.target.x+FixedMul(-65*FRACUNIT, cos(s.angle)), s.target.y+FixedMul(-65*FRACUNIT, sin(s.angle)), true)
								s.z = s.target.z
								else
								s.z = s.target.z
								P_TryMove(s, s.target.x+FixedMul(-65*FRACUNIT, cos(s.angle)), s.target.y+FixedMul(-65*FRACUNIT, sin(s.angle)), true)
								end
								P_InstaThrust(s, 0, 0)
									if not p.lddiscount
									S_StartSound(s, sfx_rail1)
									S_StartSound(s, sfx_rail1)
									p.smsradialboosteffect = P_SpawnMobj(s.x, s.y, s.z, MT_RADIALBOOST)
									p.smsradialboosteffect.target = s
									elseif (p.lddiscount == 1)
									S_StartSound(s, sfx_bedie1)
									P_SpawnMobj(s.x, s.y, s.z, MT_SMSAIRBOOST)
									elseif (p.lddiscount == 2)
									S_StartSound(s, sfx_s3k4e)
									P_SpawnMobj(s.x, s.y, s.z, MT_BURSTLIGHT)
									else
									S_StartSound(s, sfx_s3k83)
									P_SpawnMobj(s.x, s.y, s.z, MT_SMSGROUNDBOOST)
									end
								end
						end
				   elseif not G_PlatformGametype() or s.battlemodsms
				    for z in players.iterate
					 if z.mo
					 and not (s == z.mo)
					 and not (s.x > z.mo.x+750*FRACUNIT)
					 and not (s.x < z.mo.x-750*FRACUNIT)
					 and not (s.y > z.mo.y+750*FRACUNIT)
					 and not (s.y < z.mo.y-750*FRACUNIT)
					 and not (s.z > z.mo.z+475*FRACUNIT)
					 and not (s.z < z.mo.z-435*FRACUNIT)
					 and not (p.ctfteam and p.ctfteam == z.ctfteam)
					 and not z.powers[pw_flashing]
					 and P_CheckSight(s, z.mo)
					 s.target = z.mo
					 p.sms_flamedelay = 36
						if (s.target and s.target.player)
							if s.target.player.cmphspamreduce //Oops, they've been attacked recently. Give them extra time.
							and not p.hypermysticsonic
							s.cmphdelayjump = 19
							p.sms_comethaymaker = 0
							p.sms_ringburst = 0
							p.sms_flamedelay = 55
							s.momx = $/8
							s.momy = $/8
							P_SetObjectMomZ(s, 44*FRACUNIT)
							s.state = S_PLAY_ROLL
							p.powers[pw_nocontrol] = 2
							p.pflags = $ & ~PF_JUMPED & ~PF_SPINNING
							S_StartSound(s, sfx_s255)
							S_StartSound(s, sfx_s255)
							s.ghs = P_SpawnMobj(s.x, s.y, s.z, MT_BURSTLIGHT)
							s.ghs.color = s.color
							s.ghs.blendmode = AST_ADD
							else
							p.pflags = $ & ~PF_JUMPED
							P_HomingAttack(s, s.target) //Home into our chosen player.
							S_StartSound(s, sfx_cmph)
							p.sms_comethaymaker = 36
							p.sms_ringburst = 0
							s.target.player.cmphspamreduce = 900
								if not p.hypermysticsonic
								s.state = S_SMSCOMETHAYMAKER1
									if s.battlemodsms and not p.powers[pw_flashing]
									p.powers[pw_flashing] = 50
									s.flags2 = MF2_DONTDRAW
									end
								else
								s.state = S_HMSCOMETHAYMAKER1
								end
							end
							z.smpawncher = p //Pre-emptive warning
							z.cmphwarning = 8
						end
					  end
				     end
				   end
				end
			end
					
			if s.cmphdelayjump
				s.cmphdelayjump = $-1
				P_SpawnGhostMobj(s)
				p.powers[pw_nocontrol] = 2
				
				if P_PlayerInPain(p)
				s.cmphdelayjump = 0
				s.target = nil
				elseif s.state != S_PLAY_ROLL
				s.state = S_PLAY_ROLL
				end
				
				if s.target and s.target.player and s.target.health and not (s.target == s)
					P_HomingAttack(s, s.target)
					s.momz = $*4/5
					A_FaceTarget(s)
					
					if s.cmphdelayjump == 1 and s.target and s.target.health //Enough stalling, chaaaarge!
					s.cmphdelayjump = 0
						p.pflags = $ & ~PF_JUMPED
						P_HomingAttack(s, s.target) //Home into our chosen player.
						S_StartSound(s, sfx_cmph)
						p.sms_comethaymaker = 36
						p.sms_ringburst = 0
						s.target.player.cmphspamreduce = 900
							if not p.hypermysticsonic
							s.state = S_SMSCOMETHAYMAKER1
								if s.battlemodsms and not p.powers[pw_flashing]
								p.powers[pw_flashing] = 50
								s.flags2 = MF2_DONTDRAW
								end
							else
							s.state = S_HMSCOMETHAYMAKER1
							end
					elseif (s.target.player.cmphdodge or s.target.player.sms_dodging) //They dodged already?!
						s.cmphdelayjump = 0
						p.sms_comethaymaker = 0
						P_HomingAttack(s, s.target)
						s.target = nil
						if not p.hypermysticsonic
						s.state = S_SMSCOMETHAYMAKER2
						else
						s.state = S_HMSCOMETHAYMAKER2
						end
					elseif not (s.target.player.cmphwarning and s.target.player.cmphwarning > 1) //Give them a dodge prompt
					and not s.target.player.cmphdodge
					and not (s.target.player.ctfteam and (s.target.player.ctfteam == s.target.player.ctfteam))
						s.target.player.smpawncher = p
						s.target.player.cmphwarning = 3
							if s.target.player.powers[pw_tailsfly]
							s.target.state = S_PLAY_FALL
							s.target.player.powers[pw_tailsfly] = 0
							s.target.player.fly1 = 0
							s.target.player.secondjump = 0
							end			
					end
				else
					s.momz = $/3 //Oops, target stopped existing, cancel that ticket.
					s.cmphdelayjump = 0
					s.target = nil
				end
			end
			
			
			
			
			
			if ((s.state == S_HMSCOMETHAYMAKER2) or (s.state == S_SMSCOMETHAYMAKER2))
			  if (p.pflags & PF_DIRECTIONCHAR) or (p.pflags & PF_ANALOGMODE) //Because directionchar can't do anything right
			  p.drawangle = s.angle
			  end
			  if s.target
			  P_SetObjectMomZ(s, 0)
			  P_InstaThrust(s, s.angle, 0)
			  p.sms_comethaymaker = 0
				if  G_GametypeHasSpectators()
				and (P_FaceStabCheckMeleeRange(s) or P_CheckSight(s, s.target))
					if p.hypermysticsonic
						if s.target.player.powers[pw_invulnerability]
						s.target.player.powers[pw_invulnerability] = 0  //No defense
						P_RestoreMusic(s.target.player)
						end
						if not s.battlemodsms
						P_RemoveShield(s.target.player)
						end
						s.target.player.losstime = 2000
						P_FlashPal(s.target.player, PAL_MIXUP, 5)
						P_DamageMobj(s.target, s, s)
						P_SpawnMobj(s.target.x, s.target.y, s.target.z, MT_BURSTWAVE)
						P_InstaThrust(s.target, s.angle, 125*FRACUNIT)
						S_StartSound(s.target, sfx_nerf)
						s.target.player.cmphspamreduce = 900
						p.powers[pw_nocontrol] = 8
						if s.target.health //I COULD stop dead people, but this is hilarious.
							P_SetObjectMomZ(s.target, 12*FRACUNIT)
							s.target.state = S_PLAY_PAIN
							s.target.player.hmsbpunch = true
						end
					elseif not (s.target.player and (s.target.player.cmphdodge or s.target.player.sms_dodging) ) and (s.tics == 10)
						if not s.battlemodsms
						P_RemoveShield(s.target.player)
						end
						P_FlashPal(s.target.player, PAL_MIXUP, 4)
						P_DamageMobj(s.target, s, s)
						P_InstaThrust(s.target, s.angle, 125*FRACUNIT)
						S_StartSound(s.target, sfx_nerf)
						s.target.player.cmphspamreduce = 900
						if not s.battlemodsms
						P_RemoveShield(s.target.player)
						end

						if s.target.health //I COULD remove instathrust and stop dead people, but it's hilarious.
							P_SetObjectMomZ(s.target, 12*FRACUNIT)
							s.target.state = S_PLAY_PAIN
						end
					end
				 end
				end
			end

			if p.sms_comethaymaker
			and s.target
				if (G_GametypeHasSpectators() or s.battlemodsms)
				p.sms_boostdrain = $+1
				end
			
			  if (p.pflags & (PF_DIRECTIONCHAR|PF_ANALOGMODE)) //Because directionchar can't do anything right...
				s.forcesmsangletimer = 9
				s.forcesmsangle = R_PointToAngle2(s.x, s.y, s.target.x, s.target.y)
			  end
			//  if not s.target.player
			//  s.target.flags = $|MF_SHOOTABLE|MF_ENEMY & ~MF_NOCLIPTHING & ~MF_NOCLIP
			//  end
			p.charflags = $ & ~SF_RUNONWATER
				if (s.state == S_SMSCOMETHAYMAKER1)
				p.powers[pw_nocontrol] = 2//Automated attack! Let SMS do his thing.
					if G_GametypeHasSpectators()
						for z in players.iterate
							if z.mo and ( (s.target and z.mo == s.target)
							or ( (FixedHypot(FixedHypot(z.mo.x-s.x, z.mo.y-s.y), z.mo.z-s.z) <= 585*FRACUNIT) and not (z.mo.z > s.z+(375*FRACUNIT)) and not (z.mo.z < s.z-(375*FRACUNIT)) ) ) 
							and not (z.cmphwarning and z.cmphwarning > 1)
							and not z.cmphdodge
							and not (z.ctfteam and (z.ctfteam == p.ctfteam))
							and not (z.mo == s)
							z.smpawncher = p
							z.cmphwarning = 3
								if z.powers[pw_tailsfly]
								z.mo.state = S_PLAY_FALL
								z.powers[pw_tailsfly] = 0
								z.fly1 = 0
								z.secondjump = 0
								end				
							end
						end
					end
					if (s.target.type == MT_MINUS)
					and not s.target.fusrodah
					P_SetObjectMomZ(s.target, 1*FRACUNIT)
					s.target.flags = $|MF_SHOOTABLE|MF_ENEMY
					s.target.state = S_MINUS_AERIAL1
					end

					if not (s.target.player and ((s.target.player.cmphdodge) or (s.target.player.sms_dodging)) )
					s.angle = (R_PointToAngle2(s.x, s.y, s.target.x, s.target.y))
					s.momx = FixedMul(FixedDiv(s.target.x-s.x, 450*FRACUNIT), FixedDiv(132*FRACUNIT, 3*FRACUNIT/2))
					s.momy = FixedMul(FixedDiv(s.target.y-s.y, 450*FRACUNIT), FixedDiv(132*FRACUNIT, 3*FRACUNIT/2))
					s.momz = FixedMul(FixedDiv(s.target.z-s.z, 450*FRACUNIT), FixedDiv(132*FRACUNIT, 3*FRACUNIT/2))
						if (P_CheckMeleeRange(s) and not (s.target and s.target.player)) //Give players some time to react.
						or s.target.fusrodah
						or not s.target.health //Don't chase dead people.
						s.state = S_SMSCOMETHAYMAKER2 //Skip straight to the punching if you're already there.
						p.sms_comethaymaker = 1
						end
					end
				elseif (s.state == S_HMSCOMETHAYMAKER1)
				p.powers[pw_nocontrol] = 2
					if (s.target.type == MT_MINUS)
					and not s.target.fusrodah
					P_SetObjectMomZ(s.target, 1*FRACUNIT)
					s.target.flags = $|MF_SHOOTABLE|MF_ENEMY
					s.target.state = S_MINUS_AERIAL1
					end
					if ((FixedHypot(s.target.x-s.x, s.target.y-s.y)) < 940*FRACUNIT)
					s.angle = (R_PointToAngle2(s.x, s.y, s.target.x, s.target.y))
					s.momx = FixedMul(FixedDiv(s.target.x-s.x, 512*FRACUNIT), FixedDiv(132*FRACUNIT, 3*FRACUNIT/2))
					s.momy = FixedMul(FixedDiv(s.target.y-s.y, 512*FRACUNIT), FixedDiv(132*FRACUNIT, 3*FRACUNIT/2))
					s.momz = FixedMul(FixedDiv(s.target.z-s.z, 512*FRACUNIT), FixedDiv(132*FRACUNIT, 3*FRACUNIT/2))
						if P_FaceStabCheckMeleeRange(s)
						or s.target.fusrodah
						or not s.target.health //Don't chase dead people.
						s.state = S_HMSCOMETHAYMAKER2 //HMS needs more range or he'll kill his enemy before the punch.
						p.sms_comethaymaker = 1
						end
					end
				end
			end


//SMS' momentum is his greatest weapon to cause insane damage. 
//In this move, the Atomic Dive, SMS charges downward with explosive power.
//The more speed you pick up, the grander the devastation!
//Use this one wisely...

		if p.smsatomdivestun
		and not ((s.state == S_SMS_ATOMLAND1) or (s.state == S_SMS_ATOMLAND2) or (s.state == S_HMS_ATOMLAND) or (p.smsdivetimer and not p.hypermysticsonic) or s.sdodgeoh)
			p.smsatomdivestun = nil
		end
		if ((s.state == S_SMS_ATOMLAND1) or (s.state == S_SMS_ATOMLAND2) or (s.state == S_HMS_ATOMLAND))
		or (p.smsdivetimer and not p.hypermysticsonic)
		or s.sdodgeoh
			if s.sdodgeoh and (P_IsObjectOnGround(s) or s.dodgespinslide)
			and not (p.sms_dodging and not P_IsObjectOnGround(s))
			and not ((s.state == S_PLAY_SPRING) or (s.state == S_PLAY_PAIN) or (s.state == S_SMS_SIDEDODGE1))
			and not p.powers[pw_carry]
				if s.sliderollang == nil
					if (p.pflags & PF_ANALOGMODE)
					s.sliderollang = p.drawangle
					else
					s.sliderollang = s.angle
					end
				end
					if P_IsObjectOnGround(s)
					p.drawangle = s.sliderollang-FixedAngle(p.speed)
					s.sliderollang = $-FixedAngle(p.speed)
					else
					p.drawangle = s.sliderollang-FixedAngle(p.speed/2)
					s.sliderollang = $-FixedAngle(p.speed/2)
					end
				s.state = S_SMS_DODGELAND
					if not p.powers[pw_nocontrol] or p.powers[pw_nocontrol] == 1
					p.powers[pw_nocontrol] = 2
					end
				if (p.speed > 4*FRACUNIT) and P_IsObjectOnGround(s)
				S_StartSound(s, sfx_s3k7e)
				s.spinrundust = P_SpawnMobj(s.x+FixedMul(24*FRACUNIT, cos(p.drawangle+ANGLE_90)),s.y+FixedMul(24*FRACUNIT, sin(p.drawangle+ANGLE_90)), s.z, MT_SPINDUST)
				s.spinrundust.frame = P_RandomRange(0,2)
				s.spinrundust = P_SpawnMobj(s.x+FixedMul(24*FRACUNIT, cos(p.drawangle-ANGLE_90)),s.y+FixedMul(24*FRACUNIT, sin(p.drawangle-ANGLE_90)), s.z, MT_SPINDUST)
				s.spinrundust.frame = P_RandomRange(0,2)
				end
			end
			if not p.smsatomdivestun
			p.smsatomdivestun = s.angle	
			elseif not s.sdodgeoh
			s.angle = p.smsatomdivestun
			end
		end
		if p.smsdivedelay
		p.smsdivedelay = $-1
		end
		if p.atomdivetargetspin
		p.atomdivetargetspin = $-1
		end
		if s.hmspowerbombcam
		s.hmspowerbombcam = $-1
			if not P_IsObjectOnGround(s)
			s.hmspowerbombcam = 0
			elseif (p.cmd.buttons & BT_CUSTOM3)
				if p.hypermysticsonic
				p.camerascale =  FRACUNIT*24//Explosion cam.
				else
				p.camerascale =  FRACUNIT*3 
				end
				s.bhlcamtimer = 2
			end
		end
		if p.smsdivetimer or p.smsdivefloat or p.smsatomicdivefail
			if (s.state == S_SMS_ADVFALL1 or s.state == S_SMS_ADVFALL2)
				s.dcadsms = true
				s.state = S_PLAY_ROLL
				p.panim = PA_ROLL
				s.eflags = $ & ~MFE_JUSTHITFLOOR			
			elseif s.dcadsms
				s.dcadsms = false
				s.state = S_PLAY_ROLL
				p.panim = PA_ROLL
				s.eflags = $ & ~MFE_JUSTHITFLOOR
			else
				if not ((p.panim == PA_ROLL) or p.hypermysticsonic)
				and not ((s.state == S_SMS_ATOMDIVE) or (s.state == S_PLAY_ROLL) or (p.panim == PA_FALL))
				and not (s.eflags & MFE_JUSTHITFLOOR)
				p.smsdivetimer = 0
				p.smsdivefloat = 0
				p.smsdivedelay = 0
				p.smsatomicdivefail = 0
				s.smsdropdash = false
				end
				if (P_IsObjectOnGround(s) and not (s.eflags & MFE_JUSTHITFLOOR))
				or (s.state == S_PLAY_PAIN) or ((s.eflags & MFE_UNDERWATER and not p.hypermysticsonic) or s.eflags & MFE_GOOWATER) or not s.health
				or p.powers[pw_carry] or A_HMSCheckDeathPit(s)
				p.smsdivetimer = 0
				p.smsdivefloat = 0
				p.smsdivedelay = 0
				p.smsatomicdivefail = 0
				s.smsdropdash = false
				end
			end
		end	
		//SMS version startup of atomdive.
			if (  ( (p.cmd.buttons & (BT_TOSSFLAG|BT_WEAPONPREV)) and not (p.sms_tossflaghold and p.sms_tossflaghold > 1) and not (p.weaponprevhold and p.weaponprevhold > 1) )
			or ( (p.cmd.buttons == BT_USE and not (p.spinhold and p.spinhold > 1)) and ( ((p.cmd.forwardmove < 0) and not (p.pflags & PF_ANALOGMODE)) or (p.cmd.forwardmove == 0 and p.cmd.sidemove == 0 and (p.pflags & PF_ANALOGMODE)) ) )  )
			
			and ((p.pflags & PF_JUMPED) or (s.state == S_PLAY_SPRING) or p.hometrickanim or p.ringburstfly) //Mamamia
			and not p.hypermysticsonic //HMS has different plans
			and not (p.pflags & (PF_SLIDING|PF_THOKKED|PF_STASIS))
			and not p.powers[pw_carry]
			and not (p.sms_stompanim or p.sms_comethaymaker or p.gotflag or p.smsdivefloat or p.smsatomicdivefail)
			and not (s.state == S_SMS_ATOMDIVE)
			and not (s.eflags & MFE_UNDERWATER)
			and not p.smsblastboost
			and not p.sms_sontransform
					if (p.cmd.buttons == BT_USE) and not s.atomdiveusebuffer
					s.atomdiveusebuffer = 9
					else
						if (p.cmd.buttons == BT_USE) and s.atomdiveusebuffer
						s.useatommethod = true
							if (p.pflags & PF_DIRECTIONCHAR)
							p.drawangle = s.angle
							end
						end
					s.smslastspeedw = nil
					s.wthudtime = false
					s.novawave = P_SpawnMobj(s.x, s.y, s.z, MT_HMSNOVAWAVE)
		  		 	s.novawave.scale = s.scale/7
					s.novawave.tics = 2
					s.novawave.destscale = s.novawave.scalespeed+1
					s.novawave.color = s.color
					s.novawave = P_SpawnMobj(s.x, s.y, s.z+s.height, MT_HMSNOVAWAVE)
					s.novawave.scale = s.scale/11
					s.novawave.tics = 2
					s.novawave.destscale = s.novawave.scalespeed+1
					s.novawave.color = s.color
					
					p.smsdivefloat = 70
					S_StartSound(s, sfx_s3k64)
					S_StartSound(s, sfx_s3ka6)
					s.state = S_SMS_ATOMDIVE
					s.hmgodticket = true
					p.pflags = $|PF_THOKKED & ~PF_JUMPED & ~PF_SPINNING
					s.momx = 0
					s.momy = 0
					s.momz = 0
						if p.sms_ringburstfly
						p.sms_ringburst = 0
						p.sms_ringburstready = 0
						p.sms_ringburstfly = 0
							if (p.sms_boostlevel < 30)
							p.sms_boostlevel = 30
							end
						end
					
					end
			end

			//We need a special version of this for HMS!

			if (p.cmd.buttons & BT_WEAPONPREV)
			and p.hypermysticsonic //SMS has different plans
			and (p.pflags & PF_JUMPED)
			and p.speed == 0
			and (s.momz > -3*FRACUNIT and s.momz < 3*FRACUNIT)
			and not (p.hmswarpcooldown and p.hmswarpcooldown > 3)
			and not p.hmsblackhole and not P_IsObjectOnGround(s) //This can happen, apparently.
			and not (p.novafire > 37)
			and not (s.eflags & MFE_GOOWATER)
			and not (p.cmd.buttons & BT_WEAPONNEXT)
			and not (p.pflags & (PF_SPINNING|PF_SLIDING))
			and not p.powers[pw_carry]
				s.hmgodticket = true
				p.atomdiveaim = true
				p.camerascale = FRACUNIT*3/2
				s.bhlcamtimer = 2
			/*	if (p.cmd.buttons & BT_CUSTOM2) //I put in an atomdive homing function?
				and not (p.smsmeleebutton > 1)
					if (P_LookForEnemies(p, false, true)) and s.tracer //(A_SMSFindTarget(s, 7000*FRACUNIT, 25, true)) == true
					S_StartSound(s, sfx_s3k42)
					P_FlashPal(p, PAL_RECYCLE, 3)
					s.angle = R_PointToAngle2(s.x, s.y, s.tracer.x, s.tracer.y)
					end */
				if (p.cmd.buttons & (BT_USE|BT_ATTACK))
				and not (p.sms_comethaymaker or (p.cmd.buttons & BT_JUMP))
				p.smsdivefloat = 70
				s.state = S_PLAY_RUN
				s.smsdropdash = false
				p.spinhold = 2
				p.pflags = $ & ~PF_JUMPED
				p.smsdivetimer = 1
				p.smsdivefloat = 0
				P_SpawnGhostMobj(s)
				P_InstaThrust(s, s.angle, 52*FRACUNIT)
				P_SetObjectMomZ(s, -26*FRACUNIT, false)
				S_StartSound(s, sfx_beflap)
				end
			end 

			//Spawn a reticule that'll show you where you'll land. SMS always dives at a
			//45 degree angle, so this makes it easier.


			//Revert cam when not in atomdive state.

			if p.atomdiveaim
			and not (p.smsdivefloat or p.smsdivetimer)
			and not (p.hypermysticsonic and (p.cmd.buttons & BT_WEAPONPREV))
			p.atomdiveaim = false
			p.aiming = 0
			end		

			//What happens if you let go?

			if (s.state == S_SMS_ATOMDIVE)
				p.camerascale = FRACUNIT*3/2
				s.bhlcamtimer = 2
				if not ( (p.cmd.buttons & (BT_TOSSFLAG|BT_WEAPONPREV)) or ((p.cmd.buttons & BT_USE) and s.useatommethod))
				s.state = S_PLAY_FALL
				p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED
				p.smsdivefloat = 0
				end
			end

			//What happens if you fail to act in time?

			if ( (p.cmd.buttons & (BT_TOSSFLAG|BT_WEAPONPREV)) or (p.cmd.buttons & BT_USE) and s.useatommethod)
			and (s.state == S_SMS_ATOMDIVE)
			and not p.smsdivefloat
			p.smsatomicdivefail = 120
			s.state = S_PLAY_FALL
			p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED
			p.powers[pw_flashing] = 16
			S_StartSound(s, sfx_ngskid)
			end
			if p.smsatomicdivefail
			and (s.eflags & MFE_JUSTHITFLOOR)
			s.state = S_SMS_ATOMLAND1
			end

			//You can continue floating, but only for so long!
			//When ready, tap spin to divebomb!

			if (s.state == S_SMS_ATOMDIVE)
			and ( (p.cmd.buttons & (BT_TOSSFLAG|BT_WEAPONPREV)) or (p.cmd.buttons & BT_USE) and s.useatommethod)
			and p.smsdivefloat
			and not p.stompanim
				if not s.hmstorvictim
				s.momx = 0
				s.momy = 0
				end
				if (p.pflags & PF_DIRECTIONCHAR)
				s.forcesmsangletimer = 2
				s.forcesmsangle = s.angle
				end
				if p.smsdivefloat > 50
				P_SetObjectMomZ(s, -1*FRACUNIT/19)
				elseif (p.smsdivefloat > 22)
				P_SetObjectMomZ(s, -2*FRACUNIT/5)
				else
				P_SetObjectMomZ(s, -3*FRACUNIT/4)
				end
				if ((p.cmd.buttons & BT_USE) and not s.useatommethod) or ((p.cmd.buttons & BT_JUMP) and not (p.sms_jumphold and (p.sms_jumphold > 1))) or (p.cmd.buttons & (BT_ATTACK|BT_FIRENORMAL))
					s.state = S_PLAY_ROLL
					p.smsdivefloat = 0
					s.smsdropdash = false
					p.spinhold = 2
					p.smsdivetimer = 1
					P_SpawnGhostMobj(s)
					if not ( (G_PlatformGametype() and not s.battlemodsms) ) and not p.hypermysticsonic
						p.smsdivedelay = 8
						S_StartSound(s, sfx_s3k72)
						P_InstaThrust(s, s.angle, 0*FRACUNIT)
						P_SetObjectMomZ(s, 0, false)
						P_SpawnMobj(s.x, s.y, s.z, MT_BURSTLIGHT)
					else
						P_InstaThrust(s, s.angle, 50*FRACUNIT)
						s.momz = (-25*FRACUNIT)*(P_MobjFlip(s))
						S_StartSound(s, sfx_beflap)
					end
				end
			end

			//This is the diving phase itself!

			if p.smsdivetimer
			and not A_HMSCheckDeathPit(s) //Let's make sure NONE of this works....
				s.smsboostimmune = 1
				p.pflags = $|PF_JUMPDOWN
				if not s.smsdropdash //Ready up for a dropdash instead!
				and (p.cmd.buttons & BT_USE) and not (p.spinhold and p.spinhold > 1)
				s.smsdropdash = true
				S_StartSound(s, sfx_s3kabb)
				S_StartSound(s, sfx_cdfm23)
				s.novawave = P_SpawnMobj(s.x, s.y, s.z, MT_HMSNOVAWAVE)
		 		s.novawave.scale = s.scale/12
		 		s.novawave.tics = 3
		 		s.novawave.destscale = s.novawave.scalespeed+1
				
				elseif s.smsdropdash and not P_IsObjectOnGround(s)
				
				s.ringburstticket = true
					if (p.cmd.buttons & BT_JUMP) and not (p.sms_jumphold and p.sms_jumphold > 1)
					or (p.cmd.buttons & BT_CUSTOM2) and not (p.smsmeleebutton > 1)  //Nope, nvm, cancel the dropdash!
					s.smsdropdash = false
					S_StartSound(s, sfx_s222)
					S_StartSound(s, sfx_s251)
					s.novawave = P_SpawnMobj(s.x, s.y, s.z, MT_HMSNOVAWAVE)
		 			s.novawave.scale = s.scale/12
		 			s.novawave.tics = 3
					s.ringburstticket = false
					end
				end
				if (p.pflags & PF_DIRECTIONCHAR)
				p.drawangle = s.angle
				end
				if (p.smsdivetimer == 3) and (p.sms_boostlevel and p.sms_boostlevel >= 65)
				p.smsdivetimer = $+9
				end

				//Small delay in match? Okay!

				if p.smsdivedelay
					P_InstaThrust(s, s.angle, 0*FRACUNIT)
					P_SetObjectMomZ(s, 0*FRACUNIT, false)
					if (p.smsdivedelay == 1)
					p.smsdivedelay = 0
					p.smsdivetimer = 2
					P_InstaThrust(s, s.angle, 50*FRACUNIT)
					s.momz = (-25*FRACUNIT)*(P_MobjFlip(s))
					S_StartSound(s, sfx_beflap)
					end
				end
				if (p.smsdivetimer > 0 and p.smsdivetimer < 18)
				and (p.panim == PA_ROLL or p.hypermysticsonic)
				and not (s.eflags & MFE_JUSTHITFLOOR)
				and not P_IsObjectOnGround(s)
				and not p.smsdivedelay
				P_InstaThrust(s, s.angle, 50*FRACUNIT)
				s.momz = (-25*FRACUNIT)*(P_MobjFlip(s))
					if (p.powers[pw_sneakers] or p.hypermysticsonic) //Got runshoes? STRAIGHT to the 2nd level!
					and not (G_GametypeHasSpectators() and not p.hypermysticsonic)
					p.smsdivetimer = 24
					end
				end

			//Reflect off walls like a ping pong ball!

			/*	local wallbounce = R_PointInSubsector(s.x+FixedMul(32*FRACUNIT, cos(s.angle)), s.y+FixedMul(32*FRACUNIT, sin(s.angle))).sector
				if (wallbounce.floorheight > s.z)
				or ((wallbounce.ceilingheight <= s.z+s.height) and not (s.eflags & MFE_VERTICALFLIP)) */
				if not (leveltime % 2 == 0) and ( ((p.speed < 35*FRACUNIT) and (p.smsdivetimer < 19)) or ((p.speed < 64*FRACUNIT) and (p.smsdivetimer > 18)) )
				and ( ((p.smsdivetimer > 1) and not p.hypermysticsonic and not p.powers[pw_sneakers]) or ((p.smsdivetimer > 25 and (p.hypermysticsonic or p.powers[pw_sneakers]))) )
				and not s.smsatombounced and not P_IsObjectOnGround(s) and not (p.pflags & PF_JUMPED) and not p.smsdivedelay
				and not ((p.smsdivetimer < 4) and G_GametypeHasSpectators())
				and not (s.state == S_PLAY_SPRING)
					if not p.hypermysticsonic
						p.smsatomdivestun = nil
						if (p.pflags & (PF_ANALOGMODE|PF_DIRECTIONCHAR))
						p.drawangle = $ + ANGLE_180
						end
						s.angle = $ + ANGLE_180
						S_StartSound(s, sfx_doord2)
					else
						p.smsatomdivestun = nil
						if (p.pflags & (PF_ANALOGMODE|PF_DIRECTIONCHAR))
						p.drawangle = $ + ANGLE_180
						end
						s.angle = $ + ANGLE_180
						P_SpawnMobj(s.x+70*FRACUNIT, s.y+70*FRACUNIT, s.z, MT_SMSDIVEBOMB)
						P_SpawnMobj(s.x-70*FRACUNIT, s.y-70*FRACUNIT, s.z, MT_SMSDIVEBOMB)
						P_SpawnMobj(s.x, s.y, s.z, MT_SMSDIVEBOMB)
						P_NukeEnemies(s, s, 400*FRACUNIT)
						S_StartSound(s, sfx_brakrx)
						S_StartSound(s, sfx_s3kcfs)
					end
					s.smsatombounced = 2
				elseif s.smsatombounced //Give extra frames to buffer before allowing another bounce
				s.smsatombounced = $-1
				end
			end

		//Drop Dash Landings
		   if s.smsdropdash and p.smsdivetimer
		   and (s.eflags & MFE_JUSTHITFLOOR)
		   and P_IsObjectOnGround(s)
		   and not ((G_GametypeHasSpectators() or s.battlemodsms) and not p.rings)
		   	if (G_GametypeHasSpectators() or s.battlemodsms)
			P_GivePlayerRings(p, -1) --ring drain
			end
		   p.speed = 250*FRACUNIT
		   p.cmd.forwardmove = 50
			if p.hypermysticsonic or (p.powers[pw_sneakers] and G_PlatformGametype() and not s.battlemodsms) //Super DropDash
				if (p.cmd.buttons & BT_WEAPONPREV)
		  		s.nohmswarpforawhile = true //People be weird, yo.
				end
			P_InstaThrust(s, s.angle, 250*FRACUNIT)
			S_StartSound(s, sfx_kc3c)
			S_StartSound(s, sfx_s3k5f)
			S_StartSound(s, sfx_bkpoof)
			P_FlashPal(p, PAL_NUKE, 7)
			P_NukeEnemies(s, s, 500*FRACUNIT)
			s.smschargedbd = 11
			A_SMSquake(s, 104*FRACUNIT, 3, 1500)
			p.sms_boostlevel = 70
		//	s.hypermysticdash = 105 Hmm, maybe not.
			A_SMSSTOMPQUAKE(s, 125, 10, 25*FRACUNIT, 0, ANG20, 0, 20)
			A_SMSSTOMPQUAKE(s, 165, 14, 35*FRACUNIT, FRACUNIT*2, ANG30, 0, 20, SKINCOLOR_SUPERSILVER4)
			elseif (p.smsdivetimer >= 38) or (p.sms_boostlevel and p.sms_boostlevel >= 45) //Instant max-dropdash if boostleveling
			P_InstaThrust(s, s.angle, 175*FRACUNIT)
			S_StartSound(s, sfx_kc3c)
			S_StartSound(s, sfx_s3k5f)
			P_FlashPal(p, PAL_MIXUP, 3)
			P_NukeEnemies(s, s, 70*FRACUNIT)
			s.smschargedbd = 11
			A_SMSquake(s, 74*FRACUNIT, 11, 1400)
			p.sms_boostlevel = 70 //Automatically go into boostmode from this one.	
			elseif (p.smsdivetimer > 16)
			P_InstaThrust(s, s.angle, 120*FRACUNIT)
			S_StartSound(s, sfx_kc3c)
			p.sms_boostlevel = $+35
			A_SMSquake(s, 54*FRACUNIT, 7, 1000)
		  	elseif (p.smsdivetimer < 17)	
			P_InstaThrust(s, s.angle, 79*FRACUNIT)
			p.sms_boostlevel = $+24
			A_SMSquake(s, 24*FRACUNIT, 4, 500)
			end
			s.forcewarp1 = 0
			s.forcewarp2 = 0
				p.smsdivetimer = 0
				p.smsdivefloat = 0
				p.smsdivedelay = 0
				p.smsatomicdivefail = 0
				s.smsdropdash = false
				
			p.sms_autoboosthold = true
			s.smsdropdash = false
			p.pflags = $|PF_SPINNING & ~PF_STARTDASH & ~PF_THOKKED & ~PF_JUMPED
			s.state = S_PLAY_ROLL
			S_StartSound(s, sfx_cdfm35)	
			P_SpawnGhostMobj(s)
			s.smsgrboost = P_SpawnMobj(s.x, s.y, s.z, MT_SMSGROUNDBOOST)
			s.smsgrboost.tracer = s
			p.smsfullcharge = 0
			s.hjg1 = P_SpawnMobj(s.x, s.y, s.z-20*FRACUNIT, MT_HMSWAVEAURA)
			s.hjg1.dustwave = 1
			s.hjg1.sprite = SPR_SMMK
			s.hjg1.frame = 3
			s.hjg1.target = s
			s.hjg1.fuse = 15
			s.hjg1.scale = s.scale
			s.hjg1.destscale = $*2
			
			for smsbdzone = 0,05
			P_SpawnParaloop(s.x, s.y, s.z+FixedMul(15*FRACUNIT, s.scale), FixedMul(84*FRACUNIT, s.scale), 8, MT_NIGHTSPARKLE, smsbdzone*ANGLE_22h, S_SMSTSPARK1, true)
			end
		   else
		   
		//Low level landing.	
		
			if (p.smsdivetimer and ((p.smsdivetimer < 18) or ((G_GametypeHasSpectators() or s.battlemodsms) and not p.rings)) )
			and ((s.eflags & MFE_JUSTHITFLOOR) or P_IsObjectOnGround(s))
			and not (s.eflags & MFE_UNDERWATER and not p.hypermysticsonic)
					if not p.hypermysticsonic
					s.state = S_SMS_ATOMLAND1
					else
					s.state = S_HMS_ATOMLAND
					AtomBust(s)
					end
				P_InstaThrust(s, s.angle, 2*FRACUNIT)
				s.hmselcharge = 3
				p.smsdivetimer = 0
				S_StartSound(s, sfx_s3k77)
				A_SMSSTOMPSMOKE(s, 3, MT_EXPLODE)
				A_SMSSTOMPQUAKE(s, 45, 14, FRACUNIT, 0, 0, 0, 0)
				A_SMSSTOMPQUAKE(s, 65, 18, 2*FRACUNIT, 0, ANG20, 0, 0, SKINCOLOR_SUPERSILVER4)
				end
				if p.smsdivetimer
				and (p.smsdivetimer == 16)
				and (p.panim == PA_ROLL or p.hypermysticsonic)
				and not P_IsObjectOnGround(s)
					P_SpawnMobj(s.x, s.y, s.z, MT_SMSGROUNDBOOST)
					P_RadiusAttack(s, s, 100*FRACUNIT)
					S_StartSound(s, sfx_smach)
					S_StartSound(s, sfx_smach)
				end
			if p.smsdivetimer
			and (p.smsdivetimer >= 18 and p.smsdivetimer < 39)
			
				if (p.panim == PA_ROLL or p.hypermysticsonic)
				and not P_IsObjectOnGround(s)
				and not (s.eflags & MFE_JUSTHITFLOOR)
					P_RadiusAttack(s, s, 120*FRACUNIT)
					P_SpawnGhostMobj(s)
					if (leveltime % 2 == 0)
					P_InstaThrust(s, s.angle, 90*FRACUNIT)
					end
					s.momz = (-45*FRACUNIT)*(P_MobjFlip(s))
				end

				//Mid level landing!

				if (s.eflags & MFE_JUSTHITFLOOR)
				and P_IsObjectOnGround(s)
				and not (s.eflags & MFE_UNDERWATER and not p.hypermysticsonic)
				AtomBust(s)
					if not p.hypermysticsonic
					s.state = S_SMS_ATOMLAND1
					else
					s.state = S_HMS_ATOMLAND
					end
					if (G_GametypeHasSpectators() or s.battlemodsms)				
					P_GivePlayerRings(p, -1) --ring drain
					end
				s.hmselcharge = 18
				P_InstaThrust(s, s.angle, 2*FRACUNIT)
				s.momz = 0
				p.smsdivetimer = 0
	    			p.spul = P_SpawnMobj(s.x, s.y, s.z, MT_ATOMDIVEPOP)
	    			p.spul.tracer = s
				S_StartSound(s, sfx_brakrx)
				P_FlashPal(p, 4, 2)
				S_StartSound(s, sfx_s3kcfs)
				
				A_SMSSTOMPQUAKE(s, 45, 7, 5*FRACUNIT, 0, 0, 0, 13, SKINCOLOR_RED)
				A_SMSSTOMPQUAKE(s, 85, 9, 16*FRACUNIT, 0, ANG10, 0, 20, SKINCOLOR_SUPERRED5)
				A_SMSSTOMPQUAKE(s, 105, 10, 30*FRACUNIT, 0, ANG20, 0, 22, SKINCOLOR_SUPERRED1)
				
				A_SMSSTOMPQUAKE(s, 55, 7, 5*FRACUNIT, 0, ANG30, 0, 13, SKINCOLOR_FLAME)
				A_SMSSTOMPQUAKE(s, 75, 9, 16*FRACUNIT, 0, (ANG30*3), 0, 20, SKINCOLOR_SUPERRED1)
				A_SMSSTOMPQUAKE(s, 95, 10, 30*FRACUNIT, 0, (ANG20*2), 0, 22, SKINCOLOR_SUPERRED5)
				
				
				P_SpawnMobj(s.x+70*FRACUNIT, s.y+70*FRACUNIT, s.z, MT_SMSDIVEBOMB)
				P_SpawnMobj(s.x-70*FRACUNIT, s.y-70*FRACUNIT, s.z, MT_SMSDIVEBOMB)
				P_SpawnMobj(s.x-70*FRACUNIT, s.y+70*FRACUNIT, s.z, MT_SMSDIVEBOMB)
				P_SpawnMobj(s.x+70*FRACUNIT, s.y-70*FRACUNIT, s.z, MT_SMSDIVEBOMB)

				P_SpawnMobj(s.x+250*FRACUNIT, s.y, s.z, MT_SMSDIVEBOMB)
				P_SpawnMobj(s.x, s.y+250*FRACUNIT, s.z, MT_SMSDIVEBOMB)
				P_SpawnMobj(s.x-250*FRACUNIT, s.y, s.z, MT_SMSDIVEBOMB)
				P_SpawnMobj(s.x, s.y-250*FRACUNIT, s.z, MT_SMSDIVEBOMB)

				p.divebombpain = P_SpawnMobj(s.x+45*FRACUNIT, s.y, s.z, MT_SMSDIVEBOMB)
				p.divebombpain.target = s
				P_SpawnMobj(s.x, s.y+45*FRACUNIT, s.z, MT_SMSDIVEBOMB)
				P_SpawnMobj(s.x-45*FRACUNIT, s.y, s.z, MT_SMSDIVEBOMB)
				P_SpawnMobj(s.x, s.y-45*FRACUNIT, s.z, MT_SMSDIVEBOMB)

				A_SMSSTOMPSMOKE(s, 4, MT_BOSSEXPLODE, 80*FRACUNIT)
				A_SMSSTOMPSMOKE(s, 5, MT_EXPLODE, 40*FRACUNIT)
				A_SMSSTOMPSMOKE(s, 6, MT_BOSSEXPLODE)

				A_SMSkillstuff(s, 777*FRACUNIT, 500*FRACUNIT, s, true)

				if p.divebombpain
				P_NukeEnemies(p.divebombpain, s, 777*FRACUNIT)
				end
				end
			end
			if p.smsdivetimer
			and (p.smsdivetimer == 36)
			and (p.panim == PA_ROLL or p.hypermysticsonic)
			and not P_IsObjectOnGround(s)
				p.smsradialboosteffect = P_SpawnMobj(s.x, s.y, s.z, MT_RADIALBOOST)
				p.smsradialboosteffect.target = s
				P_NukeEnemies(s, s, 150*FRACUNIT)
				S_StartSound(s, sfx_s3k83)
			end
			if p.smsdivetimer
			and (p.smsdivetimer >= 37)
			and not (p.smsdivetimer >= 57 and p.hypermysticsonic)
			    s.boostpass = 1
				if (p.panim == PA_ROLL or p.hypermysticsonic)
				and not P_IsObjectOnGround(s)
				and not (s.eflags & MFE_JUSTHITFLOOR)
				P_RadiusAttack(s, s, 200*FRACUNIT)
				P_SpawnGhostMobj(s)
				p.smsgrboost = P_SpawnMobj(s.x, s.y, s.z, MT_SMSGROUNDBOOST)
				p.smsgrboost.tracer = s 
					if (leveltime % 2 == 0)
					P_InstaThrust(s, s.angle, 150*FRACUNIT)
					end
					s.momz = (-75*FRACUNIT)*(P_MobjFlip(s))
				end

				//High level landing!

				if (s.eflags & MFE_JUSTHITFLOOR)
				and P_IsObjectOnGround(s)
				and not (s.eflags & MFE_UNDERWATER and not p.hypermysticsonic)
				AtomBust(s)
					if not p.hypermysticsonic
					s.state = S_SMS_ATOMLAND1
					else
					s.state = S_HMS_ATOMLAND
					end
				P_FlashPal(p, 4, 4)
				s.hmselcharge = 40
				if (G_GametypeHasSpectators() or s.battlemodsms)				
					P_GivePlayerRings(p, -2) --ring drain
				end
				if not p.hypermysticsonic
				s.hmspowerbombcam = 45
				end
				s.momz = 0
				p.smsdivetimer = 0
						if not p.smsgraphix
						s.hjg1 = P_SpawnMobj(s.x, s.y, s.z-20*FRACUNIT, MT_HMSWAVEAURA)
						s.hjg1.dustwave = 1
						s.hjg1.dustwavet = 8
						s.hjg1.sprite = SPR_SMMK
						s.hjg1.frame = 3
						s.hjg1.target = s
						s.hjg1.fuse = 32
						s.hjg1.scale = s.scale*2
						s.hjg1.destscale = $*4
						end
				P_SpawnMobj(s.x, s.y, s.z, MT_BURSTWAVE)
				P_SpawnPlayerMissile(s, MT_SMSPOWERBOMB, MF2_SUPERFIRE)
				A_SMSSTOMPQUAKE(s, 45, 5, 5*FRACUNIT, 0, 0, 0, 7, SKINCOLOR_SUPERRED4)
				A_SMSSTOMPQUAKE(s, 85, 6, 16*FRACUNIT, 0, ANG10, 0, 22)
				A_SMSSTOMPQUAKE(s, 125, 7, 30*FRACUNIT, 0, ANG20, 0, 14)
				A_SMSSTOMPQUAKE(s, 165, 12, 40*FRACUNIT, FRACUNIT*2, ANG30, 0, 19, SKINCOLOR_SUPERSILVER4)
				
				A_SMSSTOMPQUAKE(s, 55, 5, 7*FRACUNIT, 0, ANG30, 0, 7, SKINCOLOR_RED)
				A_SMSSTOMPQUAKE(s, 75, 6, 12*FRACUNIT, 0, (ANG10*5), 0, 22)
				A_SMSSTOMPQUAKE(s, 115, 7, 25*FRACUNIT, 0, 0, 0, 14)
				A_SMSSTOMPQUAKE(s, 145, 12, 35*FRACUNIT, FRACUNIT*2, (ANG30*2), 0, 19, SKINCOLOR_SILVER)
	    			p.spul = P_SpawnMobj(s.x, s.y, s.z, MT_ATOMDIVEPOP)
	    			p.spul.tracer = s
				S_StartSound(s, sfx_spld)
				S_StartSound(s, sfx_pwbmb)
					if G_GametypeHasSpectators()
					P_InstaThrust(s, s.angle, -8*FRACUNIT)
					else
					P_InstaThrust(s, s.angle, 2*FRACUNIT)
					end
				end
			end

			if p.smsdivetimer //waa2
			and (p.smsdivetimer >= 57)
			and p.hypermysticsonic
				s.boostpass = 1
				if not P_IsObjectOnGround(s)
				and not (s.eflags & MFE_JUSTHITFLOOR)
				P_SpawnGhostMobj(s)
				P_SpawnMobj(s.x, s.y, s.z, MT_BURSTWAVE)
				p.smsgrboost = P_SpawnMobj(s.x+150*FRACUNIT, s.y+150*FRACUNIT, s.z, MT_SMSGROUNDBOOST) p.smsgrboost.tracer = s
				p.smsgrboost = P_SpawnMobj(s.x-150*FRACUNIT, s.y-150*FRACUNIT, s.z, MT_SMSGROUNDBOOST) p.smsgrboost.tracer = s
				p.smsgrboost = P_SpawnMobj(s.x, s.y, s.z+150*FRACUNIT, MT_SMSGROUNDBOOST) p.smsgrboost.color = SKINCOLOR_FLAME 
				p.smsgrboost = P_SpawnMobj(s.x, s.y, s.z-150*FRACUNIT, MT_SMSGROUNDBOOST) p.smsgrboost.color = SKINCOLOR_GOLD
				if (leveltime % 2 == 0)
				P_InstaThrust(s, s.angle, 240*FRACUNIT)
				end
				P_SetObjectMomZ(s, -120*FRACUNIT, false)
				end

				if (p.smsdivetimer == 57) and (p.hypermysticsonic)
					S_StartSound(s, sfx_s3k83)
					S_StartSound(s, sfx_beeyow) //For that extra intensity.
				end

				//Ultimate landing. HMS only.

				if (s.eflags & MFE_JUSTHITFLOOR)
				and P_IsObjectOnGround(s)
				AtomBust(s)
				s.hmselcharge = 70
				s.hmspowerbombcam = 105
				s.state = S_HMS_ATOMLAND
				P_FlashPal(p, 1, 4)
				P_FlashPal(p, 4, 10)
	    			p.spul = P_SpawnMobj(s.x, s.y, s.z, MT_ATOMDIVEPOP)
	    			p.spul.scale = 2*FRACUNIT
	    			p.spul.tracer = s
				s.momz = 0
				p.smsdivetimer = 0
				s.hmsmobjboom = P_SpawnMobj(s.x, s.y, s.z, MT_TNTDUST)
				s.hmsmobjboom.fuse = 70
				s.hmsmobjboom.destscale = $*50				
				P_SpawnPlayerMissile(s, MT_HMSPOWERBOMB, MF2_SUPERFIRE)
				P_NukeEnemies(s, s, 1*FRACUNIT)
				S_StartSound(s, sfx_spld)
				S_StartSound(s, sfx_nuexp)
				P_InstaThrust(s, s.angle, 2*FRACUNIT)
				
						A_SMSSTOMPQUAKE(s, 85, 1, 16*FRACUNIT, 0, ANG10, 0, 22, SKINCOLOR_RED)
						A_SMSSTOMPQUAKE(s, 95, 4, 70*FRACUNIT, 0, ANG30, 0, 19, SKINCOLOR_SUPERSILVER4)
						A_SMSSTOMPQUAKE(s, 75, 1, 32*FRACUNIT, 0, (ANG10*5), 0, 22)
						A_SMSSTOMPQUAKE(s, 105, 3, 78*FRACUNIT, 0, (ANG30*2), 0, 19, SKINCOLOR_SILVER)
						
					if G_GametypeHasSpectators()
					P_Telekinesis(p, 100*FRACUNIT, 2800*FRACUNIT)
					end
				end
			end
		   end
			//Remove autoboosthold
			if p.sms_autoboosthold 
				if (p.cmd.buttons & BT_CUSTOM1) or p.sms_dodging or p.footsweepanim
				or (p.hypermysticsonic and ((s.hms_jumprisen or s.hmsroflstomped) or ((p.speed < 15*FRACUNIT) and not p.cmd.sidemove and not p.cmd.forwardmove)))
				or p.powers[pw_carry]   //Switch!
				p.sms_autoboosthold = false
				elseif P_IsObjectOnGround(s) and not p.sms_ringburst
					if not p.cmd.sidemove and not p.cmd.forwardmove
					or p.skidtime
					p.sms_autoboosthold = false
					end
				end
			end

	end
//Fix a little bug where you flood the console by switching during haymaker.
	if ((s.state == S_SMSCOMETHAYMAKER2) or (s.state == S_HMSCOMETHAYMAKER2))
		if (s.skin != "sms")
			s.state = S_PLAY_RUN
			p.sms_comethaymaker = 0
			p.sms_boostlevel = 0
		elseif ((s.tics == 11) or p.sms_comethaymaker)
			p.sms_flamedelay = 11
			P_SpawnMobj(s.x, s.y, s.z, MT_BURSTWAVE)
			A_SMSquake(s, 30*FRACUNIT, 11, 4400)
			P_FlashPal(p, 1, 2)
			p.sms_boostlevel = 0
			if p.hypermysticsonic or not (G_GametypeHasSpectators() or s.battlemodsms) //No more AoE in matches. Players found it hard to predict
			P_SpawnPlayerMissile(s, MT_CMPHRADIUS) //This action is used is to copy the player's angle.
			end
			p.sms_comethaymaker = 0
		end
	end
end, MT_PLAYER)

//SMS doesn't get hurt while dodging/ringbursting, unless it's a lava, acid, or electricity sector.
//Like a true cliche Matrix dodge, though, he can stylefully ignore lasers!
//This also merges every other ShouldDamage hook.

addHook("ShouldDamage", function(s, v, vs)
if not s.player
return end
local p = s.player

	//Don't give rings in these cases.
		if v and v.valid	
			if G_GametypeHasTeams() and not (v.type == MT_SMSFIREBLAST)
				if vs and vs.player and s and s.player and (vs.player.ctfteam == p.ctfteam)
					if ((v.type == MT_HMSFIREBLAST) or (v.type == MT_HMS_NAPALM_FLAMES))
					return false end
					if s and (s.skin == "sms") and (v.flags & MF_MISSILE) and not (v.type == MT_REDRING)
					return false //Only allow red-rings so people can't feed you with autorings for an easy HMS transformation
					end
					if (vs.skin == "sms") and not (v.type == MT_SMSFIREBLAST) //Fireblast ring-sharing only!
					return false
					end
				end
			end	
			if s.player.smspickup and s.player.smspickup.valid 
			and (v == s.player.smspickup or vs == s.player.smspickup)
				return false
			elseif v and s.ibethrownbysmshelp
				return false
		
			//Kids, don't kill friends and family with black holes.

			elseif (v.type == MT_HMSBLACKHOLE)
				if (gametype == GT_COOP)
				or (v.target and v.target.player and (v.target.player.ctfteam == s.player.ctfteam))
				return false
				end

		//Even though the walljump technically becomes a missile, it should NEVER hurt players.

			elseif (v.type == MT_SMSWALLJUMP)
				return false
			elseif (v.fusrodah) //Ignore hits from enemies currently flying towards their death
				if (v.flags & MF_PAIN|MF_ENEMY|MF_BOSS)
				return false
				end
			end
		end
		if (s and s.skin == "sms")
			if s.player.hypermysticsonic //Just to be sure, HMS is invincible.
				return false
			end
			if s.battlemodsms and (s.player.sms_comethaymaker or (s.state == S_SMSCOMETHAYMAKER2) or (s.state == S_SMSCOMETHAYMAKER1)) //Don't get interrupted by a simple jump
			return false
			end
			if s.player.footsweepanim
			and v and v.valid and (v.flags & MF_ENEMY or v.flags & MF_BOSS or (v.type == MT_TNTBARREL and not (v.flags2 & MF2_EXPLOSION)))
				return false
			end
			if ( s.player.sms_dodging and (s.player.sms_dodging > 2) or (s.player.sms_ringburstfly|s.player.sms_comethaymaker|s.player.mslightspeedattack) 
			or (s.state == S_SMSCOMETHAYMAKER2 or s.state == S_SMSCOMETHAYMAKER1) or (s.state == S_SMS_LIGHTDASH))
				if not ((P_PlayerTouchingSectorSpecial(s.player, 1, 4) or P_PlayerTouchingSectorSpecial(s.player, 1, 3) or P_PlayerTouchingSectorSpecial(s.player, 1, 2))
				and not (s.player.powers[pw_shield] == SH_ELEMENTAL))
				return false
				end
			end //Negate damage once at the cost of your boost!
			if v and v.valid and (v.flags & (MF_ENEMY|MF_BOSS)) and ((p.sms_boostlevel > 64) or s.airboostimmune) and not p.hypermysticsonic and not (v.type == MT_DETON)
				if p.powers[pw_flashing] or (p.speed < 44*FRACUNIT)
				return
				end
			s.momx = $/9*-1
			s.momy = $/9*-1
			s.smsgrboost = P_SpawnMobj(v.x, v.y, v.z, MT_SMSGROUNDBOOST)
			s.smsgrboost.tracer = s
			P_SetObjectMomZ(s, 8*FRACUNIT, true)
			A_SMSquake(s, 45*FRACUNIT, 4, 1500)
			s.state = S_PLAY_FALL
			s.player.sms_boostlevel = 0
			s.player.smsatomicdivefail = 80
			S_StartSound(s, sfx_kc31)
			P_NukeEnemies(s, s, 0)
				for d = 0,15
					P_SpawnParaloop(s.x, s.y, s.z+FixedMul(20*FRACUNIT, s.scale), 10*FRACUNIT, 16, MT_NIGHTSPARKLE, d*ANGLE_22h, S_SMSTSPARK1, false)
				end
				if v and v.health
					if (v.type == MT_GSNAPPER) or (v.type == MT_CRUSHCLAW) //Trade blows with these dudes.
					P_DamageMobj(v) 
					return
					else
					P_DamageMobj(v)			
					end
				end
				if not (p.powers[pw_flashing] == -1)
				p.powers[pw_flashing] = $+16
				end
				return false
			end
			if v and v.valid and ((v.flags & MF_PAIN) or (v.type == MT_DETON)) and ((p.sms_boostlevel > 64) or s.airboostimmune) and not p.hypermysticsonic
				if p.powers[pw_flashing] or (vs and vs.player) //None of this from player-owned objects.
				or (p.speed < 44*FRACUNIT)
				or ((p.rings < 1) and not p.powers[pw_shield])
				return
				end
			s.momx = $/2
			s.momy = $/2
			P_SetObjectMomZ(s, 6*FRACUNIT)
			A_SMSquake(s, 65*FRACUNIT, 4, 1500)
			if not s.player.powers[pw_shield]
			P_PlayRinglossSound(s)
			end
			s.state = S_PLAY_PAIN
			s.airboostroll = 27
			S_StartSound(s, sfx_kc31)
			P_NukeEnemies(s, s, 0)
				for d = 0,15
					P_SpawnParaloop(s.x, s.y, s.z+FixedMul(20*FRACUNIT, s.scale), 10*FRACUNIT, 16, MT_NIGHTSPARKLE, d*ANGLE_22h, S_SMSTSPARK1, false)
				end
				if v and (v.type == MT_DETON)
					P_DamageMobj(v)			
				end
				if s.player.powers[pw_shield]
					P_RemoveShield(p)
					S_StartSound(s, sfx_shldls)
				else
					if p.sms_transformstate and p.sms_transformstate == 1
						p.sms_transformstate = 2
						P_PlayerRingBurst(p, -1) 
						P_GivePlayerRings(p, p.rings/-2)
					else
						P_PlayerRingBurst(p, -1)
						P_GivePlayerRings(p, p.rings*-1)
					end		
				end
			p.powers[pw_flashing] = 105
			return false
			end
		end
		if s.player.lightspeedchain and v //You're invincible to conventional attacks during a lightspeed attack!
			return false
		end
		
end, MT_PLAYER)

//Does our punch radius collide with an enemy? Send them flying!

local function CMPHrad(s, v)
	if s.bkhl or (v and v.fusrodah or (v.info.mass == 2006))
	return false end
	if v and s and ((v.z > s.z+s.height) or (v.z+v.height < s.z-s.height))
	return false end
		if v and v.followdist and v.target and v.target.player and v.target.player.cmphdodge //If Tails dodges the haymaker, his sentries do too!
		return false
		elseif (v.type == MT_SUSPICIOUSFACESTABBERSTATUE) and v.health and not (v.state == S_SUSPICIOUSFACESTABBERSTATUE_BURST2) 
			v.state = S_SUSPICIOUSFACESTABBERSTATUE_BURST2
			v.tics = 1
			v.fusrodah = 2
			return false
		elseif (v.type == MT_EGGROBO1)
				v.state = S_EGGROBO1_PISSED
				v.flags = MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT
				v.vxh = P_SpawnMobj(v.x, v.y, v.z, MT_CYBRAKDEMON_VILE_EXPLOSION)
				v.vxh.momx = v.momx
				v.vxh.momy = v.momy
				v.vxh.momz = v.momz
				S_StartSound(s.target, sfx_bsnipe)
				S_StartSound(v, sfx_brakrx)
				P_Thrust(v, R_PointToAngle2(s.x, s.y, v.x, v.y), 90*FRACUNIT)
				v.momz = 40*FRACUNIT
				v.fuse = 105
				v.fusrodah = 2
				P_SpawnGhostMobj(v)
				return false
		elseif (v.type == MT_EGGSHIELD) and v.health
			if v.target
			v.target.flags = $|MF_SHOOTABLE|MF_ENEMY
			P_SetObjectMomZ(v.target, 12*FRACUNIT)
			P_InstaThrust(v.target, s.angle, 125*FRACUNIT)
			P_SpawnMobj(v.target.x, v.target.y, v.target.z, MT_BURSTWAVE)
			v.target.ghs = P_SpawnMobj(v.target.x, v.target.y, v.target.z, MT_BURSTWAVE)
			v.target.ghs.momx = v.target.momx/2
			v.target.ghs.momy = v.target.momy/2
			v.target.ghs.momz = v.target.momz/2
			v.target.fusrodah = 1
			v.target.trackerspawn = P_SpawnMobj(v.target.x, v.target.y, v.target.z, MT_CMPHTRACKER)
			v.target.trackerspawn.angle = s.angle
			v.target.trackerspawn.tracer = s.target
				if s.target
				S_StartSound(s.target, sfx_nerf)
				end
				if v.target.trackerspawn
				v.target.trackerspawn.target = v.target
					if (s.target and (s.target.player.hypermysticsonic))
					v.target.fusrodah = 2
					end
				end
			end
			P_KillMobj(v, s, s.target)
			return false
		elseif (v.type == MT_EGGGUARD) and v.tracer and v.tracer.health and (v.tracer.type == MT_EGGSHIELD)
			v.tracer.state = S_NULL
			v.flags = $|MF_SHOOTABLE|MF_ENEMY
		elseif (v.type == MT_CYBRAKDEMON_ELECTRIC_BARRIER)
			if v.target.fusrodah
			return false
			end
			if s.z == s.floorz
			s.z = s.z+s.target.height/2
			end
			P_SetObjectMomZ(v.target, 12*FRACUNIT)
			P_InstaThrust(v.target, s.angle, 125*FRACUNIT)
			P_SpawnMobj(v.target.x, v.target.y, v.target.z, MT_BURSTWAVE)
			v.target.fusrodah = 1
			v.target.trackerspawn = P_SpawnMobj(v.x, v.y, v.z, MT_CMPHTRACKER)
			v.target.trackerspawn.angle = s.angle
			v.target.trackerspawn.tracer = s.target
			v.target.trackerspawn.target = v.target
			P_KillMobj(v)
			return false
		end
		if ((v.flags & (MF_ENEMY|MF_BOSS)) or (v.type == MT_METALSONIC_BATTLE) or (v.type == MT_EGGGUARD) or (v.type == MT_KOOPA) or (v.type == MT_TURRET) or ((v.type == MT_CMPHTRACKER) and v.dummyhb))
		and not (v.info.mass == 2006) and not v.fusrodah and v.health
			if (v.type == MT_TURRET) //Special treatment for special snowflakes
			v.flags = $|MF_ENEMY|MF_SHOOTABLE & ~MF_NOCLIPTHING & ~MF_NOCLIP & ~MF_NOGRAVITY
		
			elseif (v.type == MT_PTERABYTE) or (v.type == MT_PYREFLY) or (v.type == MT_DRAGONBOMBER)
			v.flags = $|MF_SCENERY|MF_BOUNCE|MF_GRENADEBOUNCE
			v.fixedbounceded = true
			
			elseif (v.type == MT_METALSONIC_BATTLE)
 			v.flags = $|MF_BOSS|MF_SHOOTABLE & ~MF_NOCLIPTHING
			
			elseif (v.type == MT_EGGGUARD) and v.tracer and v.tracer.health and (v.tracer.type == MT_EGGSHIELD)
			v.tracer.state = S_NULL
			v.flags = $|MF_SHOOTABLE|MF_ENEMY
			
			elseif (v.type == MT_CMPHTRACKER) 
				if v.target and ((v.target.type == MT_METALSONIC_BATTLE) or (v.target.type == MT_TURRET))
				v.target.flags = $|MF_BOSS|MF_SHOOTABLE & ~MF_NOCLIPTHING
				end		
			end		
			
		/*	if s.target.player.hypermysticsonic
			and G_PlatformGametype()
			and (s.radius > 500*FRACUNIT)
			s.radius = s.radius/2
			s.height = s.height/2
			return false end 
			if s.z == s.floorz
			s.z = s.z+s.target.height/2
			end */
			P_SetObjectMomZ(v, 12*FRACUNIT)
			P_InstaThrust(v, s.angle, 125*FRACUNIT)
			P_SpawnMobj(v.x, v.y, v.z, MT_BURSTWAVE)
			v.ghs = P_SpawnMobj(v.x, v.y, v.z, MT_BURSTWAVE)
			v.ghs.momx = v.momx/2
			v.ghs.momy = v.momy/2
			v.ghs.momz = v.momz/2
			v.fusrodah = 1
			v.trackerspawn = P_SpawnMobj(v.x, v.y, v.z, MT_CMPHTRACKER)
			v.trackerspawn.angle = s.angle
			v.trackerspawn.tracer = s.target
			v.trackerspawn.target = v
				if s.target
				S_StartSound(s.target, sfx_nerf)
					if s.target.player and s.target.player.hypermysticsonic
					v.fusrodah = 2
					end
				end
			return false
		elseif G_GametypeHasSpectators() and v.player
			if v.health
			and not v.player.cmphdodge
			and not (v.player.sms_dodging)
			and s.target
			and s.target.player and s.target.player.hypermysticsonic --AoE is for HMS only at this point.
			and not (v == s.target)  //Not yourself!
			and not (s.target.player.ctfteam and (v.player.ctfteam == s.target.player.ctfteam))
			and not (v.state == S_PLAY_PAIN)
				if s.target.player.hypermysticsonic
					if v.player.powers[pw_invulnerability]
					v.player.powers[pw_invulnerability] = 0  //What invincibility
					P_RestoreMusic(v.player)
					end
					P_RemoveShield(v.player)
					v.player.losstime = 2000
					P_FlashPal(v.player, PAL_MIXUP, 5)
					P_DamageMobj(v, s, s.target)
					P_SpawnMobj(v.x, v.y, v.z, MT_SMSAIRBOOST)
					P_InstaThrust(v, s.angle, 125*FRACUNIT)
				else
				if not (v.player.powers[pw_shield] == 513)
				P_RemoveShield(v.player)
				end
				P_FlashPal(v.player, PAL_MIXUP, 4)
				P_DamageMobj(v, s, s.target)
				P_SpawnMobj(v.x, v.y, v.z, MT_BURSTWAVE)
				P_RemoveShield(v.player)
					if v.health //I COULD remove instathrust and stop dead people, but this is more hilarious.
						P_SetObjectMomZ(v, 12*FRACUNIT)
						v.state = S_PLAY_PAIN
					end
				P_InstaThrust(v, s.angle, 125*FRACUNIT)
				end
			end
		end
		return false
end

addHook("MobjCollide", CMPHrad, MT_CMPHRADIUS)
addHook("MobjMoveCollide", CMPHrad, MT_CMPHRADIUS)

addHook("MobjThinker", function(f)
	if f.cmphflung
	f.cmphflung = $-1
		if f.cmphflung == 6	
		P_Thrust(f, f.angle, 125*FRACUNIT)
		end
	end
end, MT_FLINGRING)


addHook("MobjThinker", function(s)
	if (s and s.target) 
local t = s.target
		if s.cdtracker //Cooldown tracker
			if t.cmphttimer
			t.cmphttimer = $-1
			elseif s and s.valid
				if t.smspickupflags
				t.flags = t.smspickupflags
				t.smspickupflags = nil
				end
			t.cmphttimer = nil
			P_KillMobj(s)
			end
			return
//Monitor thrown tracker
		elseif s.throwntracker and s.ogsms //For thrown monitors.
			if t.valid and t.health and s.ogsms and s.ogsms.valid
				if P_IsObjectOnGround(t)
					t.rollangle = 0
					P_InstaThrust(t, s.ogsms.angle, 0)
					t.flags = $|MF_MONITOR|MF_SHOOTABLE
					t.flags = $ & ~MF_NOCLIPTHING & ~MF_NOGRAVITY
					if s and s.valid
					P_KillMobj(s)
					return
					end
				end
			else
				if s and s.valid
				P_KillMobj(s)
				return
				end
			end
			return
//SMS throwing			
		elseif s.smsthrow and s.smsthrowaim != nil and s.smsthrowang != nil and t.valid and s.smsthrowog and not t.lemmego
		s.smsthrow = $+1
			if t.cmphttimer == nil or t.cmphttimer
				if not (t.cttt and t.cttt.valid and t.cttt.health == 3)
				t.cttt = P_SpawnMobj(t.x, t.y, t.z, MT_SMSTHROWTRACKER)
				t.cttt.cdtracker = true
				t.cttt.target = t
				t.cttt.health = 3
				end
			t.cmphttimer = 5 //Generous emergency timer.
			end
			if not s.smsthrowdecideroll
			s.smsthrowdecideroll = (P_RandomRange(-12, 12))*FRACUNIT
			end
			s.flags = $|MF_SOLID & ~MF_NOCLIP
			s.radius = t.radius*20/19
			s.height = t.height
			t.ibethrownbysmshelp = 2
			P_TeleportMove(s, t.x, t.y, t.z)
			t.rollangle = $+FixedAngle(s.smsthrowdecideroll)
		local p = s
		
				if (t.momx < 0)
				s.lmomx = t.momx*-1
				else
				s.lmomx = t.momx
				end
				if (t.momy < 0)
				s.lmomy = t.momy*-1
				else
				s.lmomy = t.momy
				end
				s.momtotal = s.lmomy+s.lmomx	
			if (s.smsthrow == 2)
			S_StartSound(s, sfx_mswing)
			S_StartSound(s, sfx_mswing)
			t.momz = FixedMul(FixedMul(45*FRACUNIT, FRACUNIT), sin(s.smsthrowaim))
				if s.smsthrowguy and s.smsthrowguy.valid and s.smsthrowguy.health
					t.momx = FixedMul(FixedDiv(s.smsthrowguy.x-t.x, 450*FRACUNIT), FixedDiv(132*FRACUNIT, 3*FRACUNIT/2))
					t.momy = FixedMul(FixedDiv(s.smsthrowguy.y-t.y, 450*FRACUNIT), FixedDiv(132*FRACUNIT, 3*FRACUNIT/2))
					t.momz = FixedMul(FixedDiv(s.smsthrowguy.z-t.z, 450*FRACUNIT), FixedDiv(132*FRACUNIT, 3*FRACUNIT/2))
				elseif s.smsthrowaim != nil and (((s.smsthrowaim/FRACUNIT)/2200) != 0) and not (s.smsthrowaim < 0)
				P_InstaThrust(t, s.smsthrowang, 70*FRACUNIT/((s.smsthrowaim/FRACUNIT)/2200))
				else
				P_InstaThrust(t, s.smsthrowang, 70*FRACUNIT)
				end
				if (t.momx < 0)
				s.lmomx = t.momx*-1
				else
				s.lmomx = t.momx
				end
				if (t.momy < 0)
				s.lmomy = t.momy*-1
				else
				s.lmomy = t.momy
				end
				if s.momtotalfirst == nil //Set our first known speed!
				s.momtotalfirst = s.lmomy+s.lmomx
				end
				t.angle = R_PointToAngle2(t.x, t.y, t.x+t.momx, t.y+t.momy)
				s.momtotal = s.lmomy+s.lmomx
			end
			if (t.type == MT_PLAYER)
				if not s.alreadyexploded and t.health
				t.state = S_PLAY_PAIN
					if t.player
						if not s.pdrawangleh
						s.pdrawangleh = P_RandomRange(-18, 18)*FRACUNIT
						end
						if s.pdrawangle == nil
						s.pdrawangle = 0
						else
						t.player.drawangle = $+FixedAngle(s.pdrawangleh)
						end
					t.player.powers[pw_nocontrol] = 2
					end
				end
			end
			if s.homingbounce and s.homingbounce == 1
				P_SetObjectMomZ(t, 11*FRACUNIT)
				t.momx = 0
				t.momy = 0
				if t.player
				t.z = $+(10*FRACUNIT)*P_MobjFlip(t)
				t.eflags = $ & ~MFE_JUSTHITFLOOR
				t.state = S_PLAY_PAIN
				t.player.powers[pw_flashing] = 90 
				A_SMSquake(t, 45*FRACUNIT, 4, 900)
				end
				if s.smsthrowog and s.smsthrowog.mo
				A_SMSquake(s.smsthrowog.mo, 45*FRACUNIT, 4, 100, true)
				end
				s.smsgrboost = P_SpawnMobj(t.x, t.y, t.z, MT_BURSTWAVE)
				s.smsgrboost.tracer = t
				s.fj = P_SpawnMobj(t.x, t.y, t.z, MT_EXPLODE)
				s.fj = t.height/24 
				S_StartSound(t, sfx_s3k5d)
				P_NukeEnemies(t, s, 0)
				if s.smsthrowdecideroll
				s.smsthrowdecideroll = ($*(P_RandomRange(2,3)))*-1
				end
				s.alreadyexploded = true
				s.homingbounce = 2
				
			elseif not s.alreadyexploded and (s.smsthrow > 3) and not P_IsObjectOnGround(t)
			and ((s.momtotal != nil and s.momtotalfirst != nil
			and (s.momtotal < s.momtotalfirst/2)) or (t.z+t.height >= t.ceilingz))
				s.fj = P_SpawnMobj(t.x, t.y, t.z, MT_EXPLODE)
				s.fj.scale = t.height/24 
				s.alreadyexploded = true
				S_StartSound(t, sfx_s1bb) //Thud
					if (t.type == MT_PLAYER)
					t.state = S_PLAY_FALL
					end
					if t.player
					t.player.powers[pw_nocontrol] = 0
					t.player.powers[pw_flashing] = 16
					end
				if s.smsthrowdecideroll
				s.smsthrowdecideroll = ($/2)*-1
				end
				if (t.flags & (MF_ENEMY|MF_MISSILE)) and s.smsthrowog.mo
				P_DamageMobj(t, s.smsthrowog.mo, s.smsthrowog.mo)
				return
				end
			end
			if ((s.smsthrow > 3) and P_IsObjectOnGround(t)) or (s.smsthrow > 450) //Stop at some point incase it gets stuck.
				if P_IsObjectOnGround(t)
					if s.homingbounce and not s.alreadyexploded and not (s.smsthrow > 450)
					s.smsthrow = $+200
					return
					end
				S_StartSound(t, sfx_s1bb)
				A_SMSSTOMPSMOKE(t, 16, MT_SPINDUST)
				end
				if t.smspickupflags
				t.flags = t.smspickupflags
				t.smspickupflags = nil
				end
				t.rollangle = 0		
				if s and s.valid
				P_KillMobj(s)
				return
				end
			end
			return //Cancel, you're only dedicated to the SMS throw.
			
			
//HMS throwing		



		elseif s.hmsthrow and s.hmsthrowaim != nil and s.hmsthrowang != nil and t.valid and s.hmsthrowog and not t.lemmego
		s.hmsthrow = $+1
		local p = s
			s.flags = $|MF_SOLID & ~MF_NOCLIP
			s.radius = t.radius*20/19
			s.height = t.height
			P_TeleportMove(s, t.x, t.y, t.z)
			t.ibethrownbysmshelp = 2
			if (t.type == MT_PLAYER) and not s.playeranimstart
				if t.player
				t.player.powers[pw_nocontrol] = 2
				end
				if not s.alreadyexploded and t.health
				t.state = S_PLAY_PAIN
					if t.player
						if not s.pdrawangleh
						s.pdrawangleh = 45*FRACUNIT
						end
						if s.pdrawangle == nil
						s.pdrawangle = 0
						else
						t.player.drawangle = $+FixedAngle(s.pdrawangleh)
						end
					t.player.powers[pw_nocontrol] = 2
					end
				elseif s.alreadyexploded
					if t.player
						if (leveltime % 2 == 0)
						t.flags2 = $|MF2_DONTDRAW
						end
				//	t.player.powers[pw_flashing] = 105
					t.player.powers[pw_nocontrol] = 2
					end
					if (t.skin == "sms")
					t.state = S_PLAY_PAIN
					else
					t.state = S_PLAY_DEAD
					end
				A_BossScream(s, 0, MT_SMOKE)
				s.playeranim = 70
				s.playeranimstart = true
				end
			end	
			if not s.alreadyexploded and (s.hmsthrow > 3) and ( P_IsObjectOnGround(t)
			or s.homingbounce or (s.momtotal != nil and s.momtotalfirst != nil
			and (s.momtotal < s.momtotalfirst/2)) or (t.z+t.height >= t.ceilingz) )
				s.fj = P_SpawnMobj(t.x, t.y, t.z, MT_EXPLODE)
				s.fj.scale = t.height/24
				if not (s.hmsthrow >= 18) and s.hmsthrowog and s.hmsthrowog.mo
				P_FlashPal(p.hmsthrowog, 4, 4)
				P_SpawnMobj(t.x, t.y, t.z, MT_BURSTWAVE)
				s.homingbounce = 2
					if s.hmsthrowog and s.hmsthrowog.valid and s.hmsthrowog.mo
					s.pwb = P_SpawnMobj(t.x, t.y, t.z, MT_SMSPOWERBOMB)
					s.pwb.target = s.hmsthrowog.mo
					s.spul = P_SpawnMobj(s.x, s.y, s.z, MT_ATOMDIVEPOP)
	    			s.spul.tracer = s.hmsthrowog.mo
					end
				S_StartSound(t, sfx_spld)
				S_StartSound(t, sfx_pwbmb)
				
				elseif s.hmsthrowog and s.hmsthrowog.mo	and s.hmsthrowog.mo.valid
				
					P_FlashPal(s.hmsthrowog, 4, 10)
	    			p.spul = P_SpawnMobj(t.x, t.y, t.z, MT_ATOMDIVEPOP)
	    			p.spul.scale = 2*FRACUNIT
	    			p.spul.tracer = s.hmsthrowog.mo	
					s.hmsmobjboom = P_SpawnMobj(t.x, t.y, t.z, MT_TNTDUST)
					s.hmsmobjboom.fuse = 70
					s.hmsmobjboom.destscale = $*50
					s.pwb = P_SpawnMobj(t.x, t.y, t.z, MT_HMSPOWERBOMB)
					s.pwb.thrownnucl = true
					s.pwb.target = s.hmsthrowog.mo
					P_NukeEnemies(t, s.hmsthrowog.mo, 1*FRACUNIT)
					S_StartSound(t, sfx_spld)
					S_StartSound(t, sfx_nuexp)
				end

				t.momz = 0
				t.momx = 0
				t.momy = 0
				s.alreadyexploded = true
				if (t.flags & (MF_ENEMY|MF_MISSILE)) and s.hmsthrowog.mo
				t.rollangle = 0
				P_KillMobj(t, s.hmsthrowog.mo, s.hmsthrowog.mo)
				return
				end
			end
			if ((s.hmsthrow > 3) and P_IsObjectOnGround(t)) or (s.hmsthrow > 150) or s.playeranim //Stop at some point incase it gets stuck.
				if P_IsObjectOnGround(t) and not s.dustgfx
				A_SMSSTOMPSMOKE(t, 16, MT_SPINDUST)
				S_StartSound(t, sfx_s1bb)
				s.dustgfx = true
					if t.player and not s.playeranim and not s.alreadyexploded
					s.playeranim = 70
					s.alreadyexploded = true
					s.hmsthrow = 4
					return
					end
				end
				if not s.momact 
				t.momz = $/3
				t.momx = $/3
				t.momy = $/3
				s.momact = true
				t.rollangle = 0
				end
				if s.playeranim and not (s.hmsthrow > 150)
				s.playeranimstart = true
				A_BossScream(s, 0, MT_SMOKE)
				A_BossScream(s, 0, MT_SMOKE)
					if t.player
					t.player.powers[pw_nocontrol] = 2
					t.player.drawangle = t.angle
					end
					if P_IsObjectOnGround(t)
					s.playeranim = $-1 
						if (leveltime % 5 == 0)
						s.hmsthrow = $-1
						end
					t.rollangle = ANGLE_180
						if not s.hmsthrow or s.hmsthrow < 3
						t.rollangle = 0
						end
					t.state = S_PLAY_PAIN
					else
					s.hmsthrow = $-1
					t.rollangle = $+((FixedAngle(20*FRACUNIT)*t.rollhdecide)*-1)
				//	t.rollangle = s.rollangle
					if t.skin == "sms"
					t.state = S_PLAY_PAIN
					else
					t.state = S_PLAY_DEAD
					end
						if not s.hmsthrow or s.hmsthrow < 3
						t.rollangle = 0
						end
					end
					if not s.playeranim or s.playeranim == 1
						if t.player
							if P_IsObjectOnGround(s)
							P_DoJump(t.player, true)
							end
						t.player.powers[pw_nocontrol] = 0
						end
						t.rollangle = 0
						t.state = S_PLAY_ROLL
						if t.smspickupflags
						t.flags = t.smspickupflags
						t.smspickupflags = nil
						end
						if s and s.valid
						t.rollangle = 0
						P_KillMobj(s)
						return
						end
					end
				elseif s and s.valid and s.playeranim != nil and s.playeranim == 0
					if t
					t.rollangle = 0
						if t.smspickupflags
						t.flags = t.smspickupflags
						t.smspickupflags = nil
						end
					end
				P_KillMobj(s)
				return
				end
			end
		   if not s.alreadyexploded	and not s.playeranimstart		
			if s.hmsthrowog and s.hmsthrowog.valid and s.hmsthrowog.mo	
				if not t.rollhdecide
					if P_RandomRange(0,1)
					t.rollhdecide = 1
					else
					t.rollhdecide = -1
					end
				end
				t.rollangle = $+FixedAngle(45*FRACUNIT)*t.rollhdecide
				t.angle = $+FixedAngle(45*FRACUNIT)
				
					if not s.hmsthrow or s.hmsthrow < 3
					t.rollangle = 0
					end

			if (leveltime % 2 == 0)
			p.smsgrboost = P_SpawnGhostMobj(s)	
			p.smsgrboost.rollangle = s.rollangle
			else
			p.smsgrboost = P_SpawnMobj(t.x, t.y, t.z, MT_SMSGROUNDBOOST) p.smsgrboost.tracer = s.hmsthrowog.mo
			end
			
				if s.hmsthrow == 27
					P_FlashPal(s.hmsthrowog, PAL_NUKE, 3)
					S_StartSound(t, sfx_s3k83)
					S_StartSound(t, sfx_beeyow)
				end
			
				if (s.hmsthrow >= 27)
				p.smsgrboost = P_SpawnMobj(t.x+150*FRACUNIT, t.y+150*FRACUNIT, t.z, MT_SMSGROUNDBOOST) p.smsgrboost.tracer = s.hmsthrowog.mo
				p.smsgrboost = P_SpawnMobj(t.x-150*FRACUNIT, t.y-150*FRACUNIT, t.z, MT_SMSGROUNDBOOST) p.smsgrboost.tracer = s.hmsthrowog.mo
				p.smsgrboost = P_SpawnMobj(t.x, t.y, t.z+150*FRACUNIT, MT_SMSGROUNDBOOST) p.smsgrboost.color = SKINCOLOR_FLAME 
				p.smsgrboost = P_SpawnMobj(t.x, t.y, t.z-150*FRACUNIT, MT_SMSGROUNDBOOST) p.smsgrboost.color = SKINCOLOR_SUPERGOLD5
				end
			end	
				if (t.momx < 0)
				s.lmomx = t.momx*-1
				else
				s.lmomx = t.momx
				end
				if (t.momy < 0)
				s.lmomy = t.momy*-1
				else
				s.lmomy = t.momy
				end
				s.momtotal = s.lmomy+s.lmomx	
				
				if (s.hmsthrow == 2)
				t.rollangle = 0
				t.momz = FixedMul(FixedMul(125*FRACUNIT, FRACUNIT), sin(s.hmsthrowaim))
				P_InstaThrust(t, s.hmsthrowang, 125*FRACUNIT)
					if (t.momx < 0)
					s.lmomx = t.momx*-1
					else
					s.lmomx = t.momx
					end
					if (t.momy < 0)
					s.lmomy = t.momy*-1
					else
					s.lmomy = t.momy
					end
					s.momtotal = s.lmomy+s.lmomx
					s.momtotalfirst = s.momtotal
					t.angle = R_PointToAngle2(t.x, t.y, t.x+t.momx, t.y+t.momy)
				elseif (s.hmsthrow == 27)
				t.momz = FixedMul(FixedMul(200*FRACUNIT, FRACUNIT), sin(s.hmsthrowaim))
				P_InstaThrust(t, s.hmsthrowang, 200*FRACUNIT)
					if (t.momx < 0)
					s.lmomx = t.momx*-1
					else
					s.lmomx = t.momx
					end
					if (t.momy < 0)
					s.lmomy = t.momy*-1
					else
					s.lmomy = t.momy
					end
					s.momtotal = s.lmomy+s.lmomx
					s.momtotalfirst = s.momtotal
				end
		   end
		return //End hook early if we're at this point
		elseif s.valid and s.health
			P_KillMobj(s, s)
		end
	elseif s.valid and s.health
		P_KillMobj(s)
	end
end, MT_SMSTHROWTRACKER)

//DummyTracker, dummyhbx. Makes hitbox for enemies that have none.

addHook("MobjThinker", function(s)
	if (s and s.target) 
local t = s.target
			if s.target and s.target.valid and s.target.health
			P_TeleportMove(s, t.x, t.y, t.z)
			elseif s and s.valid
			s.state = S_NULL
			end
			return
	elseif s.valid
		P_KillMobj(s, s)
		return
	end
end, MT_SMSDUMMYTRACKER)

//This is the thinker for our tracker.
//It's responsible for killing off the enemy in explosive ways.

addHook("MobjThinker", function(s)
	if (s and s.target) 
local t = s.target
//Blackhole and Gravity Burst trackers		
		if G_GametypeHasSpectators() and (s.state == S_CMPHRADIUS2)
			P_NukeEnemies(cometpunchstrike, cometpunchstrike.target, 200*FRACUNIT)
		end
		if s.bkhl and t and s.tracer
			if s.tracer.player and (s.tracer.state == S_HMSBLACKHOLE)
			local homiedist = FixedHypot(FixedHypot(s.tracer.x - t.x, s.tracer.y - t.y), s.tracer.z - t.z)
			local speedmuller = FixedMul(30*FRACUNIT, t.scale)
				t.momx = FixedMul(FixedDiv(s.tracer.x - t.x, homiedist), speedmuller)
				t.momy = FixedMul(FixedDiv(s.tracer.y - t.y, homiedist), speedmuller)
				t.momz = FixedMul(FixedDiv(s.tracer.z - t.z, homiedist), speedmuller)
				t.bkhltracked = true
			else
				t.bkhltracked = nil
				s.state = S_NULL
			end
		elseif t.gravbu and t.health and (t.flags & (MF_ENEMY|MF_BOSS) or t.player)
			if t.player and t.health
			t.smsglowticket = 90
			end
			t.gravbu = $-1
			if (t.gravbu > 14)
				P_SetObjectMomZ(t, 30*FRACUNIT)
				if (leveltime % 2 == 0)
				t.bwc = P_SpawnMobj(t.x, t.y, t.z, MT_BURSTWAVE)
				t.bwc.color = P_RandomRange(1, SKINCOLOR_SUPERTAN3)
				end
			elseif (t.gravbu > 5)
				t.momx = t.momx/2
				t.momy = t.momy/2
				P_SetObjectMomZ(t, 22*FRACUNIT)
				P_SpawnMobj(t.x, t.y, t.z, MT_BURSTLIGHT)
			elseif (t.gravbu == 5)
				P_SetObjectMomZ(t, 18*FRACUNIT)
				P_SpawnMobj(t.x, t.y, t.z, MT_EXPLODE)
				if (t.type == MT_EGGMOBILE3 or t.type == MT_EGGMOBILE4)
				t.cmphtracker = nil
					if s.tracer
					P_KillMobj(t, s, s.tracer)
					else
					P_KillMobj(t, s)
					end
				end
			elseif t
				P_SpawnMobj(t.x, t.y, t.z, MT_EXPLODE)
			end
//Actual punching tracker
		elseif t.fusrodah and t.health // and (t.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR)) //Okay, so we're ACTUALLY tracking a Comet Haymaker victim here.
			if t.trackerspawn and t.trackerspawn.valid and (t.trackerspawn != s) and t.trackerspawn.type == MT_CMPHTRACKER
			P_KillMobj(s) //Occupied. We don't need extra
			return
			end
			if s.fusrodahfuse
			s.fusrodahfuse = $+1
			//	print(s.angle+" as well as "+s.fusrodahexplode+" Thus "+s.fusrodahfuse+" And "+s.fusrodahwallexplode+" Wheeeheeeeee! "+t.momx/FRACUNIT+" "+t.momy/FRACUNIT)
			  if ( ((leveltime % 2 == 0) or s.fusrodahfuse < 6) and (t.type == MT_METALSONIC_BATTLE)) or not (t.type == MT_METALSONIC_BATTLE)
				if not t.momx and not t.momy
				P_InstaThrust(t, s.angle, 125*FRACUNIT)
				end
				if not s.fusrodahwallexplode
				P_InstaThrust(t, s.angle, 125*FRACUNIT)
				end
			  end
				if s.fusrodahfuse < 8
				P_SetObjectMomZ(t, 115550, true)
				elseif (s.fusrodahfuse > 250) //Time limit on how long enemies can be send flying
				s.fusrodahexplode = true
				else
				P_SetObjectMomZ(t, -55355, true)
				end
			end
			P_TeleportMove(s, t.x, t.y, t.z)
			if not s.momx and not s.momy
			P_InstaThrust(t, s.angle, 10*FRACUNIT)
			P_InstaThrust(s, s.angle, 10*FRACUNIT)
			else
			s.momx = t.momx
			s.momy = t.momy
			s.momz = t.momz
			end
			if t.fixedbounceded
				t.flags = $|MF_BOUNCE|MF_SCENERY|MF_GRENADEBOUNCE
				if not t.retfus
				t.retfus = 77
				else
				t.retfus = $-1
				end
			end
			if s.spinrangle == nil
			s.spinrangle = t.angle
			else
			s.spinrangle = $+FixedAngle(44*FRACUNIT)
			end
			if not ((players[(0)] and players[(0)].smsgraphix) or (players[(1)] and players[(1)].smsgraphix))
			and not ((t.type == MT_CYBRAKDEMON) or (t.type == MT_FACESTABBER))
			t.rollangle = s.spinrangle //Rollangle on enemies is surprisingly lag-inducing sometimes
			end
			t.angle = s.spinrangle
			t.flags = $|MF_NOCLIPTHING & ~MF_FLOAT & ~MF_NOGRAVITY & ~MF_SLIDEME //Don't clip into stuff
			if not t.ghostaf //Spawn this once.
				if (t.info.mass == 2006)
				t.fusrodah = false //Nevermind, target is immune
					if s and s.valid
					P_KillMobj(s)
					end
				return
				end
			t.ghostaf = P_SpawnGhostMobj(t)
			t.ghostaf.tics = 11
		//	t.ghostaf.rollangle = t.rollangle
			s.radius = t.radius
			s.height = t.height
			s.flags = $|MF_NOCLIPTHING & ~MF_NOCLIP 
			end
			t.tics = $+1 //Stay in current animation.
			if t.type == MT_GSNAPPER or t.typpe == MT_DRAGONBOMBER
			t.target = nil
			end
			
			if s.fusrodahfuse == nil
			
			s.fusrodahfuse = 1

			elseif s.fusrodahexplode or ( ((t.momx < 599355 and t.momx > -599355) and (t.momy < 599355 and t.momy > -599355)) and t.type == MT_METALSONIC_BATTLE) 
			or (t.eflags & MFE_JUSTHITFLOOR) or (t.retfus and t.retfus == 1) // or (t.z <= t.floorz)
				if (t.type == MT_PTERABYTE) or (t.type == MT_PYREFLY) or (t.type == MT_DRAGONBOMBER)	
				t.flags = $ & ~MF_SCENERY
				end
				if (t.fusrodah == 1)
				t.cmphtracker = nil
				t.fusrodah = 0
				t.rollangle = 0
				P_SpawnMobj(t.x, t.y, t.z, MT_CYBRAKDEMON_VILE_EXPLOSION)
				P_SpawnMobj(t.x+(P_RandomRange(-90, 90)*FRACUNIT), t.y+(P_RandomRange(-90, 90)*FRACUNIT), t.z+(P_RandomRange(-30, 30)*FRACUNIT), MT_CYBRAKDEMON_VILE_EXPLOSION)
				P_SpawnMobj(t.x+(P_RandomRange(-90, 90)*FRACUNIT), t.y+(P_RandomRange(-90, 90)*FRACUNIT), t.z+(P_RandomRange(-30, 30)*FRACUNIT), MT_CYBRAKDEMON_VILE_EXPLOSION)
			//	P_SpawnMobj(t.x+(P_RandomRange(-60, 60)*FRACUNIT), t.y+(P_RandomRange(-60, 60)*FRACUNIT), t.z+(P_RandomRange(-20, 20)*FRACUNIT), MT_CYBRAKDEMON_VILE_EXPLOSION)
					if t and t.valid and s.tracer
					P_KillMobj(t, s, s.tracer)
					return
					elseif t and t.valid
					P_KillMobj(t, s)
					return
					end
				end
				if (t.fusrodah >= 2)
				t.cmphtracker = nil
				t.ultimateboom = P_SpawnMobj(t.x, t.y, t.z, MT_BURSTWAVE)
					if t.ultimateboom
					S_StartSound(t.ultimateboom, sfx_brakrx)
					t.ultimateboom.scale = 3*FRACUNIT
					t.ultimateboom.color = SKINCOLOR_RED
					t.rollangle = 0
					if t and t.valid and s.tracer
					P_KillMobj(t, s, s.tracer)
					return
					elseif t and t.valid
					P_KillMobj(t, s)
					return
					end
					t.fusrodah = 0
					end
				end
			end
			if s.fusrodahwallexplode
			s.fusrodahexplode = true
			end
		elseif s.valid and s.health
			P_KillMobj(s, s)
			return
		end
	end
end, MT_CMPHTRACKER)

addHook("MobjThinker", function(s)
	if (P_FaceStabCheckMeleeRange(s)) or (s.target and P_IsObjectOnGround(s.target))
		s.state = S_NULL
	end
end, MT_ATOMDIVETARGET)

//The Powerbomb is a slow but large explosion. If seen in time it can be dodged
//but if not, then you'll be in really bad shape. Don't get caught off guard!

addHook("MobjThinker", function(p)
	if (p and p.valid)
	and p.target
		p.blendmode = AST_ADD
		local ghs = SMSRSpawnGhost(p, 2)
		ghs.scale = $/2
		if p.state == S_SMSPOWERBOMB1
			p.scale = FRACUNIT*10
			p.color = SKINCOLOR_FLAME
			P_InstaThrust(p, p.target.angle, -10) //Move real slowly backwards.
				if p.target.battlemodsms
				P_NukeEnemies(p.target, p.target, 400*FRACUNIT) //Thanks, Battlemod
				else
				P_NukeEnemies(p, p.target, 400*FRACUNIT)
				end
			if not (p.target.player and p.target.player.smsgraphix and p.target.player.smsgraphix == 2)
			A_SMSquake(p.target, 55*FRACUNIT, 4, 6000)
			end
		end
		if p.state == S_SMSPOWERBOMB1A
			p.scale = p.scale+9001
			if not p.phase
				p.novawave = P_SpawnMobj(p.x, p.y, p.z-25*FRACUNIT, MT_HMSNOVAWAVE)
				p.novawave.color = SKINCOLOR_RED
				p.novawave.followmenoz = p
				p.scale = FRACUNIT
				p.phase = 1
				if not (p.target.player and p.target.player.smsgraphix and p.target.player.smsgraphix == 2)
				A_SMSSTOMPSMOKE(p, 2, MT_EXPLODE, 71*FRACUNIT)
				A_SMSSTOMPSMOKE(p, 4, MT_BOSSEXPLODE, 45*FRACUNIT)
				A_SMSSTOMPSMOKE(p, 7, MT_EXPLODE)
				end
			end
		end
		if p.state == S_SMSPOWERBOMB2
			p.scale = p.scale+12500
			if not (p.phase and p.phase >= 2)
				A_SMSquake(p.target, 33*FRACUNIT, 35, 5000)
				p.color = SKINCOLOR_KETCHUP
				if p.target.battlemodsms
				P_NukeEnemies(p.target, p.target,800*FRACUNIT) //Screw you too, Battlemod
				else
				P_NukeEnemies(p, p.target, 800*FRACUNIT)
				end
				p.phase = 2
			end
		end
		if p.state == S_SMSPOWERBOMB3
			p.color = SKINCOLOR_YELLOW
			p.scale = p.scale+25000
			if not (p.phase and p.phase >= 3)
				if not (p.target.player and p.target.player.smsgraphix and p.target.player.smsgraphix == 2)
				A_SMSSTOMPSMOKE(p, 8, MT_BOSSEXPLODE, 120*FRACUNIT)
				A_SMSSTOMPSMOKE(p, 12, MT_EXPLODE, 75*FRACUNIT)
				A_SMSSTOMPSMOKE(p, 16, MT_BOSSEXPLODE)
				end
			p.phase = 3
			end
		end
		if p.state == S_SMSPOWERBOMB4
			p.color = SKINCOLOR_WHITE
			p.scale = p.scale+41500
			if not (p.phase and p.phase >= 4)
			A_SMSkillstuff(p, 2250*FRACUNIT, 1222*FRACUNIT, p.target, false, true)
				if p.target.battlemodsms
				P_NukeEnemies(p.target, p.target, 1800*FRACUNIT) //Battlemod is an ass.
				elseif G_PlatformGametype()
				P_NukeEnemies(p, p.target, 2250*FRACUNIT)
				else
				P_NukeEnemies(p, p.target, 1800*FRACUNIT)
				end
			p.phase = 4
			end
		end
		if p.state == S_SMSPOWERBOMB5
			p.color = SKINCOLOR_BONE
			p.phase = 6
			p.scale = p.scale+25000
		end
		if p.state == S_SMSPOWERBOMB6
			p.color = SKINCOLOR_EMERALD
			p.scale = p.scale+15000
		end
	end
end, MT_SMSPOWERBOMB)

//A nuclear explosion isn't 1 big cloud. Like a real explosion, we have 
//to build it up, but make it feel realistic-ish with good timing and position.

addHook("MobjThinker", function(p)
	if (p and p.valid)
	and p.target
		if p.state == S_HMSPOWERBOMB1A
		and not p.phase //Otherwise this'd keep spawning clouds for the entirety of the frame.
		if p.target.player and p.target.player.hypermysticsonic
		A_SMSkillstuff(p, 4000*FRACUNIT, 1250*FRACUNIT, p.target)
		end
		A_SMSSTOMPSMOKE(p, 7, MT_BOSSEXPLODE, 70, 36*FRACUNIT, 9*FRACUNIT)
		A_SMSSTOMPSMOKE(p, 6, MT_BOSSEXPLODE, 50, 17*FRACUNIT, 3*FRACUNIT)
		if not (players[(0)] and players[(0)].smsgraphix)
		A_SMSSTOMPSMOKE(p, 4, MT_HMSLIGHTNING2)
		A_SMSSTOMPSMOKE(p, 15, MT_HMSLIGHTNING2, nil, 3*FRACUNIT, FRACUNIT/4)
		A_SMSSTOMPSMOKE(p.target, 30, MT_NIGHTSPARKLE, P_RandomRange(1, 80), nil, 5*FRACUNIT)
		end
		if not (players[(0)] and players[(0)].smsgraphix and players[(0)].smsgraphix == 2)
		A_SMSSTOMPSMOKE(p, 35, MT_SPARK, 15, 3*FRACUNIT, 5*FRACUNIT)
		A_SMSSTOMPSMOKE(p, 25, MT_SPARK, 25, 20*FRACUNIT, 4*FRACUNIT)
		A_SMSSTOMPSMOKE(p, 15, MT_BOSSEXPLODE, nil, 3*FRACUNIT, 6*FRACUNIT)
		A_SMSSTOMPSMOKE(p, 14, MT_HMSPBC, nil, nil, 2*FRACUNIT)
		end
		if p.thrownnucl
		A_SMSSTOMPSMOKE(p, 5, MT_HMSPBC, 0, -10*FRACUNIT)
		A_SMSSTOMPSMOKE(p, 3, MT_HMSPBC, 0, -20*FRACUNIT)
		end
		p.scale = FRACUNIT*3
		P_StartQuake(200*FRACUNIT, 10)
		P_InstaThrust(p, p.target.angle, -10)
		P_SpawnMobj(p.x, p.y+350*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x+350*FRACUNIT, p.y, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x-350*FRACUNIT, p.y, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x, p.y-350*FRACUNIT, p.z, MT_HMSPBC)

		P_SpawnMobj(p.x+55*FRACUNIT, p.y+120*FRACUNIT, p.z+300*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x-80, p.y-110*FRACUNIT, p.z+450*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		p.phase = 1
		end
		if p.state == S_HMSPOWERBOMB1B
		and not (p.phase and p.phase >= 2)
			if p.target.battlemodsms and not p.thrownnucl
			P_NukeEnemies(p.target, p.target, 4000*FRACUNIT) //Battlemod is a dick			
			elseif p.target.player and p.target.player.hypermysticsonic
			P_NukeEnemies(p, p.target, 4000*FRACUNIT)
			end
		P_SpawnMobj(p.x+700*FRACUNIT, p.y+700*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x-700*FRACUNIT, p.y-700*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x-700*FRACUNIT, p.y+700*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x+700*FRACUNIT, p.y-700*FRACUNIT, p.z, MT_HMSPBC)

		P_SpawnMobj(p.x, p.y, p.z+700*FRACUNIT, MT_HMSPBC)
		P_SpawnMobj(p.x, p.y, p.z+1150*FRACUNIT, MT_HMSPBC)
		p.phase = 2
		end
		if p.state == S_HMSPOWERBOMB1C
		and not (p.phase and p.phase >= 3)
		P_SpawnMobj(p.x, p.y+1250*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x+1250*FRACUNIT, p.y, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x-1250*FRACUNIT, p.y, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x, p.y-1250*FRACUNIT, p.z, MT_HMSPBC)

		P_SpawnMobj(p.x, p.y, p.z+1500*FRACUNIT, MT_HMSPBC)
		P_SpawnMobj(p.x, p.y, p.z+1850*FRACUNIT, MT_HMSPBC)
		p.phase = 3
		end
		if p.state == S_HMSPOWERBOMB2
		and not (p.phase and p.phase >= 4)
			if p.target and not p.thrownnucl
			p.target.hudboost = 1
			end
		P_StartQuake(23*FRACUNIT, 85)
		P_SpawnMobj(p.x+1650*FRACUNIT, p.y+1650*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x-1650*FRACUNIT, p.y-1650*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x-1650*FRACUNIT, p.y+1650*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x+1650*FRACUNIT, p.y-1650*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x, p.y+1650*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x, p.y-1650*FRACUNIT, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x-1650*FRACUNIT, p.y, p.z, MT_HMSPBC)
		P_SpawnMobj(p.x+1650*FRACUNIT, p.y, p.z, MT_HMSPBC)

		P_SpawnMobj(p.x, p.y, p.z+2500*FRACUNIT, MT_HMSPBC)
		P_SpawnMobj(p.x+600*FRACUNIT, p.y+400*FRACUNIT, p.z+1900*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x-600*FRACUNIT, p.y+400*FRACUNIT, p.z+1850*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x+600*FRACUNIT, p.y-400*FRACUNIT, p.z+1900*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x-600*FRACUNIT, p.y-400*FRACUNIT, p.z+1850*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)

		P_SpawnMobj(p.x+350*FRACUNIT, p.y, p.z+2250*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x-350*FRACUNIT, p.y, p.z+2200*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x, p.y-350*FRACUNIT, p.z+2250*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x, p.y-350*FRACUNIT, p.z+2200*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		p.phase = 4
		end
		if p.state == S_HMSPOWERBOMB3
		and not (p.phase and p.phase >= 5)
		P_StartQuake(6*FRACUNIT, 70)
		P_SpawnMobj(p.x, p.y, p.z+2575*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x, p.y, p.z+2000*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x+800*FRACUNIT, p.y, p.z+2300*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x-800*FRACUNIT, p.y, p.z+2350*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x, p.y-800*FRACUNIT, p.z+2300*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		P_SpawnMobj(p.x, p.y+800*FRACUNIT, p.z+2350*FRACUNIT*(P_MobjFlip(p)), MT_HMSPBC)
		p.phase = 5
		end
	end
end, MT_HMSPOWERBOMB)

//Start the clouds off REALLY small.

addHook("MobjThinker", function(s)
	if (s and s.valid)
		if s.state == S_HMSPBC0
		s.scale = FRACUNIT/20
			if s.bkhl
			s.scale = FRACUNIT
			s.scalespeed = $/11
			A_SetScale(s, FRACUNIT/20, 1)
			s.state = S_HMSPBC3
			end
		end
		if (s.state == S_HMSPBC3) and not s.bkhl and not s.riz and (s.z > s.floorz+250*FRACUNIT)
		s.momz = $+6*FRACUNIT*P_MobjFlip(s)
		s.riz = true
		end
		if s.bkhl 
			if (s.target and (s.target.state == S_HMSBLACKHOLE))
			P_HomingAttack(s, s.target)
			else
			s.momx = $/5
			s.momy = $/5
			P_SetObjectMomZ(s, 97377)
			s.bkhl = false
			end
			if P_CheckMeleeRange(s)
			and not (s.target.info.mass == 2006)
			P_KillMobj(s)
			end
		end
	end
end, MT_HMSPBC)

local function TrackerCollide(s, v)
	if v
		if v.type == MT_SMSECHECK
		return
		elseif (v.type == MT_CMPHRADIUS) and s.target and not s.target.fusrodah
		CMPHrad(v, s.target)
		return
		else
		return false
		end
	end
return false
end

addHook("MobjCollide", TrackerCollide, MT_SMSDUMMYTRACKER)
addHook("MobjMoveCollide", TrackerCollide, MT_SMSDUMMYTRACKER)

//Quick fix to Tails' tails being dumb.

addHook("MobjThinker", function(s)
	if s.tracer and s.tracer.valid
	s.rollangle = s.tracer.rollangle
	end
end, MT_TAILSOVERLAY)