-- LibreBoost, by ffoxD. Reusable content, use as long as you credit.
-- Credit to MARIOMARIO13531, and to everyone in the Discord server that helped me.
local function LibreBoost(player)
    -- Prevents the code from running in NiGHTs special stages.
	if (maptol & TOL_NIGHTS) then
		return
	end
	if player.mo.skin == "frontiersclassic" and player.mo.valid
		-- Lets the player boost.
		if not (player.pflags & PF_STASIS)
		and not (player.pflags & PF_FULLSTASIS)
		and not (player.pflags & PF_STARTDASH)
		and not (player.pflags & PF_FINISHED)
		and	player.playerstate ~= PST_DEAD
		and player.powers[pw_carry] == CR_NONE
		and not P_PlayerInPain(player)then
			if not (player.cmd.buttons & player.boostbutton)
				player.canboost = true
			end
		else
			player.canboost = false
		end
		if player.canboost == nil then
			player.canboost = true
		end
		-- Tells the game when the player shall boost, and whenever not.
		if (player.cmd.buttons & player.boostbutton)
			and player.canboost
			player.boosting = true
		else
			player.boosting = false
		end
		-- Determines how fast shall the player boost.
		player.boostspeed = 4 * player.normalspeed / 3
		-- Stores the player's speed angle.
		if player.speed > player.normalspeed then
			player.momangle2 = R_PointToAngle2(0,0,player.mo.momx,player.mo.momy)
		else
			player.momangle2 = player.mo.angle
		end
		-- What happens if the player boosts.
		if player.boosting then
			local playerfrbo = P_SpawnMobjFromMobj(player.mo, 0, 0, 0, MT_FRONTIERSBOOST)
			playerfrbo.color = SKINCOLOR_WHITE
			playerfrbo.angle = player.cmd.angleturn << 16 + R_PointToAngle2(0, 0, player.cmd.forwardmove*FRACUNIT, -player.cmd.sidemove*FRACUNIT) + ANGLE_90
			playerfrbo.scale = player.mo.scale
			playerfrbo.destscale = player.mo.scale
				if not player.cmd.forwardmove then
				player.cmd.forwardmove = 50 --Intentionally not in PreThinkFrame
			end
			player.drawangle = player.momangle2
			player.charflags = $|SF_NOSKID|SF_RUNONWATER|SF_CANBUSTWALLS
			if player.mo.state == S_PLAY_STND
				or player.mo.state == S_PLAY_WALK
				or player.mo.state == S_PLAY_WAIT
				or player.mo.state == S_PLAY_EDGE then
				player.mo.state = S_PLAY_RUN
			end
			if player.speed < (player.boostspeed) then
				P_Thrust(player.mo, player.momangle2, player.boostspeed - player.speed)
			end
		else -- What happens if the player isn't boosting. Mostly resetting values.
			if not (skins[player.mo.skin].flags & SF_NOSKID) then
				player.charflags = $ & ~SF_NOSKID
			end
			if not (skins[player.mo.skin].flags & SF_RUNONWATER) then
				player.charflags = $ & ~SF_RUNONWATER
			end
			if not (skins[player.mo.skin].flags & SF_CANBUSTWALLS ) then
				player.charflags = $ & ~SF_CANBUSTWALLS
			end
			player.hasnomomentum = true -- Prevents XMomentum from preserving your speed.
		end
	end
end

addHook("PlayerThink", LibreBoost)

addHook("MobjMoveBlocked", function(mo) -- You shall not boost if stopped by walls.
    local player = mo.player
    player.canboost = false
	player.boosting = false
end, MT_PLAYER)