Quick actions

cmd+k|ctrl+k

Navigation

Languages

TP Tool v9

Snippet info

Language

Lua

Visibility

public

Author

panickyhospital950

Created

2026-04-04T03:21:02.349112Z

Updated

2026-04-04T03:21:02.349112Z

--[[
    TP TOOL v9 | Silent AC Bypass + Pixel Font + Pixel Icons + Keybind Menu + Mobile
    
    [T]            = TP to mouse position
    [X]            = Toggle TP on/off
    [P]            = Open player TP menu
    [B]            = Set waypoint
    [N]            = TP to waypoint
    [DELETE]       = Clear waypoint
    [COMMA]        = Open keybind settings
]]

------------------------------------------------------------------------
-- CLEANUP OLD INSTANCE
------------------------------------------------------------------------
pcall(function()
    local pg = game:GetService("Players").LocalPlayer.PlayerGui
    for _, g in pairs(pg:GetChildren()) do
        if g.Name == "TPToolGui_v9" then g:Destroy() end
    end
end)
pcall(function()
    if _G._TPv9Conns then
        for _, c in pairs(_G._TPv9Conns) do
            pcall(function() c:Disconnect() end)
        end
    end
end)
_G._TPv9Conns = {}
local function conn(c) table.insert(_G._TPv9Conns, c) return c end

------------------------------------------------------------------------
-- SERVICES
------------------------------------------------------------------------
local plrs = game:GetService("Players")
local uis  = game:GetService("UserInputService")
local rs   = game:GetService("RunService")
local ts   = game:GetService("TweenService")
local lp   = plrs.LocalPlayer
local mouse = lp:GetMouse()

local char, hmn, hrp
local function grab()
    char = lp.Character
    if not char then return false end
    hmn = char:FindFirstChildOfClass("Humanoid")
    hrp = char:FindFirstChild("HumanoidRootPart")
    return hrp ~= nil and hmn ~= nil
end
grab()
conn(lp.CharacterAdded:Connect(function(c)
    c:WaitForChild("HumanoidRootPart")
    task.wait(0.2)
    grab()
end))

local enabled = true
local waypoint = nil
local playerListOpen = false
local bypassing = false
local settingsOpen = false
local rebinding = nil -- which action is being rebound

------------------------------------------------------------------------
-- KEYBINDS (editable)
------------------------------------------------------------------------
local Keybinds = {
    toggle    = {type = "key", code = Enum.KeyCode.X,      name = "X"},
    players   = {type = "key", code = Enum.KeyCode.P,      name = "P"},
    setWP     = {type = "key", code = Enum.KeyCode.B,      name = "B"},
    goWP      = {type = "key", code = Enum.KeyCode.N,      name = "N"},
    clearWP   = {type = "key", code = Enum.KeyCode.Delete, name = "DEL"},
    teleport  = {type = "key", code = Enum.KeyCode.T, name = "T"},
    settings  = {type = "key", code = Enum.KeyCode.Comma,  name = ","},
}

-- Restore saved keybinds from _G if re-executing
if _G._TPv9Keybinds then
    for k, v in pairs(_G._TPv9Keybinds) do
        if Keybinds[k] then
            Keybinds[k] = v
        end
    end
end

-- Action display names
local ACTION_NAMES = {
    teleport = "TELEPORT",
    toggle   = "TOGGLE",
    players  = "PLAYERS",
    setWP    = "SET WP",
    goWP     = "GO WP",
    clearWP  = "CLR WP",
    settings = "SETTINGS",
}

-- Order for display
local ACTION_ORDER = {"teleport","toggle","players","setWP","goWP","clearWP","settings"}

-- Get friendly name for a key/mouse input
local function GetInputName(inputType, keyCode)
    if inputType == "mouse" then
        if keyCode == Enum.UserInputType.MouseButton1 then return "MB1" end
        if keyCode == Enum.UserInputType.MouseButton2 then return "MB2" end
        if keyCode == Enum.UserInputType.MouseButton3 then return "MB3" end
        return "MOUSE"
    else
        local name = keyCode.Name
        -- Clean up common names
        if name == "LeftShift" then return "LSHIFT" end
        if name == "RightShift" then return "RSHIFT" end
        if name == "LeftControl" then return "LCTRL" end
        if name == "RightControl" then return "RCTRL" end
        if name == "LeftAlt" then return "LALT" end
        if name == "RightAlt" then return "RALT" end
        if name == "Delete" then return "DEL" end
        if name == "Backspace" then return "BKSP" end
        if name == "Return" then return "ENTER" end
        if name == "Escape" then return "ESC" end
        if name == "Space" then return "SPACE" end
        if name == "Comma" then return "," end
        if name == "Period" then return "." end
        if name == "Slash" then return "/" end
        if name == "Semicolon" then return ";" end
        if name == "BackSlash" then return "\\" end
        if name == "Minus" then return "-" end
        if name == "Equals" then return "=" end
        if #name == 4 and name:sub(1,3) == "Key" then return name:sub(4,4) end -- "KeyQ" -> "Q"
        if #name <= 4 then return name:upper() end
        return name:upper():sub(1, 5)
    end
end

------------------------------------------------------------------------
-- COLORS
------------------------------------------------------------------------
local C = {
    bg      = Color3.fromRGB(24, 24, 32),
    panel   = Color3.fromRGB(32, 32, 44),
    inner   = Color3.fromRGB(40, 40, 56),
    border  = Color3.fromRGB(80, 60, 200),
    accent  = Color3.fromRGB(120, 90, 255),
    gold    = Color3.fromRGB(255, 210, 60),
    green   = Color3.fromRGB(50, 255, 120),
    red     = Color3.fromRGB(255, 70, 70),
    purple  = Color3.fromRGB(180, 100, 255),
    yellow  = Color3.fromRGB(255, 240, 80),
    gray    = Color3.fromRGB(160, 160, 180),
    dimgray = Color3.fromRGB(100, 100, 120),
    white   = Color3.fromRGB(230, 230, 240),
    btn     = Color3.fromRGB(45, 45, 62),
    btnhov  = Color3.fromRGB(65, 55, 100),
    btnact  = Color3.fromRGB(90, 50, 150),
    flash   = Color3.fromRGB(120, 80, 255),
    orange  = Color3.fromRGB(255, 170, 50),
}

