-- Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local StarterGui = game:GetService("StarterGui")
local CoreGui = game:GetService("CoreGui")
local SoundService = game:GetService("SoundService")
local Debris = game:GetService("Debris")
local UIS = game:GetService("UserInputService")

local LocalPlayer = Players.LocalPlayer

-- State
local isFlingEnabled = false
local walkflinging = false
local noCollideEnabled = false
local hugEnabled = false
local bypassEnabled = false
local isFlingingAll = false
local antiFlingEnabled = false
local flingLoop = nil
local noCollideConnection = nil
local audioConnection = nil
local walkFlingConnection = nil

getgenv().OldPos = nil
getgenv().FPDH = workspace.FallenPartsDestroyHeight
getgenv().CurrentGameVolume = 1

-- Audio system
local mutedSounds = {}

local function registerSound(sound)
    if not sound:IsA("Sound") then return end
    local parent = sound.Parent
    if parent and (parent.Name:lower():find("voice") or parent.Name:lower():find("vc")) then return end
    if sound.Name:lower():find("voice") or sound.Name:lower():find("vc") then return end
    if not sound:GetAttribute("OriginalVolume") then
        sound:SetAttribute("OriginalVolume", sound.Volume)
    end
    mutedSounds[sound] = sound
end

local function setGameVolume(vol)
    for sound, _ in pairs(mutedSounds) do
        if sound and sound.Parent then
            local orig = sound:GetAttribute("OriginalVolume") or 0.5
            sound.Volume = vol * orig
        end
    end
end

local function scanSounds()
    for _, obj in pairs(workspace:GetDescendants()) do registerSound(obj) end
    for _, obj in pairs(SoundService:GetDescendants()) do registerSound(obj) end
end

local function startAudioWatcher(vol)
    if audioConnection then audioConnection:Disconnect() end
    scanSounds()
    setGameVolume(vol)
    audioConnection = workspace.DescendantAdded:Connect(function(obj)
        if obj:IsA("Sound") then
            task.wait()
            registerSound(obj)
            local v = getgenv().CurrentGameVolume or 1
            local orig = obj:GetAttribute("OriginalVolume")
            if orig then obj.Volume = v * orig end
        end
    end)
end

-- GUI
local ScreenGui = Instance.new("ScreenGui")
ScreenGui.Name = "TrollUI_v3"
ScreenGui.Parent = CoreGui
ScreenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
ScreenGui.ResetOnSpawn = false

local MainFrame = Instance.new("Frame")
MainFrame.Name = "MainFrame"
MainFrame.Parent = ScreenGui
MainFrame.BackgroundColor3 = Color3.fromRGB(12, 12, 12)
MainFrame.Position = UDim2.new(0.5, -310, 0.5, -210)
MainFrame.Size = UDim2.new(0, 620, 0, 420)
MainFrame.Active = true
MainFrame.Draggable = true

local UICorner = Instance.new("UICorner")
UICorner.CornerRadius = UDim.new(0, 8)
UICorner.Parent = MainFrame

local UIStroke = Instance.new("UIStroke")
UIStroke.Thickness = 4
UIStroke.Parent = MainFrame

-- Animated outline
local outlineColors = {
    Color3.fromRGB(0, 0, 0),
    Color3.fromRGB(100, 100, 100),
    Color3.fromRGB(255, 90, 0)
}
spawn(function()
    while MainFrame and MainFrame.Parent do
        for _, color in ipairs(outlineColors) do
            if not (MainFrame and MainFrame.Parent) then break end
            TweenService:Create(UIStroke, TweenInfo.new(0.5, Enum.EasingStyle.Linear), {Color = color}):Play()
            task.wait(0.5)
        end
    end
end)

-- Top bar
local TopBar = Instance.new("Frame")
TopBar.Parent = MainFrame
TopBar.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
TopBar.Size = UDim2.new(1, 0, 0, 32)
local TBC = Instance.new("UICorner"); TBC.CornerRadius = UDim.new(0, 8); TBC.Parent = TopBar

