-- << FUNCTIONS >>
function module:UpdateHipHeight(character)
	--[[
	local hrp = character:FindFirstChild("HumanoidRootPart")
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	local leftFoot = character:FindFirstChild("LeftFoot")
	if hrp and humanoid and leftFoot then
		local bottomOfHumanoidRootPart = hrp.Position.Y - (1/2 * hrp.Size.Y)
		local bottomOfFoot = leftFoot.Position.Y - (1/2 * leftFoot.Size.Y) -- Left or right. Chose left arbitrarily
		local newHipHeight = bottomOfHumanoidRootPart - bottomOfFoot
		humanoid.HipHeight = newHipHeight
	end
	--]]
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if humanoid then
		local leftFoot = character:FindFirstChild("LeftFoot")
		if leftFoot then
			humanoid:BuildRigFromAttachments()
		else
			humanoid.HipHeight = 0
		end
	end
end
function module:ChangeAllBodyColors(plr, newColor)
	local humanoid = main:GetModule("cf"):GetHumanoid(plr)
	if humanoid then
		local desc = humanoid:GetAppliedDescription()
		desc.HeadColor = newColor
		desc.LeftArmColor = newColor
		desc.RightArmColor = newColor
		desc.LeftLegColor = newColor
		desc.RightLegColor = newColor
		desc.TorsoColor = newColor
		pcall(function() humanoid:ApplyDescription(desc) end)
		if plr.Character:FindFirstChild("FakeHead") then
			for a,b in pairs(plr.Character:GetChildren()) do
				if string.sub(b.Name,1,4) == "Fake" and b:IsA("BasePart") then
					b.Color = newColor
				end
			end
		end
	end
end

function module:ChangeProperty(plr, propertyName, propertyValue)
	local humanoid = main:GetModule("cf"):GetHumanoid(plr)
	if humanoid then
		local desc = humanoid:GetAppliedDescription()
		desc[propertyName] = propertyValue
		pcall(function() humanoid:ApplyDescription(desc) end)
	end
end

