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


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 = 70
local third_person_fov = 60

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

	local torsoNames = {
		"Torso",
		"UpperTorso",
		"LowerTorso"
	}

	for _, name in ipairs(torsoNames) do
		local torso = character:FindFirstChild(name)

		if torso and torso:IsA("BasePart") then
			hidePart(torso)
		end
	end

	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

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

local function toggleViewMode()
	local character = player.Character

	if not character then
		return
	end

	firstPerson = not firstPerson

	if firstPerson then
		hideFirstPersonBody(character)
		camera.FieldOfView = first_person_fov
	else
		showHiddenParts()
		camera.FieldOfView = third_person_fov
	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)

	if firstPerson then
		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

		local lookDirection = rotation.LookVector

		local flatDirection = Vector3.new(
			lookDirection.X,
			0,
			lookDirection.Z
		)

		if flatDirection.Magnitude > 0 then
			hrp.CFrame = CFrame.lookAt(
				hrp.Position,
				hrp.Position + flatDirection.Unit
			)
		end
	else
		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

	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

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)