freeslot("sfx_sarb", "sfx_spld", "MT_RADIALBOOST", "MT_SMSSPEEDSPARKLE", "MT_SMSSPARKLESPAWN", "MT_HMSWAVEAURA", "MT_SMSSILVERRING", "MT_SSXA", "MT_SMSECHECK", "MT_SMSSOUNDOBJ", "MT_SMSRGORE", "MT_SMSRGORESPAWN", "sfx_gentrg", "sfx_harrg1", "sfx_harrg2", "sfx_harrg3")
freeslot("sfx_stst", "MT_SMSSTOMPLINE", "MT_HMSSTOMPEXPLODE", "MT_BURSTLIGHT", "MT_BURSTWAVE", "MT_SMMK", "sfx_bljp", "sfx_bljpw", "MT_SMSTSPARK", "MT_SMSSPINFIRE", "MT_SMSSTEAM", "MT_RVGMISSILE", "MT_THEMYSTICEMERALD")
freeslot("sfx_smex", "sfx_bkhl", "sfx_smach", "MT_SMSFIREBLAST", "MT_HMSFIREBLAST", "MT_HMSFLAMEREST", "MT_HMS_NAPALM_FLAMES", "MT_HMSNOVABLAST", "MT_HMSNOVABLASTHB",  "MT_HMSNOVAWAVE", "MT_HMSBLACKHOLE", "sfx_cmph", "sfx_hypemt", "sfx_machw", "sfx_machwb", "sfx_machwh", "sfx_smsdr")
freeslot("SPR_SMSG", "MT_SMSAURATRAIL", "MT_SMSSPDTHOK", "MT_SMSBLINDDASHCHARGE", "MT_SMSAIRBOOST", "MT_SMSGROUNDBOOST", "MT_SMSWALLJUMP", "MT_SMSSPRINTLINE", "MT_SMSBOOSTAURA", "MT_HMSRISEAURA", "MT_HMSSTOMPAURA", "MT_SMSSWAVE", "MT_HMSGAX", "MT_HMSGAXA", "MT_HMSGAXHB", "MT_HMSGAXT")
freeslot("sfx_hmsfly", "MT_HMSWARPPOINT", "MT_HMSWARPPOINT2", "MT_HMSWARPPOINTRETURN", "MT_HMSLIPILLAR", "MT_POWERSHARE", "MT_SMSPOWERAURA", "MT_SMSHOMINGTAURA", "MT_SMSBLINDDASH", "MT_SMSHOMING", "MT_HMSLIGHTNING1", "MT_HMSLIGHTNING2", "MT_GOLDENSHINE")
freeslot("sfx_sdodge", "sfx_sswip", "sfx_nuexp", "sfx_pwbmb", "sfx_nerf", "MT_CMPHRADIUS", "MT_SMSDIVEBOMB", "MT_ATOMDIVETARGET", "MT_SMSPOWERBOMB", "MT_HMSPOWERBOMB", "MT_HMSPBC", "MT_CMPHTRACKER", "MT_SMSTHROWTRACKER",  "MT_SMSDUMMYTRACKER", "MT_ATOMDIVEPOP")
freeslot("sfx_smsmmi", "sfx_smsmmp", "sfx_smsmmf", "sfx_smsmms", "sfx_hmsnob", "sfx_hmsnof", "sfx_smsrbt", "sfx_hmsgax", "sfx_smscrt", "sfx_smscr2")
freeslot("sfx_smsha1", "sfx_smsha2", "sfx_smsha3", "sfx_smsha4", "sfx_smsha5")

//2014: I have no idea what I'm doing - Let's Lua!
//EDIT-2019: Hey dataminer! Incase you're reading this to try and learn Lua, I suggest looking elsewhere first.
//I learned how to script WHILE making this, so alot of this is redundant, excessive, and/or terribly inefficient.
//Even the comments may be outdated and have no context anymore. Venture at your own risk!
-- GoldenShine AKA Super Mystic Sonic

local function BattleModCheck(s)
	if gametype == GT_BATTLE or gametype == GT_CP 
	or gametype == GT_ARENA or gametype == GT_SURVIVAL
	or gametype == GT_TEAMBATTLE or gametype == GT_TEAMCP or gametype == GT_BATTLECTF  or gametype == GT_TEAMARENA or gametype == GT_TEAMSURVIVAL
	or gametype == GT_DIAMOND or gametype == GT_TEAMDIAMOND or gametype == GT_EGGROBOTAG
	return true
	else
	return false
	end
end

addHook("MobjSpawn", function(s)
	if BattleModCheck(s) //Just set this here so we don't have to check every frame
	s.battlemodsms = true
	elseif s.player
	s.player.smssonicbattle = nil
	end
	s.sprst = true
	s.mssprst = true
end, MT_PLAYER)

addHook("PlayerSpawn", function(p) //Never spawn in a custom transformation!
	p.hypermysticsonic = 0
	if p.mysticsuper and p.mo
	A_ENDMYSTICSUPER(p.mo)
	end
end)

local function SetUpSMSreborn(p)
local s = p.mo --Setup alot of main variables.
		p.sweepangle = 0
		p.smsnobmgame = 2
		p.srgorelvl = 0
		p.sms_shipready = 0
		p.smsrotatespikeball3 = 0
		p.smsrotatespikeball4 = 0
		p.sms_justuncurled = 0
		p.smsmeleebutton = 0
		p.sms_dodgetap = 0
		p.sms_dodging = 0
		p.sms_ringburst = 0
		p.sms_ringburstfly = 0
		p.sms_ringburstready = 0
		p.sms_comethaymaker = 0
		p.fusrodah = 0
		p.warpedtoguy = 0
		p.hmsdash = 0
		p.hmswarpcooldown = 0
		p.hms_drain = 0
		p.hms_flamehold = 0
		p.hms_explosion = 0
		p.hmstransformdisable = 0
		p.hypermysticsonic = 0
		p.transformdown = 0
		p.sms_flamedelay = 0
		p.sms_flamebuttonhold = 0
		p.novafire = 0
		p.sms_spinuc = 0
		p.sms_runspinboost = 0
		p.sms_doubleblinddash = 0
		p.selectcooldown = 0
		p.sms_ringburstfalltimer = 0
		p.hmsblackhole = 0
		p.sms_ringburstdrain = 0
		p.sms_wallstat = 0
		p.lddiscount = 1
		p.lightdashenable = 0
		p.smsrdash = 0
		p.lightdashstart = 0
		p.elauracolors = 0
		p.spinhold = 0
		p.weaponprevhold = 0
		p.sms_truesms = 0
		p.transformstatecolors = 0
		p.lightspeedchain = 0
		p.mysticsuper = 0
		p.mslightspeedattack = 0
		p.sms_tauntcooldown = 0
		p.sms_transformstate = 0
		p.sms_sontransform = 0
		p.sms_wallstat = 0
		p.sms_wallturnaround = 0
		p.sms_jumphold = 0
		p.sms_advfall = 0
		p.sms_stompanim = 0
		p.sms_afterstompthok = false
		p.smsmeleebutton = 0
		p.smsmeleebutton2 = 0
		p.hms_stompbreak = 0
		p.sms_breakwalls = 0
		p.sms_watergrind = 0
		p.sms_boostlevel = 0
		p.sms_boostdrain = 0
		p.mxscap = 1
		p.sms_addboostlevel = false
		p.sms_addsuperboostlevel = false
		p.sms_readyairboost = 0
		p.sms_tapnothold = 0 		
		p.sms_didairboost = 0
		p.smsdontgrabme = 0
		p.autoc1mom = 2
		p.hmsmlimit = 1
			if p.skincolor and not (p.mo and p.mo.skin == "sms")
			p.sms_originalcolor = p.skincolor
			end
			if p.name //Paranoia.
				if (p.ctfteam == 1)
				p.ctfnamecolor = "\x85"+p.name+"\x80"
				elseif (p.ctfteam == 2)
				p.ctfnamecolor = "\x84"+p.name+"\x80"
				else
				p.ctfnamecolor = p.name
				end
			end
			if netgame
			p.smsautographix = true
			end
				if io --load savefile
				local file = io.openlocal("client/smsrebornsettings22.dat")
					if file 
					local code = file:read("*a")
						if code ~= nil and not (string.find(code, ";"))
						COM_BufInsertText(p, "SMSrebornautoconfig "+code)
						end
					file:close()
					end
				end
				if not p.didsmsautoconfig
					if netgame and (gametype != GT_COOP)
					A_setSMSspecialcolors(s, P_RandomRange(2,22))
					p.smsfirstcolor = true
					end
				end
			if p.bot
			p.smsdontgrabme = 2
			end		
		p.smsrebornadded = true
end

local function SetUpSMSrebornJoin(p)
local s = p.mo
	if netgame and (p != server) and (players[(0)] and (players[(0)].smsautographix)) // or players[(1)].smsautographix)
	local zmaxplayers = 0
		for z in players.iterate
		zmaxplayers = $+1
		end
					if (zmaxplayers < 5)
						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 < 7)
						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
			if io --load savefile
				local file = io.openlocal("client/smsrebornsettings22.dat")
				if file
				local code = file:read("*a")
					if code ~= nil and not (string.find(code, ";"))
					COM_BufInsertText(p, "SMSrebornautoconfig "+code)
					end
				file:close()
				end
			end
			if not p.didsmsautoconfig
				if netgame and (gametype != GT_COOP)
				CONS_Printf(p, "\x85"+"No saved SMSreborn options present! Picking random colorscheme for SMS...")
				A_setSMSspecialcolors(s, P_RandomRange(2,26))
				p.smsfirstcolor = true
				end
			end
			
			CONS_Printf(p, "\x82"+"----------"+"\x85"+"==============="+"\x82"+"------------"+"\n")
			COM_BufInsertText(p, "exec SMSreborn.cfg")
			CONS_Printf(p, "\n"+"\x82"+"Super Mystic Sonic Reborn [SRB2 2.2] -"+"\x80"+" By Golden Shine"+"\n")
			if (p == server)
			p.sms_joinsync = true
			elseif players[(0)]
			p.smsautographix = players[(0)].smsautographix
			p.hmsmlimit = players[(0)].hmsmlimit
			p.smstransformonly = players[(0)].smstransformonly
			p.hmsmlimit = players[(0)].hmsmlimit
			p.hmstransformdisable = players[(0)].hmstransformdisable		
			p.powersharerestrict =  players[(0)].powersharerestrict		
			p.smsgraphix = players[(0)].smsgraphix
			p.smsnoracegame = players[(0)].smsnoracegame	
			p.smsnomatchgame = players[(0)].smsnomatchgame		
			p.smsnobmgame = players[(0)].smsnobmgame		
			p.smsnomsspawn = players[(0)].smsnomsspawn
			p.nosmscolorspls = players[(0)].nosmscolorspls
			p.glitchydebugthrow = players[(0)].glitchydebugthrow
			elseif players[(1)]
			p.smsautographix = players[(1)].smsautographix
			p.hmsmlimit = players[(1)].hmsmlimit
			p.smstransformonly = players[(1)].smstransformonly
			p.hmsmlimit = players[(1)].hmsmlimit
			p.hmstransformdisable = players[(1)].hmstransformdisable		
			p.powersharerestrict =  players[(1)].powersharerestrict		
			p.smsgraphix = players[(1)].smsgraphix
			p.smsnoracegame = players[(1)].smsnoracegame	
			p.smsnomatchgame = players[(1)].smsnomatchgame		
			p.smsnobmgame = players[(1)].smsnobmgame		
			p.smsnomsspawn = players[(1)].smsnomsspawn
			p.nosmscolorspls = players[(1)].nosmscolorspls
			p.glitchydebugthrow = players[(1)].glitchydebugthrow
			end
				if BattleModCheck(s) //Set this here too.
				s.battlemodsms = true
				elseif s.player
				s.player.smssonicbattle = nil
				end
				if p.bot
				p.smsdontgrabme = 2
				end
			p.sms_joinsync = true
			
			if p.smstransformonly and (s.skin == "sms") and not p.sms_transformstate
				A_SMSTOSONIC(s, nil, true, true) //Cancel the mobjthinker if switching to Sonic or your stats will mess up.
				return true
			else
				return nil
			end
end

local function SetUpSMSrebornmo(p)
local s = p.mo
			if p.bot
			p.smsdontgrabme = 2
			end
			if (p.pflags & PF_GODMODE) and p.hmsgodmode
			p.pflags = $ & ~PF_GODMODE
			p.hmsgodmode = false
			end
			if p.smschangedcamera
			s.bhlcamtimer = 0
			p.camerascale = FRACUNIT
			p.smschangedcamera = nil
			end	
			if mapheaderinfo[gamemap] 
			 if mapheaderinfo[gamemap].startrings and not p.hmsrushactive
			 s.mssprst = false
				if mapheaderinfo[gamemap].bonustype == 1
				s.smsvsboss = mapheaderinfo[gamemap].startrings
				end
				if s.skin == "sms" and p.rings and not p.sms_transformstate //Less rings to discourage flamespam
				p.rings = (mapheaderinfo[gamemap].startrings)/2
				end
			 end
			 if (mapheaderinfo[gamemap].typeoflevel >= 1025)
			 s.mssprst = false
			 end
			end
			if p.sms_intoship //Don't start off with the menu.
			p.sms_intoship = 0
			p.smshudappearanim = 0
			p.accelstart = skins[s.skin].accelstart
			p.pflags = $|PF_USEDOWN & ~PF_INVIS & ~PF_GODMODE & ~PF_FORCESTRAFE & ~PF_STARTDASH & ~PF_SPINNING
			s.flags2 = $ & ~MF2_SHADOW
			end
		p.sms_ringburstfly = 0
		p.sms_ringburst = 0
		p.sms_ringburstready = 0
		p.sms_ringburstfalltimer = 0
		p.sms_ringburstdrain = 0
		p.sms_comethaymaker = 0
		p.cmphdodge = 0
		p.fusrodah = 0
		p.sms_dodging = 0
		p.footsweep01 = 0
		p.footsweep02 = 0
		p.footsweep03 = 0
		p.smsdivetimer = 0
		p.smsdivefloat = 0
		p.smsdivedelay = 0
		p.smsatomicdivefail = 0
		p.smsrotatespikeball3 = 0
		p.smsrotatespikeball4 = 0
		p.sms_justuncurled = 0
		p.sms_dodgetap = 0
		p.sms_flamedelay = 0
		p.starthmscombo = 0
		p.sms_spinuc = 0
		p.sms_runspinboost = 0
		p.sms_doubleblinddash = 0
		p.sms_ringburstdrain = 0
		p.sms_wallstat = 0
		p.hms_instamovew = 0
		p.lightdashenable = 0
		p.smsrdash = 0
		p.lightdashstart = 0
		p.lightspeedchain = 0
		p.mysticsuper = 0
		p.mslightspeedattack = 0
		p.sms_tauntcooldown = 0
		p.sms_wallstat = 0
		p.sms_wallturnaround = 0
		p.sms_advfall = 0
		p.sms_stompanim = 0
		p.sms_afterstompthok = false
		p.sms_watergrind = 0
		p.sms_boostlevel = 0
		p.sms_boostdrain = 0		
		p.sms_didairboost = 0
		p.hmswarn = 0
		p.smsrnm = 0
		p.hfear = 0
		p.hmspanic = 0
		p.mxscap = 1
		p.smsrebornadded = true
		p.smssc = false
		p.smsex = false
		p.smsgre = false
		p.smsat = false
		p.smsra = false
		p.smsin = false
		p.smspickup = nil
		s.smsgbs = 0
		s.hmsgalaxystorm = 0
		s.smsdropdash = false
		s.lastcaptureamountsms = 0
		s.lastcaptureamounthms = 0
		s.smsmsdelay = true
		s.cmphdelayjump = 0
		if s.mssprst and leveltime and not multiplayer
		s.mssprst = false
		end
		s.hmspowerbombcam = 0
		s.smsflagrgpermission = 0
		s.smsflagrg = 0
		s.eyesareuponyou = nil
		s.sprst = nil
		s.hmscombod = nil
		s.gravbu = nil
end

local function SetUpSMSrebornmo2(p)
local s = p.mo
				p.spawnsmsship = true
				for m in mobjs.iterate(mobjs)
					if m and m.valid and ((m.flags and (m.flags & MF_BOSS)) or (m.type == MT_METALSONIC_RACE)) and m.health
						if ( (FixedHypot(m.x-s.x, m.y-s.y)) <= 6000*FRACUNIT)
						p.spawnsmsship = false
						end
					end
				end
				if s and s.subsector and s.subsector.sector and ((s.subsector.sector.ceilingpic == "PIT" and s.subsector.sector.floorpic == "PIT" and s.subsector.sector.lightlevel < 64 and not (sectors[200] or sectors[205] or sectors[210] or sectors[208])) or (gamemap == 103 and s.subsector.sector.lightlevel == 0) or (gamemap == 40 and s.subsector.sector.floorheight == -1024*FRACUNIT))
				s.smshudgimmick = true
				end
				if not p.smsnomsspawn and ((p.spawnsmsship and multiplayer) or (p.spawnsmsship and (s.skin == "sms" or A_SMScompatibleskin(s)))) and not s.smshudgimmick and not p.powers[pw_carry]
					if players[(0)] and p == players[(0)] and not (players[(1)] and players[(1)].smsssp and players[(1)].smsssp.valid)
						if not (p.smsssp and p.smsssp.valid)
						p.smsssp = P_SpawnMobj(s.x, s.y, s.z+24*FRACUNIT, MT_THEMYSTICEMERALD)
						p.smsssp.tracer = s
						end
					elseif players[(0)] and players[(0)].mo == nil and p == players[(1)]
					and not (players[(0)] and players[(0)].smsssp and players[(0)].smsssp.valid)
						if not (p.smsssp and p.smsssp.valid)
						p.smsssp = P_SpawnMobj(s.x, s.y, s.z+24*FRACUNIT, MT_THEMYSTICEMERALD)
						p.smsssp.tracer = s
						end
					end
				end
				p.spawnsmsship = false
				s.mssprst = false
