-- Spring Frontflip

-- Skin/Frame table
-- Hopefully covers all characters released on the MB as of May 18th 2020
-- Excludes characters that do not have a spin, i.e. Yoshi and Jason
if not(frontfliptable)
	rawset(_G, "frontfliptable", {})
end
-- frontfliptable["skinname"] = <uncurl frame>
frontfliptable["sonic"] = E
frontfliptable["tails"] = C
frontfliptable["knuckles"] = E
frontfliptable["amy"] = D
frontfliptable["fang"] = D
frontfliptable["metalsonic"] = E
frontfliptable["silver"] = E
frontfliptable["kirby"] = D
frontfliptable["dirk"] = E
--frontfliptable["eggman"] = D -- eggy no flippy
frontfliptable["altsonic"] = E
frontfliptable["spyro"] = E -- why do 2 characters have the same skinname???
frontfliptable["advancesonic"] = D
frontfliptable["modernsonic"] = B -- Forced into fall when close to ground
frontfliptable["mechasonic"] = C
frontfliptable["ssnmighty"] = C
frontfliptable["uglyknux"] = D
frontfliptable["ivory"] = D
frontfliptable["legacyhinote"] = D
frontfliptable["sms"] = D -- Forced into fall when close to ground
frontfliptable["frank"] = E
frontfliptable["flamethedragon"] = E
frontfliptable["xsonic"] = I
frontfliptable["earlessredo"] = D
frontfliptable["bowie"] = D
frontfliptable["fhms123311"] = E
frontfliptable["flarethelizard"] = E
frontfliptable["ass"] = E
frontfliptable["derp"] = C
frontfliptable["flare"] = D
frontfliptable["msonic"] = C
frontfliptable["ovaknux"] = E -- Doesnt spin?
frontfliptable["hardsonic"] = E
frontfliptable["steve"] = H
frontfliptable["earless"] = B
frontfliptable["ssnsonichd"] = D
frontfliptable["ssntails"] = D
frontfliptable["phknux"] = B
frontfliptable["earlysonic"] = D
frontfliptable["metson"] = D
frontfliptable["metalknux"] = D
frontfliptable["ray"] = D
frontfliptable["nochuckles"] = D
frontfliptable["HMS123311"] = D -- Doesnt spin?
frontfliptable["euph"] = D
frontfliptable["ssnsonic"] = D
frontfliptable["handdrawn"] = D


-- Spring Frontflip Command
local cv_sprflip = CV_RegisterVar({
	name = "spring_frontflip",
	defaultvalue = "On",
	flags = 0,
	PossibleValue = CV_OnOff
})

-- the MEAT
addHook("MobjThinker",function(mo)
	if not cv_sprflip.value return end
	if (mapheaderinfo[gamemap].typeoflevel == TOL_NIGHTS) return end
	
	-- Spintimer setup
	if mo.spintimer == nil
	or mo.eflags & MFE_JUSTHITFLOOR
		mo.spintimer = 0
		mo.springspin = 0
		mo.pleasefall = 0
	end
	
	-- Too low, no spin because you could hit your head :(
	-- Also noticed that it forces you out of it.
	if mo.z < (mo.floorz + (mo.height*2))
	and not (mo.player.panim == PA_ABILITY)
	and not (mo.player.panim == PA_ABILITY2)
		if mo.springspin == 1
			mo.springspin = 0
			mo.pleasefall = 1
			mo.state = S_PLAY_FALL
		end
		return -- If too low, dont go downstairs
	end
	
	-- If springy then spinny
	if cv_sprflip.value
	and mo.state == S_PLAY_SPRING
	and frontfliptable[mo.skin] -- If skin is supported
		mo.spintimer = 8
		mo.springspin = 0
		mo.pleasefall = 0
	end
	
	if mo.state == S_PLAY_FALL
		mo.springspin = 1
	end
	
	-- Set rolling once and not every tic LMAO could you imagine
	if mo.pleasefall == 0
	and mo.springspin == 1
	and mo.spintimer > 0
		mo.spintimer = $1-1
		if mo.state == S_PLAY_ROLL return end -- If already rolling then no roll agaion
		mo.state = S_PLAY_ROLL
	end
	
	-- Just in case???
	if mo.eflags & MFE_SPRUNG
		mo.state = S_PLAY_SPRING
		mo.pleasefall = 0
	end
	
	-- Flippy magic
	if mo.spintimer <= 0
	and mo.springspin == 1 -- Fall state, even without FallingAnimations
	and not P_IsObjectOnGround(mo)
	and not (mo.player.pflags & PF_JUMPED)
	and not (mo.player.pflags & PF_SPINNING)
	and not (mo.player.panim == PA_ABILITY)
	and not (mo.player.panim == PA_ABILITY2)
	and not (mo.state == S_PLAY_PAIN)
	and ((mo.momz*P_MobjFlip(mo))/FRACUNIT < -2) -- Keeping consistant with FallingAnimations cause it works with that too!
		if mo.frame == frontfliptable[mo.skin] -- If frame is the frontflipframe
			mo.springspin = 0
			mo.state = S_PLAY_FALL
		end
	end
end, MT_PLAYER)