------------------------------------------------------------------------
-- PIXEL FONT
------------------------------------------------------------------------
local PX = 2
local CW = 5
local CH = 7
local SP = 1

local GLYPHS = {
    A={"01110","10001","10001","11111","10001","10001","10001"},
    B={"11110","10001","10001","11110","10001","10001","11110"},
    C={"01110","10001","10000","10000","10000","10001","01110"},
    D={"11100","10010","10001","10001","10001","10010","11100"},
    E={"11111","10000","10000","11110","10000","10000","11111"},
    F={"11111","10000","10000","11110","10000","10000","10000"},
    G={"01110","10001","10000","10111","10001","10001","01110"},
    H={"10001","10001","10001","11111","10001","10001","10001"},
    I={"11111","00100","00100","00100","00100","00100","11111"},
    J={"00111","00010","00010","00010","00010","10010","01100"},
    K={"10001","10010","10100","11000","10100","10010","10001"},
    L={"10000","10000","10000","10000","10000","10000","11111"},
    M={"10001","11011","10101","10101","10001","10001","10001"},
    N={"10001","11001","10101","10011","10001","10001","10001"},
    O={"01110","10001","10001","10001","10001","10001","01110"},
    P={"11110","10001","10001","11110","10000","10000","10000"},
    Q={"01110","10001","10001","10001","10101","10010","01101"},
    R={"11110","10001","10001","11110","10100","10010","10001"},
    S={"01111","10000","10000","01110","00001","00001","11110"},
    T={"11111","00100","00100","00100","00100","00100","00100"},
    U={"10001","10001","10001","10001","10001","10001","01110"},
    V={"10001","10001","10001","10001","01010","01010","00100"},
    W={"10001","10001","10001","10101","10101","11011","10001"},
    X={"10001","10001","01010","00100","01010","10001","10001"},
    Y={"10001","10001","01010","00100","00100","00100","00100"},
    Z={"11111","00001","00010","00100","01000","10000","11111"},
    ["0"]={"01110","10011","10101","10101","10101","11001","01110"},
    ["1"]={"00100","01100","00100","00100","00100","00100","01110"},
    ["2"]={"01110","10001","00001","00110","01000","10000","11111"},
    ["3"]={"01110","10001","00001","00110","00001","10001","01110"},
    ["4"]={"00010","00110","01010","10010","11111","00010","00010"},
    ["5"]={"11111","10000","11110","00001","00001","10001","01110"},
    ["6"]={"00110","01000","10000","11110","10001","10001","01110"},
    ["7"]={"11111","00001","00010","00100","01000","01000","01000"},
    ["8"]={"01110","10001","10001","01110","10001","10001","01110"},
    ["9"]={"01110","10001","10001","01111","00001","00010","01100"},
    [":"]={"00000","00100","00100","00000","00100","00100","00000"},
    [","]={"00000","00000","00000","00000","00000","00100","01000"},
    ["-"]={"00000","00000","00000","11111","00000","00000","00000"},
    ["."]={"00000","00000","00000","00000","00000","00000","00100"},
    ["!"]={"00100","00100","00100","00100","00100","00000","00100"},
    ["?"]={"01110","10001","00001","00110","00100","00000","00100"},
    ["="]={"00000","00000","11111","00000","11111","00000","00000"},
    ["+"]={"00000","00100","00100","11111","00100","00100","00000"},
    ["/"]={"00001","00010","00010","00100","01000","01000","10000"},
    ["("]={"00010","00100","01000","01000","01000","00100","00010"},
    [")"]={"01000","00100","00010","00010","00010","00100","01000"},
    ["["]={"01110","01000","01000","01000","01000","01000","01110"},
    ["]"]={"01110","00010","00010","00010","00010","00010","01110"},
    [">"]={"10000","01000","00100","00010","00100","01000","10000"},
    ["<"]={"00010","00100","01000","10000","01000","00100","00010"},
    ["|"]={"00100","00100","00100","00100","00100","00100","00100"},
    ["@"]={"01110","10001","10101","10111","10000","10001","01110"},
    [" "]={"00000","00000","00000","00000","00000","00000","00000"},
    ["\\"]={"10000","01000","01000","00100","00010","00010","00001"},
    [";"]={"00000","00100","00100","00000","00100","00100","01000"},
}

local function RenderPixelText(parent, text, color, scale)
    scale = scale or 1
    local ps = PX * scale
    local container = Instance.new("Frame")
    container.BackgroundTransparency = 1
    container.BorderSizePixel = 0
    container.Parent = parent
    container:SetAttribute("_txt", text)
    container:SetAttribute("_col", tostring(color))
    local totalW = 0
    local up = string.upper(text)
    for i = 1, #up do
        local ch = up:sub(i, i)
        local g = GLYPHS[ch]
        if not g then
            totalW = totalW + (CW + SP) * ps
        else
            for row = 1, CH do
                local rd = g[row]
                if rd then
                    for col = 1, CW do
                        if rd:sub(col, col) == "1" then
                            local px = Instance.new("Frame")
                            px.Size = UDim2.new(0, ps, 0, ps)
                            px.Position = UDim2.new(0, totalW + (col-1)*ps, 0, (row-1)*ps)
                            px.BackgroundColor3 = color
                            px.BorderSizePixel = 0
                            px.Parent = container
                        end
                    end
                end
            end
            totalW = totalW + (CW + SP) * ps
        end
    end
    container.Size = UDim2.new(0, totalW, 0, CH * ps)
    return container
end

local function UpdatePixelText(container, text, color, scale)
    local oldTxt = container:GetAttribute("_txt")
    local oldCol = container:GetAttribute("_col")
    local newCol = tostring(color)
    if oldTxt == text and oldCol == newCol then return end
    for _, c in pairs(container:GetChildren()) do
        if c:IsA("Frame") then c:Destroy() end
    end
    container:SetAttribute("_txt", text)
    container:SetAttribute("_col", newCol)
    scale = scale or 1
    local ps = PX * scale
    local totalW = 0
    local up = string.upper(text)
    for i = 1, #up do
        local ch = up:sub(i, i)
        local g = GLYPHS[ch]
        if not g then
            totalW = totalW + (CW + SP) * ps
        else
            for row = 1, CH do
                local rd = g[row]
                if rd then
                    for col = 1, CW do
                        if rd:sub(col, col) == "1" then
                            local px = Instance.new("Frame")
                            px.Size = UDim2.new(0, ps, 0, ps)
                            px.Position = UDim2.new(0, totalW + (col-1)*ps, 0, (row-1)*ps)
                            px.BackgroundColor3 = color
                            px.BorderSizePixel = 0
                            px.Parent = container
                        end
                    end
                end
            end
            totalW = totalW + (CW + SP) * ps
        end
    end
    container.Size = UDim2.new(0, totalW, 0, CH * ps)
end

------------------------------------------------------------------------
-- PIXEL ICONS (7x7)
------------------------------------------------------------------------
local ICON_DATA = {
    crosshair = {
        "0010100","0000000","1000001","0000000","1000001","0000000","0010100",
    },
    shield = {
        "0111110","1111111","1111111","1111111","0111110","0011100","0001000",
    },
    toggle = {
        "0001000","0001000","0110110","1000001","1000001","1000001","0111110",
    },
    flag = {
        "1111100","1111100","1111100","1000000","1000000","1000000","1000000",
    },
    people = {
        "0100010","1110111","0100010","0100010","0000000","0000000","0000000",
    },
    star = {
        "0001000","0001000","0111110","1111111","0111110","0010100","0100010",
    },
    arrow = {
        "0001000","0011100","0101010","1001001","0001000","0001000","0001000",
    },
    gear = {
        "0101010","1110111","0100010","1100011","0100010","1110111","0101010",
    },
}

local function BuildPixelIcon(parent, iconName, size, pos, color)
    local data = ICON_DATA[iconName]
    if not data then return nil end
    local frame = Instance.new("Frame")
    frame.Size = size or UDim2.new(0, 14, 0, 14)
    frame.Position = pos or UDim2.new(0, 0, 0, 0)
    frame.BackgroundTransparency = 1
    frame.BorderSizePixel = 0
    frame.Parent = parent
    local ipx = 2
    for row = 1, 7 do
        local rd = data[row]
        if rd then
            for col = 1, 7 do
                if rd:sub(col, col) == "1" then
                    local px = Instance.new("Frame")
                    px.Size = UDim2.new(0, ipx, 0, ipx)
                    px.Position = UDim2.new(0, (col-1)*ipx, 0, (row-1)*ipx)
                    px.BackgroundColor3 = color or C.white
                    px.BorderSizePixel = 0
                    px.Parent = frame
                end
            end
        end
    end
    return frame
end

local function RecolorIcon(iconFrame, color)
    if not iconFrame then return end
    for _, px in pairs(iconFrame:GetChildren()) do
        if px:IsA("Frame") then px.BackgroundColor3 = color end
    end
end

------------------------------------------------------------------------
-- ANTICHEAT BYPASS
------------------------------------------------------------------------
local AC = {}
AC.noclipParts = {}
AC.origWS = 16
AC.origJP = 50

function AC.enableNoclip()
    if not grab() then return end
    AC.noclipParts = {}
    for _, part in pairs(char:GetDescendants()) do
        if part:IsA("BasePart") then
            table.insert(AC.noclipParts, {part = part, cc = part.CanCollide})
            part.CanCollide = false
        end
    end
end

function AC.disableNoclip()
    for _, data in pairs(AC.noclipParts) do
        pcall(function() data.part.CanCollide = data.cc end)
    end
    AC.noclipParts = {}
end

function AC.zeroVelocity()
    if not grab() then return end
    pcall(function()
        hrp.Velocity = Vector3.new(0, 0, 0)
        hrp.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
        hrp.AssemblyAngularVelocity = Vector3.new(0, 0, 0)
    end)
end

function AC.silentTP(targetPos)
    if not grab() then return end
    local startPos = hrp.Position
    local diff = targetPos - startPos
    local dist = diff.Magnitude
    if dist < 60 then
        hrp.CFrame = CFrame.new(targetPos)
        AC.zeroVelocity()
        return
    end
    local stepSize = 50
    local steps = math.ceil(dist / stepSize)
    local dir = diff.Unit
    AC.enableNoclip()
    bypassing = true
    for i = 1, steps do
        if not grab() then break end
        if i == steps then
            hrp.CFrame = CFrame.new(targetPos)
        else
            hrp.CFrame = CFrame.new(startPos + dir * (stepSize * i))
        end
        AC.zeroVelocity()
        rs.RenderStepped:Wait()
    end
    bypassing = false
    AC.disableNoclip()
    AC.zeroVelocity()
end

function AC.spoofHumanoid()
    if not grab() or not hmn then return end
    pcall(function()
        AC.origWS = hmn.WalkSpeed
        AC.origJP = hmn.JumpPower
    end)
end

function AC.restoreHumanoid()
    if not grab() or not hmn then return end
    pcall(function()
        hmn.WalkSpeed = AC.origWS
        hmn.JumpPower = AC.origJP
    end)
end

------------------------------------------------------------------------
-- DRAGGABLE
------------------------------------------------------------------------
local function MakeDraggable(frame, handle)
    handle = handle or frame
    local dragging = false
    local dragStart, startPos
    conn(handle.InputBegan:Connect(function(input)
        if input.UserInputType == Enum.UserInputType.MouseButton1 or
           input.UserInputType == Enum.UserInputType.Touch then
            dragging = true
            dragStart = input.Position
            startPos = frame.Position
            input.Changed:Connect(function()
                if input.UserInputState == Enum.UserInputState.End then
                    dragging = false
                end
            end)
        end
    end))
    conn(uis.InputChanged:Connect(function(input)
        if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or
                         input.UserInputType == Enum.UserInputType.Touch) then
            local delta = input.Position - dragStart
            frame.Position = UDim2.new(
                startPos.X.Scale, startPos.X.Offset + delta.X,
                startPos.Y.Scale, startPos.Y.Offset + delta.Y
            )
        end
    end))
end

------------------------------------------------------------------------
-- GUI
------------------------------------------------------------------------
local gui = Instance.new("ScreenGui")
gui.Name = "TPToolGui_v9"
gui.ResetOnSpawn = false
gui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
gui.Parent = lp.PlayerGui

-- Main panel
local panel = Instance.new("Frame")
panel.Size = UDim2.new(0, 370, 0, 160)
panel.Position = UDim2.new(0.5, -185, 1, -180)
panel.BackgroundColor3 = C.panel
panel.BorderSizePixel = 0
panel.Parent = gui
Instance.new("UICorner", panel).CornerRadius = UDim.new(0, 8)
local ps1 = Instance.new("UIStroke", panel)
ps1.Thickness = 2
ps1.Color = C.border
ps1.Transparency = 0.3

-- Title bar
local titleBar = Instance.new("Frame")
titleBar.Size = UDim2.new(1, 0, 0, 26)
titleBar.BackgroundColor3 = C.bg
titleBar.BackgroundTransparency = 0.2
titleBar.BorderSizePixel = 0
titleBar.Parent = panel
Instance.new("UICorner", titleBar).CornerRadius = UDim.new(0, 8)
local tbFix = Instance.new("Frame")
tbFix.Size = UDim2.new(1, 0, 0, 8)
tbFix.Position = UDim2.new(0, 0, 1, -8)
tbFix.BackgroundColor3 = C.bg
tbFix.BackgroundTransparency = 0.2
tbFix.BorderSizePixel = 0
tbFix.Parent = titleBar
MakeDraggable(panel, titleBar)

BuildPixelIcon(titleBar, "star", UDim2.new(0, 14, 0, 14), UDim2.new(0, 8, 0, 6), C.gold)
local titleTC = Instance.new("Frame")
titleTC.Size = UDim2.new(0, 200, 0, 14)
titleTC.Position = UDim2.new(0, 28, 0, 6)
titleTC.BackgroundTransparency = 1
titleTC.Parent = titleBar
RenderPixelText(titleTC, "TP TOOL V8", C.gold, 1)

-- AC badge
local acBadge = Instance.new("Frame")
acBadge.Size = UDim2.new(0, 80, 0, 16)
acBadge.Position = UDim2.new(1, -88, 0, 5)
acBadge.BackgroundColor3 = C.green
acBadge.BackgroundTransparency = 0.85
acBadge.BorderSizePixel = 0
acBadge.Parent = titleBar
Instance.new("UICorner", acBadge).CornerRadius = UDim.new(0, 4)
BuildPixelIcon(acBadge, "shield", UDim2.new(0, 14, 0, 14), UDim2.new(0, 3, 0, 1), C.green)
local acBTC = Instance.new("Frame")
acBTC.Size = UDim2.new(0, 55, 0, 14)
acBTC.Position = UDim2.new(0, 18, 0, 1)
acBTC.BackgroundTransparency = 1
acBTC.Parent = acBadge
RenderPixelText(acBTC, "SILENT", C.green, 1)

-- Content
local content = Instance.new("Frame")
content.Size = UDim2.new(1, -12, 1, -34)
content.Position = UDim2.new(0, 6, 0, 30)
content.BackgroundColor3 = C.inner
content.BackgroundTransparency = 0.5
content.BorderSizePixel = 0
content.Parent = panel
Instance.new("UICorner", content).CornerRadius = UDim.new(0, 6)

-- Helper to build a row
local function MakeRow(parent, yOff, iconName, iconColor)
    local r = Instance.new("Frame")
    r.Size = UDim2.new(1, -12, 0, 18)
    r.Position = UDim2.new(0, 6, 0, yOff)
    r.BackgroundTransparency = 1
    r.Parent = parent
    local icon = BuildPixelIcon(r, iconName, UDim2.new(0, 14, 0, 14), UDim2.new(0, 0, 0, 2), iconColor)
    local tc = Instance.new("Frame")
    tc.Size = UDim2.new(0, 330, 0, 14)
    tc.Position = UDim2.new(0, 18, 0, 2)
    tc.BackgroundTransparency = 1
    tc.Parent = r
    return r, icon, tc
end

local r1, statusIconF, statusC = MakeRow(content, 6, "toggle", C.green)
local statusText = RenderPixelText(statusC, "TP ON  T=TP  X=TOG", C.green, 1)

local r2, _, coordsC = MakeRow(content, 28, "arrow", C.gray)
local coordsText = RenderPixelText(coordsC, "POS 0 0 0", C.gray, 1)

local r3, targetIconF, targetC = MakeRow(content, 50, "crosshair", C.yellow)
local targetText = RenderPixelText(targetC, "TARGET ...", C.yellow, 1)

local r4, wpIconF, wpC = MakeRow(content, 72, "flag", C.dimgray)
local wpText = RenderPixelText(wpC, "WP NONE B=SET N=GO", C.dimgray, 1)

local r5, acIconF, acC = MakeRow(content, 94, "shield", C.accent)
local acText = RenderPixelText(acC, "AC ACTIVE  ,=BINDS", C.accent, 1)

------------------------------------------------------------------------
-- CROSSHAIR
------------------------------------------------------------------------
local crossFrame = Instance.new("Frame")
crossFrame.Size = UDim2.new(0, 14, 0, 14)
crossFrame.Position = UDim2.new(0.5, -7, 0.5, -7)
crossFrame.BackgroundTransparency = 1
crossFrame.Parent = gui
for _, pos in pairs({
    {6,0},{6,2},{6,4},{6,10},{6,12},
    {0,6},{2,6},{4,6},{10,6},{12,6},
}) do
    local px = Instance.new("Frame")
    px.Size = UDim2.new(0, 2, 0, 2)
    px.Position = UDim2.new(0, pos[1], 0, pos[2])
    px.BackgroundColor3 = C.purple
    px.BorderSizePixel = 0
    px.Parent = crossFrame
end
local cDot = Instance.new("Frame")
cDot.Size = UDim2.new(0, 2, 0, 2)
cDot.Position = UDim2.new(0, 6, 0, 6)
cDot.BackgroundColor3 = C.accent
cDot.BorderSizePixel = 0
cDot.Parent = crossFrame

-- Flash
local flash = Instance.new("Frame")
flash.Size = UDim2.new(1, 0, 1, 0)
flash.BackgroundColor3 = C.flash
flash.BackgroundTransparency = 1
flash.BorderSizePixel = 0
flash.ZIndex = 10
flash.Parent = gui

------------------------------------------------------------------------
-- KEYBIND SETTINGS PANEL
------------------------------------------------------------------------
local settingsPanel = Instance.new("Frame")
settingsPanel.Size = UDim2.new(0, 260, 0, 230)
settingsPanel.Position = UDim2.new(1, -275, 0.5, -115)
settingsPanel.BackgroundColor3 = C.panel
settingsPanel.BorderSizePixel = 0
settingsPanel.Visible = false
settingsPanel.ZIndex = 5
settingsPanel.Parent = gui
Instance.new("UICorner", settingsPanel).CornerRadius = UDim.new(0, 8)
local ss1 = Instance.new("UIStroke", settingsPanel)
ss1.Thickness = 2
ss1.Color = C.orange
ss1.Transparency = 0.3

-- Settings title bar
local sTB = Instance.new("Frame")
sTB.Size = UDim2.new(1, 0, 0, 26)
sTB.BackgroundColor3 = C.bg
sTB.BackgroundTransparency = 0.2
sTB.BorderSizePixel = 0
sTB.ZIndex = 5
sTB.Parent = settingsPanel
Instance.new("UICorner", sTB).CornerRadius = UDim.new(0, 8)
local sTBFix = Instance.new("Frame")
sTBFix.Size = UDim2.new(1, 0, 0, 8)
sTBFix.Position = UDim2.new(0, 0, 1, -8)
sTBFix.BackgroundColor3 = C.bg
sTBFix.BackgroundTransparency = 0.2
sTBFix.BorderSizePixel = 0
sTBFix.ZIndex = 5
sTBFix.Parent = sTB
MakeDraggable(settingsPanel, sTB)

BuildPixelIcon(sTB, "gear", UDim2.new(0, 14, 0, 14), UDim2.new(0, 8, 0, 6), C.orange).ZIndex = 6
local sTitleC = Instance.new("Frame")
sTitleC.Size = UDim2.new(0, 150, 0, 14)
sTitleC.Position = UDim2.new(0, 28, 0, 6)
sTitleC.BackgroundTransparency = 1
sTitleC.ZIndex = 5
sTitleC.Parent = sTB
RenderPixelText(sTitleC, "KEYBINDS", C.orange, 1)

-- Settings content
local sContent = Instance.new("Frame")
sContent.Size = UDim2.new(1, -12, 1, -34)
sContent.Position = UDim2.new(0, 6, 0, 30)
sContent.BackgroundColor3 = C.inner
sContent.BackgroundTransparency = 0.5
sContent.BorderSizePixel = 0
sContent.ZIndex = 5
sContent.Parent = settingsPanel
Instance.new("UICorner", sContent).CornerRadius = UDim.new(0, 6)

-- Hint text
local hintC = Instance.new("Frame")
hintC.Size = UDim2.new(0, 230, 0, 14)
hintC.Position = UDim2.new(0, 6, 1, -20)
hintC.BackgroundTransparency = 1
hintC.ZIndex = 5
hintC.Parent = sContent
RenderPixelText(hintC, "CLICK TO REBIND", C.dimgray, 1)

-- Build keybind rows
local bindButtons = {} -- action -> {btn, labelC}
local yPos = 4

for _, action in pairs(ACTION_ORDER) do
    local row = Instance.new("Frame")
    row.Size = UDim2.new(1, -12, 0, 22)
    row.Position = UDim2.new(0, 6, 0, yPos)
    row.BackgroundTransparency = 1
    row.ZIndex = 5
    row.Parent = sContent

    -- Action name
    local nameC = Instance.new("Frame")
    nameC.Size = UDim2.new(0, 100, 0, 14)
    nameC.Position = UDim2.new(0, 0, 0, 4)
    nameC.BackgroundTransparency = 1
    nameC.ZIndex = 5
    nameC.Parent = row
    RenderPixelText(nameC, ACTION_NAMES[action], C.gray, 1)

    -- Bind button
    local btn = Instance.new("TextButton")
    btn.Size = UDim2.new(0, 90, 0, 20)
    btn.Position = UDim2.new(1, -94, 0, 1)
    btn.BackgroundColor3 = C.btn
    btn.BorderSizePixel = 0
    btn.Text = ""
    btn.AutoButtonColor = false
    btn.ZIndex = 6
    btn.Parent = row
    Instance.new("UICorner", btn).CornerRadius = UDim.new(0, 4)
    local btnStroke = Instance.new("UIStroke", btn)
    btnStroke.Color = C.border
    btnStroke.Transparency = 0.5

    -- Key label inside button
    local keyC = Instance.new("Frame")
    keyC.Size = UDim2.new(0, 80, 0, 14)
    keyC.Position = UDim2.new(0.5, -40, 0.5, -7)
    keyC.BackgroundTransparency = 1
    keyC.ZIndex = 7
    keyC.Parent = btn
    RenderPixelText(keyC, Keybinds[action].name, C.white, 1)

    btn.MouseEnter:Connect(function()
        if rebinding ~= action then
            btn.BackgroundColor3 = C.btnhov
        end
    end)
    btn.MouseLeave:Connect(function()
        if rebinding ~= action then
            btn.BackgroundColor3 = C.btn
        end
    end)
    btn.MouseButton1Click:Connect(function()
        -- Start rebinding this action
        if rebinding then
            -- Cancel previous rebind
            local prev = bindButtons[rebinding]
            if prev then
                prev.btn.BackgroundColor3 = C.btn
                UpdatePixelText(prev.keyC, Keybinds[rebinding].name, C.white, 1)
            end
        end
        rebinding = action
        btn.BackgroundColor3 = C.btnact
        UpdatePixelText(keyC, "...", C.orange, 1)
    end)

    bindButtons[action] = {btn = btn, keyC = keyC}
    yPos = yPos + 25
end

-- Function to update status text with current keybinds
local function refreshStatusText()
    local tpKey = Keybinds.teleport.name
    local togKey = Keybinds.toggle.name
    if enabled then
        UpdatePixelText(statusC, "TP ON " .. tpKey .. "=TP " .. togKey .. "=TOG", C.green, 1)
    else
        UpdatePixelText(statusC, "TP OFF " .. tpKey .. "=TP " .. togKey .. "=TOG", C.red, 1)
    end

    local wpKey = Keybinds.setWP.name
    local goKey = Keybinds.goWP.name
    if waypoint then
        local w = waypoint
        UpdatePixelText(wpC, string.format("WP %d %d %d %s=GO", math.floor(w.X), math.floor(w.Y), math.floor(w.Z), goKey), C.green, 1)
    else
        UpdatePixelText(wpC, "WP NONE " .. wpKey .. "=SET " .. goKey .. "=GO", C.dimgray, 1)
    end

    local setKey = Keybinds.settings.name
    UpdatePixelText(acC, "AC ACTIVE " .. setKey .. "=BINDS", C.accent, 1)
end

------------------------------------------------------------------------
-- PLAYER LIST
------------------------------------------------------------------------
local plrPanel = Instance.new("Frame")
plrPanel.Size = UDim2.new(0, 220, 0, 220)
plrPanel.Position = UDim2.new(0, 12, 0.5, -110)
plrPanel.BackgroundColor3 = C.panel
plrPanel.BorderSizePixel = 0
plrPanel.Visible = false
plrPanel.Parent = gui
Instance.new("UICorner", plrPanel).CornerRadius = UDim.new(0, 8)
local pls1 = Instance.new("UIStroke", plrPanel)
pls1.Thickness = 2
pls1.Color = C.border
pls1.Transparency = 0.3

local plrTB = Instance.new("Frame")
plrTB.Size = UDim2.new(1, 0, 0, 24)
plrTB.BackgroundColor3 = C.bg
plrTB.BackgroundTransparency = 0.2
plrTB.BorderSizePixel = 0
plrTB.Parent = plrPanel
Instance.new("UICorner", plrTB).CornerRadius = UDim.new(0, 8)
MakeDraggable(plrPanel, plrTB)

BuildPixelIcon(plrTB, "people", UDim2.new(0, 14, 0, 14), UDim2.new(0, 6, 0, 5), C.purple)
local plrTitleC = Instance.new("Frame")
plrTitleC.Size = UDim2.new(0, 120, 0, 14)
plrTitleC.Position = UDim2.new(0, 24, 0, 5)
plrTitleC.BackgroundTransparency = 1
plrTitleC.Parent = plrTB
RenderPixelText(plrTitleC, "PLAYERS", C.purple, 1)

local plrScroll = Instance.new("ScrollingFrame")
plrScroll.Size = UDim2.new(1, -12, 1, -32)
plrScroll.Position = UDim2.new(0, 6, 0, 28)
plrScroll.BackgroundColor3 = C.inner
plrScroll.BackgroundTransparency = 0.5
plrScroll.BorderSizePixel = 0
plrScroll.ScrollBarThickness = 3
plrScroll.ScrollBarImageColor3 = C.accent
plrScroll.CanvasSize = UDim2.new(0, 0, 0, 0)
plrScroll.Parent = plrPanel
Instance.new("UICorner", plrScroll).CornerRadius = UDim.new(0, 6)
local plrLayout = Instance.new("UIListLayout", plrScroll)
plrLayout.Padding = UDim.new(0, 3)
plrLayout.SortOrder = Enum.SortOrder.LayoutOrder

