-----------------------
--| 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
