--This is where we store all seperate functions for Yu Sonic.
 

--Auto-calculates proper gravity offsets. s = Sonic. ghs = any new effect mobj.
rawset(_G, "YuFlipZ", function(s, ghs)
	if not (s.eflags & MFE_VERTICALFLIP)
		ghs.eflags = $ & ~MFE_VERTICALFLIP
		return ghs.z --remain the same.
	else
		ghs.eflags = $|MFE_VERTICALFLIP
		return s.z+s.height-FixedMul(ghs.height, s.scale)
	end
end)

--Local RNG function that won't cause desyncing. Based on Alfredo's code.
--NEVER use this for anything that needs to be synced!
local yurandomseed = 3135128580
local function YuLocalRandom(a, b, s)
	yurandomseed = $*(max(gamemap+leveltime, 1)%128)
	yurandomseed = $-(s.x+s.y+s.z)
		
	if yurandomseed == 0 --Ignore division warning.
		yurandomseed = 3126124580
	end
			
	yurandomseed = $/2
	local dumb = ((yurandomseed*36548569) >> 4) & (FRACUNIT-1)	
	return ((dumb * (b-a+1)) >> FRACBITS) + a
end

--Like most of my mods, let players turn off quakes and sudden flashes if they're sensitive to it.
--There's no reason for P_, btw. It just feels good. 
rawset(_G, "P_YuQuake", function(p, intensity, tics)
	if not p.yusonictable.noquakes and (p == displayplayer)
	P_StartQuake(intensity, tics)
	end
end)
rawset(_G, "P_YuFlash", function(p, pal, tics)
	if not p.yusonictable.noflashes
	P_FlashPal(p, pal, tics)
	end
end)

--Locks up controls.

rawset(_G, "YuNoControls", function(p, yu, extra)
	yu.custom3 = 10
	yu.custom2 = 10
	yu.spin = 10
	yu.jump = 10
	if extra
	p.pflags = $|PF_JUMPDOWN|PF_USEDOWN
	end
end)

local function DoSpinRev(p, s, yu, color, spinver)
		local blendmode = AST_TRANSLUCENT	
			if color == SKINCOLOR_SABLUETRAIL or p.powers[pw_super]
			or yu.customtrailshiny or yu.lsacharged
				blendmode = AST_ADD
			end
			local offset = 0
			if (leveltime % 2 == 0)
				offset = 2*s.scale
			elseif leveltime % 3 == 0
				offset = -3*s.scale
			elseif leveltime % 5 == 0
				offset = 3*s.scale		
			end
			for d = -1,1,1
				local rev = P_SpawnMobjFromMobj(s, 0, 0, s.momz-(s.scale*8), MT_YUTHOKDISP)
				rev.tracer = s
				rev.angle = p.drawangle
				rev.spritexoffset = $+(offset*d*3)
				
				if spinver --Spinning and bouncing. Doesn't render at all for software.
					rev.scale = s.scale*(25+d)/23
					rev.spriteyoffset = $-(2*s.scale)-offset
					rev.sprite = SPR_YTK8
					if color == SKINCOLOR_SABLUETRAIL 
						rev.frame = A|FF_FULLBRIGHT|TR_TRANS80
					else
						rev.frame = A|FF_FULLBRIGHT|TR_TRANS90
					end
					if (leveltime % 2 == 0)
						rev.spriteyscale = 73000+(s.spriteyscale/10)
						rev.spritexscale = s.spritexscale
						rev.dispoffset = -1
					elseif (leveltime % 3 == 0)
						rev.spriteyscale = 68000+(s.spriteyscale/10)
						rev.spritexscale = s.spritexscale+5000
						rev.rollangle = s.rollangle+ANG20
					else
						rev.spriteyscale = 65000+(s.spriteyscale/10)
						rev.spritexscale = s.spritexscale+15000
						rev.rollangle = s.rollangle-ANG10
					end
				else --Startdash
					rev.sprite = SPR_YTK9 --Aura sprite
					rev.scale = s.scale*(25+d)/24					
					if (yu.spincharge < 48*FRACUNIT)
						rev.frame = A|FF_FULLBRIGHT|TR_TRANS90
					else
						rev.frame = A|FF_FULLBRIGHT|TR_TRANS80
					end	
					rev.rollangle = s.rollangle+FixedAngle(offset*6*d)	
					rev.spriteyoffset = $-(6*s.scale)-offset	
					rev.spriteyscale = 60000+(s.spriteyscale/10)
					rev.spritexscale = s.spritexscale+8001
				end
				
				rev.blendmode = blendmode				
				rev.tics = 3
				rev.yustartdash = true
				if p.powers[pw_super] and (d == -1) and not spinver
					rev.color = SKINCOLOR_FLAME
				else
					rev.color = color
				end
			end
return rev
end
 
--Adventure-style air drag. This is seriously necessary to make him less OP...

rawset(_G, "YuAirDrag", function(p, s, yu)
	if (yu.noairdrag or yu.noairdrag2)
	and not yu.supersonic and not (yu.bouncestate == 1) --Oops, disabled for a while.
	return
	end
	if yu.superflight and yu.supersonic
	or (yu.nobouncedrag and yu.bouncestate)
	return
	end
local airdrag = 804
local nostick = false
	if not (yu.direct > 2)
	or yu.forcenostick
	airdrag = $+18
	nostick = 18
		if yu.forcenostick
		airdrag = $+yu.forcenostick
		nostick = $+yu.forcenostick
		else
		yu.forcebuilder = 0
		end
	end
	
	if (yu.bouncestate == 1) or yu.lsacharged
		if (p.speed < 50*s.scale)
			s.momx = $*80/81
			s.momy = $*80/81
			
		else
			s.momx = $*40/41 --Increased drag
			s.momy = $*40/41
		end
		
	elseif yu.supersonic and not yu.bouncestate
	and (yu.direct > 2)
		if (p.speed < 125*s.scale) and not (p.speed > 145*s.scale)
		or (yu.superaura and p.speed < 145*s.scale) --Super Sonic has inverted air drag. Basically, he's faster in the air.
			if yu.superaura
			s.momx = FixedDiv(FixedMul($, 100), 99)
				if not ((s.flags2 & MF2_TWOD) or twodlevel)
				s.momy = FixedDiv(FixedMul($, 100), 99)
				end
			else
				s.momx = FixedDiv(FixedMul($, 150), 149)
				if not ((s.flags2 & MF2_TWOD) or twodlevel)
				s.momy = FixedDiv(FixedMul($, 150), 149)
				end
			end
			if (p.speed > 70*s.scale)
			yu.runfriction = yu.groundfriction+((p.speed/s.scale)*98)
			yu.frictionlock = 25
				if (yu.runfriction > FRACUNIT)
				yu.runfriction = FRACUNIT
				end
			end
		end
		if p.isxmomentum and (p.speed > 150*s.scale) and not p.xmomtoggledoff --Infinitely accelerate in xmom because xmom is dum
			local num = (p.speed/s.scale)*2
			s.momx = FixedDiv(FixedMul($, num), num-1)
				if not ((s.flags2 & MF2_TWOD) or twodlevel)
				s.momy = FixedDiv(FixedMul($, num), num-1)
				end
		end
	elseif (p.speed > 38*s.scale) or nostick  --Slow down in the air, you're not as fast here
		if (p.xmomtoggledoff or not p.isxmomentum) --No air drag with Xmom. OP as hell.
			if (p.speed > 46*FRACUNIT)
				s.momx = FixedDiv(FixedMul($, 800), airdrag+4)
				s.momy = FixedDiv(FixedMul($, 800), airdrag+4)
			else
				if yu.forcenostick and (p.speed < 20*s.scale)
					s.momx = FixedDiv(FixedMul($, 800), 808)
					s.momy = FixedDiv(FixedMul($, 800), 808)				
				else
					s.momx = FixedDiv(FixedMul($, 800), airdrag)
					s.momy = FixedDiv(FixedMul($, 800), airdrag)	
				end
			end
		end
	end
	yu.forcenostick = 0	
end)

--Spawn jumpball around Sonic.

rawset(_G, "YuJumpBallSpawn", function(p, s, yu)
	if ((leveltime % 2 == 0) and not yu.bouncestate)
	or ( ((p.pflags & PF_THOKKED) and (yu.hominganim or yu.hominganim2 or yu.hominganim3)) and not p.homing and not yu.lsaattack)
	or yu.lsacharged and not yu.lsaattack 
	or (yu.homingtrick and not yu.noaura and not yu.bouncestate)
	or yu.spawnedballalready
	or not p.mo
	return --Return means the function will stop in this case.
	end
	yu.jumpball = P_SpawnMobjFromMobj(s, 0,0,0, MT_YUJUMPBALL)
	
		if yu.jumpball
		yu.jumpball.target = s
		yu.jumpball.tracer = s
		yu.jumpball.mirrored = s.mirrored
		yu.jumpball.skin = s.skin
		yu.jumpball.angle = p.drawangle
		yu.jumpball.rollangle = s.rollangle
		yu.jumpball.colorized = s.colorized
		yu.jumpball.color = s.color
		yu.jumpball.sprite = SPR_PLAY
		
local color = YuAuraColor(s, nil, yu, true)	
	
		if s.state == S_PLAY_SPINDASH--Spinrevving ball?
		yu.jumpball.sprite2 = SPR2_CLMB
			--Spawn weird shakey spindash-charge aura from SA1.
			DoSpinRev(p, s, yu, color)
		else
			yu.jumpball.sprite2 = SPR2_JBAL
		end
		
		if p.powers[pw_super] or yu.lsacharged
		yu.jumpball.blendmode = AST_ADD
		end
		
		local sonicframe = s.frame & ~TR_TRANS10 & ~TR_TRANS20 & ~TR_TRANS30 & ~TR_TRANS40 & ~TR_TRANS50 & ~TR_TRANS60 & ~TR_TRANS70 & ~TR_TRANS80 & ~TR_TRANS90
			if yu.bouncestate or yu.lsaattack or s.state == S_PLAY_SPINDASH
				if not yu.lsaattack and not p.powers[pw_super] and not yu.bouncestate
				yu.jumpball.frame = sonicframe|TR_TRANS10
				else
				yu.jumpball.frame = sonicframe
					if yu.bouncestate
						if (s.frame & ~FF_FULLBRIGHT & ~FF_SPR2SUPER & ~FF_TRANSMASK) == D
						s.frame = E
						end
						yu.jumpball.sprite2 = SPR2_BBAL
						yu.jumpball.spriteyscale = FRACUNIT+2050
						yu.jumpball.spritexscale = FRACUNIT+2050
						if s.color == SKINCOLOR_SABLUETRAIL
						yu.jumpball.color = SKINCOLOR_BLUE
						end
						if (leveltime % 2 == 0)
							yu.jumpball.frame = sonicframe|TR_TRANS50
						else
							yu.jumpball.shadowscale = FRACUNIT --Sonic flickers at this frame, so have this thing cast a shadow then.
						end
						if s.spriteyscale == FRACUNIT+10002
						yu.jumpball.spriteyscale = FRACUNIT+10002
						yu.jumpball.spritexscale = FRACUNIT-15002
						end
					end
				end
			else
				yu.jumpball.frame = sonicframe|TR_TRANS30
			end 
		end
		yu.spawnedballalready = true
end)

--Determine Aura color based on player color.

rawset(_G, "YuAuraColor", function(s, color, yu, careaboutyu)
	if not (s.player and s.player.yusonictable)
	color = s.color
	return color
	end
	if yu.supersonic or (s.player.powers[pw_carry] == CR_NIGHTSMODE)
		if yu.hypersonic
			color = s.player.yuemeraldcolors2[yu.hypercolor]+4
		else
			if not yu.superaura
				color = SKINCOLOR_SAYELLOWAURA
			else
				color = SKINCOLOR_SUPERSKY2
			end
		end
		return color
	elseif yu.customtrail and not G_GametypeHasTeams()
		color = yu.customtrail	
		return color
	else
		color = s.color --Default
		if careaboutyu and yu.lsacharged
			color = SKINCOLOR_CORNFLOWER
		elseif ((s.color >= SKINCOLOR_SA2SONIC) and (s.color <= SKINCOLOR_DARKNIGHT))
		or ((s.color >= SKINCOLOR_CERULEAN) and (s.color <= SKINCOLOR_COBALT))
			color = SKINCOLOR_SABLUETRAIL
		elseif ((s.color >= SKINCOLOR_CARBON) and (s.color <= SKINCOLOR_BLACK)) or (s.color == SKINCOLOR_GOLD)
			color = SKINCOLOR_SAYELLOWAURA
		end
		return color
	end
end)

--SA2-style jump trail.
--OG SA2 has 3 big auras that all increasingly lag behind Sonic a little. We have 1 aura that stays on him, and 5 slowly shrinking ones.

rawset(_G, "YuJumpTrail", function(p, s, yu)
	if (yu.bouncestate and (s.state != S_PLAY_FALL))
	or p.powers[pw_carry]
	or (yu.noaura and (p.pflags & PF_JUMPED))
	return
	end
	if p.mo
	
	local color = YuAuraColor(s, nil, yu, true)
	local blendmode = AST_TRANSLUCENT		
	if color == SKINCOLOR_SABLUETRAIL or p.powers[pw_super]
	or yu.customtrailshiny or yu.lsacharged
		blendmode = AST_ADD
	end

			local jumptrail = P_SpawnMobjFromMobj(s, 0, 0, s.momz, MT_YUJUMPTRAIL)
			jumptrail.scale = s.scale*25/17
			jumptrail.tracer = s						
			jumptrail.scalespeed = $+6500
			jumptrail.destscale = jumptrail.scalespeed+1
			jumptrail.sprite = SPR_YTK7
			jumptrail.frame = A|FF_FULLBRIGHT|TR_TRANS70
			jumptrail.color = color			
			jumptrail.blendmode = blendmode 
				
			if yu.superaura and yu.supersonic
				P_TeleportMove(jumptrail, jumptrail.x-(s.momx/-2), jumptrail.y-(s.momy/-2), jumptrail.z)
			end
				--Now the rest. The jumptrail's more like spaced out orbs than a real "trail"
				
				for d = 13,38,5
				
						if d == 13
							jumptrail = P_SpawnMobj(s.x, s.y, s.z-(6*s.scale)-(s.momz/2), MT_YUJUMPTRAIL)
						elseif d == 23
							jumptrail = P_SpawnMobj(s.x-(s.momx/30*25), s.y-(s.momy/30*25), s.z-(2*s.scale)-s.momz-((s.momz/25)*d), MT_YUJUMPTRAIL)
						else
							jumptrail = P_SpawnMobj(s.x-(s.momx/30*d), s.y-(s.momy/30*d), s.z-(2*s.scale)-s.momz-((s.momz/25)*d), MT_YUJUMPTRAIL)
						end
						
						if yu.superaura and yu.supersonic
							P_TeleportMove(jumptrail, jumptrail.x-(s.momx/-2), jumptrail.y-(s.momy/-2), jumptrail.z)
						end

						if d == 13
							jumptrail.scale = s.scale*25/17
						elseif d == 18
							jumptrail.scale = s.scale*50/41
						else	
						
							if d == 23
								jumptrail.scale = s.scale*25/23
							elseif d == 28
								jumptrail.scale = s.scale*25/27							
							else
								jumptrail.scale = s.scale*29/d											
							end	
							jumptrail.sprite = SPR_YTK7
							jumptrail.frame = A|TR_TRANS90
						end
						
						jumptrail.scalespeed = $+6500
						jumptrail.destscale = jumptrail.scalespeed+1	
						jumptrail.color = color
						jumptrail.z = YuFlipZ(s, jumptrail)
						jumptrail.blendmode = blendmode
						if (p == displayplayer) and not CV_FindVar("chasecam").value
						jumptrail.flags2 = $|MF2_DONTDRAW
						end
				end
	end
end)

--Frameskip and footblur. Only works with walking, running and rolling frames!

rawset(_G, "YuFrameSkip", function(p, s, yu, treshold)
if p.powers[pw_super] --Never with Super Sonic!
or (s.flags2 & MF2_DONTDRAW)
return end

local nextframe = ((s.frame & ~FF_FULLBRIGHT & ~FF_PAPERSPRITE)+1) 
local currentframe = (nextframe-1)

	if (nextframe == I) or (nextframe >= J) --Too far! Go back to the first frame!
		nextframe = A
		currentframe = H
	end
 	if (nextframe < A) 
		nextframe = H
		currentframe = G
	end	
	if (currentframe < A)
	currentframe = H
	end
	
	if (p.speed > treshold)
		if (s.tics > 1) --Go as fast as you can!
			s.tics = 1
		else --Okay, time to get to work!	
			--Foot Blur!
			local tmomz = (s.z-yu.lastz) --For slopes.
				if (tmomz > 0)
					tmomz = 0
				end
				local ghs = P_SpawnMobjFromMobj(s, 0, 0, tmomz-3*s.scale, MT_YUTHOK)
				ghs.angle = p.drawangle
				ghs.eflags = s.eflags
				ghs.skin = s.skin
				ghs.color = s.color
				ghs.tracer = s
				ghs.sprite = SPR_YUZL
				ghs.colorized = s.colorized	
				ghs.rollangle = s.rollangle
				if (leveltime % 2 == 0)
					ghs.frame = currentframe|TR_TRANS30
					ghs.spritexscale = FRACUNIT+11000
					ghs.spriteyoffset = -1*FRACUNIT
				elseif (leveltime % 3 == 0)
					ghs.frame = currentframe|TR_TRANS40
					ghs.spritexscale = FRACUNIT+18000
					ghs.spriteyoffset = -4*FRACUNIT
				else
					ghs.frame = currentframe|TR_TRANS60 --Try TR_TRANS80 or TR_TRANS90 if you wanna mess with the transparency.
					ghs.spritexscale = FRACUNIT+4000
				end
				ghs.tics = 2
				P_TeleportMove(ghs, s.x+s.momx, s.y+s.momy, s.z+tmomz)
				
			--When running superfast, move in a more stable manner!
			
				if (s.state == S_PLAY_RUN)
				local nframe = (s.frame & ~FF_FULLBRIGHT & ~FF_PAPERSPRITE)
					if (nframe == A) or (nframe == E) --Remember to set the spriteyoffset for the NEXT frame, not the current.
					s.spriteyoffset = -1*FRACUNIT
					ghs.frame = currentframe|TR_TRANS10
					elseif (nframe == B) or (nframe == F)
					s.spriteyoffset = -3*FRACUNIT
					elseif (nframe == C) or (nframe == G)
					s.spriteyoffset = -2*FRACUNIT 
					elseif (nframe == D) or (nframe == H)
					s.spriteyoffset = FRACUNIT
					end
					yu.resetspriteoffset = 2
				end
		end
	end
end)

--Adventure-style spin trail.

rawset(_G, "YuSpinTrail", function(p, s, yu, blendforce)
	if (p.powers[pw_carry] == CR_NIGHTSMODE)
		blendforce = AST_ADD
	elseif (p.speed < 16*s.scale)
	and ((s.momz > -3*s.scale) and (s.momz < 3*s.scale)) --too slow. Don't spawn
	
	or p.powers[pw_carry] == CR_ZOOMTUBE --this often blinds our player.
	or p.realmo != s
		return
	end
	if yu.alreadytrailed --Once per frame. This'll get real laggy otherwise.
		return
	else
		yu.alreadytrailed = true 
	end	
	
local renderer = 1
	if p == displayplayer --This part doesn't need to sync.
		renderer = CV_FindVar("renderer").value
	end
local spintrailcolor = YuAuraColor(s, nil, yu, true)			
local blendmode = AST_TRANSLUCENT

	if blendforce
		blendmode = blendforce
	elseif (spintrailcolor >= SKINCOLOR_SABLUETRAIL and spintrailcolor <= SKINCOLOR_YULSA) or p.powers[pw_super]
	or yu.customtrailshiny or yu.lsacharged
		blendmode = AST_ADD
	end
	--Setup done.

	if not yu.bouncestate --Looks like Wario ended up liking this version more.
	
	/*	if yu.lsaattack and yu.lsahoming	
		local jumptrail
			jumptrail = P_SpawnMobjFromMobj(s, 0, 0, s.momz, MT_YUJUMPTRAIL)
			jumptrail.scale = s.scale*50/34
			jumptrail.tracer = s					
			jumptrail.scalespeed = $+6500
			jumptrail.destscale = jumptrail.scalespeed+1
			jumptrail.sprite = SPR_YTK8
			jumptrail.frame = A|TR_TRANS70
			jumptrail.spriteyoffset = -4*FRACUNIT
			jumptrail.color = spintrailcolor
			jumptrail.blendmode = blendmode
			A_CapeChase(jumptrail, 1,0)
		end */
	
		--Now to calculate for the actual spintrail.
		
		local density = 16*FRACUNIT --Software is less powerful and can't handle as many sprites.
		
		if ((p == displayplayer) and renderer == 2) --Since OpenGL is more accurate, it benefits more from a higher density as well.
		density = 6*FRACUNIT
			--The messy burst aura ahead of the pack, hovering over your spinball
			if (p.pflags & PF_SPINNING) and not p.powers[pw_carry] and not yu.lsadash
				DoSpinRev(p, s, yu, spintrailcolor, blendmode)
			end		
			if (spintrailcolor >= SKINCOLOR_SABLUETRAIL and spintrailcolor <= SKINCOLOR_SAREDTRAIL)
			or (spintrailcolor >= SKINCOLOR_RUBY and spintrailcolor <= SKINCOLOR_CRIMSON) --Aren't you special?
			density = 4*FRACUNIT
			end
		end

		local dist = FixedDiv(FixedMul((R_PointToDist2(0, 0, R_PointToDist2(0, 0, s.momx, s.momy), (s.z-yu.lastz)) / density), FRACUNIT), s.scale)
		
		if dist > 180 --Even if we get this fast through xmom or whatever, we don't need 180+, c'mon.
			dist = 180
		elseif dist <= 0
			dist = 1
		end
		
		local xdistog = (s.momx/dist)
		local ydistog = (s.momy/dist)
		local zdistog = (s.z-yu.lastz)
		
		if zdistog == 0
		zdistog = 1
		end
		zdistog = $/dist
		
		local xdist = 0
		local ydist = 0
		local zdist = 0
		
		--Keep counting down by -1 until we reach 0. Because Sonic needs 5*FRACUNIT to spawn these, it's impossible to get a "divide by 0" error.
			for i = dist,1,-1
				if s.scale != FRACUNIT
					xdist = FixedDiv(FixedMul((s.momx/dist)*i, FRACUNIT), s.scale)
					ydist = FixedDiv(FixedMul((s.momy/dist)*i, FRACUNIT), s.scale)
					zdist = FixedDiv(FixedMul(((s.z-yu.lastz)/dist)*i, FRACUNIT), s.scale)
				else
					xdist = xdistog*i
					ydist = ydistog*i
					zdist = zdistog*i			
				end
				local spintrail = P_SpawnMobjFromMobj(s, xdist, ydist, zdist, MT_YUSPINTRAIL)	
				spintrail.scale = s.scale*10/9
				spintrail.color = spintrailcolor
				spintrail.blendmode = blendmode
				spintrail.sprite = SPR_YTK8
					if renderer == 2 or (p.powers[pw_carry] == CR_NIGHTSMODE) --2 is OpenGL.
						spintrail.frame = A|TR_TRANS90 & ~FF_FULLBRIGHT
					else
						spintrail.frame = A|TR_TRANS70 & ~FF_FULLBRIGHT
					end
					
					if yu.lsahoming or yu.lsadash--Last longer today with these sparkling LSA pills!
					spintrail.tics = 30
					spintrail.fuse = 30
					spintrail.frame = $|FF_FULLBRIGHT
						if yu.lsadash
						spintrail.scale = $*7/6
						spintrail.scalespeed = $/2
						spintrail.destscale = spintrail.scalespeed+1
						P_SetObjectMomZ(spintrail, spintrail.scalespeed*11, true)
						end
						if yu.attackpriority
							spintrail.color = SKINCOLOR_RUBY
						elseif yu.supersonic
							spintrail.color = spintrailcolor
						else
							spintrail.color = SKINCOLOR_SABLUETRAIL
						end
						spintrail.blendmode = AST_ADD
					elseif yu.customtrailtaper
						spintrail.scalespeed = $*10/6
						spintrail.scale = ($*7/6)-(spintrail.scalespeed/i)
						spintrail.destscale = spintrail.scalespeed+1
						P_SetObjectMomZ(spintrail, spintrail.scalespeed*11, true)
					end
					if (i < 3) and (p == displayplayer) and not CV_FindVar("chasecam").value
				//	or (renderer != 2 and density == 2*FRACUNIT and ((i % 2 == 0) or (i % 3 == 0)))
					spintrail.flags2 = $|MF2_DONTDRAW
					end
			end
		
	else --Bounce version!
			
				local jumptrail
				jumptrail = P_SpawnMobjFromMobj(s, 0, 0, s.momz, MT_YUJUMPTRAIL)
				jumptrail.scale = s.scale*50/34
				jumptrail.tracer = s					
				jumptrail.scalespeed = $+6500
				jumptrail.destscale = jumptrail.scalespeed+1
				jumptrail.sprite = SPR_YTK7
				jumptrail.frame = A|FF_FULLBRIGHT|TR_TRANS70
				jumptrail.color = spintrailcolor
				jumptrail.blendmode = blendmode			
			
				if yu.supersonic
					if yu.lsadash
						spintrailcolor = P_RandomRange(SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERGOLD5)
					elseif yu.hypersonic
						spintrailcolor = P_RandomRange(SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERPURPLE5)
					end
				end
						
				for d = 0,16

				local spintrail = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUSPINTRAIL)
				spintrail.scale = s.scale*10/9
				spintrail.color = spintrailcolor
				spintrail.blendmode = blendmode
				spintrail.sprite = SPR_YTK7
					if (s.eflags & MFE_VERTICALFLIP)
						spintrail.eflags = $|MFE_VERTICALFLIP
						spintrail.spriteyoffset = -15*FRACUNIT
					end
							
					if (d == 0) --Just assume divide by 0 is 0, geez. Quit bitching, game...
						P_TeleportMove(spintrail, s.x+s.momx/3, s.y+s.momy/3, s.z-s.momz-3*s.scale)
					elseif yu.bouncestate
						P_TeleportMove(spintrail, s.x-(s.momx/d), s.y-(s.momy/d), (s.z-(s.momz/d))-3*s.scale)
					else
						P_TeleportMove(spintrail, FixedMul( (s.scale-(6535*d)), s.x)+FixedMul((6535*d), s.x-s.momx), FixedMul( (s.scale-(6535*d)), s.y)+FixedMul((6535*d), s.y-s.momy), (s.z-(s.momz/d))-3*s.scale)
					end
						
					if renderer == 2 --2 is OpenGL.
						spintrail.frame = A|TR_TRANS90
					else
						spintrail.frame = A|TR_TRANS70
					end

					if yu.bouncestate
						spintrail.scalespeed = $*2
						spintrail.destscale = spintrail.scalespeed+1
					end
					if yu.lsahoming or yu.lsadash --Last longer today with these sparkling LSA pills!
						spintrail.tics = 30
						spintrail.fuse = 30
						spintrail.frame = $|FF_FULLBRIGHT
						if yu.lsadash
							spintrail.scale = $*5/4
							spintrail.scalespeed = $/2
							spintrail.destscale = spintrail.scalespeed+1
						end
					end
				end
	end
end)

--Spawn SA2-esque wind lines behind Sonic! Function edited from SMSreborn.

