-- This whole mod is reusable, go ahead and do what you want.

-- MOMENTUM --

local debug = 0

addHook('ThinkFrame', do
	for player in players.iterate do
		if player.mo and player.mo.scale and player.mo.friction and player.mo.movefactor then
			local pmo = player.mo
			//Create history
			if player.waterlast == nil then
				player.waterlast = false
				player.dashlast = false
				player.realfriction = pmo.friction
			end
			local skin = skins[pmo.skin]
			
			//Stat adjust
			if player.charability2 == CA2_SPINDASH then
				player.mindash = skin.mindash * 3/2
			end
			local water = 1+(pmo.eflags&MFE_UNDERWATER)/MFE_UNDERWATER //Water factor for momentum halving
			local grounded = P_IsObjectOnGround(pmo)
			local nmom = skin.normalspeed //Skin normalspeed, the integral component
			//Dashmode overrides skin normalspeed
			if player.dashmode >= 3*TICRATE then
				nmom = player.normalspeed
			end
			
			local scale = pmo.scale //Normalspeed calculations are affected by scale
			local friction = FixedDiv(pmo.friction,pmo.movefactor) //Reversing friction is required for sustaining ground momentum
			local pmom = FixedDiv(FixedHypot(player.rmomx,player.rmomy),scale) //Current speed, scaled for normalspeed calculations
			local pwup = (player.powers[pw_sneakers]) or (player.powers[pw_super]) //Speed-ups multiply max allowed speed by 5/3
			local momangle = R_PointToAngle2(0,0,player.rmomx,player.rmomy) //Used for angling new momentum in ability cases
			//Adjust current speed reading for calculations with pwup status
			if pwup then
				pmom = $*3/5
			end
			local mom = FixedHypot(pmo.momx,pmo.momy)

						
			
			/////////
			//General momentum scaling
			
			//Do momentum
			if grounded then
				//The amount of momentum to sustain
				local sustain = FixedDiv(pmom*water,friction)
-- 				if pmom > player.normalspeed then
					player.normalspeed = max(nmom,sustain)
-- 				end
				if (player.mo.eflags & MFE_UNDERWATER)
					if player.speed > skin.normalspeed/2
						if player.cmd.forwardmove != 0 or player.cmd.sidemove != 0 then
							player.mo.friction = 235*FRACUNIT/256
						else
							player.mo.friction = 29*FRACUNIT/32
						end
					end
				end
			elseif not(player.dashmode) then //Dashmode overrides normalspeed in the air
				if player.normalspeed <= player.speed then
					player.normalspeed = skin.normalspeed
				else
					player.normalspeed = player.speed
				end
			end
			
			//////
			//Knuckles momentum renewal
			if player.charability == CA_GLIDEANDCLIMB then
				//Create glide history
				if player.glidelast == nil then
					player.glidelast = 0
				end
				local gliding = player.pflags&PF_GLIDING
				local thokked = player.pflags&PF_THOKKED
				local exitglide = (player.glidelast == 1 and not(gliding) and thokked)
				local landglide = (player.glidelast == 2 and not(gliding|thokked))
				//Restore glide momentum after deactivation
				if exitglide or landglide then
					pmo.momx = FixedMul(P_ReturnThrustX(nil,momangle,pmom),scale)
					pmo.momy = FixedMul(P_ReturnThrustY(nil,momangle,pmom),scale)
				end
				//Update glide history
				if gliding then
					player.glidelast = 1 //Gliding
				elseif exitglide then
					player.glidelast = 2 //Falling from glide
				elseif not(gliding|thokked) then
					player.glidelast = 0 //Not in glide state
				end
			end
			
			//////
			//Fang momentum renewal
			if player.charability == CA_BOUNCE then
				//Create bounce history
				if player.bouncelast == nil then
					player.bouncelast = false
				end
				if player.pflags&PF_BOUNCING and not(player.bouncelast) //Activate bounce
					or (not(player.pflags&PF_BOUNCING) and player.pflags&PF_THOKKED and player.bouncelast) //Deactivate bounce
					//Undo the momentum cut from bounce activation/deactivation
					pmo.momx = FixedMul(P_ReturnThrustX(nil,momangle,pmom),scale)
					pmo.momy = FixedMul(P_ReturnThrustY(nil,momangle,pmom),scale)
					pmo.momz = $*2
				end
				//Update bounce history
				player.bouncelast = (player.pflags&PF_BOUNCING > 0)
			end
			
			//Update history
			player.waterlast = (pmo.eflags&MFE_UNDERWATER > 0)
			player.dashlast = (player.pflags&PF_STARTDASH > 0)
			
			//DEBUG//
			if debug then
				print("momz " + pmo.momz/FRACUNIT)
				print("actionspd   " + player.actionspd/FRACUNIT)
				print("pmom        " + pmom/FRACUNIT)
				print("speed " + player.speed/FRACUNIT)
				print("normalspeed " + player.normalspeed/FRACUNIT)
			end
		end
	end
end)

-- SPRING AIR LOCK --

local sprung = 0
local springtimer = 0

addHook('ThinkFrame', do
	for player in players.iterate do
		local skin = skins[player.mo.skin]
		if player.mo.eflags & MFE_SPRUNG then
			sprung = 1
			springtimer = 15
		elseif P_IsObjectOnGround(player.mo) then
			sprung = 0
			springtimer = 0
		end
		if sprung == 1 and springtimer ~= 0
			player.acceleration = 0
			player.accelstart = 0
			springtimer = $ - 1
		else
			-- Increased air control
			if not P_IsObjectOnGround(player.mo) then
				player.acceleration = skin.acceleration*2
				player.accelstart = skin.accelstart*2
			else
				player.acceleration = skin.acceleration
				player.accelstart = skin.accelstart
			end
		end
	end
end)