local function thestatesyoucantfuckingdivein(p)
	if p.mo.state == S_PLAY_PP_SUPERJUMP
	or p.mo.state == S_PLAY_SHOULDERBASHSTART
	or p.taunting
	or p.grabbing
	or p.kungfu
	or p.mo.state == S_PLAY_PP_DIVE
	or p.mo.state == S_PLAY_CELHIT
	or p.superpp
	or p.bodyslam
	or p.bodyslamstart
	or p.assonfire
	or p.superjumpcharge
	or p.redirecttimer > 0
		return true
	else
		return false
	end
end

addHook("PlayerThink", function(p)
	if not P_IsObjectOnGround(p.mo)
	and p.ppc
	and not thestatesyoucantfuckingdivein(p)
	and p.c2tics == 1
	and p.playerstate == PST_LIVE
	and not P_PlayerInPain(p)
	and not p.powers[pw_carry]
	and not P_UpperCutAnimation(p)
	and not p.cantgrab
		P_Thrust(p.mo, p.mo.angle, 10*FRACUNIT)
		P_SetObjectMomZ(p.mo, -32*FRACUNIT)
		p.mo.state = S_PLAY_PP_DIVE
		if (p.pflags & PF_SPINNING)
			p.pflags = $ & ~PF_SPINNING
		end
	end
end)

freeslot("S_PLAY_DIVECANCEL","S_PLAY_DIVECANCELLAND","SPR2_DCLN")

states[S_PLAY_DIVECANCEL] = {
	sprite = SPR_PLAY,
	frame = SPR2_NATK,
	tics = 2,
	nextstate = S_PLAY_DIVECANCEL
}

states[S_PLAY_DIVECANCELLAND] = {
	sprite = SPR_PLAY,
	frame = SPR2_DCLN|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_DIVECANCELLAND
}

addHook("ThinkFrame", do
	for p in players.iterate
		if p.mo and p.mo.valid
		and not p.divecancel
			p.divecancelspeed = -5*FRACUNIT
		end
		if p.divecancel
			p.divecancelspeed = $ - FRACUNIT
		end
	end
end)

addHook("JumpSpecial", function(p)
	if p.mo and p.mo.valid
	and p.ppc
	and p.mo.state == S_PLAY_PP_DIVE
	and not (p.pflags & PF_JUMPDOWN)
		p.pflags = $ & ~PF_JUMPED
		P_SetObjectMomZ(p.mo, 10*FRACUNIT)
		S_StartSound(p.mo, sfx_bodys)
		p.divecancel = true
		p.mo.momx = $1/2
		p.mo.momy = $1/2
	end
end)

local function stuff(p)
	local ghost = P_SpawnGhostMobj(p.mo)
	ghost.fuse = 3
	if not S_SoundPlaying(p.mo, sfx_body)
		S_StartSound(p.mo, sfx_body)
	end
	if p.mo.state ~= S_PLAY_DIVECANCEL
		p.mo.state = S_PLAY_DIVECANCEL
	end
end

local function spring(p)
	if (p.mo.eflags & MFE_SPRUNG)
		p.divecancel = false
		S_StartSound(p.mo, sfx_sprong)
		p.mo.state = S_PLAY_SPRING
		p.mo.momz = $*5/4
	end
end

local function goo(p)
	if (p.mo.eflags & MFE_GOOWATER or p.powers[pw_carry] or P_PlayerInPain(p) or p.playerstate == PST_DEAD)
	and p.divecancel
		p.divecancel = false
		p.divecancelland = false
		p.mo.state = S_PLAY_PP_ROLLIN
	end
end

local function CheckAndCrumble(mo, sec)
  for fof in sec.ffloors()
    if not (fof.flags & FF_EXISTS) continue end -- Does it exist?
    if not (fof.flags & FF_BUSTUP) continue end -- Is it bustable?
    
    if mo.z + mo.height < fof.bottomheight continue end -- Are we too low?
    if mo.z > fof.topheight continue end -- Are we too high?

    -- Check for whatever else you may want to    

    EV_CrumbleChain(fof) -- Crumble
  end
end

local function setstates(p)
	if p.mo.state ~= S_PLAY_DIVECANCELLAND
	and p.mo.frame ~= E
		p.mo.state = S_PLAY_DIVECANCELLAND
	end
end

addHook("ThinkFrame", do
	for p in players.iterate
		if p.divecancel == nil
			p.divecancel = false
		end
		if p.divecancelland == nil
			p.divecancelland = false
		end
		if p.divecancel
			P_SetObjectMomZ(p.mo, p.divecancelspeed)
			stuff(p)
			spring(p)
			goo(p)
		end
		if p.divecancel
		and (P_IsObjectOnGround(p.mo) or p.mo.eflags & MFE_JUSTHITFLOOR)
			S_StartSound(p.mo, sfx_bonk)
			p.divecancelland = true
		end
		if p.divecancelland
			setstates(p)
			p.pflags = ($|PF_STASIS|PF_JUMPSTASIS)
			P_InstaThrust(p.mo, p.mo.angle, 0*FRACUNIT)
			p.divecancel = false
			CheckAndCrumble(p.mo, p.mo.subsector.sector)
		end
		if p.divecancelland
		and p.mo.frame == E
			p.divecancelland = false
			p.pflags = ($ & ~PF_STASIS|PF_JUMPSTASIS)
			p.mo.state = S_PLAY_STND
		end
	end
end)