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_MPEEL1", "S_PLAY_MPEEL2", "S_PLAY_MPEEL3", "S_PLAY_MPEEL4", "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_MPEEL1] = {SPR_PLAY, SPR2_DASH1, 1, nil, 0, 0, S_PLAY_MPEEL2}
states[S_PLAY_MPEEL2] = {SPR_PLAY, SPR2_DASH2, 1, nil, 0, 0, S_PLAY_MPEEL3}
states[S_PLAY_MPEEL3] = {SPR_PLAY, SPR2_DASH3, 1, nil, 0, 0, S_PLAY_MPEEL4}
states[S_PLAY_MPEEL4] = {SPR_PLAY, SPR2_DASH4, 1, nil, 0, 0, S_PLAY_MPEEL1}
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(
"sfx_pelchr",
"sfx_pelrel"
)

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

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

// 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 == "ultsonic"
			//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 not (player.pflags & PF_SPINNING)
				and player.cmd.buttons & BT_CUSTOM1
			    and not (player.playerstate == PST_DEAD)
				and not player.bouncing
				and not (player.exiting)
				and not (player.pflags & PF_SLIDING)
					if player.mo.peelsound == 0
						S_StartSound(player.mo, sfx_pelchr)
						player.mo.peelsound = 1
						player.prevnormalspeed = player.normalspeed
					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 <= 50) and not (player.powers[pw_super]))
				or ((player.mo.peelouttimer >= 1) and (player.mo.peelouttimer <= 14) and (player.powers[pw_super]))
					player.normalspeed = player.prevnormalspeed
					P_InstaThrust(player.mo, player.mo.angle, FixedMul(player.normalspeed, player.mo.scale))
					player.mo.state = S_PLAY_WALK
					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
				and player.mo.peelouttimer < 50
					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
				if player.mo.peelouttimer >= 50
					if not ((player.mo.state >= S_PLAY_MPEEL1) and (player.mo.state <= S_PLAY_MPEEL4))
					or ((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_MPEEL1
					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 >= 50) 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.mchyper
							P_StartQuake(25*FRACUNIT, 16)
							P_NukeEnemies(player.mo, player.mo, 1500*FRACUNIT)
							if player.mcflashes
								P_FlashPal(player, PAL_WHITE, 8)
							end
							S_StartSound(player.mo, sfx_s3k4e)
						end
//						player.norolltimer = TICRATE
						player.striketimer = TICRATE
					end
					P_InstaThrust(player.mo, player.mo.angle, FixedMul(70*FRACUNIT, player.mo.scale))
					if not player.powers[pw_super]
						player.dashmode2 = 3*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))
				or ((player.mo.state >= S_PLAY_MPEEL1) and (player.mo.state <= S_PLAY_MPEEL4))
					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)


// SuperPhanto already contributed quite a bit to MCSonic v2, so I'll reuse this resource of his and edit it to work.
freeslot("SPR_PEEL")

addHook("ThinkFrame", do
	for player in players.iterate
		if (player.mo.valid) and (player.mo.skin == "ultsonic")
			if player.dashmode2 >= 2*TICRATE and not player.mo.peelouttimer
			or player.mo.peelouttimer >= 50
				if player.mo.state == S_PLAY_DASH and not player.powers[pw_super]
				or player.mo.peelouttimer and not player.powers[pw_super]
					for i = -40, 40
						
						local force = i*FRACUNIT/3
						local angle = ANGLE_90

						local shiftx = FixedMul(cos(player.drawangle + angle), force)
						local shifty = FixedMul(sin(player.drawangle + angle), force)
						
						local shiftx2 = FixedMul(cos(player.drawangle), FRACUNIT)
						local shifty2 = FixedMul(sin(player.drawangle), FRACUNIT)
						
						if i > 20
						or i < -20
							local peelout = P_SpawnMobjFromMobj(player.mo, shiftx2 + shiftx, shifty2 + shifty, 0, MT_OVERLAY)
							peelout.target = player.mo
							peelout.fuse = 1
							peelout.sprite = SPR_PEEL
							if i < 0
								if player.mo.frame == A
									peelout.frame = A
								elseif player.mo.frame == B
									peelout.frame = B
								elseif player.mo.frame == C
									peelout.frame = C
								elseif player.mo.frame == D
									peelout.frame = D
								end
								peelout.angle = player.drawangle + ANGLE_90/6
							else
								if player.mo.frame == A
									peelout.frame = C
								elseif player.mo.frame == B
									peelout.frame = D
								elseif player.mo.frame == C
									peelout.frame = A
								elseif player.mo.frame == D
									peelout.frame = B
								end
								peelout.angle = player.drawangle - ANGLE_90/6
							end
							peelout.renderflags = RF_PAPERSPRITE
							peelout.scale = player.mo.scale/2
							if player.mo.eflags & MFE_VERTICALFLIP
								peelout.eflags = $ | MFE_VERTICALFLIP
								peelout.z = player.mo.z + player.mo.height - peelout.height
							end
						end
					end
				end
			end
		end
	end
end)

local function DashSprites(player)

	if not player.mo or not player.mo.valid then
		return
	end

	if player.mo.skin != "ultsonic" then
		return
	end

	if player.dashmode2 == nil then
		player.dashmode2 = 0
	end

	if player.runspeed == nil then
		player.runspeed = 28*FRACUNIT
	end
	
	if player.dashmode2 >= 2*TICRATE
		if player.speed > 36*FRACUNIT
		and player.mo.state == S_PLAY_RUN
			player.mo.state = S_PLAY_DASH
		end
		if player.mo.state == S_PLAY_DASH
		and player.speed <= 21*FRACUNIT
			if player.speed >= player.runspeed
				player.mo.state = S_PLAY_RUN
			else
				player.mo.state = S_PLAY_WALK
			end
		end
	end
	
	if player.mo.state == S_PLAY_DASH
	and player.dashmode2 < 2*TICRATE
		if player.speed >= player.runspeed
			player.mo.state = S_PLAY_RUN
		else
			player.mo.state = S_PLAY_WALK
		end
	end
	
	if player.powers[pw_super]
	and player.mchyper
		if player.mo.state == S_PLAY_RUN
			player.mo.state = S_PLAY_DASH
		end
	end
end

addHook("PlayerThink", DashSprites)