function A_HMSfiretrail(s, var1) //Var1 = Optional Custom Object
if s.player and s.player.smsgraphix and s.player.smsgraphix == 2
return
end
if not var1 var1 = MT_SPINFIRE end
	for d = -1,1,2 do
			if s and not (s.eflags & MFE_TOUCHWATER)
			and s.health
			local dist = (P_RandomRange(16,24)*s.scale)
			local ang = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)+(ANGLE_90*d)
				if (s.eflags & MFE_VERTICALFLIP)
				s.hmseruptflame = P_SpawnMobj(s.x+(FixedMul(dist, cos(ang))), s.y+(FixedMul(dist, sin(ang))), s.ceilingz, var1)
				else
				s.hmseruptflame = P_SpawnMobj(s.x+(FixedMul(dist, cos(ang))), s.y+(FixedMul(dist, sin(ang))), s.floorz, var1)
				end			
				if s.hmseruptflame and s.hmseruptflame.valid
				local ff = s.hmseruptflame
				ff.eflags = s.eflags
				ff.target = s
				ff.angle = s.angle+((ANG2+ANG2)*d)
				if s and s.player and (s.player.speed > 40*FRACUNIT)
				ff.momx = s.momx/2
				ff.momy = s.momy/2
				P_Thrust(ff, ang, s.player.speed/P_RandomRange(32, 128))
				end
					if ff.type == MT_SPINFIRE
					ff.state = S_HMSFPILLAR1
					ff.tics = P_RandomRange(1,4)
					ff.scale = s.scale*10/P_RandomRange(10, 12)
						if not s.momx
						s.momx = 8
						end
					ff.health = 1	
					ff.flags = MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY|MF_FIRE & ~MF_NOCLIPHEIGHT
					else
					ff.scale = s.scale
					end
					if ff and ff.valid and ((ff.z > s.z+s.height) or (ff.z < s.z-s.height))
					ff.state = S_NULL
					end
				end
			end
	end
end

//Different from A_SMSSTOMPSMOKE! This works with FF_PAPERSPRITE sprites.
//var1=base radius | var2 = scale(15) | Var3 = TravelSpeed | Var4 = MomZ | Var5 = Additional Angle value | Var6 = Additional Z offset | Var7 = Optional Fuse | Var8 = Color | Var9 = ObjType
function A_SMSSTOMPQUAKE(s, var1, var2, var3, var4, var5, var6, var7, var8, var9)
if s.player and s.player.smsgraphix and s.player.smsgraphix == 2
return
end
if not var1 var1 = 45 end 
if not var2 var2 = 15 end
if not var3 var3 = 0 end
if not var4 var4 = 0 end
if not var5 var5 = 0 end
if not var6 var6 = 0 end
if not var7 var7 = 10 end
if not var8 var8 = s.color end 
if not var9 var9 = MT_SMSSWAVE end //Perhaps I've added too many variables?
	for d = 0,5 do 
	local cal = (ANG60*d)
	s.sqwave = P_SpawnMobj(s.x+FixedMul(var1*cos(s.angle+var5+cal), s.scale), s.y+FixedMul(var1*sin(s.angle+var5+cal), s.scale), s.z+var6, var9)
		s.sqwave.target = s
		s.sqwave.fuse = var7
		s.sqwave.angle = s.angle+var5+ANG60*d+ANGLE_90
		s.sqwave.scale = (s.scale*8)/var2
			if (var2 and var2 < 7)
			s.sqwave.scalespeed = $*3
			elseif (s.scale > FRACUNIT)
			s.sqwave.scalespeed = $*2		
			elseif not (s.player and s.player.hypermysticsonic)
			s.sqwave.scalespeed = $*8/13
			end
		s.sqwave.destscale = s.sqwave.scalespeed+1
		s.sqwave.color = var8
		s.sqwave.eflags = s.eflags
		s.sqwave.flags2 = s.flags2 & ~MF2_DONTDRAW & ~MF2_SHADOW
			if s and ((s.type == MT_THOK) or s.player and s.player.hypermysticsonic)
			s.sqwave.frame = $|FF_FULLBRIGHT
			end
		if var4
		s.sqwave.momz = var4
		end
		if var3
		P_Thrust(s.sqwave, R_PointToAngle2(s.x, s.y, s.sqwave.x, s.sqwave.y), var3)
		end
		if var9 and var9 == MT_HMSWAVEAURA
		s.sqwave.momx = $+(s.momx)
		s.sqwave.momy = $+(s.momy)
		s.sqwave.sprite = SPR_SMMK
		s.sqwave.dustwave2 = 1
		s.sqwave.frame = 8
		s.sqwave.destscale = 10*FRACUNIT
		end
	end
end

//Function to kill stuff!
function A_SMSkillstuff(actor, var1, var2, var3, var4, var5)
	if actor
	local p = actor
	    	for m in mobjs.iterate(mobjs)
			 if m and (m.flags & (MF_ENEMY|MF_BOSS))
				if var1 and m.valid and m.health and ((FixedHypot(FixedHypot(m.x-p.x, m.y-p.y), m.z-p.z)) <= var1)
				and not (m.info.mass == 2006)
					if var4 and not (m.z < p.z-(150*FRACUNIT*(P_MobjFlip(p))) )
 	    				 if (m.health > 1)
						 m.health = $-1
 	    				 end
					elseif var5
 	    				 	if (m.health < 6)
							m.health = 1
 	    				 	elseif (m.health > 4)
							m.health = $-4
 	    				 	end
					else
						P_KillMobj(m, p, var3)
					end
				end
			 end
			end
	end
end

//var1 = spawn dist | var2 = item type | var3 = Optional Z Spawn | Var4 = Optional Additional Z momentum | Var5 = Scale | Var6 = Color
function A_SMSSTOMPSMOKE(actor, var1, var2, var3, var4, var5, var6)
	if not (actor)
		return
	end
	for sa = 0,08 // This is how many spawn.
		local smmk = P_SpawnMobj(actor.x, actor.y, actor.z+FixedMul(FRACUNIT, (P_MobjFlip(actor)*actor.scale)), var2)
		smmk.target = actor
		if smmk.type == MT_HMSLIGHTNING2 and actor.type == MT_HMSPOWERBOMB
			if not var4
			smmk.growx2 = true
			end
			smmk.color = SKINCOLOR_SUPERGOLD5
			smmk.flags = $|MF_NOCLIP & ~MF_SOLID
			smmk.silentl = true
		end
		if smmk.type == MT_BOSSEXPLODE and actor.hmsspinpass
		smmk.state = $+P_RandomRange(0,4)
		end
		
		if var5
		smmk.scale = var5
		else
		smmk.scale = actor.scale
		end
		
		smmk.flags = $|MF_NOCLIPHEIGHT
		smmk.eflags = actor.eflags
		smmk.flags2 = actor.flags2
		smmk.smssmmk = true
		smmk.momx = ( (var1*(actor.scale/FRACUNIT))*cos((sa*ANGLE_45)) + (actor.momx/2) )
		smmk.momy = ( (var1*(actor.scale/FRACUNIT))*sin((sa*ANGLE_45)) + (actor.momy/2) )
		if (smmk and smmk.type == MT_ENERGYBALL)
		smmk.sprite = SPR_SMBO
		smmk.state = S_SMSBOOSTAURA1
		smmk.tics = 12
		A_FaceTarget(smmk)
		smmk.angle = $+ANGLE_180
		smmk.frame = 3|TR_TRANS70
		smmk.flags = $ & ~MF_MISSILE & ~MF_PAIN & ~MF_SOLID
		smmk.color = P_RandomRange(SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERTAN3)
		smmk.fuse = 12
		smmk.destscale = $/10
			if not var4
			smmk.momz = actor.momz/2
			end
			
		elseif smmk and (smmk.type == MT_NIGHTSPARKLE)
		
		smmk.state = S_SMSTSPARK1
		smmk.coverride = true
		smmk.scale = $*4
		smmk.destscale = $*6
			if P_RandomRange(0,1) and not (actor.type == MT_HMSNOVABLAST)
			smmk.momz = actor.momz/3
			end
		end
		
		if var3
		P_TeleportMove(smmk, smmk.x, smmk.y, smmk.z+FixedMul(var3, (P_MobjFlip(actor)*actor.scale)))
		end
		if var4 //Var5 is on top.
		smmk.momz = var4
		end
		if var6
		smmk.color = var6
		end
		
		if (actor.eflags & MFE_UNDERWATER)
		P_SetObjectMomZ(smmk, 2*FRACUNIT, true)
		end
	end
