Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --script by boxrum
- local service = {
- uis = game:GetService("UserInputService"),
- players = game:GetService("Players"),
- userSettings = UserSettings():GetService("UserGameSettings"),
- run = game:GetService("RunService"),
- tween = game:GetService("TweenService")
- }
- local dynamic = {
- cameraData = {
- rotation = Vector2.new(0,0),
- zoom = 20,
- smoothZoom = 0,
- currentTilt = 0,
- rightClicking = false,
- shiftLock = false,
- raycast = {
- currentCollide = nil,
- clipZoom = 0
- }
- }
- }
- local settings = {
- mode = "r6",--will auto set
- minZoom = 0,
- maxZoom = 2000,
- zoomSmoothing = 0.75,-- 0-1
- tilt = {
- strength = 0.2,
- drift = 0.9, -- 0-1
- turnTilt = 2--degrees
- },
- maxAngle = 89,
- minAngle = -89,
- zoomTransparencyStart = 3,
- wallClip = false--camera collisions
- }
- local funcs = {--utility stuff
- solveBasedOnMode = function(list)
- return list[settings.mode]
- end,
- getCamera = function()
- local camera = workspace.CurrentCamera
- if not camera then
- camera = Instance.new("Camera")
- camera.Parent = workspace
- workspace.CurrentCamera = camera
- end
- return camera
- end,
- lerp = function(a,b,t)
- return a*(1-t)+b*t
- end,
- getSubjectCFrame = function(subject)
- local isHumanoid = subject:IsA("Humanoid")
- if not isHumanoid then
- return CFrame.new(subject.Position)
- end
- local rootPart = subject.RootPart
- if not rootPart then
- warn("Humanoid has no root part")
- return CFrame.new(0,0,0)
- end
- local cframe = CFrame.new(rootPart.Position+subject.CameraOffset)
- return cframe
- end,
- setCharacterTransparency = function(character,transparency)
- local all = character:GetDescendants()
- for _,v in pairs(all) do
- if not v:IsA("BasePart") then
- continue
- end
- local goal = transparency-v.Transparency
- v.LocalTransparencyModifier = goal
- end
- end,
- getFilterList = function(filter)
- local list = workspace:GetDescendants()
- local newList = {}
- for i,obj in pairs(list) do
- if not filter(obj) then
- continue
- end
- table.insert(newList,obj)
- end
- return newList
- end,
- }
- local characterData = {
- bodyParts = {},
- }
- local player = service.players.LocalPlayer
- function dynamic.cameraData:GetCharacterTransparencyGoal()--long ass function name
- local zoom = self.smoothZoom
- local amnt = math.clamp(-zoom/settings.zoomTransparencyStart + 1,0,1)
- local squared = 1-(1-amnt)^2
- return squared
- end
- function dynamic.cameraData:getRaycastZoom(origin, dest, exclude)
- local function filterObject(obj)
- local checks = {
- table.find(exclude,obj),
- obj:IsA("BasePart") and obj.Transparency+obj.LocalTransparencyModifier>=1,
- obj:IsA("BasePart") and obj.CanCollide == false,
- player.Character and obj:IsDescendantOf(player.Character)
- }
- for _,v in pairs(checks) do
- if not v then
- continue
- end
- return true
- end
- return false
- end
- local filterList = funcs.getFilterList(filterObject)
- local zoom = self.smoothZoom
- local params = RaycastParams.new()
- params.FilterDescendantsInstances = filterList
- local info = workspace:Raycast(origin, dest-origin, params)
- if not info then
- self.raycast.currentCollide = nil
- return zoom
- end
- --warn(filterList)
- --warn(info.Instance)
- local cameraMoving = service.uis:GetMouseDelta().Magnitude>0--mouse delta moving
- if (cameraMoving and self.raycast.currentCollide ~= info.Instance) or not settings.wallClip then
- return zoom--camera is still moving and has hit a new part (return existing zoom instead of colliding), prevents flickering when moving camera fast
- end
- self.raycast.currentCollide = info.Instance
- local hitPoint = info.Position
- local distance = (origin-hitPoint).Magnitude
- local newZoom = distance
- return newZoom
- end
- local function getCharacterParts(player)
- local character = player.Character or player.CharacterAdded:Wait()
- local humanoid = character:FindFirstChildOfClass("Humanoid") or character:WaitForChild("Humanoid")
- settings.mode = humanoid.RigType.Name
- local torso = funcs.solveBasedOnMode({
- R15 = character:FindFirstChild("UpperTorso"),
- R6 = character:FindFirstChild("Torso")
- })
- local head = character:WaitForChild("Head")
- return character,torso,head,humanoid--this is tilt im doing
- end
- function characterData:SetHumanoidProperty(property,value)
- local humanoid = self.bodyParts[4]
- if not humanoid then
- warn("Humanoid not found; cant set properties")
- end
- humanoid[property] = value
- end
- function characterData:GetHumanoidValue(property)
- local humanoid = self.bodyParts[4]
- if not humanoid then
- warn("Humanoid not found; cant get properties")
- end
- return humanoid[property]
- end
- function dynamic.cameraData:BuildCFrame(Z)--z is the tilt basically
- local function buildRaw(zoom)
- local frame = CFrame.Angles(0,-self.rotation.X,0)*CFrame.Angles(-self.rotation.Y,0,0)*CFrame.new(0,0,zoom)*CFrame.Angles(0,0,math.rad(Z))
- return frame
- end
- local subject = funcs.getCamera().CameraSubject
- local origin = subject and funcs.getSubjectCFrame(subject) or CFrame.new(0,0,0)
- local dest = origin.Position + buildRaw(self.smoothZoom).Position
- local newZoom = dynamic.cameraData:getRaycastZoom(origin.Position,dest,{player.Character})
- local finalFrame = buildRaw(newZoom)
- return finalFrame
- end
- function dynamic.cameraData:GetCameraFrame()--gets the camera cframe which can then be offset by a cframe of any object later
- local camera = funcs.getCamera()
- camera.CameraType = Enum.CameraType.Scriptable
- local zoom = self.zoom
- local firstPerson = zoom == 0
- if firstPerson or self.shiftLock then
- service.uis.MouseBehavior = Enum.MouseBehavior.LockCenter
- elseif self.rightClicking then
- service.uis.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
- else
- service.uis.MouseBehavior = Enum.MouseBehavior.Default
- end
- local sensitivity = service.uis.MouseDeltaSensitivity
- local rotation = self.rotation
- local delta = service.uis:GetMouseDelta()--lemme check it
- local tiltA = service.uis:IsKeyDown(Enum.KeyCode.A) and -settings.tilt.turnTilt or 0
- local tiltD = service.uis:IsKeyDown(Enum.KeyCode.D) and settings.tilt.turnTilt or 0
- local tiltS = service.uis:IsKeyDown(Enum.KeyCode.S) and settings.tilt.turnTilt or 0
- local tiltW = service.uis:IsKeyDown(Enum.KeyCode.W) and -settings.tilt.turnTilt or 0
- local addedTilt = tiltA + tiltD
- local addedTiltX = tiltS+tiltW
- local newTilt = delta.X*settings.tilt.strength/sensitivity + addedTilt
- self.currentTilt = funcs.lerp(self.currentTilt,newTilt,(1-settings.tilt.drift)/2)
- local newRotation = rotation+Vector2.new(math.rad(delta.X),math.rad(delta.y)) * (sensitivity/2)
- self.rotation = Vector2.new(
- newRotation.X%(math.pi*2),--loop over if rotation exceeds 360 degrees (2*pi in radians)
- math.clamp(newRotation.Y,math.rad(settings.minAngle),math.rad(settings.maxAngle))-- limit the vertical angle
- )
- return self:BuildCFrame(-self.currentTilt), firstPerson, self.shiftLock
- end
- function characterData.StopCamera()
- service.run:UnbindFromRenderStep("CameraControl")
- end
- function characterData:StartCamera(offset)
- local character,torso,head,humanoid = table.unpack(self.bodyParts)
- service.run:BindToRenderStep("CameraControl",1,function()
- --funcs.getCamera().CameraSubject = torso--doing constantly
- dynamic.cameraData.smoothZoom = funcs.lerp(dynamic.cameraData.smoothZoom,dynamic.cameraData.zoom,1-settings.zoomSmoothing)
- local subject = funcs.getCamera().CameraSubject
- local origin = subject and funcs.getSubjectCFrame(subject) or CFrame.new(0,0,0)
- local cameraFrame, firstPerson, shiftLock = dynamic.cameraData:GetCameraFrame()
- local shiftLockOffset = CFrame.new((shiftLock and not firstPerson and character and character.PrimaryPart) and 3 or 0,0,0)
- local newFrame = origin*CFrame.new(offset)*cameraFrame*shiftLockOffset
- local camOrient = Vector3.new(newFrame:ToOrientation())
- funcs.getCamera().CFrame = newFrame
- local autoOn = characterData:GetHumanoidValue("AutoRotate")
- if dynamic.cameraData.shiftLock then--"only setting the value when needed and not constantly" - my only excuse for branch
- if autoOn then
- characterData:SetHumanoidProperty("AutoRotate",false)
- end
- else
- if not autoOn then
- characterData:SetHumanoidProperty("AutoRotate",true)
- end
- end
- if character then
- local characterTransparency = dynamic.cameraData:GetCharacterTransparencyGoal()
- funcs.setCharacterTransparency(character,characterTransparency)
- end
- local character = player.Character
- if not character or not character.PrimaryPart then
- return
- end
- if not shiftLock and not firstPerson then
- return
- end
- local charFrame = character:GetPrimaryPartCFrame()
- local charRot = Vector3.new(charFrame:ToOrientation())
- local rotation = CFrame.Angles(charRot.X,camOrient.Y,charRot.Z)
- character:SetPrimaryPartCFrame(CFrame.new(charFrame.Position)*rotation)
- end)
- local run1,run2 = nil,nil
- local function endProcesses()
- warn("Ending processes")
- characterData.StopCamera()
- if run1 then
- run1:Disconnect()
- run1 = nil
- end
- if run2 then
- run2:Disconnect()
- run2 = nil
- end
- end
- local run1 = humanoid.Destroying:Connect(endProcesses)
- local run2 = humanoid.Died:Connect(endProcesses)
- end
- function characterData:Init()
- self.bodyParts = {getCharacterParts(player)}
- --funcs.getCamera().CameraSubject = self.bodyParts.torso--lock on
- service.uis.InputBegan:Connect(function(input)
- local inputTypes = {
- MouseButton2 = function()
- dynamic.cameraData.rightClicking = true
- end,
- Keyboard = function()--roblox forever
- local keycode = input.KeyCode
- local isShift = keycode == Enum.KeyCode.LeftShift or keycode == Enum.KeyCode.RightShift
- if isShift then
- dynamic.cameraData.shiftLock = not dynamic.cameraData.shiftLock--invert
- end
- end,
- }
- local func = inputTypes[input.UserInputType.Name]
- if type(func)~="function" then
- return
- end
- func()
- end)
- service.uis.InputChanged:Connect(function(input)
- local inputTypes = {
- MouseWheel = function()
- local direction = -input.Position.Z * ((dynamic.cameraData.zoom+4)/4)--scroll increment -1 or 1
- local newZoom = math.clamp(dynamic.cameraData.zoom+direction, settings.minZoom, settings.maxZoom)
- dynamic.cameraData.zoom = (dynamic.cameraData.zoom<3 and direction<0) and 0 or newZoom--player is zooming in and is already very close to being fully zoomed in
- end,
- }
- local func = inputTypes[input.UserInputType.Name]
- if type(func)~="function" then
- return
- end
- func()
- end)
- service.uis.InputEnded:Connect(function(input)
- local inputTypes = {
- MouseButton2 = function()
- dynamic.cameraData.rightClicking = false
- end,
- }
- local func = inputTypes[input.UserInputType.Name]
- if type(func)~="function" then
- return
- end
- func()
- end)
- end
- characterData:Init()
- characterData:StartCamera(Vector3.new(0,1.5,0))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement