freeslot("S_PLAY_PEEL1", "S_PLAY_PEEL2", "S_PLAY_PEEL3", "S_PLAY_PEEL4", "S_PLAY_PWALK1", "S_PLAY_PWALK2", "S_PLAY_PWALK3", "S_PLAY_PWALK4", "S_PLAY_PWALK5", "S_PLAY_PWALK6", "S_PLAY_PWALK7", "S_PLAY_PWALK8", "S_PLAY_PWALK9", "S_PLAY_PWALK10", "S_PLAY_PWALK11", "S_PLAY_PWALK12", "S_PLAY_PWALK13", "S_PLAY_PWALK14", "S_PLAY_PWALK15", "S_PLAY_PWALK16", "S_PLAY_SPEEL1", "S_PLAY_SPEEL2")
states[S_PLAY_PWALK1] = {SPR_PLAY, SPR2_WALK1, 4, nil, 0, 0, S_PLAY_PWALK2}
states[S_PLAY_PWALK2] = {SPR_PLAY, SPR2_WALK2, 4, nil, 0, 0, S_PLAY_PWALK3}
states[S_PLAY_PWALK3] = {SPR_PLAY, SPR2_WALK3, 4, nil, 0, 0, S_PLAY_PWALK4}
states[S_PLAY_PWALK4] = {SPR_PLAY, SPR2_WALK4, 3, nil, 0, 0, S_PLAY_PWALK5}
states[S_PLAY_PWALK5] = {SPR_PLAY, SPR2_WALK5, 3, nil, 0, 0, S_PLAY_PWALK6}
states[S_PLAY_PWALK6] = {SPR_PLAY, SPR2_WALK6, 3, nil, 0, 0, S_PLAY_PWALK7}
states[S_PLAY_PWALK7] = {SPR_PLAY, SPR2_WALK7, 2, nil, 0, 0, S_PLAY_PWALK8}
states[S_PLAY_PWALK8] = {SPR_PLAY, SPR2_WALK8, 2, nil, 0, 0, S_PLAY_PWALK9}
states[S_PLAY_PWALK9] = {SPR_PLAY, SPR2_WALK1, 2, nil, 0, 0, S_PLAY_PWALK10}
states[S_PLAY_PWALK10] = {SPR_PLAY, SPR2_WALK2, 1, nil, 0, 0, S_PLAY_PWALK11}
states[S_PLAY_PWALK11] = {SPR_PLAY, SPR2_WALK3, 1, nil, 0, 0, S_PLAY_PWALK12}
states[S_PLAY_PWALK12] = {SPR_PLAY, SPR2_WALK4, 1, nil, 0, 0, S_PLAY_PWALK13}
states[S_PLAY_PWALK13] = {SPR_PLAY, SPR2_WALK5, 1, nil, 0, 0, S_PLAY_PWALK14}
states[S_PLAY_PWALK14] = {SPR_PLAY, SPR2_WALK6, 1, nil, 0, 0, S_PLAY_PWALK15}
states[S_PLAY_PWALK15] = {SPR_PLAY, SPR2_WALK7, 1, nil, 0, 0, S_PLAY_PWALK16}
states[S_PLAY_PWALK16] = {SPR_PLAY, SPR2_WALK8, 1, nil, 0, 0, S_PLAY_PEEL1}
states[S_PLAY_PEEL1] = {SPR_PLAY, SPR2_RUN_1, 1, nil, 0, 0, S_PLAY_PEEL2}
states[S_PLAY_PEEL2] = {SPR_PLAY, SPR2_RUN_2, 1, nil, 0, 0, S_PLAY_PEEL3}
states[S_PLAY_PEEL3] = {SPR_PLAY, SPR2_RUN_3, 1, nil, 0, 0, S_PLAY_PEEL4}
states[S_PLAY_PEEL4] = {SPR_PLAY, SPR2_RUN_4, 1, nil, 0, 0, S_PLAY_PEEL1}
states[S_PLAY_SPEEL1] = {SPR_PLAY, SPR2_RUN_1, 1, nil, 0, 0, S_PLAY_SPEEL2}
states[S_PLAY_SPEEL2] = {SPR_PLAY, SPR2_RUN_2, 1, nil, 0, 0, S_PLAY_SPEEL1}

freeslot(
"S_DROPDASH",
"SPR_DRPD",
"sfx_drpdsh",
"sfx_pelchr",
"sfx_pelrel",
"sfx_airrol",
"MT_INSTASHIELD",
"S_INSTASHIELD1",
"S_INSTASHIELD1B",
"S_INSTASHIELD2",
"S_INSTASHIELD2B",
"S_INSTASHIELD3",
"S_INSTASHIELD3B",
"S_INSTASHIELD4",
"S_INSTASHIELD4B",
"S_INSTASHIELD5",
"S_INSTASHIELD5B",
"S_INSTASHIELD6",
"S_INSTASHIELD6B",
"S_INSTASHIELD7",
"S_INSTASHIELD7B",
"SPR_TWSP",
"S_POSE1",
"S_POSE2",
"S_POSE3",
"SPR_POSE",
"S_SPRINGTWIRL",
"SPR_SPTW",
"S_BURN",
"SPR_BURN",
"S_ELECTRO1",
"S_ELECTRO2",
"SPR_ELED",
"S_PLAY_LDSH", 
"S_PLAY_LDSH2",
"S_DAB",
"SPR_DABM"
)

states[S_DROPDASH] = {
	sprite = SPR_DRPD,
	frame = FF_ANIMATE,
	tics = -1,
	var1 = 5,
	var2 = 1,
	nextstate = S_PLAY_ROLL
}

sfxinfo[sfx_drpdsh] = {
	singular = false,
	caption = "Dropdash"
}

sfxinfo[sfx_pelchr] = {
	singular = false,
	caption = "Peelout charge"
}

sfxinfo[sfx_pelrel] = {
	singular = false,
	caption = "Peelout release"
}

sfxinfo[sfx_airrol] = {
	singular = false,
	caption = "Air roll"
}

states[S_POSE1] = {
	sprite = SPR_POSE,
	frame = A,
	tics = 5,
	nextstate = S_POSE2
}

states[S_POSE2] = {
	sprite = SPR_POSE,
	frame = B,
	tics = 5,
	nextstate = S_POSE3
}

states[S_POSE3] = {
	sprite = SPR_POSE,
	frame = C,
	tics = -1,
	nextstate = S_PLAY_STND
}

states[S_SPRINGTWIRL] = {
	sprite = SPR_SPTW,
	frame = FF_ANIMATE,
	tics = -1,
	var1 = 7,
	var2 = 2,
	nextstate = S_PLAY_SPRING
}

mobjinfo[MT_INSTASHIELD] = {
	doomednum = -1,
	spawnhealth = 1,
	spawnstate = S_INSTASHIELD1,
	radius = 32*FRACUNIT,
	height = 32*FRACUNIT,
	flags = MF_NOGRAVITY|MF_NOCLIPHEIGHT
}

states[S_BURN] = {
	sprite = SPR_BURN,
	frame = A,
	tics = -1,
	nextstate = S_BURN
}

states[S_ELECTRO1] = {
	sprite = SPR_ELED,
	frame = A,
	tics = -1,
	nextstate = S_ELECTRO2
}

states[S_ELECTRO2] = {
	sprite = SPR_ELED,
	frame = B,
	tics = -1,
	nextstate = S_ELECTRO1
}

states[S_PLAY_LDSH] = {
	sprite = SPR_LDSH,
	frame = A,
	tics = 0,
	nextstate = S_PLAY_LDSH2
}

states[S_PLAY_LDSH2] = {
	sprite = SPR_LDSH,
	frame = A,
	tics = 1,
	nextstate = S_PLAY_RUN
}

states[S_DAB] = {
	sprite = SPR_DABM,
	frame = A,
	tics = -1,
	nextstate = S_PLAY_STND
}

states[S_INSTASHIELD1] = {SPR_TWSP, 0|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD1B}
states[S_INSTASHIELD1B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_INSTASHIELD2}
states[S_INSTASHIELD2] = {SPR_TWSP, 1|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD2B}
states[S_INSTASHIELD2B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_INSTASHIELD3}
states[S_INSTASHIELD3] = {SPR_TWSP, 2|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD3B}
states[S_INSTASHIELD3B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_INSTASHIELD4}
states[S_INSTASHIELD4] = {SPR_TWSP, 3|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD4B}
states[S_INSTASHIELD4B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_INSTASHIELD5}
states[S_INSTASHIELD5] = {SPR_TWSP, 4|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD5B}
states[S_INSTASHIELD5B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_INSTASHIELD6}
states[S_INSTASHIELD6] = {SPR_TWSP, 5|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD6B}
states[S_INSTASHIELD6B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_INSTASHIELD7}
states[S_INSTASHIELD7] = {SPR_TWSP, 5|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD7B}
states[S_INSTASHIELD7B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_INSTASHIELD1}

local DustSpawnCooldown = 0

// Momentum Thrust.
// Based some code off of the Jump Thrust by CobaltBW.
// This is due to the friend group's love for the Jump Thrust.

local SpeedLimit = function(mo,amt)
	if mo.eflags&MFE_UNDERWATER then
		amt = $/2
	end
	if FixedHypot(mo.momx,mo.momy) > amt then
		local ang = R_PointToAngle2(0,0,mo.momx,mo.momy)
		mo.momx = P_ReturnThrustX(mo,ang,amt)
		mo.momy = P_ReturnThrustY(mo,ang,amt)
	end
end

local function momentumThok(player)
	if player.mo.skin != "mcsonic" return end
	
	if player.bouncing
		return true
	end
	
	if player.pflags & PF_THOKKED return end
	
	local angle = player.mo.angle
	local actionspd = player.actionspd	
	local xshift = player.cmd.forwardmove*FRACUNIT
	local yshift = player.cmd.sidemove*FRACUNIT
	local x = player.mo.x
	local y = player.mo.y
	local vthrust = 8+(1/2)
	local hthrust = FixedHypot(xshift,yshift)/50
	
	if (player.mo.eflags & MFE_UNDERWATER)
		vthrust = $ * 2 / 3
	end
	
	if player.hyper
		vthrust = $ * 3 / 2
	end
	
	P_Thrust(player.mo, player.cmd.angleturn << 16 + R_PointToAngle2(0, 0, player.cmd.forwardmove*FRACUNIT, -player.cmd.sidemove*FRACUNIT), FixedMul(hthrust, player.actionspd))
	
	SpeedLimit(player.mo,60*player.mo.scale)
	
	P_SetObjectMomZ(player.mo, (vthrust*player.jumpfactor), false)
	
	P_SpawnThokMobj(player)
	P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_DUST)
	S_StartSound(player.mo, sfx_thok)
	player.pflags = $|PF_THOKKED
	if player.hyper
		P_StartQuake(25*FRACUNIT, 16)
		P_NukeEnemies(player.mo, player.mo, 1500*FRACUNIT)
		P_FlashPal(player, PAL_WHITE, 8)
	end
end

addHook("AbilitySpecial", momentumThok)

local function momentumThokeffect(player)
	if player.mo.skin != "mcsonic" return end

	if DustSpawnCooldown > 0
		DustSpawnCooldown = $1 - 1
	end
	
	if player.pflags & PF_THOKKED
	and not (player.pflags & PF_SHIELDABILITY)
	and DustSpawnCooldown == 0
	and not player.hypertrans
		P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_DUST)
		DustSpawnCooldown = TICRATE/4
	end
	
	if player.pflags & PF_THOKKED
	and not (player.pflags & PF_SHIELDABILITY)
	and DustSpawnCooldown == 0
	and not player.hypertrans
		player.thrustfactor = skins[player.mo.skin].thrustfactor * 3 / 2
	elseif not (player.pflags & PF_THOKKED)
		player.thrustfactor = skins[player.mo.skin].thrustfactor
	end
end

addHook("PlayerThink", momentumThokeffect)

// Dashmode.
// Based off source code.

local function PlayerSpawnClearing(player)
	if not (player.mo and player.mo.valid) return end 
	if player.mo.skin != "mcsonic" return end
	
	player.rbdashmode = 0
	player.normalspeed = skins[player.mo.skin].normalspeed
	player.jumpfactor = skins[player.mo.skin].jumpfactor
	player.charflags = $1 & ~SF_RUNONWATER
