local Players = game:GetService("Players") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local LocalPlayer = Players.LocalPlayer local startOffsetX = 0 local startOffsetY = 0 local startOffsetZ = 0 local comAdornment = Instance.new("SphereHandleAdornment") comAdornment.Radius = 0.4 comAdornment.Color3 = Color3.fromRGB(255, 255, 0) comAdornment.AlwaysOnTop = true comAdornment.ZIndex = 10 comAdornment.Adornee = workspace.Terrain comAdornment.Parent = workspace.Terrain local comLine = Instance.new("LineHandleAdornment") comLine.Thickness = 3 comLine.Color3 = Color3.fromRGB(255, 255, 255) comLine.AlwaysOnTop = true comLine.Adornee = workspace.Terrain comLine.Parent = workspace.Terrain local gui = Instance.new("ScreenGui") gui.Name = "COM_Dragger_Gui" gui.ResetOnSpawn = false gui.Parent = LocalPlayer:WaitForChild("PlayerGui") local savedPos = LocalPlayer:FindFirstChild("COM_UI_SavedPos") if not savedPos then savedPos = Instance.new("Vector3Value") savedPos.Name = "COM_UI_SavedPos" savedPos.Value = Vector3.new(100, 100, 0) savedPos.Parent = LocalPlayer end local savedCOMPos = LocalPlayer:FindFirstChild("COM_SavedPos") if not savedCOMPos then savedCOMPos = Instance.new("Vector3Value") savedCOMPos.Name = "COM_SavedPos" savedCOMPos.Value = Vector3.new(startOffsetX, startOffsetY, startOffsetZ) savedCOMPos.Parent = LocalPlayer end local mainFrame = Instance.new("Frame") mainFrame.Name = "MainFrame" mainFrame.Size = UDim2.new(0, 150, 0, 180) mainFrame.Position = UDim2.new(0, savedPos.Value.X, 0, savedPos.Value.Y) mainFrame.BackgroundColor3 = Color3.fromRGB(0, 0, 0) mainFrame.BorderSizePixel = 2 mainFrame.BorderColor3 = Color3.fromRGB(255, 0, 0) mainFrame.Active = true mainFrame.Draggable = true mainFrame.Parent = gui UserInputService.InputEnded:Connect(function(input, gameProcessedEvent) if input.UserInputType == Enum.UserInputType.MouseButton1 then savedPos.Value = Vector3.new(mainFrame.Position.X.Offset, mainFrame.Position.Y.Offset, 0) end end) local title = Instance.new("TextLabel") title.Name = "Title" title.Size = UDim2.new(1, -20, 0, 25) title.Position = UDim2.new(0, 0, 0, 0) title.BackgroundTransparency = 1 title.Text = "COM Dragger" title.TextColor3 = Color3.fromRGB(255, 255, 255) title.TextSize = 14 title.Font = Enum.Font.Legacy title.Parent = mainFrame local closeBtn = Instance.new("TextButton") closeBtn.Name = "CloseButton" closeBtn.Size = UDim2.new(0, 20, 0, 20) closeBtn.Position = UDim2.new(1, -20, 0, 2) closeBtn.BackgroundColor3 = Color3.fromRGB(255, 0, 0) closeBtn.BorderSizePixel = 1 closeBtn.BorderColor3 = Color3.fromRGB(150, 0, 0) closeBtn.Text = "X" closeBtn.TextColor3 = Color3.fromRGB(255, 255, 255) closeBtn.TextSize = 12 closeBtn.Font = Enum.Font.Legacy closeBtn.Parent = mainFrame local modeBtn = Instance.new("TextButton") modeBtn.Name = "ModeButton" modeBtn.Size = UDim2.new(0, 130, 0, 25) modeBtn.Position = UDim2.new(0, 10, 0, 30) modeBtn.Style = Enum.ButtonStyle.RobloxButtonDefault modeBtn.Text = "Mode: Moving" modeBtn.TextSize = 12 modeBtn.Font = Enum.Font.Legacy modeBtn.Parent = mainFrame local resetBtn = Instance.new("TextButton") resetBtn.Name = "ResetButton" resetBtn.Size = UDim2.new(0, 130, 0, 25) resetBtn.Position = UDim2.new(0, 10, 0, 60) resetBtn.Style = Enum.ButtonStyle.RobloxButtonDefault resetBtn.Text = "Reset COM" resetBtn.TextSize = 12 resetBtn.Font = Enum.Font.Legacy resetBtn.Parent = mainFrame local respawnBtn = Instance.new("TextButton") respawnBtn.Name = "RespawnButton" respawnBtn.Size = UDim2.new(0, 130, 0, 25) respawnBtn.Position = UDim2.new(0, 10, 0, 90) respawnBtn.Style = Enum.ButtonStyle.RobloxButtonDefault respawnBtn.Text = "Respawn" respawnBtn.TextSize = 12 respawnBtn.Font = Enum.Font.Legacy respawnBtn.Parent = mainFrame local visBtn = Instance.new("TextButton") visBtn.Name = "VisButton" visBtn.Size = UDim2.new(0, 130, 0, 25) visBtn.Position = UDim2.new(0, 10, 0, 120) visBtn.Style = Enum.ButtonStyle.RobloxButtonDefault visBtn.Text = "Vis: On" visBtn.TextSize = 12 visBtn.Font = Enum.Font.Legacy visBtn.Parent = mainFrame local hideBtn = Instance.new("TextButton") hideBtn.Name = "HideButton" hideBtn.Size = UDim2.new(0, 130, 0, 25) hideBtn.Position = UDim2.new(0, 10, 0, 150) hideBtn.Style = Enum.ButtonStyle.RobloxButtonDefault hideBtn.Text = "Hide UI" hideBtn.TextSize = 12 hideBtn.Font = Enum.Font.Legacy hideBtn.Parent = mainFrame local isMovingMode = true local currentHandles = nil local scriptActive = true local comVisibleState = true local uiVisible = true local showBtn = Instance.new("TextButton") showBtn.Name = "ShowButton" showBtn.Size = UDim2.new(0, 30, 0, 30) showBtn.Position = UDim2.new(0, savedPos.Value.X, 0, savedPos.Value.Y) showBtn.BackgroundColor3 = Color3.fromRGB(0, 0, 0) showBtn.BorderSizePixel = 2 showBtn.BorderColor3 = Color3.fromRGB(255, 0, 0) showBtn.Text = "+" showBtn.TextColor3 = Color3.fromRGB(255, 255, 255) showBtn.TextSize = 18 showBtn.Font = Enum.Font.Legacy showBtn.Visible = false showBtn.Parent = gui local function cleanup() scriptActive = false if gui then gui:Destroy() end if comAdornment then comAdornment:Destroy() end if comLine then comLine:Destroy() end if LocalPlayer.Character then local weight = LocalPlayer.Character:FindFirstChild("COM_Shift_Weight") if weight then weight:Destroy() end local proxy = LocalPlayer.Character:FindFirstChild("COM_Drag_Proxy") if proxy then proxy:Destroy() end end if currentHandles then currentHandles:Destroy() end if renderConnection then renderConnection:Disconnect() end savedCOMPos.Value = Vector3.new(startOffsetX, startOffsetY, startOffsetZ) end modeBtn.MouseButton1Click:Connect(function() isMovingMode = not isMovingMode modeBtn.Text = isMovingMode and "Mode: Moving" or "Mode: Normal" if currentHandles then currentHandles.Visible = isMovingMode end end) resetBtn.MouseButton1Click:Connect(function() savedCOMPos.Value = Vector3.new(0, 0, 0) if LocalPlayer.Character then local hrp = LocalPlayer.Character:FindFirstChild("HumanoidRootPart") if hrp then local weight = LocalPlayer.Character:FindFirstChild("COM_Shift_Weight") if weight then local weld = weight:FindFirstChild("Weld") if weld then weld.C0 = CFrame.new(0, 0, 0) end end end end end) respawnBtn.MouseButton1Click:Connect(function() local char = LocalPlayer.Character if char then char:BreakJoints() end end) visBtn.MouseButton1Click:Connect(function() comVisibleState = not comVisibleState visBtn.Text = comVisibleState and "Vis: On" or "Vis: Off" comAdornment.Visible = comVisibleState comLine.Visible = comVisibleState end) hideBtn.MouseButton1Click:Connect(function() uiVisible = not uiVisible mainFrame.Visible = uiVisible showBtn.Visible = not uiVisible hideBtn.Text = uiVisible and "Hide UI" or "Show UI" end) showBtn.MouseButton1Click:Connect(function() uiVisible = true mainFrame.Visible = true showBtn.Visible = false hideBtn.Text = "Hide UI" end) closeBtn.MouseButton1Click:Connect(cleanup) local renderConnection local function onCharacterAdded(character) if not scriptActive then return end if renderConnection then renderConnection:Disconnect() end local hrp = character:WaitForChild("HumanoidRootPart", 5) if not hrp then return end local comWeight = Instance.new("Part") comWeight.Name = "COM_Shift_Weight" comWeight.Size = Vector3.new(1.5, 1.5, 1.5) comWeight.Color = Color3.fromRGB(255, 50, 50) comWeight.Transparency = 0.5 comWeight.CanCollide = false comWeight.Massless = false comWeight.CustomPhysicalProperties = PhysicalProperties.new(100, 0, 0, 100, 100) comWeight.Parent = character local weld = Instance.new("Weld") weld.Part0 = hrp weld.Part1 = comWeight weld.C0 = CFrame.new(savedCOMPos.Value.X, savedCOMPos.Value.Y, savedCOMPos.Value.Z) weld.Parent = comWeight local dragProxy = Instance.new("Part") dragProxy.Name = "COM_Drag_Proxy" dragProxy.Size = comWeight.Size dragProxy.Transparency = 1 dragProxy.CanCollide = false dragProxy.Anchored = true dragProxy.Parent = character local handles = Instance.new("Handles") handles.Style = Enum.HandlesStyle.Movement handles.Color3 = Color3.fromRGB(0, 150, 255) handles.Adornee = dragProxy handles.Parent = LocalPlayer:WaitForChild("PlayerGui") handles.Visible = isMovingMode currentHandles = handles local startingC0 = weld.C0 local isDragging = false local axisMap = { [Enum.NormalId.Right] = Vector3.new(1, 0, 0), [Enum.NormalId.Left] = Vector3.new(-1, 0, 0), [Enum.NormalId.Top] = Vector3.new(0, 1, 0), [Enum.NormalId.Bottom] = Vector3.new(0, -1, 0), [Enum.NormalId.Front] = Vector3.new(0, 0, -1), [Enum.NormalId.Back] = Vector3.new(0, 0, 1), } handles.MouseButton1Down:Connect(function() isDragging = true startingC0 = weld.C0 end) handles.MouseButton1Up:Connect(function() isDragging = false savedCOMPos.Value = Vector3.new(weld.C0.Position.X, weld.C0.Position.Y, weld.C0.Position.Z) end) handles.MouseDrag:Connect(function(face, distance) local delta = axisMap[face] * distance weld.C0 = startingC0 * CFrame.new(delta) end) renderConnection = RunService.RenderStepped:Connect(function() if not character.Parent or not hrp.Parent then renderConnection:Disconnect() comLine.Length = 0 comAdornment.CFrame = CFrame.new(0, -1000, 0) return end if not isDragging then dragProxy.CFrame = comWeight.CFrame end local visualCOM = comWeight.Position if comVisibleState then comAdornment.CFrame = CFrame.new(visualCOM) local distanceToCOM = (hrp.Position - visualCOM).Magnitude comLine.Length = distanceToCOM if distanceToCOM > 0.01 then comLine.CFrame = CFrame.lookAt(hrp.Position, visualCOM) * CFrame.Angles(0, math.pi, 0) else comLine.Length = 0 end else comAdornment.CFrame = CFrame.new(0, -1000, 0) comLine.Length = 0 end end) end if LocalPlayer.Character then task.spawn(onCharacterAdded, LocalPlayer.Character) end LocalPlayer.CharacterAdded:Connect(onCharacterAdded)