////////////////////////////////////////////////////////
------------You Vs Sonic! Ultimate Edition!------------
----Do you think you got what it takes to beat him?----
///////////////////////////////////////////////////////
--Created by SpeedyM!
--Credits: Sound Effects gotten from Ring Racers in Various Games, Adventure Sonic, Modern Sonic, X Sonic, and Speedy Sonic
--Sprites & GFX by DBZ
--Some of the Sprites & GFX are actually by me =D
--Battle Music from Street Fighter X

freeslot("MT_ULTIMATEBOSS_SONIC", --Mobjs
"sfx_vsson1", "sfx_vsson2", "sfx_vsson3", "sfx_vsson4", "sfx_vsson5", "sfx_vsson6", "sfx_vsson7", "sfx_vsson8", "sfx_vsson9", --Sound Effects
"sfx_vsson0", "sfx_vssona", "sfx_vssonb", "sfx_vssonc", "sfx_vssond", "sfx_vssone", "sfx_vssonf", "sfx_vssong", "sfx_vssonh",
"sfx_vssoni", "sfx_vssonj", "sfx_vssonk", "sfx_vssonl", "sfx_vssonm", "sfx_vssonn", "sfx_vssono", "sfx_vssonp", "sfx_vssonq",
"sfx_vssonr", "sfx_vssons", "sfx_vssont", "sfx_vssonu", "sfx_vssonv", "sfx_vssonw", "sfx_vssonx", "sfx_vssony", "sfx_vssonz",
"sfx_vssop1", "sfx_vssop2", "sfx_vssop3", "sfx_vssop4", "sfx_vssop5", "sfx_vssop6", "sfx_vssop7", "sfx_vssop8",
"SPR_USFD", "SPR_USSM", "SPR_USDP", "SPR_USSA", --Sprites
"SPR2_USTA") --Our Sprite2 to use our own custom Sprites
if not SPR2_SHIT
	freeslot("SPR2_SHIT")
end

sfxinfo[sfx_vsson1].caption = "\x84"+"Sonic Challenges You"+"\x80"
sfxinfo[sfx_vsson2].caption = sfxinfo[sfx_jump].caption
sfxinfo[sfx_vsson3].caption = "\x84"+"Hey guy, take care!"+"\x80"
sfxinfo[sfx_vsson4].caption = "\x84"+"Better luck next time!"+"\x80"
sfxinfo[sfx_vsson5].caption = "\x84"+"Heh. Is that all you got?"+"\x80"
sfxinfo[sfx_vsson6].caption = "\x84"+"What the?!"+"\x80"
sfxinfo[sfx_vsson7].caption = "\x84"+"Huauo!"+"\x80"
sfxinfo[sfx_vsson8].caption = "\x84"+"Owch!"+"\x80"
sfxinfo[sfx_vsson9].caption = "\x84"+"Ccuh!"+"\x80"
sfxinfo[sfx_vsson0].caption = "\x84"+"Noo!"+"\x80"
sfxinfo[sfx_vssona].caption = "\x84"+"How's This!"+"\x80"
sfxinfo[sfx_vssonb].caption = "\x84"+"Let's Rock!"+"\x80"
sfxinfo[sfx_vssonc].caption = "\x82"+"Sonic Boom"+"\x80"
sfxinfo[sfx_vssond].caption = "\x82"+"Spin Flash"+"\x80"
sfxinfo[sfx_vssone].caption = "\x84"+"Tidyaaaaa!"+"\x80"
sfxinfo[sfx_vssonf].caption = "\x82"+"Flash Dash"+"\x80"
sfxinfo[sfx_vssong].caption = "Heavy Slam"
sfxinfo[sfx_vssonh].caption = "Strong Hit"
sfxinfo[sfx_vssoni].caption = "\x84"+"Yes!"+"\x80"
sfxinfo[sfx_vssonj].caption = "\x84"+"Alright!"+"\x80"
sfxinfo[sfx_vssonk].caption = "\x84"+"Come on!"+"\x80"
sfxinfo[sfx_vssonl].caption = "Explosion"
sfxinfo[sfx_vssonm].caption = "\x82"+"Sonic Storm Wave"+"\x80"
sfxinfo[sfx_vssonn].caption = "\x82"+"Sonic Storm Wave"+"\x80"
sfxinfo[sfx_vssono].caption = "\x82"+"Second In-Air Hit"+"\x80"
sfxinfo[sfx_vssonp].caption = "\x82"+"Third In-Air Hit"+"\x80"
sfxinfo[sfx_vssonq].caption = "\x84"+"WuUAAOoh"+"\x80"
sfxinfo[sfx_vssonr].caption = "\x84"+"WOAAAUH-"+"\x80"
sfxinfo[sfx_vssons].caption = "\x84"+"UWOAAOUH-"+"\x80"
sfxinfo[sfx_vssont].caption = "\x84"+"HUOAAAAAAH..."+"\x80"
sfxinfo[sfx_vssonu].caption = "Spindash"
sfxinfo[sfx_vssonv].caption = "\x84"+"Oomph..."+"\x80"
sfxinfo[sfx_vssonw].caption = "\x84"+"...That hurt~"+"\x80"
sfxinfo[sfx_vssonx].caption = "\x84"+"Sonic Is Now Serious"+"\x80"
sfxinfo[sfx_vssony].caption = "Shadow Step"
sfxinfo[sfx_vssonz].caption = "\x82"+"Super Aura Burst"+"\x80"
sfxinfo[sfx_vssop1].caption = "/"
sfxinfo[sfx_vssop2].caption = "\x82"+"Aura Burst"+"\x80"
sfxinfo[sfx_vssop3].caption = "\x82"+"Super Aura"+"\x80"
sfxinfo[sfx_vssop4].caption = "/"
sfxinfo[sfx_vssop5].caption = "\x84"+"Sonic's Party Getting Started"+"\x80"
sfxinfo[sfx_vssop6].caption = "\x82"+"Blast Away"+"\x80"
sfxinfo[sfx_vssop7].caption = "\x82"+"Special Move"+"\x80"
sfxinfo[sfx_vssop8].caption = "\x82"+"Transformation"+"\x80"

sfxinfo[sfx_vsson2].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vsson3].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vsson4].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vsson5].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vsson0].flags = SF_X4AWAYSOUND
sfxinfo[sfx_vssona].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vssonb].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vssonc].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssond].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vssone].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vssonf].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssong].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssonh].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssoni].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssonj].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssonk].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssonl].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssonm].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssonn].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssonq].flags = SF_X4AWAYSOUND
sfxinfo[sfx_vssonr].flags = SF_X4AWAYSOUND
sfxinfo[sfx_vssons].flags = SF_X4AWAYSOUND
sfxinfo[sfx_vssont].flags = SF_X8AWAYSOUND
sfxinfo[sfx_vssonu].flags = SF_X4AWAYSOUND
sfxinfo[sfx_vssonv].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vssop1].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vssop2].flags = SF_X4AWAYSOUND
sfxinfo[sfx_vssop3].flags = SF_X4AWAYSOUND
sfxinfo[sfx_vssop4].flags = SF_X2AWAYSOUND
sfxinfo[sfx_vssop6].flags = SF_X4AWAYSOUND
sfxinfo[sfx_vssop8].flags = SF_X8AWAYSOUND

local CUTSCENE1 = false --I'm sorry but just HAD TO!
rawset(_G, "USonic_CutScene", 0) --For projecting HUD for the player
addHook("MapChange", do
	USonic_CutScene = 0
end)

addHook("MapLoad", do
	if mapheaderinfo[gamemap].lvlttl != "Vs Sonic"
		CUTSCENE1 = false
	else
		local MUSIC = "UVSSON"
		if not USonic_CutScene
		and mapmusname != MUSIC
			S_ChangeMusic(tostring(MUSIC), true)
		end
		mapmusname = MUSIC
	end
end)

addHook("MobjSpawn", function(s)
	s.sprite = SPR_PLAY
	s.skin = "sonic"
	s.state = S_PLAY_STND
	s.color = SKINCOLOR_BLUE
	s.US_Energy = 0
	s.US_RingLoss = 0
	s.US_Stunned = 0
	if (leveltime)==0
	and mapheaderinfo[gamemap].lvlttl == "Vs Sonic"
	and CUTSCENE1 != true
		local SETUP = {Tick = 1, BlackTrans = 0, BlackBarScale = FU/7, Skipping = 0, Camera = P_SpawnMobj(-3429*FU, -6686*FU, 24*FU, MT_THOK)}
		local DONTPLAY = false
	---	S_StopMusic()
		if not (SETUP.Camera and SETUP.Camera.valid)
			DONTPLAY = true
		else
			SETUP.Camera.angle = FixedAngle(56*FU)
		end
		if DONTPLAY==false
			s.US_CutScene1 = SETUP
			USonic_CutScene = s.US_CutScene1
		else mapmusname = "UVSSON" S_ChangeMusic(mapmusname, true) end
		CUTSCENE1 = true
	end
--	S_StartSound(nil, sfx_vsson1)
end, MT_ULTIMATEBOSS_SONIC)

local function Sonic_SkilledChars(m)
	if not (m and m.valid) return false end
	--Hard Mode for various characters!
	if m.skin == "mastersonic" --Master Sonic -Goated
	or m.skin == "speedy" --Speedy Sonic --Also Goated
	or m.skin == "sms" --Super Mystic Sonic
	or m.skin == "xsonicserious" --X Dark Sonic
	or m.skin == "xsonic" --X Sonic... Actually had trouble even in Normal Mode-
		return true
	end
	return false
end

local function Sonic_StartSuperSonicCutscene(s) --"Now it's time to get SERIOUS."
	local SETUP = {Tick = 1, 
	BlackBarScale = 0,
	DestBlackBarScale = FU/8,
	SkipFade = 10*FU,
	Skipping = 0,
	Part = 1,
	Camera = P_SpawnMobj(2797*FU, -440*FU, 12*FU, MT_THOK)
	}
	local DONTPLAY = false
	
	if not (SETUP.Camera and SETUP.Camera.valid)
	or mapheaderinfo[gamemap].lvlttl != "Vs Sonic"
		DONTPLAY = true
	else
		SETUP.Camera.angle = FixedAngle(80*FU)
		SETUP.Camera.aiming = -ANG15
	end
	
	DONTPLAY = false
	if DONTPLAY == false --People, get in y'alls places!!
		s.US_SpinFlash = nil --Firstly, couble check on disabling everything to avoid interference.
		s.US_SonicStorm = nil
		s.US_SpecialReady = nil
		s.US_InPain = nil
		s.US_ImCooked = nil
		s.US_Jumped = nil
		s.US_HomingAttack = nil
		s.US_SpecialAttack1 = nil
		s.US_SpecialAttack2 = nil
		s.US_Finished = nil
		
		P_SetOrigin(s, 2813*FU, -385*FU, 0)
		s.angle = ANGLE_225
		s.state = S_PLAY_PAIN
		s.sprite2 = SPR2_SHIT
		s.frame = ($ & ~FF_FRAMEMASK)
		for p in players.iterate do
			p.pflags = $|PF_FULLSTASIS
			if not (p.mo and p.mo.valid) continue end
			p.mo.momx = 0
			p.mo.momy = 0
			p.mo.momz = 0
			p.mo.state = S_PLAY_STND
			P_SetOrigin(p.mo, 592*FU, -2563*FU, 0)
			p.drawangle = ANGLE_45
			p.mo.angle = ANGLE_45
		end
		
		S_FadeMusic(0, MUSICRATE)
		
		s.US_CutScene2 = SETUP --Aand ACTION!
		USonic_CutScene = s.US_CutScene2
	else
		G_ExitLevel() --Darn itt! Fine...
	end
end

--Fills up from more action up to Lvl 3!
local function Sonic_EnergyLevel(s, Energy)
	local MAXLVL = FU
	local OUTPUT = 0
	
	for i = 1,3 do
		if Energy >= min((FU/3)*i, MAXLVL)
			OUTPUT = min($+1, 3)
		end
	end
	
	return OUTPUT --
end

local function Sonic_Squash(m)
	if not (m and m.valid and m.SU_Squash)
		m.spritexscale = FU
		m.spriteyscale = FU
		m.SU_Squash = nil
		return --
	end
	
	local Squash = m.SU_Squash
	local p = m.player or nil
	
	--All Cancels you could choose from!
	local CANCELS = Squash.Cancels and type(Squash.Cancels)=="string" and string.lower(Squash.Cancels) or "_"
	local DOCANCEL = string.find(CANCELS, "ground") and (P_IsObjectOnGround(m) or (m.eflags & MFE_JUSTHITFLOOR)) and true
	or string.find(CANCELS, "midair") and not P_IsObjectOnGround(m) and true
	or string.find(CANCELS, "underwater") and (m.eflags & MFE_UNDERWATER) and true
	or string.find(CANCELS, "pain") and p and P_PlayerInPain(p)
	or string.find(CANCELS, "death") and not m.health and true
	or string.find(CANCELS, "carry") and p and p.powers[pw_carry] and true
	or string.find(CANCELS, "sprung") and ((m.eflags & MFE_SPRUNG) or p and p.powers[pw_justsprung]) and true
	
	if Squash.Squish
		Squash.Squish = max($-1, 0)
		m.spritexscale = max($-3000, FU)
		m.spriteyscale = min($+3500, FU)
	elseif Squash.Squish2
		Squash.Squish2 = max($-1, 0)
		m.spritexscale = min($+1100, FU*2)
		m.spriteyscale = max($-1400, FU/2)
	elseif Squash.HopSquash
		Squash.HopSquash = max($-1, 0)
		m.spritexscale = min($+3000, FU)
		m.spriteyscale = max($-4850, FU)
	elseif Squash.Stretch
		Squash.Stretch = max($-1, 0)
		m.spritexscale = max($-3000, FU/2)
		m.spriteyscale = min($+4550, FU*5/4)
	end
	
	if not Squash.Squish
	and not Squash.Squish2
	and not Squash.HopSquash
	and not Squash.Stretch
	or DOCANCEL
		m.spritexscale = FU
		m.spriteyscale = FU
		m.SU_Squash = nil
	end
end

local function Sonic_SkidState(s)
	if not (s and s.valid) return end
	
	local SUPER = (s.sprite2 & FF_SPR2SUPER) and FF_SPR2SUPER or 0
	s.state = S_PLAY_WALK --not S_PLAY_SKID because I guess non-players are still stuck in 2.2.13's walking frame lmao
	s.sprite2 = SPR2_SKID|SUPER
	s.frame = ($ & ~FF_FRAMEMASK)
end

local function Sonic_DoSpindashFlash(s, m)
--	S_StartSound(s, sfx_cdfm62)
	S_StartSound(s, sfx_vssond)
	s.US_SpinFlash = {Angle = R_PointToAngle2(s.x, s.y, m.x+m.momx, m.y+m.momy), Thrust = 220*m.scale, Timer = 8, SkidTime = 13}
	s.US_Energy = min($+FU/25, FU)
end

local function Sonic_DoSonicStorm(s, m)
	if not P_IsObjectOnGround(s) return end
	s.momx = $/2
	s.momy = $/2
	for i = 1,3 do
		S_StartSound(s, sfx_vssonu)
	end
	s.state = S_PLAY_SPINDASH
	s.US_SonicStorm = {Angle = R_PointToAngle2(s.x, s.y, m.x+m.momx, m.y+m.momy), FireSpeed = 190*m.scale, Charging = 1, Target = m}
	
	s.US_Energy = max($-FU/15, 0)
end

local function Sonic_SpecialSkinFinishVOC(m) --A little finisher support for funzies
	local p = m.player
	
	if not (m and m.valid and m.health and p) return end 
	if YuSonic and m.skin == "adventuresonic" and p.yusonictable and sfx_yuvocb
		YuVoice(p, m, p.yusonictable, sfx_yuvocb, true) --SA Sonic: "Hey I'll play with you some other time!"
	elseif XSon and m.skin == "xsonic" and p.xsonictable and sfx_xsvocq
		XSVoice(p, m, p.xsonictable, sfx_xsvocq, true) --X Sonic: "Eat This!!"
	elseif m.skin == "speedy" and sfx_specs2
		S_StartSound(m, sfx_specs2) --Speedy Sonic: "Here I Goo!"
	elseif Adv and m.skin == "advancedsonic" and p.advancesonic and sfx_advocb
		Adv.Voice(m, sfx_advocb) --Advance Sonic: "Aha!"
	elseif Mint and m.skin == "mint" and p.minttable and sfx_mnvoc7
		Mint.Vocals(p,m,p.minttable, sfx_mnvoc7) --Mint: "Here goes nothin'!"
	elseif Masters and m.skin == "mastersonic" and p.masterstable
		--For when we have enough voicelines for him.
	end