end


//Then let's go into the meat of things. The MobjThinker! Because who needs PlayerThink?

addHook("MobjThinker", function(s)
if not s.player
return end
	local p = s.player
		if p.sweepangle == nil
		SetUpSMSreborn(p) --Set up SMS' variables for the first time
		end
		if (p.sms_joinsync == nil) and s
			if SetUpSMSrebornJoin(p) --Whenever a player starts a game, joining netgame or not.
			return --If it's true, you were switched to Sonic, so stop the mobjthinker here.
			end
		end
		if s and s.sprst
		SetUpSMSrebornmo(p) --Whenever a player's mo spawns.
		end	
		if s and s.mssprst and not ((gametype == GT_TAG) or (gametype == GT_HIDEANDSEEK) or (p.powers[pw_carry] == CR_NIGHTSMODE))
		SetUpSMSrebornmo2(p) --Secondary mo spawning function. (For Mystic Emerald)
		end
		
		if not p.hypermysticsonic
			if p.prehmscolor
			s.color = p.prehmscolor
			p.skincolor = p.prehmspcolor
			end
			p.prehmscolor = nil
			p.prehmspcolor = nil
		end
		if p.sms_wallstathold
		p.sms_wallstathold = $-1
			if s and (s.skin == "sms")
			p.pflags = $|PF_JUMPDOWN & ~PF_STARTJUMP
			end
		end
		if p.smsgriefw
		p.smsgriefw = $-1
		end
		if s
			if s.smslsacheck //Here starts the era of the thousand timers!
			s.smslsacheck = $-1
				if not s.smslsacheck
				s.lsaclosest = nil
				s.lsatarget = nil
				end
			end
			if s.smsframejump
			s.smsframejump = $-1
			end
			if s.lsaringdebt
			s.lsaringdebt = $-1
			end
			if s.smsldcheck
			s.smsldcheck = $-1
				if not s.smsldcheck and not (s.state == S_SMS_LIGHTDASH)
				s.smsrdash = nil
				s.lastldrx = 0
				s.lastldry = 0
				s.ldclosest = nil
				end
			end
			if s.smshmcheck
			s.smshmcheck = $-1
				if not s.smshmcheck 
				s.cmphtarget = nil
				s.cmphclosest = nil
				end
			end
			if s.smscompatibleskin
			s.smscompatibleskin = $-1
			end
			if s.smslsaret
			s.smslsaret = $-1
			end
			if s.smsldret
			s.smsldret = $-1
			end
			if s.smscmphret
			s.smscmphret = $-1
			end
			if s.smspkuret
			s.smspkuret = $-1
			end				
			if s.readyforonemoreplant
			s.readyforonemoreplant = $-1
			end
			if s.specialhmscarry
			s.specialhmscarry = $-1
			end
			if p.cmphspamreduce
			p.cmphspamreduce = $-1
			end
			if s.truelsmsat
			s.truelsmsat = $-1
				if (p.pflags & PF_JUMPED)
				s.truelsmsat = 0
				end
			end
			if s.hmsrunquake
				if not (s.smssoundobj5 and s.smssoundobj5.valid and s.smssoundobj5.health)
						s.smssoundobj5 = P_SpawnMobj(s.x, s.y, s.z, MT_SMSSOUNDOBJ)
						s.smssoundobj5.master = s
						s.smssoundobj5.health = 1
						S_StartSound(s.smssoundobj5, sfx_cdfm42)
						s.smssoundobj5.smsquaketim = 4
				elseif (s.smssoundobj5 and s.smssoundobj5.valid and s.smssoundobj5.health and s.smssoundobj5.smsquaketim)
						s.smssoundobj5.smsquakerefresh = true
				end	
			s.hmsrunquake = $-1
			end
			if s.hmsmwh 
				if not (s.smssoundobj2 and s.smssoundobj2.valid and s.smssoundobj2.health)
					if (s.smssoundobj3 and s.smssoundobj3.valid and s.smssoundobj3.smsmwtim)				
							s.smssoundobj3.state = S_NULL
					end
					s.smssoundobj2 = P_SpawnMobj(s.x, s.y, s.z, MT_SMSSOUNDOBJ)
					s.smssoundobj2.master = s
					s.smssoundobj2.health = 1
					S_StartSound(s.smssoundobj2, sfx_machwh)
					s.smssoundobj2.smsmwhtim = 51 //74 for normal
				end
			
			s.hmsmwh = $-1
			end
			if s.hmsspinpass
				if not p.hypermysticsonic or (p.hypermysticsonic and p.hypermysticsonic < 5)
				or P_IsObjectOnGround(s)
				or p.hmsdash and (p.speed > FixedMul(230*FRACUNIT, s.scale))
				or (p.pflags & (PF_STARTDASH)) or p.powers[pw_carry] or (s.state == S_HMSBLACKHOLE) or (p.novafire > 37)
				or p.smsdivetimer or s.momz == 0
				or p.hmswarpcooldown
				or p.starthmscombo
				s.hmsspinpass = 0
				end
			end
			if s.hmsroflstomped and (s.rollangle == ANGLE_180)
				if not p.hms_stompbreak or not (p.cmd.buttons & BT_CUSTOM2)
					if s.hmsroflstompcd == nil
					s.hmsroflstompcd = 1					
					else
					s.hmsroflstompcd = $+1
					end
				end
				if not p.hypermysticsonic or (p.hypermysticsonic and p.hypermysticsonic < 5)
				or P_IsObjectOnGround(s) or (s.hmsroflstompcd and (s.hmsroflstompcd > 7)) or s.airboostroll
				or p.hmsdash and (p.speed > FixedMul(230*FRACUNIT, s.scale)) or s.hms_jumprisen
				or (p.pflags & (PF_STARTDASH)) or p.powers[pw_carry] or (s.state == S_HMSBLACKHOLE) or (p.novafire and p.novafire > 37)
				or p.smsdivetimer or s.momz == 0 or (s.state == S_PLAY_PAIN and p.powers[pw_nocontrol] == 2)
				or p.hmswarpcooldown
				or p.starthmscombo
				s.hmsroflstomped = false
				s.rollangle = 0
				s.hmsspinpass = 0
				end
			elseif s.hmsroflstompcd
			s.hmsroflstompcd = 0
			end
			if s.hudboost
			s.hudboost = $+1
				if (s.hudboost > 7)
				s.hudboost = 0
				end
			end
			if s.hmsforcedspin
			s.hmsforcedspin = $-1
			end
			if s.suddenquickspeed
				s.suddenquickspeed = $-1
				if p.hypermysticsonic
				s.flags2 = $|MF2_DONTDRAW
				else
				s.suddenquickspeed = 0
				s.flags2 = $ & ~MF2_DONTDRAW
				end
				if s.suddenquickspeed == 1
				s.flags2 = $ & ~MF2_DONTDRAW
				end
			end
			if s.hmscarryspinpass
			s.hmscarryspinpass = $-1
			end
			if s.haltthespam
			s.haltthespam = $-1
			end
			if s.lemmego
			s.lemmego = $-1
			end
			if s.smsthrowcd
			s.smsthrowcd = $-1
			end
			if s.iampickedupbysmshelp
			s.iampickedupbysmshelp = $-1
			end
			if s.smsanalogforward
			s.smsanalogforward = $-1
			end
			if s.smsstompcd
			s.smsstompcd = $-1
			end
			if s.ibethrownbysmshelp
			s.ibethrownbysmshelp = $-1
				if not s.ibethrownbysmshelp and s.rollangle
				s.rollangle = 0
				end
			end
			if s.smsarmablow
				if P_IsObjectOnGround(s)
				s.smsarmablow = 0
				else
				s.smsarmablow = $-1
				end
			end
			if s.sms_auradelay
			s.sms_auradelay = $-1
			end
			if s.smsbdsfx
			s.smsbdsfx = $-1
			end
			if s.smsabsfx
			s.smsabsfx = $-1
			end
			if s.hmsccd
			s.hmsccd = $-1
			end
			if s.hmspickedup
			s.hmspickedup = $-1
				if not s.hmspickedup
					if s.hmspickuptarget != nil and s.hmspickuptarget.valid
					s.hmspickuptarget.occupiedcarrying = nil
					end
					s.occupiedcarrying = nil
				end
			end
			if s.DeyCURollin
			s.DeyCURollin = $-1
				if not s.DeyCURollin and p.powers[pw_carry] == CR_ROLLOUT
				p.powers[pw_carry] = 0 //Get lost, rock.
				end
			end
			if s.sdodgeoh
			s.sdodgeoh = $-1
				if P_IsObjectOnGround(s) and not p.sms_dodging
				s.dodgespinslide = true
				end
				if not s.sdodgeoh
				s.dodgespinslide = false
				end
			end
			if p.srgorelvl
			p.srgorelvl = $-1
				if (p.srgorelvl > 150)
				p.srgorelvl = 150
				end
			end
			if s.tnospina
			s.tnospina = false
			end
			if s.hmsshieldconsume
				s.hmsshieldconsume = $-1
			end
			if s.hmsshieldconsumecd
			s.hmsshieldconsumecd = $-1
			end
			if s.atomdiveusebuffer
				if not (s.state == S_SMS_ATOMDIVE)
				s.atomdiveusebuffer	= $-1
				end
				if not ((p.cmd.buttons == 0) or (p.cmd.buttons & BT_USE))
				and not p.homing and not (p.cmd.forwardmove > 0)
				and not ((p.cmd.forwardmove or p.cmd.sidemove) and (p.pflags & PF_ANALOGMODE))
				or p.hypermysticsonic
				s.atomdiveusebuffer = 0
				s.useatommethod = false
				end
			end
			if s.useatommethod
				if not (p.cmd.buttons & BT_USE) or not (s.state == S_SMS_ATOMDIVE)
				s.useatommethod = false
				end
			end
			if s.forcesmsangletimer
				if (p.pflags & (PF_DIRECTIONCHAR|PF_ANALOGMODE)) and s.forcesmsangle
				p.drawangle = s.forcesmsangle
				end
				s.forcesmsangletimer = $-1
			end
			if s.hmstorvictim
			s.hmstorvictim = $-1
				if s.hmstorvictimang != nil
					s.hmstorvictimang = $+FixedAngle(8*FRACUNIT)
				else
					s.hmstorvictimang = p.drawangle //Just incase.
				end
				if not (s.state == S_PLAY_ROLL)
				p.drawangle = s.hmstorvictimang
				s.rollangle = s.hmstorvictimang
				end
				if not s.hmstorvictim and s.rollangle
				s.rollangle = 0
				end
			end
			if s.hmsusebuffer
				if not (p.cmd.buttons & BT_USE) or not p.hypermysticsonic
				s.hmsusebuffer = $-1
				end
			end
			if s.airboostroll 
				if (((s.state == S_SMS_AIRBOOST) or (s.state == S_PLAY_PAIN) or (s.state == S_SMS_LIGHTDASH)) or p.hypermysticsonic) and not P_IsObjectOnGround(s)
				and not ((p.speed < 30*FRACUNIT) and (s.state != S_PLAY_PAIN) and (s.state != S_SMS_LIGHTDASH)) and not (s.flags2 & MF2_TWOD)
					if (s.airboostroll == 1)
					s.airboostroll = 0
					s.rollangle = 0
					else
					s.airboostroll = $-1
						if s.hmsrotateright
						s.rollangle = $-FixedAngle(53*FRACUNIT)
						else
						s.rollangle = $+FixedAngle(53*FRACUNIT)
						end
					//	if p.hypermysticsonic and (p.hmsdash and p.hmsdash == 2)
					//	p.viewrollangle = s.rollangle
					//	s.hmscchange = true 
					//	end
					end
				else
				s.airboostroll = 0
				s.rollangle = 0
				end
			elseif s.hmscchange and not s.smstrickroll 
			p.viewrollangle = 0
			s.hmscchange = false
			end
			if p.smsdontgrabme and p.smsdontgrabme == 1
			s.iasmsp = 0
			elseif not (p.cmd.buttons or p.cmd.sidemove or p.cmd.forwardmove)
				if p.smsdontgrabme and p.smsdontgrabme == 2
				s.iasmsp = 140
				end
				s.iasmsp = s.iasmsp and $+1 or 1
			else
			s.iasmsp = 0
			end
		end
		
//Debug code to test Mystic Supers/Spawn Mystic Emeralds.
	
	/*	if (s and s.skin != "sms")
			if p.rings and not p.mysticsuper and (p.cmd.buttons & BT_CUSTOM2) and (p.cmd.buttons & BT_CUSTOM1) and (p.cmd.buttons & BT_CUSTOM3)
			A_STARTMYSTICSUPER(s)
			end
		elseif (s and s.skin == "sms")
			if (p.cmd.buttons & BT_CUSTOM2) and (p.cmd.buttons & BT_CUSTOM1) and (p.cmd.buttons & BT_CUSTOM3) and p.speed == 0 and not p.sms_flamedelay
			p.sms_flamedelay = 105
			P_SpawnMobj(s.x, s.y, s.z, MT_THEMYSTICEMERALD)
			end
		end */
		if s.supersmsrecoil2
			s.recoilthrust = nil
			p.powers[pw_nocontrol] = 0
					if s.supersmsrecoil2 == 17
						s.rollangle = 0
						s.supersmsrecoil2 = 16
						if s.supersmsrecoil2ang != nil
						P_InstaThrust(s, s.supersmsrecoil2ang, -65*FRACUNIT)
						end
					elseif (s.eflags & MFE_JUSTHITFLOOR)
						s.rollangle = 0
						s.supersmsrecoil2 = 0
						s.supersmsrecoil = false						
						if CBW_Battle and CBW_Battle.DoDebris
							S_StartSound(s, sfx_cdfm42)
							for d = 0,08
							CBW_Battle.DoDebris(s,P_RandomChance(FRACUNIT/2),P_RandomRange(5,20))
							end
						end
					elseif s.supersmsrecoil2 == 16
					s.supersmsrecoil = false
					s.rollangle = $-FixedAngle(35*FRACUNIT)
						if ((s.momx < 699355 and s.momx > -699355) and (s.momy < 699355 and s.momy > -699355))
						s.state = S_PLAY_DRWN
						P_SetObjectMomZ(s, 3*FRACUNIT) s.momx = 0 s.momy = 0
						s.supersmsrecoil2 = $-1
						S_StartSound(s, sfx_cdfm42)
						S_StartSound(s, sfx_kc40)
						S_StartSound(s, sfx_s3k9b)						
						A_SMSquake(s, 60*FRACUNIT, 8, 901)
						P_SpawnMobj(s.x, s.y, s.z, MT_BURSTWAVE)
						S_StartSound(s, sfx_altow1)
						p.rings = 10
						P_PlayerRingBurst(p, 10)
						p.rings = 0
						local bsl = P_SpawnMobj(s.x, s.y, s.z-12*FRACUNIT, MT_BURSTLIGHT)
						bsl.color = SKINCOLOR_WHITE
							for d = 0,15
							CBW_Battle.DoDebris(s,P_RandomChance(FRACUNIT/2),P_RandomRange(5,20))
							end	
						end
					elseif (s.supersmsrecoil2 > 1)
						s.rollangle = 0
						s.supersmsrecoil = false
						s.supersmsrecoil2 = $-1
						s.state = S_PLAY_DRWN
						s.momz = $/99 s.momx = 0 s.momy = 0
					else
						s.rollangle = 0
						s.state = S_PLAY_PAIN					
						s.supersmsrecoil2 = 0
					end
		end
		if (s and s.skin != "sms") //Set it back once so the classic physics script can reset it for us.
		  if p.sms_transformstate
		  p.sms_transformstate = 0
		  end
		  if s.smskability
		  	if s.abilitytogive
			s.abilitytogive = 0
			end
		  s.smskability = false
		  end
		  if p.isclassicsms and not p.mysticsuper
		  p.isclassic = nil
		  p.isclassicsms = nil
		  end
		  if p.smssonicbattle
				if (s.skin != "sonic" and not (s.skin == "sms" and p.sms_transformstate))
				p.smssonicbattle = false
				end
		  end
		  if s.sprite == SPR_SMSO or s.sprite == SPR_HMSO
		  s.sprite = SPR_PLAY
		  s.state = S_PLAY_SPRING
		  end
		  if not p.smsfirstcolor 
				if (p.shinyglosscoat and p.shinyglosscoat > 1)
				or p.nosmscolorspls
				p.smsfirstcolor = true
					if p.nosmscolorspls
					A_setSMSspecialcolors(s, 0)
					end
				elseif not p.smsfcc or (p.smsfcc != p.skincolor)	
		  		p.smsfcc = p.skincolor
				end
		  end
		  if s.battlemodsms
		  		if s.ssittcpls2
					s.ssittcpls2 = $-1
					p.skincolor = s.ssittcpls
					s.color = s.ssittcpls
					p.sms_originalcolor = s.ssittcpls
					
					if not s.ssittcpls2
					s.ssittcpls = nil
					end
				end
		  		if s.lastbmrings //Refund rings and maybe spawn a shield to make it easier to re-transform
		  			if not s.supersmsrecoil2
						if not (CBW_Battle and CBW_Battle.SkinVars)
						p.shieldstock = 1 --Extra reserve pity shield
						end
						if (s.lastbmrings > 10)
						P_GivePlayerRings(p, 10)
							if not p.powers[pw_shield]
								if (s.lastbmrings > 59)
									p.powers[pw_shield] = SH_FORCE|1
								elseif (s.lastbmrings > 29)
								p.powers[pw_shield] = SH_PITY
								end
							S_StartSound(s, sfx_shield)
							P_NukeEnemies(s, s, 0)
							P_SpawnShieldOrb(p)
							end
						else
						P_GivePlayerRings(p, s.lastbmrings)
						end
					end
				s.lastbmrings = 0
				end
			end
		elseif (s and s.skin == "sms")
			if not s.abilitytogive or s.abilitytogive != -8
			s.abilitytogive = -8
			s.smskability = true
			end
			if not p.smsfirstcolor //Introduce players to SMS with his true color
				if G_GametypeHasTeams()
			  	elseif not p.smsfcc or (p.smsfcc == p.skincolor)
				p.skincolor = SKINCOLOR_YELLOW
				end
				p.smsfirstcolor = true
			end
			if p.bot
				if (p.speed < 10*FRACUNIT) and P_IsObjectOnGround(s)
				s.smsbottf = s.smsbottf and $+1 or 1
				else
				s.smsbottf = 0
				end
				if p.dobotpowershare
				p.dobotpowershare = $-1
				end
			end
			if p.superkey != "off"
				if mmtINTHEPK3
				CONS_Printf(p, "\x85"+"Turned off superkey for"+"\x82 SMS.\x85 Remember to turn it on again if you switch characters!")
				end
				p.superkey = "off"
			end
			if s.battlemodsms
				if s.skin == "sms"
					if not s.supersmsrecoil
						if ((p.powers[pw_nocontrol] > 5) and (s.recoilthrust and (s.recoilthrust > 10*FRACUNIT)) )
						s.supersmsrecoil = true
						P_SetObjectMomZ(s, -6*FRACUNIT, true)
						A_SMSquake(s, 60*FRACUNIT, 5, 1500)
						S_StartSound(s, sfx_smscrt)
						p.powers[pw_nocontrol] = $*2
						s.recoilthrust = $*5/4
						P_SpawnGhostMobj(s)
						P_SpawnMobj(s.x, s.y, s.z, MT_BURSTWAVE)
						A_SMSSTOMPSMOKE(s, 30, MT_HMSLIGHTNING2, 0, 20*FRACUNIT, FRACUNIT/2, SKINCOLOR_LAVENDER)
							if not P_IsObjectOnGround(s)
							s.supersmsrecoillanding = true
							end
						end
					elseif s.supersmsrecoil
						if s.supersmsrecoillanding
						S_StartSound(s, sfx_smscrt)
						if not p.smsgraphix
						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
						end
						A_SMSSTOMPSMOKE(s, 60, MT_SPINDUST, nil, nil, 2*FRACUNIT)
						A_SMSSTOMPQUAKE(s, 45, 14, FRACUNIT, 0, 0, 0, 0, SKINCOLOR_SUPERGOLD3)
						A_SMSSTOMPQUAKE(s, 80, 18, 2*FRACUNIT, 0, ANG20, 0, 0, SKINCOLOR_SUPERSILVER4)
						s.supersmsrecoillanding = false
						end
						if (p.powers[pw_nocontrol] <= 1)
						s.supersmsrecoil = false					
						else
							if P_IsObjectOnGround(s) and CBW_Battle and CBW_Battle.DoDebris
							s.sprite = SPR_SMSO
							s.frame = Q|FF_FULLBRIGHT
							s.ghs = P_SpawnGhostMobj(s)
							s.ghs.tics = 3
							CBW_Battle.DoDebris(s,P_RandomChance(FRACUNIT/2),P_RandomRange(5,20))
							end
							if P_RandomRange(0,1)
							S_StartSound(s, sfx_cdfm42)
							end
						A_SMSquake(s, P_RandomRange(30,60)*FRACUNIT, 2, 1200)
						end					
					end
					if (p.rings > 299)
					p.sms_flamedelay = 10
						if (p.cmd.buttons & (BT_ATTACK|BT_FIRENORMAL))
						and not (p.hypermysticsonic or p.sms_ringburstfly or p.sms_stompanim or p.exiting or p.homing)
						and not p.powers[pw_nocontrol]
			  			and not p.exiting and not P_PlayerInPain(p) and not (p.charmed and p.charmedtime)
						and not p.powers[pw_carry]
						and not (p.pflags & (PF_GAMETYPEOVER|PF_STASIS))
							if P_IsObjectOnGround(s)
							P_SetObjectMomZ(s, 50*FRACUNIT, false)
							end
							p.sms_flamedelay = 15
							A_TOGOEVENFURTHERBEYOND(s) //Become Hyper Mystic Sonic!
						end		
					end
				end
			/*	if p.captureamount --Mild capture speed nerf incase SMS becomes OP here.
					if (leveltime % 5 == 0) 
					and s.lastcaptureamountsms and (s.lastcaptureamountsms < p.captureamount)
					p.captureamount = $-1 //Slightly slower capture speed for SMS.
					end			
				s.lastcaptureamountsms = p.captureamount
				end */
			  if p.smsnobmgame and p.smsnobmgame == 2
				if not p.sms_transformstate
				p.presmsskin = "sonic"
				s.playerhomecharge = false
				A_SMSTOSONIC(s, nil, true, true)
				p.smssonicbattle = true
				S_StartSound(s, sfx_appear, p)
				P_FlashPal(p, PAL_MIXUP, 3)		
				CONS_Printf(p, "\x82"+"Sonic's special Battle ability is now the Super Mystic transformation!")
					if s.skin != "sms" and p.sms_originalcolor
					s.ssittcpls = p.sms_originalcolor
					s.ssittcpls2 = 2
					end
				return
				else
						if p.powers[pw_shield] //No extra hits while in battle mode!
							if not (p.powers[pw_shield] == SH_PINK or p.powers[pw_shield] == SH_PITY)
							and not s.hmsshieldconsumecd
							P_GivePlayerRings(p, 5) //But feel free to gain some extra rings!
							s.hmsshieldconsume = 18
							s.hmsshieldconsumecd = 105
							end
						P_RemoveShield(p)
						p.powers[pw_shield] = 0
						end
						if (p.sms_transformstate < 2)
						p.sms_transformstate = 2 //Only 1 hitpoint in battle mode!
						end
				end
			  elseif p.smsnobmgame and p.smsnobmgame == 1
			 	p.presmsskin = "sonic"
				A_SMSTOSONIC(s, nil, true, true)
				p.smssonicbattle = false	
		 		S_StartSound(s, sfx_lose)
				CONS_Printf(p, "\x85"+"SMS is not allowed in Battlemode matches right now!")	 
				return 
			  elseif not p.smsnobmgame
			  end
			elseif p.smsnomatchgame and G_GametypeHasSpectators()
				P_FlashPal(p, PAL_NUKE, 4)
		 		S_StartSound(s, sfx_lose)
				CONS_Printf(p, "\x85"+"SMS is not allowed in Matches right now!")	  
				A_SMSTOSONIC(s, nil, true, true)
				return
			elseif p.smstransformonly and not p.sms_transformstate and not G_GametypeHasSpectators()
		  		P_FlashPal(p, PAL_NUKE, 4)
		 		S_StartSound(s, sfx_lose)
				CONS_Printf(p, "\x85"+"SMS is available only as transformation now!")	  
				A_SMSTOSONIC(s, nil, true, true)
				return //Don't continue any further in this case.
		  end
		  if p.isclassic or p.isclassic == nil  //No Classic physics for SMS.
		  p.isclassic = false
		  p.isclassicsms = true
		  end
		  
		//Controls catch. If you slam into a wall despite still holding forwards, grant a free tic where SMS will propell himself forwards
		//again, making it feel as if he never slowed down much, and like YOU may not have been playing sloppily. Yay for sneaky mercy mechanics for newbies!
		
			if s.hmslastspeedn
				if (p.cmd.buttons & BT_CUSTOM1) and (p.cmd.forwardmove > 0) and P_IsObjectOnGround(s)
				and ( ( (p.speed < s.hmslastspeedn-40*FRACUNIT) and not (p.pflags & PF_SPINNING)) or ((p.speed < 5*FRACUNIT) and (p.pflags & PF_SPINNING) and p.hypermysticsonic) )
				and ( p.hypermysticsonic or (s.state == (S_PLAY_STND|S_PLAY_WALK|S_PLAY_RUN)) or ((s.state >= S_SMS_BOOST01) and (s.state <= S_SMS_BOOST04)) )
				s.smsmovesuccess = false
					for d = 1,18
						if not s.smsmovesuccess and not (d >= 6 and d <= 12)
							if (P_TryMove(s, s.x+FixedMul(100*FRACUNIT, cos(ANG20*d)), s.y+FixedMul(100*FRACUNIT, sin (ANG20*d)), false) )
							s.smsmovesuccess = true
							A_BossScream(s, 0, MT_EXPLODE)
							end
						end
					end
				
				
				P_InstaThrust(s, s.angle, s.hmslastspeedn)
					if P_RandomRange(0,1)
					S_StartSound(s, sfx_s3k7e)
					A_BossScream(s, 0, MT_EXPLODE)
					else
					A_BossScream(s, 0, MT_WATERZAP)
					S_StartSound(s, sfx_s3k9a)
					end
				end					
			s.hmslastspeedn = nil //You only get 1 extra chance.
			end
			
		//SMS' strong spring code. Mimmicks the way Amy interacts with springs, but is tweaked for horizontal springs.
		
		  if s.vertstrongspring
		  	if not P_PlayerInPain(p)
		  			if s.horstrongspring2
					s.momx = $*7/4
					s.momy = $*7/4
					else
						if s.vertstrongspring
						s.momz = $*40/33
						end
						if s.horstrongspring
						s.momx = $*5/4
						s.momy = $*5/4
						end
					end
				s.vertstrongspring = false
				s.horstrongspring = false
				s.horstrongspring2 = false
			end
		  end		
		  if (p.powers[pw_sneakers] and (s.battlemodsms or not G_PlatformGametype()))
			p.mxscap = 2
			if p.powers[pw_sneakers] == 699
			p.powers[pw_sneakers] = 698
			P_FlashPal(p, PAL_RECYCLE, 3)
			CONS_Printf(p, "\x82"+"Combat shoes powerup! Combat moves drain no rings for a while!")
			S_StartSound(s, sfx_steam2)
			end
		  else
			p.mxscap = 1
		  end
		  
			if s.sms_painr == nil
			s.sms_painr = 0
			end
			if p.sms_boostlevel
				if p.hypermysticsonic
				or not s.health
				or p.knucklewaving
				p.sms_boostlevel = 0
				end
				if ((p.sms_boostlevel > 32) and (p.sms_boostlevel < 66)) and (p.panim == PA_RUN) and P_IsObjectOnGround(s)
				s.spinrundust = P_SpawnMobj(s.x+FixedMul(24*FRACUNIT, cos(s.angle+ANGLE_90)),s.y+FixedMul(24*FRACUNIT, sin(s.angle+ANGLE_90)), s.z, MT_SPINDUST)
				s.spinrundust.frame = P_RandomRange(0,2)
				s.spinrundust = P_SpawnMobj(s.x+FixedMul(24*FRACUNIT, cos(s.angle-ANGLE_90)),s.y+FixedMul(24*FRACUNIT, sin(s.angle-ANGLE_90)), s.z, MT_SPINDUST)
				s.spinrundust.frame = P_RandomRange(0,2)
				end
			end
			if ((p.cmd.buttons & BT_CUSTOM1) or p.sms_autoboosthold) and not (p.smsblastboost and not p.hypermysticsonic) and not (p.sms_ringburstfly and p.sms_ringburstfly == 1)
			
			//Super Sonic X Aura! ...or Ultra Instinct. Your pick!
			
				if ((s.tics == 1) and (s.state == S_PLAY_STND))
					s.tics = 9
				elseif s.state == S_PLAY_WAIT
					s.state = S_PLAY_STND
				end
				if s.health
				s.smsglowticket = 2 //Not usually a glowing color? Well, you get to glow today!
				end
				
			  if (p.speed < 99*FRACUNIT) and not (p.sms_boostlevel > 64) and s.health	
			  	s.ssxaticket = true
			  end		
				if not G_GametypeHasSpectators()
				and (p.sms_boostlevel < 65)
				and not (s.eflags & MFE_UNDERWATER and not p.hypermysticsonic)
				and not p.smsblastboost
				and not (p.pflags & PF_STASIS) 
				and not p.powers[pw_nocontrol]
				and not p.sms_dodging
					if p.hypermysticsonic
					s.hmgodticket = true
					p.normalspeed = (242*FRACUNIT)
					else
					p.normalspeed = (121*FRACUNIT)/p.mxscap
					end
				elseif (((p.normalspeed != (60*FRACUNIT)/p.mxscap) and not p.hypermysticsonic) or (p.hypermysticsonic and (p.normalspeed != (120*FRACUNIT))))
					if (p.sms_boostlevel < 65)
					and not (p.pflags & PF_STASIS) //No control? Wait a little bit!
					and not (G_GametypeHasSpectators() or p.gotflag)
						if p.hypermysticsonic
						p.normalspeed = (120*FRACUNIT)
						else
						p.normalspeed = (60*FRACUNIT)/p.mxscap //Normal speed. Still pretty speedy, though!
						end
					end
				end

				if G_GametypeHasSpectators()
							
					if (p.rings)
					and (p.sms_boostlevel < 65)
					and not p.gotflag
					and not p.smsblastboost
					and not (p.pflags & PF_STASIS) and not p.sms_dodging
					and not (s.eflags & MFE_UNDERWATER and not p.hypermysticsonic)
						if p.hypermysticsonic
						s.hmgodticket = true
						p.normalspeed = (242*FRACUNIT)
						else
						p.normalspeed = (121*FRACUNIT)/p.mxscap
						end

					elseif (((p.normalspeed != (60*FRACUNIT)/p.mxscap) and not p.hypermysticsonic) or (p.hypermysticsonic and (p.normalspeed != (120*FRACUNIT))))
					and not (p.sms_boostlevel >= 65)
					and not p.gotflag
						if p.hypermysticsonic
						p.normalspeed = (120*FRACUNIT)
						else
						p.normalspeed = (60*FRACUNIT)/p.mxscap
						end
						p.thrustfactor = 7
						p.sms_boostlevel = 0
					end
				end

				//Afterimages! They only appear when in boost mode while going fast enough.

				if not G_GametypeHasSpectators()
				and not (p.pflags & (PF_SPINNING|PF_SLIDING))
				and not (p.powers[pw_carry])
				and not (s.eflags & MFE_GOOWATER)
				and not p.smsblastboost
					if p.speed >= FixedMul(52*FRACUNIT, s.scale)
					and s.health
					s.hmslastspeedn = p.speed
						if not (p.sms_boostlevel > 65) and not (s.hmsspinpass and p.hypermysticsonic)
						s.sprintghost = P_SpawnGhostMobj(s) //Singular afterimage
						s.sprintghost.tics = 2
						s.sprintghost.rollangle = s.rollangle
						end
						s.smsspeedticket = true
					end
				end
			elseif p.smsblastboost
				p.normalspeed = (38*FRACUNIT)/p.mxscap
			end
			if not s.smsspeedticket and (p.speed > FixedMul(78*FRACUNIT, s.scale))
			s.smsspeedticket = true
			s.hmslastspeedn = p.speed
			end
			//Incase you're in Match/CTF, add ring draining abilities.
			if G_GametypeHasSpectators()
				if (p.powers[pw_emeralds] == 0) and (p.powers[pw_invulnerability] == 700 and p.powers[pw_sneakers] == 700)
				p.powers[pw_invulnerability] = 0 //Give 50 rings instead of that fake match super form
				p.powers[pw_sneakers] = 0
				P_GivePlayerRings(p, 50)
				P_RestoreMusic(p)
				S_StartSound(s, sfx_token)
				end	
				if not p.rings
					p.sms_boostlevel = 0
				end
					if s.smsflagrgpermission and not p.gotflag //Delay in picking up CTF flag
						s.smsflagrg = s.smsflagrg and $+1 or 1
						if (s.smsflagrg > 24)
						s.smsflagrg = 21
						elseif (s.smsflagrg % 6 == 0)
						s.flagsmssfx = true
						end
					s.smsflagrgpermission = $-1	
					elseif s.smsflagrg
						s.smsflagrgpermission = 0
						s.smsflagrg = 0
						s.flagsmssfx = false
					end
				if (p.rings > 199) and not p.hypermysticsonic //Add a beacon stolen--err, borrowed from Samus.
				  s.smsglowticket = 2
					if (s.eflags & MFE_VERTICALFLIP)
						s.zapsms = P_SpawnMobj(s.x, s.y, s.z-s.height*10/12, MT_THOK)
					else
						s.zapsms = P_SpawnMobj(s.x, s.y, s.z+s.height*10/12, MT_THOK)
					end
				  if s.zapsms
				  s.zapsms.scale = s.scale
				  s.zapsms.destscale = s.scale/(P_RandomRange(1,5))
				  s.zapsms.momx = s.momx
				  s.zapsms.momy = s.momy
				  s.zapsms.momz = s.momz+((P_RandomRange(30, 100))*FRACUNIT)*P_MobjFlip(s)
				  s.zapsms.eflags = s.eflags
				  s.zapsms.frame = $|FF_FULLBRIGHT
				  s.zapsms.tics = 8
				  s.zapsms.color = P_RandomRange(SKINCOLOR_SUPERGOLD1, SKINCOLOR_SUPERGOLD5)
				  end
				end
				if (((p.cmd.buttons & BT_CUSTOM1) or p.sms_autoboosthold) or (p.sms_boostlevel >= 65))
				and not (s.eflags & (MFE_UNDERWATER|MFE_GOOWATER))
				and not (p.pflags & (PF_SPINNING))
				and not (p.powers[pw_carry])
				and not p.smsblastboost
				and s.health
					if (p.speed >= FixedMul(70*FRACUNIT, s.scale)) and not (s.hmsspinpass and p.hypermysticsonic)
					p.sms_boostdrain = $+1
					s.hmslastspeedn = p.speed
					s.sprintghost = P_SpawnGhostMobj(s)
					s.sprintghost.rollangle = s.rollangle
					s.smsspeedticket = true
					end
                end
			end
			if p.sms_boostdrain == 3
			and s.health
			and not p.ringburstfly
			and not p.hypermysticsonic
				P_GivePlayerRings(p, -1) //Take rings when the timer resets.
				p.sms_boostdrain = $+1
			elseif (p.sms_boostdrain > 12)
				p.sms_boostdrain = 0
			end
			if p.smsblastboost and not p.hypermysticsonic
			and not p.gotflag
				p.normalspeed = (38*FRACUNIT)/p.mxscap	
				p.runspeed = 26*FRACUNIT
				s.changedmyrsd = true
			elseif (((p.normalspeed != (60*FRACUNIT)/p.mxscap) and not p.hypermysticsonic) or (p.hypermysticsonic and (p.normalspeed != (120*FRACUNIT))))
			and (p.sms_boostlevel < 65)
			and not ((p.cmd.buttons & BT_CUSTOM1) or p.sms_autoboosthold) //Failsafe!
			and not p.gotflag
				if p.hypermysticsonic
				p.normalspeed = (120*FRACUNIT)
				else
				p.normalspeed = (60*FRACUNIT)/p.mxscap
				end
			end 

			//When SMS holds a flag, nerf him please for the love of god!

			if (p.gotflag or (s.eflags & MFE_UNDERWATER))
			and not p.hypermysticsonic
				if p.gotflag
				p.normalspeed = 1965000/p.mxscap
				p.mindash = 40*FRACUNIT
				p.maxdash = 71*FRACUNIT
				p.sms_boostlevel = 0
				elseif (s.eflags & MFE_UNDERWATER)
				p.mindash = 64*FRACUNIT //Blinddash needs to be nerfed too.
				end
			elseif ((p.mindash == 40*FRACUNIT) or (p.mindash == 64*FRACUNIT))
			p.mindash = 101*FRACUNIT
				if not (p.hypermysticsonic)
				p.maxdash = 147*FRACUNIT
				end
			end

		//SMS gets special runshoes powers....oh dear.
		//Eh.....what could possibly go wrong?

		  if not p.hypermysticsonic
		  	if p.secondjump == 167
				if p.smsblastboost
					if (s.state == S_PLAY_ROLL) or (p.pflags & PF_JUMPED)
					s.state = S_PLAY_SPRING
					s.eflags = $|MFE_SPRUNG
					p.pflags = $ & ~PF_JUMPED
					elseif (s.state == S_PLAY_SPRING) and (s.momz*P_MobjFlip(s) > 5*FRACUNIT)
					s.ghs = P_SpawnGhostMobj(s)
					s.ghs.tics = P_RandomRange(3,4)
					end
				else
				p.secondjump = 0
				end
			end
		  if s.smsthokanim
		  	if p.panim == PA_ROLL or p.panim == 8 or p.panim == 10
		  	s.state = S_SMSTHOKANIM
				if (p.charability == CA_HOMINGTHOK or p.cmd.buttons & BT_USE) and not p.smsblastboost
				s.tics = 2
				end
			p.pflags = $|PF_JUMPED
			end
			
		  s.smsthokanim = false
		  end
		     if G_PlatformGametype() and not s.battlemodsms
			if p.speedspeedspeedspeedspeed == nil
				p.speedspeedspeedspeedspeed = 0
			end
			if (p.speedspeedspeedspeedspeed or p.smsg2gfast)
			and not p.powers[pw_sneakers]
				p.speedspeedspeedspeedspeed = 0
				p.smsg2gfast = false
			end
			if not p.smsg2gfast
				if (p.powers[pw_sneakers] > 600)
				and s.health
				and not p.exiting
					p.smsg2gfast = true
				end
			elseif p.smsg2gfast
				if not (p.powers[pw_extralife]) and not p.nohmstheme
				and s.health
				and not p.exiting
				and not p.sms_intoship
				S_ChangeMusic(1034, false, p)
				end
			end
			if (p.powers[pw_sneakers] == 1) and not p.sms_intoship and not p.nohmstheme
			P_RestoreMusic(p)
			end

			if not s.health and p.powers[pw_sneakers]
				p.powers[pw_sneakers] = 0
				p.powers[pw_invulnerability] = 0
				p.speedspeedspeedspeedspeed = 0
			end
			if s.sneakerjcd
				if (s.sneakerjcd == 1) and (p.pflags & PF_JUMPED)
					if s.sneakjuw == 7 and (p.powers[pw_underwater] or (s.eflags & MFE_UNDERWATER)) 
					s.sneakjuw = 10 //Still underwater? Then keep your momentum.
					end
					if s.sneakerwc
					P_SetObjectMomZ(s, (-28*FRACUNIT)*10/s.sneakjuw, true)
					elseif ((p.pflags & PF_STARTJUMP) and (p.cmd.buttons & BT_JUMP))
					P_SetObjectMomZ(s, (-20*FRACUNIT)*10/s.sneakjuw, true)
					else
					P_SetObjectMomZ(s, (-13*FRACUNIT)*10/s.sneakjuw, true)
					end
				s.sneakerjumpgfx = false
				s.sneakerwc = false
				end
				if s.sneakerjcd
					s.sneakerjcd = $-1
					A_SMSSTOMPSMOKE(s, P_RandomRange(15, 30), MT_SPINDUST)
				end
			/*	s.sneakthk = P_SpawnMobj(s.x, s.y, s.z, MT_THOK)
				s.sneakthk.color = P_RandomRange(SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERSILVER5)
				s.sneakthk.destscale = $*P_RandomRange(2, 10)
				s.sneakthk.scalespeed = $*P_RandomRange(1,3) */
				if P_IsObjectOnGround(s) or (p.sms_wallstat == 59) or (s.momz*P_MobjFlip(s) <= 0)
				or (s.state == S_PLAY_SPRING) or p.homing or p.powers[pw_carry]
				s.sneakerjcd = 0
				s.sneakerjumpgfx = false
				s.sneakerwc = false
				end
			elseif s.sneakerjumpgfx and not (p.pflags & PF_JUMPED)
				s.sneakerjumpgfx = false
				s.sneakerwc = false
			end
			if (p.powers[pw_sneakers] > 3)
			and s.health
				if (p.pflags & PF_STARTDASH) and (p.dashspeed < p.maxdash)
				and not G_GametypeHasSpectators()
				p.dashspeed = p.maxdash //Instant maxdash
				S_StartSound(s, sfx_spndsh)
				end
				if ((p.pflags & PF_JUMPED) and not s.sneakerjumpgfx)
				and not G_GametypeHasSpectators() //Not for spectator gametypes.
					if not (s.z > s.floorz+24*FRACUNIT)
					A_SMSSTOMPSMOKE(s, 24, MT_SPINDUST)
					P_SpawnGhostMobj(s)
					P_SetObjectMomZ(s, 18*FRACUNIT, true)
					s.sneakerjcd = 4
					s.sneakerwc = false
					end
						if (s.eflags & MFE_UNDERWATER) or p.powers[pw_underwater]
						s.sneakjuw = 7
						else
						s.sneakjuw = 10
						end
				s.sneakerjumpgfx = true
				end
			   if p.exiting 
			  	p.powers[pw_sneakers] = 2
			  	p.powers[pw_invulnerability] = 2
			   else
				if not (p.powers[pw_shield] == (SH_WHIRLWIND) or p.powers[pw_shield] == (SH_WHIRLWIND|SH_FIREFLOWER))
				p.jumpfactor = 72535
				end
				p.accelstart = 140
				p.thrustfactor = 10
				if (p.speed > 0) and not p.mslightspeedattack
				P_RadiusAttack(s, s, 137*FRACUNIT)
					if (p.sms_boostlevel < 32)
					p.sms_boostlevel = 32
					end
					if not p.powers[pw_carry]
					s.sprintghost = P_SpawnGhostMobj(s)
					s.sprintghost.rollangle = s.rollangle
					end
					if (p.speed > FixedMul(110*FRACUNIT, s.scale))
					P_RadiusAttack(s, s, 220*FRACUNIT) 
					s.boostpass = 1
						if (p.speed > FixedMul(140*FRACUNIT, s.scale))
						s.hmslastspeedn = p.speed //Sneakers get all the mercy.
						s.smsgrboost = P_SpawnMobj(s.x, s.y, s.z, MT_SMSGROUNDBOOST)
						s.smsgrboost.tracer = s
							if (p.speed > FixedMul(180*FRACUNIT, s.scale))
								if P_IsObjectOnGround(s)
								s.hmsrunquake = 1
								end
							A_SMSquake(s, 12*FRACUNIT, 1, 2500)
							P_RadiusAttack(s, s, 320*FRACUNIT)
							end
						elseif s.hmslastspeedn
						s.hmslastspeedn = nil
						end
					end
				end
			   end
			end
		     end
		  end

			//When running REALLY fast for extended periods of time, you can break your
			//"speed limit". We'll call it "Speed Break" for now, after Sonic and the Secret Rings. 
			if not s.smsboostimmune
				if ( ((p.speed >= FixedMul(78*FRACUNIT, s.scale) and not ((p.powers[pw_sneakers]) and (G_PlatformGametype() and not s.battlemodsms))) or ((p.speed >= 78*FRACUNIT) and ((p.cmd.buttons & BT_CUSTOM1) or p.sms_autoboosthold))
				or ((p.speed >= 26*FRACUNIT) and ((p.cmd.buttons & BT_CUSTOM1) or p.sms_autoboosthold) and ((s.flags2 & MF2_TWOD) or twodlevel)) ) )
				and (P_IsObjectOnGround(s) or (p.panim == PA_RUN) or ((leveltime % 3 == 0) and (p.cmd.buttons & BT_CUSTOM1) and not p.sms_ringburstfly and not P_IsObjectOnGround(s) and not (p.sms_boostlevel > 59)) )
				and not p.smsblastboost
					p.sms_addboostlevel = true
				elseif p.sms_addboostlevel
					p.sms_addboostlevel = false
				end
				if ( ((p.speed >= FixedMul(106*FRACUNIT, s.scale) and not ((p.powers[pw_sneakers]) and (G_PlatformGametype() and not s.battlemodsms))) or ((p.speed >= 106*FRACUNIT) and ((p.cmd.buttons & BT_CUSTOM1) or p.sms_autoboosthold))
				or ((p.speed >= 39*FRACUNIT) and ((p.cmd.buttons & BT_CUSTOM1) or p.sms_autoboosthold) and ((s.flags2 & MF2_TWOD) or twodlevel)) ) )
				and (P_IsObjectOnGround(s) or (p.panim == PA_RUN) )
				and not p.smsblastboost
					p.sms_addsuperboostlevel = true
				elseif p.sms_addsuperboostlevel
					p.sms_addsuperboostlevel = false
				end
				if (p.sms_boostlevel > 1)
					if ( ((p.speed < FixedMul(63*FRACUNIT, s.scale)) and P_IsObjectOnGround(s) and not (s.flags2 & MF2_TWOD) and not twodlevel and not (p.panim == PA_ROLL) and not (s.state == S_SMS_AIRBOOST))
					or ((p.speed < FixedMul(27*FRACUNIT, s.scale)) and P_IsObjectOnGround(s) and ((s.flags2 & MF2_TWOD) or twodlevel) and not (p.panim == PA_ROLL) and not (s.state == S_SMS_AIRBOOST)))
					or (s.state == S_PLAY_PAIN) or (s.state == S_PLAY_RIDE)
					p.sms_boostlevel = 1
					end
				end
			else
				s.smsboostimmune = $-1
			end
			
			if s.health and (p.sms_boostlevel >= 65) //If the "timer" hits 65, Speed Break!
			and not p.hypermysticsonic //Just incase.
				if (p.pflags & PF_STARTDASH) and (p.dashspeed < p.maxdash)
				p.dashspeed = p.maxdash //Instant maxdash
				S_StartSound(s, sfx_spndsh)
				end
			
				p.thrustfactor = 10	
				
				//Haymaker check.
			
				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.justcheckin = true
				s.eymon.target = s
				s.eymon.height = 1200*FRACUNIT
				s.eymon.radius = 660*FRACUNIT
				end
				if p.hypermysticsonic
				p.normalspeed = (310*FRACUNIT) //HMS doesn't use this mechanic yet, but just incase....
				else
					if P_IsObjectOnGround(s) and ( p.cmd.sidemove or (s.lastangleturn != nil and s.lastangleturn != p.cmd.angleturn) )
					and ((s.state >= S_SMS_BOOST01) and (s.state <= S_SMS_BOOST04))
						if not s.driftsens
						s.driftsens = 1
						else
						s.driftsens = $+1
						end
						if (s.driftsens > 6) //Spam drifting sounds and smoke!
							s.deathsmoke = P_SpawnMobj(s.x+P_RandomRange(-67, 67)*FRACUNIT, s.y+P_RandomRange(-67, 67)*FRACUNIT, s.z, MT_TNTDUST)
							if s.deathsmoke
							P_Thrust(s.deathsmoke, s.angle+ANGLE_90, 30*FRACUNIT*P_RandomRange(-1, 1)) 
							s.deathsmoke.scale = $/P_RandomRange(1,4)
							s.deathsmoke.destscale = $*5
							s.deathsmoke.fuse = 42
							end
							
							s.deathsmoke = P_SpawnMobj(s.x+P_RandomRange(-67, 67)*FRACUNIT, s.y+P_RandomRange(-67, 67)*FRACUNIT, s.z, MT_SPINDUST)
							if s.deathsmoke
							P_Thrust(s.deathsmoke, s.angle+ANGLE_90, 30*FRACUNIT*P_RandomRange(-1, 1)) 
							s.deathsmoke.scale = $*P_RandomRange(1,3)
							s.deathsmoke.frame = $+P_RandomRange(0,2)
							s.deathsmoke.destscale = $*5
							s.deathsmoke.tics = 8
							end
						
							if not (s.smssoundobj and s.smssoundobj.valid and s.smssoundobj.health)
							s.smssoundobj = P_SpawnMobj(s.x, s.y, s.z, MT_SMSSOUNDOBJ)
							s.smssoundobj.master = s
							s.smssoundobj.health = 1
							S_StartSound(s.smssoundobj, sfx_smsdr)
							s.smssoundobj.smsdrtim = 65
							end
						end
					elseif s.driftsens and P_IsObjectOnGround(s)
					s.driftsens = 0
					end
					s.lastangleturn = p.cmd.angleturn
				p.normalspeed = (155*FRACUNIT)/p.mxscap
				end
				if (s.state != S_SMS_ATOMDIVE)
					if (p.speed > FixedMul(110*FRACUNIT, s.scale)) and P_IsObjectOnGround(s)
					s.hmslastspeedn = p.speed //Mercy mechanic.
					elseif s.hmslastspeedn
					s.hmslastspeedn = nil
					end
				s.sprintghost = P_SpawnGhostMobj(s)
				s.sprintghost.rollangle = s.rollangle
				end
				if s.state == S_PLAY_RUN
					s.state = S_SMS_BOOST01
				end
			elseif (p.thrustfactor != 7) and not (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))

				p.thrustfactor = 7
			end
			if ((s.state >= S_SMS_BOOST01) and (s.state <= S_SMS_BOOST04))
				if (p.speed < FixedMul(69*FRACUNIT, s.scale))
				and not p.hypermysticsonic
				s.state = S_PLAY_RUN
				end
			elseif (p.sms_boostlevel >= 65)
				if ((s.eflags & MFE_UNDERWATER) or p.smsblastboost) //No speed break underwater!
				p.sms_boostlevel = 0
				elseif (p.pflags & PF_STARTDASH) and (p.speed < FixedMul(FRACUNIT, s.scale))  //Lose speedbreak if you charge your spindash too slowly.
					p.sms_boostlevel = 32 //But retain a little	
				end
			end



			//Forces afterimages when at extreme speeds regardless of what.
			//Also, if you have the flag and go beyond a certain speed, slow dooown!


			if (p.speed >= FixedMul(140*FRACUNIT, s.scale))
			and P_IsObjectOnGround(s)
			and not (p.pflags & (PF_SPINNING|PF_SLIDING))
			and not (s.eflags & MFE_GOOWATER)
			and not s.hmsrotate
				s.sprintghost = P_SpawnGhostMobj(s)
				s.sprintghost.rollangle = s.rollangle
				s.smsspeedticket = true
				if (p.sms_boostlevel >= 65)
				A_SMSSpinFire(s, MT_SMSSPINFIRE, FRACUNIT/2)
					if not (s.scale < FRACUNIT/2)
						if (s.smsgbs != nil)
						s.smsgbs = $+1
						else
						s.smsgbs = 1
						end
						if not (s.smsgbs > 14)
							if s.smsgbs == 1
								if not ((s.smssoundobj4 and s.smssoundobj4.valid and s.smssoundobj4.health)
								and s.smssoundobj4.machwbtol2 and (s.smssoundobj4.machwbtol2 < 50))
								s.smssoundobj4 = P_SpawnMobj(s.x, s.y, s.z, MT_SMSSOUNDOBJ)
								s.smssoundobj4.master = s
								s.smssoundobj4.health = 1
								S_StartSound(s.smssoundobj4, sfx_machwb)
								s.smssoundobj4.smsmachwb = 1
								end
							end
						s.smsgrboost = P_SpawnMobj(s.x, s.y, s.z, MT_SMSGROUNDBOOST)
						s.smsgrboost.tracer = s
						s.smsgrboost.smsgbs = s.smsgbs
						end
					end
				end
			elseif s.smsgbs
			s.smsgbs = 0
			end
			if p.gotflag
			and (p.speed >= FixedMul(88*FRACUNIT, s.scale))
			and not (p.powers[pw_carry])
				P_InstaThrust(s, s.angle, 60*FRACUNIT) //InstaThrust can easily break a game, so we need lots of conditions.
			end

			//It's a bird, it's a plane, it's SUUUUPER SONIC! ...huh?
			//Actually, SMS can't fly. But he can definitly use the airboost. 

			if p.sms_readyairboost
				if P_IsObjectOnGround(s)
				p.sms_readyairboost = 0
				end
				if not ( (p.cmd.buttons & BT_CUSTOM1) or ((p.pflags & PF_THOKKED) and (p.cmd.buttons & BT_JUMP) and not p.sms_jumphold) )
				p.sms_readyairboost = $-1 //Not holding dash? Then count down!
				s.readyairboostdelay = false
				end
			end
			if p.sms_didairboost
				if (P_IsObjectOnGround(s) or (p.pflags & PF_JUMPED) or (s.state ~= S_SMS_AIRBOOST))
					p.sms_didairboost = 0 //Reset the SMS_didairboost state!
				end
			elseif (p.cmd.buttons & BT_CUSTOM1) or ((p.pflags & PF_THOKKED) and (p.cmd.buttons & BT_JUMP) and not p.sms_jumphold and not (p.cmd.buttons & BT_USE))
				p.sms_tapnothold = $+1 //The second timer, just for this one move

				if ((p.pflags & PF_JUMPED) or p.hometrickanim)
					if not P_IsObjectOnGround(s)
					and not p.hypermysticsonic //You'll have a different airboost as HMS.
					and not p.powers[pw_nocontrol]
					and not p.powers[pw_carry] and not p.smsblastboost
					and not (p.sms_tapnothold > 2)
					and not p.gotflag
					and not (p.pflags & (PF_STASIS))
					and not (p.sms_readyairboost > 0)
						if (p.cmd.buttons & BT_CUSTOM1) and not ((p.pflags & PF_THOKKED) and (p.cmd.buttons & BT_JUMP) and not p.sms_jumphold and not (p.cmd.buttons & BT_USE))
						p.sms_readyairboost = 4
						else
						p.sms_readyairboost = 10
						end
						s.readyairboostdelay = true
					end
				end
			    if not s.readyairboostdelay and p.sms_readyairboost //These essentially create the sensitivity
			    and (p.sms_tapnothold < 4)
				if ((p.pflags & PF_JUMPED) or p.hometrickanim)
					if not p.hypermysticsonic //You'll have a different airboost as HMS.
					and not P_IsObjectOnGround(s)
					and not p.powers[pw_nocontrol] //Panicky people double-tap the boost button after walljumps, apparently. Stop them, magical script!
					and not p.gotflag and not p.sms_intoship
					and not p.sms_afterstompthok
					and not p.sms_stompanim 
					and not p.homing 
					and not (p.sms_readyairboost < 1) //Gotta mash fast!
					and not ( ((p.sms_tapnothold > 3) and not ((p.pflags & PF_THOKKED) and (p.cmd.buttons & BT_JUMP) and not p.sms_jumphold and not (p.cmd.buttons & BT_USE))) or (p.sms_tapnothold > 5) )  //Sergeant, this is a TAP ability!
					and not p.smsrdash and not (p.hookring and (p.cmd.buttons & BT_CUSTOM1)) and not p.mslightspeedattack
					and not p.powers[pw_carry]
						if not (p.cmd.buttons & BT_CUSTOM1) //Oh, you're using the jump method!
						p.sms_autoboosthold = true
						end
						s.sprintghost = P_SpawnGhostMobj(s)
						s.sprintghost.rollangle = s.rollangle
						p.sms_boostlevel = $+20
						P_SetObjectMomZ(s, 0)
						p.pflags = ($) & ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED)
						p.sms_tapnothold = 0
						p.sms_readyairboost = 0
						s.state = S_SMS_AIRBOOST
							if s.hmsrotateright
							s.hmsrotateright = true
							else
							s.hmsrotateright = true
							end
						if not (s.eflags & MFE_UNDERWATER)
						p.sms_stompanim = 0 
						s.airboostimmune = 7
						if not ((p.pflags & PF_ANALOGMODE) and p.cmd.sidemove) //Don't ruin the illusion, you fool.
						s.airboostroll = 9
						end
						A_SMSquake(s, 32*FRACUNIT, 4)
						end
						p.sms_didairboost = 1
						p.hometrickanim = false
						if (p.pflags & PF_DIRECTIONCHAR) and not (p.pflags & PF_ANALOGMODE)
						s.forcesmsangletimer = 8
						s.forcesmsangle = s.angle
						end
							if not (s.eflags & MFE_UNDERWATER)
								p.smsarboost = P_SpawnMobj(s.x, s.y, s.z+((20*FRACUNIT)*(P_MobjFlip(s))), MT_SMSAIRBOOST)
								p.smsarboost.tracer = s
								if (P_MobjFlip(s) == 1)
								p.smsarboost.z = $+11*FRACUNIT
								end
								S_StartSound(s, sfx_sarb)
								//Airboost voice RNG. Different from Blinddash version.
									if not s.smsabsfx
									local sfxrng = P_RandomRange(1,20)
										s.smsabsfx = 25
										if sfxrng < 11
										S_StartSound(s, sfx_smsha4)
										elseif sfxrng < 16
										S_StartSound(s, sfx_smsha5)
										elseif sfxrng < 18 and not (s.lastbdsfx and s.lastbdsfx > 15 and s.lastbdsfx < 18)
										S_StartSound(s,sfx_smsha2)
										elseif sfxrng < 20
										S_StartSound(s,sfx_smsha1)
										else
										S_StartSound(s,sfx_smsha2)
										end
									s.lastbdsfx = sfxrng --We can just reuse the blinddash value here.
									end
							else
								P_SpawnMobj(s.x, s.y, s.z, MT_MEDIUMBUBBLE)
								P_SpawnMobj(s.x, s.y, s.z+10*FRACUNIT, MT_MEDIUMBUBBLE)
								P_SpawnMobj(s.x+5*FRACUNIT, s.y+5*FRACUNIT, s.z+4*FRACUNIT, MT_SMALLBUBBLE)
								S_StartSound(s, sfx_s3k47)
							end
						if (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))

							P_InstaThrust(s, s.angle, 195*FRACUNIT) //CRAZY airboost with runshoes
							P_RadiusAttack(s, s, 192*FRACUNIT)
						elseif (s.eflags & MFE_UNDERWATER)
						and not (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))  //If no runshoes, then...
							P_InstaThrust(s, s.angle, FixedMul(16*FRACUNIT, s.scale)+5*FRACUNIT) //Crappy airboost in water.
						elseif G_GametypeHasSpectators()
							if p.rings
							P_GivePlayerRings(p, -1) //If not underwater and no runshoes in match, take a ring per airboost.
							P_InstaThrust(s, s.angle, FixedMul(90*FRACUNIT, s.scale)+10*FRACUNIT) //Normal airboost
							P_RadiusAttack(s, s, 128*FRACUNIT)
							else
							P_InstaThrust(s, s.angle, FixedMul(43*FRACUNIT, s.scale)+7*FRACUNIT) //Normal airboost for players with no rings.
							P_RadiusAttack(s, s, 50*FRACUNIT)
							end
						else
							P_InstaThrust(s, s.angle, FixedMul(90*FRACUNIT, s.scale)+10*FRACUNIT) //Normal airboost
							P_RadiusAttack(s, s, 128*FRACUNIT)
						end
					end
				end
			    end
			elseif p.sms_tapnothold
				p.sms_tapnothold = 0
			end

			//Waterrunning! Looks like they gave up on removing runonwater after Lua, so there goes the fancy run-on-water custom code...

			if p.homing
			or p.gotflag
			or p.smsdivetimer or s.sdodgeoh
			or (p.pflags & PF_SLIDING) or (s.state == S_PLAY_PAIN)
				p.charflags = $ & ~SF_RUNONWATER
			elseif not (p.charflags & SF_RUNONWATER) and not ((p.pflags & PF_SLIDING) or (s.state == S_PLAY_PAIN))
				p.charflags = $|SF_RUNONWATER
			end

			//When going fast enough, SMS'll slide over the water!

			if (s.eflags & MFE_TOUCHWATER) and (p.speed > FixedMul(75*FRACUNIT, s.scale))
				if not (s.eflags & MFE_UNDERWATER)
				and s.health
				and P_IsObjectOnGround(s)
				and not p.hypermysticsonic
				and not (s.state == S_SMSWATERGRIND1 or s.state == S_SMSWATERGRIND2)
				and not (p.pflags & PF_SPINNING)
				and not (s.eflags & MFE_GOOWATER) //Too much friction on solid water for this.
				and not p.sms_stompanim
				and not p.homing
				and (s.momz == 0) //Only if you're not losing altitude!
				s.state = S_SMSWATERGRIND1
				p.sms_watergrind = 2
				end
			elseif p.sms_watergrind
				p.sms_watergrind = $-1
			end
			if p.sms_watergrind
				if not (p.cmd.forwardmove > 0)
					s.forcesmsangletimer = 2
					s.forcesmsangle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
				end
				if P_IsObjectOnGround(s)
					if (p.speed < FixedMul(76*FRACUNIT, s.scale))
					and (s.eflags & MFE_TOUCHWATER)
						if not p.hypermysticsonic
						and not (s.state == S_PLAY_SPRING)
						s.state = S_PLAY_RUN
						p.sms_watergrind = $-1
						end
					end
				else
				p.sms_watergrind = 0
				end
			end
			if (s.state == S_SMSWATERGRIND1 or s.state == S_SMSWATERGRIND2)
			and ((p.sms_watergrind == 0) or not (s.eflags & MFE_TOUCHWATER)) //How are you grinding on NOTHING?!
			and not (s.state == S_PLAY_SPRING)
			s.state = S_PLAY_RUN
			end

		//Knuckles' walls? ...destroy them.
		//Essentially gives SMS a Knuckles-powered spindash/boost/footsweep/airboost

			//Spinning doesn't take care of breakable walls in the air, we'll have the airboost break walls for us too.

			if ((((p.pflags & PF_SPINNING) or (p.sms_boostlevel >= 65)) and P_IsObjectOnGround(s)) or p.sms_didairboost or p.footsweepanim)
				if not (p.pflags & PF_STARTDASH)
				and not (p.pflags & PF_JUMPED)
				and not p.homing
					p.charflags = $|SF_CANBUSTWALLS
				//	p.charability = CA_GLIDEANDCLIMB
				//	p.sms_breakwalls = 1
				end
			elseif not (p.pflags & PF_SPINNING)
			and not p.footsweepanim and not p.sms_didairboost
				p.sms_breakwalls = 0
				p.charflags = $|SF_CANBUSTWALLS
				p.charability = CA_THOK
			end
			if p.sms_breakwalls
				if ((p.pflags & PF_JUMPED) or (P_IsObjectOnGround(s) and not ((p.pflags & PF_SPINNING) or (p.sms_boostlevel >= 65))))
				and not p.footsweepanim
					p.sms_breakwalls = 0
					p.sms_didairboost = 0
					p.charability = CA_THOK
					p.charflags = $ & ~SF_CANBUSTWALLS
				end
			end

//Pow! Stomp attack, SMS version!

			if (p.sms_stompanim or p.sms_afterstompthok)
				if P_PlayerInPain(p) or p.powers[pw_carry]
				p.sms_stompanim = 0
				p.sms_afterstompthok = false
				end
				p.charflags = $|SF_STOMPDAMAGE
			elseif (p.charflags & SF_STOMPDAMAGE)
				p.charflags = $ & ~SF_STOMPDAMAGE
			end
			if s.sms_juststomped
			s.sms_juststomped = $-1
			end
			if (p.cmd.buttons & BT_CUSTOM2)
				p.smsmeleebutton = $+1
			elseif p.smsmeleebutton
				p.smsmeleebutton = 0
			end
			if (p.cmd.buttons & BT_CUSTOM2)
				p.smsmeleebutton2 = $+1
			elseif p.smsmeleebutton2
				p.smsmeleebutton2 = 0
			end

			if (p.cmd.buttons & BT_CUSTOM2) //SMS stomp
				if (p.pflags & PF_JUMPED) //Only during regular jumps
				or p.sms_didairboost or p.hometrickanim
					if not p.hypermysticsonic //Not HMS? Get a lame stomp, then.
					and not (p.smsmeleebutton > 1) and s.health
					and not (s.eflags & MFE_GOOWATER) //This stops swimming in goo water
					and not p.sms_afterstompthok
					and not (p.pflags & (PF_SLIDING|PF_STASIS))
					and not (p.powers[pw_carry]) and not s.smsstompcd
					and not (s.state == S_PLAY_PAIN) and not (s.state == S_PLAY_RIDE)
					and not p.gotflag and not p.readyready
					and not s.sms_juststomped
					and not p.sms_comethaymaker and not p.mslightspeedattack
					and not (s.smscmphret and p.smseasyhaymaker)
					and not (p.cmd.buttons & BT_CUSTOM1 and not p.smseasyhaymaker and (p.cmd.forwardmove < 0) and (p.smsmeleebutton < 17) and (p.sms_boostlevel >= 64) and not (p.cmd.sidemove < 0) and not (p.cmd.sidemove > 0) and not p.ringburstfly)
					and not p.sms_dodging and not p.smsblastboost and not p.sms_intoship
					and not p.homing //Not when homing on enemies!
						if not (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))
						and not (s.eflags & MFE_UNDERWATER)
						and not (s.scale >= 2*FRACUNIT)
							if (s.momz >= FixedMul(-30*FRACUNIT, s.scale)) //Already going down fast? Then don't keep setting this.
								P_SetObjectMomZ(s, -30*FRACUNIT)
								p.pflags = $|PF_JUMPED & ~PF_SPINNING
								S_StartSound(s, sfx_stst)
								s.stompanimburst = 16
							else
								P_SetObjectMomZ(s, -12*FRACUNIT, 1) //Add some relative speed.
								p.pflags = $|PF_JUMPED & ~PF_SPINNING
								S_StartSound(s, sfx_stst)
								s.stompanimburst = 16
							end
						elseif (s.momz >= FixedMul(-14*FRACUNIT, s.scale))
						and (s.eflags & MFE_UNDERWATER)
						and not (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))
						and not (s.scale >= 2*FRACUNIT)
								P_SetObjectMomZ(s, -14*FRACUNIT)
								p.pflags = $|PF_JUMPED & ~PF_SPINNING
								S_StartSound(s, sfx_splash)
								P_SpawnMobj(s.x, s.y, s.z, MT_MEDIUMBUBBLE)
								P_SpawnMobj(s.x, s.y+3*FRACUNIT, s.z-4*FRACUNIT, MT_SMALLBUBBLE)
						elseif (s.momz >= FixedMul(-60*FRACUNIT, s.scale))
						and (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms)) or (s.scale >= 2*FRACUNIT)
								P_SetObjectMomZ(s, -60*FRACUNIT)
								p.pflags = $|PF_JUMPED & ~PF_SPINNING
								S_StartSound(s, sfx_stst)
						end
						if p.sms_ringburstfly
						p.sms_ringburstfly = 0
						P_InstaThrust(s, s.angle, 0)
						end
						p.sms_stompanim = $+1
					end
				end
			end

			if p.sms_stompanim
			p.smsmeleebutton = 850
				if p.sms_afterstompthok
				p.sms_stompanim = 0 
				end
				if (((s.state == 23) or (s.state == S_PLAY_ROLL)) and (p.pflags & PF_JUMPED))
				or p.hometrickanim or (s.state == S_SMS_AIRBOOST)
				p.pflags = $ & ~PF_JUMPED
				p.hometrickanim = false
				s.state = S_SMS_STOMP1
				P_SpawnGhostMobj(s)
				end

				//SMS can still thok out of a stomp!

				if ((s.state == S_SMS_STOMP1) or (s.state == S_SMS_STOMP2))
				and p.sms_stompanim
					if (p.cmd.buttons & BT_JUMP)
					and not (p.sms_jumphold and p.sms_jumphold > 1)
					and not (s.eflags & MFE_JUSTHITFLOOR)
					and not P_IsObjectOnGround(s)
					and not (s.state == S_PLAY_SPRING)
						if not p.powers[pw_carry]
						s.state = S_PLAY_ROLL
						p.pflags = $|PF_JUMPED & ~PF_JUMPDOWN & ~PF_THOKKED
						end
						p.sms_stompanim = 0
						p.hometrickanim = false
						p.sms_afterstompthok = true
					end
				end
			end

			if ((s.state == S_SMS_STOMP1) or (s.state == S_SMS_STOMP2)) and not p.hypermysticsonic
				if (s.eflags & MFE_GOOWATER)
				p.sms_stompanim = 0
				p.hometrickanim = false
				p.sms_afterstompthok = false
				s.state = S_SMS_ADVFALL1
				end
				if not p.sms_stompanim and not p.powers[pw_carry]
					if not P_IsObjectOnGround(s)
					p.pflags = $|PF_JUMPED
					s.state = S_PLAY_ROLL
					else
					s.state = S_PLAY_RUN
					end
				end
			end

			if (p.sms_stompanim or p.sms_afterstompthok)
			and s.health //Let's make sure NONE of this works....
			p.charflags = $ & ~SF_RUNONWATER 
				if s.stompanimburst
					if (s.stompanimburst % 2 == 0) and not P_IsObjectOnGround(s) and not (s.eflags & MFE_UNDERWATER)
						s.hmsstompr = P_SpawnMobj(s.x+s.momx, s.y+s.momy, s.z+(s.stompanimburst*FRACUNIT)*P_MobjFlip(s), MT_HMSSTOMPAURA)
						if (s.stompanimburst > 10)
						s.hmsstompr.scale = (s.scale*2)*s.stompanimburst/8
						else
						s.hmsstompr.scale = (s.scale*2)*10/8
						end
						s.hmsstompr.eflags = s.eflags
						s.hmsstompr.target = s
						if (s.stompanimburst > 14)
						s.hmsstompr.frame = P_RandomRange(5,7)|FF_FULLBRIGHT|TR_TRANS40
						s.hmsstompr.color = SKINCOLOR_FLAME
						s.hmsstompr.z = $+19*FRACUNIT*P_MobjFlip(s)
						elseif (s.stompanimburst < 6)
						s.hmsstompr.frame = P_RandomRange(5,7)|FF_FULLBRIGHT|TR_TRANS70
						s.hmsstompr.color = SKINCOLOR_EMERALD
						else
						s.hmsstompr.frame = P_RandomRange(5,7)|FF_FULLBRIGHT|TR_TRANS60
						s.hmsstompr.color = s.color
						end
							s.hmsstompr.ghostaura = P_SpawnGhostMobj(s.hmsstompr)
							s.hmsstompr.ghostaura.destscale = s.hmsstompr.ghostaura.scalespeed+1
							if not (s.z > s.floorz+60*FRACUNIT)
							s.hmsstompr.ghostaura.tics = 6
							end
							s.hmsstompr.ghostaura.momz = s.momz*-1/2
					end
					s.stompanimburst = $-1
				end
				if not (s.eflags & MFE_JUSTHITFLOOR)
					if not ( ((s.state == S_SMS_STOMP1) or (s.state == S_SMS_STOMP2)) or p.pflags & PF_JUMPED)
					or (s.eflags & MFE_GOOWATER)
						if not (s.state == S_PLAY_FALL and p.pflags & PF_THOKKED)
						p.sms_stompanim = 0
						p.sms_afterstompthok = false
						end
					end
				end

				P_RadiusAttack(s, s, FixedMul(114*FRACUNIT, s.scale))
				if (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))
					P_NukeEnemies(s, s, FixedMul(128*FRACUNIT, s.scale))
				end
				if (s.eflags & MFE_UNDERWATER)
				and not (s.eflags & MFE_JUSTHITFLOOR)
				and not P_IsObjectOnGround(s)
				and (p.lddiscount and p.lddiscount == 2)
				P_SpawnPlayerMissile(s, MT_MEDIUMBUBBLE) //(s.x, s.y, s.z, MT_MEDIUMBUBBLE)
				p.smsstmpbbl = P_SpawnMobj(s.x-20*FRACUNIT, s.y-20*FRACUNIT, s.z+2*FRACUNIT, MT_SMALLBUBBLE)
				p.smsstmpbbl.scale = s.scale
				p.smsstmpbbl = P_SpawnMobj(s.x+20*FRACUNIT, s.y+20*FRACUNIT, s.z+2*FRACUNIT, MT_SMALLBUBBLE)
				p.smsstmpbbl.scale = s.scale
				end

				if p.powers[pw_nocontrol]
				or (s.state == S_PLAY_PAIN)
				or p.homing //Homing won't naturally cancel out SMS' stomp, so I'll have to do that manually
				or (p.pflags & PF_SLIDING) //Don't get stuck stomping in water currents
				p.sms_stompanim = 0
				p.sms_afterstompthok = false
				end

				//You're going up while stomping? ...huh? Well, cancel that ticket then

				if ( ((P_MobjFlip(s) == -1) and (s.momz < -9001)) or ((P_MobjFlip(s) == 1) and (s.momz > 9001)) )
				and not p.powers[pw_nocontrol]
				and not (p.sms_wallstat and p.sms_wallstat >= 60) //Disables this from happening during walljumps.
				p.sms_stompanim = 0
				p.sms_afterstompthok = false
					if not p.powers[pw_carry]
					p.pflags = $|PF_JUMPED
					end
					if p.scoreadd
					P_SetObjectMomZ(s, -12*FRACUNIT)
					end
				end

				if (s.eflags & MFE_JUSTHITFLOOR)				
					local sectorz = R_PointInSubsector(s.x, s.y).sector //Stomp 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)						
							P_SetObjectMomZ(s, -32*FRACUNIT)
							p.pflags = $|PF_JUMPED & ~PF_SPINNING
							if not p.hypermysticsonic
							s.state = S_SMS_STOMP1
							end
							p.sms_stomplandcancel = true
							end
						end
						
						if (p.powers[pw_shield] == (SH_ELEMENTAL) or p.powers[pw_shield] == (SH_ELEMENTAL|SH_FIREFLOWER))
						or (p.powers[pw_shield] == (SH_FLAMEAURA) or p.powers[pw_shield] == (SH_FLAMEAURA|SH_FIREFLOWER))
						P_ElementalFire(p, true)
							if not (s.eflags & MFE_UNDERWATER)
							S_StartSound(s, sfx_s3k47) S_StartSound(s, sfx_s3k47) S_StartSound(s, sfx_s3k47) //Emulate the shield's stompfire since SMS already has a stomp of his own
							end
						end
						if s.battlemodsms and (p.speed < 90*FRACUNIT) and not (p.sms_boostlevel >= 65) //Battlemod stomp anti-spam.
							p.sms_wallstat = 50 
							s.retmhtsfx = 48
							s.smsstompcd = 15
							p.sms_flamedelay = 10
							P_SetObjectMomZ(s, 5*FRACUNIT)
							p.pflags = $|PF_JUMPDOWN
							s.state = S_PLAY_ROLL
							P_SpawnGhostMobj(s)
							s.momx = $/2
							s.momy = $/2
						end						
						if p.sms_stomplandcancel
						p.sms_stomplandcancel = false
						else
							p.sms_stompanim = 0
							s.sms_juststomped = 6
							
								if not (s.eflags & MFE_UNDERWATER)
								A_SMSSTOMPQUAKE(s, 45, 14, FRACUNIT, 0, 0, 0, 0, SKINCOLOR_SUPERRED4)
								A_SMSSTOMPQUAKE(s, 65, 16, 2*FRACUNIT, 0, ANG10)
								A_SMSSTOMPQUAKE(s, 85, 18, 3*FRACUNIT, 0, ANG20, 0, 0, SKINCOLOR_SUPERSILVER4)
								end
								if (s.scale >= FRACUNIT/2)
								and ((p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms))
								or (s.scale >= 2*FRACUNIT) or (p.sms_stompanim >= 9001))
								S_StartSound(s, sfx_brakrx)
								A_SMSSTOMPSMOKE(s, 18, MT_SMMK)
								A_SMSquake(s, 38*FRACUNIT, 8, 2300)
								P_RadiusAttack(s, s, 400*FRACUNIT)
								elseif (s.eflags & MFE_UNDERWATER)
								S_StartSound(s, sfx_s3k7d) //Make bubbles spawn when SMS hits the floor!
								A_SMSSTOMPSMOKE(s, 13, MT_SMALLBUBBLE)
								A_SMSSTOMPQUAKE(s, 45, 15, 4*FRACUNIT, 0, 0, 0, 0, 0, MT_SMALLBUBBLE)
								A_SMSSTOMPQUAKE(s, 25, 15, 4*FRACUNIT, 0, 0, 0, 0, 0, MT_MEDIUMBUBBLE)
								else
								S_StartSound(s, sfx_s3k77) //Make dust clouds spawn around SMS when he hits the floor.
								A_SMSSTOMPSMOKE(s, 8, MT_SMMK)
								A_SMSquake(s, 7*FRACUNIT, 2, 700, true)
								P_RadiusAttack(s, s, 64*FRACUNIT)
								end
						end
				end
			end

		//Pow! Stomp Attack, HMS version!

			if (p.hypermysticsonic > 40) //No HMS? No HMS stomp.
			and (p.cmd.buttons & BT_CUSTOM2)
			and not p.powers[pw_carry]
				if (p.pflags & PF_JUMPED) 
					if not (p.cmd.buttons & BT_CUSTOM1 and (p.cmd.forwardmove < 0) and (p.smsmeleebutton < 17) and not (p.cmd.sidemove < 0) and not (p.cmd.sidemove > 0))
					and not (p.pflags & PF_SLIDING)
					and not p.hmsblackhole
					and not p.sms_comethaymaker
					and not (p.novafire > 37)
					and not p.starthmscombo
					and not (p.cmd.buttons & (BT_WEAPONPREV|BT_JUMP|BT_TOSSFLAG))
					and not P_IsObjectOnGround(s) //What would this even achieve?
						s.hms_jumprisen = 0
						if not s.hmsspinfreeze and not (p.cmd.buttons & BT_TOSSFLAG)
						s.rollangle = ANGLE_180
						s.hmsroflstomped = true
						end
						if (s.momz*P_MobjFlip(s) >= FixedMul(-27*FRACUNIT, s.scale))
						P_SetObjectMomZ(s, FixedMul(-27*FRACUNIT, s.scale))
						end
						if not s.hmsstompsfx
						
						
						s.hmsstompsfx = true
						if not s.haltthespam
						and not p.smsgraphix
						s.novawave = P_SpawnMobj(s.x, s.y, s.z+s.height, MT_HMSNOVAWAVE) 
						s.novawave.scale = s.scale*10/P_RandomRange(9,15)
						A_SMSSTOMPSMOKE(s, P_RandomRange(10,30), MT_DUST)
						A_SMSSTOMPSMOKE(s, 20, MT_ENERGYBALL, 200)
						end
						P_SetObjectMomZ(s, FixedMul(-9*FRACUNIT, s.scale), true)
						S_StartSound(s, sfx_stst)
						s.haltthespam = 5
							if (s.momz*P_MobjFlip(s) < 0)
							A_SMSquake(s, (s.momz*-1)/2, ((s.momz*-1)/FRACUNIT)/12)
							end
						end
						if not (s.eflags & MFE_GOOWATER)
						and not (p.smsgraphix and p.smsgraphix == 2)
							if (leveltime % 2 == 0)
							A_SMSSTOMPSMOKE(s, P_RandomRange(12,40), MT_BOSSEXPLODE)
							end
							if (leveltime % 3 == 0)
								if P_RandomRange(0,1)
								P_NukeEnemies(s, s, FixedMul(400*FRACUNIT, s.scale))
								else
								A_SMSSTOMPSMOKE(s, P_RandomRange(12,20), MT_WATERZAP)
								end
							end
						end
						if (leveltime % 2 == 0)
							s.hmsstompr = P_SpawnMobj(s.x+s.momx, s.y+s.momy, s.z, MT_HMSSTOMPAURA)
							s.hmsstompr.scale = (s.scale*2)*10/P_RandomRange(4,8)
							if (s.hmsstompr.scale <= s.scale*2*10/7)
							s.hmsstompr.z = $-14*FRACUNIT*P_MobjFlip(s)
							elseif (s.hmsstompr.scale >= s.scale*2*10/5)
							s.hmsstompr.z = $+9*FRACUNIT*P_MobjFlip(s)
							end
							s.hmsstompr.eflags = s.eflags
								if (s.eflags & MFE_VERTICALFLIP)
								s.hmsstompr.z = $-FixedMul(20*FRACUNIT, s.scale)
								end
							s.hmsstompr.target = s
							s.hmsstompr.color = P_RandomRange(SKINCOLOR_SUPERORANGE1, SKINCOLOR_SUPERORANGE5)
							s.hmsstompr.frame = P_RandomRange(5, 7)|FF_FULLBRIGHT|TR_TRANS30
							
										s.hmsstompr.ghostaura = P_SpawnGhostMobj(s.hmsstompr)
										s.hmsstompr.ghostaura.scalespeed = $/2
										s.hmsstompr.ghostaura.destscale = s.hmsstompr.ghostaura.scalespeed+1
										s.hmsstompr.ghostaura.momx = s.momx/2
										s.hmsstompr.ghostaura.momy = s.momy/2
										s.hmsstompr.ghostaura.tics = 5
										s.hmsstompr.ghostaura.momz = $+10*FRACUNIT*P_MobjFlip(s)
										
						else
							s.hmsstompr = P_SpawnMobj(s.x+s.momx, s.y+s.momy, s.z, MT_HMSSTOMPAURA)
							s.hmsstompr.scale = (s.scale*2)*10/P_RandomRange(4,9)
							s.hmsstompr.eflags = s.eflags
								if (s.eflags & MFE_VERTICALFLIP)
								s.hmsstompr.z = $-FixedMul(20*FRACUNIT, s.scale)
								end
							s.hmsstompr.target = s
							s.hmsstompr.color = P_RandomRange(SKINCOLOR_SUPERRED1, SKINCOLOR_SUPERGOLD5)
							s.hmsstompr.frame = T|FF_FULLBRIGHT|TR_TRANS40
						end
						
						
						s.sprintghost = P_SpawnGhostMobj(s)
						s.sprintghost.rollangle = s.rollangle
						if not s.hmsspinfreeze and not (p.cmd.buttons & BT_TOSSFLAG)
						s.hmsspinpass = 8
						end
						if s.hmsspinpass and s.hmsspinang != nil
						s.sprintghost.angle = s.hmsspinang
						end
						p.hms_stompbreak = $+1
					else
						p.hms_stompbreak = 0
					end
				end
				if ( (p.hms_stompbreak > 2) or (p.speed > FixedMul(137*FRACUNIT, s.scale)))
				and (s.eflags & MFE_JUSTHITFLOOR)
				and not A_HMSCheckDeathPit(s)
					local sectorz = R_PointInSubsector(s.x, s.y).sector //Stomp 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)						
							P_SetObjectMomZ(s, -32*FRACUNIT)
							p.pflags = $|PF_JUMPED & ~PF_SPINNING
							end
					end
					A_SMSSTOMPQUAKE(s, 45, 6, 8*FRACUNIT, 0, 0, 0, 20, SKINCOLOR_SUPERRED4)
					A_SMSSTOMPQUAKE(s, 85, 8, 15*FRACUNIT, 0, ANG10, 0, 20)
					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)
				
					S_StartSound(s, sfx_spld)
					A_SMSSTOMPSMOKE(s, 15, MT_BOSSEXPLODE)
					A_SMSquake(s, 55*FRACUNIT, 13, 3400)
					p.spld = P_SpawnMobj(s.x+FixedMul(100*FRACUNIT, cos(s.angle)), s.y+FixedMul(100*FRACUNIT, sin(s.angle)), s.z, MT_HMSSTOMPEXPLODE)
					p.spld.target = s
					p.spld = P_SpawnMobj(s.x+FixedMul(-100*FRACUNIT, cos(s.angle)), s.y+FixedMul(-100*FRACUNIT, sin(s.angle)), s.z, MT_HMSSTOMPEXPLODE)
					p.spld.target = s
					p.spld = P_SpawnMobj(s.x+FixedMul(-100*FRACUNIT, cos(s.angle)), s.y+FixedMul(100*FRACUNIT, sin(s.angle)), s.z, MT_HMSSTOMPEXPLODE)
					p.spld.target = s
					p.spld = P_SpawnMobj(s.x+FixedMul(100*FRACUNIT, cos(s.angle)), s.y+FixedMul(-100*FRACUNIT, sin(s.angle)), s.z, MT_HMSSTOMPEXPLODE)
					p.spld.target = s
					s.sms_juststomped = 2
					P_NukeEnemies(s, s, FixedMul(777*FRACUNIT, s.scale))
					p.hms_stompbreak = 0
				end

			   //Little feature that lets HMS float like Super Sonic. Not that useful, but hey, who knows?

			   if (p.cmd.buttons & BT_TOSSFLAG) or ((p.cmd.buttons & BT_JUMP) and s.hms_jumprisen)
			   and (p.pflags & PF_JUMPED)
			   and not P_IsObjectOnGround(s)
			    if s.hmsspinpass or s.hmsroflstomped
				s.hmsroflstomped = false
				s.hmsstompsfx = false
				s.rollangle = 0
				s.hmsspinpass = 0
				end
			    s.hms_jumprisen = 2
			   	s.hmgodticket = true
				P_SetObjectMomZ(s, 0)
			   end
			elseif s.hmsstompsfx
			s.hmsstompsfx = false
			end 

