local function G(G)local f=math.min(Utility.ViewSizeY()*.33,250)local v=f return G.X<=v and G.Y>Utility.ViewSizeY()-f end local function f(G)local f=math.min(Utility.ViewSizeY()*.33,250)local v=f return G.X>=Utility.ViewSizeX()-v and G.Y>Utility.ViewSizeY()-f end local function v(G)local f=findPlayerHumanoid(Player)return f~=nil and f.Health>0 end local function e(G)if G~=nil then for G,f in pairs(G:GetChildren())do if f:IsA("\084\111\111\108")then return f end end end end local function z(G,f)local v=40 local e={}do local G=f for f=0,15,1 do table.insert(e,CFrame.Angles(0,(math.pi/8)*f,0)*G)end end local z={}local function j()for G,e in pairs(z)do local z=-1*f local j=(z:Dot(e.Vector)+1)/2 local r=e.Distance/v e.Value=j*r end end for f,e in pairs(e)do local j,r=Utility.Raycast(Ray.new(G,e*v),true,{Player.Character})if r then table.insert(z,{Vector=e,Distance=(r-G).magnitude})else table.insert(z,{Vector=e;Distance=v})end end j()table.sort(z,function(G,f)return G.Value>f.Value end)return z end local j=1 local r=nil local b=nil local Y=nil local o=nil local function w()if r then r:Cancel()end if Y then Y:disconnect()Y=nil end if o then o:disconnect()o=nil end if b then DebrisService:AddItem(b,0)b=nil end end local i=nil local Q=0 local O=0 local function t(G)j=j+1 local f=j local t=workspace.CurrentCamera local h=Player.Character if not v(h)then return end if#G==1 then if t then local f=Utility.GetUnitRay(G[1].x,G[1].y,MyMouse.ViewSizeX,MyMouse.ViewSizeY,t)local v=Ray.new(f.Origin,f.Direction*400)local j,I=Utility.Raycast(v,true,{h})local Z,N=Utility.FindChacterAncestor(j)local l=h and(h:FindFirstChild("\072\117\109\097\110\111\105\100")and(h:FindFirstChild("\072\117\109\097\110\111\105\100")).Torso)local m=l.CFrame.p if Z and(N and(N.Torso and(N.Torso.CFrame.p-l.CFrame.p).magnitude<7))then w()local G=findPlayerHumanoid(Player)if G then G:MoveTo(I)end Q=Q+1 local f=Q local v=e(h)if v then v:Activate()LastFired=tick()end elseif I and h then local G=Pather(h,I)if G:IsValidPath()then O=0 Player:Move(Vector3.new(1,0,0))Player:Move(Vector3.new(0,0,0))G:Start()if BindableEvent_OnFailStateChanged then BindableEvent_OnFailStateChanged:Fire(false)end w()local f=CreateDestinationIndicator(I)f.Parent=t r=G b=f if i then i:Run()end Y=G.Finished:connect(function()if i then i:Stop()end if f then if b==f then b=nil end DebrisService:AddItem(f,0)f=nil end if Z then local G=findPlayerHumanoid(Player)Q=Q+1 local f=Q local v=e(h)if v then v:Activate()LastFired=tick()end if G then G:MoveTo(I)end end local G=l and l.CFrame.p if G and(m and tick()-Utility.GetLastInput()>2)then local f=z(G,((m-G)*Vector3.new(1,0,1)).unit)if f[1]and(f[1].Vector and(f[1].Vector.magnitude>=.5 and f[1].Distance>3))then if CameraModule then local v=CameraModule:LookAtPreserveHeight(G+f[1].Vector*f[1].Distance)local e,z=CameraModule:TweenCameraLook(v)end end end end)o=G.PathFailed:connect(function()if i then i:Stop()end if f then FlashRed(f)DebrisService:AddItem(f,3)end end)else if I then local G=CreateDestinationIndicator(I)FlashRed(G)DebrisService:AddItem(G,1)G.Parent=t if b==nil then O=O+1 if O>=3 then if BindableEvent_OnFailStateChanged then BindableEvent_OnFailStateChanged:Fire(true)end w()end end end end else end end elseif#G>=2 then if t then Q=Q+1 local f=Q local v=Utility.AveragePoints(G)local z=Utility.GetUnitRay(v.x,v.y,MyMouse.ViewSizeX,MyMouse.ViewSizeY,t)local j=e(h)if j then j:Activate()LastFired=tick()end end end end local function h()local v={}local e=0 local z=Enum.HumanoidStateType.Running local j={}local r=0 local Y=tick()local o=Vector2.new()local Q=tick()local O=Vector2.new()local h=tick()local I={[Enum.KeyCode.W]=true,[Enum.KeyCode.A]=true;[Enum.KeyCode.S]=true;[Enum.KeyCode.D]=true,[Enum.KeyCode.Up]=true;[Enum.KeyCode.Down]=true}local Z=nil local N=nil local l=nil local m=nil local s=nil local q=nil local L=nil local n=nil local H=nil local function x(G)if G then G:disconnect()end end local function F()x(Z)x(N)x(l)x(m)x(s)x(q)x(L)x(H)x(n)pcall(function()RunService:UnbindFromRenderStep("\067\108\105\099\107\084\111\077\111\118\101\082\101\110\100\101\114\085\112\100\097\116\101")end)end local function u(G)return G==G and(G~=1/0 and G~=-1/0)end local function K(G,f)return math.atan2(f.X*G.Z-f.Z*G.X,f.X*G.X+f.Z*G.Z)end CameraModule=ClassicCameraModule()do function CameraModule.LookAtPreserveHeight(f,G)local v=workspace.CurrentCamera local e=v.Focus.p local z=v.CoordinateFrame local j=(Vector3.new(z.lookVector.x,0,z.lookVector.z)).magnitude local r=(Vector3.new(G.x,e.y,G.z)-e).unit*j local b=r+Vector3.new(0,z.lookVector.y,0)local Y=(e-v.CoordinateFrame.p).magnitude local o=e-b.unit*Y return CFrame.new(o,o+b)end function CameraModule.TweenCameraLook(v,G,f)local e=2.718281828459 local function z(G)return 1/(1+e^(-G*1.5))end local function j(G,f,v,e)if G>=e then return f+v end return v*math.sin((G/e)*(math.pi/2))+f end local r,b=CFrameInterpolator(CFrame.new(Vector3.new(),v:GetCameraLook()),G-G.p)r=Utility.Clamp(0,math.pi,r)local Y=.65*z(r-math.pi/4)+.15 if f then Y=r/f end local o=tick()local w=o+Y v.UpdateTweenFunction=function()local G=tick()-o local f=Utility.Clamp(0,1,j(G,0,1,Y))local e=b(f)local z=K(e.lookVector,v:GetCameraLook())if u(z)and math.abs(z)>.0001 then v.RotateInput=v.RotateInput+Vector2.new(z,0)end return G>=w or f>=1 end end end local function c(G,f)if j[G]==nil and not f then r=r+1 end j[G]=f end local function U(G,f)if j[G]==nil then j[G]=f if not f then r=r+1 end end end local function k(G,f)if j[G]~=nil and j[G]==false then r=r-1 end j[G]=nil end local function M(v)F()N=UIS.InputBegan:connect(function(v,e)if v.UserInputType==Enum.UserInputType.Touch then c(v,e)local z=G(v.Position)local r=f(v.Position)if r or z then for e,j in pairs(j)do if e~=v then local v=G(e.Position)local j=f(e.Position)if e.UserInputState~=Enum.UserInputState.End and(z and j or r and v)then if BindableEvent_OnFailStateChanged then BindableEvent_OnFailStateChanged:Fire(true)end return end end end end end if e==false and(v.UserInputType==Enum.UserInputType.Keyboard and I[v.KeyCode])then w()end if v.UserInputType==Enum.UserInputType.MouseButton1 then Y=tick()o=v.Position end if v.UserInputType==Enum.UserInputType.MouseButton2 then Q=tick()O=v.Position end end)l=UIS.InputChanged:connect(function(G,f)if G.UserInputType==Enum.UserInputType.Touch then U(G,f)end end)m=UIS.InputEnded:connect(function(G,f)if G.UserInputType==Enum.UserInputType.Touch then k(G,f)end if G.UserInputType==Enum.UserInputType.MouseButton2 then h=tick()local f=G.Position if h-Q<.25 and(f-O).magnitude<5 then local G={f}t(G)end end end)Z=UIS.TouchTap:connect(function(G,f)if not f then t(G)end end)if not UIS.TouchEnabled then if i then i:Stop()i=nil end i=AutoJumper()end local function e()if CameraModule then if CameraModule.UserPanningTheCamera then CameraModule.UpdateTweenFunction=nil else if CameraModule.UpdateTweenFunction then local G=CameraModule.UpdateTweenFunction()if G then CameraModule.UpdateTweenFunction=nil end end end CameraModule:Update()end end local z=pcall(function()RunService:BindToRenderStep("\067\108\105\099\107\084\111\077\111\118\101\082\101\110\100\101\114\085\112\100\097\116\101",Enum.RenderPriority.Camera.Value-1,e)end)if not z then if H then H:disconnect()end H=RunService.RenderStepped:connect(e)end local function r(G)if UIS.TouchEnabled then if G:IsA("\084\111\111\108")then G.ManualActivationOnly=true end end if G:IsA("\072\117\109\097\110\111\105\100")then x(s)s=G.Died:connect(function()DebrisService:AddItem(b,1)if i then i:Stop()i=nil end end)end end q=v.ChildAdded:connect(function(G)r(G)end)n=v.ChildRemoved:connect(function(G)if UIS.TouchEnabled then if G:IsA("\084\111\111\108")then G.ManualActivationOnly=false end end end)for G,f in pairs(v:GetChildren())do r(f)end end local S=false function v.Stop(G)if S then F()w()if i then i:Stop()i=nil end if CameraModule then CameraModule.UpdateTweenFunction=nil CameraModule:SetEnabled(false)end if UIS.TouchEnabled then local G=Player.Character if G then for G,f in pairs(G:GetChildren())do if f:IsA("\084\111\111\108")then f.ManualActivationOnly=false end end end end S=false end end function v.Start(G)if not S then if Player.Character then M(Player.Character)end L=Player.CharacterAdded:connect(M)if CameraModule then CameraModule:SetEnabled(true)end S=true end end return v end return h

local function IsInBottomLeft(pt)
	local joystickHeight = math.min(Utility.ViewSizeY() * 0.33, 250)
	local joystickWidth = joystickHeight
	return pt.X <= joystickWidth and pt.Y > Utility.ViewSizeY() - joystickHeight
end

local function IsInBottomRight(pt)
	local joystickHeight = math.min(Utility.ViewSizeY() * 0.33, 250)
	local joystickWidth = joystickHeight
	return pt.X >= Utility.ViewSizeX() - joystickWidth and pt.Y > Utility.ViewSizeY() - joystickHeight
end

local function CheckAlive(character)
	local humanoid = findPlayerHumanoid(Player)
	return humanoid ~= nil and humanoid.Health > 0
end

local function GetEquippedTool(character)
	if character ~= nil then
		for _, child in pairs(character:GetChildren()) do
			if child:IsA('Tool') then
				return child
			end
		end
	end
end

local function ExploreWithRayCast(currentPoint, originDirection)
	local TestDistance = 40
	local TestVectors = {}
	do
		local forwardVector = originDirection;
		for i = 0, 15 do
			table.insert(TestVectors, CFrame.Angles(0, math.pi / 8 * i, 0) * forwardVector)
		end
	end

	local testResults = {}
	-- Heuristic should be something along the lines of distance and closeness to the traveling direction
	local function ExploreHeuristic()
		for _, testData in pairs(testResults) do
			local walkDirection = -1 * originDirection
			local directionCoeff = (walkDirection:Dot(testData['Vector']) + 1) / 2
			local distanceCoeff = testData['Distance'] / TestDistance
			testData["Value"] = directionCoeff * distanceCoeff
		end
	end

	for i, vec in pairs(TestVectors) do
		local hitPart, hitPos = Utility.Raycast(Ray.new(currentPoint, vec * TestDistance), true, {Player.Character})
		if hitPos then
			table.insert(testResults, {Vector = vec; Distance = (hitPos - currentPoint).magnitude})
		else
			table.insert(testResults, {Vector = vec; Distance = TestDistance})
		end
	end

	ExploreHeuristic()

	table.sort(testResults, function(a,b) return a["Value"] > b["Value"] end)

	return testResults
