Advertisement
nebunet

freecam

Apr 30th, 2023 (edited)
869
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.21 KB | None | 0 0
  1. -- yoinked from roblox studio default freecam script
  2. -- (yes, it's built in you just have to press left shift + p to activate)
  3. -- only works in studio though, but this one works universally
  4.  
  5. --!nonstrict
  6. ------------------------------------------------------------------------
  7. -- Freecam
  8. -- Cinematic free camera for spectating and video production.
  9. ------------------------------------------------------------------------
  10.  
  11. local pi    = math.pi
  12. local abs   = math.abs
  13. local clamp = math.clamp
  14. local exp   = math.exp
  15. local rad   = math.rad
  16. local sign  = math.sign
  17. local sqrt  = math.sqrt
  18. local tan   = math.tan
  19.  
  20. local ContextActionService = game:GetService("ContextActionService")
  21. local Players = game:GetService("Players")
  22. local RunService = game:GetService("RunService")
  23. local StarterGui = game:GetService("StarterGui")
  24. local UserInputService = game:GetService("UserInputService")
  25. local Workspace = game:GetService("Workspace")
  26. local Settings = UserSettings()
  27. local GameSettings = Settings.GameSettings
  28.  
  29. local LocalPlayer = Players.LocalPlayer
  30. if not LocalPlayer then
  31.     Players:GetPropertyChangedSignal("LocalPlayer"):Wait()
  32.     LocalPlayer = Players.LocalPlayer
  33. end
  34.  
  35. local Camera = Workspace.CurrentCamera
  36. Workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function()
  37.     local newCamera = Workspace.CurrentCamera
  38.     if newCamera then
  39.         Camera = newCamera
  40.     end
  41. end)
  42.  
  43. local FFlagUserExitFreecamBreaksWithShiftlock
  44. do
  45.     local success, result = pcall(function()
  46.         return UserSettings():IsUserFeatureEnabled("UserExitFreecamBreaksWithShiftlock")
  47.     end)
  48.     FFlagUserExitFreecamBreaksWithShiftlock = success and result
  49. end
  50.  
  51. ------------------------------------------------------------------------
  52.  
  53. local TOGGLE_INPUT_PRIORITY = Enum.ContextActionPriority.Low.Value
  54. local INPUT_PRIORITY = Enum.ContextActionPriority.High.Value
  55. local FREECAM_MACRO_KB = {Enum.KeyCode.LeftShift, Enum.KeyCode.P}
  56.  
  57. local NAV_GAIN = Vector3.new(1, 1, 1)*64
  58. local PAN_GAIN = Vector2.new(0.75, 1)*8
  59. local FOV_GAIN = 300
  60.  
  61. local PITCH_LIMIT = rad(90)
  62.  
  63. local VEL_STIFFNESS = 1.5
  64. local PAN_STIFFNESS = 1.0
  65. local FOV_STIFFNESS = 4.0
  66.  
  67. ------------------------------------------------------------------------
  68.  
  69. local Spring = {} do
  70.     Spring.__index = Spring
  71.  
  72.     function Spring.new(freq, pos)
  73.         local self = setmetatable({}, Spring)
  74.         self.f = freq
  75.         self.p = pos
  76.         self.v = pos*0
  77.         return self
  78.     end
  79.  
  80.     function Spring:Update(dt, goal)
  81.         local f = self.f*2*pi
  82.         local p0 = self.p
  83.         local v0 = self.v
  84.  
  85.         local offset = goal - p0
  86.         local decay = exp(-f*dt)
  87.  
  88.         local p1 = goal + (v0*dt - offset*(f*dt + 1))*decay
  89.         local v1 = (f*dt*(offset*f - v0) + v0)*decay
  90.  
  91.         self.p = p1
  92.         self.v = v1
  93.  
  94.         return p1
  95.     end
  96.  
  97.     function Spring:Reset(pos)
  98.         self.p = pos
  99.         self.v = pos*0
  100.     end
  101. end
  102.  
  103. ------------------------------------------------------------------------
  104.  
  105. local cameraPos = Vector3.new()
  106. local cameraRot = Vector2.new()
  107. local cameraFov = 0
  108.  
  109. local velSpring = Spring.new(VEL_STIFFNESS, Vector3.new())
  110. local panSpring = Spring.new(PAN_STIFFNESS, Vector2.new())
  111. local fovSpring = Spring.new(FOV_STIFFNESS, 0)
  112.  
  113. ------------------------------------------------------------------------
  114.  
  115. local Input = {} do
  116.     local thumbstickCurve do
  117.         local K_CURVATURE = 2.0
  118.         local K_DEADZONE = 0.15
  119.  
  120.         local function fCurve(x)
  121.             return (exp(K_CURVATURE*x) - 1)/(exp(K_CURVATURE) - 1)
  122.         end
  123.  
  124.         local function fDeadzone(x)
  125.             return fCurve((x - K_DEADZONE)/(1 - K_DEADZONE))
  126.         end
  127.  
  128.         function thumbstickCurve(x)
  129.             return sign(x)*clamp(fDeadzone(abs(x)), 0, 1)
  130.         end
  131.     end
  132.  
  133.     local gamepad = {
  134.         ButtonX = 0,
  135.         ButtonY = 0,
  136.         DPadDown = 0,
  137.         DPadUp = 0,
  138.         ButtonL2 = 0,
  139.         ButtonR2 = 0,
  140.         Thumbstick1 = Vector2.new(),
  141.         Thumbstick2 = Vector2.new(),
  142.     }
  143.  
  144.     local keyboard = {
  145.         W = 0,
  146.         A = 0,
  147.         S = 0,
  148.         D = 0,
  149.         E = 0,
  150.         Q = 0,
  151.         U = 0,
  152.         H = 0,
  153.         J = 0,
  154.         K = 0,
  155.         I = 0,
  156.         Y = 0,
  157.         Up = 0,
  158.         Down = 0,
  159.         LeftShift = 0,
  160.         RightShift = 0,
  161.     }
  162.  
  163.     local mouse = {
  164.         Delta = Vector2.new(),
  165.         MouseWheel = 0,
  166.     }
  167.  
  168.     local NAV_GAMEPAD_SPEED  = Vector3.new(1, 1, 1)
  169.     local NAV_KEYBOARD_SPEED = Vector3.new(1, 1, 1)
  170.     local PAN_MOUSE_SPEED    = Vector2.new(1, 1)*(pi/64)
  171.     local PAN_GAMEPAD_SPEED  = Vector2.new(1, 1)*(pi/8)
  172.     local FOV_WHEEL_SPEED    = 1.0
  173.     local FOV_GAMEPAD_SPEED  = 0.25
  174.     local NAV_ADJ_SPEED      = 0.75
  175.     local NAV_SHIFT_MUL      = 0.25
  176.  
  177.     local navSpeed = 1
  178.  
  179.     function Input.Vel(dt)
  180.         navSpeed = clamp(navSpeed + dt*(keyboard.Up - keyboard.Down)*NAV_ADJ_SPEED, 0.01, 4)
  181.  
  182.         local kGamepad = Vector3.new(
  183.             thumbstickCurve(gamepad.Thumbstick1.X),
  184.             thumbstickCurve(gamepad.ButtonR2) - thumbstickCurve(gamepad.ButtonL2),
  185.             thumbstickCurve(-gamepad.Thumbstick1.Y)
  186.         )*NAV_GAMEPAD_SPEED
  187.  
  188.         local kKeyboard = Vector3.new(
  189.             keyboard.D - keyboard.A + keyboard.K - keyboard.H,
  190.             keyboard.E - keyboard.Q + keyboard.I - keyboard.Y,
  191.             keyboard.S - keyboard.W + keyboard.J - keyboard.U
  192.         )*NAV_KEYBOARD_SPEED
  193.  
  194.         local shift = UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) or UserInputService:IsKeyDown(Enum.KeyCode.RightShift)
  195.  
  196.         return (kGamepad + kKeyboard)*(navSpeed*(shift and NAV_SHIFT_MUL or 1))
  197.     end
  198.  
  199.     function Input.Pan(dt)
  200.         local kGamepad = Vector2.new(
  201.             thumbstickCurve(gamepad.Thumbstick2.Y),
  202.             thumbstickCurve(-gamepad.Thumbstick2.X)
  203.         )*PAN_GAMEPAD_SPEED
  204.         local kMouse = mouse.Delta*PAN_MOUSE_SPEED
  205.         mouse.Delta = Vector2.new()
  206.         return kGamepad + kMouse
  207.     end
  208.  
  209.     function Input.Fov(dt)
  210.         local kGamepad = (gamepad.ButtonX - gamepad.ButtonY)*FOV_GAMEPAD_SPEED
  211.         local kMouse = mouse.MouseWheel*FOV_WHEEL_SPEED
  212.         mouse.MouseWheel = 0
  213.         return kGamepad + kMouse
  214.     end
  215.  
  216.     do
  217.         local function Keypress(action, state, input)
  218.             keyboard[input.KeyCode.Name] = state == Enum.UserInputState.Begin and 1 or 0
  219.             return Enum.ContextActionResult.Sink
  220.         end
  221.  
  222.         local function GpButton(action, state, input)
  223.             gamepad[input.KeyCode.Name] = state == Enum.UserInputState.Begin and 1 or 0
  224.             return Enum.ContextActionResult.Sink
  225.         end
  226.  
  227.         local function MousePan(action, state, input)
  228.             local delta = input.Delta
  229.             mouse.Delta = Vector2.new(-delta.y, -delta.x)
  230.             return Enum.ContextActionResult.Sink
  231.         end
  232.  
  233.         local function Thumb(action, state, input)
  234.             gamepad[input.KeyCode.Name] = input.Position
  235.             return Enum.ContextActionResult.Sink
  236.         end
  237.  
  238.         local function Trigger(action, state, input)
  239.             gamepad[input.KeyCode.Name] = input.Position.z
  240.             return Enum.ContextActionResult.Sink
  241.         end
  242.  
  243.         local function MouseWheel(action, state, input)
  244.             mouse[input.UserInputType.Name] = -input.Position.z
  245.             return Enum.ContextActionResult.Sink
  246.         end
  247.  
  248.         local function Zero(t)
  249.             for k, v in pairs(t) do
  250.                 t[k] = v*0
  251.             end
  252.         end
  253.  
  254.         function Input.StartCapture()
  255.             ContextActionService:BindActionAtPriority("FreecamKeyboard", Keypress, false, INPUT_PRIORITY,
  256.                 Enum.KeyCode.W, Enum.KeyCode.U,
  257.                 Enum.KeyCode.A, Enum.KeyCode.H,
  258.                 Enum.KeyCode.S, Enum.KeyCode.J,
  259.                 Enum.KeyCode.D, Enum.KeyCode.K,
  260.                 Enum.KeyCode.E, Enum.KeyCode.I,
  261.                 Enum.KeyCode.Q, Enum.KeyCode.Y,
  262.                 Enum.KeyCode.Up, Enum.KeyCode.Down
  263.             )
  264.             ContextActionService:BindActionAtPriority("FreecamMousePan",          MousePan,   false, INPUT_PRIORITY, Enum.UserInputType.MouseMovement)
  265.             ContextActionService:BindActionAtPriority("FreecamMouseWheel",        MouseWheel, false, INPUT_PRIORITY, Enum.UserInputType.MouseWheel)
  266.             ContextActionService:BindActionAtPriority("FreecamGamepadButton",     GpButton,   false, INPUT_PRIORITY, Enum.KeyCode.ButtonX, Enum.KeyCode.ButtonY)
  267.             ContextActionService:BindActionAtPriority("FreecamGamepadTrigger",    Trigger,    false, INPUT_PRIORITY, Enum.KeyCode.ButtonR2, Enum.KeyCode.ButtonL2)
  268.             ContextActionService:BindActionAtPriority("FreecamGamepadThumbstick", Thumb,      false, INPUT_PRIORITY, Enum.KeyCode.Thumbstick1, Enum.KeyCode.Thumbstick2)
  269.         end
  270.  
  271.         function Input.StopCapture()
  272.             navSpeed = 1
  273.             Zero(gamepad)
  274.             Zero(keyboard)
  275.             Zero(mouse)
  276.             ContextActionService:UnbindAction("FreecamKeyboard")
  277.             ContextActionService:UnbindAction("FreecamMousePan")
  278.             ContextActionService:UnbindAction("FreecamMouseWheel")
  279.             ContextActionService:UnbindAction("FreecamGamepadButton")
  280.             ContextActionService:UnbindAction("FreecamGamepadTrigger")
  281.             ContextActionService:UnbindAction("FreecamGamepadThumbstick")
  282.         end
  283.     end
  284. end
  285.  
  286. local function GetFocusDistance(cameraFrame)
  287.     local znear = 0.1
  288.     local viewport = Camera.ViewportSize
  289.     local projy = 2*tan(cameraFov/2)
  290.     local projx = viewport.x/viewport.y*projy
  291.     local fx = cameraFrame.rightVector
  292.     local fy = cameraFrame.upVector
  293.     local fz = cameraFrame.lookVector
  294.  
  295.     local minVect = Vector3.new()
  296.     local minDist = 512
  297.  
  298.     for x = 0, 1, 0.5 do
  299.         for y = 0, 1, 0.5 do
  300.             local cx = (x - 0.5)*projx
  301.             local cy = (y - 0.5)*projy
  302.             local offset = fx*cx - fy*cy + fz
  303.             local origin = cameraFrame.p + offset*znear
  304.             local _, hit = Workspace:FindPartOnRay(Ray.new(origin, offset.unit*minDist))
  305.             local dist = (hit - origin).magnitude
  306.             if minDist > dist then
  307.                 minDist = dist
  308.                 minVect = offset.unit
  309.             end
  310.         end
  311.     end
  312.  
  313.     return fz:Dot(minVect)*minDist
  314. end
  315.  
  316. ------------------------------------------------------------------------
  317.  
  318. local function StepFreecam(dt)
  319.     local vel = velSpring:Update(dt, Input.Vel(dt))
  320.     local pan = panSpring:Update(dt, Input.Pan(dt))
  321.     local fov = fovSpring:Update(dt, Input.Fov(dt))
  322.  
  323.     local zoomFactor = sqrt(tan(rad(70/2))/tan(rad(cameraFov/2)))
  324.  
  325.     cameraFov = clamp(cameraFov + fov*FOV_GAIN*(dt/zoomFactor), 1, 120)
  326.     cameraRot = cameraRot + pan*PAN_GAIN*(dt/zoomFactor)
  327.     cameraRot = Vector2.new(clamp(cameraRot.x, -PITCH_LIMIT, PITCH_LIMIT), cameraRot.y%(2*pi))
  328.  
  329.     local cameraCFrame = CFrame.new(cameraPos)*CFrame.fromOrientation(cameraRot.x, cameraRot.y, 0)*CFrame.new(vel*NAV_GAIN*dt)
  330.     cameraPos = cameraCFrame.p
  331.  
  332.     Camera.CFrame = cameraCFrame
  333.     Camera.Focus = cameraCFrame*CFrame.new(0, 0, -GetFocusDistance(cameraCFrame))
  334.     Camera.FieldOfView = cameraFov
  335. end
  336.  
  337. local function CheckMouseLockAvailability()
  338.     local devAllowsMouseLock = Players.LocalPlayer.DevEnableMouseLock
  339.     local devMovementModeIsScriptable = Players.LocalPlayer.DevComputerMovementMode == Enum.DevComputerMovementMode.Scriptable
  340.     local userHasMouseLockModeEnabled = GameSettings.ControlMode == Enum.ControlMode.MouseLockSwitch
  341.     local userHasClickToMoveEnabled =  GameSettings.ComputerMovementMode == Enum.ComputerMovementMode.ClickToMove
  342.     local MouseLockAvailable = devAllowsMouseLock and userHasMouseLockModeEnabled and not userHasClickToMoveEnabled and not devMovementModeIsScriptable
  343.  
  344.     return MouseLockAvailable
  345. end
  346.  
  347. ------------------------------------------------------------------------
  348.  
  349. local PlayerState = {} do
  350.     local mouseBehavior
  351.     local mouseIconEnabled
  352.     local cameraType
  353.     local cameraFocus
  354.     local cameraCFrame
  355.     local cameraFieldOfView
  356.     local screenGuis = {}
  357.     local coreGuis = {
  358.         Backpack = true,
  359.         Chat = true,
  360.         Health = true,
  361.         PlayerList = true,
  362.     }
  363.     local setCores = {
  364.         BadgesNotificationsActive = true,
  365.         PointsNotificationsActive = true,
  366.     }
  367.  
  368.     -- Save state and set up for freecam
  369.     function PlayerState.Push()
  370.         for name in pairs(coreGuis) do
  371.             coreGuis[name] = StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType[name])
  372.             StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType[name], false)
  373.         end
  374.         for name in pairs(setCores) do
  375.             setCores[name] = StarterGui:GetCore(name)
  376.             StarterGui:SetCore(name, false)
  377.         end
  378.         local playergui = LocalPlayer:FindFirstChildOfClass("PlayerGui")
  379.         if playergui then
  380.             for _, gui in pairs(playergui:GetChildren()) do
  381.                 if gui:IsA("ScreenGui") and gui.Enabled then
  382.                     screenGuis[#screenGuis + 1] = gui
  383.                     gui.Enabled = false
  384.                 end
  385.             end
  386.         end
  387.  
  388.         cameraFieldOfView = Camera.FieldOfView
  389.         Camera.FieldOfView = 70
  390.  
  391.         cameraType = Camera.CameraType
  392.         Camera.CameraType = Enum.CameraType.Custom
  393.  
  394.         cameraCFrame = Camera.CFrame
  395.         cameraFocus = Camera.Focus
  396.  
  397.         mouseIconEnabled = UserInputService.MouseIconEnabled
  398.         UserInputService.MouseIconEnabled = false
  399.  
  400.         if FFlagUserExitFreecamBreaksWithShiftlock and CheckMouseLockAvailability() then
  401.             mouseBehavior = Enum.MouseBehavior.Default
  402.         else
  403.             mouseBehavior = UserInputService.MouseBehavior
  404.         end
  405.         UserInputService.MouseBehavior = Enum.MouseBehavior.Default
  406.     end
  407.  
  408.     -- Restore state
  409.     function PlayerState.Pop()
  410.         for name, isEnabled in pairs(coreGuis) do
  411.             StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType[name], isEnabled)
  412.         end
  413.         for name, isEnabled in pairs(setCores) do
  414.             StarterGui:SetCore(name, isEnabled)
  415.         end
  416.         for _, gui in pairs(screenGuis) do
  417.             if gui.Parent then
  418.                 gui.Enabled = true
  419.             end
  420.         end
  421.  
  422.         Camera.FieldOfView = cameraFieldOfView
  423.         cameraFieldOfView = nil
  424.  
  425.         Camera.CameraType = cameraType
  426.         cameraType = nil
  427.  
  428.         Camera.CFrame = cameraCFrame
  429.         cameraCFrame = nil
  430.  
  431.         Camera.Focus = cameraFocus
  432.         cameraFocus = nil
  433.  
  434.         UserInputService.MouseIconEnabled = mouseIconEnabled
  435.         mouseIconEnabled = nil
  436.  
  437.         UserInputService.MouseBehavior = mouseBehavior
  438.         mouseBehavior = nil
  439.     end
  440. end
  441.  
  442. local function StartFreecam()
  443.     local cameraCFrame = Camera.CFrame
  444.     cameraRot = Vector2.new(cameraCFrame:toEulerAnglesYXZ())
  445.     cameraPos = cameraCFrame.p
  446.     cameraFov = Camera.FieldOfView
  447.  
  448.     velSpring:Reset(Vector3.new())
  449.     panSpring:Reset(Vector2.new())
  450.     fovSpring:Reset(0)
  451.  
  452.     PlayerState.Push()
  453.     RunService:BindToRenderStep("Freecam", Enum.RenderPriority.Camera.Value, StepFreecam)
  454.     Input.StartCapture()
  455. end
  456.  
  457. local function StopFreecam()
  458.     Input.StopCapture()
  459.     RunService:UnbindFromRenderStep("Freecam")
  460.     PlayerState.Pop()
  461. end
  462.  
  463. ------------------------------------------------------------------------
  464.  
  465. do
  466.     local enabled = false
  467.  
  468.     function ToggleFreecam()
  469.         if enabled then
  470.             StopFreecam()
  471.         else
  472.             StartFreecam()
  473.         end
  474.         enabled = not enabled
  475.     end
  476.  
  477.     local function CheckMacro(macro)
  478.         for i = 1, #macro - 1 do
  479.             if not UserInputService:IsKeyDown(macro[i]) then
  480.                 return
  481.             end
  482.         end
  483.         ToggleFreecam()
  484.     end
  485.  
  486.     local function HandleActivationInput(action, state, input)
  487.         if state == Enum.UserInputState.Begin then
  488.             if input.KeyCode == FREECAM_MACRO_KB[#FREECAM_MACRO_KB] then
  489.                 CheckMacro(FREECAM_MACRO_KB)
  490.             end
  491.         end
  492.         return Enum.ContextActionResult.Pass
  493.     end
  494.  
  495.     ContextActionService:BindActionAtPriority("FreecamToggle", HandleActivationInput, false, TOGGLE_INPUT_PRIORITY, FREECAM_MACRO_KB[#FREECAM_MACRO_KB])
  496. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement