freeslot(
"MT_CAREXPLODE","MT_GTHOK",
"S_PLAY_LDSH", "S_PLAY_LDSH2","S_GTHOK",
"sfx_djmpdv", "sfx_stmpdv", "sfx_heatst", "sfx_ftheat", "sfx_heatnd", "sfx_kart", "sfx_kartgo", "sfx_krtdft", "sfx_sa2dsh", "sfx_sajdsh")

states[S_PLAY_LDSH] = {SPR_PLAY, SPR2_GLID|FF_SPR2MIDSTART, 1, A_HomingChase, 50*FRACUNIT, 0, S_PLAY_LDSH2}
states[S_PLAY_LDSH2] = {SPR_PLAY, SPR2_GLID|FF_SPR2MIDSTART, 2, A_GhostMe, 0, 0, S_PLAY_FALL}

COM_AddCommand("supercar", function(player)
	if player.supercar == false
		player.supercar = true
		CONS_Printf(player, "Greeneyes will now drive a car.")
	elseif player.supercar == true
		player.supercar = false
		CONS_Printf(player, "Greeneyes will no longer drive a car.")
	end
end, 0)

COM_AddCommand("simplequickstep", function(player, arg)
	if arg
		if arg == "1" or arg == "true" or arg == "on"
			if io and player == consoleplayer
				local file = io.openlocal("client/greeneyes/quickstep.dat", "w+")
				file:write(arg)
				file:close()
			end
			player.simplequickstep = true
			CONS_Printf(player, "You can now hold Fire and press strafe to quickstep!")
		elseif arg == "0" or arg == "false" or arg == "off"
			if io and player == consoleplayer
				local file = io.openlocal("client/greeneyes/quickstep.dat", "w+")
				file:write(arg)
				file:close()
			end	
			player.simplequickstep = false
			CONS_Printf(player, "You can now press Fire or Fire normal to quickstep!")
		elseif player.simplequickstep
			CONS_Printf(player, "simplequickstep [on/off] - Changes the input method for the quickstep. Currently on.")
		else
			CONS_Printf(player, "simplequickstep [on/off] - Changes the input method for the quickstep. Currently off.")
		end
	elseif player.simplequickstep
		CONS_Printf(player, "simplequickstep [on/off] - Changes the input method for the quickstep. Currently on.")
	else
		CONS_Printf(player, "simplequickstep [on/off] - Changes the input method for the quickstep. Currently off.")
	end
end, 0)

COM_AddCommand("simpleabilities", function(player, arg)
	if arg
		if arg == "1" or arg == "true" or arg == "on"
			if io and player == consoleplayer
				local file = io.openlocal("client/greeneyes/abilities.dat", "w+")
				file:write(arg)
				file:close()
			end
			player.simpleabilities = true
			CONS_Printf(player, "You can now press Jump twice to Double Jump, and press Spin to Stomp!")
		elseif arg == "0" or arg == "false" or arg == "off"
			if io and player == consoleplayer
				local file = io.openlocal("client/greeneyes/abilities.dat", "w+")
				file:write(arg)
				file:close()
			end	
			player.simpleabilities = false
			CONS_Printf(player, "You can now press Custom 1 to Double Jump, and press Custom 2 to Stomp!")
		elseif player.simpleabilities
			CONS_Printf(player, "simpleabilities [on/off] - Changes the input method for Greeneyes' aerial abilities. Currently on.")
		else
			CONS_Printf(player, "simpleabilities [on/off] - Changes the input method for Greeneyes' aerial abilities. Currently off.")
		end
	elseif player.simpleabilities
		CONS_Printf(player, "simpleabilities [on/off] - Changes the input method for Greeneyes' aerial abilities. Currently on.")
	else
		CONS_Printf(player, "simpleabilities [on/off] - Changes the input method for Greeneyes' aerial abilities. Currently off.")
	end
end, 0)

--FixedLerp
local function FixedLerp(a, b, w)
    return FixedMul((FRACUNIT - w), a) + FixedMul(w, b)
end

//Skydive
addHook("MobjSpawn", function(mo) mo.skydive = 0 end, MT_PLAYER)
addHook("MobjSpawn", function(mo) mo.skydivelock = 0 end, MT_PLAYER)
addHook("MobjSpawn", function(mo) mo.wasdiving = 0 end, MT_PLAYER)

//Sonic Advance 2 styled acceleration
addHook("MobjSpawn", function(mo) mo.isrunning = 0 end, MT_PLAYER)
addHook("MobjSpawn", function(mo) mo.timer4 = 0 end, MT_PLAYER)

addHook("ThinkFrame", do
	for player in players.iterate
		if player.lightdash == nil
			player.lightdash = 0
		end
		if player.tossflagdown == nil
			player.tossflagdown = 1
		end
		if player.prevrings == nil
			player.prevrings = 1
		end
		if player.prevscore == nil
			player.prevscore = 1
		end
		if player.notboostmeter == nil
			player.notboostmeter = 1
		end
		if player.heatready == nil
			player.heatready = 1
		end
		if player.notboostmeter > 40
			player.notboostmeter = 40
		end
		if player.feelingheat == nil
			player.feelingheat = 0
		end
		if player.heatadvance == nil
			player.heatadvance = 0
		end
		if player.supercar == nil
			player.supercar = false
		end
		if player.drivingsupercar == nil
			player.drivingsupercar = 0
		end
		if player.simplequickstep == nil
			player.simplequickstep = false
		end
		if player.simpleabilities == nil
			player.simpleabilities = false
		end
		if player.heatstats == nil
			player.heatstats = 0
		end
		
		if player.mo and (player.mo.skin == "greeneyesonic")
		and player.powers[pw_carry] != CR_NIGHTSMODE
		and (player.playerstate == PST_LIVE)
			
		//Skydiving	
		//commenting this out because I didn't like it
		
-- 			if (player.mo.state == S_PLAY_FALL)
-- 			and player.cmd.buttons & BT_CUSTOM1
-- 				player.mo.skydive = 1
-- 			end
-- 			if player.mo.skydive == 1
-- 			and not (player.cmd.buttons & BT_CUSTOM1)
-- 				player.mo.skydivelock = 1
-- 				player.mo.wasdiving = 1
-- 			end
-- 			if player.mo.skydivelock == 1
-- 				/*if (player.feelingheat == 1)
-- 					player.normalspeed = 55*FRACUNIT
-- 				else
-- 					player.normalspeed = 31*FRACUNIT
-- 				end*/
-- 				if not (player.cmd.buttons & BT_CUSTOM2)
-- 					if player.mo.momz < -3*FRACUNIT
-- 						P_SetObjectMomZ(player.mo, -3*FRACUNIT, false)
-- 					end
-- 					if (player.mo.state == S_PLAY_FALL)
-- 						player.mo.sprite2 = SPR2_TAL0
-- 					end
-- 				end
-- 				if (player.cmd.buttons & BT_CUSTOM2)
-- 					--P_SetObjectMomZ(player.mo, -24*FRACUNIT, false)
-- 					if (player.mo.state == S_PLAY_FALL)
-- 						player.mo.sprite2 = SPR2_TAL1
-- 					end
-- 				end
					
-- 				if player.mo.skydivelock == 1
-- 				and (player.cmd.buttons & BT_CUSTOM1)
-- 					player.mo.skydivelock = 0
-- 					player.mo.pflags = PF_JUMPED
-- 					player.mo.state = S_PLAY_ROLL
-- 					player.mo.skydive = 0
-- 					/*if (player.feelingheat == 1)
-- 						player.normalspeed = 60*FRACUNIT
-- 					else
-- 						player.normalspeed = 36*FRACUNIT
-- 					end*/
-- 				end
-- 				if player.mo.skydivelock == 1
-- 				and P_IsObjectOnGround(player.mo)
-- 					player.mo.skydivelock = 0
-- 					player.mo.skydive = 0
-- 				end
-- 			end
-- 			if P_IsObjectOnGround(player.mo)
-- 				player.mo.wasdiving = 0
-- 			end
		//Jumping Spin Control-lock begone!	
			if player.pflags & PF_JUMPED
				player.pflags = $1 & ~PF_SPINNING
			end
		//Momentum Homing	
			if player.mo.state == S_PLAY_SPRING
			and (player.pflags & PF_JUMPED)
			and (player.pflags & PF_JUMPDOWN)
			and not (player.mo.eflags & MFE_SPRUNG)
				P_Thrust(player.mo, player.mo.angle, player.normalspeed)
				P_SetObjectMomZ(player.mo, 10*FRACUNIT, false)
				player.doublejumped = nil
				player.mo.state = S_PLAY_JUMP
				player.pflags = $ & ~PF_NOJUMPDAMAGE
				player.pflags = $ & ~PF_THOKKED
			elseif player.mo.state == S_PLAY_SPRING
			and (player.pflags & PF_JUMPED)
			and not (player.pflags & PF_JUMPDOWN)
				player.doublejumped = nil
				player.mo.state = S_PLAY_JUMP
				player.pflags = $ & ~PF_NOJUMPDAMAGE
				player.pflags = $ & ~PF_THOKKED
			end
			
			/*if (player.pflags & PF_JUMPED)
				--player.mo.prevframe = player.mo.frame
				if (player.mo.state == S_PLAY_JUMP)
				and (player.cmd.buttons & BT_SPIN)
					player.mo.state = S_PLAY_ROLL
					--player.mo.frame = player.mo.prevframe
				elseif (player.mo.state == S_PLAY_ROLL)
				and not (player.cmd.buttons & BT_SPIN)
					player.mo.state = S_PLAY_JUMP
					--player.mo.frame = player.mo.prevframe
				end
			end*/
			
			if (player.cmd.buttons & BT_SPIN)
			and not player.homing
				player.charability = CA_THOK
			else
				player.charability = CA_HOMINGTHOK
			end
			
		//Heat mode stuff
			if player.heattrans == nil
				player.heattrans = 0
			end
			if player.heatcounter == nil
				player.heatcounter = 0
			end
			if player.heatscale == nil
				player.heatscale = 0
			end
			if player.heatcounter < 17
				player.heatcounter = $ + 1
			end
			if player.heatcounter == 17
				player.heatcounter = 1
			end
			
			if player.heatcounter == 1
				player.heattrans = TR_TRANS10
				player.heatscale = 1
			end
			if player.heatcounter == 2
			or player.heatcounter == 16
				player.heattrans = TR_TRANS20
				player.heatscale = 2
			end
			if player.heatcounter == 3
			or player.heatcounter == 15
				player.heattrans = TR_TRANS30
				player.heatscale = 3
			end
			if player.heatcounter == 4
			or player.heatcounter == 14
				player.heattrans = TR_TRANS40
				player.heatscale = 4
			end
			if player.heatcounter == 5
			or player.heatcounter == 13
				player.heattrans = TR_TRANS50
				player.heatscale = 5
			end
			if player.heatcounter == 6
			or player.heatcounter == 12
				player.heattrans = TR_TRANS60
				player.heatscale = 6
			end
			if player.heatcounter == 7
			or player.heatcounter == 11
				player.heattrans = TR_TRANS70
				player.heatscale = 7
			end
			if player.heatcounter == 8
			or player.heatcounter == 10
				player.heattrans = TR_TRANS80
				player.heatscale = 8
			end
			if player.heatcounter == 9
				player.heattrans = TR_TRANS90
				player.heatscale = 9
			end
			
			if player.feelingheat == 1
				for i = 0, 32
					local trail = P_SpawnMobjFromMobj(player.mo, 0, 0, 0, MT_GTHOK)
					local percent = FRACUNIT * (i * 10) / 100
					local tx = FixedLerp(player.mo.x, player.mo.previousx, percent)
					local ty = FixedLerp(player.mo.y, player.mo.previousy, percent)
					local tz = FixedLerp(player.mo.z, player.mo.previousz, percent)
					P_TeleportMove(trail, tx, ty, tz + 20 * FRACUNIT)
					if player.skincolor == skins[player.mo.skin].prefcolor
						trail.color = SKINCOLOR_RUBY
					else
						trail.color = ColorOpposite(player.skincolor)
					end
					trail.angle = R_PointToAngle2(0, 0, player.mo.momx, player.mo.momy)
					if trail.heatscale == nil
						trail.scale = (player.heatscale*FRACUNIT/4) - percent/2
						trail.heatscale = 0
					end
					trail.fuse = 1
					trail.frame = $|TR_TRANS70
				end
				/*local heat = P_SpawnMobjFromMobj(player.mo,0,0,20*FRACUNIT,MT_GTHOK)
				if heat and heat.valid
					if player.skincolor == skins[player.mo.skin].prefcolor
						heat.color = SKINCOLOR_RUBY
					else
						heat.color = ColorOpposite(player.skincolor)
					end
					heat.scale = player.heatscale*FRACUNIT/4
					heat.fuse = 8
					--heat.destscale = 0
					heat.frame = $|player.heattrans
				end
				*/
				player.normalspeed = 60*FRACUNIT
				player.actionspd = 150*FRACUNIT
				player.acceleration = 55
				player.accelstart = 125
				player.heatstats = 1
				player.heatadvance = $1+1
				if player.heatadvance >= 7
				and player.notboostmeter >= 0
					player.notboostmeter = $1 - 1
					player.heatadvance = 0
				end
			end
			
			if (player.pflags & PF_JUMPED and player.homing > 0)
			or ((player.pflags & PF_SPINNING) and not (player.pflags & PF_JUMPED) and (player.speed > FixedMul(player.mo.scale, 15*FRACUNIT) and not (player.pflags & PF_STARTDASH)))
				for i = 0, 7
					local percent = FRACUNIT * (i * 10) / 100
					local trail = P_SpawnGhostMobj(player.mo)
					local tx = FixedLerp(player.mo.x, player.mo.previousx, percent)
					local ty = FixedLerp(player.mo.y, player.mo.previousy, percent)
					local tz = FixedLerp(player.mo.z, player.mo.previousz, percent)
					P_TeleportMove(trail, tx, ty, tz - 4 * FRACUNIT)
					trail.state = mobjinfo[player.thokitem].spawnstate
					trail.color = player.mo.color
					trail.frame = A|FF_TRANS90
					trail.angle = R_PointToAngle2(0, 0, player.mo.momx, player.mo.momy)
					trail.fuse = 7
				end
			end
			
			if player.feelingheat == 0
			and player.heatstats == 1
				player.normalspeed = skins["greeneyesonic"].normalspeed
				player.actionspd = skins["greeneyesonic"].actionspd
				player.acceleration = skins["greeneyesonic"].acceleration
				player.accelstart = skins["greeneyesonic"].accelstart
				player.heatstats = 0
			end
			
			if player.notboostmeter == 0
			and player.feelingheat == 1
				S_StartSound(player.mo, sfx_heatnd)
				player.feelingheat = 0
			end
	
		//Sonic Advance 2 inspired Boost mode
			if ((FixedHypot(player.mo.momx, player.mo.momy) > player.runspeed) or (player.mo.state == S_PLAY_SPINDASH))
			and player.mo.isrunning == 0
			and player.mo.timer4 == 0
				player.mo.timer4 = 140
			end
			if player.mo.timer4 > 0
			and ((FixedHypot(player.mo.momx, player.mo.momy) > player.runspeed) or (player.mo.state == S_PLAY_SPINDASH))
				player.mo.timer4 = $1 - 1
			end
			if FixedHypot(player.mo.momx, player.mo.momy) < player.runspeed
			and player.mo.timer4 > 0
			and player.mo.timer4 < 139
				if not (player.mo.state == S_PLAY_SPINDASH)
					player.mo.timer4 = 0
				end
			end
			if ((FixedHypot(player.mo.momx, player.mo.momy) > player.runspeed) or (player.mo.state == S_PLAY_SPINDASH))
			and player.mo.timer4 == 35
				player.mo.isrunning = 1
				S_StartSound(player.mo, sfx_sa2dsh)
			end
			if player.mo.timer4 == 1
				player.mo.timer4 = 0
			end
			if player.mo.isrunning == 1
				if (leveltime % 10 == 0)
					player.runningtimer = $ + 1
				end
				if (player.feelingheat == 1)
					player.normalspeed = min( (player.runningtimer + 76)*FRACUNIT, 90*FRACUNIT)
				else
					player.normalspeed = min( (player.runningtimer + 52)*FRACUNIT, 70*FRACUNIT)
				end
				if (leveltime % 2 == 0)
					local ghost = P_SpawnGhostMobj(player.mo)
					ghost.blendmode = AST_ADD
					ghost.colorized = true
				end
			end
			if FixedHypot(player.mo.momx, player.mo.momy) < player.runspeed
			and player.mo.timer4 < 32
			and P_IsObjectOnGround(player.mo)
				if not (player.mo.state == S_PLAY_SPINDASH)
					player.mo.isrunning = 0
				end
			end
			if player.mo.isrunning == 0
				player.runningtimer = 0
				if (player.feelingheat == 1)
					player.normalspeed = 60*FRACUNIT
				else
					player.normalspeed = 36*FRACUNIT
				end
			end
		//SuperCar	
			if (player.supercar == true)
				player.charflags = $ | SF_DASHMODE
				if player.carexplodetimer == nil
					player.carexplodetimer = 0
				end
				if player.dashmode > 3*TICRATE
					
					if player.drivingsupercar == 0
						S_StartSound(player.mo, sfx_kartgo)
					end
					player.drivingsupercar = 1
					player.charflags = $ | SF_MACHINE
					player.mo.state = S_PLAY_DASH
					if P_IsObjectOnGround(player.mo)
						P_SpawnSkidDust(player, player.mo.radius)
						S_StartSound(player.mo, sfx_kart)
					end
					
					player.nomoredashmodeflash = P_SpawnGhostMobj(player.mo)
					player.nomoredashmodeflash.fuse = 1
					player.nomoredashmodeflash.frame = player.mo.frame
				end
				
				if player.dashmode < 3*TICRATE
				and player.drivingsupercar == 1
					player.carexplosion = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_THOK)
					player.carexplosion.fuse = 35
					player.carexplosion.state = S_INVISIBLE
					player.carexplodetimer = 35
					player.charflags = $ & ~SF_MACHINE
					player.drivingsupercar = 0
				end
				if player.carexplodetimer > 0
				and player.carexplosion.valid
					player.carexplodetimer = $ - 1
					A_BossScream(player.carexplosion, 1, MT_CAREXPLODE)
					S_StartSound(player.carexplosion, sfx_s244)
				end
			elseif (player.supercar == false)
				player.charflags = $ & ~SF_DASHMODE
			end			
			
			if (player.pflags & PF_GODMODE)
				player.notboostmeter = 40
			end
		//Double jump
			if ((player.cmd.buttons & BT_CUSTOM1) or (player.simpledoublejump == 1))
			and (player.pflags & PF_JUMPED)
			and not player.powers[pw_carry]
			and not (player.pflags & PF_STASIS)
			and not (player.pflags & PF_JUMPSTASIS)
			and not (player.mo.tracer and player.mo.tracer.type == MT_TUBEWAYPOINT)
			and not P_IsObjectOnGround(player.mo)
			and not (player.pflags & PF_THOKKED)
			and not player.c1down
			and player.lightdash == 0
			and player.doublejumped == nil
				if (P_MobjFlip(player.mo) == -1 and player.mo.momz >= 0)
				or (P_MobjFlip(player.mo) == 1 and player.mo.momz <= 0)
					if player.mo.eflags & MFE_UNDERWATER
						P_SetObjectMomZ(player.mo, 5*FixedMul(player.mo.scale, player.jumpfactor), false)
					else
						P_SetObjectMomZ(player.mo, 10*FixedMul(player.mo.scale, player.jumpfactor), false)
					end
				else
					if player.mo.eflags & MFE_UNDERWATER
						P_SetObjectMomZ(player.mo, 5*FixedMul(player.mo.scale, player.jumpfactor), true)
					else
						P_SetObjectMomZ(player.mo, 10*FixedMul(player.mo.scale, player.jumpfactor), true)
					end
				end
				S_StartSound(player.mo, sfx_djmpdv)
				P_SpawnGhostMobj(player.mo)
				player.doublejumped = 0
			end
			
			if P_IsObjectOnGround(player.mo)
				player.doublejumped = nil
			end
			if (player.wasjuststomping == nil) then
				player.wasjuststomping = false
			end
			
			if player.prevrings < player.rings
				if player.powers[pw_super] then player.notboostmeter = $1 + (player.rings - player.prevrings) end
				player.notboostmeter = $1 + (player.rings - player.prevrings)
			end
			if player.prevscore < player.score
				if player.powers[pw_super] then player.notboostmeter = $1 + (player.score - player.prevscore)/100 end
				player.notboostmeter = $1 + (player.score - player.prevscore)/100
			end
			
			if player.notboostmeter == 40
			and player.heatready == 0
				S_StartSound(player.mo, sfx_ftheat)
				player.heatready = 1
			elseif player.notboostmeter == 40
			and player.heatready == 1
			end
			
			if player.notboostmeter < 40
				player.heatready = 0
			end
			
			if player.exiting
				player.feelingheat = 0
			end
			
			if player.feelingheat == 0
				if player.notboostmeter < 40
				and (leveltime % TICRATE == 0)
					player.notboostmeter = $+1 
				end
			end
			
			if (player.cmd.buttons & BT_CUSTOM3)
			and player.feelingheat != 1
			and player.notboostmeter == 40
			and not player.powers[pw_carry]
			and not player.powers[pw_carry]
			and not (player.pflags & PF_STASIS)
			and not (player.pflags & PF_JUMPSTASIS)
			and not (player.exiting)
			and not (player.mo.tracer and player.mo.tracer.type == MT_TUBEWAYPOINT)
				player.feelingheat = 1
				S_StartSound(player.mo, sfx_heatst)
			end
		//Uncurl
			if not player.powers[pw_carry]
			and (player.cmd.buttons & BT_USE)
			and (player.pflags & PF_USEDOWN)
			and not (player.mo.state == S_PLAY_PAIN)
			and not (player.mo.tracer and player.mo.tracer.type == MT_TUBEWAYPOINT)
			and not (player.pflags & PF_STASIS)
			and (player.pflags & PF_SPINNING)
			and not (player.pflags & PF_STARTDASH)
			and not (player.exiting)
			and player.spinningtime > 1
			and (P_IsObjectOnGround(player.mo)) then
				player.mo.state = S_PLAY_WALK
				player.pflags = $1 & ~PF_SPINNING
			end

			if (player.pflags & PF_SPINNING) and not (player.pflags & PF_USEDOWN) then
				player.spinningtime = $+1
			else
				player.spinningtime = 0
			end
			
			
		//Lightspeed Dash
			if (((player.cmd.buttons & BT_TOSSFLAG) and not player.tossflagdown) or player.lightdash > 0)
			and not player.powers[pw_carry]
			and not (player.pflags & PF_STASIS)
			and not (player.pflags & PF_JUMPSTASIS)
			and not (player.pflags & PF_SPINNING)
			and not (player.powers[pw_shield] == SH_ATTRACT)
			and not (player.exiting)
			and not (player.mo.state == player.mo.info.painstate)
				A_FindTarget (player.mo, MT_RING, 0)
				if player.mo.target
				and player.mo.target.type == MT_RING
					A_CheckTrueRange (player.mo, 200, S_PLAY_LDSH)
				end
				
				if player.mo.state >= S_PLAY_LDSH and player.mo.state <= S_PLAY_LDSH2
					//player.mo.angle = R_PointToAngle2(player.mo.x, player.mo.y, player.mo.target.x, player.mo.target.y)
					player.drawangle = R_PointToAngle2(player.mo.x, player.mo.y, player.mo.target.x, player.mo.target.y)
					player.lightdash = 5
					if player.powers[pw_super]
						player.mo.sprite2 = $|FF_SPR2SUPER
					end
				end
			else
				player.lightdash = 0
			end
		//Speed Stomp
			if ((player.cmd.buttons & BT_CUSTOM2) or (player.simplestomp == 1))
			and not player.powers[pw_carry]
			and not (player.pflags & PF_STASIS)
			and not (player.pflags & PF_JUMPSTASIS)
			and not (player.mo.eflags & MFE_GOOWATER)
			and not (player.exiting)
			and not (player.mo.tracer and player.mo.tracer.type == MT_TUBEWAYPOINT)
			and not P_IsObjectOnGround(player.mo)
			and not (player.mo.state == player.mo.info.painstate)
			and player.lightdash == 0
				P_SetObjectMomZ(player.mo, FRACUNIT*-12, true)
				player.pflags = $1|PF_JUMPED
				P_SpawnGhostMobj(player.mo)
				if (player.wasjuststomping == false) then
					S_StartSound(player.mo, sfx_stmpdv)
				end
				player.wasjuststomping = true
			else 
				player.wasjuststomping = false
			end
			player.mo.previousx = player.mo.x
			player.mo.previousy = player.mo.y
			player.mo.previousz = player.mo.z
		
		
			if (player.cmd.buttons & BT_CUSTOM2)
				player.c2down = true
			else
				player.c2down = false
			end
			
			if (player.cmd.buttons & BT_TOSSFLAG)
				player.tossflagdown = true
			else
				player.tossflagdown = false
			end
			
			player.c1down = player.cmd.buttons & BT_CUSTOM1
			player.jumpdown = player.cmd.buttons & BT_JUMP
			
			
			if (player.lightdash > 0)
				player.lightdash = $1 - 1
			end
			
			if player.mo.state == S_PLAY_LDSH
			or player.mo.state == S_PLAY_LDSH2
			and not (player.pflags & PF_JUMPED)
				player.pflags = $ | PF_JUMPED
			end
				
			player.prevrings = player.rings
			player.prevscore = player.score
			
			if not (player.cmd.buttons & BT_JUMP)
				player.simpledoublejump = 0
			end
			if not (player.cmd.buttons & BT_SPIN)
				player.simplestomp = 0
			elseif (player.cmd.buttons & BT_SPIN)
			and not P_IsObjectOnGround(player.mo)
			and player.simpleabilities == true
				player.simplestomp = 1
			end
			if (player.cmd.buttons & BT_SPIN)
			and not player.wasspinning
			and not player.spindown
			and P_GetPlayerControlDirection(player) == 0
			and (player.pflags & PF_SPINNING)
			and P_IsObjectOnGround(player.mo)
			and not (player.pflags & PF_STARTDASH)
				player.dashspeed = $+player.speed
				player.mo.momx = 0
				player.mo.momy = 0
				player.mo.state = S_PLAY_SPINDASH
				player.pflags = $|PF_SPINNING|PF_STARTDASH
			end
			player.wasspinning = player.pflags & PF_SPINNING
			player.spindown = player.cmd.buttons & BT_SPIN
		end
	end