end

addHook("PlayerSpawn", PlayerSpawnClearing)

local function Dashmode(player)
	local maxdashmode = 2*TICRATE
	if not (player.mo and player.mo.valid) then return end 
	if player.mo.skin != "mcsonic" return end
	
	if player.gotflag
	or player.powers[pw_carry]
	or player.exiting
	or maptol & TOL_NIGHTS
	or not (player.playerstate == PST_LIVE)
		if player.dashmode2 >= maxdashmode
			player.normalspeed = skins[player.mo.skin].normalspeed
			player.jumpfactor = skins[player.mo.skin].jumpfactor
			player.charflags = $1 & ~SF_RUNONWATER
			S_StartSound(player.mo, sfx_kc65)
		end
		player.dashmode2 = 0
		return
	end
	
	if player.dashmode2 == nil
		player.dashmode2 = 0
	end
	
	if player.striketimer == nil
		player.striketimer = 0
	end
	
	local prevdashmode = player.dashmode2
	
	if P_PlayerInPain(player)
		player.dashmode2 = 0
		player.normalspeed = skins[player.mo.skin].normalspeed // Reset to default if not capable of entering dash mode.
		player.jumpfactor = skins[player.mo.skin].jumpfactor
		player.charflags = $1 & ~SF_RUNONWATER
	end
	
	if (player.speed >= FixedMul(player.runspeed, player.mo.scale) 	or (player.pflags & PF_STARTDASH))
	and P_IsObjectOnGround(player.mo)
	and not player.powers[pw_super]
		player.dashmode2 = $ + 1
		if player.dashmode2 == maxdashmode
			S_StartSound(player.mo, sfx_kc4d)
		end
	elseif (player.speed < FixedMul(player.runspeed, player.mo.scale)) 
	and not (player.pflags & PF_SPINNING)
	and P_IsObjectOnGround(player.mo) 
		if player.dashmode2 > 0
			player.dashmode2 = $ - 3
			
			if (player.dashmode2 + 3) >= maxdashmode and player.dashmode2 < maxdashmode
				S_StartSound(player.mo, sfx_kc65)
			end
		elseif player.dashmode2 < 0
			player.dashmode2 = 0
		end
	end
	
	if player.speed <= 10*FRACUNIT
		if not (player.pflags & PF_STARTDASH)
		and not (player.pflags & PF_SPINNING)
		and P_IsObjectOnGround(player.mo)
			player.dashmode2 = 0
			player.normalspeed = skins[player.mo.skin].normalspeed // Reset to default if not capable of entering dash mode.
			player.jumpfactor = skins[player.mo.skin].jumpfactor
			player.charflags = $1 & ~SF_RUNONWATER
		end
	end
	
	if player.dashmode2 < maxdashmode
		if prevdashmode >= maxdashmode
			player.normalspeed = skins[player.mo.skin].normalspeed // Reset to default if not capable of entering dash mode.
			player.jumpfactor = skins[player.mo.skin].jumpfactor
			player.charflags = $1 & ~SF_RUNONWATER
		end
	elseif P_IsObjectOnGround(player.mo)
		if player.normalspeed < skins[player.mo.skin].normalspeed * 55 / 36
			player.normalspeed = $ + FRACUNIT/15
		end
		
		if player.jumpfactor < FixedMul(skins[player.mo.skin].jumpfactor, 5*FRACUNIT/4) // Boost jump height.
			player.jumpfactor = $ + FRACUNIT/900
		end
	end
	
	if player.dashmode2 >= maxdashmode
		local ghost = P_SpawnGhostMobj(player.mo)
		ghost.fuse = 4
		player.charflags = $1|SF_RUNONWATER
		if P_IsObjectOnGround(player.mo)
			local dust = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z + ((player.mo.eflags & MFE_VERTICALFLIP)/MFE_VERTICALFLIP * (player.mo.height - mobjinfo[MT_SPINDUST].height)),
			MT_SPINDUST)
		
			if player.mo.eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) // overrides fire version
				dust.state = S_SPINDUST_BUBBLE1
			end
			
			dust.momx = P_RandomRange(-7,7)*FRACUNIT
			dust.momy = P_RandomRange(-7,7)*FRACUNIT
			dust.momz = P_RandomRange(0,5)*FRACUNIT
			
			dust.target = player.mo
			dust.eflags = $1 | (player.mo.eflags & MFE_VERTICALFLIP)
			dust.scale = player.mo.scale * 3/4
		end
	end
	
//	if player.dashmode2 >= maxdashmode
//	and player.speed >= 45*FRACUNIT
//	and not (player.powers[pw_super])
//		player.striketimer = $ + 1
//	end
	
//	if player.striketimer < TICRATE
//		player.strikenormalspeed = player.normalspeed
//	end
	
//	if player.striketimer
//		if player.striketimer >= TICRATE
//			if player.speed <= 36*FRACUNIT
//			or player.dashmode2 < maxdashmode
//				if P_IsObjectOnGround(player.mo)
//					player.striketimer = 0
//					player.mo.colorized = false
//					if not player.mo.peeloutrun
//						player.normalspeed = player.strikenormalspeed
//					end
//				end
//			end
//		else
//			if player.speed <= 45*FRACUNIT
//			or player.dashmode2 < maxdashmode
//				if P_IsObjectOnGround(player.mo)
//					player.striketimer = 0
//				end
//			end
//		end
//	end
	
//	if player.striketimer >= TICRATE
//		if not player.mo.peeloutrun
//			player.normalspeed = 70*FRACUNIT
//		end
		
//		if leveltime % 5 == 0
//			local strikesparkle = P_SpawnMobj(player.mo.x+(P_RandomRange(16,-16)*FRACUNIT),player.mo.y+(P_RandomRange(16,-16)*FRACUNIT),player.mo.z+(P_RandomRange(8,-8)*FRACUNIT),MT_STRIKESPARKLES)
//			strikesparkle.color = player.mo.color
//			strikesparkle.colorized = true
//			strikesparkle.scale = $ * 3 / 2
//			
//			strikesparkle.momx = P_RandomRange(5,-5)*FRACUNIT
//			strikesparkle.momy = P_RandomRange(5,-5)*FRACUNIT
//			strikesparkle.momz = P_RandomRange(5,-5)*FRACUNIT
//		end
		
//		if leveltime % 2 == 0
//			player.mo.colorized = true
//		elseif player.striketimer >= TICRATE
//		and leveltime % 2 != 0
//			player.mo.colorized = false
//		end	
//	end
end

addHook("PlayerThink", Dashmode)

//local function StatesWithDamage(player, badnik)
//	if player.mo and player.mo.valid
//		if player.striketimer >= TICRATE
//			return true
//		end
//	end
//end

//addHook("PlayerCanDamage", StatesWithDamage)

//local function StatesWithInvinc(target, inflictor, source, damage, damagetype)
//	if target and target.valid
//		if target.player.striketimer >= TICRATE
//		and not (damagetype & DMG_DEATHMASK)
//			return false
//		end
//	end
//end

//addHook("ShouldDamage", StatesWithInvinc, MT_PLAYER)
	
// Peelout.
// Reused from MotdSpork.

addHook("ThinkFrame", do
	for player in players.iterate
		if not player.mo return end
			if player.mo and player.mo.skin == "mcsonic"
			//CONS_Printf(player, player.mo.peelouttimer)
				if player.mo.state == S_PLAY_STND
					player.normalspeed = 36*FRACUNIT
				end
				if player.mo.peelouttimer == nil
					player.mo.peelouttimer = 0
				end
				if player.mo.peelout == nil
					player.mo.peelout = 0
				end
				if player.mo.peeloutrun == nil
					player.mo.peeloutrun = 0
				end
				if player.mo.peelsound == nil
					player.mo.peelsound = 0
				end
				if player.mo.peelsound2 == nil
					player.mo.peelsound2 = 0
				end
				if player.pflags & PF_SPINNING
					player.mo.peelouttimer = 0
				end
				if (P_PlayerInPain(player))
				or (player.playerstate == PST_DEAD)
					player.normalspeed = 36*FRACUNIT
					player.mo.peelouttimer = 0
					player.mo.peelout = 0
					player.mo.peeloutrun = 0
					player.mo.peelsound = 0
					player.mo.peeloutsound = 0
				end
				if P_IsObjectOnGround(player.mo)
				and player.speed == 0
				and not (player.pflags & PF_SPINNING)
				and player.cmd.buttons & BT_CUSTOM1
			    and not (player.playerstate == PST_DEAD)
				and not player.bouncing
					if player.mo.peelsound == 0
						S_StartSound(player.mo, sfx_pelchr)
						player.mo.peelsound = 1
						
					end
					if player.mo.peelouttimer < 60
						player.mo.peelouttimer = $1 + 1
					end
					player.normalspeed = 0
					player.pflags = $1|PF_STASIS
					if player.drawangle ~= player.mo.angle
						local diff = 0
						local factor = 0
						diff = player.mo.angle - player.drawangle
						factor = 8
						if diff > ANGLE_180
							diff = InvAngle(InvAngle(diff)/(factor or 1))
						else
							diff = $ / (factor or 1)
						end
						player.drawangle = $ + diff
					
					end
					if not (player.mo.eflags & MFE_GOOWATER) then
						for i=(leveltime%7)/2,(leveltime%7) do
							local particle = P_SpawnMobj(player.mo.x, player.mo.y,
							player.mo.z + ((player.mo.eflags & MFE_VERTICALFLIP)/MFE_VERTICALFLIP * (player.mo.height - mobjinfo[MT_SPINDUST].height)),
							MT_SPINDUST)
							if (player.powers[pw_shield] == SH_ELEMENTAL and not (player.mo.eflags & MFE_TOUCHWATER or player.mo.eflags & MFE_UNDERWATER)) then
								particle.state = S_SPINDUST_FIRE1
								particle.bubble = false
							elseif (player.mo.eflags & MFE_TOUCHWATER or player.mo.eflags & MFE_UNDERWATER) then
								particle.state = S_SPINDUST_BUBBLE1
								particle.bubble = true
							else
								particle.state = S_SPINDUST1
								particle.bubble = false
							end
					
							particle.target = player.mo
							particle.eflags = $1 | (player.mo.eflags & MFE_VERTICALFLIP)
							particle.scale = player.mo.scale*2/3
							P_SetObjectMomZ(particle, player.mo.peelouttimer*FRACUNIT/50+P_RandomByte()<<10, false)
							P_InstaThrust(particle, player.mo.angle+(P_RandomRange(-ANG30/FRACUNIT, ANG30/FRACUNIT)*FRACUNIT), FixedMul(-player.mo.peelouttimer*FRACUNIT/12-1*FRACUNIT-P_RandomByte()<<11, player.mo.scale))
							P_TryMove(particle, particle.x+particle.momx, particle.y+particle.momy, true)
						end
					end
				end
			if not (player.cmd.buttons & BT_CUSTOM1) 
				if ((player.mo.peelouttimer >= 1) and (player.mo.peelouttimer <= 35) and not (player.powers[pw_super]))
				or ((player.mo.peelouttimer >= 1) and (player.mo.peelouttimer <= 14) and (player.powers[pw_super]))
					player.normalspeed = 36*FRACUNIT
					player.mo.state = 14
					player.mo.peelouttimer = 0
					player.mo.peelsound = 0
				end
			end
			
			if player.powers[pw_super] == 0
				if player.mo.peelouttimer >= 1
				and player.mo.peelouttimer <= 30
					if not (player.mo.state >= S_PLAY_PWALK1)
					and (player.mo.state <= S_PLAY_PWALK16)
						player.mo.state = S_PLAY_PWALK1
					end
				end
				if player.mo.peelouttimer >= 31
					if not ((player.mo.state >= S_PLAY_PEEL1) and (player.mo.state <= S_PLAY_PEEL4))
					or ((player.mo.state >= S_PLAY_PWALK1) and (player.mo.state <= S_PLAY_PWALK16))
						player.mo.state = S_PLAY_PEEL1
					end
				end
			else
				if player.mo.peelouttimer >= 1
				and player.mo.peelouttimer <= 14
					if not (player.mo.state >= S_PLAY_PWALK8)
					and (player.mo.state <= S_PLAY_PWALK16)
						player.mo.state = S_PLAY_PWALK8
					end
				end
				if player.mo.peelouttimer >= 15
					if not (player.mo.state >= S_PLAY_SPEEL1)
					and (player.mo.state <= S_PLAY_SPEEL2)
						player.mo.state = S_PLAY_SPEEL1
					end
				end
			end
			if not (player.cmd.buttons & BT_CUSTOM1)
				if ((player.mo.peelouttimer >= 31) and not (player.powers[pw_super]))
				or ((player.mo.peelouttimer >= 15) and (player.powers[pw_super]))
					if player.mo.peelsound == 1
						player.mo.state = S_PLAY_RUN
						S_StartSound(player.mo, sfx_pelrel)
						player.mo.peelsound = 0
						player.mo.peelout = 1
						if player.hyper
							P_StartQuake(25*FRACUNIT, 16)
							P_NukeEnemies(player.mo, player.mo, 1500*FRACUNIT)
							P_FlashPal(player, PAL_WHITE, 8)
						end
					end
					P_InstaThrust(player.mo, player.mo.angle, FixedMul(70*FRACUNIT, player.mo.scale))
					if not player.powers[pw_super]
						player.dashmode2 = 4*TICRATE
					end
					player.mo.peelouttimer = 0
					player.drawangle = player.mo.angle
				end
				
			end
			if player.speed > 45*FRACUNIT
			and player.mo.peelout == 1
				player.mo.peeloutrun = 1
				player.normalspeed = 70*FRACUNIT
			end
			if player.speed <= 45*FRACUNIT
			and player.mo.peeloutrun == 1
				player.mo.peelout = 0
				player.mo.peeloutrun = 0
				player.normalspeed = 36*FRACUNIT
			end
			if player.pflags & PF_JUMPED
				if ((player.mo.state >= S_PLAY_PWALK1) and (player.mo.state <= S_PLAY_PWALK16))
				or ((player.mo.state >= S_PLAY_PEEL1) and (player.mo.state <= S_PLAY_PEEL4))
				or ((player.mo.state >= S_PLAY_SPEEL1) and (player.mo.state <= S_PLAY_SPEEL2))
					player.mo.state = S_PLAY_ROLL
				end
				if player.normalspeed == 0*FRACUNIT
					player.normalspeed = 36*FRACUNIT
				end
				player.mo.peelouttimer = 0
				player.mo.peelsound = 0
				player.mo.peelsound2 = 0
			end
		end
	end
end)

// Drop Dash
// Iteration upon an iteration.

local ThokSpawnCooldown = 0

local function DropDash(player)
	if not player.mo and player.mo.valid return end
	
	if player.droptimer == nil
		player.droptimer = 0
	end
	
	if player.dropspeed == nil
		player.dropspeed = 36*FRACUNIT
	end
	
	if (player.mo.skin != "mcsonic") return end
	
	if ThokSpawnCooldown > 0
		ThokSpawnCooldown = $1 - 1
	end
	
	if player.powers[pw_super] == 1
		return
	end
	
	if P_PlayerInPain(player) or not(player.playerstate == PST_LIVE) or player.exiting or player.powers[pw_nocontrol]
		player.triedtodash = false
		player.droptimer = 0
//		player.mo.state = S_PLAY_ROLL
	end
		
	if (player.pflags & PF_JUMPED)
		if (player.triedtodash) then
			player.droptimer = 0
			player.mo.state = S_PLAY_JUMP
		else
			if (player.pflags & PF_USEDOWN) then
				player.droptimer = $1 + 1
				if player.dropspeed < 72*FRACUNIT and not player.hyper
				or player.hyper and player.dropspeed < 120*FRACUNIT
					if player.powers[pw_super]
						player.dropspeed = $ + FRACUNIT * 6 / 4
					else
						player.dropspeed = $ + FRACUNIT * 3 / 4
					end
				end
//				print(player.dropspeed/FRACUNIT)
			elseif player.droptimer > 0 then
				player.droptimer = 0
				player.triedtodrop = true
				player.dropspeed = 36*FRACUNIT
			end
		end
	end
	
	if (player.droptimer == 15) then
//	and not player.mo.state == S_DROPDASH
		S_StartSound(player.mo, sfx_drpdsh)
		player.mo.state = S_DROPDASH
	end
	
	if player.mo.state == S_DROPDASH
	and not (player.pflags & PF_USEDOWN)
		player.mo.state = S_PLAY_ROLL
	end
	
	if player.powers[pw_justsprung]
	or P_PlayerInPain(player)
		player.triedtodash = false
		player.droptimer = 0
		player.dropspeed = 36*FRACUNIT
	end
		
	
	if player.droptimer >= 15
	and player.powers[pw_super] 
	and P_IsObjectOnGround(player.mo)
		P_StartQuake(15*FRACUNIT,6)
	end
			
	if (player.mo.eflags & MFE_JUSTHITFLOOR or P_IsObjectOnGround(player.mo)) then
		if (player.droptimer >= 15) then
			player.mo.state = S_PLAY_ROLL
			player.pflags = $1|PF_SPINNING
			local radius = player.mo.radius >> FRACBITS
			P_SpawnMobjFromMobj(player.mo, P_RandomRange(-radius, radius) << FRACBITS, P_RandomRange(-radius, radius) << FRACBITS, 0, MT_SPINDUST)
			P_SpawnMobjFromMobj(player.mo, P_RandomRange(-radius, radius) << FRACBITS, P_RandomRange(-radius, radius) << FRACBITS, 0, MT_SPINDUST)
			P_SpawnMobjFromMobj(player.mo, P_RandomRange(-radius, radius) << FRACBITS, P_RandomRange(-radius, radius) << FRACBITS, 0, MT_SPINDUST)
			P_SpawnMobjFromMobj(player.mo, P_RandomRange(-radius, radius) << FRACBITS, P_RandomRange(-radius, radius) << FRACBITS, 0, MT_SPINDUST)
			P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.dropspeed+(player.speed/8), player.mo.scale))
			S_StartSound(player.mo, sfx_zoom, player)
			if player.hyper
				P_StartQuake(25*FRACUNIT, 16)
				P_NukeEnemies(player.mo, player.mo, 1500*FRACUNIT)
				P_FlashPal(player, PAL_WHITE, 8)
			end
//			DoSpindust(player, player.dropspeed)
		end
		player.triedtodash = false
		player.droptimer = 0
		player.dropspeed = 36*FRACUNIT
	end
end
				
addHook("PlayerThink", DropDash)

local function HyperMCSonic(player)
	if player.mo.skin != "mcsonic" return end
	
	if player.hypertrans == nil
		player.hypertrans = false
	end
	
	if player.rings >= 100
	and player.powers[pw_super] > 1
		player.hypercapable = true
	elseif (player.rings < 100 and player.powers[pw_super])
	or not player.powers[pw_super]
		player.hypercapable = false
	end
	
	if player.hyper
		player.hypercapable = false
	end
	
	if player.hypercapable
	and player.powers[pw_super]
	and player.cmd.buttons & BT_CUSTOM3
	and player.pflags & PF_JUMPED
	and not player.hyper
		player.pflags = $1|PF_THOKKED
		player.mo.state = S_PLAY_SUPER_TRANS1
		player.hypertrans = true
		S_StartSound(player.mo, sfx_s3k9f)
		player.hyper = true
	end
	
	if player.hypertrans
		player.mo.momx = 0
		player.mo.momy = 0
		player.mo.momz = 0
	end
	
	if player.hypertrans
	and not (player.mo.state >= S_PLAY_SUPER_TRANS1 and player.mo.state <= S_PLAY_SUPER_TRANS6)
		player.hypertrans = false
		player.pflags = $1 & ~PF_THOKKED
		P_StartQuake(25*FRACUNIT, 16)
		P_NukeEnemies(player.mo, player.mo, 1500*FRACUNIT)
		P_FlashPal(player, PAL_WHITE, 8)
	end
	
	if player.hyper
	and not player.powers[pw_super]
		player.hyper = false
	end

	if player.hyper
		player.powers[pw_underwater] = 100*TICRATE
		player.powers[pw_spacetime] = 100*TICRATE
		
		if player.mo.skin == "mcsonic"
			if player.hypertrans
			and player.mo.state != S_PLAY_SUPER_TRANS1
			and player.mo.state != S_PLAY_SUPER_TRANS2
			and player.mo.state != S_PLAY_SUPER_TRANS3
				player.mo.color = SKINCOLOR_HYPER7
			elseif not player.hypertrans
				player.mo.color = (SKINCOLOR_HYPER1 + abs(((player.powers[pw_super] >> 2) % 9) - 6))
			end
		end
		
		if (player.speed > 1*FRACUNIT or player.mo.momz > 1*FRACUNIT or player.mo.momz < -1*FRACUNIT)
		and not player.hypertrans
			local afterimage = P_SpawnGhostMobj(player.mo)
			
			afterimage.color = player.mo.color
			afterimage.colorized = true
		end
		
		player.jumpfactor = skins[player.mo.skin].jumpfactor * 3 / 2
		
		if player.charability2 == CA2_SPINDASH
			player.mindash = 60*FRACUNIT
			player.maxdash = 120*FRACUNIT
		end
		
		if leveltime % 5 == 0
			local strikesparkle = P_SpawnMobj(player.mo.x+(P_RandomRange(16,-16)*FRACUNIT),player.mo.y+(P_RandomRange(16,-16)*FRACUNIT),player.mo.z+(player.mo.height/2)+(P_RandomRange(8,-8)*FRACUNIT),MT_STRIKESPARKLES)
			strikesparkle.color = player.mo.color
			strikesparkle.colorized = true
			strikesparkle.scale = player.mo.scale * 3 / 2
			
			strikesparkle.momx = P_RandomRange(5,-5)*FRACUNIT
			strikesparkle.momy = P_RandomRange(5,-5)*FRACUNIT
			strikesparkle.momz = P_RandomRange(5,-5)*FRACUNIT
		end
		
		if (leveltime % 35 == 18) and not player.hypertrans
			P_GivePlayerRings(player, -1)
		end
		
		if not (player.powers[pw_extralife])
			S_ChangeMusic("HYPE", true, player)
		end
		
		if player.cmd.buttons & BT_CUSTOM2
		and player.pflags & PF_JUMPED
			player.hyper = false
			player.dehyper = true
			if player.dashmode < 3*TICRATE
				player.jumpfactor = skins[player.mo.skin].jumpfactor
			end
			if player.charability2 == CA2_SPINDASH
				player.mindash = skins[player.mo.skin].mindash
				player.maxdash = skins[player.mo.skin].maxdash
			end
			P_RestoreMusic(player)
		end
	else
		if player.dashmode < 3*TICRATE
			player.jumpfactor = skins[player.mo.skin].jumpfactor
		end
		if player.charability2 == CA2_SPINDASH
			player.mindash = skins[player.mo.skin].mindash
			player.maxdash = skins[player.mo.skin].maxdash
		end
	end
	
	if P_IsObjectOnGround(player.mo)
		player.dehyper = false
	end
	
	if player.powers[pw_super]
	and not player.hyper
		if player.cmd.buttons & BT_CUSTOM2
		and not player.prejumpcustom2
		and not player.dehyper
		and player.pflags & PF_JUMPED
			player.powers[pw_super] = 0
			P_RestoreMusic(player)
			P_SpawnShieldOrb(player)
			player.mo.color = player.skincolor
		end
	end
		
	if player.cmd.buttons & BT_CUSTOM2
		player.prejumpcustom2 = true
	else
		player.prejumpcustom2 = false
	end
end

addHook("PlayerThink", HyperMCSonic)

local function InstaShield(player)
	if (player.mo) and (player.mo.skin == "mcsonic") //sonic
	and not (player.instashield == 1) and not (player.pflags & PF_THOKKED) and not (player.pflags & PF_USEDOWN) and not player.powers[pw_shield] and not player.powers[pw_invulnerability] and not player.powers[pw_carry] and not player.powers[pw_super]
		player.invisiframe = 1
		S_StartSound(player.mo, sfx_s3k42)
		local instashield = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_INSTASHIELD)
		instashield.target = player.mo
		instashield.scale = player.mo.scale
		instashield.fuse = 12
		player.tracer = instashield
		player.pflags = $1|PF_SHIELDABILITY
		if (player.realmo.eflags & MFE_VERTICALFLIP)
			instashield.eflags = $|MFE_VERTICALFLIP
		end
		player.instashield = 1
		return true
	end
end

addHook("PlayerThink", function(player)
	if (player.instashield == 1) and P_IsObjectOnGround(player.mo) //instashield checks
		player.instashield = 0
		if (player.tracer and player.tracer.valid) and player.tracer.type == MT_INSTASHIELD
			P_KillMobj(player.tracer)
		end
	end
	if (player.instashield == 1) and (player.invisiframe == 1)
		player.mo.frame = ($1 & FF_FRAMEMASK)|FF_FULLBRIGHT
		player.mo.colorized = true
	end
	if ((player.invisiframe == 1) and not (player.tracer and player.tracer.valid and player.tracer.type == MT_INSTASHIELD))
		player.invisiframe = nil
		player.mo.colorized = false
	end
end)

addHook("JumpSpinSpecial", InstaShield)

local function InstaCheck(sonic, inflictor, source, damage, element)
	if (sonic.player) and sonic.player.tracer and sonic.player.tracer.valid and sonic.player.tracer.health and sonic.player.tracer.type == MT_INSTASHIELD
		if not (element == DMG_INSTAKILL) and not (element == DMG_DROWNED) and not (element == DMG_SPACEDROWN) and not (element == DMG_DEATHPIT) and not (element == DMG_CRUSHED) and not (element == DMG_SPECTATOR)
			return false  //do not damage player while instashield is active
		end
	end
end

addHook("ShouldDamage", InstaCheck)

local function InstaCollide(insta, mobj) //instashield attacks function as an expanded roll hitbox and can damage things normal spins can't
	if not (insta.z-FixedMul(32*FRACUNIT, insta.scale) > mobj.z+mobj.height)
	and not(mobj.z-FixedMul(32*FRACUNIT, insta.scale) > insta.z+insta.height)
		if (mobj.valid and mobj.health and (mobj.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) or (mobj.flags & MF_PUSHABLE and mobj.flags & MF_SHOOTABLE)))
			P_DamageMobj(mobj, insta, insta.target)
			if ((insta.target.momz < 0) and not (insta.target.eflags & MFE_VERTICALFLIP))
				P_SetObjectMomZ(insta.target, -insta.target.momz)
			elseif ((insta.target.momz > 0) and (insta.target.eflags & MFE_VERTICALFLIP))
				P_SetObjectMomZ(insta.target, insta.target.momz)
			end
			if (mobj.info.spawnhealth > 1)
				P_InstaThrust(insta.target, insta.target.angle, -insta.target.player.speed)
			end
		end
	else
		return nil
	end
end

addHook("MobjMoveCollide", InstaCollide, MT_INSTASHIELD)
addHook("MobjCollide", InstaCollide, MT_INSTASHIELD)

// Victory posing. Originally a S3A 1103 reference.

local function VictoryPose(player)
	if player.mo.skin != "mcsonic" return end
	
	if (player.pflags & PF_FINISHED)
	or (player.exiting)
		if (player.mo.state == S_PLAY_STND or player.mo.state == S_PLAY_WAIT)
		and player.speed == 0
			player.mo.state = S_POSE1
		end
	end
	
	if (player.mo.state >= S_POSE1 and player.mo.state <= S_POSE3)
	and player.speed > 0
		if player.speed < player.runspeed
			player.mo.state = S_PLAY_WALK
		else
			player.mo.state = S_PLAY_RUN
		end
	end
end

addHook("PlayerThink", VictoryPose)

// Burnt death animation
// For example: If the player dies to lava, instead of having the normal death animation, they'll have a grayscale death animation, as a reference to the unused frames from Sonic 1-Sonic 3 & Knuckles.

local function BurntDeath(target, inflictor, source, damage)
	if target
	and target.player
//	and inflictor == nil
//	and source == nil
		if target.skin == "mcsonic"
			if damage == DMG_FIRE
				target.player.burnt = true
				return false
			elseif damage == DMG_ELECTRIC
				target.player.elec = true
				return false
			end
		end
	end
end

addHook("MobjDeath", BurntDeath)

local function BurntUnset(player)
	player.burnt = false
	player.elec = false
end

addHook("PlayerSpawn", BurntUnset)

local function ForceState(player)
	if player.burnt
		if not (leveltime & 3)
			P_SpawnMobj(player.mo.x+(P_RandomRange(-10,10)*FRACUNIT),player.mo.y+(P_RandomRange(-10,10)*FRACUNIT),player.mo.z+(P_RandomRange(-10,10)*FRACUNIT),MT_DUST)
		end
		player.mo.state = S_BURN
	elseif player.elec
		if not (leveltime & 3)
			P_SpawnMobj(player.mo.x+(P_RandomRange(-10,10)*FRACUNIT),player.mo.y+(P_RandomRange(-10,10)*FRACUNIT),player.mo.z+(P_RandomRange(-10,10)*FRACUNIT),MT_DUST)
		end
		if (leveltime & 1) == 0
			player.mo.state = S_ELECTRO1
		else
			player.mo.state = S_ELECTRO2
		end
	end
end

addHook("PlayerThink", ForceState)

// Bounce
// Haha, Blade, shut up.

