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


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

local player = Players.LocalPlayer

--------------------------------------------------
-- SETTINGS
--------------------------------------------------

local FOV = 70

local CAMERA_HEIGHT = 1.45

local MOUSE_SENSITIVITY = 0.0025
local TOUCH_SENSITIVITY = 0.004

local CAMERA_SMOOTHNESS = 14

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

--------------------------------------------------
-- VARIABLES
--------------------------------------------------

local character
local humanoid
local rootPart
local head

local targetYaw = 0
local targetPitch = 0

local currentYaw = 0
local currentPitch = 0

local cameraTouch = false
local lastTouchPosition = Vector2.zero

--------------------------------------------------
-- HIDE PARTS FROM LOCAL PLAYER
--------------------------------------------------

local function updateVisibility()

	if not character then
		return
	end

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

		if object:IsA("BasePart") then

			-- Hide head
			if object == head then
				object.LocalTransparencyModifier = 1

			-- Hide upper torso
			elseif object.Name == "UpperTorso" then
				object.LocalTransparencyModifier = 1

			-- Keep everything else visible
			else
				object.LocalTransparencyModifier = 0
			end

		elseif object:IsA("Decal") then

			-- Hide face
			if head and object:IsDescendantOf(head) then
				object.Transparency = 1
			end
		end
	end
end

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

local function setupCharacter(newCharacter)

	character = newCharacter

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

	humanoid.AutoRotate = false

	local camera = workspace.CurrentCamera

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

	--------------------------------------------------
	-- INITIAL CAMERA DIRECTION
	--------------------------------------------------

	local look = rootPart.CFrame.LookVector

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

	currentYaw = targetYaw

	targetPitch = 0
	currentPitch = 0

	updateVisibility()
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 camera = workspace.CurrentCamera
		local viewport = camera.ViewportSize

		-- Right side controls camera
		if input.Position.X >= viewport.X * 0.45 then

			cameraTouch = 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 cameraTouch 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
		cameraTouch = false
	end
end)

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

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

		local camera = workspace.CurrentCamera

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

		if humanoid.Health <= 0 then
			return
		end

		--------------------------------------------------
		-- CAMERA TYPE
		--------------------------------------------------

		camera.CameraType = Enum.CameraType.Scriptable

		--------------------------------------------------
		-- KEEP UPPER TORSO HIDDEN
		--------------------------------------------------

		updateVisibility()

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

		local alpha = math.clamp(
			deltaTime * CAMERA_SMOOTHNESS,
			0,
			1
		)

		currentYaw +=
			(targetYaw - currentYaw) * alpha

		currentPitch +=
			(targetPitch - currentPitch) * alpha

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

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

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

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

		--------------------------------------------------
		-- APPLY CAMERA
		--------------------------------------------------

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

		camera.FieldOfView = FOV

		--------------------------------------------------
		-- BODY FOLLOWS HORIZONTAL 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
)

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

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

player.CharacterAdded:Connect(function(newCharacter)

	task.wait()

	setupCharacter(newCharacter)
end)