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


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

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

local FOV = 70

local MOUSE_SENSITIVITY = 0.0025
local TOUCH_SENSITIVITY = 0.004

local CAMERA_HEIGHT = 1.45
local SMOOTHNESS = 0.18

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

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

--------------------------------------------------
-- HIDE UPPER BODY FROM FIRST PERSON
--------------------------------------------------

local function updateBodyVisibility()

	if not character then
		return
	end

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

		if object:IsA("BasePart") then

			-- Head is always hidden
			if object == head then
				object.LocalTransparencyModifier = 1

			-- Upper torso is hidden
			elseif object.Name == "UpperTorso" then
				object.LocalTransparencyModifier = 1

			else
				-- Arms, lower torso, legs and accessories remain visible
				object.LocalTransparencyModifier = 0
			end

		elseif object:IsA("Decal") then

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

--------------------------------------------------
-- CHARACTER SETUP
--------------------------------------------------

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

	updateBodyVisibility()

	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 * 0.45 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(
	"CustomFirstPersonCamera",
	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

		-- Keep visibility correct at all times.
		-- This also covers running, jumping,
		-- falling, landing and swimming.
		updateBodyVisibility()

		camera.CameraType =
			Enum.CameraType.Scriptable

		--------------------------------------------------
		-- SMOOTH ROTATION
		--------------------------------------------------

		yaw +=
			(targetYaw - yaw) *
			SMOOTHNESS

		pitch +=
			(targetPitch - pitch) *
			SMOOTHNESS

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

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

		--------------------------------------------------
		-- CAMERA ROTATION
		--------------------------------------------------

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

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

		camera.FieldOfView = FOV

		--------------------------------------------------
		-- BODY ROTATION
		--------------------------------------------------

		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
)

--------------------------------------------------
-- SPAWN
--------------------------------------------------

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

player.CharacterAdded:Connect(function(char)

	task.wait(0.1)

	setupCharacter(char)
end)