//:sadge:
freeslot("sfx_mach1", "sfx_mach2", "sfx_mach3", "sfx_mach4", "S_PLAY_MACH1", "SPR2_MAC1")
sfxinfo[sfx_mach1].caption = "Slow Steps"
sfxinfo[sfx_mach2].caption = "Faster Steps"
sfxinfo[sfx_mach3].caption = "Dashing"
sfxinfo[sfx_mach4].caption = "Full Speed Ahead!"

states[S_PLAY_MACH1] = {
	sprite = SPR_PLAY,
	frame = SPR2_MAC1|FF_ANIMATE,
	tics = 30,
	var1 = 2,
	var2 = 2,
	nextstate = S_PLAY_RUN
}

local normalnormalspeed = 36*FRACUNIT
local machusreset = 0*FRACUNIT

local function mach1animation(p)
	if p.mo.state == S_PLAY_MACH1
		return true
	else
		return false
	end
end

addHook("ThinkFrame", do
	for p in players.iterate
		if p.machspeed == nil
			p.machspeed = 0
		end	

		if p.machcounter == nil
			p.machcounter = 0
		end

		if p.ppc
		and p.mo and p.mo.valid
			if mach1animation(p)
			and not P_UpperCutAnimation(p)
			and not p.grabbing
				p.machspeed = 1
			end
			if p.speed >= 27*FRACUNIT
			and p.machcounter < mach3time
			and not mach1animation(p)
			and not P_UpperCutAnimation(p)
			and not p.grabbing
				p.machspeed = 2
			end
			if p.speed >= 27*FRACUNIT
			and leveltime%5 == 0
			and P_IsObjectOnGround(p.mo)
			and not mach1animation(p)
			and (p.cmd.forwardmove or p.cmd.sidemove)
			or leveltime%5 == 0
			and p.ptwallrun
				p.machcounter = $+FRACUNIT
			end
			if p.machcounter >= mach3time
			and p.machcounter < mach4time
				p.machspeed = 3
			end
		end
	end
end)

addHook("ThinkFrame", do
	for p in players.iterate
		if p.mo and p.mo.valid
		and p.machspeed >= 3
		and P_IsObjectOnGround(p.mo)
		and leveltime%5 == 0
		and (p.cmd.forwardmove or p.cmd.sidemove)
		or p.ptwallrun
		and p.machspeed >= 3
		and leveltime%5 == 0
			p.normalspeed = $+FRACUNIT
		end
	end
end)

addHook("PlayerThink", function(p)
	if p.ppc
	and p.machcounter >= mach4time
		p.machspeed = 4
	end
end)

local function resetmystuff(p)
	p.normalspeed = normalnormalspeed
	p.machcounter = machusreset
	if p.machspeed >= 3
		p.machspeed = 2
	end
end

addHook("PlayerThink", function(p)
	if p.ppc
	and p.machspeed >= 3
		p.charflags = $|SF_RUNONWATER
	elseif p.machspeed < 3
		p.charflags = $ & ~SF_RUNONWATER
	end
end)

addHook("PlayerThink", function(p)
	if p.ppc
	and mach1animation(p)
	and not S_SoundPlaying(p.mo, sfx_mach1)
		S_StartSound(p.mo, sfx_mach1)
	elseif not mach1animation(p)
	and S_SoundPlaying(p.mo, sfx_mach1)
	and p.ppc
		S_StopSoundByID(p.mo, sfx_mach1)
	end
end)

addHook("PlayerThink", function(p)
	if p.ppc
	and p.mo.state == S_PLAY_RUN
	and not S_SoundPlaying(p.mo, sfx_mach2)
	and p.machspeed < 3
		S_StartSound(p.mo, sfx_mach2)
	elseif p.mo.state ~= S_PLAY_RUN
	and S_SoundPlaying(p.mo, sfx_mach2)
	and p.ppc
	and not p.ptwallrun
		S_StopSoundByID(p.mo, sfx_mach2)
	end
end)

addHook("PlayerThink", function(p)
	if p.ppc
	and p.machspeed == 3
	and not S_SoundPlaying(p.mo, sfx_mach3)
	and p.speed >= 30*FRACUNIT
	and not p.grabbing
	and p.mo.state ~= S_PLAY_PP_SUPERJUMP
		S_StartSound(p.mo, sfx_mach3)
	elseif (p.speed < 30*FRACUNIT or p.grabbing or p.mo.state == S_PLAY_PP_SUPERJUMP or p.machspeed ~= 3)
	and S_SoundPlaying(p.mo, sfx_mach3)
	and p.ppc
		S_StopSoundByID(p.mo, sfx_mach3)
	end
end)

addHook("PlayerThink", function(p)
	if p.ppc
	and p.machspeed == 4
	and not S_SoundPlaying(p.mo, sfx_mach4)
	and p.speed >= 30*FRACUNIT
	and not p.grabbing
	and p.mo.state ~= S_PLAY_PP_SUPERJUMP
		S_StartSound(p.mo, sfx_mach4)
	elseif (p.speed < 30*FRACUNIT or p.grabbing or p.mo.state == S_PLAY_PP_SUPERJUMP or p.machspeed ~= 4)
	and S_SoundPlaying(p.mo, sfx_mach4)
	and p.ppc
		S_StopSoundByID(p.mo, sfx_mach4)
	end
end)

addHook("PlayerThink", function(p)
	if p.ppc
	and p.speed < 20*FRACUNIT
	and not p.ptwallrun
	and not p.taunting
		resetmystuff(p)
	end
	if p.ppc
	and p.machspeed == 3
	and (p.mo.state == S_PLAY_RUN or p.mo.state == S_PLAY_PP_MACHJUMP or p.mo.state == S_PLAY_FALL or p.mo.state == S_PLAY_MACHJUMPSTART or p.mo.state == S_PLAY_WALK or p.mo.state == S_PLAY_SPRING)
		p.mo.state = S_PLAY_PP_MACH3
	end
	if p.machspeed < 3
	and (p.mo.state == S_PLAY_PP_MACH3 or p.mo.state == S_PLAY_PP_MACH4)
	and p.ppc
		p.mo.state = S_PLAY_RUN
	end
end)

addHook("PlayerThink", function(p)
	if p.ppc
	and p.machspeed == 4
	and (p.mo.state == S_PLAY_PP_MACH3 or p.mo.state == S_PLAY_RUN or p.mo.state == S_PLAY_WALK or p.mo.state == S_PLAY_SPRING)
		p.mo.state = S_PLAY_PP_MACH4
	end
end)

addHook("PlayerCanDamage", function(p)
	if p.machcounter >= 10*FRACUNIT then
		return true
	end
end)

addHook("PlayerThink", function(p)
	if (p.speed <= 5*FRACUNIT or p.mo.state == S_PLAY_WALK)
	and p.ppc
		p.machspeed = 0
	end
end)

addHook("PlayerThink", function(p)
	if p.machspeed >= 3
		p.charflags = $|SF_CANBUSTWALLS
	elseif p.machspeed < 3
	and p.ppc
		p.charflags = skins[p.mo.skin].flags
	end
end)

addHook("MobjMoveCollide", function(mo, spike) -- Spike breaking by ARJr. from delf's boost mod
    if mo.valid
    and (mo.type == MT_PLAYER)
	and mo.player.machspeed >= 3
    and spike.type == MT_SPIKE
		if (spike.z >= (mo.z - 16*FRACUNIT)) and (spike.z <= (mo.z + mo.height + 16*FRACUNIT))
			P_KillMobj(spike, mo, mo)
			mo.player.score = $+10
		elseif (spike.flags2 & MF2_OBJECTFLIP)
		and (spike.z <= (mo.z - 16*FRACUNIT)) and (spike.z >= (mo.z + mo.height+ 16*FRACUNIT))
			P_KillMobj(spike, mo, mo)
			mo.player.score = $+10
        end
    end
end)

local function cmd(p)
	if (p.cmd.forwardmove or p.cmd.sidemove)
		return true
	else
		return false
	end
end

