local function P_RingNearby(player) -- Is a ring in range?
    local closest
	closest = NULL

	for mo in mobjs.iterate()

		if (mo.health <= 0) -- Not a valid ring
			continue
        end

		if not (mo.type == MT_RING or mo.type == MT_COIN)
			continue
        end

		if (P_AproxDistance(P_AproxDistance(player.mo.x-mo.x, player.mo.y-mo.y),
			player.mo.z-mo.z) > 192*FRACUNIT) -- Out of range
			continue
        end

		if not P_CheckSight(player.mo, mo) -- Out of sight
			continue
        end

		if (closest and P_AproxDistance(P_AproxDistance(player.mo.x-mo.x, player.mo.y-mo.y),
			player.mo.z-mo.z) > P_AproxDistance(P_AproxDistance(player.mo.x-closest.x,
			player.mo.y-closest.y), player.mo.z-closest.z))
			continue
        end

		-- Found a target
		closest = mo
    end

	if closest then
		return true
    end

	return false
end

local function P_LightDash(source, enemy) -- Home in on your target

	if not source.tracer
		return -- Nothing to home in on!
    end

	-- adjust direction
	local dest = source.tracer

	if not dest then
		return
    end

	-- change angle
	source.angle = R_PointToAngle2(source.x, source.y, enemy.x, enemy.y)

	-- change slope
	local dist = P_AproxDistance(P_AproxDistance(dest.x - source.x, dest.y - source.y), dest.z - source.z);

	if dist < 1
		dist = 1
    end

	source.momx = FixedMul(FixedDiv(dest.x - source.x, dist), (60*FRACUNIT))
	source.momy = FixedMul(FixedDiv(dest.y - source.y, dist), (60*FRACUNIT))
	source.momz = FixedMul(FixedDiv(dest.z - source.z, dist), (60*FRACUNIT))
end

local function P_LookForRings(player)
    local found
    player.mo.target = NULL
    player.mo.tracer = NULL

	for mo in mobjs.iterate()

		if (mo.health <= 0) then -- Not a valid ring
			continue
        end

		if not (mo.type == MT_RING or mo.type == MT_COIN)
			continue
        end

		if (P_AproxDistance(P_AproxDistance(player.mo.x-mo.x, player.mo.y-mo.y),
			player.mo.z-mo.z) > 192*FRACUNIT) -- Out of range
			continue
        end

		if not P_CheckSight(player.mo, mo) -- Out of sight
			continue
        end

		if (player.mo.target and P_AproxDistance(P_AproxDistance(player.mo.x-mo.x,
			player.mo.y-mo.y), player.mo.z-mo.z) >
			P_AproxDistance(P_AproxDistance(player.mo.x-player.mo.target.x,
			player.mo.y-player.mo.target.y), player.mo.z-player.mo.target.z))
			continue
        end

		-- Found a target
		found = true
		player.mo.target = mo
		player.mo.tracer = mo
	end

	if found then
		P_ResetPlayer(player)
		player.mo.state = S_PLAY_GLIDE
		P_ResetScore(player)
		P_LightDash(player.mo, player.mo.tracer)
		return
    end
	player.mo.momx = FixedDiv(player.mo.momx,2*FRACUNIT)
	player.mo.momy = FixedDiv(player.mo.momy,2*FRACUNIT)
	player.mo.momz = FixedDiv(player.mo.momz,2*FRACUNIT)
	player.lightdash = false
end

addHook("PlayerThink", function(player)
    if (P_RingNearby(player))
		player.lightdashallowed = true

		if (player.cmd.buttons & BT_ATTACK) and (player.mo and player.mo.skin == "frontiersclassic")
			if not player.attackdown
				player.lightdash = TICRATE;
				player.attackdown = true;
            end
		elseif not (player.cmd.buttons & BT_ATTACK)
			player.attackdown = false
        end
	else
		player.lightdashallowed = false
    end

	if player.lightdash
		P_LookForRings(player)
		player.powers[pw_flashing] = 2
    end
end)
