Загрузка данных


local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Lighting = game:GetService("Lighting")
local GuiService = game:GetService("GuiService")
local GameSettings = UserSettings():GetService("UserGameSettings")

-- ================= НАСТРОЙКИ =================
local Settings = {
	-- Позиция камеры относительно головы
	CameraHeight = -0.25,
	CameraBack = -1.9,     -- минус = вперёд, плюс = назад
	CameraSide = 0,
	DownPullIn = 0.3,

	-- Мышка
	MouseSensitivity = 0.003,
	MaxDeltaPerFrame = 120,
	MaxPitchDeg = 80,
	SettingsKey = Enum.KeyCode.P,   -- меню настроек

	-- FOV (максимум в Roblox = 120)
	IdleFOV = 100,
	WalkFOV = 110,
	SprintFOV = 120,
	FOVSmoothing = 7,

	-- Движение
	WalkSpeed = 16,
	SprintSpeed = 26,
	SprintKey = Enum.KeyCode.LeftShift,

	-- Покачивание при ходьбе и беге
	BobEnabled = true,
	BobVertical = 0.28,
	BobHorizontal = 0.2,
	BobSpeed = 0.45,
	BobRoll = 0.035,
	BobPitch = 0.025,
	SprintBobMultiplier = 1.8,
	BobSmoothing = 10,

	-- Динамическая камера
	StrafeTiltDeg = 2.5,    -- наклон при шаге вбок
	TurnTiltDeg = 1.5,      -- наклон при резком повороте мыши
	RunLeanDeg = 1.5,       -- наклон вперёд на бегу

	-- Прыжок и приземление
	JumpEnabled = true,
	JumpLift = 1.2,
	LandDip = 5,
	LandPitch = 0.5,

	-- Дыхание в покое
	IdleEnabled = true,
	IdleVertical = 0.03,
	IdleHorizontal = 0.015,
	IdleRotation = 0.004,
	IdleSpeed = 0.3,
	IdleDelay = 300,
	IdleFade = 5,

	-- Усталость от долгого бега
	FatigueEnabled = true,
	BlurAfter = 30,
	BlurDuration = 10,
	BlurMaxSize = 8,
	DimAfter = 60,
	DimDuration = 30,
	DimBrightness = -0.2,
	DimSaturation = -0.35,

	-- Предмет в руке (вид от первого лица)
	ViewmodelEnabled = true,
	ViewmodelOffset = Vector3.new(0.8, -0.7, -2.2),   -- вправо, вниз, вперёд
	ViewmodelRotation = Vector3.new(0, 0, 0),         -- в градусах, если предмет смотрит не туда
	ViewmodelSway = 0.0015,
	ViewmodelBob = 1,

	-- Третье лицо (только после смерти)
	ThirdPersonDistance = 10,
	ThirdPersonSide = 1.5,
	ThirdPersonFOV = 70,

	-- Видимость тела
	ViewAccessories = false,
	ViewModels = false,
	HeadLocalTransparency = 1,
	HiddenParts = {},
}
-- =============================================

local player = Players.LocalPlayer
local camera = workspace.CurrentCamera

local character, humanoid, root
local sprinting = false
local bobTime, idleTime, standTime = 0, 0, 0
local bobOffset = Vector3.zero
local moveAlpha = 0
local locked = {}
local yaw, pitch = 0, 0
local jumpY, jumpVel, jumpPitch, jumpPitchVel, fallSpeed = 0, 0, 0, 0, 0
local dynRoll, dynPitch = 0, 0
local sensMult = 1
local fovOffset = 0
local menuOpen = false
local viewmodel = nil
local swayCur = Vector2.zero
local vmSprint = 0

-- ================= ЭФФЕКТЫ УСТАЛОСТИ =================
for _, name in ipairs({ "FatigueBlur", "FatigueDim" }) do
	local old = Lighting:FindFirstChild(name)
	if old then old:Destroy() end
end

local blur = Instance.new("BlurEffect")
blur.Name = "FatigueBlur"
blur.Size = 0
blur.Parent = Lighting

local dim = Instance.new("ColorCorrectionEffect")
dim.Name = "FatigueDim"
dim.Parent = Lighting

