freeslot("sfx_grab","S_PLAY_GRABSTART1","S_PLAY_GRABSTART2","S_PLAY_GRABAIRSTART","S_PLAY_GRABAIR","SPR2_GRJS","SPR_GRBS","S_PLAY_GRABEND","SPR2_GRBE","S_PLAY_ROLLGETUP","SPR2_ROLG")
sfxinfo[sfx_grab].caption = "Grab Dash"

states[S_PLAY_GRABSTART1] = {
	sprite = SPR_GRBS,
	frame = A|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_GRABSTART2
}

states[S_PLAY_GRABSTART2] = {
	sprite = SPR_GRBS,
	frame = B|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_PP_GRABDASH
}

states[S_PLAY_GRABEND] = {
	sprite = SPR_PLAY,
	frame = SPR2_GRBE|FF_ANIMATE,
	tics = 8,
	var1 = 2,
	var2 = 2,
	nextstate = S_PLAY_RUN
}

states[S_PLAY_ROLLGETUP] = {
	sprite = SPR_PLAY,
	frame = SPR2_ROLG|FF_ANIMATE,
	tics = 12,
	var2 = 1,
	var2 = 1,
	nextstate = S_PLAY_RUN
}

states[S_PLAY_GRABAIRSTART] = {
	sprite = SPR_PLAY,
	frame = SPR2_GRJS|FF_ANIMATE,
	tics = 8,
	var1 = 2,
	var2 = 2,
	nextstate = S_PLAY_GRABAIR
}

states[S_PLAY_GRABAIR] = {
	sprite = SPR_PLAY,
	frame = SPR2_CLNG,
	tics = 1,
	nextstate = S_PLAY_GRABAIR
}

local function resetmystuff(p)
	p.normalspeed = skins[p.mo.skin].normalspeed
	p.machcounter = 0*FRACUNIT
	if p.machspeed >= 3
		p.machspeed = 2
	end
end

addHook("ThinkFrame", function(player)
	for player in players.iterate
		if player.c1tics == nil
			player.c1ics = 0
		end
		if player.grabbing == nil
			player.grabbing = false
		end
		if player.grabtics == nil
			player.grabtics = 0
		end
		if player.mo.skin == "prpeppino"
		and (player.cmd.buttons & BT_CUSTOM1)
		and player.mo and player.mo.valid
			player.c1tics = $1+1
		else
			player.c1tics = 0
		end
		if player.grabmachspeed == nil
			player.grabmachspeed = 0
		end
		if not player.grabbing
			player.grabmachspeed = player.machcounter
		end
	end
end)

local function dowave(p)
	local mo = p.mo
	for i = -1, 1, 2
		local ang = i * ANG10
		local factor = FixedMul(4*mo.scale, cos(ang))
		local x = P_ReturnThrustX(mo, p.drawangle + ANGLE_180 + ang, 24*mo.scale)
		local y = P_ReturnThrustY(mo, p.drawangle + ANGLE_180 + ang, 24*mo.scale)
		local dust = P_SpawnMobjFromMobj(mo, x, y, 0, MT_THOK)
		dust.scale = mo.scale
		dust.angle = R_PointToAngle2(dust.x, dust.y, mo.x, mo.y)
		dust.state = S_FASTJUMPCLOUD
		dust.momx = FixedMul(factor, cos(dust.angle - i*ANGLE_90))
		dust.momy = FixedMul(factor, sin(dust.angle - i*ANGLE_90))
	end
end

addHook("ThinkFrame", do
	for player in players.iterate
		local mo = player.mo
		if player.mo.skin == "prpeppino"
		and player.c1tics == 1
		and not player.grabbing
		and not player.powers[pw_carry]
		and not (player.exiting)
		and not (player.pflags & PF_STASIS)
		and not player.bodyslam
		and player.mo.state ~= S_PLAY_REDIRECTSTART1
		and player.mo.state ~= S_PLAY_REDIRECTSTART2
		and player.mo.state ~= S_PLAY_REDIRECTSTART3
		and player.mo.state ~= S_PLAY_REDIRECTSTART4
		and not player.bodyslamstart
		and player.mo.state ~= S_PLAY_PP_REDIRECT
		and player.mo.state ~= S_PLAY_REDIRECTFALL
		and not player.ptwallrun
		and player.mo.state ~= S_PLAY_CELHIT
		and player.mo.state ~= S_PLAY_PP_DIVE
		and not player.divecancel
		and player.mo.state ~= S_PLAY_DIVECANCELLAND
		and not player.superpp
		and not P_PlayerInPain(player)
		and not player.divecancelland
		and player.mo.state ~= S_PLAY_PP_SJSTART
		and (player.mo.state ~= S_PLAY_PP_SUPERJUMP)
		and player.mo.state ~= S_PLAY_PP_SHOLDERBASH
		and player.mo.state ~= S_PLAY_BODYLAND
		and not P_UpperCutAnimation(player)
		and player.mo.state ~= S_PLAY_SUPERCHARGE
		and player.mo.state ~= S_PLAY_SHOULDERBASHSTART
		and not (player.pflags & PF_SPINNING)
		and not player.taunting
		and not player.powers[pw_nocontrol]
		and not player.assonfire
		and player.playerstate == PST_LIVE
			player.grabbing = true
			S_StartSound(player.mo, sfx_grab)
			dowave(player)
		end
		if player.grabbing
			player.grabtics = $1+1
			player.charflags = $|SF_NOSKID
			local ghost = P_SpawnGhostMobj(player.mo)
			ghost.frame = $|TR_TRANS10|FF_FULLBRIGHT
			ghost.fuse = 3
			player.machspeed = 0
			player.machcounter = 0*FRACUNIT
			resetmystuff(player)
			P_InstaThrust(player.mo, player.mo.angle, 36*FRACUNIT)
		end
		if (player.powers[pw_carry] or P_PlayerInPain(player) or player.taunting)
			player.grabbing = false
			player.grabtics = 0
		end	
		if player.grabtics == 20
			player.grabbing = false
			player.machcounter = 5*FRACUNIT
			player.charflags = skins[player.mo.skin].flags
			player.grabtics = 0
			if P_IsObjectOnGround(player.mo)
				player.mo.state = S_PLAY_GRABEND
			else
				player.mo.state = S_PLAY_FALL
			end
		end
	end
end)

