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


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
