freeslot("SPR_PEEL","sfx_nspd","SPR2_FDSH","S_PLAY_NOTSOAP_MACH4","SPR2_UPCN","S_PLAY_NOTSOAP_UPPERCUTCANCEL")
states[S_PLAY_NOTSOAP_MACH4] = {
  sprite = SPR_PLAY,
  frame = SPR2_FDSH,
  nextstate = S_PLAY_NOTSOAP_MACH4
}

states[S_PLAY_NOTSOAP_UPPERCUTCANCEL] = {
  sprite = SPR_PLAY,
  frame = SPR2_UPCN,
  nextstate = S_PLAY_NOTSOAP_UPPERCUTCANCEL
}

addHook("ThinkFrame", do
	for player in players.iterate
		if (player and player.mo and player.mo.valid) and (player.mo.skin == "notsoap")
			if player.dashmode >= 3*TICRATE
				player.nomoredashmodeflash = P_SpawnMobjFromMobj(player.mo,0,0,0,MT_OVERLAY)
				player.nomoredashmodeflash.target = player.mo
				player.nomoredashmodeflash.skin = player.mo.skin
				player.nomoredashmodeflash.sprite = player.mo.sprite
				player.nomoredashmodeflash.spritexscale = player.mo.spritexscale
				player.nomoredashmodeflash.spriteyscale = player.mo.spriteyscale
				player.nomoredashmodeflash.sprite2 = player.mo.sprite2
				player.nomoredashmodeflash.color = player.mo.color
				player.nomoredashmodeflash.angle = player.drawangle
				player.nomoredashmodeflash.info.dispoffset = 1
				player.nomoredashmodeflash.frame = player.mo.frame
				player.nomoredashmodeflash.fuse = 1
				player.nomoredashmodeflash.rollangle = player.mo.rollangle
				player.nomoredashmodeflash.roll = player.mo.roll
				player.nomoredashmodeflash.pitch = player.mo.pitch
			end
			if player.mo.state == S_PLAY_DASH
			or player.mo.state == S_PLAY_NOTSOAP_MACH4
				if not player.powers[pw_super] and not (player.solchar and player.solchar.istransformed)
					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
						peelout.rollangle = player.mo.rollangle
						peelout.roll = player.mo.roll
						peelout.pitch = player.mo.pitch
						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)

freeslot("sfx_nsup")

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
		if player.playerstate == PST_DEAD then
			player.mach4 = 0
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
		if player.dashmode >= 3*TICRATE and player.speed >= 45*FRACUNIT
			player.mach4 = 1
			player.powers[pw_strong] = STR_DASH|STR_ANIM|STR_PUNCH|STR_STOMP|STR_WALL|STR_SPIKE
		else
			player.mach4 = 0
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
		if player.mach4 == 1 and P_IsObjectOnGround(player.mo) and not (player.pflags & PF_SPINNING) and player.playerstate ~= PST_DEAD
			player.mo.state = S_PLAY_NOTSOAP_MACH4
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
		if player.mach4 == 1 and player.mo.state == S_PLAY_DASH and not (player.pflags & PF_SPINNING) and player.playerstate ~= PST_DEAD
			player.mo.state = S_PLAY_NOTSOAP_MACH4
		end
	end
end)

//workaround for weird buggy buggy buggy buggy bugyg buggy buggy buggy bugyg ubygu bugyg ubgyg buggy buggy buggy
addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
		if player.mach4 == 1 and (player.pflags & PF_SPINNING) and player.playerstate ~= PST_DEAD
			player.mo.state = S_PLAY_ROLL
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mach4 == 0 and player.mo.state == S_PLAY_NOTSOAP_MACH4 and not (player.pflags & PF_SPINNING) and player.playerstate ~= PST_DEAD
		player.mo.state = S_PLAY_DASH
	end
end)

addHook("PlayerThink", function(player)
    if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap"
		if (player.powers[pw_justsprung] or player.mo.eflags & MFE_SPRUNG) and player.mo.state != S_PLAY_SPRING then 
			player.dashmode = DASHMODE_MAX
		end
    end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mach4 == 1 then
		if not S_SoundPlaying(player.mo, sfx_nspd)
			S_StartSound(player.mo, sfx_nspd)
		end
	else
		S_StopSoundByID(player.mo, sfx_nspd)
	end
end)

addHook("ThinkFrame", do
	for player in players.iterate
	    if player.holdingc1 == nil or player.playerstate == PST_DEAD or (player.pflags & PF_SPINNING)
			player.holdingc1 = 0
		end
	end
end)