rawset(_G, "YuWindSpawn", function(p, s, yu)
if (p.speed < 41*s.scale)
return
end
	local tmomx = (s.x-yu.lastx)
	local tmomy = (s.y-yu.lasty) 
	local tmomz = (s.z-yu.lastz) --SRB2's mom values won't help me here.
	for d = -1,1,2			
			local ghs = P_SpawnMobj(s.x+(tmomx/2)+FixedMul((P_RandomRange(9, 35)*s.scale*d), cos(s.angle+ANGLE_90)), s.y+(tmomy/2)+FixedMul((P_RandomRange(9, 35)*s.scale*d), sin(s.angle+ANGLE_90)), s.z+tmomz+(P_RandomRange(1, 58)*P_MobjFlip(s))*s.scale, MT_YUWINDLINE)			
			ghs.scale = s.scale
			ghs.eflags = s.eflags
			ghs.angle = R_PointToAngle2(s.x, s.y, (s.x+s.momx), (s.y+s.momy))-((ANG2*3)*d)
			ghs.momx = tmomx/4 ghs.momy = tmomy/4 ghs.momz = tmomz-(tmomz/2)			
			if ((s.momz*P_MobjFlip(s)) < -4*s.scale)
				P_Thrust(ghs, s.angle+ANGLE_90, 1*s.scale*d)
			else
				P_Thrust(ghs, s.angle+ANGLE_90, 3*s.scale*d)
			end
			ghs.flags = $|MF_SCENERY
						
			if (s.eflags & MFE_UNDERWATER)
				ghs.fuse = 7
				if leveltime % 2 == 0
				ghs.state = S_MEDIUMBUBBLE
				else
				ghs.state = S_SMALLBUBBLE
				end
			end
			if s.eflags & MFE_VERTICALFLIP
			ghs.spriteyoffset = -46*FRACUNIT
			end
			if yu.superaura and yu.supersonic
			ghs.blendmode = AST_ADD
			ghs.colorized = true
			ghs.color = SKINCOLOR_BLUE
			end
	 end
end)

--Adjust hats for SA-Sonic!

rawset(_G, "YuHatAdjust", function(p, s, yu, t)
if not t.valid
return
end
			local def = s.spriteyoffset+18*FRACUNIT
				if yu.supersonic
					def = s.spriteyoffset+29*FRACUNIT
				end
				t.spriteyscale = s.spriteyscale
				t.spritexscale = s.spritexscale
				t.rollangle = s.rollangle
				if p.panim == PA_ROLL
					t.spriteyoffset = s.spriteyoffset-12*FRACUNIT
				elseif p.panim == PA_WALK
					if not yu.supersonic
					t.spriteyoffset = def+3*FRACUNIT
					else
					t.spriteyoffset = def-3*FRACUNIT
					end
				elseif p.panim == PA_RUN and yu.supersonic or p.panim == PA_PAIN or p.panim == PA_RIDE
					t.spriteyoffset = def-14*FRACUNIT
				elseif s.state == S_PLAY_DEAD
					t.spriteyoffset = s.spriteyoffset-30*FRACUNIT
				else
					t.spriteyoffset = def
				end
end)

--Bit excessive, making a simplified peelout-carry code just for some revenge against Pointy.

rawset(_G, "YuTakeOverPeelout", function(p, s, yu, tp, t)
		if t and t.valid	
			t.state = S_PLAY_PAIN
			tp.powers[pw_carry] = CR_GENERIC
			tp.drawangle = p.drawangle+ANGLE_180
			P_TeleportMove(t,
				s.x + P_ReturnThrustX(s, p.drawangle, -s.radius-t.radius),
				s.y + P_ReturnThrustY(s, p.drawangle, -s.radius-t.radius),
				s.z + (s.eflags & MFE_VERTICALFLIP and s.height-t.height or 0))
			tp.pflags = $|PF_STASIS & ~PF_SPINNING & ~PF_JUMPED
			t.momx = s.momx t.momy = s.momy t.momz = s.momz
			t.z = s.z+P_MobjFlip(t)

			if P_IsObjectOnGround(s) --Drag that bad-touch jerk
				t.rollangle = ANGLE_180+(P_RandomRange(-30,30)*ANG1)
				if leveltime % 6 == 0
					S_StartSoundAtVolume(t, sfx_cdfm42, 55)
					S_StartSoundAtVolume(t, sfx_s3k5d, 55)
				end
				P_YuQuake(tp, 8*FRACUNIT, 1)
				P_YuQuake(p, 5*FRACUNIT, 1)
				local ghs = P_SpawnMobjFromMobj(t, 0, 0, 0, MT_SPINDUST)
				P_InstaThrust(ghs, ANGLE_45*P_RandomRange(1,8), 10*t.scale)
				ghs.scale = t.scale
				ghs.destscale = $*99
				ghs.tics = 1
				ghs.color = SKINCOLOR_BEIGE
				ghs.colorized = true
			else
				t.rollangle = 0
			end
		
		--Cancel conditions
			local cancel = false
				if (yu.brakeanim > 4) or (yu.farthok > 4)
				or (tp.cmd.buttons & BT_JUMP)	
					P_SetObjectMomZ(t, 12*FRACUNIT, true)
					t.momx = 2*s.momx
					t.momy = 2*s.momy
					tp.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING
					t.state = S_PLAY_JUMP
					S_StartSound(t, sfx_s3k51)
					S_StartSound(s, sfx_mswing)
					cancel = true
				elseif (p.speed < 32*s.scale)
				or p.powers[pw_carry]
					P_DoPlayerPain(tp, s, s)
					tp.drawangle = p.drawangle + ANGLE_180
					t.momx = 3*s.momx/4
					t.momy = 3*s.momy/4
					cancel = true
				end
				if cancel
					if t and t.valid
					tp.powers[pw_carry] = 0
					t.rollangle = 0
					t.tracer = nil
					end
					yu.pointytakeover = nil
					return
				end
		else
			yu.pointytakeover = nil
			return	
		end
end)

--Santa Sonic is in town to give everyone gifts!

local function YuSetSpawn(p,s,yu,ghs)
	if ghs and ghs.valid
	local donoclip = false
	local rngang = P_RandomRange(1,359)*ANG1
	
		if not (ghs.flags & MF_NOCLIPTHING)
		donoclip = true
		ghs.flags = $|MF_NOCLIPTHING
		end
		
		for d = 1,16
			if ghs and ghs.valid and P_TryMove(ghs, ghs.x+FixedMul(70*s.scale, cos(rngang+(ANG20*d)) ), ghs.y+FixedMul(70*s.scale, sin (rngang+(ANG20*d)) ), true)
				if donoclip
				ghs.flags = $ & ~MF_NOCLIPTHING
				end
			return true
			end
		end
	end
	return false
end

rawset(_G, "YuSantaSonic", function(p, s, yu)

	if yu.endlvl or p.exiting --Stage exit? No gifts now!
		return false
	end
			local gifted = false
			local giftedname = nil
			local amountofrings = true
			
					for z in players.iterate
								if (z.mo and z.mo.valid and z.mo ~= s) and (FixedHypot(z.mo.x-s.x, z.mo.y-s.y) <= 500*FRACUNIT)
								
										if z.mo.skin == "samus" or z.mo.skin == "basesamus"	--Give items!		
										
											local ghs = P_SpawnMobj(s.x, s.y, s.z, P_RandomRange(MT_BMPKU, MT_SATK))
												for d = 1,8
												local st = P_SpawnMobjFromMobj(ghs,0,0,0, MT_THOK)
												YuSetSpawn(p,s,yu,st)
												st.state = S_IVSP
												st.fuse = 70
												st.scale = $*2
												P_InstaThrust(st, s.angle+(ANGLE_45*d), 18*FRACUNIT)
												end
											CONS_Printf(z, "\x82"+p.name+"\x80 offered you an item!")
											gifted = true

										elseif z.mo.skin == "duke" --Give weaponry!		
											local ghs = P_SpawnMobj(s.x, s.y, s.z, P_RandomRange(MT_PISTOL, MT_SHOTGUN))
											YuSetSpawn(p,s,yu,ghs)
												for d = 1,8
												local st = P_SpawnMobjFromMobj(ghs,0,0,0, MT_THOK)
												st.state = S_IVSP
												st.fuse = 70
												st.scale = $*2
												P_InstaThrust(st, s.angle+(ANGLE_45*d), 18*FRACUNIT)
												end
											CONS_Printf(z, "\x82"+p.name+"\x80 brought you some toys! Wait, why did he have these?!")	
											gifted = true
										
										elseif z.mo.skin == "nasya" --Gift shield!
										
											local fireflower = 0
											if z.powers[pw_shield] & SH_FIREFLOWER
											fireflower = SH_FIREFLOWER
											end
											local shield = (z.powers[pw_shield] & SH_NOSTACK)
											if (shield <= 1)
											or shield == SH_PINK
											
											local rngtable = {SH_WHIRLWIND,SH_ARMAGEDDON,SH_ELEMENTAL, SH_ATTRACT, SH_FLAMEAURA, SH_BUBBLEWRAP,SH_THUNDERCOIN, (SH_FORCE|1)}
											
												z.powers[pw_shield] = (rngtable[P_RandomRange(1,11)])|fireflower
												P_SpawnShieldOrb(z)
												CONS_Printf(z, "\x82"+p.name+"\x80 tossed you a shield!")	
												gifted = true
											end
											
											for d = 1,8
												local st = P_SpawnMobjFromMobj(z.mo,0,0,0, MT_THOK)
												st.state = S_IVSP
												st.fuse = 70
												st.scale = $*2
												P_InstaThrust(st, s.angle+(ANGLE_45*d), 18*FRACUNIT)
											end
											
										elseif z.mo.skin == "wido" or z.mo.skin == "sms" --Gift speeeeeeeeeeeed!
										
											if not z.powers[pw_sneakers]
											and not z.powers[pw_super]
											and not z.hypermysticsonic
											local ghs = P_SpawnMobjFromMobj(z.mo, 0, 0, 0, MT_SNEAKERS_BOX)
											ghs.flags2 = $|MF2_DONTDRAW
											ghs.flags = $|MF_NOCLIPTHING
											P_DamageMobj(ghs, z.mo, z.mo)
											
												if ghs and ghs.valid
												ghs.flags2 = $|MF2_DONTDRAW
												ghs.flags = $|MF_NOCLIPTHING|MF_NOCLIP & ~MF_SHOOTABLE
												S_StopSound(ghs)
												ghs.state = S_NULL
												gifted = true
												CONS_Printf(z, "\x82"+p.name+"\x80 brought you some coffee!")	
												end
												for d = 1,8
												local st = P_SpawnMobjFromMobj(z.mo,0,0,0, MT_THOK)
												st.state = S_IVSP
												st.fuse = 70
												st.scale = $*2
												P_InstaThrust(st, s.angle+(ANGLE_45*d), 18*FRACUNIT)
												end	
											end									
											
										elseif (z.mo.skin == "yoshi" or z.mo.skin == "joshi")
										and z.yosheggs != nil --Give eggs!
											
											if (z.yosheggs < 8)
											local eggstogive = (8-z.yosheggs)
												for i = 1,eggstogive
												z.yosheggs = $+1
												local ghs = P_SpawnMobjFromMobj(z.mo, 0, 0, 0, MT_FOLLOWEGG)
												ghs.threshold = z.yosheggs
												ghs.tracer = z.mo
												ghs.color = P_RandomRange(1,#skincolors-1)
										
												YuSetSpawn(p,s,yu,ghs)
												
													for d = 1,4
													local st = P_SpawnMobjFromMobj(ghs,0,0,0, MT_THOK)
													st.state = S_IVSP
													st.fuse = 35
													st.scale = $*2
													P_InstaThrust(st, (ANGLE_90*d), 18*FRACUNIT)
													end
												end
												gifted = true
												CONS_Printf(z, "\x82"+p.name+"\x80 gifted you some eggs! Don't ask where they got them!")
											end
											
										elseif z.mo.skin == "skip" --Give scrap!
										
											for i = 1,9
												local ghs = P_SpawnMobjFromMobj(s,0,0,0,MT_SKIPMETALSCRAP)
												ghs.target = z.mo
												ghs.threshold = 2
												ghs.shadowscale = FRACUNIT/2
												ghs.reactiontime = ghs.scale
												ghs.color = SKINCOLOR_CLOUDY
												ghs.cusval = ghs.color
												ghs.colorized = true
												P_SetObjectMomZ(ghs, FRACUNIT*10, true)
												P_InstaThrust(ghs, FixedAngle(360*P_RandomFixed()), 15*P_RandomFixed())
											end							
											gifted = true
											CONS_Printf(z, "\x82"+p.name+"\x80 threw you some scrap!")	
											
										elseif z.mo.skin == "modernsonic" and z.boostmeter ~= nil --Give sparklies!
										
											if z.boostmeter < 110
											z.boostmeter = 110
											end
											for i = 1,15
												local boostenergy = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_BOOSTENERGY)
												boostenergy.target = z.mo
												boostenergy.boostchasetimer = 225
												boostenergy.color = SKINCOLOR_SKY
												boostenergy.momx = ((P_RandomRange(-10, 10)*FRACUNIT)*P_MobjFlip(boostenergy.target))
												boostenergy.momy = ((P_RandomRange(-10, 10)*FRACUNIT)*P_MobjFlip(boostenergy.target))
												boostenergy.momz = ((P_RandomRange(10, 15)*FRACUNIT)*P_MobjFlip(boostenergy.target)+boostenergy.target.momz)
												boostenergy.scale = boostenergy.target.scale*2
												boostenergy.frame = A|FF_TRANS80|FF_FULLBRIGHT
												if not boostenergy.target.player.boostenergy then boostenergy.target.player.boostenergy = {} end
												table.insert(boostenergy.target.player.boostenergy,boostenergy)
											end
											gifted = true
											CONS_Printf(z, "\x82"+p.name+"\x80 gave you a rush!")	
											
										elseif z.mo.skin == "shadow" and z.shadow ~= nil and z.shadow.snaps ~= nil --Give bike!
										
											local ghs = P_SpawnMobjFromMobj(s, 50*s.scale*P_RandomRange(-2,2), 50*s.scale*P_RandomRange(-2,2), 0, MT_SHADOW_BOX)
											if ghs and ghs.valid
												YuSetSpawn(p,s,yu,ghs)
												gifted = true
												CONS_Printf(z, "\x82"+p.name+"\x80 got you an awesome bike!")	
											end
											for d = 1,8
												local st = P_SpawnMobjFromMobj(ghs,0,0,0, MT_THOK)
												st.state = S_IVSP
												st.fuse = 70
												st.scale = $*2
												P_InstaThrust(st, s.angle+(ANGLE_45*d), 18*FRACUNIT)
											end
											
										elseif z.mo.skin == "jet" and z.air ~= nil --Give...air.
										
											for d = 1,16
												local st = P_SpawnMobjFromMobj(z.mo, 0,0,0, MT_EXPLODE)
												st.scale = $*3
												P_SetObjectMomZ(st, 6*FRACUNIT)
												P_InstaThrust(st, ((ANG1*22)*d), 6*FRACUNIT)	
											end
											S_StartSound(z.mo, sfx_gasp)
											S_StartSound(z.mo, sfx_wdjump)
											S_StartSound(z.mo, sfx_wdjump)
											z.air = 100
											gifted = true
											CONS_Printf(z, "\x82"+p.name+"\x80 tossed you a scuba tank! Hey, it'll work!")							
											--Why not. For the meme.
											if z.powers[pw_underwater]
												if (z.powers[pw_underwater] < 440)
													P_RestoreMusic(z)
												end
												if (z.powers[pw_underwater] < 1200)
													z.powers[pw_underwater] = 1200
												end
											end
											if z.powers[pw_spacetime] and (z.powers[pw_spacetime] < 450)
												z.powers[pw_spacetime] = 450
											end											

											
										elseif z.mo.skin == "mario" and z.mariospinsfx ~= nil --Give powerups!
											local rngtable = {MT_FLAMEAURA_BOX,MT_BUBBLEWRAP_BOX,MT_THUNDERCOIN_BOX, MT_PITY_BOX, MT_ATTRACT_BOX, MT_FORCE_BOX,MT_ARMAGEDDON_BOX, MT_WHIRLWIND_BOX, MT_ELEMENTAL_BOX, MT_SNEAKERS_BOX, MT_INVULN_BOX}
											local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, rngtable[P_RandomRange(1,11)])
											ghs.flags2 = $|MF2_DONTDRAW
											ghs.flags = $|MF_NOCLIPTHING
											YuSetSpawn(p,s,yu,ghs)
											P_DamageMobj(ghs, z.mo, z.mo)
											if ghs and ghs.valid
												ghs.flags2 = $|MF2_DONTDRAW
												ghs.flags = $|MF_NOCLIPTHING|MF_NOCLIP & ~MF_SHOOTABLE
												S_StopSound(ghs)
												ghs.state = S_NULL
												gifted = true
												CONS_Printf(z, "\x82"+p.name+"\x80 found this powerup for you!")	
											end
										end
										if z.powers[pw_super] or z.hypermysticsonic --Give rings!
											if amountofrings
												for d = 1,16
												local st = P_SpawnMobjFromMobj(s, 0,0,s.height*2, MT_FLINGRING)
												st.fuse = 250
												P_SetObjectMomZ(st, -2*FRACUNIT)
												P_InstaThrust(st, ((ANG1*22)*d), 6*FRACUNIT)
													if p.powers[pw_nocontrol] < 35
													p.powers[pw_nocontrol] = 35
													end
												end
												gifted = true
												amountofrings = nil
												CONS_Printf(z, "\x82"+p.name+"\x80 offers you their energy!")	
											end
										end
								end
					end
					
			if gifted
				for d = 1,8
				local ghs = P_SpawnMobjFromMobj(s,0,0,0, MT_THOK)
				ghs.state = S_IVSP
				ghs.fuse = 70
				P_InstaThrust(ghs, s.angle+(ANGLE_45*d), 18*FRACUNIT)
				end
			S_StartSound(s, sfx_hidden)
			yu.gavepowerup = true
			end
			amountofrings = nil
end)


--Make stuff shiny. Doesn't need to come from a player, btw.

rawset(_G, "YuGoldenShine", function(p, s, yu, color, style)
local renderer = 2
if (p == consoleplayer)
	renderer = CV_FindVar("renderer").value
	if (p != displayplayer)
	end	
end
	for d = 1,style
	local shine = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_YUTHOK)
	shine.sprite = SPR_YTK6  
	shine.frame = A|TR_TRANS90|FF_FULLBRIGHT
		if style == 3
			if d == 1
			shine.scale = (s.scale*5)/7
			else
				if renderer == 1 --Software can't handle this.
				shine.flags2 = $|MF2_DONTDRAW
				end
				if d == 2
				shine.scale = (s.scale*5)/8
				else			
				shine.scale = (s.scale*5)/12
				end
			end
		else
		shine.scale = s.scale
		end
	shine.tics = 2
	shine.momx = s.momx
	shine.momy = s.momy
	shine.momz = s.momz
	shine.blendmode = AST_ADD
	if leveltime % 2 == 0
		shine.scalespeed = $-500
	else
		shine.scalespeed = $+1000
	end
	shine.destscale = 9
	shine.flags = MF_NOCLIP|MF_NOCLIPHEIGHT
	
		if color --Unique color?
			shine.color = color
			shine.colorized = true
		end
		if style == 3 --Adventure style sparkle lines!
			if d == 3
			shine.sprite = SPR_YTK6 
			shine.frame = A|TR_TRANS70|FF_FULLBRIGHT
			end
			
			if (p ~= displayplayer) and (leveltime % 5 ~= 0)//renderer == 1 and 
			return --Don't display effect of others if you're on software. Yes, software sucks that badly, it's ridiculous.
			end
			local ghs
			local ghs2			
			local angle = YuLocalRandom(0,359,s)*ANG1
			
				if not yu.invincibilityline --Vertical


					if not YuLocalRandom(0,1,s)			
					ghs = P_SpawnMobj(s.x+s.momx, s.y+s.momy, s.z+s.momz+(s.height*4/3), MT_YUTHOKDISP)				
					ghs.ivheight = (s.height*10/YuLocalRandom(5,8,s))
					ghs.ivthrust = YuLocalRandom(3,11,s)*s.scale
					P_SetObjectMomZ(ghs, ghs.ivthrust)
					end
				
				yu.invincibilityline = 1
				
				elseif yu.invincibilityline == 1 --Diagonal
				
				ghs = P_SpawnMobj(s.x+s.momx, s.y+s.momy, s.z+s.momz+(s.height*2/3), MT_YUTHOKDISP)			
				ghs.ivheight = (s.height/2)			
				ghs.ivthrust = YuLocalRandom(10,13,s)*s.scale				
				P_InstaThrust(ghs, angle, ghs.ivthrust)
				P_SetObjectMomZ(ghs, ghs.ivthrust)
					if renderer == 1 and (leveltime % 2 == 0) --Software can't handle that
					ghs.flags2 = $|MF2_DONTDRAW
					end
					
					if not P_IsObjectOnGround(s) 
					ghs2 = P_SpawnMobj(s.x+s.momx, s.y+s.momy, s.z+s.momz, MT_YUTHOKDISP)			
					ghs2.ivheight = (s.height/-9)
					ghs2.ivthrust = YuLocalRandom(-10,-13,s)*s.scale
					ghs2.invertspark = true
					P_InstaThrust(ghs2, angle, ghs2.ivthrust)
					P_SetObjectMomZ(ghs2, ghs2.ivthrust)
						if renderer == 1 and (leveltime % 2 == 0) --Software can't handle this either.
						ghs2.flags2 = $|MF2_DONTDRAW
						end
					end
				
				yu.invincibilityline = 2
				
				else --Horizontal			
				
				ghs = P_SpawnMobj(s.x+s.momx, s.y+s.momy, s.z+s.momz+s.height/3, MT_YUTHOKDISP)			
				ghs.ivthrust = YuLocalRandom(30,35,s)*s.scale
				ghs.ivheight = (s.height*2/5)
				
				P_InstaThrust(ghs, angle, ghs.ivthrust)	
				yu.invincibilityline = 0		
				end

				if ghs and ghs.valid
				ghs.invthrustx = ghs.momx
				ghs.invthrusty = ghs.momy
				ghs.invthrustz = ghs.momz
				ghs.momx = s.momx ghs.momy = s.momy ghs.momz = s.momz
				ghs.scale = s.scale/11
				
				ghs.frame = $|FF_FULLBRIGHT|TR_TRANS30
				ghs.momx = $+s.momx ghs.momy = $+s.momy ghs.momz = $+s.momz+(s.scale*2*P_MobjFlip(s))
				ghs.yulsatarget = s
				ghs.invincibleaura = true
				ghs.tics = 7
				ghs.scalespeed = $/10
				ghs.color = color
				ghs.yulsanum = yu.invincibilityline+1
				ghs.blendmode = AST_ADD
				ghs.destscale = ghs.scalespeed+1
					if renderer == 1 and (leveltime % 2 == 0) --Software can't handle this one
					ghs.flags2 = $|MF2_DONTDRAW
					end
				end
				
				if ghs2 and ghs2.valid
				ghs2.invthrustx = ghs2.momx
				ghs2.invthrusty = ghs2.momy
				ghs2.invthrustz = ghs2.momz*-1
				ghs2.momx = s.momx ghs2.momy = s.momy ghs2.momz = s.momz
				ghs2.scale = s.scale/11
				
				ghs2.frame = $|FF_FULLBRIGHT|TR_TRANS30
				ghs2.momx = $+s.momx ghs2.momy = $+s.momy ghs2.momz = $+s.momz+(s.scale*2*P_MobjFlip(s))
				ghs2.yulsatarget = s
				ghs2.invincibleaura = true
				ghs2.tics = 7
				ghs2.scalespeed = $/10
				ghs2.color = color
				ghs2.yulsanum = yu.invincibilityline+1
				ghs2.blendmode = AST_ADD
				ghs2.destscale = ghs2.scalespeed+1
					if renderer == 1 and (leveltime % 2 == 0) --Software can't handle anything
					ghs2.flags2 = $|MF2_DONTDRAW
					end
				end
		end	
	end
		
end)

--Stop Lightdash related properties. Momentum stuff will have to be done manually still.

rawset(_G, "YuStopLSA", function(p, s, yu)
	yu.lsahoming = 0
		if s.target and yu.lsatarget and s.target == yu.lsatarget
		s.target = nil
		end
	yu.vertstylecharge = 0	
	yu.ldvertstyle = false	
	yu.lsatarget = nil
	yu.lsaattack = 0
	yu.lightdashing = false
	yu.lsaclosest = nil
	yu.lightdashtimer = 0
	yu.lsacheck = 0
	yu.lsatarget = nil
	yu.prevringx = nil yu.prevringy = nil yu.prevringz = nil
	if not ((p.cmd.buttons & BT_USE) and yu.startdash and yu.spin == 2 and (p.pflags & PF_STARTDASH))
	p.pflags = $ & ~PF_SPINNING	& ~PF_STARTDASH
	yu.startdash = 0
	end
end)


--MATH...MAAAAAAAAATHHHH.......groan. Yeah, if I was good at that, maybe. This only came to be out of trying random numbers 1000 times.
--I say yes way too casually to requests like "why not apply BOTH SA1 and SA2 LightSpeed fx for the lulz"

rawset(_G, "YuLSAglow", function(p, s, yu, momz, dist, glow, freq, postthink)
			
				--Setup
				if yu.lsaangle == nil or yu.lsaangle2 == nil
				yu.lsaangle = 90
				yu.lsaangle2 = yu.lsaangle*ANG1
				end
				
				if glow
				--Our glow pulses around us.
					if yu.lsaglow > 2000
					yu.lsaglowd = -1
					elseif yu.lsaglow < 970
					yu.lsaglowd = 1
					end
					yu.lsaglow = $+(970*yu.lsaglowd)
				
				--Spawn the encasing glow around Sonic's form.
					for d = 0,2			
					local ghs = P_SpawnMobjFromMobj(s, 0, 0, (s.scale*-8), MT_YUTHOKDISP)
					
						ghs.skin = "adventuresonic"
					
						if d != 0
							ghs.scale = s.scale+(((s.scale/7)*d+(yu.lsaglow*d)))
							if not ((ghs.spriteyscale-yu.lsaglow) < 1)
							ghs.spriteyscale = $-yu.lsaglow
							end
							ghs.spritexscale = FRACUNIT+yu.lsaglow
						end
						if (s.eflags & MFE_VERTICALFLIP)
							ghs.z = YuFlipZ(s, ghs)+(s.scale*8)
							P_SetObjectMomZ(ghs, ghs.scalespeed*100, true)
						end
						if p.ctfteam and p.ctfteam == 1 and G_GametypeHasTeams() or yu.attackpriority
						ghs.color = SKINCOLOR_RED --In CTF/teammatch, glow red instead of blue if you're on red team.
						else
						ghs.color = SKINCOLOR_YULSA
						end
						if p.powers[pw_super] and not p.ctfteam
						ghs.color = SKINCOLOR_SUPERSILVER1
						ghs.scalespeed = $*4
						ghs.blendmode = AST_ADD
						end
						ghs.colorized = true
						
						if postthink
							ghs.angle = p.drawangle
							ghs.tics = 1
							P_TeleportMove(ghs, s.x, s.y, s.z-((((s.scale*7)*d)-(ghs.scale-s.scale))*P_MobjFlip(s)))
							ghs.sprite = s.sprite
							ghs.rollangle = s.rollangle
							ghs.sprite2 = s.sprite2
							ghs.spriteyoffset = $+s.spriteyoffset
							ghs.spritexoffset = $+s.spritexoffset
							if d == 0
							ghs.frame = (s.frame & ~FF_TRANSMASK)|TR_TRANS40|FF_FULLBRIGHT
							else
							ghs.frame = (s.frame & ~FF_TRANSMASK)|(TR_TRANS40+(d*FRACUNIT))|FF_FULLBRIGHT
							end
						else
							ghs.tics = 2
							ghs.yulsatarget = s --This is your hedgehog.
							ghs.yulsanum = d --Remember what number you're assigned						
						end
				
					end
				end
				
				if yu.lsadash
				return
				end
				
				--Spawn Sonic's large glowing orbs of justice
				if (leveltime % freq == 0)
				
				/*	--Reverse angle everytime.
					if yu.lsaorbangle == ANGLE_180
					yu.lsaorbangle = 0
					else
					yu.lsaorbangle = ANGLE_180
					end */
				
				local ghs = P_SpawnMobj(s.x+FixedMul(dist, cos(yu.lsaangle2)), s.y+FixedMul(dist, sin(yu.lsaangle2)), s.z+(s.scale*8), MT_YULDORB)
					ghs.target = s
					ghs.tracer = s
					ghs.yuldmomz = momz
					ghs.yulddist = dist
						if momz == 1 and not p.powers[pw_super]
						ghs.scale = s.scale/7
						else
						ghs.scale = s.scale/4
						end
					ghs.blendmode = AST_ADD
					ghs.yuldangle = yu.lsaangle2
					ghs.tics = 45
						if (s.eflags & MFE_VERTICALFLIP)
						ghs.z = YuFlipZ(s, ghs)+(s.scale*8)
						end
					ghs.frame = K|FF_FULLBRIGHT|TR_TRANS20 & ~TR_TRANS50 & ~TR_TRANS60 & ~TR_TRANS40 & ~TR_TRANS30
					if p.powers[pw_super]
						if yu.hypersonic
						ghs.color = p.yuemeraldcolors2[yu.hypercolor]+4
						else
						ghs.color = s.color
						end
					else
					ghs.color = SKINCOLOR_SUPERSKY5
					end
				end
				
				--Keep the angle change at the end!
				if (yu.lsaangle > 358)
					yu.lsaangle = 0
				else
					yu.lsaangle = $+20
				end
end)