end)

addHook("AbilitySpecial", function(player)
	if player.mo and (player.mo.skin == "greeneyesonic")
		if (player.charability == CA_HOMINGTHOK)
		and not P_LookForEnemies(player, true, false)
		and not (player.pflags & PF_THOKKED)
		and player.simpleabilities == true
			player.charability = CA_NONE
			player.simpledoublejump = 1
		end
		if (player.charability == CA_THOK)
		and not (player.pflags & PF_THOKKED)
		or (player.charability == CA_HOMINGTHOK)
		and not P_LookForEnemies(player, true, false)
		and not (player.pflags & PF_THOKKED)
		and player.simpleabilities == false
		or player.simpleabilities == true
		and player.cmd.forwardmove == 50
		and not P_LookForEnemies(player, true, false)
		and not (player.pflags & PF_THOKKED)
			P_InstaThrust(player.mo, player.mo.angle, max(player.speed, player.actionspd/2))
			S_StartSound(player.mo, sfx_sajdsh)
			P_SpawnThokMobj(player)
			player.mo.state = S_PLAY_GLIDE
			player.pflags = $ & ~PF_NOJUMPDAMAGE
			player.pflags = $ | PF_THOKKED
		end
	end
end)


addHook("MapLoad", do
	for player in players.iterate
		if player.mo and (player.mo.skin == "greeneyesonic")
			player.lightdash = 0
			player.tossflagdown = 0
			player.jumpdown = 0
			player.prevrings = 0
			player.notboostmeter = 0
			player.heatready = 0
			player.feelingheat = 0
			player.heatadvance = 0
			player.drivingsupercar = 0
		end
	end
end)