local sprintTime = 0
local blurT = nil
local dimT = nil
local blurFired = false

local function envelope(t, duration, fadeIn, fadeOut)
	return math.clamp(t / fadeIn, 0, 1) * math.clamp((duration - t) / fadeOut, 0, 1)
end

local function resetFatigue()
	sprintTime = 0
	blurT = nil
	dimT = nil
	blurFired = false
	blur.Size = 0
	dim.Brightness = 0
	dim.Saturation = 0
end

-- ================= МЕНЮ НАСТРОЕК =================
local playerGui = player:WaitForChild("PlayerGui")
local oldGui = playerGui:FindFirstChild("CameraSettings")
if oldGui then oldGui:Destroy() end

local gui = Instance.new("ScreenGui")
gui.Name = "CameraSettings"
gui.ResetOnSpawn = false
gui.DisplayOrder = 50
gui.Enabled = false
gui.Parent = playerGui

local panel = Instance.new("Frame")
panel.Size = UDim2.fromOffset(340, 210)
panel.AnchorPoint = Vector2.new(0.5, 0.5)
panel.Position = UDim2.fromScale(0.5, 0.5)
panel.BackgroundColor3 = Color3.fromRGB(20, 22, 28)
panel.BackgroundTransparency = 0.08
panel.BorderSizePixel = 0
panel.Parent = gui

local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, 10)
corner.Parent = panel

local function makeLabel(text, y, size)
	local l = Instance.new("TextLabel")
	l.BackgroundTransparency = 1
	l.Position = UDim2.fromOffset(20, y)
	l.Size = UDim2.new(1, -40, 0, size)
	l.Font = Enum.Font.GothamMedium
	l.TextSize = 16
	l.TextColor3 = Color3.fromRGB(235, 235, 240)
	l.TextXAlignment = Enum.TextXAlignment.Left
	l.Text = text
	l.Parent = panel
	return l
end

makeLabel("Настройки камеры  (P — закрыть)", 14, 24)

local function makeSlider(y, title, min, max, start, decimals, onChange)
	local label = makeLabel("", y, 22)

	local track = Instance.new("Frame")
	track.Position = UDim2.fromOffset(20, y + 34)
	track.Size = UDim2.new(1, -40, 0, 8)
	track.BackgroundColor3 = Color3.fromRGB(70, 74, 86)
	track.BorderSizePixel = 0
	track.Parent = panel

	local fill = Instance.new("Frame")
	fill.BackgroundColor3 = Color3.fromRGB(90, 150, 255)
	fill.BorderSizePixel = 0
	fill.Size = UDim2.new(0, 0, 1, 0)
	fill.Parent = track

	local knob = Instance.new("Frame")
	knob.AnchorPoint = Vector2.new(0.5, 0.5)
	knob.Size = UDim2.fromOffset(16, 16)
	knob.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
	knob.BorderSizePixel = 0
	knob.Parent = track
	local kc = Instance.new("UICorner")
	kc.CornerRadius = UDim.new(1, 0)
	kc.Parent = knob

	local hit = Instance.new("TextButton")
	hit.BackgroundTransparency = 1
	hit.Text = ""
	hit.AutoButtonColor = false
	hit.Position = UDim2.fromOffset(20, y + 22)
	hit.Size = UDim2.new(1, -40, 0, 32)
	hit.Parent = panel

	local function setValue(v)
		v = math.clamp(v, min, max)
		local m = 10 ^ decimals
		v = math.floor(v * m + 0.5) / m
		local a = (v - min) / (max - min)
		fill.Size = UDim2.new(a, 0, 1, 0)
		knob.Position = UDim2.new(a, 0, 0.5, 0)
		label.Text = string.format("%s: %." .. decimals .. "f", title, v)
		onChange(v)
	end

	local function fromX(x)
		local a = math.clamp((x - track.AbsolutePosition.X) / track.AbsoluteSize.X, 0, 1)
		setValue(min + (max - min) * a)
	end

	local dragging = false
	hit.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			dragging = true
			fromX(input.Position.X)
		end
	end)
	UserInputService.InputChanged:Connect(function(input)
		if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
			fromX(input.Position.X)
		end
	end)
	UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			dragging = false
		end
	end)

	setValue(start)
end

makeSlider(56, "Чувствительность", 0.1, 3, 1, 2, function(v) sensMult = v end)
makeSlider(124, "FOV (смещение)", -30, 10, 0, 0, function(v) fovOffset = v end)

local function setMenu(open)
	menuOpen = open
	gui.Enabled = open
end

-- ================= ТЕЛО И ПРЕДМЕТЫ =================
local function classify(part)
	if not part:IsA("BasePart") or not character then return nil end
	if part.Name == "Head" and part.Parent == character then
		return Settings.HeadLocalTransparency
	end
	if part:FindFirstAncestorOfClass("Accessory") then
		return Settings.ViewAccessories and 0 or 1
	end
	if part:FindFirstAncestorOfClass("Tool") then
		return Settings.ViewmodelEnabled and 1 or 0
	end
	if part.Parent == character then
		if table.find(Settings.HiddenParts, part.Name) then
			return 1
		end
		return 0
	end
	if part:FindFirstAncestorOfClass("Model") ~= character and Settings.ViewModels then
		return 0
	end
	return nil
end

local function register(part)
	local value = classify(part)
	if value ~= nil then
		locked[part] = value
	end
end

local function setTransparency(fp)
	for part, value in pairs(locked) do
		part.LocalTransparencyModifier = fp and value or 0
	end
end

local function clearViewmodel()
	if viewmodel then
		viewmodel.model:Destroy()
		viewmodel = nil
	end
end

local function buildViewmodel(tool)
	clearViewmodel()
	if not Settings.ViewmodelEnabled then return end
	local handle = tool:FindFirstChild("Handle") or tool:FindFirstChildWhichIsA("BasePart", true)
	if not handle then return end

	local model = Instance.new("Model")
	model.Name = "ViewmodelTool"
	local items = {}

	for _, d in ipairs(tool:GetDescendants()) do
		if d:IsA("BasePart") then
			local c = d:Clone()
			if c then
				for _, x in ipairs(c:GetDescendants()) do
					if x:IsA("LuaSourceContainer") or x:IsA("JointInstance") or x:IsA("WeldConstraint") or x:IsA("Sound") then
						x:Destroy()
					end
				end
				c.Anchored = true
				c.CanCollide = false
				c.CanQuery = false
				c.CanTouch = false
				c.CastShadow = false
				c.Massless = true
				c.Parent = model
				table.insert(items, { part = c, rel = handle.CFrame:ToObjectSpace(d.CFrame) })
			end
		end
	end

	model.Parent = camera
	viewmodel = { model = model, items = items, tool = tool }
end

local function updateViewmodel(dt, moving, dx, dy, mult)
	if not viewmodel then return end

	swayCur = swayCur:Lerp(Vector2.new(-dx, dy) * Settings.ViewmodelSway, math.clamp(dt * 10, 0, 1))
	vmSprint += (((sprinting and moving) and 1 or 0) - vmSprint) * math.clamp(dt * 8, 0, 1)

	local bob = Vector3.new(
		math.sin(bobTime) * 0.03 * mult,
		-math.abs(math.sin(bobTime)) * 0.04 * mult,
		0
	) * moveAlpha * Settings.ViewmodelBob

	local pos = Settings.ViewmodelOffset
		+ bob
		+ Vector3.new(swayCur.X, swayCur.Y, 0)
		+ Vector3.new(0.15, -0.25, 0.15) * vmSprint

	local r = Settings.ViewmodelRotation
	local base = camera.CFrame
		* CFrame.new(pos)
		* CFrame.Angles(math.rad(r.X), math.rad(r.Y), math.rad(r.Z))
		* CFrame.Angles(swayCur.Y * 3 + 0.2 * vmSprint, swayCur.X * 3 - 0.5 * vmSprint, 0.15 * vmSprint)

	for _, item in ipairs(viewmodel.items) do
		item.part.CFrame = base * item.rel
	end
end

local function syncLook()
	if not root then return end
	local look = root.CFrame.LookVector
	yaw = math.atan2(-look.X, -look.Z)
	pitch = 0
end

-- ================= ПЕРСОНАЖ =================
local function setupCharacter(char)
	character = char
	humanoid = char:WaitForChild("Humanoid")
	root = char:WaitForChild("HumanoidRootPart")
	locked = {}
	sprinting = false
	bobTime = 0
	standTime = 0
	bobOffset = Vector3.zero
	moveAlpha = 0
	jumpY, jumpVel, jumpPitch, jumpPitchVel, fallSpeed = 0, 0, 0, 0, 0
	dynRoll, dynPitch = 0, 0
	swayCur = Vector2.zero
	vmSprint = 0
	clearViewmodel()
	resetFatigue()

	humanoid.WalkSpeed = Settings.WalkSpeed
	humanoid.AutoRotate = false
	humanoid.CameraOffset = Vector3.zero
	camera.CameraType = Enum.CameraType.Scriptable
	syncLook()

	for _, d in ipairs(char:GetDescendants()) do
		register(d)
	end
	char.DescendantAdded:Connect(register)
	char.DescendantRemoving:Connect(function(d)
		if d:IsA("BasePart") then
			d.LocalTransparencyModifier = 0
		end
		locked[d] = nil
	end)

	local function onChildAdded(child)
		if child:IsA("Tool") then
			buildViewmodel(child)
		end
	end
	char.ChildAdded:Connect(onChildAdded)
	char.ChildRemoved:Connect(function(child)
		if viewmodel and viewmodel.tool == child then
			clearViewmodel()
		end
	end)
	for _, c in ipairs(char:GetChildren()) do
		onChildAdded(c)
	end

	humanoid.StateChanged:Connect(function(_, new)
		if not Settings.JumpEnabled then return end
		if new == Enum.HumanoidStateType.Jumping then
			jumpVel += Settings.JumpLift
		elseif new == Enum.HumanoidStateType.Landed then
			local impact = math.clamp(fallSpeed / 50, 0.25, 1)
			jumpVel -= Settings.LandDip * impact
			jumpPitchVel -= Settings.LandPitch * impact
			fallSpeed = 0
		end
	end)

	char:GetAttributeChangedSignal("Ragdoll"):Connect(function()
		if not char:GetAttribute("Ragdoll") then
			humanoid.AutoRotate = false
			syncLook()
		end
	end)
end

-- ================= УПРАВЛЕНИЕ =================
UserInputService.InputBegan:Connect(function(input, processed)
	if processed then return end

	if input.KeyCode == Settings.SettingsKey then
		setMenu(not menuOpen)
		return
	end

	if not humanoid then return end
	if input.KeyCode == Settings.SprintKey then
		sprinting = true
		humanoid.WalkSpeed = Settings.SprintSpeed
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if input.KeyCode == Settings.SprintKey and humanoid then
		sprinting = false
		humanoid.WalkSpeed = Settings.WalkSpeed
	end
end)

-- ================= УСТАЛОСТЬ =================
RunService.Heartbeat:Connect(function(dt)
	if not Settings.FatigueEnabled or not root or not humanoid then return end

	local speed = (root.AssemblyLinearVelocity * Vector3.new(1, 0, 1)).Magnitude
	local running = sprinting and speed > 10 and humanoid.Health > 0

	if running then
		sprintTime += dt
		if sprintTime >= Settings.BlurAfter and not blurFired then
			blurFired = true
			blurT = 0
		end
		if sprintTime >= Settings.DimAfter then
			dimT = 0
			sprintTime = 0
			blurFired = false
		end
	else
		sprintTime = math.max(0, sprintTime - dt * 2)
		if sprintTime < Settings.BlurAfter then
			blurFired = false
		end
	end

	if blurT then
		blurT += dt
		if blurT >= Settings.BlurDuration then
			blurT = nil
			blur.Size = 0
		else
			blur.Size = Settings.BlurMaxSize * envelope(blurT, Settings.BlurDuration, 1.5, 3)
		end
	end

	if dimT then
		dimT += dt
		if dimT >= Settings.DimDuration then
			dimT = nil
			dim.Brightness = 0
			dim.Saturation = 0
		else
			local e = envelope(dimT, Settings.DimDuration, 3, 6)
			dim.Brightness = Settings.DimBrightness * e
			dim.Saturation = Settings.DimSaturation * e
		end
	end
end)

