--=============================HMS FUNCTIONS=========================================
--This lump houses functions for HMS-exclusive stuff. HMS-exclusive GFX are in LUA_GFX2.
--If a function is meant for both SMS and HMS, then it'll probably be in LUA_FUNCTIONS.
--===================================================================================

//Because people will make that joke
function A_TOGOEVENFURTHERBEYOND(s)
	if not (s.valid and s.skin == "sms" and s.player) return end --
	local p = s.player
	
		--CANCEL CONDITIONS!
		if p.hypermysticsonic or p.sms_intoship return end --
		
		if p.hmstransformdisable == 2 --HMS doesn't use Chaos Emeralds for the transformation normally.
			if not All7Emeralds(emeralds)
				if not G_GametypeHasSpectators()
					CONS_Printf(p, "You currently need the 7 Chaos Emeralds to transform into HMS.")
					return --
				end
			end
		end	
		if p.hmstransformdisable == 1 and not G_GametypeHasSpectators() --Can't disable HMS in match/CTF.
		or p.smsnoracegame == 2 and (gametype == GT_RACE) --Can't go HMS in race with the "all-super" setting!
			CONS_Printf(p, "HMS is currently disabled.") return --
		end
		if p.hmshascome and G_GametypeHasSpectators() --1 HMS per match.
			CONS_Printf(p, "\x89"+"Can't transform under all this pressure!") return --
		end
		if (p.speedbombactive or p.g2gfast4lifeactive or p.hmsrushactive or p.skillstripcv) and (gametype == GT_COOP) 
			CONS_Printf(p, "You cannot transform in these gamemodes!") return --SMSchallenges modes.
		end
			
		--Hyper Mystic Sonic is INCREDIBLY game intensive and chaotic.
		--It helps to let servers control how many HMS' can be present, for lag or sanity reasons.
		if netgame
			local AUTO = false
			local ztotal = 0
			local zmaxplayers = 0						
			for z in players.iterate
				zmaxplayers = $+1
				if z.hypermysticsonic
					ztotal = $+1
				end
				if z.smsautographix
					AUTO = true
				end
			end
			if p.hmsmlimit != nil and (ztotal >= p.hmsmlimit)
				CONS_Printf(p, "\x85"+"Server limit for Hyper Mystic Sonic players already reached!\x80 ("+p.hmsmlimit+")")	
				return --
			end	
			--If HMS appears, the tolerance for high graphics goes down.
			if AUTO and zmaxplayers
				if (zmaxplayers < 7) --Small netgame with 6 or less people, full steam ahead!
					for z in players.iterate
						if z.smsgraphix != 0
							CONS_Printf(z, "SMS graphics auto-adjusted to\x83 full")	
							z.smsgraphix = 0
						end
					end
			 	elseif (zmaxplayers < 9) --Medium netgame, slow it down a notch...
					for z in players.iterate
						if z.smsgraphix != 1
							CONS_Printf(z, "SMS graphics auto-adjusted to\x84 medium")	
							z.smsgraphix = 1
						end
					end
			 	else --Busy netgame, minimum graphics!
					for z in players.iterate 
						if z.smsgraphix != 2
							CONS_Printf(z, "SMS graphics auto-adjusted to\x85 minimum")	
							z.smsgraphix = 2
						end
					end
				end
			end
		end
		s.SMS_AllowFlickies = nil
		s.SMS_MineCarting = nil
		s.forceHMSyellanim = nil --From player warp.
		s.HayMakerPunch = nil
		s.SMS_DLtrail = nil
		p.wasHMS = true --We've been HMS, remember that for later.
		s.SMS_locked = true
		p.smsmeleebutton = 850
		p.smsdivefloat = 0
		p.smsatomicdivefail = 0
		p.homing = 0
		
		p.sms_attracttl = nil
		p.sms_sontransform = 0
		p.sms_hugeflametoss = 0
		p.footsweep01 = 0
		p.footsweep02 = 0
		p.footsweep03 = 0
		p.footsweepanim = false
		p.hometrickanim = false
		p.smsboostpanim = false
		s.hmsroflstomped = false
		s.hmsspinpass = 0
		s.sdodgecd = 0
		s.sdodgelvl = 0
		s.SMS_BDboostloss = nil
		s.hmgodmticket = nil
		
		p.charability = CA_NONE
		p.charflags = $|SF_RUNONWATER & ~SF_NOSKID
		p.pflags = $ & ~(PF_STARTDASH|PF_SPINNING|PF_THOKKED|PF_STARTJUMP|PF_SLIDING|PF_FULLSTASIS)
		s.prehmscolor = s.color
		s.prehmspcolor = p.skincolor
		p.hypermysticsonic = 1
		
		s.hmgodticket = false
		p.powers[pw_nocontrol] = 16
		s.boostpass = false
		
		--Reset some special values...
		p.novafire = 35
		p.hmsblackhole = 35
		s.hms_jumprisen = 0
		s.HMS_warpselectcooldown = nil
		s.hmsspinpass = nil
		s.hmsusebuffer = 0
		s.hmsgalaxystorm = 35
		s.hmspowerbombcam = 0
		p.hms_gravburstcd = 35
		p.hms_explosion = 0
		p.hms_instamove = 0
		p.hms_instamovew = 0
		p.hmswarpcooldown = 35	
		p.hmsdash = 0
		
		s.SMS_squashtable = nil --Have this reset.
		s.spriteyscale = FRACUNIT
		s.spritexscale = FRACUNIT
		s.spritexoffset = 0
		s.spriteyoffset = 0
		s.rollangle = 0		
		
		s.state = S_HMSTRANSFORM1
		s.momx = 0
		s.momy = 0
		s.momz = 0
		p.sms_wallstat = 0
		s.hmsshieldconsume = 0
		
		
		A_SMSquake(s, 10*FRACUNIT, 22, 8022) --A bigger quake comes later in the animation.
		P_NukeEnemies(s, s, 750*s.scale)
		
		if SMS_Graphix(s) != 2
			SMS_Embers(s, s, 0)
			HMS_AuraStorm(s, nil, SKINCOLOR_BONE, nil, G|TR_TRANS50)
			local ghs = HMS_GigaJetBolt(s, FRACUNIT/2, 24)
			ghs.tracer = s
			ghs.dispoffset = -5
		else
			local ghs = P_SpawnMobjFromMobj(s, 
			FixedMul(-2*s.scale, cos(s.angle)), 
			FixedMul(-2*s.scale, sin(s.angle)),
			0, MT_HMSLIPILLAR)
			ghs.scalespeed = 17500
			ghs.fuse = 38
			ghs.target = s
			ghs.color = SKINCOLOR_BONE
		end
		SMS_WallJumpDelete(s, true)

		S_StartSound(nil, sfx_hypemt)
		P_RestoreMusic(p)
		
		if not p.nohmstheme
			if p == consoleplayer
				COM_BufInsertText(p, "tunes HMS") --Otherwise it'll go back to the main stage theme after 1-up sounds...
			end
			if SUBVERSION != 11 --Disabled until 2.2.12.
				if s.hmsmpos
					S_ChangeMusic("HMS", true, p, 0, s.hmsmpos, 150, 150)
				elseif not s.hmsmpos
					s.hmsmpos = 1
				end
			end
		end
		//P_RestoreMusic(p)
		
		--Darken the heavens, everybody is screwed now....!
		if G_GametypeHasSpectators() and not modeattacking
			P_StartQuake(35*FRACUNIT, 45)
			if mapheaderinfo[gamemap] and mapheaderinfo[gamemap].skynum
				p.hfear = mapheaderinfo[gamemap].skynum --Remember the sky number to reload later.
				if mapheaderinfo[gamemap].skynum != (21 or 22) --Outter space can just remain outter space.
					P_SetupLevelSky(11)
				end
			else
				p.hfear = 1
			end
			for z in players.iterate
				z.hmshascome = p
				if z.mo and (z.mo != s) --Warn everyone
					z.mo.hmsfearmessage = 64
				end
				P_FlashPal(z, PAL_NUKE, 12)
			end
			for sector in sectors.iterate --Darken the world.
				sector.lightlevel = max(($-31), 0)
			end
		end	
		return true --Success!
end

--We were HMS, but no longer are? Reset stats!
rawset(_G, "HMS_UntransformedStats", function(s, p, FORGETSTUFF) 
		if s.prehmscolor --Reset colors!
			s.color = s.prehmscolor
			p.skincolor = s.prehmspcolor
		end
		
		--Don't need to remember this stuff.
		s.prehmscolor = nil
		s.prehmspcolor = nil
		s.hmslivesc = nil
		s.tniy6 = nil
		s.tniy5 = nil
		s.tniy4 = nil
		s.tniy3 = nil
		s.tniy2 = nil
		s.tniy = nil
		s.HMS_7flame = nil
		s.HMS_SkipHBnext = nil
		s.HMS_FireCoords = nil	
		s.HMS_FireCoords2 = nil	
		s.HMS_FireCoords3 = nil
		s.HMS_warpselectcooldown = nil	
		s.HMS_lastNB = nil
		s.wvspwncd = nil
		s.haltthespam = nil
		s.hmgodmticket = nil
		s.hmsdashDOWN = nil
		s.HMS_airboostspeedtimer = nil
		
		if FORGETSTUFF == true return true end --
			
		if s.starthmscombo
			s.starthmscombo = nil
			s.flags = $ & ~MF_NOCLIPTHING & ~MF_BOUNCE
		end
		if s.hmscarryset
			s.hmscarryset = false
			p.pflags = $ & ~PF_CANCARRY
		end
		if s.hmsgodmode or (p.pflags & PF_GODMODE)
			p.pflags = $ & ~PF_GODMODE
			s.hmsgodmode = nil
		end
		if s.hmsforcedspin
		or s.hmsspinang
			s.hmsforcedspin = nil
			s.hmsspinang = 0
			s.rollangle = 0
		end
		if p.hypermystictaxi
			p.hypermystictaxi = false
		end		
		p.sms_sontransform = 0
		p.powers[pw_ignorelatch] = 0
		p.wasHMS = nil
		p.hypermysticsonic = 0
		if p.accelstart == 140
			p.accelstart = skins[s.skin].accelstart
		end
		if not p.nohmstheme
			COM_BufInsertText(p, "tunes -default")
			P_RestoreMusic(p)
		end
		
		if (s.skin == "sms")
			if leveltime
				HMS_UntransformGFX(s)
			end			
			if (p.maxdash != skins[s.skin].maxdash) and not p.gotflag
				p.maxdash = skins[s.skin].maxdash
			end
			if p.powers[pw_sneakers] or SMSSHIELD(p, SH_WHIRLWIND)
				p.jumpfactor = 87250
			else
				p.jumpfactor = skins[s.skin].jumpfactor
			end
		else
			if (p.maxdash != skins[s.skin].maxdash)
				p.maxdash = skins[s.skin].maxdash
			end
			p.jumpfactor = skins[s.skin].jumpfactor
		end
--		print("\x83 Ran HMS untransform stats.")
		return true --
end)

