local function v(v,u,X)local x={}local Z local j if X~=nil then Z=X j=X else Z=UseDirectPath j=UseDirectPathForVehicle end x.Cancelled=false x.Started=false x.Finished=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116")x.PathFailed=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116")x.PathComputing=false x.PathComputed=false x.OriginalTargetPoint=v x.TargetPoint=v x.TargetSurfaceNormal=u x.DiedConn=nil x.SeatedConn=nil x.BlockedConn=nil x.TeleportedConn=nil x.CurrentPoint=0 x.HumanoidOffsetFromPath=ZERO_VECTOR3 x.CurrentWaypointPosition=nil x.CurrentWaypointPlaneNormal=ZERO_VECTOR3 x.CurrentWaypointPlaneDistance=0 x.CurrentWaypointNeedsJump=false x.CurrentHumanoidPosition=ZERO_VECTOR3 x.CurrentHumanoidVelocity=0 x.NextActionMoveDirection=ZERO_VECTOR3 x.NextActionJump=false x.Timeout=0 x.Humanoid=findPlayerHumanoid(Player)x.OriginPoint=nil x.AgentCanFollowPath=false x.DirectPath=false x.DirectPathRiseFirst=false local w=x.Humanoid and x.Humanoid.RootPart if w then x.OriginPoint=w.CFrame.p local v=2 local u=5 local X=true local N=x.Humanoid.SeatPart if N and N:IsA("\086\101\104\105\099\108\101\083\101\097\116")then local Z=N:FindFirstAncestorOfClass("\077\111\100\101\108")if Z then local w=Z.PrimaryPart Z.PrimaryPart=N if j then local w=Z:GetExtentsSize()v=(AgentSizeIncreaseFactor*.5)*math.sqrt(w.X*w.X+w.Z*w.Z)u=AgentSizeIncreaseFactor*w.Y X=false x.AgentCanFollowPath=true x.DirectPath=j end Z.PrimaryPart=w end else local j=(GetCharacter()):GetExtentsSize()v=(AgentSizeIncreaseFactor*.5)*math.sqrt(j.X*j.X+j.Z*j.Z)u=AgentSizeIncreaseFactor*j.Y X=x.Humanoid.JumpPower>0 x.AgentCanFollowPath=true x.DirectPath=Z x.DirectPathRiseFirst=x.Humanoid.Sit end x.pathResult=PathfindingService:CreatePath({AgentRadius=v,AgentHeight=u,AgentCanJump=X})end function x.Cleanup(v)if x.stopTraverseFunc then x.stopTraverseFunc()x.stopTraverseFunc=nil end if x.MoveToConn then x.MoveToConn:Disconnect()x.MoveToConn=nil end if x.BlockedConn then x.BlockedConn:Disconnect()x.BlockedConn=nil end if x.DiedConn then x.DiedConn:Disconnect()x.DiedConn=nil end if x.SeatedConn then x.SeatedConn:Disconnect()x.SeatedConn=nil end if x.TeleportedConn then x.TeleportedConn:Disconnect()x.TeleportedConn=nil end x.Started=false end function x.Cancel(v)x.Cancelled=true x:Cleanup()end function x.IsActive(v)return x.AgentCanFollowPath and(x.Started and not x.Cancelled)end function x.OnPathInterrupted(v)x.Cancelled=true x:OnPointReached(false)end function x.ComputePath(v)if x.OriginPoint then if x.PathComputed or x.PathComputing then return end x.PathComputing=true if x.AgentCanFollowPath then if x.DirectPath then x.pointList={PathWaypoint.new(x.OriginPoint,Enum.PathWaypointAction.Walk),PathWaypoint.new(x.TargetPoint,x.DirectPathRiseFirst and Enum.PathWaypointAction.Jump or Enum.PathWaypointAction.Walk)}x.PathComputed=true else x.pathResult:ComputeAsync(x.OriginPoint,x.TargetPoint)x.pointList=x.pathResult:GetWaypoints()x.BlockedConn=x.pathResult.Blocked:Connect(function(v)x:OnPathBlocked(v)end)x.PathComputed=x.pathResult.Status==Enum.PathStatus.Success end end x.PathComputing=false end end function x.IsValidPath(v)x:ComputePath()return x.PathComputed and x.AgentCanFollowPath end x.Recomputing=false function x.OnPathBlocked(u,v)local X=v>=x.CurrentPoint if not X or x.Recomputing then return end x.Recomputing=true if x.stopTraverseFunc then x.stopTraverseFunc()x.stopTraverseFunc=nil end x.OriginPoint=x.Humanoid.RootPart.CFrame.p x.pathResult:ComputeAsync(x.OriginPoint,x.TargetPoint)x.pointList=x.pathResult:GetWaypoints()if#x.pointList>0 then x.HumanoidOffsetFromPath=x.pointList[1].Position-x.OriginPoint end x.PathComputed=x.pathResult.Status==Enum.PathStatus.Success if ShowPath then x.stopTraverseFunc,x.setPointFunc=ClickToMoveDisplay.CreatePathDisplay(x.pointList)end if x.PathComputed then x.CurrentPoint=1 x:OnPointReached(true)else x.PathFailed:Fire()x:Cleanup()end x.Recomputing=false end function x.OnRenderStepped(u,v)if x.Started and not x.Cancelled then x.Timeout=x.Timeout+v if x.Timeout>UnreachableWaypointTimeout then x:OnPointReached(false)return end x.CurrentHumanoidPosition=x.Humanoid.RootPart.Position+x.HumanoidOffsetFromPath x.CurrentHumanoidVelocity=x.Humanoid.RootPart.Velocity while x.Started and x:IsCurrentWaypointReached()do x:OnPointReached(true)end if x.Started then x.NextActionMoveDirection=x.CurrentWaypointPosition-x.CurrentHumanoidPosition if x.NextActionMoveDirection.Magnitude>ALMOST_ZERO then x.NextActionMoveDirection=x.NextActionMoveDirection.Unit else x.NextActionMoveDirection=ZERO_VECTOR3 end if x.CurrentWaypointNeedsJump then x.NextActionJump=true x.CurrentWaypointNeedsJump=false else x.NextActionJump=false end end end end function x.IsCurrentWaypointReached(v)local u=false if x.CurrentWaypointPlaneNormal~=ZERO_VECTOR3 then local v=x.CurrentWaypointPlaneNormal:Dot(x.CurrentHumanoidPosition)-x.CurrentWaypointPlaneDistance local X=-x.CurrentWaypointPlaneNormal:Dot(x.CurrentHumanoidVelocity)local Z=math.max(1.0,.0625*X)u=v<Z else u=true end if u then x.CurrentWaypointPosition=nil x.CurrentWaypointPlaneNormal=ZERO_VECTOR3 x.CurrentWaypointPlaneDistance=0 end return u end function x.OnPointReached(u,v)if v and not x.Cancelled then if x.setPointFunc then x.setPointFunc(x.CurrentPoint)end local v=x.CurrentPoint+1 if v>#x.pointList then if x.stopTraverseFunc then x.stopTraverseFunc()end x.Finished:Fire()x:Cleanup()else local u=x.pointList[x.CurrentPoint]local X=x.pointList[v]local Z=x.Humanoid:GetState()local j=Z==Enum.HumanoidStateType.FallingDown or Z==Enum.HumanoidStateType.Freefall or Z==Enum.HumanoidStateType.Jumping if j then local v=X.Action==Enum.PathWaypointAction.Jump if not v and x.CurrentPoint>1 then local Z=x.pointList[x.CurrentPoint-1]local j=u.Position-Z.Position local w=X.Position-u.Position local N=(Vector2.new(j.x,j.z)).Unit local F=(Vector2.new(w.x,w.z)).Unit local R=.996 v=N:Dot(F)<R end if v then x.Humanoid.FreeFalling:Wait()wait(.1)end end if FFlagUserNavigationClickToMoveSkipPassedWaypoints then x:MoveToNextWayPoint(u,X,v)else if x.setPointFunc then x.setPointFunc(v)end if X.Action==Enum.PathWaypointAction.Jump then x.Humanoid.Jump=true end x.Humanoid:MoveTo(X.Position)x.CurrentPoint=v end end else x.PathFailed:Fire()x:Cleanup()end end function x.MoveToNextWayPoint(Z,v,u,X)x.CurrentWaypointPlaneNormal=v.Position-u.Position x.CurrentWaypointPlaneNormal=Vector3.new(x.CurrentWaypointPlaneNormal.X,0,x.CurrentWaypointPlaneNormal.Z)if x.CurrentWaypointPlaneNormal.Magnitude>ALMOST_ZERO then x.CurrentWaypointPlaneNormal=x.CurrentWaypointPlaneNormal.Unit x.CurrentWaypointPlaneDistance=x.CurrentWaypointPlaneNormal:Dot(u.Position)else x.CurrentWaypointPlaneNormal=ZERO_VECTOR3 x.CurrentWaypointPlaneDistance=0 end x.CurrentWaypointNeedsJump=u.Action==Enum.PathWaypointAction.Jump x.CurrentWaypointPosition=u.Position x.CurrentPoint=X x.Timeout=0 end function x.Start(u,v)if not x.AgentCanFollowPath then x.PathFailed:Fire()return end if x.Started then return end x.Started=true ClickToMoveDisplay.CancelFailureAnimation()if ShowPath then if v==nil or v then x.stopTraverseFunc,x.setPointFunc=ClickToMoveDisplay.CreatePathDisplay(x.pointList,x.OriginalTargetPoint)end end if#x.pointList>0 then x.HumanoidOffsetFromPath=Vector3.new(0,x.pointList[1].Position.Y-x.OriginPoint.Y,0)x.CurrentHumanoidPosition=x.Humanoid.RootPart.Position+x.HumanoidOffsetFromPath x.CurrentHumanoidVelocity=x.Humanoid.RootPart.Velocity x.SeatedConn=x.Humanoid.Seated:Connect(function(v,u)x:OnPathInterrupted()end)x.DiedConn=x.Humanoid.Died:Connect(function()x:OnPathInterrupted()end)x.TeleportedConn=(x.Humanoid.RootPart:GetPropertyChangedSignal("\067\070\114\097\109\101")):Connect(function()x:OnPathInterrupted()end)x.CurrentPoint=1 x:OnPointReached(true)else x.PathFailed:Fire()if x.stopTraverseFunc then x.stopTraverseFunc()end end end local N=x.TargetPoint+x.TargetSurfaceNormal*1.5 local F=Ray.new(N,Vector3.new(0,-1,0)*50)local R,k=Workspace:FindPartOnRayWithIgnoreList(F,getIgnoreList())if R then x.TargetPoint=k end x:ComputePath()return x end


