local g=require((game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")):WaitForChild("\078\101\118\101\114\109\111\114\101"))local C=g("\081\117\097\116\101\114\110\105\111\110")local Q=math.pi local D=math.atan2 local q,S=math.exp,math.log local W,z=math.cos,math.sin local X=math.acos local function t(g)local C=getmetatable(g)if type(C)=="\116\097\098\108\101"and C.__type~=nil then return C.__type else return type(g)end end local R={}local L={__type="\113\117\097\116\101\114\110\105\111\110"}local x={"\119","\120","\121";"\122"}function L.__index(g,C)return g[x[C]]end local function v(g,C,Q,D)return setmetatable({w=g or 1;x=C or 0,y=Q or 0,z=D or 0},L)end R.new=v local function s(g)return v(C.QuaternionFromCFrame(g))end R.fromCFrame=s local function n(g,Q)local D,q,S=0,0,0 if Q then D,q,S=Q.x,Q.y,Q.z end return CFrame.new(D,q,S,C.QuaternionToCFrame(g))end R.toCFrame=n local function p(g)local C,Q,D,q=g.w,g.x,g.y,g.z local S=((C*C+Q*Q)+D*D)+q*q if S>0 then return v(C/S,-Q/S,-D/S,-q/S)else return v(0)end end R.inv=p local function J(g)return v(-g.w,-g.x,-g.y,-g.z)end L.__unm=J R.unm=J local function f(g,C)local Q,D=t(g),t(C)if Q=="\113\117\097\116\101\114\110\105\111\110"and D=="\113\117\097\116\101\114\110\105\111\110"then return v(g.w+C.w,g.x+C.x,g.y+C.y,g.z+C.z)elseif Q=="\113\117\097\116\101\114\110\105\111\110"and D=="\110\117\109\098\101\114"then return v(g.w+C,g.x,g.y,g.z)elseif Q=="\110\117\109\098\101\114"and D=="\113\117\097\116\101\114\110\105\111\110"then return v(g+C.w,C.x,C.y,C.z)end end L.__add=f R.add=f local function e(g,C)local Q,D=t(g),t(C)if Q=="\113\117\097\116\101\114\110\105\111\110"and D=="\113\117\097\116\101\114\110\105\111\110"then return v(g.w-C.w,g.x-C.x,g.y-C.y,g.z-C.z)elseif Q=="\113\117\097\116\101\114\110\105\111\110"and D=="\110\117\109\098\101\114"then return v(g.w-C,g.x,g.y,g.z)elseif Q=="\110\117\109\098\101\114"and D=="\113\117\097\116\101\114\110\105\111\110"then return v(g-C.w,-C.x,-C.y,-C.z)end end L.__sub=e R.sub=e local function b(g,C)local Q,D=t(g),t(C)if Q=="\113\117\097\116\101\114\110\105\111\110"and D=="\113\117\097\116\101\114\110\105\111\110"then local Q,D,q,S,W,z,X,t=g.w,g.x,g.y,g.z,C.w,C.x,C.y,C.z return v(((Q*W-D*z)-q*X)-S*t,((Q*z+D*W)+q*t)-S*X,((Q*X-D*t)+q*W)+S*z,((Q*t+D*X)-q*z)+S*W)elseif Q=="\113\117\097\116\101\114\110\105\111\110"and D=="\110\117\109\098\101\114"then return v(g.w*C,g.x*C,g.y*C,g.z*C)elseif Q=="\110\117\109\098\101\114"and D=="\113\117\097\116\101\114\110\105\111\110"then return v(g*C.w,g*C.x,g*C.y,g*C.z)end end L.__mul=b R.mul=b local function c(g,C)local Q,D=t(g),t(C)if Q=="\113\117\097\116\101\114\110\105\111\110"and D=="\113\117\097\116\101\114\110\105\111\110"then local Q,D,q,S,W,z,X,t=g.w,g.x,g.y,g.z,C.w,C.x,C.y,C.z local R=((W*W+z*z)+X*X)+t*t if R>0 then return v((((W*Q+z*D)+X*q)+t*S)/R,(((W*D-z*Q)-X*S)+t*q)/R,(((W*q+z*S)-X*Q)-t*D)/R,(((W*S-z*q)+X*D)-t*Q)/R)else return v(0)end elseif Q=="\113\117\097\116\101\114\110\105\111\110"and D=="\110\117\109\098\101\114"then return v(g.w/C,g.x/C,g.y/C,g.z/C)elseif Q=="\110\117\109\098\101\114"and D=="\113\117\097\116\101\114\110\105\111\110"then local Q,D,q,S=C.w,C.x,C.y,C.z local W=((Q*Q+D*D)+q*q)+S*S if W>0 then local C=g/W return v(C*Q,-C*D,-C*q,-C*S)else return v(0)end end end L.__div=c R.div=c local function r(g,C)local R,L=t(g),t(C)if R=="\113\117\097\116\101\114\110\105\111\110"and L=="\113\117\097\116\101\114\110\105\111\110"then local Q,D,t,R=g.w,g.x,g.y,g.z local L=(D*D+t*t)+R*R local x=Q*Q+L if x>0 then if L>0 then local g=x^.5 local C=X(Q/g)/L^.5 Q,D,t,R=S(g),D*C,t*C,R*C else Q,D,t,R=S(x)/2,0,0,0 end else Q,D,t,R=-math.huge,0,0,0 end local s,n,p,J=C.w,C.x,C.y,C.z local f=q(((Q*s-D*n)-t*p)-R*J)local e,b,c=((Q*n+D*s)+t*J)-R*p,((Q*p-D*J)+t*s)+R*n,((Q*J+D*p)-t*n)+R*s local r=(e*e+b*b)+c*c if r>0 then local g=r^.5 local C=(f*z(g))/g return v(f*W(g),e*C,b*C,c*C)else return v(f)end elseif R=="\113\117\097\116\101\114\110\105\111\110"and L=="\110\117\109\098\101\114"then local q,S,X,t=g.w,g.x,g.y,g.z local R=(S*S+X*X)+t*t if R>0 then local g=R^.5 local Q=(q*q+R)^(C/2)local L=C*D(g,q)local x=(Q*z(L))/g return v(Q*W(L),S*x,X*x,t*x)else if q<0 then local g=(-q)^C local D=(g*z(Q*C))*.57735026918963 return v(g*W(Q*C),D,D,D)else return v(q^C)end end elseif R=="\110\117\109\098\101\114"and L=="\113\117\097\116\101\114\110\105\111\110"then local D,q,S,X=C.w,C.x,C.y,C.z if g>0 then local C=g^D local Q=(q*q+S*S)+X*X if Q>0 then local g=Q^.5 local D=(C*z(g))/g return v(C*W(g),q*D,S*D,X*D)else return v(C)end elseif g<0 then local C=(-g)^D local t=(q*q+S*S)+X*X local R,L=C*W(Q*D),C*z(Q*D)if t>0 then local g=t^.5 local C,Q=W(g),z(g)/g local D,x=R*Q,(L*C)*.57735026918963 return v(R*C-L*Q,D*q+x,D*S+x,D*X+x)else warn("\072\105\116\116\105\110\103 \119\101\105\114\100 \113\117\097\116\101\114\110\105\111\110 \101\100\103\101 \099\097\115\101\033")return v(nil,nil,nil,nil)end elseif((D*D+q*q)+S*S)+X*X>0 then return v(0)else return v()end end end L.__pow=r R.pow=r local function i(g)local C,Q,D,q=g.w,g.x,g.y,g.z return(((C*C+Q*Q)+D*D)+q*q)^.5 end L.__len=i R.length=i R.magnitude=i local function B(g,C)C=C or 3 return((("\044 \037\046"..(C.."\102")):rep(4)):sub(3)):format(g.w,g.x,g.y,g.z)end L.__tostring=B R.tostring=B local function A(g)local C,Q,D,q=g.w,g.x,g.y,g.z local W=(Q*Q+D*D)+q*q local z=C*C+W if z>0 then if W>0 then local g=z^.5 local t=X(C/g)/W^.5 return v(S(g),Q*t,D*t,q*t)else return v(S(z)/2)end else return v(-math.huge)end end R.log=A local function j(g)local C=q(g.w)local Q,D,S=g.x,g.y,g.z local X=(Q*Q+D*D)+S*S if X>0 then local g=X^.5 local q=(C*z(g))/g return v(C*W(g),Q*q,D*q,S*q)else return v(C)end end R.exp=j local function I(g)local C,Q,D,q=g.w,g.x,g.y,g.z local S=((C*C+Q*Q)+D*D)+q*q if S>0 then local g=S^.5 return v(C/g,Q/g,D/g,q/g)else return v()end end R.normalize=I R.unit=I local function G(g)local C,Q,D,q=g.w,g.x,g.y,g.z local S=(Q*Q+D*D)+q*q if S>0 then local g=(C*C+S)^.5 local W=((g-C)/(2*S))^.5 return v(((g+C)/2)^.5,Q*W,D*W,q*W)else return v((C*C)^.25)end end R.sqrt=G return R
--- Quaternion data type object
-- @author xXxMoNkEyMaNxXx
-- @classmod Quaternion

local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore"))

local Quaternion = require("Quaternion")

local pi = math.pi
local atan2 = math.atan2
local exp, log = math.exp, math.log
local cos, sin = math.cos, math.sin
local acos = math.acos

local function TYPE(x)
	local xMet=getmetatable(x)
	if type(xMet)=="table" and xMet.__type~=nil then
		return xMet.__type
	else
		return type(x)
	end
end

local Q={}
local metatable={__type="quaternion"}
local alt={"w","x","y","z"}
function metatable.__index(q,i)
	return q[alt[i]]
end

local function new(w,x,y,z)
	return setmetatable({w=w or 1,x=x or 0,y=y or 0,z=z or 0},metatable)
end
Q.new=new

local function fromCFrame(cframe)
	return new(Quaternion.QuaternionFromCFrame(cframe))
end
Q.fromCFrame = fromCFrame

local function toCFrame(q, position)
	local x, y, z = 0, 0, 0
	if position then
		x, y, z = position.x, position.y, position.z
	end
	return CFrame.new(x, y, z, Quaternion.QuaternionToCFrame(q))
end
Q.toCFrame = toCFrame

local function inv(q)
	local w,x,y,z=q.w,q.x,q.y,q.z
	local m=w*w+x*x+y*y+z*z
	if m>0 then
		return new(w/m,-x/m,-y/m,-z/m)
	else
		return new(0)
	end
end
Q.inv=inv

--Unary minus; -q
local function unm(q)
	return new(-q.w,-q.x,-q.y,-q.z)
end
metatable.__unm=unm
Q.unm=unm
local function add(q0,q1)
	local t0,t1=TYPE(q0),TYPE(q1)
	if t0=="quaternion" and t1=="quaternion" then
		return new(q0.w+q1.w,q0.x+q1.x,q0.y+q1.y,q0.z+q1.z)
	elseif t0=="quaternion" and t1=="number" then
		return new(q0.w+q1,q0.x,q0.y,q0.z)
	elseif t0=="number" and t1=="quaternion" then
		return new(q0+q1.w,q1.x,q1.y,q1.z)
	end
end
metatable.__add=add
Q.add=add
local function sub(q0,q1)
	local t0,t1=TYPE(q0),TYPE(q1)
	if t0=="quaternion" and t1=="quaternion" then
		return new(q0.w-q1.w,q0.x-q1.x,q0.y-q1.y,q0.z-q1.z)
	elseif t0=="quaternion" and t1=="number" then
		return new(q0.w-q1,q0.x,q0.y,q0.z)
	elseif t0=="number" and t1=="quaternion" then
		return new(q0-q1.w,-q1.x,-q1.y,-q1.z)
	end
end
metatable.__sub=sub
Q.sub=sub
local function mul(q0,q1)
	local t0,t1=TYPE(q0),TYPE(q1)
	if t0=="quaternion" and t1=="quaternion" then
		local w0,x0,y0,z0,w1,x1,y1,z1=q0.w,q0.x,q0.y,q0.z,q1.w,q1.x,q1.y,q1.z
		return new(w0*w1-x0*x1-y0*y1-z0*z1,w0*x1+x0*w1+y0*z1-z0*y1,w0*y1-x0*z1+y0*w1+z0*x1,w0*z1+x0*y1-y0*x1+z0*w1)
	elseif t0=="quaternion" and t1=="number" then
		return new(q0.w*q1,q0.x*q1,q0.y*q1,q0.z*q1)
	elseif t0=="number" and t1=="quaternion" then
		return new(q0*q1.w,q0*q1.x,q0*q1.y,q0*q1.z)
	end
end
metatable.__mul=mul
Q.mul=mul
local function div(q0,q1)
	local t0,t1=TYPE(q0),TYPE(q1)
	if t0=="quaternion" and t1=="quaternion" then
		local w0,x0,y0,z0,w1,x1,y1,z1=q0.w,q0.x,q0.y,q0.z,q1.w,q1.x,q1.y,q1.z
		local m1=w1*w1+x1*x1+y1*y1+z1*z1
		if m1>0 then--This is the quaternion that gets you from q1 to q0 from q1: mul(inv(q1),q0).  (quaternion division is actually ambiguous)
			return new((w1*w0+x1*x0+y1*y0+z1*z0)/m1,(w1*x0-x1*w0-y1*z0+z1*y0)/m1,(w1*y0+x1*z0-y1*w0-z1*x0)/m1,(w1*z0-x1*y0+y1*x0-z1*w0)/m1)
		else
			return new(0)
		end
	elseif t0=="quaternion" and t1=="number" then
		return new(q0.w/q1,q0.x/q1,q0.y/q1,q0.z/q1)
	elseif t0=="number" and t1=="quaternion" then
		local w1,x1,y1,z1=q1.w,q1.x,q1.y,q1.z
		local m1=w1*w1+x1*x1+y1*y1+z1*z1
		if m1>0 then
			local m=q0/m1
			return new(m*w1,-m*x1,-m*y1,-m*z1)
		else
			return new(0)
		end
	end
end
metatable.__div=div
Q.div=div
local function pow(q0,q1)
	local t0,t1=TYPE(q0),TYPE(q1)
	if t0=="quaternion" and t1=="quaternion" then
		local w0,x0,y0,z0=q0.w,q0.x,q0.y,q0.z
		local vv=x0*x0+y0*y0+z0*z0
		local mm=w0*w0+vv
		if mm>0 then
			if vv>0 then
				local m=mm^0.5
				local s=acos(w0/m)/vv^0.5
				w0,x0,y0,z0=log(m),x0*s,y0*s,z0*s
			else
				w0,x0,y0,z0=log(mm)/2,0,0,0
			end
		else
			w0,x0,y0,z0=-math.huge,0,0,0
		end
		local w1,x1,y1,z1=q1.w,q1.x,q1.y,q1.z
		local m=exp(w0*w1-x0*x1-y0*y1-z0*z1)
		local x,y,z=w0*x1+x0*w1+y0*z1-z0*y1,w0*y1-x0*z1+y0*w1+z0*x1,w0*z1+x0*y1-y0*x1+z0*w1
		local vv=x*x+y*y+z*z
		if vv>0 then
			local v=vv^0.5
			local s=m*sin(v)/v
			return new(m*cos(v),x*s,y*s,z*s)
		else
			return new(m)
		end
	elseif t0=="quaternion" and t1=="number" then
		local w,x,y,z=q0.w,q0.x,q0.y,q0.z
		local vv=x*x+y*y+z*z
		if vv>0 then
			local v=vv^0.5
			local m=(w*w+vv)^(q1/2)
			local theta=q1*atan2(v,w)
			local s=m*sin(theta)/v
			return new(m*cos(theta),x*s,y*s,z*s)
		else
			if w<0 then
				local m=(-w)^q1
				local s=m*sin(pi*q1)*0.57735026918962576450914878050196--3^-0.5
				return new(m*cos(pi*q1),s,s,s)
			else
				return new(w^q1)
			end
		end
	elseif t0=="number" and t1=="quaternion" then
		local w,x,y,z=q1.w,q1.x,q1.y,q1.z
		if q0>0 then
			local m=q0^w
			local vv=x*x+y*y+z*z
			if vv>0 then
				local v=vv^0.5
				local s=m*sin(v)/v
				return new(m*cos(v),x*s,y*s,z*s)
			else
				return new(m)
			end
		elseif q0<0 then--Not a good idea to use this.
			local m=(-q0)^w
			local vv=x*x+y*y+z*z
			local mc,ms=m*cos(pi*w),m*sin(pi*w)
			if vv>0 then
				local v=vv^0.5
				local c,s=cos(v),sin(v)/v
				local vc,vs=mc*s,ms*c*0.57735026918962576450914878050196
				return new(mc*c-ms*s,vc*x+vs,vc*y+vs,vc*z+vs)--This is probably TERRIBLY wrong, but raising a negative number to the power of a quaternion is ill-defined in the first place.
			else
				--- No idea why this is broken! Weird edge case!
				warn("Hitting weird quaternion edge case!")
				return new(nil, nil, nil, nil)
				--return new(c,s,s,s)
			end
		elseif w*w+x*x+y*y+z*z>0 then
			return new(0)
		else
			return new()--anyeting to da powa of 0 is 1 dud
		end
	end
end
metatable.__pow=pow
Q.pow=pow
local function length(q)
	local w,x,y,z=q.w,q.x,q.y,q.z
	return (w*w+x*x+y*y+z*z)^0.5
end
metatable.__len=length
Q.length=length
Q.magnitude=length
local function Qtostring(q,precision)
	precision=precision or 3
	return (", %."..precision.."f"):rep(4):sub(3):format(q.w,q.x,q.y,q.z)
end
metatable.__tostring=Qtostring
Q.tostring=Qtostring

local function Qlog(q)
	local w,x,y,z=q.w,q.x,q.y,q.z
	local vv=x*x+y*y+z*z
	local mm=w*w+vv
	if mm>0 then
		if vv>0 then
			local m=mm^0.5
			local s=acos(w/m)/vv^0.5
			return new(log(m),x*s,y*s,z*s)
		else
			return new(log(mm)/2)--lim v->0 x/v*acos(a/(a*a+v*v)^0.5)=0 when a is positive
		end
	else
		return new(-math.huge)
	end
end
Q.log=Qlog

local function Qexp(q)
	local m=exp(q.w)
	local x,y,z=q.x,q.y,q.z
	local vv=x*x+y*y+z*z
	if vv>0 then
		local v=vv^0.5
		local s=m*sin(v)/v
		return new(m*cos(v),x*s,y*s,z*s)
	else
		return new(m)
	end
end
Q.exp=Qexp

local function Qnormalize(q)
	local w,x,y,z=q.w,q.x,q.y,q.z
	local mm=w*w+x*x+y*y+z*z
	if mm>0 then
		local m=mm^0.5
		return new(w/m,x/m,y/m,z/m)
	else
		return new()
	end
end
Q.normalize=Qnormalize
Q.unit=Qnormalize

local function Qsqrt(q)
	local w,x,y,z=q.w,q.x,q.y,q.z
	local vv=x*x+y*y+z*z
	if vv>0 then
		local m=(w*w+vv)^0.5
		local s=((m-w)/(2*vv))^0.5
		return new(((m+w)/2)^0.5,x*s,y*s,z*s)
	else
		return new((w*w)^0.25)
	end
end
Q.sqrt=Qsqrt

return Q
