local function B(B)if B.Magnitude==0 then return Vector3.zero end return B.Unit end return function(G,R,p)debug.profilebegin("\082\111\116\097\116\105\111\110 \067\111\110\115\116\114\097\105\110\116")local r=G.ParentIndex local c=p.Bones[r]if not c then debug.profileend()return R end local j=c.RotationLimit if j>=180 then debug.profileend()return R end local y=p.Bones[c.ParentIndex]if not y then debug.profileend()return R end local W=c.Position local l=B(c.Position-y.Position)local a=(R-W).Magnitude local Y=B(R-W)if j<=0 then debug.profileend()return W+l*a end local f=math.rad(G.RotationLimit)local H=math.acos(l:Dot(Y))local q if H>=f then local G=B(l:Cross(Y))q=CFrame.fromAxisAngle(G,f)*l else q=Y end R=W+q*a debug.profileend()return R end
local function SafeUnit(v3)
	if v3.Magnitude == 0 then
		return Vector3.zero
	end

	return v3.Unit
end

return function(self, Position, BoneTree)
	debug.profilebegin("Rotation Constraint")
	local ParentIndex = self.ParentIndex
	local ParentBone = BoneTree.Bones[ParentIndex]

	if not ParentBone then
		debug.profileend()
		return Position
	end

	local ParentBoneLimit = ParentBone.RotationLimit

	if ParentBoneLimit >= 180 then
		debug.profileend()
		return Position
	end

	local GrandParentBone = BoneTree.Bones[ParentBone.ParentIndex]

	if not GrandParentBone then
		debug.profileend()
		return Position
	end

	local ParentBonePosition = ParentBone.Position
	local DefaultDirection = SafeUnit(ParentBone.Position - GrandParentBone.Position)

	local DistanceToParent = (Position - ParentBonePosition).Magnitude
	local DirectionToSelf = SafeUnit(Position - ParentBonePosition)

	if ParentBoneLimit <= 0 then
		debug.profileend()
		return ParentBonePosition + DefaultDirection * DistanceToParent
	end

	local RotationLimit = math.rad(self.RotationLimit)
	local VectorAngle = math.acos(DefaultDirection:Dot(DirectionToSelf))
	local LimitedVector

	if VectorAngle >= RotationLimit then
		local Cross = SafeUnit(DefaultDirection:Cross(DirectionToSelf))
		LimitedVector = CFrame.fromAxisAngle(Cross, RotationLimit) * DefaultDirection
	else
		LimitedVector = DirectionToSelf
	end

	Position = ParentBonePosition + LimitedVector * DistanceToParent

	debug.profileend()
	return Position
end