addHook("ThinkFrame", do
	for p in players.iterate
		if p.ppc
		and not (p.cmd.buttons & BT_USE)
		or p.ppc
		and P_UpperCutAnimation(p)
			p.normalspeed = 13*FRACUNIT
			p.machspeed = 0
		elseif p.ppc
		and (p.cmd.buttons & BT_USE)
		and not P_UpperCutAnimation(p)
		and p.machcounter < mach3time
			p.normalspeed = 36*FRACUNIT
		end
		if (p.mo.state == S_PLAY_WALK)
		and cmd(p)
		and (p.cmd.buttons & BT_USE)
		and not p.powers[pw_pushing]
		and p.machspeed < 3
		and p.ppc
			p.mo.state = S_PLAY_MACH1
		end
		if p.mo.state == S_PLAY_MACH1
		and p.ppc
		and (p.powers[pw_pushing] or p.machspeed >= 3 or not cmd(p) or not (p.cmd.buttons & BT_USE))
			p.mo.state = S_PLAY_RUN
		end
		if p.mo.state == S_PLAY_MACH1
		and not cmd(p)
		and p.ppc
		or p.ppc
		and p.powers[pw_pushing]
		and p.mo.state == S_PLAY_MACH1
		or p.ppc
		and not (p.cmd.buttons & BT_USE)
		and p.mo.state == S_PLAY_MACH1
			p.mo.state = S_PLAY_RUN
		end
	end
end)

addHook("ThinkFrame", do
	for p in players.iterate
		local mo = p.mo
		if p.ppc
		and p.machspeed >= 3
		and not cmd(p)
		and (p.cmd.buttons & BT_USE)
		and not (p.pflags & PF_STASIS)
		and not p.powers[pw_nocontrol]
		and not p.powers[pw_pushing]
		and not (p.exiting)
		and p.mo.state ~= S_PLAY_PP_REDIRECT
		and p.mo.state ~= S_PLAY_REDIRECTFALL
		and not p.taunting
			p.drawangle = mo.angle
			P_InstaThrust(p.mo, p.drawangle, p.normalspeed)
		end
	end
end)

freeslot("S_MACH4RING","SPR_M4RI")

states[S_MACH4RING] = {
	sprite = SPR_M4RI,
	frame = A|FF_PAPERSPRITE
}

rawset(_G, "P_CreateRing", function(p)
	local ring = P_SpawnMobj(p.mo.x,p.mo.y,p.mo.z,MT_THOK)
	ring.state = S_MACH4RING
	ring.fuse = 999
	ring.tics = 20
	ring.angle = p.drawangle+ANGLE_90
	ring.scale = p.mo.scale-FRACUNIT/2
	ring.destscale = p.mo.scale*2
	ring.colorized = true
	ring.color = SKINCOLOR_WHITE
	if (p.mo.eflags & MFE_VERTICALFLIP)
		ring.flags2 = $|MF2_OBJECTFLIP
		ring.eflags = $|MFE_VERTICALFLIP
	end
end)

addHook("ThinkFrame", do
	for p in players.iterate
		if p.mo.state == S_PLAY_PP_MACH4
		and leveltime%5 == 0
			P_CreateRing(p)
		end
	end
end)

addHook("ThinkFrame", do
	for p in players.iterate
		if p.mo.state == S_PLAY_PP_SUPERJUMP
		and leveltime%5 == 0
			local ring = P_SpawnMobj(p.mo.x,p.mo.y,p.mo.z,MT_THOK)
			ring.state = S_MACH4RING
			ring.fuse = 999
			ring.tics = 20
			ring.angle = p.drawangle+ANGLE_90
			ring.scale = p.mo.scale-FRACUNIT/2
			ring.destscale = p.mo.scale*2
			ring.colorized = true
			ring.renderflags = $|RF_FLOORSPRITE
			ring.color = SKINCOLOR_WHITE
			if (p.mo.eflags & MFE_VERTICALFLIP)
				ring.flags2 = $|MF2_OBJECTFLIP
				ring.eflags = $|MFE_VERTICALFLIP
			end
		end
	end
end)

addHook("PlayerThink", function(p)
	if p.machspeed >= 3
	and not (p.cmd.buttons & BT_USE)
	and not P_IsObjectOnGround(p.mo)
		p.machcounter = 0*FRACUNIT
		p.machspeed = 0
		p.mo.state = S_PLAY_FALL
	end
end)