local function Bounce(player)
	if not player.mo and player.mo.valid return end
	if not (player.playerstate == PST_LIVE) return end
	if player.mo.skin != "mcsonic" return end
	
	if player.bouncecount == nil
		player.bouncecount = 0
	end
	
	if player.nobounce == nil
		player.nobounce = false
	end
	
	if player.cmd.buttons & BT_CUSTOM1
	and player.pflags & PF_JUMPED
	and not P_IsObjectOnGround(player.mo)
	and not player.custom1down
	and not player.bouncing
	and not player.hypertrans
	and not player.nobounce
		player.bouncing = true
		P_SetObjectMomZ(player.mo, -24*FRACUNIT, false)
		player.bouncecount = $ + 1
	end
	
	if P_IsObjectOnGround(player.mo)
	and not player.bouncing
		player.bouncecount = 0
	end
	
	if P_IsObjectOnGround(player.mo)
	and player.bouncing
		player.bouncing = false
		if player.bouncecount < 3
			player.mo.state = S_PLAY_JUMP
			player.pflags = $|PF_JUMPED
		else
			player.mo.state = S_PLAY_SPRING
		end
		
		for i = 0, 8
			local fa = (i*(ANGLE_180/4))
			local dust = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_SPINDUST)
			dust.momx = FixedMul(sin(fa),20*FRACUNIT)
            dust.momy = FixedMul(cos(fa),20*FRACUNIT)
		end
		
		if player.mo.eflags & MFE_UNDERWATER and not player.powers[pw_super]
			P_SetObjectMomZ(player.mo, 10*FRACUNIT+(player.bouncecount*FRACUNIT*2)/2, false)
		elseif player.mo.eflags & MFE_UNDERWATER and player.powers[pw_super]
			P_SetObjectMomZ(player.mo, 10*FRACUNIT+(player.bouncecount*FRACUNIT*2), false)
		elseif player.powers[pw_super] and not (player.mo.eflags & MFE_UNDERWATER)
			P_SetObjectMomZ(player.mo, 10*FRACUNIT+(player.bouncecount*FRACUNIT*2)*2, false)
		else
			P_SetObjectMomZ(player.mo, 10*FRACUNIT+(player.bouncecount*FRACUNIT*2), false)
		end
		
		if player.hyper
			P_StartQuake(25*FRACUNIT, 16)
			P_NukeEnemies(player.mo, player.mo, 1500*FRACUNIT)
			P_FlashPal(player, PAL_WHITE, 8)
		end
		
		S_StartSound(player.mo, sfx_s3k44, player)
		player.pflags = $1 & ~PF_SPINNING
	end	
	
	if player.mo.eflags & MFE_SPRUNG
	and player.bouncing
		player.bouncing = false
		player.mo.momz = $*6/5
		player.mo.momx = $*4/3
		player.mo.momy = $*4/3
		for i = 0, 8
			local fa = (i*(ANGLE_180/4))
			local dust = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_SPINDUST)
			dust.momx = FixedMul(sin(fa),20*FRACUNIT)
            dust.momy = FixedMul(cos(fa),20*FRACUNIT)
		end
		S_StartSound(player.mo, sfx_sprong, player)
	end	
	
	if player.bouncing
		local trail = P_SpawnGhostMobj(player.mo)
			
		for i = 0,9
			trail.fuse = 9
			trail.state = S_THOK
			trail.scale = FRACUNIT - (i * FRACUNIT/240)
			trail.destscale = 0
		end
	end
	
	if player.bouncing
		if (P_PlayerInPain(player))
		or player.powers[pw_carry]
			player.bouncing = false
		end
	end
	
	if P_IsObjectOnGround(player.mo)
	or (P_PlayerInPain(player))
	or player.powers[pw_carry]
		player.nobounce = false
	end
	
	if player.bouncing
	and P_IsObjectInGoop(player.mo)
		player.bouncing = false
		player.nobounce = true
	end
	
	if player.cmd.buttons & BT_CUSTOM1
		player.custom1down = true
	else
		player.custom1down = false
	end
end

addHook("PlayerThink", Bounce)

local function EnemyHurtThwick(enemy, mo)
	if not mo or not mo.valid return end
	if mo.skin != "mcsonic" return end
	local player = mo.player
	if (player == nil) or (player.playerstate != PST_LIVE) return end	
	if not enemy and enemy.valid return end
	
	if enemy.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR)
		if player.bouncing
			P_SetObjectMomZ(player.mo, 12*FRACUNIT+(abs(player.mo.momz)-24*FRACUNIT), false)
			player.bouncecount = $ - 1
			player.bouncing = false
			S_StartSound(mo, sfx_s3k44, player)
		end
	end
end

addHook("MobjDamage", EnemyHurtThwick)

// Air Roll - If you aren't in a curled-up state, you can curl back up.

local function AirRoll(player)
	if not (player.mo and player.mo.valid) then return end 
	if player.mo.skin != "mcsonic" return end
	
	if not P_IsObjectOnGround(player.mo)
	and not (player.mo.state == S_PLAY_JUMP)
	and not (player.mo.state == S_PLAY_ROLL)
	and not (player.mo.state == S_DROPDASH)
	and player.bouncecount < 3
	and not (P_PlayerInPain(player))
	and not (player.powers[pw_shield] == SH_WHIRLWIND and player.pflags & PF_SHIELDABILITY)
//	and not player.cantrick
		player.mo.state = S_PLAY_ROLL
		player.pflags = $1 & ~PF_SPINNING
		player.pflags = $1 | PF_JUMPED
		player.pflags = $1 | PF_THOKKED
		S_StartSound(player.mo, sfx_airrol)
	end
end
				
addHook("SpinSpecial",AirRoll)

local function RestoreRollControl(player)
	if player.mo.skin != "mcsonic" return end
	
	if player.pflags & PF_SPINNING
	and not P_IsObjectOnGround(player.mo)
		if player.pflags & PF_JUMPED
			player.pflags = $1 & ~PF_SPINNING
		else
			player.pflags = $1 & ~PF_SPINNING
			player.pflags = $1 | PF_JUMPED
			player.pflags = $1 | PF_THOKKED
		end
	end
end

addHook("PlayerThink", RestoreRollControl)

local function SpindashAnimation(player)
	if player.mo.skin != "mcsonic" return end
	
	if player.pflags & PF_STARTDASH
	and player.dashspeed < player.mindash + (player.maxdash-player.mindash)/6
		player.mo.state = S_PLAY_ROLL
		P_SpawnThokMobj(player)
	elseif player.mo.state == S_PLAY_ROLL
	and player.dashspeed > player.mindash + (player.maxdash-player.mindash)/6
		player.mo.state = S_PLAY_SPINDASH
	end
end

addHook("PlayerThink", SpindashAnimation)