local E={}do local T={}function T.Create()local E={}local T=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116")local B=nil local u=nil function E.fire(E,...)B={...}u=select("\035",...)T:Fire()end function E.connect(v,E)if not E then error("\099\111\110\110\101\099\116\040\110\105\108\041",2)end return T.Event:connect(function()E(unpack(B,1,u))end)end function E.wait(E)T.Event:wait()assert(B,"\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(B,1,u)end return E end E.Signal=T function E.Create(E)return function(T)local B=Instance.new(E)for E,T in pairs(T)do if type(E)=="\110\117\109\098\101\114"then T.Parent=B else B[E]=T end end return B end end local function B(E,T,B)return math.max(math.min(T,B),E)end E.Clamp=B local function u()local E=workspace.CurrentCamera local T=E and E.ViewportSize.X or 0 local B=E and E.ViewportSize.Y or 0 if T==0 then return 1024 else if T>B then return T else return B end end end E.ViewSizeX=u local function v()local E=workspace.CurrentCamera local T=E and E.ViewportSize.X or 0 local B=E and E.ViewportSize.Y or 0 if B==0 then return 768 else if T>B then return B else return T end end end E.ViewSizeY=v local function S()return u()/v()end E.AspectRatio=S local function Z(E)if E then local T=E:FindFirstChild("\072\117\109\097\110\111\105\100")if T then return E,T else return Z(E.Parent)end end end E.FindChacterAncestor=Z local function R(E,T,B,u,v)return v:ScreenPointToRay(E,T)end E.GetUnitRay=R local K=workspace.FindPartOnRayWithIgnoreList local function s(E,T,B)local u=B or{}local v,S=K(workspace,E,u)if v then if T and v.CanCollide==false then table.insert(u,v)return s(E,T,u)end return v,S end return nil,nil end E.Raycast=s E.Round=function(E,T)T=T or 1 return math.floor((E+T/2)/T)*T end local function Y(E)local T=Vector2.new(0,0)if#E>0 then for B=1,#E,1 do T=T+E[B]end T=T/#E end return T end E.AveragePoints=Y local function b(E,T)return E+.1>T and E-.1<T end E.FuzzyEquals=b local o=0 UIS.InputBegan:connect(function(E,T)if not T then if E.UserInputType==Enum.UserInputType.Touch or E.UserInputType==Enum.UserInputType.MouseButton1 or E.UserInputType==Enum.UserInputType.MouseButton2 then o=tick()end end end)E.GetLastInput=function()return o end end local T={}local function B(E)local B=E and E.Character if B then local u=T[E]if u and u.Parent==B then return u else T[E]=nil for B,u in pairs(B:GetChildren())do if u:IsA("\072\117\109\097\110\111\105\100")then T[E]=u return u end end end end end local function u(E,T)local B=CFrame.fromAxisAngle local u=(CFrame.new()).components local v=(CFrame.new()).inverse local S=Vector3.new local Z=math.acos local R=math.sqrt local K=1/math.sqrt(2)local s,Y,b,o,L,m,r,k,d,O,j,Q=u(v(E)*T)local X=(((o+k)+Q)-1)/2 local l=S(j-d,m-O,r-L)local D=T.p-E.p local t if X>=.999 then return 0,function(T)return E+D*T end elseif X<=-0.999 then t=math.pi o=(o+1)/2 k=(k+1)/2 Q=(Q+1)/2 if o>k and o>Q then if o<.001 then l=S(0,K,K)else local E=R(o)r=(r+L)/4 O=(O+m)/4 l=S(E,r/E,O/E)end elseif k>Q then if k<.001 then l=S(K,0,K)else local E=R(k)r=(r+L)/4 j=(j+d)/4 l=S(r/E,E,j/E)end else if Q<.001 then l=S(K,K,0)else local E=R(Q)O=(O+m)/4 j=(j+d)/4 l=S(O/E,j/E,E)end end else t=Z(X)end return t,function(T)return E*B(l,t*T)+D*T end end

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 clamp(low, high, num)
		return math.max(math.min(high, num), low)
	end
	Utility.Clamp = clamp

	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 RayCastIgnoreList = workspace.FindPartOnRayWithIgnoreList
	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 = Vector2.new(0,0)
		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
			for _, child in pairs(character:GetChildren()) do
				if child:IsA('Humanoid') then
					humanoidCache[player] = child
					return child
				end
			end
		end
	end
end

local function CFrameInterpolator(c0, c1) -- (CFrame from, CFrame to) -> (float theta, (float fraction -> CFrame between))
	local fromAxisAngle = CFrame.fromAxisAngle
	local components = CFrame.new().components
	local inverse = CFrame.new().inverse
	local v3 = Vector3.new
	local acos = math.acos
	local sqrt = math.sqrt
	local invroot2 = 1 / math.sqrt(2)
	-- The expanded matrix
	local _, _, _, xx, yx, zx,
	               xy, yy, zy,
	               xz, yz, zz = components(inverse(c0)*c1)
	-- The cos-theta of the axisAngles from
	local cosTheta = (xx + yy + zz - 1)/2
	-- Rotation axis
	local rotationAxis = v3(yz-zy, zx-xz, xy-yx)
	-- The position to tween through
	local positionDelta = (c1.p - c0.p)
	-- Theta
	local theta;
	-- Catch degenerate cases
	if cosTheta >= 0.999 then
		-- Case same rotation, just return an interpolator over the positions
		return 0, function(t)
			return c0 + positionDelta*t
		end
	elseif cosTheta <= -0.999 then
		-- Case exactly opposite rotations, disambiguate
		theta = math.pi
		xx = (xx + 1) / 2
		yy = (yy + 1) / 2
		zz = (zz + 1) / 2
		if xx > yy and xx > zz then
			if xx < 0.001 then
				rotationAxis = v3(0, invroot2, invroot2)
			else
				local x = sqrt(xx)
				xy = (xy + yx) / 4
				xz = (xz + zx) / 4
				rotationAxis = v3(x, xy/x, xz/x)
			end
		elseif yy > zz then
			if yy < 0.001 then
				rotationAxis = v3(invroot2, 0, invroot2)
			else
				local y = sqrt(yy)
				xy = (xy + yx) / 4
				yz = (yz + zy) / 4
				rotationAxis = v3(xy/y, y, yz/y)
			end
		else
			if zz < 0.001 then
				rotationAxis = v3(invroot2, invroot2, 0)
			else
				local z = sqrt(zz)
				xz = (xz + zx) / 4
				yz = (yz + zy) / 4
				rotationAxis = v3(xz/z, yz/z, z)
			end
		end
	else
		-- Normal case, get theta from cosTheta
		theta = acos(cosTheta)
	end
	-- Return the interpolator
	return theta, function(t)
		return c0*fromAxisAngle(rotationAxis, theta*t) + positionDelta*t
	end
end