end

local TapId = 1
local ExistingPather = nil
local ExistingIndicator = nil
local PathCompleteListener = nil
local PathFailedListener = nil

local function CleanupPath()
	if ExistingPather then
		ExistingPather:Cancel()
	end
	if PathCompleteListener then
		PathCompleteListener:disconnect()
		PathCompleteListener = nil
	end
	if PathFailedListener then
		PathFailedListener:disconnect()
		PathFailedListener = nil
	end
	if ExistingIndicator then
		DebrisService:AddItem(ExistingIndicator, 0)
		ExistingIndicator = nil
	end
end


local AutoJumperInstance = nil
local ShootCount = 0
local FailCount = 0
local function OnTap(tapPositions)
	-- Good to remember if this is the latest tap event
	TapId = TapId + 1
	local thisTapId = TapId


	local camera = workspace.CurrentCamera
	local character = Player.Character


	if not CheckAlive(character) then return end
	-- This is a path tap position
	if #tapPositions == 1 then
		if camera then
			local unitRay = Utility.GetUnitRay(tapPositions[1].x, tapPositions[1].y, MyMouse.ViewSizeX, MyMouse.ViewSizeY, camera)
			local ray = Ray.new(unitRay.Origin, unitRay.Direction*400)
			local hitPart, hitPt = Utility.Raycast(ray, true, {character})

			local hitChar, hitHumanoid = Utility.FindChacterAncestor(hitPart)
			local torso = character and character:FindFirstChild("Humanoid") and character:FindFirstChild("Humanoid").Torso
			local startPos = torso.CFrame.p
			if hitChar and hitHumanoid and hitHumanoid.Torso and (hitHumanoid.Torso.CFrame.p - torso.CFrame.p).magnitude < 7 then
				CleanupPath()

				local myHumanoid = findPlayerHumanoid(Player)
				if myHumanoid then
					myHumanoid:MoveTo(hitPt)
				end

				ShootCount = ShootCount + 1
				local thisShoot = ShootCount
				-- Do shooot
				local currentWeapon = GetEquippedTool(character)
				if currentWeapon then
					currentWeapon:Activate()
					LastFired = tick()
				end
			elseif hitPt and character then
				local thisPather = Pather(character, hitPt)
				if thisPather:IsValidPath() then
					FailCount = 0
					-- TODO: Remove when bug in engine is fixed
					Player:Move(Vector3.new(1, 0, 0))
					Player:Move(Vector3.new(0, 0, 0))
					thisPather:Start()
					if BindableEvent_OnFailStateChanged then
						BindableEvent_OnFailStateChanged:Fire(false)
					end
					CleanupPath()

					local destinationGlobe = CreateDestinationIndicator(hitPt)
					destinationGlobe.Parent = camera

					ExistingPather = thisPather
					ExistingIndicator = destinationGlobe

					if AutoJumperInstance then
						AutoJumperInstance:Run()
					end

					PathCompleteListener = thisPather.Finished:connect(function()
						if AutoJumperInstance then
							AutoJumperInstance:Stop()
						end
						if destinationGlobe then
							if ExistingIndicator == destinationGlobe then
								ExistingIndicator = nil
							end
							DebrisService:AddItem(destinationGlobe, 0)
							destinationGlobe = nil
						end
						if hitChar then
							local humanoid = findPlayerHumanoid(Player)
							ShootCount = ShootCount + 1
							local thisShoot = ShootCount
							-- Do shoot
							local currentWeapon = GetEquippedTool(character)
							if currentWeapon then
								currentWeapon:Activate()
								LastFired = tick()
							end
							if humanoid then
								humanoid:MoveTo(hitPt)
							end
						end
						local finishPos = torso and torso.CFrame.p --hitPt
						if finishPos and startPos and tick() - Utility.GetLastInput() > 2 then
							local exploreResults = ExploreWithRayCast(finishPos, ((startPos - finishPos) * Vector3.new(1,0,1)).unit)
							-- Check for Nans etc..
							if exploreResults[1] and exploreResults[1]["Vector"] and exploreResults[1]["Vector"].magnitude >= 0.5 and exploreResults[1]["Distance"] > 3 then
								if CameraModule then
									local rotatedCFrame = CameraModule:LookAtPreserveHeight(finishPos + exploreResults[1]["Vector"] * exploreResults[1]["Distance"])
									local finishedSignal, duration = CameraModule:TweenCameraLook(rotatedCFrame)
								end
							end
						end
					end)
					PathFailedListener = thisPather.PathFailed:connect(function()
						if AutoJumperInstance then
							AutoJumperInstance:Stop()
						end
						if destinationGlobe then
							FlashRed(destinationGlobe)
							DebrisService:AddItem(destinationGlobe, 3)
						end
					end)
				else
					if hitPt then
						-- Feedback here for when we don't have a good path
						local failedGlobe = CreateDestinationIndicator(hitPt)
						FlashRed(failedGlobe)
						DebrisService:AddItem(failedGlobe, 1)
						failedGlobe.Parent = camera
						if ExistingIndicator == nil then
							FailCount = FailCount + 1
							if FailCount >= 3 then
								if BindableEvent_OnFailStateChanged then
									BindableEvent_OnFailStateChanged:Fire(true)
								end
								CleanupPath()
							end
						end
					end
				end
			else
				-- no hit pt
			end
		end
	elseif #tapPositions >= 2 then
		if camera then
			ShootCount = ShootCount + 1
			local thisShoot = ShootCount
			-- Do shoot
			local avgPoint = Utility.AveragePoints(tapPositions)
			local unitRay = Utility.GetUnitRay(avgPoint.x, avgPoint.y, MyMouse.ViewSizeX, MyMouse.ViewSizeY, camera)
			local currentWeapon = GetEquippedTool(character)
			if currentWeapon then
				currentWeapon:Activate()
				LastFired = tick()
			end
		end
	end