local TitleLabel = Instance.new("TextLabel")
TitleLabel.Parent = TopBar
TitleLabel.BackgroundTransparency = 1
TitleLabel.Position = UDim2.new(0, 10, 0, 0)
TitleLabel.Size = UDim2.new(1, -80, 1, 0)
TitleLabel.Font = Enum.Font.GothamBold
TitleLabel.Text = "Troll UI v3"
TitleLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
TitleLabel.TextSize = 14
TitleLabel.TextXAlignment = Enum.TextXAlignment.Left

local function makeTopBtn(text, posX)
    local b = Instance.new("TextButton")
    b.Parent = TopBar
    b.BackgroundColor3 = Color3.fromRGB(50, 50, 50)
    b.Position = UDim2.new(1, posX, 0, 4)
    b.Size = UDim2.new(0, 24, 0, 24)
    b.Font = Enum.Font.GothamBold
    b.Text = text
    b.TextColor3 = Color3.fromRGB(255, 255, 255)
    b.TextSize = 14
    local c = Instance.new("UICorner"); c.CornerRadius = UDim.new(0, 4); c.Parent = b
    return b
end

local MinimizeBtn = makeTopBtn("—", -54)
local CloseBtn = makeTopBtn("X", -26)
CloseBtn.BackgroundColor3 = Color3.fromRGB(180, 30, 30)

local function makeBtn(text, posX, posY, w, h)
    local b = Instance.new("TextButton")
    b.Parent = MainFrame
    b.BackgroundColor3 = Color3.fromRGB(255, 90, 0)
    b.Position = UDim2.new(0.5, posX, posY, 0)
    b.Size = UDim2.new(0, w, 0, h)
    b.Font = Enum.Font.GothamBold
    b.Text = text
    b.TextColor3 = Color3.fromRGB(255, 255, 255)
    b.TextSize = h > 35 and 15 or 13
    b.TextWrapped = true
    local c = Instance.new("UICorner"); c.CornerRadius = UDim.new(0, 6); c.Parent = b
    return b
end

local function setToggle(btn, state)
    btn.BackgroundColor3 = state
        and Color3.fromRGB(0, 200, 80)
        or Color3.fromRGB(255, 90, 0)
end

-- Username input
local UsernameBox = Instance.new("TextBox")
UsernameBox.Parent = MainFrame
UsernameBox.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
UsernameBox.Position = UDim2.new(0.5, -145, 0.15, 0)
UsernameBox.Size = UDim2.new(0, 196, 0, 32)
UsernameBox.Font = Enum.Font.Gotham
UsernameBox.PlaceholderText = "Enter username..."
UsernameBox.Text = ""
UsernameBox.TextColor3 = Color3.fromRGB(255, 255, 255)
UsernameBox.PlaceholderColor3 = Color3.fromRGB(120, 120, 120)
UsernameBox.TextSize = 13
UsernameBox.ClearTextOnFocus = false
local UBC = Instance.new("UICorner"); UBC.CornerRadius = UDim.new(0, 6); UBC.Parent = UsernameBox

-- Dropdown button
local DropdownBtn = Instance.new("TextButton")
DropdownBtn.Parent = MainFrame
DropdownBtn.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
DropdownBtn.Position = UDim2.new(0.5, 55, 0.15, 0)
DropdownBtn.Size = UDim2.new(0, 28, 0, 32)
DropdownBtn.Font = Enum.Font.GothamBold
DropdownBtn.Text = "▼"
DropdownBtn.TextColor3 = Color3.fromRGB(200, 200, 200)
DropdownBtn.TextSize = 12
local DBC = Instance.new("UICorner"); DBC.CornerRadius = UDim.new(0, 6); DBC.Parent = DropdownBtn

-- Dropdown list
local DropdownFrame = Instance.new("Frame")
DropdownFrame.Parent = MainFrame
DropdownFrame.BackgroundColor3 = Color3.fromRGB(25, 25, 25)
DropdownFrame.Position = UDim2.new(0.5, -145, 0.15, 36)
DropdownFrame.Size = UDim2.new(0, 224, 0, 0)
DropdownFrame.Visible = false
DropdownFrame.ZIndex = 10
DropdownFrame.ClipsDescendants = true
local DFC = Instance.new("UICorner"); DFC.CornerRadius = UDim.new(0, 6); DFC.Parent = DropdownFrame

local DropdownLayout = Instance.new("UIListLayout")
DropdownLayout.Parent = DropdownFrame
DropdownLayout.SortOrder = Enum.SortOrder.LayoutOrder
DropdownLayout.Padding = UDim.new(0, 1)

local dropdownOpen = false

local function refreshDropdown()
    for _, child in pairs(DropdownFrame:GetChildren()) do
        if child:IsA("TextButton") then child:Destroy() end
    end
    local count = 0
    for _, player in pairs(Players:GetPlayers()) do
        if player ~= LocalPlayer then
            count += 1
            local entry = Instance.new("TextButton")
            entry.Parent = DropdownFrame
            entry.BackgroundColor3 = Color3.fromRGB(35, 35, 35)
            entry.Size = UDim2.new(1, 0, 0, 28)
            entry.Font = Enum.Font.Gotham
            entry.Text = "  " .. player.Name
            entry.TextColor3 = Color3.fromRGB(220, 220, 220)
            entry.TextSize = 12
            entry.TextXAlignment = Enum.TextXAlignment.Left
            entry.ZIndex = 11
            local EC = Instance.new("UICorner"); EC.CornerRadius = UDim.new(0, 4); EC.Parent = entry
            entry.MouseButton1Click:Connect(function()
                UsernameBox.Text = player.Name
                dropdownOpen = false
                TweenService:Create(DropdownFrame, TweenInfo.new(0.15), {Size = UDim2.new(0, 224, 0, 0)}):Play()
                task.wait(0.15)
                DropdownFrame.Visible = false
                DropdownBtn.Text = "▼"
            end)
            entry.MouseEnter:Connect(function() entry.BackgroundColor3 = Color3.fromRGB(55, 55, 55) end)
            entry.MouseLeave:Connect(function() entry.BackgroundColor3 = Color3.fromRGB(35, 35, 35) end)
        end
    end
    return count
end

DropdownBtn.MouseButton1Click:Connect(function()
    dropdownOpen = not dropdownOpen
    if dropdownOpen then
        local count = refreshDropdown()
        DropdownFrame.Visible = true
        DropdownFrame.Size = UDim2.new(0, 224, 0, 0)
        local targetH = math.min(count * 29, 145)
        TweenService:Create(DropdownFrame, TweenInfo.new(0.15), {Size = UDim2.new(0, 224, 0, targetH)}):Play()
        DropdownBtn.Text = "▲"
    else
        TweenService:Create(DropdownFrame, TweenInfo.new(0.15), {Size = UDim2.new(0, 224, 0, 0)}):Play()
        task.wait(0.15)
        DropdownFrame.Visible = false
        DropdownBtn.Text = "▼"
    end
end)

-- Buttons
local FlingBtn      = makeBtn("Fling",        90,  0.15, 80, 32)
local UnflingBtn    = makeBtn("Unfling",       178, 0.15, 80, 32)
local FlingAllBtn   = makeBtn("Fling All",    -300, 0.35, 120, 38)
local WalkFlingBtn  = makeBtn("Walk Fling",   -165, 0.35, 120, 38)
local NoCollideBtn  = makeBtn("No Collide",   -30,  0.35, 120, 38)
local AntiFlingBtn  = makeBtn("Anti-Fling",    110, 0.35, 120, 38)
local HugBtn        = makeBtn("Hug (H)",      -300, 0.55, 120, 38)
local ChatBypassBtn = makeBtn("Chat Bypass",  -165, 0.55, 120, 38)
local JorkBtn       = makeBtn("Jork",         -30,  0.55, 120, 38)