end

local function Sonic_DoSpecialAttack2(s, m)
	--Special Move 2: Boost Combo
	
	s.US_SpecialReady = 20
	for p in players.iterate do
		if not (p.mo and p.mo.valid) continue end
	--	p.US_LockButtons = ($ or 0)+1
	--	p.US_LockMoving = ($ or 0)+1
		p.US_UseSameButtons = 1
		p.pflags = $|PF_USEDOWN|PF_JUMPDOWN
		p.mo.flags = $|MF_NOTHINK
		P_InstaThrust(m, R_PointToAngle2(p.mo.x, p.mo.y, p.mo.x+m.momx, p.mo.y+p.mo.momy), p.speed)
	end
	for mo in mobjs.iterate() do
		if not (mo and mo.valid) continue end
		S_StopSound(mo)
	end
	local gfx = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
	gfx.color = SKINCOLOR_SKY
	gfx.blendmode = AST_ADD
	gfx.renderflags = RF_FULLBRIGHT
	gfx.scale = s.scale
	gfx.destscale = 99*FU
	gfx.scalespeed = s.scale/2
	gfx.fuse,gfx.tics = 15,15
	s.US_SpecialAttack2 = {Angle = (m and m.valid and m.health) and R_PointToAngle2(s.x, s.y, m.x+m.momx*5/2, m.y+m.momy*5/2) or s.angle,
	Boost = 180*m.scale, BoostSFX = sfx_vssonc, Ready = true}
	s.angle = s.US_SpecialAttack2.Angle
	
	s.momx = 0
	s.momy = 0
	s.momz = 0
--	S_StartSound(nil, sfx_s3kb3)
--	S_StartSound(nil, sfx_s227)
	S_StartSound(nil, sfx_vssop7)
	S_StartSound(s, sfx_vssona)
--	s.US_SpinFlash = {Angle = R_PointToAngle2(s.x, s.y, m.x+m.momx, m.y+m.momy), Thrust = 220*m.scale, Timer = 8, SkidTime = 13}
	s.US_Energy = max($-FU/3, 0)
end

local function Sonic_Quake(s, INTENSITY, TICS, RADIUS, FLASH)
	if not (s and s.valid and INTENSITY and TICS) return end
	local p = consoleplayer
	
	if s.player and (s.player==p)
		P_StartQuake(INTENSITY, TICS)
		if FLASH
			P_FlashPal(p, PAL_WHITE, FLASH)
		end
	else local TRUEDIST = FixedHypot(FixedHypot(s.x-p.mo.x, s.y-p.mo.y), s.z-p.mo.z)
		if TRUEDIST <= RADIUS
			P_StartQuake(INTENSITY, TICS)
			if FLASH
				P_FlashPal(p, PAL_WHITE, FLASH)
			end
		end
	end
end

rawset(_G, "Sonic_GibSound", function(s, SFX, FUSE, VOL, SELFPLAYER)
	if not (s and s.valid) return end
	SFX = (SFX) or sfx_thok
	local sfx = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
	sfx.flags = $|MF2_DONTDRAW
	sfx.fuse,sfx.tics = FUSE,FUSE
	if VOL != nil
		S_StartSoundAtVolume(sfx, SFX, VOL, SELFPLAYER)
	else
		S_StartSound(sfx, SFX, SELFPLAYER)
	end
end)


addHook("BossThinker", function(s)
	if not (s and s.valid) return end
	
	if s.SU_Squash
		Sonic_Squash(s)
	end
	
	if s.US_SpecialReady
--	and s.health
	and not s.US_DeathTimer
--	and not s.US_InPain
		local brightmobj = P_SpawnGhostMobj(s)
		brightmobj.renderflags = RF_FULLBRIGHT
		brightmobj.tics = 2
		brightmobj.fuse = 50
		brightmobj.frame = ($ & ~FF_TRANSMASK)
		for p in players.iterate do
			if not (p.mo and p.mo.valid) continue end
		--	p.US_LockButtons = ($ or 0)+1
		--	p.US_LockMoving = ($ or 0)+1
			
			p.US_UseSameButtons = true
			p.mo.flags = $|MF_NOTHINK
			local brightplayer = P_SpawnGhostMobj(p.mo)
			brightplayer.renderflags = RF_FULLBRIGHT
			brightplayer.tics = 2
			brightplayer.fuse = 50
			brightplayer.frame = ($ & ~FF_TRANSMASK)
		end
		for sector in sectors.iterate do --It's like those muegen games again!
			local light = min(s.US_SpecialReady, 10)*10
			P_SpawnLightningFlash(sector)
			sector.lightlevel = max($-light, 0)
		end
		s.US_SpecialReady = max($-1, 0)
	elseif s.US_SpecialReady != nil
		for p in players.iterate do
			if not (p.mo and p.mo.valid) continue end
			p.mo.flags = $ & ~(MF_NOTHINK)
		end
		s.US_SpecialReady = nil
	end
	
	if s.US_CutScene2 --Cutscene 2: "Playtime's Over!"
		local Scene = s.US_CutScene2
		local p = consoleplayer
		
		Scene.Tick = min($+1, FU) --How long the CutScene has been at it
	--	print(Scene.Tick)
		
		if Scene.Part == 1
			if Scene.Tick == 55 --Scene Triggers
				S_StartSound(s, sfx_vssonw) --"*groan*"
			end
			if Scene.Tick >= 80 and Scene.Tick <= 89
				s.spritexoffset = (Scene.Tick % 2) and -FU or FU
				if Scene.Tick == 89
					s.spritexoffset = 0
				end
			end
			if Scene.Tick == 100 --"That hurt..."
				s.state = S_PLAY_PAIN
				s.sprite2 = SPR2_USTA
				s.frame = ($ & ~FF_FRAMEMASK)|B
			end
			if Scene.Tick >= 138 and Scene.Tick < 150
				if Scene.Tick == 138
					s.state = S_PLAY_PAIN
					s.sprite2 = SPR2_SHIT
					s.frame = ($ & ~FF_FRAMEMASK)
					s.spritexscale = FU
					s.spriteyscale = FU
					s.SU_Squash = {Squish2 = 12}
				end
				s.spritexoffset = (Scene.Tick % 2) and -FU*2 or FU*2
			end
			if Scene.Tick == 150
				s.spritexoffset = 0
				S_StartSound(s, sfx_vsson2)
				P_SetObjectMomZ(s, 9*FU, false)
				if P_IsObjectOnGround(s)
					s.z = $+s.scale*3*P_MobjFlip(s)
				end
				s.state = S_PLAY_ROLL
				s.US_SceneJump = 10
			end
			if s.US_SceneJump
				if P_IsObjectOnGround(s) and s.US_SceneJump >= 10
					Sonic_SkidState(s)
					s.spritexscale = FU
					s.spriteyscale = FU
					s.SU_Squash = {Squish2 = 10}
					S_StartSound(s, sfx_s3k4c)
					US_SpawnLandDust(s)
					s.US_SceneJump = 9
				elseif s.US_SceneJump < 10
					Sonic_SkidState(s)
					s.US_SceneJump = max($-1, 0)
					if not s.US_SceneJump
						s.state = S_PLAY_STND
					end
				end
			end
			if Scene.Tick == 242 --Suspense
				Scene.Part = 2
				S_ChangeMusic("UVSUSP", false)
				S_StartMusicCaption("Suspense", 566)
				s.state = S_PLAY_STND
				s.sprite2 = SPR2_USTA
				s.frame = ($ & ~FF_FRAMEMASK)|C
			end
		elseif Scene.Part == 2
			if s.state == S_PLAY_STND
				s.state = S_PLAY_STND
				s.sprite2 = SPR2_USTA
				s.frame = ($ & ~FF_FRAMEMASK)|C
			end
			
			for p in players.iterate do
				if not (p.mo and p.mo.valid) continue end
				if Scene.Tick == 723
				and p.mo.state != S_PLAY_WAIT
					p.mo.state = S_PLAY_WAIT
				end
			end
			
			if Scene.Tick == 808
				Scene.Part = 3
				s.state = S_PLAY_STND
				s.sprite2 = SPR2_USTA
				s.frame = ($ & ~FF_FRAMEMASK)|D
			end
		elseif Scene.Part == 3 
			if Scene.Tick == 809 --"Now it's time to get SERIOUS."
				S_StartSound(s, sfx_vssonx)
			end
			
			for p in players.iterate do
				if not (p.mo and p.mo.valid) continue end
				if Scene.Tick == 880 --"Wha?"
				and p.mo.state != S_PLAY_STND 
					S_StartSound(p.mo, sfx_s25a)
					p.mo.state = S_PLAY_STND
					p.mo.spritexscale = FU-(FU/6)
					p.mo.spriteyscale = FU+(FU/5)
					p.mo.SU_Squash = {HopSquash = 10}
				end
			end
			
			if Scene.Tick == 898 --He's vanishing!
				US_SpawnShadowStep(s, false, FF_TRANS10, s.scale*3/2)
				S_StartSound(nil, sfx_vssony)
			end
			if Scene.Tick == 898 or Scene.Tick == 904 or Scene.Tick == 910
				s.flags2 = $|MF2_DONTDRAW
				Scene.LightLevel = nil
			elseif Scene.Tick == 901 or Scene.Tick == 907 or Scene.Tick == 913
				s.flags2 = $ & ~(MF2_DONTDRAW)
				Scene.LightLevel = 0
				Scene.FullBrightSonic = true
			end
			if s.US_SceneChaosEmeralds --Call upon the 7 Emeralds!
				local COLOR = {SKINCOLOR_SHAMROCK, SKINCOLOR_MAGENTA, SKINCOLOR_SKY, --Which color emerald should be
				SKINCOLOR_COBALT, SKINCOLOR_GOLDENROD, SKINCOLOR_PEPPER, SKINCOLOR_GREY}
				if s.US_SceneChaosEmeralds != true
					if s.US_SceneChaosEmeralds == 10*FU
						if s.momz*P_MobjFlip(s) < s.scale
							s.US_SceneChaosEmeralds = 9*FU
							s.momz = 0
						end
					else
						s.momz = 0
						for i = 0,6 do
							local X = FixedMul(s.radius*3, cos(ANG60*i))
							local Y = FixedMul(s.radius*3, sin(ANG60*i)) 
							local gfx = P_SpawnMobjFromMobj(s, X, Y, s.height/4, MT_THOK)
							gfx.frame = ($ & ~FF_TRANSMASK)|s.US_SceneChaosEmeralds
							gfx.tics = 2
							gfx.fuse = 50
							gfx.renderflags = RF_FULLBRIGHT
							gfx.blendmode = AST_ADD
							gfx.color = COLOR[i+1]
						end
						s.US_SceneChaosEmeralds = max($-FU, 0)
						if not s.US_SceneChaosEmeralds
							S_StartSound(s, sfx_s3kb3)
							US_ChaosEmeraldWarp(s, COLOR, Scene.Tick)
							s.US_SceneChaosEmeralds = true
						end
					end
				else
					s.momz = 0
					
					for d = 1,2 do
						for i = 0,6 do
							local X = FixedMul(s.radius*3, cos(ANG60*i+Scene.Tick*ANG2))
							local Y = FixedMul(s.radius*3, sin(ANG60*i+Scene.Tick*ANG2))
							local em = P_SpawnMobjFromMobj(s, X, Y, s.height/4, MT_THOK)
							em.sprite = SPR_CEMG
							em.frame = ($ & ~(FF_FRAMEMASK|FF_TRANSMASK))|i --Brain Power.
							em.renderflags = RF_FULLBRIGHT
							em.color = COLOR[i+1]
							em.tics = 2
							em.dispoffset = 1
							em.fuse = 50
							if d == 2
								em.blendmode = AST_ADD
								em.frame = ($ & ~FF_TRANSMASK)|FF_TRANS30
								em.dispoffset = 2
								em.colorized = true
							end
						end
					end
				end
			end
			if Scene.Tick == 910
				s.z = 1100*FU
				s.momz = 10*s.scale*P_MobjFlip(s)
				s.state = S_PLAY_FALL
				s.US_SceneChaosEmeralds = 10*FU
			end
			if Scene.Tick == 964
				S_StartSound(s, sfx_vssop1)
				s.SU_Squash = {Squish2 = 3}
			end
			if Scene.Tick == 967 --Reversed TRNS Animation (Cuz I found it cool)
				s.state = S_PLAY_FALL
				s.sprite2 = SPR2_TRNS
				s.frame = ($ & ~FF_FRAMEMASK)|B
				s.tics = 105
				s.anim_duration = 105
			end
			if Scene.Tick == 971
				s.sprite2 = SPR2_TRNS
				s.frame = ($ & ~FF_FRAMEMASK)
			end
			
			if Scene.Tick == 987 --Here it comes!!
				S_ChangeMusic("UVSUPR", false)
			end
			
			if Scene.Tick == 1001 --BOOOM!!!
				Scene.Part = 4
				s.US_SceneChaosEmeralds = nil
				s.color = skins[s.skin].supercolor+4
				s.state = S_PLAY_FALL
				s.sprite2 = SPR2_TRNS
				s.renderflags = $|RF_FULLDARK
				s.dispoffset = 3
				s.frame = ($ & ~FF_FRAMEMASK)|D
				s.tics = 500
				s.anim_duration = 500
				P_FlashPal(p, PAL_MIXUP, 2)
				p.US_WhiteFlash = FF_TRANS30
				Scene.LightLevel = 145
				S_StartSound(nil, sfx_vssonz)
				
				US_SpawnFlashDash(s, SKINCOLOR_WHITE, AST_TRANSLUCENT, 0)
			end
		elseif Scene.Part ==4
			if Scene.Tick >= 1001  
				s.momz = 0
				local Quake = 28*FU
				if Scene.Tick >= 1044 and Scene.Tick < 1229
					Quake = 13*FU
				elseif Scene.Tick >= 1244 and not Scene.AscendingQuake
					Quake = 0
				elseif Scene.AscendingQuake
					Quake = Scene.AscendingQuake
				end
				
				if Quake and Scene.Tick < 1267 --I swear I'm not doing this on purpose.
					P_StartQuake(Quake, 3)
				end
				
				if Scene.Tick < 1244
					if (Scene.Tick % 9)==0
						local COLOR = (Scene.Tick % 18)==0 and SKINCOLOR_WHITE or SKINCOLOR_GOLDENROD
						US_SpawnFlashDash(s, COLOR, AST_ADD, 0)
						local z = P_SpawnMobj(s.x, s.y, s.floorz, MT_THOK)
						z.flags2 = MF2_DONTDRAW
						z.tics = 2
						z.fuse = 2
						US_HeavyFloorImpact(z, SKINCOLOR_GOLDENROD)
					end
					for i = 1,20 do
						US_SuperTransFormGFX(s)
					end
					for d = -1,1,2 do
						local ANGLE = FixedAngle(P_RandomRange(0, 359)*FU)
						local DIST = P_RandomRange(FixedInt(s.radius), 300)*s.scale
						local ZOFFSET = s.floorz+P_RandomRange(10, 2000)*s.scale*P_MobjFlip(s)
						local MOMZ = P_RandomRange(13, 21)*FU
						local FUSE = 20
						
						local gfx = P_SpawnMobjFromMobj(s, FixedMul(DIST, cos(ANGLE)), FixedMul(DIST, sin(ANGLE)), 0, MT_THOK)
						gfx.z = ZOFFSET
						gfx.flags = $|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY|MF_NOBLOCKMAP
						gfx.scale = s.scale*5/2
						gfx.sprite = SPR_RAIN
						gfx.frame = ($ & ~FF_FRAMEMASK)
						gfx.angle = ANGLE
						gfx.blendmode = AST_ADD
						gfx.colorized,gfx.color = true,SKINCOLOR_GOLDENROD
						gfx.renderflags = $|RF_FULLBRIGHT
						gfx.fuse = FUSE
						gfx.tics = FUSE
						P_SetObjectMomZ(gfx, MOMZ, false)
					end
				end
			end
			if Scene.Tick == 1003 --Intense Flashing!
				P_FlashPal(p, PAL_INVERT, 2)
			end
			
			if Scene.Tick == 1040
				S_StartSound(s, sfx_vssop8)
			end
			
			if Scene.Tick >= 1044 and Scene.Tick < 1229 --The wind.. is too... MUCH!
				for p in players.iterate do
					if not (p.mo and p.mo.valid) continue end
					if not (p.powers[pw_super] or p.mo.skin == "sms" or p.mo.skin == "xsonicserious") --For anyone super, I guess can aura farm haha
					and Scene.Tick <= 1185
						if Scene.Tick == 1185
							S_StartSound(p.mo, sfx_s3k81, p)
							S_StartSound(p.mo, sfx_s3kae, p)
							S_StartSound(p.mo, sfx_s3k51, p)
							p.drawangle = R_PointToAngle2(p.mo.x, p.mo.y, s.x, s.y)
							P_InstaThrust(p.mo, p.drawangle, -108*FU)
							p.mo.z = $+p.mo.scale*3*P_MobjFlip(p.mo)
							P_SetObjectMomZ(p.mo, 20*FU, false)
							p.mo.state = S_PLAY_PAIN
							if XSon and p.mo.skin == "xsonic" and p.xsonictable and sfx_xsvoc4 --A little XSonic support loll
								XSVoice(p, p.mo, p.xsonictable, sfx_xsvoc4)
								p.mo.sprite2 = SPR2_CLNG
								p.mo.frame = ($ & ~FF_FRAMEMASK)
							end
						else
							if p.mo.state != S_PLAY_EDGE
								p.mo.state = S_PLAY_EDGE
							end
							p.drawangle = R_PointToAngle2(p.mo.x, p.mo.y, s.x, s.y)
							local PERSPECTIVE = Scene.Tick >= 1128 and FU*2 or FU
							P_InstaThrust(p.mo, p.drawangle, -PERSPECTIVE)
						end
					end
					if p.mo.skin == "sms" or XSon and p.xsonictable and IsXSonic(p.mo) and XS_Super(p)==3
						if p.mo.state != S_PLAY_EDGE
							p.mo.state = S_PLAY_EDGE
						end
					end
					local glow = P_SpawnGhostMobj(p.mo) --The light is causing a glow effect on your player!
					glow.renderflags = RF_SEMIBRIGHT
					P_TryMove(glow, p.mo.x+p.mo.momx, p.mo.y+p.mo.momy, false)
					glow.tracer = p.mo
					glow.z = p.mo.z+p.mo.momz
					glow.colorized = true
					glow.dispoffset = 1
					glow.color = SKINCOLOR_GOLDENROD
					glow.blendmode = AST_ADD
					glow.tics = 2
					glow.fuse = 50
					glow.frame = ($ & ~FF_TRANSMASK)|FF_TRANS70
					A_CapeChase(glow, 1, 0)
				end
			end
			
			if Scene.Tick == 1244
				S_StartSound(s, sfx_vssop1)
				s.SU_Squash = {Squish2 = 3}
				s.state = S_PLAY_SUPER_TRANS1
				s.frame = ($ & ~FF_FRAMEMASK)
			end
			
			if s.state == S_PLAY_SUPER_TRANS4
				s.renderflags = $ & ~(RF_FULLDARK)
				Scene.FullBrightSonic = nil
				S_StopSoundByID(s, sfx_vssop8)
			end
			
			if Scene.Tick >= 1257 and Scene.Tick < 1266
			and Scene.LightLevel
				Scene.LightLevel = min($+15, 255)
				if Scene.LightLevel == 255
					Scene.LightLevel = nil
				end
			end
			
			if Scene.Tick == 1256
				Scene.AscendingQuake = FU
			end
			
			if Scene.Tick == 1266
				P_FlashPal(p, PAL_MIXUP, 2)
				Scene.SuperAura = true
				p.US_WhiteFlash = FF_TRANS70
				s.dispoffset = 0
				s.state = S_PLAY_FALL
				s.sprite2 = SPR2_TRNS
				s.frame = ($ & ~FF_FRAMEMASK)|G
				s.tics = 500
				s.anim_duration = 500
				Scene.AscendingQuake = nil
			end
			
			if Scene.Tick == 1318
				S_StartSound(s, sfx_vssop4)
				s.state = S_PLAY_EDGE
				s.spritexscale = FU+(FU/5)
				s.spriteyscale = FU-(FU/5)
				s.SU_Squash = {Squish = 10}
			end
			
			if Scene.Tick == 1378
				Scene.Part = 5
				for p in players.iterate do
					if not (p.mo and p.mo.valid) continue end --Yeahh I knoww, they got flinged farther than that, but like, I can break laws too, right? 
					P_SetOrigin(p.mo, -412*FU, -3482*FU, 0)
					p.mo.angle = R_PointToAngle2(p.mo.x, p.mo.y, s.x, s.y)
					if not (p.powers[pw_super] or p.mo.skin == "sms" or p.mo.skin == "xsonicserious")
						p.mo.state = S_PLAY_PAIN
						if p.mo.skin == "adventuresonic"
							p.mo.sprite2 = SPR2_TAL5
						elseif SPR2_SHIT and P_IsValidSprite2(p.mo, SPR2_SHIT)
							p.mo.sprite2 = SPR2_SHIT
						end
						p.mo.frame = ($ & ~FF_FRAMEMASK)|A
					else
						p.mo.state = S_PLAY_STND
					end
				end
			end
		elseif Scene.Part == 5
			if not P_IsObjectOnGround(s)
				s.momz = 0
			end
			
			for p in players.iterate do
				if not (p.mo and p.mo.valid) continue end
				if not (p.powers[pw_super] or p.mo.skin == "sms" or p.mo.skin == "xsonicserious")
				and Scene.Tick < 1557
					p.mo.state = S_PLAY_PAIN
					if p.mo.skin == "adventuresonic"
						p.mo.sprite2 = SPR2_TAL5
					elseif SPR2_SHIT and P_IsValidSprite2(p.mo, SPR2_SHIT)
						p.mo.sprite2 = SPR2_SHIT
					end
					p.mo.frame = ($ & ~FF_FRAMEMASK)|A
				end
				
				if Scene.Tick == 1556
				and p.mo.state == S_PLAY_PAIN
					p.mo.state = S_PLAY_STND
					p.mo.spritexscale = FU-(FU/6)
					p.mo.spriteyscale = FU+(FU/5)
					p.mo.SU_Squash = {HopSquash = 10}
					S_StartSound(p.mo, sfx_ngjump)
				end
			end
			
			if Scene.Tick == 1655 --"Okay then..."
				S_StartSound(s, sfx_vssop5)
				s.state = S_PLAY_EDGE
				s.sprite2 = SPR2_USTA
				s.frame = ($ & ~FF_FRAMEMASK)|E
				s.tics = 500
				s.anim_duration = 500
			end
			if Scene.Tick >= 1657
			and ((Scene.Tick % states[S_PLAY_EDGE].tics)==0 or Scene.Tick == 1658 or Scene.Tick == 1722)
			and s.state == S_PLAY_EDGE
				s.sprite2 = SPR2_USTA
				local FRAME = (s.frame & FF_FRAMEMASK)
				if FRAME < H
					if (FRAME & FF_FRAMEMASK) == G
						s.frame = ($ & ~FF_FRAMEMASK)|F
					else
						s.frame = ($ & ~FF_FRAMEMASK)|G
					end
				else
					if (FRAME & FF_FRAMEMASK) == J
						s.frame = ($ & ~FF_FRAMEMASK)|I
					else
						s.frame = ($ & ~FF_FRAMEMASK)|J
					end
				end
			end
			
			if Scene.Tick == 1719 --"Let's get this party started."
				s.state = S_PLAY_EDGE
				s.sprite2 = SPR2_USTA
				s.frame = ($ & ~FF_FRAMEMASK)|H
				s.tics = 500
				s.anim_duration = 500
				S_FadeMusic(0, MUSICRATE*2)
			end
			
			if Scene.Tick == 1797 --He's vanishing again!
				US_SpawnShadowStep(s, false, FF_TRANS10, s.scale*3/2)
				if Scene.SuperAura
					Scene.SuperAura.NoSFX = true
					Scene.SuperAura.NoDBZ = true
				end
				S_StartSound(nil, sfx_vssony)
				s.flags2 = $|MF2_DONTDRAW
			end
			if Scene.Tick == 1799 or Scene.Tick == 1803
				s.flags2 = $ & ~(MF2_DONTDRAW)
			elseif Scene.Tick == 1801 or Scene.Tick == 1805
				s.flags2 = $|MF2_DONTDRAW
			end
			
			if Scene.Tick == 1807
				S_StartSound(nil, sfx_vssony)
				Scene.Part = 6
				P_SetOrigin(s, -367*FU, -3451*FU, 0) --BRO'S RIGHT AT MY FACE!
				US_SpawnShadowStep(s, false, FF_TRANS10, s.scale*3/2)
				s.state = S_PLAY_STND
				s.angle = FixedAngle(216*FU)
			end
		elseif Scene.Part == 6 --FINALLY Final Part!
			if Scene.Tick == 1809 or Scene.Tick == 1813 or Scene.Tick == 1816
				s.flags2 = $ & ~(MF2_DONTDRAW)
			elseif Scene.Tick == 1811 or Scene.Tick == 1815
				s.flags2 = $|MF2_DONTDRAW
			end
			
			if Scene.Tick >= 1829
				for p in players.iterate do
					if not (p.mo and p.mo.valid) continue end
					if Scene.Tick == 1829 --"Boo!" Got Jumpscared
						S_StartSound(p.mo, sfx_alart, p)
						p.mo.state = S_PLAY_PAIN
						P_SetObjectMomZ(p.mo, 6*FU, false)
						p.mo.z = $+p.mo.scale*3*P_MobjFlip(p.mo)
						P_InstaThrust(p.mo, p.mo.angle, -3*FU)
						p.mo.spritexscale = FU-(FU/6)
						p.mo.spriteyscale = FU+(FU/5)
						p.mo.SU_Squash = {HopSquash = 10}
					end
					if Scene.Tick == 1841 --POW!
						S_StartSound(nil, sfx_vssonh)
						P_FlashPal(p, PAL_MIXUP, 3)
						P_SetOrigin(p.mo, -2171*FU, -4892*FU, 799*FU)
						P_SetObjectMomZ(p.mo, 40*FU, false)
						P_StartQuake(80*FU, 7)
						P_InstaThrust(p.mo, R_PointToAngle2(s.x, s.y, p.mo.x, p.mo.y)+ANGLE_180, -108*FU)
						p.mo.z = $+p.mo.scale*3*P_MobjFlip(p.mo)
						p.mo.state = S_PLAY_PAIN
						S_StartSound(p.mo, sfx_s3k51, p)
						if XSon and p.mo.skin == "xsonic" and p.xsonictable and sfx_xsvoc5 and not XS_Super(p)
							XSVoice(p, p.mo, p.xsonictable, sfx_xsvoc5)
							p.mo.sprite2 = SPR2_CLNG
							p.mo.frame = ($ & ~FF_FRAMEMASK)
						end
					end
					if Scene.Tick >= 1841
						p.mo.flags = $|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT
					end
					if Scene.Tick >= 1911
						p.mo.flags2 = $|MF2_DONTDRAW
					end
				end
			end
			
			if Scene.Tick >= 1886 and Scene.Tick < 1908
				if Scene.Tick == 1886
					P_SetOrigin(s, -1365*FU, -4722*FU, 0)
					s.angle = FixedAngle(234*FU)
					P_InstaThrust(s, s.angle, 80*FU)
					S_StartSound(nil, sfx_skid)
				end
				Sonic_SkidState(s)
				US_SpawnSkidDust(s)
				s.momx = FixedDiv(FixedMul($, 34), 36)
				s.momy = FixedDiv(FixedMul($, 34), 36)
				if Scene.Tick == 1898
					s.spritexscale = FU
					s.spriteyscale = FU
					s.SU_Squash = {Squish2 = 10}
				end
			end
			if Scene.Tick >= 1908 and Scene.Tick < 1935
				s.momz = $+(P_GetMobjGravity(s) or -FU/2)*P_MobjFlip(s)
			end
			if Scene.Tick == 1908
				P_SetObjectMomZ(s, 26*FU, false)
				S_StartSound(nil, sfx_vsson2)
				s.state = S_PLAY_SPRING
				s.z = $+s.scale*3*P_MobjFlip(s)
				s.spritexscale = FU-(FU/6)
				s.spriteyscale = FU+(FU/5)
				s.SU_Squash = {HopSquash = 10}
			end
			if Scene.Tick >= 1925 and Scene.Tick < 1935
				if Scene.Tick == 1925
					s.spritexscale = FU
					s.spriteyscale = FU
					s.SU_Squash = {Squish2 = 10}
					Scene.AscendingQuake = FU*8
				end
				P_StartQuake(Scene.AscendingQuake, 3)
				Sonic_SkidState(s)
			end
			if Scene.Tick == 1935 --ZOOM!
				S_StartSound(nil, sfx_vssop6)
				s.flags2 = $|MF2_DONTDRAW
				
				local gfxb = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
				gfxb.color = SKINCOLOR_GOLDENROD
				gfxb.colorized = true
				gfxb.blendmode = AST_ADD
				gfxb.renderflags = RF_FULLBRIGHT
				gfxb.destscale = 99*FU
				gfxb.scalespeed = FU*3
				gfxb.fuse = 15
				gfxb.tics = 15
				p.US_WhiteFlash = FF_TRANS70
				
				local gfx = P_SpawnMobj(s.x, s.y, s.z, MT_THOK)
				gfx.flags2 = MF2_DONTDRAW
				gfx.tics = 51
				gfx.fuse = 51
				
				P_InstaThrust(gfx, s.angle-FixedAngle(38*FU), 131*s.scale)
				gfx.angle = s.angle-FixedAngle(38*FU)
				gfx.scale = $*2
				gfx.color = skins[s.skin].supercolor+4
				gfx.LoopDeLoop = 1
				
				Scene.BlastAway = gfx
			end
			
			if Scene.Tick >= 1935 and Scene.BlastAway and Scene.BlastAway.valid
				local Trail = Scene.BlastAway
				local LOOPX = FixedMul(FixedMul(50*FU, cos(Trail.LoopDeLoop*ANG20)), cos(Trail.angle+ANGLE_90))
				local LOOPY = FixedMul(FixedMul(50*FU, cos(Trail.LoopDeLoop*ANG20)), sin(Trail.angle+ANGLE_90))
				local LOOPZ = FixedMul(15*FU, sin(Trail.LoopDeLoop*ANG20))
				
				if Trail.LoopDeLoop < 25
					Trail.LoopDeLoop = $+1
					Trail.momx = $+LOOPX
					Trail.momy = $+LOOPY
					Trail.momz = $+LOOPZ
				end
				
				local trail = P_SpawnMobjFromMobj(Trail, 0,0,0, MT_THOK)
				trail.color = Trail.color
				trail.blendmode = AST_ADD
				trail.renderflags = RF_FULLBRIGHT
				trail.fuse = 20
				trail.tics = 20
				trail.frame = ($ & ~FF_TRANSMASK)
				trail.scale = Trail.scale
			end
		end
		
		if Scene.DestBlackBarScale
		and Scene.BlackBarScale != Scene.DestBlackBarScale
			Scene.BlackBarScale = $+(Scene.DestBlackBarScale-$)/20
		end
		
		if (Scene.Camera and Scene.Camera.valid)
			Scene.Camera.tics = 2
			Scene.Camera.fuse = 2
			
			if Scene.Tick == 158
				P_SetOrigin(Scene.Camera, 2942*FU, -387*FU, 16*FU)
				Scene.Camera.angle = FixedAngle(201*FU)
				Scene.Camera.aiming = 0
			elseif Scene.Tick == 242 --Dragon Ball ahh Suspense
				P_SetOrigin(Scene.Camera, 2617*FU, -584*FU, 24*FU)
				Scene.Camera.angle = ANGLE_45
				P_InstaThrust(Scene.Camera, Scene.Camera.angle, FU/2)
			elseif Scene.Tick == 393
				P_SetOrigin(Scene.Camera, 831*FU, -2327*FU, 24*FU)
				Scene.Camera.angle = ANGLE_225 --Didn't know this existed. How convienient!
				P_InstaThrust(Scene.Camera, Scene.Camera.angle, FU*3/4)
			elseif Scene.Tick == 521
				P_SetOrigin(Scene.Camera, 2741*FU, -459*FU, 24*FU)
				Scene.Camera.angle = ANGLE_45
				P_InstaThrust(Scene.Camera, Scene.Camera.angle, FU/5)
			elseif Scene.Tick == 671
				P_SetOrigin(Scene.Camera, 745*FU, -2400*FU, 24*FU)
				Scene.Camera.angle = FixedAngle(226*FU)
				P_InstaThrust(Scene.Camera, Scene.Camera.angle, FU/3)
			elseif Scene.Tick == 808
				Scene.Camera.momx = 0
				Scene.Camera.momy = 0
				P_SetOrigin(Scene.Camera, 2805*FU, -413*FU, 24*FU)
				Scene.Camera.angle = ANGLE_90
			elseif Scene.Tick == 870
				P_SetOrigin(Scene.Camera, 693*FU, -2462*FU, 24*FU)
				Scene.Camera.angle = ANGLE_225
			elseif Scene.Tick == 893
				Scene.Camera.angle = FixedAngle(80*FU)
				Scene.Camera.aiming = -ANG30
				P_SetOrigin(Scene.Camera, 2709*FU, -800*FU, 242*FU)
			--	P_SetOrigin(Scene.Camera
			elseif Scene.Tick >= 910 and Scene.Tick < 987
				Scene.Camera.z = $+(1250*FU-$)/5
				Scene.Camera.aiming = $+(-$)/5
			elseif Scene.Tick >= 987 and Scene.Tick < 1001 --Ohh boy this is gonna be a fun one. (Not) | Edit: It sure wasn't :sob:
				local CAMDIST = FixedHypot(Scene.Camera.x-s.x, Scene.Camera.y-s.y)
				local ANGLE = R_PointToAngle2(Scene.Camera.x, Scene.Camera.y, s.x, s.y)
				if Scene.Tick == 987
				--	Scene.Camera.SceneSwirve = Scene.Camera.angle-ANGLE_45
					Scene.Camera.SceneSwirveSpeed = FU
					Scene.Camera.Swirve = {X = s.x+FixedMul(CAMDIST, cos(ANGLE+ANGLE_180)), Y = s.y+FixedMul(CAMDIST, sin(ANGLE+ANGLE_180))}
				end
				Scene.Camera.angle = ANGLE
				P_MoveOrigin(Scene.Camera, Scene.Camera.Swirve.X, Scene.Camera.Swirve.Y, Scene.Camera.z)
				local CAMANGLE = ANGLE+ANGLE_180+FixedAngle(Scene.Camera.SceneSwirveSpeed*3)
				CAMDIST = $-Scene.Camera.SceneSwirveSpeed*6
				Scene.Camera.Swirve.X = s.x+FixedMul(CAMDIST, cos(CAMANGLE))
				Scene.Camera.Swirve.Y = s.y+FixedMul(CAMDIST, sin(CAMANGLE))
				Scene.Camera.z = max($-Scene.Camera.SceneSwirveSpeed/3, s.z+s.height/2)
				Scene.Camera.SceneSwirveSpeed = $+FU
				
			elseif Scene.Tick >= 1001 and Scene.Tick < 1044
				if Scene.Tick == 1001
					Scene.Camera.momx = 0
					Scene.Camera.momy = 0
					Scene.Camera.SceneSwirveSpeed = nil
					Scene.Camera.Swirve = nil
					Scene.Camera.angle = FixedAngle(39*FU)
					P_SetOrigin(Scene.Camera, 2695*FU, -480*FU, 1240*FU)
					Scene.Camera.DestXY = {X = 2485*FU, Y = -654*FU}
				end
				P_MoveOrigin(Scene.Camera, Scene.Camera.x+(Scene.Camera.DestXY.X-Scene.Camera.x)/20, 
				Scene.Camera.y+(Scene.Camera.DestXY.Y-Scene.Camera.y)/20,
				Scene.Camera.z)
			elseif Scene.Tick >= 1044 and Scene.Tick < 1128
				if Scene.Tick == 1044
					Scene.Camera.angle = FixedAngle(76*FU)
					P_SetOrigin(Scene.Camera, 2384*FU, -953*FU, 1056*FU)
					Scene.Camera.DestXY = {X = 599*FU, Y = -2732*FU, Z = 16*FU}
				end
				P_MoveOrigin(Scene.Camera, Scene.Camera.x+(Scene.Camera.DestXY.X-Scene.Camera.x)/10, 
				Scene.Camera.y+(Scene.Camera.DestXY.Y-Scene.Camera.y)/10,
				Scene.Camera.z+(Scene.Camera.DestXY.Z-Scene.Camera.z)/10)
			elseif Scene.Tick == 1128
				Scene.Camera.DestXY = nil
				Scene.Camera.angle = FixedAngle(223*FU)
				P_SetOrigin(Scene.Camera, 658*FU, -2502*FU, 16*FU)
			elseif Scene.Tick == 1229
				Scene.Camera.DestXY = {X = 2614*FU, Y = -563*FU}
				Scene.Camera.angle = FixedAngle(41*FU)
				P_SetOrigin(Scene.Camera, 2686*FU, -499*FU, 1230*FU)
			elseif Scene.Tick >= 1247 and Scene.Tick < 1378
				P_MoveOrigin(Scene.Camera, Scene.Camera.x+(Scene.Camera.DestXY.X-Scene.Camera.x)/8, 
				Scene.Camera.y+(Scene.Camera.DestXY.Y-Scene.Camera.y)/8,
				Scene.Camera.z)
			elseif Scene.Tick == 1378
				P_SetOrigin(Scene.Camera, 2882*FU, -405*FU, 1230*FU)
				Scene.Camera.angle = FixedAngle(193*FU)
				P_InstaThrust(Scene.Camera, Scene.Camera.angle-ANGLE_90, FU/10)
			elseif Scene.Tick == 1505
				P_SetOrigin(Scene.Camera, -357*FU, -3495*FU, 24*FU)
				Scene.Camera.angle = FixedAngle(171*FU)
				P_InstaThrust(Scene.Camera, Scene.Camera.angle-ANGLE_90, FU/10)
			elseif Scene.Tick == 1617
				Scene.Camera.momx = 0
				Scene.Camera.momy = 0
				Scene.Camera.angle = FixedAngle(141*FU)
				Scene.Camera.aiming = ANG2*2
				P_SetOrigin(Scene.Camera, 2864*FU, -434*FU, 1224*FU)
			elseif Scene.Tick == 1807
				Scene.Camera.angle = FixedAngle(121*FU)
				Scene.Camera.aiming = 0
				P_SetOrigin(Scene.Camera, -330*FU, -3562*FU, 24*FU)
			elseif Scene.Tick >= 1841 and Scene.Tick < 1935
				if Scene.Tick == 1841
					P_SetOrigin(Scene.Camera, -748*FU, -4832*FU, 216*FU)
					Scene.Camera.aiming = ANG10
					Scene.Camera.Tracker = P_SpawnMobj(-2171*FU, -4892*FU, 799*FU, MT_THOK)
					Scene.Camera.Tracker.flags2 = MF2_DONTDRAW
					Scene.Camera.Tracker.tics = 1000
					Scene.Camera.Tracker.fuse = 1000
					P_InstaThrust(Scene.Camera.Tracker, R_PointToAngle2(Scene.Camera.Tracker.x, Scene.Camera.Tracker.y, s.x, s.y), -108*FU)
				end
			--	P_RemoveMobj(Scene.Camera)
				if Scene.Camera.Tracker and Scene.Camera.Tracker.valid
					Scene.Camera.angle = R_PointToAngle2(Scene.Camera.x, Scene.Camera.y, Scene.Camera.Tracker.x, Scene.Camera.Tracker.y)
				end
			elseif Scene.Tick == 1935
				if Scene.Camera.Tracker and Scene.Camera.Tracker.valid
					P_RemoveMobj(Scene.Camera.Tracker)
				end
			end
		end
		
		local SKIPHOLD = false
		for p in players.iterate do
			if (server and server.valid and not isdedicatedserver and (server.US_BackupButtons & BT_SPIN)
			or IsPlayerAdmin(p) and (p.US_BackupButtons & BT_SPIN))
				SKIPHOLD = true
			end
		end
		if SKIPHOLD==true
			Scene.Skipping = min(($ or 0)+FU/53, FU)
		else Scene.Skipping = 0 end
		local SKIP = Scene.Skipping >= FU and true or false
		
		if Scene.AscendingQuake
			Scene.AscendingQuake = $+FU*3
		end
		
		if Scene.SuperAura
			if Scene.SuperAura == true
				S_StartSound(s, sfx_vssop2)
				Scene.SuperAura = {SFX = 98, Tick = 1, Aura = nil}
				s.eflags = $|MFE_FORCESUPER
				US_HeavyFloorImpact(s, SKINCOLOR_GOLDENROD)
			else
				Scene.SuperAura.Tick = $+1
			--	s.sprite2 = $|FF_SPR2SUPER
				s.color = skins[s.skin].supercolor+abs(FixedMul(4, sin(Scene.Tick*ANG15))) --Animate Super Color
				
				if not (s.flags2 & MF2_DONTDRAW)
					local aura = P_SpawnGhostMobj(s) --Overlay glow
					aura.renderflags = RF_FULLBRIGHT
					P_TryMove(aura, s.x+s.momx, s.y+s.momy, false)
					aura.z = s.z+s.momz
					aura.colorized = true
					aura.dispoffset = 1
					aura.color = SKINCOLOR_GOLDENROD
					aura.blendmode = AST_ADD
					aura.tics = 2
					aura.fuse = 50
					aura.frame = ($ & ~FF_TRANSMASK)|FF_TRANS60
					
					local RADIUS = FixedInt(s.radius) --Sparkle Aura
					local X = P_RandomRange(-RADIUS, RADIUS)
					local Y = P_RandomRange(-RADIUS, RADIUS)
					local Z = P_RandomRange(0, 50)
					local SCALEDIV = P_RandomRange(1, 3)
					local FLOAT = P_RandomRange(2, 3)
					
					local aura2 = P_SpawnMobjFromMobj(s, X*FU, Y*FU, Z*s.scale, MT_BOXSPARKLE)
					aura2.blendmode = AST_ADD
					aura2.color = SKINCOLOR_GOLDENROD
					aura2.colorized = true
					aura2.frame = ($ & ~FF_TRANSMASK)|FF_TRANS30
					aura2.scale = ($*3/2)/SCALEDIV
					aura2.tics = P_RandomRange(6, 14)
					P_SetObjectMomZ(aura2, FLOAT*FU, false)
					
					if not Scene.SuperAura.NoDBZ
						US_RenderSuperAura(s, SKINCOLOR_YELLOW) --Dragon Ball Z Super Aura??
					end
				end
				
				if Scene.SuperAura.Tick >= 18
				and not Scene.SuperAura.NoSFX
					Scene.SuperAura.SFX = max($-1, 0)
					if not S_SoundPlaying(s, sfx_vssop3)
					or not Scene.SuperAura.SFX
						Scene.SuperAura.SFX = 98
						S_StartSound(s, sfx_vssop3)
					end
				elseif Scene.SuperAura.NoSFX
				and S_SoundPlaying(s, sfx_vssop3)
					S_StopSoundByID(s, sfx_vssop3)
				end
			end
		end
		
		if Scene.LightLevel != nil
			for sector in sectors.iterate do
				P_SpawnLightningFlash(sector)
				sector.lightlevel = Scene.LightLevel
			end
			if Scene.FullBrightSonic
				local brightmobj = P_SpawnGhostMobj(s)
				brightmobj.renderflags = RF_FULLBRIGHT
				P_TryMove(brightmobj, s.x+s.momx, s.y+s.momy, false)
				brightmobj.z = s.z+s.momz
				brightmobj.tics = 2
				brightmobj.fuse = 50
				brightmobj.frame = ($ & ~FF_TRANSMASK)
			end
		end
		
		if (p and p.valid)
		and Scene.Camera and Scene.Camera.valid
			p.awayviewmobj = Scene.Camera
			p.awayviewtics = 2
			p.awayviewaiming = Scene.Camera.aiming
		end
		
		if Scene.Tick == 2026 --Heyyy! That's the year I'm currently making this!
		or SKIP==true
			G_SetCustomExitVars(nil, 1)
			G_ExitLevel()
		end
		return --
	end
	
	if s.US_ImCooked --Hahaa... Man I'm dead... :skull:
		if not s.US_SpecialReady
			if consoleplayer and consoleplayer.mo
				P_FlashPal(consoleplayer, PAL_MIXUP, 3)
			end
			local inf = s.US_ImCooked.Inflictor or nil
			local so = s.US_ImCooked.Source or s.US_ImCooked.Inflictor
			
			Sonic_GibSound(s, sfx_vssonh, 70)
			S_StartSound(s, sfx_vssont)
			s.state = S_PLAY_PAIN
			s.US_Finished = 1
			s.US_ImCooked = nil
			local ANGLE = (inf and inf.valid) and R_PointToAngle2(s.x, s.y, inf.x, inf.y) or s.angle 
			s.angle = ANGLE
			s.flags = $|MF_NOCLIPTHING & ~(MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY)
			P_InstaThrust(s, ANGLE, -108*s.scale)
			if (s.momz*P_MobjFlip(s) < 9*s.scale)
				P_SetObjectMomZ(s, 9*FU, false)
			end
			if P_IsObjectOnGround(s)
				s.z = $+s.scale*3*P_MobjFlip(s)
			end
			
			local SPARKCOLOR = (so and so.valid) and so.color or (inf and inf.valid) and inf.color or nil
			SpawnHitSpark(s, SPARKCOLOR, s.scale*4)
			
		else
			return true --This stops the mobj's thinking from here
		end
	end
	
	if s.US_Finished
		local PAUSE = FU
		local DONE = false
		
		if s.US_Finished == 1
			PAUSE = 1
			
			s.rollangle = $-ANG30
			s.state = S_PLAY_PAIN
			
			if P_IsObjectOnGround(s)
				s.eflags = ($ & ~MFE_JUSTHITFLOOR)
				s.state = S_PLAY_PAIN
				s.sprite2 = SPR2_SHIT
				s.frame = ($ & ~FF_FRAMEMASK)
				Sonic_GibSound(s, sfx_s3k49, 18)
				US_SpawnHeavyLandDust(s)
				Sonic_Quake(s, 20*FU, 5, 2200*FU)
				PAUSE = 0
			end
		elseif s.US_Finished <= 7
			PAUSE = 7
			
			s.momx = 0
			s.momy = 0
			s.momz = 0
			
			if s.US_Finished == 7
				P_SetObjectMomZ(s, 20*FU, false)
				if P_IsObjectOnGround(s)
					s.z = $+s.scale*3*P_MobjFlip(s)
				end
				
				s.state = S_PLAY_PAIN
				P_InstaThrust(s, s.angle, -32*s.scale)
				PAUSE = 0
			end
		elseif s.US_Finished == 8
			PAUSE = 8
			
			s.rollangle = $-ANG15
			s.state = S_PLAY_PAIN
			s.momz = $+(P_GetMobjGravity(s) or -FU/2)*4*P_MobjFlip(s)
			
			if P_IsObjectOnGround(s)
				s.momx = 0
				s.momy = 0
				Sonic_GibSound(s, sfx_s3k5d, 18)
				s.spritexscale = FU+(FU/2)
				s.spriteyscale = FU-(FU/2)
				s.SU_Squash = {Squish = 10}
				s.rollangle = 0
				US_SpawnLandDust(s)
				Sonic_Quake(s, 22*FU, 3, 1140*FU)
				
				s.state = S_PLAY_PAIN
				s.sprite2 = SPR2_SHIT
				s.frame = ($ & ~FF_FRAMEMASK)
				PAUSE = 0
			end
		elseif s.US_Finished <= 113
			PAUSE = 113
			s.state = S_PLAY_PAIN
			s.sprite2 = SPR2_SHIT
			s.frame = ($ & ~FF_FRAMEMASK)
			
			if s.US_Finished == 113
				Sonic_StartSuperSonicCutscene(s)
				s.US_Finished = nil
				return --
			end
		end
		s.US_Finished = min($+1, PAUSE or FU)
		
		return --
	end
	
	if s.US_DeathTimer --He's Defeated!!
		s.US_DeathTimer = $+1
		s.state = S_PLAY_DEAD
		s.flags = $|MF_NOCLIP|MF_NOCLIPHEIGHT
		if s.US_DeathTimer == 19
			S_StartSound(s, sfx_vsson0)
			s.state = S_PLAY_DRWN
		end
		if s.US_DeathTimer >= 19
			s.state = S_PLAY_DRWN
		end
		return
	end
	
	if s.US_CutScene1 --Cutscene 1: "A Blue Blur has arrived."
		local Scene = s.US_CutScene1
		local p = consoleplayer
		
		Scene.Tick = min($+1, FU) --How long the CutScene has been at it
		
		if Scene.Tick == 20 --Scene Triggers
			local MUSIC = "UVSSON" 
			S_ChangeMusic(MUSIC, true)
			mapmusname = MUSIC
			Scene.FadeBlack = true
			Scene.Part = 1
		end
		if Scene.Tick == 237
			P_SetOrigin(Scene.Camera, 3382*FU, 210*FU, 48*FU)
			Scene.Camera.momx = 0
			Scene.Camera.momy = 0
			Scene.Camera.angle = ANGLE_45
			Scene.Part = 2
		end
		if Scene.Part == 1
			if s.state == S_PLAY_STND
				s.state = S_PLAY_STND
			end
		elseif Scene.Part == 2
			Scene.Camera.z = max($-FU/5, 24*FU)
			if Scene.Tick == 265 --Hm...
				S_StartSound(s, sfx_vsson1)
			end
			if Scene.Tick == 295
				s.spritexscale = FU+2256
				s.spriteyscale = FU-4256
				s.SU_Squash = {Squish2 = 4, Cancels = "death"}
			end
			if Scene.Tick == 299 --Finally decided to show up, eh?
				s.state = S_PLAY_WAIT
				s.spritexscale = FU-(FU/4)
				s.spriteyscale = FU+(FU/3)
				s.SU_Squash = {HopSquash = 10, Cancels = "death"}
			end
			if Scene.Tick == 406
				s.spritexscale = FU
				s.spriteyscale = FU
				s.SU_Squash = {Stretch = 4, Cancels = "death"}
			end
			if Scene.Tick == 410 --Bring it on!
				s.state = S_PLAY_STND
				s.sprite2 = SPR2_USTA
				s.frame = ($ & ~FF_FRAMEMASK)
				s.spritexscale = FU+(FU/4)
				s.spriteyscale = FU-(FU/4)
				s.SU_Squash = {Squish = 10, Cancels = "midair-death"}
				US_SpawnLandDust(s)
				S_StartSound(s, sfx_s3k99)
			end
			
			if s.state == S_PLAY_WAIT
				s.tics = max($, 3)
				s.frame = ($ & ~FF_FRAMEMASK)
			end
		end
		
		if Scene.FadeBlack and (leveltime % 3)==0
			Scene.BlackTrans = min($+FU, 10*FU)
		end
		
		if Scene.Camera and Scene.Camera.valid
			Scene.Camera.tics = 2
			Scene.Camera.fuse = 2
			if Scene.Part == 1
				P_InstaThrust(Scene.Camera, Scene.Camera.angle-ANGLE_90, FU/4)
			end
		end
		
		local SKIPHOLD = false
		for p in players.iterate do
			if (server and server.valid and not isdedicatedserver and (server.US_BackupButtons & BT_SPIN)
			or IsPlayerAdmin(p) and (p.US_BackupButtons & BT_SPIN))
				SKIPHOLD = true
			end
		end
		if SKIPHOLD==true
			Scene.Skipping = min(($ or 0)+FU/53, FU)
		else Scene.Skipping = 0 end
		local SKIP = Scene.Skipping >= FU and true or false
		
		if p and p.valid
		and Scene.Camera and Scene.Camera.valid
			p.awayviewmobj = Scene.Camera
			p.awayviewtics = 2
		end
		if not USonic_CutScene
			USonic_CutScene = s.US_CutScene1
		end
		
		if Scene.Tick == 452 --This Scene Trigger should be at the end.
		or SKIP==true
			s.US_CutScene1 = nil
			USonic_CutScene = 0
			for p in players.iterate do
				p.US_WhiteFlash = 0
				if (p.mo and p.mo.valid)
					p.mo.reactiontime = 15
				end
			end
			if SKIP==true
				S_SetMusicPosition(12306)
			end
		end
	end
	
	P_BossTargetPlayer(s, true)
	local m = s.target
	local p = m.player
	
	if s.US_DontHurt
		s.US_DontHurt = max($-1, 0)
	else s.US_DontHurt = 0 end
	
	if s.US_Invulnerable
		s.US_Invulnerable = max($-1, 0)
	elseif s.US_Invulnerable
		s.flags = $|MF_SHOOTABLE
		s.US_Invulnerable = 0 
	end
	
	if s.US_FallState
	and s.state == S_PLAY_FALL
	and not P_IsObjectOnGround(s)
		s.US_DontHurt = max($, 1)
	else s.US_FallState = nil end
	
	if P_IsObjectOnGround(s)
	and not s.US_InPain
	and not s.US_SpinFlash
		if (s.momx or s.momy)
			local SPEED = abs(s.momx)+abs(s.momy)
			
			if SPEED >= 32*s.scale
				if s.state != S_PLAY_RUN
					s.state = S_PLAY_RUN
				end
			else
				if s.state != S_PLAY_WALK
					s.state = S_PLAY_WALK
				end
			end
		else
			if s.state != S_PLAY_STND and s.state != S_PLAY_WAIT
				s.state = S_PLAY_STND
			end
		end
	end
	
	if s.US_Jumped
	and s.state == S_PLAY_ROLL
	and not (P_IsObjectOnGround(s) or (s.eflags & MFE_JUSTHITFLOOR))
	and not s.US_InPain
	and not s.US_SpinFlash
		s.US_Jumped = $+1
	else
		s.US_Jumped = nil
	end
	
	if s.US_HomingEffect and s.US_HomingEffect.valid
		local gfx = s.US_HomingEffect
		gfx.sprite = s.sprite
		gfx.sprite2 = s.sprite2
		gfx.frame = ($ & ~FF_FRAMEMASK)|(s.frame & FF_FRAMEMASK)
		gfx.angle = s.angle
		gfx.spriteyoffset = s.spriteyoffset
		gfx.spritexoffset = s.spritexoffset
		gfx.spriteyscale = s.spriteyscale
		gfx.spritexscale = s.spritexscale
		gfx.mirrored = s.mirrored and true or false
		gfx.rollangle = s.rollangle or 0
		A_CapeChase(gfx, 1, 0)
	else
		s.US_HomingEffect = nil
	end
	
	if s.US_HomingAttack
	and not P_IsObjectOnGround(m)
	and not s.US_InPain
	and not s.US_SpinFlash
	and s.US_Jumped
	and not s.US_SpecialAttack1
		s.US_HomingAttack.Tick = min($+1, 20)
		s.state = S_PLAY_ROLL
		if s.US_HomingAttack.Tick == 20
			s.US_HomingAttack = nil
			s.US_Jumped = nil
			s.state = S_PLAY_FALL
			s.momz = $/5
		end
	else
		s.US_HomingAttack = nil
	end
	
	if s.US_InPain --Ouch!
	and (s.state == S_PLAY_PAIN
	and not P_IsObjectOnGround(s) or s.US_Stunned)
		s.US_InPain = $+1
		s.US_DontHurt = max($, 1)
		
		if s.US_InPain == 18
			s.flags = $|MF_SHOOTABLE
		end
		
		if s.US_Recovery
		and s.US_Stunned
			local PAUSE = FU
			local STOP = false
			
			if s.US_Stunned == 1
				if s.US_Recovery <= 12
					PAUSE = 12
					if s.US_Recovery == 12
						if not P_IsObjectOnGround(s)
							STOP = true
						else
							P_SetObjectMomZ(s, 983040, false)
							P_InstaThrust(s, s.angle, -25*s.scale)
							if P_IsObjectOnGround(s)
								s.z = $+s.scale*3*P_MobjFlip(s)
							end
							s.state = S_PLAY_ROLL
							S_StartSound(s, sfx_jump)
							PAUSE = 0 --Continue
						end
					end
				elseif s.US_Recovery == 13
					PAUSE = 13
					if s.state != S_PLAY_ROLL
						s.state = S_PLAY_ROLL
					end
					s.momz = $+(P_GetMobjGravity(s) or -FU/2)*2*P_MobjFlip(s)
					if P_IsObjectOnGround(s)
						P_SetObjectMomZ(s, 10*FU, false)
						s.momx = $*8/10
						s.momy = $*8/10
						if P_IsObjectOnGround(s)
							s.z = $+s.scale*3*P_MobjFlip(s)
						end
						S_StartSound(s, sfx_vsson2)
						s.renderflags = P_MobjFlip(s)==-1 and $|RF_VERTICALFLIP or ($ & ~RF_VERTICALFLIP)
						s.rollangle = 0
						PAUSE = 0
						s.state = S_PLAY_SPRING
						s.spritexscale = FU-(FU/2)
						s.spriteyscale = FU+(FU*3/4)
						s.SU_Squash = {HopSquash = 10, Cancels = "death"}
					end
				elseif s.US_Recovery == 14
					PAUSE = 14
					s.state = S_PLAY_SPRING
					s.rollangle = $+ANG20
					s.angle = $+ANGLE_45
					local gfx = P_SpawnGhostMobj(s)
					gfx.fuse,gfx.tics = 5,5
					gfx.colorized = true
					gfx.color = SKINCOLOR_SKY
					gfx.blendode = AST_ADD
					
					if P_IsObjectOnGround(s)
						s.state = S_PLAY_SKID
						s.spritexscale = FU
						s.spriteyscale = FU
						s.SU_Squash = {Squish2 = 10, Cancels = "death"}
						S_StartSound(s, sfx_s3k4c)
						US_SpawnLandDust(s)
						PAUSE = 0
						s.rollangle = 0
						if m and m.valid and m.health
							s.angle = R_PointToAngle2(s.x, s.y, m.x, m.y)
						end
					end
				elseif s.US_Recovery <= 24
					PAUSE = 24
					Sonic_SkidState(s)
					s.momx = 0
					s.momy = 0
					if not P_IsObjectOnGround(s)
					or s.US_Recovery == 24
						STOP = true
					end
				end
			elseif s.US_Stunned == 2
				if s.US_Recovery <= 6
					PAUSE = 6
					s.momx = 0
					s.momy = 0
					s.momz = 0
					
					s.sprite2 = SPR2_SHIT
					s.frame = ($ & ~FF_FRAMEMASK)
					
					if s.US_Recovery == 6
						if not P_IsObjectOnGround(s)
							STOP = true
						else
							s.state = S_PLAY_PAIN
							P_SetObjectMomZ(s, 10*FU, false)
							P_InstaThrust(s, s.angle, -23*s.scale)
							if P_IsObjectOnGround(s)
								s.z = $+s.scale*3*P_MobjFlip(s)
							end
							PAUSE = 0 --Continue
						end
					end
				elseif s.US_Recovery == 7
					PAUSE = 7
					s.state = S_PLAY_PAIN
					s.rollangle = $-FixedAngle(FU*6)
					s.momz = $+(P_GetMobjGravity(s) or -FU/2)*2*P_MobjFlip(s)
					
					if P_IsObjectOnGround(s)
						s.momx = $/4
						s.momy = $/4
						Sonic_GibSound(s, sfx_s3k5d, 18)
						s.spritexscale = FU+(FU/2)
						s.spriteyscale = FU-(FU/2)
						s.SU_Squash = {Squish = 10, Cancels = "midair-death"}
						s.rollangle = 0
						US_SpawnLandDust(s)
						Sonic_Quake(s, 20*FU, 2, 450*FU)
						
						s.state = S_PLAY_PAIN
						s.sprite2 = SPR2_SHIT
						s.frame = ($ & ~FF_FRAMEMASK)
						PAUSE = 0
					end
				elseif s.US_Recovery <= 45
					PAUSE = 45
					local SPEED = abs(s.momx)+abs(s.momy)
					s.state = S_PLAY_PAIN
					s.sprite2 = SPR2_SHIT
					s.frame = ($ & ~FF_FRAMEMASK)
					if s.US_Recovery == 32
						s.spritexscale = FU
						s.spriteyscale = FU
						s.SU_Squash = {Squish2 = 13, Cancels = "death"}
					end
					
					if s.US_Recovery >= 32
						if (leveltime % 2)
							s.spritexoffset = -FU*3
						else
							s.spritexoffset = FU*3
						end
					end
					if SPEED > 2*s.scale
						US_SpawnSkidDust(s)
					end
					
					if s.US_Recovery == 45
						if not P_IsObjectOnGround(s)
							STOP = true
						else
							PAUSE = 0
							s.rollangle = ANGLE_180
							P_SetObjectMomZ(s, 5*FU, false)
							if P_IsObjectOnGround(s)
								s.z = $+s.scale*3*P_MobjFlip(s)
							end
							S_StartSound(s, sfx_ngjump)
							s.state = S_PLAY_SKID
							s.spritexscale = FU-(FU/2)
							s.spriteyscale = FU+(FU*3/4)
							s.SU_Squash = {HopSquash = 10, Cancels = "death"}
						end
					end
				elseif s.US_Recovery == 46
					PAUSE = 46
					s.rollangle = max($-ANGLE_45, 0)
					s.momz = $+(P_GetMobjGravity(s) or -FU/2)*2*P_MobjFlip(s)
					s.state = S_PLAY_SPRING
					
					if P_IsObjectOnGround(s)
						s.state = S_PLAY_SKID
						S_StartSound(s, sfx_s3k4c)
						US_SpawnLandDust(s)
						PAUSE = 0
						s.rollangle = 0
						s.spritexscale = FU
						s.spriteyscale = FU
						s.SU_Squash = {Squish2 = 12, Cancels = "death"}
					end
				elseif s.US_Recovery <= 58
					PAUSE = 58
					Sonic_SkidState(s)
					s.momx = 0
					s.momy = 0
					if not P_IsObjectOnGround(s)
					or s.US_Recovery == 58
						STOP = true
					end
				end
			end
			
			s.US_Recovery = min($+1, PAUSE or FU)
			
			if STOP != false
				s.renderflags = P_MobjFlip(s)==-1 and $|RF_VERTICALFLIP or ($ & ~RF_VERTICALFLIP)
				s.rollangle = 0
				s.spritexoffset = 0
				s.US_Invulnerable = 18
				s.US_PainStreak = 0
				s.US_InPain = 0
				s.US_Stunned = 0
				s.US_Recovery = 0
				
				if not P_IsObjectOnGround(s)
					S_StartSound(s, sfx_s1c0)
					s.state = S_PLAY_FALL
					s.US_DontHurt = 5
					s.US_FallState = true
				end
			end
		elseif P_IsObjectOnGround(s)
		and s.US_Stunned
		and not s.US_Recovery
			s.momx = 0
			s.momy = 0
			s.US_Recovery = 1
			if s.US_Stunned == 1
				S_StartSound(s, sfx_s3k4a)
				s.rollangle = 0
				s.renderflags = P_MobjFlip(s)==1 and $|RF_VERTICALFLIP or ($ & ~RF_VERTICALFLIP) 
				s.state = S_PLAY_RIDE
				s.spritexscale = FU
				s.spriteyscale = FU
				s.SU_Squash = {Squish2 = 12, Cancels = "death"}
			elseif s.US_Stunned == 2
				s.state = S_PLAY_PAIN
				s.sprite2 = SPR2_SHIT
				s.frame = ($ & ~FF_FRAMEMASK)
				Sonic_GibSound(s, sfx_s3k49, 18)
				US_SpawnHeavyLandDust(s)
				Sonic_Quake(s, 20*FU, 5, 450*FU)
			end
		elseif s.US_Stunned
			s.US_Recovery = 0
			local ROLLSPEED = s.US_Stunned==2 and FU*20 or FU*4
			s.rollangle = $-FixedAngle(ROLLSPEED)
			s.spritexoffset = 0
		end
	else
		if s.US_Stunned
			s.US_Invulnerable = 9
			s.renderflags = P_MobjFlip(s)==-1 and $|RF_VERTICALFLIP or ($ & ~RF_VERTICALFLIP)
			s.rollangle = 0
			s.spritexoffset = 0
		end
		if s.US_InPain
			s.flags = $|MF_SHOOTABLE
			s.US_PainStreak = 0
		end
		s.US_InPain = 0
		s.US_Stunned = 0
		s.US_Recovery = 0
	end
	s.flags2 = $ & ~(MF2_FRET)
	
	if s.US_Taunt
	and m.health
	and not s.US_InPain
		s.US_Taunt = max($-1, 0)
		if not s.US_Taunt
			local VOICE = {sfx_vssoni, sfx_vssonj, sfx_vssonk}
			local SAY = VOICE[P_RandomRange(1, #VOICE)]
			S_StartSound(s, SAY)
		end
	end
	
	if s.US_SpinFlash --Spindash too fast for eyes!
	and not s.US_InPain
	and not s.US_SpecialAttack1
	and not s.US_SpecialAttack2
		P_InstaThrust(s, s.US_SpinFlash.Angle, s.US_SpinFlash.Thrust)
		if s.US_SpinFlash.Timer
			s.state = S_PLAY_SPINDASH
			s.flags = $ & ~(MF_SHOOTABLE)
			s.US_SpinFlash.Timer = max($-1, 0)
			local gfx = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
			gfx.color = s.color
			gfx.blendmode = AST_TRANSLUCENT
			if not s.US_SpinFlash.Timer
				S_StartSound(s, sfx_skid)
				Sonic_SkidState(s)
				s.US_SpinFlash.Thrust = $/4
				P_InstaThrust(s, s.US_SpinFlash.Angle, s.US_SpinFlash.Thrust)
				s.flags = $|MF_SHOOTABLE
				US_SpawnSkidDust(s)
			end
		elseif s.US_SpinFlash.SkidTime
			Sonic_SkidState(s)
			US_SpawnSkidDust(s)
			s.US_SpinFlash.SkidTime = max($-1, 0)
			s.US_SpinFlash.Thrust = FixedDiv(FixedMul($, 34), 40)
			P_InstaThrust(s, s.US_SpinFlash.Angle, s.US_SpinFlash.Thrust)
			if not s.US_SpinFlash.SkidTime
				s.US_SpinFlash = nil
				
			--	local ANGLEDIFFER = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)-R_PointToAngle2(s.x, s.y, m.x+m.momy, m.y+m.momy)
			--	if ANGLEDIFFER > ANGLE_180
			--		ANGLEDIFFER = InvAngle(InvAngle($))
			--	end
			--	if ANGLEDIFFER < 0 ANGLEDIFFER = InvAngle($) end
				
			--	if ANGLEDIFFER > ANGLE_90
			--		print("Hey!")
			--	end
			end
		end
	elseif s.US_SpinFlash
		s.US_SpinFlash = nil
		s.flags = $|MF_SHOOTABLE
	end
	
	if s.US_SonicStorm
	and not s.US_InPain
	and not s.US_SpecialAttack1
	and not s.US_SpecialAttack2
		local Storm = s.US_SonicStorm
		if not Storm.Released
			Storm.Angle = Target and Target.valid and Target.health and R_PointToAngle2(s.x, s.y, Target.x, Target.y) or s.angle
			s.angle = Storm.Angle
			Storm.Charging = min($+1, 15)
			s.state = S_PLAY_SPINDASH
			s.momx = 0
			s.momy = 0
			if Storm.Charging == 15
				US_SpawnSonicStorm(s, Storm.Angle, Storm.FireSpeed)
				P_InstaThrust(s, Storm.Angle, -21*s.scale)
				P_SetObjectMomZ(s, 10*FU, false)
				s.state = S_PLAY_ROLL
				Storm.Released = true
				US_SpawnLandDust(s)
				S_StopSoundByID(s, sfx_vssonu)
				S_StartSound(s, sfx_zoom)
			end
		--	FireSpeed = 210*m.scale, Charging = 1}
		elseif s.momz*P_MobjFlip(s) < m.scale*3
			s.state = S_PLAY_FALL
			s.US_FallState = true
			s.US_DontHurt = 5
			s.US_SonicStorm = nil
		end
	elseif s.US_SonicStorm
		s.US_SonicStorm = nil
	end
	
	if s.US_SpecialAttack1
	and not s.US_InPain
	and s.health
		--Special Move 1: Homimg Drive
		local Special = s.US_SpecialAttack1
		local t = Special.Target
		local DIST = FixedHypot(s.x-t.x, s.y-t.y)
		
		if P_PlayerInPain(t.player) and Special.PlayerStunned
			t.player.US_LockButtons = 2
			t.player.cmd.buttons = 0
			t.player.drawangle = $-ANG20
		else
			Special.PlayerStunned = false
		end
		
		if Special.Falling
			s.momz = $+(P_GetMobjGravity(s) or -FU/2)*2*P_MobjFlip(s)
			local gfx = P_SpawnGhostMobj(s)
			gfx.fuse,gfx.tics = 5,5
			if P_IsObjectOnGround(s)
			or (s.eflags & MFE_JUSTHITFLOOR)
				Special.Ready = 16
				Special.Falling = false
				S_StartSound(s, sfx_s3k4c)
				US_SpawnLandDust(s)
				Special.Angle = R_PointToAngle2(s.x, s.y, m.x+m.momy, m.y+m.momy)
				s.angle = Special.Angle
				Sonic_SkidState(s)
				s.SU_Squash = {Squish2 = 15, Cancels = "death"}
			end
		elseif Special.Ready
			Special.Ready = max($-1, 0)
			Special.Angle = R_PointToAngle2(s.x, s.y, m.x+m.momy, m.y+m.momy)
			s.angle = Special.Angle
			Sonic_SkidState(s)
			local CALCULATEDLAND = false
			local FLOOR = P_MobjFlip(s) == 1 and s.floorz or s.ceilingz
			local FLOORDIST = abs(m.z-FLOOR)
			local SPEED = 131*s.scale
		--	if
			
			if CALCULATEDLAND
			or not Special.Ready
				s.flags = $ & ~(MF_SHOOTABLE)
				Sonic_GibSound(s, sfx_cdfm01, 2*TICRATE+18)
				P_InstaThrust(s, Special.Angle, SPEED)
				Special.DashSpeed = SPEED
				s.state = S_PLAY_SPINDASH
				Special.GO = 29
			end
		elseif Special.GO
			Special.GO = max($-1, 0)
			P_InstaThrust(s, Special.Angle, Special.DashSpeed)
			s.state = S_PLAY_SPINDASH
			local gfx = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
			gfx.color = s.color
			gfx.blendmode = AST_TRANSLUCENT
			s.flags = $ & ~(MF_SHOOTABLE)
			s.angle = Special.Angle
			
			if not Special.GO
				S_StartSound(s, sfx_skid)
				Sonic_SkidState(s)
				Special.DashSpeed = $/4
				Special.SkidTime = 14
				P_InstaThrust(s, Special.Angle, Special.DashSpeed)
				s.flags = $|MF_SHOOTABLE
				US_SpawnSkidDust(s)
			end
		elseif Special.SkidTime
			s.angle = Special.Angle
			Sonic_SkidState(s)
			US_SpawnSkidDust(s)
			Special.SkidTime = max($-1, 0)
			Special.DashSpeed = FixedDiv(FixedMul($, 34), 40)
			P_InstaThrust(s, Special.Angle, Special.DashSpeed)
			if not Special.SkidTime
				s.US_SpecialAttack1 = nil
			end
		else
			s.flags = $|MF_SHOOTABLE
			s.US_SpecialAttack1 = nil
		end
	elseif s.US_SpecialAttack1
		s.flags = $|MF_SHOOTABLE
		s.US_SpecialAttack1 = nil
	end
	
	if s.US_SpecialAttack2
	and not s.US_InPain
	and s.health
		local Special = s.US_SpecialAttack2
		local Target = Special.Target
		
		if Special.Ready
			Sonic_SkidState(s)
			if not s.US_SpecialReady
				s.angle = Special.Angle
				P_InstaThrust(s, Special.Angle, Special.Boost)
				s.state = S_PLAY_RUN
				S_StartSound(s, Special.BoostSFX)
				Special.Ready = false
				Special.BoostTime = 21
			end
		elseif Special.BoostTime
			Special.BoostTime = max($-1, 0)
			P_InstaThrust(s, Special.Angle, Special.Boost)
			s.state = S_PLAY_RUN
			s.angle = Special.Angle
			
			if s.US_HardMode
				Special.Angle = R_PointToAngle2(s.x, s.y, m.x+m.momx, m.y+m.momy)
			end
			
			local gfx = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
			gfx.color = s.color
			gfx.blendmode = AST_TRANSLUCENT
			s.angle = Special.Angle
			
			if not Special.BoostTime
				S_StartSound(s, sfx_skid)
				Sonic_SkidState(s)
				Special.Boost = $/5
				Special.SkidTime = 19
				P_InstaThrust(s, Special.Angle, Special.Boost)
				US_SpawnSkidDust(s)
			end
		elseif Special.SkidTime
			s.angle = Special.Angle
			Sonic_SkidState(s)
			US_SpawnSkidDust(s)
			Special.SkidTime = max($-1, 0)
			Special.Boost = FixedDiv(FixedMul($, 34), 38)
			P_InstaThrust(s, Special.Angle, Special.Boost)
			if not Special.SkidTime
				Special.Stop = true
				s.US_SpecialAttack2 = nil
			end
		else
			Special.SkidTime = 0
			Special.BoostTime = 0
			Special.Ready = false
		end
		
		if Special.PrepJump
			Sonic_SkidState(s)
			Special.PrepJump = max($-1, 0)
			if Special.PrepJump > 10
				P_InstaThrust(s, Special.Angle, Special.Boost)
				US_SpawnSkidDust(s)
				local gfx = P_SpawnGhostMobj(s)
				gfx.fuse,gfx.tics = 6,6
				gfx.colorized = true
				gfx.color = SKINCOLOR_SKY
				gfx.blendode = AST_ADD
			else
				Special.Angle = (Target and Target.valid and Target.health) and R_PointToAngle2(s.x, s.y, Target.x+Target.momx, Target.y+Target.momy) or s.angle
				s.angle = Special.Angle
				s.SU_Squash = {Squish2 = Special.PrepJump, Cancels = "death"}
			end
			
			if not Special.PrepJump
				if not (Target and Target.valid and Target.health and not (Target.flags & (MF_NOCLIP|MF_NOCLIPTHING)))
					Special.Stop = true
				else
					Special.AttemptHomingBoost = 28
					Special.Boost = 110*s.scale
				end
			end
		elseif Special.AttemptHomingBoost
			Special.AttemptHomingBoost = max($-1, 0)
			if (Target and Target.valid and Target.health)
			and Special.AttemptHomingBoost
				local DIST = FixedHypot(s.x-Target.x, s.y-Target.y)
				local TRUEDIST = FixedHypot(DIST, s.z-Target.z)
				
				s.momx = FixedMul(FixedDiv((Target.x+Target.momx)-s.x, TRUEDIST), 110*s.scale)
				s.momy = FixedMul(FixedDiv((Target.y+Target.momy)-s.y, TRUEDIST), 110*s.scale)
				s.momz = FixedMul(FixedDiv((Target.z+Target.momz+Target.height/4)-s.z, TRUEDIST), 110*s.scale)
				
				s.state = S_PLAY_SPINDASH
				local gfx = P_SpawnGhostMobj(s)
				gfx.fuse,gfx.tics = 4,4
				gfx.colorized = true
				gfx.color = SKINCOLOR_SKY
				gfx.blendode = AST_ADD
			else
				Special.Stop = true
				s.US_FallState = true
				s.state = S_PLAY_FALL
				s.US_DontHurt = 5
				S_StartSound(s, sfx_s1b6)
			end
		elseif Special.BoostCombo
			if (Target and Target.valid and Target.health)
				Special.BoostCombo = max($-1, 0)
				Target.player.camerascale = skins[Target.skin].camerascale*5/2
				Target.momx = 0
				Target.momy = 0
				Target.momz = 0
				s.momx = 0
				s.momx = 0
				s.momz = 0
				P_TryMove(s, Target.x+Target.momx, Target.y+Target.momx, true)
				if (Special.BoostCombo % 5)==0
					US_SpawnFlashDash(s, SKINCOLOR_COBALT)
					SpawnHitSpark(Target, SKINCOLOR_COBALT, s.scale*3/4)
					Sonic_GibSound(m, sfx_vssonf, 35)
					Sonic_Quake(Target, 33*FU, 3, 1250*FU)
					Target.player.US_LockButtons = 10
					Target.player.US_PainState = true
					if not P_PlayerInPain(Target.player)
						P_DoPlayerPain(Target.player, s, s)
					end
					if (Special.BoostCombo % 10)==0 and Target.player.rings and not Target.player.powers[pw_shield]
						P_PlayerRingBurst(Target.player, 1)
						Target.player.rings = max($-1, 0)
					end
				end
				P_InstaThrust(Target, 0, 0)
				if not Special.BoostCombo
					Target.player.camerascale = skins[Target.skin].camerascale
					Target.player.US_LockButtons = 2*TICRATE
					Target.player.US_PainState = true
					P_SetObjectMomZ(Target, 8*FU, true)
					if P_TryMove(s, m.x, m.y, false)
						s.z = (Target.z+Target.height)*P_MobjFlip(Target)
					end
					s.momx = 0
					s.momy = 0
					P_SetObjectMomZ(s, 15*FU, false)
					S_StartSound(s, sfx_vsson2)
					US_SpawnShadowStep(s, true, nil, s.scale*2)
					s.flags2 = $ & ~(MF2_DONTDRAW)
					s.state = S_PLAY_SPRING
					Special.QuickTrick = 35
					Target.player.aiming = ANG30*P_MobjFlip(s)
				end
			else 
				Special.Stop = true 
			end
		elseif Special.QuickTrick
			s.rollangle = $-FixedAngle(abs(s.momz*2))
			Special.Angle = R_PointToAngle2(s.x, s.y, Target.x, Target.y)
			Target.player.US_LockButtons = max($, 35)
			Target.player.US_PainState = true
			if not Special.QuickTrick
			or s.momz*P_MobjFlip(s) < s.scale
				S_StartSound(s, sfx_cdfm01)
				s.rollangle = 0
				s.state = S_PLAY_SPINDASH
				Special.SonicEagle = 29 --Sonic Eagle Time!!
				Special.QuickTrick = 0
			end
		elseif Special.SonicEagle
			local DIST = FixedHypot(s.x-Target.x, s.y-Target.y)
			local TRUEDIST = FixedHypot(DIST, s.z-Target.z)
				
			s.state = S_PLAY_SPINDASH
			s.momx = FixedMul(FixedDiv((Target.x+Target.momx)-s.x, max(TRUEDIST, 1)), 110*s.scale)
			s.momy = FixedMul(FixedDiv((Target.y+Target.momy)-s.y, max(TRUEDIST, 1)), 110*s.scale)
			s.momz = FixedMul(FixedDiv((Target.z+Target.momz+Target.height/2)-s.z, max(TRUEDIST, 1)), 110*s.scale)
			
			local gfx = P_SpawnMobjFromMobj(s, 0,0,0, MT_THOK)
			gfx.color = SKINCOLOR_SKY
			gfx.blendmode = AST_ADD
			
			if not Special.SonicEagle
				Special.Stop = true
				s.US_FallState = true
				s.state = S_PLAY_FALL
				s.US_DontHurt = 5
				S_StartSound(s, sfx_s1b6)
			end
		end
		
		if Special.Stop
			s.US_SpecialAttack2 = nil
			s.flags = $|MF_SHOOTABLE
			s.flags2 = $ & ~(MF2_DONTDRAW)
			s.rollangle = 0
			if Target and Target.valid
				Target.player.camerascale = skins[Target.skin].camerascale
			end
		end
	elseif s.US_SpecialAttack2
		s.US_SpecialAttack2 = nil
		s.flags = $|MF_SHOOTABLE
		s.flags2 = $ & ~(MF2_DONTDRAW)
		s.rollangle = 0
		if Target and Target.valid
			Target.player.camerascale = skins[Target.skin].camerascale
		end
	end
	--	(m and m.valid and m.health) and R_PointToAngle2(s.x, s.y, m.x+m.momx*2, m.y+m.momy*2) or s.angle,
	--Boost = 180*m.scale, BoostSFX = sfx_vssonc, Ready = true}
	
	if not (m and m.valid and p) return end
	
	if Sonic_SkilledChars(m)
		s.US_HardMode = true
	else
		s.US_HardMode = false
	end
	
	if not netgame and not m.health and p.deadtimer and not p.bot --Sonic Taunts at your performance =(
		if p.deadtimer == 1
		and p.lives
			S_FadeMusic(0, MUSICRATE)
		end
		
		local VOICE = {sfx_vsson3, sfx_vsson4, sfx_vsson5}
		if p.deadtimer == 34
		and not s.SU_DeathTaunt
			local SFX = VOICE[P_RandomRange(1, #VOICE)]
			S_StartSoundAtVolume(s, SFX, 50, p)
			if S_SoundPlaying(s, SFX)
				S_StartSound(nil, SFX)
			end
			p.deadtimer = min($, 33)
			s.SU_DeathTaunt = true
		end
		local STOP = #VOICE
		for i = 1,#VOICE do
			if not S_SoundPlaying(s, VOICE[i])
				STOP = max($-1, 0)
			end
		end
		if STOP and s.SU_DeathTaunt
			p.deadtimer = min($, 33)
		end
		
	end
	
	if m.health
		local angle = R_PointToAngle2(s.x, s.y, m.x, m.y)
		local SPEED = abs(s.momx+s.momy)
		
		if not s.US_CutScene1
		and not s.US_CutScene2
		and not s.US_SpinFlash
		and not s.US_InPain
		and not s.US_SpecialAttack1
		and not s.US_SpecialAttack2
		and not s.US_SonicStorm
		and not p.US_SonicEagleSLAM
			if not s.US_FallState
				if P_IsObjectOnGround(s)
					P_Thrust(s, angle, s.scale*5)
					angle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
				else
					P_Thrust(s, angle, s.scale)
				end
				s.angle = angle
			end
			
			local DIST = FixedHypot(s.x-m.x, s.y-m.y)
			local TRUEDIST = FixedHypot(DIST, s.z-m.z)
			local VULNERABLE = not p.powers[pw_flashing] 
			and not p.powers[pw_invulnerability] 
			and not p.powers[pw_super] 
			and not (m.flags & (MF_NOCLIP|MF_NOCLIPTHING))
			and true or false
			
			if (leveltime % 90)>=45
			and (leveltime % 12)==0 --25
			and P_IsObjectOnGround(s)
			and s.US_TWasOnGround
			and abs(angle-R_PointToAngle2(s.x, s.y, m.x+m.momx, m.y+m.momy)) < (s.US_HardMode and ANG30 or ANG15) --Try an even tighter attempt!
			and TRUEDIST < (s.US_HardMode and 1577*s.scale or 966*s.scale)
			and TRUEDIST > 100*s.scale
			and VULNERABLE
			and Sonic_EnergyLevel(s, s.US_Energy)>=1
				Sonic_DoSpecialAttack2(s, m)
				return --
			end
			
			if s.US_Jumped and s.US_Jumped > 20
			and not P_IsObjectOnGround(s)
			and s.momz*P_MobjFlip(s) < 6*s.scale
			and (leveltime % 5)==0
			and TRUEDIST < 1000*s.scale
			and not s.US_HomingAttack
			and not s.US_HomingEffect
				s.US_Jumped = min($, 5)
				s.momx = FixedMul(FixedDiv((m.x+m.momx)-s.x, TRUEDIST), 110*s.scale)
				s.momy = FixedMul(FixedDiv((m.y+m.momy)-s.y, TRUEDIST), 110*s.scale)
				s.momz = FixedMul(FixedDiv((m.z+m.momz+m.height/4)-s.z, TRUEDIST), 110*s.scale)
				S_StartSound(s, sfx_s3ka2) --Replace with Sonic 4's Homing Attack Sound
				s.US_HomingAttack = {Tick = 1, MOMX = m.momx, MOMY = m.momy, MOMZ = m.momz, USEMOM = true}
				local gfx = P_SpawnGhostMobj(s)
				gfx.colorized = true
				gfx.color = SKINCOLOR_COBALT
				gfx.tics,gfx.fuse = 20,20
				gfx.tracer = s
				gfx.blendmode = AST_ADD
				s.US_HomingEffect = gfx
			end
			
			if (leveltime % 3)==0
			and abs(angle-R_PointToAngle2(s.x, s.y, m.x+m.momx, m.y+m.momy)) < ANG20
			and s.US_TWasOnGround
			and SPEED >= 15*s.scale
			and TRUEDIST < 890*s.scale
			and TRUEDIST > 150*s.scale
			and not s.US_HomingEffect
			and P_IsObjectOnGround(s)
				Sonic_DoSpindashFlash(s, m)
			end
			
			if (leveltime % 8)==0
			and TRUEDIST < max(SPEED*24, 200*s.scale)
			and P_IsObjectOnGround(s)
			and not s.US_HomingEffect
			and not s.US_SpinFlash
				P_SetObjectMomZ(s, 10*FU, false)
				S_StartSound(s, sfx_vsson2)
				s.state = S_PLAY_ROLL
				s.US_Jumped = 1
			end
			
			if (leveltime % 70)>=35
			and (leveltime % (TRUEDIST<= (890*s.scale)-SPEED and 52 or 12))==0
			and abs(angle-R_PointToAngle2(s.x, s.y, m.x+m.momx, m.y+m.momy)) < ANG30
			and P_IsObjectOnGround(s)
			and not s.US_HomingEffect
			and TRUEDIST < 2330*s.scale
			and VULNERABLE
			and s.US_Energy >= FU/6 --Not letting this become too abusable
				Sonic_DoSonicStorm(s, m)
			end
		end
	end
	
	s.US_TWasOnGround = max(($ or 0)-1, 0)
	if P_IsObjectOnGround(m)
		s.US_TWasOnGround = 5
	end
end, MT_ULTIMATEBOSS_SONIC)

addHook("PlayerSpawn", function(p)
	if p.US_SonicEagleSLAM
		p.US_SonicEagleSLAM = nil
		if (p.mo and p.mo.valid)
			p.mo.rollangle = 0
			p.mo.spritexoffset = 0
			p.mo.flags = $ & ~(MF_NOTHINK|MF_NOCLIPTHING)
		end
	end
end)
addHook("PreThinkFrame", function(p)
	for p in players.iterate do
		local m = p.mo
		
		p.US_BackupButtons = p.cmd.buttons
		if USonic_CutScene --In a Cut-Scene, lock our controls.
			local BUTTONS = p.cmd.buttons
			p.cmd.buttons = 0
			p.cmd.forwardmove = 0
			p.cmd.sidemove = 0
			--Buttt maybe some exceptions for some characters, specificallly to keep their taunts.
			if m and m.valid
				if m.skin == "xsonic" or m.skin == "xsonicserious" or m.skin == "kou" or m.skin == "speedym" or m.skin == "skip" or m.skin == "jana"
					if (BUTTONS & BT_TOSSFLAG)
						p.cmd.buttons = BT_TOSSFLAG
					end
				elseif m.skin == "adventuresonic" or m.skin == "modernsonic" or m.skin == "mint"
					if (BUTTONS & BT_TOSSFLAG)
						p.cmd.buttons = BT_TOSSFLAG
					end
					if (BUTTONS & BT_CUSTOM2)
						p.cmd.buttons = $|BT_CUSTOM2
					end
				elseif m.skin == "speedy"
					if (BUTTONS & BT_WEAPONNEXT)
						p.cmd.buttons = BT_WEAPONNEXT
					end
					if (BUTTONS & BT_WEAPONPREV)
						p.cmd.buttons = BT_WEAPONPREV
					end
				end
			end
		end
		
		if not (m and m.valid) continue end
		
		if p.US_UseSameButtons
			p.cmd.buttons = (p.US_LastButtons or 0)
			p.cmd.forwardmove = (p.US_LastForwardMove or 0)
			p.cmd.sidemove = (p.US_LastSideMove or 0)
			p.US_UseSameButtons = nil
		end
		
		if p.US_LockButtons
			if p.US_PainState
			and not P_PlayerInPain(p)
				p.US_LockButtons = 0
				p.US_LockMoving = 0
				p.US_PainState = nil
			else
				p.US_LockButtons = max($-1, 0)
				p.cmd.buttons = 0
			end
		else p.US_LockButtons = 0 end
		
		if p.US_LockMoving
			if p.US_PainState
			and not P_PlayerInPain(p)
				p.US_LockMoving = 0
				p.US_PainState = nil
			else
				p.US_LockMoving = max($-1, 0)
				p.cmd.forwardmove = 0
				p.cmd.sidemove = 0
			end
		else p.US_LockMoving = 0 end
		
		if p.US_PainState
		and not P_PlayerInPain(p)
			p.US_PainState = nil
		end
	end
end)

addHook("PlayerThink", function(p)
	if mapheaderinfo[gamemap].lvlttl == "Vs Super Sonic"
		p.pflags = $|PF_FULLSTASIS
		p.US_LockButtons = 2
		p.US_LockMoving = 2
		
		if (server and server.valid and (server.US_BackupButtons & BT_JUMP) or IsPlayerAdmin(p) and (p.cmd.buttons & BT_JUMP)) 
		and leveltime >= 2*TICRATE
		or (isdedicatedserver and leveltime >= 20*TICRATE)
			G_SetCustomExitVars(nil, 1)
			G_ExitLevel()
		end
	end
	
	if p.US_WhiteFlash != nil
		if (leveltime % 3)==0
			p.US_WhiteFlash = min($+FU, FU*10)
		end
		if p.US_WhiteFlash >= FU*10
			p.US_WhiteFlash = nil
		end
	end
	
	if not (p.mo and p.mo.valid) return end
	local m = p.mo
	
	if m.SU_Squash
		Sonic_Squash(m)
	end
	
	if USonic_CutScene
		if m.state == S_PLAY_STND
			m.tics = states[S_PLAY_STND].tics
		end
	end
	
	if p.US_SonicEagleSLAM
	and m.health
	and not p.powers[pw_carry]
		local Slam = p.US_SonicEagleSLAM
		if not Slam.SoundPlayed
			S_StartSound(m, Slam.PlaySound)
			Slam.SoundPlayed = true
		end
		local DEADSPRITE = false
		Slam.Tick = $+1
		p.US_LockMoving = max($, 2)
		p.US_LockButtons = max($, 2)
		
		if p.minttable and p.minttable.recovertime --Pain Recovery somehow bypassing the PreThink Stasis I had to :sob:
			p.minttable.recovertime = 0
		end
		if p.yusonictable and p.yusonictable.painrecovery
			p.yusonictable.painrecovery = 0
		end
		
		p.US_PainState = nil
		p.powers[pw_nocontrol] = max($, 2)
	--	m.flags = $|MF_NOCLIPTHING
		m.state = S_PLAY_PAIN
		p.powers[pw_flashing] = max($, 2)
		m.flags2 = $ & ~(MF2_DONTDRAW)
		if not (m.flags & MF_NOTHINK)
		and not (Slam.Slammed and Slam.Slammed=="Done")
			Slam.Angle = ($ or p.drawangle)-ANGLE_45
			p.drawangle = Slam.Angle
			m.rollangle = $-ANG20
		end
		
		if Slam.Impact and (m.flags & MF_NOTHINK)
			Slam.Impact = max($-1, 0)
			if not Slam.Impact
				m.flags = $ & ~(MF_NOTHINK)
			end
		else Slam.Impact = 0 end
		
		if not Slam.Slammed
			local gfx = P_SpawnGhostMobj(m)
			gfx.fuse,gfx.tics = 5,5
			m.momz = $+(P_GetMobjGravity(m) or -m.scale/2)*3
			if (m.eflags & MFE_JUSTHITFLOOR) or P_IsObjectOnGround(m)
				S_StartSound(m, sfx_vssong)
				Slam.Slammed = true
				Slam.HitGround = 1
				US_SpawnHeavyLandDust(m)
				Sonic_Quake(m, 38*FU, 8, 1500*FU)
				US_HeavyFloorImpact(m, SKINCOLOR_COBALT)
				if Slam.Inflictor
					p.powers[pw_flashing] = 0
					P_DamageMobj(m, nil, Slam.Inflictor)
				else
					P_DoPlayerPain(p)
				end
				if m.health
					Slam.Impact = 6
				--	m.momz = 60*m.scale*P_MobjFlip(m)
					m.state = S_PLAY_PAIN
					DEADSPRITE = true
					m.flags = $|MF_NOTHINK
					m.eflags = $ & ~(MFE_JUSTHITFLOOR)
					P_SetObjectMomZ(m, 50*FU, false)
					P_InstaThrust(m, (p.speed) and R_PointToAngle2(m.x, m.y, m.x+m.momx, m.x+m.momy) or m.angle+ANGLE_180, 55*m.scale)
					if P_IsObjectOnGround(m)
						m.z = $+m.scale*3*P_MobjFlip(m)
					end
					p.cmd.buttons = 0
				end
			end
		elseif Slam.Slammed == true
			if not Slam.Impact
				m.momz = $+(P_GetMobjGravity(m) or -m.scale/2)*3
				p.powers[pw_flashing] = 3*TICRATE
				if (m.eflags & MFE_JUSTHITFLOOR) or P_IsObjectOnGround(m)
					m.state = S_PLAY_PAIN
					DEADSPRITE = true
					Slam.HitGround = ($ or 0)+1
					m.eflags = $ & ~(MFE_JUSTHITFLOOR)
					if Slam.HitGround > 2
						Slam.Slammed = "Done"
						Sonic_GibSound(m, sfx_s3k5d, 18)
						Slam.TrytoGetUp = 1
						m.spritexscale = FU+(FU/2)
						m.spriteyscale = FU-(FU/2)
						m.SU_Squash = {Squish = 10, Cancels = "midair-death-carry-sprung"}
						m.momx = 0
						m.momy = 0
						m.rollangle = 0
						p.cmd.buttons = 0
						US_SpawnLandDust(m)
					else
						Sonic_GibSound(m, sfx_s3k49, 18)
						US_SpawnHeavyLandDust(m)
						Sonic_Quake(m, 28*FU, 6, 500*FU)
						P_SetObjectMomZ(m, 20*FU, false)
						if P_IsObjectOnGround(m)
							m.z = $+m.scale*3*P_MobjFlip(m)
						end
						P_InstaThrust(m, (p.speed) and R_PointToAngle2(m.x, m.y, m.x+m.momx, m.x+m.momy) or m.angle+ANGLE_180, 23*m.scale)
						Slam.Impact = 5
						m.flags = $|MF_NOTHINK
					end
				end
			end
		elseif Slam.Slammed == "Done"
			Slam.TrytoGetup = min(($ or 1)+1, 60)
			p.powers[pw_flashing] = 3*TICRATE
			DEADSPRITE = true
			if Slam.TrytoGetup >= 30
				if (leveltime % 2)
					m.spritexoffset = -FU*3
				else
					m.spritexoffset = FU*3
				end
				if Slam.TrytoGetup == 60
					S_StartSound(m, sfx_ngjump)
					m.state = S_PLAY_STND
					m.spritexscale = FU-(FU/3)
					m.spriteyscale = FU+(FU/2)
					m.SU_Squash = {HopSquash = 11, Cancels = "death-carry-sprung"}
					p.US_SonicEagleSLAM = nil
					m.rollangle = 0
					m.spritexoffset = 0
					m.flags = $ & ~(MF_NOTHINK|MF_NOCLIPTHING)
					p.powers[pw_flashing] = 3*TICRATE-1
				end
			end
		end
		 
		if m.state == S_PLAY_PAIN
		and DEADSPRITE 
			if m.skin == "adventuresonic"
				m.sprite2 = SPR2_TAL5 --Don't think I didn't see you in that corner =)
			elseif SPR2_SHIT and P_IsValidSprite2(m, SPR2_SHIT)
				m.sprite2 = SPR2_SHIT
			end
			m.frame = ($ & ~FF_FRAMEMASK)|A
		end
		
		if m.momz*P_MobjFlip(m) > -m.scale
		and not Slam.Slammed
			p.US_SonicEagleSLAM = nil
			m.rollangle = 0
			m.spritexoffset = 0
		end
		
		if Slam.Slammed and not P_PlayerInPain(p)
			p.US_SonicEagleSLAM = nil
			m.rollangle = 0
			m.spritexoffset = 0
			m.flags = $ & ~(MF_NOTHINK|MF_NOCLIPTHING)
			p.powers[pw_flashing] = 3*TICRATE-1
		end
	elseif p.US_SonicEagleSLAM
		p.US_SonicEagleSLAM = nil
		m.rollangle = 0
		m.spritexoffset = 0
		m.flags = $ & ~(MF_NOTHINK|MF_NOCLIPTHING)
	end
	
	p.US_LastForwardMove = p.cmd.forwardmove
	p.US_LastSideMove = p.cmd.sidemove
	p.US_LastButtons = p.cmd.buttons
	--= {Inflictor = s, PlaySound = sfx_s3k51, Tick = 1}
end)

addHook("MobjDamage", function(s, i, so)
	if (i==so) and i.player
		local p = i.player
		if not P_IsObjectOnGround(s)
		and s.state == S_PLAY_ROLL
		and not s.US_DontHurt
		--	i.momx = -($/2)
		--	i.momy = -($/2)
			p.pflags = $ & ~(PF_JUMPED|PF_SPINNING|PF_THOKKED|PF_STARTDASH)
			if i.state == S_PLAY_ROLL or i.state == S_PLAY_JUMP or i.state == S_PLAY_SPINDASH
				i.state = P_IsObjectOnGround(i) and (p.speed and S_PLAY_WALK or S_PLAY_STND) or S_PLAY_FALL
			end
			SpawnHitSpark(s)
			Sonic_GibSound(s, sfx_s3k49, 18)
			s.momx = -($/2)
			s.momy = -($/2)
			if s.US_HardMode
				s.US_DontHurt = 19
				s.state = S_PLAY_ROLL
				s.US_Jumped = 1
			else
				s.state = S_PLAY_FALL
				s.US_FallState = true
				s.US_DontHurt = 5
			end
			return true
		end
	end
	
	if s.US_InPain and (s.US_InPain < 18 or s.US_Stunned) return true end
	if s.US_Invulnerable or (s.US_SpecialAttack2 and s.US_SpecialAttack2.BoostTime and i.skin == "xsonic") return true end
	
	s.health = max($-1, 0)
	if not s.health
		P_KillMobj(s, i, so)
	--	s.renderflags = P_MobjFlip(s)==-1 and $|RF_VERTICALFLIP or ($ & ~RF_VERTICALFLIP)
	--	s.rollangle = 0
		
	--	s.US_ImCooked = {}
	--	s.state = S_PLAY_DEAD
	--	s.US_DeathTimer = 1
	--	S_StartSound(s, s.info.deathsound)
	--	s.flags = $|MF_NOCLIP--|MF_NOCLIPHEIGHT
	--	P_SetObjectMomZ(s, 10*FU, false)
	--	s.momx = 0
	---	s.momy = 0
	else
		local VOICE = {sfx_vsson6, sfx_vsson7, sfx_vsson8, sfx_vsson9}
		local SAY = VOICE[P_RandomRange(1, #VOICE)]
		local SUPERHIT = 0
		local RINGLOSS = false
		local DIDHITSPARK = false
		local KNOCKBACK = 20
		local KNOCKBACKZ = 7
		
		s.US_PainStreak = ($ or 0)+1
		s.US_RingLoss = min(($ or 0)+1, 3)
		
	--	s.US_RingLoss = 3 --For KnockBack Testing
		if s.US_PainStreak > 1
			local SCALE = s.US_PainStreak > 2 and s.scale*3 or s.scale*2
			SpawnHitSpark(s, so.color, SCALE)
			DIDHITSPARK = true
			
			if s.US_PainStreak > 2
				RINGLOSS = true
				SUPERHIT = 2
			end
			if so.player
				local SFX = s.US_PainStreak > 2 and sfx_vssonp or sfx_vssono
				S_StartSound(nil, SFX, so.player)
			end
		end
		if s.US_RingLoss == 3
		and so.player and so.player.rings <= 5 --You seem to be running low... Lemme help ya :)
			RINGLOSS = true
			if not SUPERHIT
				SUPERHIT = 1
			end
		end
		
		if SUPERHIT
			VOICE = {sfx_vssonq, sfx_vssonr, sfx_vssons} --Replace with more exxagerative pain grunts 
			if SUPERHIT == 1
				table.remove(VOICE, 2)
			end
			SAY = VOICE[P_RandomRange(1, #VOICE)]
			
			if not DIDHITSPARK
				SpawnHitSpark(s, so.color, s.scale*2)
			end
			
			if SUPERHIT == 1
				KNOCKBACK = 35
				KNOCKBACKZ = 8
			elseif SUPERHIT == 2
				KNOCKBACK = 66
				KNOCKBACKZ = 13
			end
			
			s.US_Stunned = SUPERHIT
		end
		
		if RINGLOSS != false
			S_StartSound(s, sfx_altow1)
			s.US_RingLoss = 0
			for d = 1,3 do
				local ANGLE = R_PointToAngle2(s.x, s.y, i.x, i.y)
				local ring = P_SpawnMobj(s.x+FixedMul(s.radius, cos(ANGLE+ANGLE_180)), s.y+FixedMul(s.radius, sin(ANGLE+ANGLE_180)), s.z+s.height+i.momz, MT_FLINGRING)
				ring.angle = ANG60*d
				ring.scale = s.scale
				ring.blendmode = AST_ADD
				ring.fuse,ring.tics = 500,20
				P_InstaThrust(ring, ring.angle, 3*FU)
				P_SetObjectMomZ(ring, 5*FU, true)
			end
		end
		
		if not s.US_InPain or SUPERHIT
			S_StartSound(s, SAY)
			s.state = S_PLAY_PAIN
		end
		local ANGLE = R_PointToAngle2(s.x, s.y, i.x, i.y)
		P_InstaThrust(s, ANGLE, -KNOCKBACK*s.scale)
		if (s.momz*P_MobjFlip(s) < KNOCKBACKZ*s.scale)
			P_SetObjectMomZ(s, KNOCKBACKZ*FU, false)
	--	else
	--		P_SetObjectMomZ(s, 7*FU, true)
		end
		if P_IsObjectOnGround(s)
			s.z = $+s.scale*3*P_MobjFlip(s)
		end
		
		s.US_InPain = 1
		
		s.flags = $ & ~(MF_SHOOTABLE)
		s.flags2 = $|MF2_FRET
		s.US_Energy = min($+FU/15, FU)
	end
	
	return true
end,MT_ULTIMATEBOSS_SONIC)
addHook("MobjDeath", function(s, i, so)
	if not s.US_DeathTimer
		if (i and i.valid)
			local inf = i
			s.US_SpecialReady = 20
			for p in players.iterate do
				if not (p.mo and p.mo.valid) continue end
			--	p.US_LockButtons = ($ or 0)+1
			--	p.US_LockMoving = ($ or 0)+1
				p.US_UseSameButtons = 1
				p.pflags = $|PF_USEDOWN|PF_JUMPDOWN
				p.mo.flags = $|MF_NOTHINK
				P_InstaThrust(p.mo, R_PointToAngle2(p.mo.x, p.mo.y, p.mo.x+p.mo.momx, p.mo.y+p.mo.momy), p.speed)
			end
			for mo in mobjs.iterate() do
				if not (mo and mo.valid) continue end
				S_StopSound(mo)
			end
			if (so and so.valid)
				Sonic_SpecialSkinFinishVOC(so)
				inf = so
			end
			local gfx = P_SpawnMobjFromMobj(inf, 0,0,0, MT_THOK)
			gfx.color = SKINCOLOR_SKY
			gfx.blendmode = AST_ADD
			gfx.renderflags = RF_FULLBRIGHT
			gfx.scale = inf.scale
			gfx.destscale = 99*FU
			gfx.scalespeed = s.scale/2
			gfx.fuse,gfx.tics = 15,15
			s.momx = 0
			s.momy = 0
			s.momz = 0
		--	S_StartSound(nil, sfx_s3kb3)
		--	S_StartSound(nil, sfx_s227)
			S_StartSound(nil, sfx_vssop7)
		end
		s.US_ImCooked = {Inflictor = i, Source = so}
	--	s.renderflags = P_MobjFlip(s)==-1 and $|RF_VERTICALFLIP or ($ & ~RF_VERTICALFLIP)
	--	s.rollangle = 0
	--	s.state = S_PLAY_DEAD
	--	s.US_DeathTimer = 1
	--	S_StartSound(s, s.info.deathsound)
	--	s.flags = $|MF_NOCLIP|MF_NOCLIPHEIGHT & ~(MF_NOGRAVITY)
	--	P_SetObjectMomZ(s, 10*FU, false)
	--	s.momx = 0
	--	s.momy = 0
	end
	return true
end,MT_ULTIMATEBOSS_SONIC)
local function Sonic_Collision(s, m)
	if not (s and s.valid and s.health and m and m.valid and m.player and m.health) return end
	if (s.z > m.z+m.height)
	or (s.z+s.height < m.z)
		return
	end
	local p = m.player
	local VULNERABLE = not p.powers[pw_flashing] 
	and not p.powers[pw_invulnerability] 
	and not p.powers[pw_super] 
	and not (m.flags & (MF_NOCLIP|MF_NOCLIPTHING))
	and true or false
	
	if s.US_SpecialAttack2 and s.US_SpecialAttack2.SonicEagle and not p.US_SonicEagleSLAM
		p.US_SonicEagleSLAM = {Inflictor = s, PlaySound = sfx_s3k51, Tick = 1}
		SpawnHitSpark(m, SKINCOLOR_COBALT, m.scale)
		P_SetObjectMomZ(m, -60*FU, false)
		p.aiming = -ANG30*P_MobjFlip(m)
		S_StartSound(m, sfx_vssonh)
		Sonic_GibSound(s, sfx_vssonh, 2*TICRATE)
	--	m.flags = $|MF_NOCLIPTHING
		
		P_InstaThrust(s, s.angle, -9*s.scale)
		if P_IsObjectOnGround(s)
			s.z = $+s.scale*3*P_MobjFlip(s)
		end
		P_SetObjectMomZ(s, 9*FU, false)
		
		s.state = S_PLAY_FALL
		s.US_FallState = true
		s.US_DontHurt = 5
		s.US_Taunt = 13
		s.US_SpecialAttack2.SonicEagle = 0
		s.US_SpecialAttack2.Stop = true
		
		return false --
	end
	
	if s.US_SpecialAttack2 and s.US_SpecialAttack2.AttemptHomingBoost and (s.US_SpecialAttack2.Target==m)
		S_StartSound(s, sfx_vssone)
		s.US_SpecialAttack2.BoostCombo = 40
		s.US_SpecialAttack2.AttemptHomingBoost = 0
		s.flags2 = $|MF2_DONTDRAW
		
		return false
	elseif s.US_SpecialAttack2 and s.US_SpecialAttack2.BoostCombo and (s.US_SpecialAttack2.Target==m)
		return false
	end
	
	if s.US_SpecialAttack1 and s.US_SpecialAttack1.GO and not s.US_SpecialAttack1.Attacked
		p.powers[pw_flashing] = 0
		p.US_LockButtons = 26
		p.US_PainState = true
		P_DamageMobj(m, s, s, 1)
		if m.health
			P_InstaThrust(m, R_PointToAngle2(m.x, m.y, m.x+m.momx, m.y+m.momy), s.US_SpecialAttack1.DashSpeed/2)
		end
		s.US_SpecialAttack1.PlayerStunned = false
		s.US_SpecialAttack1.DashSpeed = $/3
		SpawnHitSpark(m, SKINCOLOR_COBALT, m.scale)
		Sonic_GibSound(s, sfx_s3k9b, 2*TICRATE)
		S_StartSound(m, sfx_s3k9b)
		
		s.US_SpecialAttack1.Attacked = true
		s.US_Energy = min($+FU/6, FU)
		return false --
	end
	
	if s.US_HomingAttack
	and VULNERABLE
		P_DoPlayerPain(p, m, m)
		SpawnHitSpark(m, SKINCOLOR_COBALT, m.scale*3/2)
		s.US_Jumped = nil
		s.US_HomingAttack = nil
		s.state = S_PLAY_FALL
		Sonic_GibSound(s, sfx_s3k96, 23)
		S_StartSound(m, sfx_s3k61)
		s.momx = -($/8)
		s.momy = -($/8)
		s.state = S_PLAY_FALL
		s.US_FallState = true
		s.US_DontHurt = 5
		P_SetObjectMomZ(s, 10*FU, false)
		s.US_SpecialAttack1 = {Target = m, Falling = true, PlayerStunned = true}
		s.US_Energy = min($+FU/20, FU)
		return false
	end
	
	if s.US_SpinFlash and s.US_SpinFlash.Timer
	and VULNERABLE
		local ANGLEDIFFER = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)-R_PointToAngle2(m.x, m.y, m.x+m.momx, m.y+m.momy)
		ANGLEDIFFER = $+ANGLE_180
		if ANGLEDIFFER > ANGLE_180
			ANGLEDIFFER = InvAngle(InvAngle($))
		end
		if ANGLEDIFFER < 0 ANGLEDIFFER = InvAngle($) end
		
		if p.speed > 60*s.scale
		and ANGLEDIFFER < ANGLE_45
			SpawnHitSpark(s, nil, s.scale*2)
			s.US_SpinFlash = nil
			s.state = S_PLAY_PAIN
			s.angle = R_PointToAngle2(s.x-s.momx, s.y-s.momy, m.x, m.y)
			P_InstaThrust(s, s.angle, -13*s.scale)
			if (s.momz*P_MobjFlip(s) < 6*s.scale)
				P_SetObjectMomZ(s, 6*FU, false)
			end
			if P_IsObjectOnGround(s)
				s.z = $+s.scale*3*P_MobjFlip(s)
			end
			s.US_InPain = 11
			s.flags = $ & ~(MF_SHOOTABLE)
			s.flags2 = $|MF2_FRET
			
			if XSon and (m.skin == "xsonic" or m.skin ==  "xsonicserious") --You can't get the upper part in this =)
			and p.xsonictable and p.xsonictable.zipdash
				p.xsonictable.zipcd = 18
			end
			
			P_InstaThrust(m, R_PointToAngle2(m.x, m.y, m.x+m.momx, m.y+m.momy), -15*m.scale)
			p.pflags = $|PF_JUMPDOWN|PF_USEDOWN & ~(PF_SPINNING|PF_STARTDASH)
			
			S_StartSound(s, sfx_vssonv) --Oof...
			Sonic_GibSound(s, sfx_iceb, 20)
			Sonic_GibSound(s, sfx_s3kaa, 35)
			return --
		else
			P_DamageMobj(m, s, s, 1)
		end
		s.US_Energy = min($+FU/15, FU)
		return false
	end
end
addHook("MobjCollide", Sonic_Collision, MT_ULTIMATEBOSS_SONIC)
addHook("MobjMoveCollide", Sonic_Collision, MT_ULTIMATEBOSS_SONIC)

addHook("MobjDamage", function(m, i, so, dmg, dmgtype)
	if not (m and m.valid and m.player and m.health and so and so.valid and so.health) return end
	local p = m.player
	
	if so.type != MT_ULTIMATEBOSS_SONIC return end
	
	local VULNERABLE = not p.powers[pw_flashing] 
	and not p.powers[pw_invulnerability] 
	and not p.powers[pw_super] 
	and not (m.flags & (MF_NOCLIP|MF_NOCLIPTHING))
	and true or false
	
	if (i==so) and so.US_DontHurt
		return true
	end
	
	if (i==so) and so.US_SpecialAttack2 and so.US_SpecialAttack2.BoostTime
		P_DoPlayerPain(p, so, so)
		SpawnHitSpark(m)
		p.US_LockButtons = 100
		p.US_PainState = true
		P_InstaThrust(m, R_PointToAngle2(m.x, m.y, m.x+m.momx, m.y+m.momy), so.US_SpecialAttack2.Boost/6)
		P_SetObjectMomZ(m, 25*FU, false)
		
		so.US_SpecialAttack2 = {Target = m, Boost = so.US_SpecialAttack2.Boost/12, PrepJump = 30, 
		Angle = R_PointToAngle2(so.x, so.y, m.x+m.momx, m.y+m.momy)
		}
		so.flags = $ & ~(MF_SHOOTABLE)
		Sonic_SkidState(so)
		S_StartSound(so, sfx_skid)
		US_SpawnSkidDust(so)
		return true
	end
end,MT_PLAYER)