end


local function CreateClickToMoveModule()
	local this = {}

	local LastStateChange = 0
	local LastState = Enum.HumanoidStateType.Running
	local FingerTouches = {}
	local NumUnsunkTouches = 0
	-- PC simulation
	local mouse1Down = tick()
	local mouse1DownPos = Vector2.new()
	local mouse2Down = tick()
	local mouse2DownPos = Vector2.new()
	local mouse2Up = tick()

	local movementKeys = {
		[Enum.KeyCode.W] = true;
		[Enum.KeyCode.A] = true;
		[Enum.KeyCode.S] = true;
		[Enum.KeyCode.D] = true;
		[Enum.KeyCode.Up] = true;
		[Enum.KeyCode.Down] = true;
	}

	local TapConn = nil
	local InputBeganConn = nil
	local InputChangedConn = nil
	local InputEndedConn = nil
	local HumanoidDiedConn = nil
	local CharacterChildAddedConn = nil
	local OnCharacterAddedConn = nil
	local CharacterChildRemovedConn = nil
	local RenderSteppedConn = nil


	local function disconnectEvent(event)
		if event then
			event:disconnect()
		end
	end

	local function DisconnectEvents()
		disconnectEvent(TapConn)
		disconnectEvent(InputBeganConn)
		disconnectEvent(InputChangedConn)
		disconnectEvent(InputEndedConn)
		disconnectEvent(HumanoidDiedConn)
		disconnectEvent(CharacterChildAddedConn)
		disconnectEvent(OnCharacterAddedConn)
		disconnectEvent(RenderSteppedConn)
		disconnectEvent(CharacterChildRemovedConn)
		pcall(function() RunService:UnbindFromRenderStep("ClickToMoveRenderUpdate") end)
	end



	local function IsFinite(num)
		return num == num and num ~= 1/0 and num ~= -1/0
	end
	
	local function findAngleBetweenXZVectors(vec2, vec1)
		return math.atan2(vec1.X*vec2.Z-vec1.Z*vec2.X, vec1.X*vec2.X + vec1.Z*vec2.Z)
	end
	
	-- Setup the camera
	CameraModule = ClassicCameraModule()

	do
		-- Extend The Camera Module Class
		function CameraModule:LookAtPreserveHeight(newLookAtPt)
			local camera = 	workspace.CurrentCamera

			local focus = camera.Focus.p

			local cameraCFrame = camera.CoordinateFrame
			local mag = Vector3.new(cameraCFrame.lookVector.x, 0, cameraCFrame.lookVector.z).magnitude
			local newLook = (Vector3.new(newLookAtPt.x, focus.y, newLookAtPt.z) - focus).unit * mag
			local flippedLook = newLook + Vector3.new(0, cameraCFrame.lookVector.y, 0)

			local distance = (focus - camera.CoordinateFrame.p).magnitude

			local newCamPos = focus - flippedLook.unit * distance
			return CFrame.new(newCamPos, newCamPos + flippedLook)
		end

		function CameraModule:TweenCameraLook(desiredCFrame, speed)
			local e = 2.718281828459
			local function SCurve(t)
				return 1/(1 + e^(-t*1.5))
			end
			local function easeOutSine(t, b, c, d)
				if t >= d then return b + c end
				return c * math.sin(t/d * (math.pi/2)) + b;
			end

			local theta, interper = CFrameInterpolator(CFrame.new(Vector3.new(), self:GetCameraLook()), desiredCFrame - desiredCFrame.p)
			theta = Utility.Clamp(0, math.pi, theta)
			local duration = 0.65 * SCurve(theta - math.pi/4) + 0.15
			if speed then
				duration = theta / speed
			end
			local start = tick()
			local finish = start + duration

			self.UpdateTweenFunction = function()
				local currTime = tick() - start
				local alpha = Utility.Clamp(0, 1, easeOutSine(currTime, 0, 1, duration))
				local newCFrame = interper(alpha)
				local y = findAngleBetweenXZVectors(newCFrame.lookVector, self:GetCameraLook())
				if IsFinite(y) and math.abs(y) > 0.0001 then
					self.RotateInput = self.RotateInput + Vector2.new(y, 0)
				end
				return (currTime >= finish or alpha >= 1)
			end
		end
	end
	--- Done Extending


	local function OnTouchBegan(input, processed)
		if FingerTouches[input] == nil and not processed then
			NumUnsunkTouches = NumUnsunkTouches + 1
		end
		FingerTouches[input] = processed
	end

	local function OnTouchChanged(input, processed)
		if FingerTouches[input] == nil then
			FingerTouches[input] = processed
			if not processed then
				NumUnsunkTouches = NumUnsunkTouches + 1
			end
		end
	end

	local function OnTouchEnded(input, processed)
			--print("Touch tap fake:" , processed)
			--if not processed then
			--	OnTap({input.Position})
			--end
		if FingerTouches[input] ~= nil and FingerTouches[input] == false then
			NumUnsunkTouches = NumUnsunkTouches - 1
		end
		FingerTouches[input] = nil
	end


	local function OnCharacterAdded(character)
		DisconnectEvents()

		InputBeganConn = UIS.InputBegan:connect(function(input, processed)
			if input.UserInputType == Enum.UserInputType.Touch then
				OnTouchBegan(input, processed)


				-- Give back controls when they tap both sticks
				local wasInBottomLeft = IsInBottomLeft(input.Position)
				local wasInBottomRight = IsInBottomRight(input.Position)
				if wasInBottomRight or wasInBottomLeft then
					for otherInput, _ in pairs(FingerTouches) do
						if otherInput ~= input then
							local otherInputInLeft = IsInBottomLeft(otherInput.Position)
							local otherInputInRight = IsInBottomRight(otherInput.Position)
							if otherInput.UserInputState ~= Enum.UserInputState.End and ((wasInBottomLeft and otherInputInRight) or (wasInBottomRight and otherInputInLeft)) then
								if BindableEvent_OnFailStateChanged then
									BindableEvent_OnFailStateChanged:Fire(true)
								end
								return
							end
						end
					end
				end
			end

			 -- Cancel path when you use the keyboard controls.
			if processed == false and input.UserInputType == Enum.UserInputType.Keyboard and movementKeys[input.KeyCode] then
				CleanupPath()
			end
			if input.UserInputType == Enum.UserInputType.MouseButton1 then
				mouse1Down = tick()
				mouse1DownPos = input.Position
			end
			if input.UserInputType == Enum.UserInputType.MouseButton2 then
				mouse2Down = tick()
				mouse2DownPos = input.Position
			end
		end)

		InputChangedConn = UIS.InputChanged:connect(function(input, processed)
			if input.UserInputType == Enum.UserInputType.Touch then
				OnTouchChanged(input, processed)
			end
		end)

		InputEndedConn = UIS.InputEnded:connect(function(input, processed)
			if input.UserInputType == Enum.UserInputType.Touch then
				OnTouchEnded(input, processed)
			end

			if input.UserInputType == Enum.UserInputType.MouseButton2 then
				mouse2Up = tick()
				local currPos = input.Position
				if mouse2Up - mouse2Down < 0.25 and (currPos - mouse2DownPos).magnitude < 5 then
					local positions = {currPos}
					OnTap(positions)
				end
			end
		end)
		TapConn = UIS.TouchTap:connect(function(touchPositions, processed)
			if not processed then
				OnTap(touchPositions)
			end
		end)

		if not UIS.TouchEnabled then -- PC
			if AutoJumperInstance then
				AutoJumperInstance:Stop()
				AutoJumperInstance = nil
			end
			AutoJumperInstance = AutoJumper()
		end

		local function Update()
			if CameraModule then
				if CameraModule.UserPanningTheCamera then
					CameraModule.UpdateTweenFunction = nil
				else
					if CameraModule.UpdateTweenFunction then
						local done = CameraModule.UpdateTweenFunction()
						if done then
							CameraModule.UpdateTweenFunction = nil
						end
					end
				end
				CameraModule:Update()
			end
		end
		
		local success = pcall(function() RunService:BindToRenderStep("ClickToMoveRenderUpdate",Enum.RenderPriority.Camera.Value - 1,Update) end)
		if not success then
			if RenderSteppedConn then
				RenderSteppedConn:disconnect()
			end
			RenderSteppedConn = RunService.RenderStepped:connect(Update)
		end

		local function OnCharacterChildAdded(child)
			if UIS.TouchEnabled then
				if child:IsA('Tool') then
					child.ManualActivationOnly = true
				end
			end
			if child:IsA('Humanoid') then
				disconnectEvent(HumanoidDiedConn)
				HumanoidDiedConn = child.Died:connect(function()
					DebrisService:AddItem(ExistingIndicator, 1)
					if AutoJumperInstance then
						AutoJumperInstance:Stop()
						AutoJumperInstance = nil
					end
				end)
			end
		end

		CharacterChildAddedConn = character.ChildAdded:connect(function(child)
			OnCharacterChildAdded(child)
		end)
		CharacterChildRemovedConn = character.ChildRemoved:connect(function(child)
			if UIS.TouchEnabled then
				if child:IsA('Tool') then
					child.ManualActivationOnly = false
				end
			end
		end)
		for _, child in pairs(character:GetChildren()) do
			OnCharacterChildAdded(child)
		end
	end

	local Running = false

	function this:Stop()
		if Running then
			DisconnectEvents()
			CleanupPath()
			if AutoJumperInstance then
				AutoJumperInstance:Stop()
				AutoJumperInstance = nil
			end
			if CameraModule then
				CameraModule.UpdateTweenFunction = nil
				CameraModule:SetEnabled(false)
			end
			-- Restore tool activation on shutdown
			if UIS.TouchEnabled then
				local character = Player.Character
				if character then
					for _, child in pairs(character:GetChildren()) do
						if child:IsA('Tool') then
							child.ManualActivationOnly = false
						end
					end
				end
			end
			Running = false
		end
	end

	function this:Start()
		if not Running then
			if Player.Character then -- retro-listen
				OnCharacterAdded(Player.Character)
			end
			OnCharacterAddedConn = Player.CharacterAdded:connect(OnCharacterAdded)
			if CameraModule then
				CameraModule:SetEnabled(true)
			end
			Running = true
		end
	end

	return this
end

return CreateClickToMoveModule