--Are we above a death pit?

rawset(_G, "YuCheckPit", function(p, s, yu, skip)
	if skip or not P_IsObjectOnGround(s)
		if P_PlayerTouchingSectorSpecial(p, 1, 7) or P_PlayerTouchingSectorSpecial(p, 1, 6)
			if s.subsector and s.subsector.sector
			and ( ((s.floorz == s.subsector.sector.floorheight) and not (s.eflags & MFE_VERTICALFLIP)) or ((s.eflags & MFE_VERTICALFLIP) and (s.ceilingz == s.subsector.sector.ceilingheight)) )
			return true
			elseif not s.subsector //Can't obtain info? Then assume it's a death pit
			return true
			end
		end
	end
	return false
end)

--Another lazy function.

rawset(_G, "YuCancelTricks", function(p, s, yu)
	yu.homingtrick = 0
	yu.lsatrick = nil
	s.rollangle = 0
	yu.chosentrick = 0
	yu.lsatrickrollang = 0
	yu.lsatrickanim = 0
	yu.advance2trail = 0
end)

--The beginning of the bounce attack!

rawset(_G, "YuStartBounce", function(p, s, yu)
if p.gotflag -- Not with the flag.
or yu.lsadash or yu.lsahoming or p.exiting
return end
		p.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING	
			if not ((s.eflags & MFE_UNDERWATER) and (s.eflags & MFE_GOOWATER))
				if (s.momz*P_MobjFlip(s) > -25*FRACUNIT)
				P_SetObjectMomZ(s, -35*FRACUNIT)
				else
				P_SetObjectMomZ(s, -10*FRACUNIT, true)
				end			
			else
				if (s.momz*P_MobjFlip(s) > -11*FRACUNIT)
				P_SetObjectMomZ(s, -16*FRACUNIT)
				else
				P_SetObjectMomZ(s, -5*FRACUNIT, true)
				end
			end
			if (yu.hypersonic or yu.mysticsuper) and (s.momz*P_MobjFlip(s) < 0)
			s.momz = $*2
			end
		YuCancelTricks(p, s, yu)
		
		if not yu.nobouncedrag
			s.momx = $*3/4
			s.momy = $*3/4
			yu.noairdrag = 0
			yu.superaura = 0
			yu.superaurabuild = 0
		elseif yu.nbdtarget and yu.nbdtarget.valid
			local t = yu.nbdtarget
			if (p.speed < 32*s.scale) and t.health
				P_InstaThrust(s, R_PointToAngle2(s.x, s.y, t.x, t.y), -32*FRACUNIT)	
			end
		end
		
		s.state = S_PLAY_ROLL
			if not yu.bouncestate
			yu.firstbounce = false
			end
		yu.edgestop = 0
		
		if not yu.bouncestate
		and (yu.supersonic or p.powers[pw_sneakers])
			yu.superbouncetime = 11
		end
		
		yu.bouncestate = 1
		yu.spin = 3
		yu.startdash = 0
		yu.bounceframe = 2
		s.spriteyscale = FRACUNIT+10002
		s.spritexscale = FRACUNIT-15002
		yu.alteredscale = false
end)

--Stop the LSA Dash!(The part where Sonic dashes forwards, not necessarily the homing/lightdashing, though that'll end here too)

rawset(_G, "YuStopLSAdash", function(p, s, yu)
		YuResetBounce(p, s, yu)
		yu.ldvertstyle = false		
		yu.startdash = 0
		yu.lightdashtimer = 0		
		yu.lsadash = 0
		yu.ringtarget = nil
		yu.hitspring = 0
		yu.lsahoming = 0
		yu.lightdashing = false
		yu.noairdrag2 = 4
		yu.prevringx = nil yu.prevringy = nil yu.prevringz = nil
end)

--A special function for the special state of the Bounce Attack!

rawset(_G, "YuBounce", function(p, s, yu)
yu.noairdrag = 0
				if yu.bouncefloor and s.pmomz --Teleport up if you're on a platform so you don't hit it again, because SRB2 coding is genius.
					if (s.eflags & MFE_VERTICALFLIP) 
						if (s.pmomz > 0)
						s.momz = $+s.pmomz*-1
						end
					else
						if (s.pmomz < 0) --Don't decrease bounce height when bouncing off lowering platforms.
						s.momz = $+s.pmomz*-1
						end
					end
					s.eflags = $ & ~MFE_JUSTHITFLOOR
					s.z = $+(6*s.scale*P_MobjFlip(s))
					p.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING
					yu.firstbounce = true
					yu.bouncefloor = 0
				end
				if s.state == S_PLAY_ROLL
					if not (leveltime % 2 == 0)
					s.flags2 = $|MF2_DONTDRAW
					end
					if s.tics > 1 or s.anim_duration > 1
						s.anim_duration = 1
						s.tics = 1
					end
					if ((s.frame & ~FF_FULLBRIGHT & ~FF_SPR2SUPER) >= H)
						s.frame = A
					else
						s.frame = $+1
					end
				end
				
				if not s.health or (s.eflags & MFE_SPRUNG) or P_PlayerInPain(p)
				or p.powers[pw_carry] or (s.state == S_PLAY_PAIN) or (s.state == S_PLAY_GASP) --Cancel bounce when...
					YuResetBounce(p, s, yu)
					return
				elseif yu.bouncestate == 1 --Going down?
					YuSpinTrail(p, s, yu)
					DoSpinRev(p, s, yu, YuAuraColor(s, nil, yu, true), true)
					if (s.state != S_PLAY_ROLL)
						s.state = S_PLAY_ROLL
					end
					if (s.eflags & MFE_GOOWATER) and (s.momz*P_MobjFlip(s) >= 1)
					and ( ((s.z <= s.floorz+5*FRACUNIT) and not (s.eflags & MFE_VERTICALFLIP))
					or ((s.z+s.height >= s.ceilingz-20*FRACUNIT) and (s.eflags & MFE_VERTICALFLIP)) )
						P_SetObjectMomZ(s, 760000)
						yu.bouncestate = 2
						S_StartSound(s, sfx_yusfx3)
						yu.firstbounce = true
						return
					end
					if (s.momz*P_MobjFlip(s) > FRACUNIT) and not s.pmomz --Wait, we're going UP? How?? Well, switch to phase 2 then...
						yu.bouncestate = 2
						S_StartSound(s, sfx_yusfx3)
						yu.firstbounce = true						
						return
					end
					
					if ((s.eflags & MFE_JUSTHITFLOOR) or P_IsObjectOnGround(s)) --Land on the floor and BOUNCE!
					
						local sectorz = R_PointInSubsector(s.x, s.y).sector //Break through bustable floors below!
						for fof in sectorz.ffloors()
							if (fof.flags & FF_EXISTS) and ((fof.flags & FF_STRONGBUST) or (fof.flags & FF_BUSTUP))
							and not (s.z-99*FRACUNIT >= fof.topheight)
							and not (s.z+99*FRACUNIT+s.height < fof.bottomheight)
							local line = fof.master
							EV_CrumbleChain(fof)
								if (line.flags & ML_EFFECT5)
   								P_LinedefExecute(P_AproxDistance(line.dx, line.dy) >> FRACBITS, s, fof.target)
								end
							end
						end
						
						if P_PlayerTouchingSectorSpecial(p, 3, 6) or P_PlayerTouchingSectorSpecial(p, 3, 5)
						YuResetBounce(p, s, yu) --Speed pad? Cancel bounce and run!
						s.momz = 0
						S_StartSound(s, sfx_zoom)
							if (s.state == S_PLAY_ROLL) and not (p.pflags & PF_SPINNING)
							s.state = S_PLAY_FALL
							end
						return
						end
						
						s.pmomz = 0
						yu.runfriction = yu.groundfriction
						yu.skipgroundcheck = 2
						yu.bouncexstretch = 70
						yu.bounceystretch = 132
						
						s.state = S_PLAY_ROLL
						s.sprite2 = SPR2_ROLL

						if (s.eflags & MFE_UNDERWATER)
							yu.firstbounce = false
							P_SetObjectMomZ(s, 560000)
						elseif yu.firstbounce
							P_SetObjectMomZ(s, 930000)				
						else --Bounce higher on your second bounce.
							yu.firstbounce = true
							P_SetObjectMomZ(s, 820000)
						end
						if yu.hypersonic or yu.mysticsuper
						P_YuQuake(p, 50*FRACUNIT, 3)			
						S_StartSound(s, sfx_brakrx) S_StartSound(s, sfx_s1b9)
							if yu.hypersonic
								P_NukeEnemies(s, s, 1100*s.scale)
							else
								P_NukeEnemies(s, s, 250*s.scale)
							end
							if (s.momz*P_MobjFlip(s) > 0)
							s.momz = $*10/8
							end
							local rng = P_RandomRange(7,44)
							for d = 0,7 --Rocks!
								local debris = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_BOSSJUNK)
								if debris and debris.valid
								debris.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE|MF_NOCLIPTHING
								debris.sprite = SPR_ROIA
								debris.frame = A
								debris.rollangle = (P_RandomRange(0,359)*ANG1)
								P_InstaThrust(debris, (ANGLE_45*d)-(rng*ANG1), rng*s.scale)
								P_SetObjectMomZ(debris, 13*s.scale-(rng/10), false)
								end
							end
							
						end
						
						yu.bouncefloor = 2
						p.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING	& ~PF_STARTJUMP			
						S_StartSound(s, sfx_yusfx3)
						yu.bouncestate = 2
						
						if (s.ceilingz-s.floorz < s.height+FRACUNIT) --Bounced into a tight coridor? Transition to spin.
						YuResetBounce(p, s, yu)
						p.pflags = $|PF_SPINNING & ~PF_THOKKED & ~PF_JUMPED & ~PF_STARTJUMP	
						end				
					end		
				end
				if (p.pflags & PF_THOKKED) --Fast Thok from bounce cancel!
					YuResetBounce(p, s, yu)
					s.state = S_PLAY_FALL
					s.momx = $*24/18
					if not ((s.flags2 & MF2_TWOD) or twodlevel)
						s.momy = $*24/18
					end
					yu.frictionlock = 7
					yu.runfriction = FRACUNIT
					s.friction = FRACUNIT
				end
end)
--Lazy function to reset LSA properties
rawset(_G, "ResetLSA", function(p, s, yu)
	yu.lsaattack = 0
	yu.lightdashing = false
	yu.lsaattackchain = 0
	yu.hadnotarget = 0
	yu.lsadeadjump = 0
	yu.lsahoming = 0
	yu.lightdashtimer = 0
	yu.lsatarget = nil
	yu.lsaclosest = nil
	S_StopSoundByID(s, sfx_yusfx5)
	S_StopSoundByID(s, sfx_yusfx6)
	if P_IsObjectOnGround(s) and (s.state == S_PLAY_ROLL) and not (p.pflags & PF_SPINNING)
		s.state = S_PLAY_FALL
	end
end)

--Lazy function to reset bounce properties
rawset(_G, "YuResetBounce", function(p, s, yu)
	yu.firstbounce = false
	yu.bouncestate = 0
	s.spriteyscale = FRACUNIT
	s.spritexscale = FRACUNIT
	yu.bouncexstretch = 100
	yu.bounceystretch = 100
	yu.skipgroundcheck = 0
end)

--Lazy function to reset pretty much all properties.

rawset(_G, "YuResetAll", function(p, s, yu)
	p.yumenutable = nil
	if p == consoleplayer and p.yusonictable and p.yusonictable.yumusic
		if S_MusicName() == "YUSUPR"	
			COM_BufInsertText(p, "tunes -default")
			P_RestoreMusic(p)
		end
	end
	yu.mysticsuper = 0
	yu.bosskiller = 0
	yu.nbdtarget = nil
	yu.nobouncedrag = 0	
	yu.endlvl = 0
	yu.tauntstate = 0
	yu.fallbuffer = 0
	yu.fallbuffer2 = 0
	yu.tauntdoll = 0
	yu.tauntroll = 0		
	yu.tauntno = 0	
	yu.tauntcd = 10
	yu.tauntdead = false
	yu.deathtouchedground = false
	yu.hassupershield = nil
	yu.startdash = 0
	yu.airborne = 0
	yu.advance2trail = 0
	yu.advance2roll = 0
	yu.homingtrick = 0
	yu.strongbspring = nil
	yu.strongspring = 0
	yu.sa2jumpdone = false
	yu.ledgeprotectcd = 0
	yu.edgestop = 0
	yu.speedup = 0
	yu.speedupreward = nil
	yu.speeduprewardfail = nil
	yu.frictionspeedtreshold = 0
	yu.frictionlock = 0
	yu.spindashfriction = false
	yu.groundfriction = 59392
	yu.runfriction = 59392
	yu.frictionreset = 180
	yu.alteredscale = false
	yu.bouncestate = 0
	yu.bouncefloor = 0
	yu.firstbounce = false
	yu.bouncexstretch = 100
	yu.bounceystretch = 100
	yu.maxcrush = 0
	yu.skipgroundcheck = 0
	yu.painrecovery = 0 
	yu.falltransition = 0
	yu.framejump = 5
	yu.noairdrag = 0
	yu.noubercontrol = 0
	yu.lastslopeunstuck = 0	
	yu.hitspring = 0
	yu.homingrecurl = 0
	yu.homingsetup = false
	yu.hominganim = 4
	yu.hominganim2 = 4
	yu.hominganim3 = 4
	yu.hominganimstart = 0
	yu.nospindrag = 50
	yu.lsacharged = false
	yu.lsaattack = 0
	yu.ringtarget = nil
	yu.lsadash = 0
	yu.dramaticdeath = false
	yu.burning = 0
	yu.spacedeath = false
	yu.drowning = false
	yu.drownanim = 0
	yu.drownanim2 = 0
	yu.electricdeath = 0
	yu.bombdeath = false
	yu.eleccolorized = false
	yu.lightdashing = false
	yu.spinanimspeed = 0
	yu.flyswitchdisabled = false
	yu.supersonic = false
	yu.hypersonic = false
	yu.downtheholedeath = false
	yu.downthehole = 0
	yu.downtheholefire = 0
	yu.ret2transform = 0
	yu.supertransform = 0
	yu.superflash = 0
	yu.superflashd = 1
	yu.hypermemories = 0
	yu.uncurlanim = nil
	yu.superaura = 0
	yu.superaurabuild = 0
	yu.nosarun4 = 0
	yu.vaultreadytarget = nil
	yu.superorigin = nil
	if s.valid 
		if yu.superoffset != 0
		s.spriteyoffset = 0
		end
		if s.state == S_PLAY_FLY
		s.state = S_PLAY_FALL
		end
	end
	yu.superoffset = 0
	yu.superoffsetd = 1	
	yu.jump = 0
	yu.spin = 0
	yu.custom2 = 0
	yu.custom3 = 0
	if not p.powers[pw_super]	
		p.charflags = $ & ~SF_CANBUSTWALLS
	end
	if yu.forceyuangletimer
		yu.forceyuangletimer = 0
		p.pflags = $ & ~PF_FORCESTRAFE
	end
end)

--Yes, uncurling comes with alot of special properties for Yu Sonic

rawset(_G, "YuUncurl", function(p, s, yu)
		if (s.eflags & MFE_UNDERWATER) or p.gotflag
			if s.friction > FRACUNIT
			s.friction = FRACUNIT
			yu.runfriction = FRACUNIT
			end
			s.momx = $*10/11 --No friction shenanigans underwater. Only slow.
			s.momy = $*10/11
		else
			s.friction = FRACUNIT
			yu.runfriction = FRACUNIT
					
			yu.frictionlock = 8
			if p.speed > 2*FRACUNIT
				yu.frictionlock = $+((p.speed/FRACUNIT)/4)
			end
			if yu.frictionlock > 20
			yu.frictionlock = 20
			end
		end
					
		p.pflags = $|PF_USEDOWN & ~PF_SPINNING & ~PF_STARTDASH & ~PF_THOKKED & ~PF_JUMPED
		
			if not P_IsObjectOnGround(s)
				yu.superaurabuild = $+3
				if (s.momz*P_MobjFlip(s) > 6*s.scale)
					s.state = S_PLAY_SPRING
				else
					s.state = S_PLAY_FALL
				end
			else
				yu.superaurabuild = $+1
				if (p.speed < 45*s.scale)
						s.state = S_PLAY_WALK
				else
						s.state = S_PLAY_RUN
				end
				s.frame = P_RandomRange(0,7)
					
				yu.uncurlanim = A
				s.sprite2 = SPR2_ROLL
				s.frame = A
			end
		yu.frictionreset = 180
		yu.startdash = 0
		yu.spin = 3
end)

--Lightdash cancel gfx

rawset(_G, "YuLSAgfx", function(p, s, yu)
		if not (yu.bonkeddash > 3)
		local boom = P_SpawnMobjFromMobj(s, 0, 0,0, MT_YUINSTASHIELD)
		boom.scalespeed = $*6
		boom.destscale = s.scale*99
		boom.blendmode = AST_ADD
		end
		for d = 1,4
		local ghs = P_SpawnGhostMobj(s)
			ghs.tics = 6+(d*3)
			ghs.fuse = 6+(d*3)
			ghs.scalespeed = $*d
			ghs.destscale = $*99
			ghs.frame = $ & ~TR_TRANS50 & ~TR_TRANS60 & ~TR_TRANS70 & ~TR_TRANS80
			ghs.frame = $|(TR_TRANS50+(d*FRACUNIT))
			ghs.flags = $|MF_NOCLIPHEIGHT
			ghs.momz = $-((ghs.scalespeed*12)*P_MobjFlip(s))
			if yu.supersonic
			ghs.blendmode = AST_ADD
			ghs.color = SKINCOLOR_CRIMSON
			else
			ghs.color = (SKINCOLOR_SUPERSKY5-d)
			end
			ghs.colorized = true
			ghs.momx = (s.momx*3)/2 ghs.momy = (s.momy*3)/d
		end
end)

--Cancel LSA. Comes with some aftereffects.

rawset(_G, "YuCancelLSA", function(p, s, yu)
		S_StartSound(s, sfx_mswing)
		yu.lsacharged = false
		yu.lsacharge = 0
			if not yu.autojumproll
			s.momx = $/2 s.momy = $/2
			end
		YuLSAgfx(p,s,yu)
		if not P_IsObjectOnGround(s) and not p.homing and not p.powers[pw_carry] and not yu.autojumproll
			s.momz = $/2
			s.state = S_PLAY_FALL
			yu.sa2jumpdone = false
		end
end)

--LSA Impact. Extra effects to make hitting enemies with this more juicy!

--Determine our color real quick....
local function DoDebrisColor(s, debris, color)
color = SKINCOLOR_SILVER
		if s.color
			color = s.color
		elseif (s.type == MT_BLUECRAWLA) or (s.type == MT_SPRINGSHELL)  or (s.type == MT_YELLOWSHELL) or (s.type == MT_PENGUINATOR)
			color = SKINCOLOR_CORNFLOWER
		elseif (s.type == MT_GFZFISH) or (s.type == MT_CRAWLACOMMANDER) or (s.type == MT_METALSONIC_BATTLE)
			color = SKINCOLOR_COBALT
		elseif (s.type == MT_GSNAPPER) or (s.type == MT_JETTBOMBER) or (s.type == MT_ROBOHOOD)
			color = SKINCOLOR_GREEN
		elseif (s.type == MT_REDCRAWLA) or (s.type == MT_REDBUZZ) or (s.type == MT_DETON) or (s.type == MT_VULTURE) or (s.type == MT_CRUSHSTACEAN)
			color = SKINCOLOR_RED
		elseif (s.type == MT_EGGGUARD) or (s.type == MT_BANPYURA) or (s.type == MT_PTERABYTE)
			color = SKINCOLOR_LAVENDER
		elseif (s.type == MT_FACESTABBER) or (s.type == MT_JETJAW)
			color = SKINCOLOR_CRIMSON
		elseif (s.type == MT_DRAGONBOMBER) or (s.type == MT_PYREFLY) or (s.type == MT_CANARIVORE) or (s.type == MT_SNAILER) or (s.type == MT_GOLDBUZZ)
		or (s.type == MT_HIVEELEMENTAL) or (s.type == MT_BUMBLEBORE)
			color = SKINCOLOR_GOLD
		elseif (s.type == MT_JETTGUNNER) or (s.type == MT_CYBRAKDEMON)
			color = SKINCOLOR_BROWN
		elseif (s.type == MT_UNIDUS) or (s.type == MT_POPUPTURRET) or (s.type == MT_MINUS)
			color = SKINCOLOR_CARBON
		end
return color
end

--Hyper Sonic's powerful impact!

rawset(_G, "YuChaosImpact", function(p, s, yu)
								if not yu.noflashes or not yu.hypersonic
									for d = 1,20,3
										local ghs = P_SpawnGhostMobj(s)
										ghs.colorized = true
										ghs.color = SKINCOLOR_SUPERSILVER4+d
											if d == 1
												ghs.frame = $|FF_PAPERSPRITE|FF_FULLBRIGHT & ~TR_TRANS10 & ~TR_TRANS20 & ~TR_TRANS30 & ~TR_TRANS40 & ~TR_TRANS50 & ~TR_TRANS60 & ~TR_TRANS70 & ~TR_TRANS80 & ~TR_TRANS90
												ghs.angle = p.drawangle+ANGLE_90
											else
												ghs.blendmode = AST_ADD
												ghs.rollangle = (ANG10+(ANG2*4))*d
												ghs.angle = (ANG10+(ANG2*4))*d
												ghs.frame = $|FF_PAPERSPRITE|FF_FULLBRIGHT
												ghs.z = $+(18*s.scale*P_MobjFlip(s))
											end
										ghs.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
										ghs.scale = (s.scale*10)/7
										ghs.scalespeed = $*20/11
										ghs.tics = 20 ghs.fuse = 20
										ghs.destscale = 1
											if d == 1
											ghs.spriteyscale = 95356
											else
											ghs.spriteyscale = (FRACUNIT*11)/(d*5)
											end
										ghs.spritexscale = (FRACUNIT/(d*2))*100
									end
									for d = 1,2
										local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUTHOK)
										ghs.destscale = $*999
										ghs.scalespeed = $*16
										if d == 2
											ghs.color = SKINCOLOR_EMERALD
											ghs.scalespeed = $/2
											ghs.tics = 22
											ghs.fuse = 22
										else
											ghs.color = s.color
											ghs.tics = 16
											ghs.fuse = 16
										end
										ghs.blendmode = AST_REVERSESUBTRACT
										ghs.flags2 = MF2_SHADOW
									end
								end
								
								S_StartSound(s, sfx_kc4d)
								S_StartSound(s, sfx_kc40)
								S_StartSound(s, sfx_kc40)
								S_StartSound(s, sfx_kc3b)
								if yu.hypersonic
									P_NukeEnemies(s, s, 1420*FRACUNIT)
								else
									P_NukeEnemies(s, s, 350*FRACUNIT)
								end
								
								P_YuQuake(p, 70*FRACUNIT, 15)
								for d = 1,16
									local ghs = P_SpawnMobjFromMobj(s,0,0,10*s.scale, MT_MINECARTSPARK)
									ghs.scale = s.scale/4
									ghs.fuse = 17
									P_InstaThrust(ghs, (ANGLE_45/2)*d, 22*s.scale)
									ghs.momz = (14*s.scale)*P_MobjFlip(s)
								end
end)


rawset(_G, "YuLSAimpact", function(p, so, yu, s) --s is target getting hit, so is the player.

			if CBW_Chaos and (gametype == GT_CHAOS)
				if s and ((s.flags & MF_ENEMY) or (s.flags & MF_BOSS))
				yu.lsalimit = $+1
				end
			end
			yu.lsadeadjump = 1
			so.target = nil
			yu.lsalasttarget = yu.lsatarget
			yu.lsaclosest = nil
			yu.lsatarget = nil

			S_StartSound(so, sfx_bedeen)
			S_StartSound(so, sfx_brakrx)	
			
				for d = 0,7
					local debris = P_SpawnMobj(s.x+(P_RandomRange(-50,50)*s.scale), s.y+(P_RandomRange(-50,50)*s.scale), s.z+(P_RandomRange(5,80)*s.scale), MT_BOSSJUNK)
					if debris and debris.valid
					debris.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE|MF_NOCLIPTHING
					debris.scale = s.scale*30/P_RandomRange(20,35)
					debris.sprite = SPR_YUSO
					debris.frame = P_RandomRange(17,21)
					debris.color = SKINCOLOR_SILVER
					P_InstaThrust(debris, so.angle+(P_RandomRange(-30,30)*ANG1), (P_RandomRange(10,36)*s.scale)+p.speed)
					P_SetObjectMomZ(debris, P_RandomRange(2,12)*s.scale, false)
					
						if (s.flags & MF_ENEMY) --Actually hit an enemy?
							if (debris.frame < T)
							debris.color = DoDebrisColor(s, debris, color)
							end
							if (d > 6) --Break off specific pieces.
								if (s.type == MT_BLUECRAWLA)
								debris.sprite = SPR_BRKN
								debris.frame = A
								elseif s.type == MT_REDCRAWLA
								debris.sprite = SPR_BRKN
								debris.frame = A
								debris.color = SKINCOLOR_CRIMSON
								debris.colorized = true
								elseif s.type == GOLDBUZZ
								debris.sprite = SPR_BRKN
								debris.frame = I
								elseif (s.type == MT_SPRINGSHELL) or (s.type == MT_YELLOWSHELL)
								debris.sprite = SPR_BRKN
								debris.frame = E							
								elseif s.type == MT_FACESTABBER
								debris.sprite = SPR_BRKN
								debris.frame = Q							
								elseif s.type == MT_GSNAPPER
								debris.sprite = SPR_BRKN
								debris.frame = U								
								end
							end
						end
					end
				end
				
				local boom = P_SpawnMobjFromMobj(s, 0, 0,0, MT_YUINSTASHIELD)
				boom.scalespeed = $*11
				boom.destscale = s.scale*99
				boom.blendmode = AST_ADD
			
end)

--Lightdash function. Searches blockmaps, then rushes for the rings! No nearby target = FAIL.

rawset(_G, "YuLightDash", function(p, s, yu)

	local spring = false
	local skip = false
	local lock = 0
	local oldtarget = yu.ringtarget --If we had a target prior to this, store it here!
	
	if yu.ringtarget and yu.ringtarget.valid and not (yu.ringtarget.health <= 0)
	skip = true
	else
	yu.ringtarget = nil --We'll start with no target, then.
	end
	
	if P_IsObjectOnGround(s) --No ground today.
	s.z = s.z+(10*FRACUNIT*P_MobjFlip(s))
	end	
	--Okay, now let's search for a ring.
	if not skip --If we're not at our current ring yet, then don't look for a new one!
   	searchBlockmap("objects", function(ref, m) --Blockmaps save us the trouble from having to look through ALL of the map.
	
		if not yu.ldvertstyle 
		and ( (m.flags & MF_SPRING) and not m.info.damage --Without a damage value, springs have no horizontal power!
		or ((m.type >= MT_FAN) and (m.type <= MT_BLUESPRING)) )
			spring = true --Found a spring-esque object. Vertical lightdash is practically guaranteed!
		end
		if ((m.type == MT_RING) or (m.type == MT_COIN) or (m.type == MT_BLUESPHERE) --Anything around?
		or ((m.type == MT_REDTEAMRING) and p.ctfteam == 1)
		or ((m.type == MT_BLUETEAMRING) and p.ctfteam == 2)
		or ((m.type >= MT_BOUNCERING) and (m.type <= MT_GRENADEPICKUP)))
			if not (m.health <= 0) --It's alive and we can see it?
			and (P_CheckSight(s, m))
			and not (m.subsector == s.subsector and (m.z < (s.floorz-5*s.scale)))
			and (m.flags & MF_SPECIAL) --Conveniently all objects we're looking for have MF_SPECIAL.
			
				--Vertical ring-follow style! We'll no longer chase rings at or below our height, ensuring we go skyward!
				if yu.ldvertstyle
					if (yu.prevringx == m.x and yu.prevringy == m.y) and not (yu.prevringz == m.z) and not (m.z <= s.z)
					and not (m.z > (s.z+(364*FRACUNIT*P_MobjFlip(s))) )
						yu.ringtarget = m
						lock = 1
					elseif lock != 1
					local lastditch = 0
						for d = 41,1,-4
						if not lastditch
							if (FixedHypot(s.x-m.x, s.y-m.y) <= ((150*FRACUNIT)/d)) --Let's try this first. Favor vertical upward lines!
								if yu.ldvertstyle == -1
									if not (yu.prevringz >= m.z) and not (s.z >= m.z)
									and not (m.z > (s.z+(364*FRACUNIT*P_MobjFlip(s))) )	
									yu.ringtarget = m
									lastditch = d
									end
									
								else
									if not (yu.prevringz <= m.z) and not (m.z <= s.z)
									and not (m.z > (s.z+(364*FRACUNIT*P_MobjFlip(s))) )
									yu.ringtarget = m
									lastditch = d
									end
								end
							end
						end
						end
					end
				else	
					if spring and yu.prevringx == m.x and yu.prevringy == m.y and not yu.prevringz == m.z
					and not (m.z > s.z+(364*FRACUNIT*P_MobjFlip(s)))
					and not (m.z < s.z-(140*FRACUNIT*P_MobjFlip(s)))
						yu.ringtarget = m
						s.momx = $/40 s.momy = $/40
						yu.vertstylecharge = $+2
						lock = 1
					elseif spring and lock != 1 and (FixedHypot(s.x-m.x, s.y-m.y) <= 31*FRACUNIT) --Second attempt. Distance check.
					and not (m.z > s.z+(364*FRACUNIT*P_MobjFlip(s)))
					and not (m.z < s.z-(140*FRACUNIT*P_MobjFlip(s)))
						if not (yu.ringtarget and FixedHypot(FixedHypot(s.x-m.x, s.y-m.y), s.z-m.z) >
						FixedHypot(FixedHypot(s.x-yu.ringtarget.x, s.y-yu.ringtarget.y), s.z-yu.ringtarget.z))					
						yu.ringtarget = m
						s.momx = $/2 s.momy = $/2
						yu.vertstylecharge = $+2
						lock = 2
						end
					elseif not lock and (FixedHypot(FixedHypot(s.x-m.x, s.y-m.y),s.z-m.z) <= 300*FRACUNIT) --Still no? Try all-around then!
						if not (yu.ringtarget and FixedHypot(FixedHypot(s.x-m.x, s.y-m.y), s.z-m.z) >
							FixedHypot(FixedHypot(s.x-yu.ringtarget.x, s.y-yu.ringtarget.y), s.z-yu.ringtarget.z)) --Closest one gets priority!
							yu.ringtarget = m
        				end
					end
				end
				
			end
		end
  	end, s, s.x-300*FRACUNIT, s.x+300*FRACUNIT, s.y-300*FRACUNIT, s.y+300*FRACUNIT)
	end
	
	--Ring Dashing time!
	
	if yu.ringtarget and yu.ringtarget.valid --Did we find a target?
	local t = yu.ringtarget
		s.state = S_YU_LIGHTDASH
		if not yu.ldvertstyle
			s.angle = R_PointToAngle2(s.x, s.y, t.x, t.y)
			p.drawangle = s.angle
		else
			s.angle = yu.lsadashlastangle --Try not to disorient the player with spazzing while we go up!
			p.drawangle = s.angle
		end
		
		--This homing setup we use for LSA too, to end up EXACTLY where the ring actually is rather than beelining from 1 inch away.
		local mult = FixedHypot(FixedHypot(t.x-s.x, t.y-s.y), t.z-s.z)
		if mult < 1
			mult = 1
    	end
		s.momx = FixedMul(FixedDiv(t.x-s.x, mult), (70*FRACUNIT)) 
		s.momy = FixedMul(FixedDiv(t.y-s.y, mult), (70*FRACUNIT))
		s.momz = FixedMul(FixedDiv(t.z-s.z, mult), (70*FRACUNIT))		
	
		p.pflags = $ & ~PF_JUMPED & ~PF_SPINNING & ~PF_STARTDASH
		yu.startdash = 0
		yu.lsacheck = 3
		yu.lsaclosest = nil
		yu.lsadash = 0
		yu.lsaattack = 0
		yu.lightdashaftereffects = 12
		yu.lightdashtimer = $+1						
		yu.framejump = 0
		yu.nosarun4 = 2
						
			if yu.spin == 1 --Mash to break free early if you can't wait 1 second when the Lightdash gets stuck.
				yu.lightdashtimer = $+10
			end
			if oldtarget != t
			yu.lightdashtimer = 1
				if not yu.ldvertstyle			
					if (yu.vertstylecharge < 0)
						yu.vertstylecharge = 0
					end
					if t.x == yu.prevringx
					and t.y == yu.prevringy
					yu.vertstylecharge = $+3
					end
					if (yu.vertstylecharge > 5) or spring
						if (s.momz < -1)
							yu.ldvertstyle = -1
						else
							yu.ldvertstyle = 1
						end
					end
				end
			end
			if (yu.lightdashtimer < 40) --Give Sonic the LSAhoming property while we're doing this.
				yu.lsahoming = 5
			else --Okay, we're homing onto the same target too long, stop this madness!
				s.momx = $/5
				s.momy = $/5
				s.momz = $/5
				YuStopLSAdash(p, s, yu)
				S_StartSound(s, sfx_ngskid)
				YuStopLSA(p, s, yu)
				ResetLSA(p, s, yu)
				yu.lsahoming = 0
				yu.lightdashtimer = 0
			end
			
			--Finally, save this thing's coordinates!
			yu.prevringx = t.x
			yu.prevringy = t.y
			yu.prevringz = t.z
			
		return true --Success!
    elseif yu.lightdashing --We're at the end of the Lightdash!
		if (yu.ldvertstyle or ((s.momz*P_MobjFlip(s)) > 19*FRACUNIT)) and yu.lsadashlastangle != nil
		s.angle = yu.lsadashlastangle
		end
		yu.prevringx = nil
		yu.prevringy = nil
		yu.prevringz = nil
		yu.ringtarget = nil
		yu.lsahoming = 0
		yu.lsacheck = 0
		yu.lightdashtimer = 0
		yu.vertstylecharge = 0
		yu.ldvertstyle = false
		yu.lightdashing = false
		yu.speedupreward = true
		yu.lsatarget = nil
		s.target = nil
	end
	return false
end)

--The main LightSpeed Attack and LightDash function! Let's gooo! Also, make sure Sonic has a target before activating this function!

rawset(_G, "YuLightSpeed", function(p, s, yu)

				if not yu.lsaattack and not yu.lightdashing --We dunno what type of move we're using? Then determine that first.
					if s.target and s.target.valid and s.target.health and P_CheckSight(s, s.target) and yu.lsatarget and s.target == yu.lsatarget
					local m = s.target
					yu.hadnotarget = 1
						if ((m.type == MT_RING) or (m.type == MT_COIN) or (m.type == MT_BLUESPHERE) 
						or (m.type == MT_REDTEAMRING)
						or (m.type == MT_BLUETEAMRING)
						or ((m.type >= MT_BOUNCERING) and (m.type <= MT_GRENADEPICKUP))) --Yep, these are lightdash objects.
						
							yu.lsaattack = 0
							yu.lightdashing = true						
							
						else --If it's not those it's probably something we wanna attack.
						
							yu.lsaattack = 1
							yu.lightdashing = false
							yu.lsaattackchain = 2
							YuLSAgfx(p, s, yu)
							if (s.state != S_PLAY_ROLL) --Always rollin', always hatin'
								s.state = S_PLAY_ROLL
							end	
							
						end
						yu.bonkeddash = 0
						yu.hitspring = 0
						yu.lsadeadjump = 0
						yu.lightdashtimer = 0								
					end
				end
				
				if yu.lightdashing --Lightdash!
					
					YuLightDash(p, s, yu) --Big Function
					YuNoControls(p, yu, true)
					//	yu.forceyuangletimer = 2
					//	yu.forceyuangle = s.angle
					
					if yu.lightdashing and yu.lsahoming
					or yu.lightdashaftereffects
						local ghs = P_SpawnGhostMobj(s)
						ghs.rollangle = s.rollangle
						ghs.tics = 14 ghs.fuse = 14 ghs.destscale = $*3
						ghs.colorized = true
						if p.powers[pw_super]
							ghs.color = s.color
						else
							ghs.color = SKINCOLOR_SUPERSKY3
						end
						ghs.frame = $|TR_TRANS90 & ~TR_TRANS30 & ~TR_TRANS40 & ~TR_TRANS50 & ~TR_TRANS60 & ~TR_TRANS70 & ~TR_TRANS80
						ghs.flags2 = $|MF2_SHADOW
						ghs.blendmode = AST_ADD
						
						if yu.lightdashing
						p.pflags = $ & ~PF_SPINNING & ~PF_JUMPED & ~PF_STARTDASH & ~PF_THOKKED & ~PF_NOJUMPDAMAGE
						end
					end
					
				elseif yu.lsaattack --Lightspeed Attack!
				
				YuSpinTrail(p, s, yu)
					if p == consoleplayer 
						if CV_FindVar("cam_speed").string != "0.03999"
						yu.lsacamspeed = CV_FindVar("cam_speed").string
						COM_BufInsertText(p, "cam_speed 0.03999")
						end
					end
				
					--Our sound timers.
					if yu.setuplsasfx
					yu.setuplsasfx = $-1
						if not yu.setuplsasfx
						yu.setuplsasfx2 = 26
						S_StopSoundByID(s, sfx_yusfx5)
						S_StartSound(s, sfx_yusfx6)
						end
					elseif yu.setuplsasfx2
						yu.setuplsasfx2 = $-1
						if not yu.setuplsasfx2
						yu.setuplsasfx2 = 25
						yu.setuplsasfx = 0
						S_StartSound(s, sfx_yusfx6)
						end
					end
					yu.lsadash = 0
					yu.lsahoming = 5
					yu.noairdrag = 9
					yu.lightdashing = false
					YuNoControls(p, yu, true)
					yu.startdash = 0
					p.pflags = $|PF_JUMPED|PF_THOKKED & ~PF_SPINNING & ~PF_STARTDASH & ~PF_NOJUMPDAMAGE
					
					
					if (yu.lsaattackchain > 2) and not p.sms_intoship
					
						local detect = P_SpawnMobj(s.x+FixedMul(170*FRACUNIT,cos(s.angle)), s.y+FixedMul(170*FRACUNIT,sin(s.angle)), s.z-800*FRACUNIT, MT_YUECHECK)
						if detect and detect.valid
						detect.target = s
						detect.height = 1600*FRACUNIT
						detect.radius = 1200*FRACUNIT
						end
						
						yu.lsaattackchain = 2
						yu.lsaattack = 1
						if (s.state != S_PLAY_ROLL) --Always rollin', always hatin'
						s.state = S_PLAY_ROLL
						end
						
					elseif not yu.lsaattackchain
					
						if not s.target 
						or (s.target and s.target.health)
							ResetLSA(p, s, yu)
							if not yu.autojumproll
							s.momx = $/2 s.momy = $/2 s.momz = $/2
							end
						end
					end
					
					if yu.lsaattack --Check again incase yu.lsaattack was set to 0 before.
 					P_RadiusAttack(s, s, 30*FRACUNIT)
					yu.lsaattack = $+1
					
						if s.target and s.target.valid and s.target.health
						and not (s.target.flags2 & MF2_FRET)
						and not (yu.lsalasttarget and (s.target == yu.lsalasttarget))
						and ((FixedHypot(s.target.x-s.x, s.target.y-s.y)) < 1400*FRACUNIT)
						and (P_CheckSight(s, s.target))
						
						local t = s.target
						yu.lsaattackchain = 2
						yu.lsadeadjump = 0
						yu.hadnotarget = 0
						s.lsaclosest = nil
						s.lsatarget = nil
						s.angle = (R_PointToAngle2(s.x, s.y, t.x, t.y))
						yu.forceyuangletimer = 2
						yu.forceyuangle = s.angle
													
							if P_IsObjectOnGround(s) and not (t.subsector == s.subsector)
							or ((t.floorz > s.z) and not (s.eflags & MFE_VERTICALFLIP))
							or ((t.ceilingz < s.z-s.height) and (s.eflags & MFE_VERTICALFLIP))
								
								if ((t.floorz > s.z+200*FRACUNIT) and not (s.eflags & MFE_VERTICALFLIP))
								P_SetObjectMomZ(s, 200*FRACUNIT) --We've got a ways to go. Let's speed this up!						
								else
								P_SetObjectMomZ(s, 75*FRACUNIT) --Hop up a bit and get to a favorable attacking position!
								end
								
							elseif (yu.lsaattack < 6)
								P_SetObjectMomZ(s, (6*FRACUNIT*yu.lsaattack))
								s.momx = ((FixedMul(FixedDiv(t.x-s.x, 512*FRACUNIT), FixedDiv(261*FRACUNIT, 3*FRACUNIT/2)))/3)/yu.didmanuallsa
								if not (s.flags2 & MF2_TWOD or twodlevel)
								s.momy = ((FixedMul(FixedDiv(t.y-s.y, 512*FRACUNIT), FixedDiv(261*FRACUNIT, 3*FRACUNIT/2)))/3)/yu.didmanuallsa
								end
							else
								s.momx = FixedMul(FixedDiv(t.x-s.x, 512*FRACUNIT), FixedDiv(261*FRACUNIT, 3*FRACUNIT/2))/yu.didmanuallsa
								if not (s.flags2 & MF2_TWOD or twodlevel)
								s.momy = FixedMul(FixedDiv(t.y-s.y, 512*FRACUNIT), FixedDiv(261*FRACUNIT, 3*FRACUNIT/2))/yu.didmanuallsa
								end
								s.momz = FixedMul(FixedDiv(s.target.z-s.z, 512*FRACUNIT), FixedDiv(261*FRACUNIT, 3*FRACUNIT/2))
							end
							
							yu.didmanuallsa = 1
							
							if (yu.lsaattack < 30) --People want this feature, man. You know they do.
							and not (P_FaceStabCheckMeleeRange(s)) --What kind of LSA can't fly circles around your foes?
								if (yu.direct > 2)
								local dirang = (p.cmd.angleturn<<16)+(R_PointToAngle2(0, 0, p.cmd.forwardmove<<16, -(p.cmd.sidemove<<16)))
								P_Thrust(s, R_PointToAngle2(s.x-s.momx,s.y-s.momy, s.x+P_ReturnThrustX(s,dirang, 60*FRACUNIT), s.y+P_ReturnThrustY(s, dirang, 60*FRACUNIT)), 60*FRACUNIT)
								yu.didmanuallsa = 2
								end
							end

							--Stuck on a wall RIGHT next to your target? Let's blow it up and pretend we didn't get stuck on anything!

							if (p.speed < 5*FRACUNIT) and (yu.lsaattack > 8) and ((s.momz > -5*FRACUNIT) and (s.momz < 5*FRACUNIT))
							and (FixedHypot(FixedHypot(t.x-s.x, t.y-s.y), t.z-s.z) < 192*FRACUNIT)
								if yu.supersonic							
								P_DamageMobj(t, s, s)
							
								P_SetObjectMomZ(s, 80*FRACUNIT)
								s.momx = FixedMul(FixedDiv(t.x-s.x, 512*FRACUNIT), FixedDiv(261*FRACUNIT, 3*FRACUNIT/2))
									if not (s.flags2 & MF2_TWOD or twodlevel)
									s.momy = FixedMul(FixedDiv(t.y-s.y, 512*FRACUNIT), FixedDiv(261*FRACUNIT, 3*FRACUNIT/2))
									end
								elseif not yu.bonked 
									yu.bonkeddash = $+3
									yu.bonked = 1
									if (yu.bonkeddash > 4)
										yu.bonkeddash = 0
										YuCancelLSA(p, s, yu)
										YuStopLSAdash(p, s, yu)
										ResetLSA(p, s, yu)	
										if yu.forceyuangletimer
										yu.forceyuangletimer = 0
										p.pflags = $ & ~PF_FORCESTRAFE
										end
										YuBonk(p, s, yu)
										yu.bonked = 7
										return --Is it over?
									end
								end			
							end
					
							--Now for a billion special occasions.
							
							if (t.type == MT_SPRINGSHELL) //These jerks! Use P_Radius so we don't just recoil from their springs
							or (t.type == MT_YELLOWSHELL)
							
								P_RadiusAttack(s, s, 70*FRACUNIT)
							
							elseif (t.type == MT_TURRET) //Kill even the infamous turrets.
								if (FixedHypot(FixedHypot(t.x-s.x, t.y-s.y), t.z-s.z) < 70*FRACUNIT)
								P_KillMobj(t, s, s)
								end

							elseif (t.type == MT_SPINCUSHION)
							
								if t.health
								t.flags = $|MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE|MF_BOUNCE & ~MF_PAIN				
									if (t.state < S_SPINCUSHION_STOP2)
									t.state = S_SPINCUSHION_STOP2
									end
								end
								
							elseif (t.type == MT_MINUS)
							
								if (t.state != t.info.missilestate)
								t.state = t.info.missilestate
								t.flags = $|MF_SPECIAL|MF_SHOOTABLE
									if (t.z < t.floorz+20*FRACUNIT)
									t.z = $+(20*FRACUNIT*P_MobjFlip(t))
									t.momz = 0
									end
								end
							
							elseif (t.type == MT_EGGROBO1)
							
								if (FixedHypot(FixedHypot(t.x-s.x, t.y-s.y), t.z-s.z) < 89*FRACUNIT)
								P_SpawnMobj(t.x, t.y, t.z, MT_EXPLODE)
								YuLSAimpact(p, s, yu, t)
								yu.lsaattack = 1
								yu.lsaattackchain = 2
								
									if t and t.valid
									t.state = S_NULL
									end
								end
								
							elseif (t.type == MT_METALSONIC_BATTLE) --Yay, the worst boss in the game.
								if (FixedHypot(FixedHypot(t.x-s.x, t.y-s.y), t.z-s.z) < 89*FRACUNIT)
									if (t.state == S_METALSONIC_FLOAT) --DOOODGE!
										P_TryMove(s, t.x, t.y)
										s.z = t.z
										yu.hadnotarget = 12
										yu.lsaattack = 1
										yu.lsaattackchain = 2
										P_InstaThrust(s, R_PointToAngle2(s.x, s.y, t.x, t.y), -60*FRACUNIT)
										yu.nosarun4 = 70										
										s.target = nil
									elseif (t.health > 1)
									yu.hadnotarget = 12
									yu.lsaattack = 1
									yu.lsaattackchain = 2
										if ((t.state == S_METALSONIC_STUN) or (t.state == S_METALSONIC_VECTOR)) and not t.yulsaresist
											for d = 1,5
											P_SpawnMobj(t.x+P_RandomRange(-70,70)*t.scale, t.y+P_RandomRange(-70,70)*t.scale, t.z+P_RandomRange(-20,50)*t.scale, MT_CYBRAKDEMON_VILE_EXPLOSION)
											end		
											
										YuLSAimpact(p, s, yu, t)										
										t.health = $-2
										P_YuQuake(p, 50*FRACUNIT, 12)	
										
										else
										t.health = $-1
											for d = 1,3
											P_SpawnMobj(t.x+P_RandomRange(-70,70)*t.scale, t.y+P_RandomRange(-70,70)*t.scale, t.z+P_RandomRange(-20,50)*t.scale, MT_SONIC3KBOSSEXPLODE)
											end											
											S_StartSound(t, sfx_cybdth)
											S_StartSound(s, sfx_dmpain)
											P_YuQuake(p, 30*FRACUNIT, 3)												
										end
										
										t.yulsaresist = true --Always do this!
										P_InstaThrust(s, R_PointToAngle2(s.x, s.y, t.x, t.y), -70*FRACUNIT)
										yu.nosarun4 = 70
										
									else
									YuLSAimpact(p, s, yu, t)
									P_KillMobj(t, s, s)
									end
								end
								
							elseif (t.type == MT_SUSPICIOUSFACESTABBERSTATUE)
								if (FixedHypot(FixedHypot(t.x-s.x, t.y-s.y), t.z-s.z) < 70*FRACUNIT)							
									if not (t.state == S_SUSPICIOUSFACESTABBERSTATUE_BURST2)
									t.state = S_SUSPICIOUSFACESTABBERSTATUE_BURST2
										if (t.tics > 2)
										t.tics = 2
										end
									elseif (t.tics > 2) and (t.state == S_SUSPICIOUSFACESTABBERSTATUE_BURST2)
										t.tics = 1
									end
								end
							elseif (t.flags & MF_MONITOR) and t.health
							
								if (FixedHypot(FixedHypot(t.x-s.x, t.y-s.y), t.z-s.z) < 70*FRACUNIT)
								P_KillMobj(t, s, s)
								end
								
							elseif (t.type == MT_EGGSHIELD)
								if (FixedHypot(FixedHypot(t.x-s.x, t.y-s.y), t.z-s.z) < 89*FRACUNIT)
									if t.target and t.target.valid and t.target.health and (t.target.type == MT_EGGGUARD)
									t.target.flags = $|MF_ENEMY|MF_SHOOTABLE
									P_KillMobj(t.target, s, s)
									end
									YuLSAimpact(p, s, yu, t)
									if t and t.valid
									t.state = S_NULL --Vanish!
									end								
								end				
								
							elseif (t.health == 2) and ((t.flags & MF_ENEMY) or (t.flags & MF_BOSS))
							and not t.yulsaresist
								if (t.flags & MF_BOSS)
								yu.nosarun4 = 90 --Prepare to boing
								end
							t.health = 1 --You only have 1 health as far as the Lightspeed Attack is concerned!
							
							end
							
							if (yu.lsaattack > 29)
							
								s.momx = $*2
								if not (s.flags2 & MF2_TWOD or twodlevel)	
								s.momy = $*2 --We're outta time, speed up and get that MF!
								end
								s.momz = $*2
							end
							
							--We're stuck...shoot! What can we do??
							if s.target and s.target.valid
								if not (s.eflags & MFE_VERTICALFLIP) and ( (s.z+s.height >= s.ceilingz) or ((t.floorz < s.floorz) and (t.subsector == s.subsector) and (t.ceilingz < s.floorz) and (s.z < s.floorz+50*FRACUNIT))) --Hit a ceiling!
								or (s.z <= s.floorz) and (s.eflags & MFE_VERTICALFLIP)
								
								S_StartSound(s, sfx_dmpain)
								S_StartSound(s, sfx_cdfm28)
								P_RadiusAttack(s, s, 200*FRACUNIT)
								s.target = nil
								end
							end
							
						else
							if (yu.lsadeadjump != 2)
							yu.lsadeadjump = 1
							end
						end
					end
				
					yu.hadnotarget = $+1
					
					if (yu.lsaattack > 35)
					or (yu.hadnotarget > 3)
					or (yu.lsadeadjump and (yu.lsadeadjump == 1))
					and ((s.target and not s.target.health) or (s.target and (s.target.flags2 & MF2_FRET)) or (s.target and not s.target.valid) or not s.target)
					or yu.forceswitchtarget
						yu.forceswitchtarget = nil
						s.lsaclosest = nil
						s.lsatarget = nil
						yu.lsaattackchain = 4
						yu.lsadeadjump = 2
						p.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING & ~PF_STARTJUMP
						P_SetObjectMomZ(s, FRACUNIT)
						if not yu.autojumproll
						s.momx = $/3 s.momy = $/3
						end
						
						if (yu.hadnotarget > 2) or (yu.lsalimit > 1) --Couldn't find a target for too long? Then finish the attack!
							if (s.eflags & MFE_UNDERWATER)
							P_SetObjectMomZ(s, 9*FRACUNIT)
							else
							P_SetObjectMomZ(s, 16*FRACUNIT) --Jump off that last enemy in style!
							end
							if not yu.autojumproll
							s.momx = $/2 s.momy = $/2
							end
							yu.airborne = 0
							yu.sa2jumpdone = false
							yu.homingtrick = 40
							yu.airstart = 10
							yu.homingresist = 15
							yu.lsatrickanim = 39 yu.lsatrickrollang = 0
							ResetLSA(p, s, yu)	
						elseif (yu.lsaattack > 35)
							yu.lsalimit = 0
							yu.airborne = 0
							yu.sa2jumpdone = false
							yu.homingtrick = 40
							yu.airstart = 10
							yu.lsatrickanim = 39 yu.lsatrickrollang = 0
							yu.homingresist = 15
							if not yu.autojumproll
							s.momz = $/4 s.momx = $/4 s.momy = $/4
							end
							ResetLSA(p, s, yu)
						
						else
							YuSpinTrail(p, s, yu)
							
							local detect = P_SpawnMobj(s.x+FixedMul(170*FRACUNIT,cos(s.angle)), s.y+FixedMul(170*FRACUNIT,sin(s.angle)), s.z-800*FRACUNIT, MT_YUECHECK)
							if detect and detect.valid
							detect.target = s
							detect.height = 1600*FRACUNIT
							detect.radius = 1200*FRACUNIT
							end
						
						end
					end
					
				// This party can't go on forever! Here's some cases where it's gotta stop!

					if (p.pflags & (PF_GLIDING|PF_STASIS|PF_SPINNING))
					and not (p.powers[pw_carry])
						ResetLSA(p, s, yu)
					end
					
					if not (p.panim == PA_ROLL) and yu.lsahoming
					P_SetMobjStateNF(s, S_PLAY_ROLL)
					p.pflags = $|PF_JUMPED --You son of a....KEEP ROLLING, do you WANT me to strangle you?!
					end
					yu.bonked = 0
				end

end)

--Our spindash! Other than it using the PF_SPINNING flag for convenience, pretty much an original ability.

rawset(_G, "YuSpinDash", function(p, s, yu)

 	if yu.bouncestate
	or (p.pflags & PF_JUMPED)
	or (yu.lsacharged)
 	return
 	end
	
			if yu.spin == 1 and (p.cmd.buttons & BT_USE) and not p.exiting
				
				--Not spinning! Initialize spindash!
				
				if not (p.pflags & PF_SPINNING) and not yu.startdash and (P_IsObjectOnGround(s) or yu.framejump)
				and ((s.state <= S_PLAY_DASH) or (s.state == S_PLAY_EDGE)) and not yu.bouncestate
					s.state = S_PLAY_SPINDASH
					yu.startdash = 2
					p.pflags = $|PF_SPINNING|PF_STARTDASH|PF_USEDOWN & ~PF_THOKKED & ~PF_JUMPED
					yu.lsacharged = false
					yu.lsacharge = 0
					
					if p.gotflag
						yu.spincharge = 11*FRACUNIT
					elseif p.powers[pw_sneakers] or p.powers[pw_super]
						yu.spincharge = 20*FRACUNIT
						yu.lsacharge = 20
					elseif yu.mysticsuper
						yu.spincharge = 30*FRACUNIT
					else
						yu.spincharge = 15*FRACUNIT
					end
					
					if not p.rmomx and not p.rmomy
					P_Thrust(s, p.drawangle, 500)
					end
					
					yu.spin = 2
					
					if not (yu.direct > 1)
					yu.spinanglecooldown = 2
					end
				--Spawn Yuvault	
					if not (yu.yuvault and yu.yuvault.valid)
						yu.yuvault = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUVAULT)
						yu.yuvault.tics = 6
						yu.yuvault.target = s
					else
						yu.yuvault.tics = 6
					end	
					
				--We're uncurling from a spin!
				
				elseif (p.pflags & PF_SPINNING) and not yu.startdash 
				and not (p.pflags & PF_JUMPED) and (s.state == S_PLAY_ROLL or s.state == S_PLAY_SPINDASH) 

					YuUncurl(p,s,yu)
		
				end
				
			elseif (yu.spin > 1) and yu.startdash and (p.cmd.buttons & BT_USE) --We're holding the button and charging the spin!
				
				if not (yu.yuvault and yu.yuvault.valid)
					yu.yuvault = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUVAULT)
					yu.yuvault.tics = 8
					yu.yuvault.target = s
				else
					yu.yuvault.tics = 8	
				end
				
				if (P_IsObjectOnGround(s) or yu.framejump or yu.startdash)
				p.pflags = $|PF_SPINNING|PF_STARTDASH & ~PF_THOKKED & ~PF_JUMPED
					if s.state != S_PLAY_SPINDASH 
					s.state = S_PLAY_SPINDASH
					end
					yu.startdash = 2
					yu.framejump = 5 --We can always jump while charging a spindash, even in midair.
				end
				
				if (yu.startdash and not P_IsObjectOnGround(s))
					s.momx = $*33/34 --Slow down if charging in midair.
					s.momy = $*33/34 --Don't want startdash-jumping to become too much of an OP meta-move, it's intended as a safety net...
				end 
				
				if (yu.spincharge < 85*FRACUNIT)
					if p.gotflag
					yu.spincharge = $+87770
					else
					yu.spincharge = $+167770 --How fast we charge.
					end
					if (yu.spincharge > 85*FRACUNIT) and not yu.mysticsuper --Our maxdash value, basically.
					yu.spincharge = 85*FRACUNIT
					end
				end
				if yu.mysticsuper --Mystic Super Charging.	
					if (yu.spincharge > 70*FRACUNIT)
						if not (yu.spincharge > 200*FRACUNIT) and not S_SoundPlaying(s, sfx_bejet1)
							S_StartSound(s, sfx_s3ka3)
							S_StartSound(s, sfx_s3k53)
							S_StartSound(s, sfx_bejet1)
						end
						local ghs = P_SpawnMobj(s.x+(P_RandomRange(-200,200)*s.scale), s.y+(P_RandomRange(-200,200)*s.scale), s.z, MT_YUTHOK)
						ghs.blendmode = AST_ADD
						ghs.colorized = true
						ghs.color = P_RandomRange(SKINCOLOR_SUPERRED3, SKINCOLOR_SUPERGOLD5)
						ghs.scale = $*P_RandomRange(1,5)
						ghs.rollangle = (P_RandomRange(-90,90)*ANG1)
						ghs.state = S_WATERZAP
						ghs.tics = $+P_RandomRange(2,15)
						ghs.frame = $|FF_FULLBRIGHT
					end				
					if (yu.spincharge < 450*FRACUNIT) --Mystic Super gets ridiculous spindash power!!
						yu.spincharge = $+167770 --Charge faster!
						P_YuQuake(p, (yu.spincharge/4), 1)
					end
				end
				
				if yu.spinguideline and not (s.flags2 & MF2_TWOD or twodlevel or s.currentaxis or yu.mysticsuper)
					local num = 10-((yu.spincharge/9)/FRACUNIT)
					local maxnum = ((yu.spincharge/2)/FRACUNIT)-2
					-- A little aiming reticule, fancier version of my SMS version.
					for i = num,maxnum,1
					local dist = yu.spincharge/3*i
					local asph = P_SpawnMobj(s.x+FixedMul(dist ,cos(s.angle)), s.y+FixedMul(dist ,sin(s.angle)), s.z+(s.height*10/13), MT_YUTHOK)
						if (s.scale/2-(i*1000) > 0)	//Avoid sigsevs, thx			
							asph.scale = s.scale/2-(i*1000)
						else
							asph.scale = 500
						end
						asph.dispoffset = -10
						asph.flags2 = $|MF2_SHADOW
						asph.color = SKINCOLOR_SUPERSILVER1
						asph.tics = 2
						if (s.eflags & MFE_VERTICALFLIP)
						asph.z = $-36*s.scale
						end
						if (p == displayplayer) and not CV_FindVar("chasecam").value
						or (dist < p.speed+(3*s.scale))
						asph.flags2 = $|MF2_DONTDRAW
						end
					end
				end
				
				if p.gotflag
					yu.lsacharge = 0 --None of this, sorry.
				else
					yu.lsacharge = $+1
					YuLSAglow(p, s, yu, -1, (170*s.scale), false, 14)
					YuLSAglow(p, s, yu, 0, (250*s.scale), false, 19)
					
					if (yu.lsacharge == 44)
					
						local boom = P_SpawnMobjFromMobj(s, 0, 0,0, MT_YUINSTASHIELD)
						boom.scalespeed = $*7
						boom.destscale = s.scale*99
						boom.colorized = true
						boom.blendmode = AST_ADD
						boom.color = SKINCOLOR_CORNFLOWER
						
					elseif (yu.lsacharge > 80) and not yu.mysticsuper --Charged long enough? Lightspeed ready!
						YuUncurl(p, s, yu)
						yu.runfriction = yu.groundfriction
						s.momx = $/2 s.momy = $/2 s.momz = $/2
						yu.framejump = 8
						YuLSAgfx(p,s,yu)
						yu.lsacharge = 0
						yu.lsalimit = 0
						yu.lsaangle = 90
						yu.lsacharged = true
						yu.lsalasttarget = nil
						yu.homingresist = 16 --Frames of "invincibility"
						YuVoice(p, s, yu, sfx_yuvoc4) --Readyyy!!
						if p.powers[pw_super]
							P_YuQuake(p, 5*FRACUNIT, 7)
							for d = 0,6,2
							local boom = P_SpawnMobjFromMobj(s, 0, 0,0, MT_YUINSTASHIELD)
							boom.scale = $+(50000*d)
							boom.scalespeed = $*7+d
							boom.destscale = s.scale*99
							boom.colorized = true
							boom.blendmode = AST_ADD
							boom.color = SKINCOLOR_AETHER+d
							end	
						end
					end
				end
			
			elseif not (p.cmd.buttons & BT_USE) --Release the spin charge! Add speed depending on actual speed!
			and yu.startdash and yu.spincharge
			
				yu.lsacharge = 0				
				yu.startdash = 0
				yu.edgestop = 0
				yu.homingtrick = 0
				yu.chosentrick = 0
				s.state = S_PLAY_ROLL
				
				local endspeed
				local cmomx2 = p.cmomx*5/3 --Don't forget this.
				local cmomy2 = p.cmomy*5/3
				
					if not yu.mysticsuper
						if (p.powers[pw_sneakers] or p.powers[pw_super])
						and not p.gotflag
							if (p.speed > 101*s.scale)
							yu.spincharge = $-8*FRACUNIT
							elseif (p.speed > 40*s.scale)
							yu.spincharge = $-5*FRACUNIT
							end					
						else
							if (p.speed > 85*s.scale) or p.gotflag --Diminishing boosts if already going ultrafast
							yu.spincharge = $-8*FRACUNIT
							elseif (p.speed > 30*s.scale)
							yu.spincharge = $-5*FRACUNIT
							end
						end
					end

					if not P_IsObjectOnGround(s)					
					yu.spincharge = $*5/11 --Slower underwater or if done from midair
					else
						if (s.eflags & MFE_UNDERWATER)
						yu.spincharge = $*3/4
						end
					end
					
					yu.spindashhover = 42 --Incase you wanna do that thing.
					
					if (yu.spincharge < 4*FRACUNIT) --Always gain 4 minimum.
					yu.spincharge = 4*FRACUNIT
					end
					
					yu.spincharge = ($/FRACUNIT)*s.scale --NOW we convert it to be properly scaled with Sonic's scale.
					
					--Total End Speed
					endspeed = p.speed+yu.spincharge
					if not yu.mysticsuper --Our spindash limits!
						if p.powers[pw_sneakers] or p.powers[pw_super]
							if (endspeed > 125*s.scale)
							endspeed = 125*s.scale
							end
						else
							if (endspeed > 107*s.scale)
							endspeed = 107*s.scale
							end
						end
					yu.superbounceprep = (endspeed/4)/FRACUNIT
					end
					if (gametype == GT_RACE or gametype == GT_COMPETITION) and (leveltime < 140)
						endspeed = 0 --Not going anywhere until the race starts, bub
					elseif p.gotflag and (endspeed > 65*s.scale)
						endspeed = 65*s.scale
					elseif p.speed > endspeed
						endspeed = p.speed --Kay, don't let the spindash slow you DOWN, tho'
					end

				if (s.friction > FRACUNIT)
					yu.frictionlock = 0
					yu.runfriction = FRACUNIT
					s.friction = FRACUNIT
				end
				
				if endspeed+3*s.scale > yu.savedspeed
				yu.savedspeed = endspeed+3*s.scale
				end
				yu.savedspeedtimer = 4
				if not yu.direct	
					P_InstaThrust(s, p.drawangle, endspeed)
					yu.spinanglecooldown = 2
				else
					if (s.flags2 & MF2_TWOD or twodlevel)
					P_InstaThrust(s, s.angle, endspeed)
					else
					P_InstaThrust(s, p.drawangle, endspeed)
					end	
				end
				if yu.mysticsuper
					if (endspeed > 120*FRACUNIT)
					S_StartSound(s, sfx_smach)
					yu.hudboost = 1
					P_YuQuake(p, endspeed/4, (endspeed/FRACUNIT)/30)
					end
					yu.frictionlock = 8
					yu.runfriction = FRACUNIT
					s.friction = FRACUNIT		
				end

				s.momx = $+cmomx2
				s.momy = $+cmomy2
				
				yu.framejump = 5
				S_StopSoundByID(s, sfx_yusfx1)
				S_StopSoundByID(s, sfx_yusfx2)			
				p.pflags = $|PF_SPINNING|PF_USEDOWN & ~PF_STARTDASH
				S_StartSound(s, sfx_zoom)				
			end
end)

--The sparkles that appear when Sonic becomes Super Sonic or reverts!

rawset(_G, "YuSuperSparkles", function(p, s, yu, rotate, intensity)
	for d = 1,intensity
	
		local ghs
		
		if rotate
			ghs = P_SpawnMobj(s.x+FixedMul(P_RandomRange(1,300)*s.scale, cos(p.drawangle+ANGLE_90+(P_RandomRange(-20,20)*ANG1))),
			s.y+FixedMul(P_RandomRange(1,300)*s.scale, sin(p.drawangle+ANGLE_90+(P_RandomRange(-20,20)*ANG1))) ,
			s.z+P_RandomRange(-50,50)*s.scale, MT_THOK)
		else
			ghs = P_SpawnMobj(s.x+P_RandomRange(-400,400)*s.scale, s.y+P_RandomRange(-400,400)*s.scale, s.z+P_RandomRange(-150,100)*s.scale, MT_THOK)
		end
			ghs.blendmode = AST_ADD
			ghs.sprite = SPR_YUSO
			ghs.frame = J|FF_FULLBRIGHT|(P_RandomRange(0,9)*FRACUNIT)
			
			if rotate
			ghs.scale = s.scale
			ghs.fuse = 8
			ghs.tics = 50
			P_Thrust(ghs, R_PointToAngle2(ghs.x, ghs.y, s.x, s.y), -25*FRACUNIT)
			else
				if (leveltime % 2 == 0)
					ghs.scale = $/2
				elseif (leveltime % 3 == 0)
					ghs.scale = $/3
				end
			ghs.scalespeed = $/P_RandomRange(1,9)
			ghs.fuse = 17*intensity
			ghs.tics = 17*intensity+30
			end
			
			ghs.destscale = $*999
			ghs.eflags = s.eflags
				if not P_RandomRange(0,4)
				ghs.color = P_RandomRange(SKINCOLOR_SUPERGOLD1, SKINCOLOR_SUPERGOLD5)
				else
				ghs.color = P_RandomRange(SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERGOLD5)
				end
			P_SetObjectMomZ(ghs, P_RandomRange(-1,3)*FRACUNIT)
	end
end)

--The sparkles that appear when Sonic becomes Super Sonic or reverts!

rawset(_G, "YuSuperFlyStart", function(p, s, yu, on)
--Not if disabled! Though it's never disabled by default, 
--This is just for mods that want to use a certain set of Super Sonic's moveset.
if yu.flyswitchdisabled
return
end
				if yu.lsacharged
					YuCancelLSA(p, s, yu)
				end
				if yu.lsadash
					YuStopLSAdash(p, s, yu)
				end
				if yu.lsaattack or yu.lsahoming or yu.lsadash
					YuStopLSA(p, s, yu)
				end
				if yu.bouncestate
					YuResetBounce(p, s, yu)
				end
				if not on --Turning off flight!
					if ((s.state >= S_PLAY_SUPER_TRANS1) and (s.state <= S_PLAY_SUPER_TRANS6))
					return
					end
							yu.superflight = 0
							yu.flighthoming = 0
							yu.nogravity = nil
							s.flags = $ & ~MF_NOGRAVITY
							S_StartSound(s, sfx_s236)
							S_StartSound(s, sfx_s3k7e)
							S_StartSound(s, sfx_s236)
							S_StartSound(s, sfx_s3k7e)							
							local ghs = P_SpawnGhostMobj(s)
							ghs.blendmode = AST_ADD
							ghs.destscale = $*99
							p.pflags = $ & ~PF_CANCARRY
							
							if not P_IsObjectOnGround(s)
							p.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING & ~PF_STARTDASH & ~PF_STARTJUMP
								s.state = S_PLAY_ROLL
							else --Grounded, then.
								p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING
								s.state = S_PLAY_FALL
							end
							
				else --Switching flight mode on!
				
							p.pflags = $|PF_CANCARRY
							P_SetObjectMomZ(s, 8*FRACUNIT)
							p.pflags = $|PF_THOKKED|PF_FORCESTRAFE & ~PF_STARTDASH & ~PF_SPINNING & ~PF_JUMPED & ~PF_STARTJUMP
							yu.startdash = 0
							p.powers[pw_nocontrol] = 15
							yu.forceyuangletimer = 15
							yu.forceyuangle = s.angle
							yu.supertransformangle = s.angle
							yu.lsacharge = 0
							s.flags = $|MF_NOGRAVITY
							s.momx = $/2 s.momy = $/2
							yu.airborne = 55
							yu.flighthoming = 0
							yu.superflyrun = 0
							yu.superflyswitch = 19
							S_StartSound(s, sfx_yusfx8)
							YuNoControls(p, yu, true)
							yu.hominganimstart = 0
							yu.hominganim = 0 yu.hominganim2 = 0 yu.hominganim3 = 0
							yu.homingtrick = 0
							yu.farthok = 0
							yu.sa2jumpdone = true
							s.state = S_PLAY_SPRING
				end
end)

--Shortcut for all aura functions.
local function DoYuAura(ghs, p, s, yu, mom, infront)
local angle = p.drawangle
		if yu.forceyuangletimer or s.rollangle != 0
		angle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
		end
		if infront
			P_TeleportMove(ghs, s.x+FixedMul(12*s.scale, cos(angle)), s.y+FixedMul(12*s.scale, sin(angle)), s.z)
		else
			if (p.panim == PA_FALL)
			P_TeleportMove(ghs, s.x, s.y, s.z-(5*s.scale*P_MobjFlip(s)))
			elseif (p.panim == PA_RIDE)
			P_TeleportMove(ghs, s.x, s.y, s.z-(25*s.scale*P_MobjFlip(s)))
			else		
			P_TeleportMove(ghs, s.x, s.y, s.z)
			end
		end
		ghs.momx = s.momx
		ghs.momy = s.momy
		ghs.momz = s.momz
		if (s.eflags & MFE_VERTICALFLIP)
			ghs.z = YuFlipZ(s, ghs)
		else
			ghs.eflags = $ & ~MFE_VERTICALFLIP
		end		
		if mom
		ghs.angle = angle
		end
		ghs.fuse = 2
		ghs.spriteyscale = FRACUNIT+YuLocalRandom(0,3000,s)
		ghs.spritexscale = FRACUNIT+YuLocalRandom(0,3000,s)
		ghs.blendmode = AST_ADD
		if (p == displayplayer) and not CV_FindVar("chasecam").value
			ghs.flags2 = $|MF2_DONTDRAW
		else
			ghs.flags2 = $ & ~MF2_DONTDRAW
		end			
end

--The Golden Shield Aura, the Blue Bolt aura, and the Flight Aura!

rawset(_G, "YuSuperAura", function(p, s, yu, flyaura, share)

local maxaura = 4
local maxaura2 = 2
if p != displayplayer or ((p == consoleplayer) and CV_FindVar("renderer").value != 2)
	maxaura = 0
	maxaura2 = 0
end

	if flyaura and not share
	local ghs
		if (p.speed > 44*s.scale) --DIAGIONAL
			if not (yu.yuauraflyd and yu.yuauraflyd.valid) --The center one!
				yu.yuauraflyd = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUAURAFLYD)
			end			
			ghs = yu.yuauraflyd			
				ghs.scale = s.scale*10/11 
				if flyaura == 1 --Going up!
					ghs.frame = $ & ~FF_VERTICALFLIP
					ghs.spriteyoffset = FRACUNIT-9
				else --Going down!
					ghs.frame = $|FF_VERTICALFLIP
					ghs.spriteyoffset = FRACUNIT*-85
				end
				DoYuAura(ghs, p, s, yu, true, true)
				ghs.angle = p.drawangle
			
		else --Straight up/down!
			if not (yu.yuaurafly and yu.yuaurafly.valid) --The center one!
				yu.yuaurafly = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUAURAFLY)
			end			
			ghs = yu.yuaurafly			
				ghs.scale = s.scale*10/11
				if flyaura == 1 --Going up!
					ghs.rollangle = 0
					ghs.spriteyoffset = 0
				else --Going DOWN!
					ghs.rollangle = ANGLE_180
					ghs.spriteyoffset = FRACUNIT*-48
				end
				DoYuAura(ghs, p, s, yu)
		end
		if ghs and ghs.valid
			if yu.hypersonic
				ghs.color = (p.yuemeraldcolors2[yu.hypercolor])+4
				ghs.colorized = true
			elseif (p.rings < 10)
				if leveltime % 2 == 0
					ghs.color = SKINCOLOR_RED
				else
					ghs.color = SKINCOLOR_VIOLET
				end
					ghs.colorized = true
			else
					ghs.colorized = false
			end
		end
		
	return
	end
	
	--Not a fly aura, then, so....
		
				if not yu.superaura or share --Super Sonic's Golden Shield!
				  if p.powers[pw_shield] == SH_YUSUPERSHIELD and yu.superorigin and yu.superorigin.player 
					yu.superauraframe = $-1
					if (yu.superauraframe < B)
					yu.superauraframe = H
					end
				local superaura2 = yu.superauraframe+1
					if superaura2 >= I
					superaura2 = B
					end
				local superaura3 = superaura2+1
					if superaura3 >= I
					superaura3 = B
					end					
					
					for d = 0,maxaura
					local ghs
						if (p.panim == PA_RIDE) and s.skin == "adventuresonic"
						ghs = P_SpawnMobjFromMobj(s, 0, 0, -22*s.scale, MT_YUTHOKDISP)
						else
						ghs = P_SpawnMobjFromMobj(s, 0, 0, s.height/12, MT_YUTHOKDISP)
						end
						ghs.yulsatarget = s
						ghs.yulsanum = d
						ghs.superaura = true
						ghs.sprite = SPR_BUBS
						ghs.tics = 2
						ghs.blendmode = AST_ADD
						ghs.colorized = true
						ghs.spritexoffset = s.spritexoffset
						if (s.eflags & MFE_VERTICALFLIP)
							ghs.spriteyoffset = s.spriteyoffset-20*FRACUNIT
						else
							ghs.spriteyoffset = s.spriteyoffset
						end
							if d == 0
								if not maxaura
								ghs.frame = (yu.superauraframe+1)|FF_FULLBRIGHT|TR_TRANS20
								else
								ghs.frame = (yu.superauraframe+1)|FF_FULLBRIGHT|TR_TRANS50+(d*FRACUNIT)	
								end
							elseif d < 3
							ghs.frame = (superaura2)|FF_FULLBRIGHT|TR_TRANS50+(d*FRACUNIT)
							else
							ghs.frame = (superaura3)|FF_FULLBRIGHT|TR_TRANS50+(d*FRACUNIT)
							end
							ghs.scale  = FixedDiv(FixedMul($, skins[s.skin].shieldscale), FRACUNIT)+(d*(s.scale/10))
							if (yu.superorigin.player.rings < 10)
								ghs.color = SKINCOLOR_RED+d
							elseif yu.superorigin.player.yusonictable.hypersonic
								ghs.color = yu.superorigin.player.yuemeraldcolors2[yu.superorigin.player.yusonictable.hypercolor]+4
							else
								ghs.color = SKINCOLOR_SUPERGOLD5-d
							end
					end			
					
				  else --Super Sonic actual AURA! More of a shield than a Super Saiyan aura, until we get past the Dreamcast days.
				  
				 	if yu.superflyswitch or yu.supertransformangle or yu.flighthoming
					or ((p.rings < 10) and p.speed < 54*s.scale) or (p.powers[pw_super] == 1 and not yu.hypersonic) --SA2 AURA for transforming and running out of rings!

					if not (yu.yuaurasa2 and yu.yuaurasa2.valid) --The center one!
						yu.yuaurasa2 = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUAURASA2)
					end
					local ghs = yu.yuaurasa2
					local ogframe = yu.yuaurasa2.frame

						for d = 0,maxaura2,2

							if d != 0
							ghs = P_SpawnMobj(s.x, s.y, s.z+s.height/12, MT_YUAURASA2)
							ghs.frame = YuLocalRandom(0, 5, s)|FF_FULLBRIGHT|TR_TRANS80 & ~TR_TRANS50 & ~TR_TRANS30 & ~TR_TRANS70
							elseif not maxaura2
								ghs.frame = $|TR_TRANS20 & ~FF_TRANSMASK
							end

						ghs.scale = s.scale+(d*(s.scale/10))
						ghs.spriteyoffset = yu.superoffset
						DoYuAura(ghs, p, s, yu)
							if (p.rings < 10)
								ghs.color = SKINCOLOR_RED+d
								ghs.colorized = true
							elseif yu.hypersonic
								ghs.color = ((p.yuemeraldcolors2[yu.hypercolor])+4)-d
								ghs.colorized = true
							else
								ghs.colorized = false
								ghs.color = SKINCOLOR_SADXSUPERSONIC
							end
						end


					elseif (p.speed > 54*s.scale) or yu.farthok --GOLD AURA FOR RUNNING
				 		if p.powers[pw_carry]
				 			return
				 		end
						if not (yu.yuaurarun and yu.yuaurarun.valid) --The center one!
							yu.yuaurarun = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUAURARUN)
						end
						local ghs = yu.yuaurarun
						local ogframe = yu.yuaurarun.frame

						for d = 0,maxaura,2
							if d != 0
							ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUAURARUN) --ANOTHER TWO.
								if d < 3 and not yu.hypersonic
								ghs.frame = YuLocalRandom(0,5,s)|FF_FULLBRIGHT|TR_TRANS80 & ~TR_TRANS50
								else
								ghs.frame = YuLocalRandom(0,5,s)|FF_FULLBRIGHT|TR_TRANS90 & ~TR_TRANS50
								end
							elseif not maxaura
								ghs.frame = YuLocalRandom(0,5,s)|FF_FULLBRIGHT|TR_TRANS20 & ~TR_TRANS50
							end
							ghs.scale = s.scale*(10+d)/13
							ghs.spriteyoffset = (-3*FRACUNIT)*d
							DoYuAura(ghs, p, s, yu, true, true)
							if yu.lsacharged
								ghs.color = YuLocalRandom(SKINCOLOR_SUPERSILVER3, SKINCOLOR_SUPERGOLD2, s)
								ghs.colorized = true
								ghs.scale = (s.scale*(11+d))/YuLocalRandom(10,14,s)						
							elseif yu.hypersonic
								ghs.color = ((p.yuemeraldcolors2[yu.hypercolor])+4)-d
								ghs.colorized = true
							elseif p.rings < 10
								ghs.color = SKINCOLOR_RED+d
								ghs.colorized = true
							else
								ghs.colorized = false
							end				
						end
					else --MAIN AURA, emulating SA1's aura!


						if not (yu.yuauragold and yu.yuauragold.valid) --The center one!
							yu.yuauragold = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUAURAGOLD)
						end	
						local ghs = yu.yuauragold
						local ogframe = yu.yuauragold.frame
					
						for d = 0,maxaura
							if d != 0
							ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUAURAGOLD) --ANOTHER TWO.
								if d < 3
								ghs.frame = ogframe|FF_FULLBRIGHT|TR_TRANS80 & ~TR_TRANS30 & ~TR_TRANS50
								else
								ghs.frame = ogframe|FF_FULLBRIGHT|TR_TRANS90
								end
							elseif not maxaura
								ghs.frame = $ & ~FF_TRANSMASK
							end
							ghs.spriteyoffset = yu.superoffset-5*FRACUNIT
							ghs.scale = (s.scale*(11+d))/YuLocalRandom(11,14,s)
							DoYuAura(ghs, p, s, yu)
							if yu.lsacharged
								ghs.color = YuLocalRandom(SKINCOLOR_SUPERSILVER3, SKINCOLOR_SUPERGOLD2,s)
								ghs.colorized = true
								ghs.scale = (s.scale*(11+d))/YuLocalRandom(10,14,s)
							elseif yu.hypersonic
								ghs.color = ((p.yuemeraldcolors2[yu.hypercolor])+4)-d
									if ghs.color <= SKINCOLOR_SUPERSILVER5
									ghs.color = SKINCOLOR_SUPERSKY5-d
									elseif (ghs.color <= SKINCOLOR_SUPERORANGE5 and ghs.color > SKINCOLOR_SUPERORANGE1)
									ghs.color = SKINCOLOR_PURPLE-d
									end
								ghs.colorized = true
							elseif p.rings < 10
								ghs.color = SKINCOLOR_RED+d
								ghs.colorized = true
							else
								ghs.colorized = false
							end				
						end
					end							
				  end
				  
				else
					if p.powers[pw_carry]
				 		return
				 	end
					--Blue Bolt Boost Aura. The true first "boost" aura!

						if not (yu.yuaurabb and yu.yuaurabb.valid) --The center one!
							yu.yuaurabb = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUAURABLUEBOLT)
						end			
						local ghs = yu.yuaurabb
						local ogframe = yu.yuaurabb.frame
					
						for d = 0,maxaura
							if d != 0
							ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUAURABLUEBOLT) --ANOTHER TWO.
								if d < 3
								ghs.frame = ogframe|FF_FULLBRIGHT|TR_TRANS80 & ~TR_TRANS50
								else
								ghs.frame = ogframe|FF_FULLBRIGHT|TR_TRANS90
								end
							elseif not maxaura
								ghs.frame = $|TR_TRANS20 & ~FF_TRANSMASK							
							end
							ghs.scale = s.scale*(11+d)/10
							DoYuAura(ghs, p, s, yu, true, true)
							if yu.hypersonic
								ghs.color = SKINCOLOR_ICY+d
								ghs.colorized = true
							elseif p.rings < 10
								ghs.color = SKINCOLOR_AZURE+d
								ghs.colorized = true
							else
								ghs.colorized = false
							end				
						end
				end
end)

--You can use the Far Thok here.

rawset(_G, "YuFarThok", function(p, s, yu, homecancel)
			if yu.spin and (yu.spin < 4)
			
						yu.hominganim = 0 yu.hominganim2 = 0 yu.hominganim3 = 0
						yu.homingtrick = 0
						
						if homecancel --Cancel your homing properties if there's target nearby.
							yu.hominganimstart = 12
							p.homing = 0
							yu.prehomecancel = 0
							s.angle = yu.prehomeangle
							p.drawangle = yu.prehomeangle
							if (yu.lastz > s.z-100*s.scale) and (yu.lastz < s.z+100*s.scale)
								s.z = yu.lastz
							end
							yu.homingsetup = false
							yu.hominganim = 0 yu.hominganim2 = 0 yu.hominganim3 = 0
						end
						
						if not (p.pflags & PF_ANALOGMODE)
						p.drawangle = s.angle
						end
						
						p.pflags = $|PF_THOKKED & ~PF_JUMPED & ~PF_SPINNING & ~PF_STARTDASH
						s.state = S_PLAY_FLOAT_RUN
						yu.farthok = 9
						yu.sa2jumpdone = true
						yu.edgestop = 0
						yu.noairdrag2 = 18
						S_StartSound(s, sfx_rail2)
						P_SpawnGhostMobj(s)
						S_StopSoundByID(s, sfx_yuvoc1)
						yu.frictionlock = 9
						yu.runfriction = FRACUNIT
						s.friction = FRACUNIT
						yu.fallbuffer = 0
						yu.fallbuffer2 = 0
							if (yu.spin < 2) --Correction for our buffer feature.
								yu.spin = 2
							end
							if (yu.jump < 2)
								yu.jump = 2
							end	
							if (s.eflags & MFE_UNDERWATER) --No underwater haxx. It's slowed down.										
								P_InstaThrust(s, s.angle, (26+yu.hominganimstart)*s.scale)
								yu.noairdrag2 = 3
									if (s.eflags & MFE_GOOWATER)
									P_SetObjectMomZ(s, FRACUNIT) --Up we go!
									else
									P_SetObjectMomZ(s, -s.scale)
									end
							else --Later input means a less efficient far-thok!
								P_InstaThrust(s, s.angle, (42+yu.hominganimstart)*s.scale)
								P_SetObjectMomZ(s, 0)
							end
							yu.hominganimstart = 0
							
							if yu.hypersonic or yu.mysticsuper --Ridiculously OP Far Thok for Hyper Sonic.
								s.momx = $*3 --Three times the speed!
								s.momy = $*3
								P_YuQuake(p, 60*FRACUNIT, 9)							
								if not yu.superaura --Instant superaura!
									yu.superaurabuild = 16
								end
								if yu.hypersonic
									P_NukeEnemies(s, s, 1440*s.scale) --BOOM!
									P_YuFlash(p, PAL_WHITE, 3) --FLASH!
									S_StartSound(s, sfx_bkpoof) --KAPOW!
								elseif yu.mysticsuper
									S_StartSound(s, sfx_smach)
									yu.hudboost = 1
								end
								S_StartSound(s, sfx_zoom) --ZOOM!
							end
							if ((s.flags2 & MF2_TWOD) or twodlevel) --2D mode is a pain in the ass.
								s.momy = 0
							end				
			end
end)

--Are we dead or faking it?

rawset(_G, "YuDeathState", function(s, p, yu)

		yu.nosarun4 = 3
		YuNoControls(p, yu, true)
		p.pflags = $ & ~PF_JUMPED & ~PF_SPINNING & ~PF_THOKKED & ~PF_STARTDASH
		
		if yu.tauntdead
			//	s.state = S_PLAY_DEAD
			//	s.flags = $|MF_BOUNCE
			//	YuDeathAnim(s, p, yu)
			if yu.direct or s.state != S_PLAY_DEAD or ((p.speed > s.scale) or s.momz)
			s.state = S_PLAY_FALL
			p.pflags = $ & ~PF_INVIS
			yu.tauntdead = false
			end
			return
		end
				
		if not s.health
				if not yu.downtheholedeath --Didn't fall into a pit?
					if yu.drowning --Drowning
						if yu.deathstart
						S_StartSound(s, sfx_splash)
						yu.drownanim = 90
						yu.superauraframe = A
						P_YuQuake(p, 9*FRACUNIT, 32)
						else
							if yu.drownanim
							yu.drownanim = $-1
								if (p.deadtimer > 5)
								p.deadtimer = 5
								end
								P_SetObjectMomZ(s, FRACUNIT/6, true)
							end
						YuDeathAnim(s, p, yu)
						end
						s.momx = $*80/81 s.momy = $*80/81 s.momz = $/2	
						
					
					elseif yu.burning --Died to Lava or Fire?	
					
						yu.burning = $-1
						if yu.deathstart
						S_StartSound(s, sfx_s3k48)
						P_YuQuake(p, 12*FRACUNIT, 7)
						P_YuFlash(p, PAL_NUKE, 2)
						YuVoice(p, s, yu, sfx_yuvocf)
							--Lava or random fire?
							if P_PlayerTouchingSectorSpecial(p, 1, 3) and P_IsObjectOnGround(s) --You fell in lava!
									for d = 1,8
										local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_SPINDUST)
										P_InstaThrust(ghs, ANGLE_45*d, 20*s.scale)
										ghs.scale = s.scale
										ghs.state = S_LAVASPLISH
										ghs.eflags = s.eflags
										ghs.flags = $ & ~MF_NOGRAVITY
										P_SetObjectMomZ(ghs, 7*s.scale)
									end
									for d = 1,16
										local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_SPINDUST)
										P_InstaThrust(ghs, (ANGLE_45/2)*d, 30*s.scale)
										ghs.scale = s.scale
										ghs.state = S_SPINDUST_FIRE1
										ghs.eflags = s.eflags
										ghs.flags = $ & ~MF_NOGRAVITY
										P_SetObjectMomZ(ghs, 14*s.scale)
									end
									s.momz = 0 s.momx = $/4 s.momy = $/4
							else
								P_SetObjectMomZ(s, 6*FRACUNIT)
								if yu.deathangle != nil
									P_InstaThrust(s, yu.deathangle, -10*s.scale)
								else
									P_InstaThrust(s, s.angle, -10*s.scale)
								end
							end
						end
						
						--Death by fire really looks gruesome....
						
						YuDeathAnim(s, p, yu)
						
						if not P_RandomRange(0,5)
							S_StartSound(s, sfx_s1c8)
						end
						if P_PlayerTouchingSectorSpecial(p, 1, 3) and P_IsObjectOnGround(s)
							s.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
							P_SetObjectMomZ(s, -FRACUNIT/4)
						elseif (s.eflags & MFE_UNDERWATER)
							yu.burning = 0
						end
						local ghs = P_SpawnMobj(s.x+(P_RandomRange(-40,40)*s.scale), s.y+(P_RandomRange(-40,40)*s.scale), s.z+(P_RandomRange(-10,40)*s.scale), MT_SPINDUST)
						ghs.scale = s.scale/P_RandomRange(1,5)
						ghs.state = S_SPINDUST_FIRE1
						ghs.eflags = s.eflags
						ghs.scalespeed = $*P_RandomRange(1,2)
						ghs.destscale = $*99
						P_SetObjectMomZ(ghs, P_RandomRange(0,5)*s.scale)

						if not yu.burning --All good things must come to an end.
							yu.bombdeath = true
							s.color = SKINCOLOR_CARBON
							s.colorized = true
							yu.eleccolorized = true
						end						
						
					elseif yu.spacedeath --Suffocated in space?
						if yu.deathstart
							YuVoice(p, s, yu, sfx_yuvocf)
							s.momx = $*6/7 s.momy = $*6/7
								if P_IsObjectOnGround(s)
								s.z = $+(5*s.scale*P_MobjFlip(s))
								end	
								if (s.momz*P_MobjFlip(s) > -FRACUNIT)
								P_SetObjectMomZ(s, 9*FRACUNIT)
								else
								P_SetObjectMomZ(s, 3*FRACUNIT)
								end
							yu.spaceanim = 30
							
						else
						YuDeathAnim(s, p, yu)
							if yu.spaceanim
							s.sprite2 = SPR2_GASP
							s.frame = A
							yu.spaceanim = $-1
							s.momx = $*50/51
							s.momy = $*50/51
							s.momz = $*40/41
								if (yu.spaceanim > 15)
								P_YuQuake(p, 7*FRACUNIT, 2)
								s.spritexscale = FRACUNIT+5500
								s.spriteyscale = FRACUNIT+5500
								elseif s.spritexscale > FRACUNIT and s.spriteyscale > FRACUNIT
								s.spritexscale = FRACUNIT-7000
								s.spriteyscale = FRACUNIT-7000
								s.momz = $/3
								end
								
								if not yu.spaceanim
								s.spriteyscale = FRACUNIT
								s.spritexscale = FRACUNIT
								end
							end
						end
					else
					--REGULAR DEATH ANIMATION
						if yu.deathstart
							P_YuQuake(p, 80*FRACUNIT, 6)
							P_YuFlash(p, PAL_NUKE, 4)
							P_SetObjectMomZ(s, 10*FRACUNIT)
							YuVoice(p, s, yu, sfx_yuvoce)
							if yu.deathangle != nil
								P_InstaThrust(s, yu.deathangle, -15*s.scale)
							else
								P_InstaThrust(s, s.angle, -15*s.scale)
							end
							if yu.electicdeath
							S_StartSound(s, sfx_buzz2)
							end
						elseif (s.eflags & MFE_UNDERWATER) and not yu.electricdeath --Switch to drowning death.
							s.momx = $/4
							s.momy = $/4
							yu.drowning = true
							yu.drownanim = 0
							yu.drownanim2 = 17
							S_StartSound(s, sfx_gloop)
							S_StartSound(s, sfx_cdfm38)
							P_YuQuake(p, 80*FRACUNIT, 3)						
						end
						YuDeathAnim(s, p, yu)
						
						if yu.electricdeath
						yu.electricdeath = $-1
							if p.deadtimer > 30
							p.deadtimer = 30
							end
							if yu.electricdeath == 53
							S_StartSound(s, sfx_buzz2)
							end
							
							if (yu.electricdeath % 2 == 0)
							s.color = SKINCOLOR_SUPERGOLD2
							s.colorized = true
							yu.eleccolorized = true
							else
							s.color = SKINCOLOR_JET
							s.colorized = true
							yu.eleccolorized = true
							end
							
							local ghs = P_SpawnGhostMobj(s)
							P_InstaThrust(ghs, P_RandomRange(1,359)*ANG1, 6*s.scale)
							P_SetObjectMomZ(ghs, P_RandomRange(3,-2)*s.scale, true)
							ghs.momx = $+s.momx
							ghs.momy = $+s.momy
							ghs.momz = $+s.momz
							ghs.rollangle = s.rollangle+(P_RandomRange(-40,40)*ANG1)
							ghs.spriteyscale = $*4/P_RandomRange(1,10)
							ghs.spritexscale = $*4/P_RandomRange(1,10)
								local elecc={SKINCOLOR_SUPERGOLD2, SKINCOLOR_SUPERTAN5, SKINCOLOR_SUPERGOLD4, SKINCOLOR_JET, SKINCOLOR_SUPERSILVER1}
								ghs.color = elecc[P_RandomRange(1,5)]
								ghs.colorized = true
								ghs.scale = $*10/P_RandomRange(10,6)
								ghs.destscale = $*99
							
							local ghs = P_SpawnMobj(s.x+(P_RandomRange(-70,70)*s.scale), s.y+(P_RandomRange(-70,70)*s.scale), s.z+(P_RandomRange(-20,30)*s.scale), MT_YUTHOK)
								if ghs and ghs.valid
									ghs.blendmode = AST_ADD
									ghs.colorized = true
									ghs.color = P_RandomRange(SKINCOLOR_SUPERORANGE3, SKINCOLOR_SUPERGOLD1)
									ghs.scale = $*P_RandomRange(2,6)
									ghs.rollangle = s.rollangle+(P_RandomRange(-90,90)*ANG1)
									ghs.state = S_WATERZAP
									ghs.tics = $+P_RandomRange(2,15)
									ghs.frame = $|FF_FULLBRIGHT
								end
							s.spriteyscale = FRACUNIT+P_RandomRange(-6000,6000)
							s.spritexscale = FRACUNIT+P_RandomRange(-6000,6000)
							
								if not yu.electricdeath
								s.spriteyscale = FRACUNIT
								s.spritexscale = FRACUNIT
								s.color = p.skincolor
								s.colorized = false
								yu.bombdeath = true --This part is a bit gruesome, lemme know if you want it gone.
								YuVoice(p, s, yu, sfx_yuvocf)
								end
								
						end
						if yu.bombdeath	and (leveltime % 2 == 0)			
							local ghs = P_SpawnMobj(s.x+P_RandomRange(35,-35)*s.scale, s.y+P_RandomRange(35,-35)*s.scale, s.z+P_RandomRange(30,-10)*s.scale, MT_SMOKE)
							ghs.scale = $/P_RandomRange(1,5)
							ghs.destscale = $*99
							ghs.scalespeed = $*P_RandomRange(1,3)
							P_SetObjectMomZ(ghs, P_RandomRange(2,8)*FRACUNIT, true)
							s.color = SKINCOLOR_CARBON
							s.colorized = true
							yu.eleccolorized = true
						end
					end
				else
					yu.ragdoll = yu.ragdoll and $+(ANG2*2) or (ANG2)
					s.rollangle = yu.ragdoll
				end
		end
end)


--Death animation ragdoll physics.

rawset(_G, "YuDeathAnim", function(s, p, yu)
	if yu.downtheholedeath
	return
	end
	if P_CheckDeathPitCollide(s) --Transition into falling-to-death
	s.flags = $|MF_NOCLIPHEIGHT
		if s.momz*P_MobjFlip(s) > -22*FRACUNIT
		s.momz = -22*FRACUNIT*P_MobjFlip(s)
		end
	return
	end
 			if yu.drowning --Drowning animation is complex because it needed to replace a whole animation for Metalwario.
				if yu.drownanim
					if (yu.superauraframe >= H)
					yu.superauraframe = A
					end
					if (yu.drownanim > 30)
						if P_IsObjectOnGround(s) --Never touch the ground during this.
							s.z = $+(5*s.scale*P_MobjFlip(s))
						end
						if (yu.drownanim > 60)
							yu.superauraframe = $+1	
							s.sprite2 = SPR2_RUN_
							if (s.eflags & MFE_UNDERWATER)
							P_SetObjectMomZ(s, FRACUNIT*2, true)
							end
						else
							if (s.eflags & MFE_UNDERWATER)
							P_SetObjectMomZ(s, FRACUNIT, true)
							end
							if (yu.drownanim > 54)
							yu.superauraframe = $+1
							else
								if (yu.drownanim > 44)
									if yu.drownanim % 2 == 0
									yu.superauraframe = $+1
									end
								elseif yu.drownanim % 4 == 0
								yu.superauraframe = $+1
								end
							end
						s.sprite2 = SPR2_WALK
						end
						
						if (yu.drownanim % 2 == 0) --Bubbles!
						local rng = P_RandomRange(sfx_bubbl1, sfx_splash)
						S_StartSound(s, rng)
					
						local ghs = P_SpawnMobj(s.x+(P_RandomRange(-42,42)*s.scale), s.y+(P_RandomRange(-42,42)*s.scale), s.z+(P_RandomRange(-15,15)*s.scale), MT_SPINDUST)
						ghs.scale = s.scale*2/P_RandomRange(1,5)
						ghs.state = S_SPINDUST_BUBBLE1
						ghs.eflags = s.eflags
						P_SetObjectMomZ(ghs, P_RandomRange(0,5)*s.scale)
						P_InstaThrust(ghs, s.angle+ANGLE_180, P_RandomRange(0,5)*s.scale)
						end
						
						s.frame = yu.superauraframe
						
					else --Gasping animation
					
						if yu.drownanim > 21
							yu.ragdoll = yu.ragdoll and $+((ANG1)*yu.lsaglow) or (ANG1*yu.lsaglow)
							s.sprite2 = SPR2_RIDE
						else
							yu.ragdoll = yu.ragdoll and $+((ANG2)*yu.lsaglow) or (ANG2*yu.lsaglow)
							s.sprite2 = SPR2_GASP
							P_SetObjectMomZ(s, -FRACUNIT/2, true)
						end
						s.frame = A
						s.rollangle = yu.ragdoll
							if (yu.drownanim == 17) --Big exhale! SA1 was scarily detailed with this! ..other than having no mouth, but we'll just assume one for this.
						//	P_YuFlash(p, PAL_NUKE, 3)
							S_StartSound(s, sfx_cdfm38)
							s.rollangle = 0
							yu.ragdoll = 0
								P_YuQuake(p, 80*FRACUNIT, 3)
								
								for d = 1,16
								local rng = P_RandomRange(sfx_bubbl1, sfx_splash)
								S_StartSound(s, rng)
									if d == 1
										local ghs2 = P_SpawnMobj(s.x+FixedMul(12*s.scale,cos(s.angle)), s.y+FixedMul(12*s.scale,sin(s.angle)), s.z+(52*s.scale*P_MobjFlip(s)), MT_EXTRALARGEBUBBLE)
										ghs2.eflags = s.eflags
										ghs2.scale = s.scale
									else
										local ghs2 = P_SpawnMobj(s.x+FixedMul(12*s.scale,cos(s.angle)), s.y+FixedMul(12*s.scale,sin(s.angle)), s.z+(52*s.scale*P_MobjFlip(s)), P_RandomRange(MT_SMALLBUBBLE, MT_MEDIUMBUBBLE))
										ghs2.eflags = s.eflags
										ghs2.scale = s.scale
										P_SetObjectMomZ(ghs2, P_RandomRange(2,15)*s.scale)
										P_InstaThrust(ghs2, s.angle+P_RandomRange(-34,34)*ANG1, P_RandomRange(1,24)*s.scale)
									end
								end
								
							else
								if (yu.drownanim % 3 == 0) --MORE Bubbles!
								local rng = P_RandomRange(sfx_bubbl1, sfx_splash)
								S_StartSound(s, rng)
								end
					
								local ghs = P_SpawnMobj(s.x+FixedMul(12*s.scale,cos(s.angle)), s.y+FixedMul(12*s.scale,sin(s.angle)), s.z+(45*s.scale*P_MobjFlip(s)), P_RandomRange(MT_SMALLBUBBLE, MT_MEDIUMBUBBLE))
								ghs.scale = s.scale*3/P_RandomRange(1,6)
								ghs.eflags = s.eflags
								P_SetObjectMomZ(ghs, P_RandomRange(1,8)*s.scale)
								P_InstaThrust(ghs, s.angle+P_RandomRange(-60,60)*ANG1, P_RandomRange(1,24)*s.scale)
							end	
							if not yu.drownanim
							yu.drownanim2 = 1
							yu.ragdoll = yu.ragdoll and $+((ANG30)*yu.lsaglow) or (ANG30*yu.lsaglow)
							s.rollangle = yu.ragdoll
							end
					end
				else --Idle.
						s.sprite2 = SPR2_DEAD
						s.frame = A
						if P_IsObjectOnGround(s) or (s.z < s.floorz+FRACUNIT*5)
						yu.ragdoll = 0
						s.rollangle = 0
						else
						
							if yu.drownanim2
							yu.drownanim2 = $-1
							yu.ragdoll = yu.ragdoll and $+(ANG2*2*yu.lsaglow) or (ANG10*yu.lsaglow)
								for d = 1,2
									local ghs2 = P_SpawnMobjFromMobj(s, 0, 0, 0, P_RandomRange(MT_SMALLBUBBLE, MT_MEDIUMBUBBLE))
									ghs2.eflags = s.eflags
									ghs2.scale = s.scale
									P_SetObjectMomZ(ghs2, P_RandomRange(-10,6)*s.scale)
									P_InstaThrust(ghs2, P_RandomRange(0,359)*ANG1, P_RandomRange(10,35)*s.scale)
								end
							end
						
							if (((yu.ragdoll/ANG1) >= 176) or ((yu.ragdoll/ANG1) <= -176))
							yu.ragdoll = ANGLE_180
							else//if (s.eflags & MFE_UNDERWATER)
							yu.ragdoll = yu.ragdoll and $+(ANG1*yu.lsaglow) or (ANG1*yu.lsaglow)
							end
						s.rollangle = yu.ragdoll
				//		p.drawangle = yu.ragdoll-(ANGLE_90*yu.lsaglow)
							if (s.eflags & MFE_UNDERWATER)
							s.z = $+(FRACUNIT*P_MobjFlip(s))
						//	P_SetObjectMomZ(s, 3*FRACUNIT)
							end
						end					
							if not (yu.corpse and yu.corpse.valid)
								yu.corpse = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUTHOK)
								local corpse = yu.corpse
								corpse.flags = s.flags
								corpse.skin = "adventuresonic"
								corpse.sprite = SPR_PLAY
								corpse.sprite2 = SPR2_DEAD
								corpse.frame = A
								corpse.eflags = s.eflags
								corpse.angle = p.drawangle 
								corpse.scale = s.scale
								corpse.rollangle = s.rollangle
								corpse.colorized = s.colorized
								corpse.color = s.color
								s.flags2 = $|MF2_DONTDRAW
							else --Keep it around.
								s.flags2 = $|MF2_DONTDRAW
								yu.corpse.flags = s.flags
								yu.corpse.rollangle = s.rollangle
								P_TeleportMove(yu.corpse, s.x, s.y, s.z)
								yu.corpse.color = s.color
								yu.corpse.colorized = s.colorized
								yu.corpse.tics = 3
							end					
				end

				
			--Okay!! So NOT drowning, then. Do other death animation!
				
 			else
 						s.flags2 = $ & ~MF2_DONTDRAW & ~MF2_SHADOW
						
						if P_PlayerTouchingSectorSpecial(p, 1, 3) --Touching Lava.				
							if (yu.burning < 3) 
							yu.burning = 90
							s.flags = $|MF_NOCLIPHEIGHT & ~MF_NOCLIP & ~MF_SHOOTABLE
							P_SetObjectMomZ(s, -FRACUNIT)						
							end
						s.flags = $|MF_NOCLIPHEIGHT & ~MF_NOCLIP & ~MF_SHOOTABLE					
 						elseif P_CheckDeathPitCollide(s)
						s.flags = $|MF_NOCLIPHEIGHT & ~MF_NOCLIP & ~MF_SHOOTABLE
						else
 						s.flags = $ & ~MF_NOCLIPHEIGHT & ~MF_NOCLIP & ~MF_SHOOTABLE
						end
						
						if P_IsObjectOnGround(s)
							s.sprite2 = SPR2_DEAD
							s.frame = A
							s.rollangle = 0
							s.momx = $*21/22
							s.momy = $*21/22
							if (p.deadtimer > 70) and not P_CheckDeathPitCollide(s)
								if not (yu.corpse and yu.corpse.valid)
								yu.corpse = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUTHOK)
								local corpse = yu.corpse
								corpse.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
								corpse.skin = "adventuresonic"
								corpse.sprite = SPR_PLAY
								corpse.sprite2 = SPR2_DEAD
								corpse.frame = A
								corpse.eflags = s.eflags
								corpse.angle = p.drawangle 
								corpse.scale = s.scale
								corpse.colorized = s.colorized
								corpse.color = s.color
								else --Keep it around.
								s.flags2 = $|MF2_DONTDRAW
								P_TeleportMove(yu.corpse, s.x, s.y, s.z)
								yu.corpse.color = s.color
								yu.corpse.colorized = s.colorized
								yu.corpse.tics = 3
								end
							end
							
							if s.x+4*FRACUNIT < yu.lastx or s.x-4*FRACUNIT > yu.lastx --Dust sliding
							or s.y+4*FRACUNIT < yu.lasty or s.y-4*FRACUNIT > yu.lasty
							
							S_StartSound(s, sfx_s3kd1s)
							local ghs = P_SpawnMobj(s.x+P_RandomRange(-30,30)*s.scale, s.y+P_RandomRange(-30,30)*s.scale, s.z, MT_SPINDUST)
							ghs.scale = s.scale
							ghs.color = SKINCOLOR_BEIGE
							ghs.colorized = true
							end
							
							
							yu.lastx = s.x
							yu.lasty = s.y
								if yu.ragdoll
									if not yu.burning and not yu.spacedeath and not yu.drowning
								//	S_StartSound(s, sfx_s3k9b) --dramatic crusher stomp
								//	S_StartSound(s, sfx_s3k81) --Echoing sound
									S_StartSound(s, sfx_cdfm42)
									S_StartSound(s, sfx_s3k5d)
										P_YuQuake(p, 50*FRACUNIT, 3)	
										for d = 1,8
											local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_SPINDUST)
											P_InstaThrust(ghs, ANGLE_45*d, 10*s.scale)
											ghs.scale = s.scale
											ghs.destscale = $*99
											ghs.tics = 1
											ghs.color = SKINCOLOR_BEIGE
											ghs.colorized = true
										end
									end
								yu.ragdoll = nil
								end
						else
							if yu.spacedeath
								s.sprite2 = SPR2_DEAD
								s.frame = A
								yu.ragdoll = yu.ragdoll and $+(ANG2+ANG1) or (ANG2+ANG1)
									if yu.spaceanim
										if not (s.rollangle and (s.rollangle > (ANGLE_90)))
										s.rollangle = yu.ragdoll --Cut further code shenanigans out when you're KO'd.
										end
									else
									yu.ragdoll = $+(ANGLE_45/5)
									s.rollangle = yu.ragdoll
									p.drawangle = yu.ragdoll
									s.momz = $*10/11
									end
							else
								s.sprite2 = SPR2_PAIN
								s.frame = A
								yu.ragdoll = yu.ragdoll and $+((ANG10+ANG1)*yu.lsaglow) or (ANG10*yu.lsaglow)
								s.rollangle = yu.ragdoll --Cut further code shenanigans out when you're KO'd.
							end
						end
			end

end)

--Super Sonic Transform animation!

