-- Ghost Menu — Advanced ESP v2
-- Skeleton, Chams, Kill Feed, Look Arrow, Weapon Labels, Panic Key
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local CoreGui = game:GetService("CoreGui")
local UIS = game:GetService("UserInputService")
local HttpService = game:GetService("HttpService")
local LocalPlayer = Players.LocalPlayer
local Camera = workspace.CurrentCamera
-- =====================
-- CONFIG
-- =====================
local Config = {
Enabled = true,
Boxes = false,
NameTags = true,
PartLabels = false,
HealthBar = true,
Distance = false,
Tracers = false,
Skeleton = true,
WeaponLabel = false,
LookArrow = true,
Chams = false,
ChamsColor = Color3.fromRGB(180, 200, 255),
ChamsOccColor = Color3.fromRGB(60, 60, 120),
TeamCheck = true,
VisibilityCheck = true,
PartLabelsToggle = false,
MaxDistance = 1000,
TracerOrigin = "Mouse",
SkeletonThick = 1,
PanicKey = Enum.KeyCode.Insert,
Hidden = false,
}
-- Ghost palette
local Ghost = {
bg = Color3.fromRGB(8, 8, 14),
surface = Color3.fromRGB(14, 14, 22),
surfaceHi = Color3.fromRGB(20, 20, 32),
border = Color3.fromRGB(50, 55, 90),
accent = Color3.fromRGB(120, 140, 220),
accentDim = Color3.fromRGB(60, 70, 130),
accentGlow = Color3.fromRGB(160, 180, 255),
textPrimary = Color3.fromRGB(200, 210, 240),
textMuted = Color3.fromRGB(100, 110, 150),
textDim = Color3.fromRGB(60, 65, 100),
onGreen = Color3.fromRGB(80, 200, 140),
onGreenDim = Color3.fromRGB(30, 80, 60),
offGray = Color3.fromRGB(28, 28, 40),
danger = Color3.fromRGB(200, 80, 100),
panelBg = Color3.fromRGB(11, 11, 18),
}
local COL_VIS = Color3.fromRGB(80, 220, 120)
local COL_OCC = Color3.fromRGB(220, 70, 70)
local COL_TXT = Color3.fromRGB(220, 220, 240)
local COL_TXT_OCC = Color3.fromRGB(180, 80, 80)
local COL_DIST = Color3.fromRGB(255, 255, 255)
-- =====================
-- SKELETON CONNECTIONS
-- =====================
local SKELETON = {
{"Head", "UpperTorso"},
{"Head", "Torso"},
{"UpperTorso", "LowerTorso"},
{"LowerTorso", "RightUpperLeg"},
{"LowerTorso", "LeftUpperLeg"},
{"RightUpperLeg", "RightLowerLeg"},
{"LeftUpperLeg", "LeftLowerLeg"},
{"RightLowerLeg", "RightFoot"},
{"LeftLowerLeg", "LeftFoot"},
{"UpperTorso", "RightUpperArm"},
{"UpperTorso", "LeftUpperArm"},
{"RightUpperArm", "RightLowerArm"},
{"LeftUpperArm", "LeftLowerArm"},
{"RightLowerArm", "RightHand"},
{"LeftLowerArm", "LeftHand"},
-- R6 fallbacks
{"Torso", "Right Arm"},
{"Torso", "Left Arm"},
{"Torso", "Right Leg"},
{"Torso", "Left Leg"},
}
local TRACKED_PARTS = {
Head = "Head",
UpperTorso = "Torso",
Torso = "Torso",
RightUpperArm = "R.Arm",
LeftUpperArm = "L.Arm",
RightUpperLeg = "R.Leg",
LeftUpperLeg = "L.Leg",
RightHand = "R.Hand",
LeftHand = "L.Hand",
RightFoot = "R.Foot",
LeftFoot = "L.Foot",
HumanoidRootPart = "Root",
}
-- =====================
-- KILL FEED
-- =====================
local KillFeed = {}
local MAX_KILLS = 6
local KILL_EXPIRE = 8 -- seconds
-- =====================
-- DRAWING HELPER
-- =====================
local function newDrawing(t, props)
local d = Drawing.new(t)
for k, v in pairs(props) do d[k] = v end
return d
end
-- =====================
-- ESP STORAGE
-- =====================
local ESPObjects = {}
local function createESP(player)
if ESPObjects[player] then return end
local obj = { Parts = {}, SkeletonLines = {}, Highlights = {} }
for partName, partLabel in pairs(TRACKED_PARTS) do
obj.Parts[partName] = {
dot = newDrawing("Circle", {
Visible = false, Radius = 4, Thickness = 1.5,
Color = COL_VIS, Filled = true, ZIndex = 4,
}),
outline = newDrawing("Circle", {
Visible = false, Radius = 5, Thickness = 1,
Color = Color3.fromRGB(0,0,0), Filled = false, ZIndex = 3,
}),
label = newDrawing("Text", {
Visible = false, Text = partLabel, Size = 11,
Color = COL_TXT, Center = false, Outline = true,
OutlineColor = Color3.fromRGB(0,0,0), ZIndex = 5,
}),
tracer = newDrawing("Line", {
Visible = false, Color = COL_VIS,
Thickness = 0.8, Transparency = 0.55, ZIndex = 1,
}),
}
end
-- Skeleton lines
for i = 1, #SKELETON do
obj.SkeletonLines[i] = newDrawing("Line", {
Visible = false, Color = COL_VIS,
Thickness = Config.SkeletonThick,
Transparency = 0.3, ZIndex = 2,
})
end
-- Corner box
obj.Corners = {}
obj.BoxLines = {}
for i = 1, 8 do
obj.Corners[i] = newDrawing("Line", {
Visible = false, Color = Color3.fromRGB(180,200,255),
Thickness = 2, ZIndex = 3,
})
end
for i = 1, 4 do
obj.BoxLines[i] = newDrawing("Line", {
Visible = false, Color = Color3.fromRGB(180,200,255),
Thickness = 1, ZIndex = 2,
})
end
obj.NameTag = newDrawing("Text", {
Visible = false, Text = player.Name, Size = 13,
Color = Ghost.textPrimary, Center = true,
Outline = true, OutlineColor = Color3.fromRGB(0,0,0), ZIndex = 6,
})
obj.DistLabel = newDrawing("Text", {
Visible = false, Text = "", Size = 11,
Color = COL_DIST, Center = true,
Outline = true, OutlineColor = Color3.fromRGB(0,0,0), ZIndex = 5,
})
obj.WeaponLabel = newDrawing("Text", {
Visible = false, Text = "", Size = 11,
Color = Ghost.textMuted, Center = true,
Outline = true, OutlineColor = Color3.fromRGB(0,0,0), ZIndex = 5,
})
obj.LookArrow = newDrawing("Triangle", {
Visible = false,
Color = Color3.fromRGB(255, 220, 80),
Filled = true, ZIndex = 5,
})
obj.HealthBarBG = newDrawing("Line", {
Visible = false, Color = Color3.fromRGB(0,0,0),
Thickness = 4, ZIndex = 2,
})
obj.HealthBar = newDrawing("Line", {
Visible = false, Color = COL_VIS,
Thickness = 3, ZIndex = 3,
})
ESPObjects[player] = obj
end
local function hideAll(obj)
for _, p in pairs(obj.Parts) do
p.dot.Visible = false; p.outline.Visible = false
p.label.Visible = false; p.tracer.Visible = false
end
for _, l in pairs(obj.SkeletonLines) do l.Visible = false end
for _, l in pairs(obj.Corners) do l.Visible = false end
for _, l in pairs(obj.BoxLines) do l.Visible = false end
obj.NameTag.Visible = false
obj.DistLabel.Visible = false
obj.WeaponLabel.Visible = false
obj.LookArrow.Visible = false
obj.HealthBarBG.Visible = false
obj.HealthBar.Visible = false
-- Remove chams
for _, h in pairs(obj.Highlights) do h:Destroy() end
obj.Highlights = {}
end
local function removeESP(player)
local obj = ESPObjects[player]
if not obj then return end
for _, p in pairs(obj.Parts) do
p.dot:Remove(); p.outline:Remove()
p.label:Remove(); p.tracer:Remove()
end
for _, l in pairs(obj.SkeletonLines) do l:Remove() end
for _, l in pairs(obj.Corners) do l:Remove() end
for _, l in pairs(obj.BoxLines) do l:Remove() end
obj.NameTag:Remove()
obj.DistLabel:Remove()
obj.WeaponLabel:Remove()
obj.LookArrow:Remove()
obj.HealthBarBG:Remove()
obj.HealthBar:Remove()
for _, h in pairs(obj.Highlights) do h:Destroy() end
ESPObjects[player] = nil
end
-- =====================
-- CHAMS
-- =====================
local function applyChams(player, character)
local obj = ESPObjects[player]
if not obj then return end
for _, h in pairs(obj.Highlights) do h:Destroy() end
obj.Highlights = {}
if not Config.Chams then return end
local h = Instance.new("SelectionBox")
h.Color3 = Config.ChamsColor
h.LineThickness = 0
h.SurfaceTransparency = 0.4
h.SurfaceColor3 = Config.ChamsColor
h.Adornee = character
h.Parent = CoreGui
table.insert(obj.Highlights, h)
end
local function updateChams(player)
local obj = ESPObjects[player]
if not obj then return end
local char = player.Character
if not char then return end
if Config.Chams then
if #obj.Highlights == 0 then applyChams(player, char) end
for _, h in pairs(obj.Highlights) do
h.Color3 = Config.ChamsColor
h.SurfaceColor3 = Config.ChamsColor
end
else
for _, h in pairs(obj.Highlights) do h:Destroy() end
obj.Highlights = {}
end
end
-- =====================
-- HELPERS
-- =====================
local function partIsVisible(character, part)
if not Config.VisibilityCheck then return true end
local origin = Camera.CFrame.Position
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = {character, LocalPlayer.Character}
return workspace:Raycast(origin, part.Position - origin, params) == nil
end
local function isSameTeam(player)
if not Config.TeamCheck then return false end
return LocalPlayer.Team and player.Team and LocalPlayer.Team == player.Team
end
local function hpColor(pct)
return Color3.fromRGB(220,70,70):Lerp(Color3.fromRGB(80,220,120), pct)
end
local function getCharacterBounds(character)
local sMinX, sMinY = math.huge, math.huge
local sMaxX, sMaxY = -math.huge, -math.huge
local any = false
for _, p in pairs(character:GetDescendants()) do
if p:IsA("BasePart") then
local s = p.Size / 2
local pos = p.Position
for _, c in pairs({
Vector3.new(pos.X-s.X,pos.Y-s.Y,pos.Z-s.Z),
Vector3.new(pos.X-s.X,pos.Y-s.Y,pos.Z+s.Z),
Vector3.new(pos.X-s.X,pos.Y+s.Y,pos.Z-s.Z),
Vector3.new(pos.X-s.X,pos.Y+s.Y,pos.Z+s.Z),
Vector3.new(pos.X+s.X,pos.Y-s.Y,pos.Z-s.Z),
Vector3.new(pos.X+s.X,pos.Y-s.Y,pos.Z+s.Z),
Vector3.new(pos.X+s.X,pos.Y+s.Y,pos.Z-s.Z),
Vector3.new(pos.X+s.X,pos.Y+s.Y,pos.Z+s.Z),
}) do
local sp, on = Camera:WorldToViewportPoint(c)
if on then
any = true
sMinX = math.min(sMinX, sp.X); sMinY = math.min(sMinY, sp.Y)
sMaxX = math.max(sMaxX, sp.X); sMaxY = math.max(sMaxY, sp.Y)
end
end
end
end
if not any then return nil end
return {
tl = Vector2.new(sMinX, sMinY), tr = Vector2.new(sMaxX, sMinY),
bl = Vector2.new(sMinX, sMaxY), br = Vector2.new(sMaxX, sMaxY),
cx = (sMinX+sMaxX)/2, w = sMaxX-sMinX, h = sMaxY-sMinY,
}
end
local function drawCornerBox(obj, b, color)
local tl,tr,bl,br = b.tl,b.tr,b.bl,b.br
local w,h = b.w*0.25, b.h*0.25
local dim = Color3.new(color.R*0.3, color.G*0.3, color.B*0.3)
local pts = {
{tl, Vector2.new(tl.X+w,tl.Y)}, {tl, Vector2.new(tl.X,tl.Y+h)},
{tr, Vector2.new(tr.X-w,tr.Y)}, {tr, Vector2.new(tr.X,tr.Y+h)},
{bl, Vector2.new(bl.X+w,bl.Y)}, {bl, Vector2.new(bl.X,bl.Y-h)},
{br, Vector2.new(br.X-w,br.Y)}, {br, Vector2.new(br.X,br.Y-h)},
}
for i,p in ipairs(pts) do
obj.Corners[i].From = p[1]; obj.Corners[i].To = p[2]
obj.Corners[i].Color = color; obj.Corners[i].Visible = true
end
local lines = {{tl,tr},{bl,br},{tl,bl},{tr,br}}
for i,p in ipairs(lines) do
obj.BoxLines[i].From = p[1]; obj.BoxLines[i].To = p[2]
obj.BoxLines[i].Color = dim; obj.BoxLines[i].Visible = true
end
end
local function getWeapon(character)
for _, child in pairs(character:GetChildren()) do
if child:IsA("Tool") then return child.Name end
end
return nil
end
local function isLookingAtMe(character)
local myChar = LocalPlayer.Character
if not myChar then return false end
local myRoot = myChar:FindFirstChild("HumanoidRootPart")
local theirRoot = character:FindFirstChild("HumanoidRootPart")
if not myRoot or not theirRoot then return false end
local toMe = (myRoot.Position - theirRoot.Position).Unit
local theirLook = theirRoot.CFrame.LookVector
return theirLook:Dot(toMe) > 0.85 -- ~31 degree cone
end
-- =====================
-- KILL FEED TRACKING
-- =====================
local function addKillFeedEntry(victim, killer)
table.insert(KillFeed, 1, {
text = (killer or "?") .. " → " .. victim,
time = tick(),
})
if #KillFeed > MAX_KILLS then
table.remove(KillFeed, #KillFeed)
end
end
-- Track humanoid deaths
local trackedHumanoids = {}
local function trackCharacter(player)
local char = player.Character
if not char then return end
local hum = char:FindFirstChildOfClass("Humanoid")
if not hum or trackedHumanoids[hum] then return end
trackedHumanoids[hum] = true
hum.Died:Connect(function()
trackedHumanoids[hum] = nil
-- Try to find killer from creator tag
local tag = hum:FindFirstChild("creator")
local killerName = tag and tag.Value and tag.Value.Name or nil
addKillFeedEntry(player.Name, killerName)
end)
end
for _, p in pairs(Players:GetPlayers()) do
if p ~= LocalPlayer then
p.CharacterAdded:Connect(function() trackCharacter(p) end)
if p.Character then trackCharacter(p) end
end
end
Players.PlayerAdded:Connect(function(p)
p.CharacterAdded:Connect(function() trackCharacter(p) end)
end)
-- Kill feed drawings (persistent label stack)
local KillFeedLabels = {}
for i = 1, MAX_KILLS do
KillFeedLabels[i] = newDrawing("Text", {
Visible = false, Text = "", Size = 12,
Color = Ghost.textPrimary, Center = false,
Outline = true, OutlineColor = Color3.fromRGB(0,0,0), ZIndex = 10,
})
end
-- =====================
-- RENDER LOOP
-- =====================
RunService.RenderStepped:Connect(function()
-- Kill feed update (always runs regardless of ESP enabled)
do
local vp = Camera.ViewportSize
local now = tick()
local active = {}
for _, entry in pairs(KillFeed) do
if now - entry.time < KILL_EXPIRE then
table.insert(active, entry)
end
end
KillFeed = active
for i = 1, MAX_KILLS do
local entry = active[i]
if entry and not Config.Hidden then
local age = now - entry.time
local alpha = math.clamp(1 - (age / KILL_EXPIRE), 0.2, 1)
KillFeedLabels[i].Text = entry.text
KillFeedLabels[i].Position = Vector2.new(vp.X - 220, 60 + (i-1) * 18)
KillFeedLabels[i].Transparency = 1 - alpha
KillFeedLabels[i].Visible = true
else
KillFeedLabels[i].Visible = false
end
end
end
if not Config.Enabled or Config.Hidden then
for _, obj in pairs(ESPObjects) do hideAll(obj) end
return
end
local vp = Camera.ViewportSize
local screenCenter = Vector2.new(vp.X / 2, vp.Y)
for player, obj in pairs(ESPObjects) do
if not player or not player.Parent then
removeESP(player); continue
end
local character = player.Character
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
local rootPart = character and character:FindFirstChild("HumanoidRootPart")
if not character or not humanoid or not rootPart or humanoid.Health <= 0 then
hideAll(obj); continue
end
if isSameTeam(player) then hideAll(obj); continue end
local myRoot = LocalPlayer.Character and LocalPlayer.Character:FindFirstChild("HumanoidRootPart")
if not myRoot then hideAll(obj); continue end
local dist = math.floor((rootPart.Position - myRoot.Position).Magnitude)
if dist > Config.MaxDistance then hideAll(obj); continue end
local _, rootOnScreen = Camera:WorldToViewportPoint(rootPart.Position)
if not rootOnScreen then hideAll(obj); continue end
local hpPct = math.clamp(humanoid.Health / humanoid.MaxHealth, 0, 1)
local bounds = getCharacterBounds(character)
local minX, minY = math.huge, math.huge
local maxX, maxY = -math.huge, -math.huge
-- ---- Part dots ----
for partName, drawings in pairs(obj.Parts) do
local part = character:FindFirstChild(partName)
if not part or not part:IsA("BasePart") then
drawings.dot.Visible = false; drawings.outline.Visible = false
drawings.label.Visible = false; drawings.tracer.Visible = false
continue
end
local sp, onScreen = Camera:WorldToViewportPoint(part.Position)
if not onScreen then
drawings.dot.Visible = false; drawings.outline.Visible = false
drawings.label.Visible = false; drawings.tracer.Visible = false
continue
end
local sx, sy = sp.X, sp.Y
minX = math.min(minX,sx); maxX = math.max(maxX,sx)
minY = math.min(minY,sy); maxY = math.max(maxY,sy)
local vis = partIsVisible(character, part)
local dotCol = vis and COL_VIS or COL_OCC
local txtCol = vis and COL_TXT or COL_TXT_OCC
drawings.dot.Position = Vector2.new(sx,sy)
drawings.dot.Color = dotCol
drawings.dot.Filled = vis
drawings.dot.Visible = true
drawings.outline.Position = Vector2.new(sx,sy)
drawings.outline.Visible = true
drawings.label.Position = Vector2.new(sx+7, sy-5)
drawings.label.Color = txtCol
drawings.label.Visible = Config.PartLabels
if Config.Tracers then
local orig = Config.TracerOrigin == "Mouse"
and (function() local m = UIS:GetMouseLocation(); return Vector2.new(m.X,m.Y) end)()
or screenCenter
drawings.tracer.From = orig
drawings.tracer.To = Vector2.new(sx,sy)
drawings.tracer.Color = dotCol
drawings.tracer.Visible = true
else
drawings.tracer.Visible = false
end
end
-- ---- Skeleton ----
if Config.Skeleton then
for i, conn in ipairs(SKELETON) do
local a = character:FindFirstChild(conn[1])
local b = character:FindFirstChild(conn[2])
local line = obj.SkeletonLines[i]
if a and b and a:IsA("BasePart") and b:IsA("BasePart") then
local spA, onA = Camera:WorldToViewportPoint(a.Position)
local spB, onB = Camera:WorldToViewportPoint(b.Position)
if onA and onB then
local visA = partIsVisible(character, a)
local visB = partIsVisible(character, b)
line.Color = (visA and visB) and COL_VIS or COL_OCC
line.From = Vector2.new(spA.X, spA.Y)
line.To = Vector2.new(spB.X, spB.Y)
line.Thickness = Config.SkeletonThick
line.Visible = true
else
line.Visible = false
end
else
line.Visible = false
end
end
else
for _, l in pairs(obj.SkeletonLines) do l.Visible = false end
end
-- ---- Corner box ----
if Config.Boxes and bounds then
local rootVis = partIsVisible(character, rootPart)
local boxColor = rootVis and Color3.fromRGB(180,200,255) or Color3.fromRGB(80,80,120)
drawCornerBox(obj, bounds, boxColor)
else
for _, l in pairs(obj.Corners) do l.Visible = false end
for _, l in pairs(obj.BoxLines) do l.Visible = false end
end
-- ---- Name tag ----
if Config.NameTags and minY < math.huge then
obj.NameTag.Text = player.Name
obj.NameTag.Position = Vector2.new((minX+maxX)/2, minY - 16)
obj.NameTag.Visible = true
else
obj.NameTag.Visible = false
end
-- ---- Distance ----
if Config.Distance and maxY > -math.huge then
obj.DistLabel.Text = "[" .. dist .. "m]"
obj.DistLabel.Position = Vector2.new((minX+maxX)/2, maxY + 5)
obj.DistLabel.Color = COL_DIST
obj.DistLabel.Visible = true
else
obj.DistLabel.Visible = false
end
-- ---- Weapon label ----
if Config.WeaponLabel and maxY > -math.huge then
local weapon = getWeapon(character)
if weapon then
local offset = Config.Distance and 18 or 5
obj.WeaponLabel.Text = "🗡 " .. weapon
obj.WeaponLabel.Position = Vector2.new((minX+maxX)/2, maxY + offset)
obj.WeaponLabel.Visible = true
else
obj.WeaponLabel.Visible = false
end
else
obj.WeaponLabel.Visible = false
end
-- ---- Look arrow (only if looking at me) ----
if Config.LookArrow and isLookingAtMe(character) then
local headPart = character:FindFirstChild("Head")
if headPart then
local sp, on = Camera:WorldToViewportPoint(headPart.Position)
if on then
local cx, cy = sp.X, sp.Y - 22
local size = 7
-- Triangle pointing down toward the head
obj.LookArrow.PointA = Vector2.new(cx, cy + size)
obj.LookArrow.PointB = Vector2.new(cx - size, cy - size)
obj.LookArrow.PointC = Vector2.new(cx + size, cy - size)
obj.LookArrow.Color = Color3.fromRGB(255, 80, 80)
obj.LookArrow.Visible = true
else
obj.LookArrow.Visible = false
end
else
obj.LookArrow.Visible = false
end
else
obj.LookArrow.Visible = false
end
-- ---- Health bar ----
if Config.HealthBar and minY < math.huge then
local barX = minX - 8
local fillTop = maxY - (maxY - minY) * hpPct
obj.HealthBarBG.From = Vector2.new(barX, minY)
obj.HealthBarBG.To = Vector2.new(barX, maxY)
obj.HealthBarBG.Visible = true
obj.HealthBar.From = Vector2.new(barX, fillTop)
obj.HealthBar.To = Vector2.new(barX, maxY)
obj.HealthBar.Color = hpColor(hpPct)
obj.HealthBar.Visible = true
else
obj.HealthBarBG.Visible = false
obj.HealthBar.Visible = false
end
-- ---- Chams ----
updateChams(player)
end
end)
-- =====================
-- PLAYER MANAGEMENT
-- =====================
local function onPlayerAdded(player)
if player == LocalPlayer then return end
createESP(player)
player.CharacterAdded:Connect(function(char)
task.wait(0.5)
if Config.Chams then applyChams(player, char) end
trackCharacter(player)
end)
end
local function onPlayerRemoving(player)
removeESP(player)
end
for _, p in pairs(Players:GetPlayers()) do onPlayerAdded(p) end
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)
-- =====================
-- PANIC KEY
-- =====================
UIS.InputBegan:Connect(function(input, gp)
if gp then return end
if input.KeyCode == Config.PanicKey then
Config.Hidden = not Config.Hidden
-- Hide/show the menu frame
if ScreenGui then
for _, obj in pairs(ESPObjects) do
if Config.Hidden then hideAll(obj) end
end
end
end
end)
-- =====================
-- GHOST MENU UI
-- =====================
local ScreenGui = Instance.new("ScreenGui")
ScreenGui.Name = "GhostMenu"
ScreenGui.Parent = CoreGui
ScreenGui.ResetOnSpawn = false
ScreenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
local MENU_W = 245
local MENU_H = 560
local MINI_H = 38
local MainFrame = Instance.new("Frame")
MainFrame.Parent = ScreenGui
MainFrame.BackgroundColor3 = Ghost.bg
MainFrame.BackgroundTransparency = 0.06
MainFrame.Position = UDim2.new(0, 20, 0.5, -(MENU_H/2))
MainFrame.Size = UDim2.new(0, MENU_W, 0, MENU_H)
MainFrame.Active = true
MainFrame.Draggable = true
MainFrame.BorderSizePixel = 0
local MFC = Instance.new("UICorner"); MFC.CornerRadius = UDim.new(0, 10); MFC.Parent = MainFrame
local BorderStroke = Instance.new("UIStroke")
BorderStroke.Thickness = 1
BorderStroke.Color = Ghost.border
BorderStroke.Transparency = 0.35
BorderStroke.Parent = MainFrame
local GlowBar = Instance.new("Frame")
GlowBar.Parent = MainFrame
GlowBar.BackgroundColor3 = Ghost.accent
GlowBar.BackgroundTransparency = 0.7
GlowBar.BorderSizePixel = 0
GlowBar.Position = UDim2.new(0.1, 0, 0, 0)
GlowBar.Size = UDim2.new(0.8, 0, 0, 1)
spawn(function()
local t = 0
while MainFrame and MainFrame.Parent do
t += 0.05
GlowBar.BackgroundTransparency = 0.4 + math.sin(t) * 0.3
task.wait(0.05)
end
end)
-- Top bar
local TopBar = Instance.new("Frame")
TopBar.Parent = MainFrame
TopBar.BackgroundTransparency = 1
TopBar.Size = UDim2.new(1, 0, 0, 38)
TopBar.BorderSizePixel = 0
local TitleLbl = Instance.new("TextLabel")
TitleLbl.Parent = TopBar
TitleLbl.BackgroundTransparency = 1
TitleLbl.Position = UDim2.new(0, 12, 0, 2)
TitleLbl.Size = UDim2.new(1, -90, 0, 20)
TitleLbl.Font = Enum.Font.GothamBold
TitleLbl.Text = "👻 Ghost Menu"
TitleLbl.TextColor3 = Ghost.accentGlow
TitleLbl.TextSize = 13
TitleLbl.TextXAlignment = Enum.TextXAlignment.Left
local SubLbl = Instance.new("TextLabel")
SubLbl.Parent = TopBar
SubLbl.BackgroundTransparency = 1
SubLbl.Position = UDim2.new(0, 12, 0, 22)
SubLbl.Size = UDim2.new(1, -90, 0, 14)
SubLbl.Font = Enum.Font.Gotham
SubLbl.Text = "Advanced ESP · " .. Config.PanicKey.Name .. " to hide"
SubLbl.TextColor3 = Ghost.textDim
SubLbl.TextSize = 10
SubLbl.TextXAlignment = Enum.TextXAlignment.Left
-- Divider
local Divider = Instance.new("Frame")
Divider.Parent = MainFrame
Divider.BackgroundColor3 = Ghost.border
Divider.BackgroundTransparency = 0.55
Divider.BorderSizePixel = 0
Divider.Position = UDim2.new(0, 10, 0, 38)
Divider.Size = UDim2.new(1, -20, 0, 1)
-- Minimized info bar (shown when minimized)
local MiniBar = Instance.new("Frame")
MiniBar.Parent = MainFrame
MiniBar.BackgroundTransparency = 1
MiniBar.Position = UDim2.new(0, 10, 0, 10)
MiniBar.Size = UDim2.new(1, -20, 0, 18)
MiniBar.Visible = false
local MiniLbl = Instance.new("TextLabel")
MiniLbl.Parent = MiniBar
MiniLbl.BackgroundTransparency = 1
MiniLbl.Size = UDim2.new(1, 0, 1, 0)
MiniLbl.Font = Enum.Font.GothamBold
MiniLbl.Text = ""
MiniLbl.TextColor3 = Ghost.textDim
MiniLbl.TextSize = 10
MiniLbl.TextXAlignment = Enum.TextXAlignment.Left
local function updateMiniBar()
local parts = {}
if Config.Enabled then table.insert(parts, "ESP ON") end
if Config.Skeleton then table.insert(parts, "SKEL") end
if Config.Chams then table.insert(parts, "CHAMS") end
if Config.Boxes then table.insert(parts, "BOX") end
if Config.Tracers then table.insert(parts, "TRACE") end
if Config.LookArrow then table.insert(parts, "LOOK") end
MiniLbl.Text = #parts > 0 and table.concat(parts, " · ") or "👻 Ghost Menu"
MiniLbl.TextColor3 = Config.Enabled and Ghost.accentGlow or Ghost.textDim
end
-- Top buttons
local function makeTopBtn(text, posX, bgColor, txtColor)
local b = Instance.new("TextButton")
b.Parent = TopBar
b.BackgroundColor3 = bgColor or Ghost.surfaceHi
b.BackgroundTransparency = 0.15
b.Position = UDim2.new(1, posX, 0, 9)
b.Size = UDim2.new(0, 22, 0, 22)
b.Font = Enum.Font.GothamBold
b.Text = text
b.TextColor3 = txtColor or Ghost.textMuted
b.TextSize = 12
b.BorderSizePixel = 0
local c = Instance.new("UICorner"); c.CornerRadius = UDim.new(0, 5); c.Parent = b
local s = Instance.new("UIStroke"); s.Thickness = 1; s.Color = Ghost.border; s.Transparency = 0.5; s.Parent = b
b.MouseEnter:Connect(function()
TweenService:Create(b, TweenInfo.new(0.1), {BackgroundTransparency = 0}):Play()
end)
b.MouseLeave:Connect(function()
TweenService:Create(b, TweenInfo.new(0.1), {BackgroundTransparency = 0.15}):Play()
end)
return b
end
local MinBtn = makeTopBtn("—", -52, Ghost.surfaceHi, Ghost.textMuted)
local CloseBtn = makeTopBtn("×", -26, Ghost.danger, Color3.fromRGB(255,255,255))
-- Scroll
local Scroll = Instance.new("ScrollingFrame")
Scroll.Parent = MainFrame
Scroll.Position = UDim2.new(0, 0, 0, 42)
Scroll.Size = UDim2.new(1, 0, 1, -42)
Scroll.BackgroundTransparency = 1
Scroll.BorderSizePixel = 0
Scroll.ScrollBarThickness = 2
Scroll.ScrollBarImageColor3 = Ghost.accentDim
Scroll.CanvasSize = UDim2.new(0, 0, 0, 0)
Scroll.AutomaticCanvasSize = Enum.AutomaticSize.Y
Scroll.ClipsDescendants = true
local ScrollLayout = Instance.new("UIListLayout")
ScrollLayout.Parent = Scroll
ScrollLayout.SortOrder = Enum.SortOrder.LayoutOrder
ScrollLayout.Padding = UDim.new(0, 3)
local ScrollPad = Instance.new("UIPadding")
ScrollPad.Parent = Scroll
ScrollPad.PaddingTop = UDim.new(0, 8)
ScrollPad.PaddingLeft = UDim.new(0, 10)
ScrollPad.PaddingRight = UDim.new(0, 10)
ScrollPad.PaddingBottom = UDim.new(0, 10)
-- Section label
local function makeSectionLabel(text, order)
local wrapper = Instance.new("Frame")
wrapper.Parent = Scroll
wrapper.BackgroundTransparency = 1
wrapper.Size = UDim2.new(1, 0, 0, 22)
wrapper.LayoutOrder = order
local l = Instance.new("TextLabel")
l.Parent = wrapper
l.BackgroundTransparency = 1
l.Size = UDim2.new(1, 0, 1, 0)
l.Font = Enum.Font.GothamBold
l.Text = text
l.TextColor3 = Ghost.accentDim
l.TextSize = 10
l.TextXAlignment = Enum.TextXAlignment.Left
l.TextTransparency = 0.2
local line = Instance.new("Frame")
line.Parent = wrapper
line.BackgroundColor3 = Ghost.accentDim
line.BackgroundTransparency = 0.7
line.BorderSizePixel = 0
line.Position = UDim2.new(0, 0, 1, -1)
line.Size = UDim2.new(1, 0, 0, 1)
end
-- Toggle row
local function makeToggleRow(label, order, currentVal, callback)
local row = Instance.new("Frame")
row.Parent = Scroll
row.BackgroundColor3 = Ghost.surface
row.BackgroundTransparency = 0.3
row.Size = UDim2.new(1, 0, 0, 30)
row.BorderSizePixel = 0
row.LayoutOrder = order
local RC = Instance.new("UICorner"); RC.CornerRadius = UDim.new(0, 6); RC.Parent = row
local RS = Instance.new("UIStroke"); RS.Thickness = 1; RS.Color = Ghost.border; RS.Transparency = 0.7; RS.Parent = row
local lbl = Instance.new("TextLabel")
lbl.Parent = row
lbl.BackgroundTransparency = 1
lbl.Position = UDim2.new(0, 10, 0, 0)
lbl.Size = UDim2.new(1, -60, 1, 0)
lbl.Font = Enum.Font.Gotham
lbl.Text = label
lbl.TextColor3 = Ghost.textPrimary
lbl.TextSize = 12
lbl.TextXAlignment = Enum.TextXAlignment.Left
local pill = Instance.new("Frame")
pill.Parent = row
pill.Position = UDim2.new(1, -46, 0.5, -9)
pill.Size = UDim2.new(0, 36, 0, 18)
pill.BorderSizePixel = 0
local PC = Instance.new("UICorner"); PC.CornerRadius = UDim.new(1, 0); PC.Parent = pill
local PS = Instance.new("UIStroke"); PS.Thickness = 1; PS.Color = Ghost.border; PS.Transparency = 0.5; PS.Parent = pill
local knob = Instance.new("Frame")
knob.Parent = pill
knob.Size = UDim2.new(0, 12, 0, 12)
knob.BorderSizePixel = 0
local KC = Instance.new("UICorner"); KC.CornerRadius = UDim.new(1, 0); KC.Parent = knob
local function refresh(val)
TweenService:Create(pill, TweenInfo.new(0.2), {
BackgroundColor3 = val and Ghost.onGreenDim or Ghost.offGray
}):Play()
TweenService:Create(knob, TweenInfo.new(0.2), {
Position = val and UDim2.new(1,-15,0.5,-6) or UDim2.new(0,3,0.5,-6),
BackgroundColor3 = val and Ghost.onGreen or Ghost.textDim
}):Play()
updateMiniBar()
end
refresh(currentVal)
local btn = Instance.new("TextButton")
btn.Parent = row
btn.BackgroundTransparency = 1
btn.Size = UDim2.new(1, 0, 1, 0)
btn.Text = ""
btn.ZIndex = 5
btn.MouseButton1Click:Connect(function()
currentVal = not currentVal
refresh(currentVal)
callback(currentVal)
end)
btn.MouseEnter:Connect(function()
TweenService:Create(row, TweenInfo.new(0.15), {BackgroundTransparency = 0.1}):Play()
end)
btn.MouseLeave:Connect(function()
TweenService:Create(row, TweenInfo.new(0.15), {BackgroundTransparency = 0.3}):Play()
end)
end
-- Slider row
local function makeSliderRow(label, order, minV, maxV, current, callback)
local row = Instance.new("Frame")
row.Parent = Scroll
row.BackgroundColor3 = Ghost.surface
row.BackgroundTransparency = 0.3
row.Size = UDim2.new(1, 0, 0, 48)
row.BorderSizePixel = 0
row.LayoutOrder = order
local RC = Instance.new("UICorner"); RC.CornerRadius = UDim.new(0, 6); RC.Parent = row
local RS = Instance.new("UIStroke"); RS.Thickness = 1; RS.Color = Ghost.border; RS.Transparency = 0.7; RS.Parent = row
local lbl = Instance.new("TextLabel")
lbl.Parent = row
lbl.BackgroundTransparency = 1
lbl.Position = UDim2.new(0, 10, 0, 5)
lbl.Size = UDim2.new(1, -20, 0, 16)
lbl.Font = Enum.Font.Gotham
lbl.Text = label .. ": " .. current
lbl.TextColor3 = Ghost.textPrimary
lbl.TextSize = 12
lbl.TextXAlignment = Enum.TextXAlignment.Left
local trackBG = Instance.new("Frame")
trackBG.Parent = row
trackBG.Position = UDim2.new(0, 10, 0, 30)
trackBG.Size = UDim2.new(1, -20, 0, 5)
trackBG.BackgroundColor3 = Ghost.surfaceHi
trackBG.BorderSizePixel = 0
local TBC = Instance.new("UICorner"); TBC.CornerRadius = UDim.new(1, 0); TBC.Parent = trackBG
local trackFill = Instance.new("Frame")
trackFill.Parent = trackBG
trackFill.BackgroundColor3 = Ghost.accent
trackFill.BorderSizePixel = 0
trackFill.Size = UDim2.new((current-minV)/(maxV-minV), 0, 1, 0)
local TFC = Instance.new("UICorner"); TFC.CornerRadius = UDim.new(1, 0); TFC.Parent = trackFill
local thumb = Instance.new("Frame")
thumb.Parent = trackBG
thumb.BackgroundColor3 = Ghost.accentGlow
thumb.BorderSizePixel = 0
thumb.AnchorPoint = Vector2.new(0.5, 0.5)
thumb.Size = UDim2.new(0, 10, 0, 10)
thumb.Position = UDim2.new((current-minV)/(maxV-minV), 0, 0.5, 0)
local ThC = Instance.new("UICorner"); ThC.CornerRadius = UDim.new(1, 0); ThC.Parent = thumb
local dragging = false
local function updateSlider(x)
local pct = math.clamp((x - trackBG.AbsolutePosition.X) / trackBG.AbsoluteSize.X, 0, 1)
local val = math.floor(minV + (maxV - minV) * pct)
trackFill.Size = UDim2.new(pct, 0, 1, 0)
thumb.Position = UDim2.new(pct, 0, 0.5, 0)
lbl.Text = label .. ": " .. val
callback(val)
end
trackBG.InputBegan:Connect(function(inp)
if inp.UserInputType == Enum.UserInputType.MouseButton1 then
dragging = true; updateSlider(inp.Position.X)
end
end)
UIS.InputEnded:Connect(function(inp)
if inp.UserInputType == Enum.UserInputType.MouseButton1 then dragging = false end
end)
UIS.InputChanged:Connect(function(inp)
if dragging and inp.UserInputType == Enum.UserInputType.MouseMovement then
updateSlider(inp.Position.X)
end
end)
end
-- Tracer origin cycler
local function makeTracerOriginRow(order)
local row = Instance.new("Frame")
row.Parent = Scroll
row.BackgroundColor3 = Ghost.surface
row.BackgroundTransparency = 0.3
row.Size = UDim2.new(1, 0, 0, 30)
row.BorderSizePixel = 0
row.LayoutOrder = order
local RC = Instance.new("UICorner"); RC.CornerRadius = UDim.new(0, 6); RC.Parent = row
local RS = Instance.new("UIStroke"); RS.Thickness = 1; RS.Color = Ghost.border; RS.Transparency = 0.7; RS.Parent = row
local lbl = Instance.new("TextLabel")
lbl.Parent = row
lbl.BackgroundTransparency = 1
lbl.Position = UDim2.new(0, 10, 0, 0)
lbl.Size = UDim2.new(0, 100, 1, 0)
lbl.Font = Enum.Font.Gotham
lbl.Text = "Tracer From"
lbl.TextColor3 = Ghost.textPrimary
lbl.TextSize = 12
lbl.TextXAlignment = Enum.TextXAlignment.Left
local options = {"Mouse", "Bottom"}
local current = 1
local btn = Instance.new("TextButton")
btn.Parent = row
btn.BackgroundColor3 = Ghost.surfaceHi
btn.BackgroundTransparency = 0.2
btn.Position = UDim2.new(1, -92, 0.5, -10)
btn.Size = UDim2.new(0, 82, 0, 20)
btn.Font = Enum.Font.GothamBold
btn.Text = "⟳ " .. options[current]
btn.TextColor3 = Ghost.accentGlow
btn.TextSize = 11
btn.BorderSizePixel = 0
local BC = Instance.new("UICorner"); BC.CornerRadius = UDim.new(0, 4); BC.Parent = btn
local BS = Instance.new("UIStroke"); BS.Thickness = 1; BS.Color = Ghost.border; BS.Transparency = 0.6; BS.Parent = btn
btn.MouseButton1Click:Connect(function()
current = current == 1 and 2 or 1
Config.TracerOrigin = options[current]
btn.Text = "⟳ " .. options[current]
end)
end
-- Color picker row (simple preset cycles)
local function makeColorRow(label, order, presets, callback)
local row = Instance.new("Frame")
row.Parent = Scroll
row.BackgroundColor3 = Ghost.surface
row.BackgroundTransparency = 0.3
row.Size = UDim2.new(1, 0, 0, 30)
row.BorderSizePixel = 0
row.LayoutOrder = order
local RC = Instance.new("UICorner"); RC.CornerRadius = UDim.new(0, 6); RC.Parent = row
local RS = Instance.new("UIStroke"); RS.Thickness = 1; RS.Color = Ghost.border; RS.Transparency = 0.7; RS.Parent = row
local lbl = Instance.new("TextLabel")
lbl.Parent = row
lbl.BackgroundTransparency = 1
lbl.Position = UDim2.new(0, 10, 0, 0)
lbl.Size = UDim2.new(0, 100, 1, 0)
lbl.Font = Enum.Font.Gotham
lbl.Text = label
lbl.TextColor3 = Ghost.textPrimary
lbl.TextSize = 12
lbl.TextXAlignment = Enum.TextXAlignment.Left
local current = 1
local swatchSize = 16
local startX = MENU_W - 10 - (#presets * (swatchSize + 4))
for i, color in ipairs(presets) do
local swatch = Instance.new("TextButton")
swatch.Parent = row
swatch.BackgroundColor3 = color
swatch.Position = UDim2.new(0, startX + (i-1)*(swatchSize+4), 0.5, -swatchSize/2)
swatch.Size = UDim2.new(0, swatchSize, 0, swatchSize)
swatch.Text = ""
swatch.BorderSizePixel = 0
local SC = Instance.new("UICorner"); SC.CornerRadius = UDim.new(1,0); SC.Parent = swatch
local SS = Instance.new("UIStroke")
SS.Color = Ghost.border; SS.Thickness = 1; SS.Transparency = 0.5; SS.Parent = swatch
swatch.MouseButton1Click:Connect(function()
-- Highlight selected
for j = 1, #presets do
local other = row:GetChildren()[j + 2]
end
SS.Transparency = 0
SS.Color = Color3.fromRGB(255,255,255)
callback(color)
end)
end
end
-- ========================
-- BUILD UI
-- ========================
makeSectionLabel("ELEMENTS", 1)
makeToggleRow("ESP Enabled", 2, Config.Enabled, function(v) Config.Enabled = v; updateMiniBar() end)
makeToggleRow("Corner Boxes", 3, Config.Boxes, function(v) Config.Boxes = v; updateMiniBar() end)
makeToggleRow("Skeleton", 4, Config.Skeleton, function(v) Config.Skeleton = v; updateMiniBar() end)
makeToggleRow("Name Tags", 5, Config.NameTags, function(v) Config.NameTags = v end)
makeToggleRow("Part Labels", 6, Config.PartLabels, function(v) Config.PartLabels = v end)
makeToggleRow("Health Bar", 7, Config.HealthBar, function(v) Config.HealthBar = v end)
makeToggleRow("Distance", 8, Config.Distance, function(v) Config.Distance = v end)
makeToggleRow("Weapon Label", 9, Config.WeaponLabel, function(v) Config.WeaponLabel = v end)
makeToggleRow("Look Arrow", 10, Config.LookArrow, function(v) Config.LookArrow = v; updateMiniBar() end)
makeToggleRow("Tracers", 11, Config.Tracers, function(v) Config.Tracers = v; updateMiniBar() end)
makeSectionLabel("SKELETON", 12)
makeSliderRow("Thickness", 13, 1, 6, Config.SkeletonThick, function(v) Config.SkeletonThick = v end)
makeSectionLabel("CHAMS", 14)
makeToggleRow("Chams", 15, Config.Chams, function(v)
Config.Chams = v
updateMiniBar()
if not v then
for _, obj in pairs(ESPObjects) do
for _, h in pairs(obj.Highlights) do h:Destroy() end
obj.Highlights = {}
end
end
end)
makeColorRow("Chams Color", 16, {
Color3.fromRGB(180,200,255),
Color3.fromRGB(80, 220,120),
Color3.fromRGB(220,70, 70),
Color3.fromRGB(255,220,80),
Color3.fromRGB(200,100,255),
Color3.fromRGB(80, 200,220),
}, function(c) Config.ChamsColor = c end)
makeSectionLabel("FILTERS", 17)
makeToggleRow("Team Check", 18, Config.TeamCheck, function(v) Config.TeamCheck = v end)
makeToggleRow("Visibility Check", 19, Config.VisibilityCheck, function(v) Config.VisibilityCheck = v end)
makeTracerOriginRow(20)
makeSliderRow("Max Distance", 21, 50, 2000, Config.MaxDistance, function(v) Config.MaxDistance = v end)
-- =====================
-- MINIMIZE
-- =====================
local minimized = false
MinBtn.MouseButton1Click:Connect(function()
minimized = not minimized
Scroll.Visible = not minimized
Divider.Visible = not minimized
TitleLbl.Visible = not minimized
SubLbl.Visible = not minimized
MiniBar.Visible = minimized
updateMiniBar()
TweenService:Create(MainFrame, TweenInfo.new(0.2, Enum.EasingStyle.Quad), {
Size = minimized
and UDim2.new(0, MENU_W, 0, MINI_H)
or UDim2.new(0, MENU_W, 0, MENU_H)
}):Play()
MinBtn.Text = minimized and "+" or "—"
end)
-- =====================
-- CLOSE — full destroy
-- =====================
CloseBtn.MouseButton1Click:Connect(function()
-- Kill all ESP drawings
for player, _ in pairs(ESPObjects) do removeESP(player) end
-- Kill kill feed labels
for _, lbl in pairs(KillFeedLabels) do lbl:Remove() end
-- Disconnect all RunService (handled by ScreenGui destroy stopping renders)
-- Clear tracked humanoids
trackedHumanoids = {}
KillFeed = {}
-- Destroy GUI
ScreenGui:Destroy()
print("Ghost Menu closed.")
end)
updateMiniBar()
print("Ghost Menu loaded. " .. Config.PanicKey.Name .. " = panic toggle.")
To embed this project on your website, copy the following code and paste it into your website's HTML: