--!nonstrict --[[========================================================================= DragDetector probe v2 v1 was wrong. It measured how far a part moved after each method and called any movement success -- with no control. An unanchored part drifts on its own: gravity, settling, the game nudging it. A couple of studs of that read as "it worked". v2 fixes the experiment: * a CONTROL pass first -- do nothing, measure the drift. Every method is then judged against that baseline, not against zero. * every push is UPWARD, because gravity opposes it. A part that rises is unambiguous; a part that moves "somewhat" is not. * each method runs TWICE and has to work both times. * the part's own state is reported first, since an anchored part or a PermissionPolicy of Nobody explains everything on its own. =========================================================================]] local Players = game:GetService("Players") local RunService = game:GetService("RunService") local LocalPlayer = Players.LocalPlayer local SETTLE = 20 -- frames to let things calm down before measuring local MEASURE = 25 -- frames per measured window local PUSH = 60 -- studs / screen-pixels-worth of shove local function guiHost() if gethui then local ok, host = pcall(gethui) if ok and host then return host end end local ok, core = pcall(game.GetService, game, "CoreGui") if ok and core then return core end return LocalPlayer:WaitForChild("PlayerGui") end local gui = Instance.new("ScreenGui") gui.Name = "DragProbe2" gui.ResetOnSpawn = false gui.IgnoreGuiInset = true gui.Parent = guiHost() local frame = Instance.new("Frame") frame.Size = UDim2.new(0, 560, 0, 360) frame.Position = UDim2.new(0.5, -280, 0, 40) frame.BackgroundColor3 = Color3.fromRGB(16, 16, 22) frame.BorderSizePixel = 0 frame.Parent = gui Instance.new("UICorner", frame).CornerRadius = UDim.new(0, 8) local text = Instance.new("TextLabel") text.BackgroundTransparency = 1 text.Position = UDim2.new(0, 12, 0, 10) text.Size = UDim2.new(1, -24, 1, -20) text.Font = Enum.Font.Code text.TextSize = 13 text.TextColor3 = Color3.fromRGB(215, 220, 235) text.TextXAlignment = Enum.TextXAlignment.Left text.TextYAlignment = Enum.TextYAlignment.Top text.TextWrapped = true text.Text = "probing..." text.Parent = frame local lines = {} local function log(line) lines[#lines + 1] = line if #lines > 22 then table.remove(lines, 1) end text.Text = table.concat(lines, "\n") print("[dragprobe] " .. line) end local function wait(frames) for _ = 1, frames do RunService.Heartbeat:Wait() end end local function findDetector() for _, inst in ipairs(workspace:GetDescendants()) do if inst:IsA("DragDetector") then local node = inst.Parent for _ = 1, 3 do if not node then break end if node:IsA("BasePart") then return inst, node end node = node.Parent end end end return nil end task.spawn(function() log("== DragDetector probe v2 (with control) ==") local det, part = findDetector() if not det then log("no DragDetector in workspace -- nothing to test.") return end local function readProp(name) local ok, v = pcall(function() return det[name] end) return ok and tostring(v) or "n/a" end log("part: " .. part:GetFullName()) log(string.format(" Anchored=%s Enabled=%s RunLocally=%s", tostring(part.Anchored), readProp("Enabled"), readProp("RunLocally"))) log(string.format(" Response=%s Permission=%s", readProp("ResponseStyle"), readProp("PermissionPolicy"))) if part.Anchored then log("!! the part is ANCHORED -- nothing can move it. That is the answer.") return end if readProp("PermissionPolicy") == "Enum.DragDetectorPermissionPolicy.Nobody" then log("!! PermissionPolicy is Nobody -- the game forbids dragging it.") return end local box = Instance.new("SelectionBox") box.Adornee = part box.Color3 = Color3.fromRGB(120, 200, 255) box.Transparency = 0.6 box.LineThickness = 0.04 box.Parent = gui -- how much does it move on its own? local function window(fn) wait(SETTLE) local from = part.Position local ok, err = true, nil if fn then ok, err = pcall(fn) end wait(MEASURE) local to = part.Position return (to - from).Magnitude, to.Y - from.Y, ok, err end log("") log("control: measuring drift with NO input...") local baseMag, baseUp = window(nil) local base2 = select(1, window(nil)) local baseline = math.max(baseMag, base2) log(string.format(" drifts %.2f / %.2f studs on its own (up %.2f)", baseMag, base2, baseUp)) log(string.format(" -> anything under %.2f studs means NOTHING", baseline * 3 + 1)) local threshold = baseline * 3 + 1 local results = {} local function test(name, fn) local pass, detail = 0, "" for run = 1, 2 do local mag, up, ok, err = window(fn) if not ok then detail = "ERR " .. tostring(err) break end -- must beat the baseline AND go the way we pushed (up) if mag > threshold and up > threshold * 0.5 then pass = pass + 1 end detail = detail .. string.format("[%.1f up%.1f] ", mag, up) end results[name] = pass log(string.format("%s: %s -> %s", name, detail, pass == 2 and "WORKS" or (pass == 1 and "inconsistent" or "no effect"))) end -- force the settings once, so later methods get the best chance pcall(function() det.Enabled = true end) pcall(function() det.RunLocally = false end) pcall(function() det.MaxActivationDistance = 1e6 end) pcall(function() det.ResponseStyle = Enum.DragDetectorResponseStyle.Geometric end) log("") test("1 DragFrame", function() det.DragFrame = det.DragFrame + Vector3.new(0, PUSH, 0) end) test("2 RestartDrag+Frame", function() det:RestartDrag() det.DragFrame = det.DragFrame + Vector3.new(0, PUSH, 0) end) local hasVim = pcall(function() return game:GetService("VirtualInputManager") end) if hasVim then test("3 simulated drag", function() local VIM = game:GetService("VirtualInputManager") local cam = workspace.CurrentCamera local sp, onScreen = cam:WorldToViewportPoint(part.Position) if not onScreen then error("off-screen -- look at the part") end VIM:SendMouseButtonEvent(sp.X, sp.Y, 0, true, game, 0) for i = 1, 14 do VIM:SendMouseMoveEvent(sp.X, sp.Y - i * 20, game) RunService.Heartbeat:Wait() end VIM:SendMouseButtonEvent(sp.X, sp.Y - 280, 0, false, game, 0) end) else log("3 simulated drag: no VirtualInputManager on this executor") end log("") local any = false for name, pass in pairs(results) do if pass == 2 then any = true end end if any then log("VERDICT: at least one method beat the control, twice, upward.") log("Tell me which one and the hub will use exactly that.") else log("VERDICT: nothing beat the control. Dragging does not work here.") log("v1 said otherwise because it had no control pass -- a couple of") log("studs of gravity read as success. It was measuring nothing.") end task.delay(20, function() box:Destroy() gui:Destroy() end) end)