scripts.nitaimaarek.com 11 scripts Log in
  1. scripts
  2. Optimizer — misc switches, anti-lag, auto-collect, prompts, clickdetectors, remote fuzzer (nm-lib)

Optimizer — misc switches, anti-lag, auto-collect, prompts, clickdetectors, remote fuzzer (nm-lib)

optimizer misc godmode anti-void dragdetector anti-afk auto-collect proximityprompt clickdetector remotespy fuzzer nm-lib universal

Works in any game. Misc switches (god mode w/ learned killbricks, anti-void, speed/jump, noclip, anti-AFK, anti-fog, full bright, hide GUIs, instant reset, rejoin same server, server hop), anti-lag, auto-collect, ProximityPrompt + ClickDetector automation, DragDetector spam, network ownership modes, and a remote fuzzer with vocabulary harvesting, player payloads and admin-remote blacklisting. Follows you between servers via queueonteleport -- no autoexec, nothing written to disk. Ctrl+H menu, Ctrl+Shift+S panic.
Paste it into any executor. It always pulls the latest version of this script.
125 views· 4,514 lines· 144.2 KB· added 22d ago raw

Source

--!nonstrict
--[[=========================================================================
    Optimizer  --  nm-lib build
    Anti-lag + auto-collect, rewritten for throughput.

    Perf rules this file follows, in order of how much they actually bought:

      1. Nothing scans the workspace on a frame. The part/pickup registries
         are maintained by DescendantAdded/DescendantRemoving as O(1) swap-
         remove dense arrays, so the hot loop walks a packed array with an
         integer cursor instead of pairs()-ing a dict full of dead refs.
      2. Teleporting pickups is OFF by default. firetouchinterest does not
         need proximity; skipping the CFrame write removes two physics-graph
         writes per pickup, which is the single biggest win in this script.
      3. Zero allocation in the hot loop: no closures, no per-part pcall, no
         per-part tables. One pcall wraps the whole batch.
      4. Toggle values are mirrored into plain upvalues by their callbacks,
         so the loop never touches Library.Options.x.Value.
      5. Every bulk operation (anti-lag apply, anti-lag revert, collect-all)
         runs through one chunked job runner, so a 60k-part map never hitches.
      6. One Heartbeat connection total. Idle cost is three comparisons.
      7. Property writes are guarded by a compare -- re-writing an identical
         Material still dirties the render + replication path.

    docs: https://nitaimaarek.com/nm
=========================================================================]]

local Library = loadstring(game:HttpGet("https://nitaimaarek.com/nm-lib"))()

--=========================================================================
-- locals: every hot symbol is pulled into a register slot up front
--=========================================================================

local RunService       = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players          = game:GetService("Players")
local Lighting         = game:GetService("Lighting")

local LocalPlayer = Players.LocalPlayer
local Mouse       = LocalPlayer:GetMouse()
local Terrain     = workspace.Terrain
local Heartbeat   = RunService.Heartbeat

local fireTouch   = firetouchinterest           -- nil on stock clients
local fireProx    = fireproximityprompt
local fireClick   = fireclickdetector
local table_move  = table.move
local table_create= table.create
local table_clear = table.clear
local math_min    = math.min
local string_match= string.match
local string_find = string.find
local string_lower= string.lower
local format      = string.format

local MAT_SMOOTH  = Enum.Material.SmoothPlastic
local QUALITY_LOW = Enum.QualityLevel.Level01
local QUALITY_AUTO= Enum.QualityLevel.Automatic
local MB1         = Enum.UserInputType.MouseButton1
local TAU         = math.pi * 2

-- modern clients expose the assembly properties; older ones only the aliases
-- Velocity first, deliberately. It is what every working ownership script
-- uses; AssemblyLinearVelocity is only a fallback for clients that dropped
-- the alias. Deviating from the proven property was one of the reasons the
-- earlier build did nothing.
local VEL_PROP, ANG_PROP = "Velocity", "RotVelocity"
do
    local probe = Instance.new("Part")
    if not pcall(function() probe.Velocity = Vector3.new() end) then
        VEL_PROP, ANG_PROP = "AssemblyLinearVelocity", "AssemblyAngularVelocity"
    end
    probe:Destroy()
end

--=========================================================================
-- dense set: O(1) insert, O(1) swap-remove, array-fast to iterate
--=========================================================================

local function newSet(reserve)
    return { items = table_create(reserve or 64), index = {}, n = 0 }
end

local function setAdd(s, v)
    if s.index[v] then return false end
    local n = s.n + 1
    s.n = n
    s.items[n] = v
    s.index[v] = n
    return true
end

local function setRemove(s, v)
    local i = s.index[v]
    if not i then return false end
    local n = s.n
    local last = s.items[n]
    s.items[i] = last
    s.index[last] = i
    s.items[n] = nil
    s.index[v] = nil
    s.n = n - 1
    return true
end

local function setClear(s)
    table_clear(s.items)
    table_clear(s.index)
    s.n = 0
end

local partSet   = newSet(8192)   -- every BasePart in workspace
local pickSet   = newSet(2048)   -- ...that carries a TouchInterest
local selSet    = newSet(256)    -- selected parts (membership, not visuals)

--=========================================================================
-- anti-lag bookkeeping: parallel arrays, so nothing allocates per part
--=========================================================================

local touched   = newSet(8192)   -- parts we changed
local oldMat    = table_create(8192)
local oldShadow = table_create(8192)
local oldRefl   = table_create(8192)

local fxSet     = newSet(512)    -- effects we disabled
local oldFx     = table_create(512)

local savedLight, savedTerrain, lightStash = {}, {}, nil

local EFFECTS = {
    ParticleEmitter = true, Trail = true, Smoke = true, Fire = true,
    Sparkles = true, Beam = true, Explosion = true,
    PointLight = true, SpotLight = true, SurfaceLight = true,
}

local function recordTouched(part)
    if touched.index[part] then return end
    local n = touched.n + 1
    touched.n = n
    touched.items[n] = part
    touched.index[part] = n
    oldMat[n]    = part.Material
    oldShadow[n] = part.CastShadow
    oldRefl[n]   = part.Reflectance
end

local function dropTouched(part)
    local i = touched.index[part]
    if not i then return end
    local n = touched.n
    local last = touched.items[n]
    touched.items[i] = last
    touched.index[last] = i
    oldMat[i], oldShadow[i], oldRefl[i] = oldMat[n], oldShadow[n], oldRefl[n]
    touched.items[n] = nil
    oldMat[n], oldShadow[n], oldRefl[n] = nil, nil, nil
    touched.index[part] = nil
    touched.n = n - 1
end

--=========================================================================
-- mirrored state -- the hot loop reads these, never Library.Options
--=========================================================================

local antiLagOn   = false
local collectOn   = false
local selectModeOn= false
local teleportOn  = false
local perFrame    = 120
local applyBudget = 1500
local filterMode  = 1            -- 1 all | 2 selected only | 3 all but selected
local boxCap      = 150
local boxColor    = Color3.fromRGB(96, 178, 235)

local killParts   = {}           -- [part] = true, learned damaging parts
local killCount   = 0
local godOn       = false

local rootPart    = nil          -- cached; never FindFirstChild per frame
local cursor      = 1

--=========================================================================
-- registry hooks
--=========================================================================

local function optimize(part)
    recordTouched(part)
    if part.Material ~= MAT_SMOOTH then part.Material = MAT_SMOOTH end
    if part.CastShadow then part.CastShadow = false end
    if part.Reflectance ~= 0 then part.Reflectance = 0 end
end

local activeNames = {}           -- [baseName] = compiled pattern
local boxes       = {}           -- [part] = SelectionBox
local boxCount    = 0

local function addBox(part)
    if boxes[part] or boxCount >= boxCap then return end
    local box = Instance.new("SelectionBox")
    box.Adornee = part
    box.Color3 = boxColor
    box.SurfaceColor3 = boxColor
    box.LineThickness = 0.04
    box.SurfaceTransparency = 0.8
    box.Parent = part
    boxes[part] = box
    boxCount = boxCount + 1
end

local function dropBox(part)
    local box = boxes[part]
    if not box then return end
    box:Destroy()
    boxes[part] = nil
    boxCount = boxCount - 1
end

local function onPartAdded(part)
    if not setAdd(partSet, part) then return end
    if antiLagOn then optimize(part) end
    if part:FindFirstChildOfClass("TouchTransmitter") then
        setAdd(pickSet, part)
    end
    -- a part streaming in joins a group that is already selected
    if next(activeNames) then
        local name = part.Name
        for _, pattern in pairs(activeNames) do
            if string_match(name, pattern) then
                setAdd(selSet, part)
                addBox(part)
                break
            end
        end
    end
end

local function onPartRemoved(part)
    setRemove(partSet, part)
    setRemove(pickSet, part)
    setRemove(selSet, part)
    dropTouched(part)
    dropBox(part)
end

--=========================================================================
-- chunked job runner -- every bulk op goes through this, so nothing hitches
--=========================================================================

-- A queue, not a single slot: toggling anti-lag and a bypass in the same
-- breath must not silently drop one of them.
local jobs = {}

local function startJob(items, n, budget, work, done, label)
    jobs[#jobs + 1] = { items = items, n = n, i = 1, budget = budget,
                        work = work, done = done, label = label }
end

local function stepJob()
    local job = jobs[1]
    local items, work = job.items, job.work
    local i, n = job.i, job.n
    local stop = math_min(i + job.budget - 1, n)
    for k = i, stop do
        local item = items[k]
        if item then work(item) end
    end
    job.i = stop + 1
    if job.i > n then
        table.remove(jobs, 1)
        if job.done then job.done() end
    end
end

local function snapshot(set)
    local n = set.n
    return table_move(set.items, 1, n, 1, table_create(n)), n
end

--=========================================================================
-- anti-lag
--=========================================================================

local LIGHT_PROPS = {
    GlobalShadows = false, Brightness = 1, FogEnd = 1e6,
    EnvironmentDiffuseScale = 0, EnvironmentSpecularScale = 0,
}
local TERRAIN_PROPS = {
    WaterWaveSize = 0, WaterWaveSpeed = 0,
    WaterReflectance = 0, WaterTransparency = 0,
}

local function killEffects()
    for _, inst in ipairs(workspace:GetDescendants()) do
        if EFFECTS[inst.ClassName] and setAdd(fxSet, inst) then
            oldFx[fxSet.n] = inst.Enabled
            inst.Enabled = false
        end
    end
end

local function flattenLighting()
    for prop, value in pairs(LIGHT_PROPS) do
        pcall(function()
            savedLight[prop] = Lighting[prop]
            Lighting[prop] = value
        end)
    end
    for prop, value in pairs(TERRAIN_PROPS) do
        pcall(function()
            savedTerrain[prop] = Terrain[prop]
            Terrain[prop] = value
        end)
    end
    -- stash, never ClearAllChildren: Sky/Atmosphere/post FX must come back
    lightStash = Instance.new("Folder")
    for _, child in ipairs(Lighting:GetChildren()) do
        child.Parent = lightStash
    end
    pcall(function() settings().Rendering.QualityLevel = QUALITY_LOW end)
end

local function restoreLighting()
    for prop, value in pairs(savedLight) do
        pcall(function() Lighting[prop] = value end)
    end
    for prop, value in pairs(savedTerrain) do
        pcall(function() Terrain[prop] = value end)
    end
    table_clear(savedLight)
    table_clear(savedTerrain)
    if lightStash then
        for _, child in ipairs(lightStash:GetChildren()) do
            child.Parent = Lighting
        end
        lightStash:Destroy()
        lightStash = nil
    end
    for i = 1, fxSet.n do
        local fx = fxSet.items[i]
        if fx.Parent then fx.Enabled = oldFx[i] end
    end
    setClear(fxSet)
    table_clear(oldFx)
    pcall(function() settings().Rendering.QualityLevel = QUALITY_AUTO end)
end

local statusLabel, promptLabel, clickLabel
local partsLabel, pickLabel, selLabel

local function setAntiLag(on)
    if antiLagOn == on then return end
    antiLagOn = on

    if on then
        killEffects()
        flattenLighting()
        local items, n = snapshot(partSet)
        startJob(items, n, applyBudget, function(part)
            if part.Parent then optimize(part) end
        end, function()
            statusLabel:SetText("anti-lag: applied to " .. touched.n .. " parts")
        end, "anti-lag")
    else
        -- walk backwards: restore() swap-removes out from under the cursor
        local items, n = snapshot(touched)
        local mats = table_move(oldMat, 1, n, 1, table_create(n))
        local shad = table_move(oldShadow, 1, n, 1, table_create(n))
        local refl = table_move(oldRefl, 1, n, 1, table_create(n))
        local k = 0
        startJob(items, n, applyBudget, function(part)
            k = k + 1
            if part.Parent then
                part.Material    = mats[k]
                part.CastShadow  = shad[k]
                part.Reflectance = refl[k]
            end
        end, function()
            setClear(touched)
            table_clear(oldMat); table_clear(oldShadow); table_clear(oldRefl)
            restoreLighting()
            statusLabel:SetText("anti-lag: off, map restored")
        end, "restore")
    end
end

--=========================================================================
-- auto-collect
--
-- One pcall guards the whole batch. Inside it there is no closure creation,
-- no table churn, and no Options lookup -- just an integer cursor over a
-- packed array. The mode branch is hoisted out of the loop.
--=========================================================================

local function fireBatch(root, budget)
    local items, n = pickSet.items, pickSet.n
    if n == 0 then return end
    if cursor > n then cursor = 1 end

    local rootCF = root.CFrame
    local index  = selSet.index
    local mode   = filterMode
    local tp     = teleportOn
    local i      = cursor

    for _ = 1, budget do
        local part = items[i]
        i = i + 1
        if i > n then i = 1 end

        if part then
            local pass
            if mode == 1 then
                pass = true
            elseif mode == 2 then
                pass = index[part] ~= nil
            else
                pass = index[part] == nil
            end

            if pass and godOn and killParts[part] then pass = false end

            if pass then
                if tp then
                    local home = part.CFrame
                    part.CFrame = rootCF
                    fireTouch(root, part, 0)
                    fireTouch(root, part, 1)
                    part.CFrame = home
                else
                    fireTouch(root, part, 0)
                    fireTouch(root, part, 1)
                end
            end
        end
    end

    cursor = i
end

local function stepCollect()
    local budget = perFrame
    local n = pickSet.n
    if budget > n then budget = n end
    pcall(fireBatch, rootPart, budget)
end

--=========================================================================
-- prompts + click detectors
--
-- Same discipline as the pickup registry. Everything the fire loop needs is
-- resolved once at registration -- the owner BasePart, a pre-lowercased
-- search string, and the untouched bypass properties -- so the loop reads
-- three aligned arrays and does nothing else.
--=========================================================================

local promptSet    = newSet(512)
local promptOwner  = table_create(512)   -- BasePart the prompt hangs off
local promptText   = table_create(512)   -- lowercased action/object/parent
local oldHold      = table_create(512)
local oldPromptDist= table_create(512)
local oldLOS       = table_create(512)

local clickSet     = newSet(512)
local clickOwner   = table_create(512)
local oldClickDist = table_create(512)

local promptOn, clickOn = false, false
local promptPerFrame, clickPerFrame = 40, 40
local promptMode, clickMode = 1, 1
local promptRangeSq, clickRangeSq = nil, nil
local promptNeedle = nil
local promptBypass, clickBypass = false, false
local clickRight = false
local promptCursor, clickCursor = 1, 1

local BIG_RANGE = 1e6

local function ownerPart(inst)
    local p = inst.Parent
    for _ = 1, 3 do                      -- prompt -> attachment -> part -> model
        if not p then return nil end
        if p:IsA("BasePart") then return p end
        p = p.Parent
    end
    return nil
end

local function applyPromptBypass(prompt)
    if prompt.HoldDuration ~= 0 then prompt.HoldDuration = 0 end
    if prompt.RequiresLineOfSight then prompt.RequiresLineOfSight = false end
    if prompt.MaxActivationDistance < BIG_RANGE then
        prompt.MaxActivationDistance = BIG_RANGE
    end
end

local function addPrompt(prompt)
    if promptSet.index[prompt] then return end
    local n = promptSet.n + 1
    promptSet.n = n
    promptSet.items[n] = prompt
    promptSet.index[prompt] = n
    promptOwner[n] = ownerPart(prompt)
    local parent = prompt.Parent
    promptText[n] = string_lower(
        (prompt.ActionText or "") .. " " .. (prompt.ObjectText or "") .. " " ..
        (parent and parent.Name or ""))
    -- originals captured before we ever touch them
    oldHold[n]       = prompt.HoldDuration
    oldPromptDist[n] = prompt.MaxActivationDistance
    oldLOS[n]        = prompt.RequiresLineOfSight
    if promptBypass then applyPromptBypass(prompt) end
end

local function dropPrompt(prompt)
    local i = promptSet.index[prompt]
    if not i then return end
    local n = promptSet.n
    local last = promptSet.items[n]
    promptSet.items[i] = last
    promptSet.index[last] = i
    promptOwner[i], promptText[i] = promptOwner[n], promptText[n]
    oldHold[i], oldPromptDist[i], oldLOS[i] = oldHold[n], oldPromptDist[n], oldLOS[n]
    promptSet.items[n] = nil
    promptOwner[n], promptText[n] = nil, nil
    oldHold[n], oldPromptDist[n], oldLOS[n] = nil, nil, nil
    promptSet.index[prompt] = nil
    promptSet.n = n - 1
end

local function addClick(cd)
    if clickSet.index[cd] then return end
    local n = clickSet.n + 1
    clickSet.n = n
    clickSet.items[n] = cd
    clickSet.index[cd] = n
    clickOwner[n] = ownerPart(cd)
    oldClickDist[n] = cd.MaxActivationDistance
    if clickBypass and cd.MaxActivationDistance < BIG_RANGE then
        cd.MaxActivationDistance = BIG_RANGE
    end
end