-- Volume section
local VolLabel = Instance.new("TextLabel")
VolLabel.Parent = MainFrame
VolLabel.BackgroundTransparency = 1
VolLabel.Position = UDim2.new(0.5, -300, 0.73, 0)
VolLabel.Size = UDim2.new(0, 200, 0, 20)
VolLabel.Font = Enum.Font.GothamBold
VolLabel.Text = "Game Audio Volume"
VolLabel.TextColor3 = Color3.fromRGB(200, 200, 200)
VolLabel.TextSize = 13
VolLabel.TextXAlignment = Enum.TextXAlignment.Left

local VCLabel = Instance.new("TextLabel")
VCLabel.Parent = MainFrame
VCLabel.BackgroundTransparency = 1
VCLabel.Position = UDim2.new(0.5, 110, 0.73, 0)
VCLabel.Size = UDim2.new(0, 200, 0, 20)
VCLabel.Font = Enum.Font.Gotham
VCLabel.Text = "(voice chat unaffected)"
VCLabel.TextColor3 = Color3.fromRGB(120, 120, 120)
VCLabel.TextSize = 11
VCLabel.TextXAlignment = Enum.TextXAlignment.Left

local SliderBG = Instance.new("Frame")
SliderBG.Parent = MainFrame
SliderBG.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
SliderBG.Position = UDim2.new(0.5, -300, 0.82, 0)
SliderBG.Size = UDim2.new(0, 490, 0, 10)
local SBGC = Instance.new("UICorner"); SBGC.CornerRadius = UDim.new(0, 5); SBGC.Parent = SliderBG

local SliderFill = Instance.new("Frame")
SliderFill.Parent = SliderBG
SliderFill.BackgroundColor3 = Color3.fromRGB(255, 90, 0)
SliderFill.Size = UDim2.new(1, 0, 1, 0)
SliderFill.BorderSizePixel = 0
local SFC = Instance.new("UICorner"); SFC.CornerRadius = UDim.new(0, 5); SFC.Parent = SliderFill

local SliderThumb = Instance.new("TextButton")
SliderThumb.Parent = MainFrame
SliderThumb.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
SliderThumb.Position = UDim2.new(0.5, 185, 0.82, -5)
SliderThumb.Size = UDim2.new(0, 20, 0, 20)
SliderThumb.Text = ""
SliderThumb.BorderSizePixel = 0
local STC = Instance.new("UICorner"); STC.CornerRadius = UDim.new(1, 0); STC.Parent = SliderThumb

local VolNumLabel = Instance.new("TextLabel")
VolNumLabel.Parent = MainFrame
VolNumLabel.BackgroundTransparency = 1
VolNumLabel.Position = UDim2.new(0.5, 200, 0.79, 0)
VolNumLabel.Size = UDim2.new(0, 50, 0, 26)
VolNumLabel.Font = Enum.Font.GothamBold
VolNumLabel.Text = "100%"
VolNumLabel.TextColor3 = Color3.fromRGB(255, 90, 0)
VolNumLabel.TextSize = 13

-- Slider logic
local sliderDragging = false

local function updateSlider(pct)
    pct = math.clamp(pct, 0, 1)
    SliderFill.Size = UDim2.new(pct, 0, 1, 0)
    SliderThumb.Position = UDim2.new(0.5, -300 + pct * 490 - 10, 0.82, -5)
    VolNumLabel.Text = math.floor(pct * 100) .. "%"
    getgenv().CurrentGameVolume = pct
    setGameVolume(pct)
end

SliderThumb.MouseButton1Down:Connect(function()
    sliderDragging = true
end)

UIS.InputEnded:Connect(function(inp)
    if inp.UserInputType == Enum.UserInputType.MouseButton1 then
        sliderDragging = false
    end
end)

UIS.InputChanged:Connect(function(inp)
    if sliderDragging and inp.UserInputType == Enum.UserInputType.MouseMovement then
        local absPos = SliderBG.AbsolutePosition.X
        local absSize = SliderBG.AbsoluteSize.X
        updateSlider((inp.Position.X - absPos) / absSize)
    end
end)

SliderBG.InputBegan:Connect(function(inp)
    if inp.UserInputType == Enum.UserInputType.MouseButton1 then
        local absPos = SliderBG.AbsolutePosition.X
        local absSize = SliderBG.AbsoluteSize.X
        updateSlider((inp.Position.X - absPos) / absSize)
    end
end)

startAudioWatcher(1)

-- Helpers
local function getPlayerByName(name)
    name = name:lower()
    for _, p in pairs(Players:GetPlayers()) do
        if p ~= LocalPlayer then
            if p.Name:lower():match("^"..name) or p.DisplayName:lower():match("^"..name) then
                return p
            end
        end
    end
end

local function notify(title, text, dur)
    StarterGui:SetCore("SendNotification", {Title=title, Text=text, Duration=dur})
end

-- Core fling
local function skidFling(TargetPlayer)
    local Character = LocalPlayer.Character
    local Humanoid = Character and Character:FindFirstChildOfClass("Humanoid")
    local RootPart = Humanoid and Humanoid.RootPart
    if not (Character and Humanoid and RootPart) then return end

    local TCharacter = TargetPlayer.Character
    if not TCharacter then return end
    local THumanoid = TCharacter:FindFirstChildOfClass("Humanoid")
    local TRootPart = THumanoid and THumanoid.RootPart
    local THead = TCharacter:FindFirstChild("Head")
    local Accessory = TCharacter:FindFirstChildOfClass("Accessory")
    local Handle = Accessory and Accessory:FindFirstChild("Handle")

    if RootPart.Velocity.Magnitude < 50 then
        getgenv().OldPos = RootPart.CFrame
    end
    if THumanoid and THumanoid.Sit then
        return notify("Error", "Target is sitting", 5)
    end

    workspace.CurrentCamera.CameraSubject = THead or Handle or THumanoid
    if not TCharacter:FindFirstChildWhichIsA("BasePart") then return end

    local function FPos(BasePart, Pos, Ang)
        RootPart.CFrame = CFrame.new(BasePart.Position) * Pos * Ang
        Character:SetPrimaryPartCFrame(CFrame.new(BasePart.Position) * Pos * Ang)
        RootPart.Velocity = Vector3.new(9e7, 9e7 * 10, 9e7)
        RootPart.RotVelocity = Vector3.new(9e8, 9e8, 9e8)
    end

    local function SFBasePart(BasePart)
        local Time = tick()
        local Angle = 0
        repeat
            if not (RootPart and THumanoid) then break end
            if BasePart.Velocity.Magnitude < 50 then
                Angle += 100
                FPos(BasePart, CFrame.new(0,1.5,0)+THumanoid.MoveDirection*BasePart.Velocity.Magnitude/1.25, CFrame.Angles(math.rad(Angle),0,0)); task.wait()
                FPos(BasePart, CFrame.new(0,-1.5,0)+THumanoid.MoveDirection*BasePart.Velocity.Magnitude/1.25, CFrame.Angles(math.rad(Angle),0,0)); task.wait()
                FPos(BasePart, CFrame.new(2.25,1.5,-2.25)+THumanoid.MoveDirection*BasePart.Velocity.Magnitude/1.25, CFrame.Angles(math.rad(Angle),0,0)); task.wait()
                FPos(BasePart, CFrame.new(-2.25,-1.5,2.25)+THumanoid.MoveDirection*BasePart.Velocity.Magnitude/1.25, CFrame.Angles(math.rad(Angle),0,0)); task.wait()
            else
                FPos(BasePart, CFrame.new(0,1.5,THumanoid.WalkSpeed), CFrame.Angles(math.rad(90),0,0)); task.wait()
                FPos(BasePart, CFrame.new(0,-1.5,-THumanoid.WalkSpeed), CFrame.Angles(0,0,0)); task.wait()
                FPos(BasePart, CFrame.new(0,1.5,TRootPart.Velocity.Magnitude/1.25), CFrame.Angles(math.rad(90),0,0)); task.wait()
                FPos(BasePart, CFrame.new(0,-1.5,-TRootPart.Velocity.Magnitude/1.25), CFrame.Angles(0,0,0)); task.wait()
                FPos(BasePart, CFrame.new(0,-1.5,0), CFrame.Angles(math.rad(-90),0,0)); task.wait()
            end
        until BasePart.Velocity.Magnitude > 500
            or BasePart.Parent ~= TCharacter
            or TargetPlayer.Parent ~= Players
            or THumanoid.Sit
            or Humanoid.Health <= 0
            or tick() > Time + 2
    end

    workspace.FallenPartsDestroyHeight = 0/0
    local BV = Instance.new("BodyVelocity")
    BV.Name = "EpixVel"; BV.Parent = RootPart
    BV.Velocity = Vector3.new(9e8, 9e8, 9e8)
    BV.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
    Humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated, false)

    if TRootPart and THead then
        SFBasePart((TRootPart.CFrame.p - THead.CFrame.p).Magnitude > 5 and THead or TRootPart)
    elseif TRootPart then SFBasePart(TRootPart)
    elseif THead then SFBasePart(THead)
    elseif Handle then SFBasePart(Handle)
    end

    BV:Destroy()
    Humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated, true)
    workspace.CurrentCamera.CameraSubject = Humanoid

    repeat
        RootPart.CFrame = getgenv().OldPos * CFrame.new(0,0.5,0)
        Character:SetPrimaryPartCFrame(getgenv().OldPos * CFrame.new(0,0.5,0))
        Humanoid:ChangeState("GettingUp")
        for _, x in pairs(Character:GetChildren()) do
            if x:IsA("BasePart") then
                x.Velocity = Vector3.new()
                x.RotVelocity = Vector3.new()
            end
        end
        task.wait()
    until (RootPart.Position - getgenv().OldPos.p).Magnitude < 25
    workspace.FallenPartsDestroyHeight = getgenv().FPDH