//Hold Spindash in midair to homing attack!
//This used to be LUA_HMAT

			if p.sms_wallturnaround
			s.angle = s.angle + ANGLE_180 //Turn around if holding backwards.
			p.sms_wallturnaround = 0
			end
			if (p.cmd.buttons & BT_JUMP)
				p.sms_jumphold = $+1
			elseif p.sms_jumphold
				p.sms_jumphold = 0
			end

			if ((s.flags2 & MF2_TWOD) or twodlevel)
			and (p.homing or p.sms_wallstat or p.smsrdash)
			s.momy = 0 // Prevent 2D shifts into 3D by accident.
			end

			if p.homing and (p.homing > 5)
			p.homingtrickcharge = 4
				if s.battlemodsms and s.tracer and ((s.tracer.type == MT_PLAYER) or (s.tracer.type == MT_TARGETDUMMY)) //We're going after a target dummy? ...kay then.
					if (p.homing > 49) //It hurts how broken the homing attack is in battlemod. SMS is a superform, but we STILL need to nerf it
					S_StartSound(s, sfx_s3k72)
					P_InstaThrust(s, s.angle, 0*FRACUNIT)
					P_SetObjectMomZ(s, 2*FRACUNIT)
					s.ghs = P_SpawnMobj(s.x, s.y, s.z, MT_BURSTLIGHT)
					s.ghs.color = s.color
					p.homing = 49
					S_StartSound(s, sfx_spndsh)
					elseif (p.homing > 41)
					P_InstaThrust(s, s.angle, -FRACUNIT)
					P_SetObjectMomZ(s, FRACUNIT, false)
					elseif (p.homing == 41)
						s.playerhomecharge = true
						S_StartSound(s, sfx_cdfm62)
						if not (s.tracer and (FixedHypot(FixedHypot(s.x-s.tracer.x, s.y-s.tracer.y), s.z-s.tracer.z) < 900*FRACUNIT))
						P_InstaThrust(s, s.angle, 40*FRACUNIT)
						P_SetObjectMomZ(s, -20*FRACUNIT, false)
						p.homing = 0
						s.playerhomecharge = false
						s.playerhomechargefail = 21		
						end
					end
				
				
			 	elseif (s.eflags & MFE_UNDERWATER)
				s.momx = $*5/7 s.momy = $*5/7 s.momz = $*5/7
				elseif (s.z-(s.momz*5/3) > s.floorz) and not p.hometrickanim
				s.momx = $*5/3 s.momy = $*5/3 s.momz = $*5/3 //Home faster than your average homing attack!
				end
			elseif s.playerhomechargefail
				s.playerhomechargefail = $-1
				if P_IsObjectOnGround(s)
					s.playerhomechargefail = 0
					s.flags2 = $|MF2_DONTDRAW
					s.momx = $/2
					s.momy = $/2
					A_SMSSTOMPSMOKE(s, 18, MT_SPINDUST)
					A_SMSSTOMPSMOKE(s, 38, MT_SPINDUST)
					P_SetObjectMomZ(s, 4*FRACUNIT, false)
					S_StartSound(s, sfx_cdfm14)
					p.pflags = $|PF_JUMPED|PF_THOKKED & ~PF_SPINNING
					s.state = S_PLAY_ROLL	
				end
			elseif s.playerhomecharge
				if s.battlemodsms and p.homing and (p.homing == 1) and (p.pflags & PF_JUMPED)
				P_SpawnGhostMobj(s)
				s.state = S_PLAY_FALL
				p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED
				end
				if s.tracer and ((s.tracer.type == MT_PLAYER) or (s.tracer.type == MT_TARGETDUMMY))
					if not P_IsObjectOnGround(s)
						P_SetObjectMomZ(s, 10*FRACUNIT, false)
						if ((s.state == S_PLAY_FALL) or (p.panim == PA_FALL))
							p.sms_wallstat = 50 //You screwed up. Apply cooldown
							s.retmhtsfx = 48
							s.smsstompcd = 15
							P_InstaThrust(s, R_PointToAngle2(s.x, s.y, s.tracer.x, s.tracer.y), -16*FRACUNIT)
							p.sms_flamedelay = 15 //Set this or it'll become the new meta instead.
							p.powers[pw_nocontrol] = 0
							s.recoilthrust = 0 //I'll do this manually, thanks
							p.pflags = $|PF_JUMPED|PF_THOKKED
							s.state = S_PLAY_ROLL
						else
						p.sms_wallstat = 50 //You screwed up. Apply cooldown
						s.retmhtsfx = 48
						s.smsstompcd = 15
						p.pflags = $|PF_JUMPED|PF_THOKKED
						s.state = S_PLAY_ROLL
					//	s.forcesmstrick = true				
					//	if (s.momz*P_MobjFlip(s) > (FixedMul(10*FRACUNIT, s.scale)))
						end				
					end
				end
				s.playerhomecharge = false
			end
			if p.homingtrickcharge
			p.homingtrickcharge = $-1
			end

			if p.hometrickanim
				p.smstricktrail = P_SpawnMobj(s.x, s.y, s.z-((6*FRACUNIT)*(P_MobjFlip(s))), MT_SMSHOMINGTAURA)
					if p.smstricktrail
					p.smstricktrail.scale = s.scale*25/16
					p.smstricktrail.scalespeed = $+300
					p.smstricktrail.target = s
					A_SetScale(p.smstricktrail, 10, 1)
						if ((p.smscoatc5 and p.smscoatc5 == SKINCOLOR_GREY) or (s.color >= SKINCOLOR_CARBON and s.color <= SKINCOLOR_BLACK) or (s.color >= SKINCOLOR_RUBY and s.color <= SKINCOLOR_KETCHUP))
						A_ChangeColorAbsolute(p.smstricktrail, 0, SKINCOLOR_SUPERGOLD4)
						elseif (s.color != 0) and not SMSisyellow(s)
						A_ChangeColorAbsolute(p.smstricktrail, 0, s.color)
						else
						p.smstricktrail.color = SKINCOLOR_BONE
						end
					end
				if not ((s.state >= S_SMS_PREHOMET1) and (s.state <= S_SMS_SIDET))
				or (P_IsObjectOnGround(s) and (s.eflags & MFE_JUSTHITFLOOR))
				or p.hypermysticsonic
				p.hometrickanim = false
				p.homingtrickcharge = 0
				end
			end
			if not P_IsObjectOnGround(s)
			and not p.hypermysticsonic //No Homing Attack when HMS!
			and ((p.cmd.buttons & BT_USE) or p.homing)
			and not (s.state == S_PLAY_RIDE) //prevents a weird animation glitch.
					if (p.pflags & PF_JUMPED) or p.hometrickanim  //No reason for it to work on the floor.
					and not (p.sms_stompanim or p.sms_afterstompthok)
					and not p.smsblastboost
						p.charability = CA_HOMINGTHOK
						if (p.sms_wallstat == 0)
						and not p.homing
						p.charflags = $|SF_MULTIABILITY
						end

					else //return thok when SMS
						if not p.hypermysticsonic //Preventing colissions with HMS script
						and not (p.cmd.buttons & BT_USE)
						and not (p.sms_breakwalls)
						and not p.smsblastboost
							p.charability = CA_THOK
							p.charflags = $ & ~SF_MULTIABILITY
						end
					end
			end
			if s.wthudtime //Little visual and audio cue to make walljumping easier.
				if (s.smslastspeedw == nil) or (s.smslastspeedw and (p.speed > s.smslastspeedw/3))
			   	s.smslastspeedw = p.speed
			   	elseif s.smslastspeedw and (p.speed < s.smslastspeedw/3)
				if (s.eflags & MFE_UNDERWATER)				
			   	s.smswd = P_SpawnMobj(s.x, s.y, s.z, MT_MEDIUMBUBBLE)
				else
				s.smswd = P_SpawnMobj(s.x+FixedMul(9*FRACUNIT, cos(s.angle)), s.y+FixedMul(9*FRACUNIT, sin(s.angle)), s.z, MT_EXPLODE)
				end
			   	s.smswd.scale = s.scale
			   	s.smswd.momz = s.momz*3/4
				
					s.smswd = P_SpawnMobj(s.x+FixedMul(15*FRACUNIT, cos(s.angle+ANGLE_90)), s.y+FixedMul(15*FRACUNIT, sin(s.angle+ANGLE_90)), s.z+(s.height/2), MT_SPINDUST)
						s.smswd.scale = s.scale*2
						if (s.eflags & MFE_UNDERWATER)
						s.smswd.state = S_SPINDUST_BUBBLE1
						elseif (leveltime % 2 == 0)	
						s.smswd.state = S_SPINDUST3
						end
						s.smswd.frame = $|TR_TRANS60
						
						
					s.smswd = P_SpawnMobj(s.x-FixedMul(15*FRACUNIT, cos(s.angle+ANGLE_90)), s.y-FixedMul(15*FRACUNIT, sin(s.angle+ANGLE_90)), s.z+(s.height/2), MT_SPINDUST)
						s.smswd.scale = s.scale*2
						if (s.eflags & MFE_UNDERWATER)
						s.smswd.state = S_SPINDUST_BUBBLE1
						elseif (leveltime % 2 == 0)	
						s.smswd.state = S_SPINDUST3
						end
						s.smswd.frame = $|TR_TRANS60
				
						S_StartSound(s, sfx_s3k7e)
						
			   	s.smslastspeedw = nil
				s.wthudtime = false
			   	end
				if P_IsObjectOnGround(s) or p.hypermysticsonic or not (p.pflags & PF_JUMPED)
				or (p.pflags & (PF_THOKKED|PF_SPINNING|PF_SLIDING)) or p.homing
				s.wthudtime = false
				end
			end

			if p.sms_wallstat
			   if (p.pflags & PF_JUMPED)		   
				if not (p.pflags & PF_THOKKED) and not s.retmhtsfx
				s.retmhtsfx = 50
				elseif not (p.pflags & PF_THOKKED)
				//	A_BossScream(s, 0, MT_SMSTSPARK) --Old boring function
				s.smswd = P_SpawnMobj(s.x+FixedMul(9*FRACUNIT, cos(s.angle+ANGLE_90)), s.y+FixedMul(9*FRACUNIT, sin(s.angle+ANGLE_90)), s.z+(s.height/3), MT_THOK)
						s.smswd.scale = s.scale
						s.smswd.destscale = 5
						s.smswd.momx = s.momx/2
						s.smswd.momy = s.momy/2
						if ((p.smscoatc5 and p.smscoatc5 == SKINCOLOR_GREY) or (s.color >= SKINCOLOR_CARBON and s.color <= SKINCOLOR_BLACK) or (s.color >= SKINCOLOR_RUBY and s.color <= SKINCOLOR_KETCHUP))
							s.smswd.color = SKINCOLOR_SUPERGOLD3
						else
							s.smswd.color = s.color
						end
						s.smswd.frame = $|TR_TRANS80 & ~TR_TRANS70 & ~TR_TRANS60
						
					s.smswd = P_SpawnMobj(s.x-FixedMul(9*FRACUNIT, cos(s.angle+ANGLE_90)), s.y-FixedMul(9*FRACUNIT, sin(s.angle+ANGLE_90)), s.z+(s.height/3), MT_THOK)
						s.smswd.scale = s.scale
						s.smswd.destscale = s.smswd.scalespeed+1
						s.smswd.momx = s.momx/2
						s.smswd.momy = s.momy/2
						if ((p.smscoatc5 and p.smscoatc5 == SKINCOLOR_GREY) or (s.color >= SKINCOLOR_CARBON and s.color <= SKINCOLOR_BLACK) or (s.color >= SKINCOLOR_RUBY and s.color <= SKINCOLOR_KETCHUP))
							s.smswd.color = SKINCOLOR_SUPERGOLD3
						else
							s.smswd.color = s.color
						end
						s.smswd.frame = $|TR_TRANS80 & ~TR_TRANS70 & ~TR_TRANS60
				elseif s.retmhtsfx and (p.pflags & PF_THOKKED)
				s.retmhtsfx = $-1
					if (s.retmhtsfx == 46)
					S_StartSound(s, sfx_s238)
					end
					if (s.retmhtsfx < 46)
					s.smswd = P_SpawnMobj(s.x+FixedMul(15*FRACUNIT, cos(s.angle+ANGLE_90)), s.y+FixedMul(15*FRACUNIT, sin(s.angle+ANGLE_90)), s.z+(s.height/2), MT_SPINDUST)
						s.smswd.scale = s.scale
						if (s.eflags & MFE_UNDERWATER)
						s.smswd.state = S_SPINDUST_BUBBLE1
						elseif (leveltime % 2 == 0)	
						s.smswd.state = S_SPINDUST3
						end
						s.smswd.frame = $|TR_TRANS60
						
						
					s.smswd = P_SpawnMobj(s.x-FixedMul(15*FRACUNIT, cos(s.angle+ANGLE_90)), s.y-FixedMul(15*FRACUNIT, sin(s.angle+ANGLE_90)), s.z+(s.height/2), MT_SPINDUST)
						s.smswd.scale = s.scale
						if (s.eflags & MFE_UNDERWATER)
						s.smswd.state = S_SPINDUST_BUBBLE1
						elseif (leveltime % 2 == 0)	
						s.smswd.state = S_SPINDUST3
						end
						s.smswd.frame = $|TR_TRANS60
					end
				end
				
				if p.sms_wallstat == 1 and (p.pflags & PF_THOKKED)
				S_StartSound(s, sfx_cdfm50)
				s.tcs = P_SpawnMobj(s.x, s.y, s.z, MT_THUNDERCOIN_SPARK)
				s.retmhtsfx = 0
					if s.tcs and s.tcs.valid
					s.tcs.fuse = 11
					s.tcs.momx = s.momx/2
					s.tcs.momy = s.momy/2
					s.tcs.momz = s.momz/2
					end
				end
				if (p.pflags & PF_DIRECTIONCHAR) and (p.sms_wallstat == 59)
					s.forcesmsangletimer = 2
					s.forcesmsangle = s.angle
				end
			   end
				if P_IsObjectOnGround(s) //If you're on the ground, who cares.
				or p.homing //Are you homing? You'll need your multiability back, then.
				or (s.state == S_PLAY_PAIN) //Got hurt in midair and recovered? Receive multithok!
				or p.powers[pw_carry] //Skillfull players could run into trouble with this.
				p.sms_wallstat = 0
				s.retmhtsfx = 0
				end
			end

			//Fixes a bug where the homing attack's multiability stops SMS from spinjumping
			//Fixes a bug where multiability can be carried over to Speed Thok.

			if (P_IsObjectOnGround(s) or not (p.cmd.buttons & BT_USE)) or p.homing
				p.charflags = $ & ~SF_MULTIABILITY
			end
			if (s.state == S_PLAY_FALL) and not ((s.momz > 17*FRACUNIT) and (s.momz < 22*FRACUNIT))
				if s.tornadoretcharge == nil
				s.tornadoretcharge = 0
				end
				if s.iampickedupbysmshelp or s.cmphttimer
				s.tornadoretcharge = 50
				end
			s.tornadoretcharge = $+1
			elseif s.tornadoretcharge and not (s.state == S_PLAY_FALL)
			s.tornadoretcharge = 0
			end						
			if (p.pflags & PF_THOKKED)
			and not (p.pflags & PF_JUMPED)
			and s.state == S_PLAY_FALL and not p.smsatomicdivefail and not p.powers[pw_carry]
			p.pflags = $|PF_JUMPED
			s.state = S_PLAY_ROLL
			end
			if (s.state == S_PLAY_FALL) and (s.tornadoretcharge == nil or (s.tornadoretcharge < 2)) and not p.powers[pw_nocontrol]
			and (s.momz > 17*FRACUNIT) and not p.hypermysticsonic and not s.iampickedupbysmshelp and not s.cmphttimer
				if not p.lddiscount
				and not (p.lasthomingtrick and p.lasthomingtrick == 1)
					s.state = S_SMS_FLIPT1
					p.lasthomingtrick = 1
				elseif (p.lddiscount == 1)
				and not (p.lasthomingtrick and p.lasthomingtrick == 2)
					s.state = S_SMS_ROLLT1
					p.lasthomingtrick = 2
				elseif not (p.lasthomingtrick and p.lasthomingtrick == 3)
					s.state = S_SMS_PREHOMET1
					p.lasthomingtrick = 3
				else
					s.state = S_SMS_FLIPT1
					p.lasthomingtrick = 1
				end
			p.hometrickanim = true
			p.pflags = $ & ~PF_JUMPED
			p.homingtrickcharge = 0
			end

			//Thok against a wall while holding spin to do a super walljump!


			if not p.hypermysticsonic //No walljump when HMS!
			and not p.homing
			--Add the framejump here
				if P_IsObjectOnGround(s)
				s.smsframejump = 10
				end
				if (p.cmd.buttons & BT_USE)
				and (p.pflags & PF_USEDOWN)
				and not p.smsblastboost
					p.thokitem = MT_SMSWALLJUMP
				else
					p.thokitem = MT_SMSAURATRAIL //return normal thokitem if doing none of these.
				end
				
			//If you're currently homing onto something
			//spawn a different object that doesn't activate a spring-ability.

			elseif p.homing
				if (s.eflags & MFE_UNDERWATER)
				p.thokitem = 0
				A_BossScream(s, 0, MT_SMALLBUBBLE)
				else
				p.thokitem = MT_SMSHOMING
				end
				if (p.powers[pw_sneakers] and (G_PlatformGametype() and not s.battlemodsms)) and p.homing == 104 and s.target  // and s.presmsmomx != nil and s.presmsmomy ~= nil and (s.presmsmomx+s.presmsmomy >= 25*FRACUNIT)
				s.momy = 0
				s.momx = 0
				s.momz = 0
				s.z = s.target.z+s.target.height
				P_TryMove(s, s.target.x, s.target.y, true) //Super instant homing with sneakers!
				end 
				if p.homing == 87
				and (p.speed < 50000)
				p.pflags = $|PF_SPINNING & ~PF_JUMPED
				end
			end

			//Fancy tricks! Yesh!

			if p.homingtrickcharge
			and not p.homing
			and ( ( (p.pflags & PF_JUMPED) and (p.pflags & PF_NOJUMPDAMAGE) // if s.playerhomecharge and P_IsObjectOnGround(s)
			and ((p.speed < 22*FRACUNIT))
			and ( (s.momz > (( (FixedMul(2*FRACUNIT, s.scale)) )*(P_MobjFlip(s)))) or (s.eflags & MFE_UNDERWATER)) ) or s.forcesmstrick )
			s.forcesmstrick = false
			  if ((p.cmd.buttons & BT_CUSTOM1) or (p.autoc1mom and (p.autoc1mom == 1)) or ((p.autoc1mom and (p.autoc1mom == 2)) and (((p.cmd.forwardmove > 25) and not (p.pflags & PF_ANALOGMODE)) or ((p.cmd.sidemove or p.cmd.forwardmove) and (p.pflags & PF_ANALOGMODE)))))
			  and not s.forcesmstrick //Optional homing "momentum"
			  P_Thrust(s, s.angle, 25*FRACUNIT)
			  end
			  if (s.eflags & MFE_UNDERWATER) and not p.powers[pw_carry]
					p.pflags = $|PF_JUMPED &~ PF_NOJUMPDAMAGE & ~PF_THOKKED
					if s.state == S_PLAY_SPRING or s.state == S_PLAY_FALL
					s.state = S_PLAY_ROLL //No cocky tricks underwater.
					end
			  else
			  local smshometrick = P_RandomRange(0, 3)
				if not smshometrick
				and not (p.lasthomingtrick and p.lasthomingtrick == 1)
					s.state = S_SMS_FLIPT1
					p.lasthomingtrick = 1
				elseif (smshometrick == 1)
				and not (p.lasthomingtrick and p.lasthomingtrick == 2)
					s.state = S_SMS_ROLLT1
					p.lasthomingtrick = 2
				elseif (smshometrick == 2)
				and not (p.lasthomingtrick and p.lasthomingtrick == 4)
					s.state = S_SMS_SIDET
					s.rollangle = 0
					p.lasthomingtrick = 4
					s.smstrickroll = true
					s.smstrickrollang = 0
						if s.hmsrotateright
						s.hmsrotateright = false
						else
						s.hmsrotateright = true
						end
				elseif not (p.lasthomingtrick and p.lasthomingtrick == 3)
					s.state = S_SMS_PREHOMET1
					p.lasthomingtrick = 3
				else
					s.state = S_SMS_FLIPT1
					p.lasthomingtrick = 1
				end
				p.hometrickanim = true
				p.pflags = $|PF_JUMPED & ~PF_THOKKED
				p.homingtrickcharge = 0
					if (s.scale > 2*FRACUNIT)
					S_StartSound(s, sfx_brakrx)
					A_SMSSTOMPSMOKE(s, 18, MT_EXPLODE)
					A_SMSquake(s, 16*FRACUNIT, 6, 2800)
					P_RadiusAttack(s, s, 377*FRACUNIT)
					end
			  end
			elseif p.hometrickanim
			and not P_IsObjectOnGround(s)
				p.pflags = $|PF_JUMPED & ~PF_THOKKED
				if (s.state == S_SMS_SIDET) and not s.airboostroll
					if s.smstrickrollang == nil
					s.smstrickrollang = 0
					end
					if s.hmsrotateright
					s.rollangle = $-FixedAngle(16*FRACUNIT)
						if (s.tics < 19) and (s.tics > 5)
						p.drawangle = s.smstrickrollang-FixedAngle(45*FRACUNIT)
						s.smstrickrollang = $-FixedAngle(45*FRACUNIT)
						end
					else
					s.rollangle = $+FixedAngle(16*FRACUNIT)
						if (s.tics < 19) and (s.tics > 5)
						p.drawangle = s.smstrickrollang+FixedAngle(45*FRACUNIT)
						s.smstrickrollang = $+FixedAngle(45*FRACUNIT)
						end
					end
					s.smstrickroll = true
					if s.hmscchange and p.smsg2gfast and p.powers[pw_sneakers]
					s.hmscchange = true
					p.viewrollangle = s.rollangle
					end
					
					if (s.tics <= 2)
					s.rollangle = 0
					s.smstrickrollang = 0
					s.smstrickroll = false
						if (s.tics == 1) and ((s.momz*P_MobjFlip(s)) > 19*FRACUNIT)
						s.state = S_SMS_ROLLT5
						end
					end
				end
				if (p.pflags & PF_NOJUMPDAMAGE)
				p.pflags = $ & ~PF_NOJUMPDAMAGE
				end
				if (p.cmd.buttons & BT_JUMP)
				and not (p.sms_jumphold and p.sms_jumphold > 1) and not p.powers[pw_carry]
					s.state = S_PLAY_ROLL
					p.pflags = $|PF_JUMPED & ~PF_JUMPDOWN & ~PF_THOKKED & ~PF_NOJUMPDAMAGE
					p.hometrickanim = false
				end
			elseif s.smstrickroll
				if not s.airboostroll
				s.rollangle = 0
				end
				s.smstrickroll = false
			end