function module:ChangeProperties(plr, properties)
	local humanoid = main:GetModule("cf"):GetHumanoid(plr)
	if humanoid then
		--[[
		local desc = humanoid:GetAppliedDescription()
		for pName, pValue in pairs(properties) do
			desc[pName] = pValue
		end
		pcall(function() humanoid:ApplyDescription(desc) end)--]]
		for a,b in pairs(humanoid:GetChildren()) do
			local targetName = string.lower(b.Name)
			for propName, propValue in pairs(properties) do
				propName = string.lower(propName)
				if string.sub(targetName, -#propName) == propName then
					b.Value = propValue
					break
				end
			end
		end
	end
end

function module:ClearProperty(plr, propertyName)
	local humanoid = main:GetModule("cf"):GetHumanoid(plr)
	if humanoid then
		local desc = humanoid:GetAppliedDescription()
		desc[propertyName] = ""
		pcall(function() humanoid:ApplyDescription(desc) end)
	end
end

function module:ResetProperty(plr, propertyName)
	local humanoid = main:GetModule("cf"):GetHumanoid(plr)
	if humanoid then
		local mainDesc = main.players:GetHumanoidDescriptionFromUserId(plr.UserId)
		local desc = humanoid:GetAppliedDescription()
		desc[propertyName] = mainDesc[propertyName]
		pcall(function() humanoid:ApplyDescription(desc) end)
	end
end

function module:SetScale(plr, scaleType, scaleValue)
	local humanoid = main:GetModule("cf"):GetHumanoid(plr)
	if humanoid then
		local desc = humanoid:GetAppliedDescription()
		desc[scaleType.."Scale"] = scaleValue
		pcall(function() humanoid:ApplyDescription(desc) end)
	end
end

function module:AddAccessory(plr, accessoryId)
	local humanoid = main:GetModule("cf"):GetHumanoid(plr)
	if humanoid then
		local info = main:GetModule("cf"):GetProductInfo(accessoryId)
		if info.AssetTypeId then
			local propertyName = accessoryTypes[info.AssetTypeId]
			if propertyName and info.AssetTypeId then
				local desc = humanoid:GetAppliedDescription()
				desc[propertyName] = desc[propertyName]..","..accessoryId
				pcall(function() humanoid:ApplyDescription(desc) end)
			end
		end
	end
end

function module:ClearAccessories(plr)
	local humanoid = main:GetModule("cf"):GetHumanoid(plr)
	if humanoid then
		local desc = humanoid:GetAppliedDescription()
		for i,v in pairs(accessoryTypes) do
			desc[v] = ""
		end
		desc.HatAccessory = ""
		pcall(function() humanoid:ApplyDescription(desc) end)
	end
end

function module:CreateFakeBodyPart(character, bodyPart)
	local fakePartName = "Fake"..bodyPart.Name
	local fakePart = character:FindFirstChild(fakePartName)
	if not fakePart then
		local mesh = bodyPart:FindFirstChildOfClass("SpecialMesh")
		if bodyPart.Name == "Head" and mesh then
			if mesh.MeshType == Enum.MeshType.Head then
				fakePart = main.server.Assets.FakeHead:Clone()
				local size = bodyPart.Size
				local scaleUp = mesh.Scale.Y/1.25
				fakePart.Size = Vector3.new(size.X*0.6*scaleUp, size.Y*1.2*scaleUp, size.Z*1.19*scaleUp)
				fakePart.CFrame = bodyPart.CFrame * CFrame.new(0, mesh.Offset.Y, 0)
			else
				fakePart = bodyPart:Clone()
				fakePart:ClearAllChildren()
				mesh:Clone().Parent = fakePart
			end
		else
			fakePart = bodyPart:Clone()
			fakePart:ClearAllChildren()
		end
		fakePart.CanCollide = false
		fakePart.Name = "Fake"..bodyPart.Name
		local weld = Instance.new("WeldConstraint")
		weld.Part0 = fakePart
		weld.Part1 = bodyPart
		weld.Parent = fakePart
		bodyPart.Transparency = 1
		fakePart.Parent = character
	end
	fakePart.Color = bodyPart.Color
	return fakePart
end

function module:ClearFakeBodyParts(character)
	for a,b in pairs(character:GetChildren()) do
		if b:IsA("BasePart") then
			if string.sub(b.Name, 1, 4) == "Fake" then
				b:Destroy()
			elseif b.Name ~= "HumanoidRootPart" then
				b.Transparency = 0
			end
		end
	end
end

function module:SetHeadMeshSize(plr, scale)
	local head = main:GetModule("cf"):GetHead(plr)
	if head then
		local mesh = head:FindFirstChildOfClass("SpecialMesh")
		if mesh then
			local osize = mesh:FindFirstChild("OriginalSize")
			if not osize then
				osize = Instance.new("Vector3Value")
				osize.Name = "OriginalSize"
				osize.Value = mesh.Scale
				osize.Parent = mesh
			end
			main:GetModule("MorphHandler"):ClearAccessories(plr)
			mesh.Scale = Vector3.new(osize.Value.X*scale.X, osize.Value.Y*scale.Y, osize.Value.Z*scale.Z)
			local yOffset = 0
			if scale.Y == 0.75 then
				yOffset = -0.15
			elseif scale.Y == 2 then
				yOffset = 0.45
			end
			mesh.Offset = Vector3.new(0, yOffset, 0)
		end
	end
end

function module:ChangeFace(char, faceId)
	local head = char:FindFirstChild("Head")
	if head then
		local face = head:FindFirstChild("face")
		if face then
			face.Texture = "rbxassetid://"..faceId
		end
	end
end

function module:BecomeTargetPlayer(player, targetId)
	local humanoid = main:GetModule("cf"):GetHumanoid(player)
	if humanoid then
		local success, desc
		--[[local plr = main.players:GetPlayerByUserId(targetId)
		if plr and not useOriginal then
			success, desc = pcall(function() return plr.Character.Humanoid:GetAppliedDescription() end)
		else--]]
			success, desc = pcall(function() return main.players:GetHumanoidDescriptionFromUserId(targetId) end)
		--end
		if success then
			pcall(function() humanoid:ApplyDescription(desc) end)
		end
	end
end

function module:ClearCharacter(character)
	for a,b in pairs(character:GetDescendants()) do
		if b:IsA("Shirt") or b:IsA("ShirtGraphic") or b:IsA("Pants") or b:IsA("Accessory") or b:IsA("Hat") or b:IsA("CharacterMesh") or b:IsA("BodyColors") then
			b:Destroy()
		elseif b.Name == "Chest" or b.Name == "Arm1" or b.Name == "Arm2" or b.Name == "Leg1" or b.Name == "Leg2" or b.Name == "ExtraFeatures" or b.Name == "ExtraFace" then
			b:Destroy()
		end
	end
end