I know this is pretty much a request, which is not allowed on this site, but when it comes to FE I just really hate it

This is a local script which is put inside the StarterGui (it's a first person script), you don't need to change anything about the math, just change the things that are related to UserInputService because that service doesn't work in normal scripts

wait()
local InputService = game:GetService("UserInputService")
local Camera = game.Workspace.CurrentCamera
local Player = game.Players.LocalPlayer
local Character = Player.Character
local Head = Character.Head
local Torso = Character.Torso
local RootPart = Character.HumanoidRootPart
local RootJoint = RootPart.RootJoint
local Neck = Torso.Neck
Camera.FieldOfView = 70
Camera.CameraType = "Scriptable"
InputService.MouseBehavior = Enum.MouseBehavior.LockCenter

repeat
	wait(0.5)
until Character and Head and Torso and RootPart and RootJoint and Neck



local v3 = Vector3.new
local cf = CFrame.new
local components = cf().components
local inverse = cf().inverse
local fromAxisAngle = CFrame.fromAxisAngle
local atan, atan2 = math.atan, math.atan2
local acos = math.acos

local function toAxisAngleFromVector(v)
	local z = v.z
	return z * z < 0.99999 and v3(v.y, -v.x, 0).unit * acos(-z) or v3()
end

local function AxisAngleLookOrientation(c, v, t)--CFrame,Vector,Tween
	local c = c - c.p
	local rv = (inverse(c) * v).unit
	local rz = rv.z
	return rz * rz < 0.99999 and c * fromAxisAngle(v3(rv.y, -rv.x, 0), acos(-rz) * (t or 1)) or c
end

local function AxisAngleLookNew(v, t)--CFrame,Vector,Tween
	local rv = v.unit
	local rz = rv.z
	return rz * rz < 0.99999 and fromAxisAngle(v3(rv.y, -rv.x, 0), acos(-rz) * (t or 1)) or cf()
end

local function AxisAngleLook(c, v, t)--CFrame,Vector,Tween
	local rv = (inverse(c) * v).unit
	local rz = rv.z
	return rz * rz < 0.99999 and c * fromAxisAngle(v3(rv.y, -rv.x, 0), acos(-rz) * (t or 1)) or c
end




local Sensitivity = 0.005


local CameraDirection = Vector3.new(0, 0, 1)

local function EulerAnglesYX(l)
	local x, z = l.x, l.z
	return atan(l.y / (x * x + z * z) ^ 0.5), -atan2(x, -z)
end

local function AnglesXY(l)
	local z = l.z
	return atan2(l.y, -z), -atan2(l.x, -z)
end

local function MouseMoved(Input)
	if Input.UserInputType == Enum.UserInputType.MouseMovement then
		local dx, dy = Input.Delta.x * Sensitivity, Input.Delta.y * Sensitivity
		local m2 = dx * dx + dy * dy
		if m2 > 0 then
			CameraDirection = (AxisAngleLookOrientation(RootPart.CFrame, CameraDirection) * fromAxisAngle(v3(-dy, -dx, 0), m2 ^ 0.5)).lookVector
		end
		local RootOrientation = RootPart.CFrame - RootPart.Position
		local RelativeDirection = RootOrientation:inverse() * CameraDirection
		local AngX, AngY = AnglesXY(RelativeDirection)--RootOrientation:inverse()*
		if AngX < -1.57 * 11 / 12 then
			local y, z, c, s = RelativeDirection.y, RelativeDirection.z, math.cos(-1.57 * 11 / 12 - AngX), -math.sin(-1.57 * 11 / 12 - AngX)
			z, y = z * c - y * s, z * s + y * c
			CameraDirection = RootOrientation * v3(RelativeDirection.x < 0 and -(1 - y * y - z * z) ^ 0.5 or (1 - y * y - z * z) ^ 0.5, y, z)
		elseif AngX > 1.57 * 11 / 12 then
			local y, z, c, s = RelativeDirection.y, RelativeDirection.z, math.cos(1.57 * 11 / 12 - AngX), -math.sin(1.57 * 11 / 12 - AngX)
			z, y = z * c - y * s, z * s + y * c
			CameraDirection = RootOrientation * v3(RelativeDirection.x < 0 and -(1 - y * y - z * z) ^ 0.5 or (1 - y * y - z * z) ^ 0.5, y, z)
		end
	end
end

local Mouse = Player:GetMouse()

local Zoom = -0.7

Mouse.KeyDown:connect(function(k) 
	if k == "e" then 	
		Zoom = -0.7
	elseif k == "q" then
		Zoom = -0.7
	end
end)

InputService.InputChanged:connect(MouseMoved)

Neck.C1 = cf()

local _
local DirectionBound = 3.14159 / 3
local CurrentAngY = 0

local function CameraUpdate()
	Camera.CameraType = "Scriptable"
	local cx, cz = CameraDirection.x, CameraDirection.z
	local rvx, rvz = RootPart.Velocity.x, RootPart.Velocity.z
	if rvx * rvx + rvz * rvz > 4 and cx * rvx + cz * rvz < -0.5 * (cx * cx + cz * cz) ^ 0.5 * (rvx * rvx + rvz * rvz) ^ 0.5 then
		DirectionBound = math.min(DirectionBound * 0.9, math.abs(CurrentAngY * 0.9))
	else
		DirectionBound = DirectionBound * 0.1 + 3.14159 / 3 * 0.9
	end
	local AngX, AngY = EulerAnglesYX((RootPart.CFrame - RootPart.Position):inverse() * CameraDirection)
	if AngY > DirectionBound then
		RootPart.CFrame = RootPart.CFrame * CFrame.Angles(0, AngY - DirectionBound, 0)
	elseif AngY < -DirectionBound then
		RootPart.CFrame = RootPart.CFrame * CFrame.Angles(0, AngY + DirectionBound, 0)
	end
	_, CurrentAngY = EulerAnglesYX((RootPart.CFrame - RootPart.Position):inverse() * CameraDirection)
	local CameraOrientation = AxisAngleLookNew((RootPart.CFrame - RootPart.Position):inverse() * CameraDirection, 1)
	Neck.C0 = CFrame.new(0, 1, 0) * CameraOrientation * CFrame.new(0, 0.5, 0) -------------------------------- HEAD POSITION -------------------------------
	local PreCam = AxisAngleLook(RootPart.CFrame * cf(0, 1, 0), RootPart.CFrame * v3(0, 1, 0) + CameraDirection) * CFrame.new(0, 0.825, 0)
	if Zoom == 8 then
		local Part, Position = workspace:findPartOnRay(Ray.new(PreCam.p, PreCam.lookVector * -8), Character)
		Camera.CoordinateFrame = PreCam * CFrame.new(0, 0, (Position - PreCam.p).magnitude)
	else
		Camera.CoordinateFrame = PreCam * CFrame.new(0, 0, Zoom + 1) --------------------------- CAM POSITION ------------------------------------------
	end
end

game:GetService("RunService").RenderStepped:connect(CameraUpdate)

4 comments

0

OOF this is really long...

0

Suggest searching on YouTube on RemoteEvents, Bindables etc

0

its not really that hard to convert, all you need to do is change any parts that are related to UserInputService

0

If you hate FE quit developing. FE will overrun roblox anytime soon.