--Going to dump timer countdowns and most value trackers here to not TOTALLY clutter the main thinker....
 
--First, let the game know Yu Sonic just spawned.

addHook("MobjSpawn", function(s)
	s.yusonicspawned = true --This value is picked up by the PlayerThink hook, which then actually does the work when ready.
end, MT_PLAYER)

addHook("PlayerThink", function(p)
	if not p.valid
	return
	end
	if p.realmo and p.realmo.valid and p.yusonictable --Don't even bother otherwise.
	local s = p.realmo
	local yu = p.yusonictable
		if (consoleplayer and CV_FindVar("cam_speed").string == "0.03999")
			if not (yu.lsaattack or yu.lightdashing or yu.lsahoming or yu.strongspring)
			or s.skin != "adventuresonic"
				if yu.lsacamspeed
				COM_BufInsertText(p, "cam_speed "+yu.lsacamspeed) --We'll get camera controls soon...
				else
				COM_BufInsertText(p, "cam_speed 0.3")
				end
			end
		end
		if yu.camscale and not (p.exiting or s.state == S_PLAY_FLY)
			p.camerascale = yu.camscale
			yu.camscale = nil
		end	
		if s.yusonicspawned
			if yu.corpse --Remove your corpse, you respawned.
				if yu.corpse.valid
				yu.corpse.state = S_NULL
				end					
			yu.corpse = nil
			end
			--Stoopid level bug.
			if (gamemap == 25 and netgame and mapheaderinfo[gamemap].lvlttl == "Black Core" and (leveltime > 1))
				local maxplay = 0
				for z in players.iterate
					if z and z.mo
					maxplay = $+1
					end
				end
				if maxplay == 1 --Just 1 guy trying to skip the level by dying? Restart level.
					G_SetCustomExitVars(gamemap, 1)
					G_ExitLevel()
				end
			end
			if (leveltime < 3)
			yu.gavepowerup = nil
			end
			
			yu.ignorevaults = 20 --Ignore vault jumps for a sec!
			
			if s.skin == "adventuresonic" --Are we Yu Sonic?			
			YuResetAll(p, s, yu)
				if not netgame
					yu.spswitch = 7
					if not yu.hasloaded --Load our settings automatically outside netgames.
					SAsaveorload(p, false, true)
					yu.hasloaded = true
					end
					if not yu.hasbeennotified
					yu.samenunote = 500
					end
				end
				if yu.spawnmemories and not p.powers[pw_carry]
					yu.spawnmemories = nil
					if not yu.hyperpower
					S_StartSound(s, sfx_s3k7d, p)
					S_StartSound(s, sfx_s3kcel, p)
					yu.hypermemories = 220
					yu.superflash = 9*FRACUNIT
					yu.hyperpower = true
						if yu.bhz and yu.bhz == 2
						yu.bhz = 1
						end
					end
				end	
			end
			if yu.gametype != nil and gametype != yu.gametype
				yu.hypermemories = 0
				yu.hyperpower = false
			end
			yu.gametype = gametype
			s.yusonicspawned = false --Even if not, remove this value still. We only want to check once.
		end
		if yu.samenunote
			yu.samenunote = $-1
			if not yu.samenunote --And now never notify them of this again.
			yu.hasbeennotified = true
			SAsaveorload(p, true, false, true)
			end
		end
		if yu.ignorevaults
			yu.ignorevaults = $-1		
		end
		if yu.vaultready
			yu.vaultready = $-1
			 if yu.vaultanim
			 or ((gametype == GT_RACE or gametype == GT_COMPETITION) and (leveltime < 140))
				yu.vaultready = 0 --Not now.
				
			elseif yu.vaultreadytarget and yu.vaultreadytarget.valid and (yu.jump == 1)
				local t = yu.vaultreadytarget
				
				P_TryMove(s, yu.vaultreadytarget.x, yu.vaultreadytarget.y)
			
					if P_IsObjectOnGround(s)
					s.z = $+((5*FRACUNIT)*P_MobjFlip(s))
					end
			
				P_DoJump(p, true)
				
				if s.skin == "adventuresonic"
					s.momz = $*20/13
				else
					if s.skin == "surge" and p.stt
						SurgeMaxAura(p, s, p.stt)
					end				
					if (skins[s.skin].jumpfactor >= FRACUNIT) or p.powers[pw_super]
					s.momz = $*20/9
					else
					s.momz = $*10/3
					end
				end
				p.yusonictable.vaultanim = 10
				p.pflags = $ & ~PF_THOKKED & ~PF_SPINNING & ~PF_STARTDASH
				P_Thrust(s, t.angle, 5*s.scale)
				s.momx = $*9/8
				s.momy = $*9/8
				S_StartSound(s, sfx_s25b) S_StartSound(s, sfx_s3k42) S_StartSound(s, sfx_s3k56)
				

					local ghs = P_SpawnGhostMobj(s)
					ghs.state = S_PLAY_RIDE
					P_TeleportMove(ghs, t.x, t.y, t.z)
					ghs.rollangle = ANGLE_180
					ghs.angle = s.angle+ANGLE_180
					ghs.tics = 16
					ghs.fuse = 16
					ghs.eflags = s.eflags
					ghs.destscale = $*99
					ghs.momx = s.momx/2
					ghs.momy = s.momy/2
					ghs.momz = s.momz/8
					ghs.spriteyoffset = 30*s.scale
				
			end
		end
		if p.powers[pw_carry]
			if (p.powers[pw_carry] == CR_NIGHTSMODE)
				return --Ignore the whole thinker.
			elseif (p.powers[pw_carry] == CR_PLAYER)
			and s.tracer and s.tracer.player and ((s.tracer.player.panim == PA_RUN) or (s.tracer.state == S_PLAY_FLOAT_RUN))
				s.spriteyoffset = 18*s.scale
				s.yusfoffset = true
			end
		else
			if s.yusfoffset
			s.yusfoffset = nil
			s.spriteyoffset = 0
			end
		end
		if s.skin == "adventuresonic" --Okay, for real, are we Yu Sonic?
			if yu.spswitch
			yu.spswitch = $-1
				--Little command to pick colors for single player!
				if ((p.cmd.buttons & BT_CUSTOM3) or (p.cmd.buttons & BT_CUSTOM2)  or (p.cmd.buttons & BT_CUSTOM1))
				S_StartSound(nil, sfx_kc39, p)
				yu.spswitch = 0
					for d = 0,6,3
						local boom = P_SpawnMobjFromMobj(s, 0, 0,0, MT_YUINSTASHIELD)
						boom.scalespeed = $*(6+d)
						boom.destscale = s.scale*99
					end
					if (p.cmd.buttons & BT_CUSTOM3)
						p.skincolor = SKINCOLOR_ADVANCESONIC
						print("Held\x84 Custom 3\x80 on spawn to select the Sonic Advance color!")
						p.mo.color = SKINCOLOR_ADVANCESONIC
					elseif (p.cmd.buttons & BT_CUSTOM2)
						p.skincolor = SKINCOLOR_SADXSONIC
						print("Held\x87 Custom 2\x80 on spawn to select the SADX color!")
						p.mo.color = SKINCOLOR_SADXSONIC
					else
						p.skincolor = SKINCOLOR_SA2SONIC
						print("Held\x82 Custom 1\x80 on spawn to select the SA2 color!")
						p.mo.color = SKINCOLOR_SA2SONIC
					end
				end
			end
			if yu.otherchar --Oh, we just switched to YuSonic! Take note and reset all active values.
				yu.otherchar = false
				YuResetAll(p, s, yu)
				if not yu.hasloaded --Load our settings automatically outside netgames.
				and not netgame
					SAsaveorload(p, false, true)
					yu.hasloaded = true
				end
			end	
			
			--Update our controls every frame.
			local forwardmove = p.cmd.forwardmove
			local sidemove = p.cmd.sidemove
			if (sidemove < 0)
				sidemove = $*-1
			end
			if (forwardmove < 0)
				forwardmove = $*-1
			end
			if forwardmove > sidemove
				yu.direct = forwardmove
			else
				yu.direct = sidemove --Decide how hard we're pressing the stick! From 0 to 50!
			end
			yu.turnang = (p.cmd.angleturn<<16)+(R_PointToAngle2(0, 0, p.cmd.forwardmove<<16, -(p.cmd.sidemove<<16)))
			yu.alreadytrailed = false
			
			if p.gotflag --Nerf the HIFL out of Sonic when he holds a flag.
			--Other chars retain their spindash powers, but SA-Sonic's spindash is his main ability and thus needs to be nerfed.
				p.normalspeed = (32*FRACUNIT)/yu.shoes
				p.jumpfactor = FRACUNIT
				yu.flagstats = true
			else
				if yu.flagstats --Only do this once.
					p.jumpfactor = skins[s.skin].jumpfactor
					yu.flagstats = false
				end
				 --Set normalspeed early on so it can be overwritten easily.
				if yu.bouncestate
					p.normalspeed = (32*FRACUNIT)/yu.shoes
				else
					if not P_IsObjectOnGround(s)
						if not yu.lsacharged
						p.normalspeed = (38*FRACUNIT)/yu.shoes
						else
						p.normalspeed = (20*FRACUNIT)/yu.shoes
						end
					else
						if not yu.lsacharged
						p.normalspeed = (48*FRACUNIT)/yu.shoes
						
							if (p.panim <= PA_PAIN) and (p.panim >= PA_IDLE) --BRUTE FORCE TEST DEBUG
							
								if (p.pflags & PF_SPINNING) or (p.pflags & PF_STARTDASH)
								p.pflags = $ & ~PF_SPINNING & ~PF_STARTDASH
								end
								if (p.pflags & PF_JUMPED) or (p.pflags & PF_THOKKED)
								p.pflags = $ & ~PF_JUMPED & ~PF_THOKKED
								end
								
							end
							
						else					
						p.normalspeed = (26*FRACUNIT)/yu.shoes
						end
					end
				end
			end	

			yu.groundfriction = s.friction --The ground's true friction. Must be early in the code.
			
			if yu.spawnedballalready
			yu.spawnedballalready = false
			end
			
			if yu.downthehole --Fell into a pit. Way to go, genius
			yu.downthehole = $-1
				if not s.health --Only actually do the effects if you're really dead.
				yu.downtheholedeath = true
					if yu.downthehole == 1
					s.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIPTHING & ~MF_SOLID & ~MF_NOGRAVITY
					YuVoice(p, s, yu, sfx_yuvocc)
					end
					S_StopSoundByID(s, skins["adventuresonic"].soundsid[SKSPLDET1])
					S_StopSoundByID(s, skins["adventuresonic"].soundsid[SKSPLDET2])
					S_StopSoundByID(s, skins["adventuresonic"].soundsid[SKSPLDET3])
					S_StopSoundByID(s, skins["adventuresonic"].soundsid[SKSPLDET4])
				
					s.momx = yu.downtheholemomx
					s.momy = yu.downtheholemomy

					if (s.momz*P_MobjFlip(s) > -22*FRACUNIT)
						s.momz = yu.downtheholemomz --SRB2 won't let you through without a certain velocity...
						if (s.momz*P_MobjFlip(s) > -22*FRACUNIT)				
						P_SetObjectMomZ(s, -22*FRACUNIT)
						end
					end
					if yu.downtheholestate == S_PLAY_ROLL
					s.state = S_PLAY_FALL
					else
					s.state = yu.downtheholestate
					end
				end
			end
			if yu.downtheholefire
				if not s.health
				yu.downtheholefire = $-1
					for d = 1,2 --Do it...! ...now do it again!
					local ghs = P_SpawnMobj(s.x+P_RandomRange(-30,30)*s.scale, s.y+P_RandomRange(-30,30)*s.scale, s.z, MT_SONIC3KBOSSEXPLODE)
						if ghs and ghs.valid
						ghs.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
						ghs.blendmode = AST_ADD
						ghs.colorized = true
						if P_RandomRange(0,1)
						ghs.color = P_RandomRange(SKINCOLOR_RED, SKINCOLOR_FLAME)
						else
						ghs.color = P_RandomRange(SKINCOLOR_SUPERORANGE3, SKINCOLOR_SUPERGOLD3)
						end
						ghs.scale = $*10/P_RandomRange(4,24)
						ghs.state = $+P_RandomRange(0,2)
						ghs.destscale = $*99
						ghs.tics = $+P_RandomRange(0,7)
						ghs.frame = $|FF_FULLBRIGHT
						end
					end
				else
				yu.downtheholefire = 0
				end
			end
			if yu.tauntdead
				if not s.health 	
				or s.state != S_PLAY_DEAD
				yu.tauntdead = false
				end
			end
			if P_IsObjectOnGround(s)
				if yu.fallbuffer
					if (yu.fallbuffer > 1)
					and (p.cmd.buttons & BT_JUMP) and (p.pflags & PF_JUMPDOWN)
					p.pflags = $ & ~PF_JUMPDOWN
					end
					yu.fallbuffer = 0
				end
				if yu.fallbuffer2
					if (yu.fallbuffer2 > 1) and (p.cmd.buttons & BT_SPIN)
					and not (p.pflags & PF_SPINNING)
					yu.spin = 0
					p.pflags = $ & ~PF_USEDOWN
					end
					yu.fallbuffer2 = 0				
				end
				if yu.sa2jumpdone
					yu.sa2jumpdone = false
					yu.homingsetup = false
				end
				if yu.airborne
				yu.airborne = 0
					if not yu.bouncestate
						if not (yu.direct > 2)
						yu.forceledgeprotect = 12
						elseif (p.speed < 31*FRACUNIT)
						yu.forceledgeprotect = 3
						end
					end
				end
				if yu.brakeanim and not yu.bouncestate
				yu.forceledgeprotect = 8
				end
				if yu.lsaattackchain
				yu.lsaattackchain = $-1
					if not yu.lsaattack
					yu.lsaattackchain = 0
					yu.lsadeadjump = 0
					end
				end
				if yu.hitspring
					if (yu.hitspring > 1)
					yu.hitspring = 1
					else
					yu.hitspring = 0
					end
				end
				if (p.pflags & PF_THOKKED) and (p.pflags & PF_STARTDASH) --Fix a dumb SRB2 bug with bouncing sideways.
					yu.startdash = 0
					p.pflags = $ & ~PF_STARTDASH & ~PF_THOKKED
					s.state = S_PLAY_FALL
				elseif (s.eflags & MFE_JUSTHITFLOOR)
					if yu.startdash and not (p.cmd.buttons & BT_USE) and not (p.pflags & PF_STARTDASH)
					and not ((s.state == S_PLAY_SPINDASH) or (s.state == S_PLAY_ROLL))
					yu.startdash = 0
					p.pflags = $ & ~PF_STARTDASH
					end
				end
				if yu.airstart --Reset to 0
				yu.airstart = 0
				yu.homingsetup = false
				end				
			else
				if yu.hitspring
					yu.hitspring = $+1
					if (yu.hitspring > 99999)
						if not ((p.pflags & PF_JUMPED) or (p.pflags & PF_SPINNING))
						yu.noairdrag = 0 --Welcome back, air drag! Our player wanted SA-Sonic's controls back, but that'll come at a cost.
						yu.noairdrag2 = 0
						YuAirDrag(p, s, yu)
						end
					elseif (yu.hitspring > 6) and (yu.direct > 7)
						yu.hitspring = $+10000
						yu.forcebuilder = 0
					end
				end
				if yu.airstart and not yu.hitspring --Improve acceleration when starting in the air.
				yu.airstart = $-1
				end
				if p.powers[pw_carry] or ((s.state <= S_PLAY_DASH) or (s.state == S_PLAY_EDGE))
				or (yu.framejump and not (p.pflags & PF_JUMPED))
				or yu.startdash
				yu.airborne = 0
				else
				yu.airborne = $+1 --How many frames have we been in the air?
					if (yu.airborne < 3) 
					yu.watertransition = false
					
						if (yu.lsacharge > 43)
						and (p.pflags & PF_JUMPED) and (yu.spin > 3) --Get access one second earlier!
						
							YuLSAgfx(p,s,yu)
							yu.lsacharge = 0
							yu.lsaangle = 90
							yu.lsacharged = true
							yu.lsalasttarget = nil
							yu.lsalimit = 0
							yu.homingresist = 16
							YuVoice(p, s, yu, sfx_yuvoc4) --Readyyy!
							if p.powers[pw_super]
								S_StartSound(s, sfx_s3k47)
								P_YuQuake(p, 25*FRACUNIT, 5)
								for d = 0,6,2
								local boom = P_SpawnMobjFromMobj(s, 0, 0, 0-s.momz, MT_YUINSTASHIELD)
								boom.scale = $+(50000*d)
								boom.scalespeed = $*7+d
								boom.destscale = s.scale*99
								boom.colorized = true
								boom.blendmode = AST_ADD
								boom.color = SKINCOLOR_AETHER+d
								end	
							end							
					
						elseif ((p.pflags & PF_JUMPED) and (p.pflags & PF_SPINNING)) and yu.jump
							p.pflags = $ & ~PF_SPINNING --Try to turn off the spinning flag to give back improved air control
						elseif yu.lsacharge
						yu.lsacharge = 0
						end		
					end
				end
			end
			if yu.superbounceprep
			yu.superbounceprep = $-1
				if (yu.superbounceprep <= 0)
				yu.superbounceprep = 0
				end
			end
			if yu.canencourage
			yu.canencourage = $-1
			end
			if yu.speedupreward
				if not (yu.lightdashing or yu.lsadash or yu.lsahoming)
				yu.speedup = 6 --1/6th of a second, I'm sure people will notice. :P
				yu.speedupreward = nil
					if not yu.hitspring
					p.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_NOJUMPDAMAGE & ~PF_SPINNING & ~PF_STARTDASH
					--Snap to the floor and run or drop like a brick!
						if ( ((s.z < s.floorz+80*FRACUNIT) and not (s.eflags & MFE_VERTICALFLIP))
						or ((s.z > s.ceilingz-80*FRACUNIT) and (s.eflags & MFE_VERTICALFLIP)) )
							p.pflags = $ & ~PF_JUMPED
							s.state = S_PLAY_RUN
							P_SetObjectMomZ(s, -7*FRACUNIT)
							yu.forceledgeprotect = 10
							yu.lightdashaftereffects = 20
							
							if (s.eflags & MFE_VERTICALFLIP)
							s.z = s.ceilingz
							else
							s.z = s.floorz
							end
						else		
							for d = 1,5 --VERY strict.
								if (p.speed > 40*FRACUNIT)
								s.momx = $*5/6
								s.momy = $*5/6
								end
							end	
						
							if not (p.cmd.buttons & BT_JUMP) and not (p.cmd.buttons & BT_USE)	
								if ((s.momz*P_MobjFlip(s)) > 19*FRACUNIT) --Speed caps. Very strict!
									for d = 1,5 --VERY strict.
										if (p.speed > 18*FRACUNIT)
										s.momx = $*4/5
										s.momy = $*4/5
										end
									end	
									yu.airborne = 0
									yu.sa2jumpdone = false
									yu.homingtrick = 40
									yu.homingresist = 15
									yu.lsatrickanim = 39
									P_SetObjectMomZ(s, 19*FRACUNIT) --Only gain so much vertical height!
								elseif ((s.momz*P_MobjFlip(s)) < 0)
									P_SetObjectMomZ(s, 500) --Don't fling yourself into a pit at the speed of light.
								end
								if not yu.lsahoming and not P_IsObjectOnGround(s)
									s.state = S_PLAY_ROLL
								else
									s.state = S_PLAY_FALL
								end
							end
						end
					end

					if (p.cmd.buttons & BT_JUMP) and not yu.speeduprewardfail --Auto-jump from your lightdash
						s.state = S_PLAY_ROLL
						local lastmomz = s.momz
						P_DoJump(p, true)
							if ((lastmomz*(P_MobjFlip(s))) > 0) --Add your last momz to your jump. And only if it benefits you.
							s.momz = $+(lastmomz/2)
							end
						p.pflags = $|PF_JUMPDOWN & ~PF_STARTJUMP
						yu.painrecovery = 0
						yu.autojumproll = 2
						--MomZ caps just incase
						if ((s.momz*P_MobjFlip(s)) > 19*FRACUNIT)
							yu.airborne = 0
							yu.sa2jumpdone = false
							yu.homingtrick = 40
							yu.homingresist = 15
							yu.lsatrickanim = 39			
							P_SetObjectMomZ(s, 19*FRACUNIT)
							if (p.speed > 40*FRACUNIT)
							s.momx = $/2
							s.momy = $/2
							end
						elseif ((s.momz*P_MobjFlip(s)) < 0)
							P_SetObjectMomZ(s, 0)
						end			
					elseif (p.cmd.buttons & BT_USE) and not yu.speeduprewardfail --Auto-roll from your lightdash
						P_InstaThrust(s, R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy), 80*FRACUNIT)
						if ((s.momz*P_MobjFlip(s)) > 19*FRACUNIT)
						P_SetObjectMomZ(s, 19*FRACUNIT)
						end
						s.momz = $/2
						s.state = S_PLAY_SPINDASH
						yu.startdash = 2
						p.pflags = $|PF_SPINNING|PF_STARTDASH & ~PF_JUMPED & ~PF_THOKKED & ~PF_NOJUMPDAMAGE
						yu.spincharge = 15*FRACUNIT
						yu.spin = 2
						yu.lsacharge = 10
						yu.autojumproll = 2
						if not (yu.direct > 2)
							yu.spinanglecooldown = 2
						end				
					end
					yu.speeduprewardfail = nil
				end
			end
			if yu.speedup --Speed up! Temporary buff you gain after the lightdash!
			yu.speedup = $-1 
			
				local ghs = P_SpawnMobj(s.x+(P_RandomRange(-75,75)*s.scale),s.y+(P_RandomRange(-75,75)*s.scale),s.z+(P_RandomRange(-20,68)*s.scale),MT_YUTHOK)
				ghs.eflags = s.eflags
				P_SetObjectMomZ(ghs, P_RandomRange(1,4)*s.scale, true)
				ghs.scale = s.scale/40
				ghs.destscale = $*99
				ghs.scalespeed = $/8
				ghs.blendmode = AST_ADD
				ghs.tics = P_RandomRange(12,24)
				ghs.frame = (Z+1)|FF_FULLBRIGHT|TR_TRANS50
				
				if p.powers[pw_super]
					ghs.color = s.color
				else
					ghs.color = SKINCOLOR_SUPERSKY5
				end
				
				if (yu.direct > 2)
				and not (p.pflags & PF_SPINNING) and not (p.pflags & PF_STARTDASH)
				and not p.homing and not yu.lsadash and not yu.startdash
					if ((p.speed < 89*FRACUNIT) or (yu.supersonic and (p.speed < 140*FRACUNIT)))
						if (p.speed < 35*FRACUNIT) or (p.pflags & PF_JUMPED)
						P_Thrust(s, yu.turnang, 18777)
						else
						P_Thrust(s, yu.turnang, 47777)
						end
						yu.runfriction = FRACUNIT
						yu.groundfriction = FRACUNIT
						s.friction = FRACUNIT
						yu.frictionlock = 2
					else
						yu.frictionlock = 15
						yu.runfriction = FRACUNIT
						yu.groundfriction = FRACUNIT
						s.friction = FRACUNIT
					end
				end
				
			end
			if (p.speed < 50*FRACUNIT)
				yu.frictionspeedtreshold = $+1
			else
				yu.frictionspeedtreshold = 0
			end
			if yu.lsahoming
			yu.lsahoming = $-1
			yu.noairdrag = 3
				if (yu.lsahoming <= 0)				
					if yu.lightdashing and not yu.autojumproll
					s.momx = $/4
					s.momy = $/4
					s.momz = $/4
					YuStopLSAdash(p, s, yu)
					end
					YuStopLSA(p, s, yu)
					ResetLSA(p, s, yu)
					yu.lsahoming = 0
			/*	elseif yu.spin == 1 --Manual cancel. Mostly as a failsafe.
					YuStopLSA(p, s, yu)
					p.pflags = $|PF_JUMPED
					s.momx = $/4
					s.momy = $/4
					P_SetObjectMomZ(s, FRACUNIT*4)
					S_StartSound(s, sfx_s1a2)
					s.state = S_PLAY_ROLL */
				end
			end
			if yu.lightdashaftereffects --Friction is locked and you'll crash through enemies for some frames after lightdashing.
			yu.lightdashaftereffects = $-1
			yu.framejump = 7
			
				if (p.pflags & PF_JUMPED) or (p.pflags & PF_SPINNING) or yu.hitspring
				or not (yu.direct > 2)
				or (p.speed < 6*s.scale)
					yu.lightdashaftereffects = 0
				elseif P_IsObjectOnGround(s)
				
					if yu.lightdashaftereffects > 11
						local ghs = P_SpawnGhostMobj(s)
						ghs.rollangle = s.rollangle
						ghs.tics = 14 ghs.fuse = 14 ghs.destscale = $*3
						ghs.colorized = true
						if p.powers[pw_super]
						ghs.color = s.color
						else
						ghs.color = SKINCOLOR_SUPERSKY3
						end
						ghs.blendmode = AST_ADD
						ghs.frame = $|TR_TRANS90 & ~TR_TRANS30 & ~TR_TRANS40 & ~TR_TRANS50 & ~TR_TRANS60 & ~TR_TRANS70 & ~TR_TRANS80
						ghs.flags2 = $|MF2_SHADOW
					end
				end
			end
			if yu.attackpriority --Ignore rings if this is on!
				yu.attackpriority = $-1
			end
			
			--Lightspeed Dash! The part BEFORE you home into stuff!
			
			if yu.lsadash
			
				--Set up bonk and 2D y-axis parameters...
			
				if (yu.lsadash > 1)				
					if (yu.lsadash == 18 or yu.lsadash == 36)
						yu.bonkeddash = 0
						if not yu.lightdashing
							yu.lsadashlastangle = s.angle	
						end		
					elseif not yu.bonked
						if (p.speed < 20*s.scale) --Method 2 of detecting bonks, for surefireness.
						yu.bonkeddash = $+3
						yu.bonked = 1
						end
					end
					if yu.bonkeddash
						yu.bonkeddash = $-1
						if (yu.bonkeddash > 3)
							if yu.supersonic
								if not (yu.direct > 24) --You can redirect if you want to!
									s.angle = $+ANGLE_180
									p.drawangle = $+ANGLE_180
									S_StartSound(s, sfx_cdfm42)
									P_YuQuake(p, 34*FRACUNIT, 2)
									yu.bonkeddash = 0
								end
							else --Uh oh, you're cutting your LSA short!
								yu.lsadash = 1
							end
						end
					end
					if (s.flags2 & MF2_TWOD or twodlevel)
					yu.yteleport = s.y
					end
				end
				yu.bonked = 0
				yu.lsadash = $-1
				yu.changedcharflags = 10
				p.charflags = $|SF_CANBUSTWALLS
				yu.framejump = 0
				yu.jump = 10 yu.spin = 10 yu.custom3 = 10
				yu.sa2jumpdone = true
				yu.nosarun4 = 3 
				p.homing = 0
				yu.hominganim = 0 yu.hominganim2 = 0 yu.hominganim3 = 0
				YuSpinTrail(p, s, yu)
				YuLSAglow(p, s, yu, 0, 100*FRACUNIT, true, 20)			
				p.pflags = $|PF_THOKKED|PF_JUMPDOWN|PF_USEDOWN & ~PF_STARTJUMP & ~PF_SPINNING & ~PF_STARTDASH
				s.state = S_PLAY_FLOAT_RUN
				s.momz = 0
			
			--This is the direction to thrust Sonic in.
			
				if yu.forceyuangletimer
				P_Thrust(s, yu.forceyuangle, 5*FRACUNIT)
					if p.powers[pw_super]
						yu.forceyuangletimer = 0
						p.pflags = $ & ~PF_FORCESTRAFE
						P_InstaThrust(s, s.angle, 130*FRACUNIT)					
					else
						yu.forceyuangletimer = 2
						p.pflags = $|PF_FORCESTRAFE
						P_InstaThrust(s, yu.forceyuangle, 70*FRACUNIT)
					end
					
				else
				
				P_Thrust(s, s.angle, 5*FRACUNIT)
					if p.powers[pw_super]
						yu.forceyuangletimer = 0
						p.pflags = $ & ~PF_FORCESTRAFE
						P_InstaThrust(s, s.angle, 130*FRACUNIT)					
					else			
						P_InstaThrust(s, s.angle, 70*FRACUNIT)
					end
				end
				
				yu.lsaclosest = nil
				yu.vertstylecharge = 0
				yu.ldvertstyle = false
				yu.lightdashing = false
				yu.lsaattack = 0 
				
				--Are we able to lightdash? If so, transition into that smoothly!
				
				if not yu.attackpriority and YuLightDash(p, s, yu)
				
					yu.startz = s.z
					yu.lsacheck = 3
					yu.vertstylecharge = 0
					yu.lightdashing = true
					P_RadiusAttack(s, s, 300*FRACUNIT) --Small starting burst!
							
					for d = 3,5,2		
						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.destscale = s.scale*99
						boom.flags2 = $|MF2_SHADOW
						boom.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIPTHING
					end
					if p == consoleplayer
						if CV_FindVar("cam_speed").string != "0.03999"
						yu.lsacamspeed = CV_FindVar("cam_speed").string
						COM_BufInsertText(p, "cam_speed 0.03999")
						end
					end
					
				else
				
					local detect = P_SpawnMobj(s.x+FixedMul(300*FRACUNIT,cos(s.angle)), s.y+FixedMul(300*FRACUNIT,sin(s.angle)), s.z-400*FRACUNIT, MT_YUECHECK)
					yu.lsacheck = 3
				
					if detect and detect.valid
					detect.target = s
					detect.momx = 2 detect.momy = 2
					detect.height = 800*FRACUNIT
					detect.radius = 300*FRACUNIT
					end
					
				end
				if not yu.lsadash
				and not yu.lsaattack and not yu.lightdashing
				and not yu.lsahoming
					yu.speeduprewardfail = true
					YuCancelLSA(p, s, yu)
					YuStopLSAdash(p, s, yu)
					yu.speedupreward = true
					
					if (yu.bonkeddash > 3) and not yu.supersonic --BONK! HIT A WALL, IDIOT.
						YuBonk(p, s, yu)
					end
				end
			else
				if yu.bonked 
					if yu.bonked > 1 --Bonk animation!
						P_SetObjectMomZ(s, 2*FRACUNIT)
						if yu.lsadashlastangle != nil
						p.drawangle = yu.lsadashlastangle
						s.angle = yu.lsadashlastangle
						P_InstaThrust(s, yu.lsadashlastangle, -18*FRACUNIT)
						end
					end
					yu.bonked = $-1
					if not yu.bonked and not P_IsObjectOnGround(s)
						p.pflags = $|PF_JUMPED & ~PF_THOKKED
						s.state = S_PLAY_ROLL
						P_SetObjectMomZ(s, -3*FRACUNIT, true)
					end					
				end
				if yu.yteleport != nil --Ugh, 2D mode SUCKS. Can't lock momy either because people abuse the Y-axis for visual spectacle.
					if (s.flags2 & MF2_TWOD or twodlevel)
					and not yu.lsahoming and not p.powers[pw_carry]
					and not yu.lsaattack and not p.homing
					and not yu.hitspring
						s.momy = 0
						P_TryMove(s, s.x, yu.yteleport, true)
						s.momy = 0
						yu.yteleport = nil
					end
				end
				if yu.changedcharflags
					if not yu.lsahoming and not p.powers[pw_super]
					yu.changedcharflags = $-1
						if not yu.changedcharflags
						p.charflags = $ & ~SF_CANBUSTWALLS
						yu.changedcharflags = nil
						end
					end
				end
			end
			
			if yu.autojumproll
			yu.autojumproll = $-1
				if not yu.autojumproll and (p.pflags & PF_JUMPED) and (s.momz*P_MobjFlip(s) < 10*s.scale) and yu.jump
					if (s.eflags & MFE_UNDERWATER)
						if (s.momz*P_MobjFlip(s) < 7*s.scale)
						P_SetObjectMomZ(s, 7*FRACUNIT)
						end
					else
					P_SetObjectMomZ(s, 10*FRACUNIT)
					end
				end
			end
			if yu.superbouncetime
				yu.superbouncetime = $-1
			end
			if yu.forceledgeprotect
			yu.forceledgeprotect = $-1
			end
			if yu.nosarun4
			yu.nosarun4 = $-1
				if P_IsObjectOnGround(s)
				yu.nosarun4 = 0
				end
			end
			if yu.edgenope and (p.speed < 6*s.scale)
				yu.edgenope = $-1
			end
			if yu.lsacheck
			yu.lsacheck = $-1
			end
			if yu.hudboost
			yu.hudboost = $+1
				if yu.hudboost > 7
				yu.hudboost = 0
				end
			end
			if yu.supertrick
				yu.supertrick = $-1
			end
			if yu.hypermemories
			yu.hypermemories = $-1
				if not yu.hypermemories
				S_StartSound(s, sfx_s3k9c)
				P_YuFlash(p, PAL_RECYCLE, 4)
				P_NukeEnemies(s, s, 0)
				end
			end
			if yu.superflash --The super transformation flash!
				if yu.superflashd == 1
					if not yu.superflash
						yu.superflashd = -1
						yu.superflash = FRACUNIT
					else
						if (leveltime % 2 == 0) and not (yu.hypermemories or yu.endlvl) 
						or yu.hypermemories and (leveltime % 12 == 0)
						or yu.endlvl and (leveltime % 5 == 0)
						yu.superflash = $-FRACUNIT
							if yu.superflash <= 1 and not yu.hypermemories
							yu.superflashd = -1
								if yu.endlvl
								yu.superflash = 3*FRACUNIT								
								else
								yu.superflash = 6*FRACUNIT
								end
							end
						end
					end

				else --And fade back out if yu.endlvl.
					if (leveltime % 2 == 0) and not (yu.hypermemories) 
					or yu.hypermemories and (leveltime % 12 == 0)
						yu.superflash = $+(FRACUNIT*3)
					end

					if not yu.superflash
					or yu.superflash >= 9*FRACUNIT
					yu.superflashd = 1
					yu.superflash = 0
					end
				end
				if not yu.endlvl
				YuSuperSparkles(p, s, yu, false, 3)
				end
			end
			if (p.rings < 50) or p.powers[pw_super] or p.powers[pw_shield] or yu.supertransform
				p.charflags = $|SF_SUPER
			elseif (p.charflags & SF_SUPER)
				p.charflags = $ & ~SF_SUPER
				--56014 mods trying to force SF_SUPER on you NO MATTER WHAT. Screw all of you!
				if (p.pflags & PF_JUMPED)
				p.pflags = $|PF_USEDOWN
				end
			end			
			if yu.bouncefloor --Checks if you bounced off a moving platform for 2 tics.
				yu.bouncefloor = $-1
			end
			if yu.startdash --Yu-Sonic's version of the PF_STARTDASH flag.
				yu.startdash = $-1
			end
			if p.powers[pw_sneakers]
				if not P_IsObjectOnGround(s) and not p.powers[pw_super]
				yu.shoes = 2
					if (p.speed >= yu.savedspeed) --System to make superbouncing window easier
						yu.savedspeed = p.speed
						yu.savedspeedtimer = 3
					elseif yu.savedspeedtimer
						yu.savedspeedtimer = $-1
						if not yu.savedspeedtimer
							yu.savedspeed = p.speed
						end
					end	
				else
				yu.shoes = 1
				end
				
			else
				yu.shoes = 1
			end	
			if yu.spinanglecooldown
				if not (p.pflags & PF_SPINNING)
				or (yu.direct > 2)
				yu.spinanglecooldown = $-1
				end
			end
			if yu.falltransition --Animation related.
				yu.falltransition = $-1
			end
			if yu.dustdevilfling
			yu.dustdevilfling = $-1
				if not (p.pflags & PF_JUMPED) and ((s.state != S_PLAY_YUHELICOPTER) or (s.sprite != SPR2_WIND))
				and not P_IsObjectOnGround(s) and not (yu.ledgegrabcooldown > 24)
				s.state = S_PLAY_YUHELICOPTER
				end
			end
			if yu.fanspin
			yu.fanspin = $-1
				if not (p.pflags & PF_JUMPED) and (s.state != S_PLAY_YUHELICOPTER) and not P_IsObjectOnGround(s) and not (yu.ledgegrabcooldown > 24)
				s.state = S_PLAY_YUHELICOPTER
				end			
			end		
			if yu.noubercontrol --SA-style Spindash controls are locked with this active.
			yu.noubercontrol = $-1
			end
			if yu.noairdrag --Airdrag doesn't apply with this active.
				if (yu.noairdrag > 115) --Absolute cap.
				yu.noairdrag = 115
				end
				if not ((p.pflags & PF_SPINNING) and P_IsObjectOnGround(s) and (leveltime % 2 == 0))
				yu.noairdrag = $-1
				end
			end
			if yu.noairdrag2 --Airdrag2 is the same thing, but resets if you hit the ground.
				yu.noairdrag2 = $-1
				if P_IsObjectOnGround(s)
				yu.noairdrag2 = 0
				end
			end
			if yu.maxcrush
				yu.maxcrush = $-1
			end			
			if yu.nospindrag --Nospin drag means no "extra" negative momentum from slopes, so Adventure Sonic can make certain launches.
				yu.nospindrag = $-1
			end
			if yu.deathstart --Count down beginning of death animation.
			yu.deathstart = $-1
				if not yu.deathstart 
				yu.deathangle = nil
					if (leveltime % 2 == 0) --Decide whether to roll left or right.
					yu.lsaglow = -1
					else
					yu.lsaglow = 1
					end
				end
			end
			if p.powers[pw_justlaunched] and not (p.pflags & PF_JUMPED)
			yu.noairdrag = $+22 --Gain some speed when launching.
			s.momx = $*10/9
				if not ((s.flags2 & MF2_TWOD) or twodlevel)
				s.momy = $*10/9
				end
			s.momz = $*10/9
			end
			
			--Force the player's angle for a while if this is set.
			
			if yu.forceyuangletimer
				if yu.forceyuangle != nil and (p.pflags & (PF_DIRECTIONCHAR|PF_ANALOGMODE))
				and not p.powers[pw_carry] == CR_DUSTDEVIL and not yu.fanspin
					p.drawangle = yu.forceyuangle
					p.pflags = $|PF_FORCESTRAFE
				end
				
			yu.forceyuangletimer = $-1
			
				if (s.state == S_PLAY_YUHELICOPTER or yu.fanspin)
				and not P_IsObjectOnGround(s) and not (yu.ledgegrabcooldown > 24)
					if s.state != S_PLAY_YUHELICOPTER
					s.state = S_PLAY_YUHELICOPTER
					end
				
					if yu.forceyuangletimer < 2
					yu.forceyuangletimer = 2
					end
					local zoom = FixedAngle(8*FRACUNIT)
					if p.speed > 16*FRACUNIT
						zoom = (FixedAngle(p.speed))/2
					end
				//	yu.forceyuangle = yu.forceyuangle and yu.forceyuangle+zoom or p.drawangle
				end		
				
				if yu.forceyuangletimer <= 0
					p.pflags = $ & ~PF_FORCESTRAFE
					yu.forceangletimer = 0
				end
			end	
			if yu.supereyes --Super Sonic message animation.
				yu.supereyes = $-1
			end
			if yu.tauntcd
				yu.tauntcd = $-1
			end
			if yu.skipgroundcheck --For the bounce attack
				yu.skipgroundcheck = $-1
			end
			if yu.strongspring --Triple springs allow you to bounce in your jump frames, but they don't exist in SRB2.
			--Since blue springs are useless to SA-Sonic with his jumpheight, we'll allow it on them specifically. 
			yu.strongspring = $-1
				if not P_IsObjectOnGround(s) and (s.momz*P_MobjFlip(s) > 0) and (yu.jump)
					if yu.strongspring == 26 and yu.jump
						if p == consoleplayer 
							if CV_FindVar("cam_speed").string != "0.03999"
							yu.lsacamspeed = CV_FindVar("cam_speed").string
							COM_BufInsertText(p, "cam_speed 0.03999")
							end
						end
						if yu.strongbspring
						s.momz = $*20/14
						yu.strongspring = 11
						end
					S_StartSound(s, sfx_sprong)							
					s.momz = $*40/33
					s.momx = 0
					s.momy = 0
					s.state = S_PLAY_ROLL
					p.pflags = $|PF_JUMPED & ~PF_THOKKED & ~PF_SPINNING & ~PF_STARTDASH	
					end				
					YuJumpBallSpawn(p, s, yu)
					
					local ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_IVSP)
					ghs.blendmode = AST_ADD
					if (leveltime % 2 == 0)
						ghs.scale = $*2
					elseif (leveltime % 3 == 0)
						ghs.scale = $*3
					end
					ghs.destscale = ghs.scalespeed+1
					ghs.colorized = true
					ghs.color = SKINCOLOR_RED	
				else
					if not yu.jump and not P_IsObjectOnGround(s) and (s.momz*P_MobjFlip(s) > 0)
					s.momz = $/2
					end
					yu.strongspring = 0
					if s.state == S_PLAY_ROLL and P_IsObjectOnGround(s)
					s.state = S_PLAY_FALL
					end
				end
				yu.strongbspring = nil
			end
			
			--This slight variation on the thok makes quite a difference on gameplay
			
			if yu.farthok 
				yu.nosarun4 = 6
				yu.farthok = $-1
				yu.homingsetup = false
				yu.hominganimstart = 0
				yu.hominganim = 0 yu.hominganim2 = 0 yu.hominganim3 = 0
				 
				if yu.farthok == 8 and (s.state == S_PLAY_ROLL) and (p.pflags & PF_THOKKED) and not P_IsObjectOnGround(s)
				s.state = S_PLAY_FLOAT_RUN
				elseif ((s.state == S_PLAY_WALK) or (s.state == S_PLAY_FLOAT)) and not P_IsObjectOnGround(s)
				s.state = S_PLAY_FLOAT_RUN --We shall fight this game until our last breath.
					if yu.supersonic and p.powers[pw_super]
						if (yu.ledgeprotectanim > C)
						yu.ledgeprotectanim = A
						else
						yu.ledgeprotectanim = $+1
						end
						s.frame = yu.ledgeprotectanim|FF_FULLBRIGHT //|FF_SPR2SUPER
					end
				end
				if (s.eflags & MFE_UNDERWATER) and (yu.farthok > 3)
					local rng = P_RandomRange(20,48)*s.scale
					local rngz = (P_RandomRange(34,64)*P_MobjFlip(s))*s.scale
					s.momz = 0
					s.momx = $*20/21
					s.momy = $*20/21 --Floatier but slower.
					for d = -1,1,2
					local bubble = P_SpawnMobj(s.x-(rng*d),s.y-(rng*d),s.z+rngz,MT_SMALLBUBBLE)
						if bubble and bubble.valid
						bubble.scale = s.scale
						end
					end
				elseif not yu.farthok
					if ((s.state == S_PLAY_FLOAT_RUN) and (p.pflags & PF_THOKKED))
					or P_IsObjectOnGround(s) and ((s.state == S_PLAY_FLOAT_RUN) or (s.state == S_PLAY_ROLL))
					s.state = S_PLAY_FALL
					p.pflags = $|PF_THOKKED & ~PF_SPINNING & ~PF_JUMPED & ~PF_STARTJUMP & ~PF_STARTJUMP
					end
				end
			end
			
			if yu.homingresist --For a few frames you can hurt enemies AFTER the homing attack hits the ground.
			yu.homingresist = $-1 
			end
			
			--Homing Tricks! ...and all the other tricks, under 1 umbrella.
			if yu.homingtrick 
			yu.homingtrick = $-1
			
				if ((yu.lsatrickanim and (p.pflags & PF_JUMPED) and not (p.pflags & PF_THOKKED)) or yu.advance2trail) --The LSA, though...
				and not p.powers[pw_carry] and not yu.bouncestate
				and (s.state == S_PLAY_SPRING or s.state == S_PLAY_RIDE or s.state == S_PLAY_JUMP or s.state == S_PLAY_ROLL)
				
					yu.lsatrickanim = $-1
					yu.lsatrick = true
					yu.chosentrick = 0
					
					if yu.lsatrickanim < 21
						s.state = S_PLAY_SPRING
						if yu.advance2trail
							if (yu.advance2trail < 36)
							yu.advance2trail = 36
							end
							if yu.lsatrickanim == 8
								yu.advance2roll = 11
							end
							if s.rollangle == 0
								s.rollangle = ANG10*11
							end
							if yu.lsatrickanim <= 1
							s.state = S_PLAY_FLOAT_RUN
							end
						elseif not yu.ballspinonly and yu.lsatrickanim == 8
							yu.advance2roll = 11
						end
					else
						s.state = S_PLAY_RIDE
					end
					
					s.rollangle = $-FixedAngle(16*FRACUNIT)
				
						if (yu.lsatrickanim < 39) and (yu.lsatrickanim > 5)
							p.drawangle = yu.lsatrickrollang-FixedAngle(32*FRACUNIT)
							yu.lsatrickrollang = $-FixedAngle(32*FRACUNIT)	
							
						elseif (yu.lsatrickanim <= 2)
							if not yu.advance2trail
							s.rollangle = 0
							end
							yu.lsatrickrollang = 0
							yu.lsatrick = nil
							yu.sa2jumpdone = true
							p.drawangle = R_PointToAngle(s.x, s.y, s.x+s.momx, s.y+s.momy)	
							if (yu.lsatrickanim == 1) and not (s.momz*P_MobjFlip(s) > FRACUNIT)
								s.state = S_PLAY_FALL
							end
						end	
						
				elseif yu.lsatrickanim
				
					yu.lsatrick = nil
					s.rollangle = 0
					yu.chosentrick = 0
					yu.lsatrickrollang = 0
					yu.lsatrickanim = 0
					
				elseif yu.chosentrick and not yu.noaura and not (yu.lsatrick and yu.chosentrick > 99) --For hybrid and SA2 gamestyle only!
				
					--HOMING TRICK 
					yu.sa2jumpdone = true
					yu.spawnedballalready = true
					if yu.chosentrick == 100 --Airfall!
						if (p.panim <= PA_FALL and p.panim >= PA_ROLL)
							if (s.momz*P_MobjFlip(s) < (s.scale*4))
								s.state = S_PLAY_GLIDE
								yu.chosentrick = 0
								yu.stophomingtrick = true
							else
								if s.state != S_PLAY_ROLL
								s.state = S_PLAY_ROLL
								end
								if (s.tics > 1)
									s.tics = 1
								end
							end
						end
					elseif yu.chosentrick == 200 --Invisible skateboard pose!
						if (p.panim <= PA_FALL and p.panim >= PA_ROLL) or s.state == S_PLAY_YUHOMINGTRICK
							if s.state != S_PLAY_YUHOMINGTRICK
								s.state = S_PLAY_YUHOMINGTRICK
							end
							if (s.momz*P_MobjFlip(s) > 18*s.scale) and (s.tics > 1)
								s.tics = 1
							elseif (s.momz*P_MobjFlip(s) > 4*s.scale) and (s.tics > 2)
								s.tics = 2							
							end
						end
						
					elseif yu.chosentrick < 100 --Slightly different flip trick from the LSA variety!
					
						yu.chosentrick = $-1 --Go to PostThinkFrame!
						
						if (yu.chosentrick < 16)
						 --End early??
							if (s.state == S_PLAY_RIDE or s.state == S_PLAY_SPRING)
								s.state = S_PLAY_FALL
							end
							yu.chosentrick = 0
							yu.stophomingtrick = true	
							s.rollangle = 0
						end
						
					end
				end
							
				if yu.stophomingtrick
				yu.stophomingtrick = false
					if (yu.homingtrick > 1)
					yu.homingtrick = 1
					yu.chosentrick = 0
					end
				else
					if (p.panim == PA_ROLL or p.panim == PA_JUMP) --Speed up the non-jumpball roll to make it look less awkward.
					and (s.tics > 1) and not yu.chosentrick and (s.momz*P_MobjFlip(s) > 2*s.scale)
					and not yu.noaura
					s.tics = 1
					end				
				end
				if not yu.homingtrick
				yu.chosentrick = 0
				end
				
			elseif yu.lsatrick
				yu.lsatrick = nil
				s.rollangle = 0
				yu.chosentrick = 0
				yu.lsatrickrollang = 0
				yu.lsatrickanim = 0
			end
			if yu.htrickroll --Keep doing this unless you thokked or landed
			yu.htrickroll = $-1
			s.rollangle = yu.htrickroll		
				if P_IsObjectOnGround(s) or (yu.htrickroll < 31)
				or (p.pflags & PF_THOKKED) or yu.bouncestate
				or p.homing or p.powers[pw_carry] or (yu.ledgegrabcooldown > 24)
				or ((s.state != S_PLAY_RIDE) and (s.state != S_PLAY_SPRING) and (yu.htrickroll < 66) and s.spriteyoffset == 27*FRACUNIT)
				yu.htrickroll = 0
				s.rollangle = 0
				s.spriteyoffset = 0
					if not p.powers[pw_carry] and not (yu.ledgegrabcooldown > 24)
					s.state = S_PLAY_FALL
					end
				end
			end
			
			--Air Drag cutter!
			
			if yu.advance2trail
			yu.advance2trail = $-1			
				if (yu.advance2trail > 25)
					if s.state == S_PLAY_FLOAT_RUN
						if (leveltime % 2 == 0)
							s.frame = A
						else
							s.frame = B
						end
						s.tics = 2
						s.anim_duration = 1
					elseif p.panim == PA_WALK
						s.state = S_PLAY_FALL
					end
					
					--Afterimage trail!
					
					local ghs = P_SpawnGhostMobj(s)
					ghs.colorized = true
					ghs.fuse = 6	
					if p.powers[pw_super]
						ghs.color = s.color
					else
						ghs.color = SKINCOLOR_SKY
					end
					ghs.blendmode = AST_ADD
					--The part that makes it look Advance 2-ish!
					if leveltime % 2 == 0
						ghs.momx = s.momx/2
						ghs.momy = s.momy/2
						ghs.momz = s.momz/2
					elseif leveltime % 3 == 0
						ghs.momx = s.momx/4
						ghs.momy = s.momy/4
						ghs.momz = s.momz/4				
					end
					
				end
				if not yu.lsatrickanim and not yu.advance2roll
					if p.speed < 70*s.scale and yu.advance2trail
					yu.advance2trail = $-1
						if p.speed < 42*s.scale and yu.advance2trail
						yu.advance2trail = $-1
						end
					end
				end
				if not yu.advance2trail and ((s.state == S_PLAY_FALL) or (s.state == S_PLAY_SPRING) or (s.state == S_PLAY_RIDE))
				and not (yu.hitspring >= 100000)
				yu.hitspring = 100000
					if yu.noairdrag2 < 24
					yu.noairdrag2 = 24
					end
					if s.state == S_PLAY_RIDE
					s.state = S_PLAY_SPRING
					end
				end
			end
			if yu.advance2roll
				s.rollangle = ANG10*yu.advance2roll
				yu.advance2roll = $-1
				if not yu.advance2roll
					if yu.advance2trail 
					yu.hitspring = 100000
					yu.noairdrag2 = yu.advance2trail
					end
					s.rollangle = 0
				end
			end
			--Don't stop on ledges for a while.
			if yu.ledgeprotectcd 
			yu.ledgeprotectcd = $-1
			yu.edgenope = $+1
				if (s.state == S_PLAY_EDGE)
					if (s.tics > 1)
					s.tics = 1
					end
				end
				yu.ledgeprotectanim = $+1
				if ((yu.ledgeprotectanim & ~FF_SPR2SUPER & ~FF_FULLBRIGHT & ~FF_TRANSMASK) > E)
					yu.ledgeprotectanim = A
				end				
				if not yu.ledgeprotectcd
					yu.ledgeprotectanim = A
					yu.ledgeprotectangle = nil
					if s.sprite2 == SPR2_EDGE and (p.panim == PA_IDLE)
					s.state = S_PLAY_EDGE				
					end
				end				
			end
			if yu.ledgereactivate
				if (p.pflags & PF_JUMPED) or (p.speed > 10*s.scale) or (p.pflags & PF_SPINNING) or yu.hitspring
				yu.ledgereactivate = nil
				end
			end
			if yu.resetspriteoffset --Needed.
				yu.resetspriteoffset = $-1
				if not yu.resetspriteoffset
				s.spriteyoffset = 0
				s.spritexoffset = 0
				end
			end
			if yu.bounceframe
				yu.bounceframe = $-1
				if not yu.bounceframe
				yu.alteredscale = true
				end
			end
			if yu.ledgegrabcooldown --Can't grab the ledge for a little bit!
			yu.ledgegrabcooldown = $-1

				if (yu.ledgegrabcooldown > 24) --But also, let's do our ledgegrab animation!

				s.rollangle = 0

					if ((s.state == S_PLAY_RIDE) or (s.state == S_PLAY_SPRING)) and (p.pflags & PF_JUMPED)
					p.pflags = $|PF_THOKKED
					p.acceleration = 60
					yu.spin = 5 --No bouncing or thokking for a few frames.
					yu.alteredscale = true
						if (yu.ledgegrabcooldown > 26)
							if yu.supersonic
							s.sprite2 = SPR2_MLEE|FF_SPR2SUPER
							s.frame = A
							else
							s.sprite2 = SPR2_MLEE
								if yu.ledgegrabcooldown >= 28
								s.frame = B
								else
								s.frame = A
								end
							end
						end
						if yu.ledgegrabcooldown == 29 --Very specific behaviour each frame.
							s.spriteyoffset = -31*FRACUNIT
							s.spriteyscale = 74355	
						elseif yu.ledgegrabcooldown == 28
							s.spriteyscale = 95355
							s.spriteyoffset = -44*FRACUNIT
						elseif yu.ledgegrabcooldown == 27
							s.spriteyoffset = -25*FRACUNIT
							s.spriteyscale = 65355

						local ghs = P_SpawnGhostMobj(s)
								ghs.spriteyoffset = -30*FRACUNIT

						elseif yu.ledgegrabcooldown == 26
							s.spriteyoffset = 7*FRACUNIT
							s.spriteyscale = 50355
							s.state = S_PLAY_SPRING
						
							local ghs = P_SpawnGhostMobj(s)
							ghs.tics = 5 ghs.fuse = 5
							ghs.spriteyscale = 50355					
						
						elseif yu.ledgegrabcooldown == 25
							s.spriteyoffset = -2*FRACUNIT
							s.spriteyscale = FRACUNIT
							s.state = S_PLAY_SPRING						
						end						
					end
				elseif yu.ledgegrabcooldown == 24

					s.spriteyoffset = 0
					s.spritexscale = FRACUNIT --Doesn't get modified, buuut....
					s.spriteyscale = FRACUNIT
					if ((s.state == S_PLAY_RIDE) or (s.state == S_PLAY_SPRING)) and (p.pflags & PF_JUMPED)
					p.pflags = $ & ~PF_THOKKED
					s.state = S_PLAY_JUMP
					s.momz = $/3
						if (s.momz*P_MobjFlip(s) > 6*s.scale)
						P_SetObjectMomZ(s, 6*FRACUNIT)
						end
						if yu.ledgeupangle != nil --Thrust Sonic just a lil in the angle we saved so he gets on the ledge even without input
						P_Thrust(s, yu.ledgeupangle, 97770)
						end
						if (s.state == S_PLAY_ROLL) and (p.pflags & PF_JUMPED)
						and (s.tics > 1) and yu.ballspinonly
						s.tics = 1
						end
						yu.ledgeupangle = nil
					end

				else
					if yu.ledgeupangle != nil
					and yu.ledgegrabcooldown < 24
					yu.ledgeupangle = nil
					end	
				end
			end

			--Friction modifiers to keep Sonic's speed when uncurling or running down slopes!

			if yu.groundfriction != yu.runfriction and (yu.runfriction != 0)  
			and not yu.lightdashaftereffects and not yu.spindashfriction
			
				if (yu.runfriction < yu.groundfriction) --ANY of these happen at all, your superfriction is gone, mister.
				or ((p.speed < 50*s.scale) and yu.frictionspeedtreshold > 4)
				or (yu.jump == 1 and (p.pflags & PF_JUMPED) and (p.pflags & PF_STARTJUMP))
				or (p.cmd.sidemove == 0 and p.cmd.forwardmove == 0) or p.gotflag
				or yu.brakeanim or (s.state == S_PLAY_PAIN) or (p.pflags & PF_SPINNING)
				or (p.speed > 220*s.scale)
					yu.runfriction = yu.groundfriction
					yu.frictionreset = 180
					yu.frictionlock = 0
					
				elseif yu.runfriction > yu.groundfriction
				
					if (yu.runfriction > FRACUNIT) --Never go above FRACUNIT or we'll reach infinite speeds.
					yu.runfriction = FRACUNIT
					else
						if yu.frictionlock
							if (p.powers[pw_super] or yu.mysticsuper or (p.isxmomentum and not p.xmomtoggledoff))
							and yu.direct
								if (leveltime % 8 == 0) and not yu.superaura --Lose friction slower. 'cause you're technically floating. Idiot.
								yu.frictionlock = $-1
								end
							else
							yu.frictionlock = $-1
							end
						else
							if (p.isxmomentum and not p.xmomtoggledoff)
							yu.runfriction = $-1 --Xmom's weird.
							elseif p.powers[pw_super] or yu.mysticsuper
							yu.runfriction = $-29
							else
							yu.runfriction = $-45
							end
						end
					end
				end
				
				s.friction = yu.runfriction
				
				if yu.frictionreset
				yu.frictionreset = $-1
					if not yu.frictionreset --Failsafe.
					yu.runfriction = yu.groundfriction
					yu.frictionreset = 180
					yu.frictionlock = 0
					end
				end
			end
			if yu.forcebuilder
			yu.forcebuilder = $-1
				if P_IsObjectOnGround(s) or p.powers[pw_nocontrol] or p.powers[pw_carry]
				or yu.farthok or yu.hominganimstart or p.homing or (yu.hitspring and yu.hitspring < 100000)
				yu.forcebuilder = 0
				end
			end
			if yu.hominganimstart --Indicates you're doing the homing attack-roll.
			yu.hominganimstart = $-1
				if not (p.pflags & PF_THOKKED) and not yu.farthok
				yu.hominganimstart = 0
				yu.hominganim = 4 yu.hominganim2 = 4 yu.hominganim3 = 4
				end
			end

			if yu.bouncexstretch < 100 --Stretching X effect when landing with a bounce.

				if yu.bouncestate >= 2
				s.spritexscale = FRACUNIT*100/yu.bouncexstretch
				end
				
			yu.bouncexstretch = $+4
			
				if yu.bouncexstretch >= 100
				yu.bouncexstretch = 100
				s.spritexscale = FRACUNIT		
				end
			end
			
			if yu.bounceystretch > 100 --Stretching Y effect when landing with a bounce.
				if yu.bouncestate >= 2
				s.spriteyscale = FRACUNIT*100/yu.bounceystretch
				end
				
			yu.bounceystretch = $-4
			
				if yu.bounceystretch <= 100
				yu.bounceystretch = 100
				s.spriteyscale = FRACUNIT		
				end
			end
			
			if yu.superbounce
			yu.superbounce = $-1
			
				local bouncecolor = P_RandomRange(SKINCOLOR_SUPERSILVER3, SKINCOLOR_SUPERGOLD5)
			
				local ghs = P_SpawnGhostMobj(s)
				ghs.blendmode = AST_ADD
				ghs.color = s.color
				ghs.tics = 11
				ghs.colorized = true
				ghs.destscale = ghs.scalespeed+1
				
				ghs = P_SpawnMobjFromMobj(s, 0, 0, 0, MT_IVSP)
				ghs.blendmode = AST_ADD
					if (leveltime % 2 == 0)
						ghs.scale = $*2
					elseif (leveltime % 3 == 0)
						ghs.scale = $*3
					end
				ghs.destscale = ghs.scalespeed+1
				ghs.colorized = true
				ghs.color = bouncecolor
				
			end
			
			if yu.startdash or (p.pflags & PF_STARTDASH) or yu.bouncestate == 1 --Stretch and squash while charging spindash
				if yu.yspinstretch > 85 --81 before
					if (leveltime % 2 == 0) or yu.bouncestate == 1
					yu.yspinstretch = $-1
					end
				end
				if yu.xspinstretch < 138 --158 before
					if (leveltime % 2 == 0) or yu.bouncestate == 1
					yu.xspinstretch = $+2
					end
					if yu.xspinstretch > 138
					yu.xspinstretch = 138 --failsafe
					end
				end
			elseif yu.yspinstretch != 100 or yu.xspinstretch != 100
			yu.xspinstretch = 100 yu.yspinstretch = 100
			end
			
			if yu.spindashfriction
			yu.spindashfriction = false
				if not P_IsObjectOnGround(s)
				or not (p.pflags & PF_SPINNING)
				s.friction = 59392
				end
			end
			
			--Button timers. If it's 1, you literally JUST tapped the button. If it's 0, you've let go. 
			--If it's above 1, you've been holding the button for over a tic. (example: If it's 35, you've been holding it for 1 second)
			--These won't register if p.powers[pw_nocontrol] is active. 
			
			if (p.cmd.buttons & BT_CUSTOM3)
				yu.custom3 = $+1
			else
				yu.custom3 = 0
			end
			if (p.cmd.buttons & BT_USE)
				yu.spin = $+1
			else
				yu.spin = 0
			end	
		end
		
		--This applies to all skins...

		if yu.flyencouragement
			yu.flyencouragement = $-1
		end
		if p.exiting and (gametype == GT_COOP)
			if yu.bosskiller
			
				if yu.bouncestate
					YuResetBounce(p, s, yu)
				end			
				if p.powers[pw_nocontrol] < 70
					p.powers[pw_nocontrol] = 70
				end
				if (s.momz*P_MobjFlip(s) > 0)
					s.momz = 0
				end
				s.momx = 0
				s.momy = 0
				yu.spin = 15
				yu.jump = 15
				yu.startdash = 0
				p.pflags = $ & ~PF_STARTDASH & ~PF_SPINNING & ~PF_JUMPED
				
				if P_IsObjectOnGround(s) and (p.exiting < 97) 
					if s.state != S_PLAY_FLY
						if yu.bosskiller == 1
						YuVoice(p, s, yu, sfx_yuvocb, true)
						s.state = S_PLAY_FLY
						yu.tauntstate = 1
						yu.bosskiller = 2
						end
					end
					if not yu.camscale
					yu.camscale = p.camerascale
					p.camerascale = 28221
					end
				end
			end
			if yu.endlvl --Exit level victory animation!	
			yu.endlvl = $+1
				if (yu.endlvl > 38)
					s.momx = p.cmomx
					s.momy = p.cmomy
				end
				if (yu.endlvl > 150) and (leveltime > 151) --Shouldn't be possible. Exitlevel.
					G_ExitLevel()
				end
			end
		end
		
		--Get ready to revert Super Sonic's gravity when he's not flying.
		if yu.nogravity and not (yu.superflight and yu.supersonic)
			yu.nogravity = $-1
			s.flags = $ & ~MF_NOGRAVITY
		end
		
		--Super shield behaviour
		if p.powers[pw_shield] == SH_YUSUPERSHIELD
			if not yu.superorigin or not yu.superorigin.valid
			or (yu.superorigin.player and not yu.superorigin.player.powers[pw_super])
			or (yu.supersonic and s.skin == "adventuresonic")
				if p.powers[pw_shield] == SH_YUSUPERSHIELD			
					p.powers[pw_shield] = 0
				end
				P_NukeEnemies(s, s, 256*s.scale)
				yu.superorigin = nil
				for d = 1,18
					YuSuperSparkles(p, s, yu, false, 4)
				end
			else
				if (p.powers[pw_super] or p.mysticsuper or p.hypermysticsonic) and (leveltime % 70 == 0) --Half ring drain!
				P_GivePlayerRings(p, 1)
				end
				if (p.pflags & PF_SPINNING) and P_IsObjectOnGround(s) and (p.speed > 8*s.scale)
				P_ElementalFire(p)
				end
				YuSuperAura(p, s, yu, nil, true)
			end
			yu.hassupershield = true
		elseif yu.hassupershield
			if not p.powers[pw_shield]
			P_YuQuake(p, 50*FRACUNIT, 3)
			P_NukeEnemies(s, s, 444*s.scale)
			end
			yu.hassupershield = nil
		end		
		
		if (p.cmd.buttons & BT_JUMP) --Button timer outside of the "adventuresonic" check on purpose.
			yu.jump = $+1
		else
			yu.jump = 0
		end
		if (p.cmd.buttons & BT_CUSTOM2)
			yu.custom2 = $+1
		else
			yu.custom2 = 0
		end
			
	end
end)