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


local sensitivity_pc = 0.8
local sensitivity_mobile = 1.5
local first_person_key = Enum.KeyCode.F

local camera_height = 1.5
local forward_offset = 0

local max_angl = math.rad(89)
local mouse_cursor = false
local smooth = 0.15

local first_person_fov = 90
local third_person_fov = 80

local walk_bob_speed = 8
local walk_bob_amount = 0.02
local run_bob_speed = 12
local run_bob_amount = 0.04
local side_bob_amount = 0.015

local third_person_distance = 8
local third_person_height = 2

local uis = game:GetService("UserInputService")
local runService = game:GetService("RunService")

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

local currentPitch = 0
local currentYaw = 0
local targetPitch = 0
local targetYaw = 0

local draggingTouch = false
local lastTouch = Vector2.new(0, 0)

local firstPerson = true

local sensitivity = uis.TouchEnabled and sensitivity_mobile or sensitivity_pc

local hiddenParts = {}

local crosshairGui
local crosshair

--------------------------------------------------
-- СКРЫВАЕМ ТОЛЬКО ГОЛОВУ И АКСЕССУАРЫ
-- ТОРС НЕ ТРОГАЕМ
--------------------------------------------------

local function hidePart(part)
	if not part or not part.Parent then
		return
	end

	if part:IsA("BasePart") then
		if hiddenParts[part] == nil then
			hiddenParts[part] = part.LocalTransparencyModifier
		end

		part.LocalTransparencyModifier = 1
	end
end

local function hideFirstPersonBody(character)

	for object in pairs(hiddenParts) do
		if object and object.Parent then
			if object:IsA("BasePart") then
				object.LocalTransparencyModifier = 0
			end
		end
	end

	hiddenParts = {}

	-- Голова
	local head = character:FindFirstChild("Head")

	if head then
		hidePart(head)

		for _, object in ipairs(head:GetDescendants()) do
			if object:IsA("BasePart") then
				hidePart(object)
			end
		end
	end

	-- ВАЖНО:
	-- Torso / UpperTorso / LowerTorso НЕ СКРЫВАЕМ

	-- Аксессуары
	for _, object in ipairs(character:GetChildren()) do
		if object:IsA("Accessory") then
			for _, accessoryPart in ipairs(object:GetDescendants()) do
				if accessoryPart:IsA("BasePart") then
					hidePart(accessoryPart)
				end
			end
		end
	end
end

local function showHiddenParts()

	for object, oldValue in pairs(hiddenParts) do
		if object and object.Parent then
			if object:IsA("BasePart") then
				object.LocalTransparencyModifier = oldValue
			end
		end
	end

	hiddenParts = {}
end

--------------------------------------------------
-- CROSSHAIR
--------------------------------------------------

local function createCrosshair()

	if crosshairGui then
		crosshairGui:Destroy()
	end

	crosshairGui = Instance.new("ScreenGui")
	crosshairGui.Name = "CameraCrosshair"
	crosshairGui.ResetOnSpawn = false
	crosshairGui.IgnoreGuiInset = true
	crosshairGui.Parent = player:WaitForChild("PlayerGui")

	crosshair = Instance.new("TextLabel")
	crosshair.Name = "Crosshair"
	crosshair.AnchorPoint = Vector2.new(0.5, 0.5)
	crosshair.Position = UDim2.fromScale(0.5, 0.5)
	crosshair.Size = UDim2.fromOffset(24, 24)
	crosshair.BackgroundTransparency = 1
	crosshair.Text = "+"
	crosshair.TextColor3 = Color3.new(1, 1, 1)
	crosshair.TextSize = 18
	crosshair.Font = Enum.Font.GothamBold
	crosshair.Visible = firstPerson
	crosshair.Parent = crosshairGui
end

--------------------------------------------------
-- ПЕРЕКЛЮЧЕНИЕ 1 / 3 ЛИЦО
--------------------------------------------------