addHook("PlayerSpawn", function(player)
	if not netgame return end
	if player.mo and (player.mo.skin == "greeneyesonic")
		player.lightdash = 0
		player.tossflagdown = 0
		player.jumpdown = 0
		player.prevrings = 0
		player.notboostmeter = 0
		player.heatready = 0
		player.feelingheat = 0
		player.heatadvance = 0
		player.drivingsupercar = 0
	end
end)


addHook("PlayerSpawn", function(p)
	if io and p == consoleplayer and p.simplequickstep == nil
		local file = io.openlocal("client/greeneyes/quickstep.dat")
		if file
			local string = file:read("*a")
			if string == "1" or string == "true" or string == "on"
				COM_BufInsertText(p, "simplequickstep on")
			elseif string == "0" or string == "false" or string == "off" or string == nil
				COM_BufInsertText(p, "simplequickstep off")
			end
			file:close()
		end
	end
end)
addHook("PlayerSpawn", function(p)
	if io and p == consoleplayer and p.simpleabilities == nil
		local file = io.openlocal("client/greeneyes/abilities.dat")
		if file
			local string = file:read("*a")
			if string == "1" or string == "true" or string == "on"
				COM_BufInsertText(p, "simpleabilities on")
			elseif string == "0" or string == "false" or string == "off" or string == nil
				COM_BufInsertText(p, "simpleabilities off")
			end
			file:close()
		end
	end
end)