//Var1 determines if you lose rings or not when untransforming! Var2 is momentum
function A_TOGOBACKTOTHEWAYYOUWERE(s, var1, var2)
	if not s.player return end --	
	local p = s.player
	local RESTOREDMUSIC = false
			--End Hyper Mystic Panic?
			if p.hfear
				if G_GametypeHasSpectators() and leveltime
					for sector in sectors.iterate
						sector.lightlevel = ($+31)
					end
					S_StartSound(nil, sfx_s3k66)
					P_SetupLevelSky(p.hfear)
			 	end
				for z in players.iterate
					z.hmshascome = nil
					p.hfear = nil
					P_FlashPal(z, PAL_MIXUP, 3)	
					if not z.nohmstheme
						COM_BufInsertText(z, "tunes -default")
						P_RestoreMusic(z)
						RESTOREDMUSIC = true
					end
				end
			end
			--Remove HMS theme.
			if not p.nohmstheme and p.hypermysticsonic 
			and not RESTOREDMUSIC
				COM_BufInsertText(p, "tunes -default")
				P_RestoreMusic(p)
			end
			
			s.rollangle = 0
			
			--No effects if you just switched level.
			if leveltime
				P_FlashPal(p, PAL_MIXUP, 7)
				S_StartSound(s, sfx_s3k66)
				P_RadiusAttack(s, s, 250*s.scale)
				if SMS_Graphix(s) != 2
					for d = 0,15
						P_SpawnParaloop(s.x, s.y, s.z+FixedMul(20*FRACUNIT, s.scale), 10*FRACUNIT, 16, MT_NIGHTSPARKLE, d*ANGLE_22h, S_SMSTSPARK1, false)
					end
				end				
			end
			
			--End manual transformation sequence?
			if p.sms_transformstate
				if leveltime
					local ghs = P_SpawnGhostMobj(s)
					ghs.destscale = $*99
					ghs.fuse = 20 ghs.tics = 22
					ghs.blendmode = AST_ADD
					ghs.colorized = true
				end	
				if p.presmsskin
					R_SetPlayerSkin(p, p.presmsskin)
					s.skin = p.presmsskin
					COM_BufInsertText(p, "skin "+p.presmsskin)
				else
					R_SetPlayerSkin(p, "sonic")
					s.skin = "sonic"
					COM_BufInsertText(p, "skin sonic")
				end
				
				p.sms_transformstate = 0	
				p.ffdelaycs = 3
				
				if not (p.powers[pw_shield] & SH_FIREFLOWER)
				and not ((mariomode) and p.powers[pw_invulnerability])
					s.color = p.sms_originalcolor
				else
					s.color = SKINCOLOR_WHITE
				end				
				p.skincolor = p.sms_originalcolor
				
			elseif not var1 and leveltime
				P_GivePlayerRings(p, -20)
			end			
			if G_GametypeHasSpectators()
				p.rings = 0
				p.hms_drain = 1
			end
			
			HMS_UntransformedStats(s, p) --Remove all stats associated with HMS.
			p.hypermysticsonic = 0			
			p.pflags = $ & ~PF_GODMODE	
			
			//Continue the atomdive!
			if not p.smsdivetimer
				if (p.pflags & PF_STARTDASH)
					p.pflags = $ & ~PF_STARTDASH & ~PF_SPINNING
					p.dashspeed = 0
				end
				if var2
					s.momx = $/4
					s.momy = $/4
					s.momz = $/3
				else
           			P_InstaThrust(s, s.angle, 0)
				end
				if not var1
					p.powers[pw_nocontrol] = $+16
				end
				if not (p.powers[pw_carry] == CR_NIGHTSMODE)
					s.state = S_PLAY_FALL
					p.pflags = $ & ~PF_JUMPED
				end
			else
				s.dcadsms = true
				p.smsdivetimer = 37
				s.state = S_PLAY_ROLL
				p.panim = PA_ROLL
			end			
end

--VAR1 = Optional Custom Object. MT_SPINFIRE by default.
function A_HMSfiretrail(s, var1) //Var1 = Optional Custom Object
	if (s.eflags & MFE_TOUCHWATER) or SMS_Graphix(s) == 2
	or not s.health	
		return --Cancel!
	end
	--Get setup out of the way.
	var1 = (var1) and $ or MT_SPINFIRE
	
	local ang = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
	local SPEED = abs(s.momx)+abs(s.momy)
	local dist = SMSLocalRNG(13,24,s)*s.scale
	local ths, ZCORRECT
	if not P_IsObjectOnGround(s)
		if (s.eflags & MFE_VERTICALFLIP)
			ZCORRECT = s.ceilingz
		else
			ZCORRECT = s.floorz
		end	
	end
	
	for d = -1,1,2 --skip 0.
		local ghs = P_SpawnMobjFromMobj(s, 
		FixedMul(dist, cos(ang+(ANGLE_90*d))), 
		FixedMul(dist, sin(ang+(ANGLE_90*d))), 
		0,
		var1)
				
		if ghs and ghs.valid
			ghs.target = s
			ghs.angle = s.angle+(ANG2*2*d)
			
			if SPEED > 40*s.scale
				ghs.momx = s.momx/2
				ghs.momy = s.momy/2
				P_Thrust(ghs, ang, SPEED/SMSLocalRNG(32, 128,s))
			end
			if ZCORRECT
				ghs.z = ZCORRECT
			end			

			if (ghs.type == MT_SPINFIRE)
				ghs.state = S_HMSFPILLAR1
				ghs.tics = SMSLocalRNG(1,4, ghs)
				ghs.scale = (s.scale*10)/SMSLocalRNG(10, 12,ghs)
				if not s.momx
					s.momx = 8
				end
				ghs.health = 1
				ghs.flags = MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY|MF_FIRE & ~MF_NOCLIPHEIGHT
				--Do we still exist after becoming a missile? Then stop entirely IF....
				if ghs.valid and (abs(ghs.z-s.z) > 88*s.scale)
					ghs.state = S_NULL return nil
				end				
			end
		end
		if d != 1 --Return first flame as "ths"
			ths = ghs
		end
	end
	return ths,ghs --Return both flames.
end

--HMSstomp is the HMS stomp, for stomping as HMS.
rawset(_G, "HMS_stomp", function(s, p)
	if (p.cmd.buttons & BT_CUSTOM2)
	
			if (p.pflags & PF_JUMPED)
			
					if not (p.cmd.buttons & BT_CUSTOM1 and (p.cmd.forwardmove < -20) and (p.smsmeleebutton < 17) and not (abs(p.cmd.sidemove) > 6) )
					and not SMS_Locked(s, p)
					and not (p.pflags & PF_SLIDING)
					and not (p.cmd.buttons & (BT_WEAPONPREV|BT_JUMP|BT_TOSSFLAG))
					and not P_IsObjectOnGround(s)
					
						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) > -29*s.scale) --Minimum stomp speed.
							P_SetObjectMomZ(s, -29*FRACUNIT)
						end
						
						local ghs 				
						if not s.hmsstompsfx
							if SMS_Graphix(s) == 0
								HMS_StompGFX(s, p)
								if not s.haltthespam
									ghs = P_SpawnMobjFromMobj(s, 0, 0, s.height, MT_HMSNOVAWAVE) 
									ghs.scale = (s.scale*10)/SMSLocalRNG(9,15,s)
									A_SMSSTOMPSMOKE(s, SMSLocalRNG(30,10,s), MT_DUST)
									A_SMSSTOMPSMOKE(s, 20, MT_ENERGYBALL, 200)
								end
								ghs = SMS_LightFlash(s, SKINCOLOR_SMS5R, FRACUNIT-26000, nil, Z+3|TR_TRANS30)
								ghs.tracer = s
								ghs.sttfade = 14
								ghs.fuse = 7
								ghs.scalespeed = FRACUNIT-18000	
								
								ghs = SMS_ElectricBody(s, 5, SKINCOLOR_RED)
								ghs.spriteyscale = FRACUNIT+42000
								ghs.spritexscale = FRACUNIT+45000								
							end
							
							s.hmsstompsfx = true
							P_SetObjectMomZ(s, -12*FRACUNIT, true)
							S_StartSound(s, sfx_stst)
							s.haltthespam = 5
							
							if (s.momz*P_MobjFlip(s) < 0) --Quake depends on vertical speed.

								A_SMSquake(s,
								max( 10*FRACUNIT, min(180*FRACUNIT, abs(s.momz/2)) ),
								max( min( 12 , abs(s.momz)/(FRACUNIT/12) ), 2)
								)
								
								if not (s.SMS_squashtable and s.SMS_squashtable.timer > 2)
									s.spritexscale = FRACUNIT-15100
									s.spriteyscale = FRACUNIT+19100
									s.spriteyoffset = -5*FRACUNIT
									s.SMS_squashtable = {timer = 3, Xspeed = 6500, Yspeed = 7500, air = true}
								end							
							
								if not s.SMS_DLtrail and not SMS_Graphix(s)					
									s.SMS_lastz = s.z-s.momz+(s.height*2)
									s.SMS_DLtrail = {timer = 3, color = SKINCOLOR_SKY, colorized = true,
									momx = s.momx, momy = s.momy, fuse = 5, spritexscale = FRACUNIT*2}
									SMS_ContinuousTrail(s, s.SMS_DLtrail)
									s.SMS_lastz = s.z
								end							
							end
						end
						if not (s.eflags & MFE_GOOWATER)
						and SMS_Graphix(s) != 2
							if (leveltime % 3 == 0)
								if (leveltime % 3 == 0)
									P_NukeEnemies(s, s, 400*s.scale)
								else
									A_SMSSTOMPSMOKE(s, SMSLocalRNG(12,20,s), MT_WATERZAP)
								end			
							elseif (leveltime % 2 == 0)
								A_SMSSTOMPSMOKE(s, SMSLocalRNG(12,40,s), MT_BOSSEXPLODE)
								if leveltime % 14 == 0
									HMS_StompGFX(s, p)
								end			
							end
						end
						
						if (leveltime % 2 == 0)
							ghs = SMS_FootSweepSlash(s, FF_TRANS10, leveltime*(ANG1*33))
							if ghs and ghs.valid
								ghs.momz = $+(s.momz/3)
								ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
							end
							
							local ghs = P_SpawnMobjFromMobj(s, s.momx, s.momy, 0, MT_HMSSTOMPAURA)
							ghs.scale = (s.scale*20)/SMSLocalRNG(4,8,s)
							if (ghs.scale <= (s.scale*20)/7)
								ghs.z = $-14*s.scale*P_MobjFlip(s)
							elseif (ghs.scale >= (s.scale*20)/5)
								ghs.z = $+9*s.scale*P_MobjFlip(s)
							end
							if (s.eflags & MFE_VERTICALFLIP)
								ghs.z = $-(20*s.scale)
							end
							ghs.target = s
							ghs.color = SMSLocalRNG(SKINCOLOR_SUPERORANGE1, SKINCOLOR_SUPERORANGE5,s)
							ghs.frame = SMSLocalRNG(5, 7,ghs)|TR_TRANS30
							
							--A ghost of a ghost!
							ghs.ghostaura = P_SpawnGhostMobj(ghs)
							ghs.ghostaura.scalespeed = $/2
							ghs.ghostaura.destscale = ghs.ghostaura.scalespeed+1
							ghs.ghostaura.momx = s.momx/2
							ghs.ghostaura.momy = s.momy/2
							ghs.ghostaura.tics = 5
							ghs.ghostaura.blendmode = AST_ADD
							ghs.ghostaura.momz = $+10*s.scale*P_MobjFlip(s)
										
						else
							local ghs = P_SpawnMobjFromMobj(s, s.momx, s.momy, 0, MT_HMSSTOMPAURA)
							ghs.scale = (s.scale*20)/SMSLocalRNG(4,9,s)
							ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
							ghs.blendmode = AST_ADD
							if (s.eflags & MFE_VERTICALFLIP)
								ghs.z = $-(20*s.scale)
							end
							ghs.target = s
							ghs.color = SMSLocalRNG(SKINCOLOR_SUPERRED1, SKINCOLOR_SUPERGOLD5,ghs)
							ghs.frame = T|TR_TRANS40
						end
						if (not s.bhlcamtimer or s.bhlcamtimer == 1) --Zoom out camera a bit for better visibility.
							p.camerascale =  FRACUNIT*3/2
							s.bhlcamtimer = 2
						end
						local ghs = SMSRSpawnGhost(s)
						if not s.hmsspinfreeze and not (p.cmd.buttons & BT_TOSSFLAG)
							s.hmsspinpass = 8
						end
						if s.hmsspinpass and s.hmsspinang != nil and ghs
							ghs.angle = s.hmsspinang
						end
						p.hms_stompbreak = $+1
						s.SMS_stompmom = (p.hms_stompbreak > 2) and s.momz or 0
					else
						p.hms_stompbreak = 0
					end
				end
				
				--LANDING!
				if (s.eflags & MFE_JUSTHITFLOOR)
					if ( (p.hms_stompbreak > 2) or (p.speed > 137*s.scale))
					and not A_HMSCheckDeathPit(s)
						SMS_stompimpact(s, p, 3)
					end
					return true --
				end

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

				if (p.cmd.buttons & BT_TOSSFLAG)
				or ((p.cmd.buttons & BT_JUMP) and s.hms_jumprisen)
			   		if (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_jumphold = 10
						s.hms_readyriseboost = 0
			   			s.hms_jumprisen = 2
			   			s.hmgodticket = true
						s.momz = 0
					end
				end
	else
		if (leveltime % 14 == 0)
			if s.rollangle == ANGLE_180
			and (s.momz*P_MobjFlip(s) < -30*s.scale)
			and not(p.cmd.buttons & BT_TOSSFLAG)
				s.hmsstompsfx = true
				HMS_StompGFX(s, p)
			end
		end
		if s.hmsstompsfx
			s.hmsstompsfx = false
		end		
	end 
end)

