Advertisement
Steamhesaproblox

Roblox Freecam script

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