local function toggleViewMode()

	local character = player.Character

	if not character then
		return
	end

	local humanoid = character:FindFirstChildOfClass("Humanoid")

	firstPerson = not firstPerson

	if firstPerson then

		hideFirstPersonBody(character)

		camera.FieldOfView = first_person_fov

		if humanoid then
			humanoid.AutoRotate = false
		end

	else

		showHiddenParts()

		camera.FieldOfView = third_person_fov

		if humanoid then
			humanoid.AutoRotate = true
		end
	end

	if crosshair then
		crosshair.Visible = firstPerson
	end
end

--------------------------------------------------
-- КАМЕРА
--------------------------------------------------

local function updateCamera()

	local character = player.Character

	if not character then
		return
	end

	local hrp = character:FindFirstChild("HumanoidRootPart")
	local humanoid = character:FindFirstChildOfClass("Humanoid")

	if not hrp or not humanoid then
		return
	end

	-- Плавность камеры
	currentYaw =
		currentYaw
		+ (targetYaw - currentYaw) * smooth

	currentPitch =
		currentPitch
		+ (targetPitch - currentPitch) * smooth

	local rotation =
		CFrame.Angles(0, currentYaw, 0)
		* CFrame.Angles(currentPitch, 0, 0)

	--------------------------------------------------
	-- 1-Е ЛИЦО
	--------------------------------------------------

	if firstPerson then

		-- Отключаем автоматическое вращение тела,
		-- чтобы A/S/D не дёргали камеру.
		humanoid.AutoRotate = false

		local bob = CFrame.new()

		if humanoid.MoveDirection.Magnitude > 0.05
			and humanoid.FloorMaterial ~= Enum.Material.Air then

			local running = humanoid.WalkSpeed > 16

			local speed =
				running
				and run_bob_speed
				or walk_bob_speed

			local amount =
				running
				and run_bob_amount
				or walk_bob_amount

			local t = os.clock() * speed

			local x =
				math.cos(t * 0.5)
				* side_bob_amount

			local y =
				math.abs(math.sin(t))
				* amount

			bob =
				CFrame.new(x, y, 0)
				* CFrame.Angles(
					0,
					0,
					math.sin(t * 0.5) * 0.008
				)
		end

		local cameraPosition =
			hrp.Position
			+ Vector3.new(
				0,
				camera_height,
				0
			)

		camera.CFrame =
			CFrame.new(cameraPosition)
			* rotation
			* bob

		camera.FieldOfView = first_person_fov

	--------------------------------------------------
	-- 3-Е ЛИЦО
	--------------------------------------------------

	else

		humanoid.AutoRotate = true

		local cameraDirection =
			rotation.LookVector

		local cameraPosition =
			hrp.Position
			- cameraDirection * third_person_distance
			+ Vector3.new(
				0,
				third_person_height,
				0
			)

		camera.CFrame =
			CFrame.lookAt(
				cameraPosition,
				hrp.Position
				+ Vector3.new(0, 1.5, 0)
			)

		camera.FieldOfView = third_person_fov
	end

	if crosshair then
		crosshair.Visible = firstPerson
	end
end

--------------------------------------------------
-- НАСТРОЙКА
--------------------------------------------------

local function setupCamera(character)

	camera.CameraType =
		Enum.CameraType.Scriptable

	camera.FieldOfView =
		first_person_fov

	uis.MouseIconEnabled =
		mouse_cursor

	firstPerson = true

	local humanoid =
		character:FindFirstChildOfClass("Humanoid")

	if humanoid then
		humanoid.AutoRotate = false
	end

	hideFirstPersonBody(character)

	createCrosshair()

	--------------------------------------------------
	-- МОБИЛЬНАЯ КНОПКА
	--------------------------------------------------

	if uis.TouchEnabled then

		local playerGui =
			player:WaitForChild("PlayerGui")

		local oldGui =
			playerGui:FindFirstChild(
				"MobileViewToggle"
			)

		if oldGui then
			oldGui:Destroy()
		end

		local gui =
			Instance.new("ScreenGui")

		gui.Name =
			"MobileViewToggle"

		gui.ResetOnSpawn =
			false

		gui.Parent =
			playerGui

		local button =
			Instance.new("TextButton")

		button.Name =
			"ToggleButton"

		button.Size =
			UDim2.fromOffset(30, 30)

		button.Position =
			UDim2.fromOffset(20, 20)

		button.BackgroundColor3 =
			Color3.new(
				0.2,
				0.2,
				0.2
			)

		button.BackgroundTransparency =
			0.3

		button.BorderSizePixel =
			0

		button.Text =
			"1"

		button.TextColor3 =
			Color3.new(1, 1, 1)

		button.TextScaled =
			true

		button.Parent =
			gui

		local corner =
			Instance.new("UICorner")

		corner.CornerRadius =
			UDim.new(0, 10)

		corner.Parent =
			button

		button.MouseButton1Click:Connect(
			function()

				toggleViewMode()

				button.Text =
					firstPerson
					and "1"
					or "3"
			end
		)
	end