local function refreshPlrList()
    for _, c in pairs(plrScroll:GetChildren()) do
        if c:IsA("TextButton") then c:Destroy() end
    end
    local count = 0
    for _, p in pairs(plrs:GetPlayers()) do
        if p ~= lp then
            count = count + 1
            local btn = Instance.new("TextButton")
            btn.Size = UDim2.new(1, -6, 0, 22)
            btn.BackgroundColor3 = C.btn
            btn.BorderSizePixel = 0
            btn.AutoButtonColor = false
            btn.Text = ""
            btn.Parent = plrScroll
            Instance.new("UICorner", btn).CornerRadius = UDim.new(0, 4)
            BuildPixelIcon(btn, "people", UDim2.new(0, 14, 0, 14), UDim2.new(0, 4, 0, 4), C.gray)
            local nc = Instance.new("Frame")
            nc.Size = UDim2.new(0, 160, 0, 14)
            nc.Position = UDim2.new(0, 22, 0, 4)
            nc.BackgroundTransparency = 1
            nc.Parent = btn
            RenderPixelText(nc, p.DisplayName, C.white, 1)
            btn.MouseEnter:Connect(function() btn.BackgroundColor3 = C.btnhov end)
            btn.MouseLeave:Connect(function() btn.BackgroundColor3 = C.btn end)
            btn.MouseButton1Click:Connect(function()
                if not grab() then return end
                local tc = p.Character
                if tc and tc:FindFirstChild("HumanoidRootPart") then
                    doTP(tc.HumanoidRootPart.Position + Vector3.new(0, 3, 0))
                end
            end)
        end
    end
    plrScroll.CanvasSize = UDim2.new(0, 0, 0, count * 25)
end

------------------------------------------------------------------------
-- TP FUNCTION
------------------------------------------------------------------------
function doTP(pos)
    if not grab() then return end
    flash.BackgroundTransparency = 0.35
    ts:Create(flash, TweenInfo.new(0.4, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
        BackgroundTransparency = 1
    }):Play()
    AC.spoofHumanoid()
    AC.silentTP(pos + Vector3.new(0, 0.5, 0))
    AC.restoreHumanoid()
    UpdatePixelText(acC, "AC CLEAN", C.green, 1)
    RecolorIcon(acIconF, C.green)
    task.delay(2, function()
        refreshStatusText()
        RecolorIcon(acIconF, C.accent)
    end)
end

------------------------------------------------------------------------
-- INPUT HANDLING (with rebind support)
------------------------------------------------------------------------
local function checkBind(action, inputObj)
    local bind = Keybinds[action]
    if not bind or bind.type == "none" then return false end
    if bind.type == "key" then
        return inputObj.KeyCode == bind.code
    elseif bind.type == "mouse" then
        return inputObj.UserInputType == bind.code
    end
    return false
end

conn(uis.InputBegan:Connect(function(inp, gpe)
    -- REBIND MODE: capture next input
    if rebinding then
        local action = rebinding
        local bd = bindButtons[action]
        
        -- Determine if key or mouse
        if inp.UserInputType == Enum.UserInputType.Keyboard then
            local name = GetInputName("key", inp.KeyCode)
            Keybinds[action] = {type = "key", code = inp.KeyCode, name = name}
        elseif inp.UserInputType == Enum.UserInputType.MouseButton1 then
            -- MB1 click on button starts rebind, don't bind MB1
            -- Only bind if not clicking inside settings panel
            return
        elseif inp.UserInputType == Enum.UserInputType.MouseButton2 then
            -- MB2 reserved for camera rotation, skip
            return
        elseif inp.UserInputType == Enum.UserInputType.MouseButton3 then
            Keybinds[action] = {type = "mouse", code = Enum.UserInputType.MouseButton3, name = "MB3"}
        else
            return
        end
        
        -- Remove this key from any OTHER action (exclusive keybinds)
        local newBind = Keybinds[action]
        for _, otherAction in pairs(ACTION_ORDER) do
            if otherAction ~= action then
                local ob = Keybinds[otherAction]
                if ob.type == newBind.type and ob.code == newBind.code then
                    Keybinds[otherAction] = {type = "none", code = nil, name = "---"}
                    local oBd = bindButtons[otherAction]
                    if oBd then
                        UpdatePixelText(oBd.keyC, "---", C.red, 1)
                    end
                end
            end
        end
        
        -- Update button display
        UpdatePixelText(bd.keyC, Keybinds[action].name, C.white, 1)
        bd.btn.BackgroundColor3 = C.btn
        rebinding = nil
        
        -- Save to _G for persistence across re-executes
        _G._TPv9Keybinds = Keybinds
        
        -- Refresh status text to show new keybinds
        refreshStatusText()
        return
    end
    
    if gpe then return end
    
    -- Toggle
    if checkBind("toggle", inp) then
        enabled = not enabled
        if enabled then
            RecolorIcon(statusIconF, C.green)
        else
            RecolorIcon(statusIconF, C.red)
        end
        refreshStatusText()
    end
    
    -- Players
    if checkBind("players", inp) then
        playerListOpen = not playerListOpen
        plrPanel.Visible = playerListOpen
        if playerListOpen then refreshPlrList() end
    end
    
    -- Set waypoint
    if checkBind("setWP", inp) then
        if grab() then
            waypoint = hrp.Position
            RecolorIcon(wpIconF, C.green)
            refreshStatusText()
        end
    end
    
    -- Go waypoint
    if checkBind("goWP", inp) then
        if waypoint then doTP(waypoint) end
    end
    
    -- Clear waypoint
    if checkBind("clearWP", inp) then
        waypoint = nil
        RecolorIcon(wpIconF, C.dimgray)
        refreshStatusText()
    end
    
    -- Settings
    if checkBind("settings", inp) then
        settingsOpen = not settingsOpen
        settingsPanel.Visible = settingsOpen
        if not settingsOpen and rebinding then
            -- Cancel any active rebind
            local bd = bindButtons[rebinding]
            if bd then
                bd.btn.BackgroundColor3 = C.btn
                UpdatePixelText(bd.keyC, Keybinds[rebinding].name, C.white, 1)
            end
            rebinding = nil
        end
    end
    
    -- Teleport (mouse buttons handled here too)
    if checkBind("teleport", inp) then
        if enabled then
            local hit = mouse.Hit
            if hit then
                doTP(hit.Position)
                local p = hit.Position
                UpdatePixelText(targetC, string.format("TP! %d %d %d", math.floor(p.X), math.floor(p.Y), math.floor(p.Z)), C.purple, 1)
                RecolorIcon(targetIconF, C.purple)
            end
        end
    end
end))

