local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local CONFIG = {
TRIGGER_KEY = Enum.KeyCode.X,
CAMERA_POINTS = {
Vector3.new(284, 25, 257),
Vector3.new(248, 25, 257),
Vector3.new(248, 25, -226),
Vector3.new(283, 25, -226)
},
INDICATOR_SIZE = UDim2.new(0, 20, 0, 20),
SMOOTHING_SPEED = 0.2,
MAX_OFFSET = 180,
OFFSET_SCALING = .7,
GUI_TOGGLE_KEY = Enum.KeyCode.G -- Key to toggle the GUI
}
local camera = workspace.CurrentCamera
local player = Players.LocalPlayer
local mouse = player:GetMouse()
-- State tracking
local isKeyHeld = false
local selectedPoint = nil
local indicators = {}
local initialLookVector = nil
local isAHeld = false
local isDHeld = false
local scriptEnabled = true
local settingsGui = nil
-- Key name mappings for display
local keyNames = {
[Enum.KeyCode.A] = "A", [Enum.KeyCode.B] = "B", [Enum.KeyCode.C] = "C", [Enum.KeyCode.D] = "D",
[Enum.KeyCode.E] = "E", [Enum.KeyCode.F] = "F", [Enum.KeyCode.G] = "G", [Enum.KeyCode.H] = "H",
[Enum.KeyCode.I] = "I", [Enum.KeyCode.J] = "J", [Enum.KeyCode.K] = "K", [Enum.KeyCode.L] = "L",
[Enum.KeyCode.M] = "M", [Enum.KeyCode.N] = "N", [Enum.KeyCode.O] = "O", [Enum.KeyCode.P] = "P",
[Enum.KeyCode.Q] = "Q", [Enum.KeyCode.R] = "R", [Enum.KeyCode.S] = "S", [Enum.KeyCode.T] = "T",
[Enum.KeyCode.U] = "U", [Enum.KeyCode.V] = "V", [Enum.KeyCode.W] = "W", [Enum.KeyCode.X] = "X",
[Enum.KeyCode.Y] = "Y", [Enum.KeyCode.Z] = "Z",
[Enum.KeyCode.One] = "1", [Enum.KeyCode.Two] = "2", [Enum.KeyCode.Three] = "3", [Enum.KeyCode.Four] = "4",
[Enum.KeyCode.Five] = "5", [Enum.KeyCode.Six] = "6", [Enum.KeyCode.Seven] = "7", [Enum.KeyCode.Eight] = "8",
[Enum.KeyCode.Nine] = "9", [Enum.KeyCode.Zero] = "0",
[Enum.KeyCode.LeftShift] = "L-Shift", [Enum.KeyCode.RightShift] = "R-Shift",
[Enum.KeyCode.LeftControl] = "L-Ctrl", [Enum.KeyCode.RightControl] = "R-Ctrl",
[Enum.KeyCode.LeftAlt] = "L-Alt", [Enum.KeyCode.RightAlt] = "R-Alt",
[Enum.KeyCode.Space] = "Space", [Enum.KeyCode.Tab] = "Tab"
}
local function createSettingsGui()
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "CameraControlSettings"
screenGui.ResetOnSpawn = false
screenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
-- Main frame
local mainFrame = Instance.new("Frame")
mainFrame.Name = "MainFrame"
mainFrame.Size = UDim2.new(0, 300, 0, 350)
mainFrame.Position = UDim2.new(0.5, -150, 0.5, -175)
mainFrame.BackgroundColor3 = Color3.fromRGB(30, 30, 40)
mainFrame.BorderSizePixel = 0
mainFrame.Active = true
mainFrame.Draggable = true
mainFrame.Parent = screenGui
local mainCorner = Instance.new("UICorner")
mainCorner.CornerRadius = UDim.new(0, 8)
mainCorner.Parent = mainFrame
-- Title
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Size = UDim2.new(1, 0, 0, 40)
titleLabel.Position = UDim2.new(0, 0, 0, 0)
titleLabel.BackgroundTransparency = 1
titleLabel.Text = "Camera Control Settings"
titleLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
titleLabel.TextScaled = true
titleLabel.Font = Enum.Font.SourceSansBold
titleLabel.Parent = mainFrame
-- Close button
local closeButton = Instance.new("TextButton")
closeButton.Name = "CloseButton"
closeButton.Size = UDim2.new(0, 30, 0, 30)
closeButton.Position = UDim2.new(1, -35, 0, 5)
closeButton.BackgroundColor3 = Color3.fromRGB(200, 50, 50)
closeButton.Text = "X"
closeButton.TextColor3 = Color3.fromRGB(255, 255, 255)
closeButton.TextScaled = true
closeButton.Font = Enum.Font.SourceSansBold
closeButton.Parent = mainFrame
local closeCorner = Instance.new("UICorner")
closeCorner.CornerRadius = UDim.new(0, 4)
closeCorner.Parent = closeButton
-- Enable/Disable Toggle
local enableFrame = Instance.new("Frame")
enableFrame.Size = UDim2.new(1, -20, 0, 50)
enableFrame.Position = UDim2.new(0, 10, 0, 50)
enableFrame.BackgroundTransparency = 1
enableFrame.Parent = mainFrame
local enableLabel = Instance.new("TextLabel")
enableLabel.Size = UDim2.new(0.6, 0, 1, 0)
enableLabel.Position = UDim2.new(0, 0, 0, 0)
enableLabel.BackgroundTransparency = 1
enableLabel.Text = "Script Enabled:"
enableLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
enableLabel.TextScaled = true
enableLabel.Font = Enum.Font.SourceSans
enableLabel.TextXAlignment = Enum.TextXAlignment.Left
enableLabel.Parent = enableFrame
local enableToggle = Instance.new("TextButton")
enableToggle.Name = "EnableToggle"
enableToggle.Size = UDim2.new(0.3, 0, 0, 30)
enableToggle.Position = UDim2.new(0.65, 0, 0, 10)
enableToggle.BackgroundColor3 = scriptEnabled and Color3.fromRGB(50, 200, 50) or Color3.fromRGB(200, 50, 50)
enableToggle.Text = scriptEnabled and "ON" or "OFF"
enableToggle.TextColor3 = Color3.fromRGB(255, 255, 255)
enableToggle.TextScaled = true
enableToggle.Font = Enum.Font.SourceSansBold
enableToggle.Parent = enableFrame
local enableCorner = Instance.new("UICorner")
enableCorner.CornerRadius = UDim.new(0, 4)
enableCorner.Parent = enableToggle
-- Trigger Key Setting
local keyFrame = Instance.new("Frame")
keyFrame.Size = UDim2.new(1, -20, 0, 50)
keyFrame.Position = UDim2.new(0, 10, 0, 110)
keyFrame.BackgroundTransparency = 1
keyFrame.Parent = mainFrame
local keyLabel = Instance.new("TextLabel")
keyLabel.Size = UDim2.new(0.5, 0, 1, 0)
keyLabel.Position = UDim2.new(0, 0, 0, 0)
keyLabel.BackgroundTransparency = 1
keyLabel.Text = "Trigger Key:"
keyLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
keyLabel.TextScaled = true
keyLabel.Font = Enum.Font.SourceSans
keyLabel.TextXAlignment = Enum.TextXAlignment.Left
keyLabel.Parent = keyFrame
local keyButton = Instance.new("TextButton")
keyButton.Name = "KeyButton"
keyButton.Size = UDim2.new(0.4, 0, 0, 30)
keyButton.Position = UDim2.new(0.55, 0, 0, 10)
keyButton.BackgroundColor3 = Color3.fromRGB(60, 60, 80)
keyButton.Text = keyNames[CONFIG.TRIGGER_KEY] or "X"
keyButton.TextColor3 = Color3.fromRGB(255, 255, 255)
keyButton.TextScaled = true
keyButton.Font = Enum.Font.SourceSans
keyButton.Parent = keyFrame
local keyCorner = Instance.new("UICorner")
keyCorner.CornerRadius = UDim.new(0, 4)
keyCorner.Parent = keyButton
-- Max Offset Setting
local offsetFrame = Instance.new("Frame")
offsetFrame.Size = UDim2.new(1, -20, 0, 70)
offsetFrame.Position = UDim2.new(0, 10, 0, 170)
offsetFrame.BackgroundTransparency = 1
offsetFrame.Parent = mainFrame
local offsetLabel = Instance.new("TextLabel")
offsetLabel.Size = UDim2.new(1, 0, 0, 30)
offsetLabel.Position = UDim2.new(0, 0, 0, 0)
offsetLabel.BackgroundTransparency = 1
offsetLabel.Text = "Max Offset: " .. CONFIG.MAX_OFFSET
offsetLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
offsetLabel.TextScaled = true
offsetLabel.Font = Enum.Font.SourceSans
offsetLabel.TextXAlignment = Enum.TextXAlignment.Left
offsetLabel.Parent = offsetFrame
local offsetTextBox = Instance.new("TextBox")
offsetTextBox.Name = "OffsetTextBox"
offsetTextBox.Size = UDim2.new(1, 0, 0, 30)
offsetTextBox.Position = UDim2.new(0, 0, 0, 35)
offsetTextBox.BackgroundColor3 = Color3.fromRGB(60, 60, 80)
offsetTextBox.Text = tostring(CONFIG.MAX_OFFSET)
offsetTextBox.TextColor3 = Color3.fromRGB(255, 255, 255)
offsetTextBox.TextScaled = true
offsetTextBox.Font = Enum.Font.SourceSans
offsetTextBox.PlaceholderText = "Enter max offset value"
offsetTextBox.Parent = offsetFrame
local offsetBoxCorner = Instance.new("UICorner")
offsetBoxCorner.CornerRadius = UDim.new(0, 4)
offsetBoxCorner.Parent = offsetTextBox
-- Offset Scaling Setting
local scalingFrame = Instance.new("Frame")
scalingFrame.Size = UDim2.new(1, -20, 0, 70)
scalingFrame.Position = UDim2.new(0, 10, 0, 250)
scalingFrame.BackgroundTransparency = 1
scalingFrame.Parent = mainFrame
local scalingLabel = Instance.new("TextLabel")
scalingLabel.Size = UDim2.new(1, 0, 0, 30)
scalingLabel.Position = UDim2.new(0, 0, 0, 0)
scalingLabel.BackgroundTransparency = 1
scalingLabel.Text = "Offset Scaling: " .. CONFIG.OFFSET_SCALING
scalingLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
scalingLabel.TextScaled = true
scalingLabel.Font = Enum.Font.SourceSans
scalingLabel.TextXAlignment = Enum.TextXAlignment.Left
scalingLabel.Parent = scalingFrame
local scalingTextBox = Instance.new("TextBox")
scalingTextBox.Name = "ScalingTextBox"
scalingTextBox.Size = UDim2.new(1, 0, 0, 30)
scalingTextBox.Position = UDim2.new(0, 0, 0, 35)
scalingTextBox.BackgroundColor3 = Color3.fromRGB(60, 60, 80)
scalingTextBox.Text = tostring(CONFIG.OFFSET_SCALING)
scalingTextBox.TextColor3 = Color3.fromRGB(255, 255, 255)
scalingTextBox.TextScaled = true
scalingTextBox.Font = Enum.Font.SourceSans
scalingTextBox.PlaceholderText = "Enter scaling value (0.1 - 2.0)"
scalingTextBox.Parent = scalingFrame
local scalingBoxCorner = Instance.new("UICorner")
scalingBoxCorner.CornerRadius = UDim.new(0, 4)
scalingBoxCorner.Parent = scalingTextBox
-- Event connections
closeButton.MouseButton1Click:Connect(function()
screenGui:Destroy()
settingsGui = nil
end)
enableToggle.MouseButton1Click:Connect(function()
scriptEnabled = not scriptEnabled
enableToggle.BackgroundColor3 = scriptEnabled and Color3.fromRGB(50, 200, 50) or Color3.fromRGB(200, 50, 50)
enableToggle.Text = scriptEnabled and "ON" or "OFF"
if not scriptEnabled and isKeyHeld then
-- Stop camera control if script is disabled
isKeyHeld = false
selectedPoint = nil
local indicatorsGui = player.PlayerGui:FindFirstChild("CameraPointIndicators")
if indicatorsGui then
indicatorsGui:Destroy()
end
RunService:UnbindFromRenderStep("ProximityCameraControl")
end
end)
local isWaitingForKey = false
keyButton.MouseButton1Click:Connect(function()
if isWaitingForKey then return end
isWaitingForKey = true
keyButton.Text = "Press Key..."
keyButton.BackgroundColor3 = Color3.fromRGB(100, 100, 120)
local connection
connection = UserInputService.InputBegan:Connect(function(input, gameProcessed)
if gameProcessed then return end
if input.UserInputType == Enum.UserInputType.Keyboard then
CONFIG.TRIGGER_KEY = input.KeyCode
keyButton.Text = keyNames[input.KeyCode] or input.KeyCode.Name
keyButton.BackgroundColor3 = Color3.fromRGB(60, 60, 80)
isWaitingForKey = false
connection:Disconnect()
end
end)
end)
offsetTextBox.FocusLost:Connect(function()
local newValue = tonumber(offsetTextBox.Text)
if newValue and newValue >= 0 and newValue <= 1000 then
CONFIG.MAX_OFFSET = newValue
offsetLabel.Text = "Max Offset: " .. CONFIG.MAX_OFFSET
else
offsetTextBox.Text = tostring(CONFIG.MAX_OFFSET)
end
end)
scalingTextBox.FocusLost:Connect(function()
local newValue = tonumber(scalingTextBox.Text)
if newValue and newValue >= 0.1 and newValue <= 2.0 then
CONFIG.OFFSET_SCALING = newValue
scalingLabel.Text = "Offset Scaling: " .. CONFIG.OFFSET_SCALING
else
scalingTextBox.Text = tostring(CONFIG.OFFSET_SCALING)
end
end)
screenGui.Parent = player.PlayerGui
return screenGui
end
local function createIndicators()
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "CameraPointIndicators"
screenGui.ResetOnSpawn = false
for i, point in ipairs(CONFIG.CAMERA_POINTS) do
local frame = Instance.new("Frame")
frame.Size = CONFIG.INDICATOR_SIZE
frame.AnchorPoint = Vector2.new(0.5, 0.5)
frame.BackgroundColor3 = Color3.fromRGB(255, 0, 0)
frame.BorderSizePixel = 0
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(1, 0)
corner.Parent = frame
frame.Parent = screenGui
indicators[i] = frame
end
screenGui.Parent = player.PlayerGui
return screenGui
end
local function updateIndicators()
for i, point in ipairs(CONFIG.CAMERA_POINTS) do
local screenPos, isOnScreen = camera:WorldToScreenPoint(point)
local indicator = indicators[i]
if isOnScreen then
indicator.Position = UDim2.new(0, screenPos.X, 0, screenPos.Y)
indicator.Visible = true
indicator.BackgroundColor3 = (point == selectedPoint)
and Color3.fromRGB(0, 255, 0)
or Color3.fromRGB(255, 0, 0)
else
indicator.Visible = false
end
end
end
local function findClosestPoint()
local closestPoint = CONFIG.CAMERA_POINTS[1]
local closestDistance = math.huge
for _, point in ipairs(CONFIG.CAMERA_POINTS) do
local screenPos, isOnScreen = camera:WorldToScreenPoint(point)
if isOnScreen then
local distance = (Vector2.new(mouse.X, mouse.Y) - Vector2.new(screenPos.X, screenPos.Y)).Magnitude
if distance < closestDistance then
closestDistance = distance
closestPoint = point
end
end
end
return closestPoint
end
local function updateCamera()
if not isKeyHeld or not selectedPoint or not scriptEnabled then return end
updateIndicators()
local characterPosition = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
and player.Character.HumanoidRootPart.Position
or camera.CFrame.Position
local distanceToPoint = (characterPosition - selectedPoint).Magnitude
local offsetAmount
if distanceToPoint <= 13 then
offsetAmount = 0
else
offsetAmount = math.min(distanceToPoint * CONFIG.OFFSET_SCALING, CONFIG.MAX_OFFSET)
end
local offsetPosition = selectedPoint
local dir = (selectedPoint - characterPosition)
dir = Vector3.new(dir.X, 0, dir.Z).Unit
local rightVector = dir:Cross(Vector3.new(0, 1, 0)).Unit
local distanceToPoint = (characterPosition - selectedPoint).Magnitude
local offsetAmount
if distanceToPoint <= 13 then
offsetAmount = 0
else
offsetAmount = math.min(distanceToPoint * CONFIG.OFFSET_SCALING, CONFIG.MAX_OFFSET) * 1.07
end
local offsetPosition = selectedPoint
if isAHeld then
offsetPosition = offsetPosition
+ Vector3.new(0, offsetAmount, 0)
+ rightVector * offsetAmount
elseif isDHeld then
offsetPosition = offsetPosition
+ Vector3.new(0, offsetAmount, 0)
- rightVector * offsetAmount
end
local targetCFrame = CFrame.lookAt(characterPosition, offsetPosition)
local currentCFrame = camera.CFrame
local newCFrame = currentCFrame:Lerp(targetCFrame, CONFIG.SMOOTHING_SPEED)
camera.CFrame = CFrame.new(currentCFrame.Position) * CFrame.fromOrientation(newCFrame:ToOrientation())
local targetCFrame = CFrame.lookAt(characterPosition, offsetPosition)
local currentCFrame = camera.CFrame
local newCFrame = currentCFrame:Lerp(targetCFrame, CONFIG.SMOOTHING_SPEED)
camera.CFrame = CFrame.new(currentCFrame.Position) * CFrame.fromOrientation(newCFrame:ToOrientation())
end
local function onInputBegan(input, gameProcessed)
if gameProcessed then return end
if input.KeyCode == CONFIG.GUI_TOGGLE_KEY then
if settingsGui then
settingsGui:Destroy()
settingsGui = nil
else
settingsGui = createSettingsGui()
end
return
end
if not scriptEnabled then return end
if input.KeyCode == CONFIG.TRIGGER_KEY then
isKeyHeld = true
selectedPoint = findClosestPoint()
initialLookVector = camera.CFrame.LookVector
if not player.PlayerGui:FindFirstChild("CameraPointIndicators") then
createIndicators()
end
RunService:BindToRenderStep(
"ProximityCameraControl",
Enum.RenderPriority.Camera.Value,
updateCamera
)
elseif input.KeyCode == Enum.KeyCode.A then
isAHeld = true
elseif input.KeyCode == Enum.KeyCode.D then
isDHeld = true
end
end
local function onInputEnded(input, gameProcessed)
if input.KeyCode == CONFIG.TRIGGER_KEY then
isKeyHeld = false
selectedPoint = nil
local indicatorsGui = player.PlayerGui:FindFirstChild("CameraPointIndicators")
if indicatorsGui then
indicatorsGui:Destroy()
end
RunService:UnbindFromRenderStep("ProximityCameraControl")
elseif input.KeyCode == Enum.KeyCode.A then
isAHeld = false
elseif input.KeyCode == Enum.KeyCode.D then
isDHeld = false
end
end
UserInputService.InputBegan:Connect(onInputBegan)
UserInputService.InputEnded:Connect(onInputEnded)
game:BindToClose(function()
local indicatorsGui = player.PlayerGui:FindFirstChild("CameraPointIndicators")
if indicatorsGui then
indicatorsGui:Destroy()
end
if settingsGui then
settingsGui:Destroy()
end
end)