--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--
--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--
--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--
--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--
--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--


module.getQueueFunction = function(character)
	-- Get all the base parts and values needed to further calculate everything
	local humanoid		=character:WaitForChild("Humanoid")
	local rootpart		=character:WaitForChild("HumanoidRootPart")
	local uppertorso	=character:WaitForChild("UpperTorso")
	local lowertorso	=character:WaitForChild("LowerTorso")
	local waistjoint	=uppertorso:WaitForChild("Waist")
	local rootjoint		=lowertorso:WaitForChild("Root")
	local root0			=rootjoint.C0
	local root1			=rootjoint.C1
	local waist1		=waistjoint.C1
	
	local rightupperleg	=character:WaitForChild("RightUpperLeg")
	local rightlowerleg	=character:WaitForChild("RightLowerLeg")
	local leftupperleg	=character:WaitForChild("LeftUpperLeg")
	local leftlowerleg	=character:WaitForChild("LeftLowerLeg")
	local righthip		=rightupperleg:WaitForChild("RightHip")
	local rightknee		=rightlowerleg:WaitForChild("RightKnee")
	local lefthip		=leftupperleg:WaitForChild("LeftHip")
	local leftknee		=leftlowerleg:WaitForChild("LeftKnee")
	local righthip0		=righthip.C0
	local rightknee0	=rightknee.C0
	local lefthip0		=lefthip.C0
	local leftknee0		=leftknee.C0
	--
	
	local direction		= V3(1,0,1) -- This will be changed
	local stride		= 2.3 -- Changes how far the legs move
	local cycleSpeed	= 14 -- How fast the leg-movement cycle is. Change this to suit your needs!
	local left,right	= 0,math.pi -- Initial rotations
	
	local strideCF		= CF(0,0,-stride/2) -- Turn that stride number into a CFrame we can use
	
	local raycastParams = RaycastParams.new() -- Used for raycasting
	raycastParams.FilterDescendantsInstances = {character}
	raycastParams.IgnoreWater = true
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	
	--
	
	return function(dt) -- dt, or delta, is the amount of time passed between render frames. 1/dt = frames per second
		local dt10		=math.min(dt*10,1) -- Normalize dt for our needs
		
		local lowercf	=lowertorso.CFrame -- Our position
		local rootcf	=rootpart.CFrame -- Another position
		local rootvel0	=rootpart.Velocity -- Our movement velocity
		local rootvel,rootvelm
		local climbing	=humanoid:GetState()==Enum.HumanoidStateType.Climbing -- Are we climbing?
		
		--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--
		--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--
		
		if climbing then -- Don't animate if we are climbing, it looks weird
			rootvel		=rootvel0
			rootvelm	=rootvel.Magnitude
			direction	=rootcf.lookVector
		else
			rootvel		=rootvel0*x_and_y
			rootvelm	=rootvel.Magnitude
			
			if rootvelm>0.1 then
				direction	=direction:Lerp(rootvel.unit, dt10)
			end
		end
		
		--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--
		--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--
		
		local up		=rootvelm/16
		local cycle		=up*dt*cycleSpeed
		right			=(right+cycle)%tau
		left			=(left+cycle)%tau
		
		--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--
		--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--
		
		if rootvelm>0.1 then --// When moving
			-- Relative Velocity
			local relv0		=lowercf:vectorToObjectSpace(rootvel)
			local relv1		=relv0*0.2
			local relvx		=relv0.X/rootvel.Magnitude
			
			do -- Upper Torso
				waistjoint.C1	=waistjoint.C1:Lerp(waist1*ANGLES(math.rad(relv1.Z),0.1*math.cos(right)-2*math.rad(relv1.X),math.rad(-relv1.X)):inverse(),dt10)		
			end
			
			do -- Right Leg
				local hip			=(rootcf*rhipcf).p
				local ground		=(rootcf*rhipcf2).p
				local desiredPos	=(CF(ground, ground+direction)*ANGLES(-right, 0, 0)*strideCF).p
				local offset		=(desiredPos-hip)
				local raycastResult = workspace:Raycast(hip,offset.unit*(offset.magnitude+0.5),raycastParams)
				local footPos = raycastResult and raycastResult.Position or (hip + offset.unit*(offset.magnitude+0.5))
				
				local plane,th1,th2		=solveLegIK(lowercf*righthip0,footPos, 0.55,1.15) -- 0.55,1.15
				righthip.C0				=righthip.C0:Lerp(lowercf:toObjectSpace(plane)*ANGLES(th1,0,0),0.25)
				rightknee.C0			=rightknee.C0:Lerp(rightknee0*ANGLES(th2,0,0),0.25)
			end
			
			do-- Left Leg
				local hip			=(rootcf*lhipcf).p
				local ground 		=(rootcf*lhipcf2).p
				local desiredPos	=(CF(ground, ground+direction)*ANGLES(-left, 0, 0)*strideCF).p
				local offset		=(desiredPos-hip)
				local raycastResult = workspace:Raycast(hip,offset.unit*(offset.magnitude+0.5),raycastParams)
				local footPos = raycastResult and raycastResult.Position or (hip + offset.unit*(offset.magnitude+0.5))
				
				local plane,th1,th2		=solveLegIK(lowercf*lefthip0,footPos, 0.55,1.15)
				lefthip.C0				=lefthip.C0:Lerp(lowercf:toObjectSpace(plane)*ANGLES(th1,0,0),0.25)
				leftknee.C0				=leftknee.C0:Lerp(leftknee0*ANGLES(th2,0,0),0.25)
			end
			
			--|||||||||||--
			--|||||||||||--
			
		else --// When not moving
			-- Upper Torso
			waistjoint.C1	=waistjoint.C1:Lerp(waist1, dt10)
			
			do -- Right Leg
				local hipcf			=(rootcf*rhipcf)
				local hip			=hipcf.p
				local desiredPos	=(hipcf*rIdle).p
				local offset		=(desiredPos-hip)
				local raycastResult = workspace:Raycast(hip,offset.unit*(offset.magnitude+0.5),raycastParams)
				local footPos = raycastResult and raycastResult.Position or (hip + offset.unit*(offset.magnitude+0.5))
				
				local plane,th1,th2		=solveLegIK(lowercf*righthip0,footPos, 0.55,1.15)
				righthip.C0				=righthip.C0:Lerp(lowercf:toObjectSpace(plane)*ANGLES(th1,0,0),0.25)
				rightknee.C0			=rightknee.C0:Lerp(rightknee0*ANGLES(th2,0,0),0.25)
			end
			
			do -- Left Leg
				local hipcf			=(rootcf*lhipcf)
				local hip			=hipcf.p
				local desiredPos	=(hipcf*lIdle).p
				local offset		=(desiredPos-hip)
				local raycastResult = workspace:Raycast(hip,offset.unit*(offset.magnitude+0.5),raycastParams)
				local footPos = raycastResult and raycastResult.Position or (hip + offset.unit*(offset.magnitude+0.5))
				
				local plane,th1,th2		=solveLegIK(lowercf*lefthip0,footPos, 0.55,1.15)
				lefthip.C0				=lefthip.C0:Lerp(lowercf:toObjectSpace(plane)*ANGLES(th1,0,0),0.25)
				leftknee.C0				=leftknee.C0:Lerp(leftknee0*ANGLES(th2,0,0),0.25)
			end
			
			--|||||||||||--
			--|||||||||||--
		end
	end
	
	--
end

return module