-- ================= КАМЕРА КАЖДЫЙ КАДР =================
pcall(function() RunService:UnbindFromRenderStep("FirstPersonBody") end)
pcall(function() RunService:UnbindFromRenderStep("LockBodyTransparency") end)

RunService:BindToRenderStep("FirstPersonBody", Enum.RenderPriority.Camera.Value + 1, function(dt)
	if not humanoid or not root or not character then return end
	local head = character:FindFirstChild("Head")
	if not head then return end

	if camera.CameraType ~= Enum.CameraType.Scriptable then
		camera.CameraType = Enum.CameraType.Scriptable
	end

	local ragdoll = character:GetAttribute("Ragdoll") == true
	local alive = humanoid.Health > 0
	local fp = alive

	setTransparency(fp)

	-- предмет в руке виден только в первом лице
	if viewmodel then
		local want = (fp and not ragdoll) and camera or nil
		if viewmodel.model.Parent ~= want then
			viewmodel.model.Parent = want
		end
	end

	-- мышка
	local dx, dy = 0, 0
	if menuOpen or GuiService.MenuIsOpen then
		UserInputService.MouseBehavior = Enum.MouseBehavior.Default
	else
		UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
		local delta = UserInputService:GetMouseDelta()
		local m = Settings.MaxDeltaPerFrame
		dx = math.clamp(delta.X, -m, m)
		dy = math.clamp(delta.Y, -m, m)
		local sens = Settings.MouseSensitivity * sensMult * GameSettings.MouseSensitivity
		yaw -= dx * sens
		local lim = math.rad(Settings.MaxPitchDeg)
		pitch = math.clamp(pitch - dy * sens, -lim, lim)
	end

	-- пружины прыжка и приземления
	local vy = root.AssemblyLinearVelocity.Y
	if vy < 0 then fallSpeed = math.max(fallSpeed, -vy) end
	local sdt = math.min(dt, 1 / 30)
	jumpVel += (-120 * jumpY - 14 * jumpVel) * sdt
	jumpY += jumpVel * sdt
	jumpPitchVel += (-120 * jumpPitch - 14 * jumpPitchVel) * sdt
	jumpPitch += jumpPitchVel * sdt

	-- рагдол: камера едет за головой
	if ragdoll and fp then
		local target = head.CFrame * CFrame.new(0, 0.15, -0.6)
		camera.CFrame = camera.CFrame:Lerp(target, math.clamp(dt * 18, 0, 1))
		return
	end

	-- персонаж смотрит туда же, куда камера
	if alive and not ragdoll then
		root.CFrame = CFrame.new(root.Position) * CFrame.Angles(0, yaw, 0)
	end

	local speed = (root.AssemblyLinearVelocity * Vector3.new(1, 0, 1)).Magnitude
	local onGround = humanoid.FloorMaterial ~= Enum.Material.Air
	local moving = onGround and speed > 1 and humanoid.MoveDirection.Magnitude > 0

	-- третье лицо (после смерти)
	if not fp then
		local pivot = head.Position + Vector3.new(0, 0.3, 0)
		local rot = CFrame.fromEulerAnglesYXZ(pitch, yaw, 0)
		local desired = pivot + rot:VectorToWorldSpace(Vector3.new(Settings.ThirdPersonSide, 0, Settings.ThirdPersonDistance))

		local params = RaycastParams.new()
		params.FilterType = Enum.RaycastFilterType.Exclude
		params.FilterDescendantsInstances = { character }
		local dir = desired - pivot
		local hit = workspace:Raycast(pivot, dir, params)
		local pos = desired
		if hit then
			pos = hit.Position - dir.Unit * 0.4
		end

		camera.CFrame = CFrame.new(pos) * rot
		camera.FieldOfView += (Settings.ThirdPersonFOV - camera.FieldOfView) * math.clamp(dt * Settings.FOVSmoothing, 0, 1)
		return
	end

	-- первое лицо
	moveAlpha += ((moving and 1 or 0) - moveAlpha) * math.clamp(dt * 8, 0, 1)

	local mult = sprinting and Settings.SprintBobMultiplier or 1
	local walkOffset = Vector3.zero
	local roll, bobPitch = 0, 0

	if Settings.BobEnabled and moving then
		bobTime += dt * speed * Settings.BobSpeed
	end
	if Settings.BobEnabled then
		walkOffset = Vector3.new(
			math.sin(bobTime) * Settings.BobHorizontal * mult,
			math.abs(math.sin(bobTime)) * Settings.BobVertical * mult - Settings.BobVertical * mult * 0.5,
			0
		) * moveAlpha
		roll = math.sin(bobTime) * Settings.BobRoll * mult * moveAlpha
		bobPitch = math.sin(bobTime * 2) * Settings.BobPitch * mult * moveAlpha
	end

	local idleOffset = Vector3.zero
	local idleRoll, idlePitch = 0, 0
	if Settings.IdleEnabled then
		idleTime += dt * Settings.IdleSpeed
		if moving then standTime = 0 else standTime += dt end
		local idleAlpha = (1 - moveAlpha) * math.clamp((standTime - Settings.IdleDelay) / Settings.IdleFade, 0, 1)
		idleOffset = Vector3.new(
			math.sin(idleTime * 0.6) * Settings.IdleHorizontal,
			math.sin(idleTime) * Settings.IdleVertical,
			0
		) * idleAlpha
		idleRoll = math.sin(idleTime * 0.7) * Settings.IdleRotation * idleAlpha
		idlePitch = math.sin(idleTime * 0.9 + 1) * Settings.IdleRotation * idleAlpha
	end

	-- динамика: наклон при шаге вбок, при повороте мыши, наклон вперёд на бегу
	local rel = root.CFrame:VectorToObjectSpace(root.AssemblyLinearVelocity)
	local strafe = math.clamp(rel.X / Settings.WalkSpeed, -1, 1)
	local forward = math.clamp(-rel.Z / Settings.SprintSpeed, -1, 1)
	local targetRoll = -strafe * math.rad(Settings.StrafeTiltDeg)
		- math.clamp(dx / 40, -1, 1) * math.rad(Settings.TurnTiltDeg)
	local targetPitch = -math.max(forward, 0) * math.rad(Settings.RunLeanDeg)
	dynRoll += (targetRoll - dynRoll) * math.clamp(dt * 8, 0, 1)
	dynPitch += (targetPitch - dynPitch) * math.clamp(dt * 6, 0, 1)

	bobOffset = bobOffset:Lerp(walkOffset + idleOffset, math.clamp(dt * Settings.BobSmoothing, 0, 1))

	local downFactor = 1 - math.clamp(-math.sin(pitch), 0, 1) * Settings.DownPullIn
	local localOffset = Vector3.new(Settings.CameraSide, Settings.CameraHeight + jumpY, Settings.CameraBack * downFactor) + bobOffset
	local yawCF = CFrame.Angles(0, yaw, 0)
	local pos = head.Position + yawCF:VectorToWorldSpace(localOffset)

	camera.CFrame = CFrame.new(pos)
		* CFrame.fromEulerAnglesYXZ(pitch, yaw, 0)
		* CFrame.Angles(bobPitch + idlePitch + jumpPitch + dynPitch, 0, roll + idleRoll + dynRoll)

	-- предмет в руке
	updateViewmodel(dt, moving, dx, dy, mult)

	-- FOV
	local targetFov = Settings.IdleFOV
	if moving then
		targetFov = sprinting and Settings.SprintFOV or Settings.WalkFOV
	end
	targetFov = math.clamp(targetFov + fovOffset, 1, 120)
	camera.FieldOfView += (targetFov - camera.FieldOfView) * math.clamp(dt * Settings.FOVSmoothing, 0, 1)
end)

-- прозрачность тела в самый последний момент перед отрисовкой
RunService:BindToRenderStep("LockBodyTransparency", Enum.RenderPriority.Last.Value, function()
	setTransparency(humanoid ~= nil and humanoid.Health > 0)
end)

player.CharacterAdded:Connect(setupCharacter)
if player.Character then
	setupCharacter(player.Character)
end