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


local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

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

-- CAMERA
local CAMERA_HEIGHT = 1.35
local FOV = 70

local MOUSE_SENSITIVITY = 0.0025
local TOUCH_SENSITIVITY = 0.004

local SMOOTHNESS = 0.18

local MAX_PITCH = math.rad(85)
local MIN_PITCH = math.rad(-85)

-- BODY
local SHOW_BODY = true

-- MOBILE
local TOUCH_CAMERA_START = 0.45

local character
local humanoid
local rootPart
local head

local yaw = 0
local pitch = 0

local targetYaw = 0
local targetPitch = 0

local touchingCamera = false
local lastTouchPosition = Vector2.zero

--------------------------------------------------
-- HEAD
--------------------------------------------------

local function hideHead()
	if not head then
		return
	end

	head.LocalTransparencyModifier = 1

	for _, object in ipairs(head:GetDescendants()) do
		if object:IsA("BasePart") then
			object.LocalTransparencyModifier = 1
		elseif object:IsA("Decal") then
			object.Transparency = 1
		end
	end
end

--------------------------------------------------
-- BODY
--------------------------------------------------

local function showBody()
	if not character then
		return
	end

	for _, object in ipairs(character:GetDescendants()) do

		if object:IsA("BasePart") then

			if object ~= head then
				object.LocalTransparencyModifier = 0
			end

		elseif object:IsA("Decal") then

			if not object:IsDescendantOf(head) then
				object.Transparency = 0
			end
		end
	end
end

--------------------------------------------------
-- CHARACTER
--------------------------------------------------

local function setupCharacter(char)

	character = char

	humanoid = char:WaitForChild("Humanoid")
	rootPart = char:WaitForChild("HumanoidRootPart")
	head = char:WaitForChild("Head")

	camera.CameraType = Enum.CameraType.Scriptable
	camera.FieldOfView = FOV

	humanoid.AutoRotate = false

	-- Hide ONLY head
	hideHead()

	-- Keep entire body visible
	showBody()

	local look = rootPart.CFrame.LookVector

	targetYaw = math.atan2(
		-look.X,
		-look.Z
	)

	yaw = targetYaw

	targetPitch = 0
	pitch = 0
end

--------------------------------------------------
-- MOUSE
--------------------------------------------------

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

	if gameProcessed then
		return
	end

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

		local delta = input.Delta

		targetYaw -=
			delta.X
			* MOUSE_SENSITIVITY

		targetPitch -=
			delta.Y
			* MOUSE_SENSITIVITY

		targetPitch = math.clamp(
			targetPitch,
			MIN_PITCH,
			MAX_PITCH
		)
	end
end)

--------------------------------------------------
-- TOUCH START
--------------------------------------------------

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

	if gameProcessed then
		return
	end

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

		local viewport = camera.ViewportSize

		if input.Position.X >=
			viewport.X * TOUCH_CAMERA_START then

			touchingCamera = true
			lastTouchPosition = input.Position
		end
	end
end)

--------------------------------------------------
-- TOUCH MOVE
--------------------------------------------------

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

	if gameProcessed then
		return
	end

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

		local position = input.Position

		local delta =
			position
			- lastTouchPosition

		lastTouchPosition = position

		targetYaw -=
			delta.X
			* TOUCH_SENSITIVITY

		targetPitch -=
			delta.Y
			* TOUCH_SENSITIVITY

		targetPitch = math.clamp(
			targetPitch,
			MIN_PITCH,
			MAX_PITCH
		)
	end
end)

--------------------------------------------------
-- TOUCH END
--------------------------------------------------

UserInputService.InputEnded:Connect(function(input)

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

		touchingCamera = false
	end
end)

--------------------------------------------------
-- CAMERA
--------------------------------------------------

RunService:BindToRenderStep(
	"NewFirstPersonCamera",
	Enum.RenderPriority.Camera.Value + 1,
	function()

		if not character
			or not humanoid
			or not rootPart
			or not head then
			return
		end

		if humanoid.Health <= 0 then
			return
		end

		camera.CameraType =
			Enum.CameraType.Scriptable

		--------------------------------------------------
		-- KEEP BODY VISIBLE
		--------------------------------------------------

		if SHOW_BODY then
			showBody()
		end

		hideHead()

		--------------------------------------------------
		-- SMOOTH CAMERA
		--------------------------------------------------

		yaw +=
			(targetYaw - yaw)
			* SMOOTHNESS

		pitch +=
			(targetPitch - pitch)
			* SMOOTHNESS

		--------------------------------------------------
		-- CAMERA POSITION
		--------------------------------------------------

		local cameraPosition =
			rootPart.Position
			+ Vector3.new(
				0,
				CAMERA_HEIGHT,
				0
			)

		--------------------------------------------------
		-- ROTATION
		--------------------------------------------------

		local rotation =
			CFrame.Angles(
				0,
				yaw,
				0
			)
			* CFrame.Angles(
				pitch,
				0,
				0
			)

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

		camera.FieldOfView = FOV

		--------------------------------------------------
		-- BODY FOLLOWS CAMERA
		--------------------------------------------------

		local look =
			rotation.LookVector

		local flatLook =
			Vector3.new(
				look.X,
				0,
				look.Z
			)

		if flatLook.Magnitude > 0 then

			rootPart.CFrame =
				CFrame.lookAt(
					rootPart.Position,
					rootPart.Position
					+ flatLook.Unit
				)
		end
	end
)

--------------------------------------------------
-- START
--------------------------------------------------

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

player.CharacterAdded:Connect(function(char)

	task.wait(0.1)

	setupCharacter(char)
end)