--Warp Dash
rawset(_G, "HMS_Warp", function(s, p)
				if s.forcewarp1
					if (s.forcewarp1 == 1)
						s.state = S_HMS_INSTANTWARP2
						p.pflags = $|PF_USEDOWN
					else
						s.state = S_HMS_INSTANTWARP1
					end
					p.pflags = $ & ~PF_SPINNING
					s.forcewarp1 = $-1
				end
				if s.forcewarp2
					if (s.forcewarp2 == 1)
						s.state = S_HMS_INSTANTWARP3
						p.pflags = $|PF_USEDOWN
					else
						s.state = S_HMS_INSTANTWARP2
					end
					p.pflags = $ & ~PF_SPINNING
					s.forcewarp2 = $-1
				end
				if s.state == S_HMS_INSTANTWARP2
					if (p.pflags  & PF_SPINNING)
						s.forcewarp2 = 2
						p.pflags = $ & ~PF_SPINNING
					end
					p.pflags = $|PF_JUMPED|PF_USEDOWN
					
				--	A_FindTarget (s, MT_HMSWARPPOINT, 0)
					if (s.target and s.target.type == MT_HMSWARPPOINT) and not s.target.dontwarptome
						local secheck = R_PointInSubsector(s.target.x, s.target.y).sector
						for fof in secheck.ffloors()
							if (fof.flags & FF_EXISTS) and ((fof.flags & FF_STRONGBUST) or (fof.flags & FF_BUSTUP))
							and not (s.target.z-99*FRACUNIT >= fof.topheight)
							and not (s.target.z+99*FRACUNIT < fof.bottomheight)
							EV_CrumbleChain(secheck, fof)
							end
						end			
						
						if P_CheckPosition(s, s.target.x, s.target.y, s.target.z)
						and not (secheck.ceilingheight-secheck.floorheight < (P_GetPlayerSpinHeight(p)))
						and not s.target.dontwarptome
						
							S_StartSound(s, sfx_s3k83)
                            P_NukeEnemies(s, s, 850*s.scale)
							
							local QuickDetour = s.target
							A_FindTarget(s, MT_HMSWARPPOINTRETURN, 0)
							if (s.target and s.target.type == MT_HMSWARPPOINTRETURN)
								local ghs = HMS_BigBangVortex(s, 33, FRACUNIT/2, ANG1*69, E|TR_TRANS10, SKINCOLOR_ZEEJIN5)
								ghs.dispoffset = -2
								ghs.blendmode = AST_TRANSLUCENT
								P_MoveOrigin(ghs, s.target.x, s.target.y, s.target.z)
								
								local ths = HMS_GigaJetBolt(ghs, FRACUNIT, 35)
								ths.colorized = true
								ths.color = SKINCOLOR_DUSK
								ths.dispoffset = 1
								
								ths = P_SpawnMobjFromMobj(ghs, 0,0,0, MT_HMSNOVAWAVE)
								ths = P_SpawnMobjFromMobj(ghs, 0,0,0, MT_HMSNOVAWAVE)
								ths.rollangle = ANGLE_90
								ths.dispoffset = 6
								ths = P_SpawnMobjFromMobj(ghs, 0,0,0, MT_HMSNOVAWAVE)
								ths.rollerwave = 16*FRACUNIT
								ths.dispoffset = 11

								ths = P_SpawnGhostMobj(s)
								ths.tics = 29
								ths.dispoffset = 3
								ths.colorized = true
								ths.color = SKINCOLOR_SMSROVERGLOW
								ths.scalespeed = $*3
								ths.destscale = $*20
								P_MoveOrigin(ths, s.target.x, s.target.y, s.target.z)
							end	
							s.target = QuickDetour
							
							if (s.subsector.sector == s.target.subsector.sector)
							and s.subsector.sector.floorpic == s.target.subsector.sector.floorpic //Same sector...be careful.
							and not s.target.ihavetped
								s.z = s.target.z
								P_TryMove(s, s.target.x, s.target.y, true) //Fake warp! (to prevent us clipping through walls)
							else
								P_MoveOrigin(s, s.target.x, s.target.y, s.target.z) //True Warp!
							end
							s.momz = 0
							s.momx = 0
							s.momy = 0
							P_FlashPal(p, 1, 2) //Brings up a bright white flash.
							local ghs = P_SpawnGhostMobj(s)
							ghs.tics = 20
							ghs.color = SKINCOLOR_RED
							ghs.colorized = true
							ghs.scalespeed = $*3
							ghs.destscale = $*20
						else
							P_KillMobj(s.target)
						end
						if s.tics == 2
							local ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_HMSNOVAWAVE)
							ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_HMSNOVAWAVE)
							ghs.rollangle = ANGLE_90
							ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_HMSNOVAWAVE)
							ghs.rollerwave = 16*FRACUNIT
							
							S_StartSound(s, sfx_s3k83)
                            P_NukeEnemies(s, s, 850*s.scale)
							
							local ghs = HMS_GigaJetBolt(s, nil, 14)
							ghs.tracer = s
							ghs.dispoffset = 1
							ghs.tracer = s
							ghs.frame = $+FRACUNIT
							ghs.colorized = true
							ghs.color = SKINCOLOR_ORANGE
							ghs.GSoffsetX = -9*s.scale
							ghs.GSoffsetY = -9*s.scale
							ghs.GSoffsetZ = 0
						
							ghs = SMS_LightFlash(s, SKINCOLOR_COBALT)
							ghs.tracer = s
							ghs.frame = $+FRACUNIT*3
							ghs.fuse = 14
							ghs.GSoffsetX = -16*s.scale
							ghs.GSoffsetY = -16*s.scale
							ghs.GSoffsetZ = -4*s.scale	
							
							ghs = SMS_ElectricBody(s,10)
							ghs.blendmode = AST_SUBTRACT
							ghs.mirrored = true

						end
					end
					SMS_StompGFX(s, p, true, true)
					
				elseif (s.state == S_HMS_INSTANTWARP3 or (p.hmswarpcooldown == 2 or p.hmswarpcooldown == 1))
				and not p.smsdivetimer
				
					if not P_IsObjectOnGround(s)
						s.momz = 0
					else
						p.pflags = $|PF_JUMPDOWN|PF_USEDOWN
					end
					
					s.momx = 0 s.momy = 0
					s.hmsgcheck = true
				
					local secheck = R_PointInSubsector(s.x, s.y).sector
					if (secheck.ceilingheight-secheck.floorheight < (P_GetPlayerSpinHeight(p)))
					or (p.pflags & PF_SPINNING)
					or not secheck
						A_FindTarget(s, MT_HMSWARPPOINTRETURN, 0)
						if (s.target and s.target.type == MT_HMSWARPPOINTRETURN)
							P_MoveOrigin(s, s.target.x, s.target.y, s.target.z) //Warp back!
							p.pflags = $ & ~PF_SPINNING
						end
					end
					if p.hmswarpcooldown == 2
						local ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_HMSNOVAWAVE)
						ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_HMSNOVAWAVE)
						ghs.rollangle = ANGLE_90
						ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_HMSNOVAWAVE)
						ghs.scale = s.scale
						ghs.rollerwave = -16*FRACUNIT
					end
				end
end)

--Is our target a properly existing destination?
rawset(_G, "HMS_InstantMoveCheck", function(s, p)
	if p.warpedtoguy == nil
	or (p.warpedtoguy > 31)
		p.warpedtoguy = 0
	elseif (p.warpedtoguy < 0)
		p.warpedtoguy = 31
	end
	local tp = players[p.warpedtoguy]
	if tp and tp.valid 
	and tp.mo
	and tp.mo != s 
	and tp.mo.health
		return true
	else
		return false
	end
end)

--Instant Transmis--Instant Movement! Appear in front of anyone in multiplayer instantly!
rawset(_G, "HMS_InstantMovement", function(s, p)

	--Concentrating, finding target!
	if (s.state == S_HMS_INSTANTMOVE1) --Concentrating!
		s.momz = 0
		s.momx = 0
		s.momy = 0
		p.normalspeed = 0
		p.pflags = $ & ~PF_JUMPED & ~PF_SPINNING

					if not (p.cmd.buttons & BT_WEAPONNEXT)	
					
						for i = 1,33
							if HMS_InstantMoveCheck(s, p)
								s.state = S_HMS_INSTANTMOVE2 break
							end
							p.warpedtoguy = $+1
							if i >= 33
								s.state = S_PLAY_FALL
							end
						end
						
					elseif not s.HMS_warpselectcooldown

						local cancel = false
						
						if (p.cmd.buttons & BT_SPIN) --Cancel
						and (p.spinhold < 2)
						
							cancel = true
							
						--Selecting process
						elseif ((p.cmd.buttons & BT_CAMRIGHT) or (p.cmd.sidemove > 15))
						or (p.cmd.buttons & BT_CAMLEFT) or (p.cmd.sidemove < -15)
							local leftright = ((p.cmd.buttons & BT_CAMRIGHT) or (p.cmd.sidemove > 15)) and 1 or -1
							for i = 1,33
								if p.warpedtoguy == nil
									p.warpedtoguy = 0
								elseif p.warpedtoguy == 0 and leftright == -1
									p.warpedtoguy = 31
								else
									p.warpedtoguy = $+leftright
								end
								if HMS_InstantMoveCheck(s, p) --Success!
									S_StartSound(s, sfx_rail2)
									s.HMS_warpselectcooldown = 8
									break
								elseif (i >= 33)
									cancel = true
								end
							end						
						end
						
						if cancel
							S_StartSound(s, sfx_ngskid) --fail!
							p.hms_instamove = 50
							s.state = S_PLAY_FALL
						else
							if HMS_InstantMoveCheck(s, p) --Aim at target!				
								local tg = players[p.warpedtoguy].mo
								p.getpersonname = tg.player.name
								s.angle = R_PointToAngle2(s.x, s.y, tg.x, tg.y)
							else
								p.getpersonname = "-"
							end						
						end
					end

	elseif (s.state == S_HMS_INSTANTMOVE2) --The warping state.
	and not p.powers[pw_carry]
	
				if HMS_InstantMoveCheck(s, p)
				and not p.hms_instamove
					
					local tg = players[p.warpedtoguy]
					
					if not (G_PlatformGametype() and not s.battlemodsms)
					and not (G_GametypeHasTeams() and (p.ctfteam == tg.mo.player.ctfteam))
					
						if not p.hms_instamovew
							if tg.powers[pw_sneakers] or (tg.mo.skin == "sms")
								p.hms_instamovew = 40 //Get other SMS players quicker.
								tg.mo.eyesareuponyou = 40
							else
								p.hms_instamovew = 66
								tg.mo.eyesareuponyou = 65
							end
								
                            P_StartQuake(10*FRACUNIT, 75)
							P_NukeEnemies(s, s, 750*FRACUNIT)
							P_FlashPal(tg.mo.player, PAL_NUKE, 8)
							P_FlashPal(p, PAL_NUKE, 8)
							S_StartSound(tg.mo, sfx_bgxpld)
							S_StartSound(tg.mo, sfx_rail2)
							S_StartSound(tg.mo, sfx_litng2)
							S_StartSound(s, sfx_rumble)
							
							local ghs = P_SpawnMobj(tg.mo.x, tg.mo.y, tg.mo.z, MT_HMSLIPILLAR)
							A_ChangeColorAbsolute(ghs, 0, SKINCOLOR_RED)
							
							P_SpawnMobj(tg.mo.x, tg.mo.y, tg.mo.z, MT_HMSLIPILLAR)
							P_SpawnMobj(s.x, s.y, s.z+20*FRACUNIT, MT_HMSLIPILLAR)
							
							A_ChangeColorAbsolute(ghs, 0, SKINCOLOR_RED)
							p.instalocx = tg.mo.x
							p.instalocy = tg.mo.y
							p.instalocz = tg.mo.z

						elseif p.hms_instamovew and (p.hms_instamovew > 1)
							
							if (leveltime % 2 == 0)
								local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_HMSNOVAWAVE) //Bigger and of the Super Mystic variety this time!
								ghs.scale = s.scale*10/P_RandomRange(5, 30)
								ghs.rollangle = P_RandomRange(1,359)*ANG1
								ghs.color = P_RandomRange(SKINCOLOR_BLACK, SKINCOLOR_SUPERGOLD5)
							end
							
							s.state = S_HMS_INSTANTMOVE2
							p.powers[pw_nocontrol] = 2
							p.novafire = 38
							s.momz = 0
							s.momx = 0
							p.normalspeed = 0
							p.pflags = $ & ~PF_JUMPED
						end
					end
						
					if tg and (G_PlatformGametype() and not s.battlemodsms)
					or G_GametypeHasTeams() and (p.ctfteam == tg.mo.player.ctfteam)
					or (p.hms_instamovew == 1)
						
						P_FlashPal(p, 1, 4)
						P_FlashPal(tg, 1, 4)
						
						--Leave ghost before you move.
						local ghs = P_SpawnGhostMobj(s)
						ghs.sprite = SPR_HMSO
						ghs.frame = I|FF_FULLBRIGHT|TR_TRANS20
						ghs.tics = 60
						ghs.color = SKINCOLOR_SUPERSKY5
						ghs.flags2 = $ & ~MF2_SHADOW
						ghs.scalespeed = $*5
						ghs.destscale = $*30

						--Teleport
						if ((G_PlatformGametype() and not s.battlemodsms)) or (G_GametypeHasTeams() and (p.ctfteam == tg.mo.player.ctfteam))
							P_MoveOrigin(s, tg.mo.x, tg.mo.y, tg.mo.z)
							s.spritexscale = FRACUNIT-60000
							s.spriteyscale = FRACUNIT*3
							s.SMS_squashtable = {timer = 7, Xspeed = 9800, Yspeed = FRACUNIT/2}	
						elseif (p.instalocx != nil) and p.instalocy != nil and p.instalocz != nil
							P_MoveOrigin(s, p.instalocx, p.instalocy, p.instalocz)
							s.spritexscale = FRACUNIT-60000
							s.spriteyscale = FRACUNIT*3
							s.SMS_squashtable = {timer = 7, Xspeed = 9800, Yspeed = FRACUNIT/2}							
						end
						s.SMS_ControlAlter = {
						timer = 23,
						removebuttons = (BT_WEAPONNEXT|BT_WEAPONPREV)
						}					
						p.instalocx = nil
						p.instalocy = nil
						p.instalocz = nil	
						
						--Show up uninvited.
						S_StopSound(s)
						P_SetObjectMomZ(s, 2*FRACUNIT)
						S_StartSound(s, sfx_s3k83)
						s.angle = tg.mo.angle
						s.eflags = tg.mo.eflags
						
						--Spoop them.
						ghs = P_SpawnGhostMobj(s)
						ghs.sprite = SPR_HMSO
						ghs.frame = I|FF_FULLBRIGHT|TR_TRANS20
						ghs.tics = 50
						ghs.color = SKINCOLOR_RED
						ghs.flags2 = $ & ~MF2_SHADOW
						ghs.scalespeed = $*5
						ghs.destscale = $*30
						
						--Nuke them.
						s.momx = 0 s.momy = 0
						P_NukeEnemies(s, s, 1234*s.scale)
						
						--And dazzle them with shiny effects.
						local ghs = P_SpawnMobjFromMobj(s,0,0,0, MT_HMSNOVAWAVE)
						ghs.scale = s.scale*2
						ghs.color = SKINCOLOR_CRIMSON
						
						ghs = P_SpawnMobjFromMobj(s,0,0,0, MT_HMSNOVAWAVE)
						ghs.scale = s.scale*2
						ghs.rollerwave = 16*FRACUNIT
						ghs.color = SKINCOLOR_EMERALD
						
						
						if SMS_Graphix(s) != 2
							ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_HMSNOVAWAVE)
							ghs.scale = s.scale*2
							ghs.color = SKINCOLOR_SUPERGOLD5
							ghs.rollangle = ANGLE_90
							
							for i = -2,1
								SMS_FlameWalls(s, FRACUNIT, 60*FRACUNIT, 256*i*FRACUNIT, A|FF_TRANS10, SKINCOLOR_SMS5R, 42, s)
							end
							A_SMSSTOMPQUAKE(s, 55, 14, FRACUNIT, 0, 0, 0, 0, SKINCOLOR_FLAME)
							SMS_SparkleFlash(tg.mo, nil, nil, FRACUNIT*2)
							
							if SMS_Graphix(s) == 0
								local ghs = SMS_LightFlash(s, SKINCOLOR_WHITE, FRACUNIT, 8, nil)	
								ghs.fuse = 20
						
								SMS_ElectricBody(s)					
								SMS_SmokeCircle(s)
							end
						end
						s.forceHMSyellanim = 24
						
						s.bhlcamtimer = 5
						p.camerascale = FRACUNIT*2
						
						--Cooldown and animation stuff.
						p.hms_instamove = 37
						p.hms_instamovew = 0
						
						//Special flag sync.
						if not (tg.mo.flags2 & MF2_TWOD) 
							s.flags2 = $ & ~MF2_TWOD
						else
							s.flags2 = $|MF2_TWOD
						end
						if not (tg.mo.flags2 & MF2_OBJECTFLIP)
							s.flags2 = $ & ~MF2_OBJECTFLIP
						else
							s.flags2 = $|MF2_OBJECTFLIP
						end						
					end
				end
	end
end)

--Getting Warp Conditions+Input down?
rawset(_G, "HMS_WarpInput", function(s, p)
	if not SMS_Locked(s, p)
	and not p.smsdivetimer
	and not p.hmsthrownnorise
	
		if P_IsObjectOnGround(s) 
			if (p.pflags & PF_SPINNING) and (s.z < s.floorz)
				s.z = s.floorz //Fix for lava stuckage.
			end
			s.z = $+(16*s.scale*P_MobjFlip(s))
		end
		P_SpawnMobjFromMobj(s, 0,0,0, MT_HMSWARPPOINTRETURN)
		P_SetObjectMomZ(s, 3*FRACUNIT)

		
		local ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_HMSWARPPOINT)
		ghs.angle = s.angle
		ghs.hmst = s
		ghs.ogz = ghs.z
		s.target = ghs
		P_InstaThrust(ghs, s.angle, 150*s.scale)
		p.hmswarpcooldown = 11
		if (p.pflags  & PF_SPINNING)
			s.forcewarp1 = 2
			p.pflags = $ & ~PF_SPINNING
		end
		s.state = S_HMS_INSTANTWARP1
		
		ghs = P_SpawnGhostMobj(s)
		ghs.tics = 20
		ghs.color = SKINCOLOR_SUPERSKY5
		ghs.scalespeed = $*3
		ghs.destscale = $*20
		
		s.momx = 0 
		s.momy = 0
		return true
	end
	return false
end)

--Calculate Hyper Mystic Sonic's timeshatter trajectory
/*
rawset(_G, "HMS_TimeShatter", function(s)
	for d = 1,9999
		if s
		return
		end
	end
end) */

--Cause a tornado as Hyper Mystic Sonic!
rawset(_G, "HMStornado", function (s, v, total, sprite, frame)
		--Set up wind!
		
		local wind = s.hmstor
		local wind2 = s.hmstor2
		while (wind and wind.valid)		
			P_MoveOrigin(wind,
			wind.x+40*FixedMul(s.scale, cos(wind.angle)),
			wind.y+40*FixedMul(s.scale, sin(wind.angle)),
			wind.z)
			
			wind.angle = $+(ANG1*5)
			wind.frame = ($ & FF_FRAMEMASK)|TR_TRANS50
			wind = wind.tracer --Chain to the last spawned object.
		end
		while (wind2 and wind2.valid)
			P_MoveOrigin(wind2, 
			wind2.x-40*FixedMul(s.scale, cos(wind2.angle)),
			wind2.y-40*FixedMul(s.scale, sin(wind2.angle)),
			wind2.z)
			
			wind2.angle = $-(ANG1*5)
			wind2.frame = ($ & FF_FRAMEMASK)|TR_TRANS50
			wind2 = wind2.tracer
		end
		
		--Sound object.
		if (leveltime % 70 == 0)
			s.tormobj = P_SpawnMobjFromMobj(s, 0,0, 80*s.scale, MT_THOK)
			s.tormobj.flags2 = $|MF2_DONTDRAW
			s.tormobj.tics = 72
			s.tormobj.fuse = 72
			S_StartSound(s.tormobj, sfx_s3kcel)
		end
						
			--Tornado hitbox.
			local ghs = P_SpawnMobj(s.x, s.y, s.z-9000*FRACUNIT, MT_SMSECHECK)
		
			if (leveltime % 5 == 0)
				if ghs and ghs.valid
					ghs.hmstornado = true
					ghs.target = s
					ghs.height = 99900*FRACUNIT
					ghs.radius = 1800*FRACUNIT
				end
			end
			
			//DNA-like tornado!
			if (leveltime % 12 == 0) 
				//We set the local wind variables at the top of the script!
				wind = P_SpawnMobj(s.x+560*FixedMul(s.scale, cos(ANGLE_90)), s.y+560*FixedMul(s.scale, sin(ANGLE_90)), s.z-(s.scale*80), MT_DUSTLAYER)
				wind.angle = ANGLE_180 //Remember that it's a papersprite!
				wind.flags = $|MF_NOCLIPHEIGHT
				wind.momz = (40*P_MobjFlip(s))*s.scale
				wind.scale = s.scale*8
				wind.momx = s.momx
				wind.momy = s.momy
				wind.tracer = s.hmstor
				s.hmstor = wind
				
			elseif (leveltime % 6 == 0) --Must be an elseif
				
				wind2 = P_SpawnMobj(s.x-560*FixedMul(s.scale, cos(ANGLE_90)), s.y-560*FixedMul(s.scale, sin(ANGLE_90)), s.z-(s.scale*80), MT_DUSTLAYER)
				wind2.angle = 0
				wind2.flags = $|MF_NOCLIPHEIGHT
				wind2.momz = (40*P_MobjFlip(s))*s.scale
				wind2.scale = s.scale*8
				wind2.momx = s.momx
				wind2.momy = s.momy
				wind2.tracer = s.hmstor2
				s.hmstor2 = wind2
			end
			
			local rng1 = P_RandomRange(-100,100) --Do a few less RNG calls if we can...
			local rng2 = P_RandomRange(-100,100)
			
			--Tornado ground effects.
			for d = 1,4,3
				ghs = P_SpawnMobj(
				s.x+s.momx+FixedMul( (rng1*FRACUNIT), cos(s.angle+(ANGLE_90*d))),
				s.y+s.momy+FixedMul( (rng2*FRACUNIT), sin(s.angle+(ANGLE_90*d))),
				s.z+(((rng2 or 1)/5)-d)*FRACUNIT,
				MT_HMSSTOMPAURA)
				
				ghs.scale = (s.scale*2)*10/(2+d)
				ghs.eflags = s.eflags
				ghs.tics = 10
				P_SetObjectMomZ(ghs, (6+(d*4))*FRACUNIT)
				if (s.eflags & MFE_VERTICALFLIP)
					ghs.z = $-(20*s.scale)
				end
				ghs.target = s
				ghs.color = P_RandomRange(SKINCOLOR_SUPERRED1, SKINCOLOR_SUPERGOLD5)
				ghs.frame = T|FF_FULLBRIGHT|TR_TRANS70
				ghs.scalespeed = $*10/(10+d)
				ghs.destscale = ghs.scalespeed+1
			end
			
			--Rocks flying out of the ground.
			if leveltime % 2
				if (s.eflags & MFE_VERTICALFLIP)
					ghs = P_SpawnMobj(
					s.x+((rng1*7)*FRACUNIT),
					s.y+((rng2*7)*FRACUNIT),
					s.ceilingz,
					MT_THOK)
				else
					ghs = P_SpawnMobj(
					s.x+((rng1*7)*FRACUNIT),
					s.y+((rng2*7)*FRACUNIT),
					s.floorz,
					MT_THOK)
				end
				
				P_SetObjectMomZ(ghs, max(10, 5+abs((rng1 or 1)/10) )
				*FRACUNIT )
				
				if leveltime % 8 == 0			
				elseif leveltime % 6 == 0
					ghs.scale = (s.scale*5)/3				
				elseif leveltime % 4 == 0
					ghs.scale = s.scale/3
				else
					ghs.scale = s.scale/2
				end
				ghs.eflags = s.eflags
				ghs.fuse = 70
				ghs.target = s
				if ghs.floorz == ghs.ceilingz
					ghs.state = S_NULL
				else
					ghs.state = S_ROCKCRUMBLEA
				end
			end
end)