addHook("PlayerThink", function(p)
	if p.grabbing
	and p.mo.state ~= S_PLAY_PP_GRABDASH
	and p.mo.state ~= S_PLAY_GRABSTART1
	and p.mo.state ~= S_PLAY_GRABSTART2
	and P_IsObjectOnGround(p.mo)
		p.mo.state = S_PLAY_GRABSTART1
	end
	if p.grabbing
	and p.mo.state ~= S_PLAY_GRABAIR
	and p.mo.state ~= S_PLAY_GRABAIRSTART
	and not P_IsObjectOnGround(p.mo)
		p.mo.state = S_PLAY_GRABAIRSTART
	end
end)

addHook("PlayerCanDamage", function(player)
	if player.grabbing then
		return true
	end
end)

addHook("PlayerSpawn", function(p)
	p.grabbing = false
	p.grabtics = 0
end)

addHook("ThinkFrame", do
	for p in players.iterate
		if p.grabbing
		and not P_IsObjectOnGround(p.mo)
			p.grabtics = 1
		end
		if p.grabbing
		and (p.mo.eflags & MFE_JUSTHITFLOOR)
			p.grabbing = false
			p.grabtics = 0
		end
	end
end)

freeslot("S_PLAY_LUNGELOOP","SPR2_LUNL","S_PLAY_LUNGESTART1","S_PLAY_LUNGESTART2","S_PLAY_LUNGESTART3","S_PLAY_LUNGESTART4","S_PLAY_LUNGESTART5","S_PLAY_LUNGESTART6","S_PLAY_LUNGESTART7","S_PLAY_LUNGESTART8","S_PLAY_LUNGESTART9","S_PLAY_LUNGESTART10","SPR_LUNS")

states[S_PLAY_LUNGESTART1] = {
	sprite = SPR_LUNS,
	frame = A|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_LUNGESTART2
}

states[S_PLAY_LUNGESTART2] = {
	sprite = SPR_LUNS,
	frame = B|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_LUNGESTART3
}

states[S_PLAY_LUNGESTART3] = {
	sprite = SPR_LUNS,
	frame = C|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_LUNGESTART4
}

states[S_PLAY_LUNGESTART4] = {
	sprite = SPR_LUNS,
	frame = D|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_LUNGESTART5
}

states[S_PLAY_LUNGESTART5] = {
	sprite = SPR_LUNS,
	frame = E|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_LUNGESTART6
}

states[S_PLAY_LUNGESTART6] = {
	sprite = SPR_LUNS,
	frame = F|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_LUNGESTART7
}

states[S_PLAY_LUNGESTART7] = {
	sprite = SPR_LUNS,
	frame = G|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_LUNGESTART8
}

states[S_PLAY_LUNGESTART8] = {
	sprite = SPR_LUNS,
	frame = H|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_LUNGESTART9
}

states[S_PLAY_LUNGESTART9] = {
	sprite = SPR_LUNS,
	frame = I|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_LUNGESTART10
}

states[S_PLAY_LUNGESTART10] = {
	sprite = SPR_LUNS,
	frame = J|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_LUNGELOOP
}

states[S_PLAY_LUNGELOOP] = {
	sprite = SPR_PLAY,
	frame = SPR2_LUNL,
	tics = 2,
	nextstate = S_PLAY_LUNGELOOP
}

addHook("JumpSpecial", function(p)
	if p.grabbing
	and P_IsObjectOnGround(p.mo)
	and not (p.pflags & PF_JUMPDOWN)
		P_SetObjectMomZ(p.mo, 10*FRACUNIT)
		S_StartSound(p.mo, sfx_jump)
		p.mo.state = S_PLAY_LUNGESTART1
		p.grabtics = 0
		p.grabbing = false
		p.pflags = $|PF_JUMPED
		return true
	end
end)

addHook("PlayerThink", function(p)
	if p.ppc
	and (p.pflags & PF_JUMPED)
	and (p.pflags & PF_SPINNING)
		p.pflags = $ & ~PF_SPINNING
	end
end)

freeslot("S_PLAY_PUNCH")

states[S_PLAY_PUNCH] = {
	sprite = SPR_PLAY,
	frame = SPR2_MLEE|FF_ANIMATE,
	var1 = 2,
	var2 = 2,
	tics = 8,
	nextstate = S_PLAY_RUN
}

//Should damage is my new best friend
addHook("MobjDamage", function(target, inflictor, source, damage, damagetype)
	if inflictor and inflictor.valid
	and inflictor.player and inflictor.player.valid
	and target and target.valid
	and (target.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR))
	and inflictor.player.grabbing
		inflictor.player.grabbing = false
		inflictor.player.grabtics = 0
		P_InstaThrust(inflictor, inflictor.angle, inflictor.player.speed)
		inflictor.state = S_PLAY_PUNCH
	end
end)

rawset(_G, "P_ResetGrab", function(p)
	p.grabbing = false
	p.grabtics = 0
end)

addHook("PlayerSpawn", function(p)
	P_ResetGrab(p)
	p.taunting = false
	p.tauntingtimer = 0
end)

addHook("PlayerThink", function(p)
	if not p.grabbing
	and p.mo.state == S_PLAY_PP_GRABDASH
		p.mo.state = S_PLAY_RUN
	end
end)

freeslot("S_PLAY_PP_SLIDE","SPR2_SLIP") --slip under deez nuts

states[S_PLAY_PP_SLIDE] = {
	sprite = SPR_PLAY,
	frame = SPR2_SLIP,
	tics = 1,
	nextstate = S_PLAY_PP_SLIDE
}

addHook("PlayerThink", function(p)
	local mo = p.mo
	
	if p.grabbing
	and p.cmd.forwardmove < -20
	and P_IsObjectOnGround(p.mo)
		p.mo.state = S_PLAY_PP_SLIDE
		Resettheshet(p)
	end
	if p.slidingtics == nil
		p.slidingtics = 0
	end
	if p.mo.state == S_PLAY_PP_SLIDE
		p.height = P_GetPlayerSpinHeight(p)
		p.slidingtics = $1+1
		p.pflags = $|PF_JUMPSTASIS
		p.powers[pw_nocontrol] = 150000000000000000000000000
		P_InstaThrust(p.mo, p.mo.angle, 42*FRACUNIT)
		p.machcounter = 0*FRACUNIT
	elseif p.ppc
	and p.mo.state ~= S_PLAY_PP_SLIDE
		p.height = skins[p.mo.skin].height
	end
	if p.slidingtics == 26
	and p.cmd.forwardmove > -20
		p.machcounter = 10*FRACUNIT
		p.mo.state = S_PLAY_ROLLGETUP
		p.powers[pw_nocontrol] = 0
		p.slidingtics = 0
		p.pflags = $ & ~PF_JUMPSTASIS
	end
	if (P_PlayerInPain(p) or p.playerstate == PST_DEAD or p.powers[pw_carry])
		p.slidingtics = 0
		p.powers[pw_nocontrol] = 0
	end
end)

freeslot("S_PLAY_GRABBUMP","SPR2_GRBB","sfx_bump")
sfxinfo[sfx_bump].caption = "Bumped on a wall"

states[S_PLAY_GRABBUMP] = {
	sprite = SPR_PLAY,
	frame = SPR2_GRBB,
	tics = 1,
	nextstate = S_PLAY_GRABBUMP
}

addHook("MobjMoveBlocked", function(mo)
	if mo.player and mo.player.valid
	and mo.player.grabbing
	and P_IsObjectOnGround(mo)
		mo.player.grabbing = false
		mo.player.grabtics = 0
		P_SetObjectMomZ(mo, 4*FRACUNIT)
		mo.state = S_PLAY_GRABBUMP
		S_StartSound(mo, sfx_bump)
	end
end, MT_PLAYER)

freeslot("S_PLAY_GRABAIRCANCEL")

states[S_PLAY_GRABAIRCANCEL] = {
	sprite = SPR_PLAY,
	frame = SPR2_GLID|FF_ANIMATE,
	tics = 20,
	var1 = 2,
	var2 = 2,
	nextstate = S_PLAY_FALL
}

addHook("ThinkFrame", do
	for p in players.iterate
		if p.grabbing
		and not P_IsObjectOnGround(p.mo)
		and p.cmd.forwardmove < -20
			p.grabbing = false
			p.grabtics = 0
			p.mo.state = S_PLAY_GRABAIRCANCEL
			P_InstaThrust(p.mo, p.mo.angle, 9*FRACUNIT)
		end
	end
end)