I am using A* pathfinding for an AI because the Roblox Pathfinding algorithm doesn't meet my needs, but it seems to keep looping through the starting part. It doesn't move on to any of the other parts in the open list, and parts that are ALREADY in the open list are simply re-added as if they are new parts. Any help is appreciated!

Code:

local module = {}

function module.FindPath(Map, BeginModel, EndModel)
	
	local Start = BeginModel.PrimaryPart	
	local Finish = EndModel.PrimaryPart	
	
	local Closed = {}
	local Open = {Start}	
	
	Start.BrickColor = BrickColor.White()	
	Finish.BrickColor = BrickColor.White()
	
	if not Start:FindFirstChild("g") and not Start:FindFirstChild("h") and not Start:FindFirstChild("f") then local g, h, f = Instance.new("NumberValue", Start), Instance.new("NumberValue", Start), Instance.new("NumberValue", Start) g.Name, h.Name, f.Name = "g", "h", "f"	end
	Start.g.Name, Start.h.Name, Start.f.Name = "g", "h", "f"	
	
	wait()	
	
	Start.g.Value = 0 -- Steps from the start
	Start.h.Value = CalculateHeuristic(Start, Finish, 1) -- Avg. Distance from end
	Start.f.Value = Start.g.Value + Start.h.Value -- Total
	
	wait()	
	
	 while #Open > 0 do	
		
		--print("open: "..tostring((unpack(Open))))
		
        local CurrentSearch = OpenWLeastF(Open)

		CurrentSearch.BrickColor = BrickColor.Blue()

        if CurrentSearch == Finish then
			print("done!")
            return print("done") -- PUT CODE FOR GENERATING PATH HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 7u8u9287654gf298654fg296435gt24 <<-------
    	end

		table.insert(Closed, CurrentSearch) -- Adds to closed list, but CurrentSearch is still NOT NIL. It is simply in the CLOSED LIST.
		Open[CurrentSearch] = nil
	
        for _, Neighbor in pairs(GetNeighboringParts(CurrentSearch)) do 
	
            if not Closed[Neighbor] and not Open[Neighbor] then
	
				if not Neighbor:FindFirstChild("g") and not Neighbor:FindFirstChild("h") and not Neighbor:FindFirstChild("f") then local g, h, f = Instance.new("NumberValue", Neighbor), Instance.new("NumberValue", Neighbor), Instance.new("NumberValue", Neighbor) g.Name, h.Name, f.Name = "g", "h", "f"	end
				
                Neighbor.g.Value = CurrentSearch.g.Value + GetMagnitude(CurrentSearch, Neighbor)
                Neighbor.h.Value = CalculateHeuristic(Neighbor, Finish, 1)
                Neighbor.f.Value = Neighbor.g.Value + Neighbor.h.Value 

                table.insert(Open, Neighbor)
				print(unpack(Open))
            end
		end

	 wait(1)
	
	 end
	
end

function GetNeighboringParts(Part)
	local Neighbors = {}
	
	local pseudoPart = Part:Clone()
	pseudoPart.Parent = Part
	pseudoPart.Position = Part.Position
	pseudoPart.Size = Part.Size + Vector3.new(1,0,1)
	
	for _, obj in pairs (pseudoPart:GetTouchingParts()) do
		if Neighbors[obj] == nil and obj ~= Part then
			table.insert(Neighbors, obj)
		end
	end
	
	pseudoPart:Destroy()
	
	return Neighbors
end

function GetMagnitude(Part2, Part1)
	local Mag = (Part2.Position - Part1.Position).Magnitude
	return Mag
end

function OpenWLeastF(Open, CurrentNode)
	
	local Best = CurrentNode
	
	for i, node in pairs (Open) do
		if node ~= nil then
			local f = Open[i].f.Value
			if not Best or f < Best.f.Value then -- Best.f.value is the f value within the part that is currently Best.
				Best = node
			end
		end
	end	
	
	print(Best.f.Value)
	return Best -- Returns a part (keep in mind that returning the Best.Parent would return the model, if I want to in the future!)
	
end

function CalculateHeuristic(Node, End, MvmtCost)
	local movement_cost = MvmtCost or 1 		
	return movement_cost*math.sqrt((Node.Position.x-End.Position.x)^2 + (Node.Position.y-End.Position.y)^2)	
end


return module