/*
--Hyper Mystic Sonic's Hyper Rise.
rawset(_G, "HMS_HyperRise", function(s, p) 
	--Envelop in a golden aura when rising fast!
	if (abs(s.momz) > 2*s.scale)
		if (leveltime % 2 == 0) and not (p.smsgraphix == 2)
			A_SMSSTOMPSMOKE(s, P_RandomRange(5, 20), MT_NIGHTSPARKLE, P_RandomRange(1, 75)*FRACUNIT, nil, nil, SKINCOLOR_SUPERGOLD5)
		end
		if s.jumprsmoke and s.jumprsmoke.valid
			s.jumprsmoke.fed = 2
			s.jumprsmoke.fuse = 3
		else
			s.jumprsmoke = P_SpawnMobjFromMobj(s,0,0,0, MT_HMSRISEAURA)
			s.jumprsmoke.initscale = s.scale*3/2
			s.jumprsmoke.target = s
			s.jumprsmoke.fed = 2
			s.jumprsmoke.fuse = 3
		end
		
		local ghs = P_SpawnGhostMobj(s)
		ghs.rollangle = s.rollangle
		ghs.blendmode = AST_ADD
		if s.hmsspinang != nil and s.hmsspinpass
			ghs.angle = s.hmsspinang
		end
		if s.momz
			ghs.z = $-(24*s.scale*P_MobjFlip(s))
		end
	end
	 --Starting boost!
	if (s.hms_jumprisen == 4)
		p.pflags = $|PF_JUMPED & ~PF_STARTJUMP
		S_StartSound(s, sfx_kc5b)
		s.hms_jumprisen = 3
		
		--Colorful explosion on initial burst
		if not p.smsgraphix
		and not s.haltthespam
			local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_HMSNOVAWAVE) 
			ghs.scale = s.scale*10/P_RandomRange(9,15)	
			A_SMSSTOMPSMOKE(s, 20, MT_ENERGYBALL, 200)
		end
		if not s.haltthespam
			s.haltthespam = 2
		else
			s.haltthespam = max($,2)
		end
		
		P_SetObjectMomZ(s, 8*FRACUNIT+25000, true) //Spam the button to rise even faster.
	
		if (s.momz > 0) and not (s.eflags & MFE_VERTICALFLIP)
		or (s.momz < 0) and (s.eflags & MFE_VERTICALFLIP)
			A_SMSquake(s, s.momz/2, (s.momz/FRACUNIT)/12)
		end
	elseif s.hms_jumprisen 
		s.hms_jumprisen = $-1
	end		
end)

--HMS rising flight function. Fly up, my pretty!
rawset(_G, "HMS_Rise", function(s, p) 

		if (p.cmd.buttons & BT_CUSTOM2) and (p.cmd.buttons & BT_TOSSFLAG)
		and not (p.cmd.buttons & BT_JUMP)
			s.hms_readyriseboost = 2
			s.hms_jumphold = 10
			print("SUPERFLY!")
			HMS_SuperFly(s, p) --Final demo style superfly instead?	
			return --
		end
		
		if (p.cmd.buttons & BT_TOSSFLAG) --Good to go right away!
			s.hms_jumphold = 10
			s.hms_readyriseboost = 0
		else
			s.hms_jumphold = 0
			s.hms_readyriseboost = 2 
		end
		
		print(s.hms_jumprisen)
		
		--We keep jumprisen at 3 to fuel it, otherwise...
		if not s.hms_jumprisen
			s.hms_jumprisen = 4 --Blast skywards!
		else
			s.hms_jumprisen = 3 --Uphold boost dash instead!
		end	
		
		if s.momz and not s.hmsspinfreeze
			s.hmsspinpass = 16
		end			
		 --Don't need to set this if you're already going over 40.
		if not (s.momz*P_MobjFlip(s) >= 40*s.scale) 
			P_SetObjectMomZ(s, 40*FRACUNIT)
		end
		
		s.hmgodticket = true
		s.hmsstompsfx = false
		
		--Fly and rise normally?
		if not (p.cmd.buttons & BT_TOSSFLAG)
		and not ((p.pflags & PF_STARTJUMP) and (s.momz*P_MobjFlip(s)) > s.scale)
		and not (s.momz*(P_MobjFlip(s)) > 12*s.scale)
			if (s.state == S_PLAY_SPRING) or (p.panim == PA_SPRING)
				s.state = S_PLAY_RUN
			end
			p.sms_jumphold = 0				
			if (p.cmd.buttons & BT_FIRENORMAL)
			and (s.z > s.ceilingz-120*FRACUNIT) and (s.floorz < s.ceilingz-300*FRACUNIT) //Not in extremely tight spaces.
				s.momz = 0
			else
				P_SetObjectMomZ(s, 7*FRACUNIT, false)
			end
			p.pflags = $|PF_JUMPED & ~PF_STARTJUMP & ~PF_SPINNING
		end		
end)

--final demo style superfly
rawset(_G, "HMS_SuperFly", function(s, p)  //Recreating the old superfly.
	if not (p.pflags & PF_STARTDASH)
	and not P_IsObjectOnGround(s)
		if (p.cmd.buttons & BT_FIRENORMAL)
		and (s.z > s.ceilingz-120*FRACUNIT) and (s.floorz < s.ceilingz-300*FRACUNIT) //Not in extremely tight spaces.
			s.momz = 0
		end
		p.pflags = $|PF_JUMPED & ~PF_STARTJUMP & ~PF_SPINNING
		return true
	end	
end) */

--Fire the NovaBlast!
rawset(_G, "HMS_FireNovaBlast", function(s, p, instant)	
			s.novazaim = false
			if instant != nil
				p.novafire = 101
				s.state = S_HMSNOVAFIRE2
				s.tics = 61 s.anim_duration = 61
				s.momz = 0
				p.hypermysticsonic = max($, 41)
				P_FlashPal(p, PAL_NUKE,6)
				S_StartSound(s, sfx_smsfx8)
				A_SMSquake(s, 80*FRACUNIT, 60, 1800)
				HMS_NovaBlastShine(s, 100)
				SMS_Embers(s, s,0)	
				SMS_GroundWindBlast(s)
			else
				s.state = S_HMSNOVAFIRE1
				p.novafire = 125
			end
			p.pflags = $|PF_ATTACKDOWN
			s.hmgodticket = true
			S_StartSound(s, sfx_beeyow)
			s.spritexscale = FRACUNIT+12100
			s.spriteyscale = FRACUNIT-10000
			s.spriteyoffset = 5*FRACUNIT
			s.SMS_squashtable = {timer = 6, Xspeed = 4200, Yspeed = 4500, air = true}	
					
			local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_HMSNOVAWAVE)
			ghs.color = SKINCOLOR_CRIMSON
			ghs.followmenoz = s
					
			ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_HMSLIGHTNING2)
			ghs.followsms = s
			ghs.ltimershort = true 
			ghs.color = SKINCOLOR_CRIMSON
			
			if not P_IsObjectOnGround(s)		
				p.pflags = $|PF_JUMPED	& ~PF_SPINNING & ~PF_THOKKED
			end
			return true --
end)


