--[Yuji Uekawa style Sonic]--
--Sprites made by Metalwario64.
--Lua made by GoldenShine.

addHook("PlayerThink", function(p)
	if not p.yusonictable
	SetupYuSonic(p) --No table? Make one, then!
	return
	end
	
	--MENU is active! The way this is build is that NONE of this even exists unless the menu's active.
	--Less stuff for the game's to remember, so it's probably my most optimized menu thus far.
	--It's also written to be more understandable than my other menus.	
	if p.yumenutable
		YuMenuThinker(p, p.yumenutable, p.yusonictable)	
	end
	
	if p.realmo and p.realmo.valid
	
	local s = p.realmo --s will refer to the player object you're watching as you play [AKA player.mo]
	local yu = p.yusonictable --yu will refer to the table with values we created for Yu Sonic. [YUTIMERS]	
		if s.skin == "adventuresonic" --Are we Yu Sonic?
		
			p.mrcecustomskin = 2 --Opt out of Mystic Realm CE.
			
		--First, the massive super transformation animation!
		
			if yu.supertransform
				YuSuperTransform(p, s, yu)
			end
		--Custom3 action!	
		
			if yu.custom3 == 1 and not (p.cmd.buttons & BT_TOSSFLAG)
			and not (p.powers[pw_carry] or p.powers[pw_nocontrol] or (p.panim == PA_PAIN)
			or yu.lsadash or yu.lsahoming or yu.lsacharged or p.readyforpowershare or p.powers[pw_super])
			
			local didit = false
						
				if (p.rings >= 50) and All7Emeralds(emeralds) --Transform, almighty hedgehog!!
				and not ((yu.bouncestate == 1) or p.exiting or yu.lsacharged or yu.supertransform)
				and (p.sms_sontransform == nil or ((p.pflags & PF_JUMPED) and not p.readyforpowershare and not yu.mysticsuper)) --You'll have to jump if SMS is added. Sorry!
				
					if yu.yumusic
						if not (mapheaderinfo[gamemap].levelflags & LF_NOSSMUSIC)
						S_ChangeMusic("YUSUPR", true, p)
						end
					end
					
					didit = true
					p.pflags = $|PF_THOKKED|PF_FORCESTRAFE & ~PF_STARTDASH & ~PF_SPINNING & ~PF_JUMPED & ~PF_STARTJUMP
					p.powers[pw_nocontrol] = 30
					yu.forceyuangletimer = 30
					yu.forceyuangle = s.angle
					yu.supertransformangle = s.angle
					yu.presupertransformangle = s.angle
					p.drawangle = s.angle
					yu.supertransform = 35
						if yu.supereyes > 8
						yu.supereyes = 8
						end
						if P_IsObjectOnGround(s)
						S_StartSound(s, sfx_kc3c)
							for d = 0,7
							P_SpawnParaloop(s.x, s.y, s.z, 30*FRACUNIT, 4, MT_NIGHTSPARKLE, d*(ANG20*2), S_XPLD1, true)
							end
						end
						
					P_SetObjectMomZ(s, 14*FRACUNIT)
					S_StartSound(s, sfx_yusfx8)
					S_StartSound(s, sfx_s3ka6)
					S_StartSound(s, sfx_s3ka2)
						
				elseif not (yu.bouncestate == 1) and ((p.pflags & PF_JUMPED) or ((p.pflags & PF_SPINNING) and not P_IsObjectOnGround(s))) --Oops, you don't meet the requirements!
					if not (p.pflags & PF_THOKKED)
						didit = true
						local ghs = P_SpawnGhostMobj(s)
						ghs.destscale = $*99
						ghs.scalespeed = $*3
						ghs.sprite2 = SPR2_FRUN
						ghs.frame = A|TR_TRANS80
						P_SetObjectMomZ(ghs, ghs.scalespeed*-18)
						yu.airstart = 14
						s.state = S_PLAY_FALL
						s.momz = 0 s.momx = 0 s.momy = 0
						p.pflags = $|PF_THOKKED & ~PF_SPINNING & ~PF_STARTDASH & ~PF_JUMPED & ~PF_STARTJUMP
						S_StartSound(s, sfx_s3k64)
						S_StartSound(s, sfx_s3ka6)
						
						if p.powers[pw_shield]
							if ((p.powers[pw_shield] == SH_ARMAGEDDON) or p.powers[pw_shield] == (SH_ARMAGEDDON|SH_FIREFLOWER)) --Blow up the shield! 
							P_BlackOw(p) --Manual explosion shield
							elseif ((p.powers[pw_shield] == SH_WHIRLWIND) or p.powers[pw_shield] == (SH_WHIRLWIND|SH_FIREFLOWER))
							P_DamageMobj(s, nil, nil, 1, DMG_DEATHPIT) --Oh no! The air I breathed was made of Death Pit!!
							didit = false --Manual whirlwind jump!
							end
						end
					end
				end
				if didit
					yu.custom3 = 20
					yu.hominganimstart = 0
					yu.hominganim = 0 yu.hominganim2 = 0 yu.hominganim3 = 0
					yu.homingtrick = 0
					yu.farthok = 0
					yu.sa2jumpdone = true						
					yu.lsacharge = 0
					yu.spin = 5
					yu.jump = 5
					yu.airborne = 55
					yu.startdash = 0
					didit = false
				end
			end		
			
		--I'll show you Super Sonic power! if yu.supersonic
		
			if p.powers[pw_super]
				yu.supersonic = true --Use this value instead of pw_super to determine when Sonic's untransformed.

					if p.powers[pw_super] == 1
						if (s.state == S_PLAY_SUPER_TRANS2) --Jump straight to the next frame!
							s.state = S_PLAY_SUPER_TRANS3
							s.tics = 2
						elseif (s.state == S_PLAY_SUPER_TRANS6)
							if (leveltime % 2 == 0)
								if ((s.frame & ~FF_FULLBRIGHT & ~FF_SPR2SUPER) >= H)
									s.frame = F
								else
									s.frame = $+1
								end
							end
							if s.tics == 1
							yu.superflight = 1
							yu.startssturn = 7
								local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUTHOK)
								ghs.sprite = SPR_YUA1
								ghs.frame = A|FF_FULLBRIGHT|TR_TRANS90
								ghs.destscale = $*99
								ghs.scalespeed = $*6
								ghs.tics = 6
								ghs.blendmode = AST_ADD
							yu.jump = 0 yu.spin = 0
							p.pflags = $ & ~PF_JUMPDOWN & ~PF_USEDOWN
							end
						end
					elseif yu.startssturn
						yu.forceyuangletimer = yu.startssturn
						yu.forceyuangle = (yu.presupertransformangle-ANGLE_90)-((ANG1*7)*yu.startssturn)
						yu.startssturn = $-1
					end				
				--SUPERFLOW. Determines spike physics for Super Sonic!
					if (p.speed or s.momz) and not ((p.panim == PA_IDLE) or (p.panim == PA_EDGE))
						if not (yu.superflow >= 77)
						 	if (yu.superflow < 50)
								if (yu.superflow < 38)
								yu.superflow = $+1	
								end
								if ((p.speed > 18*FRACUNIT) or s.momz) or (p.pflags & PF_SPINNING)
								yu.superflow = $+2
								end
							end
							if (p.speed > 60*FRACUNIT) or (p.pflags & PF_SPINNING)
								yu.superflow = $+4
								if (p.speed > 90*FRACUNIT)
									yu.superflow = $+10
								end
							end
							if (s.momz < -14*FRACUNIT) or (s.momz > 14*FRACUNIT)
							yu.superflow = $+2
								if (s.momz < -20*FRACUNIT) or (s.momz > 20*FRACUNIT)
								yu.superflow = $+5
								end
							end
						end
					end
					if (p.speed >= yu.savedspeed) 
						yu.savedspeed = p.speed
						yu.savedspeedtimer = 3
					elseif yu.savedspeedtimer
						yu.savedspeedtimer = $-1
						if not yu.savedspeedtimer
							yu.savedspeed = p.speed
						end
					end			
						
					if yu.superflow
					
						yu.superflow = $-1
						
						if ((p.panim == PA_IDLE) or (p.panim == PA_EDGE) or (p.panim == PA_WALK)) and (s.anim_duration > 1)
							if (yu.superflow > 60)
							or (p.panim == PA_WALK and (yu.superflow > 38))
								s.anim_duration = 1
							elseif yu.superflow > 45 
								if s.anim_duration > 2
								s.anim_duration = 2
								end
							elseif yu.superflow > 34
								if s.anim_duration > 3
								s.anim_duration = 3
								end
							elseif yu.superflow > 18
								if s.anim_duration > 4
								s.anim_duration = 4
								end
							elseif s.anim_duration > 5
								s.anim_duration = 5
							end
						end
						if (yu.superflow > 77)
							yu.superflow = 77
						end
					end
				
				--Spawn YuVault!
				if (gametype == GT_COOP)
					if not (yu.yuvault2 and yu.yuvault2.valid)
						yu.yuvault2 = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YUVAULT)
						yu.yuvault2.tics = 6
						yu.yuvault2.target = s
						yu.yuvault2.supervault = true
					else
						yu.yuvault2.tics = 6	
					end
				end
				
				if yu.hypersonic
						--Use vanilla colors incase we're not using xmom.
						yu.hypercolor = $+1
						if yu.noflashes
							yu.hypercolor = 7
						elseif yu.hypercolor > 7
							yu.hypercolor = 1
						end
						yu.hypercolor2 = $+1
						if yu.hypercolor2 > 14 or yu.noflashes
							yu.hypercolor2 = 1
						end
						if yu.noflashes
						s.color = SKINCOLOR_WHITE
						else
						s.color = p.yuemeraldcolors4[yu.hypercolor2]
							local amount = 1
							if (p.speed > 110*s.scale)
							amount = 8
							end
							for d = 1,amount,7
								local ghs = P_SpawnMobjFromMobj(s, P_RandomRange(-10*d, 10*d)*s.scale, P_RandomRange(-10*d, 10*d)*s.scale, 20*s.scale, MT_SUPERSPARK) 
								ghs.momx = P_RandomRange(-9,9)*s.scale ghs.momy = P_RandomRange(-9,9)*s.scale
								ghs.momz =  P_RandomRange(-9,8+d)*s.scale
								ghs.colorized = true
								ghs.color = p.yuemeraldcolors2[yu.hypercolor]+4					
								ghs.fuse = 8+(d*5)
								ghs.scale = s.scale*2/3
							end
						end
						
						if (p.speed > 4*FRACUNIT or s.momz > 2*FRACUNIT or s.momz < -2*FRACUNIT) and not yu.superflight --Afterimages when moving.
							local ghs = P_SpawnGhostMobj(s)
							ghs.color = p.yuemeraldcolors2[yu.hypercolor]
							ghs.momx = s.momx/4
							ghs.momy = s.momy/4
							ghs.colorized = true
							ghs.rollangle = s.rollangle
							ghs.blendmode = AST_ADD
						end
						
						--Hyper Sonic has no need for mere peasant lungs.
						if p.powers[pw_underwater]
							if (p.powers[pw_underwater] < 440)
							P_RestoreMusic(p) --Cancel drowning theme.
							end
							if (p.powers[pw_underwater] < 1200)
							p.powers[pw_underwater] = 1200
							end
						end
						if p.powers[pw_spacetime] and (p.powers[pw_spacetime] < 450)
							p.powers[pw_spacetime] = 450
						end
						
				elseif (p.powers[pw_super] > 1) or (s.state >= S_PLAY_SUPER_TRANS3)
					--COLOR behaviour!
					if not p.SuperColor or (p.SuperColor and p.SuperColor == "default") //Compatibility with supercolors
						if p.skincolor == SKINCOLOR_ADVANCESONIC
						s.color = SKINCOLOR_ADVANCESUPERSONIC --Decree from the Metal overlord
						else
						s.color = SKINCOLOR_SADXSUPERSONIC
						end
					end
					
				end
				
				--Floating up and down in spot to emulate SA1 a bit more in SA1 mode.
				
				if yu.superoffset != 0 or ((p.panim == PA_IDLE) or (p.panim == PA_EDGE))
					if (yu.superoffsetd == 1) and ((p.panim == PA_IDLE) or (p.panim == PA_EDGE)) --Going up
						if (yu.superoffset > 4*FRACUNIT)
							yu.superoffsetd = -1
						else
							if (yu.superoffset > 3*FRACUNIT)
							yu.superoffset = $+8500
							else
							yu.superoffset = $+12000
							end						
						end
					elseif (yu.superoffsetd == -1) --Going down! We always go down if we're not idling.
						if (yu.superoffset <= 0)
						yu.superoffsetd = 1
						else
							if (yu.superoffset < 2*FRACUNIT)
							yu.superoffset = $-8500
							else
							yu.superoffset = $-12000
							end
						end
					end
					if yu.superflight 
					yu.superoffset = 0 --Flight mode! So forget about it!
					end
					s.spriteyoffset = yu.superoffset
				end				

				--The Custom 3 HUD Button!

				if not yu.superflyswitch and not (p.powers[pw_super] < 21)
				and not (yu.lsacharged or yu.lsadash or yu.lsahoming)
				and not p.powers[pw_carry] and not p.powers[pw_nocontrol] and not (p.panim == PA_PAIN)
				and not p.readyforpowershare
					if not (yu.ret2transform >= 9)
					yu.ret2transform = $+1
					end
				elseif yu.ret2transform
					yu.ret2transform = $-1
				end		
				
				if yu.superflyswitch
				
					--This is kinda copying off supertransform.
					p.pflags = $|PF_CANCARRY
					yu.superflyswitch = $-1	
					if yu.supertransformangle != nil
					yu.supertransformangle = $-(ANGLE_45/2)
					else
					yu.supertransformangle = p.drawangle
					end
					if not yu.flighthoming
					p.pflags = $|PF_THOKKED|PF_FORCESTRAFE & ~PF_STARTDASH & ~PF_SPINNING & ~PF_JUMPED & ~PF_STARTJUMP
					end
					s.state = S_PLAY_SPRING
					yu.startdash = 0
				
					local ghs = P_SpawnGhostMobj(s)
					ghs.destscale = $*99
					ghs.blendmode = AST_ADD
					ghs.angle = yu.supertransformangle
					ghs.colorized = true
					ghs.color = SKINCOLOR_SUPERGOLD1
					ghs.destscale = ghs.scalespeed+1
				
					local ghs = P_SpawnGhostMobj(s)
					ghs.destscale = $*99
					ghs.blendmode = AST_ADD
					ghs.colorized = true
					ghs.angle = yu.supertransformangle
					ghs.tics = 2
					ghs.scale = s.scale*6/5
					ghs.color = SKINCOLOR_SUPERGOLD1
					ghs.flags2 = $|MF2_SHADOW
					P_TeleportMove(ghs, s.x+s.momx, s.y+s.momy, s.z+s.momz)	
				
					if P_IsObjectOnGround(s)
					s.z = $+5*(s.scale*P_MobjFlip(s))
					end
					if yu.superflyswitch < 4 or (yu.superflyswitch == 7)
					s.momz = $/2
					end
					
					if not yu.superflyswitch
					yu.jump = 0
					yu.spin = 0
					yu.flighthoming = 0
					yu.superflight = 1
					s.flags = $|MF_NOGRAVITY
					yu.supertransformangle = nil
					yu.forceyuangletimer = 0
					p.pflags = $|PF_JUMPED & ~PF_FORCESTRAFE & ~PF_STARTDASH & ~PF_SPINNING & ~PF_STARTJUMP	& ~PF_THOKKED
					p.charflags = $|SF_SUPER|SF_CANBUSTWALLS
					yu.changedcharflags = 10
					end	
					
				elseif yu.custom3 == 1 and not (p.cmd.buttons & BT_TOSSFLAG) --Switch to flight, emulating SA2-flying.	
				
					if not yu.supertransform
					and not (yu.lsacharged or yu.lsadash or yu.lsahoming)
					and not p.powers[pw_carry] and not p.powers[pw_nocontrol] and not (p.panim == PA_PAIN)
					and (p.powers[pw_super] > 1)
					
						if yu.superflight
						
							YuSuperFlyStart(p, s, yu)
							
						else
						
							YuSuperFlyStart(p, s, yu, true)
							
						end
					end
				end			
				if not yu.superflight --Super Sonic has special superspeed mechanics when not in flight mode! 
					if (p.speed > 80*s.scale)
					and (p.pflags & PF_JUMPED) and not yu.bouncestate
					and ((s.state == S_PLAY_ROLL) or (s.state == S_PLAY_SPRING) or (s.state == S_PLAY_FALL) or (s.state == S_PLAY_JUMP))
						YuJumpBallSpawn(p, s, yu) --Forcibly spawn the jumpball at high speeds in your Super state.
						if s.state != S_PLAY_ROLL
							s.state = S_PLAY_ROLL
						end
					end
					if not yu.superaura --Gotta build up speed! Best way to do so is in the air, Super Sonic's specialty!
					
						if ((p.speed > 110*s.scale) or ((p.speed > 100*s.scale) and not P_IsObjectOnGround(s)) or ((p.speed > 90*s.scale) and not P_IsObjectOnGround(s) and (p.pflags & PF_JUMPED)))						
						and not p.powers[pw_carry] and not yu.brakeanim and not yu.lsadash
						and (yu.direct > 2)
							yu.superaurabuild = $+1
						elseif yu.superaurabuild
							yu.superaurabuild = $-1
						end
						--Must be in midair! Super Sonic's whole thing is that he's faster in midair, I don't want #spamdash-meta-except-super
						if (yu.superaurabuild > 15) and not P_IsObjectOnGround(s) and not yu.lsadash
						yu.superaura = 7 --Blue Bolt Aura! You accelerate faster and your speed is easier to uphold!
						yu.superaurabuild = 0
						yu.hudboost = 1
						S_StartSound(s, sfx_yusfx7)
							if (s.state == S_PLAY_FALL)
							s.state = S_PLAY_ROLL
								if not (p.pflags & PF_JUMPED)
								p.pflags = $|PF_JUMPED & ~PF_THOKKED
								end
							end
							if not yu.noflashes
								for d = 1,5
							
								local boom = P_SpawnMobjFromMobj(s, 0, 0,0, MT_YUINSTASHIELD)
								boom.scalespeed = $*(d*3)
								boom.tics = $+d
								boom.momx = (s.momx/d)/2
								boom.momy = (s.momy/d)/2
								boom.momz = (s.momz/d)/2
								boom.colorized = true
								boom.color = SKINCOLOR_SUPERGOLD5-d+1
								boom.destscale = s.scale*99
								boom.blendmode = AST_ADD
								boom.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIPTHING
								end
							end
						end
						
					else

						if not (yu.direct > 2)
						or yu.brakeanim or p.powers[pw_carry]
						or yu.lsacharged or yu.ledgegrabcooldown > 24
						or p.homing or yu.hominganimstart --Any of these things, your aura's done for.
							yu.superaura = 0
							yu.superaurabuild = 0
						elseif (p.speed < 76*s.scale) --Going to slow? You'll lose your aura!
							yu.superaura = $-1	
							
								if (p.speed < 10*s.scale)
								yu.superaura = $-1
								end
								if (yu.superaura < 0)
								yu.superaura = 0
								end
								yu.superaurabuild = 0
						else --Otherwise...aura awaaaay! yu.superaura = yu.bluebolt, btw.
							P_RadiusAttack(s, s, 185*FRACUNIT) --Smash anything that comes your way!
							yu.superaura = 7
							if (p.speed < 116*s.scale)
								if (yu.direct > 2) and P_IsObjectOnGround(s)
								and not (p.pflags & PF_SPINNING)
								s.momx = $*100/99 --Speed up, you can't seriously be this slow with your bolt aura!
									if not (s.flags2 & MF2_TWOD or twodlevel)
									s.momy = $*100/99
									end
								end
							end
						end
					
					end
					
				else --if yu.superflight
				
					p.pflags = $|PF_CANCARRY --Carry players! Looks silly, but why not!

					for d = -4,4
					local ghs = P_SpawnMobj(
					s.x+(P_RandomRange(1200,-1200)*s.scale)+(s.momx*25),
					s.y+(P_RandomRange(1200,-1200)*s.scale)+(s.momy*25),
					s.z+((P_RandomRange(800,-400)*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
						ghs.scale = s.scale/P_RandomRange(2,5)
						ghs.sprite = SPR_PRTL
						ghs.frame = A|FF_FULLBRIGHT
						ghs.eflags = s.eflags
						P_SetObjectMomZ(ghs, P_RandomRange(2,6)*s.scale, true)
						if (p.rings < 10)
						ghs.color = SKINCOLOR_CRIMSON
						ghs.colorized = true
						ghs.flags2 = MF2_SHADOW
						end
						if p != displayplayer --Don't draw? Can we get away with not spawning them at all, maybe?
						ghs.flags2 = $|MF2_DONTDRAW
						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 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)
							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)
								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 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
						
						--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)
								if (yu.superidleframe > G)
									yu.superidleframe = A
								end	
								if (p.speed >= 8*s.scale) or (yu.direct > 30)
									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
								if not yu.noflashes
									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)
								P_NukeEnemies(s, s, 1420*FRACUNIT)
								
								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
						
						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
						YuSuperFlyStart(p, s, yu)
					end
					
				end


				
			else --if not supersonic!
			
			
			
				if yu.superoffset != 0
					s.spriteyoffset = 0
				end
				yu.superoffset = 0
				yu.superoffsetd = 1
				
				if (p.rings >= 50) and All7Emeralds(emeralds)
					if not (yu.bouncestate == 1)
					and not p.exiting
					and not yu.supertransform
					and not (yu.lsacharged or yu.lsadash or yu.lsahoming) and not p.exiting
					and not p.powers[pw_carry] and not p.powers[pw_nocontrol] and not (p.panim == PA_PAIN)
					and not p.readyforpowershare
						if not (yu.ret2transform >= 9)
						yu.ret2transform = $+1
							if not yu.supereyed
								yu.supereyes = 109 --Animation timer.
								S_StartSound(s, sfx_s3k52, p)
								S_StartSound(s, sfx_s3k9c, p)
								yu.supereyed = true --Animation has started, okay!
							end
						end
					elseif yu.ret2transform
						yu.ret2transform = $-1
					end
				elseif yu.ret2transform
					yu.ret2transform = $-1
				end
			
				if yu.supersonic and not p.powers[pw_super] --Not p.powers[pw_super] but yu.supersonic means you've untransformed!
			
				YuLSAgfx(p,s,yu)
					for d = 1,6
					YuSuperSparkles(p, s, yu, false, 4)
					end
					yu.supertransformangle = nil
					yu.forceyuangletimer = 0
					p.pflags = $ & ~PF_FORCESTRAFE
					p.charflags = $ & ~SF_SUPER
					p.charflags = $ & ~SF_CANBUSTWALLS
					yu.changedcharflags = 10
				s.flags = $ & ~MF_NOGRAVITY
				S_StartSound(s, sfx_yusfxa)
				yu.supersonic = false
				yu.hypersonic = false
					if p == consoleplayer and yu.yumusic
						if S_MusicName() == "YUSUPR" or S_MusicName() == "_super" --Restore music
						COM_BufInsertText(p, "tunes -default")
						P_RestoreMusic(p)
						end
					end
					if (s.state == S_PLAY_EDGE)
						s.state = S_PLAY_STND
					end
					if not P_IsObjectOnGround(s) and s.health
					and not ((s.state == S_PLAY_SPRING) or (s.state == S_PLAY_FALL))
					and not (p.powers[pw_carry] or p.powers[pw_nocontrol])
						p.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING & ~PF_STARTDASH & ~PF_STARTJUMP
						s.state = S_PLAY_ROLL
						yu.sa2jumpdone = false
						yu.airborne = 0
					end
				end
				
				--Custom Adventure Music!
				if p == consoleplayer and yu.yumusic
					if S_MusicName() == "YUSHOE"
						if not p.powers[pw_sneakers]
						COM_BufInsertText(p, "tunes -default")
						P_RestoreMusic(p)
						S_ChangeMusic("YUINV", false, p)
						elseif p.powers[pw_sneakers] == 699
						S_StartMusicCaption("Hey You! It's Time To Speed Up!", 699, p)
						end
					elseif S_MusicName() == "YUINV"
						if not p.powers[pw_invulnerability]
						COM_BufInsertText(p, "tunes -default")
						P_RestoreMusic(p)
						elseif p.powers[pw_invulnerability] == 699
						S_StartMusicCaption("Invincible...No Fear!", 699, p)
						end				
					end
				end

				--Prism glow ala Adventure!

				if p.powers[pw_invulnerability]
					local FlashMobjC={SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERPURPLE3,SKINCOLOR_SUPERSKY2, SKINCOLOR_SUPERSKY4, SKINCOLOR_SUPERSKY5, SKINCOLOR_SUPERPERIDOT2}
					YuGoldenShine(p, s, yu, FlashMobjC[P_RandomRange(1,6)], 3)
				end
			end
		
			--The Lightdash and Lightspeed Attack!
			
			if yu.lsacheck and (yu.lsatarget or yu.lightdashing)
			or yu.lsaattack
			
				YuLightSpeed(p, s, yu) --Huge function, so it's stashed away in YU-FUNCTIONS to not clutter this too much.
				
			elseif not yu.lsacheck and (yu.ldclosest or yu.lightdashing or yu.lsaattack)
				ResetLSA(p, s, yu)
				yu.ldclosest = nil
			end		
			--The "list of things that change when Sonic's being carried"
			if p.powers[pw_carry] 
				yu.framejump = 0
				YuResetBounce(p, s, yu)
				yu.nosarun4 = 2
				yu.airleverage = 0
				yu.superflight = 0
					yu.yteleport = s.y
					if yu.lsahoming or yu.lsacharged
					YuStopLSA(p, s, yu)
					YuCancelLSA(p, s, yu)
					end
					
					if not (p.powers[pw_carry] == CR_NIGHTSMODE)
					yu.jump = 5
						if not (p.powers[pw_carry] == CR_MINECART)
						and not (p.powers[pw_carry] == CR_PLAYER) 
						yu.spin = 5
						end
					end
					yu.startdash = 0
					
					if (p.powers[pw_carry] == CR_MACESPIN)
						if not (s.state == S_PLAY_ROLL)
						s.state = S_PLAY_ROLL
						end
					elseif (p.powers[pw_carry] == CR_ROLLOUT)
						if s.state == S_PLAY_ROLL and ((p.pflags & PF_JUMPED) or (p.pflags & PF_SPINNING)) --Cancel a rare bug
							p.pflags = $ & ~PF_JUMPED & ~PF_SPINNING & ~PF_STARTDASH & ~PF_THOKKED
							s.state = S_PLAY_WALK
						end
					elseif (p.powers[pw_carry] == CR_DUSTDEVIL)
					
						yu.hitspring = 2 --Have spring properties after this!
						if (s.eflags & MFE_VERTICALFLIP)
							if s.z > s.ceilingz-60*s.scale
							s.z = $-25*s.scale
							end						
						else --How are you getting stuck in the ground?! Get outta there!
							if s.z < s.floorz+80*s.scale
							s.z = $+30*s.scale
							end
						end
						if not yu.supersonic
						yu.dustdevilfling = 2
						s.state = S_PLAY_YUHELICOPTER
						end
						
					elseif (p.powers[pw_carry] == CR_ZOOMTUBE)
						yu.resetspriteoffset = 2
						
				--NiGHTS! Let's make it a bit more entertaining and Sonic-y!
				--It's not easy, there's a reason most people don't bother with unique NiGHTS behaviour.

					elseif (p.powers[pw_carry] == CR_NIGHTSMODE)
					
						YuNiGHTSSuperSonic(p, s, yu)
						
						return --We're done here. Abort code.	
					elseif (p.powers[pw_carry] == CR_PLAYER)
					
						if s.state == S_PLAY_RIDE and (p.pflags & PF_JUMPED)
						p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING & ~PF_STARTDASH
						end
						
						if s.tracer and s.tracer.player
						and (s.tracer.player.powers[pw_tailsfly] < 15) and not s.tracer.player.yusonictable.flyencouragement
						and (s.tracer.player.charability == CA_FLY)
							yu.canencourage = 2
							
							if yu.spin == 1 and (p.cmd.buttons & BT_SPIN) --Hang in there!
							
							s.tracer.player.yusonictable.flyencouragement = 490
							s.tracer.player.powers[pw_tailsfly] = $+200
							s.tracer.momz = $/2
							if s.tracer.state == S_PLAY_FLY_TIRED
							s.tracer.state = S_PLAY_FLY
							end
							
							YuVoice(p, s, yu, sfx_yuvocd, true)
							
							--The Sonic thumbs up!
							local yeah = P_SpawnMobj(s.x, s.y, s.z+s.scale*50, MT_YUTHOK)
							yeah.sprite = SPR_YUSO
							yeah.frame = W|TR_TRANS10|FF_FULLBRIGHT
							yeah.color = s.color
							yeah.scale = s.scale/26
							yeah.destscale = s.scale
							yeah.scalespeed = $/2
							yeah.tics = 26
							yeah.fuse = 26
							yeah.angle = s.angle
							P_Thrust(yeah, s.angle+ANGLE_90, 6*s.scale)
							yeah.momz = $+(((9*s.scale)*P_MobjFlip(s))+(s.tracer.momz*10/6))
							yeah.momx = $+(s.tracer.momz*10/9)
							yeah.momy = $+(s.tracer.momz*10/9)
							
							local ghs = P_SpawnGhostMobj(s)
							ghs.colorized = true
							ghs.color = SKINCOLOR_SUPERGOLD2
							ghs.destscale = $*99
							
							for d = 1,8
							local bouncecolor = P_RandomRange(SKINCOLOR_SUPERSILVER3, SKINCOLOR_SUPERGOLD5)
			
							ghs = P_SpawnMobj(s.x+P_RandomRange(-50,50)*s.scale, s.y+P_RandomRange(-50,50)*s.scale, s.z+P_RandomRange(-40,40)*s.scale, MT_IVSP)
							ghs.blendmode = AST_ADD
							ghs.scale = $*P_RandomRange(1,3)
							ghs.destscale = ghs.scalespeed+1
							ghs.colorized = true
							ghs.color = bouncecolor
							end
							
							local boom = P_SpawnMobjFromMobj(s, 0, 0,0, MT_YUINSTASHIELD)
							boom.scalespeed = $*11
							boom.destscale = s.scale*99
							boom.blendmode = AST_ADD
							boom.color = s.color
							boom.colorized = true
							end
						end
					end
			end
			
			--DEATH animations! For DEATH! And DYING! And being DEAD!!
			--It's really in-depth all things considered, not in part thanks to having to fight SRB2's death behaviour.
			
			if (s.state == S_PLAY_DEAD) or (s.health < 1)
				yu.nosarun4 = 3
				yu.spin = 9
				yu.jump = 9
				yu.custom3 = 9
				p.pflags = $|PF_JUMPDOWN|PF_USEDOWN
				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
					s.state = S_PLAY_FALL
					p.pflags = $ & ~PF_INVIS
					yu.tauntdead = false
					end
				elseif 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
			elseif yu.ragdoll != nil
				yu.ragdoll = nil
				s.rollangle = 0
			end
			
			if yu.noaura --This is really crude, but we gotta fight the system, man
				if S_SoundPlaying(s, skins["adventuresonic"].soundsid[SKSJUMP])
				S_StopSoundByID(s, skins["adventuresonic"].soundsid[SKSJUMP])
				S_StartSound(s, sfx_yusfx4)
				end
				if S_SoundPlaying(s, skins["adventuresonic"].soundsid[SKSZOOM])
				S_StopSoundByID(s, skins["adventuresonic"].soundsid[SKSZOOM])
				S_StartSound(s, sfx_yusfxg)
				end				
			end		
			--The LightSpeed Attack/Lightdash is charged! Let's add on some effects!
			if yu.lsacharged
			yu.lsaangle2 = yu.lsaangle*ANG1
			yu.ignorevaults = 10
				yu.noairdrag = 0 --Always get airdrag in LSA-mode
				yu.noairdrag2 = 0
				YuGoldenShine(p, s, yu, nil, 1) --The actual blue glow spawns in PostThinkFrame!
				
				if multiplayer
					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
				end

				if p.gotflag or p.powers[pw_carry] or p.exiting --Situations where it auto-cancels.
				or ((gametype == GT_RACE or gametype == GT_COMPETITION) and (leveltime < 140) and not (p.cmd.buttons & BT_SPIN))		
				
					YuCancelLSA(p, s, yu)
				
				--And if you let go off spin??
				
				elseif not yu.spin and not (p.cmd.buttons & BT_USE) or (yu.custom3 == 1)
				
					YuCancelLSA(p, s, yu)
					if yu.custom3 == 1
						yu.attackpriority = 36
						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.sprite = SPR_YUSO
							ghs.frame = J|FF_FULLBRIGHT|TR_TRANS40
							P_InstaThrust(ghs, (s.angle-ANGLE_90)+(ANGLE_22h*d), -36*s.scale)
							P_SetObjectMomZ(ghs, i*4*s.scale)							
							ghs.fuse = 14
							ghs.tics = 25
							ghs.color = SKINCOLOR_PURPLE
							ghs.blendmode = AST_ADD
							ghs.scale = $/2
							end
						end	
					end
					
					if p.powers[pw_super]
					yu.lsadash = 36
					else
					p.powers[pw_nocontrol] = 2
					yu.forceyuangletimer = 20
					yu.forceyuangle = s.angle
					p.pflags = $|PF_FORCESTRAFE
					yu.lsadash = 18
					end
					p.charflags = $|SF_CANBUSTWALLS
					yu.hitspring = 0
					yu.setuplsasfx = 38
					S_StartSound(s, sfx_yusfx5)
					YuVoice(p, s, yu, sfx_yuvoc5)
					s.momz = 0 s.momx = 0 s.momy = 0
					
					if P_IsObjectOnGround(s)
					s.z = $+(8*FRACUNIT*P_MobjFlip(s))
					end
				end

				if (p.panim == PA_IDLE)
					if (s.state != S_PLAY_STND)
						s.state = S_PLAY_STND
					elseif (s.tics < 3)
						s.tics = 35
					end
				elseif ((p.panim == PA_ROLL) or (p.panim == PA_JUMP))
					if (s.tics > 1)
						s.tics = 1
						s.anim_duration = 1
					end
				end	
			end
			
			--Spawn the ledgegrab object. first if it doesn't exist.
			--Btw, this also protects you from falling OFF ledges. It's a bit overly complicated.

			if not (yu.ledgegrab and yu.ledgegrab.valid)
				yu.ledgegrab = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_YULEDGEGRAB)
				if yu.ledgegrab and yu.ledgegrab.valid
					yu.ledgegrab.flags2 = $|MF2_DONTDRAW
					yu.ledgegrab.target = s
				end
			else --So it's here. Begin operation!
			
			yu.ledgegrab.scale = s.scale
			yu.ledgegrab.yuactive = false --First checks for grabbing the ledge
			yu.ledgegrab.yuactive2 = false --Second checks for not falling OFF a ledge
			yu.ledgegrab.tics = 3 
				
				if (s.eflags & MFE_VERTICALFLIP) --Flip, damnit!
					P_TeleportMove(yu.ledgegrab, s.x, s.y, s.z-(s.height*5/3))
					yu.ledgegrab.eflags = $|MFE_VERTICALFLIP
				else
					P_TeleportMove(yu.ledgegrab, s.x, s.y, s.z+(s.height*5/3))
					yu.ledgegrab.eflags = $ & ~MFE_VERTICALFLIP
				end
				
				
			--Okay, do the ledgegrab check if you're airborne and falling or farthokking!
				
				if not P_IsObjectOnGround(s)
					if (s.momz*P_MobjFlip(s) < -s.scale)
					and ((yu.airborne > 7) or yu.farthok or yu.advance2trail)
				
					and ( (p.pflags & PF_JUMPED) or ((s.state == S_PLAY_FALL) or ((s.state >= S_PLAY_GLIDE) and (s.state <= S_PLAY_MELEE_LANDING)))
					or (p.pflags & PF_THOKKED) or yu.hominganim or yu.hominganim2 or yu.hominganim3)
				
					and not yu.startdash 
					and not (yu.bouncestate == 1)
					and not yu.ledgegrabcooldown
					and not (yu.superflight and yu.supersonic)
					and not p.powers[pw_carry]
					and not yu.lsahoming
					
					local method = 0
					local ledgeang
						if (yu.direct > 7)
							method = 1 --Prioritize this first.
						elseif (yu.hominganimstart and (p.pflags & PF_THOKKED) or yu.farthok)
						or YuCheckPit(p, s, yu, true)
							method = 2 --Thokking or death pit anti-panic measures can force a ledgegrab.
						end
						if method
							yu.ledgegrab.yuactive = true
								if method == 2
									ledgeang = p.drawangle
								else
								
									if not ((s.flags2 & MF2_TWOD or twodlevel))
									
									ledgeang = yu.turnang
									
									else --Different input for 2D.
										if (p.cmd.sidemove > 0) 
										ledgeang = 0
										else
										ledgeang = ANGLE_180
										end
									end
								end

								P_TryMove(yu.ledgegrab, s.x+FixedMul(36*s.scale, cos(ledgeang) ), s.y+FixedMul(36*s.scale, sin (ledgeang) ), true)

								if (s.eflags & MFE_VERTICALFLIP)
									if ( (yu.ledgegrab.z+36*s.scale) > yu.ledgegrab.ceilingz)
									yu.ledgegrab.z = yu.ledgegrab.ceilingz
									else
									yu.ledgegrab.z = $+(36*s.scale)
									end
								else
									if ( (yu.ledgegrab.z-36*s.scale) < yu.ledgegrab.floorz)
									yu.ledgegrab.z = yu.ledgegrab.floorz
									else
									yu.ledgegrab.z = $-(36*s.scale)
									end
								end								
						end
					end
					
			--on the ground? Then check for ledge dropoff instead. Edge protect. Edge guard. Edge stop? Ledgestop? Ledge Stop? Ledge Protect!
			
				elseif (yu.forceledgeprotect or (yu.edgenope and not (p.pflags & PF_SPINNING)) or not (yu.direct > 2) )
				
					if (p.speed > 3*s.scale)
				
					and ((s.state <= S_PLAY_DASH) or (s.state == S_PLAY_EDGE) or yu.startdash or yu.lightdashing)
					and not ((p.pflags & PF_SPINNING) and not yu.startdash)
					and not (yu.bouncestate or yu.ledgeprotectcd or yu.ledgereactivate or p.powers[pw_carry] or p.exiting or (s.eflags & MFE_GOOWATER) )
				
					and not (p.powers[pw_super] and (s.eflags & MFE_TOUCHWATER) and not (s.eflags & MFE_UNDERWATER))
					and not (s.standingslope and ((s.standingslope.zdelta > 19999) or (s.standingslope.zdelta < -19999)))
					
						yu.ledgegrab.flags = $|MF_MISSILE
						yu.ledgegrab.sonicang = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
						P_TeleportMove(yu.ledgegrab, s.x+FixedMul((p.speed+(20*s.scale)), cos(yu.ledgegrab.sonicang)),s.y+FixedMul((p.speed+(20*s.scale)), sin(yu.ledgegrab.sonicang)), s.z)					
					
						yu.ledgegrab.yuactive2 = true
					end
				end
			end


			--CHOOSE YOUR TAUNTS!
			if (p.cmd.buttons & BT_WEAPONMASK) --Returns 1 to 7, so we get 7 extra taunts!
				if not yu.weaponmask
					if not G_RingSlingerGametype()
						S_StartSound(s, sfx_cdfm47, p)
					end
					yu.weaponmask = true
					yu.tauntno = (p.cmd.buttons & BT_WEAPONMASK)
				end
			else
				yu.weaponmask = false
			end
			
		--Speed up Sonic's running animation and give him windlines.
			if (s.state == S_PLAY_RUN)
				if ((p.speed >= 23*s.scale) or not ((s.flags2 & MF2_TWOD or twodlevel)))
					if (yu.direct > 30) and P_IsObjectOnGround(s)
					s.tics = 1
					YuFrameSkip(p, s, yu, 64*s.scale)
					end
					YuWindSpawn(p, s, yu)
				end
			--Have Sonic move his feet faster at the start of a walk like in Adventure
			
			elseif (s.state == S_PLAY_WALK) 
			
				if yu.brakeanim --MORE DUST FOR THE SKID GOD
				
					local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_SPINDUST)
					if (leveltime % 2 == 0)
						P_InstaThrust(ghs, s.angle+ANGLE_90, 21*FRACUNIT)
					else
						P_InstaThrust(ghs, s.angle-ANGLE_90, 21*FRACUNIT)
					end
					if (s.eflags & MFE_UNDERWATER)
						ghs.state = S_SPINDUST_BUBBLE1
					end
					
					yu.edgenope = 7		
					if sprite2 != SPR2_SKID
						s.sprite2 = SPR2_SKID
					end
				
				elseif (yu.direct > 2)
				and not (s.eflags & MFE_UNDERWATER)
				and not p.gotflag and not yu.lsacharged --Slower animation underwater/with flag/lsa
				
					if ((s.flags2 & MF2_TWOD) or twodlevel) --You move slower in 2D, so we have to adjust the animation
						if (s.tics > 1)
						s.tics = $-1
							if (p.speed < 7*s.scale) and (s.tics > 1)
							s.tics = $-1
							end
						end
					else
						if (p.speed < 45*s.scale)
							if (p.speed < 21*s.scale)
								if (s.tics > 1) and not s.didframe == s.frame
								s.tics = $-1
								end							
								if (p.speed < 7*s.scale) 
									if (s.tics > 1)
									s.tics = $-1
									end
									if (s.tics > 2)
									s.tics = $-1
									end	
								end
								s.didframe = s.frame
							else
								if (s.tics > 1)
								s.tics = $-1 --$ means "current". So whatever 's.tics' is set to currently, minus 1.
								end
							end
						end
					end
				end
				
				YuFrameSkip(p, s, yu, 34*s.scale)
				
				if (p.pflags & PF_THOKKED) and (p.pflags & PF_JUMPED)
					p.pflags = $ & ~PF_THOKKED & ~PF_JUMPED --bugfix
				end
					
			elseif (p.panim == PA_IDLE)
					if (s.state == S_PLAY_WAIT) --Speed up the waiting animation.
						if (s.anim_duration > 3)
						s.anim_duration = 3
						end
						if p.powers[pw_super] --What? How?
						s.state = S_PLAY_STND
						end
					end
					if not p.powers[pw_super]
						if p.hugged --Sonic's not the hugging type.
							if s.state != S_PLAY_STND
							s.state = S_PLAY_STND
							end
							s.tics = 20
							s.anim_duration = 20
							s.sprite2 = SPR2_HUG_
						end
						if s.sprite2 == SPR2_HUG
							yu.huggroan = $+1
							if yu.huggroan == 55 --Why me.
								YuVoice(p, s, yu, sfx_yuvocv, false)
							end
						else
							if yu.huggroan
							yu.huggroan = 0
							end
							
						--Doubt Sonic would unironically do a Kazotsky kick without mocking someone, but he's a fun loving dude!
							if s.milnejoin and s.milnejoin.valid --Definitely not an excuse to save Metalwario effort on spriting!
								if yu.custom3 == 1 and s.state != S_PLAY_YUPARTYTIME
									yu.custom3 = 10
									s.state = S_PLAY_YUPARTYTIME
									if not yu.ignorevaults --All taunts get annoying after a while.
										yu.ignorevaults = 350
										YuVoice(p, s, yu, sfx_yuvocw, true)
									end
									if (p.powers[pw_nocontrol] < 18)
										p.powers[pw_nocontrol] = 18
									end
								else
									if (s.milnejoinyu and s.milnejoinyu.valid) and not (p.speed or s.momz) --Spawn the symbol.
									s.milnejoinyu.tics = 3
									else
									s.milnejoinyu = P_SpawnMobjFromMobj(s, 0, 0, s.height*2, MT_THOK)
									s.milnejoinyu.tics = 3
									s.milnejoinyu.sprite = SPR_MLCR
									s.milnejoinyu.frame = C|FF_FULLBRIGHT
									end
								end
							end
						end
					end
					
					--You can do a taunt from here!
					
					if ((p.cmd.buttons & BT_TOSSFLAG) and ((yu.custom2 == 1) or (yu.custom3 == 1)) or ((p.cmd.buttons & BT_WEAPONNEXT) and (p.cmd.buttons & BT_WEAPONPREV)))
					and not yu.direct
					and not yu.tauntcd
						if yu.supersonic
							if s.state != S_PLAY_EDGE
							and ((p.panim == PA_IDLE) or yu.superflight and not yu.flighthoming)
							and (p.speed < 35*s.scale) and ((s.momz > -5*s.scale) and (s.momz < 5*s.scale))	
							
								if (p.cmd.buttons & BT_CUSTOM3)						
									YuVoice(p, s, yu, sfx_yuvoc9, true)
									s.state = S_PLAY_EDGE
									
									if multiplayer
									yu.tauntcd = 50
									end
									
									local ghs = P_SpawnGhostMobj(s)
									ghs.destscale = $*99
									ghs.colorized = true
									ghs.blendmode = AST_ADD
								else
									if multiplayer
									yu.tauntcd = 99
									end
									s.state = S_PLAY_SUPER_TRANS1
									if p.powers[pw_nocontrol] < 33
									p.powers[pw_nocontrol] = 33
									end
									S_StartSound(s, sfx_kc4d)
									S_StartSound(s, sfx_yusfx9)
									P_YuQuake(p, 50*FRACUNIT, 11)
									
									if not yu.tauntno
									
										YuVoice(p, s, yu, sfx_yuvoc7, true)
										
									elseif (yu.tauntno < 8)
									
										if yu.tauntno == 2
										YuVoice(p, s, yu, sfx_yuvocu, true) --Lemme see your true power!
										elseif yu.tauntno == 4
										YuVoice(p, s, yu, sfx_yuvoco, true) --Ready to surrender?
										elseif yu.tauntno == 5
										YuVoice(p, s, yu, sfx_yuvocp, true) --Do you know who I am?!
										elseif yu.tauntno == 6
										YuVoice(p, s, yu, sfx_yuvocq, true) --It's no use.										
										else
										YuVoice(p, s, yu, sfx_yuvocg-1+yu.tauntno, true)
										end
										
									end
									
									for d = 1,13
										local ghs = P_SpawnGhostMobj(s)
										ghs.scale = s.scale
										ghs.destscale = $*99
										ghs.scalespeed = $*d
										P_SetObjectMomZ(ghs, ghs.scalespeed*-5, true)
										ghs.fuse = 8 ghs.tics = 22
										ghs.rollangle = ANGLE_180-((ANGLE_45/2)*d)
										ghs.color = SKINCOLOR_RUBY+d
										ghs.colorized = true
										P_SetObjectMomZ(ghs, -15*FRACUNIT)
										ghs.blendmode = AST_ADD
										ghs.flags2 = $|MF2_SHADOW
									end
									for d = 0,8	
										local ghs2 = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_IVSP)
										ghs2.colorized = true
										ghs2.color = SKINCOLOR_SUPERGOLD1+d
										ghs2.scale = s.scale*2
										ghs2.blendmode = AST_ADD
										ghs2.momz = 6*s.scale
										P_InstaThrust(ghs2, (ANG1*70)*d, 15*s.scale)									
									end
								end
								yu.tauntno = 0
								s.momx = 0 s.momy = 0 s.momz = 0
							end
						else --if not yu.supersonic
							if (s.state != S_PLAY_DEAD) and (s.state != S_PLAY_EDGE)
								if (p.cmd.buttons & BT_CUSTOM3) --Pretend to die!
									YuVoice(p, s, yu, sfx_yuvocf, true) --ugh, I'm tired
									s.state = S_PLAY_DEAD
									yu.tauntdead = true
									S_StartSound(s, sfx_cdfm42)
									S_StartSound(s, sfx_s3k5d)
									if multiplayer
									yu.tauntcd = 85
									end
									if yu.lsacharged --Cause people assumed this a glitch.
									YuCancelLSA(p, s, yu)
									end
									P_YuQuake(p, 8*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						
								else
									if multiplayer
									yu.tauntcd = 70
									end
									s.state = S_PLAY_FLY
									yu.tauntstate = 1
									p.pflags = $|PF_JUMPDOWN|PF_USEDOWN
									yu.spin = 10 yu.jump = 10
									if not yu.tauntno
										if (leveltime % 2 == 0)
										YuVoice(p, s, yu, sfx_yuvocr, true)
										else
										YuVoice(p, s, yu, sfx_yuvocn, true)
										end
									elseif (yu.tauntno < 8)
									YuVoice(p, s, yu, sfx_yuvocg-1+yu.tauntno, true)
									end
								end
							yu.tauntno = 0
							end							
						end
					end
					
			--This silly dancing with Milne thing
			
			elseif s.state == S_PLAY_YUPARTYTIME
			
				if p.speed or s.momz or yu.direct
					if s.state == S_PLAY_YUPARTYTIME --Double check!
					s.state = S_PLAY_FALL
					end
				end
			
			--In pain we trust.
			
			elseif (p.panim == PA_PAIN)
			
				if p.powers[pw_flashing]
				
					yu.lsacharged = false
					if yu.homingtrick
					YuCancelTricks(p, s, yu)
					end
					
				--RECOVERY JUMP IF AN ENEMY KNOCKS SONIC OFF A CLIFF.
				
					if (yu.painrecovery > 28)
						if (p.cmd.buttons & BT_JUMP) and s.health --Hold the button for all I care, it's fine!
							s.state = S_PLAY_ROLL
							P_DoJump(p, true)
							P_SetObjectMomZ(s, 138500, true) --Slightly higher than a regular jump
							yu.painrecovery = 0
						end
					else
						yu.painrecovery = $+1
					end
				end
			
			--Rolling animation! Is there a reason it should be here, though...?
			
			elseif (s.state == S_PLAY_ROLL) or (s.state == S_PLAY_JUMP) or (s.state == S_PLAY_SPINDASH)
				if yu.painrecovery
				yu.painrecovery = 0
				end
				
				--This is Sonic's stylish Adventure jumpball!
				if not (yu.ballspinonly and (p.pflags & PF_JUMPED) and not yu.bouncestate)
				or p.homing
					YuJumpBallSpawn(p, s, yu)
					if yu.framejump and (p.pflags & PF_JUMPED)
					yu.framejump = 0 --Just incase, cancel framejump.
					end
				end
			
			--Check to see if you're in a fan sector and switch to helicoptering animation!
			
			elseif (s.state == S_PLAY_FALL) or yu.fanspin or (s.state == S_PLAY_YUHELICOPTER)
				if s.state == S_PLAY_YUHELICOPTER
					if (p.speed > 50*s.scale)  or (s.momz*P_MobjFlip(s) > 16*s.scale)
						if (s.tics > 2)
						s.tics = $-1
						end
					end
				end
				if not (p.pflags & PF_JUMPED) and not (p.pflags & PF_THOKKED) and not yu.homingtrick and not yu.supersonic
				and s.subsector and s.subsector.sector
				and not P_IsObjectOnGround(s) and not (yu.ledgegrabcooldown > 24)
				local fancheck = false
				local sectorz = s.subsector.sector
					if sectorz.special == 20480
						fancheck = true
					elseif not fancheck --FOF check, then?
						for fof in sectorz.ffloors()
							if fof.sector and (fof.sector.special == 20480)
							fancheck = true
							end
						end
					end
					if fancheck 
						s.state = S_PLAY_YUHELICOPTER
						yu.fanspin = 2
					end
				end	
				
			--Animation presets for EDGE frames.	
				
			elseif (s.state == S_PLAY_EDGE)
			
				if yu.supersonic
					if (s.tics > 7) or (s.tics < 0)
					s.tics = 7
					end
					if (s.anim_duration > 7) or (s.anim_duration < 0)
					s.anim_duration = 7
					end					
				elseif (s.tics > 2)
					s.tics = 2 --Don't animate as obnoxiously slow as SRB2's default...
				end

			--Don't go into walking frames out of bubble gasp!	
				
			elseif s.state == S_PLAY_GASP
				if s.tics == 1
				YuResetBounce(p, s, yu)
				s.state = S_PLAY_FALL 
				end
				
			--Our victory/taunt anim! Uses S_PLAY_FLY because it'll slow down underwater conveniently!

			elseif (s.state == S_PLAY_FLY) or (s.state == S_PLAY_SWIM)
			--Setup this as our calculation reference so we don't get screwed by weird circumstances.
			local frame = (s.frame & ~FF_FULLBRIGHT & ~FF_SPR2SUPER & ~FF_VERTICALFLIP & ~FF_PAPERSPRITE & ~FF_TRANSMASK)

				--Edit durations, we want this animation to look just right!

				if (frame < 16)
					
					--Stay in place, scoundrel!
					s.momx = p.cmomx
					s.momy = p.cmomy
					p.pflags = $|PF_JUMPDOWN|PF_USEDOWN
					s.eflags = $ & ~MFE_JUSTHITFLOOR
					
					if (yu.bosskiller and p.exiting) or not p.exiting
					
						if (s.anim_duration <= 1 or s.tics <= 1) and (frame == K) and (yu.tauntstate >= 3)
						local goforit = false
							if ((p.cmd.buttons & BT_JUMP) and not (p.cmd.buttons & BT_SPIN)) or (yu.bosskiller and p.exiting)
							
								 --Advance's Thumbs Up!
								yu.tauntstate = 7
								frame = R
								goforit = true
								
							elseif (p.cmd.buttons & BT_JUMP) and (p.cmd.buttons & BT_SPIN)
								 --Emblem pose!
								yu.tauntstate = 6 
								frame = Y
								S_StartSound(s, sfx_kc50)
								goforit = true							
								
							elseif (p.cmd.buttons & BT_SPIN) --Snappy Thumbs up!
								
								yu.tauntstate = 8
								frame = Z+5
								goforit = true
								for d = 1,3 --LOUDER!
									S_StartSound(s, sfx_s3k99)
								end

								if (s.tics != 2)
								s.tics = 2
								end
								if (s.anim_duration != 2)
								s.anim_duration = 2
								end									
								
							end
							if  goforit
								if (s.tics != 3)
								s.tics = 3
								end
								if (s.anim_duration != 3)
								s.anim_duration = 3
								end							
							end
						end
						
					end
					--Lenghten duration of some frames! Remember that SRB2 considers frame 1 as "0", so frame 9 is actually 10, etc.
					if (p.exiting > 50) and (frame <= 1) and not yu.bosskiller
						s.tics = 2
					elseif (frame == J+1) and (yu.tauntstate < 3)
						s.tics = $+4
						yu.tauntstate = 3
					elseif frame == 14 and (yu.tauntstate < 4)
						s.tics = $+3
						yu.tauntstate = 4			
					end
				end
				if frame == 14 and (s.tics == 1) and (yu.tauntstate < 5)
					frame = 13 --Repeat by decree of Metalwario!
					yu.tauntstate = 5
				elseif (yu.tauntstate < 9) and (frame == U) and (s.tics <= 1)
					yu.tauntstate = 9
					s.tics = $+4
				elseif (frame == Q) or (frame == X) or (frame == Z+4) or (frame >= 34) --Okay, stay in THIS frame permanently!
					s.tics = 3
					yu.tauntstate = 50
				end
				if not yu.endlvl and not p.exiting --Cancel taunt?
					if (p.pflags & PF_JUMPED or yu.hitspring)
						yu.tauntstate = 0
						yu.hitspring = 0
					elseif yu.direct --Okay, we're done here!
						if P_IsObjectOnGround(s)
						s.state = S_PLAY_WALK
						else
						s.state = S_PLAY_FALL
						end
						yu.tauntstate = 0
					end
				end
				
				if s.sprite2 == SPR2_FLY_  --Now, our actual output frames!
					s.frame = frame
				end
				
			end
			
			--SA2-emulating jump.
			
			if (p.pflags & PF_JUMPED) and yu.ballspinonly 
			and not ( yu.bouncestate or (yu.ledgegrabcooldown > 23) or (p.pflags & PF_NOJUMPDAMAGE) or yu.lsadash or yu.lsahoming or yu.lsatrickanim)
				if yu.airborne --Do the SA2 jump!
					if (yu.airborne < 6)
						yu.sa2jumpdone = false 
						if s.state != S_PLAY_SPRING
							s.state = S_PLAY_SPRING
						end
					elseif (((s.momz*P_MobjFlip(s)) > -284000) and not yu.sa2jumpdone) or (yu.airborne < 19)
						if s.state != S_PLAY_JUMP
							s.state = S_PLAY_JUMP
						else
							if ((s.tics > 1) or (s.anim_duration > 1)) and (p.pflags & PF_STARTJUMP)
							and (p.cmd.buttons & BT_JUMP) 
								s.tics = 1
								s.anim_duration = 1
							end	
						end
					elseif not yu.sa2jumpdone
						if s.state == S_PLAY_JUMP and not (s.state == S_PLAY_GLIDE)
							s.state = S_PLAY_FALL
						end
						yu.sa2jumpdone = true
					end
				end
			end		
			
			if (p.powers[pw_noautobrake] < 2) --We have our own autobrake system, don't interfere.
				p.powers[pw_noautobrake] = 2
			end
		--Walking on air? Let's not. You get a few frames, then transition into walking.
			
			if yu.bouncestate --Bouncing behaviour after you're already in a bounce.
				YuBounce(p, s, yu)
			end
				
			if not P_IsObjectOnGround(s) and not p.powers[pw_carry]
				
				if yu.framejump --For a few frames, jump or spin even after you walked off a ledge.	
				yu.framejump = $-1
				end
				
				--Apply Air Drag when.....

				if yu.jump == 1 and yu.framejump --Execute the frame jump
					if ( (((s.state <= S_PLAY_DASH) or (s.state == S_PLAY_EDGE)) or s.state == S_PLAY_SPINDASH or s.state == S_PLAY_ROLL)
					or yu.startdash and not yu.bouncestate )
					and not ((p.pflags & PF_THOKKED) or (p.pflags & PF_JUMPED)) and not yu.bouncestate
					and not yu.lsahoming and not yu.lightdashing
					local oldmomz = s.momz
					if (oldmomz > s.scale)
						s.momx = FixedDiv(FixedMul($, 48), 48+(oldmomz/s.scale))
						if not ((s.flags2 & MF2_TWOD) or twodlevel)
							s.momy = FixedDiv(FixedMul($, 48), 48+(oldmomz/s.scale))
						end
					end
					yu.airleverage = p.speed
					yu.framejump = 0
					P_DoJump(p, true)
					p.pflags = $ & ~PF_SPINNING & ~PF_THOKKED & ~PF_STARTDASH
					yu.startdash = 0
					yu.noairdrag = 0 --Cancel any no-airdrag situations.
					yu.noairdrag2 = 0
						if (oldmomz*P_MobjFlip(s) > 0) --Always work in the player's favor.
						s.momz = $+oldmomz
						end
					end
				end
				
				if ( (p.pflags & PF_JUMPED) or (p.pflags & PF_THOKKED) or (p.pflags & PF_SPINNING) )
				
					YuAirDrag(p, s, yu) --This is the main thing keeping SA-Sonic in check balance-wise.
					
					if yu.bouncestate --Bouncing with the bros
					
						if yu.bouncestate == 2 --AFTER the bounce, going upwards!
							if yu.spin == 1 and not (s.eflags & MFE_GOOWATER) --Do another bounce!
							
								YuStartBounce(p, s, yu)

							elseif (s.momz*P_MobjFlip(s) < -5000) --Go into falling animation. Purely cosmetic, it's still your jumping/bouncing state.
								s.state = S_PLAY_FALL
								p.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING
							end				
						end
						
					elseif yu.spin == 1 and not (p.pflags & PF_THOKKED) and not yu.bouncestate --Start the Bounce Attack or uncurl!
						
						--We're uncurling in midair. Play out some cool effects and pierce air resistance!
						if (p.pflags & PF_SPINNING) and not (p.pflags & PF_JUMPED) and not yu.jump
							YuUncurl(p, s, yu)
							S_StartSound(s, sfx_yusfxc)							
							yu.advance2trail = 39
							s.momx = $*11/10
							if not (s.flags2 & MF2_TWOD or twodlevel)
							s.momy = $*11/10
							end
							if (s.momz*P_MobjFlip(s) > 16*s.scale)
								yu.homingtrick = 40
								yu.lsatrickanim = 39
								yu.airborne = 0
								s.state = S_PLAY_SPRING
								yu.sa2jumpdone = false
								if yu.supersonic
									YuVoice(p, s, yu, sfx_yuvoc9, true)
								else
									YuVoice(p, s, yu, sfx_yuvocs, true)
								end
							end
						elseif not ((s.state >= S_PLAY_SUPER_TRANS1) and (s.state <= S_PLAY_SUPER_TRANS6))
							YuStartBounce(p, s, yu) --Let's bounce!
						end
						
					elseif (p.pflags & PF_SPINNING)
						if (s.eflags & MFE_TOUCHWATER)
						yu.watertransition = true
						elseif yu.watertransition
						yu.watertransition = false
							if (p.pflags & PF_SPINNING) and ((s.momz*P_MobjFlip(s)) > 0) and (yu.noairdrag < 20)
							and not (p.pflags & PF_JUMPED)
							yu.noairdrag2 = 30 --Bouncing off water? No air drag for a bit.
							end
						end
						
						if (p.pflags & PF_THOKKED) and not ((p.pflags & PF_JUMPED) or (p.pflags & PF_NOJUMPDAMAGE))
						p.pflags = $ & ~PF_THOKKED --Remove. What's the worst that could happen?
						end
					
						if yu.jump == 1 --Thok out of a midair spin with jump if you like.
						and not ((p.pflags & PF_JUMPED) or (p.pflags & PF_THOKKED))
					
							if yu.framejump
								local oldmomz = s.momz
								yu.framejump = 0
								P_DoJump(p, true)
								yu.startdash = 0
								s.state = S_PLAY_JUMP
								p.pflags = $ & ~PF_SPINNING & ~PF_THOKKED & ~PF_STARTDASH
							
								if (oldmomz*P_MobjFlip(s) > 0) --Always work in the player's favor.
								s.momz = $+oldmomz
								end
							
							else
						
								s.state = S_PLAY_JUMP
								p.pflags = $|PF_JUMPED & ~PF_SPINNING & ~PF_JUMPDOWN & ~PF_THOKKED & ~PF_STARTDASH
								yu.startdash = 0
							end
						elseif yu.jump and yu.spindashhover --A weird quirk from Adventure. The Spindash Hover. Fairly harmless to bring in.
						and not ((p.pflags & PF_JUMPED) or yu.startdash)
							yu.spindashhover = $-1
							
							if (p.speed > 16*s.scale)
								if yu.spindashhover == 41
								S_StartSound(s, sfx_s3k47)
								P_SetObjectMomZ(s, FRACUNIT, true)
								end
								if not  (s.momz*P_MobjFlip(s) < -18*s.scale)
									if yu.supersonic
										yu.spindashhover = 40
										if not ((s.ceilingz < s.z+120*FRACUNIT) and not (s.eflags & MFE_VERTICALFLIP))
										and not ((s.floorz > s.z-120*FRACUNIT) and (s.eflags & MFE_VERTICALFLIP))
										P_SetObjectMomZ(s, yu.spindashhover*998, true)
										end
									elseif not (s.momz*P_MobjFlip(s) > 3*s.scale) --Sorry! No launching off slopes into space.
										P_SetObjectMomZ(s, yu.spindashhover*664, true)
									end
								end
							
							local hovercolor = P_RandomRange(SKINCOLOR_SUPERSILVER3, SKINCOLOR_SUPERGOLD5) --Sparkle to indicate you're doing it, and that this isn't a glitch.				
							local ghs = P_SpawnMobj(s.x, s.y, s.z+(s.momz*2), MT_IVSP)
							ghs.blendmode = AST_ADD
							if yu.supersonic
								ghs.scale = s.scale*2
								ghs.frame = $+(P_RandomRange(0,15))|FF_FULLBRIGHT						
							else
								ghs.scale = s.scale
								ghs.frame = $+(P_RandomRange(0,15))|FF_FULLBRIGHT|(P_RandomRange(0,5)*FRACUNIT)
							end
							ghs.destscale = ghs.scalespeed+1
							ghs.colorized = true
							ghs.color = hovercolor
							
							end
						end
					end
				end
				if not (yu.superflight and yu.supersonic)
				
				--Buffer system to make platforming easier.
					if ((p.panim == PA_FALL) or yu.farthok or yu.hominganimstart)
					and not yu.bouncestate
						if (p.cmd.buttons & BT_JUMP) and not (p.cmd.buttons & BT_SPIN)
						and (yu.farthok < 8)
							if not yu.fallbuffer and yu.jump == 1
								yu.fallbuffer = 6
								yu.fallbuffer2 = 0
							elseif (yu.fallbuffer > 1)
								yu.fallbuffer = $-1
							end
						elseif (p.cmd.buttons & BT_SPIN) and not (p.cmd.buttons & BT_JUMP)
							if not yu.fallbuffer2 and yu.spin == 1
								yu.fallbuffer2 = 5
								yu.fallbuffer = 0
							elseif (yu.fallbuffer > 1)
								yu.fallbuffer2 = $-1
							end						
						end
					else
						yu.fallbuffer = 0
					end
				--Switch to falling frames animation when airborne!
					if (yu.falltransition > 4) --Run off a ledge, take about 4 frames to go into falling frames.
						if (s.momz*P_MobjFlip(s) > 7*s.scale)
						s.state = S_PLAY_SPRING
						else
						s.state = S_PLAY_FALL
						end
						yu.hitspring = 100000
						yu.falltransition = 0
					else
						if (s.state <= S_PLAY_DASH) or ((s.state == S_PLAY_FLOAT_RUN) and not yu.farthok)
						and not (p.pflags & PF_SLIDING)
						and not yu.lsahoming and not yu.lsadash
							yu.falltransition = $+2
						end				
					end
				end
				
			elseif not p.powers[pw_carry] --You ARE on the ground then?
			
				if (yu.framejump < 5) --Regain your framejump!
				yu.framejump = 5
				end
				yu.airleverage = p.speed
				if not yu.skipgroundcheck --Can't be on the ground for more than 1 frame when bouncing or it'll cancel!
					if yu.firstbounce
					YuResetBounce(p, s, yu)
					end
					if yu.lasttrick
					yu.lasttrick = 0
					end
					if yu.bouncestate == 2 --AFTER the bounce, going upwards!
						if P_IsObjectOnGround(s) or ((s.state <= S_PLAY_DASH) or (s.state == S_PLAY_EDGE))
							if (s.state != S_PLAY_FALL and s.state != S_PLAY_ROLL)
							YuResetBounce(p, s, yu)
							end
						end	
					end
				end	
			end
			
		--START OF SARUN4, the codename for Adventure Sonic's custom physics and controls system.
		
			--First, 2D doesn't use most of this!
			if ((s.flags2 & MF2_TWOD) or twodlevel)
				if (p.pflags & PF_SPINNING) and not (p.pflags & PF_THOKKED)
					if P_PlayerTouchingSectorSpecial(p, 4, 7)
					yu.noairdrag = 50
					end
					if yu.startdash
					s.momx = FixedDiv(FixedMul($, 40), 41) --Sloooow doooown....
					end
				elseif P_IsObjectOnGround(s) and not yu.supersonic
				and not yu.brakeanim and not yu.bouncestate 
						--Braking...in TWODDDD
						if (p.cmd.sidemove < 0) and (s.momx > 20*s.scale)
						or (p.cmd.sidemove > 0) and (s.momx < -20*s.scale)
						yu.brakeanim = (p.speed/10)/FRACUNIT
						yu.forcebrakeangle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y)
						yu.edgenope = 7
						S_StartSound(s, sfx_skid)
							if (yu.brakeanim > 18) --Max value!
								yu.brakeanim = 18
							elseif (yu.brakeanim < 6) --Min value! 
								yu.brakeanim = 6
							end
						end							
				end
				
			--GROUND CONTROL!!!	
			
			elseif (P_IsObjectOnGround(s) or (p.pflags & PF_SPINNING)) --GROUND CONTROL!!!
			and not yu.nosarun4			
			local goforit = 0
			local momangle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
			local trueturn = (momangle-yu.turnang)
				if trueturn != 0
					trueturn = $/ANG1
					if trueturn < 0
						trueturn = $*-1
					end
				end
				if (yu.direct > 2)		
					if (p.pflags & PF_SPINNING) and not (p.pflags & PF_THOKKED)
						if P_PlayerTouchingSectorSpecial(p, 4, 7)
						yu.noairdrag = 50
						end
						if not P_IsObjectOnGround(s) and not yu.startdash
							goforit = 1
						elseif not yu.noubercontrol and not ((s.momx or s.momy) and yu.startdash and (p.speed < 6*s.scale))
						and not (s.eflags & MFE_JUSTHITFLOOR)
							goforit = 2
						end
					elseif (p.speed > 4*s.scale)
					and not (yu.brakeanim or yu.startdash)
					and not (p.yusonictable.ledgegrabcooldown > 24)
					and not (yu.hominganimstart and (p.pflags & PF_ANALOGMODE))
						if (trueturn > 145) and (p.speed > 20*s.scale)
						and not yu.supersonic and not yu.bouncestate --Custom brake code because vanilla SRB2 is dumb.
						yu.brakeanim = (p.speed/10)/FRACUNIT
						yu.forcebrakeangle = momangle
						yu.edgenope = 7
						S_StartSound(s, sfx_skid)
							if (yu.brakeanim > 18) --Max value!
								yu.brakeanim = 18
							elseif (yu.brakeanim < 6) --Min value! 
								yu.brakeanim = 6
							end							
						elseif (p.speed < 70*s.scale)
							goforit = 1
						end	
					end	
				end			
				if goforit != 0		
					if (trueturn > 12) or goforit == 2
					local premomx = s.momx
					local premomy = s.momy
						if (trueturn > 55)
							if (yu.edgenope < 8)
							yu.edgenope = $+1 --Save this for later!
							end
							if (trueturn > 120)
								yu.edgenope = 8
							end						
						elseif yu.edgenope
							yu.edgenope = $-1
						end
						local oldtrueturn = trueturn
						trueturn = ($*10)/40
						
						if trueturn > 100
							trueturn = 100  --Max turn value! ...just incase.
						end
						local moveang = R_PointToDist2(s.x, s.y, s.x+s.momx, s.y+s.momy)
						local xadd = P_ReturnThrustX(s, yu.turnang, moveang)+p.cmomx
						local yadd = P_ReturnThrustY(s, yu.turnang, moveang)+p.cmomy
						
						if not (goforit == 2 and yu.spinanglecooldown)
						and (xadd or yadd)
						P_InstaThrust(s, R_PointToAngle2(s.x-s.momx,s.y-s.momy, s.x+xadd, s.y+yadd), moveang)						
							if goforit == 2 --Spindash physics
							and not s.currentaxis
								s.momy = FixedDiv(FixedMul($, 348), 349) s.momx = FixedDiv(FixedMul($, 348), 349) --Gradually slow down.
								if yu.spindashcontrol == 2
									s.momy = FixedDiv(FixedMul($, 100), 125)+(premomy/5)
									s.momx = FixedDiv(FixedMul($, 100), 125)+(premomx/5)
								elseif yu.spindashcontrol == 3
									s.momy = $/2+(premomy/2)
									s.momx = $/2+(premomx/2)
								elseif yu.spindashcontrol == 4
									for d = 1,2
									s.momy = $/2+(premomy/2)
									s.momx = $/2+(premomx/2)
									end
								elseif yu.spindashcontrol == 5
									for d = 1,3
									s.momy = $/2+(premomy/2)
									s.momx = $/2+(premomx/2)
									end
								elseif yu.spindashcontrol == 6
									for d = 1,4
									s.momy = $/2+(premomy/2)
									s.momx = $/2+(premomx/2)
									end									
								end
								
							elseif goforit == 1
							
								--It's CALCULATION TIME. The harder you turn the stick, the more
								--your old momentum will be converted into this fancy new direction

								s.momx = FixedMul(s.momx, FixedDiv(trueturn, 100)) + FixedMul(premomx, FixedDiv(100-trueturn, 100))
								s.momy = FixedMul(s.momy, FixedDiv(trueturn, 100)) + FixedMul(premomy, FixedDiv(100-trueturn, 100))
								
								if oldtrueturn > 40
								--Now gradually slow down, moreso if turning harshly!
									if oldtrueturn > 99 
										if P_IsObjectOnGround(s) or (p.speed < 24*s.scale)
										s.momy = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/200))
										s.momx = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/200))										
										else
										s.momy = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/80))
										s.momx = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/80))									
										end
									elseif oldtrueturn > 80
									s.momy = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/500))
									s.momx = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/500))
									elseif oldtrueturn > 69
									s.momy = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/750))
									s.momx = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/750))										
									else
									s.momy = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/800))
									s.momx = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/800))
									end
								end
								
							end
						end
					else
						yu.edgenope = 0				
					end
				end
				
			elseif not yu.nosarun4 --AIR CONTROL!!!		
			local goforit = 0
			
				if (p.pflags & PF_SPINNING)
					if yu.noubercontrol	and not P_IsObjectOnGround(s)	
						P_SetObjectMomZ(s, FRACUNIT/5, true)
					elseif (yu.startdash or P_IsObjectOnGround(s))
					and not yu.noubercontrol and not ((s.momx or s.momy) and yu.startdash and (p.speed < 6*s.scale))
					and not (s.eflags & MFE_JUSTHITFLOOR)
					goforit = 2
					end
				end
				
				if not ((p.pflags & PF_SPINNING) or yu.startdash)
				
				and (yu.direct > 3)

				and not p.homing and not (p.yusonictable.ledgegrabcooldown > 24)
				and not (yu.homingtrick > 38)
				
				local momangle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
				local trueturn = (momangle-yu.turnang)
					if trueturn != 0
						trueturn = $/ANG1
						if trueturn < 0
						trueturn = $*-1
						end
					end
					if (trueturn > 10) --If the input's not significant, no need for complex physic alterations.
					
					local oldtrueturn = trueturn
					local premomx = s.momx
					local premomy = s.momy
					local moveang = s.angle
						if (trueturn > 45)
							if (yu.edgenope < 8)
								yu.edgenope = $+1 --Save this for later!
								end
								if (trueturn > 120)
								yu.edgenope = 8
								end	
							elseif yu.edgenope
								yu.edgenope = $-1
							end					
							trueturn = ($*10)/100
							if trueturn > 100
							trueturn = 100  --Max turn value! ...just incase.
							end			
							moveang = R_PointToDist2(s.x, s.y, s.x+s.momx, s.y+s.momy)
							local xadd = P_ReturnThrustX(s, yu.turnang, moveang)+p.cmomx
							local yadd = P_ReturnThrustY(s, yu.turnang, moveang)+p.cmomy

							if xadd or yadd
								if (oldtrueturn > 154) and (p.speed > 5*s.scale)
									 --We're clearly trying to come to a stop here.
									if ((p.speed > 23*s.scale) and not yu.supersonic) or (p.speed > 34*s.scale)
										p.drawangle = momangle
										if not (yu.forcebuilder > 8) --Experimental turn-around system. Build back-drive power!
										yu.forcebuilder = $+2
										end
									yu.forcenostick = 1 --Incase Metalwario sees this. Make this a higher number to increase braking speed.
									
									else
									
										if (yu.airleverage <= 16*s.scale)									

											yu.airleverage = $+(s.scale)
											yu.forcenostick = 50
											if (p.speed < s.scale)
											yu.airleverage = 20*s.scale
											end								
										else
										
										local moveangtrue = moveang
										
											if (p.speed < moveangtrue)
											moveangtrue = $-p.speed
											end
											local div = ((p.speed/5)/s.scale)
											moveangtrue = $+(FRACUNIT*3)
											P_InstaThrust(s, R_PointToAngle2(s.x-(s.momx/div),s.y-(s.momy/div), s.x+xadd, s.y+yadd), moveangtrue)
										end
									end
								else
									if (yu.airleverage <= 16*s.scale)									

										yu.airleverage = $+(s.scale)
										
									else
										P_InstaThrust(s, R_PointToAngle2(s.x-s.momx,s.y-s.momy, s.x+xadd, s.y+yadd), moveang)
										if yu.forcebuilder and (p.speed and (p.speed < 10*s.scale))
										local speeddiv = p.speed/FRACUNIT
											if speeddiv < 5
											speeddiv = 5
											end
											P_Thrust(s, yu.turnang, (230*FRACUNIT)/speeddiv)
										end
									end
								end

							--It's CALCULATION TIME. The harder you turn the stick, the more
							--your old momentum will be converted into this fancy new direction

							s.momx = FixedMul(s.momx, FixedDiv(trueturn, 100)) + FixedMul(premomx, FixedDiv(100-trueturn, 100))
							s.momy = FixedMul(s.momy, FixedDiv(trueturn, 100)) + FixedMul(premomy, FixedDiv(100-trueturn, 100))
							
							s.momy = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/500)) s.momx = FixedDiv(FixedMul($, 2000), 2000+((trueturn*1000)/500))
							end
					else
						if yu.hitspring --Delay this, I doubt the player wants airdrag back if they're holding forward.
							if (yu.hitspring > 30000) and (yu.hitspring < 100000)
							yu.hitspring = $-10000 
							end
						end
					yu.edgenope = 0
					end				
				end
			end	
--END OF SARUN4. 

			if yu.alteredscale --Altered scale? Should we change back?
				if not ((p.pflags & PF_STARTDASH) or yu.startdash)
				and not (yu.ledgegrabcooldown > 23)
				s.spriteyscale = FRACUNIT
				s.spritexscale = FRACUNIT
				yu.alteredscale = false
				end
			end
			if yu.startdash	--Spindash charging properties.
					if yu.jump <= 2 and (p.pflags & PF_STARTJUMP) and (p.pflags & PF_JUMPED)
						p.pflags = $ & ~PF_SPINNING & ~PF_STARTDASH
						s.spriteyscale = FRACUNIT
						s.spritexscale = FRACUNIT
						yu.alteredscale = false
						s.friction = yu.groundfriction
						yu.spindashfriction = false
						S_StopSoundByID(s, sfx_yusfx2)
						S_StopSoundByID(s, sfx_yusfx1)
					else
						s.spriteyscale = FRACUNIT*68/((yu.yspinstretch*100)/132)
						s.spritexscale = FRACUNIT*66/((yu.xspinstretch*100)/130)
						yu.alteredscale = true
						s.friction = FixedDiv(FixedMul(yu.groundfriction, 100), 95)
						yu.spindashfriction = true
							if s.friction > FRACUNIT
							s.friction = FRACUNIT
							end

						if yu.setupspinsfx
							if yu.setupspinsfx == 23
							S_StartSound(s, sfx_yusfx1) --Starting spindash sound!
							S_StopSoundByID(s, sfx_yusfx2)
							yu.setupspinsfx2 = 27
							end
							yu.setupspinsfx = $-1
						else
							if yu.setupspinsfx2 == 27
							S_StartSound(s, sfx_yusfx2) --Continued charging sound!
							end
							yu.setupspinsfx2 = $-1
							if yu.setupspinsfx2 < 1
							yu.setupspinsfx2 = 27
							end							
						end
					end
			end
			if (p.pflags & PF_SPINNING)
				if (p.powers[pw_flashing] and p.powers[pw_flashing] < 12)
				and (P_PlayerTouchingSectorSpecial(p, 3, 6) or P_PlayerTouchingSectorSpecial(p, 3, 5))
				and P_IsObjectOnGround(s)
					--Hey, we touched a speed pad! Speedpad?
					yu.startdash = 0
					p.pflags = $ & ~PF_STARTDASH
					yu.noubercontrol = 14
					YuResetBounce(p, s, yu)
					yu.framejump = 25
					yu.nospindrag = 60
					yu.noairdrag = 60
					S_StopSoundByID(s, sfx_yusfx2)
					S_StopSoundByID(s, sfx_yusfx1)				
				elseif s.standingslope and ((s.standingslope.zdelta > 9999) or (s.standingslope.zdelta < -9999))
					if yu.startdash --On slopes, slow down more if charging
						s.momx = FixedDiv(FixedMul($, 70), 71)
						s.momy = FixedDiv(FixedMul($, 70), 71)
					else
						yu.frictionlock = 3
						yu.groundfriction = FRACUNIT
						yu.runfriction = FRACUNIT
						yu.spindashfriction = true
						s.friction = FRACUNIT
					end
				end	
				if not yu.startdash and not (p.pflags & PF_JUMPED) --Experimenting with spintrails!
					YuSpinTrail(p, s, yu)
				end 
			else
				if yu.startdash
				yu.startdash = 0
				end
				if yu.setupspinsfx != 23
				yu.setupspinsfx = 23
				S_StopSoundByID(s, sfx_yusfx1)
				end
			end

			if (p.pflags & PF_JUMPED)
				
				--Set Sonic up for a recurl when he hits an opponent, like in SA1.
				
				if not p.homing
				yu.prehomeangle = s.angle
				end
				
				if p.homing
					yu.yteleport = s.y
					if yu.prehomecancel
					yu.prehomecancel = $-1
						YuFarThok(p, s, yu, true)
					end
					YuSpinTrail(p, s, yu)
					yu.homingresist = 4					
					yu.homingsetup = true
					yu.hominganim = 4 yu.hominganim2 = 4 yu.hominganim3 = 4
					yu.sa2jumpdone = true
					yu.noairdrag2 = 2
					yu.chosentrick = 0
					yu.homingtrick = 0
					
					YuResetBounce(p, s, yu)
					
					if (s.state != S_PLAY_ROLL)
					s.state = S_PLAY_ROLL
					end
					if (p.homing > 8) and (p.speed < 10*FRACUNIT) and (s.momz < 3*s.scale and s.momz > -3*s.scale)
					p.homing = $-8
					end
					--Fixing some stupid vanilla bug.
					if s.target and s.target.valid and ((FixedHypot(s.target.x-s.x, s.target.y-s.y)) > 4000*FRACUNIT)
						p.homing = 0
						if yu.prehomeangle != nil
						s.angle = yu.prehomeangle
						end
						P_InstaThrust(s, s.angle, 40*FRACUNIT)
						yu.homingsetup = false
						s.state = S_PLAY_FALL
					end
					
				else --Not homing, then.

					yu.prehomecancel = 3
					yu.prehomeangle = s.angle
				
					if yu.homingsetup
					yu.homingsetup = false
						yu.sa2jumpdone = false
						if (s.state == S_PLAY_SPRING) or (yu.supersonic and ((s.state == S_PLAY_ROLL) or (s.state == S_PLAY_JUMP)))
							if ( ((p.pflags & PF_NOJUMPDAMAGE) or P_IsObjectOnGround(s)) or not yu.hitspring)
							or not (p.pflags & PF_JUMPED) and not (p.pflags & PF_NOJUMPDAMAGE) and not yu.hitspring and not (p.pflags & PF_SPINNING)
								if not (p.pflags & PF_NOJUMPDAMAGE)
									P_SetObjectMomZ(s, 14*FRACUNIT, false)
								end
								s.z = $+((5*s.scale)*P_MobjFlip(s))	
								s.state = S_PLAY_ROLL
								yu.noairdrag2 = 6
								yu.advance2trail = 0
								p.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_NOJUMPDAMAGE
								yu.airborne = 0
								yu.homingtrick = 40
								
								if yu.supersonic or yu.noaura
									yu.chosentrick = 0
								else
									if yu.lasttrick == 2
										yu.lasttrick = 0
										yu.chosentrick = 69
										yu.htrickroll = 69
									elseif yu.lasttrick == 1
										yu.chosentrick = 200
										yu.lasttrick = 2									
									else
										yu.chosentrick = 100
										yu.lasttrick = 1	
									end
									yu.airborne = 30
									yu.sa2jumpdone = true
								end
								
								yu.airstart = 10
								if (s.momz*P_MobjFlip(s) > 17*s.scale)
								P_SetObjectMomZ(s, 13*FRACUNIT, false)
								end
							end
						end
						yu.hominganim = 4 yu.hominganim2 = 4 yu.hominganim3 = 4
						yu.homingresist = 2
					elseif not (yu.hominganim == 4) and not yu.hominganimstart
					yu.hominganim = 4 yu.hominganim2 = 4 yu.hominganim3 = 4
					end
				
					--Spawn the jumptrail		
					if not (p.pflags & PF_THOKKED) and not ((s.state >= S_PLAY_SUPER_TRANS1) and (s.state <= S_PLAY_SUPER_TRANS6))
					YuJumpTrail(p, s, yu)
					end
				end
				
			end

			--Our homing thok's a lil' complicated!
		
			if (p.pflags & PF_THOKKED)
			
				if (s.state == S_PLAY_FLOAT_RUN)
				s.tics = 1
				end
			
				if ((((s.state == S_PLAY_FALL) or (s.state == S_PLAY_GLIDE) or (s.state == S_PLAY_YUHOMINGTRICK) or yu.chosentrick) and not (p.pflags & PF_JUMPED)) or yu.hominganimstart  or yu.chosentrick)
				and not p.homing and not (p.yusonictable.ledgegrabcooldown > 24) and not yu.farthok
					
					if yu.hominganimstart
						if yu.supersonic
						s.sprite2 = SPR2_ROLL|FF_SPR2SUPER
						else
						s.sprite2 = SPR2_ROLL
						end
	
					--This is similar to spindash control. But you slow down more the more you turn.

						if ( (yu.hominganimstart > 2) and (p.pflags & PF_ANALOGMODE))
						and not yu.noubercontrol
						and not (s.eflags & MFE_JUSTHITFLOOR)
						and not ((s.flags2 & MF2_TWOD) or twodlevel)
						and (yu.direct > 2)
						
						local momangle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)						
												
							--Only steer if it's significant.					
							if ( (yu.turnang > momangle+(ANG1*8)) or (yu.turnang < momangle-(ANG1*8)) )
							local premomx = s.momx
							local premomy = s.momy								
							
							local moveang = R_PointToDist2(s.x, s.y, s.x+s.momx, s.y+s.momy)
							local xadd = P_ReturnThrustX(s,yu.turnang, moveang)+p.cmomx
							local yadd = P_ReturnThrustY(s, yu.turnang, moveang)+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), moveang)
								end
								s.momy = $/2+(premomy/2)
								s.momx = $/2+(premomx/2)
								s.momy = $/2+((premomy*10)/23) --MAAAAAATH
								s.momx = $/2+((premomx*10)/23)								
							end
						end
					
					--Advanced technique that mimmicks SA1's A+B far thok, and also Sonic Advance's airdash at the same time. May nerf this later.						
						YuFarThok(p, s, yu)						
						
					end
					--Do a little roll and "hut" when you thok without homing into anything. SA2 style.			
					if yu.hominganim
						if yu.hominganim == 4
							if yu.ledgegrabcooldown
							yu.ledgegrabcooldown = 0
							end
							if (yu.airborne < 20)
							yu.airborne = 20 --We'll treat you like you've been airborne for a bit.
							end
						yu.hominganim2 = 4 yu.hominganim3 = 4
						yu.hominganimstart = 12
						yu.advance2trail = 0
						yu.fallbuffer = 0
						yu.nosarun4 = 2
						yu.chosentrick = 0
						yu.homingtrick = 0
						yu.sa2jumpdone = true
						s.state = S_PLAY_ROLL
						p.pflags = $|PF_JUMPED|PF_THOKKED
						YuVoice(p, s, yu, sfx_yuvoc1)
						
							if (s.momz*P_MobjFlip(s) > -FRACUNIT)
							P_SetObjectMomZ(s, -99900, true)
							end
							
						end			
					yu.hominganim = $-1
						local frame = I-(yu.hominganim*2)
						if (frame < A) or (frame > H)
						frame = A
						end
						s.sprite2 = SPR2_ROLL
						s.frame = frame
					YuSpinTrail(p, s, yu)
					
					elseif yu.hominganim2
						yu.hominganim2 = $-1
						local frame = I-(yu.hominganim2*2)
						if (frame < A) or (frame > H)
						frame = A
						end
						s.frame = frame
						YuJumpTrail(p, s, yu)
					
					elseif yu.hominganim3
						yu.hominganim3 = $-1				
						local frame = I-(yu.hominganim3*2)
						if (frame < A) or (frame > H)
						frame = A
						end
						s.frame = frame
							if not yu.hominganim3
							s.state = S_PLAY_FALL
							p.pflags = $ & ~PF_JUMPED
							end
					end
				end
			end
			

			--For the 2006 mod, to prevent infinite speed from no friction
			
			if p.machspeedmode 
				if yu.frictionlock > 10
					yu.frictionlock = 10
				end
				if (p.speed > 117*FRACUNIT) or (s.eflags & MFE_JUSTHITFLOOR)
					s.friction = 59392
					yu.runfriction = yu.groundfriction
				end
			end
			if p.cc_menu and not p.cc_menu.active
				p.cc_menu.buttontime = 500 --Disable ChrispyChar menu when SA-Sonic.		
			end
			
			if p.isxmomentum --Xmom support! Keep ground friction, no air drag(which is a mistake), and Hyper Sonic.
				p.noxmomchar = 2 --OR I just edit Xmom itself to solve the problem like this, lmao.
				yu.hyperpower = true
			--But first, asserting our dominance. Xmom LOVES forcing itself on you no matter how much it'd screw up your Lua.
			--As far as I know, there's no value to opt out of ALL of it's changes so you can customize stuff yourself.
			/*	p.thokforce = nil --Don't screw with my animations.
				s._spintime = 50 --Don't screw with my uncurl. I already have one.
				p.cantrick = false --Don't screw my abilities with your trick system.
				s.skipcrouching = true --Yep, definitely Skip. Definitely not just stopping xmom from breaking our physics.
				p.hyper = nil --Don't mangle my stats, I'll handle Hyper Sonic myself, thanks. */
			end
			
			if s.currentaxis --This exists. Let's do what we can to fight it, I suppose.
				p.normalspeed = 48*FRACUNIT
				p.thrustfactor = skins[s.skin].thrustfactor
				p.accelstart = skins[s.skin].accelstart
				p.acceleration = skins[s.skin].acceleration*3
				if (p.speed < 20000) and p.cmd.sidemove --What the hell even is this? Get moving!
				P_InstaThrust(s, s.angle, FRACUNIT/2)
				end
				if (p.pflags & PF_ANALOGMODE)
					p.pflags = $ & ~PF_ANALOGMODE
					if (p.powers[pw_flashing] < 35)
						S_StartSound(nil, sfx_thok, p)
						s.z = $+30*FRACUNIT*P_MobjFlip(s)
						p.powers[pw_flashing] = 35
						s.flags2 = $|MF2_DONTDRAW
						CONS_Printf(p, "\x85"+"Turned off Simple Mode for compatibility with stage!")
					end
				end
			end					
			--Hat support! Puts them near SA-Sonic's actual head. That's more support than the vanilla characters get.
			if s.hat and s.hat.valid
				local def = s.spriteyoffset+18*FRACUNIT
				if yu.supersonic
					def = s.spriteyoffset+29*FRACUNIT
				end
				s.hat.spriteyscale = s.spriteyscale
				s.hat.spritexscale = s.spritexscale
				s.hat.rollangle = s.rollangle
				if p.panim == PA_ROLL
					s.hat.spriteyoffset = s.spriteyoffset-12*FRACUNIT
				elseif p.panim == PA_WALK
					if not yu.supersonic
					s.hat.spriteyoffset = def+3*FRACUNIT
					else
					s.hat.spriteyoffset = def-3*FRACUNIT
					end
				elseif p.panim == PA_RUN and yu.supersonic or p.panim == PA_PAIN or p.panim == PA_RIDE
					s.hat.spriteyoffset = def-14*FRACUNIT
				elseif s.state == S_PLAY_DEAD
					s.hat.spriteyoffset = s.spriteyoffset-30*FRACUNIT
				else
					s.hat.spriteyoffset = def
				end
			end
			
			if p.mysticsuper --We'll do this custom, but thanks for the heads up that we transformed, SMS!
				yu.mysticsuper = 1
				p.readyforpowershare = 0
				p.mysticsuper = 0	
				p.myssmulta = nil
				p.charflags = $ & ~SF_MULTIABILITY
				p.myssrunow = nil
				p.charflags = $ & ~SF_RUNONWATER
				s.lightspeedpermission = nil
				p.myssskin = nil
				yu.supersonic = true
				S_StartSound(s, sfx_bkpoof)
				P_YuFlash(p, PAL_RECYCLE, 5)
				P_YuQuake(p, 50*FRACUNIT, 12)
				YuVoice(p, s, yu, sfx_yuvoc7, true)
				P_SetObjectMomZ(s, 3*FRACUNIT)
				s.state = S_PLAY_SPRING
				s.color = SKINCOLOR_MYSTICAL4
				p.jumpfactor = skins[s.skin].jumpfactor
				if p.powers[pw_nocontrol] < 3
					p.powers[pw_nocontrol] = 3
				end
				yu.custom3 = 15
				local ghs = P_SpawnGhostMobj(s)
				ghs.fuse = 16
				ghs.tics = 30
				ghs.destscale = $*99
			elseif yu.mysticsuper --Okay, so OUR mystic super!!
				if p.rings
					p.readyforpowershare = 0
					yu.noairdrag = 7
					yu.nospindrag = 7
					if not (p.pflags & PF_STARTDASH) -- How optimized of me.
						S_StopSoundByID(s, sfx_s3ka3)
						S_StopSoundByID(s, sfx_s3k53)
						S_StopSoundByID(s, sfx_bejet1)	
					end
					if (leveltime % 6 == 0) and (s.color <= SKINCOLOR_MYSTICAL5+1)
						s.color = $+1
					end
					if (s.color < SKINCOLOR_MYSTICAL1 or s.color > SKINCOLOR_MYSTICAL5)
					s.color = SKINCOLOR_MYSTICAL1
					end
					p.powers[pw_invulnerability] = 7777
					p.powers[pw_sneakers] = 7777
					YuSuperAura(p, s, yu)			
					if (leveltime % 35 == 0)
					p.rings = $-1
					end
				else --Aaand we're done!
					yu.mysticsuper = 0
					A_ENDMYSTICSUPER(s, true)
					p.powers[pw_sneakers] = 0
					p.powers[pw_invulnerability] = 0
					P_RestoreMusic(p)
					s.color = p.skincolor
					p.jumpfactor = skins[s.skin].jumpfactor
					p.acceleration = skins[s.skin].acceleration
				end
			end
			
			
			--Slope physics unique to Yu Sonic. You gain speed faster from spinning downhill, but also lose more when going uphill.
	
			if s.standingslope
				local tmomz = (s.z-yu.lastz)
				local method = false
				if ((p.pflags & PF_SPINNING) and not yu.startdash)
					method = 3
				elseif (p.panim == PA_RUN) and (yu.direct > 7)
					if ( ((tmomz < 0) and not (s.eflags & MFE_VERTICALFLIP))
					or ((tmomz > 0) and (s.eflags & MFE_VERTICALFLIP)) )
						if (p.speed < 80*s.scale) and not (s.eflags & MFE_UNDERWATER)
							method = 2
						end
					end
				end
				if method and (p.speed < 165*s.scale) and not yu.nospindrag --Upper limit, then regular physics can take over.
				local extraspeed = (method*(s.standingslope.zdelta)*(P_MobjFlip(s)))
					if (method < 3)
						if (yu.runfriction < FRACUNIT-500) and (s.friction < FRACUNIT-500)
						yu.runfriction = FRACUNIT
						s.friction = FRACUNIT
						end
						if extraspeed > ((s.scale*4)/10)
						extraspeed = (s.scale*4)/10
						end
					end				
					if not (extraspeed == 0)
						if (tmomz*P_MobjFlip(s) > 10*s.scale)
						else
						P_Thrust(s, s.standingslope.xydirection, extraspeed)
						end
					end
				elseif (p.speed >= 165*s.scale) --Really extreme cases.
				yu.nospindrag = 7
					--SRB2 colission screws up when going too fast on slopes with slightly corrupt nodes.
					--I hate having to do this for a vanilla bug, but you know they'll blame SA-Sonic for it.
					if P_IsObjectOnGround(s) and s.x == yu.lastx and s.y == yu.lasty
						yu.lastslopeunstuck = $+1
						if yu.lastslopeunstuck >= 3
						yu.lastslopeunstuck = 0
							for d = 1,8
							P_TryMove(s, s.x+FixedMul(FRACUNIT, cos(s.angle+ANGLE_45)), s.y+FixedMul(FRACUNIT, sin (s.angle+ANGLE_45)), true)
							end
							if (s.eflags & MFE_VERTICALFLIP)
							s.z = s.ceilingz
							else
							s.z = s.floorz
							end
						end
					end
				end
					
				if (p.speed < 5*FRACUNIT) and (p.speed < yu.savedspeed) and (p.pflags & PF_SPINNING) and not yu.startdash --Are we now below our last speed? If so, uncurl if too slow.
					YuUncurl(p,s,yu)
					p.pflags = $|PF_JUMPDOWN|PF_USEDOWN & ~PF_THOKKED
					yu.jump = 10 yu.spin = 10
				elseif not (p.pflags & PF_SPINNING) and (p.speed > yu.savedspeed)
				and ( ((s.eflags & MFE_VERTICALFLIP) and (s.z > yu.lastz)) or ((s.z < yu.lastz) and not (s.eflags & MFE_VERTICALFLIP)) )
				and (p.speed > 35*FRACUNIT)
				
				--Due to the way SA-Sonic's running physics work, he'd normally be even faster RUNNING down slopes than spinning.
				--So we need a system to counteract that. Meaning extra resistance when running, and extra speed when rolling.
				
					if (p.speed < 75*FRACUNIT)
					P_Thrust(s, s.standingslope.xydirection, -2*(s.standingslope.zdelta)*(P_MobjFlip(s)))
					else
					P_Thrust(s, s.standingslope.xydirection, -4*(s.standingslope.zdelta)*(P_MobjFlip(s)))
					end
				
				end
			end		

		--Acceleration adjustment. SA-Sonic's accel is normally low, but there's exceptions.

			if yu.supersonic and yu.superaura
				p.acceleration = 72
					if (yu.direct > 2)
						yu.frictionlock = 11
						yu.groundfriction = FRACUNIT
						yu.runfriction = FRACUNIT
					end
			elseif not P_IsObjectOnGround(s)	
				if yu.airstart
					if (p.speed < 9*s.scale)
					or ((yu.supertrick and (p.speed < 22*s.scale) and yu.supersonic))
						p.acceleration = 60 --Superfast accel!
						if not (yu.homingtrick and (p.speed > 4*s.scale))
						and not yu.strongspring
							if (yu.direct > 2)
							local uw = 1
								if (s.eflags & MFE_UNDERWATER)
								uw = 2
								end
								if yu.hitspring or (s.state == S_PLAY_FALL)
									if (yu.hitspring < 100000)
									P_Thrust(s, yu.turnang, 12100/uw) --SUBTLE
									end
								else
								P_Thrust(s, yu.turnang, 71500/uw)
								end
							end
						end
					end
				end
				if not ((s.flags2 & MF2_TWOD) or twodlevel)
					if (p.speed < 13*s.scale)
						p.acceleration = 36
					else
					local accel = 24+(18)-((p.speed/FRACUNIT)/2)
						if accel < 28
						accel = 28
						elseif accel > 35
						accel = 35
						end
					p.acceleration = accel --Gradually slow acceleration the faster you go.
					end
				else
					p.acceleration = 28 
				end
			else
				if p.powers[pw_sneakers] --Nyoom!
					p.acceleration = 34
				elseif ((p.speed < 64*s.scale) and p.powers[pw_super]) or (p.speed < 32*s.scale)
					p.acceleration = 29
				else
					p.acceleration = 28 
				end
			end		
			
		--We doing an uncurl?
		
			if yu.uncurlanim != nil
			yu.uncurlanim = $+1		
				if yu.uncurlanim > 6 or yu.uncurlanim < 0
				yu.uncurlanim = nil
				p.pflags = $ & ~PF_THOKKED
					if (yu.brakeanim or not p.speed)
						if P_IsObjectOnGround(s)
							s.state = S_PLAY_STND
						else
							if (s.momz*P_MobjFlip(s) > s.scale)
							s.state = S_PLAY_SPRING
							else
							s.state = S_PLAY_FALL
							end
							yu.hitspring = 100000
						end
					end
				end
			end
			
			YuSpinDash(p,s,yu) --Sure, let's just...kinda tack on the spindash ability as a function at the end?
			
			if s.health
			yu.lastx = s.x --Record our last coordinates for certain functions!
			yu.lasty = s.y
			end
			yu.lastz = s.z
			
		else 
		
		--So we're not YU Sonic then? if not s.skin == "adventuresonic"
		
			if not yu.otherchar
			yu.otherchar = true
				if yu.mysticsuper
					yu.mysticsuper = 0
					A_ENDMYSTICSUPER(s, true)
					p.powers[pw_sneakers] = 0
					p.powers[pw_invulnerability] = 0
					P_RestoreMusic(p)
					s.color = p.skincolor
					p.jumpfactor = skins[s.skin].jumpfactor
					p.normalspeed = skins[s.skin].normalspeed
					p.acceleration = skins[s.skin].acceleration
				end	
				if yu.alteredscale or yu.bounceframe
					s.spritexscale = FRACUNIT
					s.spriteyscale = FRACUNIT
				end
				if yu.nogravity or yu.superflyswitch
					yu.supersonic = false
					yu.superflight = 0
					yu.nogravity = 0
					s.flags = $ & ~MF_NOGRAVITY
				end			
				if yu.eleccolorized --Incase you somehow switch during Yu Sonic's electrocution death anim
					s.color = p.skincolor
					s.colorized = false
					yu.eleccolorized = false
				end
				if p == consoleplayer and yu.yumusic
					if S_MusicName() == "YUSUPR" or S_MusicName() == "YUINV" or S_MusicName() == "YUSHOE" or S_MusicName() == "YUCLR"
					COM_BufInsertText(p, "tunes -default")
					P_RestoreMusic(p)
					end
				end
			end
		end
	end
end)

--We NEED a postthinkframe unfortunately. Otherwise there'll be all kinds of mess-ups with certain animations.

addHook("PostThinkFrame", do
	for p in players.iterate
		if p.realmo and p.yusonictable
		local s = p.realmo
		local yu = p.yusonictable
			if s.skin == "adventuresonic" 	
				if not p.powers[pw_super]
					if (p.powers[pw_carry] == CR_DUSTDEVIL or yu.fanspin)
					and not P_IsObjectOnGround(s) and not (yu.ledgegrabcooldown > 24)
						s.state = S_PLAY_YUHELICOPTER
					
						if p.powers[pw_carry] == CR_DUSTDEVIL
							s.sprite2 = SPR2_GLID
						elseif yu.fanspin
						s.state = S_PLAY_YUHELICOPTER
							if yu.fanspin
								if (leveltime % 3 == 0)
									yu.superauraframe = $+1
								end
								if (yu.superauraframe > H)
									yu.superauraframe = A
								end
							s.sprite2 = SPR2_WIND
							s.frame = yu.superauraframe
							end
						end
					elseif yu.uncurlanim
						if (s.state <= S_PLAY_DASH) and not (p.pflags & PF_SPINNING) and not (p.pflags & PF_JUMPED)
							s.sprite = SPR_PLAY
							s.sprite2 = SPR2_ROLL
							s.frame = yu.uncurlanim
						end
					elseif p.sms_sontransform --Transforming into SMS.
						if (p.sms_sontransform < 20)
							s.sprite2 = SPR2_TRNS
							s.frame = H+(p.sms_sontransform/5)
							if ((s.frame & ~FF_FULLBRIGHT & ~FF_SPR2SUPER) <= H)
								s.frame = $+1
							end
						else
							s.sprite2 = SPR2_TRNS
							s.frame = L
						end
					elseif (yu.homingtrick and yu.chosentrick and (yu.chosentrick < 100))
							if yu.chosentrick > 66
						
								s.state = S_PLAY_ROLL 
								s.rollangle = (yu.htrickroll*(ANG20)+(ANG30*2))*-1
							
							elseif yu.chosentrick > 48
						
								s.rollangle = (yu.htrickroll*ANG20+(6*ANG20)+(ANG1*150))*-1
								if yu.chosentrick > 38
								s.state = S_PLAY_SPRING
								else
								s.state = S_PLAY_RIDE
								s.spriteyoffset = 27*FRACUNIT
								end
							
								p.drawangle = s.angle+(yu.chosentrick*ANGLE_45)
							elseif yu.chosentrick > 26
						
								s.rollangle = (yu.htrickroll*(ANG1*14)+(13*ANG20))*-1
								s.state = S_PLAY_RIDE	
								s.spriteyoffset = 27*FRACUNIT
								p.drawangle = s.angle+(yu.chosentrick*ANGLE_22h)
							
							elseif s.state == S_PLAY_RIDE
								s.state = S_PLAY_FALL
							end	
						
							if (yu.htrickroll < 31)
								s.rollangle = 0
								if s.spriteyoffset == 27*FRACUNIT
								s.spriteyoffset = 0
								end
								yu.htrickroll = 0
								s.state = S_PLAY_FALL
								p.drawangle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
								yu.chosentrick = 0
							end
					elseif yu.brakeanim and not yu.bouncestate
						if yu.brakeanim
						yu.brakeanim = $-1
							if yu.forcebrakeangle != nil 
								p.drawangle = yu.forcebrakeangle
							end					
						end
						if p.panim == PA_WALK or p.panim == PA_RUN or s.sprite2 == SPR2_SKID
						
							s.sprite2 = SPR2_SKID
							if leveltime % 2 == 0
							s.frame = B
							elseif leveltime % 3 == 0
							s.frame = C
							else
							s.frame = A
							end
						
						end
					end
				end
				if (yu.bouncestate == 1) and P_IsObjectOnGround(s)
					if s.sprite2 != SPR2_ROLL
						s.sprite2 = SPR2_ROLL
						if ((s.frame & ~FF_TRANSMASK & ~FF_SPR2SUPER & ~FF_FULLBRIGHT) > H)
						s.frame = A
						end
						YuJumpBallSpawn(p, s, yu)
					end	
				end
				if s.currentaxis --I will go as fast as I WANT, damn you!
					p.normalspeed = 48*FRACUNIT
					p.thrustfactor = skins[s.skin].thrustfactor
					p.accelstart = skins[s.skin].accelstart
					p.acceleration = skins[s.skin].acceleration*3			
				end
				
				if yu.lsadash or ((yu.advance2trail > 25) and (s.state == S_PLAY_FALL))
					s.state = S_PLAY_FLOAT_RUN
					s.sprite = SPR_PLAY
					if yu.supersonic
						s.sprite2 = SPR2_FRUN|FF_SPR2SUPER
					else
						s.sprite2 = SPR2_FRUN
					end
				elseif yu.supersonic and not yu.superflight
				and not ((s.state >= S_PLAY_SUPER_TRANS1) and (s.state <= S_PLAY_SUPER_TRANS4))
					YuSuperAura(p, s, yu)
				end
				
				if yu.lsaattack and (s.state != S_PLAY_ROLL)
					s.state = S_PLAY_ROLL
				elseif yu.ledgeprotectcd --Don't get stopped every frame or anything.
				
					if ((p.panim == PA_IDLE) or (p.panim == PA_WALK))
					and (yu.ledgeprotectcd > 4)
					and (p.speed < 7*s.scale) --Force animation in these circumstances.	
						if yu.supersonic
							s.sprite2 = SPR2_EDGE|FF_SPR2SUPER
						else
							s.sprite2 = SPR2_EDGE
						end
						s.frame = yu.ledgeprotectanim
						if yu.ledgeprotectangle
							s.angle = yu.ledgeprotectangle
							p.drawangle = yu.ledgeprotectangle
						end
					end
					if not yu.ledgeprotectcd
						s.state = S_PLAY_EDGE
						s.frame = yu.ledgeprotectanim
					end
				end
				if yu.downthehole and yu.downtheholestate and s.state != yu.downtheholestate and not s.health --Stay in deathstate
					s.state = yu.downtheholestate
				elseif yu.lsacharged
					YuLSAglow(p, s, yu, 1, (45*s.scale), true, 11, true)
				end
				if yu.forceyuangletimer
					if yu.forceyuangle != nil
					p.drawangle = yu.forceyuangle
						if yu.supertransformangle != nil
						p.drawangle = yu.supertransformangle
						YuSuperSparkles(p, s, yu, true, 4)
						end
					end
				end
				if p.powers[pw_invulnerability] or yu.mysticsuper
					if not p.powers[pw_super]
					s.frame = $|FF_FULLBRIGHT --Always fullbright!
					end
				end
			end	
			
			--Every character has this animation.
			
			if yu.vaultanim	
				yu.vaultanim = $-1
				s.spriteyscale = FRACUNIT
				s.spritexscale = FRACUNIT
				s.rollangle = 0
				
				if (yu.vaultanim > 1)
					if not P_IsObjectOnGround(s)
					s.state = S_PLAY_ROLL
					s.sprite2 = SPR2_RIDE
					s.frame = A
					s.rollangle = ANGLE_180
					p.drawangle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)-ANGLE_180
					end
					
					if (yu.vaultanim > 8)
						s.spriteyscale = 45000
						s.spritexscale = 80000
						yu.alteredscale = true
						
						for d = 1,16
						local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_PARTICLE)
						ghs.angle = (ANGLE_45/2)*d
						ghs.fuse = 8
						ghs.scale = s.scale
						ghs.destscale = $*99
						P_InstaThrust(ghs, ghs.angle, 24*s.scale)
						end
					end
				end
			end					
		end
	end
end)

--DON'T change the music if...!

local function RulesOfSonic(oldname, newname)
	if not (consoleplayer and consoleplayer.valid
	and consoleplayer.yusonictable and consoleplayer.yusonictable.yumusic and not consoleplayer.yusonictable.otherchar)
	return
	end
	if newname == "_CLEAR" or newname == "_clear" --This one always wins the priority contest.
		S_ChangeMusic("YUCLR", false, consoleplayer)
		return true	
	elseif (oldname == "YUSUPR" or oldname == "YUINV" or oldname == "YUSHOE" or oldname == "YUCLR")
		if newname == "_inv" --Don't get interrupted by certain jingles or super music.
		or newname == "_minv"
		or newname == "_shoes"
		or newname == "_super"
		or newname == "_clear"
		or newname == "_1up"
			return true
		end
	elseif newname == "_super" and consoleplayer.yusonictable.yumusic
		S_ChangeMusic("YUSUPR", true, consoleplayer)
		return true
	else	
		if not consoleplayer.exiting and not consoleplayer.yusonictable.supersonic
			if newname == "_inv" 
				COM_BufInsertText(consoleplayer, "tunes YUINV")
				S_ChangeMusic("YUINV", false, consoleplayer)
				return true
			elseif newname == "_shoes"
				COM_BufInsertText(consoleplayer, "tunes YUSHOE")
				S_ChangeMusic("YUSHOE", false, consoleplayer)
				return true
			end
		end
	end
end
addHook("MusicChange", RulesOfSonic)