//quickstep from Modern Abilities for 2.1, by MotdSpork
freeslot("sfx_sonicd")
addHook("ThinkFrame", do
	for player in players.iterate
		if player.mo
			if not (player.mo.sidestepping)
				player.mo.sidestepping = 0
			end
			if not (player.mo.sidetimer)
				player.mo.sidetimer = 0
			end
			if not (player.mo.sidestep)
				player.mo.sidestep = 0
			end
			if not (player.mo.prevspeed)
				player.mo.prevspeed = 0
			end
			if player.mo.sidestepping == 0
				player.prevspeed = player.speed
			end
			if (player.mo and (player.mo.skin == "greeneyesonic"))
			and not (player.exiting)
			and not (player.pflags & PF_STASIS)
			//I HATE WHAT I'M ABOUT TO DO!!
				if player.simplequickstep == false
					if P_IsObjectOnGround(player.mo)
					and player.mo and player.mo.valid //and player.health
					//and player.cmd.sidemove < 0
					and player.mo.sidestepping == 0
					and player.cmd.buttons & BT_ATTACK
						if not (player.mo.eflags & MFE_UNDERWATER)
							P_InstaThrust(player.mo, player.cmd.angleturn<<16 + ANGLE_90, (FixedMul(64*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
						else
							P_InstaThrust(player.mo, player.cmd.angleturn<<16 + ANGLE_90, (FixedMul(28*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
						end
						S_StartSound(player.mo, sfx_sonicd)
						player.mo.sidestepping = 1
						player.mo.sidetimer = 2
						player.mo.sidestep = 1
					else
						if P_IsObjectOnGround(player.mo)
						and player.mo and player.mo.valid //and player.health
						//and player.cmd.sidemove > 0
						and player.mo.sidestepping == 0
						and player.cmd.buttons & BT_FIRENORMAL
							if not (player.mo.eflags & MFE_UNDERWATER)
								P_InstaThrust(player.mo, player.cmd.angleturn<<16 - ANGLE_90, (FixedMul(64*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
							else
								P_InstaThrust(player.mo, player.cmd.angleturn<<16 - ANGLE_90,  (FixedMul(28*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
							end
							S_StartSound(player.mo, sfx_sonicd)
							player.mo.sidestepping = 1
							player.mo.sidetimer = 2
							player.mo.sidestep = 1
						end
						if not (player.cmd.buttons & BT_ATTACK)
						and not (player.cmd.buttons & BT_FIRENORMAL)
						and player.mo.sidestepping == 1
							player.mo.sidestepping = 0
						end
						if player.mo.sidestep == 1
						and player.mo.sidetimer == 0
							player.mo.sidestep = 0
							P_InstaThrust(player.mo, player.cmd.angleturn<<16 - ANGLE_90, (FixedMul(0*FRACUNIT, player.mo.scale)+0*FRACUNIT)+cos(player.aiming))
							P_InstaThrust(player.mo, player.cmd.angleturn<<16 + ANGLE_90, (FixedMul(0*FRACUNIT, player.mo.scale)+0*FRACUNIT)+cos(player.aiming))
							P_InstaThrust(player.mo, player.mo.angle, player.prevspeed)
							if player.prevspeed <= 1*FRACUNIT
								player.mo.state = S_PLAY_STND
							end
						end	
					end
					if player.mo.sidetimer > 0
						P_SpawnGhostMobj(player.mo)
						player.mo.sidetimer = $1 - 1
					end
			//If anyone reading this has tips, please let me know :)
				elseif player.simplequickstep == true
					if player.cmd.buttons & BT_ATTACK
					or player.cmd.buttons & BT_FIRENORMAL
						player.drawangle = player.mo.angle
					end
					
					if P_IsObjectOnGround(player.mo)
					and player.mo and player.mo.valid //and player.health
					and player.cmd.sidemove < 0
					and player.mo.sidestepping == 0
						if player.cmd.buttons & BT_ATTACK
						or player.cmd.buttons & BT_FIRENORMAL
							if not (player.mo.eflags & MFE_UNDERWATER)
								P_InstaThrust(player.mo, player.cmd.angleturn<<16 + ANGLE_90, (FixedMul(64*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
							else
								P_InstaThrust(player.mo, player.cmd.angleturn<<16 + ANGLE_90, (FixedMul(28*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
							end
							S_StartSound(player.mo, sfx_sonicd)
							player.mo.sidestepping = 1
							player.mo.sidetimer = 2
							player.mo.sidestep = 1
						end
					else
						if player.cmd.sidemove > 0
						and player.mo and player.mo.valid //and player.health
						and player.mo.sidestepping == 0
						and P_IsObjectOnGround(player.mo)
							if player.cmd.buttons & BT_ATTACK
							or player.cmd.buttons & BT_FIRENORMAL
								if not (player.mo.eflags & MFE_UNDERWATER)
									P_InstaThrust(player.mo, player.cmd.angleturn<<16 - ANGLE_90, (FixedMul(64*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
								else
									P_InstaThrust(player.mo, player.cmd.angleturn<<16 - ANGLE_90,  (FixedMul(28*FRACUNIT, player.mo.scale)+5*FRACUNIT)+cos(player.aiming))
								end
								S_StartSound(player.mo, sfx_sonicd)
								player.mo.sidestepping = 1
								player.mo.sidetimer = 2
								player.mo.sidestep = 1
							end
						end
						if (player.cmd.sidemove == 0)
						and player.mo.sidestepping == 1
							player.mo.sidestepping = 0
						end
						if player.mo.sidestep == 1
						and player.mo.sidetimer == 0
							player.mo.sidestep = 0
							P_InstaThrust(player.mo, player.cmd.angleturn<<16 - ANGLE_90, (FixedMul(0*FRACUNIT, player.mo.scale)+0*FRACUNIT)+cos(player.aiming))
							P_InstaThrust(player.mo, player.cmd.angleturn<<16 + ANGLE_90, (FixedMul(0*FRACUNIT, player.mo.scale)+0*FRACUNIT)+cos(player.aiming))
							P_InstaThrust(player.mo, player.mo.angle, player.prevspeed)
							if player.prevspeed <= 1*FRACUNIT
								player.mo.state = S_PLAY_STND
							end
						end	
					end
					if player.mo.sidetimer > 0
						P_SpawnGhostMobj(player.mo)
						player.mo.sidetimer = $1 - 1
					end
				end
			end
		end
	end
end)

//Music
addHook("MusicChange", function(oldname, newname)
	if consoleplayer
		local character = skins[consoleplayer.skin].name
		if (character == "greeneyesonic")
			if newname == "_super"
				return "GSUPER"
			elseif newname == "_inv"
				return "GINV"
			elseif newname == "_shoes"
				return "GSHOES"
			end
		end
	end
end)