end

-- Fling single
FlingBtn.MouseButton1Click:Connect(function()
    if isFlingEnabled then return end
    isFlingEnabled = true
    setToggle(FlingBtn, true)
    flingLoop = RunService.Heartbeat:Connect(function()
        if not isFlingEnabled then return end
        local name = UsernameBox.Text
        if name == "" then return end
        local target = getPlayerByName(name)
        if target and target.Character then skidFling(target) end
    end)
end)

UnflingBtn.MouseButton1Click:Connect(function()
    isFlingEnabled = false
    setToggle(FlingBtn, false)
    if flingLoop then flingLoop:Disconnect(); flingLoop = nil end
    local char = LocalPlayer.Character
    if char and getgenv().OldPos then
        local hum = char:FindFirstChildOfClass("Humanoid")
        local root = hum and hum.RootPart
        if root then
            root.CFrame = getgenv().OldPos
            char:SetPrimaryPartCFrame(getgenv().OldPos)
            hum:ChangeState("GettingUp")
        end
    end
end)

-- Fling all
FlingAllBtn.MouseButton1Click:Connect(function()
    isFlingingAll = not isFlingingAll
    setToggle(FlingAllBtn, isFlingingAll)
    if not isFlingingAll then return end

    local function hasFlung(char)
        local h = char:FindFirstChildOfClass("Humanoid")
        return h and h.RootPart and h.RootPart.Velocity.Magnitude > 500
    end

    local function spinFling(target)
        local char = LocalPlayer.Character
        local hum = char and char:FindFirstChildOfClass("Humanoid")
        local root = hum and hum.RootPart
        if not (char and hum and root) then return end
        local tc = target.Character
        if not tc then return end
        local th = tc:FindFirstChildOfClass("Humanoid")
        local tr = th and th.RootPart
        if not tr or (th and th.Sit) then return end

        getgenv().OldPos = root.CFrame
        workspace.FallenPartsDestroyHeight = 0/0

        local BV = Instance.new("BodyVelocity")
        BV.Parent = root
        BV.Velocity = Vector3.new(9e9, 9e9, 9e9)
        BV.MaxForce = Vector3.new(math.huge, math.huge, math.huge)

        workspace.CurrentCamera.CameraSubject = th
        local angle, t = 0, tick()
        repeat
            if not isFlingingAll then break end
            angle += 250
            local pos = Vector3.new(
                tr.Position.X + math.cos(math.rad(angle)),
                tr.Position.Y,
                tr.Position.Z + math.sin(math.rad(angle))
            )
            root.CFrame = CFrame.new(pos) * CFrame.Angles(0, math.rad(angle), 0)
            char:SetPrimaryPartCFrame(root.CFrame)
            root.Velocity = Vector3.new(9e9, 9e9*15, 9e9)
            root.RotVelocity = Vector3.new(0, 9e9, 0)
            task.wait(0.01)
        until hasFlung(tc) or tick() > t + 1.5 or not isFlingingAll

        BV:Destroy()
        if getgenv().OldPos then
            root.CFrame = getgenv().OldPos
            char:SetPrimaryPartCFrame(getgenv().OldPos)
        end
        workspace.FallenPartsDestroyHeight = getgenv().FPDH
    end

    spawn(function()
        while isFlingingAll do
            local char = LocalPlayer.Character
            if char and char:FindFirstChild("Humanoid") and char.Humanoid.Health > 0 then
                for _, p in pairs(Players:GetPlayers()) do
                    if p ~= LocalPlayer and p.Character then
                        spinFling(p)
                        if not isFlingingAll then break end
                    end
                end
            end
            task.wait(0.9)
        end
        local hum = LocalPlayer.Character and LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
        if hum then workspace.CurrentCamera.CameraSubject = hum end
    end)
end)

-- Walk fling (touch-based, no self-modification)
local function startWalkFling(char)
    local Root = char:WaitForChild("HumanoidRootPart")

    if walkFlingConnection then
        walkFlingConnection:Disconnect()
        walkFlingConnection = nil
    end

    walkFlingConnection = Root.Touched:Connect(function(hit)
        if not walkflinging then return end

        local targetChar = hit.Parent
        local targetPlayer = Players:GetPlayerFromCharacter(targetChar)
        if not targetPlayer or targetPlayer == LocalPlayer then return end

        local targetHum = targetChar:FindFirstChildOfClass("Humanoid")
        local targetRoot = targetChar:FindFirstChild("HumanoidRootPart")
        if not targetHum or not targetRoot then return end
        if targetHum.Health <= 0 then return end

        local BV = Instance.new("BodyVelocity")
        BV.Parent = targetRoot
        BV.Velocity = Vector3.new(math.random(-1,1)*9e4, 9e4, math.random(-1,1)*9e4)
        BV.MaxForce = Vector3.new(math.huge, math.huge, math.huge)

        local BRV = Instance.new("BodyAngularVelocity")
        BRV.Parent = targetRoot
        BRV.AngularVelocity = Vector3.new(9e4, 9e4, 9e4)
        BRV.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)

        Debris:AddItem(BV, 0.2)
        Debris:AddItem(BRV, 0.2)
    end)
end

WalkFlingBtn.MouseButton1Click:Connect(function()
    walkflinging = not walkflinging
    setToggle(WalkFlingBtn, walkflinging)
    if walkflinging then
        if LocalPlayer.Character then
            startWalkFling(LocalPlayer.Character)
        end
    else
        if walkFlingConnection then
            walkFlingConnection:Disconnect()
            walkFlingConnection = nil
        end
    end
end)

LocalPlayer.CharacterAdded:Connect(function(char)
    if walkflinging then startWalkFling(char) end
end)

-- No collide
local function restoreCollisions()
    for _, p in pairs(Players:GetPlayers()) do
        if p ~= LocalPlayer and p.Character then
            for _, part in pairs(p.Character:GetDescendants()) do
                if part:IsA("BasePart") then
                    part.CanCollide = true
                    part.CustomPhysicalProperties = PhysicalProperties.new(0.7, 0.3, 0.5)
                end
            end
        end
    end
end

