local function h(h)for n,i in pairs(TrackedLimbs)do h[#h+1]=n.Position end end local function n(h)for n=1,MOVE_CASTS,1 do local i,o=HumanoidRootPart.Position,HumanoidRootPart.Velocity local c=(Vector3_new(o.X,0,o.Z)).Magnitude/2 local O=((n-1)*HumanoidRootPart.CFrame.lookVector)*c h[#h+1]=i+O end end local function i(h)local n=HumanoidRootPart.CFrame local i=n.p local o=n-i local c=Character:GetExtentsSize()/2 h[#h+1]=i for n=1,#CORNER_FACTORS,1 do h[#h+1]=i+o*(c*CORNER_FACTORS[n])end end local function o(h)local n=nil if Mode==MODE.CIRCLE1 then n=HumanoidRootPart.CFrame else local h=Camera.CoordinateFrame n=(h-h.p)+HumanoidRootPart.Position end h[#h+1]=n.p for i=0,CIRCLE_CASTS-1,1 do local o=((2*math_pi)/CIRCLE_CASTS)*i local c=3*Vector3_new(math_cos(o),math_sin(o),0)h[#h+1]=n*c end end local function c(i)h(i)n(i)end local function O(h)local n=TorsoPart.CFrame.upVector.unit local i=TorsoPart.CFrame.rightVector.unit h[#h+1]=TorsoPart.CFrame.p h[#h+1]=TorsoPart.CFrame.p+n h[#h+1]=TorsoPart.CFrame.p-n h[#h+1]=TorsoPart.CFrame.p+i h[#h+1]=TorsoPart.CFrame.p-i if HeadPart then h[#h+1]=HeadPart.CFrame.p end local o=CFrame.new(ZERO_VECTOR3,Vector3_new(Camera.CoordinateFrame.lookVector.X,0,Camera.CoordinateFrame.lookVector.Z))local c=TorsoPart and TorsoPart.Position or HumanoidRootPart.Position local O={TorsoPart}if HeadPart then O[#O+1]=HeadPart end for n=1,CHAR_OUTLINE_CASTS,1 do local i=((2*math_pi)*n)/CHAR_OUTLINE_CASTS local l=o*(3*Vector3_new(math_cos(i),math_sin(i),0))l=Vector3_new(l.X,math_max(l.Y,-2.25),l.Z)local L=Ray.new(c+l,-3*l)local E,s=game.Workspace:FindPartOnRayWithWhitelist(L,O,false,false)if E then h[#h+1]=s+.2*(c-s).unit end end end
-----------------------
--| Local Functions |--
-----------------------

local function LimbBehavior(castPoints)
	for limb, _ in pairs(TrackedLimbs) do
		castPoints[#castPoints + 1] = limb.Position
	end
end

local function MoveBehavior(castPoints)
	for i = 1, MOVE_CASTS do
		local position, velocity = HumanoidRootPart.Position, HumanoidRootPart.Velocity
		local horizontalSpeed = Vector3_new(velocity.X, 0, velocity.Z).Magnitude / 2
		local offsetVector = (i - 1) * HumanoidRootPart.CFrame.lookVector * horizontalSpeed
		castPoints[#castPoints + 1] = position + offsetVector
	end
end

local function CornerBehavior(castPoints)
	local cframe = HumanoidRootPart.CFrame
	local centerPoint = cframe.p
	local rotation = cframe - centerPoint
	local halfSize = Character:GetExtentsSize() / 2 --NOTE: Doesn't update w/ limb animations
	castPoints[#castPoints + 1] = centerPoint
	for i = 1, #CORNER_FACTORS do
		castPoints[#castPoints + 1] = centerPoint + (rotation * (halfSize * CORNER_FACTORS[i]))
	end
end

local function CircleBehavior(castPoints)
	local cframe = nil
	if Mode == MODE.CIRCLE1 then
		cframe = HumanoidRootPart.CFrame
	else
		local camCFrame = Camera.CoordinateFrame
		cframe = camCFrame - camCFrame.p + HumanoidRootPart.Position
	end
	castPoints[#castPoints + 1] = cframe.p
	for i = 0, CIRCLE_CASTS - 1 do
		local angle = (2 * math_pi / CIRCLE_CASTS) * i
		local offset = 3 * Vector3_new(math_cos(angle), math_sin(angle), 0)
		castPoints[#castPoints + 1] = cframe * offset
	end
end

local function LimbMoveBehavior(castPoints)
	LimbBehavior(castPoints)
	MoveBehavior(castPoints)
end

local function CharacterOutlineBehavior(castPoints)
	local torsoUp = TorsoPart.CFrame.upVector.unit
	local torsoRight = TorsoPart.CFrame.rightVector.unit

	-- Torso cross of points for interior coverage
	castPoints[#castPoints + 1] = TorsoPart.CFrame.p
	castPoints[#castPoints + 1] = TorsoPart.CFrame.p + torsoUp
	castPoints[#castPoints + 1] = TorsoPart.CFrame.p - torsoUp
	castPoints[#castPoints + 1] = TorsoPart.CFrame.p + torsoRight
	castPoints[#castPoints + 1] = TorsoPart.CFrame.p - torsoRight
	if HeadPart then
		castPoints[#castPoints + 1] = HeadPart.CFrame.p
	end

	local cframe = CFrame.new(
		ZERO_VECTOR3,
		Vector3_new(Camera.CoordinateFrame.lookVector.X, 0, Camera.CoordinateFrame.lookVector.Z)
	)
	local centerPoint = (TorsoPart and TorsoPart.Position or HumanoidRootPart.Position)

	local partsWhitelist = { TorsoPart }
	if HeadPart then
		partsWhitelist[#partsWhitelist + 1] = HeadPart
	end

	for i = 1, CHAR_OUTLINE_CASTS do
		local angle = (2 * math_pi * i / CHAR_OUTLINE_CASTS)
		local offset = cframe * (3 * Vector3_new(math_cos(angle), math_sin(angle), 0))

		offset = Vector3_new(offset.X, math_max(offset.Y, -2.25), offset.Z)

		local ray = Ray.new(centerPoint + offset, -3 * offset)
		local hit, hitPoint = game.Workspace:FindPartOnRayWithWhitelist(ray, partsWhitelist, false, false)

		if hit then
			-- Use hit point as the cast point, but nudge it slightly inside the character so that bumping up against
			-- walls is less likely to cause a transparency glitch
			castPoints[#castPoints + 1] = hitPoint + 0.2 * (centerPoint - hitPoint).unit
		end
	end
end