--HMScombo, the God Breaker! Toss Flag + Custom 2 on nearby enemies.
--Ridiculously stupidly made code, but won't cause lag with the way it's laid out.
rawset(_G, "HMS_GodBreaker", function(s, p)

		  s.SMS_locked = true --overkill, tbh.
		  p.powers[pw_noautobrake] = max($,2)
		  p.powers[pw_ignorelatch] = 32768
		  p.powers[pw_nocontrol] = 2 --You can shift your angle, but otherwise it's "no controls" thing.
		  s.flags = $|MF_NOCLIPTHING --Don't clip on stuff for a bit.
		  p.pflags = $ & ~PF_SPINNING & ~PF_STARTDASH
		  s.starthmscombo = max($-1, 0)
		   
			local t = s.hmsspint2
			
			if t.player --Special behaviour for players.
				local tp = t.player
				P_FlashPal(tp, PAL_MIXUP, 10)
				tp.powers[pw_nocontrol] = 2
				tp.powers[pw_flashing] = -1
				tp.powers[pw_tailsfly] = 0
				tp.secondjump = 0
				tp.fly1 = 0
				if not tp.MSsettings
					tp.viewrollangle = t.rollangle
				end
				tp.pflags = $|PF_JUMPDOWN|PF_USEDOWN & ~(PF_JUMPED|PF_SLIDING|PF_SPINNING)
				tp.buttons = $ & ~(BT_CUSTOM3|BT_CUSTOM2|BT_CUSTOM1|BT_TOSSFLAG)
				t.hmscchange = true
				tp.smsmeleebutton = 850
				t.SMS_locked = true
				t.sprite = SPR_PLAY --Force painframe without the state.
				t.sprite2 = SPR2_PAIN
				t.frame = $ & ~FF_FRAMEMASK
				t.tics = 500
				t.anim_duration = 500
				t.nuuuuuuuuu = true
			end
			
			--15 tics after the last hit, continue!
			if (s.starthmscombo == 1) or (p.rings <= 1)
				HMS_AuraStorm(s)
				local ghs = SMS_LightFlash(s, SKINCOLOR_MYSTICAL1)
				ghs.tracer = s
				ghs.frame = $+(2*FRACUNIT)
				ghs.fuse = 50
				ghs.spriteyoffset = -16*FRACUNIT
				
				p.powers[pw_ignorelatch] = 0
				s.flags = $ & ~(MF_NOCLIPTHING|MF_BOUNCE)
				P_SpawnMobjFromMobj(s, 0,0,0, MT_SMSGROUNDBOOST)
				P_SetObjectMomZ(s, 8*FRACUNIT)
				P_AddPlayerScore(p, 100)
				s.state = S_PLAY_FALL
				if not P_IsObjectOnGround(s)
					p.pflags = $|PF_JUMPED & ~PF_THOKKED
				end
				
				if t.valid and t.health 
				and not (t.player and t.player.hypermysticsonic)
				and not (t.type == MT_CRUSHSTACEAN) 
				and not (t.type == MT_BANPYURA) //These two crash the game for some reason.
				and not (t.info.mass == 2006) 
					t.rollangle = 0
					if (t.player and t.player.ctfnamecolor and p.ctfnamecolor)
						P_PlayerFlagBurst(t.player)
						print("RIP: "+t.player.ctfnamecolor+". You will be missed. But not by "+p.ctfnamecolor+", who clearly hates you.")
					end
					if G_PlatformGametype()
						P_KillMobj(t, nil, s)
					else
						P_KillMobj(t)
					end
				end
			--	if (p.rings <= 1) --...??
			--		P_GivePlayerRings(p, -2)
			--	end
				s.hmsspint2 = nil
				s.starthmscombo = 0
				return --
			end

			if (s.starthmscombo <= 160 and s.starthmscombo > 1)	
			
				if (t.health <= 1) --You keep your ass alive until we're done.
					t.health = 3
				end
				
				t.anim_duration = 5
				t.godbreakervictim = true
				
				if t.fuse
					t.fuse = $+1 //Extend their fuse.
				end
				if (t.z+t.height > t.ceilingz)
					t.z = t.ceilingz-t.height
				end
				if (s.starthmscombo > 80)
					t.rollangle = leveltime*FixedAngle(55*FRACUNIT)
				elseif (s.starthmscombo > 30)
					t.rollangle = leveltime*FixedAngle(40*FRACUNIT)
				else
					t.rollangle = leveltime*FixedAngle(16*FRACUNIT)
				end
				if t.player
					t.player.rings = 2
					P_PlayerFlagBurst(t.player)
				end
			end
			if (s.starthmscombo <= 160 and s.starthmscombo > 105)
			
				if (s.starthmscombo < 160)
					if (t.type == MT_MINUS)
						t.state = S_MINUS_AERIAL2
						t.flags = $|MF_SHOOTABLE|MF_SPECIAL
					elseif (t.info.painstate == S_NULL)
						P_SetMobjStateNF(t, t.info.spawnstate)
					else
						P_SetMobjStateNF(t, t.info.painstate)
					end
				end
				if (t.type == MT_GOLDBUZZ) or (t.type == MT_REDBUZZ)
					P_TryMove(t, t.x+FixedMul(44*FRACUNIT, cos(s.angle)), t.y+FixedMul(44*FRACUNIT, sin(s.angle)) , true)
					P_TryMove(s, s.x+FixedMul(44*FRACUNIT, cos(s.angle)), s.y+FixedMul(44*FRACUNIT, sin(s.angle)) , true)
				end
				
				t.angle = t.angle+ANGLE_45
				t.tics = 106
				t.reactiontime = 106 //Set these so nothing'll change
				s.momx = t.momx
				s.momy = t.momy
				s.momz = t.momz
				s.state = S_PLAY_HMSCOMBO1
				
					if t.player
						t.target = nil //Forget your target. Think about yourself!
					end
					if t.tracer and t.tracer.player //Trace HMS, not any other player
						t.tracer = s
					elseif t.tracer and t.tracer.valid and (t.type == MT_GSNAPPER)
						t.tracer.momx = t.momx
						t.tracer.momy = t.momy
						t.tracer.momz = t.momz
						t.tracer.rollangle = t.rollangle
					end

					if s.starthmscombo == 159
						SMS_PunchSmear(s,p)
						SMS_GroundWindBlast(s)
						SMS_RisingCraterFlames(s)
						A_SMSSTOMPSMOKE(s, 70, MT_HMSLIGHTNING2, nil, -5*FRACUNIT, nil, SKINCOLOR_SUPERGOLD5)
						S_StartSound(s, sfx_bkpoof)
						S_StartSound(s, sfx_nerf)
						P_FlashPal(p, PAL_NUKE, 10)
						A_SMSquake(s, 60*FRACUNIT, 6, 6022)
						P_InstaThrust(t, s.angle, 40*FRACUNIT)
						P_SpawnMobjFromMobj(t, 0, 0, 0, MT_BURSTWAVE)
						P_SpawnMobjFromMobj(s, 0,0,0, MT_BURSTLIGHT)
						P_SetObjectMomZ(t, 10*FRACUNIT)
						s.state = S_PLAY_RUN
						local ghs = P_SpawnMobjFromMobj(s,0,0,0, MT_RADIALBOOST)
						ghs.color = SKINCOLOR_YELLOW
						s.z = t.z
						P_TryMove(s, t.x, t.y, true)

					elseif s.starthmscombo == 149
						SMS_PunchSmear(s,p)
						SMS_RisingFlames(s)
						SMS_WindBlast(s)
						S_StartSound(s, sfx_nerf)
						A_SMSquake(s, 54*FRACUNIT, 5, 6022)
						P_InstaThrust(t, s.angle-ANGLE_22h, 55*FRACUNIT)
						P_SpawnMobjFromMobj(t, 0,0,0, MT_BURSTWAVE)
						P_SetObjectMomZ(t, 1*FRACUNIT)

					elseif s.starthmscombo == 141
						SMS_ElectricRecoil(s)
						S_StartSound(s, sfx_nerf)
						P_InstaThrust(t, s.angle+ANGLE_22h, 40*FRACUNIT)
						A_SMSquake(s, 52*FRACUNIT, 8, 6022)
						P_SetObjectMomZ(t, 16*FRACUNIT)
						P_SpawnMobj(t.x, t.y, t.z, MT_BURSTWAVE)
						P_SpawnMobj(t.x-175*FRACUNIT, t.y+150*FRACUNIT, t.z+100*FRACUNIT, MT_BURSTLIGHT)
						P_SpawnMobj(t.x+175*FRACUNIT, t.y-160*FRACUNIT, t.z-10*FRACUNIT, MT_BURSTLIGHT)
						
					elseif (s.starthmscombo == 137 or s.starthmscombo == 114 or s.starthmscombo == 154)
						local COLORTABLE = {SKINCOLOR_SMS1R, SKINCOLOR_SMS3R, SKINCOLOR_SMS5R, SKINCOLOR_ORANGE, SKINCOLOR_RED, SKINCOLOR_LIME, SKINCOLOR_EMERALD, SKINCOLOR_MINT, SKINCOLOR_WHITE}
						SMS_PunchSmear(s,p)
						SMS_WindBlast(t)
						S_StartSound(t, sfx_nerf)
						P_SpawnMobj(t.x+80*FRACUNIT, t.y-70*FRACUNIT, t.z+25*FRACUNIT, MT_BURSTWAVE)
						P_SpawnMobj(t.x+120*FRACUNIT, t.y-150*FRACUNIT, t.z+50*FRACUNIT, MT_BOSSEXPLODE)
						P_SpawnMobj(t.x-140*FRACUNIT, t.y+170*FRACUNIT, t.z-5*FRACUNIT, MT_BOSSEXPLODE)
						P_SpawnMobj(t.x+300*FRACUNIT, t.y+290*FRACUNIT, t.z+77*FRACUNIT, MT_BURSTLIGHT)
						P_SpawnMobj(t.x-280*FRACUNIT, t.y-277*FRACUNIT, t.z-33*FRACUNIT, MT_BURSTLIGHT)	
						
						--Draw an attack line!
						local ghs = P_SpawnMobjFromMobj(s,0,0,0, MT_SMSAUTOFRAME)
						ghs.sprite = SPR_HMSO
						ghs.renderflags = RF_NOCOLORMAPS|RF_FULLBRIGHT
						ghs.frame = G|TR_TRANS90
						ghs.frame = (s.starthmscombo == 114) and $|FF_HORIZONTALFLIP or $
						ghs.blendmode = AST_ADD
						ghs.fuse = 11 ghs.tics = 99
						ghs.scalespeed = FRACUNIT/10
						ghs.sttfade = 9
						ghs.sttYspeed = FRACUNIT*4
						ghs.destscale = 1
						ghs.COLORT_trail = COLORTABLE
						ghs.COLORT_trailno = 9
						ghs.ENDtrans = 0
						
						local ANGLE = s.angle+(SMSLocalRNG(-60, 60, s)*ANG1)
						P_SetOrigin(ghs,
						t.x+t.momx+FixedMul(-300*s.scale, cos(ANGLE)),
						t.y+t.momy+FixedMul(-300*s.scale, sin(ANGLE)),
						t.z+(t.height/4)+(SMSLocalRNG(-199, 199, s)*s.scale))
						SMS_DrawTrail(s, ghs, MT_SMSAUTOFRAME)
						ghs.state = S_NULL
						
						local ghs = SMS_DashGFX(s, SKINCOLOR_RED) 
						ghs.fuse = 8
						ghs.sttspeed = 1
						ghs.sttfade = true
						ghs.frame = (s.starthmscombo == 114) and ($|FF_HORIZONTALFLIP & ~FF_TRANSMASK) or ($ & ~FF_TRANSMASK)


					elseif s.starthmscombo == 132
						SMS_ElectricRecoil(s)
						S_StartSound(s, sfx_nerf)
						P_InstaThrust(t, s.angle-ANGLE_11hh, 47*FRACUNIT)
						A_SMSquake(s, 80*FRACUNIT, 10, 6022)
						P_SpawnMobj(t.x, t.y, t.z, MT_BURSTWAVE)
						P_SpawnMobj(t.x-150*FRACUNIT, t.y-200*FRACUNIT, t.z+70*FRACUNIT, MT_BURSTWAVE)
						P_SpawnMobj(t.x+240*FRACUNIT, t.y+190*FRACUNIT, t.z+50*FRACUNIT, MT_BURSTWAVE)
						P_SetObjectMomZ(t, -10*FRACUNIT)
						
					elseif s.starthmscombo == 120
						SMS_ElectricRecoil(s)
						SMS_PunchSmear(s,p)
						SMS_RisingCraterFlames(s)
						S_StartSound(s, sfx_nerf)
						A_SMSquake(s, 64*FRACUNIT, 6, 6022)
						P_InstaThrust(t, s.angle+ANGLE_11hh, 43*FRACUNIT)
						P_SpawnMobj(t.x, t.y, t.z, MT_BURSTWAVE)
						P_SpawnMobj(t.x+195*FRACUNIT, t.y-180*FRACUNIT, t.z+80*FRACUNIT, MT_BURSTLIGHT)
						P_SpawnMobj(t.x-186*FRACUNIT, t.y+177*FRACUNIT, t.z-20*FRACUNIT, MT_BURSTLIGHT)
						P_SetObjectMomZ(t, 14*FRACUNIT)
					end

			--Below 105 now!
			
			elseif (s.starthmscombo <= 105 and s.starthmscombo > 80)
			
				if (t.type == MT_MINUS)
					t.state = S_MINUS_AERIAL2
					t.flags = $|MF_SHOOTABLE|MF_SPECIAL
				elseif ((t.info.deathstate != S_NULL) and (t.player or t.flags & MF_BOSS) and (t.skin != "sms"))
					P_SetMobjStateNF(t, t.info.deathstate)
				elseif ((t.info.painstate != S_NULL) and (t.player or t.flags & MF_BOSS))
					P_SetMobjStateNF(t, t.info.painstate)
				else
					P_SetMobjStateNF(t, t.info.spawnstate)
				end

				P_SpawnMobjFromMobj(t, 
				((P_RandomRange(FixedMul(-56, t.scale), FixedMul(56, t.scale)))*FRACUNIT), 
				((P_RandomRange(FixedMul(-56, t.scale), FixedMul(56, t.scale)))*FRACUNIT), 
				((P_RandomRange(FixedMul(1, t.scale), FixedMul(65, t.scale)))*FRACUNIT),
				MT_BOSSEXPLODE)

				t.angle = s.angle+ANGLE_180
				s.momx = 0
				s.momy = 0
				s.momz = 1
				
					if s.starthmscombo == 105
						SMS_RisingCraterFlames(s)
						SMS_RisingFlames(s)
						S_StartSound(s, sfx_nerf)
						A_SMSquake(s, 93*FRACUNIT, 5, 10022)
						P_InstaThrust(t, s.angle+ANGLE_11hh, 56*FRACUNIT)
						P_SpawnMobj(t.x, t.y, t.z, MT_BURSTWAVE)
						t.momz = 0
						s.state = S_PLAY_RUN
						
					elseif s.starthmscombo == 100
						SMS_RisingCraterFlames(s)
						S_StartSound(t, sfx_s3k4b)
						S_StartSound(s, sfx_s3kbcs)
						P_InstaThrust(t, s.angle, 0)
						P_SpawnMobj(t.x, t.y, t.z, MT_BURSTLIGHT)
						P_SetObjectMomZ(t, 16*FRACUNIT)
					end
					
			--80 or below	
			
			elseif (s.starthmscombo > 15 and s.starthmscombo <= 80)
				if (t.type == MT_MINUS)
					t.state = S_MINUS_AERIAL2
				elseif (t.info.painstate == S_NULL)
					P_SetMobjStateNF(t, t.info.spawnstate)
				else
					P_SetMobjStateNF(t, t.info.painstate)
				end
				t.angle = t.angle-(ANGLE_11hh/2)
				s.hmgodticket = true
				s.state = S_PLAY_HMSCOMBO2
				s.momx = 0
				s.momy = 0
				if (t.z+190*FRACUNIT < s.z) and ((s.starthmscombo < 45) or (t.flags & MF_BOSS))
					s.momz = -50*FRACUNIT
					t.momz = $/2
				elseif (t.z-190*FRACUNIT > s.z) and ((s.starthmscombo < 45) or (t.flags & MF_BOSS))
					s.momz = 50*FRACUNIT
					t.momz = $/2
				else
					s.momz = 1
				end
				if (s.starthmscombo > 20 and s.starthmscombo < 63)
					SMS_StompGFX(s, p, true, true)
				end				
				if (t.momz < 2*FRACUNIT)
					if (s.starthmscombo >= 63)
						P_SetObjectMomZ(t, -6*FRACUNIT)
						P_InstaThrust(t, s.angle, 7*FRACUNIT)
						HMS_NegativeZone(s, s, true, SKINCOLOR_BLACK, A|FF_TRANS70)
					elseif (s.starthmscombo > 45)
						P_SetObjectMomZ(t, -4*FRACUNIT)
						P_InstaThrust(t, s.angle, 3*FRACUNIT)
						HMS_NegativeZone(s, s, true, SKINCOLOR_BLACK, A|FF_TRANS50)
					else
						P_SetObjectMomZ(t, -105355)
						P_InstaThrust(t, s.angle, 0)
						P_FlashPal(p, PAL_MIXUP, 2)
						if t.player
							P_FlashPal(t.player, PAL_MIXUP, 2)
						end
					end
				end	
				
				if s.starthmscombo == 80
						SMS_QuickDustGFX(s)
						s.SMS_DLtrail = {timer = 1, colorized = true, color = SKINCOLOR_RED}
						s.z = max(t.z-140*s.scale, s.floorz+10*s.scale) --Warp!
						P_TryMove(s, t.x, t.y, true)
						SMS_ContinuousTrail(s, s.SMS_DLtrail)
						S_StartSound(t, sfx_s3k7c)
						S_StartSound(t, sfx_s3k83)
						P_FlashPal(p, PAL_MIXUP, 4)
						P_InstaThrust(s, s.angle, 0)
						P_SpawnMobjFromMobj(s, 0, 0, 0, MT_BURSTLIGHT)
						s.state = S_PLAY_HMSCOMBO2
						SMS_GroundWindBlast(s)
						SMS_MediumDustGFX(s)
						SMS_GoldWaves(s,p)
						SMS_ElectricBody(s, 35)
						
				elseif s.starthmscombo == 63
				
					SMS_GroundWindBlast(s)
					s.bhlcamtimer = 130
					S_StartSound(s, sfx_s3ka0)
					P_FlashPal(p, 3, 3)
					local ghs = P_SpawnMobjFromMobj(s, 0,0, -5*FRACUNIT, MT_BURSTWAVE)
					ghs.color = SKINCOLOR_RED
					SMS_ElectricBody(s, 43)	
						
				elseif s.starthmscombo == 45
					s.bhlcamtimer = 30
					p.camerascale = FRACUNIT*4
					S_StartSound(t, sfx_s3k9c)
					S_StartSound(s, sfx_beeyow)
				end
				
			 --The last 15 tics. Not counting exact 1.	
			elseif (s.starthmscombo <= 15 and s.starthmscombo > 1)
			local ghs
				if (t.type == MT_MINUS)
					t.state = S_MINUS_AERIAL2
				elseif (t.info.painstate == S_NULL)
					P_SetMobjStateNF(t, t.info.spawnstate)
				else
					P_SetMobjStateNF(t, t.info.painstate)
				end

				P_SpawnMobjFromMobj(t,
				((P_RandomRange(FixedMul(-150, t.scale), FixedMul(150, t.scale)))*FRACUNIT), 
				((P_RandomRange(FixedMul(-150, t.scale), FixedMul(150, t.scale)))*FRACUNIT), 
				((P_RandomRange(FixedMul(-20, t.scale), FixedMul(130, t.scale)))*FRACUNIT),
				MT_BOSSEXPLODE)

				t.angle = t.angle-(ANGLE_11hh/4)
				s.momx = 0
				s.momy = 0
				s.momz = 1
				t.momz = 0
				s.hmgodticket = true
				s.state = S_PLAY_HMSCOMBO3
							
				local COLORTABLE = {SKINCOLOR_SMS1R, SKINCOLOR_SMS3R, SKINCOLOR_SMS5R, SKINCOLOR_ORANGE, SKINCOLOR_RED, SKINCOLOR_LIME, SKINCOLOR_EMERALD, SKINCOLOR_MINT, SKINCOLOR_WHITE}
				local HMSCOLOR = COLORTABLE[SMS_TimeFrame(9, 1)]
				HMS_AuraStorm(s, nil, HMSCOLOR, nil, nil, nil)
				HMS_BoltStorm(s, HMSCOLOR, 7, SMSLocalRNG(1,37, s)*ANG1, SMSLocalRNG(-50,550, s))
				
				COLORTABLE = {SKINCOLOR_SMS1R, SKINCOLOR_SMS3R, SKINCOLOR_SMS5R, SKINCOLOR_ORANGE, SKINCOLOR_RED, SKINCOLOR_SMS4R, SKINCOLOR_SMS2R, SKINCOLOR_SMS1R, SKINCOLOR_MYSTICAL5}
				HMSCOLOR = COLORTABLE[SMS_TimeFrame(5, 1)]
				
				if s.starthmscombo == 15 --The final hit! Make it count!
				
				p.camerascale = FRACUNIT
				s.bhlcamtimer = 0
				A_SMSquake(s, 87*FRACUNIT, 34, 21022)
				S_StartSound(t, sfx_s3k81)
				P_FlashPal(p, 4, 4)
				S_StartSound(s, sfx_pwbmb)
				S_StartSound(t, sfx_s3k54)
				
				SMS_GoldWaves(s,p) --Kitchen sink, goooo!
				
				local ghs = HMS_GigaJetBolt(s)
				ghs.tracer = s
				
				SMS_GroundWindBlast(s)
				SMS_WindBlast(s)
				
	    	 		for m in mobjs.iterate(mobjs)
						if ((m.flags & MF_ENEMY) or (m.flags & MF_BOSS))
						and m.health
						and not m.hmscombod
						and not (m == t)
							if ((FixedHypot(m.x-ghs.x, m.y-ghs.y)) < 3200*FRACUNIT)
							P_KillMobj(m, ghs, s)
							end
						end
						if G_GametypeHasSpectators()
						and m.player and m.health
						and not m.hmscombod
						and not m.player.hypermysticsonic
						and not (m.player.ctfteam and (m.player.ctfteam == p.ctfteam))
							if ((FixedHypot(m.x-ghs.x, m.y-ghs.y)) < 2800*FRACUNIT)
							P_DamageMobj(m, ghs, s)
							P_InstaThrust(m, m.angle, -10*FRACUNIT)
							P_SetObjectMomZ(m, 24*FRACUNIT)
							end
						end
	    	 		end

					for i = -1,1,2
						local ghs = P_SpawnMobjFromMobj(s, (400*FRACUNIT*i), (400*FRACUNIT*i), -100*FRACUNIT, MT_HMSLIPILLAR)
						ghs.color = COLORTABLE[P_RandomRange(1,9)]
					
						ghs = P_SpawnMobjFromMobj(s, -(400*FRACUNIT*i), (400*FRACUNIT*i), -100*FRACUNIT, MT_HMSLIPILLAR)
						ghs.color = COLORTABLE[P_RandomRange(1,9)]
					
						ghs = P_SpawnMobjFromMobj(s, (400*FRACUNIT*i), 0, -100*FRACUNIT, MT_HMSLIPILLAR)
						ghs.color = COLORTABLE[P_RandomRange(1,9)]
					end

					local ghs = P_SpawnMobjFromMobj(t, 0, 0, -10*FRACUNIT, MT_BURSTWAVE)
					ghs.color = SKINCOLOR_RED

				elseif s.starthmscombo == 7
				
				S_StartSound(s, sfx_s3k54)

					for i = -1,1,2 --Why am I bothering to improve this mess...
					local ghs = P_SpawnMobjFromMobj(s, 1250*FRACUNIT, (1250*FRACUNIT*i), s.z-1000*FRACUNIT, MT_HMSLIPILLAR)
					ghs.color = COLORTABLE[P_RandomRange(1,9)]
					ghs = P_SpawnMobjFromMobj(s, -(1250*FRACUNIT*i), -(1250*FRACUNIT*i), s.z-1000*FRACUNIT, MT_HMSLIPILLAR)
					ghs.color = COLORTABLE[P_RandomRange(1,9)]

					ghs = P_SpawnMobjFromMobj(s, -(1250*FRACUNIT*i), (1250*FRACUNIT*i), s.z-1000*FRACUNIT, MT_HMSLIPILLAR)
					ghs.color = COLORTABLE[P_RandomRange(1,9)]

					ghs = P_SpawnMobjFromMobj(s,0,(1250*FRACUNIT*i),-(1250*FRACUNIT*i), MT_HMSLIPILLAR)
					ghs.color = COLORTABLE[P_RandomRange(1,9)]

					ghs = P_SpawnMobjFromMobj(s,(1250*FRACUNIT*i),0,-(1250*FRACUNIT*i), MT_HMSLIPILLAR)
					ghs.color = COLORTABLE[P_RandomRange(1,9)]
					end

				elseif s.starthmscombo == 2
				
					if not t.hmscombopreflags == nil
						t.flags = t.hmscombopreflags
						t.rollangle = 0
 						t.flags = $|MF_NOCLIPTHING
					end
					
					local ghs = P_SpawnMobjFromMobj(s,0,0,-5*FRACUNIT, MT_BURSTWAVE)
					ghs.color = SKINCOLOR_RED

					S_StartSound(t, sfx_s3k54)
				
					for i = -1,1,2 
					ghs = P_SpawnMobjFromMobj(s,(2600*FRACUNIT*i), (2600*FRACUNIT*i), 0, MT_HMSLIPILLAR)
					ghs.color = COLORTABLE[P_RandomRange(1,9)]
					ghs = P_SpawnMobjFromMobj(s,-(2600*FRACUNIT*i), -(2600*FRACUNIT*i), 0, MT_HMSLIPILLAR)
					ghs.color = COLORTABLE[P_RandomRange(1,9)]

					ghs = P_SpawnMobjFromMobj(s,-(2600*FRACUNIT*i), (2600*FRACUNIT*i), 0, MT_HMSLIPILLAR)
					ghs.color = COLORTABLE[P_RandomRange(1,9)]

					ghs = P_SpawnMobjFromMobj(s,0,(2600*FRACUNIT*i), 0, MT_HMSLIPILLAR)
					ghs.color = COLORTABLE[P_RandomRange(1,9)]

					ghs = P_SpawnMobjFromMobj(s,(2600*FRACUNIT*i), 0, 0, MT_HMSLIPILLAR)
					ghs.color = COLORTABLE[P_RandomRange(1,9)]
					end
					
				end				
				return --
			end
end)

