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

addHook("PlayerThink", function(p)
	if not p.valid
	return
	end
	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 others.
	
	if p.yumenutable
		YuMenuThinker(p, p.yumenutable, p.yusonictable)	
	end
	
	if p.mo and p.mo.valid	
	local s = p.mo --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.

		--Custom3 action!	
		
			if yu.custom3 == 1 and not ((p.cmd.buttons & BT_TOSSFLAG) and P_IsObjectOnGround(s))
			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 --Can't localize this because of P_RandomRange, crap...
						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 and p.SuperColor ~= "default") //Compatibility with some supercolor mods.
						or (p.scolor and p.scolor ~= "default"))
							if p.skincolor == SKINCOLOR_ADVANCESONIC --Decree from the Metal overlord
								if not (consoleplayer and consoleplayer.yusonictable and consoleplayer.yusonictable.noflashes)
								and (leveltime % 2 == 0)
									s.color = SKINCOLOR_ADVANCESUPERSONIC2
								else
									s.color = SKINCOLOR_ADVANCESUPERSONIC
								end	
							else
								s.color = SKINCOLOR_SADXSUPERSONIC
							end
						end
					
				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_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
				
				YuSuperFlight(p, s, yu)
					
				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_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
				and not yu.supersonic
						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 or yu.lsadash
					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 = p.skincolor
							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 & ~PF_JUMPED & ~PF_SPINNING & ~PF_THOKKED
				if yu.tauntdead
				//	s.state = S_PLAY_DEAD
				//	s.flags = $|MF_BOUNCE
				//	YuDeathAnim(s, p, yu)
					if yu.direct or s.state != S_PLAY_DEAD or ((p.speed > s.scale) or s.momz)
					s.state = S_PLAY_FALL
					p.pflags = $ & ~PF_INVIS
					yu.tauntdead = false
					end
				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)
				--Speed up sprinting sound with footsteps mod depending on speed.
				if p.groundtexture != nil and PlayerAnimInfo
					if (p.speed >= 60*s.scale)
						PlayerAnimInfo["adventuresonic"] = {
						["runFrames"] = {0,3,5},["run"] = true,
						["walkFrames"] = {0,5}, ["walk"] = true}				
					else
						PlayerAnimInfo["adventuresonic"] = {
						["runFrames"] = {0,5},["run"] = true,
						["walkFrames"] = {0,5}, ["walk"] = true}				
					end
				end
				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 not p.powers[pw_carry]
					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] < 35
									p.powers[pw_nocontrol] = 35
									end
									S_StartSound(s, sfx_kc4d)
									S_StartSound(s, sfx_yusfx9)
									P_YuQuake(p, 50*FRACUNIT, 11)
									yu.lsaattack = 1
									P_RadiusAttack(s, s, 370*s.scale)
									yu.lsaattack = 0
									
									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!
									if not yu.lsacharged
										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
									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
				elseif (p.powers[pw_carry] == CR_MINECART) and not p.powers[pw_super] --I guess this is official now!
				local goforit = 0
					if (p.cmd.buttons & BT_CUSTOM3)
						s.sprite2 = SPR2_FLY
						s.frame = X
						goforit = 1
					elseif (p.cmd.buttons & BT_CUSTOM2)
						s.sprite2 = SPR2_FLY
						s.frame = Z+4	
						goforit = 1
					elseif (p.cmd.buttons & BT_TOSSFLAG)
						s.sprite2 = SPR2_FLY
						s.frame = 34
						goforit = 1
					end
					if goforit == 1
						if not yu.tauntcd and goforit == 1
						goforit = 2
						end
						yu.tauntcd = 70
					else
						s.state = S_PLAY_STND
					end
					if goforit == 2
						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
				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_PlayerInPain(p)				
					yu.lsacharged = false
					yu.advance2trail = 0
					if yu.homingtrick
						YuCancelTricks(p, s, yu)
					end
					if yu.lsacharged
						YuCancelLSA(p, s, yu)
					end
					if yu.lsadash
						YuStopLSAdash(p, s, yu)
					end
					if yu.lsaattack or yu.lsahoming or yu.lsadash
						YuStopLSA(p, s, yu)
					end
					if yu.bouncestate
						YuResetBounce(p, s, yu)
					end
					
				--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 == O) or (frame == P)
					yu.homingresist = 4
				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
					if yu.tauntstate != 50
					yu.tauntstate = 50
						if multiplayer and (gametype == GT_COOP) and not yu.gavepowerup --Toss Mario a bone.
							YuSantaSonic(p,s,yu)
						end
					end
					yu.tauntendcolor = p.skincolor
				end
				if not yu.endlvl and not p.exiting --Cancel taunt?
				or (yu.tauntstate == 50 and (yu.tauntendcolor != p.skincolor))
				or not s.health
					if (p.pflags & PF_JUMPED or yu.hitspring)
						yu.tauntstate = 0
						yu.hitspring = 0
					elseif yu.direct or not s.health or (yu.tauntstate == 50 and (yu.tauntendcolor != p.skincolor)) --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		
					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
							
							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
					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
					if p.sms_intoship
						s.state = S_PLAY_FALL
					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
					
					--Trying to fix a vanilla bug with the homing attack in huge maps.
					if s.target and s.target.valid and ((FixedHypot(s.target.x-s.x, s.target.y-s.y)) > 3500*FRACUNIT)
						p.homing = 0
						if yu.prehomeangle != nil
							s.angle = yu.prehomeangle
							p.drawangle = yu.prehomeangle
						end
						P_InstaThrust(s, s.angle, 40*FRACUNIT)
						yu.homingsetup = false
						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.hominganim = 4
						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

				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 myself to solve the problem like so, lmao.
				yu.hyperpower = true
			end
			
			--This exists. Let's do what we can to fight it, I suppose.
			if s.currentaxis 
				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.cmd.forwardmove > 10) or (p.cmd.forwardmove < -10))
				and not ((p.pflags & PF_SPINNING) and P_IsObjectOnGround(s))
					local forward = p.cmd.forwardmove
					if forward < 0
					forward = $*-1
					end
					s.momx = FixedDiv(FixedMul($, 162), 162+forward)
					s.momy = FixedDiv(FixedMul($, 162), 162+forward)
				end
				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) --Axis2D couldn't have done this itself?
					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
				if (p.speed > 4*s.scale) and not p.cmd.sidemove
				and ((p.pflags & PF_SPINNING) or not P_IsObjectOnGround(s))
					p.drawangle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
				end
			end		
			
			--Hat support! Puts them near SA-Sonic's actual head. That's more support than the vanilla characters get.
			
			if s.hatmobj --Only a need to do one at a time.
				if Cosmetics --Juuust making sure....
					if not (s.state == S_PLAY_DEAD)
					Cosmetics.SkinOffsets["adventuresonic"] = 12
					else
					Cosmetics.SkinOffsets["adventuresonic"] = -31
					end
				end
			elseif s.hat
				YuHatAdjust(p, s, yu, s.hat)
			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 = 0
				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)
							--Nope, nothing.
						else
							if method == 2
							P_Thrust(s, s.standingslope.xydirection, extraspeed/5)
							else
							P_Thrust(s, s.standingslope.xydirection, extraspeed)
							end
						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.tauntstate
					yu.tauntstate = 0
					if P_IsObjectOnGround(s)
					s.state = S_PLAY_FALL
					end
				end
				if yu.tauntdead 
					s.state = S_PLAY_FALL
					p.pflags = $ & ~PF_INVIS
					yu.tauntdead = false
				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.mo and p.yusonictable and p.mo.health
		local s = p.mo
		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 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 or p.thomasandhisfriends		
					
						if yu.brakeanim
						yu.brakeanim = $-1
							if yu.forcebrakeangle != nil 
								p.drawangle = yu.forcebrakeangle
							end	
							
						--Additionally, dirk surfing support!	
						
						elseif p.thomasandhisfriends

							if yu.lsacharged
								YuCancelLSA(p, s, yu)
							end
							if yu.lsadash
								YuStopLSAdash(p, s, yu)
							end
							if yu.lsaattack or yu.lsahoming or yu.lsadash
								YuStopLSA(p, s, yu)
							end
							if yu.bouncestate
								YuResetBounce(p, s, yu)
							end			
							if (p.pflags & PF_STARTDASH) or yu.startdash
								p.pflags = $ & ~PF_STARTDASH & ~PF_JUMPED & ~PF_SPINNING
								yu.startdash = 0
								s.state = S_PLAY_WALK
							end
							s.sprite2 = SPR2_SKID
							if (p.cmd.buttons & BT_SPIN)
								if s.thomasthetankengine
									if s.thomasthetankengine[1]
										if yu.spin == 1
										S_StartSound(s, sfx_zoom)
										S_StartSound(s, sfx_yusfxc)
											if not yu.tauntcd
											yu.tauntcd = 80
											YuVoice(p, s, yu, sfx_yuvocg, true)
											end
										end
										if not s.thomasthetankengine[1].player.powers[pw_sneakers]
										s.thomasthetankengine[1].player.powers[pw_sneakers] = 1
										end
										P_TryMove(s, s.thomasthetankengine[1].x+FixedMul(-100*s.scale, cos(s.thomasthetankengine[1].angle) ), s.thomasthetankengine[1].y+FixedMul(-100*s.scale, sin (s.thomasthetankengine[1].angle) ), true)
										P_InstaThrust(s.thomasthetankengine[1], s.thomasthetankengine[1].angle, 80*FRACUNIT)
										P_InstaThrust(s, s.thomasthetankengine[1].angle, 80*FRACUNIT)
										
										local ghs = P_SpawnGhostMobj(s.thomasthetankengine[1])
										ghs.colorized = true
										ghs.color = SKINCOLOR_SKY
										ghs.blendmode = AST_ADD
										YuWindSpawn(p, s, yu)
										YuWindSpawn(s.thomasthetankengine[1].player, s.thomasthetankengine[1], s.thomasthetankengine[1].player.yusonictable)
									end
								end
								yu.spin = 50
							end
							p.pflags = $|PF_USEDOWN
							if (p.cmd.buttons & BT_JUMP)
							p.pflags = $|PF_JUMPED|PF_JUMPDOWN|PF_USEDOWN & ~PF_THOKKED & ~PF_SPINNING
							end
							yu.jump = 50
							yu.custom3 = 50
						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
				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
						if p.powers[pw_super]
						s.sprite2 = SPR2_ROLL|FF_SPR2SUPER
						else
						s.sprite2 = SPR2_ROLL
						end
						s.frame = yu.uncurlanim
					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
				--The massive super transformation animation!
				if yu.supertransform
					YuSuperTransform(p, s, yu)
				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
			if yu.myshield
				if not yu.myshield.valid
					yu.myshield = nil
				elseif not (yu.myshield.flags2 & MF2_DONTDRAW)
					YuShieldThinker(yu.myshield)
				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)