rawset(_G, "YuSuperTransform", function(p, s, yu)
			yu.supertransform = $-1
			p.charflags = $|SF_CANBUSTWALLS|SF_SUPER
				if yu.supertransformangle != nil
				yu.supertransformangle = $-((ANG1*18)+1930465)
				end
				p.pflags = $|PF_THOKKED|PF_FORCESTRAFE|PF_STASIS & ~PF_STARTDASH & ~PF_SPINNING & ~PF_JUMPED & ~PF_STARTJUMP
				s.state = S_PLAY_SPRING
				s.tics = 3 s.anim_duration = 3
				s.momx = $/3 s.momy = $/3
				yu.startdash = 0
				YuNoControls(p, yu, true)

				if (yu.supertransform < 8)
					s.momz = 0
				elseif yu.supertransform --Animation into Super Sonic!
				
						--You mean the CHAOS EMERALDS?!
						for d = 1,7
							local angadd = (ANG1*51*d)+(yu.supertransform*ANG10)
							local ghs = P_SpawnMobj(s.x+FixedMul(((45+(yu.supertransform*6))*s.scale), cos(angadd)),s.y+FixedMul(((45+(yu.supertransform*6))*s.scale), sin(angadd)),
							s.z+((s.height-(yu.supertransform*s.scale*2)+(d*5*s.scale))*P_MobjFlip(s)), MT_YUTHOK) //-(yu.supertransform*s.scale*2)+(d*10*s.scale)
							
							ghs.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
							ghs.tics = 2
							ghs.eflags = s.eflags
							local FlashMobjC={SKINCOLOR_EMERALD, SKINCOLOR_PURPLE, SKINCOLOR_SKY, SKINCOLOR_RED, SKINCOLOR_GREY, SKINCOLOR_BLUE, SKINCOLOR_SUPERGOLD5}
							ghs.color = FlashMobjC[d]
							ghs.z = YuFlipZ(s, ghs)
							ghs.sprite = SPR_YTK5
							ghs.frame = A|FF_FULLBRIGHT|TR_TRANS20
							
							if yu.hyperpower and (p.rings >= 100)
								ghs.scale = (s.scale*14)/9 --SUPER emeralds!
								ghs.z = $-((10*s.scale)*P_MobjFlip(s))
								local ghs3 = P_SpawnGhostMobj(ghs)
								ghs3.blendmode = AST_ADD
								ghs3.fuse = 6
								if (leveltime % 3 == 0)
								ghs.color = SKINCOLOR_SUPERSILVER1
								ghs3.color = SKINCOLOR_SUPERSILVER1
								end
							else
								ghs.scale = (s.scale*4)/7
							end
							
							
							local ghs2 = P_SpawnMobjFromMobj(ghs, 0, 0, 0, MT_IVSP)
							ghs2.colorized = true
							ghs2.color = ghs.color
							ghs2.scale = ghs.scale*2
							ghs2.blendmode = AST_ADD
							ghs2.frame = P_RandomRange(0,12)|FF_FULLBRIGHT|TR_TRANS50
							
							if yu.supertransform == 8
								ghs2.tics = 14
								ghs2.destscale = $*99
								ghs2.frame = P_RandomRange(0,12)|FF_FULLBRIGHT|TR_TRANS20
								P_SetObjectMomZ(ghs2, 4*FRACUNIT, true)
							else
							ghs2.tics = 2
							end
							
						end				
				
					if (yu.supertransform > 15)
						if (yu.supertransform % 3 == 0) --SAVE THE FRAMES!!
						local num = 4
							if (yu.supertransform % 5 == 0) --YOU'RE GONNA DESTROY THE WHOLE PC, SONIC!
							num = 2
							end
							for d = 1,90,num
								local angadd = yu.presupertransformangle+(ANG2*2*d)
								local ghs = P_SpawnMobj(s.x+FixedMul(((135-yu.supertransform)*s.scale), cos(angadd)),s.y+FixedMul(((135-yu.supertransform)*s.scale), sin(angadd)), s.z, MT_YUTHOK)
								ghs.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
									if (d % 3 == 0)
									ghs.blendmode = AST_ADD
									end
								ghs.tics = 69
								if (d > 40 and d < 50)
								ghs.frame = 27|FF_FULLBRIGHT|TR_TRANS80
								else
								ghs.frame = 27|FF_FULLBRIGHT|TR_TRANS50
								end
								ghs.scale = s.scale
								ghs.eflags = s.eflags
								local FlashMobjC={SKINCOLOR_GOLD, SKINCOLOR_KETCHUP, SKINCOLOR_BROWN, SKINCOLOR_CRIMSON, SKINCOLOR_JET, SKINCOLOR_SUPERGOLD2, SKINCOLOR_ORANGE}			
								ghs.color = FlashMobjC[P_RandomRange(1,7)]
								ghs.z = $-(((150+yu.supertransform)*s.scale)*P_MobjFlip(s))
								P_SetObjectMomZ(ghs, 24*FRACUNIT) 
							end
						end
			
						if (yu.supertransform > 20)
							if yu.supertransform == 30
							S_StartSound(s, sfx_yusfxa)
							end
						local ghs = P_SpawnGhostMobj(s)
						ghs.destscale = $*99
						ghs.blendmode = AST_ADD
						ghs.colorized = true
						ghs.color = SKINCOLOR_SUPERGOLD1
						ghs.destscale = ghs.scalespeed+1
						s.momx = 0 s.momy = 0
				
						local ghs = P_SpawnGhostMobj(s)
						ghs.destscale = $*99
						ghs.blendmode = AST_ADD
						ghs.colorized = true
						ghs.tics = 2
						ghs.scale = s.scale*6/5
						ghs.color = SKINCOLOR_SUPERGOLD5
						ghs.flags2 = $|MF2_SHADOW
						P_TeleportMove(ghs, s.x+s.momx, s.y+s.momy, s.z+s.momz)
						end
						
					end			
					if yu.supertransform == 20 or yu.supertransform == 14
					s.momz = $*10/13
					end			
				end
				if yu.supertransform and (yu.supertransform <= 16) --Alright, sick of it, let's force this!
					s.sprite2 = SPR2_TRNS
					if (yu.supertransform > 13)
						s.frame = I
					elseif (yu.supertransform > 11)
						s.frame = J
					elseif (yu.supertransform > 6)
						s.frame = K
					elseif (yu.supertransform > 4)
						s.frame = M
					elseif (yu.supertransform > 2)
						s.frame = N
					else
						s.frame = O
					end
				end					
								
				if not yu.supertransform
				yu.supertransformangle = nil
				yu.forceyuangletimer = 0
					if P_IsObjectOnGround(s)
					s.z = $+5*(s.scale*P_MobjFlip(s))
					end
				p.pflags = $|PF_JUMPED & ~PF_FORCESTRAFE & ~PF_STARTDASH & ~PF_SPINNING & ~PF_STARTJUMP	& ~PF_THOKKED
				yu.superaura = 0
				yu.superaurabuild = 0
				p.speed = 0
				yu.lsaattack = 1
				P_RadiusAttack(s, s, 300*FRACUNIT)
				P_DoSuperTransformation(p)
				S_StopSoundByID(s, sfx_supert)
				YuVoice(p, s, yu, sfx_yuvoc7, true)
				S_StartSound(s, sfx_yusfx9)
				yu.supersonic = true
				yu.superflash = 9*FRACUNIT
				yu.superflashd = 1
				yu.flighthoming = 0
				s.flags = $ & ~MF_NOGRAVITY
				yu.changedcharflags = 10
				s.tics = $+5
				s.anim_duration = $+5
					--Hyper Sonic? We'll need 100 rings.
					if yu.hyperpower and (p.rings >= 100)
						if p.isxmomentum
						S_StartSound(s, sfx_htrns)
						end
						if yu.hypermemories
						yu.hypermemories = 0
						end
						P_YuQuake(p, 50*FRACUNIT, 33)
						P_YuFlash(p, PAL_WHITE, 11)
						P_NukeEnemies(s, s, 1536*FRACUNIT)

						yu.hypersonic = true

						if not yu.noflashes
							S_StartSound(s, sfx_bkpoof)
							S_StartSound(s, sfx_brakrx)
							for d = 1,5
							local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUTHOK)
							ghs.scale = s.scale/d
							ghs.destscale = $*999
							ghs.scalespeed = $*d
							ghs.tics = 40 ghs.fuse = 40
							ghs.color = SKINCOLOR_SUPERSILVER3+(d*5) --RAINBOOOOOW!!
							end
						end
					end
					yu.lsaattack = 0
					if (p == consoleplayer) and yu.yumusic
						if S_MusicName() == "YUSUPR" or S_MusicName() == "_super"
						COM_BufInsertText(p, "tunes YUSUPR")
						S_ChangeMusic("YUSUPR", true, p)
						S_StartMusicCaption("Live and Learn", 210, p)
						S_SetMusicPosition(1040)
						end
					end
				end
				if p.powers[pw_carry] --Somebody's trying to break it, abort.
					yu.supertransform = 0
					s.flags = $ & ~MF_NOGRAVITY
					p.pflags = $ & ~PF_FORCESTRAFE
					yu.supertransformangle = nil
					yu.forceyuangletimer = 0
					if (p == consoleplayer)
						if S_MusicName() == "YUSUPR" or S_MusicName() == "_super"
						COM_BufInsertText(p, "tunes -default")
						end
					end
				end
end)

--Putting this here to not clog main thinker.

rawset(_G, "YuSuperFlight", function(p, s, yu)
	p.pflags = $|PF_CANCARRY --Carry players! Looks silly, but why not!
	
				if (p == displayplayer) --Only spawn this for yourself! Save processing power in netgames.
					for d = -4,4
					local ghs = P_SpawnMobj(
					s.x+(YuLocalRandom(1200,-1200,s)*s.scale)+(s.momx*25),
					s.y+(YuLocalRandom(1200,-1200,s)*s.scale)+(s.momy*25),
					s.z+((YuLocalRandom(800,-400,s)*s.scale*P_MobjFlip(s)))+(s.momz*5),
					MT_THOK)
						ghs.momx = s.momx/-2
						ghs.momy = s.momy/-2
						ghs.momz = s.momz/-2
						ghs.tics = 90
						ghs.fuse = 60
						if (leveltime % 2 == 0)
						ghs.scale = s.scale/3
						elseif (leveltime % 3 == 0)
						ghs.scale = s.scale/5
						else
						ghs.scale = s.scale/2
						end
						ghs.sprite = SPR_PRTL
						ghs.frame = A|FF_FULLBRIGHT
						ghs.eflags = s.eflags
						P_SetObjectMomZ(ghs, 3*FRACUNIT, true)
						if (p.rings < 10)
						ghs.color = SKINCOLOR_CRIMSON
						ghs.colorized = true
						ghs.flags2 = MF2_SHADOW
						end
					end
				end
					
				 if not P_IsObjectOnGround(s)
				 
				 	yu.hominganimstart = 0
					yu.hominganim = 0 yu.hominganim2 = 0 yu.hominganim3 = 0
					yu.sa2jumpdone = true
					s.flags = $|MF_NOGRAVITY
					yu.nogravity = 2
					p.scoreadd = 0
					p.normalspeed = 32*FRACUNIT
					p.pflags = $|PF_THOKKED|PF_JUMPDOWN|PF_USEDOWN & ~PF_JUMPED & ~PF_STARTDASH & ~PF_SPINNING
					if yu.flightroll
						yu.flightroll = $-1
						if yu.flightroll < 5 and ((p.panim == PA_ROLL) or (p.panim == PA_JUMP))
							s.state = S_PLAY_WALK
							yu.flightroll = 0
						end
					end					
					if not yu.flighthoming
						if (p.speed > 38*s.scale)
						YuWindSpawn(p, s, yu)
							if (p.speed > 63*FRACUNIT)
								s.momx = $*50/51
								s.momy = $*50/51
							end
						end					
						if (yu.direct > 2)
														
								if (p.speed < 10*FRACUNIT) --Accelerate a little faster initially.
								local uw = 1
									if (s.eflags & MFE_UNDERWATER)
									uw = 2
									end
									P_Thrust(s, yu.turnang, 14000/uw)
								end								
								 --Air flying controls!		
						

								local premomx = s.momx
								local premomy = s.momy
								local momang = R_PointToDist2(s.x, s.y, s.x+s.momx, s.y+s.momy)
								local xadd = P_ReturnThrustX(s,yu.turnang, momang)+p.cmomx
								local yadd = P_ReturnThrustY(s, yu.turnang, momang)+p.cmomy			
								if (xadd or yadd)
								P_InstaThrust(s, R_PointToAngle2(s.x-s.momx,s.y-s.momy, s.x+xadd, s.y+yadd), momang)
								end				
								for d = 1,4
									s.momy = $/2+(premomy/2)
									s.momx = $/2+(premomx/2)
								end
						else
							s.momx = $*20/21
							s.momy = $*20/21
							if yu.superflyrun and (p.speed >= 8*FRACUNIT) --Cancel to walk!
							and ((p.panim == PA_WALK) or (p.panim == PA_RUN))
							s.state = S_PLAY_FLOAT
							yu.superflyrun = 0
							end
						end
						
						if p.yumenutable
						or ((s.state >= S_PLAY_SUPER_TRANS1) and (s.state <= S_PLAY_SUPER_TRANS6))
							s.momx = 0
				 			s.momy = 0
							s.state = S_PLAY_STND
						else				
							if yu.jump and not (yu.spin > 1) 
								YuSuperAura(p, s, yu, 1)
								yu.spin = 0
								if yu.jump == 1 --Initial upwards burst.
								yu.superflyrun = 3
								S_StartSound(s, sfx_yusfxb)
									P_YuQuake(p, 9*FRACUNIT, 3)
									if (s.momz*P_MobjFlip(s) < 5*s.scale)
									P_SetObjectMomZ(s, 6*FRACUNIT, false)
									end
								
									local ghs = P_SpawnGhostMobj(s)
									ghs.blendmode = AST_ADD
									ghs.colorized = true
									YuFlightHomingAttack(p, s, yu)
								end
							
								if not (s.momz*P_MobjFlip(s) > 15*s.scale)
								P_SetObjectMomZ(s, FRACUNIT/2, true)
								end
							elseif yu.spin and not (yu.jump > 1)
							
								local flystop = false 
								if yu.flyswitchdisabled 
									if (s.eflags & MFE_VERTICALFLIP)
										if (s.z+(17*s.scale) > s.ceilingz)
										flystop = true
										end
									elseif (s.z-(8*s.scale) < s.floorz)
										flystop = true
									end
								end
								
								YuSuperAura(p, s, yu, 2)
								yu.jump = 0
								if yu.spin == 1 --Initial downwards burst
								S_StartSound(s, sfx_yusfxb)
								yu.superflyrun = 3
									P_YuQuake(p, 9*FRACUNIT, 3)
									if (s.momz*P_MobjFlip(s) > -6*s.scale) and not flystop
										P_SetObjectMomZ(s, -7*FRACUNIT, false)
									end
									local ghs = P_SpawnGhostMobj(s)
									ghs.blendmode = AST_ADD
									ghs.colorized = true
									YuFlightHomingAttack(p, s, yu)
								end	
								if flystop
									s.momz = 0
								elseif not (s.momz*P_MobjFlip(s) < -18*s.scale)
									P_SetObjectMomZ(s, -FRACUNIT/2, true)
								end
							else
								if ((s.momz >= -s.scale) and (s.momz <= s.scale))
									s.momz = 0
								else
									s.momz = $*30/31
								end
							end
						end
						
						--Alright! What's our animation?
						
						if (s.momz*P_MobjFlip(s) > 8*s.scale) and (p.speed < 52*s.scale)
							if yu.jump
								if (s.state != S_PLAY_SPRING)
									s.state = S_PLAY_SPRING
									yu.superflyrun = 3
									if not S_SoundPlaying(s, sfx_yusfxb)
									S_StartSound(s, sfx_yusfxb)
									end
								elseif s.tics > 1
								s.tics = 1
								end					
							end
						elseif (s.momz*P_MobjFlip(s) < -8*s.scale) and (p.speed < 52*s.scale)
							if yu.spin
								if (s.state != S_PLAY_FALL) 
									s.state = S_PLAY_FALL
									yu.superflyrun = 3
									if not S_SoundPlaying(s, sfx_yusfxb)
									S_StartSound(s, sfx_yusfxb)
									end								
								elseif s.tics > 1
								s.tics = 1
								end
							end
						else
							if yu.superflyrun and (p.speed >= 8*FRACUNIT) 
							and ((p.panim == PA_WALK) or (p.panim == PA_RUN))
							
								if (yu.superidleframe > D)
									yu.superidleframe = A
								end					
								s.state = S_PLAY_RUN
								s.frame = yu.superidleframe|FF_FULLBRIGHT
								yu.superidleframe = $+1		
								
							elseif (p.panim == PA_IDLE) or (s.state == S_PLAY_FALL) or (s.state == S_PLAY_SPRING)
							or (p.panim == PA_WALK) or (p.panim == PA_RUN)
							or ((s.state >= S_PLAY_RIDE) and (s.state <= S_PLAY_CLIMB))							
								if (yu.superidleframe > G)
									yu.superidleframe = A
								end	
								if (p.speed >= 8*s.scale) or ((yu.direct > 30) and not p.yumenutable)
									s.state = S_PLAY_WALK
									if (yu.superflow < 77) and (p.speed > 24*FRACUNIT)
									yu.superflow = $+((p.speed/16)/FRACUNIT)
									end
								else
									s.state = S_PLAY_STND
									if yu.superflow and p.speed < 3*FRACUNIT and s.momz > -3*FRACUNIT and s.momz < 3*FRACUNIT
									yu.superflow = $-1
									end									
								end
								
								s.frame = yu.superidleframe|FF_FULLBRIGHT
								yu.superidletics = $-1
								if yu.hypersonic
									 --Stationary frame gfx.
									local ghs = P_SpawnGhostMobj(s)
									ghs.spriteyscale = FRACUNIT+P_RandomRange(0,5000)
									ghs.spritexscale = FRACUNIT+P_RandomRange(0,31000)
									ghs.color = s.player.yuemeraldcolors2[yu.hypercolor]+P_RandomRange(0,3)
									ghs.fuse = 4
									ghs.flags2 = $|MF2_SHADOW
									ghs.colorized = true
									ghs.rollangle = s.rollangle
									ghs.dispoffset = -50
									ghs.blendmode = AST_ADD
									P_SetObjectMomZ(ghs, FRACUNIT*P_RandomRange(2,5))
								end
								
								if yu.superflyrun
								yu.superflyrun = $-1
								end
								
								if yu.superflow
									if (yu.superidletics > 1)
										if ( (yu.superflow > 60)
										or (((p.panim == PA_WALK) and yu.superflow > 38) and p.speed > 24*FRACUNIT) )
										and not ((p.panim == PA_RUN) and (p.speed < 48*FRACUNIT))
											yu.superidletics = 0
										elseif yu.superflow > 45 
											if yu.superidletics > 2
											yu.superidletics = 1
											end
										elseif yu.superflow > 34
											if yu.superidletics > 3
											yu.superidletics = 2
											end
										elseif yu.superflow > 18
											if yu.superidletics > 4
											yu.superidletics = 3
											end
										elseif yu.superidletics > 5
											yu.superidletics = 4
										end
									end
									yu.superflow = $-1
								end
								if yu.superidletics <= 0
									yu.superidleframe = $+1
									yu.superidletics = 7
								end							
							end
						end
						
						if yu.hypersonic
						
							if (p.speed > 4*FRACUNIT or s.momz > 2*FRACUNIT or s.momz < -2*FRACUNIT) --Afterimages when moving.
								local ghs = P_SpawnGhostMobj(s)
								ghs.color =  p.yuemeraldcolors4[yu.hypercolor2]
								ghs.momx = s.momx/4
								ghs.momy = s.momy/4
								ghs.colorized = true
								ghs.rollangle = s.rollangle
								ghs.blendmode = AST_ADD
							else
								 --Stationary frame gfx.
								local ghs = P_SpawnGhostMobj(s)
								ghs.spriteyscale = FRACUNIT+P_RandomRange(0,5000)
								ghs.spritexscale = FRACUNIT+P_RandomRange(0,31000)
								ghs.color = s.color//+P_RandomRange(0,3)
								ghs.fuse = 4
								ghs.flags2 = $|MF2_SHADOW
								ghs.colorized = true
								ghs.rollangle = s.rollangle
								ghs.dispoffset = 30
								ghs.blendmode = AST_ADD
								P_SetObjectMomZ(ghs, FRACUNIT*P_RandomRange(2,5))
							end
						end
						if yu.superflyswitch --Do it again.
						s.state = S_PLAY_SPRING
						end
						
					else --IF yu.flighthoming
					--Custom Basic Homing Attack since SA2 had something like that.
					
						yu.flighthoming = $-1
						yu.flightroll = 26
						s.state = S_PLAY_ROLL

						if (yu.flighthoming > 6) and (p.speed < 10*FRACUNIT) and (s.momz < 3*s.scale and s.momz > -3*s.scale)
						yu.flighthoming = $-6
						end						
						
						local ghs = P_SpawnGhostMobj(s)
						ghs.blendmode = AST_ADD
						ghs.colorized = true
						
						YuJumpBallSpawn(p, s, yu)
						p.pflags = $|PF_JUMPED|PF_THOKKED & ~PF_SPINNING
						
						if not s.target or not (s.target and s.target.valid) or not (s.target and s.target.health) 
						or (s.target and (s.target.flags2 & MF2_FRET))
						or (s.target and not (s.target.flags & MF_SHOOTABLE) and not ((s.target.type == MT_EGGGUARD) or (s.target.type == MT_EGGSHIELD) or (s.target.flags & MF_SPRING)) )
						or (yu.flighthoming <= 0)
						yu.flighthoming = 0
						if p.speed > 120*s.scale
						s.momx = $/-14
							if not (s.flags2 & MF2_TWOD or twodlevel)
							s.momy = $/-14
							end
						else
						s.momx = $/3
						s.momy = $/3
						end
						yu.supertrick = 30
						yu.flighthoming = 0
						if s.target and s.target.valid
						YuLSAimpact(p, s, yu, s.target)
						else
						YuLSAimpact(p, s, yu, s)
						end
						s.target = nil
						yu.lsadeadjump = 0
						P_SetObjectMomZ(s, 6*FRACUNIT, false)
						
							if yu.hypersonic
							YuChaosImpact(p, s, yu)
							end
						
						elseif s.target
						local t = s.target
						s.momx = ( FixedMul(FixedDiv(t.x-s.x, 512*FRACUNIT), FixedDiv(261*FRACUNIT, 3*FRACUNIT/2)))*33/yu.flighthoming
						s.momy = (FixedMul(FixedDiv(t.y-s.y, 512*FRACUNIT), FixedDiv(261*FRACUNIT, 3*FRACUNIT/2)))*33/yu.flighthoming
						s.momz = (FixedMul(FixedDiv(s.target.z-s.z, 512*FRACUNIT), FixedDiv(261*FRACUNIT, 3*FRACUNIT/2)))*33/yu.flighthoming
						end	
					end
				 end		
				 
				--CANCEL CONDITIONS!
				 
				if ((P_IsObjectOnGround(s) or p.powers[pw_carry]) and not yu.flighthoming) or not p.powers[pw_super]
					if yu.flighthoming
					s.momx = $/3
					s.momy = $/3
					end
					if not (yu.flyswitchdisabled and P_IsObjectOnGround(s))
						YuSuperFlyStart(p, s, yu)
					else
						s.z = $+(5*(s.scale*P_MobjFlip(s)))
					end
				end
end)

rawset(_G, "YuFlightHomingAttack", function(p, s, yu)
	if not p.bot and not yu.flighthoming and not p.homing
		s.target = nil --Paranoia
		s.target = P_LookForEnemies(p, true, true)
		if s.target and s.target.valid and not (s.target.type == MT_BIGMINE)
		and not ((FixedHypot(s.target.x-s.x, s.target.y-s.y)) > 4000*FRACUNIT)
		yu.flighthoming = 40
		end
	end
end)

--How to shield. Be aggressive as hell and think in mobjthinker and postthinkframe alike.

rawset(_G, "YuShieldThinker", function(t)
	t.frame = $ & ~FF_TRANSMASK
	t.colorized = true
	
		if (t.type == MT_ATTRACT_ORB)
			if (leveltime % 8 == 0)
				t.color = SKINCOLOR_SKY
				t.frame = $|TR_TRANS50
			else
				t.color = SKINCOLOR_ICY
				t.frame = $|TR_TRANS60
			end
			return --Return if we don't want TR_TRANS60
			
		elseif (t.type == MT_ELEMENTAL_ORB)
			
			if (leveltime % 8 == 0)
				local ghs = P_SpawnMobj(t.x-P_RandomRange(-51, 51)*t.scale, t.y+P_RandomRange(-51, 51)*t.scale, t.z+10*t.scale, MT_THOK)
				ghs.eflags = t.eflags
				ghs.blendmode = AST_ADD
				P_SetObjectMomZ(ghs, 4*FRACUNIT)
				if t.bubble --Alternate.
					t.bubble = false
					ghs.state = S_SPINDUST_FIRE1
					ghs.scale = t.scale/3
					ghs.fuse = 10		
				else
					t.bubble = true
					ghs.state = S_SPINDUST_BUBBLE1
					ghs.fuse = 14
				end			
				ghs.scalespeed = $/3
				ghs.destscale = $*99
			end
			
			t.frame = $|TR_TRANS50 
			t.color = SKINCOLOR_QUAIL
			
			if t.tracer --It's so ugly, pls go away
				if (t.tracer.state < S_ARMA1) or (t.tracer.state > S_ARMA16)
				t.tracer.flags2 = $|MF2_SHADOW
				t.tracer.state = S_ARMA1
				end
			end		
			return
			
		elseif (t.type == MT_THUNDERCOIN_ORB) or (t.type == MT_THUNDERCOIN_SPARK)
		
 			--So Metalwario likes the Sonic Advance attraction shield? Okay, let's do that then!
			
			if t.badassshield
			t.badassshield = false
				if t.tracer and t.tracer.valid
				t.tracer.state = S_MAGN1
				t.tracer.flags2 = $ & ~MF2_SHADOW
				t.tracer.frame = $ & ~FF_TRANSMASK
				t.tracer.colorized = true
				end
			end
			
			t.flags2 = $|MF2_DONTDRAW
			
			if t.tracer and t.tracer.valid
				t.tracer.frame = $|FF_FULLBRIGHT
				t.tracer.color = SKINCOLOR_SAPPHIRE
				t.tracer.blendmode = AST_TRANSLUCENT
			end		
			return 	
			
		elseif (t.type == MT_FORCE_ORB) --This is way too Opaque
		
			if t.myyusonic and t.myyusonic.valid and (t.myyusonic.powers[pw_shield] <= 256)
				if t.badassshield or (t.state < S_PITY1) or (t.state > S_PITY12)
				t.state = S_PITY1
				t.color = SKINCOLOR_SA2SONIC
				t.badassshield = false
				end
			end
			
		elseif (t.type == MT_ARMAGEDDON_ORB) --More subtle, but more stylized. Wanted to a Black Shield reference here.
		
			t.frame = $|TR_TRANS70
			t.blendmode = AST_TRANSLUCENT --AST_SUBTRACT makes for a cool black shield.
			t.color = SKINCOLOR_BLACK
			
			if t.tracer --Dunno what to do to get the second ring. t.tracer.tracer or t.tracer.target ain't it.
				t.tracer.color = SKINCOLOR_YELLOW
				t.tracer.colorized = true
				t.tracer.blendmode = AST_ADD
			end
			return
			
		elseif (t.type == MT_PITY_ORB) --Sweet SA2 shield, baby!
		
			if t.badassshield
			t.badassshield = false
			t.state = S_MAGN1
			end	
			t.color = SKINCOLOR_EMERALD
			t.frame = $|TR_TRANS70
			return
		end
		
	t.frame = $|TR_TRANS60
end)

--NiGHTS special!