--Some minor things when you're moving above 6*s.scale speed.
rawset(_G, "HMS_SpeedingBehaviour", function(s, p) 
					--Spawn rising floor flames!
					if not (s.eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) //No flames when underwater, ofcourse.
					and not A_HMSCheckDeathPit(s) //Not when on a death pit....
					
					//	A_SMSquake(s, p.speed/3, 1, (p.speed/65355)*700, true)
						if (p.speed > 138*s.scale)
						s.hmsmwh = 1
							if (p.pflags & PF_SPINNING)
								s.hmsfsfx = false
								A_SMSSpinFire(s, MT_SMSSPINFIRE, 65357)
								A_SMSSpinFire(s, MT_SMSSPINFIRE, 65357, 5*FRACUNIT)
							else
								if not s.hmsfsfx
									s.hmsfsfx = true
									S_StartSound(s, sfx_s3k43) //S_StartSound(s, sfx_s3k48)
								end
								A_HMSfiretrail(s)
							end
							if s.maxtimex == nil
								s.maxtimex = 0
								s.maxtimey = 0
								s.maxtimers = 0
							end
							if s.x == s.maxtimex and s.y == s.maxtimey
								if s.maxtimers == nil
									s.maxtimers = 1							
								else
								s.maxtimers = $+1
									if (s.maxtimers > 31)
										s.z = s.floorz+5*FRACUNIT
										P_DoJump(p, false) //SRB2's colission is screwing you. Stop this madness.
										s.momx = 0
										s.momy = 0
										s.momz = 0
									end
								end
							else
								s.maxtimers = 0				
							end
						
							s.maxtimex = s.x
							s.maxtimey = s.y
						else
							if not s.hmsfsfx
								s.hmsfsfx = true
								S_StartSound(s, sfx_s3k43) //S_StartSound(s, sfx_s3k48)
							end
					  		if SMS_Graphix(s) != 2
								if (s.eflags & MFE_JUSTHITFLOOR)
								or (leveltime % 2 == 0)
								or (p.speed > 56*s.scale)
									A_HMSfiretrail(s)
								end
				     		end
						end
					end
					if (p.speed >= 137*s.scale) --We've got alot of speed!
						s.hmsmwh = 1
						if (leveltime % 2 == 0)
							if (leveltime % 4 == 0)
								P_NukeEnemies(s, s, 650*s.scale)
							else
								for i = -1,1
									local ghs = SMS_CraterSpew(s, s.angle+(ANG1*120*i), 13)
									if ghs and ghs.valid
										ghs.spritexscale = $*3/2
										ghs.spriteyscale = $*3/2
										ghs.momx = ($*9)+FixedDiv(FixedMul(s.momx, 2),3)
										ghs.momy = ($*9)+FixedDiv(FixedMul(s.momy, 2),3)
										ghs.smsrgtimer = 23
									end
								end
							end
						end
						local ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_SMSGROUNDBOOST)
						ghs.tracer = s
						A_SMSquake(s, 14*FRACUNIT, 1, 4122, true)
						s.hmsrunquake = 1
					end
					return true --
