local X={}do local G={}function G.Create()local X={}local G=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116")local F=nil local c=nil function X.fire(X,...)F={...}c=select("\035",...)G:Fire()end function X.connect(T,X)if not X then error("\099\111\110\110\101\099\116\040\110\105\108\041",2)end return G.Event:connect(function()X(unpack(F,1,c))end)end function X.wait(X)G.Event:wait()assert(F,"\077\105\115\115\105\110\103 \097\114\103 \100\097\116\097\044 \108\105\107\101\108\121 \100\117\101 \116\111 \058\084\119\101\101\110\083\105\122\101\047\080\111\115\105\116\105\111\110 \099\111\114\114\117\112\116\105\110\103 \116\104\114\101\097\100\114\101\102\115\046")return unpack(F,1,c)end return X end X.Signal=G function X.Create(X)return function(G)local F=Instance.new(X)for X,G in pairs(G)do if type(X)=="\110\117\109\098\101\114"then G.Parent=F else F[X]=G end end return F end end local function F()local X=workspace.CurrentCamera local G=X and X.ViewportSize.X or 0 local F=X and X.ViewportSize.Y or 0 if G==0 then return 1024 else if G>F then return G else return F end end end X.ViewSizeX=F local function c()local X=workspace.CurrentCamera local G=X and X.ViewportSize.X or 0 local F=X and X.ViewportSize.Y or 0 if F==0 then return 768 else if G>F then return F else return G end end end X.ViewSizeY=c local function T()return F()/c()end X.AspectRatio=T local function a(X)if X then local G=X:FindFirstChild("\072\117\109\097\110\111\105\100")if G then return X,G else return a(X.Parent)end end end X.FindChacterAncestor=a local function I(X,G,F,c,T)return T:ScreenPointToRay(X,G)end X.GetUnitRay=I local function K(X,G,F)local c=F or{}local T,a=RayCastIgnoreList(workspace,X,c)if T then if G and T.CanCollide==false then table.insert(c,T)return K(X,G,c)end return T,a end return nil,nil end X.Raycast=K X.Round=function(X,G)G=G or 1 return math_floor((X+G/2)/G)*G end local function n(X)local G=ZERO_VECTOR2 if#X>0 then for F=1,#X,1 do G=G+X[F]end G=G/#X end return G end X.AveragePoints=n local function B(X,G)return X+.1>G and X-.1<G end X.FuzzyEquals=B local Z=0 UIS.InputBegan:connect(function(X,G)if not G then if X.UserInputType==Enum.UserInputType.Touch or X.UserInputType==Enum.UserInputType.MouseButton1 or X.UserInputType==Enum.UserInputType.MouseButton2 then Z=tick()end end end)X.GetLastInput=function()return Z end end local G={}local function F(X)local F=X and X.Character if F then local c=G[X]if c and c.Parent==F then return c else G[X]=nil local c=F:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")if c then G[X]=c end return c end end end local c do local X=(CFrame.new()).components local G=(CFrame.new()).inverse local F=math.acos c=function(c,T)local a,I,K,n,B,Z,r,V,g,L,d,s=X(G(c)*T)local u=(((n+V)+s)-1)/2 if u>=.999 then return 0 elseif u<=-0.999 then return math_pi else return F(u)end end end
--------------------------UTIL LIBRARY-------------------------------
local Utility = {}
do
	local Signal = {}

	function Signal.Create()
		local sig = {}

		local mSignaler = Instance.new("BindableEvent")

		local mArgData = nil
		local mArgDataCount = nil

		function sig:fire(...)
			mArgData = { ... }
			mArgDataCount = select("#", ...)
			mSignaler:Fire()
		end

		function sig:connect(f)
			if not f then
				error("connect(nil)", 2)
			end
			return mSignaler.Event:connect(function()
				f(unpack(mArgData, 1, mArgDataCount))
			end)
		end

		function sig:wait()
			mSignaler.Event:wait()
			assert(mArgData, "Missing arg data, likely due to :TweenSize/Position corrupting threadrefs.")
			return unpack(mArgData, 1, mArgDataCount)
		end

		return sig
	end
	Utility.Signal = Signal

	function Utility.Create(instanceType)
		return function(data)
			local obj = Instance.new(instanceType)
			for k, v in pairs(data) do
				if type(k) == "number" then
					v.Parent = obj
				else
					obj[k] = v
				end
			end
			return obj
		end
	end

	local function ViewSizeX()
		local camera = workspace.CurrentCamera
		local x = camera and camera.ViewportSize.X or 0
		local y = camera and camera.ViewportSize.Y or 0
		if x == 0 then
			return 1024
		else
			if x > y then
				return x
			else
				return y
			end
		end
	end
	Utility.ViewSizeX = ViewSizeX

	local function ViewSizeY()
		local camera = workspace.CurrentCamera
		local x = camera and camera.ViewportSize.X or 0
		local y = camera and camera.ViewportSize.Y or 0
		if y == 0 then
			return 768
		else
			if x > y then
				return y
			else
				return x
			end
		end
	end
	Utility.ViewSizeY = ViewSizeY

	local function AspectRatio()
		return ViewSizeX() / ViewSizeY()
	end
	Utility.AspectRatio = AspectRatio

	local function FindChacterAncestor(part)
		if part then
			local humanoid = part:FindFirstChild("Humanoid")
			if humanoid then
				return part, humanoid
			else
				return FindChacterAncestor(part.Parent)
			end
		end
	end
	Utility.FindChacterAncestor = FindChacterAncestor

	local function GetUnitRay(x, y, viewWidth, viewHeight, camera)
		return camera:ScreenPointToRay(x, y)
	end
	Utility.GetUnitRay = GetUnitRay

	local function Raycast(ray, ignoreNonCollidable, ignoreList)
		local ignoreList = ignoreList or {}
		local hitPart, hitPos = RayCastIgnoreList(workspace, ray, ignoreList)
		if hitPart then
			if ignoreNonCollidable and hitPart.CanCollide == false then
				table.insert(ignoreList, hitPart)
				return Raycast(ray, ignoreNonCollidable, ignoreList)
			end
			return hitPart, hitPos
		end
		return nil, nil
	end
	Utility.Raycast = Raycast

	Utility.Round = function(num, roundToNearest)
		roundToNearest = roundToNearest or 1
		return math_floor((num + roundToNearest / 2) / roundToNearest) * roundToNearest
	end

	local function AveragePoints(positions)
		local avgPos = ZERO_VECTOR2
		if #positions > 0 then
			for i = 1, #positions do
				avgPos = avgPos + positions[i]
			end
			avgPos = avgPos / #positions
		end
		return avgPos
	end
	Utility.AveragePoints = AveragePoints

	local function FuzzyEquals(numa, numb)
		return numa + 0.1 > numb and numa - 0.1 < numb
	end
	Utility.FuzzyEquals = FuzzyEquals

	local LastInput = 0
	UIS.InputBegan:connect(function(inputObject, wasSunk)
		if not wasSunk then
			if
				inputObject.UserInputType == Enum.UserInputType.Touch
				or inputObject.UserInputType == Enum.UserInputType.MouseButton1
				or inputObject.UserInputType == Enum.UserInputType.MouseButton2
			then
				LastInput = tick()
			end
		end
	end)
	Utility.GetLastInput = function()
		return LastInput
	end
end

local humanoidCache = {}
local function findPlayerHumanoid(player)
	local character = player and player.Character
	if character then
		local resultHumanoid = humanoidCache[player]
		if resultHumanoid and resultHumanoid.Parent == character then
			return resultHumanoid
		else
			humanoidCache[player] = nil -- Bust Old Cache
			local humanoid = character:FindFirstChildOfClass("Humanoid")
			if humanoid then
				humanoidCache[player] = humanoid
			end
			return humanoid
		end
	end
end

local GetThetaBetweenCFrames
do
	local components = CFrame.new().components
	local inverse = CFrame.new().inverse
	local acos = math.acos

	GetThetaBetweenCFrames = function(c0, c1) -- (CFrame from, CFrame to) -> (float theta)
		local _, _, _, xx, yx, zx, xy, yy, zy, xz, yz, zz = components(inverse(c0) * c1)
		local cosTheta = (xx + yy + zz - 1) / 2

		if cosTheta >= 0.999 then
			-- Same rotation
			return 0
		elseif cosTheta <= -0.999 then
			-- Oposite rotations
			return math_pi
		else
			return acos(cosTheta)
		end
	end
end