-- Mouse button handlers removed (InputBegan handles all binds exclusively)

------------------------------------------------------------------------
-- MOBILE SUPPORT
------------------------------------------------------------------------
local isMobile = uis.TouchEnabled and not uis.KeyboardEnabled

if isMobile then
    -- Mobile button bar at bottom-left
    local mobileBar = Instance.new("Frame")
    mobileBar.Size = UDim2.new(0, 320, 0, 52)
    mobileBar.Position = UDim2.new(0, 10, 1, -65)
    mobileBar.BackgroundColor3 = C.bg
    mobileBar.BackgroundTransparency = 0.3
    mobileBar.BorderSizePixel = 0
    mobileBar.Parent = gui
    Instance.new("UICorner", mobileBar).CornerRadius = UDim.new(0, 8)
    Instance.new("UIStroke", mobileBar).Color = C.border

    local mButtons = {
        {label = "TP", icon = "crosshair", color = C.purple, action = "teleport_touch"},
        {label = "TOG", icon = "toggle", color = C.green, action = "toggle"},
        {label = "PLR", icon = "people", color = C.accent, action = "players"},
        {label = "WP+", icon = "flag", color = C.orange, action = "setWP"},
        {label = "GO", icon = "arrow", color = C.yellow, action = "goWP"},
        {label = "SET", icon = "gear", color = C.gray, action = "settings"},
    }

    for idx, info in pairs(mButtons) do
        local btn = Instance.new("TextButton")
        btn.Size = UDim2.new(0, 48, 0, 44)
        btn.Position = UDim2.new(0, 6 + (idx - 1) * 52, 0, 4)
        btn.BackgroundColor3 = C.btn
        btn.BorderSizePixel = 0
        btn.Text = ""
        btn.AutoButtonColor = false
        btn.ZIndex = 8
        btn.Parent = mobileBar
        Instance.new("UICorner", btn).CornerRadius = UDim.new(0, 6)

        BuildPixelIcon(btn, info.icon, UDim2.new(0, 14, 0, 14), UDim2.new(0.5, -7, 0, 3), info.color).ZIndex = 9
        local lc = Instance.new("Frame")
        lc.Size = UDim2.new(0, 40, 0, 14)
        lc.Position = UDim2.new(0.5, -20, 0, 22)
        lc.BackgroundTransparency = 1
        lc.ZIndex = 9
        lc.Parent = btn
        RenderPixelText(lc, info.label, info.color, 1)

        btn.MouseEnter:Connect(function() btn.BackgroundColor3 = C.btnhov end)
        btn.MouseLeave:Connect(function() btn.BackgroundColor3 = C.btn end)

        btn.MouseButton1Click:Connect(function()
            if info.action == "teleport_touch" then
                if enabled and grab() then
                    local hit = mouse.Hit
                    if hit then
                        doTP(hit.Position)
                        local p = hit.Position
                        UpdatePixelText(targetC, string.format("TP! %d %d %d", math.floor(p.X), math.floor(p.Y), math.floor(p.Z)), C.purple, 1)
                        RecolorIcon(targetIconF, C.purple)
                    end
                end
            elseif info.action == "toggle" then
                enabled = not enabled
                if enabled then
                    RecolorIcon(statusIconF, C.green)
                else
                    RecolorIcon(statusIconF, C.red)
                end
                refreshStatusText()
            elseif info.action == "players" then
                playerListOpen = not playerListOpen
                plrPanel.Visible = playerListOpen
                if playerListOpen then refreshPlrList() end
            elseif info.action == "setWP" then
                if grab() then
                    waypoint = hrp.Position
                    RecolorIcon(wpIconF, C.green)
                    refreshStatusText()
                end
            elseif info.action == "goWP" then
                if waypoint then doTP(waypoint) end
            elseif info.action == "settings" then
                settingsOpen = not settingsOpen
                settingsPanel.Visible = settingsOpen
                if not settingsOpen and rebinding then
                    local bd = bindButtons[rebinding]
                    if bd then
                        bd.btn.BackgroundColor3 = C.btn
                        UpdatePixelText(bd.keyC, Keybinds[rebinding].name, C.white, 1)
                    end
                    rebinding = nil
                end
            end
        end)
    end

    -- Adjust main panel position for mobile
    panel.Position = UDim2.new(0.5, -185, 1, -130)
end

------------------------------------------------------------------------
-- RENDER LOOP
------------------------------------------------------------------------
local elapsed = 0
conn(rs.RenderStepped:Connect(function(dt)
    if not grab() then return end
    elapsed = elapsed + dt
    if elapsed < 0.2 then return end
    elapsed = 0
    local p = hrp.Position
    UpdatePixelText(coordsC, string.format("POS %d %d %d", math.floor(p.X), math.floor(p.Y), math.floor(p.Z)), C.gray, 1)
    if enabled and not bypassing then
        local mh = mouse.Hit
        if mh then
            local mp = mh.Position
            local dist = math.floor((mp - p).Magnitude)
            UpdatePixelText(targetC, string.format("AIM %d %d %d D=%d", math.floor(mp.X), math.floor(mp.Y), math.floor(mp.Z), dist), C.yellow, 1)
            RecolorIcon(targetIconF, C.yellow)
        end
    end
end))

-- Initial status refresh
refreshStatusText()

print("[TP TOOL v9] Loaded! Silent AC + Pixel UI + Keybind Settings")
print("  Press COMMA to open keybind settings")
print("  T=TP | X=Toggle | P=Players | B=WP | N=GoWP | DEL=ClearWP")
INFO