rawset(_G, "YuNiGHTSSuperSonic", function(p, s, yu)

			if yu.tutorialchan == nil and leveltime == 230 and not (modeattacking)
			yu.tutorialchan = 250
			end
			if yu.tutorialchan
			yu.tutorialchan = $-1
			end
					if (p.cmd.buttons & BT_USE)
							yu.spin = $+1
					else
							yu.spin = 0
					end
					p.charflags = $ & ~SF_NOSUPERSPIN --Making sure...
					yu.spawnedballalready = false
					yu.alreadytrailed = false
					
						if (s.state == S_PLAY_NIGHTS_TRANS6) and (leveltime % 2 == 0)
							if ((s.frame & ~FF_FULLBRIGHT) >= H)
							s.frame = F
							else
							s.frame = $+1
							end
						end
						if ((s.color >= SKINCOLOR_SUPERGOLD1) and (s.color <= SKINCOLOR_SUPERGOLD5))
							if p.skincolor == SKINCOLOR_ADVANCESONIC --Decree from the Metal overlord
								if not (consoleplayer and consoleplayer.yusonictable and consoleplayer.yusonictable.noflashes)
								and (leveltime % 2 == 0)
									s.color = SKINCOLOR_ADVANCESUPERSONIC2
								else
									s.color = SKINCOLOR_ADVANCESUPERSONIC
								end	
							else
								s.color = SKINCOLOR_SADXSUPERSONIC
							end
						end
						
						if p.powers[pw_flashing] and (s.state == S_PLAY_NIGHTS_STUN) --Pain animation
							yu.rollangle = yu.rollangle and $+ANG30 or ANG30
							s.rollangle = yu.rollangle
							yu.nightscharge = 0
							yu.nightsspin = 0
							yu.spritexscale = FRACUNIT
							yu.spriteyscale = FRACUNIT

						elseif yu.rollangle --End pain animation
							yu.rollangle = 0
							s.rollangle = 0
							
						elseif yu.nightsbrake
						
							yu.nightsbrake = $-1
							p.cmd.forwardmove = 0
							p.cmd.sidemove = 0
							s.rollangle = 0
							s.momx = 0 s.momy = 0 s.momz = 0
							p.powers[pw_nocontrol] = 2
							S_StopSoundByID(s, sfx_nbmper)
							S_StopSoundByID(s, sfx_nxbump)
							S_StopSoundByID(s, sfx_drill1)
							S_StopSoundByID(s, sfx_drill2)
							S_StopSoundByID(s, sfx_yusfx1)
							S_StopSoundByID(s, sfx_yusfx2)						
							
							s.state = S_PLAY_NIGHTS_STAND
							s.sprite2 = SPR2_TRNS|FF_SPR2SUPER
							
							if leveltime % 2 == 0
								s.frame = F
							elseif leveltime % 3 == 0
								s.frame = G
							else
								s.frame = H
							end
							if p.flyangle > 90 and p.flyangle < 270
								p.flyangle = 180
							else
								p.flyangle = 0
							end
							
							
						elseif ((s.state >= S_PLAY_NIGHTS_STAND) and (s.state <= S_PLAY_NIGHTS_DRILL)) or (s.state == S_PLAY_ROLL)
							if p.exiting
							yu.nightsspin = 10
							yu.spin = 50
								for d = 1,4,3
									local ghs = P_SpawnGhostMobj(s)
									ghs.rollangle = P_RandomRange(-50,50)*ANG1
									ghs.blendmode = AST_ADD
									ghs.flags2 = MF2_SHADOW
									ghs.scale = s.scale/2*d
									ghs.z = $-((7*ghs.scale)*P_MobjFlip(s))
								end
							
								if p.exiting == 62
								S_StartSound(s, sfx_yusfxb)
									for d = 1,90
									local ghs = P_SpawnMobj(s.x+FixedMul((128*s.scale), cos(s.angle+(ANG2*2*d))),s.y+FixedMul((128*s.scale), sin(s.angle+(ANG2*2*d))), s.z, MT_YUTHOK)
									ghs.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
										if (d % 2 == 0)
										ghs.blendmode = AST_ADD
										end
									ghs.tics = 69
									ghs.frame = 27|FF_FULLBRIGHT|TR_TRANS70
									ghs.scale = s.scale
									ghs.eflags = s.eflags
									local FlashMobjC={SKINCOLOR_GOLD, SKINCOLOR_RED, SKINCOLOR_CRIMSON, SKINCOLOR_CRIMSON, SKINCOLOR_JET, SKINCOLOR_SUPERGOLD2, SKINCOLOR_KETCHUP}			
									ghs.color = FlashMobjC[P_RandomRange(1,7)]
									ghs.z = $-((150*s.scale)*P_MobjFlip(s))
									P_SetObjectMomZ(ghs, 24*FRACUNIT) 
									end								
								end
							end
						 --Nothing else special happening? Then custom ability, goooo!!
						 
							if (yu.nightscharge > 28) --Don't go TOO overboard with speed/drain! (This is multiplied*4)
								yu.nightscharge = 28
							end
							
							--Allow midair spindash to make NiGHTS stages more fun.
							--This replaces his brake.
							
							if (p.cmd.buttons & BT_USE) and not ((p.cmd.buttons & BT_JUMP) and not yu.nightscharge)
							and (p.drillmeter and (p.drillmeter > 11))
							and not p.exiting

								if not yu.nightscharge
								S_StartSound(s, sfx_yusfx1)
								end
								
								yu.nightsspin = 0
								yu.spriteyscale = 80000
								yu.spritexscale = FRACUNIT/2
								yu.nightscharge = $+1
								yu.superauraframe = $+1
								
								if (yu.superauraframe > H)
								yu.superauraframe = A
								end
								
								YuJumpBallSpawn(p, s, yu)
								s.state = S_PLAY_ROLL
								s.frame = yu.superauraframe|FF_FULLBRIGHT
								
								if yu.nightscharge == 23
									S_StartSound(s, sfx_kc5b)
									local boom = P_SpawnMobjFromMobj(s, 0, 0,0, MT_YUINSTASHIELD)
									boom.scalespeed = $*7
									boom.destscale = s.scale*99
									boom.colorized = true
									boom.blendmode = AST_ADD
									boom.color = SKINCOLOR_SUPERGOLD5							
								end
								for d = 1,4,3
								local ghs = P_SpawnGhostMobj(s)
								ghs.rollangle = P_RandomRange(-50,50)*ANG1
								ghs.blendmode = AST_ADD
								ghs.flags2 = MF2_SHADOW
								ghs.scale = s.scale/2*d
								ghs.z = $-((7*ghs.scale)*P_MobjFlip(s))
								end
								P_RadiusAttack(s, s, 220*s.scale)
							
							elseif yu.nightscharge and not (p.cmd.buttons & BT_USE) --Unleash the spindash!
							and not p.exiting
								local ghs = P_SpawnMobj(s.x+s.momx, s.y+s.momy, s.z+s.momz, MT_NIGHTSBUMPER)
								ghs.sprite = SPR_NULL
								ghs.scale = ($*yu.nightscharge)/14
									if (ghs.scale < s.scale) and not (ghs.scale > 99999)
										ghs.scale = s.scale --Min Power!
									elseif (ghs.scale > 99999)
										ghs.scale = 99999 --Max power!
										S_StartSound(s, sfx_s23c)
										S_StartSound(s, sfx_s23c)
										S_StartSound(s, sfx_yusfxb)
										P_NukeEnemies(s, s, 500*FRACUNIT)
									end
									if (p.cmd.sidemove < 0)
									ghs.threshold = $-185 //Seems about right
									end
								p.bumpertime = 5
								p.drilldelay = 5
								ghs.nsonicb = s
								ghs.fuse = 1
								yu.spriteyscale = FRACUNIT
								yu.spritexscale = FRACUNIT
								s.rollangle = 0
								S_StartSound(s, sfx_kc3c)
									if (yu.nightscharge < 11)
									p.drillmeter = $-11 --Minimum drain. Spamdashing is possible, just not very useful here.
									else
									p.drillmeter = $-yu.nightscharge*4
									end
									if (p.drillmeter < 0) --Don't be glitching below 0, boy
									p.drillmeter = 0
									end
								P_SpawnGhostMobj(s)
								yu.nightsspin = 23 --Start animation!
								if not p.powers[pw_nights_helper]				
									p.powers[pw_nights_helper] = (45+(yu.nightscharge*3)) 
								end
								yu.nightscharge = 0 --AND back to 0!					
				
							elseif yu.nightsspin --If this, do the spin animation!
								if yu.nightsspin > 22
								S_StopSoundByID(s, sfx_nbmper)
								S_StopSoundByID(s, sfx_nxbump)
								S_StopSoundByID(s, sfx_ngskid)
								end
								P_RadiusAttack(s, s, 120*s.scale)
								YuSpinTrail(p, s, yu)

								yu.superauraframe = $+1
								if (yu.superauraframe & ~FF_FULLBRIGHT > H)
								yu.superauraframe = A
								end
								YuJumpBallSpawn(p, s, yu)
								s.state = S_PLAY_ROLL
								s.frame = yu.superauraframe|FF_FULLBRIGHT
								
								yu.nightsspin = $-1
								if not p.exiting
									if not yu.nightsspin
									s.state = S_PLAY_NIGHTS_FLY --Back to normal!
									end							
									if p.flyangle > 90 and p.flyangle < 270
										p.flyangle = (p.cmd.forwardmove*-1)+180
									else
										p.flyangle = p.cmd.forwardmove
									end
								end
							end
							if not p.exiting and not yu.nightsspin and not yu.nightsbrake
							and not (s.state == S_PLAY_NIGHTS_STUN)
							and ((s.state >= S_PLAY_NIGHTS_STAND) and (s.state <= S_PLAY_NIGHTS_DRILL)) or (s.state == S_PLAY_ROLL)
								if (p.cmd.buttons & BT_JUMP) and (p.cmd.buttons & BT_SPIN) --STOP! Sonic time!!
								and (yu.spin < 5)
								
									yu.rollangle = 0
									s.rollangle = 0
									yu.nightscharge = 0
									yu.nightsspin = 0
									yu.spritexscale = FRACUNIT
									yu.spriteyscale = FRACUNIT
									yu.superauraframe = A
									
									S_StartSound(s, sfx_kc4d)
									yu.nightsbrake = 23
									p.powers[pw_nocontrol] = 2
									P_RadiusAttack(s, s, 550*FRACUNIT)
									s.sprite2 = SPR2_TRNS|FF_SPR2SUPER
									s.frame = H
									
									if p.powers[pw_nights_helper] < 30		
										p.powers[pw_nights_helper] = 30
									end									
									
									for d = 0,3		
										local boom = P_SpawnMobjFromMobj(s, 0, 0,0, MT_YUINSTASHIELD)
										boom.scalespeed = $*8+(d*10)
										boom.destscale = s.scale*99
										boom.blendmode = AST_ADD
										boom.color = SKINCOLOR_RED+(d*5)
										boom.colorized = true
										
										local ghs = P_SpawnGhostMobj(s)
										ghs.scalespeed = $*1+(d*10)
										ghs.destscale = s.scale*99
										ghs.blendmode = AST_ADD
										ghs.color = SKINCOLOR_RED+(d*5)
										ghs.colorized = true										
									end
									
									P_YuQuake(p, 30*FRACUNIT, 5)
									S_StartSound(s, sfx_kc5b)
									S_StartSound(s, sfx_s3kbcs)
									for d = 0,8,2
										for i = -6,6,2 --I am actually fluent in this now, how about that?
										local ghs = P_SpawnMobjFromMobj(s, 0, 0, (i*2*s.scale)+(s.height/2), MT_THOK)
										ghs.state = S_IVSP 
										ghs.fuse = 14
										ghs.blendmode = AST_ADD
										ghs.frame = $ & ~FF_TRANSMASK
										ghs.frame = $|TR_TRANS50
										P_InstaThrust(ghs, (ANGLE_45*d), -36*s.scale)
										P_SetObjectMomZ(ghs, i*4*s.scale)
										end
									end	
									
									local ghs = P_SpawnMobj(s.x+s.momx, s.y+s.momy, s.z+s.momz, MT_NIGHTSBUMPER)
									ghs.sprite = SPR_NULL
									ghs.scale = 1
									p.bumpertime = 5
									p.drilldelay = 5
									ghs.nsonicb = s
									ghs.fuse = 1
									yu.spriteyscale = FRACUNIT
									yu.spritexscale = FRACUNIT
									s.rollangle = 0
									
									if p.drillmeter > 50 --Braking ain't free!
									p.drillmeter = $-50
									end
								end								
							end
						end
						
						s.sprite2 = $|FF_SPR2SUPER
						yu.lastx = s.x
						yu.lasty = s.y
						yu.lastz = s.z
end)

--OW, my forehead!! Why do I let you control me?!

rawset(_G, "YuBonk", function(p, s, yu)

						local boom = P_SpawnMobjFromMobj(s, 0, 0, s.height/2, MT_THOK)
						boom.scalespeed = $*5
						boom.destscale = s.scale*99
						boom.angle = p.drawangle+ANGLE_90
						boom.sprite = SPR_YUSO
						boom.frame = G|FF_PAPERSPRITE|FF_FULLBRIGHT|TR_TRANS60
						boom.fuse = 8
						P_SetObjectMomZ(boom, boom.scalespeed*11, true)
						
						yu.speeduprewardfail = false
						yu.speedupreward = false
						yu.bonkeddash = 0
						p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING
						S_StopSoundByID(s, sfx_yusfx5)
						YuVoice(p, s, yu, sfx_yuvoct)
						S_StartSound(s, sfx_cdfm42)
						yu.bonked = 7
						P_YuQuake(p, 24*FRACUNIT, 2)
						
						if yu.lsadashlastangle != nil
							p.drawangle = yu.lsadashlastangle
							s.angle = yu.lsadashlastangle
							P_InstaThrust(s, yu.lsadashlastangle, -21*FRACUNIT)
						else
							P_InstaThrust(s, s.angle, -21*FRACUNIT)
						end
						P_SetObjectMomZ(s, 6*FRACUNIT)
						s.state = S_PLAY_PAIN
						yu.nosarun4 = 7
					
						--Stars!
						for d = 0,8,2
							for i = -6,6,2 --I am actually fluent in this now, how about that?
							local ghs = P_SpawnMobjFromMobj(s, 0, 0, (i*2*s.scale)+(s.height/2), MT_THOK)
							ghs.state = S_NIGHTSSTAR
							ghs.fuse = 14
							P_InstaThrust(ghs, (s.angle-ANGLE_90)+(ANGLE_22h*d), -36*s.scale)
							P_SetObjectMomZ(ghs, i*4*s.scale)
							P_SetObjectMomZ(ghs, 2*s.scale, true)
							ghs.scale = $/4
							ghs.scalespeed = $/2
							end
						end		
end)

--Play a voiceline. If they're disabled or you're underwater, these won't work!

rawset(_G, "YuVoice", function(p, s, yu, sfx, supersonic, meonly)
	if not sfx
	or (yu.supersonic and not supersonic) --Silence is golden....badumtish.
	return
	end
	if (s.eflags & MFE_UNDERWATER) --Can't talk underwater. Unless you have a breathable air bubble, I guess!
	and not ( (p.powers[pw_shield] == (SH_ELEMENTAL) or p.powers[pw_shield] == (SH_ELEMENTAL|SH_FIREFLOWER))
	or (p.powers[pw_shield] == (SH_BUBBLEWRAP) or p.powers[pw_shield] == (SH_BUBBLEWRAP|SH_FIREFLOWER)) )
		S_StartSound(s, sfx_s3k7d)
		for d = 1,(P_RandomRange(1,4))
			local bubble = P_SpawnMobj(s.x-P_RandomRange(-35,35)*s.scale, s.y-P_RandomRange(-35,35)*s.scale, s.z+P_RandomRange(-2,20)*s.scale, MT_SMALLBUBBLE)
			if bubble and bubble.valid
			bubble.scale = s.scale
			end	
		end
	return
	end
	if (consoleplayer and consoleplayer.yusonictable.yuvoice) --Client side voice disabling!
		if not meonly
		S_StartSound(s, sfx)
		else
		S_StartSound(s, sfx, meonly)
		end
	end
end)


--Big SA-menu thinker. Handles menu navigation and changing of stats.

rawset(_G, "YuMenuThinker", function(p, yu, yuog)

--IMPORTANT: YUOG is yusonictable, YU is yusonicmenu!

	--Mobj manipulation. I don't care if people get hit or die, pick a better spot to menu!
	if p.realmo and p.realmo.valid and p.realmo.health
	local s = p.realmo
		yuog.custom2 = 10
		YuNoControls(p, p.yusonictable, true)
		p.pflags = $|PF_FORCESTRAFE
		p.yusonictable.changedcharflags = 10
		if yu.lsadashlastangle == nil
			yu.lsadashlastangle = s.angle
		else
			s.angle = yu.lsadashlastangle
			p.drawangle = yu.lsadashlastangle
		end		
		if P_IsObjectOnGround(s)
			s.momx = 0
			s.momy = 0
			if p.panim == PA_IDLE
			s.tics = 105
			end
		end
	end

	--Menu controls system.
	--If a button or direction is at 1, that means you just tapped it. Higher means you're holding it down.
	--If it's at 0, you're not currently pressing it.

	if (p.cmd.buttons & BT_JUMP)
		yu.jump = $+1
	elseif yu.jump
		yu.jump = 0
	end
	if (p.cmd.buttons & BT_USE)
		yu.spin = $+1
		yu.jump = 0 --Cancel takes priority over jump.
	elseif yu.spin
		yu.spin = 0
	end
	
	--Directional input. Only one at a time allowed ever, hard inputs are needed for more comfortable controller usage.
	
	if (p.cmd.forwardmove > 19)
		yu.up = $+1
		yu.down = 0
	else
		yu.up = 0
	end
	if (p.cmd.forwardmove < -19)
		yu.down = $+1
		yu.up = 0
	else
		yu.down = 0
	end
	if (p.cmd.sidemove > 19) and not (yu.down or yu.up)
		yu.right = $+1
		yu.left = 0
	else
		yu.right = 0
	end
	if (p.cmd.sidemove < -19) and not (yu.down or yu.up)
		yu.left = $+1
		yu.right = 0
	else
		yu.left = 0
	end
	if yu.lastsubmenu != yu.submenu
		if yu.lastsubmenu < yu.submenu
		S_StartSound(nil, sfx_yusfxf, p) --Went back.
		else
		S_StartSound(nil, sfx_yusfxd, p) --Went forwards!
		end
	end
	yu.lastsubmenu = yu.submenu

	--Translucency magic.
	
	if (yu.menutrans <= 0)
		yu.menutransd = 1
	elseif (yu.menutrans >= FRACUNIT*4)
		yu.menutransd = -1
	end
	if yu.menutranswait --Do it slooower.
		yu.menutranswait = $-1
	else
		yu.menutrans = $+(FRACUNIT*yu.menutransd)
		yu.menutranswait = 2
	end
	if yu.menutimer > 8
		yu.menutimer = 0
	else
		yu.menutimer = $+1
	end
	
	--Set scroll limits for each menu so navigation doesn't screw up.
	if yu.submenu == 0 --Basic
		yu.minvert = 3
		yu.minhoriz = 0
	elseif yu.submenu == 1 --Spintrail
		if yuog.customtrail == nil
			yu.minvert = 0
		else
			yu.minvert = 3
		end
		if yu.menuselect == 1
			yu.minhoriz = #skincolors - 1
		else
			yu.minhoriz = 0
		end
	elseif yu.submenu == 2 --Game/Jump Style
		yu.minhoriz = 0
		yu.minvert = 2
	elseif yu.submenu == 3 --Accessibility
		yu.minvert = 3
		yu.minhoriz = 0
	end
	
	--MENU NAVIGATION!
	
	if yu.up == 1	
		if yu.minvert != 0
			S_StartSound(nil, sfx_yusfxe, p)
			yu.menuselect = $-1
			yu.menuhorizontal = 0
			
			if yu.submenu == 1 and yu.menuselect == 1
			and yuog.customtrail != nil
				yu.menuhorizontal = yuog.customtrail
			end			
		end
		if (yu.menuselect < 0)
			yu.menuselect = yu.minvert 
		end
		
	elseif yu.down == 1
		if yu.minvert != 0
			S_StartSound(nil, sfx_yusfxe, p)
			yu.menuselect = $+1
			yu.menuhorizontal = 0
			
			if yu.submenu == 1 and yu.menuselect == 1
			and yuog.customtrail != nil
				yu.menuhorizontal = yuog.customtrail
			end
		end
		if (yu.menuselect > yu.minvert)
			yu.menuselect = 0
		end
		
	elseif yu.left
		if yu.submenu == 1 and yu.menuselect == 1
			if yuog.customtrail != nil --Special color select plus
			and (yu.left == 1 or (yu.left > 13 and (yu.menutimer % 3 == 0)) or yu.left > 44 and (yu.menutimer % 2 == 0))
				yu.menuhorizontal = $-1
				S_StartSound(nil, sfx_yusfxe, p)
				if (yu.menuhorizontal <= 0)
					yu.menuhorizontal = yu.minhoriz
				end
				if not (yu.menuhorizontal > #skincolors) --Failsafe!	
				yuog.customtrail = yu.menuhorizontal
				end
			end
		elseif yu.left == 1
			if yu.submenu == 3 and yu.menuselect == 0	--Spin control toggling?
				if not (yuog.spindashcontrol <= 2)
				yuog.spindashcontrol = $-1
				S_StartSound(nil, sfx_yusfxd, p)
				end
			else
				if (yu.minhoriz != 0)
					S_StartSound(nil, sfx_yusfxe, p)
					yu.menuhorizontal = 0
					yu.menuhorizontal = $-1
				end
				if yu.menuhorizontal < 0
					yu.menuhorizontal = yu.minhoriz
				end
			end
		end
		
	elseif yu.right
		if yu.submenu == 1 and yu.menuselect == 1			
			if (yu.right == 1 or (yu.right > 13 and (yu.menutimer % 3 == 0)) or yu.right > 44 and (yu.menutimer % 2 == 0))
			and yuog.customtrail != nil --Special color select minus
				S_StartSound(nil, sfx_yusfxe, p)
				yu.menuhorizontal = $+1			
				if (yu.menuhorizontal > yu.minhoriz) or (yu.menuhorizontal == 0)
					yu.menuhorizontal = 1
				end
				if not (yu.menuhorizontal > #skincolors - 1) --Failsafe!	
				yuog.customtrail = yu.menuhorizontal
				end
			end	
			
		elseif yu.right == 1
			if yu.submenu == 3 and yu.menuselect == 0	--Spin control toggling?
				if not (yuog.spindashcontrol >= 6)
				yuog.spindashcontrol = $+1
				S_StartSound(nil, sfx_yusfxd, p)
				end
			else
				if (yu.minhoriz != 0)
				S_StartSound(nil, sfx_yusfxe, p)
				yu.menuhorizontal = $+1
				end
				if yu.menuhorizontal > yu.minhoriz
					yu.menuhorizontal = 0
				end
			end
		end	
	end
	
	--CONFIRMING AND CHANGING STUFF! THE BIG ONE, BASICALLY!
	
	if yu.jump == 1
		if yu.submenu
			if not (yu.submenu == 1 and yu.menuselect == 1)
			and not (yu.submenu == 3 and yu.menuselect == 0)
			S_StartSound(nil, sfx_yusfxd, p)
			end
		end
		if yu.submenu <= 0
			if yu.menuselect == 0 --SPIN TRAILS
				yu.submenu = 1
			elseif yu.menuselect == 1 --STYLE/SOUND
				yu.submenu = 2
			elseif yu.menuselect == 2 --ACCESSIBILITY
				yu.submenu = 3
			elseif yu.menuselect == 3 --EXIT
				YuOpenMenu(p)
				return
			end
			yu.menuselect = 0
		elseif yu.submenu == 1
			if yu.menuselect == 0
				if yuog.customtrail == nil
					yuog.customtrail = p.mo.color
				else
					yuog.customtrail = nil
					yuog.customtrailshiny = nil
					yuog.customtrailtaper = nil
				end
			elseif yu.menuselect == 2 
				if not yuog.customtrailshiny
				yuog.customtrailshiny = true
				else
				yuog.customtrailshiny = nil
				end
			elseif yu.menuselect == 3 
				if not yuog.customtrailtaper
				yuog.customtrailtaper = true
				else
				yuog.customtrailtaper = nil
				end
			end
		elseif yu.submenu == 2 --GAME/SOUND menu!
			if yu.menuselect == 0
				if yuog.ballspinonly and not yuog.noaura
					yuog.ballspinonly = false
					yuog.noaura = nil
				else
					if not yuog.noaura
					yuog.ballspinonly = false
					yuog.noaura = true	
					else
					yuog.ballspinonly = true
					yuog.noaura = nil	
					end
				end
			elseif yu.menuselect == 1
				if yuog.yuvoice
				yuog.yuvoice = false
				else
				yuog.yuvoice = true
				end				
			elseif yu.menuselect == 2 
				if yuog.yumusic
				yuog.yumusic = false
				else
				yuog.yumusic = true
				end	
			end
		elseif yu.submenu == 3 --GAME/SOUND menu!
			if yu.menuselect == 1 --Btw, 0 is the spin smoothing feature and is toggled with side-movement.
				if yuog.spinguideline
				yuog.spinguideline = false
				else
				yuog.spinguideline = true
				end
			elseif yu.menuselect == 2 
				if yuog.noflashes
				yuog.noflashes = nil
				else
				yuog.noflashes = true
				end				
			elseif yu.menuselect == 3
				if yuog.noquakes
				yuog.noquakes = nil
				else
				yuog.noquakes = true
				end				
			end		
		end
		
	--CANCELING OUT OF MENUS!
	
	elseif yu.spin == 1
		if yu.submenu
			yu.menuselect = (yu.submenu-1)
			if (yu.menuselect < 0 or yu.menuselect > 3)
				yu.menuselect = 0 --Failsafe.
			end
			yu.submenu = 0
			yu.menuhorizontal = 0
		elseif yu.submenu <= 0 --Goodbye, menu!
			YuOpenMenu(p) --Make sure this is last in line or we add a "return"
			return
		end
	end
end)

--Opens OR closes the SA menu.

rawset(_G, "YuOpenMenu", function(p)
	if not p.valid
		return
	end

	if not p.yumenutable
	S_StartSound(nil, sfx_yusfxf, p)
	
		if p.yusonictable and p.yusonictable.superflight
		and p.mo and p.mo.valid and p.mo.skin == "adventuresonic"
			p.mo.momz = 0
		end
		
	--Table now exists.
		p.yumenutable = {
		menuselect = 0,
		menuhorizontal = 0,
		submenu = 0,
		up = 0,
		down = 0,
		left = 0,
		right = 0,
		jump = 0,
		spin = 0,
		minvert = 3,
		minhoriz = 0,
		lastsubmenu = 0,
		menutrans = 0,
		menutransd = 1,
		menutranswait = 5,
		menutimer = 1}
		
		return true
		
	else --Exiting out?
	
		S_StartSound(nil, sfx_yusfxd, p)
		
			if splitscreen --Player 2's turn, if they're here!
				if secondarydisplayplayer and secondarydisplayplayer.valid
					if secondarydisplayplayer.yusonictable and not secondarydisplayplayer.yumenutable
						YuOpenMenu(secondarydisplayplayer)
					elseif secondarydisplayplayer and secondarydisplayplayer.mo and secondarydisplayplayer.mo.valid
						P_SetObjectMomZ(secondarydisplayplayer.mo, FRACUNIT, true)
						secondarydisplayplayer.mo.state = S_PLAY_SPRING
					end
				end
			end
			SAsaveorload(p, true, false) --Save when closing menu!	
			
		p.yumenutable = nil
		p.pflags = $ & ~PF_FORCESTRAFE
		return false	
	end
end)