addHook("ThinkFrame", do
	for player in players.iterate
	    if player.uppercutted == nil or player.playerstate == PST_DEAD or (player.pflags & PF_SPINNING) then
			player.uppercutted = 0
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
			if (player.cmd.buttons & BT_CUSTOM1)
			and player.holdingc1 == 0
			and player.uppercutted == 0
			and player.uppercutcancel == 0
			and player.gotflag == 0
			and not (player.pflags & PF_SPINNING)
			and player.playerstate ~= PST_DEAD
			and not (player.pflags & PF_SLIDING) 
			and not (player.exiting) 
			and not (player.powers[pw_carry] == CR_NIGHTSMODE)
			and not (player.powers[pw_carry]) then
				if (player.pflags & PF_STASIS) then return end
				if (player.pflags & PF_FULLSTASIS) then return end
				if player.powers[pw_nocontrol] == 0 then
					player.mo.state = S_NOTSOAP_UPPERCUT
					P_SetObjectMomZ(player.mo, 15*FRACUNIT, false)
					player.powers[pw_strong] = STR_ANIM|STR_CEILING|STR_STOMP
					player.pflags = $|PF_JUMPED|PF_THOKKED & ~PF_STARTJUMP
					S_StartSound(player.mo, sfx_nsup)
					player.holdingc1 = 1
					player.uppercutted = 1
					player.panim = PA_ABILITY
			end
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
		if player.mo.state == S_NOTSOAP_UPPERCUT and not P_IsObjectOnGround(player.mo) and not (player.pflags & PF_SPINNING) and player.playerstate ~= PST_DEAD
			player.drawangle = leveltime*ANG1*16
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
		if player.mo.state == S_NOTSOAP_UPPERCUT then
			player.uppercutted = 1
			player.pflags = $|PF_JUMPED|PF_THOKKED
		else
			player.uppercutted = 0
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
		if player.mo.state == S_PLAY_NOTSOAP_UPPERCUTCANCEL then
			player.uppercutcancel = 1
			player.pflags = $|PF_JUMPED|PF_THOKKED
		else
			player.uppercutcancel = 0
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
			if player.mo.state == S_NOTSOAP_UPPERCUT and (player.cmd.buttons & BT_SPIN)
				player.mo.state = S_PLAY_NOTSOAP_UPPERCUTCANCEL
				player.panim = PA_ABILITY2
				if (player.powers[pw_shield] == SH_ARMAGEDDON) then
					player.powers[pw_shield] = 0
					P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_NOTSOAPEXPLOSION)
					S_StartSound(player.mo, sfx_boomr)
					P_NukeEnemies(player.mo, player.mo, 1536*FRACUNIT)
					P_FlashPal(player, PAL_NUKE, 10)
					P_InstaThrust(player.mo, player.mo.angle, 70*FRACUNIT)
				else
					P_InstaThrust(player.mo, player.mo.angle, 50*FRACUNIT)
				end
				player.pflags = $|PF_THOKKED
				player.dashmode = DASHMODE_MAX
				P_SetObjectMomZ(player.mo, 3*FRACUNIT, false)
		end
	end
end)

addHook("PlayerThink", function(player)
	if (player and player.mo and player.mo.valid) and player.mo.skin == "notsoap" then
		if not (player.cmd.buttons & BT_CUSTOM1) and player.holdingc1 == 1
			player.holdingc1 = 0
		end
	end
end)

addHook("PlayerThink", function(p)
	if not (p and p.mo and p.mo.valid)
		return false
	end

	if (p.mo.skin == "notsoap") and (p.pflags & PF_SPINNING) and not (p.pflags & PF_STARTDASH) and P_IsObjectOnGround(p.mo)
		p.thrustfactor = skins[p.mo.skin].thrustfactor * 20
	else
		p.thrustfactor = skins[p.mo.skin].thrustfactor
	end
end)


local UNCURL_LOCKTIME = 8

COM_AddCommand("notsoap_uncurltoggle", function(player, value)
	if not(player and player.valid and player.mo)
		CONS_Printf(player,"GO TO A LEVEL!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
		return
	end
	if value == "0" or value == "no" or value == "off"
		player.uncurltoggle = 0
		CONS_Printf(player,"You can now release spin to uncurl.")
	elseif value == "1" or value == "yes" or value == "on"
		player.uncurltoggle = 1
		CONS_Printf(player,"You can now re-press spin to uncurl.")
	else
		if player.uncurltoggle == 1
			CONS_Printf(player,"uncurltoggle is on. Default is on.")
		else
			CONS_Printf(player,"uncurltoggle is off. Default is on.")
		end
	end
end,0)

addHook("ThinkFrame", function(player)
	for player in players.iterate()
		//Init
		if player.init == nil
			player.init = true
			player.prevbuttons = player.cmd.buttons
			if player.uncurltoggle == nil player.uncurltoggle = 1 end
			return
		end
		
		if player.mo and player.mo and player.mo.valid and player.mo.skin == "notsoap" and player.playerstate == PST_LIVE and not player.exiting and not player.powers[pw_nocontrol] and not P_PlayerInPain(player)
			local pbtn = player.prevbuttons
			local btn = player.cmd.buttons
			local mo = player.mo
			
			//print(mo.uncurl_lock)
			//print(mo.will_uncurl)
			//Uncurl
			if mo.state == S_PLAY_ROLL and P_IsObjectOnGround(mo)
				local uncurlinput = false
				local recurlinput = false
				if player.uncurltoggle == 1
					uncurlinput = (btn & BT_USE) and not (pbtn & BT_USE)
				else
					uncurlinput = (pbtn & BT_USE) and not (btn & BT_USE)
					recurlinput = (btn & BT_USE) and not (pbtn & BT_USE)
				end
				
				if mo.uncurl_lock == UNCURL_LOCKTIME and uncurlinput
					uncurlinput = false
				end
				
				if uncurlinput
					mo.will_uncurl = true
				end
				if recurlinput
					mo.will_uncurl = false
				end
				
				if mo.uncurl_lock
					mo.uncurl_lock = max(0, $ - 1)
					
				elseif mo.will_uncurl
					mo.uncurl_lock = UNCURL_LOCKTIME
					mo.uncurlready = false
					if FixedHypot(mo.momx, mo.momy) >= player.runspeed
						mo.state = S_PLAY_RUN
					else
						mo.state = S_PLAY_WALK
					end
					if player.pflags & PF_SPINNING
						player.pflags = $1 & ~PF_SPINNING
					end
					S_StopSoundByID(mo,sfx_spin)
				end
			else
				mo.uncurl_lock = UNCURL_LOCKTIME
				mo.will_uncurl = false
			end
			player.prevbuttons = btn
		end
	end
end)