end

--------------------------------------------------
-- ПЕРСОНАЖ
--------------------------------------------------

local function onCharacterAdded(character)

	character:WaitForChild(
		"HumanoidRootPart"
	)

	currentPitch = 0
	currentYaw = 0
	targetPitch = 0
	targetYaw = 0

	setupCamera(character)

	uis.MouseBehavior =
		Enum.MouseBehavior.LockCurrentPosition

	character.ChildAdded:Connect(
		function(child)

			if firstPerson
				and child:IsA("Accessory") then

				task.wait()

				if character.Parent then
					hideFirstPersonBody(character)
				end
			end
		end
	)
end

--------------------------------------------------
-- МЫШЬ / TOUCH
--------------------------------------------------

uis.InputChanged:Connect(
	function(input, gameProcessed)

		if gameProcessed then
			return
		end

		if input.UserInputType ==
			Enum.UserInputType.MouseMovement then

			local delta =
				input.Delta

			targetYaw =
				targetYaw
				- delta.X
				* sensitivity
				* 0.005

			targetPitch =
				targetPitch
				- delta.Y
				* sensitivity
				* 0.005

			targetPitch =
				math.clamp(
					targetPitch,
					-max_angl,
					max_angl
				)

		elseif input.UserInputType ==
			Enum.UserInputType.Touch
			and draggingTouch then

			local position =
				Vector2.new(
					input.Position.X,
					input.Position.Y
				)

			local delta =
				position - lastTouch

			lastTouch =
				position

			targetYaw =
				targetYaw
				- delta.X
				* sensitivity
				* 0.005

			targetPitch =
				targetPitch
				- delta.Y
				* sensitivity
				* 0.005

			targetPitch =
				math.clamp(
					targetPitch,
					-max_angl,
					max_angl
				)
		end
	end
)

--------------------------------------------------
-- КНОПКИ
--------------------------------------------------

uis.InputBegan:Connect(
	function(input, gameProcessed)

		if gameProcessed then
			return
		end

		if input.UserInputType ==
			Enum.UserInputType.MouseButton2 then

			if uis.MouseBehavior ==
				Enum.MouseBehavior.LockCurrentPosition then

				uis.MouseBehavior =
					Enum.MouseBehavior.Default

			else

				uis.MouseBehavior =
					Enum.MouseBehavior.LockCurrentPosition
			end

		elseif input.UserInputType ==
			Enum.UserInputType.Touch then

			draggingTouch = true

			lastTouch =
				Vector2.new(
					input.Position.X,
					input.Position.Y
				)

		elseif input.KeyCode ==
			first_person_key
			and first_person_key ~= 0 then

			toggleViewMode()
		end
	end
)

uis.InputEnded:Connect(
	function(input)

		if input.UserInputType ==
			Enum.UserInputType.Touch then

			draggingTouch = false
		end
	end
)

--------------------------------------------------
-- ЗАПУСК
--------------------------------------------------

runService:BindToRenderStep(
	"CustomCamera",
	Enum.RenderPriority.Camera.Value + 1,
	updateCamera
)

if player.Character then
	onCharacterAdded(
		player.Character
	)
end

player.CharacterAdded:Connect(
	onCharacterAdded
)

player.AncestryChanged:Connect(
	function()

		if not player.Parent then

			showHiddenParts()

			uis.MouseBehavior =
				Enum.MouseBehavior.Default
		end
	end
)