end

//Depending whether you're in match/CTF/Team Match or not, you'll
//get a weaker or stronger walljump. A too strong walljump would make
//SMS even harder to hit than he already is.

function A_MATCHORNOTSPAWN(s, var1, var2)
	if not (s.target and s.target.player and s.target.health)
		return
	end
	if s.target.player.bot and s.target.valid
	s.target.angle = $+ANGLE_180-ANG20
		return
	end
local t = s.target
	if t.player.secondjump == 167 --Don't repeat.
	return
	end
	s.burstlightspawn = P_SpawnMobj(s.x, s.y, s.z, MT_BURSTLIGHT)
	s.burstlightspawn.scale = t.scale
	t.player.secondjump = 0
	t.player.homing = 0
	t.player.pflags = $|PF_JUMPED|PF_JUMPDOWN & ~PF_THOKKED & ~PF_STARTJUMP
		if s.target.player.smsblastboost --SMSblast mode now includes 2.0 SMSunleashed walljump.
			t.state = S_PLAY_SPRING
			t.eflags = $|MFE_SPRUNG
			if not t.player.powers[pw_nocontrol]
			t.player.powers[pw_nocontrol] = 3
			end
			t.player.pflags = $ & ~PF_NOJUMPDAMAGE & ~PF_THOKKED & ~PF_JUMPED & ~PF_JUMPDOWN
			if t.eflags & MFE_UNDERWATER or G_GametypeHasSpectators() or t.battlemodsms
				P_InstaThrust(t, t.angle, -2*FRACUNIT)
				S_StartSound(t, sfx_bljpw)
				P_SetObjectMomZ(t, 14*FRACUNIT, false)
			else
				P_InstaThrust(t, t.angle, -5*FRACUNIT)
				S_StartSound(t, sfx_bljp)
				P_SetObjectMomZ(t, 29*FRACUNIT, false)
			end		
			t.player.secondjump = 167
			return
		end
		if t.eflags & MFE_UNDERWATER and ( G_GametypeHasSpectators() or (t.player.sms_stompanim or t.player.sms_afterstompthok))
			if (t.player.sms_stompanim or t.player.sms_afterstompthok)
			P_SpawnMobj(t.x, t.y, t.z, MT_SPINDUST)
			S_StartSoundAtVolume(t, sfx_skid, 194)
			end
			S_StartSound(t, sfx_bljpw)
 			P_InstaThrust(t, t.angle, FixedMul(-18*FRACUNIT, t.scale))
			if ((s.momz*P_MobjFlip(s)) > 6*FRACUNIT)
			P_SetObjectMomZ(t, FRACUNIT, true)
			else
			P_SetObjectMomZ(t, 6*FRACUNIT)
			end
		elseif ( ( (G_GametypeHasSpectators() or (t.eflags & MFE_UNDERWATER or (t.player.powers[pw_underwater])))
		or (t.player.sms_stompanim or t.player.sms_afterstompthok) ) )
		and not (t.player.powers[pw_sneakers] and (G_PlatformGametype() and not t.battlemodsms))
			if (t.player.sms_stompanim or t.player.sms_afterstompthok)
			P_SpawnMobj(t.x, t.y, t.z, MT_SPINDUST)
			S_StartSoundAtVolume(t, sfx_skid, 144)
			end
			S_StartSound(t, sfx_bljpw)
			P_InstaThrust(t, t.angle, FixedMul(-26*FRACUNIT, t.scale))
			if ((s.momz*P_MobjFlip(s)) > 11*FRACUNIT)
			P_SetObjectMomZ(t, FRACUNIT, true)
			else
			P_SetObjectMomZ(t, 11*FRACUNIT)
			end
		else
			S_StartSound(t, sfx_bljp)
			A_SMSquake(t, 19*FRACUNIT, 3, 255, true)
			P_InstaThrust(t, t.angle, FixedMul(-45*FRACUNIT, t.scale))
			if ((s.momz*P_MobjFlip(s)) > 18*FRACUNIT)
			P_SetObjectMomZ(t, 2*FRACUNIT, true)
			else
			P_SetObjectMomZ(t, 18*FRACUNIT)
			end
		end
local p = t.player	
			if p.powers[pw_sneakers] and not G_GametypeHasSpectators()	
				A_SMSSTOMPSMOKE(t, 24, MT_THOK, nil, nil, nil, t.color)
				P_SetObjectMomZ(t, 27*FRACUNIT, true)
				t.sneakerjcd = 4
				t.sneakerwc = true
				if (t.eflags & MFE_UNDERWATER) or t.player.powers[pw_underwater]
				t.sneakjuw = 7
				else
				t.sneakjuw = 10
				end
				t.sneakerjumpgfx = true
			end
		
		t.wthudtime = true
		t.player.sms_stompanim = 0 //This is to cancel stomping.
		t.player.sms_afterstompthok = false
		t.state = S_SMS_WALLJUMP
		t.player.sms_wallstathold = 7
		if not (t.player.cmd.forwardmove > 0)
		t.player.sms_wallturnaround = 2 //This turns you around if you're holding back.
		t.player.sms_wallstat = 62
		t.player.powers[pw_nocontrol] = $+2
		else
		t.player.sms_wallstat = 72 //After a frontal walljump, set a longer multithok-stopping timer.
		t.player.powers[pw_nocontrol] = $+3
		end
end

//Dedicated functions to start and end Mystic Super

function A_STARTMYSTICSUPER(s, var1)
if not s and s.player and (s.skin != "samus")
return end
if s.player.sms_intoship
return end
local p = s.player
		  if p.isclassic or p.isclassic == nil  //Remove or it'll bug.
		  p.isclassic = false
		  p.isclassicsms = true
		  end
	if not var1
		p.pflags = $|PF_THOKKED
		p.powers[pw_super] = 0
		p.powers[pw_nocontrol] = 24
		p.powers[pw_invulnerability] = 7777
		if p.powers[pw_sneakers]
		p.powers[pw_sneakers] = 1
		end
		if p.powers[pw_extralife]
		p.powers[pw_extralife] = 1
		end
		p.premysticscolor = s.color
		p.mysticsuper = 1
		s.momz = 0
		s.momx = 0
		s.momy = 0
		s.state = S_PLAY_SUPER_TRANS1
		S_StartSound(nil, sfx_supert)
	end
		if (skins[s.skin].normalspeed) == 36*FRACUNIT and not s.skin == "sonic"
		p.normalspeed = 59*FRACUNIT	
		else
		p.normalspeed = (skins[s.skin].normalspeed)*12/7
		end
		if ((p.charability == CA_THOK) or (p.charability == CA_HOMINGTHOK)) or s.skin == "shadow"
		s.lightspeedpermission = true
		else
		s.lightspeedpermission = nil		
		end
		if not (p.charflags & SF_MULTIABILITY) and not (p.charability == CA_FLY) and not (p.charability == CA_TWINSPIN)
		and not (p.charability == CA_TELEKINESIS) and not (p.charability == CA_SWIM) and not (p.charability == CA_HOMINGTHOK)
		p.myssmulta = true
		p.charflags = $|SF_MULTIABILITY
		end
		if not (p.charflags & SF_RUNONWATER) 
		p.myssrunow = true
		p.charflags = $|SF_RUNONWATER
		end
		p.jumpfactor = (skins[s.skin].jumpfactor)*69/51
		p.myssskin = s.skin
		P_RemoveShield(p)
			if skins[s.skin].supercolor
				if skins[s.skin].supercolor == SKINCOLOR_SUPERSILVER1 p.mysscolor = 0
				elseif skins[s.skin].supercolor == SKINCOLOR_SUPERRED1 p.mysscolor = 5
				elseif skins[s.skin].supercolor == SKINCOLOR_SUPERORANGE1 p.mysscolor = 10
				elseif skins[s.skin].supercolor == SKINCOLOR_SUPERGOLD1 p.mysscolor = 15
				elseif skins[s.skin].supercolor == SKINCOLOR_SUPERPERIDOT1 p.mysscolor = 20
				elseif skins[s.skin].supercolor == SKINCOLOR_SUPERSKY1 p.mysscolor = 25
				elseif skins[s.skin].supercolor == SKINCOLOR_SUPERPURPLE1 p.mysscolor = 30
				elseif skins[s.skin].supercolor == SKINCOLOR_SUPERRUST1 p.mysscolor = 35
				elseif skins[s.skin].supercolor == SKINCOLOR_SUPERTAN1 p.mysscolor = 40
				else p.mysscolor = 15
				end
			else
			p.mysscolor = 15 //SuperGold is the default
			end
end

function A_FAKEANALOGANGLE(p)
	   if not (p.pflags & PF_ANALOGMODE) and not p.homecamfly
local s = p.mo
	   		s.truelsmsa = s.angle
			s.truelsmsat = 30
			if (p.cmd.forwardmove > 0) and not (p.cmd.sidemove)
			return false
			elseif (p.cmd.forwardmove > 0) and (p.cmd.sidemove < 0)
			s.angle = $+ANGLE_45
			p.drawangle = s.angle
			elseif (p.cmd.forwardmove > 0) and (p.cmd.sidemove > 0)
			s.angle = $-ANGLE_45
			p.drawangle = s.angle
			elseif not (p.cmd.forwardmove) and (p.cmd.sidemove > 0)
			s.angle = $-ANGLE_90
			p.drawangle = s.angle
			p.homecamfly = 7
			elseif not (p.cmd.forwardmove) and (p.cmd.sidemove < 0)
			s.angle = $+ANGLE_90
			p.drawangle = s.angle
			p.homecamfly = 7
			elseif (p.cmd.forwardmove < 0) and (p.cmd.sidemove < 0)
			s.angle = $+ANGLE_135
			p.drawangle = s.angle
			p.homecamfly = 14
			elseif (p.cmd.forwardmove < 0) and (p.cmd.sidemove > 0)
			s.angle = $-ANGLE_135
			p.drawangle = s.angle
			p.homecamfly = 14
			elseif (p.cmd.forwardmove < 0) and not (p.cmd.sidemove)
			s.angle = $-ANGLE_180
			p.drawangle = s.angle
			p.homecamfly = 11
		//	elseif not (p.cmd.forwardmove) and not (p.cmd.sidemove)
		//	s.angle = p.drawangle
			end
			p.pflags = $ & ~PF_JUMPDOWN
			p.cmd.buttons = $ & ~BT_JUMP
			if not p.homecamfly			
			p.homecamfly = 3
			end
			return true
		end
end

function A_ENDMYSTICSUPER(s, noskinreset)
	if not (s and s.valid and s.player)
	return
	end
local p = s.player
	if p.isclassicsms //restore classic physics if they apply
	p.isclassic = nil
	p.isclassicsms = nil
	end
	if s.health
		if not P_IsObjectOnGround(s)
		s.state = S_PLAY_SPRING
		else
		s.state = S_PLAY_RUN
		end
	end
	if not (p.smsgraphix and p.smsgraphix == 2)
		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
	end
	if not noskinreset
		if p.premysticscolor	
		s.color = p.premysticscolor
			if not (p.premysticscolor >= SKINCOLOR_SUPERSILVER1)
			p.skincolor = p.premysticscolor
			else
			p.skincolor = SKINCOLOR_YELLOW
			end
		end
		if p.myssmulta
		p.myssmulta = nil
		p.charflags = $ & ~SF_MULTIABILITY
		end
		if p.myssrunow
		p.myssrunow = nil
		p.charflags = $ & ~SF_RUNONWATER
		end
		p.normalspeed = skins[s.skin].normalspeed
		p.jumpfactor = skins[s.skin].jumpfactor
	end
		s.lightspeedpermission = nil
		p.myssskin = nil
		P_SpawnShieldOrb(p)
		if P_IsObjectOnGround(s)
		s.momx = 0
		s.momy = 0
		s.momz = 0
		p.pflags = $ & ~PF_SPINNING & ~PF_STARTDASH  & ~PF_JUMPED
		s.state = S_PLAY_STND
		p.powers[pw_nocontrol] = 16
		S_StopSound(s)
		else
		s.momx = $/2
		s.momy = $/2
		s.momz = $/3
		end
		P_FlashPal(p, PAL_MIXUP, 6)
		s.tkteleportup = nil
		s.myssswim = nil
		s.myssbacd = 0
		s.tkteleport = 0
		s.noamybadamy = false
		s.metalcharge = 0
		s.metalafterimage = 0
		s.twinrefreshonce = false
		S_StartSound(s, sfx_s3k66)
		p.mysticsuper = 0
		p.hypermysticsonic = 0
end

//Because people will make that joke

function A_TOGOEVENFURTHERBEYOND(s)
	if not (s and s.valid and s.skin == "sms" and s.player)
	or s.player.hypermysticsonic
	or s.player.sms_intoship
	return
	end
	local p = s.player
		if (p.hmstransformdisable and p.hmstransformdisable == 2)
			if not (All7Emeralds(emeralds)) and not G_GametypeHasSpectators()
			CONS_Printf(p, "You currently need the 7 Chaos Emeralds to transform into HMS.")
			return
			end
		end
		if not ((p.hmstransformdisable == 1) and not G_GametypeHasSpectators())
		and not ((p.smsnoracegame and p.smsnoracegame == 2) and (gametype == GT_RACE))
		and not (p.speedbombactive or p.g2gfast4lifeactive or p.hmsrushactive or p.skillstripcv)
			if not (G_GametypeHasSpectators() and p.hmshascome)
					local ztotal = 0
					local zmaxplayers = 0
									
					for z in players.iterate
						zmaxplayers = $+1
						if z.hypermysticsonic
						ztotal = $+1 //Count them! 4 lovely emeralds!
						end
					end
					if p.hmsmlimit != nil and (ztotal >= p.hmsmlimit)
					CONS_Printf(p, "\x85"+"Server limit for Hyper Mystic Sonic players reached!\x80 ("+p.hmsmlimit+")")	
					return
					end			
					//If HMS appears, the tolerance for graphics goes down.
					
					if netgame and (players[(0)] and players[(0)].smsautographix or players[(1)] and players[(1)].smsautographix)
					 if (zmaxplayers < 4)
						for ns in players.iterate //Full steam ahead!
							if ns.smsgraphix != 0
							CONS_Printf(ns, "SMS graphics auto-adjusted to\x83 full")	
							ns.smsgraphix = 0
							end
						end
					 elseif (zmaxplayers < 5)
						for ns in players.iterate //Slow it down....
							if ns.smsgraphix != 1
							CONS_Printf(ns, "SMS graphics auto-adjusted to\x84 medium")	
							ns.smsgraphix = 1
							end
						end
					 else
						for ns in players.iterate //Busy netgame, minimum graphics!
							if ns.smsgraphix != 2
							CONS_Printf(ns, "SMS graphics auto-adjusted to\x85 minimum")	
							ns.smsgraphix = 2
							end
						end
					 end
					end
					
					
						p.hometrickanim = false
						p.pflags = $ & ~PF_STARTDASH & ~PF_SPINNING & ~PF_THOKKED
						p.prehmscolor = s.color
						p.prehmspcolor = p.skincolor
						p.hypermysticsonic = 1
						p.hmsdash = 0
						p.novafire = 0
						s.hmgodticket = false
						p.powers[pw_nocontrol] = 2
						s.boostpass = 0
						s.hmsgalaxystorm = 0
						s.hmspowerbombcam = 0
						s.state = S_HMSTRANSFORM1
						s.momx = 0
						s.momy = 0
						s.momz = 0
						p.sms_wallstat = 0
						s.hmsshieldconsume = 0
						A_SMSquake(s, 10*FRACUNIT, 22, 8022)
						P_NukeEnemies(s, s, 750*FRACUNIT)
						p.pillarblast7 = P_SpawnMobj(s.x+FixedMul(-2*FRACUNIT, cos(s.angle)), s.y+FixedMul(-2*FRACUNIT, sin(s.angle)), s.z, MT_HMSLIPILLAR)
						p.pillarblast7.scale = s.scale
						p.pillarblast7.scalespeed = 17500
						p.pillarblast7.fuse = 38
						p.pillarblast7.target = s
						p.pillarblast7.eflags = s.eflags
						A_ChangeColorAbsolute(p.pillarblast7, 0, SKINCOLOR_BONE)
						S_StartSound(nil, sfx_hypemt)
						if not p.nohmstheme
						COM_BufInsertText(p, "tunes HMS") //Otherwise it'll go back to the main stage theme after 1-up sounds.
							if s.hmsmpos
							S_ChangeMusic("HMS", true, p, 0, s.hmsmpos, 150, 150)
							elseif not s.hmsmpos
							S_ChangeMusic("HMS", true, p, 0, 0, 150, 150)
							s.hmsmpos = 1
							end
						end
					//	P_RestoreMusic(p)
						if G_GametypeHasSpectators() and not modeattacking
							P_StartQuake(15*FRACUNIT, 45)
							if mapheaderinfo[gamemap] and mapheaderinfo[gamemap].skynum
							p.hfear = mapheaderinfo[gamemap].skynum
								if not mapheaderinfo[gamemap].skynum == (21 or 22)
								P_SetupLevelSky(11)
								end
							else
							p.hfear = 1
							end
							for z in players.iterate
								z.hmshascome = p
								if z.mo and (z.mo != s) //Warn everyone
								z.mo.hmsfearmessage = 64
								end
								P_FlashPal(z, PAL_NUKE, 12)
							end
							for sector in sectors.iterate
								sector.lightlevel = ($-31)
							end
						end
			else
			CONS_Printf(p, "\x89"+"Can't transform under all this pressure!")
			end
						
		else
			CONS_Printf(p, "HMS is currently disabled.")
		end
end
//Var1 determines if you lose rings or not when untransforming! Var2 is momentum

function A_TOGOBACKTOTHEWAYYOUWERE(s, var1, var2)
	if not (s and s.valid and s.skin == "sms" and s.player)
	or not s.player.hypermysticsonic
	return
	end
	local p = s.player
			if p.hfear 
			  if G_GametypeHasSpectators()
				for sector in sectors.iterate
					sector.lightlevel = ($+31)
				end
				S_StartSound(nil, sfx_s3k66)
				P_SetupLevelSky(p.hfear)
			  end
				for z in players.iterate
					z.hmshascome = nil
					P_FlashPal(z, PAL_MIXUP, 3)	
					if not z.nohmstheme
					COM_BufInsertText(z, "tunes -default")
					P_RestoreMusic(z)
					end
				end
			end
			p.hfear = nil
			//	COM_BufInsertText(p, "tunes -default")
			if not p.nohmstheme and p.hypermysticsonic
				COM_BufInsertText(p, "tunes -default")
			end
			p.hypermysticsonic = 0
			s.rollangle = 0
			P_FlashPal(p, PAL_MIXUP, 7)
			S_StartSound(s, sfx_s3k66)
			if not p.smsdivetimer //Continue the atomdive!
				if (p.pflags & PF_STARTDASH)
				p.pflags = $ & ~PF_STARTDASH & ~PF_SPINNING
				p.dashspeed = 0
				end
				if var2
				s.momx = $/4
				s.momy = $/4
				s.momz = $/3
				else
           		P_InstaThrust(s, s.angle, 0)
				end
				if not var1
				p.powers[pw_nocontrol] = $ + 16
				end
				if not (p.powers[pw_carry] == CR_NIGHTSMODE)
				s.state = S_PLAY_FALL
				p.pflags = $ & ~PF_JUMPED
				end
			else
				s.dcadsms = true
				p.smsdivetimer = 37
				s.state = S_PLAY_ROLL
				p.panim = PA_ROLL
			end
			P_RadiusAttack(s, s, 250*FRACUNIT)
			p.pflags = $ & ~PF_GODMODE

			if p.sms_transformstate
				P_SpawnGhostMobj(s)
				if p.presmsskin
				R_SetPlayerSkin(p, p.presmsskin)
				s.skin = p.presmsskin
				COM_BufInsertText(p, "skin "+p.presmsskin)
				else
				R_SetPlayerSkin(p, "sonic")
				s.skin = "sonic"
				COM_BufInsertText(p, "skin sonic")
				end
				p.sms_transformstate = 0	
				p.ffdelaycs = 3
				if not (p.powers[pw_shield] & SH_FIREFLOWER)
				and not ((mariomode) and p.powers[pw_invulnerability])
				s.color = p.sms_originalcolor
				else
				s.color = SKINCOLOR_WHITE
				end
				p.skincolor = p.sms_originalcolor
			elseif not var1
				P_GivePlayerRings(p, -20)
			end
			
			if G_GametypeHasSpectators()
				p.rings = 1
				p.hms_drain = 1
			end
			if not (p.smsgraphix and p.smsgraphix == 2)
				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
			end
end
//Var1: Standstill untransform or not | Var2: No State Change | Var3: NoSound or Flash
function A_SMSTOSONIC(s, var1, var2, var3)
	if s and s.skin != "sms"
	or not s.player
	return
	end
local p = s.player
				p.camerascale = s.scale*5/7
				s.bhlcamtimer = 2
				if not var3
				S_StartSound(s, sfx_s3k66)
				P_FlashPal(p, PAL_MIXUP, 4)
				P_SpawnGhostMobj(s)
					if not (p.smsgraphix and p.smsgraphix == 2)
						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
					end
				end
				if not var2 and s.health
				s.state = S_PLAY_FALL
				p.pflags = $ & ~PF_JUMPED
				end
				
					if p.presmsskin
					R_SetPlayerSkin(p, p.presmsskin)
					s.skin = p.presmsskin
					COM_BufInsertText(p, "skin "+p.presmsskin)
					else
					R_SetPlayerSkin(p, "sonic")
					s.skin = "sonic"
					COM_BufInsertText(p, "skin sonic") //This is only to stop SRB2 from screwing up.
					end
					if not (p.powers[pw_shield] & SH_FIREFLOWER)
					and not ((mariomode) and p.powers[pw_invulnerability])
						if p.sms_originalcolor != nil
						s.color = p.sms_originalcolor
						p.skincolor = p.sms_originalcolor
						else
						s.color = SKINCOLOR_BLUE
						p.skincolor = SKINCOLOR_BLUE
						end
					else
						s.color = SKINCOLOR_WHITE
					end
					if var1 //Untransform on the spot.
					p.pflags = $ & ~PF_SPINNING & ~PF_STARTDASH
						if not s.battlemodsms
						P_RadiusAttack(s, s, 150*FRACUNIT)
						end
					p.powers[pw_nocontrol] = 8
					s.momx = 0
					s.momy = 0
					else
					p.powers[pw_nocontrol] = 2
					s.momx = $/2
					s.momy = $/2
					end
					if p.sms_originalcolor != nil
					p.skincolor = p.sms_originalcolor
					end
					p.sms_transformstate = 0
					
					if G_GametypeHasTeams()
						if p.ctfteam == 1
						p.sms_originalcolor = SKINCOLOR_RED
						s.color = SKINCOLOR_RED
						p.skincolor = SKINCOLOR_RED
						elseif p.ctfteam == 2
						p.sms_originalcolor = SKINCOLOR_BLUE
						s.color = SKINCOLOR_BLUE
						p.skincolor = SKINCOLOR_BLUE						
						end				
					end
end

//Mostly unused nowadays except for BlackHole and a few other cases. 
//Searching the thinker iterates is far too intensive for SRB2 in bigger maps, even when used moderately

function A_SMSFindTarget(s, var1, var2, var3)
	local looklimit = FixedMul(var1, s.scale)
	if (var2 == 9)
		for m in mobjs.iterate(mobj)
			if not (m and ((m.type == MT_RING) or (m.type == MT_COIN)) and m.health)
			continue end

			local lookrange = FixedHypot(FixedHypot(m.x-s.x, m.y-s.y), m.z-s.z)
			if (lookrange <= looklimit)
			and not (m.z > s.z+(var1))
			and not (m.z < s.z-(var1))
				s.target = m
				looklimit = lookrange
				return true
			end
		end
	elseif (var2 == 7)
	   for m in mobjs.iterate(mobj)
		if not (m and ((m.flags & MF_BOSS) or (m.type == MT_CYBRAKDEMON) or ((m.player) and (G_GametypeHasSpectators())) or (m.flags & MF_ENEMY))
		and m.health and not m.hmscombod and not (m.player and m.player.hypermysticsonic) and not (s == m)
		) then //and not (m.type == MT_GSNAPPER) and not (m.type == MT_DRAGONBOMBER) 
		continue end

		local lookrange = FixedHypot(FixedHypot(m.x-s.x, m.y-s.y), m.z-s.z)
		if (lookrange <= looklimit)
		and not (m.z > s.z+(var1/2))
		and not (m.z < s.z-(var1/2))
		and (P_CheckSight(s, m))
			s.target = m
			looklimit = lookrange

			if not var2 then
			return
			end
		end
	   end
	elseif (var2 == 25)
	   for m in mobjs.iterate(mobj)
		if not (m and ((m.flags & (MF_BOSS|MF_ENEMY)) or (m.player and (s.battlemodsms or not G_PlatformGametype()) ))
		and m.health and not m.theghoul and not ((m.player and (m.player.powers[pw_invulnerability] or m.player.powers[pw_flashing] or (s.player.ctfteam and (m.player.ctfteam == s.player.ctfteam)) )))
		and not (s == m)) then
		continue end
		if m.player and (m.player.spectator) then
		continue end

		local lookrange = FixedHypot(FixedHypot(m.x-s.x, m.y-s.y), m.z-s.z)
		if (lookrange <= looklimit)
		and not (m.z > s.z+(var1/2))
		and not (m.z < s.z-(var1/2))
		and (P_CheckSight(s, m))
			if not s.dfclosest or ( s.dfclosest and ( (FixedHypot(FixedHypot(m.x-s.x, m.y-s.y), m.z-s.z)) < s.dfclosest) )
				s.dfclosest = (FixedHypot(FixedHypot(m.x-s.x, m.y-s.y), m.z-s.z))
				s.target = m
				looklimit = lookrange
				if m.player and not var3
				m.player.dfflame = 16
				end
			end
		end
	   end
	elseif (var2 == 15)
	   for m in mobjs.iterate(mobj)
		if not (m and (((m.flags & MF_PUSHABLE) and (m.flags & MF_SOLID)) or (m.type == MT_GARGOYLE) or ((m.flags & MF_MONITOR) and m.health))
		and not (s.player.smspickup and m == s.player.smspickup) and not (s == m)) then
		continue end

		local lookrange = FixedHypot(FixedHypot(m.x-s.x, m.y-s.y), m.z-s.z)
		if (lookrange <= looklimit)
		and not (m.z > s.z+s.height)
		and not (m.z+m.height+95355 < s.z)
		and (P_CheckSight(s, m))
			if (m.flags & MF_MONITOR)
				if m.smspickupflags
				m.flags = m.smspickupflags
				m.smspickupflags = nil
				end
				m.smspickupflags = m.flags
				m.pickedupmonitor = true
				m.flags = $ & ~MF_MONITOR
				m.flags = $ & ~MF_SHOOTABLE
				s.player.smspickup = m
				m.smspickedup = true
				m.flags = $|MF_NOGRAVITY|MF_NOCLIPTHING
				s.player.sms_tossflaghold = 5
				return true
			else
				if not ( (m.type == MT_GARGOYLE) and ((m.subsector.sector.floorpic == "DSTRACK2") or (m.subsector.sector.floorpic == "DSTRACK1")) )
					if m.smspickupflags
					m.flags = m.smspickupflags
					m.smspickupflags = nil
					end
					m.smspickupflags = m.flags
					s.player.smspickup = m
					m.smspickedup = true
					m.flags = $ & ~MF_PUSHABLE
					m.flags = $ & ~MF_SOLID
					m.flags = $|MF_NOGRAVITY|MF_NOCLIPTHING|MF_NOCLIPHEIGHT
					s.player.sms_tossflaghold = 5
					return true
				end
			end
		end
	   end
	else
	   for m in mobjs.iterate(mobj)
		if not (m and ((m.flags & (MF_ENEMY|MF_BOSS)) or (m.type == MT_EGGGUARD) or ((var2 and var2 == 20) and G_GametypeHasSpectators() and m.player) or ((m.flags & MF_MONITOR and var2 and var2 == 20))  or (((m.type == MT_CYBRAKDEMON) or (m.type == MT_MINUS)) and var2 and var2 == 1)) 
		and m.health and (m.flags & MF_SHOOTABLE or (((m.type == MT_CYBRAKDEMON) or (m.type == MT_MINUS) or (m.type == MT_EGGGUARD)) and var2 and var2 == 1)) and not (m.type == MT_DETON) and not m.fusrodah and not (m.flags2 & MF2_FRET)) then
		continue end
		if (var2 and var2 == 20 and G_GametypeHasSpectators())
		var1 = var1/2
		end
		local lookrange = FixedHypot(FixedHypot(m.x-s.x, m.y-s.y), m.z-s.z)
		if (lookrange <= looklimit)
		and not (m.z > s.z+(var1/2))
		and not (m.z < s.z-(var1/2))
		and not (m == s)
		and (P_CheckSight(s, m))
			s.target = m
			looklimit = lookrange

			if not var2 then
			return
			end
		end
	   end
	end
end

addHook("TouchSpecial", function(f, a)
	if G_GametypeHasSpectators()
	and a and a.player and a.health
	and not (a.player.powers[pw_flashing] or a.player.powers[pw_super] or a.player.powers[pw_shield] == SH_ELEMENTAL)
	and f.target and f.target.player
	and not (a == f.target) //Don't hurt yourself or teammates
	and not (a.player.ctfteam and a.player.ctfteam == f.target.player.ctfteam)
		if f.target.player.hypermysticsonic
		P_DamageMobj(a, f, f.target)
		return true
		end
	else
		return true
	end
end, MT_SMSSPINFIRE)

addHook("MobjThinker", function(f)
	if (gametype == GT_COOP) and f and f.target
		P_RadiusAttack(f, f.target, FixedMul(20*FRACUNIT, f.scale))
		f.flags = $ & ~MF_SPECIAL
	end
	if P_CheckDeathPitCollide(f)
	or (f.scale < FRACUNIT/4)
	or (f.eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
	or f.extspd
		f.state = S_NULL
		return
	end
		if f.growtimer
		f.growtimer = f.growtimer-1
			if (f.growtimer >= 29)
			and not f.extrfl
				if (f.flame1)
				P_InstaThrust(f, f.angle + ANGLE_90, 10*FRACUNIT)
				else
				P_InstaThrust(f, f.angle + ANGLE_90, -10*FRACUNIT)
				end
			end
			if (f.growtimer == 29)
				P_SpawnGhostMobj(f)
				A_SetScale(f, f.scale+200000, 1)
			end
			if (f.growtimer == 28)
			and not f.extrfl
				P_SpawnGhostMobj(f)
				if (f.flame1)
				P_InstaThrust(f, f.angle+ANGLE_90, 7*FRACUNIT)
				return
				else
				P_InstaThrust(f, f.angle+ANGLE_90, -7*FRACUNIT)
				return
				end
			end
			if (f.growtimer == 27)
			and not f.extrfl
				if (f.flame1)
				P_InstaThrust(f, f.angle+ANGLE_90, 3*FRACUNIT)
				return
				else
				P_InstaThrust(f, f.angle+ANGLE_90, -3*FRACUNIT)
				return
				end
			end
			if (f.growtimer == 26)
			P_SetObjectMomZ(f, 9*FRACUNIT)
			return
			end
			if (f.growtimer < 26)
				if P_IsObjectOnGround(f)
				f.momx = 0
				f.momy = 0
				end
			end
			if (f.growtimer == 4)
			A_SetScale(f, FRACUNIT/11, 1)
				if f.spawnhmsrestflame
				f.spawnhmsrestflame2 = P_SpawnMobj(f.x, f.y, f.z, MT_HMSFLAMEREST)
					if f.target and f.spawnhmsrestflame2 and f.spawnhmsrestflame2.valid
					f.spawnhmsrestflame2.target = f.target
						if f.target and f.target.player and f.target.player.hypermysticsonic
						f.spawnhmsrestflame2.scale = f.target.scale*9/P_RandomRange(3,9)
						else
						f.spawnhmsrestflame2.scale = f.target.scale
						end
					end
				end
			end
		end		
end, MT_SMSSPINFIRE)

//Replacement for DeathPitCollide. If var1 is true, checks for SMS only and returns false if HMS.

function A_HMSCheckDeathPit(s, var1)
if var1 and s and s.player.hypermysticsonic
return false
end
	if s and P_IsObjectOnGround(s)
		if P_PlayerTouchingSectorSpecial(s.player, 1, 7) or P_PlayerTouchingSectorSpecial(s.player, 1, 6) or P_PlayerTouchingSectorSpecial(s.player, 1, 8)
			if s.subsector and s.subsector.sector
			and ( ((s.floorz == s.subsector.sector.floorheight) and not (s.eflags & MFE_VERTICALFLIP)) or ((s.eflags & MFE_VERTICALFLIP) and (s.ceilingz == s.subsector.sector.ceilingheight)) )
			return true
			elseif not s.subsector //Can't obtain info? Assume it's a death pit
			return true
			end
		end
	end
	return false
end

function A_SMSSpinFire(s, var1, var2, var3, var4)
if s.player and s.player.smsgraphix and s.player.smsgraphix == 2
return
end
	if s and not (s.eflags & MFE_TOUCHWATER)
	and s.health
		s.spdashflame = P_SpawnMobj(s.x+P_RandomRange(-7, 7)*FRACUNIT, s.y+P_RandomRange(-7, 7)*FRACUNIT, s.z+FRACUNIT, var1)
		s.spdashflame1 = P_SpawnMobj(s.x+P_RandomRange(-7, 7)*FRACUNIT, s.y+P_RandomRange(-7, 7)*FRACUNIT, s.z+FRACUNIT, var1)
local f0 = s.spdashflame
local f1 = s.spdashflame1
			if (s.eflags & MFE_VERTICALFLIP)
			and f0 and f1
			and f0.valid and f1.valid
			and not (f0.eflags & MFE_VERTICALFLIP) and not (f1.eflags & MFE_VERTICALFLIP)
				f0.flags2 = $|MF2_OBJECTFLIP
				f1.flags2 = $|MF2_OBJECTFLIP
			end
			if var4
			f0.target = var4
			else
			f0.target = s
			end
			f0.fuse = TICRATE*3
			f0.angle = s.angle+ANG2+ANG2
			f0.scale = FixedMul(var2, s.scale) //+P_RandomRange(0, 51001)
			
			f0.growtimer = 30
				if var3
				f0.extrfl = true
				else
				f0.extspd = 0
				end
			if var4
			f1.target = var4
			else
			f0.target = s
			end
			f1.flame1 = true
			f1.fuse = TICRATE*3
			f1.angle = s.angle-ANG2-ANG2
			f1.scale = FixedMul(var2, s.scale) //+P_RandomRange(0, 51001)
			f1.growtimer = 30
				if var3
				f1.extspd = var3
				else
				f1.extspd = 0
				end
				if f0
				and (var2 == 65357)
					f0.spawnhmsrestflame = true
					f1.spawnhmsrestflame = true
				end
	end
end

//Check if you're Sonic or not.

function A_SMScompatibleskin(s)
	if s and s.skin
		if ( (string.find(s.skin, "sonic") and not string.find(s.skin, "metal") and not string.find(s.skin, "mecha") and not string.find(s.skin, "hard")) ) 
		or (s.skin == "greeneyes") or (s.skin == "sunky") or (s.skin == "werehog") or (s.skin == "earless") or (s.skin == "earlessredo")
		or (s.skin == "3dson") or (s.skin == "handdrawn") or (s.skin == "pointy") or (s.skin == "sonik") or (s.skin == "bandages")
		or s.smscompatibleskin --Set player.mo.smscompatibleskin to 2 to force your character skin to be compatible with SMS!
		return true //Everyone is Sonic, and since everyone is Sonic, EVERYONE IS SMS
		end
	end
	return false
end

function A_AtomDiveAim(p)
if p.mo and A_HMSCheckDeathPit(p.mo)
or (p.smsgraphix and p.smsgraphix == 2) and (leveltime % 2 == 0)
return
end
local a = p.mo
	while p.mo
	and (a == p.mo or not P_IsObjectOnGround(a))
	and P_CheckPosition(a, a.x+14*cos(p.mo.angle), a.y+14*sin(p.mo.angle), a.z+(14*-(32678))*(P_MobjFlip(p.mo)))
	and not ((a.z > a.ceilingz) or (a.z < a.floorz))

	a = P_SpawnMobj(a.x+14*cos(p.mo.angle), a.y+14*sin(p.mo.angle), a.z+(14*-(32678))*(P_MobjFlip(p.mo)) , MT_THOK)
	a.tics = 1
	a.scale = p.mo.scale/6
		if p.smsdivetimer
		a.color = SKINCOLOR_RED
		else
		a.color = SKINCOLOR_BLUE
		end

	end
	if not p.atomdivetargetspin
	a = P_SpawnMobj(a.x, a.y, a.z, MT_ATOMDIVETARGET)
	a.scale = p.mo.scale*2
	a.target = p.mo
		if (p.mo.eflags & MFE_VERTICALFLIP)
		a.z = $-88*FRACUNIT
		a.flags2 = $|MF2_OBJECTFLIP
		end
		if p.smsdivetimer
		a.scale = p.mo.scale*4
		if (a.flags2 & MF2_OBJECTFLIP)
		a.z = $-111*FRACUNIT
		end
		a.state = S_CYBRAKDEMONTARGETRETICULE14
		p.atomdivetargetspin = 14
		a = p.adtarget
		end
	end
end

local function burngoldenshoestoacrisp(p)
	if p.lightdashenable
			if (p.lddiscount == 2) //Nice, now that's a good price!
				p.lightdashenable = 0
				S_StartSound(nil, sfx_bubbl2)
				print(p.name+" is making goldenshoes stew!")
				P_SpawnMobj(p.mo.x+FixedMul(80*FRACUNIT, cos(p.mo.angle)), p.mo.y+FixedMul(80*FRACUNIT, sin(p.mo.angle)), p.mo.z, MT_HMSFLAMEREST)
			elseif (p.lddiscount == 1)
				S_StartSound(nil, sfx_s3k43)
				p.lightdashenable = 0
				print(p.name+" just scorched their shoes alive!")
				P_SpawnMobj(p.mo.x+FixedMul(80*FRACUNIT, cos(p.mo.angle)), p.mo.y+FixedMul(80*FRACUNIT, sin(p.mo.angle)), p.mo.z, MT_BOSSEXPLODE)
				P_SpawnMobj(p.mo.x+FixedMul(80*FRACUNIT, cos(p.mo.angle)), p.mo.y+FixedMul(40*FRACUNIT, sin(p.mo.angle)), p.mo.z, MT_BOSSEXPLODE)
				P_SpawnMobj(p.mo.x+FixedMul(40*FRACUNIT, cos(p.mo.angle)), p.mo.y+FixedMul(80*FRACUNIT, sin(p.mo.angle)), p.mo.z, MT_BOSSEXPLODE)
			elseif (p.lddiscount == 0)
				S_StartSound(nil, sfx_koopfr)
				p.lightdashenable = 0
				print(p.name+" brutally murdered their boots!")
				P_SpawnMobj(p.mo.x, p.mo.y, p.mo.z, MT_CYBRAKDEMON_VILE_EXPLOSION)
				P_SpawnMobj(p.mo.x+FixedMul(30*FRACUNIT, cos(p.mo.angle)), p.mo.y+FixedMul(30*FRACUNIT, sin(p.mo.angle)), p.mo.z, MT_CYBRAKDEMON_VILE_EXPLOSION)
				P_SpawnMobj(p.mo.x+FixedMul(30*FRACUNIT, cos(p.mo.angle)), p.mo.y+FixedMul(30*FRACUNIT, sin(p.mo.angle)), p.mo.z, MT_CYBRAKDEMON_VILE_EXPLOSION)
			else
				p.lightdashenable = 0
				S_StartSound(nil, sfx_mario7)
				print(p.name+" burned their fancy kicks!")
				P_SpawnMobj(p.mo.x+FixedMul(10*FRACUNIT, cos(p.mo.angle)), p.mo.y+FixedMul(10*FRACUNIT, sin(p.mo.angle)), p.mo.z, MT_CYBRAKDEMON_VILE_EXPLOSION)
			end
	else
	CONS_Printf(p, "You can't burn what you don't have.")
	end
end

COM_AddCommand("smsorders", function(p, v2, v3)
	if (v2 == "GlItChYdEbUgThRoW")
	and (p == server or p == admin)
		if p.glitchydebugthrow
		S_StartSound(nil, sfx_thok)
				print("\x85"+"SMS' glitchy debug throw has now been turned off")
				for z in players.iterate
				z.glitchydebugthrow = nil
				end
		else
		S_StartSound(nil, sfx_thok)
			print("\x87"+"Glitchy debug throw activated. SMS can now pick up"+"\x85"+" anything with collision."+"\x84"+" Use at your own risk, expect issues.")
			for z in players.iterate
			z.glitchydebugthrow = true
			end
		end
		return
	end
	if not G_PlatformGametype() or p.mo.battlemodsms
	CONS_Printf(p, "Sorry, shop's closed during competitive gametypes!")
	return end
	if not p.mo or not (p.mo and p.mo.skin == "sms")
	CONS_Printf(p, "You can only do this if you're SMS and alive.")
	return end
	if (p.rings < 25)
	CONS_Printf(p, "You'll need at least 25 rings to buy anything.")
	return end
	if (p.powers[pw_carry] == CR_NIGHTSMODE) //You can't use it in NiGHTS mode, so don't buy it.
	CONS_Printf(p, "Not available in NiGHTS modes!")
	return end

	if ((v2 == "goldenshoes") or (v2 == "GOLDENSHOES") or (v2 == "GoldenShoes")) or not v2
		if p.lightdashenable
		CONS_Printf(p, "You already have these!")
		return end
			if (p.lddiscount < 3)
				P_GivePlayerRings(p, -25)
				p.lightdashenable = 1
				S_StartSound(nil, sfx_nxitem)
				print(p.name+" just bought lightdash shoes!")
				CONS_Printf(p, "\x82You unlocked the lightdash!(Custom1) You can also charge the lightspeed attack!")
				return
			end
			if (p.lddiscount > 2) //Discount! Lucky you!
				P_GivePlayerRings(p, -15)
				p.lightdashenable = 1
				S_StartSound(nil, sfx_nxdone)
				print(p.name+" just got a great deal on some lightdash sneakers!")
				CONS_Printf(p, "\x82You unlocked the lightdash!(Custom1) You can also charge the lightspeed attack!")
				return
			end
	else
		return
	end
end)

COM_AddCommand("burnsmsorders", burngoldenshoestoacrisp, 0)

COM_AddCommand("hms", function(p, onoff)
	if ((onoff == "on") or (onoff == "yes") or (onoff == "1") or (onoff == "ON") or (onoff == "YES")) and (p == server or p == admin)
		S_StartSound(nil, sfx_gravch)
		for z in players.iterate
			z.hmstransformdisable = 0
			CONS_Printf(z, "The Hyper Mystic transformation has been enabled.")
		end
	elseif (((onoff == "off") or (onoff == "no") or (onoff == "0") or (onoff == "OFF") or (onoff == "NO")) and (p == server or p == admin))
		S_StartSound(nil, sfx_ngskid)
		for z in players.iterate
			z.hmstransformdisable = 1
			CONS_Printf(z, "The Hyper Mystic transformation has been disabled.")
		end
	elseif not (p == server or p == admin)
		CONS_Printf(p, "You won't be able to access this one without admin powers.")
	else
		CONS_Printf(p, "HMS ON/OFF. Manual Hyper Mystic transformations can be disabled!")
	end
end)

COM_AddCommand("smsrace", function(p, onoff)
	if ((onoff == "on") or (onoff == "yes") or (onoff == "1") or (onoff == "ON") or (onoff == "YES"))
	and (p == server or p == admin)
		for sbr in players.iterate
			sbr.smsnoracegame = 0
			S_StartSound(nil, sfx_sarb)
			CONS_Printf(sbr, "SMS has been enabled in race.")
		end
	elseif ((onoff == "off") or (onoff == "no") or (onoff == "0") or (onoff == "OFF") or (onoff == "NO"))
	and (p == server or p == admin)
		for sbr in players.iterate
			sbr.smsnoracegame = 1
			CONS_Printf(sbr, "SMS has been disabled in race.(and tag)")
			if (sbr.mo and sbr.mo.skin == "sms")
				S_StartSound(sbr.mo, sfx_altdi2)
			end
		end
	elseif ((onoff == "super") or (onoff == "all") or (onoff == "SUPER") or (onoff == "ALL"))
	and (p == server or p == admin)
		for sbr in players.iterate
			sbr.smsnoracegame = 2
			S_StartSound(nil, sfx_s3k9f)
			CONS_Printf(sbr, "Let's step up the pace! Now EVERYONE can transform at the startline!")
		end
	else
		CONS_Printf(p, "SMSRACE ON/OFF/SUPER. Will SMS be allowed in races, or not? The SUPER option transforms everyone to compensate for SMS' advantage!")
	end

	if not (p == server or p == admin)
	CONS_Printf(p, "You won't be able to access this one without admin powers.")
	end
end)

COM_AddCommand("nosmsquakes", function(p)
	if not p.nosmsquakespls
		p.nosmsquakespls = true
		CONS_Printf(p, "\x89"+"Most of the SMS quake effects generated are now turned off.")
	else
		if p.mo
		p.mo.smsqtime = 0
		end
		p.nosmsquakespls = nil
		CONS_Printf(p, "\x83"+"All of the SMS quake effects generated are now restored!")
	end
end)
COM_AddCommand("smsstats", function(p, onoff)
	if (((onoff == "on") or (onoff == "yes") or (onoff == "1") or (onoff == "ON") or (onoff == "YES"))
	and not p.smsboostmeter)
		p.smsboostmeter = true
		CONS_Printf(p, "Check out your stats!")
			if p.mo
			S_StartSound(p.mo, sfx_smach)
			end
	elseif (((onoff == "off") or (onoff == "no") or (onoff == "0") or (onoff == "OFF") or (onoff == "NO"))
	and p.smsboostmeter)
		p.smsboostmeter = false
		CONS_Printf(p, "SMS stats deactivated.")
			if p.mo
			S_StartSound(p.mo, sfx_skid)
			end
	else
		CONS_Printf(p, "SMSstats ON/OFF. Check out some helpfull stats.")
	end
end)

COM_AddCommand("smscontrols", function(p, onoff)
if onoff == "lightdash" or onoff == "Lightdash" or onoff == "LIGHTDASH" //Extra feature for Motdspork I didn't want to clog the SMSreborn menu with.
	if p.mo
	S_StartSound(p.mo, sfx_appear, p)
	end
	if not p.smsldtf
	p.smsldtf = true
	CONS_Printf(p, "\x84"+"The Lightdash is now restricted to Toss-Flag")
	return
	else
	p.smsldtf = false
	CONS_Printf(p, "\x83"+"The Lightdash is now available to Toss-Flag and Custom1")
	return
	end
end
	if not p.smstutorial
		p.smstutorial = true
		CONS_Printf(p, "\x82SMS control-aid is now active.")
	else
		p.smstutorial = false
		CONS_Printf(p, "\x83The training wheels are off!")
	end
	if p.mo
	S_StartSound(p.mo, sfx_appear, p)
	end
end)

COM_AddCommand("smsmenu", function(p)
	if p.sms_intoship
		CONS_Printf(p, "You're already in the menu.")
		return
	end
	if p.mo and p.mo.health and not p.spectator
		if not p.speed and P_IsObjectOnGround(p.mo) and not (p.pflags & PF_SPINNING)
		and not p.mo.momx and not p.mo.momy and not p.powers[pw_carry]
		or p.mo.lemmego or p.mo.iampickedupbysmshelp //Let people escape SMS' grasp.
			p.sms_shipready = 2
			p.sms_intoship = 35
			p.firstsmsshipin = true
		else
		CONS_Printf(p, "Sit still first.")
		end
	else
		CONS_Printf(p, "Exist properly first.")
	end
end)
 
//Simple function to check SMS' color
rawset(_G, "SMSisyellow", function (s, var1)
	if ((s.color >= SKINCOLOR_SUPERGOLD1 and s.color <= SKINCOLOR_SUPERGOLD5)
	or (s.color >= SKINCOLOR_SMS1R and s.color <= SKINCOLOR_MYSTICAL5)
	or s.color == SKINCOLOR_YELLOW or s.color == 0)
	return true
	else
	return false
	end
end) 

--Give Kirby extra abilities depending on SMS' projectile

if not (kirbyabilitytable)
	rawset(_G, "kirbyabilitytable", {})
end
kirbyabilitytable[MT_HMSNOVABLAST] = 12 //Screaming
kirbyabilitytable[MT_SMMK] = -1 //Tornado
kirbyabilitytable[MT_HMSLIGHTNING1] = 5 //Spark
kirbyabilitytable[MT_SPINFIRE] = 1 //Fire
kirbyabilitytable[MT_HMS_NAPALM_FLAMES] = 1
kirbyabilitytable[MT_HMSFLAMEREST] = 1
kirbyabilitytable[MT_HMSFIREBLAST] = 1
kirbyabilitytable[MT_SMSFIREBLAST] = 1
kirbyabilitytable["sms"] = -8