local function Pather(endPoint, surfaceNormal, overrideUseDirectPath)
	local this = {}

	local directPathForHumanoid
	local directPathForVehicle
	if overrideUseDirectPath ~= nil then
		directPathForHumanoid = overrideUseDirectPath
		directPathForVehicle = overrideUseDirectPath
	else
		directPathForHumanoid = UseDirectPath
		directPathForVehicle = UseDirectPathForVehicle
	end

	this.Cancelled = false
	this.Started = false

	this.Finished = Instance.new("BindableEvent")
	this.PathFailed = Instance.new("BindableEvent")

	this.PathComputing = false
	this.PathComputed = false

	this.OriginalTargetPoint = endPoint
	this.TargetPoint = endPoint
	this.TargetSurfaceNormal = surfaceNormal

	this.DiedConn = nil
	this.SeatedConn = nil
	this.BlockedConn = nil
	this.TeleportedConn = nil

	this.CurrentPoint = 0

	this.HumanoidOffsetFromPath = ZERO_VECTOR3

	this.CurrentWaypointPosition = nil
	this.CurrentWaypointPlaneNormal = ZERO_VECTOR3
	this.CurrentWaypointPlaneDistance = 0
	this.CurrentWaypointNeedsJump = false;

	this.CurrentHumanoidPosition = ZERO_VECTOR3
	this.CurrentHumanoidVelocity = 0

	this.NextActionMoveDirection = ZERO_VECTOR3
	this.NextActionJump = false

	this.Timeout = 0

	this.Humanoid = findPlayerHumanoid(Player)
	this.OriginPoint = nil
	this.AgentCanFollowPath = false
	this.DirectPath = false
	this.DirectPathRiseFirst = false

	local rootPart = this.Humanoid and this.Humanoid.RootPart
	if rootPart then
		-- Setup origin
		this.OriginPoint = rootPart.CFrame.p

		-- Setup agent
		local agentRadius = 2
		local agentHeight = 5
		local agentCanJump = true

		local seat = this.Humanoid.SeatPart
		if seat and seat:IsA("VehicleSeat") then
			-- Humanoid is seated on a vehicle
			local vehicle = seat:FindFirstAncestorOfClass("Model")
			if vehicle then
				-- Make sure the PrimaryPart is set to the vehicle seat while we compute the extends.
				local tempPrimaryPart = vehicle.PrimaryPart
				vehicle.PrimaryPart = seat

				-- For now, only direct path
				if directPathForVehicle then
					local extents = vehicle:GetExtentsSize()
					agentRadius = AgentSizeIncreaseFactor * 0.5 * math.sqrt(extents.X * extents.X + extents.Z * extents.Z)
					agentHeight = AgentSizeIncreaseFactor * extents.Y
					agentCanJump = false
					this.AgentCanFollowPath = true
					this.DirectPath = directPathForVehicle
				end

				-- Reset PrimaryPart
				vehicle.PrimaryPart = tempPrimaryPart
			end
		else
			local extents = GetCharacter():GetExtentsSize()
			agentRadius = AgentSizeIncreaseFactor * 0.5 * math.sqrt(extents.X * extents.X + extents.Z * extents.Z)
			agentHeight = AgentSizeIncreaseFactor * extents.Y
			agentCanJump = (this.Humanoid.JumpPower > 0)
			this.AgentCanFollowPath = true
			this.DirectPath = directPathForHumanoid
			this.DirectPathRiseFirst = this.Humanoid.Sit
		end

		-- Build path object
		this.pathResult = PathfindingService:CreatePath({AgentRadius = agentRadius, AgentHeight = agentHeight, AgentCanJump = agentCanJump})
	end

	function this:Cleanup()
		if this.stopTraverseFunc then
			this.stopTraverseFunc()
			this.stopTraverseFunc = nil
		end

		if this.MoveToConn then
			this.MoveToConn:Disconnect()
			this.MoveToConn = nil
		end

		if this.BlockedConn then
			this.BlockedConn:Disconnect()
			this.BlockedConn = nil
		end

		if this.DiedConn then
			this.DiedConn:Disconnect()
			this.DiedConn = nil
		end

		if this.SeatedConn then
			this.SeatedConn:Disconnect()
			this.SeatedConn = nil
		end

		if this.TeleportedConn then
			this.TeleportedConn:Disconnect()
			this.TeleportedConn = nil
		end

		this.Started = false
	end

	function this:Cancel()
		this.Cancelled = true
		this:Cleanup()
	end

	function this:IsActive()
		return this.AgentCanFollowPath and this.Started and not this.Cancelled
	end

	function this:OnPathInterrupted()
		-- Stop moving
		this.Cancelled = true
		this:OnPointReached(false)
	end

	function this:ComputePath()
		if this.OriginPoint then
			if this.PathComputed or this.PathComputing then return end
			this.PathComputing = true
			if this.AgentCanFollowPath then
				if this.DirectPath then
					this.pointList = {
						PathWaypoint.new(this.OriginPoint, Enum.PathWaypointAction.Walk),
						PathWaypoint.new(this.TargetPoint, this.DirectPathRiseFirst and Enum.PathWaypointAction.Jump or Enum.PathWaypointAction.Walk)
					}
					this.PathComputed = true
				else
					this.pathResult:ComputeAsync(this.OriginPoint, this.TargetPoint)
					this.pointList = this.pathResult:GetWaypoints()
					this.BlockedConn = this.pathResult.Blocked:Connect(function(blockedIdx) this:OnPathBlocked(blockedIdx) end)
					this.PathComputed = this.pathResult.Status == Enum.PathStatus.Success
				end
			end
			this.PathComputing = false
		end
	end

	function this:IsValidPath()
		this:ComputePath()
		return this.PathComputed and this.AgentCanFollowPath
	end

	this.Recomputing = false
	function this:OnPathBlocked(blockedWaypointIdx)
		local pathBlocked = blockedWaypointIdx >= this.CurrentPoint
		if not pathBlocked or this.Recomputing then
			return
		end

		this.Recomputing = true

		if this.stopTraverseFunc then
			this.stopTraverseFunc()
			this.stopTraverseFunc = nil
		end

		this.OriginPoint = this.Humanoid.RootPart.CFrame.p

		this.pathResult:ComputeAsync(this.OriginPoint, this.TargetPoint)
		this.pointList = this.pathResult:GetWaypoints()
		if #this.pointList > 0 then
			this.HumanoidOffsetFromPath = this.pointList[1].Position - this.OriginPoint
		end
		this.PathComputed = this.pathResult.Status == Enum.PathStatus.Success

		if ShowPath then
			this.stopTraverseFunc, this.setPointFunc = ClickToMoveDisplay.CreatePathDisplay(this.pointList)
		end
		if this.PathComputed then
			this.CurrentPoint = 1 -- The first waypoint is always the start location. Skip it.
			this:OnPointReached(true) -- Move to first point
		else
			this.PathFailed:Fire()
			this:Cleanup()
		end

		this.Recomputing = false
	end

	function this:OnRenderStepped(dt)
		if this.Started and not this.Cancelled then
			-- Check for Timeout (if a waypoint is not reached within the delay, we fail)
			this.Timeout = this.Timeout + dt
			if this.Timeout > UnreachableWaypointTimeout then
				this:OnPointReached(false)
				return
			end

			-- Get Humanoid position and velocity
			this.CurrentHumanoidPosition = this.Humanoid.RootPart.Position + this.HumanoidOffsetFromPath
			this.CurrentHumanoidVelocity = this.Humanoid.RootPart.Velocity

			-- Check if it has reached some waypoints
			while this.Started and this:IsCurrentWaypointReached() do
				this:OnPointReached(true)
			end

			-- If still started, update actions
			if this.Started then
				-- Move action
				this.NextActionMoveDirection = this.CurrentWaypointPosition - this.CurrentHumanoidPosition
				if this.NextActionMoveDirection.Magnitude > ALMOST_ZERO then
					this.NextActionMoveDirection = this.NextActionMoveDirection.Unit
				else
					this.NextActionMoveDirection = ZERO_VECTOR3
				end
				-- Jump action
				if this.CurrentWaypointNeedsJump then
					this.NextActionJump = true
					this.CurrentWaypointNeedsJump = false	-- Request jump only once
				else
					this.NextActionJump = false
				end
			end
		end
	end

	function this:IsCurrentWaypointReached()
		local reached = false

		-- Check we do have a plane, if not, we consider the waypoint reached
		if this.CurrentWaypointPlaneNormal ~= ZERO_VECTOR3 then
			-- Compute distance of Humanoid from destination plane
			local dist = this.CurrentWaypointPlaneNormal:Dot(this.CurrentHumanoidPosition) - this.CurrentWaypointPlaneDistance
			-- Compute the component of the Humanoid velocity that is towards the plane
			local velocity = -this.CurrentWaypointPlaneNormal:Dot(this.CurrentHumanoidVelocity)
			-- Compute the threshold from the destination plane based on Humanoid velocity
			local threshold = math.max(1.0, 0.0625 * velocity)
			-- If we are less then threshold in front of the plane (between 0 and threshold) or if we are behing the plane (less then 0), we consider we reached it
			reached = dist < threshold
		else
			reached = true
		end

		if reached then
			this.CurrentWaypointPosition = nil
			this.CurrentWaypointPlaneNormal	= ZERO_VECTOR3
			this.CurrentWaypointPlaneDistance = 0
		end

		return reached
	end

	function this:OnPointReached(reached)

		if reached and not this.Cancelled then
			-- First, destroyed the current displayed waypoint
			if this.setPointFunc then
				this.setPointFunc(this.CurrentPoint)
			end

			local nextWaypointIdx = this.CurrentPoint + 1

			if nextWaypointIdx > #this.pointList then
				-- End of path reached
				if this.stopTraverseFunc then
					this.stopTraverseFunc()
				end
				this.Finished:Fire()
				this:Cleanup()
			else
				local currentWaypoint = this.pointList[this.CurrentPoint]
				local nextWaypoint = this.pointList[nextWaypointIdx]

				-- If airborne, only allow to keep moving
				-- if nextWaypoint.Action ~= Jump, or path mantains a direction
				-- Otherwise, wait until the humanoid gets to the ground
				local currentState = this.Humanoid:GetState()
				local isInAir = currentState == Enum.HumanoidStateType.FallingDown
					or currentState == Enum.HumanoidStateType.Freefall
					or currentState == Enum.HumanoidStateType.Jumping

				if isInAir then
					local shouldWaitForGround = nextWaypoint.Action == Enum.PathWaypointAction.Jump
					if not shouldWaitForGround and this.CurrentPoint > 1 then
						local prevWaypoint = this.pointList[this.CurrentPoint - 1]

						local prevDir = currentWaypoint.Position - prevWaypoint.Position
						local currDir = nextWaypoint.Position - currentWaypoint.Position

						local prevDirXZ = Vector2.new(prevDir.x, prevDir.z).Unit
						local currDirXZ = Vector2.new(currDir.x, currDir.z).Unit

						local THRESHOLD_COS = 0.996 -- ~cos(5 degrees)
						shouldWaitForGround = prevDirXZ:Dot(currDirXZ) < THRESHOLD_COS
					end

					if shouldWaitForGround then
						this.Humanoid.FreeFalling:Wait()

						-- Give time to the humanoid's state to change
						-- Otherwise, the jump flag in Humanoid
						-- will be reset by the state change
						wait(0.1)
					end
				end

				-- Move to the next point
				if FFlagUserNavigationClickToMoveSkipPassedWaypoints then
					this:MoveToNextWayPoint(currentWaypoint, nextWaypoint, nextWaypointIdx)
				else
					if this.setPointFunc then
						this.setPointFunc(nextWaypointIdx)
					end
					if nextWaypoint.Action == Enum.PathWaypointAction.Jump then
						this.Humanoid.Jump = true
					end
					this.Humanoid:MoveTo(nextWaypoint.Position)

					this.CurrentPoint = nextWaypointIdx
				end
			end
		else
			this.PathFailed:Fire()
			this:Cleanup()
		end
	end

	function this:MoveToNextWayPoint(currentWaypoint, nextWaypoint, nextWaypointIdx)
		-- Build next destination plane
		-- (plane normal is perpendicular to the y plane and is from next waypoint towards current one (provided the two waypoints are not at the same location))
		-- (plane location is at next waypoint)
		this.CurrentWaypointPlaneNormal = currentWaypoint.Position - nextWaypoint.Position
		this.CurrentWaypointPlaneNormal = Vector3.new(this.CurrentWaypointPlaneNormal.X, 0, this.CurrentWaypointPlaneNormal.Z)
		if this.CurrentWaypointPlaneNormal.Magnitude > ALMOST_ZERO then
			this.CurrentWaypointPlaneNormal	= this.CurrentWaypointPlaneNormal.Unit
			this.CurrentWaypointPlaneDistance = this.CurrentWaypointPlaneNormal:Dot(nextWaypoint.Position)
		else
			-- Next waypoint is the same as current waypoint so no plane
			this.CurrentWaypointPlaneNormal	= ZERO_VECTOR3
			this.CurrentWaypointPlaneDistance = 0
		end

		-- Should we jump
		this.CurrentWaypointNeedsJump = nextWaypoint.Action == Enum.PathWaypointAction.Jump;

		-- Remember next waypoint position
		this.CurrentWaypointPosition = nextWaypoint.Position

		-- Move to next point
		this.CurrentPoint = nextWaypointIdx

		-- Finally reset Timeout
		this.Timeout = 0
	end

	function this:Start(overrideShowPath)
		if not this.AgentCanFollowPath then
			this.PathFailed:Fire()
			return
		end

		if this.Started then return end
		this.Started = true

		ClickToMoveDisplay.CancelFailureAnimation()

		if ShowPath then
			if overrideShowPath == nil or overrideShowPath then
				this.stopTraverseFunc, this.setPointFunc = ClickToMoveDisplay.CreatePathDisplay(this.pointList, this.OriginalTargetPoint)
			end
		end

		if #this.pointList > 0 then
			-- Determine the humanoid offset from the path's first point
			-- Offset of the first waypoint from the path's origin point
			this.HumanoidOffsetFromPath = Vector3.new(0, this.pointList[1].Position.Y - this.OriginPoint.Y, 0)

			-- As well as its current position and velocity
			this.CurrentHumanoidPosition = this.Humanoid.RootPart.Position + this.HumanoidOffsetFromPath
			this.CurrentHumanoidVelocity = this.Humanoid.RootPart.Velocity

			-- Connect to events
			this.SeatedConn = this.Humanoid.Seated:Connect(function(isSeated, seat) this:OnPathInterrupted() end)
			this.DiedConn = this.Humanoid.Died:Connect(function() this:OnPathInterrupted() end)
			this.TeleportedConn = this.Humanoid.RootPart:GetPropertyChangedSignal("CFrame"):Connect(function() this:OnPathInterrupted() end)

			-- Actually start
			this.CurrentPoint = 1 -- The first waypoint is always the start location. Skip it.
			this:OnPointReached(true) -- Move to first point
		else
			this.PathFailed:Fire()
			if this.stopTraverseFunc then
				this.stopTraverseFunc()
			end
		end
	end

	--We always raycast to the ground in the case that the user clicked a wall.
	local offsetPoint = this.TargetPoint + this.TargetSurfaceNormal*1.5
	local ray = Ray.new(offsetPoint, Vector3.new(0,-1,0)*50)
	local newHitPart, newHitPos = Workspace:FindPartOnRayWithIgnoreList(ray, getIgnoreList())
	if newHitPart then
		this.TargetPoint = newHitPos
	end
	this:ComputePath()

	return this
end