//Curl up off springs with the spindash button!
//Let's first make a variable so accidental curling up 
//from holding spindash during homing attacks won't happen.

			if ((s.state >= S_SMS_BOOST01) and (s.state <= S_SMS_BOOST04))
			p.smsboostpanim = true
			elseif p.smsboostpanim
			p.smsboostpanim = false
			end
			if (p.cmd.buttons & BT_USE) or (p.cmd.buttons & BT_CUSTOM2) or (p.cmd.buttons & BT_JUMP)
				if (s.state == S_PLAY_SPRING)
				and (p.sms_stompanim or not (p.pflags & PF_JUMPED))
				and not p.exiting and not (p.pflags & PF_GAMETYPEOVER) and not p.powers[pw_carry] //Fixes a bug in competition/race.
				and not (p.secondjump == 167)
					if ((p.cmd.buttons & BT_USE) or p.sms_stompanim) and not p.spinhold 
					or ((p.cmd.buttons & BT_JUMP) and not (p.sms_jumphold and p.sms_jumphold > 1) and not p.smsblastboost)
						if not p.hypermysticsonic
						P_SpawnGhostMobj(s)
						s.atomdiveusebuffer = 0
						s.state = S_PLAY_ROLL 
						p.charability = CA_THOK 
						p.charflags = $ & ~SF_CANBUSTWALLS
						end
					p.pflags = $|PF_JUMPED & ~PF_THOKKED 
						if (p.cmd.buttons & BT_JUMP)
							if p.powers[pw_carry]
							p.pflags = $|PF_JUMPDOWN
							p.sms_jumphold = 10
							else
							p.pflags = $|PF_JUMPED & ~PF_JUMPDOWN & ~PF_THOKKED & ~PF_NOJUMPDAMAGE
							end
						end						
					
					elseif ((p.cmd.buttons & BT_CUSTOM2) and not (p.smsmeleebutton > 1)
					or ((p.cmd.buttons & BT_JUMP) and not (p.sms_jumphold and p.sms_jumphold > 1) and p.smsblastboost)) and not p.hypermysticsonic
							if s.hmsrotateright
							s.hmsrotateright = true
							else
							s.hmsrotateright = true
							end
					A_SMSSTOMPSMOKE(s, 6, MT_SPARK, nil, (s.momz*4/3))
					
					if p.smsblastboost //SMSblast SMS didn't actually have this, but it's what I intended back then with the white shield.
					P_SetObjectMomZ(s, 12*FRACUNIT, false)
					S_StartSound(s, sfx_nxbump)
					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
					p.charflags = $ & ~SF_CANBUSTWALLS
					end
				end
			end
			