local function dropClick(cd)
    local i = clickSet.index[cd]
    if not i then return end
    local n = clickSet.n
    local last = clickSet.items[n]
    clickSet.items[i] = last
    clickSet.index[last] = i
    clickOwner[i], oldClickDist[i] = clickOwner[n], oldClickDist[n]
    clickSet.items[n] = nil
    clickOwner[n], oldClickDist[n] = nil, nil
    clickSet.index[cd] = nil
    clickSet.n = n - 1
end

-- The two fire loops. Identical shape to fireBatch: integer cursor over a
-- packed array, every option hoisted, one pcall around the whole batch.

local function promptBatch(budget)
    local items, owners, texts = promptSet.items, promptOwner, promptText
    local n = promptSet.n
    if n == 0 then return end
    if promptCursor > n then promptCursor = 1 end

    local index  = selSet.index
    local mode   = promptMode
    local needle = promptNeedle
    local r2     = promptRangeSq
    local rx, ry, rz = 0, 0, 0
    if r2 then
        local pos = rootPart.Position
        rx, ry, rz = pos.X, pos.Y, pos.Z
    end

    local i = promptCursor
    for _ = 1, budget do
        local slot = i
        local prompt = items[slot]
        i = i + 1
        if i > n then i = 1 end

        if prompt and prompt.Enabled then
            local pass = true
            if mode == 2 then
                pass = index[owners[slot]] ~= nil
            elseif mode == 3 then
                pass = index[owners[slot]] == nil
            end
            if pass and needle then
                pass = string_find(texts[slot], needle, 1, true) ~= nil
            end
            if pass and r2 then
                local owner = owners[slot]
                if owner then
                    local pos = owner.Position
                    local dx, dy, dz = pos.X - rx, pos.Y - ry, pos.Z - rz
                    pass = (dx * dx + dy * dy + dz * dz) <= r2
                else
                    pass = false
                end
            end
            if pass then fireProx(prompt) end
        end
    end
    promptCursor = i
end

local function clickBatch(budget)
    local items, owners = clickSet.items, clickOwner
    local n = clickSet.n
    if n == 0 then return end
    if clickCursor > n then clickCursor = 1 end

    local index = selSet.index
    local mode  = clickMode
    local r2    = clickRangeSq
    local ev    = clickRight and "RightMouseClick" or nil
    local rx, ry, rz = 0, 0, 0
    if r2 then
        local pos = rootPart.Position
        rx, ry, rz = pos.X, pos.Y, pos.Z
    end

    local i = clickCursor
    for _ = 1, budget do
        local slot = i
        local cd = items[slot]
        i = i + 1
        if i > n then i = 1 end

        if cd then
            local pass = true
            if mode == 2 then
                pass = index[owners[slot]] ~= nil
            elseif mode == 3 then
                pass = index[owners[slot]] == nil
            end
            if pass and r2 then
                local owner = owners[slot]
                if owner then
                    local pos = owner.Position
                    local dx, dy, dz = pos.X - rx, pos.Y - ry, pos.Z - rz
                    pass = (dx * dx + dy * dy + dz * dz) <= r2
                else
                    pass = false
                end
            end
            if pass then
                if ev then
                    fireClick(cd, 0, ev)
                else
                    fireClick(cd, 0)
                end
            end
        end
    end
    clickCursor = i
end

local function stepPrompts()
    local budget = promptPerFrame
    local n = promptSet.n
    if budget > n then budget = n end
    pcall(promptBatch, budget)
end

local function stepClicks()
    local budget = clickPerFrame
    local n = clickSet.n
    if budget > n then budget = n end
    pcall(clickBatch, budget)
end

local function setPromptBypass(on)
    if promptBypass == on then return end
    promptBypass = on
    local items, n = snapshot(promptSet)
    if on then
        startJob(items, n, 500, function(prompt)
            if prompt.Parent then applyPromptBypass(prompt) end
        end, nil, "prompt bypass")
    else
        startJob(items, n, 500, function(prompt)
            local i = promptSet.index[prompt]      -- slot may have shuffled
            if i and prompt.Parent then
                prompt.HoldDuration          = oldHold[i]
                prompt.MaxActivationDistance = oldPromptDist[i]
                prompt.RequiresLineOfSight   = oldLOS[i]
            end
        end, nil, "prompt restore")
    end
end

local function setClickBypass(on)
    if clickBypass == on then return end
    clickBypass = on
    local items, n = snapshot(clickSet)
    if on then
        startJob(items, n, 500, function(cd)
            if cd.Parent and cd.MaxActivationDistance < BIG_RANGE then
                cd.MaxActivationDistance = BIG_RANGE
            end
        end, nil, "click bypass")
    else
        startJob(items, n, 500, function(cd)
            local i = clickSet.index[cd]
            if i and cd.Parent then cd.MaxActivationDistance = oldClickDist[i] end
        end, nil, "click restore")
    end
end

--=========================================================================
-- remote finder + fuzzer
--
-- State lives in three tables rather than forty upvalues -- a Lua chunk gets
-- 200 locals and this file is already deep into them.
--
-- The point of this tab is not the spamming, it is working out WHICH payload
-- did something. So every fire is logged with the exact argument list, and
-- leaderstats / Backpack are watched: when one of them moves, the last three
-- payloads are printed as candidates (an effect lands a frame or two after
-- the packet, so the immediate last one is not always the culprit).
--=========================================================================

local Remotes = {
    set = newSet(512),
    path = table_create(512),      -- unique display path, aligned to the set
    cls  = table_create(512),      -- ClassName, aligned
    byPath = {},                   -- [display path] = remote
    truncated = 0,
    excludes = {},                 -- user exclusion substrings, lowercased
    blocked = 0, excluded = 0,     -- silently dropped / user-dropped counts
}

local Fuzz = {
    running = false,
    dry = false,
    interval = 0.12,
    clock = 0,
    queue = {}, qn = 0, rIdx = 1, pIdx = 1,
    payloads = {}, pn = 0,
    log = {}, logN = 0,
    recent = {},                   -- last 3 payload descriptions
    hits = {}, hitN = 0,
    watched = {},                  -- instances already wired to the hit watch
    fired = 0,
    gen = 0,                       -- invalidates late InvokeServer returns
    -- everything off at startup: arming the fuzzer should be a deliberate
    -- act, not the default state of a freshly loaded hub
    cats = { nums = false, strings = false, bools = false, insts = false,
             tables = false, vectors = false, pairs2 = false, triples = false,
             vocab = false, players = false },
    vocab = {}, vocabMax = 40, playerMax = 6,
    loop = false, laps = 0,
    jitter = 0,                    -- fraction of the interval added at random
    shuffle = false,
    skipErrors = true,             -- drop a remote that only ever errors
    errCount = {},                 -- [path] = consecutive errors
    startedAt = 0,
}

local FuzzUI = {}                  -- filled in when the tab is built

local REMOTE_CLASSES = {
    RemoteEvent = true, RemoteFunction = true, UnreliableRemoteEvent = true,
}
local BINDABLE_CLASSES = { BindableEvent = true, BindableFunction = true }

local SCAN_SERVICES = {
    "ReplicatedStorage", "ReplicatedFirst", "Workspace", "Lighting",
    "StarterGui", "StarterPack", "StarterPlayer", "SoundService",
    "Chat", "TextChatService", "MaterialService",
}

--------------------------------------------------------------- discovery

-- Never-touch list. These are admin / anticheat client remotes: firing them is
-- how you get logged, kicked or banned, and they are never what you are
-- looking for. Filtered at registration so they never appear anywhere -- not
-- in the dropdown, not in "run against all", not in the counts.
local NEVER = {
    "hdadminhdclient", "hdadmin", "adonis", "kohl", "basicadmin",
    "antiexploit", "anticheat", "anti_cheat", "reportexploit", "banhammer",
}

local function isBlacklisted(lowerPath)
    for i = 1, #NEVER do
        if string_find(lowerPath, NEVER[i], 1, true) then return true end
    end
    return false
end

local function isExcluded(lowerPath)
    local list = Remotes.excludes
    for i = 1, #list do
        if string_find(lowerPath, list[i], 1, true) then return true end
    end
    return false
end

local function ancestryText(inst)
    local parts = { inst.Name }
    local node = inst.Parent
    for _ = 1, 8 do
        if not node then break end
        parts[#parts + 1] = node.Name
        node = node.Parent
    end
    local ok, full = pcall(function() return inst:GetFullName() end)
    if ok and full then parts[#parts + 1] = full end
    return string_lower(table.concat(parts, "/"))
end

local function addRemote(inst)
    if Remotes.set.index[inst] then return end
    local path = inst:GetFullName()
    local lower = ancestryText(inst)

    if isBlacklisted(lower) then
        Remotes.blocked = Remotes.blocked + 1
        return
    end
    if isExcluded(lower) then
        Remotes.excluded = Remotes.excluded + 1
        return
    end

    if Remotes.byPath[path] then                 -- same name, same parent
        local k = 2
        while Remotes.byPath[path .. " #" .. k] do k = k + 1 end
        path = path .. " #" .. k
    end
    local n = Remotes.set.n + 1
    Remotes.set.n = n
    Remotes.set.items[n] = inst
    Remotes.set.index[inst] = n
    Remotes.path[n] = path
    Remotes.cls[n] = inst.ClassName
    Remotes.byPath[path] = inst
end

local function scanRemotes(includeBindables, done)
    setClear(Remotes.set)
    table_clear(Remotes.path)
    table_clear(Remotes.cls)
    table_clear(Remotes.byPath)
    Remotes.truncated = 0

    local roots = {}
    for _, name in ipairs(SCAN_SERVICES) do
        local ok, svc = pcall(game.GetService, game, name)
        if ok and svc then roots[#roots + 1] = svc end
    end
    if LocalPlayer then roots[#roots + 1] = LocalPlayer end

    local all = {}
    local n = 0
    for _, root in ipairs(roots) do
        local ok, kids = pcall(root.GetDescendants, root)
        if ok then
            for _, inst in ipairs(kids) do
                n = n + 1
                all[n] = inst
            end
        end
    end

    startJob(all, n, 3000, function(inst)
        local cls = inst.ClassName
        if REMOTE_CLASSES[cls] or (includeBindables and BINDABLE_CLASSES[cls]) then
            addRemote(inst)
        end
    end, done, "scan remotes")
end

--------------------------------------------------------------- payloads

-- A dynamic value is a function resolved at fire time, so a respawned
-- character or a per-remote parent is never a stale reference.
-- Dynamic values, resolved at fire time so a respawn or a leaving player
-- never leaves a stale reference. One table rather than seven upvalues --
-- this chunk is at Lua's 200-local ceiling.
local DYN = { label = setmetatable({}, { __mode = "k" }) }

function DYN.tag(label, fn)
    DYN.label[fn] = label
    return fn
end

DYN.player    = function() return LocalPlayer end
DYN.char      = function() return LocalPlayer.Character end
DYN.root      = function() return rootPart end
DYN.workspace = function() return workspace end
DYN.parent    = function(remote) return remote.Parent end

local function describe(v)
    local t = type(v)
    if t == "string" then return '"' .. v .. '"' end
    if t == "table" then
        local parts = {}
        for i = 1, #v do parts[#parts + 1] = tostring(v[i]) end
        for k, val in pairs(v) do
            if type(k) ~= "number" then
                parts[#parts + 1] = tostring(k) .. "=" .. tostring(val)
            end
        end
        return "{" .. table.concat(parts, ",") .. "}"
    end
    if t == "function" then
        if v == DYN.player then return "LocalPlayer" end
        if v == DYN.char then return "Character" end
        if v == DYN.root then return "HumanoidRootPart" end
        if v == DYN.workspace then return "workspace" end
        if v == DYN.parent then return "remote.Parent" end
        return DYN.label[v] or "<dyn>"
    end
    return tostring(v)
end

local function payload(...)
    local spec = table.pack(...)
    local labels = {}
    local dyn = false
    for i = 1, spec.n do
        labels[i] = describe(spec[i])
        if type(spec[i]) == "function" then dyn = true end
    end
    spec.dyn = dyn
    spec.label = "(" .. table.concat(labels, ", ") .. ")"
    return spec
end

-- The game already told us its nouns. Tool names, prompt action text, model
-- and folder names in ReplicatedStorage, shop button labels -- those are the
-- strings a remote actually expects. BuyItem("hi") was never going to work;
-- BuyItem("IronSword") might, and the word was sitting in the Backpack.
function Fuzz.harvest()
    local seen, out = {}, {}

    local function take(word)
        if type(word) ~= "string" then return end
        word = word:gsub("^%s+", ""):gsub("%s+$", "")
        if #word < 2 or #word > 40 then return end
        if tonumber(word) then return end          -- plain numbers are covered
        if seen[word] then return end
        if #out >= Fuzz.vocabMax then return end
        seen[word] = true
        out[#out + 1] = word
    end

    -- things you are holding or could hold
    local pack = LocalPlayer:FindFirstChild("Backpack")
    if pack then
        for _, tool in ipairs(pack:GetChildren()) do take(tool.Name) end
    end
    local char = LocalPlayer.Character
    if char then
        for _, tool in ipairs(char:GetChildren()) do
            if tool:IsA("Tool") then take(tool.Name) end
        end
    end
    local okStarter, starter = pcall(game.GetService, game, "StarterPack")
    if okStarter and starter then
        for _, tool in ipairs(starter:GetChildren()) do take(tool.Name) end
    end

    -- what the world invites you to do
    for i = 1, promptSet.n do
        local prompt = promptSet.items[i]
        if prompt.Parent then
            take(prompt.ActionText)
            take(prompt.ObjectText)
            if prompt.Parent then take(prompt.Parent.Name) end
        end
    end

    -- the game's own data folders, which is where item names usually live
    local okRS, rs = pcall(game.GetService, game, "ReplicatedStorage")
    if okRS and rs then
        for _, inst in ipairs(rs:GetChildren()) do
            take(inst.Name)
            if #out < Fuzz.vocabMax then
                for _, kid in ipairs(inst:GetChildren()) do take(kid.Name) end
            end
        end
    end

    -- and whatever the shop UI is calling things
    local gui = LocalPlayer:FindFirstChildOfClass("PlayerGui")
    if gui then
        for _, inst in ipairs(gui:GetDescendants()) do
            if inst:IsA("TextButton") or inst:IsA("TextLabel") then
                take(inst.Text)
            end
            if #out >= Fuzz.vocabMax then break end
        end
    end

    Fuzz.vocab = out
    if FuzzUI.vocab then
        FuzzUI.vocab:SetText(format("vocabulary: %d words%s", #out,
            #out > 0 and ("  e.g. " .. table.concat(out, ", ", 1,
                math_min(4, #out))) or ""))
    end
    return out
end

local function buildPayloads()
    local out = {}
    local cats = Fuzz.cats
    local function push(...) out[#out + 1] = payload(...) end

    push()                                            -- no arguments at all

    if cats.nums then
        for i = 1, 20 do push(i) end
        push(0); push(-1); push(0.5); push(100); push(1000); push(999999)
        push(math.huge)
    end
    if cats.strings then
        push("hi"); push(""); push("1"); push("true")
        push("Coin"); push("Buy"); push("all")
    end
    if cats.bools then push(true); push(false) end
    if cats.insts then
        push(DYN.player); push(DYN.char); push(DYN.root)
        push(DYN.workspace); push(DYN.parent)
    end
    if cats.tables then
        push({ 1, 2, 3 }); push({}); push({ 1 })
        push({ Amount = 1 }); push({ "hi" })
    end
    if cats.vectors then
        push(Vector3.new(0, 0, 0)); push(Vector3.new(1, 1, 1)); push(CFrame.new())
    end

    if cats.vocab then
        local words = Fuzz.harvest()
        for i = 1, #words do push(words[i]) end
    end

    -- Other players, three ways, because a remote that takes a target might
    -- want the instance, the name, or the id -- and there is no telling which.
    if cats.players then
        local others = {}
        for _, plr in ipairs(Players:GetPlayers()) do
            if plr ~= LocalPlayer then others[#others + 1] = plr end
        end
        for i = 1, math_min(#others, Fuzz.playerMax) do
            local name = others[i].Name
            push(DYN.tag("Player(" .. name .. ")", function()
                return Players:FindFirstChild(name)
            end))
            push(name)
            push(others[i].UserId)
            push(DYN.tag("Char(" .. name .. ")", function()
                local plr = Players:FindFirstChild(name)
                return plr and plr.Character
            end))
        end
    end

    if cats.pairs2 then
        local heads = { 1, "hi", true, DYN.player, 20, 0, { 1, 2, 3 }, "all" }
        local tails = { 1, "hi", true, DYN.player, 2, 0, "1", 20 }
        for _, a in ipairs(heads) do
            for _, b in ipairs(tails) do push(a, b) end
        end
    end
    if cats.triples then
        push(1, 2, 3)
        push(1, "hi", true)
        push("hi", 1, true)
        push(DYN.player, 1, true)
        push(DYN.player, "hi", 1)
        push(1, DYN.player, 1)
        push("Buy", 1, 1)
        push(1, 1, 1)
        push(DYN.char, 1, "hi")
        push({ 1, 2, 3 }, 1, "hi")
        push(true, 1, "hi")
        push(0, 0, 0)
    end

    Fuzz.payloads = out
    Fuzz.pn = #out
    if FuzzUI.count then
        FuzzUI.count:SetText(format("payloads: %d", Fuzz.pn))
    end
end

--------------------------------------------------------------- logging

local function logLine(text)
    local n = Fuzz.logN + 1
    Fuzz.logN = n
    Fuzz.log[n] = text
    if n > 400 then                                   -- ring, keep it bounded
        table_move(Fuzz.log, n - 200, n, 1, Fuzz.log)
        for i = 202, n do Fuzz.log[i] = nil end
        Fuzz.logN = 201
    end
    local labels = FuzzUI.lines
    if not labels then return end
    local total = Fuzz.logN
    for i = #labels, 1, -1 do
        local entry = Fuzz.log[total - (#labels - i)]
        labels[i]:SetText(entry or "")
    end
end

local function copyOut(text, what)
    if setclipboard then
        pcall(setclipboard, text)
        Library:Notify({ Title = "optimizer", Text = what .. " copied", Type = "success" })
    else
        print(text)
        Library:Notify({ Title = "optimizer",
            Text = "no setclipboard -- dumped to console", Type = "warn" })
    end
end

--------------------------------------------------------------- hit watch

local function noteHit(what, detail)
    local candidates = table.concat(Fuzz.recent, "   |   ")
    local line = format("HIT  %s %s\n     candidates: %s", what, detail, candidates)
    local n = Fuzz.hitN + 1
    Fuzz.hitN = n
    Fuzz.hits[n] = line
    logLine("*** " .. what .. " " .. detail)
    if FuzzUI.hit then
        FuzzUI.hit:SetText(format("hits: %d  --  last: %s %s", n, what, detail))
    end
    Library:Notify({ Title = "remote hit", Text = what .. " " .. detail, Type = "success" })
end

-- Return values are useless here -- most remotes are RemoteEvents and hand
-- back nothing. So the watcher does not read replies: it watches client-side
-- state that the SERVER moves. Any *Value under the player (leaderstats is
-- just the common case), the Backpack, and the Humanoid. When one of those
-- shifts mid-run, the last three payloads are printed as candidates.
--
-- It is a heuristic, not proof: passive income or another player's action
-- will also trip it. That is what the candidate list and the interval are
-- for -- widen the interval until each fire is individually attributable.
local VALUE_CLASSES = {
    IntValue = true, NumberValue = true, StringValue = true,
    BoolValue = true, ObjectValue = true, IntConstrainedValue = true,
}

local function watchValue(obj)
    if Fuzz.watched[obj] then return end
    Fuzz.watched[obj] = true
    local last = obj.Value
    Library:Connect(obj.Changed, function(value)
        if Fuzz.running then
            noteHit(obj.Name, tostring(last) .. " -> " .. tostring(value))
        end
        last = value
    end)
end

local function armHitWatch()
    for _, inst in ipairs(LocalPlayer:GetDescendants()) do
        if VALUE_CLASSES[inst.ClassName] then watchValue(inst) end
    end
    if not Fuzz.watched[LocalPlayer] then
        Fuzz.watched[LocalPlayer] = true
        Library:Connect(LocalPlayer.DescendantAdded, function(inst)
            if VALUE_CLASSES[inst.ClassName] then
                watchValue(inst)
            elseif inst.ClassName == "Tool" and Fuzz.running then
                noteHit("tool +", inst.Name)
            end
        end)
    end

    local char = LocalPlayer.Character
    local humanoid = char and char:FindFirstChildOfClass("Humanoid")
    if humanoid and not Fuzz.watched[humanoid] then
        Fuzz.watched[humanoid] = true
        local hp = humanoid.Health
        Library:Connect(humanoid.HealthChanged, function(value)
            if Fuzz.running then
                noteHit("Health", tostring(hp) .. " -> " .. tostring(value))
            end
            hp = value
        end)
        for _, prop in ipairs({ "WalkSpeed", "JumpPower", "MaxHealth" }) do
            local ok, signal = pcall(humanoid.GetPropertyChangedSignal, humanoid, prop)
            if ok and signal then
                Library:Connect(signal, function()
                    if Fuzz.running then
                        noteHit(prop, "-> " .. tostring(humanoid[prop]))
                    end
                end)
            end
        end
    end
end

--------------------------------------------------------------- the fuzzer

local function resolveArgs(spec, remote)
    if not spec.dyn then return spec end
    local out = { n = spec.n }
    for i = 1, spec.n do
        local v = spec[i]
        if type(v) == "function" then v = v(remote) end
        out[i] = v
    end
    return out
end

local function fireRemote(remote, cls, args, path, label)
    if cls == "RemoteEvent" or cls == "UnreliableRemoteEvent" then
        local ok, err = pcall(remote.FireServer, remote, table.unpack(args, 1, args.n))
        logLine(format("%s:FireServer%s  %s", path, label, ok and "ok" or ("ERR " .. tostring(err))))
    elseif cls == "RemoteFunction" then
        -- InvokeServer yields and can hang forever; never block the loop on it
        local gen = Fuzz.gen
        task.spawn(function()
            local ok, res = pcall(remote.InvokeServer, remote, table.unpack(args, 1, args.n))
            if gen ~= Fuzz.gen then return end        -- a late reply from a stopped run
            -- the reply is logged, but it is NOT a hit: a hit means observed
            -- state movement, and counting every non-nil return floods the list
            logLine(format("%s:InvokeServer%s  %s", path, label,
                ok and ("-> " .. tostring(res)) or ("ERR " .. tostring(res))))
        end)
    elseif cls == "BindableEvent" then
        local ok, err = pcall(remote.Fire, remote, table.unpack(args, 1, args.n))
        logLine(format("%s:Fire%s  %s", path, label, ok and "ok" or ("ERR " .. tostring(err))))
    elseif cls == "BindableFunction" then
        local ok, res = pcall(remote.Invoke, remote, table.unpack(args, 1, args.n))
        logLine(format("%s:Invoke%s  %s", path, label,
            ok and ("-> " .. tostring(res)) or ("ERR " .. tostring(res))))
    end
end

local function stopFuzz(reason)
    if not Fuzz.running then return end

    -- a finished lap restarts instead of stopping, when looping is on
    if reason == "finished" and Fuzz.loop and Fuzz.qn > 0 then
        Fuzz.laps = Fuzz.laps + 1
        Fuzz.rIdx, Fuzz.pIdx = 1, 1
        table_clear(Fuzz.errCount)
        logLine(format("-- lap %d done (%d fired), looping", Fuzz.laps, Fuzz.fired))
        return
    end

    Fuzz.running = false
    Fuzz.gen = Fuzz.gen + 1
    logLine("-- stopped: " .. reason .. " (" .. Fuzz.fired .. " fired)")
    if FuzzUI.status then
        FuzzUI.status:SetText(format("stopped -- %d fired, %d hits, %d laps",
            Fuzz.fired, Fuzz.hitN, Fuzz.laps))
    end
    if Library.Options.fuzzrun then Library.Options.fuzzrun:SetValue(false, true) end
end

local function startFuzz(list, n)
    if n == 0 or Fuzz.pn == 0 then
        Library:Notify({ Title = "optimizer",
            Text = "pick at least one remote and one payload category", Type = "warn" })
        return false
    end
    if Fuzz.shuffle then
        -- deterministic shuffle, no Math.random needed: walk the list with a
        -- stride that never revisits until it has covered everything
        local stride = n // 2
        if stride < 1 then stride = 1 end
        while n % stride == 0 and stride > 1 do stride = stride - 1 end
        local out, at = {}, 1
        for i = 1, n do
            out[i] = list[at]
            at = at + stride
            while at > n do at = at - n end
        end
        list = out
    end

    Fuzz.queue, Fuzz.qn = list, n
    Fuzz.rIdx, Fuzz.pIdx = 1, 1
    Fuzz.fired = 0
    Fuzz.laps = 0
    Fuzz.clock = 0
    Fuzz.startedAt = os.clock()
    table_clear(Fuzz.errCount)
    Fuzz.gen = Fuzz.gen + 1
    Fuzz.running = true
    logLine(format("-- run: %d remotes x %d payloads = %d fires%s",
        n, Fuzz.pn, n * Fuzz.pn, Fuzz.dry and "  (DRY RUN)" or ""))
    return true
end

local function stepFuzz(dt)
    Fuzz.clock = Fuzz.clock + dt
    if Fuzz.clock < Fuzz.interval then return end
    Fuzz.clock = 0

    local path = Fuzz.queue[Fuzz.rIdx]
    local remote = path and Remotes.byPath[path]
    if not remote or not remote.Parent then
        Fuzz.rIdx = Fuzz.rIdx + 1
        Fuzz.pIdx = 1
        if Fuzz.rIdx > Fuzz.qn then stopFuzz("finished") end
        return
    end

    local spec = Fuzz.payloads[Fuzz.pIdx]
    local slot = Remotes.set.index[remote]
    local cls = slot and Remotes.cls[slot] or remote.ClassName

    table.insert(Fuzz.recent, 1, path .. spec.label)
    Fuzz.recent[4] = nil

    if Fuzz.dry then
        logLine(format("dry  %s%s", path, spec.label))
    else
        fireRemote(remote, cls, resolveArgs(spec, remote), path, spec.label)
    end
    Fuzz.fired = Fuzz.fired + 1

    Fuzz.pIdx = Fuzz.pIdx + 1
    if Fuzz.pIdx > Fuzz.pn then
        Fuzz.pIdx = 1
        Fuzz.rIdx = Fuzz.rIdx + 1
        if Fuzz.rIdx > Fuzz.qn then
            stopFuzz("finished")
            return
        end
    end

    if FuzzUI.status then
        FuzzUI.status:SetText(format("remote %d/%d  payload %d/%d  fired %d",
            Fuzz.rIdx, Fuzz.qn, Fuzz.pIdx, Fuzz.pn, Fuzz.fired))
    end
end

--=========================================================================
-- network ownership  --  ring / fling / platform
--
-- Why the earlier attempts did nothing: writing CFrame from the client is a
-- suggestion the server discards, and AlignPosition/BodyPosition only help
-- once the server already considers the part yours. Ownership is the whole
-- problem, and it needs three things together:
--
--   1. LocalPlayer.ReplicationFocus = workspace
--      stops the server centring replication on your character.
--   2. sethiddenproperty(LocalPlayer, "SimulationRadius", math.huge) EVERY
--      frame -- the engine resets it constantly, so a throttle is not enough.
--   3. Continuously writing Velocity to the part. That write is what makes
--      the server hand ownership over and keep it there.
--
-- Once those hold, physics results replicate, so every mode below steers with
-- Velocity and never touches CFrame. Zero density is what makes it strong:
-- a massless part goes exactly where the velocity says instead of fighting
-- gravity and its own inertia.
--=========================================================================

local Net = {
    running = false,
    mode = "Ring",
    targetName = "Me",
    parts = {}, index = {}, n = 0,
    home = {},                     -- [part] = { cf, canCollide, props }
    source = "All unanchored",
    count = 1000,
    sizeCap = 0,                   -- 0 = no cap; the old hard 60 hid parts
    hold = true,                   -- keep ownership alive even when idle
    regather = 0,
    probePos = {}, probeMoved = 0, probeSample = 0,
    diagFocus = false, diagRadius = false, diagFn = false,
    range = 250,
    angle = 0,
    radius = 50, height = 100, speed = 1, pull = 1000,
    flingPower = 9000,
    platformDrop = 4, platformPart = nil,
    focusOn = false,
    status = "idle",
}

local ZERO_PROPS   -- PhysicalProperties.new(0,0,0,0,0), built lazily
local ZERO3 = Vector3.new(0, 0, 0)
local cos, sin, sqrt, atan2, abs = math.cos, math.sin, math.sqrt, math.atan2, math.abs

local function stillThere(part)
    return part and part.Parent ~= nil
end

-- Ownership, measured properly.
--
-- ReceiveAge is the time since the server last sent us this part's physics.
-- If the SERVER owns it, it refreshes constantly and the age sits at ~0 --
-- and everything we write is overridden, which is why an unowned part drifts
-- a little (our local prediction) and then snaps back the instant we stop
-- (the server's position was always the real one).
-- If WE own it, the server stops sending updates and the age climbs.
--
-- So age > 0 is the ownership test, and it is the only one a client can do.
local OWNED_AGE = 0.05

local function isOwned(part)
    local ok, age = pcall(function() return part.ReceiveAge end)
    if not ok or age == nil then return true end   -- no such property: assume yes
    return age > OWNED_AGE
end

local function targetPos()
    if Net.targetName == "Me" then
        return rootPart and rootPart.Position or nil
    end
    local plr = Players:FindFirstChild(Net.targetName)
    local char = plr and plr.Character
    local root = char and char:FindFirstChild("HumanoidRootPart")
    return root and root.Position or nil
end

-- Ownership reach. Cheap enough to run every frame, and it has to.
-- Every one of these used to be a bare pcall with the result thrown away, so
-- when the executor lacked sethiddenproperty -- or the client no longer has a
-- SimulationRadius property at all -- the script silently did nothing and
-- looked "client-sided". Now each primitive records whether it worked and the
-- tab shows it.
-- What did this executor actually give us? Every ownership primitive here is
-- optional, and a free executor missing one of them fails silently -- which is
-- indistinguishable from "the game refuses ownership" unless you look.
local function ownershipCapabilities()
    local caps = {}

    caps[#caps + 1] = "sethiddenproperty " ..
        (type(sethiddenproperty) == "function" and "yes" or "NO")
    caps[#caps + 1] = "setsimulationradius " ..
        (type(setsimulationradius) == "function" and "yes" or "NO")

    local okAge = pcall(function() return Instance.new("Part").ReceiveAge end)
    caps[#caps + 1] = "ReceiveAge " .. (okAge and "yes" or "NO")

    local okFocus = pcall(function()
        local was = LocalPlayer.ReplicationFocus
        LocalPlayer.ReplicationFocus = was
    end)
    caps[#caps + 1] = "ReplicationFocus " .. (okFocus and "yes" or "NO")

    local okRadius = false
    if type(sethiddenproperty) == "function" then
        okRadius = pcall(function()
            sethiddenproperty(LocalPlayer, "SimulationRadius", math.huge)
        end)
    end
    caps[#caps + 1] = "SimulationRadius write " .. (okRadius and "yes" or "NO")

    return table.concat(caps, "  |  ")
end

local function holdOwnership()
    if not Net.focusOn then
        Net.focusOn = true
        Net.diagFocus = pcall(function()
            LocalPlayer.ReplicationFocus = workspace
        end)
    end

    if sethiddenproperty then
        Net.diagFn = true
        Net.diagRadius = pcall(function()
            sethiddenproperty(LocalPlayer, "SimulationRadius", math.huge)
        end)
    elseif setsimulationradius then
        Net.diagFn = true
        Net.diagRadius = pcall(function() setsimulationradius(math.huge) end)
    else
        Net.diagFn = false
        Net.diagRadius = false
    end

    -- some clients still accept the plain property
    if not Net.diagRadius then
        Net.diagRadius = pcall(function()
            LocalPlayer.MaximumSimulationRadius = math.huge
            LocalPlayer.SimulationRadius = math.huge
        end)
    end
end

-- Never touch a character: walk the ancestry rather than matching limb names,
-- so R15 rigs, accessories and tool handles are all covered.
local function isCharacterPart(part)
    local node = part
    for _ = 1, 4 do
        node = node.Parent
        if not node then return false end
        if node:FindFirstChildOfClass("Humanoid") then return true end
        if Players:GetPlayerFromCharacter(node) then return true end
    end
    return false
end

local function usable(part)
    if part.Anchored then return false end
    if not part.Parent then return false end
    local size = part.Size
    local cap = Net.sizeCap
    if cap > 0 and (size.X > cap or size.Y > cap or size.Z > cap) then
        return false
    end
    return not isCharacterPart(part)
end

-- Zero density is the point: a massless part is moved exactly by the velocity
-- we write, instead of the server's gravity and inertia arguing with it.
-- V4 zeroes density and drops collision on everything, which is exactly right
-- for a ring: a weightless part goes where the velocity says and never snags.
-- It is wrong for Fling, though -- a massless part carries no momentum, so it
-- would pass through harmlessly. Fling and Platform keep their real weight.
local function retain(part, collide, massless)
    if Net.index[part] then return end
    if not ZERO_PROPS then
        ZERO_PROPS = PhysicalProperties.new(0, 0, 0, 0, 0)
    end
    Net.home[part] = {
        canCollide = part.CanCollide,
        props = part.CustomPhysicalProperties or false,
    }
    pcall(function()
        if massless then part.CustomPhysicalProperties = ZERO_PROPS end
        part.CanCollide = collide and true or false
    end)
    local n = Net.n + 1
    Net.n = n
    Net.parts[n] = part
    Net.index[part] = n
end

-- Release: give each part its collision and weight back and stop pushing it.
-- Deliberately does NOT put parts back where they were -- that would be a
-- CFrame write, which is the one thing that does not replicate, so it would
-- only snap them locally and desync you from everyone else.
local function restoreAll()
    for part, home in pairs(Net.home) do
        if stillThere(part) then
            pcall(function()
                part.CustomPhysicalProperties = home.props or nil
                part.CanCollide = home.canCollide
                part[VEL_PROP] = ZERO3
                part[ANG_PROP] = ZERO3
            end)
        end
    end
    table_clear(Net.home)
    table_clear(Net.parts)
    table_clear(Net.index)
    Net.n = 0
    Net.platformPart = nil
end

-- Fling has to make contact, so those parts keep collision. Ring parts do not,
-- or they snag on the map on the way round.
local function wantsCollision()
    return Net.mode ~= "Ring"
end

local function wantsMassless()
    return Net.mode == "Ring"
end

local function gather()
    restoreAll()
    local collide, massless = wantsCollision(), wantsMassless()
    local origin = rootPart and rootPart.Position

    if Net.source == "Selection" then
        for i = 1, selSet.n do
            local part = selSet.items[i]
            if stillThere(part) and usable(part) then retain(part, collide, massless) end
        end
    elseif Net.source == "Nearest" and origin then
        local cand, cn = {}, 0
        local limit = Net.range * Net.range
        for i = 1, partSet.n do
            local part = partSet.items[i]
            if usable(part) then
                local p = part.Position
                local dx, dy, dz = p.X - origin.X, p.Y - origin.Y, p.Z - origin.Z
                local d2 = dx * dx + dy * dy + dz * dz
                if d2 <= limit then
                    cn = cn + 1
                    cand[cn] = { part = part, d = d2 }
                end
            end
        end
        table.sort(cand, function(a, b) return a.d < b.d end)
        for i = 1, math_min(cn, Net.count) do retain(cand[i].part, collide, massless) end
    else
        for i = 1, partSet.n do
            local part = partSet.items[i]
            if usable(part) then
                retain(part, collide, massless)
                if Net.n >= Net.count then break end
            end
        end
    end

    Net.status = format("holding %d parts", Net.n)
    return Net.n
end

--------------------------------------------------------------------- modes

-- Steer by velocity toward the orbit point. Proportional, not a constant dash:
-- a fixed-magnitude push overshoots the goal and the ring shakes itself apart.
-- All three modes are the V4 loop: work out a target position for the part,
-- then set Velocity to the UNIT direction times a constant strength. Nothing
-- else. No CFrame, no movers, no ownership gate.
--
-- The gate was the real killer: you claim ownership BY writing velocity, so
-- refusing to write until you already own the part is a deadlock that can
-- never resolve. ReceiveAge is now a readout only, never a condition.
--
-- The angle comes from the part's OWN current position and is nudged by a
-- small increment each frame, and the radius is capped at the part's current
-- distance. That is what makes it smooth: a part orbits where it already is
-- and eases inward, instead of being ordered to an absolute slot on the far
-- side of the circle every frame.
local function driveTo(part, tx, ty, tz, strength)
    local pos = part.Position
    local dx, dy, dz = tx - pos.X, ty - pos.Y, tz - pos.Z
    local len = sqrt(dx * dx + dy * dy + dz * dz)
    if len < 0.001 then return end
    part[VEL_PROP] = Vector3.new(dx / len * strength,
                                 dy / len * strength,
                                 dz / len * strength)
end

local function stepRing(_, centre)
    local step = math.rad(Net.speed)
    local radius, height, strength = Net.radius, Net.height, Net.pull
    local cx, cy, cz = centre.X, centre.Y, centre.Z

    for i = 1, Net.n do
        local part = Net.parts[i]
        if stillThere(part) and not part.Anchored then
            local pos = part.Position
            local ddx, ddz = pos.X - cx, pos.Z - cz
            local distance = sqrt(ddx * ddx + ddz * ddz)
            local newAngle = atan2(ddz, ddx) + step
            local r = math_min(radius, distance)
            local ty = cy + height * abs(sin((pos.Y - cy) / height))
            driveTo(part,
                cx + cos(newAngle) * r,
                ty,
                cz + sin(newAngle) * r,
                strength)
        end
    end
end

local function stepFling(_, centre)
    local strength = Net.flingPower
    local cx, cy, cz = centre.X, centre.Y, centre.Z
    for i = 1, Net.n do
        local part = Net.parts[i]
        if stillThere(part) and not part.Anchored then
            driveTo(part, cx, cy, cz, strength)
        end
    end
end

local function platformScore(part)
    local size = part.Size
    if size.X < 4 or size.Z < 4 then return -1 end
    if size.Y > 12 then return -1 end
    return size.X * size.Z
end

local function stepPlatform(_, centre)
    local part = Net.platformPart
    if not stillThere(part) then
        local best, bestScore = nil, 0
        for i = 1, Net.n do
            local candidate = Net.parts[i]
            if stillThere(candidate) then
                local score = platformScore(candidate)
                if score > bestScore then best, bestScore = candidate, score end
            end
        end
        if not best then
            Net.status = "platform: nothing wide enough to stand on"
            return
        end
        Net.platformPart = best
        part = best
        -- the one departure from V4: a massless, non-colliding part cannot
        -- hold you up, so the platform gets its collision and weight back
        pcall(function()
            part.CanCollide = true
            local home = Net.home[part]
            part.CustomPhysicalProperties = home and home.props or nil
        end)
    end

    driveTo(part, centre.X, centre.Y - Net.platformDrop, centre.Z, Net.pull)
end

-- Readout only. Counts how many of the parts we are pushing the server has
-- stopped updating, i.e. handed to us. Never used as a condition.
local function probeOwnership()
    local sample = math_min(Net.n, 24)
    local owned = 0
    for i = 1, sample do
        local part = Net.parts[i]
        if stillThere(part) and isOwned(part) then owned = owned + 1 end
    end
    Net.probeMoved, Net.probeSample = owned, sample
end

local function stepNet(dt)
    holdOwnership()                    -- every frame, not throttled

    local centre = targetPos()
    if not centre then
        Net.status = "target has no character right now"
        return
    end

    -- re-gather periodically so parts that streamed in after the first pass
    -- are picked up; the old build gathered exactly once and never again
    Net.regather = Net.regather + dt
    if Net.n == 0 or Net.regather >= 3 then
        Net.regather = 0
        if gather() == 0 then
            Net.status = "no usable parts in range"
            return
        end
    end

    local mode = Net.mode
    if mode == "Ring" then
        pcall(stepRing, dt, centre)
    elseif mode == "Fling" then
        pcall(stepFling, dt, centre)
    else
        pcall(stepPlatform, dt, centre)
    end

    probeOwnership()
    Net.status = format("%s | %d held | OWNED %d/%d | radius:%s focus:%s",
        Net.mode, Net.n, Net.probeMoved, Net.probeSample,
        Net.diagRadius and "ok" or "FAIL",
        Net.diagFocus and "ok" or "FAIL")
end

local function stopNet(reason)
    if not Net.running then return end
    Net.running = false
    Net.status = "stopped: " .. reason
end

--=========================================================================
-- misc  --  the universal switches
--
-- Everything here leans only on engine primitives that exist in every place,
-- so none of it needs to know anything about the game it is running in.
--=========================================================================

local Misc = {
    walkspeed = 16, jump = 50, applyMove = false,
    infJump = false, noclip = false, antiVoid = false, freeze = false,
    antiRagdoll = false, autoRespawn = false, autoEquip = false,
    antiFog = false, fullBright = false, antiAfk = false, maxZoom = false,
    lastSafe = nil, safeClock = 0, reapplyClock = 0,
    freezeCF = nil,
    keepPos = false, resetPos = nil, resetting = false, lastPos = nil,
    hiddenGuis = {}, coreWas = true,
    humanoid = nil, charParts = {},
    touchLog = {},                 -- [part] = os.clock() of the last touch
    savedLight = {},
    conns = {},
}

do

-- Names that are killbricks in practically every game. Only a first guess --
-- the real list is learned below, by getting hurt once.
local KILL_WORDS = {
    "kill", "lava", "damage", "spike", "trap", "acid", "death", "die",
    "hurt", "poison", "fire", "hazard", "laser", "saw", "void",
}

local function looksLethal(name)
    name = string_lower(name)
    for i = 1, #KILL_WORDS do
        if string_find(name, KILL_WORDS[i], 1, true) then return true end
    end
    return false
end

local function markKillbrick(part, why)
    if killParts[part] then return end
    killParts[part] = true
    killCount = killCount + 1
    if Misc.killLabel then
        Misc.killLabel:SetText(format("killbricks avoided: %d  (last: %s, %s)",
            killCount, part.Name, why))
    end
end

--------------------------------------------------------------------- god

-- God mode is layered, because no single method works everywhere:
--
--   1. the death state is disabled, so a local death never resolves
--   2. CanTouch is cleared on your own limbs -- a killbrick's Touched never
--      fires server-side if the part that hit it cannot touch
--   3. health is restored on any drop, which is authoritative in the games
--      that trust the client with it and harmless in the ones that do not
--   4. anything that damages you is LEARNED and added to the killbrick list,
--      which auto-collect then refuses to fire touch interests on
--
-- (4) is the one that matters for the collector: the whole point is not
-- teleporting yourself onto a lava brick to grab the coin sitting on it.
function Misc.applyGod(on)
    godOn = on
    local char = LocalPlayer.Character
    if not char then return end

    for _, part in ipairs(char:GetDescendants()) do
        if part:IsA("BasePart") then
            pcall(function() part.CanTouch = not on end)
        end
    end

    local humanoid = Misc.humanoid
    if humanoid then
        pcall(function()
            humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, not on)
            if on then humanoid.BreakJointsOnDeath = false end
        end)
    end
end

local function onDamaged()
    if not godOn or Misc.resetting then return end
    local humanoid = Misc.humanoid
    if not humanoid then return end

    -- blame whatever touched us in the last half second
    local now = os.clock()
    for part, when in pairs(Misc.touchLog) do
        if now - when < 0.5 and part.Parent then
            markKillbrick(part, "damaged us")
        end
        if now - when > 2 then Misc.touchLog[part] = nil end
    end

    pcall(function() humanoid.Health = humanoid.MaxHealth end)
end

--------------------------------------------------------------- character

function Misc.bind(char)
    table_clear(Misc.charParts)
    Misc.touchLog = {}
    Misc.humanoid = char:FindFirstChildOfClass("Humanoid")
        or char:WaitForChild("Humanoid", 5)

    local n = 0
    for _, part in ipairs(char:GetDescendants()) do
        if part:IsA("BasePart") then
            n = n + 1
            Misc.charParts[n] = part
            Library:Connect(part.Touched, function(hit)
                Misc.touchLog[hit] = os.clock()
                if godOn and looksLethal(hit.Name) then
                    markKillbrick(hit, "name")
                end
            end)
        end
    end

    local humanoid = Misc.humanoid
    if humanoid then
        Library:Connect(humanoid.HealthChanged, function(hp)
            if hp < humanoid.MaxHealth then onDamaged() end
        end)
        -- any death, not just our own reset button
        Library:Connect(humanoid.Died, function()
            if Misc.keepPos then Misc.resetPos = Misc.lastPos end
        end)
        if Misc.antiRagdoll then
            pcall(function()
                humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
                humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
            end)
        end
    end

    if godOn then Misc.applyGod(true) end
    Misc.lastSafe = nil

    if Misc.keepPos and Misc.resetPos then
        local want = Misc.resetPos
        Misc.resetPos = nil
        task.spawn(function()
            local root = char:FindFirstChild("HumanoidRootPart")
                or char:WaitForChild("HumanoidRootPart", 10)
            if root then
                for _ = 1, 6 do            -- spawn logic can move you again
                    pcall(function() root.CFrame = want end)
                    RunService.Heartbeat:Wait()
                end
            end
        end)
    end
end

--------------------------------------------------------------- lighting

local FOG_PROPS = { FogEnd = 1e6, FogStart = 0 }
local BRIGHT_PROPS = {
    Brightness = 2, ClockTime = 14, GlobalShadows = false,
    Ambient = Color3.fromRGB(180, 180, 180),
    OutdoorAmbient = Color3.fromRGB(180, 180, 180),
}

local function saveLight(prop)
    if Misc.savedLight[prop] == nil then
        pcall(function() Misc.savedLight[prop] = Lighting[prop] end)
    end
end

local function applyLightSet(set, on)
    for prop, value in pairs(set) do
        if on then
            saveLight(prop)
            pcall(function() Lighting[prop] = value end)
        elseif Misc.savedLight[prop] ~= nil then
            pcall(function() Lighting[prop] = Misc.savedLight[prop] end)
            Misc.savedLight[prop] = nil
        end
    end
end

function Misc.applyAntiFog(on)
    applyLightSet(FOG_PROPS, on)
    for _, inst in ipairs(Lighting:GetDescendants()) do
        if inst:IsA("Atmosphere") then
            pcall(function() inst.Density = on and 0 or 0.3 end)
        elseif inst:IsA("BlurEffect") or inst:IsA("ColorCorrectionEffect") then
            pcall(function() inst.Enabled = not on end)
        end
    end
end

--------------------------------------------------------------- the loop

function Misc.step(dt)
    local char = LocalPlayer.Character
    local humanoid = Misc.humanoid
    local root = rootPart

    -- noclip has to be re-asserted constantly; the engine restores collision
    if Misc.noclip and char then
        local parts = Misc.charParts
        for i = 1, #parts do
            local part = parts[i]
            if part.Parent and part.CanCollide then part.CanCollide = false end
        end
    end

    -- Freeze: pin you in place AND hold that exact spot even if the server
    -- teleports you elsewhere. Anchoring alone does not stop a server CFrame
    -- write, so we capture the spot on freeze and re-assert it every frame.
    if Misc.freeze and root then
        if not Misc.freezeCF then Misc.freezeCF = root.CFrame end
        if not root.Anchored then root.Anchored = true end
        -- if anything (the server) moved us off the frozen spot, go back
        if (root.Position - Misc.freezeCF.Position).Magnitude > 0.05 then
            pcall(function() root.CFrame = Misc.freezeCF end)
        end
        pcall(function() root.AssemblyLinearVelocity = Vector3.new(0, 0, 0) end)
    elseif root and Misc.wasFrozen then
        pcall(function() root.Anchored = false end)
        Misc.wasFrozen = false
        Misc.freezeCF = nil
    end

    -- remember the last spot we were actually standing on
    if Misc.keepPos and root then Misc.lastPos = root.CFrame end

    if Misc.antiVoid and root and humanoid then
        Misc.safeClock = Misc.safeClock + dt
        if Misc.safeClock >= 0.25 then
            Misc.safeClock = 0
            if humanoid.FloorMaterial ~= Enum.Material.Air then
                Misc.lastSafe = root.CFrame
            end
        end
        if root.Position.Y < Misc.voidY and Misc.lastSafe then
            pcall(function()
                root.CFrame = Misc.lastSafe
                root.Velocity = Vector3.new(0, 0, 0)
            end)
        end
    end

    -- Speed / jump, EVERY frame -- not on a 0.4s timer. The timer let a game
    -- that re-writes WalkSpeed win for up to 0.4s at a time, which is what made
    -- it feel laggy and inconsistent. Per-frame with a compare-before-write is
    -- cheap and holds the value properly against a game that fights it.
    if Misc.applyMove and humanoid then
        pcall(function()
            if humanoid.WalkSpeed ~= Misc.walkspeed then
                humanoid.WalkSpeed = Misc.walkspeed
            end
            if humanoid.UseJumpPower then
                if humanoid.JumpPower ~= Misc.jump then
                    humanoid.JumpPower = Misc.jump
                end
            else
                local h = Misc.jump / 10
                if humanoid.JumpHeight ~= h then humanoid.JumpHeight = h end
            end
        end)
    end

    if godOn and not Misc.resetting
       and humanoid and humanoid.Health < humanoid.MaxHealth then
        pcall(function() humanoid.Health = humanoid.MaxHealth end)
    end
end


-- Instant reset. There is no universal way to shorten the RESPAWN -- that
-- delay is Players.RespawnTime and the server owns it -- but the death itself
-- is ours to trigger, because we own our character. So this skips the
-- hold-the-menu-button dance entirely and dies on the spot.
--
-- Health = 0 alone is refused by some games, so joints get broken too; between
-- the two, something lands in practically every place.
function Misc.instantReset()
    local char = LocalPlayer.Character
    if not char then return end

    if Misc.keepPos then Misc.resetPos = (rootPart and rootPart.CFrame) or Misc.lastPos end

    Misc.resetting = true          -- so god mode does not undo the death
    local humanoid = Misc.humanoid

    -- each step in its own pcall: one wrapper means the first method this
    -- client happens not to expose blocks every method after it
    if humanoid then
        pcall(function()
            humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, true)
        end)
        pcall(function() humanoid.Health = 0 end)
        pcall(function()
            humanoid:ChangeState(Enum.HumanoidStateType.Dead)
        end)
    end
    pcall(function() char:BreakJoints() end)
    task.delay(1, function() Misc.resetting = false end)
end

-- Hide the game's UI. Careful about two things: never hide our own window,
-- and only re-enable what was actually enabled to begin with -- blanket
-- re-enabling turns on menus the game had deliberately hidden.
-- Hide the game's UI.
--
-- Walks every PlayerGui container rather than FindFirstChildOfClass -- a real
-- client has one, but nothing guarantees it and grabbing the wrong one hides
-- nothing. Our own window lives under CoreGui/gethui, so restricting the sweep
-- to PlayerGui excludes it structurally instead of by a name check.
--
-- Only what was actually enabled gets re-enabled; blanket re-enabling would
-- switch on menus the game had deliberately hidden.
function Misc.hideGuis(on)
    if on then
        table_clear(Misc.hiddenGuis)
        for _, container in ipairs(LocalPlayer:GetChildren()) do
            if container:IsA("PlayerGui") then
                for _, gui in ipairs(container:GetDescendants()) do
                    if (gui:IsA("ScreenGui") or gui:IsA("BillboardGui")
                        or gui:IsA("SurfaceGui")) and gui.Enabled then
                        Misc.hiddenGuis[gui] = true
                        pcall(function() gui.Enabled = false end)
                    end
                end
            end
        end
        pcall(function()
            local StarterGui = game:GetService("StarterGui")
            Misc.coreWas = StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.All)
            StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false)
        end)
    else
        for gui in pairs(Misc.hiddenGuis) do
            if gui.Parent then pcall(function() gui.Enabled = true end) end
        end
        table_clear(Misc.hiddenGuis)
        pcall(function()
            local StarterGui = game:GetService("StarterGui")
            StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All,
                Misc.coreWas ~= false)
        end)
    end
end

function Misc.applyBright(on)
    applyLightSet(BRIGHT_PROPS, on)
end


end

--=========================================================================
-- drag detectors
--
-- DragDetector is the fourth interaction primitive, next to TouchInterest,
-- ProximityPrompt and ClickDetector -- and it is the interesting one, because
-- Roblox built it for client-authoritative dragging. Writing DragFrame is a
-- sanctioned client move, so it replicates by design. No ownership transfer,
-- no simulation radius, none of the fight the Network tab lost.
--
-- DragFrame is an offset CFrame, and CFrame + Vector3 translates it, so we
-- never need to know the detector's reference frame: nudge the offset by
-- exactly the delta we want each frame and the part converges on the goal.
--=========================================================================

local Drag = {
    running = false,
    mode = "Fling",
    targetName = "Me",
    perFrame = 60,
    power = 1,
    radius = 20,
    shake = 40,
    angle = 0,
    cursor = 1,
    set = nil, parts = nil,
    vim = nil, phase = "pick", frames = 0, clock = 0,
    current = nil, currentPart = nil,
    originX = 0, originY = 0, lastX = nil, lastY = nil,
    moves = 0, offscreen = 0, aimed = 0, missed = 0, starts = 0, inset = nil,
    sweep = 360, holdFrames = 20, heading = -math.pi / 2,
    method = "Simulated mouse drag", strength = 400, physical = false, perFrame = 200, cursor2 = 1,
    wrote = 0, failed = 0, movedCount = 0, lastPos = {},
    oldEnabled = nil, oldDist = nil, oldStyle = nil,
    prepped = false,
    status = "idle",
}

do

Drag.set    = newSet(256)
Drag.parts  = table_create(256)     -- the BasePart each detector drives
Drag.oldEnabled = table_create(256)
Drag.oldDist    = table_create(256)
Drag.oldStyle   = table_create(256)

local BIG = 1e6

local function dragOwner(inst)
    local node = inst.Parent
    for _ = 1, 3 do
        if not node then return nil end
        if node:IsA("BasePart") then return node end
        node = node.Parent
    end
    return nil
end

function Drag.add(inst)
    if Drag.set.index[inst] then return end
    local n = Drag.set.n + 1
    Drag.set.n = n
    Drag.set.items[n] = inst
    Drag.set.index[inst] = n
    Drag.parts[n] = dragOwner(inst)
    Drag.oldEnabled[n] = inst.Enabled
    -- the detector telling us a drag actually began
    pcall(function()
        Library:Connect(inst.DragStart, function()
            Drag.starts = Drag.starts + 1
        end)
    end)
    pcall(function() Drag.oldDist[n] = inst.MaxActivationDistance end)
    pcall(function() Drag.oldStyle[n] = inst.ResponseStyle end)
    if Drag.prepped then Drag.prep(inst) end
end

function Drag.drop(inst)
    local i = Drag.set.index[inst]
    if not i then return end
    local n = Drag.set.n
    local last = Drag.set.items[n]
    Drag.set.items[i] = last
    Drag.set.index[last] = i
    Drag.parts[i] = Drag.parts[n]
    Drag.oldEnabled[i], Drag.oldDist[i], Drag.oldStyle[i] =
        Drag.oldEnabled[n], Drag.oldDist[n], Drag.oldStyle[n]
    Drag.set.items[n] = nil
    Drag.parts[n], Drag.oldEnabled[n], Drag.oldDist[n], Drag.oldStyle[n] =
        nil, nil, nil, nil
    Drag.set.index[inst] = nil
    Drag.set.n = n - 1
end

-- Geometric response writes the CFrame straight through rather than going via
-- forces, which is both stronger and immune to the part's mass.
function Drag.prep(inst)
    pcall(function() inst.Enabled = true end)
    -- RunLocally is the game saying "this drag is cosmetic, do not replicate".
    -- If it is set, nothing else here can matter, so clear it first.
    pcall(function() inst.RunLocally = false end)
    pcall(function() inst.MaxActivationDistance = BIG end)
    pcall(function()
        inst.ResponseStyle = Drag.physical
            and Enum.DragDetectorResponseStyle.Physical
            or Enum.DragDetectorResponseStyle.Geometric
    end)
end

function Drag.setPrepped(on)
    Drag.prepped = on
    for i = 1, Drag.set.n do
        local inst = Drag.set.items[i]
        if inst.Parent then
            if on then
                Drag.prep(inst)
            else
                pcall(function() inst.Enabled = Drag.oldEnabled[i] end)
                pcall(function() inst.MaxActivationDistance = Drag.oldDist[i] end)
                pcall(function() inst.ResponseStyle = Drag.oldStyle[i] end)
            end
        end
    end
end

local function dragTargetPos()
    if Drag.targetName == "Me" then
        return rootPart and rootPart.Position or nil
    end
    local plr = Players:FindFirstChild(Drag.targetName)
    local char = plr and plr.Character
    local root = char and char:FindFirstChild("HumanoidRootPart")
    return root and root.Position or nil
end

-- Writing DragFrame does nothing without a live drag session -- the engine
-- only listens to real input. So we make real input: press the mouse on the
-- part, then throw the cursor around violently while it is held.
--
-- A drag maps the cursor ray onto a plane, so screen distance IS world
-- distance. Slamming the cursor thousands of pixels per frame, several times
-- per frame, is what turns a drag into a fling.
--
-- One cursor means one part at a time, so this cycles detectors rather than
-- driving them all at once, and it does hijack your actual mouse while on.
-- THE bug, found by instrumenting the detector's own events: mouse events
-- take SCREEN coordinates, but WorldToViewportPoint returns viewport
-- coordinates, which exclude the GUI inset. Feeding those straight in aims
-- about 36 pixels above the part and misses it, so no drag ever started.
local function screenOf(pos)
    local cam = workspace.CurrentCamera
    if not cam then return nil end
    local ok, point, onScreen = pcall(function()
        local p, v = cam:WorldToViewportPoint(pos)
        return p, v
    end)
    if not ok or not point then return nil end

    local inset = Drag.inset
    if not inset then
        local okI, got = pcall(function()
            return game:GetService("GuiService"):GetGuiInset()
        end)
        inset = (okI and got) or Vector2.new(0, 0)
        Drag.inset = inset
    end
    return { X = point.X + inset.X, Y = point.Y + inset.Y }, onScreen
end

local function mouseDown(x, y)
    pcall(function()
        Drag.vim:SendMouseButtonEvent(x, y, 0, true, game, 0)
    end)
end

local function mouseUp(x, y)
    pcall(function()
        Drag.vim:SendMouseButtonEvent(x, y, 0, false, game, 0)
    end)
end

local function mouseMove(x, y)
    pcall(function() Drag.vim:SendMouseMoveEvent(x, y, game) end)
    Drag.moves = Drag.moves + 1
end

local function releaseCurrent()
    if Drag.phase == "drag" and Drag.lastX then
        mouseUp(Drag.lastX, Drag.lastY)
    end
    Drag.phase = "pick"
    Drag.frames = 0
    Drag.current, Drag.currentPart = nil, nil
end

-- The batch methods write DragFrame straight onto EVERY detector at once --
-- no cursor, no line of sight, no one-at-a-time. They may be ignored outside
-- a live drag session, which is exactly what the MOVED counter tells you.
-- Simulated input is limited to one on-screen part but is known to land.
-- "All at once" runs both, which is the strongest thing available.
local function stepFrames(dt, restart)
    local n = Drag.set.n
    if n == 0 then return end
    if Drag.cursor2 > n then Drag.cursor2 = 1 end

    local centre = dragTargetPos()
    local strength = Drag.strength
    local budget = math_min(Drag.perFrame, n)
    local base = Drag.clock * 3        -- phase spread only; Drag.speed is gone
    local i = Drag.cursor2

    for k = 1, budget do
        local slot = i
        local inst = Drag.set.items[slot]
        local part = Drag.parts[slot]
        i = i + 1
        if i > n then i = 1 end

        if inst and inst.Parent and part and part.Parent then
            local pos = part.Position
            local dx, dy, dz

            if Drag.mode == "Drag to target" and centre then
                dx, dy, dz = centre.X - pos.X, centre.Y - pos.Y, centre.Z - pos.Z
            elseif Drag.mode == "Spin" then
                local a = base + slot
                dx, dy, dz = cos(a) * strength, 0, sin(a) * strength
            else
                local a = base * 3 + slot * 2.399
                dx = cos(a) * strength
                dy = strength
                dz = sin(a * 1.31) * strength
            end

            if restart then pcall(function() inst:RestartDrag() end) end

            local ok = pcall(function()
                inst.DragFrame = inst.DragFrame + Vector3.new(dx, dy, dz)
            end)
            if ok then
                Drag.wrote = Drag.wrote + 1
                local last = Drag.lastPos[slot]
                if last and (pos.X ~= last.X or pos.Y ~= last.Y
                             or pos.Z ~= last.Z) then
                    Drag.movedCount = Drag.movedCount + 1
                end
                Drag.lastPos[slot] = pos
            else
                Drag.failed = Drag.failed + 1
            end
        end
    end
    Drag.cursor2 = i
end

function Drag.step(dt)
    Drag.clock = Drag.clock + dt

    local method = Drag.method
    local all = (method == "All at once")
    local wantSim = all or (method == "Simulated mouse drag")

    if all or method == "DragFrame write" then
        stepFrames(dt, false)
    end
    if all or method == "RestartDrag + DragFrame" then
        stepFrames(dt, true)
    end

    if not wantSim then
        Drag.status = format("%s / %s | %d detectors | wrote %d fail %d MOVED %d",
            method, Drag.mode, Drag.set.n,
            Drag.wrote, Drag.failed, Drag.movedCount)
        return
    end

    if not Drag.vim then
        local ok, vim = pcall(game.GetService, game, "VirtualInputManager")
        if not ok or not vim then
            Drag.status = "no VirtualInputManager on this executor"
            return
        end
        Drag.vim = vim
    end

    local n = Drag.set.n
    if n == 0 then
        Drag.status = "no drag detectors in this game"
        return
    end

    if Drag.phase == "pick" then
        -- find the next detector whose part is actually on screen
        local tried = 0
        while tried < n do
            if Drag.cursor > n then Drag.cursor = 1 end
            local slot = Drag.cursor
            Drag.cursor = Drag.cursor + 1
            tried = tried + 1

            local inst = Drag.set.items[slot]
            local part = Drag.parts[slot]
            if inst and inst.Parent and part and part.Parent then
                local point, onScreen = screenOf(part.Position)
                if point and onScreen then
                    -- point at it now, confirm we are actually over it next
                    -- frame, and only then press. Pressing blind is what made
                    -- this silently do nothing before.
                    Drag.current, Drag.currentPart = inst, part
                    Drag.originX, Drag.originY = point.X, point.Y
                    Drag.lastX, Drag.lastY = point.X, point.Y
                    Drag.phase = "aim"
                    Drag.frames = 0
                    -- mostly straight up (against gravity, and unmistakable),
                    -- fanned a little so a pile does not all go one way
                    Drag.heading = -math.pi / 2 + ((slot % 5) - 2) * 0.22
                    mouseMove(point.X, point.Y)
                    return
                end
            end
        end
        Drag.offscreen = Drag.offscreen + 1
        Drag.status = format("%d detectors, none on screen -- look at one", n)
        return
    end

    if Drag.phase == "aim" then
        local part = Drag.currentPart
        if not (part and part.Parent) then
            releaseCurrent()
            return
        end
        local hit = Mouse.Target
        if hit == part or (hit and hit:IsDescendantOf(part.Parent)) then
            Drag.aimed = Drag.aimed + 1
            Drag.phase = "drag"
            Drag.frames = 0
            mouseDown(Drag.originX, Drag.originY)
        else
            Drag.missed = Drag.missed + 1
            Drag.phase = "pick"           -- something is in the way; next one
        end
        return
    end

    -- Holding. This is a straight copy of what the probe proved: ONE move per
    -- frame, travelling monotonically in a single direction, staying inside the
    -- viewport, then release.
    --
    -- The previous version oscillated the cursor with cos(a) * 3000, which was
    -- wrong three ways: the oscillation averages out to no net displacement,
    -- coordinates thousands of pixels off-screen are ignored by the engine, and
    -- input is processed once per frame so six moves in one frame collapse to
    -- the last one -- a random far-off point. "Maximum output" broke it.
    local part = Drag.currentPart
    if not (part and part.Parent) then
        releaseCurrent()
        return
    end

    Drag.frames = Drag.frames + 1
    local t = Drag.frames / Drag.holdFrames
    local cx, cy = Drag.originX, Drag.originY
    local tx, ty = cx, cy

    if Drag.mode == "Drag to target" then
        local goal = dragTargetPos()
        local point = goal and screenOf(goal)
        if point then
            tx = cx + (point.X - cx) * t
            ty = cy + (point.Y - cy) * t
        end
    elseif Drag.mode == "Spin" then
        local a = t * TAU * 2
        local r = Drag.sweep * 0.35
        tx = cx + cos(a) * r
        ty = cy + sin(a) * r
    else
        -- Fling: accelerate along one heading so the cursor is moving fastest
        -- at the moment of release, which is what actually throws the part.
        local a = Drag.heading
        local d = Drag.sweep * t * t
        tx = cx + cos(a) * d
        ty = cy + sin(a) * d
    end

    -- off-screen coordinates do nothing, so stay inside the viewport
    local cam = workspace.CurrentCamera
    local vpx, vpy = 1280, 720
    if cam then
        local size = cam.ViewportSize
        vpx, vpy = size.X, size.Y
    end
    if tx < 4 then tx = 4 elseif tx > vpx - 4 then tx = vpx - 4 end
    if ty < 4 then ty = 4 elseif ty > vpy - 4 then ty = vpy - 4 end

    mouseMove(tx, ty)
    Drag.lastX, Drag.lastY = tx, ty

    if Drag.frames >= Drag.holdFrames then
        releaseCurrent()
    end

    Drag.status = format("%s | %d found | STARTED %d | aimed %d miss %d | moves %d",
        Drag.mode, n, Drag.starts, Drag.aimed, Drag.missed, Drag.moves)
end

function Drag.stop()
    releaseCurrent()
end

end

--=========================================================================
-- carry-over  --  the hub follows you between places and servers
--
-- Deliberately NOT autoexec. Nothing is written to disk, so a Roblox crash or
-- a fresh launch starts clean; the hub only survives a teleport, which is the
-- one gap where you would otherwise lose it mid-farm.
--
-- queueonteleport is the only hook that crosses a place change: the client is
-- torn down and rebuilt, so nothing in memory carries over -- but a queued
-- source string runs on the far side. That lets the settings ride along too,
-- serialised into the queued script itself, which means this works even on
-- executors with no file access at all.
--=========================================================================

local Persist = {
    survive = true,
    queued = false,
    status = "idle",
    url = "https://scripts.nitaimaarek.com/raw/3b07cf25",
}

do

local queueTp = queueonteleport or queue_on_teleport
    or (syn and syn.queue_on_teleport)

Persist.canQueue = type(queueTp) == "function"

-- Build the script that will run on the other side: restore the settings we
-- have right now, then load the hub again.
local function carrySource()
    local blob = ""
    pcall(function()
        blob = game:GetService("HttpService"):JSONEncode(Library:GetState())
    end)

    return table.concat({
        "local s = ", string.format("%q", blob), "\n",
        "local env = (getgenv and getgenv()) or _G\n",
        "env.NMHUB_CARRY = s\n",
        "loadstring(game:HttpGet(", string.format("%q", Persist.url), "))()\n",
    })
end

-- Arm exactly once per teleport. Each queueonteleport call appends another
-- script, so arming on a timer would stack up dozens of copies of the hub on
-- the far side.
function Persist.arm(why)
    if not (Persist.survive and Persist.canQueue) then return false end
    if Persist.queued then return true end

    local ok = pcall(queueTp, carrySource())
    if ok then
        Persist.queued = true
        Persist.status = "armed for teleport (" .. (why or "?") .. ")"
        -- if the teleport never happens, let it be armed again later
        task.delay(15, function() Persist.queued = false end)
    else
        Persist.status = "queueonteleport refused"
    end
    return ok
end

-- On the far side: pick up whatever the previous instance queued for us.
function Persist.restore()
    local env = (getgenv and getgenv()) or _G
    local blob = env.NMHUB_CARRY
    env.NMHUB_CARRY = nil
    if type(blob) ~= "string" or blob == "" then
        Persist.status = Persist.canQueue and "fresh session"
            or "no queueonteleport on this executor"
        return false
    end

    local decoded
    local ok = pcall(function()
        decoded = game:GetService("HttpService"):JSONDecode(blob)
    end)
    if not ok or type(decoded) ~= "table" then
        Persist.status = "carried settings were unreadable"
        return false
    end

    pcall(function() Library:LoadState(decoded) end)
    Persist.status = "settings carried over from the last server"
    return true
end

function Persist.capabilities()
    return "queueonteleport: " .. (Persist.canQueue and "yes"
        or "NO -- the hub will not follow you")
end

end

--=========================================================================
-- selection
--=========================================================================

local function escapeMagic(s)
    return (s:gsub("([%(%)%.%%%+%-%*%?%[%]%^%$])", "%%%1"))
end

local function baseNameOf(name)
    local base = string_match(name, "^(.-)%d*$")
    return (base and base ~= "") and base or name
end

local function selectGroup(baseName)
    local pattern = "^" .. escapeMagic(baseName) .. "%d*$"
    activeNames[baseName] = pattern
    local items, n = partSet.items, partSet.n
    for i = 1, n do
        local part = items[i]
        if string_match(part.Name, pattern) then
            setAdd(selSet, part)
            addBox(part)
        end
    end
end

local function deselectGroup(baseName)
    local pattern = activeNames[baseName]
    if not pattern then return end
    activeNames[baseName] = nil
    for i = selSet.n, 1, -1 do          -- backwards: setRemove swaps the tail in
        local part = selSet.items[i]
        if string_match(part.Name, pattern) then
            dropBox(part)
            setRemove(selSet, part)
        end
    end
end

local function clearSelection()
    for part in pairs(boxes) do
        boxes[part]:Destroy()
    end
    table_clear(boxes)
    boxCount = 0
    setClear(selSet)
    table_clear(activeNames)
end

--=========================================================================
-- character cache
--=========================================================================

local function bindCharacter(char)
    rootPart = nil
    task.spawn(function()
        local root = char:FindFirstChild("HumanoidRootPart")
            or char:WaitForChild("HumanoidRootPart", 10)
        if root then rootPart = root end
    end)
end

if LocalPlayer.Character then
    bindCharacter(LocalPlayer.Character)
    pcall(Misc.bind, LocalPlayer.Character)
end

--=========================================================================
-- UI
--=========================================================================

local Window = Library:CreateWindow({
    Title = "optimizer",
    Subtitle = "nm build",
    Size = UDim2.fromOffset(560, 400),
    ToggleKey = "Ctrl+H",
    Preset = "onyx",
    PreserveState = true,
    Layout = "topbar",
    Columns = 2,
    Resizable = true,
})

local watermark = Library:Watermark({ Separator = "  |  " })
watermark:AddSegment("title", "optimizer", 1)
watermark:AddSegment("fps", Library.Counters.fps, 2)
watermark:AddSegment("ping", Library.Counters.ping, 3)
watermark:AddSegment("parts", function()
    return partSet.n .. " parts / " .. pickSet.n .. " pickups"
end, 4)

--------------------------------------------------------------- performance

do


local Perf   = Window:Tab("Performance", "speed")
local Render = Perf:Section({ Name = "Render", Side = "Left" })

Render:Toggle({
    Flag = "antilag",
    Text = "Anti-lag",
    Default = false,
    Callback = setAntiLag,
})

Render:Slider({
    Flag = "applybudget",
    Text = "Apply budget",
    Min = 250, Max = 8000, Default = 1500, Decimals = 0,
    Suffix = " parts/frame",
    Callback = function(v) applyBudget = v end,
})

Render:Divider()

Render:Label({
    Text = "Everything anti-lag changes is recorded and put back on toggle-off, including Lighting children.",
    Muted = true,
})

local Stats = Perf:Section({ Name = "Live", Side = "Right" })

partsLabel  = Stats:Label({ Text = "parts: 0", Mono = true })
pickLabel   = Stats:Label({ Text = "pickups: 0", Mono = true })
selLabel    = Stats:Label({ Text = "selected: 0", Mono = true })
promptLabel       = Stats:Label({ Text = "prompts: 0", Mono = true })
clickLabel        = Stats:Label({ Text = "detectors: 0", Mono = true })
statusLabel       = Stats:Label({ Text = "idle", Mono = true, Muted = true })
end

------------------------------------------------------------------- collect

do


local Collect = Window:Tab("Collect", "coins")
local Auto    = Collect:Section({ Name = "Auto-collect", Side = "Left" })

if not fireTouch then
    Auto:Label({ Text = "firetouchinterest missing on this executor.", Muted = true })
end

Auto:Toggle({
    Flag = "autocollect",
    Text = "Auto-collect",
    Default = false,
    Callback = function(on)
        if on and not fireTouch then
            Library:Notify({
                Title = "optimizer",
                Text = "this executor has no firetouchinterest",
                Type = "error",
            })
            Library.Options.autocollect:SetValue(false, true)
            return
        end
        collectOn = on
    end,
})

Auto:Slider({
    Flag = "perframe",
    Text = "Throughput",
    Min = 10, Max = 1000, Default = 120, Decimals = 0,
    Suffix = " /frame",
    Callback = function(v) perFrame = v end,
})

Auto:Dropdown({
    Flag = "filter",
    Text = "Filter",
    Values = { "Everything", "Selected only", "All but selected" },
    Default = "Everything",
    Callback = function(value)
        filterMode = (value == "Selected only" and 2)
            or (value == "All but selected" and 3)
            or 1
    end,
})

Auto:Toggle({
    Flag = "teleport",
    Text = "Teleport parts to me",
    Default = false,
    Callback = function(on) teleportOn = on end,
})

Auto:Label({
    Text = "Leave teleport off unless the game distance-checks the touch: it costs two physics writes per pickup and is the slowest thing here.",
    Muted = true,
})

Auto:Divider()

Auto:Button({
    Text = "Collect once (full sweep)",
    Callback = function()
        if not (fireTouch and rootPart) then return end
        local items, n = snapshot(pickSet)
        local root = rootPart
        local rootCF = root.CFrame
        startJob(items, n, perFrame, function(part)
            if part.Parent then
                if teleportOn then
                    local home = part.CFrame
                    part.CFrame = rootCF
                    pcall(fireTouch, root, part, 0)
                    pcall(fireTouch, root, part, 1)
                    part.CFrame = home
                else
                    pcall(fireTouch, root, part, 0)
                    pcall(fireTouch, root, part, 1)
                end
            end
        end, function()
            statusLabel:SetText("swept " .. n .. " pickups")
        end, "sweep")
    end,
})

local Sel = Collect:Section({ Name = "Selection", Side = "Right" })

Sel:Toggle({
    Flag = "selectmode",
    Text = "Select mode",
    Default = false,
    Callback = function(on) selectModeOn = on end,
})

Sel:Label({
    Text = "Click a part to select every part sharing its base name (Coin, Coin1, Coin27...). Click again to drop the group.",
    Muted = true,
})

Sel:Slider({
    Flag = "boxcap",
    Text = "Outline cap",
    Min = 0, Max = 600, Default = 150, Decimals = 0,
    Suffix = " boxes",
    Callback = function(v) boxCap = v end,
})

Sel:Colorpicker({
    Flag = "boxcolor",
    Text = "Outline colour",
    Default = boxColor,
    Callback = function(color)
        boxColor = color
        for _, box in pairs(boxes) do
            box.Color3 = color
            box.SurfaceColor3 = color
        end
    end,
})

Sel:Button({ Text = "Clear selection", Callback = clearSelection })
end

------------------------------------------------------------------ interact

do


local Interact = Window:Tab("Interact", "target")
local Prox     = Interact:Section({ Name = "Proximity prompts", Side = "Left" })

if not fireProx then
    Prox:Label({ Text = "fireproximityprompt missing on this executor.", Muted = true })
end

Prox:Toggle({
    Flag = "autoprompt",
    Text = "Auto-fire prompts",
    Default = false,
    Callback = function(on)
        if on and not fireProx then
            Library:Notify({ Title = "optimizer",
                Text = "this executor has no fireproximityprompt", Type = "error" })
            Library.Options.autoprompt:SetValue(false, true)
            return
        end
        promptOn = on
    end,
})

Prox:Toggle({
    Flag = "promptbypass",
    Text = "Bypass hold + range",
    Default = true,
    Callback = setPromptBypass,
})

Prox:Slider({
    Flag = "promptrate",
    Text = "Throughput",
    Min = 1, Max = 500, Default = 40, Decimals = 0,
    Suffix = " /frame",
    Callback = function(v) promptPerFrame = v end,
})

Prox:Slider({
    Flag = "promptrange",
    Text = "Range",
    Min = 0, Max = 2000, Default = 0, Decimals = 0,
    Suffix = " studs (0 = any)",
    Callback = function(v)
        promptRangeSq = (v > 0) and (v * v) or nil   -- squared: no sqrt in the loop
    end,
})

Prox:Dropdown({
    Flag = "promptfilter",
    Text = "Filter",
    Values = { "Everything", "Selected only", "All but selected" },
    Default = "Everything",
    Callback = function(value)
        promptMode = (value == "Selected only" and 2)
            or (value == "All but selected" and 3)
            or 1
    end,
})

Prox:Input({
    Flag = "promptname",
    Text = "Name contains",
    Placeholder = "collect, harvest, ...",
    Finished = true,
    Callback = function(text)
        text = (text or ""):lower():gsub("^%s+", ""):gsub("%s+$", "")
        promptNeedle = (text ~= "") and text or nil
    end,
})

Prox:Label({
    Text = "Matched against ActionText, ObjectText and the parent name, all lowercased once at registration.",
    Muted = true,
})

local Clicks = Interact:Section({ Name = "Click detectors", Side = "Right" })

if not fireClick then
    Clicks:Label({ Text = "fireclickdetector missing on this executor.", Muted = true })
end

Clicks:Toggle({
    Flag = "autoclick",
    Text = "Auto-click detectors",
    Default = false,
    Callback = function(on)
        if on and not fireClick then
            Library:Notify({ Title = "optimizer",
                Text = "this executor has no fireclickdetector", Type = "error" })
            Library.Options.autoclick:SetValue(false, true)
            return
        end
        clickOn = on
    end,
})

Clicks:Toggle({
    Flag = "clickbypass",
    Text = "Bypass range",
    Default = true,
    Callback = setClickBypass,
})

Clicks:Slider({
    Flag = "clickrate",
    Text = "Throughput",
    Min = 1, Max = 500, Default = 40, Decimals = 0,
    Suffix = " /frame",
    Callback = function(v) clickPerFrame = v end,
})

Clicks:Slider({
    Flag = "clickrange",
    Text = "Range",
    Min = 0, Max = 2000, Default = 0, Decimals = 0,
    Suffix = " studs (0 = any)",
    Callback = function(v)
        clickRangeSq = (v > 0) and (v * v) or nil
    end,
})

Clicks:Dropdown({
    Flag = "clickfilter",
    Text = "Filter",
    Values = { "Everything", "Selected only", "All but selected" },
    Default = "Everything",
    Callback = function(value)
        clickMode = (value == "Selected only" and 2)
            or (value == "All but selected" and 3)
            or 1
    end,
})

Clicks:Dropdown({
    Flag = "clickbutton",
    Text = "Button",
    Values = { "Left", "Right" },
    Default = "Left",
    Callback = function(value) clickRight = (value == "Right") end,
})

Clicks:Divider()

local Drags = Interact:Section({ Name = "Drag detectors", Side = "Left" })

Drags:Toggle({
    Flag = "dragrun",
    Text = "Spam drag",
    Default = false,
    Callback = function(on)
        Drag.running = on
        if on then
            Drag.setPrepped(true)
        else
            Drag.stop()            -- never leave the mouse button held down
        end
    end,
})

Drags:Dropdown({
    Flag = "dragmethod",
    Text = "Method",
    Values = { "Simulated mouse drag", "All at once", "DragFrame write",
               "RestartDrag + DragFrame" },
    Default = "Simulated mouse drag",
    Callback = function(v)
        Drag.method = v
        Drag.stop()
        Drag.wrote, Drag.failed, Drag.movedCount, Drag.moves = 0, 0, 0, 0
        Drag.starts, Drag.aimed, Drag.missed = 0, 0, 0
    end,
})

Drags:Slider({
    Flag = "dragstrength",
    Text = "DragFrame strength",
    Min = 10, Max = 5000, Default = 400, Decimals = 0,
    Suffix = " studs",
    Callback = function(v) Drag.strength = v end,
})

Drags:Slider({
    Flag = "dragbatch",
    Text = "Detectors per frame",
    Min = 1, Max = 1000, Default = 200, Decimals = 0,
    Callback = function(v) Drag.perFrame = v end,
})

Drags:Dropdown({
    Flag = "dragmode",
    Text = "Mode",
    Values = { "Fling", "Spin", "Drag to target" },
    Default = "Fling",
    Callback = function(v)
        Drag.mode = v
        Drag.stop()
    end,
})

Drags:Dropdown({
    Flag = "dragtarget",
    Text = "Target player",
    Values = { "Me" },
    Default = "Me",
    Callback = function(v) Drag.targetName = v end,
})

Drags:Button({
    Text = "Refresh drag targets",
    Callback = function()
        local list = { "Me" }
        for _, plr in ipairs(Players:GetPlayers()) do
            if plr ~= LocalPlayer then list[#list + 1] = plr.Name end
        end
        Library.Options.dragtarget:SetValues(list, true)
    end,
})

Drags:Slider({
    Flag = "dragsweep",
    Text = "Sweep distance",
    Min = 60, Max = 1400, Default = 360, Decimals = 0,
    Suffix = " px",
    Callback = function(v) Drag.sweep = v end,
})

Drags:Toggle({
    Flag = "dragphysical",
    Text = "Physical response (momentum)",
    Default = false,
    Callback = function(on)
        Drag.physical = on
        Drag.setPrepped(Drag.prepped)
    end,
})

Drags:Slider({
    Flag = "draghold",
    Text = "Hold per part",
    Min = 2, Max = 240, Default = 20, Decimals = 0,
    Suffix = " frames",
    Callback = function(v) Drag.holdFrames = v end,
})

Drags:Toggle({
    Flag = "dragprep",
    Text = "Force detectors on (range + geometric)",
    Default = true,
    Callback = function(on) Drag.setPrepped(on) end,
})

Drag.statusLabel = Drags:Label({ Text = "idle", Mono = true, Muted = true })

Drags:Label({
    Text = "All at once is the strongest setting: it writes DragFrame on EVERY detector each frame -- no cursor, no line of sight, all parts -- and simultaneously runs a real simulated drag on whichever one is on screen. The batch writes may be ignored by the engine outside a live drag session; MOVED in the status is what tells you whether they did anything.",
    Muted = true,
})

Drags:Label({
    Text = "STARTED in the status is the real number -- it counts DragStart events the detector itself fired, so it cannot be faked by a part drifting. aimed/miss shows whether the cursor is landing on the part; misses mean something is in front of it or it moved.",
    Muted = true,
})

Drags:Label({
    Text = "Writing DragFrame does nothing on its own -- the engine only listens to real input -- so this presses the mouse on the part and then throws the cursor around while it is held. A drag maps the cursor ray onto a plane, so screen distance IS world distance: thousands of pixels per throw, several throws per frame, is what turns a drag into a fling.",
    Muted = true,
})

Drags:Label({
    Text = "One cursor means one part at a time, so it cycles detectors and only grabs parts that are ON SCREEN -- point at what you want thrown. It also drives your real mouse while running, so expect the cursor to fight you.",
    Muted = true,
})

Drags:Label({
    Text = "Force-on clears RunLocally (the game marking a drag client-only), raises MaxActivationDistance, and switches ResponseStyle to Geometric so a heavy part throws as fast as a light one. Originals restored on toggle-off.",
    Muted = true,
})

Clicks:Label({
    Text = "Both loops run off the same registry as auto-collect, so the Selected only / All but selected filters use the parts you picked in the Collect tab.",
    Muted = true,
})
end

------------------------------------------------------------------- remotes

do


local Rem  = Window:Tab("Remotes", "link")
local Find = Rem:Section({ Name = "Find", Side = "Left" })

FuzzUI.found = Find:Label({ Text = "not scanned yet", Mono = true })

local function refreshRemoteList()
    local needle = (Library.Options.remotesearch
        and Library.Options.remotesearch.Value or ""):lower()
    local list, shown = {}, 0
    local counts = {}
    for i = 1, Remotes.set.n do
        local path = Remotes.path[i]
        local cls = Remotes.cls[i]
        counts[cls] = (counts[cls] or 0) + 1
        if needle == "" or path:lower():find(needle, 1, true) then
            if shown < 250 then
                shown = shown + 1
                list[shown] = path
            end
        end
    end
    Remotes.truncated = 0
    if Library.Options.remotelist then
        -- fresh list, nothing selected: never mass-fire by accident
        Library.Options.remotelist:SetValues(list, false)
    end

    local parts = {}
    for cls, n in pairs(counts) do
        parts[#parts + 1] = n .. " " .. cls
    end
    table.sort(parts)
    FuzzUI.found:SetText(format("%d found (%d blocked, %d excluded): %s%s",
        Remotes.set.n, Remotes.blocked, Remotes.excluded,
        #parts > 0 and table.concat(parts, ", ") or "none",
        shown < Remotes.set.n and format("  (listing %d)", shown) or ""))
end

Find:Button({
    Text = "Scan for remotes",
    Callback = function()
        scanRemotes(Library.Options.bindables.Value, function()
            refreshRemoteList()
            armHitWatch()
            logLine("-- scan: " .. Remotes.set.n .. " remotes")
        end)
    end,
})

Find:Toggle({
    Flag = "bindables",
    Text = "Include bindables",
    Default = false,
})

Find:Input({
    Flag = "remotesearch",
    Text = "Search",
    Placeholder = "part of the name or path",
    Callback = refreshRemoteList,
})

Find:Dropdown({
    Flag = "remotelist",
    Text = "Remotes",
    Values = {},
    Multi = true,
})

Find:Input({
    Flag = "remoteexclude",
    Text = "Exclude (comma separated)",
    Placeholder = "chat, damage, report",
    Finished = true,
    Callback = function(text)
        table_clear(Remotes.excludes)
        for word in tostring(text or ""):gmatch("[^,]+") do
            word = word:lower():gsub("^%s+", ""):gsub("%s+$", "")
            if #word > 0 then
                Remotes.excludes[#Remotes.excludes + 1] = word
            end
        end
        scanRemotes(Library.Options.bindables.Value, function()
            refreshRemoteList()
            logLine(format("-- rescan: %d kept, %d excluded, %d blocked",
                Remotes.set.n, Remotes.excluded, Remotes.blocked))
        end)
    end,
})

Find:Button({
    Text = "Select all listed",
    Callback = function()
        local all = {}
        for _, path in ipairs(Library.Options.remotelist.Values) do
            all[#all + 1] = path
        end
        Library.Options.remotelist:SetValue(all)
    end,
})

Find:Button({
    Text = "Deselect all",
    Callback = function()
        Library.Options.remotelist:SetValue({})
    end,
})

Find:Label({
    Text = "Admin and anticheat client remotes are dropped before they reach this list -- HD Admin, Adonis, Kohl's and anything named like an exploit reporter. Firing those is how you get logged and banned, and they are never what you are looking for.",
    Muted = true,
})

Find:Label({
    Text = "Every remote class the client can reach: RemoteEvent, RemoteFunction, UnreliableRemoteEvent, and optionally BindableEvent/BindableFunction (those are client-local, useful for reading a game's own plumbing).",
    Muted = true,
})

local Bombard = Rem:Section({ Name = "Payloads", Side = "Right" })

FuzzUI.count = Bombard:Label({ Text = "payloads: 0", Mono = true })
FuzzUI.vocab = Bombard:Label({ Text = "vocabulary: 0 words", Mono = true, Muted = true })

local function catToggle(flag, text, key, default)
    Bombard:Toggle({
        Flag = flag, Text = text, Default = default,
        Callback = function(on)
            Fuzz.cats[key] = on
            buildPayloads()
        end,
    })
end

catToggle("catnums", "Numbers 1-20 + edges", "nums", false)
catToggle("catstrings", "Strings", "strings", false)
catToggle("catbools", "Booleans", "bools", false)
catToggle("catinsts", "Instances (player, char, workspace)", "insts", false)
catToggle("cattables", "Tables", "tables", false)
catToggle("catvectors", "Vector3 / CFrame", "vectors", false)
catToggle("catvocab", "Vocabulary (the game's own words)", "vocab", false)
catToggle("catplayers", "Other players (instance / name / id)", "players", false)
catToggle("catpairs", "Pairs (2 args)", "pairs2", false)
catToggle("cattriples", "Triples (3 args)", "triples", false)

Bombard:Slider({
    Flag = "vocabmax",
    Text = "Vocabulary cap",
    Min = 5, Max = 200, Default = 40, Decimals = 0,
    Suffix = " words",
    Callback = function(v)
        Fuzz.vocabMax = v
        buildPayloads()
    end,
})

Bombard:Slider({
    Flag = "playermax",
    Text = "Players to target",
    Min = 1, Max = 30, Default = 6, Decimals = 0,
    Callback = function(v)
        Fuzz.playerMax = v
        buildPayloads()
    end,
})

Bombard:Label({
    Text = "Vocabulary harvests the game's own nouns -- tool names, prompt text, ReplicatedStorage folders, shop button labels -- and fires those instead of \"hi\". Players fires every other player in the server three ways, because a remote taking a target might want the instance, the name or the UserId and there is no telling which.",
    Muted = true,
})

Bombard:Slider({
    Flag = "fuzzinterval",
    Text = "Interval",
    Min = 10, Max = 2000, Default = 120, Decimals = 0,
    Suffix = " ms",
    Callback = function(v) Fuzz.interval = v / 1000 end,
})

Bombard:Toggle({
    Flag = "fuzzloop",
    Text = "Loop the run",
    Default = false,
    Callback = function(on) Fuzz.loop = on end,
})

Bombard:Toggle({
    Flag = "fuzzshuffle",
    Text = "Shuffle order",
    Default = false,
    Callback = function(on) Fuzz.shuffle = on end,
})

Bombard:Toggle({
    Flag = "fuzzskip",
    Text = "Skip remotes that only error",
    Default = true,
    Callback = function(on) Fuzz.skipErrors = on end,
})

Bombard:Slider({
    Flag = "fuzzjitter",
    Text = "Interval jitter",
    Min = 0, Max = 90, Default = 0, Decimals = 0,
    Suffix = " %",
    Callback = function(v) Fuzz.jitter = v / 100 end,
})

Bombard:Toggle({
    Flag = "fuzzdry",
    Text = "Dry run (log only, fire nothing)",
    Default = false,
    Callback = function(on) Fuzz.dry = on end,
})

Bombard:Toggle({
    Flag = "fuzzrun",
    Text = "Run",
    Default = false,
    Callback = function(on)
        if not on then
            stopFuzz("toggled off")
            return
        end
        local chosen = {}
        local n = 0
        local sel = Library.Options.remotelist.Value
        if type(sel) == "table" then
            for path in pairs(sel) do
                n = n + 1
                chosen[n] = path
            end
        end
        table.sort(chosen)
        armHitWatch()
        if not startFuzz(chosen, n) then
            Library.Options.fuzzrun:SetValue(false, true)
        end
    end,
})

Bombard:Button({
    Text = "Run against ALL found",
    Callback = function()
        local all = {}
        for i = 1, Remotes.set.n do all[i] = Remotes.path[i] end
        armHitWatch()
        if startFuzz(all, Remotes.set.n) then
            Library.Options.fuzzrun:SetValue(true, true)
        end
    end,
})

FuzzUI.status = Bombard:Label({ Text = "idle", Mono = true, Muted = true })
FuzzUI.hit    = Bombard:Label({ Text = "hits: 0", Mono = true })

Bombard:Label({
    Text = "Blind firing is the loudest thing in this script -- a server that logs remote traffic will see it. Dry-run first, keep the interval wide enough that one fire is attributable, and expect some payloads to break your session's game state.",
    Muted = true,
})

local LogSec = Rem:Section({ Name = "Log", Side = "Left" })

FuzzUI.lines = {}
for i = 1, 12 do
    FuzzUI.lines[i] = LogSec:Label({ Text = "", Mono = true, Muted = i < 10 })
end

LogSec:Divider()

LogSec:Button({
    Text = "Copy full log",
    Callback = function()
        copyOut(table.concat(Fuzz.log, "\n", 1, Fuzz.logN), "log")
    end,
})

LogSec:Button({
    Text = "Copy hits + candidates",
    Callback = function()
        if Fuzz.hitN == 0 then
            Library:Notify({ Title = "optimizer", Text = "no hits recorded", Type = "info" })
            return
        end
        copyOut(table.concat(Fuzz.hits, "\n", 1, Fuzz.hitN), "hits")
    end,
})

LogSec:Button({
    Text = "Clear log",
    Callback = function()
        table_clear(Fuzz.log)
        Fuzz.logN = 0
        table_clear(Fuzz.hits)
        Fuzz.hitN = 0
        for _, label in ipairs(FuzzUI.lines) do label:SetText("") end
        FuzzUI.hit:SetText("hits: 0")
    end,
})

buildPayloads()
end

------------------------------------------------------------------- network

do

local NetTab = Window:Tab("Network", "globe")
local Ctl    = NetTab:Section({ Name = "Control", Side = "Left" })

Ctl:Dropdown({
    Flag = "netmode",
    Text = "Mode",
    Values = { "Ring", "Fling", "Platform" },
    Default = "Ring",
    Callback = function(value)
        Net.mode = value
        Net.platformPart = nil
        restoreAll()                   -- collision differs per mode; re-take
    end,
})

Ctl:Dropdown({
    Flag = "nettarget",
    Text = "Target player",
    Values = { "Me" },
    Default = "Me",
    Callback = function(value) Net.targetName = value end,
})

local function refreshTargets()
    local list = { "Me" }
    for _, plr in ipairs(Players:GetPlayers()) do
        if plr ~= LocalPlayer then list[#list + 1] = plr.Name end
    end
    if Library.Options.nettarget then
        Library.Options.nettarget:SetValues(list, true)
    end
end

Ctl:Button({ Text = "Refresh players", Callback = refreshTargets })

Ctl:Toggle({
    Flag = "netrun",
    Text = "Run",
    Default = false,
    Callback = function(on)
        if not on then
            stopNet("toggled off")
            restoreAll()
            return
        end
        if not sethiddenproperty then
            Library:Notify({ Title = "network",
                Text = "this executor has no sethiddenproperty -- ownership will not hold",
                Type = "warn" })
        end
        Net.running = true
        Net.status = "running: " .. Net.mode
    end,
})

Ctl:Toggle({
    Flag = "nethold",
    Text = "Keep ownership alive",
    Default = true,
    Callback = function(on) Net.hold = on end,
})

Ctl:Slider({
    Flag = "netsizecap",
    Text = "Ignore parts bigger than",
    Min = 0, Max = 300, Default = 0, Decimals = 0,
    Suffix = " studs (0 = no cap)",
    Callback = function(v)
        Net.sizeCap = v
        restoreAll()
    end,
})

Ctl:Divider()

Ctl:Dropdown({
    Flag = "netsource",
    Text = "Parts",
    Values = { "All unanchored", "Nearest", "Selection" },
    Default = "All unanchored",
    Callback = function(value)
        Net.source = value
        restoreAll()
    end,
})

Ctl:Slider({
    Flag = "netcount",
    Text = "Part cap",
    Min = 10, Max = 5000, Default = 1000, Decimals = 0,
    Callback = function(v)
        Net.count = v
        restoreAll()
    end,
})

Ctl:Slider({
    Flag = "netrange",
    Text = "Nearest range",
    Min = 20, Max = 2000, Default = 250, Decimals = 0,
    Suffix = " studs",
    Callback = function(v)
        Net.range = v
        restoreAll()
    end,
})

Net.statusLabel = Ctl:Label({ Text = "idle", Mono = true, Muted = true })

Ctl:Label({ Text = ownershipCapabilities(), Mono = true, Muted = true })

Ctl:Label({
    Text = "The line above is what YOUR executor provides. A 'NO' on sethiddenproperty or SimulationRadius write means the ownership calls are no-ops on this client and no amount of tuning in this tab will change that -- that is an executor limitation, not a script one.",
    Muted = true,
})

Ctl:Label({
    Text = "OWNED n/m is measured from BasePart.ReceiveAge and is a readout only -- it never gates the writes. It cannot: you claim ownership BY writing velocity, so refusing to write until you already own a part is a deadlock. Watch it climb after you enable a mode; that is ownership transferring.",
    Muted = true,
})

Ctl:Label({
    Text = "Roblox grants ownership of unanchored parts automatically, by proximity to your character, which is why Nearest is the default source. The simulation-radius trick that older ring scripts rely on was removed from Player years ago; the calls are still made for old or private builds, but on a current client 'radius:ok' does not mean you got anything.",
    Muted = true,
})

Ctl:Label({
    Text = "A game that calls SetNetworkOwner(nil) on its parts keeps them server-side permanently. In that game these modes cannot work at all, from any executor.",
    Muted = true,
})

local Tune = NetTab:Section({ Name = "Tuning", Side = "Right" })

Tune:Slider({
    Flag = "ringradius",
    Text = "Ring radius",
    Min = 1, Max = 1000, Default = 50, Decimals = 0,
    Suffix = " studs",
    Callback = function(v) Net.radius = v end,
})

Tune:Slider({
    Flag = "ringheight",
    Text = "Ring height",
    Min = 1, Max = 400, Default = 100, Decimals = 0,
    Callback = function(v) Net.height = v end,
})

Tune:Slider({
    Flag = "ringspeed",
    Text = "Ring speed",
    Min = 0, Max = 30, Default = 1, Decimals = 1,
    Suffix = " deg/frame",
    Callback = function(v) Net.speed = v end,
})

Tune:Slider({
    Flag = "ringpull",
    Text = "Attraction strength",
    Min = 50, Max = 10000, Default = 1000, Decimals = 0,
    Callback = function(v) Net.pull = v end,
})

Tune:Divider()

Tune:Slider({
    Flag = "flingpower",
    Text = "Fling strength",
    Min = 500, Max = 100000, Default = 9000, Decimals = 0,
    Callback = function(v) Net.flingPower = v end,
})

Tune:Divider()

Tune:Slider({
    Flag = "platformdrop",
    Text = "Platform drop",
    Min = 1, Max = 15, Default = 4, Decimals = 1,
    Suffix = " studs",
    Callback = function(v) Net.platformDrop = v end,
})

Tune:Label({
    Text = "Every mode is the same loop: work out a target position, then set Velocity to the unit direction times a strength. Ring takes each part's own current angle and nudges it, capping the radius at the part's current distance, so parts orbit where they already are instead of being flung to a fixed slot.",
    Muted = true,
})

Library:Connect(Players.PlayerAdded, function()
    if Fuzz.cats.players then buildPayloads() end
end)
Library:Connect(Players.PlayerRemoving, function()
    if Fuzz.cats.players then buildPayloads() end
end)

Library:Connect(Players.PlayerAdded, refreshTargets)
Library:Connect(Players.PlayerRemoving, refreshTargets)
refreshTargets()

end

--------------------------------------------------------------------- misc

do

local MiscTab = Window:Tab("Misc", "sliders")
local Move    = MiscTab:Section({ Name = "Movement", Side = "Left" })

Move:Toggle({
    Flag = "movemod",
    Text = "Apply speed / jump",
    Default = false,
    Callback = function(on)
        Misc.applyMove = on
        if not on and Misc.humanoid then
            pcall(function()
                Misc.humanoid.WalkSpeed = 16
                if Misc.humanoid.UseJumpPower then
                    Misc.humanoid.JumpPower = 50
                else
                    Misc.humanoid.JumpHeight = 7.2
                end
            end)
        end
    end,
})

Move:Slider({
    Flag = "walkspeed",
    Text = "WalkSpeed",
    Min = 1, Max = 500, Default = 16, Decimals = 0,
    Callback = function(v) Misc.walkspeed = v end,
})

Move:Slider({
    Flag = "jumppower",
    Text = "Jump",
    Min = 1, Max = 500, Default = 50, Decimals = 0,
    Callback = function(v) Misc.jump = v end,
})

Move:Toggle({
    Flag = "infjump",
    Text = "Infinite jump",
    Default = false,
    Callback = function(on) Misc.infJump = on end,
})

Move:Toggle({
    Flag = "noclip",
    Text = "Noclip",
    Default = false,
    Callback = function(on)
        Misc.noclip = on
        if not on then
            for _, part in ipairs(Misc.charParts) do
                pcall(function() part.CanCollide = true end)
            end
        end
    end,
})

Move:Toggle({
    Flag = "antivoid",
    Text = "Anti-void",
    Default = false,
    Callback = function(on) Misc.antiVoid = on end,
})

Move:Toggle({
    Flag = "freeze",
    Text = "Freeze in place",
    Default = false,
    Callback = function(on)
        Misc.freeze = on
        if on then
            Misc.wasFrozen = true
            Misc.freezeCF = rootPart and rootPart.CFrame or nil
        elseif rootPart then
            pcall(function() rootPart.Anchored = false end)
            Misc.freezeCF = nil
        end
    end,
})

Move:Label({
    Text = "Freeze pins you where you are and HOLDS that exact spot -- if the server teleports you (a round start, a shove), it puts you straight back. Anti-void remembers the last ground you stood on and restores you if you fall past the void. Speed and jump apply every frame now, so a game that fights WalkSpeed cannot win.",
    Muted = true,
})

--------------------------------------------------------------- survival

local Live = MiscTab:Section({ Name = "Survival", Side = "Right" })

Live:Toggle({
    Flag = "godmode",
    Text = "God mode",
    Default = false,
    Callback = Misc.applyGod,
})

Misc.killLabel = Live:Label({ Text = "killbricks avoided: 0", Mono = true })

Live:Label({
    Text = "Four layers: the death state is disabled, CanTouch is cleared on your limbs so a killbrick's Touched never fires, health is restored on any drop, and anything that hurts you is LEARNED -- auto-collect then refuses to fire touch on it, so it stops teleporting you onto lava to reach a coin.",
    Muted = true,
})

Live:Button({
    Text = "Clear learned killbricks",
    Callback = function()
        table_clear(killParts)
        killCount = 0
        Misc.killLabel:SetText("killbricks avoided: 0")
    end,
})

Live:Button({
    Text = "Instant reset",
    Callback = function() Misc.instantReset() end,
})

Live:Toggle({
    Flag = "keeppos",
    Text = "Keep position through reset",
    Default = false,
    Callback = function(on) Misc.keepPos = on end,
})

Live:Label({
    Text = "Reset dies on the spot instead of holding the menu button. The respawn delay itself is Players.RespawnTime and the server owns it -- no client can shorten that. Keep-position applies to ANY death -- falling, killed, the Roblox reset button -- not just the button above.",
    Muted = true,
})

Live:Toggle({
    Flag = "antiragdoll",
    Text = "Anti-ragdoll",
    Default = false,
    Callback = function(on)
        Misc.antiRagdoll = on
        local humanoid = Misc.humanoid
        if humanoid then
            pcall(function()
                humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, not on)
                humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, not on)
            end)
        end
    end,
})

Live:Toggle({
    Flag = "autoequip",
    Text = "Auto-equip tools",
    Default = false,
    Callback = function(on) Misc.autoEquip = on end,
})

Live:Toggle({
    Flag = "antiafk",
    Text = "Anti-AFK",
    Default = false,
    Callback = function(on) Misc.antiAfk = on end,
})

--------------------------------------------------------------- visual

local View = MiscTab:Section({ Name = "Visual & session", Side = "Left" })

View:Toggle({
    Flag = "antifog",
    Text = "Anti-fog",
    Default = false,
    Callback = function(on)
        Misc.antiFog = on
        Misc.applyAntiFog(on)
    end,
})

View:Toggle({
    Flag = "fullbright",
    Text = "Full bright",
    Default = false,
    Callback = function(on)
        Misc.fullBright = on
        Misc.applyBright(on)
    end,
})

View:Toggle({
    Flag = "misclag",
    Text = "Anti-lag",
    Default = false,
    Callback = function(on)
        -- one source of truth: drive the Performance tab's toggle rather than
        -- keeping a second copy of the same global state
        local opt = Library.Options.antilag
        if opt and opt.Value ~= on then opt:SetValue(on) end
    end,
})

View:Toggle({
    Flag = "hideguis",
    Text = "Hide all GUIs",
    Default = false,
    Callback = function(on) Misc.hideGuis(on) end,
})

View:Toggle({
    Flag = "maxzoom",
    Text = "Unlock camera zoom",
    Default = false,
    Callback = function(on)
        Misc.maxZoom = on
        pcall(function()
            LocalPlayer.CameraMaxZoomDistance = on and 2000 or 128
        end)
    end,
})

View:Divider()

View:Button({
    Text = "Rejoin same server",
    Callback = function()
        -- TeleportToPlaceInstance with our own JobId puts us back in THIS
        -- server, not a random one. It can fail if the instance shut down or
        -- filled while we were leaving, so say so rather than silently
        -- dumping you somewhere else.
        Persist.arm("rejoin")
        local ok, err = pcall(function()
            game:GetService("TeleportService")
                :TeleportToPlaceInstance(game.PlaceId, game.JobId, LocalPlayer)
        end)
        if not ok then
            Library:Notify({
                Title = "rejoin",
                Text = "same-server rejoin failed: " .. tostring(err),
                Type = "error",
            })
        end
    end,
})

View:Button({
    Text = "Rejoin (any server)",
    Callback = function()
        Persist.arm("rejoin")
        pcall(function()
            game:GetService("TeleportService"):Teleport(game.PlaceId, LocalPlayer)
        end)
    end,
})

View:Button({
    Text = "Server hop (smallest server)",
    Callback = function()
        task.spawn(function()
            local ok, err = pcall(function()
                local TS = game:GetService("TeleportService")
                local url = "https://games.roblox.com/v1/games/" .. game.PlaceId
                    .. "/servers/Public?sortOrder=Asc&limit=100"
                local body = game:HttpGet(url)
                local best, bestPlayers
                -- no JSON decode dependency: pull the fields straight out
                for id, playing, maxp in body:gmatch(
                    '"id":"([^"]+)".-"playing":(%d+).-"maxPlayers":(%d+)') do
                    playing, maxp = tonumber(playing), tonumber(maxp)
                    if id ~= game.JobId and playing < maxp then
                        if not bestPlayers or playing < bestPlayers then
                            best, bestPlayers = id, playing
                        end
                    end
                end
                if not best then error("no other server with room") end
                Persist.arm("server hop")
                TS:TeleportToPlaceInstance(game.PlaceId, best, LocalPlayer)
            end)
            if not ok then
                Library:Notify({ Title = "server hop",
                    Text = tostring(err), Type = "error" })
            end
        end)
    end,
})

end

------------------------------------------------------------------- teleport

do

local TweenService = game:GetService("TweenService")

local TP = {
    method = "Tween",         -- Tween | Direct
    speed = 120,              -- studs/sec for tween
    waypoints = {},           -- [name] = CFrame
    order = {},               -- name order for the dropdown
    tweening = nil,
}

local function tpRoot()
    return rootPart
        or (LocalPlayer.Character and LocalPlayer.Character:FindFirstChild("HumanoidRootPart"))
end

-- Direct sets CFrame instantly. Tween slides you there at a fixed speed, which
-- reads as fast travel rather than a teleport and slips past some naive
-- position-delta checks. It cancels a tween already in flight.
local function goTo(targetCF)
    local root = tpRoot()
    if not (root and targetCF) then return false end

    if TP.tweening then pcall(function() TP.tweening:Cancel() end) TP.tweening = nil end

    if TP.method == "Direct" then
        pcall(function() root.CFrame = targetCF end)
        return true
    end

    local dist = (targetCF.Position - root.Position).Magnitude
    local time = math.max(dist / math.max(TP.speed, 1), 0.05)
    local ok, tw = pcall(function()
        return TweenService:Create(root,
            TweenInfo.new(time, Enum.EasingStyle.Linear), { CFrame = targetCF })
    end)
    if ok and tw then TP.tweening = tw ; tw:Play() end
    return true
end

local function playerCF(name)
    local plr = Players:FindFirstChild(name)
    local char = plr and plr.Character
    local root = char and char:FindFirstChild("HumanoidRootPart")
    if not root then return nil end
    -- land just beside them, facing them, not clipped inside
    return root.CFrame * CFrame.new(0, 0, 4)
end

local Tab   = Window:Tab("Teleport", "portal")
local Way   = Tab:Section({ Name = "Waypoints", Side = "Left" })

TP.wpName = Way:Input({
    Flag = "tpwpname",
    Text = "Name",
    Placeholder = "base, spawn, ...",
    Default = "",
})

local function refreshWaypoints()
    if TP.wpList then TP.wpList:SetValues(TP.order, true) end
    if TP.wpLabel then
        TP.wpLabel:SetText("saved: " .. #TP.order)
    end
end

Way:Button({
    Text = "Save current spot",
    Callback = function()
        local root = tpRoot()
        if not root then return end
        local name = (Library.Options.tpwpname and Library.Options.tpwpname.Value or "")
        name = tostring(name):gsub("^%s+", ""):gsub("%s+$", "")
        if name == "" then name = "wp" .. (#TP.order + 1) end
        if not TP.waypoints[name] then TP.order[#TP.order + 1] = name end
        TP.waypoints[name] = root.CFrame
        refreshWaypoints()
        Library:Notify({ Title = "teleport", Text = "saved '" .. name .. "'",
                         Type = "success" })
    end,
})

TP.wpList = Way:Dropdown({
    Flag = "tpwp",
    Text = "Waypoint",
    Values = {},
})

Way:Button({
    Text = "Teleport to waypoint",
    Callback = function()
        local sel = Library.Options.tpwp and Library.Options.tpwp.Value
        local cf = sel and TP.waypoints[sel]
        if cf then goTo(cf)
        else Library:Notify({ Title = "teleport", Text = "pick a waypoint",
                              Type = "warn" }) end
    end,
})

Way:Button({
    Text = "Delete waypoint",
    Callback = function()
        local sel = Library.Options.tpwp and Library.Options.tpwp.Value
        if sel and TP.waypoints[sel] then
            TP.waypoints[sel] = nil
            for i, n in ipairs(TP.order) do
                if n == sel then table.remove(TP.order, i) break end
            end
            refreshWaypoints()
        end
    end,
})

TP.wpLabel = Way:Label({ Text = "saved: 0", Mono = true, Muted = true })

local Ppl = Tab:Section({ Name = "Players", Side = "Right" })

Ppl:Dropdown({
    Flag = "tpmethod",
    Text = "Method",
    Values = { "Tween", "Direct" },
    Default = "Tween",
    Callback = function(v) TP.method = v end,
})

Ppl:Slider({
    Flag = "tpspeed",
    Text = "Tween speed",
    Min = 20, Max = 500, Default = 120, Decimals = 0,
    Suffix = " studs/s",
    Callback = function(v) TP.speed = v end,
})

Ppl:Dropdown({
    Flag = "tptarget",
    Text = "Player",
    Values = { "" },
})

local function refreshPlayers()
    local list = {}
    for _, plr in ipairs(Players:GetPlayers()) do
        if plr ~= LocalPlayer then list[#list + 1] = plr.Name end
    end
    if Library.Options.tptarget then
        Library.Options.tptarget:SetValues(list, true)
    end
end

Ppl:Button({ Text = "Refresh players", Callback = refreshPlayers })

Ppl:Button({
    Text = "Teleport to player",
    Callback = function()
        local sel = Library.Options.tptarget and Library.Options.tptarget.Value
        local cf = sel and playerCF(sel)
        if cf then goTo(cf)
        else Library:Notify({ Title = "teleport",
                              Text = "no target / they have no character",
                              Type = "warn" }) end
    end,
})

Ppl:Toggle({
    Flag = "tpfollow",
    Text = "Follow player",
    Default = false,
    Callback = function(on) TP.follow = on end,
})

Ppl:Label({
    Text = "Tween slides you over at a set speed (looks like fast travel, slips past simple distance checks); Direct snaps instantly. Follow keeps re-teleporting to the target -- with Tween that trails them, with Direct it locks onto them.",
    Muted = true,
})

Library:Connect(Players.PlayerAdded, refreshPlayers)
Library:Connect(Players.PlayerRemoving, refreshPlayers)
refreshPlayers()

-- follow loop
local followClock = 0
Library:Connect(RunService.Heartbeat, function(dt)
    if not TP.follow then return end
    followClock = followClock + dt
    if followClock < (TP.method == "Direct" and 0.1 or 0.4) then return end
    followClock = 0
    local sel = Library.Options.tptarget and Library.Options.tptarget.Value
    local cf = sel and playerCF(sel)
    if cf then goTo(cf) end
end)

end

------------------------------------------------------------------ settings

do


local Settings = Window:Tab("Settings", "gear")
local Binds    = Settings:Section({ Name = "Keybinds", Side = "Left" })

Binds:Keybind({
    Flag = "collectkey",
    Text = "Toggle collect",
    Default = "Ctrl+G",
    Mode = "Toggle",
    Callback = function()
        local opt = Library.Options.autocollect
        opt:SetValue(not opt.Value)
    end,
})

Binds:Keybind({
    Flag = "antilagkey",
    Text = "Toggle anti-lag",
    Default = "Ctrl+L",
    Mode = "Toggle",
    Callback = function()
        local opt = Library.Options.antilag
        opt:SetValue(not opt.Value)
    end,
})

Binds:Keybind({
    Flag = "panickey",
    Text = "Stop everything",
    Default = "Ctrl+Shift+S",
    Mode = "Toggle",
    Callback = function()
        Library.Options.autocollect:SetValue(false)
        Library.Options.autoprompt:SetValue(false)
        Library.Options.autoclick:SetValue(false)
        stopFuzz("panic key")
        stopNet("panic key")
        Drag.running = false
        pcall(Drag.stop)
        if Library.Options.dragrun then
            Library.Options.dragrun:SetValue(false, true)
        end
        restoreAll()
        if Library.Options.netrun then Library.Options.netrun:SetValue(false, true) end
        stopNet("panic key")
        releaseParts()
        if Library.Options.netrun then Library.Options.netrun:SetValue(false, true) end
        Library:Notify({ Title = "optimizer", Text = "everything off", Type = "warn" })
    end,
})

local Session = Settings:Section({ Name = "Session", Side = "Right" })

Session:Input({ Flag = "configname", Text = "Config", Default = "optimizer" })

Session:Button({
    Text = "Save",
    Callback = function()
        local ok = Library:SaveConfig(Library.Options.configname.Value)
        Library:Notify({ Title = "config", Text = ok and "saved" or "failed",
                         Type = ok and "success" or "error" })
    end,
})

Session:Button({
    Text = "Load",
    Callback = function()
        local ok = Library:LoadConfig(Library.Options.configname.Value)
        Library:Notify({ Title = "config", Text = ok and "loaded" or "failed",
                         Type = ok and "success" or "error" })
    end,
})

Session:Divider()

Session:Toggle({
    Flag = "surviveteleport",
    Text = "Follow me between servers",
    Default = true,
    Callback = function(on)
        Persist.survive = on
        Persist.queued = false
    end,
})

Persist.statusLabel = Session:Label({ Text = "idle", Mono = true, Muted = true })
Session:Label({ Text = Persist.capabilities(), Mono = true, Muted = true })

Session:Label({
    Text = "Deliberately not autoexec: nothing is written to disk, so a crash or a fresh Roblox launch starts clean. The hub only rides through a teleport -- place changes, server hops, rejoins -- carrying your current settings inside the queued script, so it works even with no file access.",
    Muted = true,
})

Session:Divider()
Session:Button({ Text = "Unload", Callback = function() Library:Unload() end })
end

--=========================================================================
-- workspace scan  --  chunked, so loading into a 60k-part map costs no hitch
--=========================================================================

do
    local all = workspace:GetDescendants()
    local n = #all
    startJob(all, n, 4000, function(inst)
        if inst:IsA("BasePart") then
            setAdd(partSet, inst)
            if inst:FindFirstChildOfClass("TouchTransmitter") then
                setAdd(pickSet, inst)
            end
        elseif inst:IsA("ProximityPrompt") then
            addPrompt(inst)
        elseif inst:IsA("ClickDetector") then
            addClick(inst)
        elseif inst:IsA("DragDetector") then
            Drag.add(inst)
        end
    end, function()
        statusLabel:SetText(format("indexed %d parts, %d prompts, %d detectors",
            partSet.n, promptSet.n, clickSet.n))
        -- nm-lib applies a toggle's Default silently, so a Default = true
        -- never fires its callback. Sync the bypasses here rather than at
        -- construction: this is the first moment the registry is populated.
        if Library.Options.promptbypass.Value then setPromptBypass(true) end
        if Library.Options.clickbypass.Value then setClickBypass(true) end
    end, "index")
end

Library:Connect(workspace.DescendantAdded, function(inst)
    if inst:IsA("BasePart") then
        onPartAdded(inst)
    elseif inst:IsA("TouchTransmitter") then
        -- fires on the transmitter itself, so no task.defer race
        local parent = inst.Parent
        if parent and partSet.index[parent] then setAdd(pickSet, parent) end
    elseif inst:IsA("ProximityPrompt") then
        addPrompt(inst)
    elseif inst:IsA("ClickDetector") then
        addClick(inst)
    elseif inst:IsA("DragDetector") then
        Drag.add(inst)
    elseif antiLagOn and EFFECTS[inst.ClassName] then
        if setAdd(fxSet, inst) then
            oldFx[fxSet.n] = inst.Enabled
            inst.Enabled = false
        end
    end
end)

Library:Connect(workspace.DescendantRemoving, function(inst)
    if inst:IsA("BasePart") then
        onPartRemoved(inst)
    elseif inst:IsA("TouchTransmitter") then
        local parent = inst.Parent
        if parent then setRemove(pickSet, parent) end
    elseif inst:IsA("ProximityPrompt") then
        dropPrompt(inst)
    elseif inst:IsA("ClickDetector") then
        dropClick(inst)
    elseif inst:IsA("DragDetector") then
        Drag.drop(inst)
    end
end)

--=========================================================================
-- input
--=========================================================================

Library:Connect(UserInputService.InputBegan, function(input, gameProcessed)
    if gameProcessed or not selectModeOn then return end
    if input.UserInputType ~= MB1 then return end

    local target = Mouse.Target
    if not (target and target:IsA("BasePart")) then return end

    local baseName = baseNameOf(target.Name)
    if activeNames[baseName] then
        deselectGroup(baseName)
    else
        selectGroup(baseName)
    end
end)

Library:Connect(LocalPlayer.OnTeleport, function()
    Persist.arm("teleport started")
end)

Library:Connect(LocalPlayer.CharacterAdded, function(char)
    cursor = 1
    bindCharacter(char)
    pcall(Misc.bind, char)
    armHitWatch()                   -- new Humanoid to watch
end)

Library:Connect(LocalPlayer.CharacterAdded, function(char)
    if Misc.autoRespawn then end
end)

Library:Connect(LocalPlayer.CharacterRemoving, function()
    rootPart = nil                  -- the loop's only liveness check
end)

--=========================================================================
-- the one loop
--=========================================================================

local uiClock = 0

-- The network engine gets its OWN Heartbeat, the way the reference does.
-- Sharing one callback across six engines means a throw anywhere upstream --
-- a job's work function, a prompt batch, a label write -- aborts the rest of
-- the frame, and the network tab dies silently while everything still reports
-- healthy. That failure mode is indistinguishable from "ownership refused",
-- which is exactly the wrong thing to be unable to tell apart.
Library:Connect(Heartbeat, function(dt)
    if Net.hold then holdOwnership() end
    if Net.running then stepNet(dt) end
end)

Library:Connect(Heartbeat, function(dt)
    pcall(Misc.step, dt)
end)

Library:Connect(Heartbeat, function(dt)
    if Drag.running then pcall(Drag.step, dt) end
end)

Library:Connect(UserInputService.JumpRequest, function()
    if not Misc.infJump then return end
    local humanoid = Misc.humanoid
    if humanoid then
        pcall(function()
            humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
        end)
    end
end)

Library:Connect(LocalPlayer.Idled, function()
    if not Misc.antiAfk then return end
    pcall(function()
        local vu = game:GetService("VirtualUser")
        vu:CaptureController()
        vu:ClickButton2(Vector2.new())
    end)
end)

Library:Connect(Heartbeat, function(dt)
    -- each engine isolated, so one bad part cannot take the others down
    if jobs[1] then pcall(stepJob) end

    if rootPart then
        if collectOn then pcall(stepCollect) end
        if promptOn then pcall(stepPrompts) end
        if clickOn then pcall(stepClicks) end
    end

    if Fuzz.running then pcall(stepFuzz, dt) end

    uiClock = uiClock + dt
    if uiClock >= 0.5 then
        uiClock = 0
        pcall(function()
            partsLabel:SetText(format("parts: %d", partSet.n))
            pickLabel:SetText(format("pickups: %d", pickSet.n))
            selLabel:SetText(format("selected: %d  (%d outlined)", selSet.n, boxCount))
            promptLabel:SetText(format("prompts: %d", promptSet.n))
            clickLabel:SetText(format("detectors: %d", clickSet.n))
            if Net.statusLabel then Net.statusLabel:SetText(Net.status) end
            if Persist.statusLabel then
                Persist.statusLabel:SetText(Persist.status)
            end
            if Drag.statusLabel then Drag.statusLabel:SetText(Drag.status) end
            local job = jobs[1]
            if job then
                statusLabel:SetText(format("%s: %d/%d  (%d queued)",
                    job.label, job.i - 1, job.n, #jobs - 1))
            end
        end)
    end
end)

--=========================================================================
-- teardown  --  nm-lib kills its own connections; these are ours
--=========================================================================

Library:OnUnload(function()
    collectOn, promptOn, clickOn = false, false, false
    Fuzz.running = false
    Fuzz.gen = Fuzz.gen + 1
    stopNet("unload")
    restoreAll()
    Drag.running = false
    pcall(Drag.stop)
    pcall(Drag.setPrepped, false)
    pcall(Misc.hideGuis, false)
    pcall(function()
        Misc.applyGod(false)
        Misc.applyAntiFog(false)
        Misc.applyBright(false)
        Misc.noclip, Misc.freeze, Misc.applyMove = false, false, false
        if rootPart then rootPart.Anchored = false end
    end)
    stopNet("unload")
    releaseParts()
    table_clear(jobs)
    clearSelection()

    if promptBypass then
        for i = 1, promptSet.n do
            local prompt = promptSet.items[i]
            if prompt.Parent then
                prompt.HoldDuration          = oldHold[i]
                prompt.MaxActivationDistance = oldPromptDist[i]
                prompt.RequiresLineOfSight   = oldLOS[i]
            end
        end
    end
    if clickBypass then
        for i = 1, clickSet.n do
            local cd = clickSet.items[i]
            if cd.Parent then cd.MaxActivationDistance = oldClickDist[i] end
        end
    end

    if antiLagOn then
        for i = 1, touched.n do
            local part = touched.items[i]
            if part.Parent then
                part.Material    = oldMat[i]
                part.CastShadow  = oldShadow[i]
                part.Reflectance = oldRefl[i]
            end
        end
        restoreLighting()
    end
end)

Persist.restore()

Library:Notify({
    Title = "optimizer",
    Text = "loaded. Ctrl+H menu, Ctrl+G collect, Ctrl+L anti-lag, Ctrl+Shift+S panic.",
    Type = "success",
})