NoCollideBtn.MouseButton1Click:Connect(function()
    noCollideEnabled = not noCollideEnabled
    setToggle(NoCollideBtn, noCollideEnabled)
    if noCollideConnection then noCollideConnection:Disconnect(); noCollideConnection = nil end
    if noCollideEnabled then
        noCollideConnection = RunService.Heartbeat:Connect(function()
            for _, p in pairs(Players:GetPlayers()) do
                if p ~= LocalPlayer and p.Character then
                    for _, part in pairs(p.Character:GetDescendants()) do
                        if part:IsA("BasePart") then
                            part.CanCollide = false
                            part.CustomPhysicalProperties = PhysicalProperties.new(0,0,0,0,0)
                        end
                    end
                end
            end
        end)
    else
        restoreCollisions()
    end
end)

-- Anti-fling
AntiFlingBtn.MouseButton1Click:Connect(function()
    antiFlingEnabled = not antiFlingEnabled
    setToggle(AntiFlingBtn, antiFlingEnabled)
    if antiFlingEnabled then
        loadstring(game:HttpGet("https://[Log in to view URL]"))()
    else
        getgenv().AntiFlingEnabled = false
    end
end)

-- Hug
HugBtn.MouseButton1Click:Connect(function()
    hugEnabled = not hugEnabled
    setToggle(HugBtn, hugEnabled)
    if hugEnabled then
        loadstring(game:HttpGet("https://[Log in to view URL]"))()
    end
end)

-- Chat bypass
ChatBypassBtn.MouseButton1Click:Connect(function()
    bypassEnabled = not bypassEnabled
    setToggle(ChatBypassBtn, bypassEnabled)
    if bypassEnabled then
        loadstring(game:HttpGet("https://[Log in to view URL]"))()
    end
end)

-- Jork
JorkBtn.MouseButton1Click:Connect(function()
    loadstring(game:HttpGet("https://[Log in to view URL]"))()
end)

-- Minimize
local minimized = false
MinimizeBtn.MouseButton1Click:Connect(function()
    minimized = not minimized
    for _, obj in pairs(MainFrame:GetChildren()) do
        if obj ~= TopBar and obj ~= UICorner and obj ~= UIStroke then
            obj.Visible = not minimized
        end
    end
    MainFrame.Size = minimized and UDim2.new(0, 620, 0, 36) or UDim2.new(0, 620, 0, 420)
    MinimizeBtn.Text = minimized and "+" or "—"
end)

-- Full cleanup + close
local function fullCleanup()
    isFlingEnabled = false
    walkflinging = false
    noCollideEnabled = false
    isFlingingAll = false
    hugEnabled = false
    bypassEnabled = false
    antiFlingEnabled = false

    if flingLoop then flingLoop:Disconnect(); flingLoop = nil end
    if noCollideConnection then noCollideConnection:Disconnect(); noCollideConnection = nil end
    if audioConnection then audioConnection:Disconnect(); audioConnection = nil end
    if walkFlingConnection then walkFlingConnection:Disconnect(); walkFlingConnection = nil end

    for sound, _ in pairs(mutedSounds) do
        if sound and sound.Parent then
            local orig = sound:GetAttribute("OriginalVolume")
            if orig then sound.Volume = orig end
        end
    end
    mutedSounds = {}

    workspace.FallenPartsDestroyHeight = getgenv().FPDH
    restoreCollisions()

    local char = LocalPlayer.Character
    if char then
        local hum = char:FindFirstChildOfClass("Humanoid")
        local root = char:FindFirstChild("HumanoidRootPart")
        if hum then
            hum:SetStateEnabled(Enum.HumanoidStateType.Dead, true)
            hum:SetStateEnabled(Enum.HumanoidStateType.Seated, true)
            hum.BreakJointsOnDeath = true
            hum.MaxHealth = 100
            hum.Health = 100
        end
        if root then
            root.CanCollide = true
            local bv = root:FindFirstChild("EpixVel")
            if bv then bv:Destroy() end
        end
    end

    local hum = LocalPlayer.Character and LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
    if hum then workspace.CurrentCamera.CameraSubject = hum end

    getgenv().OldPos = nil
    getgenv().AntiFlingEnabled = false
    getgenv().CurrentGameVolume = nil

    ScreenGui:Destroy()
    print("Troll UI v3 closed.")
end

CloseBtn.MouseButton1Click:Connect(fullCleanup)

print("Troll UI v3 loaded.")

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: