local I={Vector3.new(1,0,0),Vector3.new(.707,0,.707),Vector3.new(0,0,1),Vector3.new(-0.707,0,.707),Vector3.new(-1,0,0),Vector3.new(-0.707,0,-0.707),Vector3.new(0,0,-1);Vector3.new(.707,0,-0.707)}local O=4 local o=12 local v=20 local s=5 local function Y(Y,c,V)assert(typeof(Y)=="\073\110\115\116\097\110\099\101"and Y:IsA("\080\108\097\121\101\114"),"\077\117\115\116 \102\101\101\100 \097 \080\108\097\121\101\114 \116\111 \102\105\110\100 \112\111\115\105\116\105\111\110 \097\116")assert(c==nil or typeof(c)=="\086\101\099\116\111\114\051","\077\117\115\116 \102\101\101\100 \116\104\101 \112\114\101\118\105\111\117\115 \112\111\115\105\116\105\111\110 \116\111 \102\105\110\100 \099\108\111\115\101\115\116 \109\097\116\099\104 \116\111")assert(V==nil or typeof(V)=="\073\110\115\116\097\110\099\101","\077\117\115\116 \102\101\101\100 \097\110 \073\110\115\116\097\110\099\101 \097\115 \105\103\110\111\114\101 \105\110\115\116\097\110\099\101 \105\102 \103\105\118\101\110")if not Y.Character then return end local e=Y.Character:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")local b=Y.Character:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")if not(e and b)then return end local U=e.Position-Vector3.new(0,b.HipHeight,0)local a={}for o=1,#I,1 do table.insert(a,U+I[o]*O)end if c then local I=Vector3.new(c.X,U.Y,c.Z)table.sort(a,function(O,o)return(O-I).Magnitude<(o-I).magnitude end)end for I=1,#a,1 do local O=workspace:FindPartOnRayWithIgnoreList(Ray.new(U,a[I]-U),{Y.Character;V})if not O then local O=Ray.new(a[I]+Vector3.new(0,o,0),Vector3.new(0,-v,0))local Y,c,e,b=workspace:FindPartOnRay(O,V)if Y and math.abs(c.Y-U.Y)<=s then return c end end end end return Y



local scanGrid = {
	Vector3.new(1,0,0),
	Vector3.new(.707,0,.707),
	Vector3.new(0,0,1),
	Vector3.new(-.707,0,.707),
	Vector3.new(-1,0,0),
	Vector3.new(-.707,0,-.707),
	Vector3.new(0,0,-1),
	Vector3.new(.707,0,-.707),
}

local scanRadius = 4
local scanHeight = 12
local scanDepth = 20
local scanMaxDiff = 5

local function findPosition(owner, previousPosition, ignoreInstance)
	
	assert(typeof(owner) == "Instance" and owner:IsA("Player"), "Must feed a Player to find position at")
	assert(previousPosition == nil or typeof(previousPosition) == "Vector3", "Must feed the previous position to find closest match to")
	assert(ignoreInstance == nil or typeof(ignoreInstance) == "Instance", "Must feed an Instance as ignore instance if given")
	
	if not owner.Character then return end
	local root = owner.Character:FindFirstChild("HumanoidRootPart")
	local hum = owner.Character:FindFirstChildOfClass("Humanoid")
	if not (root and hum) then return end
	
	local origin = root.Position - Vector3.new(0, hum.HipHeight, 0)
	
	local finalGrid = {}
	for i = 1, #scanGrid do
		table.insert(finalGrid, origin + scanGrid[i]*scanRadius)
	end
	if previousPosition then
		local offset = Vector3.new(previousPosition.X, origin.Y, previousPosition.Z)
		table.sort(finalGrid, function(a,b) return (a - offset).Magnitude < (b - offset).magnitude end)
	end
	
	for i = 1, #finalGrid do
		
		local blocked = workspace:FindPartOnRayWithIgnoreList(Ray.new(origin, finalGrid[i] - origin), {owner.Character, ignoreInstance})
		
		if not blocked then
			
			local ray = Ray.new(
				finalGrid[i] + Vector3.new(0, scanHeight, 0),
				Vector3.new(0, -scanDepth, 0)
			)
			
			local part, position, normal, material = workspace:FindPartOnRay(ray, ignoreInstance)
			
			if part and math.abs(position.Y - origin.Y) <= scanMaxDiff then
				return position
			end
			
		end
		
	end
	
end

return findPosition