//Lets group of a bunch checks behind this for better performance.
//Better than doing P_IsObjectOnGround 500 times...

			if not P_IsObjectOnGround(s) 
			
				if P_PlayerInPain(p) //Not while in a waterslide!
				s.sms_painr = $+1
				end
			
				if (s.state == S_PLAY_SPRING) and ((s.momz*(P_MobjFlip(s))) > 6*FRACUNIT)
				and (p.pflags & PF_JUMPED) and not p.hometrickanim and not (p.pflags & PF_NOJUMPDAMAGE)
				 and not p.hypermysticsonic //Prevents spring anim bug
					p.pflags = $ & ~PF_JUMPED
				end
				//YOU MUST RECOVER! Press the jump button to undo potential insta-murder. 
				//I feel every character should have this, but alas, this is SMSreborn, not EverybodyReborn...
				if s.sms_painr
					if s.state != S_PLAY_PAIN
						s.sms_painr = 0
					elseif (s.sms_painr >= 29) //If the timer is 29(or higher), YOU MUST RECOVER!!
						if not (p.pflags & PF_SLIDING)
						and not p.powers[pw_nocontrol]
							if (p.cmd.buttons & BT_JUMP) //Ability only starts when you press jump.
							s.airboostroll = 0
							s.rollangle = 0
							s.state = S_PLAY_ROLL
							P_SetObjectMomZ(s, 9*FRACUNIT, false)
							P_DoJump(p, true)
							P_SetObjectMomZ(s, 138500, true) //Slightly higher than a normal jump.
							s.sms_painr = 0 //Bring back painrecovery to 0.
							end
						end
					end
				end		
			
				if s.state == S_PLAY_GASP and s.tics == 1 and not p.hypermysticsonic
					s.state = S_SMS_ADVFALL1
				elseif (p.panim == PA_WALK or p.panim == PA_RUN or p.smsboostpanim)
				and not (s.eflags & MFE_GOOWATER)
				and not (p.pflags & PF_SLIDING)
				and not p.exiting 	//If SMS runs off a cliff, go into a special animation that'll let you curl up again!
					p.sms_advfall = $+1
				end
				if s.state == S_SMS_ADVFALL2 //Is SMS in advanced falling states?
				or s.state == S_SMS_ADVFALL1
					if p.hypermysticsonic
						s.state = S_PLAY_ROLL
						p.pflags = $|PF_JUMPED
					elseif (p.cmd.buttons & BT_CUSTOM2)	
					and not (p.smsmeleebutton > 1)
					and not p.hypermysticsonic
					and not p.spinhold and not p.powers[pw_carry]
						A_SMSSTOMPSMOKE(s, 6, MT_SPARK, nil, (s.momz*4/3))
						P_SpawnGhostMobj(s)
						s.state = S_SMS_ROLLT2
						p.hometrickanim = true
						p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED & ~PF_NOJUMPDAMAGE
						p.homingtrickcharge = 0
					elseif ( ((p.cmd.buttons & BT_USE) and not p.spinhold)
					or ((p.cmd.buttons & BT_JUMP) and not (p.sms_jumphold and p.sms_jumphold > 1)) )
					and not p.powers[pw_carry]
						if not p.hypermysticsonic
						P_SpawnGhostMobj(s)
						s.atomdiveusebuffer = 0
						s.state = S_PLAY_ROLL
						p.charability = CA_THOK //Juuust incase.
						p.charflags = $ & ~SF_CANBUSTWALLS
						end
						p.pflags = $|PF_JUMPED & ~PF_THOKKED //Let's roll!
					end
				end
				if (p.sms_advfall > 9) //Been walking in sunshine long enough? Then falling animation, go!
				and not (s.eflags & MFE_GOOWATER)
				and not p.hypermysticsonic
					if (s.momz*P_MobjFlip(s) > 7*FRACUNIT)
					s.state = S_PLAY_SPRING
					else
					s.state = S_SMS_ADVFALL1
					end
				p.sms_advfall = 0
				end
				if (p.cmd.buttons & BT_JUMP) and s.smsframejump and (p.sms_jumphold != nil and p.sms_jumphold < 2) --Execute the frame jump
				and ((s.state == S_PLAY_RUN or s.state == S_PLAY_ROLL or s.state == S_PLAY_WALK)
				or ((s.state >= S_SMS_BOOST01) and (s.state <= S_SMS_BOOST04)) )
					local oldmomz = s.momz
					local smsghost = P_SpawnGhostMobj(s)
					P_TeleportMove(smsghost, s.x-s.momx, s.y-s.momy, s.z-s.momz)
					P_DoJump(p, true)
					if (oldmomz*P_MobjFlip(s) > 0) --Always work in the player's favor.
					s.momz = $+oldmomz
					end
					if p.powers[pw_shield] == (SH_WHIRLWIND) or p.powers[pw_shield] == (SH_WHIRLWIND|SH_FIREFLOWER)
					s.momx = $/3 s.momy = $/3
					end
				end
			else
				if s.sms_painr
					s.sms_painr = 0
				end
			end

			//When SMS runs off a cliff, he goes into special falling frames.
			//You can curl up out of these too!

			if p.sms_advfall
				if P_IsObjectOnGround(s)
				or (p.pflags & (PF_JUMPED|PF_SPINNING))
				or p.powers[pw_carry]
				or not p.panim == PA_RUN and not p.panim == PA_WALK and not p.smsboostpanim
				p.sms_advfall = 0
				p.pflags = $ & ~PF_THOKKED
				end
			end

			//If HMS runs off a cliff, let him fly again at will.

			if p.hypermysticsonic
			and (p.cmd.buttons & BT_JUMP)
				if not (p.pflags & PF_JUMPED) //If you're already jumping, you don't need this.
				and not P_IsObjectOnGround(s) //If you're on the ground, you also don't need this.
				and not (p.pflags & PF_STARTJUMP) //Because you're worth it.
				and not (p.powers[pw_carry] == CR_ZOOMTUBE)
					p.pflags = $|PF_JUMPED & ~(PF_SPINNING|PF_STARTDASH|PF_SLIDING|PF_STARTJUMP|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY|PF_GLIDING|PF_BOUNCING|PF_JUMPDOWN|PF_USEDOWN)
					if p.smsdivetimer 
					p.smsdivetimer = 0
					end
				end
			end

			//Let's give a fully charged blindddash an extra effect or two.

			if (p.pflags & PF_SPINNING)
			and P_IsObjectOnGround(s)
			and not (p.pflags & PF_JUMPED)
				if (p.dashspeed >= 146*FRACUNIT)
				p.smsfullcharge = 1
				end
			elseif p.smsfullcharge
				p.smsfullcharge = 0
			end
			if p.smsfullcharge
			and (p.pflags & PF_SPINNING)
			and (p.speed > FixedMul(104*FRACUNIT, s.scale))
			s.smsgrboost = P_SpawnMobj(s.x, s.y, s.z, MT_SMSGROUNDBOOST)
			s.smsgrboost.tracer = s
			A_SMSquake(s, 44*FRACUNIT, 9, 3000)
			p.smsfullcharge = 0
				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
			end
	end
end, MT_PLAYER)