freeslot("SPR2_BOLN","S_PLAY_BODYSLAMSTART1","S_PLAY_BODYSLAMSTART2","S_PLAY_BODYSLAMSTART3","S_PLAY_BODYSLAMSTART4","S_PLAY_BODYSLAMSTART5","S_PLAY_BODYSLAMSTART6","S_PLAY_BODYSLAMSTART7","SPR_BODS","S_PLAY_BODYSLAM","SPR2_BODL","S_PLAY_BODYLAND")

states[S_PLAY_BODYSLAMSTART1] = { 
	sprite = SPR_BODS,
	frame = A|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_BODYSLAMSTART2
}

states[S_PLAY_BODYSLAMSTART2] = { 
	sprite = SPR_BODS,
	frame = B|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_BODYSLAMSTART3
}

states[S_PLAY_BODYSLAMSTART3] = { 
	sprite = SPR_BODS,
	frame = C|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_BODYSLAMSTART4
}

states[S_PLAY_BODYSLAMSTART4] = { 
	sprite = SPR_BODS,
	frame = D|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_BODYSLAMSTART5
}

states[S_PLAY_BODYSLAMSTART5] = { 
	sprite = SPR_BODS,
	frame = E|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_BODYSLAMSTART6
}

states[S_PLAY_BODYSLAMSTART6] = { 
	sprite = SPR_BODS,
	frame = F|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_BODYSLAMSTART7
}

states[S_PLAY_BODYSLAMSTART7] = { 
	sprite = SPR_BODS,
	frame = G|FF_ANIMATE,
	tics = 2,
	nextstate = S_PLAY_BODYSLAM
}

states[S_PLAY_BODYSLAM] = { 
	sprite = SPR_PLAY,
	frame = SPR2_BODL,
	tics = 2,
	nextstate = S_PLAY_BODYSLAM
}

states[S_PLAY_BODYLAND] = { 
	sprite = SPR_PLAY,
	frame = SPR2_BOLN,
	tics = 2,
	nextstate = S_PLAY_BODYLAND
}

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

addHook("ThinkFrame", do
	for p in players.iterate
		if p.mo and p.mo.valid
		and not p.bodyslam
		and not p.bodyslamstart
			p.bodyslamspeed = -40*FRACUNIT
		end
		if p.bodyslam
			p.bodyslamspeed = $ - FRACUNIT
		end
	end
end)

freeslot("sfx_bodys","sfx_body")
sfxinfo[sfx_bodys].caption = "Body Slam Start"
sfxinfo[sfx_body].caption = "Body Slamming"

addHook("JumpSpecial", function(p)
	if p.mo.skin == "prpeppino"
	and (p.mo.state == S_PLAY_JUMP or p.mo.state == S_PLAY_SPRING or p.mo.state == S_PLAY_FALL or p.mo.state == S_PLAY_PP_MACHJUMP or p.mo.state == S_PLAY_MACH3JUMP1 or p.mo.state == S_PLAY_MACH3JUMP2 or p.mo.state == S_PLAY_MACH3JUMP3 or p.mo.state == S_PLAY_MACH3JUMP4 or p.mo.state == S_PLAY_MACH3JUMP5 or p.mo.state == S_PLAY_PP_MACH3 or p.mo.state == S_PLAY_JUMPSTART or p.mo.state == S_PLAY_PP_MACH4 or p.mo.state == S_PLAY_MACHJUMPSTART or p.mo.state == S_PLAY_WALLJUMPSTART or p.mo.state == S_PLAY_WALLJUMPLOOP or p.mo.state == S_PLAY_LUNGELOOP or p.mo.sprite == SPR_LUNS)
	and not P_IsObjectOnGround(p.mo)
	and not p.ptwallrun
	and not p.powers[pw_carry]
	and not p.assonfire
	and not (p.pflags & PF_JUMPDOWN)
		p.pflags = $ & ~PF_JUMPED
		P_SetObjectMomZ(p.mo, 10*FRACUNIT)
		S_StartSound(p.mo, sfx_bodys)
		p.mo.state = S_PLAY_BODYSLAMSTART1
		p.bodyslamstart = true
		p.mo.momx = $1/2
		p.mo.momy = $1/2
		p.machcounter = 0*FRACUNIT
		p.machspeed = 0
	end
end)

local function bodyslamanimation(p)
	if (p.mo.state == S_PLAY_BODYSLAMSTART1 or p.mo.state == S_PLAY_BODYSLAMSTART2 or p.mo.state == S_PLAY_BODYSLAMSTART3 or p.mo.state == S_PLAY_BODYSLAMSTART4 or p.mo.state == S_PLAY_BODYSLAMSTART5 or p.mo.state == S_PLAY_BODYSLAMSTART6 or p.mo.state == S_PLAY_BODYSLAMSTART7)
		return true
	else
		return false
	end
end

addHook("PlayerThink", function(p)
	if p.bodyslamstart == nil
		p.bodyslamstart = false
	end
	if p.bodyslamstart
	and not bodyslamanimation(p)
		p.bodyslamstart = false
		p.bodyslam = true
	end
end)

addHook("ThinkFrame", do
	for p in players.iterate
		if p.bodyslam
			local ghost = P_SpawnGhostMobj(p.mo)
			ghost.fuse = 3
			P_SetObjectMomZ(p.mo, p.bodyslamspeed)
			if not S_SoundPlaying(p.mo, sfx_body)
				S_StartSound(p.mo, sfx_body)
			end
		end
		if p.bodyslam
		and P_IsObjectOnGround(p.mo)
			p.mo.state = S_PLAY_BODYLAND
			CheckAndCrumble(p.mo, p.mo.subsector.sector)
			S_StartSound(p.mo, sfx_bonk)
			P_InstaThrust(p.mo, p.mo.angle, 0*FRACUNIT)
			if S_SoundPlaying(p.mo, sfx_body)
				S_StopSoundByID(p.mo, sfx_body)
			end
		end
	end
end)

addHook("PlayerThink", function(p)
	if p.bodylandtimer == nil
		p.bodylandtimer = 0
	end
	if p.mo.state == S_PLAY_BODYLAND
		p.pflags = $|PF_STASIS
		p.bodylandtimer = $1+1
		p.grabbing = false
		p.grabtics = 0
		p.pflags = $|PF_JUMPSTASIS
	end
	if p.bodylandtimer >= 1
		p.mo.state = S_PLAY_BODYLAND
		p.bodyslam = false
	end
	if p.bodylandtimer == 10
		p.mo.state = S_PLAY_STND
		p.bodylandtimer = 0
		p.pflags = $ & ~PF_JUMPSTASIS
		p.pflags = $ & ~PF_STASIS
	end
end)

addHook("PlayerThink", function(p)
	if (p.mo.eflags & MFE_GOOWATER or p.powers[pw_carry] or P_PlayerInPain(p) or p.playerstate == PST_DEAD)
	and p.bodyslam
		p.bodyslam = false
		p.mo.state = S_PLAY_PP_ROLLIN
	end
	if p.bodyslam
	and (p.mo.eflags & MFE_SPRUNG)
		p.bodyslam = false
		S_StartSound(p.mo, sfx_sprong)
		p.mo.state = S_PLAY_SPRING
		p.mo.momz = $*5/4
	end
	if not p.bodyslam
	and S_SoundPlaying(p.mo, sfx_body)
	and not p.divecancel
		S_StopSoundByID(p.mo, sfx_body)
	end
end)