end)
--Includes HMS 7-flames, Novablast, and Black Hole attack.
rawset(_G, "HMS_AirAttacks", function(s, p) 

	local GRAPHIX = SMS_Graphix(s) --So I only have to check it once.
	
		//Here's a crazy attack for you; HMS' Hypernova blast!
		//He fires a stream of concentrated energy spheres with incredible explosive power!
		
		if (s.state == S_HMSNOVAFIRE1) --Firing the NovaBlast!
		
					s.momz = 0
					
					if (s.z >= s.ceilingz-150*s.scale) and (s.floorz < s.ceilingz-150*s.scale)
						s.momz = -10*s.scale
					elseif (s.z < s.floorz+70*s.scale)
						s.momz = 10*s.scale
					end
					if (p.novafire == 124 or p.novafire == 117)
						s.momx = FixedDiv(FixedMul($, 100), 121)
						s.momy = FixedDiv(FixedMul($, 100), 121)
						if p.novafire == 124
							p.camerascale =  FRACUNIT*5/3
							P_NukeEnemies(s, s, 200*s.scale) //Nuke-stars are mostly for show.
							HMS_AuraStorm(s, nil, SKINCOLOR_RED)
							local ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
							ghs.scalespeed = $*42
							P_SetObjectMomZ(ghs, ghs.scalespeed*7, true)
							ghs.destscale = $*99
							ghs.blendmode = AST_SUBTRACT
							ghs.frame = A|TR_TRANS30
							ghs.momx = s.momx
							ghs.momy = s.momy
							s.HMS_FireCoords3 = nil
						elseif GRAPHIX == 0
							SMS_ElectricBody(s, 24, SKINCOLOR_RED)
							HMS_BoltStorm(s, SKINCOLOR_FLAME, 10, nil, -100)
							for i = 0,1
								local ghs = SMS_LightningStrike(s, SKINCOLOR_RED, R)
								ghs.dispoffset = 50
								ghs.frame = (i == 1) and $|FF_VERTICALFLIP or $
								ghs.destscale = $*99
								ghs.momx = s.momx
								ghs.momy = s.momy
							end							
						end
					end
					
					p.camerascale =  max($-50, FRACUNIT*10/9)
					s.bhlcamtimer = 2
					s.smspickupCD = 3
					if p.aiming --Limit vertical aiming for a sec.
						p.aiming = max(-8800*FRACUNIT, min(p.aiming, 8800*FRACUNIT))
					end
					if (s.tics > 4)
						HMS_NegativeZone(s, s, true, SKINCOLOR_BLACK, (s.tics > 16) and A|FF_TRANS80 or A|FF_TRANS60)
					else
						if s.tics == 4
						s.HMS_SkipHBnext = nil
							if GRAPHIX == 0					
								local ths,ghs = SMS_WindBlast(s)
								for i = 1,2
									ghs = (i == 2) and ths or $
									ghs.color = (i == 2) and SKINCOLOR_SKY or SKINCOLOR_SMS3R
									ghs.scale = $*5/(1+i)
									ghs.destscale = $*99
									ghs.momx = $+s.momx
									ghs.momy = $+s.momy
									ghs.dispoffset = 20
									ghs.scalespeed = FRACUNIT/4
									ghs.spriteyoffset = $-28*FRACUNIT
									ghs.blendmode = AST_ADD
								end	
							end
							HMS_InitialFlameGFX(s, p, nil, true)
						end
						HMS_NegativeZone(s, s, true, SKINCOLOR_SMSROVERGLOW, A|FF_TRANS30)
					end
					
			return 1 --
					
		elseif (s.state == S_HMSNOVAFIRE2)
					
					if (p.cmd.buttons & BT_SPIN) --Aiming assist buttons for gamepad/keyboard.
						p.aiming = -4500*FRACUNIT*P_MobjFlip(s)
						s.novazaim = true
					elseif (p.cmd.buttons & BT_JUMP)
						p.aiming = 3600*FRACUNIT*P_MobjFlip(s)
						s.novazaim = true
					elseif s.novazaim
						s.novazaim = false
						p.aiming = 0
					end
					
					if (s.tics > 53)
						local ghs = HMS_NovaBlastShine(s, 80-(s.tics/2))
						if ghs and ghs.valid
							P_Thrust(ghs, s.angle+(s.tics*(ANG1*78)), 18*s.scale)
						end
						if (s.tics == 60)
							s.spritexscale = FRACUNIT-19100
							s.spriteyscale = FRACUNIT+27100
							s.spriteyoffset = -7*FRACUNIT
							s.SMS_squashtable = {timer = 4, Xspeed = 9000, Yspeed = 11500, air = true}
						
							S_StartSound(s, sfx_hmsnof)
							P_FlashPal(p, 4, 7) //Only 1 flash to not cause seizures.
							s.momx = FixedDiv(FixedMul($, 100), 143)
							s.momy = FixedDiv(FixedMul($, 100), 143)							
						end
					else
						if (s.tics == 1)
							if s.novazaim
								s.novazaim = false
								p.aiming = 0
							end
						else
							s.spritexscale = FRACUNIT-2
							s.spriteyscale = FRACUNIT+2
							s.spritexoffset = SMSLocalRNG(-3*FRACUNIT-35000,3*FRACUNIT+35001,s) --Shaking HMS' sprite is more effective than the camera at this point.
							s.spriteyoffset = SMSLocalRNG(3*FRACUNIT+35000,-3*FRACUNIT-35000,s)
							s.SMS_squashtable = {timer = 2, Xspeed = 1, Yspeed = 1, air = true}						
							if s.tics % 5 == 0
								local ghs = SMS_ElectricBody(s, 5, SKINCOLOR_CRIMSON)
								ghs.blendmode = AST_TRANSLUCENT
								ghs.spriteyscale = $+29000
								ghs.spriteyoffset = 4*FRACUNIT
								ghs.spritexscale = $+12000
								ghs.rollangle = SMSLocalRNG(-20,20,s)*ANG1
								if s.tics % 10 == 0
									ghs.mirrored = true
									ghs.color = SKINCOLOR_SMS4R
								end
							end						
						end
					end
					
					p.pflags = $|PF_ATTACKDOWN
					p.camerascale = FRACUNIT*5/2
					s.bhlcamtimer = 2
					s.smspickupCD = 3
					
					if (s.z >= s.ceilingz-150*s.scale) and (s.floorz < s.ceilingz-150*s.scale)
						s.momz = -10*s.scale
					else
						s.momz = 0
					end
					if not p.sms_flamedelay
						local ghs = P_SpawnPlayerMissile(s, MT_HMSNOVABLAST, MF2_RAILRING) --Firing the NovaBlast!
						if ghs and ghs.valid //Did it spawn correctly?
							ghs.scale = s.scale*3
							ghs.destscale = 285000 //Roughly 4.3
							ghs.color = SKINCOLOR_SMS5R
							if s.HMS_SkipHBnext
								ghs.frame = D|FF_TRANS50 --Use frame D!
								ghs.blendmode = AST_TRANSLUCENT
								ghs.NOhitbox = true
								s.HMS_SkipHBnext = nil
							else
								s.HMS_SkipHBnext = true
							end
						end
						A_SMSquake(s, 8*FRACUNIT, 3, 8901)
						if GRAPHIX == 2
							p.sms_flamedelay = 5 //Slow it down so SRB2's engine can keep up
						else
							p.sms_flamedelay = 3						
						end
					end
			return 1 --
					
		elseif (s.state == S_HMSBLACKHOLE) --HMS creating a black hole.
					s.SMS_ControlAlter = {
					timer = 2,
					forwardmove = 0,
					sidemove = 0,
					removebuttons = 0}
					
					if (p.hmsblackhole > 64)
						p.aiming = 1600*FRACUNIT
				  		if GRAPHIX != 2
							if p.hmsblackhole == 124
								A_SMSSTOMPSMOKE(s, 30, MT_HMSLIGHTNING2, 0, 20*FRACUNIT, FRACUNIT/2, SKINCOLOR_JET)
							elseif p.hmsblackhole == 117
								S_StartSound(s, sfx_s3k45)
								A_SMSSTOMPSMOKE(s, 28, MT_HMSLIGHTNING2, 0, -20*FRACUNIT, FRACUNIT/2, SKINCOLOR_JET)
							elseif p.hmsblackhole == 76
								A_SMSSTOMPSMOKE(s, SMSLocalRNG(12, 27,s), MT_HMSLIGHTNING2, -5, SMSLocalRNG(20, -20,s)*FRACUNIT, FRACUNIT/SMSLocalRNG(4,1,s), SKINCOLOR_JET)
							end
						end	
						if p.hmsblackhole == 174
							p.sweepangle = s.angle
							P_FlashPal(p, 4, 10) //Quick red flash.
							A_SMSquake(s, 44*FRACUNIT, 140, 6901)
						elseif (p.hmsblackhole < 174)
							s.angle = p.sweepangle
							p.drawangle = s.angle
							if p.hmsblackhole == 65
								S_StartSound(s, sfx_kc4d)
								A_SMSSTOMPSMOKE(s, 50, MT_HMSLIGHTNING2, 0, 0, nil, SKINCOLOR_JET)
							end
						end
					else
						p.aiming = 0
				  	end
					
					s.smspickupCD = 3
					s.hmgodticket = true
					s.momz = 0
					s.momx = 0
					s.momy = 0
					
					if (p.lddiscount == 1 or p.lddiscount == 3) --Black Hole smoke.
					
					/*	local TARGET = P_LookForEnemies(p, 4000, true, false)
						if TARGET and TARGET.valid and not TARGET.bkhltracker and TARGET.bkhltracker.valid
						TARGET.bkhltracker = P_SpawnMobjFromMobj(m, 0, 0, 0, MT_CMPHTRACKER)
						TARGET.bkhltracker.bkhl = true
						TARGET.bkhltracker.target = s
						TARGET.bkhltracker.tracer = s
						end */
						
						local ghs = P_SpawnMobjFromMobj(s,
						SMSLocalRNG(-1700, 1700+p.lddiscount, s)*s.scale,
						SMSLocalRNG(-1700-p.lddiscount, 1700, s)*s.scale, 
						SMSLocalRNG(-750, 750+p.lddiscount, s)*s.scale,
						MT_HMSPBC)
						if ghs and ghs.valid
							ghs.bkhl = true
							ghs.target = s
						end
					end
			return 2 --
		end
		
		local STARTMOVE = 0
		
		--Start the Hyper Nova Blast or Black Hole?	
		if (p.cmd.buttons & BT_ATTACK) and (p.cmd.buttons & BT_FIRENORMAL)
			STARTMOVE = 2
		elseif (p.cmd.buttons & BT_ATTACK) and not (p.pflags & PF_ATTACKDOWN)
			STARTMOVE = 1	
		else
			if (p.cmd.buttons & BT_FIRENORMAL) --Ehh, this one's really not air-limited, but here goes anyway!
			and not SMS_Locked(s, p)
			and not p.objectplacer --Not with SMScheats objectplacer on!
			
				if (leveltime % 8 == 0)
				and not (p.sms_nflamehold == 1 and not p.sms_flamedelay)
					HMS_InitialFlameGFX(s, p)
				end	
				
				if not p.sms_flamedelay
				
				s.hmgodticket = true --Enables visual aura effect.
				
					local ghs --Set this now to prevent headaches later.
						
					--HMS 7 flames" projectile spam! HMS flames. HMS normalflames. 7flames"
					if p.sms_nflamehold == 1
						s.HMS_7flame = true
						HMS_InitialFlameGFX(s, p)
					end
					
					if (s.z > s.ceilingz-100*s.scale)
					and (s.floorz < s.ceilingz-300*s.scale) --Not in extremely tight spaces.
						s.z = $-19*s.scale
					end
					local ANGLE = s.angle
					if (s.hmsspinpass and s.hmsspinang != nil) --Fire in wild circles!
						ANGLE = s.hmsspinang
						local ghs = P_SpawnPlayerMissile(s, MT_HMSFIREBLAST, MF2_RAILRING)
						if ghs ghs.mainflame = 1 ghs.GRAPHIX = GRAPHIX ghs.HMS_7flame = s.HMS_7flame end --
					else
						local ghs = P_SPMAngle(s, MT_HMSFIREBLAST, ANGLE, 1, MF2_RAILRING)
						if ghs ghs.mainflame = 1 ghs.GRAPHIX = GRAPHIX ghs.HMS_7flame = s.HMS_7flame end --
					end
					local ghs
					--Now fire 6 more!
					for i = -1,1,2
						ghs = P_SPMAngle(s, MT_HMSFIREBLAST, ANGLE+(ANG10*i), 1, MF2_RAILRING)
						if ghs ghs.GRAPHIX = GRAPHIX ghs.midflame = i ghs.HMS_7flame = s.HMS_7flame end --
					end
					for i = -1,1,2
						ghs = P_SPMAngle(s, MT_HMSFIREBLAST, ANGLE+(ANG2*2*i), 1, MF2_RAILRING)
						if ghs ghs.GRAPHIX = GRAPHIX ghs.HMS_7flame = s.HMS_7flame end --
					end
					for i = -1,1,2
						ghs = P_SPMAngle(s, MT_HMSFIREBLAST, ANGLE+(ANG15*i), 1, MF2_RAILRING)
						if ghs 
							ghs.GRAPHIX = GRAPHIX 
							ghs.outterflame = i 
							ghs.HMS_7flame = s.HMS_7flame
						end
					end			
					S_StartSound(s, sfx_s3kbcs)
					p.sms_flamedelay = 3 //This small detail makes all the difference.
					if s.HMS_7flame
						s.HMS_7flame = false
					else
						s.HMS_7flame = true
					end
					return 3 --
				end
			end
			return --
		end
		if STARTMOVE		
			if P_IsObjectOnGround(s)
			or SMS_Locked(s, p)
				return --
			end
			if STARTMOVE == 1
				if not p.sms_flamedelay
				and not (p.sms_flamebuttonhold > 1)
				and not p.novafire --Not at ALL on this one!
				and not (p.smspickup and p.smspickup.valid)				
					HMS_FireNovaBlast(s, p)
					return STARTMOVE --
				end
			elseif (p.pflags & PF_JUMPED)
				
				//D-did he just....yep, HMS just summoned a goddamn black hole!
				//This move has some serious cooldown.
				
				s.state = S_HMSBLACKHOLE
				p.hmsblackhole = 175
				s.bhlcamtimer = 150
				local ghs = P_SpawnPlayerMissile(s, MT_HMSBLACKHOLE)
				if ghs and ghs.valid
					searchBlockmap("objects",function(t,m)
						if m.valid and (m.flags & (MF_ENEMY|MF_BOSS)) and not m.bkhltracked
							if (FixedHypot(FixedHypot(s.x-m.x, s.y-m.y), s.z-m.z) < 4300*s.scale)
								local ths = P_SpawnMobjFromMobj(m, 0,0,0, MT_CMPHTRACKER) --Assign black hole tracker.
								ths.bkhl = true
								ths.target = ghs
								ths.tracer = s
							end
						end
					end,s, s.x-4400*s.scale,s.x+4400*s.scale, s.y-4400*s.scale,s.y+4400*s.scale)
				end
				return STARTMOVE --
			end
		end
end)