-- Ghost Menu Ultimate v5.3
-- Universal rig resolver, bone skeleton, weapon silhouette, nameplate scaling,
-- LoS map + prediction cone, minimap grid, ESP Advanced card,
-- Combat Advanced card: ping norm, tick rate comp, flick assist,
-- multi-target suppressor, aim shake dampener, target weight system,
-- anti-aim detector + indicator, anti-lag compensation.
--// Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UIS = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local CoreGui = game:GetService("CoreGui")
local Lighting = game:GetService("Lighting")
local HttpService = game:GetService("HttpService")
local Stats = game:GetService("Stats")
local Workspace = game:GetService("Workspace")
local lp = Players.LocalPlayer
local camera = Workspace.CurrentCamera
local GhostTextMain = Color3.fromRGB(245,245,250)
local GhostTextSub = Color3.fromRGB(165,165,178)
local GhostControlOn = Color3.fromRGB(225,225,235)
local GhostControlFill= Color3.fromRGB(210,210,225)
local GhostIcon = Color3.fromRGB(220,220,232)
if not Drawing then
warn("Your executor does not support Drawing API.")
end
pcall(function()
if CoreGui:FindFirstChild("GhostMenu_v5") then CoreGui.GhostMenu_v5:Destroy() end
end)
-- =====================
-- HELPERS
-- =====================
function safeCall(fn,...) local ok,r=pcall(fn,...); if ok then return r end end
function tween(obj,t,props,style,dir) TweenService:Create(obj,TweenInfo.new(t or 0.2,style or Enum.EasingStyle.Quad,dir or Enum.EasingDirection.Out),props):Play() end
function clamp(n,a,b) return math.max(a,math.min(b,n)) end
function lerp(a,b,t) return a+(b-a)*t end
function now() return tick() end
function safePairs(t) if type(t)=="table" then return pairs(t) end; return function() return nil end,nil,nil end
function safeIpairs(t) if type(t)=="table" then return ipairs(t) end; return function() return nil end,nil,nil end
function safeRemove(o) if o then pcall(function() o:Remove() end) end end
local menuBlocksInput
function getChar(p) return p and p.Character end
function getHum(p) local c=getChar(p); return c and c:FindFirstChildOfClass("Humanoid") end
function isAlive(p) local h=getHum(p); local r=getRoot(p); return h and r and h.Health>0 end
-- =====================
-- UNIVERSAL RIG RESOLVER
-- Works on any game: R6, R15, custom blocky, Frontlines, Deadline, etc.
-- No hardcoded part names — resolves dynamically from character geometry.
-- =====================
local rigCache = {} -- [character] = {root,head,parts,bones,timestamp}
local RIG_CACHE_TTL = 2.0
function getAllParts(character)
local parts = {}
for _,v in pairs(character:GetDescendants()) do
if v:IsA("BasePart") and v.Size.Magnitude > 0.1 then
table.insert(parts, v)
end
end
return parts
end
function getCenterOfMass(parts)
local sum = Vector3.zero
local total = 0
for _,p in ipairs(parts) do
local m = p:GetMass()
sum = sum + p.Position * m
total = total + m
end
if total == 0 then return parts[1] and parts[1].Position or Vector3.zero end
return sum / total
end
function resolveRig(character)
if not character then return nil end
local cached = rigCache[character]
if cached and (now() - cached.timestamp) < RIG_CACHE_TTL then
return cached
end
local parts = getAllParts(character)
if #parts == 0 then return nil end
local com = getCenterOfMass(parts)
local hum = character:FindFirstChildOfClass("Humanoid")
-- Root: humanoid RootPart first, else part closest to CoM at bottom half
local root = hum and hum.RootPart
if not root then
local bestDist = math.huge
for _,p in ipairs(parts) do
local d = (Vector3.new(p.Position.X, com.Y, p.Position.Z) - Vector3.new(com.X, com.Y, com.Z)).Magnitude
if d < bestDist then bestDist = d; root = p end
end
end
-- Head: part furthest up from CoM (highest Y)
local head = nil
local highestY = -math.huge
for _,p in ipairs(parts) do
if p.Position.Y > highestY then
highestY = p.Position.Y
head = p
end
end
-- Aim part: for aim purposes, prefer head, else torso region
-- Torso = part closest to CoM
local torso = root
local bestTorsoDist = math.huge
for _,p in ipairs(parts) do
local d = (p.Position - com).Magnitude
if d < bestTorsoDist then bestTorsoDist = d; torso = p end
end
-- Build bone connections: proximity graph
-- Connect each part to its nearest neighbor (MST-like, practical for drawing)
local bones = {}
local used = {}
-- Sort parts top to bottom for cleaner skeleton
table.sort(parts, function(a,b) return a.Position.Y > b.Position.Y end)
for i,p in ipairs(parts) do
local bestDist = math.huge
local bestPart = nil
for j,q in ipairs(parts) do
if i ~= j then
local d = (p.Position - q.Position).Magnitude
if d < bestDist and d < 8.0 then -- max bone length 8 studs
bestDist = d
bestPart = q
end
end
end
if bestPart then
-- avoid duplicate pairs
local key = tostring(math.min(i,#parts)) .. "_" .. tostring(math.max(i,#parts))
if not used[key] then
used[key] = true
table.insert(bones, {p, bestPart})
end
end
end
local rig = {
root = root,
head = head,
torso = torso,
parts = parts,
bones = bones,
com = com,
hum = hum,
timestamp= now(),
}
rigCache[character] = rig
return rig
end
function getRoot(p)
local c = getChar(p); if not c then return nil end
local rig = resolveRig(c)
return rig and rig.root
end
function getTeamValue(p)
if not p then return nil end
if p.Team then return "Team:"..tostring(p.Team) end
if p.TeamColor then return "TeamColor:"..tostring(p.TeamColor) end
local c = p.Character
if c then
local a = c:GetAttribute("Team") or c:GetAttribute("TeamName") or c:GetAttribute("Faction") or c:GetAttribute("Side")
if a then return "Attr:"..tostring(a) end
end
return nil
end
function isTeammate(p)
if not p or p == lp then return true end
if not Config or not Config.TeamCheck then return false end
local mine = getTeamValue(lp)
local theirs= getTeamValue(p)
return mine ~= nil and theirs ~= nil and mine == theirs
end
function teamDebugSummary()
local mine = getTeamValue(lp) or "none"
local friendly,other,unknown = 0,0,0
for _,p in safeIpairs(Players:GetPlayers()) do
if p ~= lp then
local tv = getTeamValue(p)
if not tv then unknown=unknown+1
elseif isTeammate(p) then friendly=friendly+1
else other=other+1 end
end
end
return "Local: "..mine.." | Friendly: "..friendly.." | Other: "..other.." | Unknown: "..unknown
end
function getPing()
local ok,p = pcall(function() return math.floor(Stats.Network.ServerStatsItem["Data Ping"]:GetValue()) end)
return ok and p or 0
end
-- =====================
-- CONFIG
-- =====================
local Config = {
MenuKey="F1", PanicKey="End", Hidden=false,
TeamCheck=true, WallCheck=true, DistanceLimit=5000,
ESP=true, BoxESP=false, BoxStyle="Full",
NameESP=true, HealthESP=true, DistanceESP=true,
ReadableDetails=true, DetailMaxDistance=1800,
ESPStackMode="Clean", ESPNameOptional=true,
SkeletonMode="Bone", -- "Bone" | "Dots" | "Both"
SkeletonDistanceFade=true,
ArrowSmartStack=true, ArrowLabelMode="Distance",
ArrowVerticalHints=true, ArrowVerticalThreshold=18,
TracerESP=false, SkeletonESP=true, Chams=false,
OffscreenArrows=true, ArrowSize=24, ArrowPadding=90,
ArrowThreatPulse=true, TopIndicators=false, TargetInfo=true,
-- ESP Advanced
WeaponSilhouette=false,
NameplateDistanceScale=true,
NameplateMaxSize=16,
NameplateMinSize=9,
NameplateScaleRange=800,
LOSMapLines=true,
LOSPredictionCone=true,
LOSConeLength=28,
LOSConeAngle=22,
LOSLineLength=20,
-- Combat
Aimbot=false, AimKey="MouseButton2",
AimPart="Auto", -- Auto uses universal resolver
AimFOV=30, AimSmooth=1,
AimPrediction=false, AimPredictionScale=0.5,
AimHumanize=true, AimDeadzone=0,
AimAssist=true, AimAssistStrength=0.25,
SmartAimPart=true,
SilentAim=false, SilentFOV=100, SilentHitChance=100,
TriggerBot=true, TriggerFOV=20, TriggerFOVVisible=true,
TriggerDelay=0.05, TriggerHold=true,
AutoPistol=false, NoRecoil=false,
-- Combat Advanced
PingNormalize=false,
TickRateCompensate=false,
FlickAssist=false,
FlickAssistStrength=0.7,
MultiTargetSuppressor=false,
MultiTargetRadius=3,
AimShakeDampener=false,
AimShakeDampStrength=0.6,
TargetWeightSystem=true,
TargetWeightShootable=true,
TargetWeightDistance=true,
TargetWeightHealth=true,
AntiAimDetect=true,
AntiAimIndicator=true,
AntiLag=false,
AntiLagMode="Compensate", -- "Compensate" | "Match"
AntiLagOffset=0,
Crosshair=true, CrosshairGap=6, CrosshairLength=10,
CrosshairThickness=2, CrosshairDot=true, CrosshairSpin=false,
CrosshairProfile="Classic", CrosshairShootPulse=true,
CrosshairDynamicGap=true, CrosshairAutoSize=true,
ScreenAutoScale=true, ScreenScaleMin=0.72, ScreenScaleMax=1.08,
CrosshairColor=Color3.fromRGB(210,120,255),
FOVVisible=true, FOVRainbow=false, FOVThickness=1, FOVTransparency=1,
TargetLockCircle=true,
UIAccent=Color3.fromRGB(170,80,255),
Glass=true, SoftStrokes=true, ShowPreviews=true, ApplyPopups=true,
ThemePreset="Bright Phantom",
GhostBackground=true, GhostBackgroundOpacity=0.68,
GhostBackgroundImage="rbxassetid://136190147927115",
BackgroundMode="Ghost Drift", IdleGlow=true, TabTransition="Fade",
ProfileCard=false, DockMode=true, DockCompact=true,
DockAutoHide=true, DockAutoHideDelay=3, DockWakeDistance=90,
SearchSpotlight=true, HoverHelp=true, HoverHelpDelay=0.35,
ScannerMaxResults=80, ScannerShowPaths=true,
ScannerPassiveOnly=true, AggressiveScanDepth=true,
AggressiveRiskScoring=true, ScannerWatch=false, ScannerWatchInterval=2,
ScannerGuideMode=true, GhostParallax=true, GhostParallaxStrength=0.025,
ThemeAutoImage=false, AutoSaveSettings=true, AutoLoadSettings=true,
SettingsFile="GhostMenu/settings.json",
ReloadPredictor=true, ReloadStateHUD=true,
OpponentStateDebug=true, OpponentStateDetails=true,
OpponentStateSource=true, OpponentPushDebug=true,
SurroundMapHUD=true, BlindSpotMonitor=true,
SurroundRadius=120, BlindSpotRadius=80, BlindSpotAngle=120,
OpponentPushDetails=true, PushSpeedThreshold=8,
ReloadStateDetails=true, ReloadWarnLowAmmo=true,
Resolver=true,
MiniMap=false, MiniMapSize=160, MiniMapOpacity=0.55,
MiniMapZoom=2, MiniMapTeam=true, MiniMapLabels=false,
MiniMapTrail=true, MiniMapWaypoints=false,
MiniMapGrid=true, MiniMapGridSpacing=20,
}
-- =====================
-- SETTINGS AUTOSAVE
-- =====================
local ghostRuntimeOnlyKeys={Hidden=true,ESP=true}
function ghostCanUseFiles() return type(writefile)=="function" and type(readfile)=="function" end
local ghostLastSettingsPath=""; local ghostLastSaveStatus="not saved yet"
function ghostSettingsPaths()
local p=Config.SettingsFile or "GhostMenu/settings.json"
local t={p}
if p~="GhostMenu/settings.json" then table.insert(t,"GhostMenu/settings.json") end
if p~="GhostMenu_settings.json" then table.insert(t,"GhostMenu_settings.json") end
if p~="settings.json" then table.insert(t,"settings.json") end
return t
end
function ghostConfigToSaveTable()
local copy={}
for k,v in safePairs(Config) do
if not ghostRuntimeOnlyKeys[k] and type(v)~="function" then
if typeof(v)=="Color3" then copy[k]={__color=true,r=v.R,g=v.G,b=v.B}
else copy[k]=v end
end
end
copy.__FavoriteKeys={}
if FavoriteKeys then for k,v in safePairs(FavoriteKeys) do copy.__FavoriteKeys[k]=v end end
copy.__SavedLayout=SavedLayout
copy.__ghost_version="v5.3"
copy.__settings_locked=false
return copy
end
function ghostApplySaveTable(data)
if type(data)~="table" then return false end
for k,v in safePairs(data) do
if type(k)=="string" and string.sub(k,1,2)~="__" and Config[k]~=nil and not ghostRuntimeOnlyKeys[k] then
if type(v)=="table" and v.__color then
Config[k]=Color3.new(tonumber(v.r) or 1,tonumber(v.g) or 1,tonumber(v.b) or 1)
else Config[k]=v end
end
end
if type(data.__FavoriteKeys)=="table" then
FavoriteKeys=FavoriteKeys or {}
for k,v in safePairs(data.__FavoriteKeys) do FavoriteKeys[k]=v end
end
if type(data.__SavedLayout)=="table" then
SavedLayout=SavedLayout or {}
for k,v in safePairs(data.__SavedLayout) do SavedLayout[k]=v end
end
if favoriteStarButtons then for k,_ in safePairs(FavoriteKeys or {}) do pcall(function() favoriteRefreshKey(k) end) end end
if rebuildFavorites then pcall(rebuildFavorites) end
return true
end
function ghostEnsureSettingsFolder()
if type(makefolder)=="function" then
pcall(function()
if type(isfolder)=="function" then
if not isfolder("GhostMenu") then makefolder("GhostMenu") end
else makefolder("GhostMenu") end
end)
end
end
function ghostSaveConfigFile(silent)
if not ghostCanUseFiles() then ghostLastSaveStatus="failed: no writefile"; if not silent then print("Ghost: no writefile") end; return false end
ghostEnsureSettingsFolder()
local ok,json=pcall(function() return HttpService:JSONEncode(ghostConfigToSaveTable()) end)
if not ok then ghostLastSaveStatus="failed: JSON encode"; return false end
for _,path in safeIpairs(ghostSettingsPaths()) do
local wrote=pcall(function() writefile(path,json) end)
if wrote then ghostLastSettingsPath=path; ghostLastSaveStatus="saved: "..path; Config.SettingsFile=path; if not silent then print("Ghost saved: "..path) end; return true end
end
ghostLastSaveStatus="failed: all paths rejected"; return false
end
function ghostLoadConfigFile(silent)
if not ghostCanUseFiles() then return false end
for _,path in safeIpairs(ghostSettingsPaths()) do
local exists=true
if type(isfile)=="function" then exists=isfile(path) end
if exists then
local ok,txt=pcall(function() return readfile(path) end)
if ok and type(txt)=="string" and txt~="" then
local dok,data=pcall(function() return HttpService:JSONDecode(txt) end)
if dok and type(data)=="table" and data.__settings_locked==false and ghostApplySaveTable(data) then
ghostLastSettingsPath=path; ghostLastSaveStatus="loaded: "..path; Config.SettingsFile=path
if not silent then print("Ghost loaded: "..path) end; return true
end
end
end
end
return false
end
local ghostAutoSaveQueued=false
function ghostScheduleAutoSave()
if not Config.AutoSaveSettings or ghostAutoSaveQueued then return end
ghostAutoSaveQueued=true
task.delay(0.75,function() ghostAutoSaveQueued=false; if Config.AutoSaveSettings and not ghostUnloaded then ghostSaveConfigFile(true) end end)
end
if Config.AutoLoadSettings then pcall(function() ghostLoadConfigFile(true) end) end
task.spawn(function() while task.wait(5) do if Config and Config.AutoSaveSettings and not ghostUnloaded then pcall(function() ghostSaveConfigFile(true) end) end end end)
-- =====================
-- STATE
-- =====================
local ESPObjects={}
local CHLines={}
local CHDot=nil
local FOVCircle=nil; local SACircle=nil; local TriggerCircle=nil
local AimCircle=nil; local AimLine=nil; local ReloadLbl=nil
local OffArrows={}
local resolverData={}
local trackedHumanoids={}
local lastShot=0; local triggerHolding=false
local menuVisible=true; local dragging=false; local currentTab="Combat"
local aimAssistConn=nil; local autoPistolConn=nil; local recoilConn=nil
local reloadConnections={}
local lastTarget=nil; local arrowBuckets={}
local topInfoText=nil; local topInfoShadow=nil
local targetInfoText=nil; local targetInfoShadow=nil
local surroundText=nil; local surroundShadow=nil
local blindText=nil; local blindShadow=nil
local TargetLock=nil
local MiniMapFrame=nil; local MiniMapDots={}; local MiniMapWaypoints={}
local MiniMapTrail={}; local lastMiniMapTrail=0; local MiniMapDragging=false
-- LoS map drawings pool
local LOSLines={}; local LOSCones={}
local ghostUnloaded=false; local mouseDown=false
-- Anti-aim detection state
local antiAimData={} -- [player]={lastYaws={},spinDetected=false,flipDetected=false}
local antiAimIndicator=nil -- Drawing.Text
-- Aim shake dampener
local camHistory={}; local CAM_HISTORY=8
-- Tick rate detection
local tickRateSmooth=60; local tickRateSamples={}
-- Flick state
local flickActive=false; local flickTarget=nil; local flickDone=false
menuBlocksInput=function() return ghostUnloaded or menuVisible or Config.Hidden end
-- =====================
-- DRAWING FACTORY
-- =====================
function dnew(class,props)
if not Drawing then return nil end
local o=Drawing.new(class)
for k,v in safePairs(props or {}) do o[k]=v end
return o
end
function worldToScreen(pos)
local v,on=camera:WorldToViewportPoint(pos)
return Vector2.new(v.X,v.Y),on,v.Z
end
function visibleFromCamera(part,ignore)
if not Config.WallCheck then return true end
if not part then return false end
local origin=camera.CFrame.Position
local dir=part.Position-origin
local params=RaycastParams.new()
params.FilterType=Enum.RaycastFilterType.Blacklist
params.FilterDescendantsInstances={lp.Character,ignore}
params.IgnoreWater=true
local hit=Workspace:Raycast(origin,dir,params)
return (not hit) or hit.Instance:IsDescendantOf(ignore)
end
function validEnemy(p)
if not p or p==lp then return false end
if Config.TeamCheck and isTeammate(p) then return false end
if not isAlive(p) then return false end
local r=getRoot(p)
if not r then return false end
if (r.Position-camera.CFrame.Position).Magnitude>Config.DistanceLimit then return false end
return true
end
-- =====================
-- TARGET WEIGHT SYSTEM
-- Priority: shootable + distance, then health
-- =====================
function scoreTarget(p, part, screenDist)
if not Config.TargetWeightSystem then return -screenDist end
local score = 0
local ch = getChar(p)
-- 1. Shootable (wall check) - highest weight
if Config.TargetWeightShootable then
if visibleFromCamera(part, ch) then score = score + 10000 end
end
-- 2. Distance - second weight (closer = higher score)
if Config.TargetWeightDistance then
local r = getRoot(p)
local worldDist = r and (r.Position - camera.CFrame.Position).Magnitude or 9999
score = score + (Config.DistanceLimit - worldDist) * 5
end
-- 3. Health - third weight (lower health = higher score, easier kill)
if Config.TargetWeightHealth then
local hum = getHum(p)
if hum then
local hpPct = hum.Health / math.max(hum.MaxHealth, 1)
score = score + (1 - hpPct) * 1000
end
end
return score
end
-- =====================
-- UNIVERSAL AIM PART
-- Finds best aim target on any rig
-- =====================
function getAimPart(p)
local ch = getChar(p); if not ch then return nil end
local rig = resolveRig(ch); if not rig then return nil end
if Config.AimPart == "Head" then return rig.head or rig.torso end
if Config.AimPart == "Torso" then return rig.torso end
if Config.AimPart == "Root" then return rig.root end
-- Auto: prefer head if visible, else torso, else any visible part
local mouse = UIS:GetMouseLocation()
local candidates = {
{part=rig.head, priority=3},
{part=rig.torso, priority=2},
{part=rig.root, priority=1},
}
local best, bestScore = nil, -math.huge
for _,c in ipairs(candidates) do
if c.part then
local visible = visibleFromCamera(c.part, ch)
local scr,on,z = worldToScreen(c.part.Position)
if on and z > 0 then
local screenDist = (scr - mouse).Magnitude
local s = c.priority * 100 + (visible and 500 or 0) - screenDist
if s > bestScore then bestScore=s; best=c.part end
end
end
end
if best then return best end
-- Fallback: scan all parts
local bestPart, bestDist = nil, math.huge
for _,part in ipairs(rig.parts) do
if visibleFromCamera(part, ch) then
local scr,on,z = worldToScreen(part.Position)
if on and z > 0 then
local d = (scr - mouse).Magnitude
if d < bestDist then bestDist=d; bestPart=part end
end
end
end
return bestPart or rig.root
end
function predictedPos(p, part, scale)
if not part then return nil end
local basePos = part.Position
-- Anti-lag: offset position to compensate for latency
if Config.AntiLag and part:IsA("BasePart") then
local vel = part.AssemblyLinearVelocity or Vector3.zero
local ping = getPing() / 1000
if Config.AntiLagMode == "Compensate" then
-- Lead target by ping time to compensate for your shot delay
basePos = basePos + vel * ping
elseif Config.AntiLagMode == "Match" then
-- Match lag: aim where they WERE ping ms ago (for server-side hit reg)
basePos = basePos - vel * ping
end
-- Additional manual offset
if Config.AntiLagOffset ~= 0 then
basePos = basePos + vel.Unit * Config.AntiLagOffset * 0.01
end
end
if not Config.AimPrediction then return basePos end
local vel = part.AssemblyLinearVelocity or Vector3.zero
local ping = getPing() / 1000
-- Tick rate compensation: adjust prediction step to match server tick
local tickAdj = 1.0
if Config.TickRateCompensate and tickRateSmooth > 0 then
tickAdj = 60 / tickRateSmooth
end
return basePos + vel * ((scale or Config.AimPredictionScale) + ping * 0.5) * tickAdj
end
-- =====================
-- CLOSEST TARGET (weighted)
-- =====================
function closestTarget(fov, needVisible)
local best, bestScore, bestPart = nil, -math.huge, nil
local mouse = UIS:GetMouseLocation()
for _,p in safeIpairs(Players:GetPlayers()) do
if validEnemy(p) then
local part = getAimPart(p)
if part and (not needVisible or visibleFromCamera(part, getChar(p))) then
local pos = predictedPos(p, part)
if pos then
local scr,on,z = worldToScreen(pos)
if on and z > 0 then
local screenDist = (scr - mouse).Magnitude
if screenDist < (fov or Config.AimFOV) then
local s = scoreTarget(p, part, screenDist)
if s > bestScore then
bestScore=s; best=p; bestPart=part
end
end
end
end
end
end
end
return best, bestPart, bestScore
end
-- =====================
-- ANTI-AIM DETECTION
-- =====================
local ANTIAIM_SPIN_THRESHOLD = math.rad(90) -- >90 deg/frame = spinbot
local ANTIAIM_FLIP_THRESHOLD = math.rad(150) -- >150 deg flip = flip bot
local ANTIAIM_HISTORY = 6
function updateAntiAimDetection()
if not Config.AntiAimDetect then
for _,p in pairs(Players:GetPlayers()) do
if antiAimData[p] then antiAimData[p] = nil end
end
return
end
for _,p in safeIpairs(Players:GetPlayers()) do
if p ~= lp and validEnemy(p) then
local ch = getChar(p)
local rig = ch and resolveRig(ch)
if rig and rig.root then
local _,yaw,_ = rig.root.CFrame:ToEulerAnglesYXZ()
local data = antiAimData[p] or {lastYaws={}, spinDetected=false, flipDetected=false, timer=0}
table.insert(data.lastYaws, yaw)
if #data.lastYaws > ANTIAIM_HISTORY then table.remove(data.lastYaws, 1) end
-- Detect spin: large yaw delta each frame
if #data.lastYaws >= 2 then
local delta = math.abs(data.lastYaws[#data.lastYaws] - data.lastYaws[#data.lastYaws-1])
-- Normalize to 0-pi
while delta > math.pi do delta = delta - math.pi*2 end
delta = math.abs(delta)
data.spinDetected = delta > ANTIAIM_SPIN_THRESHOLD
data.flipDetected = delta > ANTIAIM_FLIP_THRESHOLD
end
data.timer = now()
antiAimData[p] = data
end
end
end
-- Cleanup stale
for p,_ in safePairs(antiAimData) do
if not Players:FindFirstChild(p.Name) then antiAimData[p] = nil end
end
end
function isAntiAiming(p)
local d = antiAimData[p]
return d and (d.spinDetected or d.flipDetected)
end
function getAntiAimType(p)
local d = antiAimData[p]
if not d then return nil end
if d.flipDetected then return "FLIP" end
if d.spinDetected then return "SPIN" end
return nil
end
-- =====================
-- AIM SHAKE DAMPENER
-- Smooths out game-induced camera shake before aim runs
-- =====================
function getDampenedCameraLook()
local cf = camera.CFrame
table.insert(camHistory, cf)
if #camHistory > CAM_HISTORY then table.remove(camHistory, 1) end
if not Config.AimShakeDampener or #camHistory < 3 then return cf end
-- Average look vectors to remove high-frequency shake
local avgLook = Vector3.zero
local avgPos = Vector3.zero
local w = 0
for i,c in ipairs(camHistory) do
local weight = i -- more recent = higher weight
avgLook = avgLook + c.LookVector * weight
avgPos = avgPos + c.Position * weight
w = w + weight
end
avgLook = (avgLook / w)
avgPos = avgPos / w
local strength = Config.AimShakeDampStrength or 0.6
local smoothedLook = cf.LookVector:Lerp(avgLook, strength)
if smoothedLook.Magnitude < 0.001 then return cf end
return CFrame.new(cf.Position, cf.Position + smoothedLook.Unit)
end
-- =====================
-- TICK RATE DETECTOR
-- =====================
local lastTickSample = now()
RunService.Heartbeat:Connect(function()
local t = now()
local dt = t - lastTickSample
lastTickSample = t
table.insert(tickRateSamples, dt)
if #tickRateSamples > 60 then table.remove(tickRateSamples, 1) end
if #tickRateSamples > 10 then
local avg = 0
for _,v in ipairs(tickRateSamples) do avg = avg + v end
avg = avg / #tickRateSamples
tickRateSmooth = tickRateSmooth * 0.9 + (1/math.max(avg,0.001)) * 0.1
end
end)
-- =====================
-- DRAWING SETUP
-- =====================
if Drawing then
FOVCircle = dnew("Circle",{Radius=Config.SilentFOV,Thickness=1,Color=GhostControlFill,Transparency=0.55,Filled=false,Visible=true})
SACircle = dnew("Circle",{Radius=Config.AimFOV,Thickness=1,Color=Color3.fromRGB(90,220,255),Transparency=0.35,Filled=false,Visible=true})
TriggerCircle= dnew("Circle",{Radius=Config.TriggerFOV,Thickness=1,Color=Color3.fromRGB(255,190,70),Transparency=0.45,Filled=false,Visible=false})
AimCircle = dnew("Circle",{Radius=3,Thickness=1,Color=Color3.fromRGB(255,255,255),Transparency=1,Filled=true,Visible=false})
AimLine = dnew("Line", {Thickness=1,Color=Color3.fromRGB(255,255,255),Transparency=0.7,Visible=false})
TargetLock = dnew("Circle",{Radius=8,Thickness=2,Color=Color3.fromRGB(90,255,150),Transparency=0.85,Filled=false,Visible=false})
topInfoShadow= dnew("Text", {Text="",Size=13,Center=false,Outline=false,Color=Color3.fromRGB(0,0,0),Transparency=0.75,Visible=false})
topInfoText = dnew("Text", {Text="",Size=13,Center=false,Outline=true, Color=Color3.fromRGB(235,235,255),Transparency=1,Visible=false})
targetInfoShadow=dnew("Text",{Text="",Size=12,Center=true,Outline=false,Color=Color3.fromRGB(0,0,0),Transparency=0.75,Visible=false})
targetInfoText =dnew("Text",{Text="",Size=12,Center=true,Outline=true, Color=Color3.fromRGB(235,255,235),Transparency=1,Visible=false})
ReloadLbl = dnew("Text", {Text="",Size=16,Center=true,Outline=true, Color=Color3.fromRGB(255,210,90),Visible=false})
CHDot = dnew("Circle",{Radius=2,Filled=true,Color=Config.CrosshairColor,Transparency=1,Visible=true})
for i=1,4 do CHLines[i]=dnew("Line",{Thickness=Config.CrosshairThickness,Color=Config.CrosshairColor,Transparency=1,Visible=true}) end
antiAimIndicator = dnew("Text",{Text="",Size=13,Center=true,Outline=true,Color=Color3.fromRGB(255,80,80),Visible=false})
-- Pre-allocate LoS line pool (one per player)
for i=1,20 do
LOSLines[i] = dnew("Line", {Visible=false,Thickness=1,Color=Color3.fromRGB(255,255,80),Transparency=0.55})
LOSCones[i] = dnew("Triangle",{Visible=false,Filled=true,Color=Color3.fromRGB(80,255,120),Transparency=0.82})
end
end
-- =====================
-- ESP OBJECT FUNCTIONS
-- =====================
function newESP(p)
if ESPObjects[p] then return ESPObjects[p] end
local o = {BoneLines={}, DotCircles={}, Highlights={}}
if Drawing then
o.Box = dnew("Square",{Thickness=1,Color=Color3.fromRGB(255,255,255),Transparency=1,Filled=false,Visible=false})
o.BoxFill = dnew("Square",{Thickness=1,Color=Color3.fromRGB(0,0,0),Transparency=0.15,Filled=true,Visible=false})
o.Name = dnew("Text", {Size=14,Center=true,Outline=true,Color=Color3.new(1,1,1),Transparency=0.92,Visible=false})
o.Health = dnew("Line", {Thickness=3,Color=Color3.fromRGB(70,255,120),Visible=false})
o.Tracer = dnew("Line", {Thickness=1,Color=GhostControlFill,Transparency=0.75,Visible=false})
o.Distance= dnew("Text", {Size=13,Center=true,Outline=true,Color=Color3.fromRGB(210,210,210),Transparency=0.92,Visible=false})
o.AntiAimLbl = dnew("Text",{Size=12,Center=true,Outline=true,Color=Color3.fromRGB(255,80,80),Visible=false})
-- Bone lines (max 30 per player for complex rigs)
for i=1,30 do
o.BoneLines[i] = dnew("Line",{Visible=false,Thickness=1,Color=Color3.fromRGB(0,255,80),Transparency=0.55})
end
-- Dot circles (max 20 per player)
for i=1,20 do
o.DotCircles[i] = dnew("Circle",{Radius=4,Filled=true,NumSides=18,Color=Color3.fromRGB(0,255,80),Transparency=1,Visible=false})
end
-- Weapon silhouette (2 lines = simple L shape representing tool)
o.WepSil = {}
for i=1,4 do
o.WepSil[i] = dnew("Line",{Visible=false,Thickness=2,Color=Color3.fromRGB(255,200,80),Transparency=0.65})
end
-- Arrow drawings
o.ArrowShadow = dnew("Triangle",{Color=Color3.fromRGB(0,0,0),Filled=true,Transparency=0.35,Visible=false})
o.ArrowGlow = dnew("Triangle",{Color=Color3.fromRGB(70,255,120),Filled=true,Transparency=0.18,Visible=false})
o.Arrow = dnew("Triangle",{Color=Color3.fromRGB(70,255,120),Filled=true,Transparency=0.92,Visible=false})
o.ArrowRidge = dnew("Line", {Thickness=1,Color=Color3.fromRGB(255,255,255),Transparency=0.7,Visible=false})
o.ArrowLabel = dnew("Text", {Text="",Size=13,Center=true,Outline=true,Color=Color3.fromRGB(230,255,235),Transparency=0.88,Visible=false})
o.ArrowSmooth = nil
end
ESPObjects[p] = o
return o
end
function hideAll(o)
if not o then return end
for _,v in safePairs(o) do
if type(v)=="table" then
for _,x in safePairs(v) do pcall(function() if x and x.Visible~=nil then x.Visible=false end end) end
else pcall(function() if v and v.Visible~=nil then v.Visible=false end end) end
end
end
function removeESP(p)
local o=ESPObjects[p]; if not o then return end
hideAll(o)
for _,v in safePairs(o) do
if type(v)=="table" then for _,x in safePairs(v) do safeRemove(x) end
else safeRemove(v) end
end
ESPObjects[p]=nil
end
function hideArrow(o)
if not o then return end
for _,k in ipairs({"Arrow","ArrowShadow","ArrowGlow","ArrowRidge","ArrowLabel"}) do
if o[k] then o[k].Visible=false end
end
end
function visualFadeByDistance(dist)
if not dist or dist<250 then return 1 end
return clamp(1-((dist-250)/1600),0.28,1)
end
function ghostDistanceColor(dist)
dist=tonumber(dist) or 9999
if dist<=100 then return Color3.fromRGB(255,60,70) end
if dist<=250 then return Color3.fromRGB(255,170,55) end
if dist<=600 then return Color3.fromRGB(210,255,80) end
return Color3.fromRGB(70,255,120)
end
function boxFromCharacter(ch)
local cf,size = ch:GetBoundingBox()
local corners = {}
for x=-1,1,2 do for y=-1,1,2 do for z=-1,1,2 do
table.insert(corners,(cf*CFrame.new(size.X/2*x,size.Y/2*y,size.Z/2*z)).Position)
end end end
local minX,minY,maxX,maxY = math.huge,math.huge,-math.huge,-math.huge
local any=false
for _,p in safeIpairs(corners) do
local s,on=worldToScreen(p)
if on then any=true end
minX=math.min(minX,s.X);minY=math.min(minY,s.Y);maxX=math.max(maxX,s.X);maxY=math.max(maxY,s.Y)
end
return Vector2.new(minX,minY),Vector2.new(maxX-minX,maxY-minY),any
end
-- =====================
-- BONE SKELETON DRAW
-- Universal — uses rig.bones from resolver
-- =====================
function drawBoneSkeleton(p, o, dist)
local ch = getChar(p)
if not ch or not o or not Config.SkeletonESP or menuBlocksInput() then
for _,l in ipairs(o.BoneLines) do l.Visible=false end
return
end
local rig = resolveRig(ch)
if not rig then
for _,l in ipairs(o.BoneLines) do l.Visible=false end
return
end
local fade = Config.SkeletonDistanceFade and visualFadeByDistance(dist) or 1
local bones = rig.bones
local mode = Config.SkeletonMode or "Bone"
-- Draw bone lines
local lineIdx = 0
if mode == "Bone" or mode == "Both" then
for _,bone in ipairs(bones) do
lineIdx = lineIdx + 1
if lineIdx > #o.BoneLines then break end
local pA, pB = bone[1], bone[2]
local sA, onA, zA = worldToScreen(pA.Position)
local sB, onB, zB = worldToScreen(pB.Position)
local line = o.BoneLines[lineIdx]
if onA and onB and zA > 0 and zB > 0 then
local visA = visibleFromCamera(pA, ch)
local visB = visibleFromCamera(pB, ch)
line.From = sA
line.To = sB
line.Color = (visA and visB) and Color3.fromRGB(0,255,80) or Color3.fromRGB(255,60,70)
line.Transparency = clamp(0.55 + (1-fade)*0.3, 0.3, 0.85)
line.Thickness = 1
line.Visible = true
else
line.Visible = false
end
end
end
for i=lineIdx+1,#o.BoneLines do o.BoneLines[i].Visible=false end
-- Draw dot circles
local dotIdx = 0
if mode == "Dots" or mode == "Both" then
for _,part in ipairs(rig.parts) do
dotIdx = dotIdx + 1
if dotIdx > #o.DotCircles then break end
local scr,on,z = worldToScreen(part.Position)
local dot = o.DotCircles[dotIdx]
if on and z > 0 then
local vis = visibleFromCamera(part, ch)
dot.Position = scr
dot.Radius = clamp(4.3 - z*0.006, 1.1, 4.3)
dot.Color = vis and Color3.fromRGB(0,255,80) or Color3.fromRGB(255,60,70)
dot.Transparency= vis and clamp(0.92+(fade-1)*0.25,0.65,1) or clamp(0.72+(fade-1)*0.25,0.45,0.9)
dot.Visible = true
else dot.Visible = false end
end
end
for i=dotIdx+1,#o.DotCircles do o.DotCircles[i].Visible=false end
end
-- =====================
-- WEAPON SILHOUETTE
-- Draws a small L-shape icon near the player to represent held tool
-- =====================
function drawWeaponSilhouette(p, o, screenPos, screenSize)
if not Config.WeaponSilhouette then
if o.WepSil then for _,l in ipairs(o.WepSil) do l.Visible=false end end
return
end
if not o.WepSil then return end
local ch = getChar(p)
local tool = nil
if ch then for _,v in pairs(ch:GetChildren()) do if v:IsA("Tool") then tool=v;break end end end
if not tool then
for _,l in ipairs(o.WepSil) do l.Visible=false end
return
end
-- Draw simple silhouette at bottom-right of bounding box
-- Shape: stock | barrel — two lines making a gun profile
local ox = screenPos.X + screenSize.X/2 + 8
local oy = screenPos.Y + screenSize.Y - 4
local col = Color3.fromRGB(255,200,80)
-- Barrel (horizontal)
o.WepSil[1].From=Vector2.new(ox,oy); o.WepSil[1].To=Vector2.new(ox+14,oy)
o.WepSil[1].Color=col; o.WepSil[1].Visible=true
-- Stock (angled down-left)
o.WepSil[2].From=Vector2.new(ox,oy); o.WepSil[2].To=Vector2.new(ox-4,oy+7)
o.WepSil[2].Color=col; o.WepSil[2].Visible=true
-- Grip (vertical short)
o.WepSil[3].From=Vector2.new(ox+4,oy); o.WepSil[3].To=Vector2.new(ox+4,oy+6)
o.WepSil[3].Color=col; o.WepSil[3].Visible=true
-- Suppressor tip (tiny)
o.WepSil[4].From=Vector2.new(ox+14,oy-2); o.WepSil[4].To=Vector2.new(ox+14,oy+2)
o.WepSil[4].Color=col; o.WepSil[4].Visible=true
end
-- =====================
-- OFFSCREEN ARROWS (unchanged from previous build)
-- =====================
function drawOffscreen(p, o)
if not o.Arrow then return end
if not Config.OffscreenArrows or not Config.ESP or menuBlocksInput() then
hideArrow(o); return
end
local r=getRoot(p); local ch=getChar(p); local myRoot=getRoot(lp)
if not r or not ch or not myRoot then hideArrow(o); return end
local raw,on,z=worldToScreen(r.Position)
local vp=camera.ViewportSize
local center=Vector2.new(vp.X/2,vp.Y/2)
local margin=Config.ArrowPadding or 42
local topMargin=math.max(74,margin)
local projected=Vector2.new(raw.X,raw.Y)
local dir=projected-center
if z<0 then dir=-dir end
if dir.Magnitude<1 then local rel=camera.CFrame:PointToObjectSpace(r.Position); dir=Vector2.new(rel.X,-rel.Y) end
if dir.Magnitude<1 then dir=Vector2.new(1,0) end
dir=dir.Unit
if z>0 and projected.X>margin and projected.X<vp.X-margin and projected.Y>topMargin and projected.Y<vp.Y-margin then
hideArrow(o); return
end
local tx,ty=math.huge,math.huge
if dir.X>0 then tx=(vp.X-margin-center.X)/dir.X elseif dir.X<0 then tx=(margin-center.X)/dir.X end
if dir.Y>0 then ty=(vp.Y-margin-center.Y)/dir.Y elseif dir.Y<0 then ty=(topMargin-center.Y)/dir.Y end
local tEdge=math.min(math.abs(tx),math.abs(ty))
if tEdge==math.huge or tEdge~=tEdge then tEdge=math.min(vp.X,vp.Y)*0.42 end
local targetPos=center+dir*tEdge
targetPos=Vector2.new(clamp(targetPos.X,margin,vp.X-margin),clamp(targetPos.Y,topMargin,vp.Y-margin))
local angle=math.atan2(dir.Y,dir.X)
local bucket=math.floor(((angle+math.pi)/(math.pi*2))*48+0.5)
arrowBuckets[bucket]=(arrowBuckets[bucket] or 0)+1
local stackIndex=arrowBuckets[bucket]
if Config.ArrowSmartStack and stackIndex>1 then
local tangent=Vector2.new(-dir.Y,dir.X)
local side=((stackIndex%2==0) and 1 or -1)
local tier=math.ceil((stackIndex-1)/2)
local offset=clamp(tier*13,-52,52)*side
local radial=dir*clamp(tier*3,0,14)
targetPos=targetPos+tangent*offset-radial
targetPos=Vector2.new(clamp(targetPos.X,margin,vp.X-margin),clamp(targetPos.Y,topMargin,vp.Y-margin))
end
o.ArrowSmooth=o.ArrowSmooth and o.ArrowSmooth:Lerp(targetPos,0.22) or targetPos
local p2=o.ArrowSmooth
local lookPart=ch:FindFirstChild("Head") or r
local toMe=myRoot.Position-lookPart.Position
local lookingAtMe=false; local canSeeMe=false
if toMe.Magnitude>0 then
lookingAtMe=lookPart.CFrame.LookVector:Dot(toMe.Unit)>0.72
local params=RaycastParams.new(); params.FilterType=Enum.RaycastFilterType.Blacklist
params.FilterDescendantsInstances={ch,lp.Character}; params.IgnoreWater=true
local hit=Workspace:Raycast(lookPart.Position,toMe,params); canSeeMe=not hit
end
local dist=(r.Position-camera.CFrame.Position).Magnitude
local verticalDelta=r.Position.Y-myRoot.Position.Y
local verticalTag=""
if Config.ArrowVerticalHints and math.abs(verticalDelta)>=(Config.ArrowVerticalThreshold or 18) then
verticalTag=(verticalDelta>0) and "UP" or "DOWN"
end
local far=dist>900
local pulse=(Config.ArrowThreatPulse and lookingAtMe and canSeeMe) and (math.sin(tick()*8)*2.5) or 0
local size=clamp((Config.ArrowSize or 16)-(dist/300)+pulse,10,22)
local spread=size*0.58; local perp=Vector2.new(-dir.Y,dir.X)
local color=ghostDistanceColor(dist)
if lookingAtMe and canSeeMe then color=Color3.fromRGB(255,60,70) end
local alpha=far and 0.42 or 0.92
local tip=p2+dir*size; local base=p2-dir*(size*0.78)
local left=base+perp*spread; local right=base-perp*spread
local shadowOffset=Vector2.new(3,3)
local glowSize=size*1.28; local glowSpread=spread*1.25
local glowTip=p2+dir*glowSize; local glowBase=p2-dir*(glowSize*0.78)
if o.ArrowGlow then
o.ArrowGlow.PointA=glowTip; o.ArrowGlow.PointB=glowBase+perp*glowSpread; o.ArrowGlow.PointC=glowBase-perp*glowSpread
o.ArrowGlow.Color=color; o.ArrowGlow.Transparency=far and 0.13 or 0.24; o.ArrowGlow.Visible=true
end
if o.ArrowShadow then
o.ArrowShadow.PointA=tip+shadowOffset; o.ArrowShadow.PointB=left+shadowOffset; o.ArrowShadow.PointC=right+shadowOffset
o.ArrowShadow.Color=Color3.fromRGB(0,0,0); o.ArrowShadow.Transparency=0.36; o.ArrowShadow.Visible=true
end
o.Arrow.PointA=tip; o.Arrow.PointB=left; o.Arrow.PointC=right
o.Arrow.Color=color; o.Arrow.Transparency=alpha; o.Arrow.Visible=true
if o.ArrowRidge then
o.ArrowRidge.From=p2-dir*(size*0.25); o.ArrowRidge.To=tip-dir*(size*0.18)
o.ArrowRidge.Color=Color3.fromRGB(255,255,255); o.ArrowRidge.Transparency=far and 0.25 or 0.55
o.ArrowRidge.Thickness=1; o.ArrowRidge.Visible=true
end
if o.ArrowLabel then
local labelMode=Config.ArrowLabelMode or "Distance"
local distText=tostring(math.floor(dist)).."m"
local vText=(verticalTag~="") and (" "..verticalTag.." "..tostring(math.floor(math.abs(verticalDelta))).."m") or ""
if labelMode=="Threat" and lookingAtMe and canSeeMe then o.ArrowLabel.Text="THREAT"..vText
elseif labelMode=="Threat" and verticalTag~="" then o.ArrowLabel.Text=verticalTag.." "..tostring(math.floor(math.abs(verticalDelta))).."m"
else o.ArrowLabel.Text=distText..vText end
o.ArrowLabel.Position=p2-dir*(size+22)+Vector2.new(0,2)
o.ArrowLabel.Color=color; o.ArrowLabel.Transparency=far and 0.55 or 0.88; o.ArrowLabel.Visible=labelMode~="Off"
end
end
-- =====================
-- MULTI-TARGET SUPPRESSOR
-- When 3+ enemies in screen FOV, widen aim and pick closest shootable
-- =====================
function getMultiTargetCount()
local count = 0
local vp = camera.ViewportSize
local center = Vector2.new(vp.X/2, vp.Y/2)
for _,p in safeIpairs(Players:GetPlayers()) do
if validEnemy(p) then
local r = getRoot(p)
if r then
local scr,on,z = worldToScreen(r.Position)
if on and z > 0 and (scr-center).Magnitude < Config.AimFOV * (Config.MultiTargetRadius or 3) then
count = count + 1
end
end
end
end
return count
end
-- =====================
-- FLICK ASSIST
-- Single fast flick to bring target into FOV, then hands back to smooth assist
-- =====================
function tryFlickAssist()
if not Config.FlickAssist or menuBlocksInput() then flickActive=false; return end
if flickActive and flickDone then flickActive=false; flickDone=false; return end
-- Find nearest target outside current FOV but within 3x FOV
local mouse = UIS:GetMouseLocation()
local best, bestDist, bestPart = nil, math.huge, nil
for _,p in safeIpairs(Players:GetPlayers()) do
if validEnemy(p) then
local part = getAimPart(p)
if part then
local scr,on,z = worldToScreen(part.Position)
if on and z > 0 then
local d = (scr - mouse).Magnitude
if d > Config.AimFOV and d < Config.AimFOV * 3 and d < bestDist then
bestDist=d; best=p; bestPart=part
end
end
end
end
end
if best and bestPart and not flickActive then
flickActive = true; flickDone = false; flickTarget = best
local scr,on,z = worldToScreen(bestPart.Position)
if on and z > 0 then
local delta = scr - mouse
local strength = Config.FlickAssistStrength or 0.7
pcall(function() mousemoverel(delta.X * strength, delta.Y * strength) end)
task.delay(0.12, function() flickDone = true end)
end
end
end
-- =====================
-- MAIN ESP UPDATE
-- =====================
local losLineIdx = 0; local losConeIdx = 0
function updateESP()
arrowBuckets = {}
losLineIdx = 0
losConeIdx = 0
local antiAimLabelTargets = {}
for _,p in safeIpairs(Players:GetPlayers()) do
if p ~= lp then
local o = newESP(p)
if Config.ESP and validEnemy(p) and not menuBlocksInput() then
local ch=getChar(p); local hum=getHum(p); local root=getRoot(p)
local rig = ch and resolveRig(ch)
local topLeft,size,on=boxFromCharacter(ch)
if on and root then
local dist=(root.Position-camera.CFrame.Position).Magnitude
local col=visibleFromCamera(rig and rig.head or root,ch) and Color3.fromRGB(120,255,170) or Color3.fromRGB(255,90,90)
o.Box.Position=topLeft;o.Box.Size=size;o.Box.Color=col;o.Box.Visible=Config.BoxESP
o.BoxFill.Position=topLeft;o.BoxFill.Size=size;o.BoxFill.Visible=Config.BoxESP and Config.Glass
local stackMode=Config.ESPStackMode or "Clean"
local hp=hum.Health/math.max(hum.MaxHealth,1)
local fade=visualFadeByDistance(dist)
local centerX=topLeft.X+size.X/2
local topY=topLeft.Y; local bottomY=topLeft.Y+size.Y
local showName=Config.NameESP and Config.ESPNameOptional and dist<650
-- Nameplate distance scaling
local nameSize = Config.NameplateMaxSize or 14
if Config.NameplateDistanceScale then
local minS = Config.NameplateMinSize or 9
local maxS = Config.NameplateMaxSize or 14
local range= Config.NameplateScaleRange or 800
nameSize = clamp(lerp(maxS, minS, dist/range), minS, maxS)
end
o.Name.Text=p.Name; o.Name.Size=nameSize
o.Name.Position=Vector2.new(centerX,topY-20)
o.Name.Color=Color3.fromRGB(245,245,250)
o.Name.Transparency=clamp(0.68+fade*0.28,0.62,0.95)
o.Name.Visible=showName and stackMode~="Minimal"
o.Health.From=Vector2.new(topLeft.X-6,bottomY)
o.Health.To=Vector2.new(topLeft.X-6,topY+size.Y*(1-hp))
o.Health.Color=Color3.fromRGB(255*(1-hp),255*hp,95)
o.Health.Transparency=clamp(0.52+fade*0.42,0.4,0.95)
o.Health.Thickness=(stackMode=="Compact") and 2 or 3
o.Health.Visible=Config.HealthESP
o.Distance.Text=(Config.HealthESP and stackMode=="Clean") and (math.floor(hum.Health).." HP | "..math.floor(dist).."m") or (math.floor(dist).."m")
o.Distance.Position=Vector2.new(centerX,bottomY+((stackMode=="Compact") and 4 or 7))
o.Distance.Color=ghostDistanceColor(dist)
o.Distance.Transparency=clamp(0.72+fade*0.22,0.65,0.94)
o.Distance.Visible=(Config.DistanceESP or (Config.HealthESP and stackMode=="Clean")) and dist<(Config.DetailMaxDistance or 1800)
o.Tracer.From=Vector2.new(camera.ViewportSize.X/2,camera.ViewportSize.Y)
o.Tracer.To=Vector2.new(topLeft.X+size.X/2,topLeft.Y+size.Y)
o.Tracer.Color=col; o.Tracer.Visible=Config.TracerESP
-- Bone skeleton
drawBoneSkeleton(p, o, dist)
-- Weapon silhouette
drawWeaponSilhouette(p, o, topLeft, size)
-- Anti-aim indicator above nameplate
local aaType = isAntiAiming(p) and getAntiAimType(p)
if aaType and Config.AntiAimIndicator then
o.AntiAimLbl.Text = "AA:"..aaType
o.AntiAimLbl.Position = Vector2.new(centerX, topY - 34)
o.AntiAimLbl.Visible = true
else o.AntiAimLbl.Visible = false end
hideArrow(o)
else
hideAll(o)
-- Clear bone/dot lines explicitly
for _,l in ipairs(o.BoneLines) do l.Visible=false end
for _,d in ipairs(o.DotCircles) do d.Visible=false end
drawOffscreen(p, o)
end
else
hideAll(o)
end
end
end
-- Global anti-aim indicator (center of screen warning)
if antiAimIndicator then
local spinning = {}
for _,p in safeIpairs(Players:GetPlayers()) do
if p ~= lp and isAntiAiming(p) then
table.insert(spinning, p.Name.."("..( getAntiAimType(p) or "?")..")")
end
end
if #spinning > 0 and Config.AntiAimDetect and Config.AntiAimIndicator and not menuBlocksInput() then
local vp = camera.ViewportSize
antiAimIndicator.Text = "AA DETECTED: "..table.concat(spinning,", ")
antiAimIndicator.Position = Vector2.new(vp.X/2, 22)
antiAimIndicator.Visible = true
else antiAimIndicator.Visible = false end
end
end
-- =====================
-- CHAMS
-- =====================
function applyChams(p,ch)
if not ch or ch:FindFirstChild("GhostCham") then return end
local h=Instance.new("Highlight")
h.Name="GhostCham";h.FillTransparency=0.65;h.OutlineTransparency=0
h.FillColor=Color3.fromRGB(170,80,255);h.OutlineColor=Color3.fromRGB(255,255,255)
h.Parent=ch
end
function updateChams()
for _,p in safeIpairs(Players:GetPlayers()) do
local ch=getChar(p)
if p~=lp and ch then
local h=ch:FindFirstChild("GhostCham")
if Config.Chams and Config.ESP and validEnemy(p) and not Config.Hidden then
if not h then applyChams(p,ch) end
elseif h then h:Destroy() end
end
end
end
-- =====================
-- RESOLVER TRACKING
-- =====================
function trackCharacter(p)
local r=getRoot(p); if not r then return end
resolverData[p]=resolverData[p] or {last=r.Position,vel=Vector3.zero,t=now()}
end
function updateResolver()
for _,p in safeIpairs(Players:GetPlayers()) do
local r=getRoot(p)
if p~=lp and r then
local d=resolverData[p] or {last=r.Position,t=now(),vel=Vector3.zero}
local dt=math.max(now()-d.t,1/60)
d.vel=(r.Position-d.last)/dt; d.last=r.Position; d.t=now()
resolverData[p]=d
end
end
updateAntiAimDetection()
end
function setupHitDetection(p)
local h=getHum(p); if not h or trackedHumanoids[h] then return end
trackedHumanoids[h]=h.Health
h.HealthChanged:Connect(function(new)
trackedHumanoids[h]=new
end)
end
function onPlayerAdded(p)
p.CharacterAdded:Connect(function(char)
task.wait(0.5)
rigCache[char] = nil -- clear rig cache on respawn
if Config.Chams then applyChams(p,char) end
trackCharacter(p); setupHitDetection(p)
end)
end
for _,p in safeIpairs(Players:GetPlayers()) do onPlayerAdded(p) end
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(function(p)
removeESP(p); resolverData[p]=nil; antiAimData[p]=nil
local ch=getChar(p); if ch then rigCache[ch]=nil end
end)
-- =====================
-- BLUR + GUI
-- =====================
local menuBlur=Instance.new("BlurEffect")
menuBlur.Size=0; menuBlur.Parent=Lighting; menuBlur.Enabled=false
local ScreenGui=Instance.new("ScreenGui")
ScreenGui.Name="GhostMenu_v5"; ScreenGui.Parent=CoreGui
ScreenGui.ResetOnSpawn=false; ScreenGui.ZIndexBehavior=Enum.ZIndexBehavior.Sibling
-- =====================
-- DOCK
-- =====================
local Dock=nil; local lastDockHover=0; local dockFadeHidden=false
function updateDockAutoHide()
if not Dock then return end
if not Config.DockMode or Config.Hidden or ghostUnloaded then Dock.Visible=false; return end
if menuVisible then dockFadeHidden=false; return end
Dock.Visible=true
if Config.DockAutoHide then
local mouse=UIS:GetMouseLocation()
local center=Vector2.new(Dock.AbsolutePosition.X+Dock.AbsoluteSize.X/2,Dock.AbsolutePosition.Y+Dock.AbsoluteSize.Y/2)
local near=(mouse-center).Magnitude<=(Config.DockWakeDistance or 90)
if near then lastDockHover=now(); dockFadeHidden=false
elseif now()-lastDockHover>=(Config.DockAutoHideDelay or 3) then dockFadeHidden=true end
else dockFadeHidden=false end
end
function updateDockStyle()
if not Dock then return end
Dock.BackgroundColor3=Color3.fromRGB(9,6,20)
local st=Dock:FindFirstChild("Stroke"); if st then st.Color=Config.UIAccent end
local targetHidden=dockFadeHidden and Config.DockAutoHide and not menuVisible
Dock.BackgroundTransparency=targetHidden and 0.86 or 0.06
for _,child in safeIpairs(Dock:GetChildren()) do
if child:IsA("TextButton") then
child.BackgroundTransparency=targetHidden and 0.72 or 0.08
child.TextTransparency=targetHidden and 0.55 or 0
end
end
end
function setDockVisible(state)
if Dock then
Dock.Visible=state and Config.DockMode and not ghostUnloaded and not Config.Hidden
if Dock.Visible then lastDockHover=now(); dockFadeHidden=false end
end
end
function makeDockButton(parent,text,w,callback)
local b=Instance.new("TextButton",parent)
b.Size=UDim2.new(0,w or 58,1,-12); b.Position=UDim2.new(0,0,0,6)
b.BackgroundColor3=Color3.fromRGB(22,10,38); b.BackgroundTransparency=0.08
b.Text=text; b.Font=Enum.Font.GothamBlack; b.TextSize=11
b.TextColor3=Color3.fromRGB(245,245,250); b.AutoButtonColor=false; b.ZIndex=141
Instance.new("UICorner",b).CornerRadius=UDim.new(0,10)
local s=Instance.new("UIStroke",b); s.Color=Config.UIAccent; s.Transparency=0.58
b.MouseButton1Click:Connect(function() callback(); ghostScheduleAutoSave() end)
return b
end
function createDock()
if Dock then return end
Dock=Instance.new("Frame",ScreenGui)
Dock.Name="GhostDock"; Dock.Size=UDim2.new(0,430,0,48)
Dock.Position=UDim2.new(0.5,-215,1,-72)
Dock.BackgroundColor3=Color3.fromRGB(9,6,20); Dock.BackgroundTransparency=0.06
Dock.BorderSizePixel=0; Dock.Visible=false; Dock.ZIndex=140
Instance.new("UICorner",Dock).CornerRadius=UDim.new(0,18)
local st=Instance.new("UIStroke",Dock); st.Name="Stroke"; st.Color=Config.UIAccent; st.Transparency=0.25; st.Thickness=1.2
local layout=Instance.new("UIListLayout",Dock)
layout.FillDirection=Enum.FillDirection.Horizontal
layout.HorizontalAlignment=Enum.HorizontalAlignment.Center
layout.VerticalAlignment=Enum.VerticalAlignment.Center
layout.Padding=UDim.new(0,8)
local pad=Instance.new("UIPadding",Dock); pad.PaddingLeft=UDim.new(0,8); pad.PaddingRight=UDim.new(0,8)
makeDockButton(Dock,"GHOST",70,function()
menuVisible=true; Config.Hidden=false; Root.Visible=true; setDockVisible(false)
if _G.GhostShowTab then _G.GhostShowTab(currentTab or "Favorited") end
end)
makeDockButton(Dock,"FAV",52,function()
menuVisible=true; Config.Hidden=false; Root.Visible=true; setDockVisible(false)
if _G.GhostShowTab then _G.GhostShowTab("Favorited") end
end)
makeDockButton(Dock,"THEME",66,function()
menuVisible=true; Config.Hidden=false; Root.Visible=true; setDockVisible(false)
if _G.GhostShowTab then _G.GhostShowTab("Theme Studio") end
end)
makeDockButton(Dock,"NOTES",62,function()
menuVisible=true; Config.Hidden=false; Root.Visible=true; setDockVisible(false)
if _G.GhostShowTab then _G.GhostShowTab("Notes") end
end)
makeDockButton(Dock,"HIDE",58,function()
menuVisible=false; Root.Visible=false; setDockVisible(true)
end)
makeDockButton(Dock,"X",42,function()
if _G.GhostUnload then _G.GhostUnload() end
end)
Dock.MouseEnter:Connect(function() lastDockHover=now(); dockFadeHidden=false end)
Dock.MouseLeave:Connect(function() lastDockHover=now() end)
Dock.InputBegan:Connect(function(i)
if i.UserInputType==Enum.UserInputType.MouseButton1 then
local draggingDock=true; local start=i.Position; local startPos=Dock.Position
local conn; conn=UIS.InputChanged:Connect(function(ch)
if draggingDock and ch.UserInputType==Enum.UserInputType.MouseMovement then
local d=ch.Position-start
Dock.Position=UDim2.new(startPos.X.Scale,startPos.X.Offset+d.X,startPos.Y.Scale,startPos.Y.Offset+d.Y)
end
end)
i.Changed:Connect(function() if i.UserInputState==Enum.UserInputState.End then draggingDock=false; if conn then conn:Disconnect() end end end)
end
end)
end
-- =====================
-- ROOT FRAME
-- =====================
local Root=Instance.new("Frame")
Root.Name="Root"; Root.Parent=ScreenGui; Root.AnchorPoint=Vector2.new(0.5,0.5)
Root.Size=UDim2.new(0,880,0,520); Root.Position=UDim2.new(0.5,0,0.5,0)
Root.BackgroundColor3=Color3.fromRGB(7,5,15); Root.BackgroundTransparency=0
Root.BorderSizePixel=0; Root.ClipsDescendants=true
local RootScale=Instance.new("UIScale",Root); RootScale.Scale=1
Instance.new("UICorner",Root).CornerRadius=UDim.new(0,28)
local rootStroke=Instance.new("UIStroke",Root); rootStroke.Color=Config.UIAccent; rootStroke.Thickness=1.2; rootStroke.Transparency=0.22
local rootGradient=Instance.new("UIGradient",Root); rootGradient.Rotation=90
rootGradient.Color=ColorSequence.new{ColorSequenceKeypoint.new(0,Color3.fromRGB(16,16,18)),ColorSequenceKeypoint.new(0.35,Color3.fromRGB(3,3,5)),ColorSequenceKeypoint.new(1,Color3.fromRGB(0,0,0))}
-- =====================
-- THEMES
-- =====================
local GhostThemeColors={
["Bright Phantom"]={accent=Color3.fromRGB(170,80,255),accent2=Color3.fromRGB(190,70,255),cross=Color3.fromRGB(210,120,255),main=Color3.fromRGB(6,4,10),side=Color3.fromRGB(4,3,8),top=Color3.fromRGB(8,5,13),card=Color3.fromRGB(14,8,24),row=Color3.fromRGB(11,7,20),stroke=Color3.fromRGB(120,55,190),text=Color3.fromRGB(245,245,250),sub=Color3.fromRGB(165,165,178)},
["Neon Wraith"]={accent=Color3.fromRGB(190,70,255),accent2=Color3.fromRGB(150,60,255),cross=Color3.fromRGB(220,135,255),main=Color3.fromRGB(4,2,8),side=Color3.fromRGB(2,2,5),top=Color3.fromRGB(6,3,11),card=Color3.fromRGB(10,5,18),row=Color3.fromRGB(8,4,15),stroke=Color3.fromRGB(130,55,210),text=Color3.fromRGB(245,245,250),sub=Color3.fromRGB(165,165,178)},
["Deep Violet"]={accent=Color3.fromRGB(150,75,255),accent2=Color3.fromRGB(175,85,255),cross=Color3.fromRGB(205,125,255),main=Color3.fromRGB(5,3,10),side=Color3.fromRGB(3,2,7),top=Color3.fromRGB(7,4,14),card=Color3.fromRGB(12,7,24),row=Color3.fromRGB(10,6,20),stroke=Color3.fromRGB(105,52,175),text=Color3.fromRGB(245,245,250),sub=Color3.fromRGB(165,165,178)},
["Void Glow"]={accent=Color3.fromRGB(130,60,255),accent2=Color3.fromRGB(200,80,255),cross=Color3.fromRGB(190,115,255),main=Color3.fromRGB(2,2,5),side=Color3.fromRGB(0,0,3),top=Color3.fromRGB(4,3,8),card=Color3.fromRGB(8,5,14),row=Color3.fromRGB(6,4,12),stroke=Color3.fromRGB(90,45,165),text=Color3.fromRGB(245,245,250),sub=Color3.fromRGB(165,165,178)},
["Glass Noir"]={accent=Color3.fromRGB(170,80,255),accent2=Color3.fromRGB(190,70,255),cross=Color3.fromRGB(210,120,255),main=Color3.fromRGB(6,4,10),side=Color3.fromRGB(4,3,8),top=Color3.fromRGB(8,5,13),card=Color3.fromRGB(14,8,24),row=Color3.fromRGB(11,7,20),stroke=Color3.fromRGB(120,55,190),text=Color3.fromRGB(245,245,250),sub=Color3.fromRGB(165,165,178)},
["High Contrast"]={accent=Color3.fromRGB(210,165,255),accent2=Color3.fromRGB(175,85,255),cross=Color3.fromRGB(235,210,255),main=Color3.fromRGB(0,0,0),side=Color3.fromRGB(0,0,0),top=Color3.fromRGB(0,0,0),card=Color3.fromRGB(8,6,10),row=Color3.fromRGB(5,4,7),stroke=Color3.fromRGB(150,90,210),text=Color3.fromRGB(245,245,250),sub=Color3.fromRGB(165,165,178)},
}
function ghostResolveBackgroundImage()
local img=Config.GhostBackgroundImage or ""
pcall(function()
if isfile and getcustomasset and isfile("GhostMenu/ghost.png") then img=getcustomasset("GhostMenu/ghost.png")
elseif isfile and getcustomasset and isfile("ghost.png") then img=getcustomasset("ghost.png") end
end)
return img
end
local GhostBg=Instance.new("Frame",Root)
GhostBg.Name="GhostBackground"; GhostBg.BackgroundTransparency=1
GhostBg.Size=UDim2.new(1,0,1,0); GhostBg.ZIndex=2
local GhostAura=Instance.new("TextLabel",GhostBg)
GhostAura.Name="GhostAura"; GhostAura.BackgroundTransparency=1
GhostAura.AnchorPoint=Vector2.new(0.5,0.5); GhostAura.Position=UDim2.new(0.70,0,0.60,0)
GhostAura.Size=UDim2.new(0,420,0,460); GhostAura.Text=""
GhostAura.Font=Enum.Font.GothamBlack; GhostAura.TextSize=64
GhostAura.TextColor3=Color3.fromRGB(18,14,24); GhostAura.TextTransparency=1
GhostAura.Rotation=-8; GhostAura.ZIndex=2; GhostAura.Visible=false
local GhostImg=Instance.new("ImageLabel",GhostBg)
GhostImg.Name="GhostImage"; GhostImg.BackgroundTransparency=1
GhostImg.AnchorPoint=Vector2.new(0.5,0.5); GhostImg.Position=UDim2.new(0.12,0,0.58,0)
GhostImg.Size=UDim2.new(0,330,0,520); GhostImg.ImageTransparency=0.36
GhostImg.ScaleType=Enum.ScaleType.Fit; GhostImg.ZIndex=2
function applyGhostTheme(name)
local th=GhostThemeColors[name or Config.ThemePreset] or GhostThemeColors["Bright Phantom"]
Config.ThemePreset=name or Config.ThemePreset
Config.UIAccent=th.accent; Config.CrosshairColor=th.cross
if Root then Root.BackgroundColor3=Color3.fromRGB(7,5,15) end
if Main then Main.BackgroundColor3=th.main end
if Sidebar then Sidebar.BackgroundColor3=th.side end
if Topbar then Topbar.BackgroundColor3=th.top end
if rootStroke then rootStroke.Color=th.accent; rootStroke.Transparency=0.18 end
pcall(function() if Content then Content.ScrollBarImageColor3=GhostControlFill end end)
if SearchBox then SearchBox.BackgroundColor3=Color3.fromRGB(13,7,20); SearchBox.TextColor3=Color3.fromRGB(245,245,250); SearchBox.PlaceholderColor3=Color3.fromRGB(165,125,205) end
if Title then Title.TextColor3=th.text end
if GhostImg then GhostImg.ImageColor3=Color3.fromRGB(255,255,255) end
for _,fn in safePairs(controls) do pcall(fn) end
end
function previewsEnabled() return Config.ShowPreviews~=false end
local bgTick=0
function updateAnimatedBackground(dt)
if not GhostBg or not Config.GhostBackground then return end
bgTick=bgTick+(dt or 0.016)
local mode=Config.BackgroundMode or "Ghost Drift"
if GhostImg then
local px,py=0,0
if Config.GhostParallax then
local m=UIS:GetMouseLocation()
local vp=camera and camera.ViewportSize or Vector2.new(1920,1080)
local strength=Config.GhostParallaxStrength or 0.025
px=((m.X/vp.X)-0.5)*strength; py=((m.Y/vp.Y)-0.5)*strength
end
if mode=="Ghost Drift" then
GhostImg.Position=UDim2.new(0.12+math.sin(bgTick*0.35)*0.010-px,0,0.58+math.cos(bgTick*0.28)*0.010-py,0)
GhostImg.Rotation=math.sin(bgTick*0.22)*3
elseif mode=="Spirit Pulse" then
GhostImg.ImageTransparency=1-clamp(0.30+(math.sin(bgTick*2)*0.08),0.1,0.75)
elseif mode=="Ghost Fog" then
GhostImg.Position=UDim2.new(0.12+math.sin(bgTick*0.18)*0.018-px,0,0.56-py,0)
GhostImg.Rotation=math.sin(bgTick*0.12)*7
end
end
end
local idlePulse=0
function updateIdleGlow(dt)
if not Config.IdleGlow then return end
idlePulse=idlePulse+(dt or 0.016)
if rootStroke then
rootStroke.Transparency=0.18+(math.sin(idlePulse*1.4)*0.05)
rootStroke.Thickness=1.2+(math.sin(idlePulse*1.4)*0.18)
end
end
local glassTargets={}
function registerGlass(obj,glassAlpha,solidAlpha)
if obj then table.insert(glassTargets,{obj=obj,glass=glassAlpha,solid=solidAlpha}) end
end
function applyGlassLook()
local useGlass=Config.Glass~=false
for _,item in safeIpairs(glassTargets) do
local obj=item.obj
if obj and obj.Parent then obj.BackgroundTransparency=useGlass and item.glass or item.solid end
end
end
function updateGhostBackground()
local show=Config.GhostBackground and not Config.Hidden
local img=ghostResolveBackgroundImage()
if GhostBg then GhostBg.Visible=show end
if GhostAura then GhostAura.Visible=false; GhostAura.TextTransparency=1 end
if GhostImg then
GhostImg.Image=img
GhostImg.ImageColor3=Color3.fromRGB(255,255,255)
GhostImg.ImageTransparency=(img~="" and show) and clamp(1-(Config.GhostBackgroundOpacity or 0.68),0.28,0.82) or 1
end
if SidebarGhostImg then
SidebarGhostImg.Image=img
SidebarGhostImg.ImageTransparency=(img~="" and show) and 0.48 or 1
end
end
local Shadow=Instance.new("ImageLabel",Root)
Shadow.Name="Shadow"; Shadow.BackgroundTransparency=1
Shadow.Image="rbxassetid://1316045217"; Shadow.ImageTransparency=1
Shadow.Size=UDim2.new(1,60,1,60); Shadow.Position=UDim2.new(0,-30,0,-30); Shadow.ZIndex=0; Shadow.Visible=false
-- =====================
-- SIDEBAR
-- =====================
local Sidebar=Instance.new("Frame",Root)
Sidebar.Size=UDim2.new(0,190,1,0); Sidebar.BackgroundColor3=Color3.fromRGB(4,3,8)
Sidebar.BackgroundTransparency=0.04; Sidebar.BorderSizePixel=0; Sidebar.ZIndex=2
Instance.new("UICorner",Sidebar).CornerRadius=UDim.new(0,24)
local sbStroke=Instance.new("UIStroke",Sidebar); sbStroke.Color=Color3.fromRGB(88,58,110); sbStroke.Transparency=0.45
local sbGrad=Instance.new("UIGradient",Sidebar); sbGrad.Rotation=90
sbGrad.Color=ColorSequence.new{ColorSequenceKeypoint.new(0,Color3.fromRGB(28,28,34)),ColorSequenceKeypoint.new(0.4,Color3.fromRGB(5,5,8)),ColorSequenceKeypoint.new(1,Color3.fromRGB(0,0,0))}
local Logo=Instance.new("TextLabel",Sidebar)
Logo.Size=UDim2.new(1,0,0,72); Logo.BackgroundTransparency=1; Logo.Text="GHOST"
Logo.Font=Enum.Font.GothamBlack; Logo.TextSize=24; Logo.TextColor3=Color3.fromRGB(255,255,255); Logo.ZIndex=3
local SubLogo=Instance.new("TextLabel",Sidebar)
SubLogo.Size=UDim2.new(1,-22,0,20); SubLogo.Position=UDim2.new(0,11,0,48)
SubLogo.BackgroundTransparency=1; SubLogo.Text="Ultimate v5.3"
SubLogo.Font=Enum.Font.Gotham; SubLogo.TextSize=12; SubLogo.TextColor3=Color3.fromRGB(150,150,165)
SubLogo.TextXAlignment=Enum.TextXAlignment.Center; SubLogo.ZIndex=3
local TabHolder=Instance.new("Frame",Sidebar)
TabHolder.BackgroundTransparency=1; TabHolder.Position=UDim2.new(0,14,0,92)
TabHolder.Size=UDim2.new(1,-28,1,-106); TabHolder.ZIndex=3
local tabLayout=Instance.new("UIListLayout",TabHolder); tabLayout.Padding=UDim.new(0,6); tabLayout.SortOrder=Enum.SortOrder.LayoutOrder
local SidebarGhostImg=Instance.new("ImageLabel",Sidebar)
SidebarGhostImg.Name="SidebarGhostImage"; SidebarGhostImg.BackgroundTransparency=1
SidebarGhostImg.AnchorPoint=Vector2.new(0.5,0.5); SidebarGhostImg.Position=UDim2.new(0.52,0,0.55,0)
SidebarGhostImg.Size=UDim2.new(0,250,0,420); SidebarGhostImg.Image=ghostResolveBackgroundImage()
SidebarGhostImg.ImageTransparency=0.42; SidebarGhostImg.ImageColor3=Color3.fromRGB(255,255,255)
SidebarGhostImg.ScaleType=Enum.ScaleType.Fit; SidebarGhostImg.ZIndex=3
local Main=Instance.new("Frame",Root)
Main.Position=UDim2.new(0,190,0,0); Main.Size=UDim2.new(1,-190,1,0)
Main.BackgroundColor3=Color3.fromRGB(6,4,10); Main.BackgroundTransparency=0.12; Main.ZIndex=2
Instance.new("UICorner",Main).CornerRadius=UDim.new(0,24)
pcall(function()
GhostBg.Parent=Main; GhostBg.Size=UDim2.new(1,0,1,0); GhostBg.Position=UDim2.new(0,0,0,0)
GhostBg.ZIndex=2; GhostAura.ZIndex=2; GhostImg.ZIndex=2
end)
local Topbar=Instance.new("Frame",Main)
Topbar.Size=UDim2.new(1,0,0,68); Topbar.BackgroundColor3=Color3.fromRGB(8,5,13)
Topbar.BackgroundTransparency=0.06; Topbar.BorderSizePixel=0; Topbar.ZIndex=60
Instance.new("UICorner",Topbar).CornerRadius=UDim.new(0,20)
local topStroke=Instance.new("UIStroke",Topbar); topStroke.Color=Color3.fromRGB(92,64,112); topStroke.Transparency=0.62
local Title=Instance.new("TextLabel",Topbar)
Title.Size=UDim2.new(0.45,0,1,0); Title.Position=UDim2.new(0,18,0,0); Title.BackgroundTransparency=1
Title.Font=Enum.Font.GothamBlack; Title.TextSize=21; Title.TextColor3=Color3.fromRGB(255,255,255)
Title.TextXAlignment=Enum.TextXAlignment.Left; Title.Text="Combat"; Title.ZIndex=61
local SearchBox=Instance.new("TextBox",Topbar)
SearchBox.Size=UDim2.new(0,220,0,34); SearchBox.Position=UDim2.new(1,-372,0.5,-17)
SearchBox.BackgroundColor3=Color3.fromRGB(0,0,0)
SearchBox.PlaceholderText="Search settings..."; SearchBox.Text=""
SearchBox.TextColor3=Color3.fromRGB(245,245,250); SearchBox.PlaceholderColor3=Color3.fromRGB(165,125,205)
SearchBox.Font=Enum.Font.Gotham; SearchBox.TextSize=13; SearchBox.ZIndex=61
Instance.new("UICorner",SearchBox).CornerRadius=UDim.new(0,17)
local ss=Instance.new("UIStroke",SearchBox); ss.Color=Color3.fromRGB(45,50,70); ss.Transparency=0.5
local Close=Instance.new("TextButton",Topbar)
Close.Size=UDim2.new(0,34,0,34); Close.Position=UDim2.new(1,-44,0.5,-17); Close.Text="H"
Close.Font=Enum.Font.GothamBold; Close.TextSize=15; Close.TextColor3=Color3.fromRGB(255,120,140)
Close.BackgroundColor3=Color3.fromRGB(8,0,4); Close.ZIndex=62
Instance.new("UICorner",Close).CornerRadius=UDim.new(0,13)
local FullClose=Instance.new("TextButton",Topbar)
FullClose.Size=UDim2.new(0,34,0,34); FullClose.Position=UDim2.new(1,-84,0.5,-17); FullClose.Text="X"
FullClose.Font=Enum.Font.GothamBold; FullClose.TextSize=16; FullClose.TextColor3=Color3.fromRGB(255,80,120)
FullClose.BackgroundColor3=Color3.fromRGB(22,4,12); FullClose.ZIndex=62
Instance.new("UICorner",FullClose).CornerRadius=UDim.new(0,13)
local Min=Instance.new("TextButton",Topbar)
Min.Size=UDim2.new(0,34,0,34); Min.Position=UDim2.new(1,-124,0.5,-17); Min.Text="-"
Min.Font=Enum.Font.GothamBold; Min.TextSize=24; Min.TextColor3=Color3.fromRGB(210,240,255)
Min.BackgroundColor3=Color3.fromRGB(5,3,10); Min.ZIndex=62
Instance.new("UICorner",Min).CornerRadius=UDim.new(0,13)
local Content=Instance.new("ScrollingFrame",Main)
Content.Position=UDim2.new(0,28,0,84); Content.Size=UDim2.new(1,-56,1,-104)
Content.BackgroundTransparency=1; Content.BorderSizePixel=0
Content.ScrollBarThickness=4; Content.ScrollBarImageColor3=GhostControlFill
Content.CanvasSize=UDim2.new(0,0,0,0); Content.ZIndex=3
local contentLayout=Instance.new("UIListLayout",Content)
contentLayout.Padding=UDim.new(0,12); contentLayout.SortOrder=Enum.SortOrder.LayoutOrder
contentLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
Content.CanvasSize=UDim2.new(0,0,0,contentLayout.AbsoluteContentSize.Y+12)
end)
local SearchDim=Instance.new("Frame",Main)
SearchDim.Name="SearchSpotlightDim"; SearchDim.Position=UDim2.new(0,0,0,68)
SearchDim.Size=UDim2.new(1,0,1,-68); SearchDim.BackgroundColor3=Color3.fromRGB(0,0,0)
SearchDim.BackgroundTransparency=1; SearchDim.BorderSizePixel=0; SearchDim.Visible=false; SearchDim.ZIndex=50
local HoverTip=Instance.new("Frame",ScreenGui)
HoverTip.Name="HoverHelpTip"; HoverTip.Size=UDim2.new(0,285,0,82)
HoverTip.BackgroundColor3=Color3.fromRGB(8,5,13); HoverTip.BackgroundTransparency=0.06
HoverTip.BorderSizePixel=0; HoverTip.Visible=false; HoverTip.ZIndex=150
Instance.new("UICorner",HoverTip).CornerRadius=UDim.new(0,14)
local HoverTipStroke=Instance.new("UIStroke",HoverTip); HoverTipStroke.Color=Config.UIAccent; HoverTipStroke.Transparency=0.25; HoverTipStroke.Thickness=1
local HoverTipTitle=Instance.new("TextLabel",HoverTip)
HoverTipTitle.BackgroundTransparency=1; HoverTipTitle.Position=UDim2.new(0,12,0,8)
HoverTipTitle.Size=UDim2.new(1,-24,0,18); HoverTipTitle.Font=Enum.Font.GothamBlack; HoverTipTitle.TextSize=12
HoverTipTitle.TextColor3=Color3.fromRGB(245,245,250); HoverTipTitle.TextXAlignment=Enum.TextXAlignment.Left; HoverTipTitle.ZIndex=151
local HoverTipBody=Instance.new("TextLabel",HoverTip)
HoverTipBody.BackgroundTransparency=1; HoverTipBody.Position=UDim2.new(0,12,0,30)
HoverTipBody.Size=UDim2.new(1,-24,1,-38); HoverTipBody.Font=Enum.Font.Gotham; HoverTipBody.TextSize=11
HoverTipBody.TextColor3=Color3.fromRGB(165,165,178); HoverTipBody.TextXAlignment=Enum.TextXAlignment.Left
HoverTipBody.TextYAlignment=Enum.TextYAlignment.Top; HoverTipBody.TextWrapped=true; HoverTipBody.ZIndex=151
local hoverToken=0
-- Startup overlay
local StartupOverlay=Instance.new("Frame",Root)
StartupOverlay.Name="StartupOverlay"; StartupOverlay.Size=UDim2.new(1,0,1,0)
StartupOverlay.BackgroundColor3=Color3.fromRGB(0,0,0); StartupOverlay.BackgroundTransparency=0.05; StartupOverlay.ZIndex=100
Instance.new("UICorner",StartupOverlay).CornerRadius=UDim.new(0,22)
local StartupTitle=Instance.new("TextLabel",StartupOverlay)
StartupTitle.BackgroundTransparency=1; StartupTitle.Position=UDim2.new(0,40,0.5,-55); StartupTitle.Size=UDim2.new(1,-80,0,36)
StartupTitle.Font=Enum.Font.GothamBlack; StartupTitle.TextSize=28; StartupTitle.TextColor3=GhostTextMain
StartupTitle.TextXAlignment=Enum.TextXAlignment.Left; StartupTitle.Text="GHOST"; StartupTitle.ZIndex=101
local StartupStatus=Instance.new("TextLabel",StartupOverlay)
StartupStatus.BackgroundTransparency=1; StartupStatus.Position=UDim2.new(0,42,0.5,-15); StartupStatus.Size=UDim2.new(1,-84,0,22)
StartupStatus.Font=Enum.Font.Gotham; StartupStatus.TextSize=13; StartupStatus.TextColor3=Color3.fromRGB(190,190,210)
StartupStatus.TextXAlignment=Enum.TextXAlignment.Left; StartupStatus.Text="Loading UI..."; StartupStatus.ZIndex=101
local StartupBar=Instance.new("Frame",StartupOverlay)
StartupBar.Position=UDim2.new(0,42,0.5,18); StartupBar.Size=UDim2.new(1,-84,0,6)
StartupBar.BackgroundColor3=Color3.fromRGB(30,30,42); StartupBar.BorderSizePixel=0; StartupBar.ZIndex=101
Instance.new("UICorner",StartupBar).CornerRadius=UDim.new(1,0)
local StartupFill=Instance.new("Frame",StartupBar)
StartupFill.Size=UDim2.new(0,0,1,0); StartupFill.BackgroundColor3=GhostControlFill
StartupFill.BorderSizePixel=0; StartupFill.ZIndex=102
Instance.new("UICorner",StartupFill).CornerRadius=UDim.new(1,0)
function startupStep(text,pct)
if StartupStatus then StartupStatus.Text=text end
if StartupFill then tween(StartupFill,0.18,{Size=UDim2.new(pct,0,1,0)}) end
end
task.spawn(function()
startupStep("Loading UI...",0.25); task.wait(0.15)
startupStep("Applying ghost theme...",0.5); task.wait(0.15)
startupStep("Restoring layout...",0.75); task.wait(0.15)
startupStep("Ready",1); task.wait(0.35)
if StartupOverlay then tween(StartupOverlay,0.3,{BackgroundTransparency=1}); task.wait(0.32); pcall(function() StartupOverlay:Destroy() end) end
end)
-- =====================
-- NOTIFICATION SYSTEM
-- =====================
local activePopups={}; local notificationHistory={}
local NotificationDrawer=nil; local NotificationList=nil
function playUISound(kind) return end
_G.GhostDockSound=function() return end
function showApplyPopup(title,body,kind)
table.insert(notificationHistory,{title=title,body=body,kind=kind,time=os.time()})
if #notificationHistory>40 then table.remove(notificationHistory,1) end
if NotificationDrawer and NotificationDrawer.Visible then rebuildNotificationDrawer() end
if not Config.ApplyPopups then return end
local pop=Instance.new("Frame",ScreenGui)
pop.BackgroundColor3=Color3.fromRGB(8,5,13); pop.BackgroundTransparency=0.08
pop.BorderSizePixel=0; pop.Size=UDim2.new(0,310,0,82)
pop.Position=UDim2.new(1,-330,0,92+(#activePopups*90)); pop.ZIndex=120
Instance.new("UICorner",pop).CornerRadius=UDim.new(0,16)
local st=Instance.new("UIStroke",pop); st.Color=(kind=="error") and Color3.fromRGB(255,80,120) or Config.UIAccent; st.Transparency=0.28; st.Thickness=1
local ttl=Instance.new("TextLabel",pop)
ttl.BackgroundTransparency=1; ttl.Position=UDim2.new(0,14,0,9); ttl.Size=UDim2.new(1,-28,0,20)
ttl.Font=Enum.Font.GothamBlack; ttl.TextSize=13; ttl.TextColor3=Color3.fromRGB(245,245,250)
ttl.TextXAlignment=Enum.TextXAlignment.Left; ttl.Text=title or "Applied"; ttl.ZIndex=121
local msg=Instance.new("TextLabel",pop)
msg.BackgroundTransparency=1; msg.Position=UDim2.new(0,14,0,33); msg.Size=UDim2.new(1,-28,0,38)
msg.Font=Enum.Font.Gotham; msg.TextSize=11; msg.TextColor3=Color3.fromRGB(165,165,178)
msg.TextXAlignment=Enum.TextXAlignment.Left; msg.TextYAlignment=Enum.TextYAlignment.Top
msg.TextWrapped=true; msg.Text=body or "Done"; msg.ZIndex=121
table.insert(activePopups,pop)
task.delay(3,function()
pcall(function() tween(pop,0.25,{BackgroundTransparency=1,Position=pop.Position+UDim2.new(0,30,0,0)}) end)
task.wait(0.28)
for i,v in safeIpairs(activePopups) do if v==pop then table.remove(activePopups,i); break end end
pcall(function() pop:Destroy() end)
end)
end
function rebuildNotificationDrawer()
if not NotificationList then return end
for _,c in safeIpairs(NotificationList:GetChildren()) do if not c:IsA("UIListLayout") then c:Destroy() end end
for i=#notificationHistory,math.max(1,#notificationHistory-8),-1 do
local item=notificationHistory[i]
local r=Instance.new("TextLabel",NotificationList)
r.BackgroundColor3=Color3.fromRGB(11,7,18); r.BackgroundTransparency=0.12
r.BorderSizePixel=0; r.Size=UDim2.new(1,0,0,46); r.Font=Enum.Font.Gotham; r.TextSize=11
r.TextWrapped=true; r.TextXAlignment=Enum.TextXAlignment.Left
r.TextColor3=Color3.fromRGB(228,210,245); r.Text=" "..(item.title or "").." - "..(item.body or ""); r.ZIndex=132
Instance.new("UICorner",r).CornerRadius=UDim.new(0,10)
end
end
function toggleNotificationDrawer()
if NotificationDrawer and NotificationDrawer.Parent then
NotificationDrawer.Visible=not NotificationDrawer.Visible; rebuildNotificationDrawer(); return
end
NotificationDrawer=Instance.new("Frame",ScreenGui)
NotificationDrawer.BackgroundColor3=Color3.fromRGB(9,6,20); NotificationDrawer.BackgroundTransparency=0.06
NotificationDrawer.BorderSizePixel=0; NotificationDrawer.Size=UDim2.new(0,360,0,360)
NotificationDrawer.Position=UDim2.new(1,-380,0,90); NotificationDrawer.ZIndex=130
Instance.new("UICorner",NotificationDrawer).CornerRadius=UDim.new(0,18)
local st=Instance.new("UIStroke",NotificationDrawer); st.Color=Config.UIAccent; st.Transparency=0.28
local title=Instance.new("TextLabel",NotificationDrawer)
title.BackgroundTransparency=1; title.Position=UDim2.new(0,16,0,12); title.Size=UDim2.new(1,-70,0,24)
title.Text="Notifications"; title.Font=Enum.Font.GothamBlack; title.TextSize=15
title.TextColor3=Color3.fromRGB(245,245,250); title.TextXAlignment=Enum.TextXAlignment.Left; title.ZIndex=131
local clear=Instance.new("TextButton",NotificationDrawer)
clear.Size=UDim2.new(0,58,0,26); clear.Position=UDim2.new(1,-72,0,12); clear.Text="Clear"
clear.Font=Enum.Font.GothamBold; clear.TextSize=11; clear.TextColor3=Color3.fromRGB(245,245,250)
clear.BackgroundColor3=Color3.fromRGB(22,10,38); clear.ZIndex=131
Instance.new("UICorner",clear).CornerRadius=UDim.new(0,9)
NotificationList=Instance.new("Frame",NotificationDrawer)
NotificationList.BackgroundTransparency=1; NotificationList.Position=UDim2.new(0,14,0,50)
NotificationList.Size=UDim2.new(1,-28,1,-64); NotificationList.ZIndex=131
local l=Instance.new("UIListLayout",NotificationList); l.Padding=UDim.new(0,8); l.SortOrder=Enum.SortOrder.LayoutOrder
clear.MouseButton1Click:Connect(function() notificationHistory={}; rebuildNotificationDrawer() end)
rebuildNotificationDrawer()
end
-- =====================
-- TAB / PAGE SYSTEM
-- =====================
local pages={}; local tabs={}; local controls={}
local cardRegistry={}; local rowRegistry={}; local collapsedCards={}
local FavoriteKeys={ESP=true,AimAssist=true,TriggerBot=true,TriggerFOVVisible=true,Crosshair=true,OffscreenArrows=true,TargetInfo=true,AimFOV=true,TriggerFOV=true,ArrowSize=true,ArrowPadding=true,FOVTransparency=true}
local favoriteItems={}; local favoriteCategories={}
local favoriteOrder={"Combat","Visuals","Crosshair","HUD","Config","Settings","Other"}
local favoriteStarButtons={}; local favDynamicBody=nil
local rebuildFavorites
local SavedLayout={LastTab="Favorited",MenuPos=nil,MenuSize=nil,Collapsed={}}
local ProfileCard=Instance.new("Frame",Sidebar)
ProfileCard.Name="ProfileCard"; ProfileCard.Position=UDim2.new(0,14,1,-62)
ProfileCard.Size=UDim2.new(1,-28,0,48); ProfileCard.BackgroundColor3=Color3.fromRGB(14,8,28)
ProfileCard.BackgroundTransparency=0.08; ProfileCard.BorderSizePixel=0; ProfileCard.ZIndex=4; ProfileCard.Visible=false
Instance.new("UICorner",ProfileCard).CornerRadius=UDim.new(0,16)
local pcStroke=Instance.new("UIStroke",ProfileCard); pcStroke.Color=Config.UIAccent; pcStroke.Transparency=0.48
local pcTitle=Instance.new("TextLabel",ProfileCard)
pcTitle.BackgroundTransparency=1; pcTitle.Position=UDim2.new(0,10,0,5); pcTitle.Size=UDim2.new(1,-20,0,16)
pcTitle.Font=Enum.Font.GothamBlack; pcTitle.TextSize=11; pcTitle.TextColor3=Color3.fromRGB(245,245,250)
pcTitle.TextXAlignment=Enum.TextXAlignment.Left; pcTitle.Text="GHOST"; pcTitle.ZIndex=62
local pcBody=Instance.new("TextLabel",ProfileCard)
pcBody.BackgroundTransparency=1; pcBody.Position=UDim2.new(0,10,0,21); pcBody.Size=UDim2.new(1,-20,0,24)
pcBody.Font=Enum.Font.Gotham; pcBody.TextSize=9; pcBody.TextColor3=Color3.fromRGB(165,165,178)
pcBody.TextXAlignment=Enum.TextXAlignment.Left; pcBody.TextYAlignment=Enum.TextYAlignment.Top
pcBody.TextWrapped=true; pcBody.Text="Bright Phantom\nRuntime 0m"; pcBody.ZIndex=62
-- Sidebar auto-collapse
local sidebarExpanded=true; local sidebarExpandedWidth=190; local sidebarCollapsedWidth=86
local sidebarLastHover=now(); local sidebarHoverPad=18
function setSidebarExpanded(state,instant)
sidebarExpanded=state
local w=state and sidebarExpandedWidth or sidebarCollapsedWidth
local t=instant and 0 or 0.24
tween(Sidebar,t,{Size=UDim2.new(0,w,1,0)},Enum.EasingStyle.Quint)
tween(Main,t,{Position=UDim2.new(0,w,0,0),Size=UDim2.new(1,-w,1,0)},Enum.EasingStyle.Quint)
tween(TabHolder,t,{Position=UDim2.new(0,state and 14 or 12,0,92),Size=UDim2.new(1,state and -28 or -24,1,-106)},Enum.EasingStyle.Quint)
tween(Logo,t,{TextTransparency=state and 0 or 1,TextSize=state and 24 or 1},Enum.EasingStyle.Quint)
tween(SubLogo,t,{TextTransparency=state and 0 or 1},Enum.EasingStyle.Quint)
ProfileCard.Visible=(state and Config.ProfileCard==true)
for name,btn in safePairs(tabs or {}) do
btn.Text=state and (btn:GetAttribute("FullLabel") or btn.Text) or (btn:GetAttribute("IconOnly") or "*")
btn.TextXAlignment=state and Enum.TextXAlignment.Left or Enum.TextXAlignment.Center
btn.TextSize=state and 13 or 16
btn.Size=UDim2.new(1,0,0,state and 36 or 42)
end
end
function sidebarMouseInside()
local m=UIS:GetMouseLocation()
local p=Sidebar.AbsolutePosition; local sz=Sidebar.AbsoluteSize
return m.X>=p.X-sidebarHoverPad and m.X<=p.X+sz.X+sidebarHoverPad and m.Y>=p.Y-sidebarHoverPad and m.Y<=p.Y+sz.Y+sidebarHoverPad
end
RunService.RenderStepped:Connect(function()
if ghostUnloaded then return end
if not Root.Visible or Config.Hidden then return end
if sidebarMouseInside() then
sidebarLastHover=now()
if not sidebarExpanded then setSidebarExpanded(true,false) end
elseif sidebarExpanded and (now()-sidebarLastHover)>0.55 then
setSidebarExpanded(false,false)
end
end)
function clearContent()
for _,c in safeIpairs(Content:GetChildren()) do if not c:IsA("UIListLayout") then c.Visible=false end end
end
function makeTab(name,icon)
local b=Instance.new("TextButton",TabHolder)
b.Size=UDim2.new(1,0,0,36); b.BackgroundColor3=Color3.fromRGB(4,4,8)
b.Text=" "..icon.." "..name
b:SetAttribute("FullLabel"," "..icon.." "..name)
b:SetAttribute("IconOnly",icon)
b.Font=Enum.Font.GothamBold; b.TextSize=13
b.TextXAlignment=Enum.TextXAlignment.Left
b.TextColor3=Color3.fromRGB(170,170,185); b.AutoButtonColor=false; b.ZIndex=4
Instance.new("UICorner",b).CornerRadius=UDim.new(0,15)
local st=Instance.new("UIStroke",b); st.Color=Config.UIAccent; st.Transparency=0.78; st.Thickness=1
tabs[name]=b
b.MouseEnter:Connect(function()
if currentTab~=name then tween(b,0.16,{BackgroundColor3=Color3.fromRGB(20,12,34),TextColor3=Color3.fromRGB(220,205,245)},Enum.EasingStyle.Quint) end
end)
b.MouseLeave:Connect(function()
if currentTab~=name then tween(b,0.16,{BackgroundColor3=Color3.fromRGB(4,4,8),TextColor3=Color3.fromRGB(170,170,185)},Enum.EasingStyle.Quint) end
end)
b.MouseButton1Click:Connect(function() showTab(name) end)
end
function makePage(name)
local f=Instance.new("Frame",Content)
f.Name=name; f.BackgroundTransparency=1; f.Size=UDim2.new(1,0,0,10); f.Visible=false; f.ZIndex=3
local l=Instance.new("UIListLayout",f); l.Padding=UDim.new(0,12); l.SortOrder=Enum.SortOrder.LayoutOrder
l:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function() f.Size=UDim2.new(1,0,0,l.AbsoluteContentSize.Y+4) end)
pages[name]=f
return f
end
function card(parent,title,icon)
local c=Instance.new("Frame",parent)
c.BackgroundColor3=Color3.fromRGB(14,8,22); c.BackgroundTransparency=0
c.BorderSizePixel=0; c.Size=UDim2.new(1,0,0,70); c.ZIndex=55
c:SetAttribute("GhostTitle",title)
registerGlass(c,0.22,0.02)
Instance.new("UICorner",c).CornerRadius=UDim.new(0,22)
local st=Instance.new("UIStroke",c); st.Color=Color3.fromRGB(120,55,190); st.Transparency=0.38
local cg=Instance.new("UIGradient",c); cg.Rotation=90
cg.Color=ColorSequence.new{ColorSequenceKeypoint.new(0,Color3.fromRGB(36,16,68)),ColorSequenceKeypoint.new(0.45,Color3.fromRGB(18,10,36)),ColorSequenceKeypoint.new(1,Color3.fromRGB(6,4,14))}
local t=Instance.new("TextLabel",c)
t.Size=UDim2.new(1,-68,0,28); t.Position=UDim2.new(0,14,0,10); t.BackgroundTransparency=1
t.Text=icon.." "..title; t.Font=Enum.Font.GothamBlack; t.TextSize=15
t.TextColor3=Color3.fromRGB(255,255,255); t.TextXAlignment=Enum.TextXAlignment.Left; t.ZIndex=57
local collapse=Instance.new("TextButton",c)
collapse.Size=UDim2.new(0,34,0,28); collapse.Position=UDim2.new(1,-46,0,10)
collapse.BackgroundColor3=Color3.fromRGB(10,8,18); collapse.BackgroundTransparency=0.1
collapse.Text="v"; collapse.Font=Enum.Font.GothamBlack; collapse.TextSize=14
collapse.TextColor3=GhostTextMain; collapse.AutoButtonColor=false; collapse.ZIndex=58
Instance.new("UICorner",collapse).CornerRadius=UDim.new(0,9)
local headerHit=Instance.new("TextButton",c)
headerHit.Size=UDim2.new(1,-60,0,44); headerHit.Position=UDim2.new(0,0,0,0)
headerHit.BackgroundTransparency=1; headerHit.Text=""; headerHit.AutoButtonColor=false; headerHit.ZIndex=56
local body=Instance.new("Frame",c)
body.BackgroundTransparency=1; body.Position=UDim2.new(0,14,0,44)
body.Size=UDim2.new(1,-28,1,-54); body.ZIndex=56
body:SetAttribute("FavCategory",parent and parent.Name or "Other")
local l=Instance.new("UIListLayout",body); l.Padding=UDim.new(0,8); l.SortOrder=Enum.SortOrder.LayoutOrder
local record={card=c,body=body,title=title,collapsed=false,height=70}
table.insert(cardRegistry,record)
local function resizeCard()
local h=l.AbsoluteContentSize.Y
record.height=h+60; body.Size=UDim2.new(1,-28,0,h)
if record.collapsed then body.Visible=false; c.Size=UDim2.new(1,0,0,48); collapse.Text=">"
else body.Visible=true; c.Size=UDim2.new(1,0,0,h+60); collapse.Text="v" end
end
record.resize=resizeCard
local function toggleCollapse()
record.collapsed=not record.collapsed; collapsedCards[title]=record.collapsed; resizeCard()
end
collapse.MouseButton1Click:Connect(toggleCollapse)
headerHit.MouseButton1Click:Connect(toggleCollapse)
l:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(resizeCard)
resizeCard()
return body,c
end
function row(parent,label,desc)
local r=Instance.new("Frame",parent)
r.BackgroundColor3=Color3.fromRGB(11,7,18); r.BackgroundTransparency=0.16
r.BorderSizePixel=0; r.Size=UDim2.new(1,0,0,46); r.ZIndex=57
r:SetAttribute("SearchText",(label.." "..(desc or "")):lower())
registerGlass(r,0.16,0.02)
Instance.new("UICorner",r).CornerRadius=UDim.new(0,18)
local st=Instance.new("UIStroke",r); st.Color=Color3.fromRGB(120,55,190); st.Transparency=0.58
local l=Instance.new("TextLabel",r)
l.BackgroundTransparency=1; l.Position=UDim2.new(0,36,0,5); l.Size=UDim2.new(0.54,0,0,18)
l.Text=label; l.Font=Enum.Font.GothamBold; l.TextSize=14; l.TextColor3=Color3.fromRGB(255,248,255)
l.TextXAlignment=Enum.TextXAlignment.Left; l.ZIndex=58
local d=Instance.new("TextLabel",r)
d.BackgroundTransparency=1; d.Position=UDim2.new(0,36,0,24); d.Size=UDim2.new(0.64,0,0,16)
d.Text=desc or ""; d.Font=Enum.Font.Gotham; d.TextSize=11; d.TextColor3=Color3.fromRGB(195,180,220)
d.TextXAlignment=Enum.TextXAlignment.Left; d.ZIndex=58
table.insert(rowRegistry,{row=r,parent=parent,text=(label.." "..(desc or "")):lower()})
return r
end
function saveLayoutState()
SavedLayout.LastTab=currentTab
SavedLayout.MenuPos={Root.Position.X.Scale,Root.Position.X.Offset,Root.Position.Y.Scale,Root.Position.Y.Offset}
SavedLayout.Collapsed=collapsedCards
end
function favoriteRefreshKey(key)
for _,btn in safeIpairs(favoriteStarButtons[key] or {}) do
btn.Text=FavoriteKeys[key] and "*" or "o"
btn.TextColor3=FavoriteKeys[key] and GhostTextMain or Color3.fromRGB(105,105,125)
end
end
function favoriteCategoryFromParent(parent)
local cur=parent
while cur do
if cur.GetAttribute and cur:GetAttribute("FavCategory") then return cur:GetAttribute("FavCategory") end
cur=cur.Parent
end
return "Other"
end
function addFavoriteStar(rowObj,key,label,desc,kind,args,category)
if not key then return end
favoriteItems[key]=favoriteItems[key] or {key=key,label=label,desc=desc,kind=kind,args=args,category=category or favoriteCategoryFromParent(rowObj.Parent)}
favoriteCategories[key]=favoriteItems[key].category or "Other"
favoriteStarButtons[key]=favoriteStarButtons[key] or {}
local star=Instance.new("TextButton",rowObj)
star.Size=UDim2.new(0,22,0,22); star.Position=UDim2.new(0,8,0.5,-11)
star.BackgroundTransparency=1; star.Text=FavoriteKeys[key] and "*" or "o"
star.Font=Enum.Font.GothamBlack; star.TextSize=15
star.TextColor3=FavoriteKeys[key] and GhostTextMain or Color3.fromRGB(105,105,125)
star.AutoButtonColor=false; star.ZIndex=60
table.insert(favoriteStarButtons[key],star)
star.MouseButton1Click:Connect(function()
FavoriteKeys[key]=not FavoriteKeys[key]; favoriteRefreshKey(key)
if rebuildFavorites then rebuildFavorites() end; ghostSaveConfigFile(true)
end)
end
function favRow(parent,label,desc)
local r=Instance.new("Frame",parent)
r.BackgroundColor3=Color3.fromRGB(11,7,18); r.BackgroundTransparency=0.16
r.BorderSizePixel=0; r.Size=UDim2.new(1,0,0,46); r.ZIndex=57
Instance.new("UICorner",r).CornerRadius=UDim.new(0,18)
local st=Instance.new("UIStroke",r); st.Color=Color3.fromRGB(120,55,190); st.Transparency=0.58
local l=Instance.new("TextLabel",r)
l.BackgroundTransparency=1; l.Position=UDim2.new(0,36,0,5); l.Size=UDim2.new(0.54,0,0,18)
l.Text=label; l.Font=Enum.Font.GothamBold; l.TextSize=14; l.TextColor3=Color3.fromRGB(255,248,255)
l.TextXAlignment=Enum.TextXAlignment.Left; l.ZIndex=58
local d=Instance.new("TextLabel",r)
d.BackgroundTransparency=1; d.Position=UDim2.new(0,36,0,24); d.Size=UDim2.new(0.64,0,0,16)
d.Text=desc or ""; d.Font=Enum.Font.Gotham; d.TextSize=11; d.TextColor3=Color3.fromRGB(195,180,220)
d.TextXAlignment=Enum.TextXAlignment.Left; d.ZIndex=58
return r
end
function buildFavoriteControl(parent,item)
if not item or not item.key then return end
local key=item.key
local r=favRow(parent,item.label,item.desc)
local unstar=Instance.new("TextButton",r)
unstar.Size=UDim2.new(0,22,0,22); unstar.Position=UDim2.new(0,8,0.5,-11)
unstar.BackgroundTransparency=1; unstar.Text="*"; unstar.Font=Enum.Font.GothamBlack
unstar.TextSize=15; unstar.TextColor3=GhostTextMain; unstar.AutoButtonColor=false; unstar.ZIndex=60
unstar.MouseButton1Click:Connect(function()
FavoriteKeys[key]=false; favoriteRefreshKey(key)
if rebuildFavorites then rebuildFavorites() end; ghostSaveConfigFile(true)
end)
if item.kind=="toggle" then
local b=Instance.new("TextButton",r)
b.Size=UDim2.new(0,54,0,26); b.Position=UDim2.new(1,-66,0.5,-13)
b.BackgroundColor3=Config[key] and GhostControlOn or Color3.fromRGB(45,48,62)
b.Text=""; b.AutoButtonColor=false; b.ZIndex=59
Instance.new("UICorner",b).CornerRadius=UDim.new(1,0)
local knob=Instance.new("Frame",b)
knob.Size=UDim2.new(0,20,0,20)
knob.Position=Config[key] and UDim2.new(1,-23,0.5,-10) or UDim2.new(0,3,0.5,-10)
knob.BackgroundColor3=Color3.fromRGB(255,255,255); knob.ZIndex=60
Instance.new("UICorner",knob).CornerRadius=UDim.new(1,0)
local function refresh()
tween(b,0.16,{BackgroundColor3=Config[key] and GhostControlOn or Color3.fromRGB(45,48,62)})
tween(knob,0.16,{Position=Config[key] and UDim2.new(1,-23,0.5,-10) or UDim2.new(0,3,0.5,-10)})
end
b.MouseButton1Click:Connect(function()
Config[key]=not Config[key]; refresh()
if controls[key] then pcall(controls[key]) end; ghostScheduleAutoSave()
end)
elseif item.kind=="slider" then
local args=item.args or {}
local min,max,step=args.min or 0,args.max or 100,args.step or 1
local val=Instance.new("TextLabel",r)
val.BackgroundTransparency=1; val.Size=UDim2.new(0,82,0,20); val.Position=UDim2.new(1,-90,0,4)
val.Font=Enum.Font.GothamBold; val.TextSize=12; val.TextColor3=GhostTextMain; val.ZIndex=59
local bar=Instance.new("Frame",r)
bar.Size=UDim2.new(0,180,0,6); bar.Position=UDim2.new(1,-214,0,31)
bar.BackgroundColor3=Color3.fromRGB(52,46,72); bar.ZIndex=59
Instance.new("UICorner",bar).CornerRadius=UDim.new(1,0)
local fill=Instance.new("Frame",bar)
fill.BackgroundColor3=GhostControlFill; fill.ZIndex=60
Instance.new("UICorner",fill).CornerRadius=UDim.new(1,0)
local draggingS=false
local function refresh()
local pct=(Config[key]-min)/(max-min)
fill.Size=UDim2.new(pct,0,1,0); val.Text=tostring(Config[key])
end
local function setFromX(x)
local pct=clamp((x-bar.AbsolutePosition.X)/bar.AbsoluteSize.X,0,1)
local v=math.floor((min+(max-min)*pct)/(step or 1)+0.5)*(step or 1)
Config[key]=clamp(v,min,max); refresh()
if controls[key] then pcall(controls[key]) end; ghostScheduleAutoSave()
end
refresh()
bar.InputBegan:Connect(function(i) if i.UserInputType==Enum.UserInputType.MouseButton1 then draggingS=true; setFromX(i.Position.X) end end)
UIS.InputEnded:Connect(function(i) if i.UserInputType==Enum.UserInputType.MouseButton1 then draggingS=false end end)
UIS.InputChanged:Connect(function(i) if draggingS and i.UserInputType==Enum.UserInputType.MouseMovement then setFromX(i.Position.X) end end)
elseif item.kind=="dropdown" then
local options=item.args and item.args.options or {}
local b=Instance.new("TextButton",r)
b.Size=UDim2.new(0,160,0,28); b.Position=UDim2.new(1,-172,0.5,-14)
b.BackgroundColor3=Color3.fromRGB(22,10,38); b.Text=tostring(Config[key]).." v"
b.Font=Enum.Font.GothamBold; b.TextSize=12; b.TextColor3=Color3.fromRGB(240,240,255); b.ZIndex=59
Instance.new("UICorner",b).CornerRadius=UDim.new(0,15)
local idx=1; for i,v in safeIpairs(options) do if v==Config[key] then idx=i end end
b.MouseButton1Click:Connect(function()
if #options<1 then return end; idx=idx%#options+1; Config[key]=options[idx]
b.Text=tostring(Config[key]).." v"
if controls[key] then pcall(controls[key]) end; ghostScheduleAutoSave()
end)
elseif item.kind=="keybind" then
local b=Instance.new("TextButton",r)
b.Size=UDim2.new(0,130,0,28); b.Position=UDim2.new(1,-142,0.5,-14)
b.BackgroundColor3=Color3.fromRGB(22,10,38); b.Text=Config[key]
b.Font=Enum.Font.GothamBold; b.TextSize=12; b.TextColor3=Color3.fromRGB(240,240,255); b.ZIndex=59
Instance.new("UICorner",b).CornerRadius=UDim.new(0,15)
local listening=false
b.MouseButton1Click:Connect(function() listening=true; b.Text="Press key..." end)
UIS.InputBegan:Connect(function(input,gp)
if listening then
listening=false
if input.UserInputType==Enum.UserInputType.MouseButton1 then Config[key]="MouseButton1"
elseif input.UserInputType==Enum.UserInputType.MouseButton2 then Config[key]="MouseButton2"
elseif input.KeyCode~=Enum.KeyCode.Unknown then Config[key]=input.KeyCode.Name end
b.Text=Config[key]
if controls[key] then pcall(controls[key]) end; ghostScheduleAutoSave()
end
end)
end
end
function toggle(parent,label,desc,key)
local r=row(parent,label,desc)
addFavoriteStar(r,key,label,desc,"toggle")
local b=Instance.new("TextButton",r)
b.Size=UDim2.new(0,54,0,26); b.Position=UDim2.new(1,-66,0.5,-13)
b.BackgroundColor3=Config[key] and GhostControlOn or Color3.fromRGB(45,48,62)
b.Text=""; b.AutoButtonColor=false; b.ZIndex=59
Instance.new("UICorner",b).CornerRadius=UDim.new(1,0)
local knob=Instance.new("Frame",b)
knob.Size=UDim2.new(0,20,0,20)
knob.Position=Config[key] and UDim2.new(1,-23,0.5,-10) or UDim2.new(0,3,0.5,-10)
knob.BackgroundColor3=Color3.fromRGB(255,255,255); knob.ZIndex=60
Instance.new("UICorner",knob).CornerRadius=UDim.new(1,0)
local function refresh()
tween(b,0.16,{BackgroundColor3=Config[key] and GhostControlOn or Color3.fromRGB(45,48,62)})
tween(knob,0.16,{Position=Config[key] and UDim2.new(1,-23,0.5,-10) or UDim2.new(0,3,0.5,-10)})
end
b.MouseButton1Click:Connect(function() Config[key]=not Config[key]; refresh(); ghostScheduleAutoSave() end)
controls[key]=refresh
end
function slider(parent,label,desc,key,min,max,step)
local r=row(parent,label,desc)
addFavoriteStar(r,key,label,desc,"slider",{min=min,max=max,step=step})
local val=Instance.new("TextLabel",r)
val.BackgroundTransparency=1; val.Size=UDim2.new(0,82,0,20); val.Position=UDim2.new(1,-90,0,4)
val.Font=Enum.Font.GothamBold; val.TextSize=12; val.TextColor3=GhostTextMain; val.ZIndex=59
local bar=Instance.new("Frame",r)
bar.Size=UDim2.new(0,180,0,6); bar.Position=UDim2.new(1,-214,0,31)
bar.BackgroundColor3=Color3.fromRGB(52,46,72); bar.ZIndex=59
Instance.new("UICorner",bar).CornerRadius=UDim.new(1,0)
local fill=Instance.new("Frame",bar)
fill.BackgroundColor3=GhostControlFill; fill.Size=UDim2.new(0,0,1,0); fill.ZIndex=60
Instance.new("UICorner",fill).CornerRadius=UDim.new(1,0)
local draggingS=false
local function setFromX(x)
local pct=clamp((x-bar.AbsolutePosition.X)/bar.AbsoluteSize.X,0,1)
local v=math.floor((min+(max-min)*pct)/(step or 1)+0.5)*(step or 1)
Config[key]=clamp(v,min,max); ghostScheduleAutoSave()
fill.Size=UDim2.new((Config[key]-min)/(max-min),0,1,0); val.Text=tostring(Config[key])
end
local function refresh()
fill.Size=UDim2.new((Config[key]-min)/(max-min),0,1,0); val.Text=tostring(Config[key])
end
refresh()
bar.InputBegan:Connect(function(i) if i.UserInputType==Enum.UserInputType.MouseButton1 then draggingS=true; setFromX(i.Position.X) end end)
UIS.InputEnded:Connect(function(i) if i.UserInputType==Enum.UserInputType.MouseButton1 then draggingS=false end end)
UIS.InputChanged:Connect(function(i) if draggingS and i.UserInputType==Enum.UserInputType.MouseMovement then setFromX(i.Position.X) end end)
controls[key]=refresh
end
function dropdown(parent,label,desc,key,options)
local r=row(parent,label,desc)
addFavoriteStar(r,key,label,desc,"dropdown",{options=options})
local b=Instance.new("TextButton",r)
b.Size=UDim2.new(0,160,0,28); b.Position=UDim2.new(1,-172,0.5,-14)
b.BackgroundColor3=Color3.fromRGB(22,10,38); b.Text=tostring(Config[key]).." v"
b.Font=Enum.Font.GothamBold; b.TextSize=12; b.TextColor3=Color3.fromRGB(240,240,255); b.ZIndex=59
Instance.new("UICorner",b).CornerRadius=UDim.new(0,15)
local idx=1; for i,v in safeIpairs(options) do if v==Config[key] then idx=i end end
b.MouseButton1Click:Connect(function()
idx=idx%#options+1; Config[key]=options[idx]; b.Text=tostring(Config[key]).." v"; ghostScheduleAutoSave()
end)
controls[key]=function() b.Text=tostring(Config[key]).." v" end
end
function keybind(parent,label,desc,key)
local r=row(parent,label,desc)
addFavoriteStar(r,key,label,desc,"keybind")
local b=Instance.new("TextButton",r)
b.Size=UDim2.new(0,130,0,28); b.Position=UDim2.new(1,-142,0.5,-14)
b.BackgroundColor3=Color3.fromRGB(22,10,38); b.Text=Config[key]
b.Font=Enum.Font.GothamBold; b.TextSize=12; b.TextColor3=Color3.fromRGB(240,240,255); b.ZIndex=59
Instance.new("UICorner",b).CornerRadius=UDim.new(0,15)
local listening=false
b.MouseButton1Click:Connect(function() listening=true; b.Text="Press key..." end)
UIS.InputBegan:Connect(function(input,gp)
if listening then
listening=false
if input.UserInputType==Enum.UserInputType.MouseButton1 then Config[key]="MouseButton1"
elseif input.UserInputType==Enum.UserInputType.MouseButton2 then Config[key]="MouseButton2"
elseif input.KeyCode~=Enum.KeyCode.Unknown then Config[key]=input.KeyCode.Name end
b.Text=Config[key]; ghostScheduleAutoSave()
end
end)
end
function button(parent,label,desc,callback)
local r=row(parent,label,desc)
local b=Instance.new("TextButton",r)
b.Size=UDim2.new(0,130,0,28); b.Position=UDim2.new(1,-142,0.5,-14)
b.BackgroundColor3=Color3.fromRGB(28,28,36); b.Text="Run"
b.Font=Enum.Font.GothamBlack; b.TextSize=12; b.TextColor3=Color3.fromRGB(255,255,255); b.ZIndex=59
Instance.new("UICorner",b).CornerRadius=UDim.new(0,15)
b.MouseButton1Click:Connect(function() callback(); ghostScheduleAutoSave() end)
end
-- =====================
-- PREVIEW HELPERS
-- =====================
function miniLabel(parent,text,pos,size,color)
local l=Instance.new("TextLabel",parent)
l.BackgroundTransparency=1; l.Position=pos; l.Size=size; l.Text=text
l.Font=Enum.Font.GothamBold; l.TextSize=11; l.TextColor3=color or Color3.fromRGB(235,235,245)
l.TextXAlignment=Enum.TextXAlignment.Left; l.ZIndex=12
return l
end
function crosshairPreview(parent)
local r=row(parent,"Live Preview","Shows crosshair while menu is open")
r.Size=UDim2.new(1,0,0,120)
local box=Instance.new("Frame",r)
box.Position=UDim2.new(1,-172,0,8); box.Size=UDim2.new(0,160,0,104)
box.BackgroundColor3=Color3.fromRGB(5,5,8); box.BorderSizePixel=0; box.ZIndex=8
Instance.new("UICorner",box).CornerRadius=UDim.new(0,14)
local st=Instance.new("UIStroke",box); st.Color=Config.UIAccent; st.Transparency=0.55
local dot=Instance.new("Frame",box)
dot.Size=UDim2.new(0,4,0,4); dot.AnchorPoint=Vector2.new(0.5,0.5); dot.Position=UDim2.new(0.5,0,0.5,0)
dot.BorderSizePixel=0; dot.ZIndex=10; Instance.new("UICorner",dot).CornerRadius=UDim.new(1,0)
local lines={}
for i=1,4 do local l=Instance.new("Frame",box); l.BorderSizePixel=0; l.ZIndex=10; lines[i]=l end
RunService.RenderStepped:Connect(function()
if ghostUnloaded or not box.Parent then return end
local col=Config.CrosshairColor
dot.BackgroundColor3=col; dot.Visible=Config.Crosshair and Config.CrosshairDot
local gap=Config.CrosshairGap; local len=Config.CrosshairLength; local th=Config.CrosshairThickness
local profile=Config.CrosshairProfile or "Classic"
local cx,cy=80,52
local specs={{cx+gap,cy-th/2,len,th},{cx-gap-len,cy-th/2,len,th},{cx-th/2,cy+gap,th,len},{cx-th/2,cy-gap-len,th,len}}
for i,l in ipairs(lines) do
local s=specs[i]
l.Position=UDim2.new(0,s[1],0,s[2]); l.Size=UDim2.new(0,s[3],0,s[4]); l.BackgroundColor3=col
l.Visible=Config.Crosshair and profile~="Dot" and not (profile=="T-Shape" and i==3)
end
end)
end
function visualPreview(parent)
local r=row(parent,"Live Preview","ESP/arrows/FOV sample while editing")
r.Size=UDim2.new(1,0,0,150)
local box=Instance.new("Frame",r)
box.Position=UDim2.new(1,-242,0,8); box.Size=UDim2.new(0,230,0,132)
box.BackgroundColor3=Color3.fromRGB(5,5,8); box.BorderSizePixel=0; box.ZIndex=8
Instance.new("UICorner",box).CornerRadius=UDim.new(0,14)
local st=Instance.new("UIStroke",box); st.Color=Config.UIAccent; st.Transparency=0.55
miniLabel(box,"VISUALS",UDim2.new(0,10,0,6),UDim2.new(1,-20,0,16),Color3.fromRGB(180,180,200))
local dummy=Instance.new("Frame",box); dummy.Position=UDim2.new(0,96,0,38); dummy.Size=UDim2.new(0,36,0,54); dummy.BackgroundColor3=Color3.fromRGB(24,26,34); dummy.BorderSizePixel=0; dummy.ZIndex=10; Instance.new("UICorner",dummy).CornerRadius=UDim.new(0,8)
local boxLine=Instance.new("Frame",box); boxLine.BackgroundTransparency=1; boxLine.Position=UDim2.new(0,91,0,33); boxLine.Size=UDim2.new(0,46,0,64); boxLine.ZIndex=11
local boxStroke=Instance.new("UIStroke",boxLine); boxStroke.Color=Color3.fromRGB(120,255,170); boxStroke.Thickness=1; boxStroke.Transparency=0.05
local name=miniLabel(box,"Target",UDim2.new(0,94,0,18),UDim2.new(0,80,0,14),Color3.fromRGB(255,255,255))
local dist=miniLabel(box,"42m",UDim2.new(0,103,0,98),UDim2.new(0,60,0,14),Color3.fromRGB(210,210,210))
local hpBack=Instance.new("Frame",box); hpBack.Position=UDim2.new(0,84,0,34); hpBack.Size=UDim2.new(0,4,0,62); hpBack.BackgroundColor3=Color3.fromRGB(45,48,62); hpBack.BorderSizePixel=0; hpBack.ZIndex=10
local hp=Instance.new("Frame",hpBack); hp.AnchorPoint=Vector2.new(0,1); hp.Position=UDim2.new(0,0,1,0); hp.Size=UDim2.new(1,0,0.72,0); hp.BackgroundColor3=Color3.fromRGB(90,255,150); hp.BorderSizePixel=0; hp.ZIndex=11
local tracer=Instance.new("Frame",box); tracer.AnchorPoint=Vector2.new(0.5,0.5); tracer.BackgroundColor3=GhostControlFill; tracer.BorderSizePixel=0; tracer.ZIndex=9
local arrow=Instance.new("TextLabel",box); arrow.BackgroundTransparency=1; arrow.Position=UDim2.new(1,-38,0,50); arrow.Size=UDim2.new(0,28,0,28); arrow.Text=">"; arrow.Font=Enum.Font.GothamBlack; arrow.TextSize=26; arrow.TextColor3=Color3.fromRGB(255,190,70); arrow.ZIndex=12
local fov=Instance.new("Frame",box); fov.AnchorPoint=Vector2.new(0.5,0.5); fov.Position=UDim2.new(0,44,0,78); fov.Size=UDim2.new(0,48,0,48); fov.BackgroundTransparency=1; fov.ZIndex=10; Instance.new("UICorner",fov).CornerRadius=UDim.new(1,0)
local fs=Instance.new("UIStroke",fov); fs.Color=Color3.fromRGB(90,220,255); fs.Thickness=1; fs.Transparency=0.35
local trig=Instance.new("Frame",box); trig.AnchorPoint=Vector2.new(0.5,0.5); trig.Position=UDim2.new(0,44,0,78); trig.Size=UDim2.new(0,30,0,30); trig.BackgroundTransparency=1; trig.ZIndex=11; Instance.new("UICorner",trig).CornerRadius=UDim.new(1,0)
local ts=Instance.new("UIStroke",trig); ts.Color=Color3.fromRGB(255,190,70); ts.Thickness=1; ts.Transparency=0.25
RunService.RenderStepped:Connect(function()
if ghostUnloaded or not box.Parent then return end
local active=(currentTab=="Visuals" or currentTab=="Favorited")
box.Visible=active and previewsEnabled()
boxStroke.Enabled=Config.BoxESP; name.Visible=Config.NameESP; dist.Visible=Config.DistanceESP
hpBack.Visible=Config.HealthESP; hp.Visible=Config.HealthESP; tracer.Visible=Config.TracerESP
arrow.Visible=Config.OffscreenArrows; fs.Thickness=Config.FOVThickness; fs.Transparency=Config.FOVTransparency
fov.Visible=Config.FOVVisible; ts.Thickness=Config.FOVThickness; ts.Transparency=Config.FOVTransparency
trig.Visible=Config.TriggerFOVVisible; arrow.TextSize=Config.ArrowSize+10
st.Color=Config.UIAccent; tracer.BackgroundColor3=GhostControlFill
tracer.Position=UDim2.new(0,70,0,104); tracer.Size=UDim2.new(0,70,0,2); tracer.Rotation=-28
end)
end
function combatPreview(parent)
local r=row(parent,"Live Preview","Aim/trigger target HUD sample")
r.Size=UDim2.new(1,0,0,150)
local box=Instance.new("Frame",r)
box.Position=UDim2.new(1,-242,0,8); box.Size=UDim2.new(0,230,0,132)
box.BackgroundColor3=Color3.fromRGB(5,5,8); box.BorderSizePixel=0; box.ZIndex=8
Instance.new("UICorner",box).CornerRadius=UDim.new(0,14)
local st=Instance.new("UIStroke",box); st.Color=Config.UIAccent; st.Transparency=0.55
miniLabel(box,"COMBAT",UDim2.new(0,10,0,6),UDim2.new(1,-20,0,16),Color3.fromRGB(180,180,200))
local aim=Instance.new("Frame",box); aim.AnchorPoint=Vector2.new(0.5,0.5); aim.Position=UDim2.new(0,58,0,76); aim.Size=UDim2.new(0,64,0,64); aim.BackgroundTransparency=1; aim.ZIndex=9; Instance.new("UICorner",aim).CornerRadius=UDim.new(1,0)
local as=Instance.new("UIStroke",aim); as.Color=Color3.fromRGB(90,220,255); as.Thickness=1; as.Transparency=0.35
local trig=Instance.new("Frame",box); trig.AnchorPoint=Vector2.new(0.5,0.5); trig.Position=UDim2.new(0,58,0,76); trig.Size=UDim2.new(0,34,0,34); trig.BackgroundTransparency=1; trig.ZIndex=10; Instance.new("UICorner",trig).CornerRadius=UDim.new(1,0)
local ts=Instance.new("UIStroke",trig); ts.Color=Color3.fromRGB(255,190,70); ts.Thickness=1; ts.Transparency=0.25
local target=Instance.new("Frame",box); target.Position=UDim2.new(0,134,0,48); target.Size=UDim2.new(0,34,0,48); target.BackgroundColor3=Color3.fromRGB(24,26,34); target.BorderSizePixel=0; target.ZIndex=10; Instance.new("UICorner",target).CornerRadius=UDim.new(0,8)
local lock=Instance.new("Frame",box); lock.AnchorPoint=Vector2.new(0.5,0.5); lock.Position=UDim2.new(0,151,0,60); lock.Size=UDim2.new(0,24,0,24); lock.BackgroundTransparency=1; lock.ZIndex=12; Instance.new("UICorner",lock).CornerRadius=UDim.new(1,0)
local ls=Instance.new("UIStroke",lock); ls.Color=Color3.fromRGB(90,255,150); ls.Thickness=2; ls.Transparency=0.1
local info=miniLabel(box,"100 HP | 42m",UDim2.new(0,118,0,98),UDim2.new(0,100,0,16),Color3.fromRGB(235,255,235))
local status=miniLabel(box,"TRG HOLD",UDim2.new(0,10,0,112),UDim2.new(1,-20,0,14),Color3.fromRGB(255,190,70))
RunService.RenderStepped:Connect(function()
if ghostUnloaded or not box.Parent then return end
local active=(currentTab=="Combat" or currentTab=="Favorited")
box.Visible=active and previewsEnabled(); st.Color=Config.UIAccent
aim.Visible=Config.FOVVisible and (Config.Aimbot or Config.AimAssist); as.Thickness=Config.FOVThickness; as.Transparency=Config.FOVTransparency
trig.Visible=Config.TriggerBot and Config.TriggerFOVVisible; ts.Thickness=Config.FOVThickness; ts.Transparency=Config.FOVTransparency
lock.Visible=Config.TargetLockCircle; info.Visible=Config.TargetInfo
status.Text=Config.TriggerBot and (Config.TriggerHold and "TRG HOLD" or "TRG TAP") or "TRG OFF"
status.TextColor3=Config.TriggerBot and Color3.fromRGB(255,190,70) or Color3.fromRGB(120,120,135)
end)
end
function hudPreview(parent)
local r=row(parent,"HUD Preview","Top indicators and target info sample")
r.Size=UDim2.new(1,0,0,112)
local box=Instance.new("Frame",r)
box.Position=UDim2.new(1,-242,0,8); box.Size=UDim2.new(0,230,0,94)
box.BackgroundColor3=Color3.fromRGB(5,5,8); box.BorderSizePixel=0; box.ZIndex=8
Instance.new("UICorner",box).CornerRadius=UDim.new(0,14)
local st=Instance.new("UIStroke",box); st.Color=Config.UIAccent; st.Transparency=0.55
local topShadow=miniLabel(box,"FPS 144 | Ping 57 | Target none",UDim2.new(0,12,0,16),UDim2.new(1,-20,0,16),Color3.fromRGB(0,0,0))
local top=miniLabel(box,"FPS 144 | Ping 57 | Target none",UDim2.new(0,10,0,14),UDim2.new(1,-20,0,16),Color3.fromRGB(235,235,255))
local target=miniLabel(box,"100 HP | 42m",UDim2.new(0,70,0,56),UDim2.new(1,-20,0,16),Color3.fromRGB(235,255,235))
RunService.RenderStepped:Connect(function()
if ghostUnloaded or not box.Parent then return end
st.Color=Config.UIAccent
top.Visible=Config.TopIndicators; topShadow.Visible=Config.TopIndicators; target.Visible=Config.TargetInfo
end)
end
-- =====================
-- MINIMAP (enhanced: grid + LoS)
-- =====================
function makeMiniMap()
if MiniMapFrame then return end
MiniMapFrame=Instance.new("Frame",ScreenGui)
MiniMapFrame.Name="GhostMiniMap"
MiniMapFrame.Size=UDim2.new(0,Config.MiniMapSize,0,Config.MiniMapSize)
MiniMapFrame.Position=UDim2.new(1,-190,1,-210)
MiniMapFrame.BackgroundColor3=Color3.fromRGB(0,0,0)
MiniMapFrame.BackgroundTransparency=Config.MiniMapOpacity
MiniMapFrame.BorderSizePixel=0; MiniMapFrame.ZIndex=20
Instance.new("UICorner",MiniMapFrame).CornerRadius=UDim.new(1,0)
local stroke=Instance.new("UIStroke",MiniMapFrame); stroke.Name="Stroke"; stroke.Color=Config.UIAccent; stroke.Transparency=0.25; stroke.Thickness=1.2
-- Grid overlay (distance rings every N studs)
-- Drawn as concentric circle strokes inside the map frame
local gridHolder=Instance.new("Frame",MiniMapFrame)
gridHolder.Name="GridHolder"; gridHolder.BackgroundTransparency=1
gridHolder.Size=UDim2.new(1,0,1,0); gridHolder.ZIndex=21
local function rebuildGrid()
for _,c in pairs(gridHolder:GetChildren()) do c:Destroy() end
if not Config.MiniMapGrid then return end
local mapSize=Config.MiniMapSize or 160
local zoom=Config.MiniMapZoom or 2
local spacing=Config.MiniMapGridSpacing or 20 -- studs
local pixelsPerStud=mapSize/2 / (mapSize/2 * zoom / mapSize * mapSize)
-- How many pixels per stud: mapSize/2 pixels = zoom*? studs from center
-- At zoom=2, center to edge = mapSize/2 px = mapSize*zoom/2 studs... let's compute:
-- pixelsPerStud = (mapSize/2) / (mapSize*zoom/2) = 1/zoom
-- So in pixels: ringRadius = spacing * (mapSize/2) / (mapSize*zoom/2) * i
-- = spacing * i / zoom (in fractional map units * mapSize/2)
local halfPx = mapSize/2
local studsPerHalf = halfPx * zoom -- studs from center to edge
local ringsMax = math.floor(studsPerHalf / spacing)
for i=1,ringsMax do
local ringPx = (spacing * i / studsPerHalf) * halfPx * 2 -- diameter in px
if ringPx > 0 and ringPx <= mapSize+4 then
local ring=Instance.new("Frame",gridHolder)
ring.AnchorPoint=Vector2.new(0.5,0.5); ring.Position=UDim2.new(0.5,0,0.5,0)
ring.Size=UDim2.new(0,ringPx,0,ringPx)
ring.BackgroundTransparency=1; ring.BorderSizePixel=0; ring.ZIndex=21
Instance.new("UICorner",ring).CornerRadius=UDim.new(1,0)
local rs=Instance.new("UIStroke",ring); rs.Color=Color3.fromRGB(60,60,80); rs.Transparency=0.55; rs.Thickness=1
end
end
end
rebuildGrid()
MiniMapFrame:GetAttributeChangedSignal("MiniMapGrid"):Connect(function() rebuildGrid() end)
local north=Instance.new("TextLabel",MiniMapFrame)
north.Name="North"; north.BackgroundTransparency=1; north.Size=UDim2.new(0,26,0,18)
north.Position=UDim2.new(0.5,-13,0,5); north.Text="N"; north.Font=Enum.Font.GothamBlack
north.TextSize=13; north.TextColor3=Color3.fromRGB(235,235,255); north.ZIndex=22
local crossA=Instance.new("Frame",MiniMapFrame)
crossA.BackgroundColor3=Color3.fromRGB(65,65,80); crossA.BackgroundTransparency=0.45
crossA.BorderSizePixel=0; crossA.AnchorPoint=Vector2.new(0.5,0.5); crossA.Position=UDim2.new(0.5,0,0.5,0)
crossA.Size=UDim2.new(1,-22,0,1); crossA.ZIndex=21
local crossB=Instance.new("Frame",MiniMapFrame)
crossB.BackgroundColor3=Color3.fromRGB(65,65,80); crossB.BackgroundTransparency=0.45
crossB.BorderSizePixel=0; crossB.AnchorPoint=Vector2.new(0.5,0.5); crossB.Position=UDim2.new(0.5,0,0.5,0)
crossB.Size=UDim2.new(0,1,1,-22); crossB.ZIndex=21
MiniMapFrame.InputBegan:Connect(function(i)
if i.UserInputType==Enum.UserInputType.MouseButton1 then
MiniMapDragging=true
local start=i.Position; local startPos=MiniMapFrame.Position
local conn; conn=UIS.InputChanged:Connect(function(ch)
if MiniMapDragging and ch.UserInputType==Enum.UserInputType.MouseMovement then
local d=ch.Position-start
MiniMapFrame.Position=UDim2.new(startPos.X.Scale,startPos.X.Offset+d.X,startPos.Y.Scale,startPos.Y.Offset+d.Y)
end
end)
i.Changed:Connect(function()
if i.UserInputState==Enum.UserInputState.End then MiniMapDragging=false; if conn then conn:Disconnect() end end
end)
end
end)
end
function minimapDot(name,color,size)
makeMiniMap()
if MiniMapDots[name] then return MiniMapDots[name] end
local d=Instance.new("Frame",MiniMapFrame)
d.Name=name; d.Size=UDim2.new(0,size or 7,0,size or 7)
d.AnchorPoint=Vector2.new(0.5,0.5); d.BackgroundColor3=color
d.BorderSizePixel=0; d.ZIndex=23
Instance.new("UICorner",d).CornerRadius=UDim.new(1,0)
local s=Instance.new("UIStroke",d); s.Color=Color3.fromRGB(0,0,0); s.Transparency=0.25; s.Thickness=1
local lbl=Instance.new("TextLabel",d)
lbl.Name="Label"; lbl.BackgroundTransparency=1; lbl.Position=UDim2.new(1,3,0.5,-7)
lbl.Size=UDim2.new(0,70,0,14); lbl.Font=Enum.Font.GothamBold; lbl.TextSize=10
lbl.TextColor3=Color3.fromRGB(245,245,250); lbl.TextXAlignment=Enum.TextXAlignment.Left
lbl.Text=""; lbl.ZIndex=24
MiniMapDots[name]=d
return d
end
function minimapWorldToMap(worldPos)
local root=getRoot(lp); if not root then return nil end
local mapSize=Config.MiniMapSize or 160
local zoom=Config.MiniMapZoom or 2
local center=Vector2.new(mapSize/2,mapSize/2)
local rel=worldPos-root.Position
local yaw=math.atan2(camera.CFrame.LookVector.X,camera.CFrame.LookVector.Z)
local cos=math.cos(-yaw); local sin=math.sin(-yaw)
local x=(rel.X*cos-rel.Z*sin)/zoom
local y=(rel.X*sin+rel.Z*cos)/zoom
local maxR=(mapSize/2)-12
local v=Vector2.new(x,-y)
if v.Magnitude>maxR then v=v.Unit*maxR end
return Vector2.new(center.X+v.X,center.Y+v.Y)
end
function minimapSetDot(name,worldPos,color,size,label)
makeMiniMap()
local mapPos=minimapWorldToMap(worldPos)
if not mapPos then return end
local mapSize=Config.MiniMapSize or 160
local d=minimapDot(name,color,size)
d.Position=UDim2.new(0,mapPos.X,0,mapPos.Y)
d.BackgroundColor3=color
local lbl=d:FindFirstChild("Label")
if lbl then lbl.Text=(Config.MiniMapLabels and label) and tostring(label) or "" end
d.Visible=true
end
-- LoS lines + prediction cones drawn on minimap using pre-allocated Drawing pool
function updateLOSMap()
if not Config.MiniMap or not MiniMapFrame or not MiniMapFrame.Visible then
for _,l in ipairs(LOSLines) do l.Visible=false end
for _,c in ipairs(LOSCones) do c.Visible=false end
return
end
local root=getRoot(lp); if not root then return end
local mapSize=Config.MiniMapSize or 160
local zoom=Config.MiniMapZoom or 2
local mapPos=MiniMapFrame.AbsolutePosition -- screen position of map frame
local li=0; local ci=0
for _,p in safeIpairs(Players:GetPlayers()) do
if p~=lp and validEnemy(p) then
local ch=getChar(p); local r=getRoot(p)
if r and ch then
local rig=resolveRig(ch)
-- Convert world pos to map-frame pixel position
local dot=minimapWorldToMap(r.Position)
if dot then
local screenDot=Vector2.new(mapPos.X+dot.X, mapPos.Y+dot.Y)
-- LoS line: short line from dot in the direction they're facing
if Config.LOSMapLines then
li=li+1; if li<=#LOSLines then
local line=LOSLines[li]
-- Use root CFrame look vector projected onto XZ plane
local look=Vector3.new(r.CFrame.LookVector.X,0,r.CFrame.LookVector.Z)
local yaw=math.atan2(camera.CFrame.LookVector.X,camera.CFrame.LookVector.Z)
local cos=math.cos(-yaw); local sin=math.sin(-yaw)
-- Rotate look into map space
local mx=( look.X*cos-look.Z*sin)
local my=( look.X*sin+look.Z*cos)
local lineLen=(Config.LOSLineLength or 20)/zoom
local endPt=screenDot+Vector2.new(mx,-my).Unit*lineLen
line.From=screenDot; line.To=endPt
line.Color=Color3.fromRGB(255,255,80)
line.Transparency=0.45; line.Thickness=1; line.Visible=true
end
end
-- Prediction cone: green filled triangle in velocity direction
if Config.LOSPredictionCone then
ci=ci+1; if ci<=#LOSCones then
local cone=LOSCones[ci]
local vel=r.AssemblyLinearVelocity or Vector3.zero
local flatVel=Vector3.new(vel.X,0,vel.Z)
if flatVel.Magnitude>1 then
local yaw=math.atan2(camera.CFrame.LookVector.X,camera.CFrame.LookVector.Z)
local cos=math.cos(-yaw); local sin=math.sin(-yaw)
local vx=(flatVel.X*cos-flatVel.Z*sin)/zoom
local vy=(flatVel.X*sin+flatVel.Z*cos)/zoom
local vDir=Vector2.new(vx,-vy).Unit
local coneLen=(Config.LOSConeLength or 28)/zoom
local halfAngle=math.rad(Config.LOSConeAngle or 22)
local perp=Vector2.new(-vDir.Y,vDir.X)
local tip=screenDot+vDir*coneLen
local base1=screenDot+perp*math.tan(halfAngle)*coneLen*0.5
local base2=screenDot-perp*math.tan(halfAngle)*coneLen*0.5
cone.PointA=tip; cone.PointB=base1; cone.PointC=base2
cone.Color=Color3.fromRGB(80,255,120)
cone.Transparency=0.72; cone.Filled=true; cone.Visible=true
else cone.Visible=false end
end
end
end
end
end
end
-- Hide unused pool slots
for i=li+1,#LOSLines do LOSLines[i].Visible=false end
for i=ci+1,#LOSCones do LOSCones[i].Visible=false end
end
function updateMiniMap()
if not Config.MiniMap or Config.Hidden or ghostUnloaded then
if MiniMapFrame then MiniMapFrame.Visible=false end
for _,l in ipairs(LOSLines) do l.Visible=false end
for _,c in ipairs(LOSCones) do c.Visible=false end
return
end
makeMiniMap()
MiniMapFrame.Visible=true
MiniMapFrame.Size=UDim2.new(0,Config.MiniMapSize,0,Config.MiniMapSize)
MiniMapFrame.BackgroundTransparency=Config.MiniMapOpacity
local stroke=MiniMapFrame:FindFirstChild("Stroke"); if stroke then stroke.Color=Config.UIAccent end
for _,dot in safePairs(MiniMapDots) do dot.Visible=false end
local root=getRoot(lp)
if root then
if Config.MiniMapTrail and now()-lastMiniMapTrail>0.35 then
lastMiniMapTrail=now()
table.insert(MiniMapTrail,root.Position)
if #MiniMapTrail>18 then table.remove(MiniMapTrail,1) end
end
local selfDot=minimapDot("self",GhostControlFill,11)
selfDot.Position=UDim2.new(0.5,0,0.5,0); selfDot.BackgroundColor3=GhostControlFill; selfDot.Visible=true
selfDot.Rotation=math.deg(math.atan2(camera.CFrame.LookVector.X,camera.CFrame.LookVector.Z))
local lbl=selfDot:FindFirstChild("Label"); if lbl then lbl.Text=Config.MiniMapLabels and "You" or "" end
if Config.MiniMapTrail then
for i,pos in safeIpairs(MiniMapTrail) do
local alpha=i/#MiniMapTrail
minimapSetDot("trail_"..i,pos,Color3.fromRGB(120,120,150),4,nil)
local dot=MiniMapDots["trail_"..i]
if dot then dot.BackgroundTransparency=0.75-(alpha*0.35) end
end
end
-- Enemy dots
for _,p in safeIpairs(Players:GetPlayers()) do
if p~=lp and validEnemy(p) then
local r=getRoot(p)
if r then
local aaType=getAntiAimType(p)
local col=aaType and Color3.fromRGB(255,80,80) or Color3.fromRGB(255,90,90)
minimapSetDot("enemy_"..p.UserId,r.Position,col,7,p.Name)
end
end
end
if Config.MiniMapTeam then
for _,p in safeIpairs(Players:GetPlayers()) do
if p~=lp and lp.Team and p.Team and p.Team==lp.Team and isAlive(p) then
local r=getRoot(p)
if r then minimapSetDot("team_"..p.UserId,r.Position,Color3.fromRGB(90,220,255),7,p.Name) end
end
end
end
if Config.MiniMapWaypoints then
for i,pos in safeIpairs(MiniMapWaypoints) do minimapSetDot("wp_"..i,pos,Color3.fromRGB(255,220,90),7,"WP"..i) end
end
end
updateLOSMap()
end
function minimapPreview(parent)
local r=row(parent,"Mini Map Preview","Self/enemy/team radar sample")
r.Size=UDim2.new(1,0,0,150)
local box=Instance.new("Frame",r)
box.Position=UDim2.new(1,-172,0,8); box.Size=UDim2.new(0,132,0,132)
box.BackgroundColor3=Color3.fromRGB(5,5,8); box.BackgroundTransparency=Config.MiniMapOpacity
box.BorderSizePixel=0; box.ZIndex=8
Instance.new("UICorner",box).CornerRadius=UDim.new(1,0)
local st=Instance.new("UIStroke",box); st.Color=Config.UIAccent; st.Transparency=0.35; st.Thickness=1
miniLabel(box,"N",UDim2.new(0.5,-8,0,5),UDim2.new(0,20,0,16),Color3.fromRGB(235,235,255))
local self=Instance.new("Frame",box); self.AnchorPoint=Vector2.new(0.5,0.5); self.Position=UDim2.new(0.5,0,0.5,0); self.Size=UDim2.new(0,9,0,9); self.BackgroundColor3=GhostControlFill; self.BorderSizePixel=0; self.ZIndex=10; Instance.new("UICorner",self).CornerRadius=UDim.new(1,0)
local enemy=Instance.new("Frame",box); enemy.AnchorPoint=Vector2.new(0.5,0.5); enemy.Position=UDim2.new(0.65,0,0.38,0); enemy.Size=UDim2.new(0,7,0,7); enemy.BackgroundColor3=Color3.fromRGB(255,90,90); enemy.BorderSizePixel=0; enemy.ZIndex=10; Instance.new("UICorner",enemy).CornerRadius=UDim.new(1,0)
local wp=Instance.new("Frame",box); wp.AnchorPoint=Vector2.new(0.5,0.5); wp.Position=UDim2.new(0.35,0,0.68,0); wp.Size=UDim2.new(0,7,0,7); wp.BackgroundColor3=Color3.fromRGB(255,220,90); wp.BorderSizePixel=0; wp.ZIndex=10; Instance.new("UICorner",wp).CornerRadius=UDim.new(1,0)
RunService.RenderStepped:Connect(function()
if ghostUnloaded or not box.Parent then return end
box.Visible=(currentTab=="Visuals" or currentTab=="Favorited") and previewsEnabled()
box.BackgroundTransparency=Config.MiniMapOpacity
st.Color=Config.UIAccent; self.BackgroundColor3=GhostControlFill
wp.Visible=Config.MiniMapWaypoints
end)
end
-- =====================
-- SCANNER (unchanged logic, kept in full)
-- =====================
local scanSnapshotA=nil; local scanSnapshotB=nil
local scannerLastText="Run Scanner Guide first. Flow: Environment Check -> Scan Game -> Aggressive Defense Scan -> Snapshot Diff."
local scannerOutput=nil; local scannerSummary=nil
local interestingWords={"remote","weapon","gun","ammo","reload","damage","hit","shoot","ray","projectile","tool","inventory","round","match","team","anti","kick","ban","flag","objective","loot","crate","key","door","vehicle","admin","moderator","report","detect","security","guard","validate","server","client","fire","invoke","replicate","cooldown","spread","recoil","camera","humanoid","health","stamina","sprint","cash","coin","xp","level","quest","mission","zone","safe","checkpoint"}
function pathOf(inst) local ok,r=pcall(function() return inst:GetFullName() end); return ok and r or tostring(inst) end
function isInterestingName(name) local n=tostring(name or ""):lower(); for _,w in safeIpairs(interestingWords) do if n:find(w,1,true) then return true,w end end; return false,nil end
function scannerSet(text,summary) scannerLastText=text or ""; if scannerOutput then scannerOutput.Text=scannerLastText end; if scannerSummary then scannerSummary.Text=summary or "Ready" end end
function collectGameMap()
local data={remotes={},remoteFunctions={},modules={},scripts={},tools={},sounds={},interesting={},all={}}
local limit=Config.ScannerMaxResults or 80
local function push(list,inst) if #list<limit then table.insert(list,Config.ScannerShowPaths and pathOf(inst) or inst.Name) end end
for _,inst in safeIpairs(game:GetDescendants()) do
data.all[pathOf(inst)]=inst.ClassName
if inst:IsA("RemoteEvent") then push(data.remotes,inst)
elseif inst:IsA("RemoteFunction") then push(data.remoteFunctions,inst)
elseif inst:IsA("ModuleScript") then push(data.modules,inst)
elseif inst:IsA("LocalScript") or inst:IsA("Script") then push(data.scripts,inst)
elseif inst:IsA("Tool") then push(data.tools,inst)
elseif inst:IsA("Sound") then push(data.sounds,inst) end
local hit,word=isInterestingName(inst.Name)
if hit and #data.interesting<limit then table.insert(data.interesting,"["..inst.ClassName.."] "..pathOf(inst).." tag="..word) end
end
return data
end
function formatList(title,list)
local out={"-- "..title.." ("..tostring(#list)..")"}
for _,v in safeIpairs(list) do table.insert(out," "..tostring(v)) end
return table.concat(out,"\n")
end
function runPassiveScan()
local d=collectGameMap()
local parts={}
table.insert(parts,formatList("RemoteEvents",d.remotes))
table.insert(parts,formatList("RemoteFunctions",d.remoteFunctions))
table.insert(parts,formatList("Tools",d.tools))
table.insert(parts,formatList("Modules",d.modules))
table.insert(parts,formatList("Scripts",d.scripts))
table.insert(parts,formatList("Sounds",d.sounds))
table.insert(parts,formatList("Interesting names",d.interesting))
local summary="Remotes "..#d.remotes.." | RF "..#d.remoteFunctions.." | Tools "..#d.tools.." | Modules "..#d.modules.." | Scripts "..#d.scripts
scannerSet(table.concat(parts,"\n\n"),summary)
showApplyPopup("Scanner complete",summary,"success")
end
function runEnvCheck()
local checks={
{"Drawing API",Drawing~=nil},{"mouse1press",type(mouse1press)=="function"},{"mouse1release",type(mouse1release)=="function"},
{"getgc",type(getgc)=="function"},{"getconnections",type(getconnections)=="function"},{"hookfunction",type(hookfunction)=="function"},
{"getrawmetatable",type(getrawmetatable)=="function"},{"setclipboard",type(setclipboard)=="function"},
{"request/http",type(request)=="function" or type(http_request)=="function"},{"ScreenGui",ScreenGui~=nil},{"Camera",camera~=nil},
}
local out={"-- Environment Capability Check"}; local okCount=0
for _,c in safeIpairs(checks) do
if c[2] then okCount=okCount+1 end
table.insert(out,(c[2] and "OK " or "MISS ")..c[1])
end
scannerSet(table.concat(out,"\n"),"Capabilities "..okCount.."/"..#checks)
end
function takeScannerSnapshot(slot)
local d=collectGameMap(); local snap={time=now(),all=d.all}
if slot=="A" then scanSnapshotA=snap else scanSnapshotB=snap end
local c=0; for _ in safePairs(snap.all) do c=c+1 end
scannerSet("Snapshot "..slot.." saved with "..tostring(c).." objects.","Snapshot "..slot.." saved")
end
function diffScannerSnapshots()
if not scanSnapshotA or not scanSnapshotB then scannerSet("Take Snapshot A and B first.","Missing snapshots"); return end
local added,removed={},{}
for path,cls in safePairs(scanSnapshotB.all) do if not scanSnapshotA.all[path] then table.insert(added,"+ ["..cls.."] "..path) end end
for path,cls in safePairs(scanSnapshotA.all) do if not scanSnapshotB.all[path] then table.insert(removed,"- ["..cls.."] "..path) end end
table.sort(added); table.sort(removed)
local limit=Config.ScannerMaxResults or 80
local out={"-- Snapshot Diff","Added: "..#added,"Removed: "..#removed,"","-- Added"}
for i=1,math.min(#added,limit) do table.insert(out,added[i]) end
table.insert(out,""); table.insert(out,"-- Removed")
for i=1,math.min(#removed,limit) do table.insert(out,removed[i]) end
scannerSet(table.concat(out,"\n"),"Diff +"..#added.." / -"..#removed)
end
function classifyRemoteName(name)
local n=tostring(name or ""):lower()
if n:find("admin") or n:find("ban") or n:find("kick") or n:find("anti") or n:find("security") then return "Security/Admin" end
if n:find("damage") or n:find("hit") or n:find("shoot") or n:find("fire") or n:find("weapon") or n:find("gun") then return "Combat/Weapon" end
if n:find("reload") or n:find("ammo") or n:find("spread") or n:find("recoil") then return "Weapon State" end
if n:find("cash") or n:find("coin") or n:find("xp") or n:find("level") or n:find("reward") then return "Economy/Reward" end
if n:find("team") or n:find("round") or n:find("match") then return "Match/Team" end
return "General"
end
function scanValueObjects(root,limit)
local out={}
for _,inst in safeIpairs(root:GetDescendants()) do
if #out>=limit then break end
if inst:IsA("ValueBase") then
local ok,val=pcall(function() return tostring(inst.Value) end)
table.insert(out,"["..inst.ClassName.."] "..pathOf(inst).." = "..(ok and val or "?"))
end
end
return out
end
function runAggressiveDefenseScan()
local limit=Config.ScannerMaxResults or 80
local d=collectGameMap()
local out={"-- Aggressive Defensive Scan","Passive deep scan only. No remotes fired.",""}
local risk=0; local categories={}
for _,inst in safeIpairs(game:GetDescendants()) do
if inst:IsA("RemoteEvent") or inst:IsA("RemoteFunction") then
local cat=classifyRemoteName(inst.Name)
categories[cat]=categories[cat] or {}
if #categories[cat]<limit then table.insert(categories[cat],"["..inst.ClassName.."] "..pathOf(inst)) end
if cat=="Security/Admin" then risk=risk+4 elseif cat=="Combat/Weapon" or cat=="Economy/Reward" then risk=risk+2 else risk=risk+1 end
end
end
table.insert(out,"Risk Score: "..tostring(risk)); table.insert(out,"")
for cat,list in safePairs(categories) do
table.insert(out,"-- "..cat.." ("..#list..")")
for _,v in safeIpairs(list) do table.insert(out," "..v) end
table.insert(out,"")
end
local values=scanValueObjects(game,limit)
table.insert(out,"-- Value Objects ("..#values..")")
for _,v in safeIpairs(values) do table.insert(out," "..v) end
scannerSet(table.concat(out,"\n"),"Aggressive scan complete | risk "..risk)
showApplyPopup("Aggressive scan complete","Risk score "..risk..".","success")
end
function runScriptIndexer()
local out={"-- Script / Module Indexer"}; local count=0
for _,inst in safeIpairs(game:GetDescendants()) do
if inst:IsA("ModuleScript") or inst:IsA("LocalScript") or inst:IsA("Script") then
local hit,word=isInterestingName(inst.Name)
if hit then count=count+1; table.insert(out,"["..inst.ClassName.."] tag="..word.." "..pathOf(inst)); if count>=(Config.ScannerMaxResults or 80) then break end end
end
end
scannerSet(table.concat(out,"\n"),"Indexed interesting scripts: "..count)
end
local scannerWatchConn=nil; local scannerWatchLast=nil
function toggleScannerWatch()
if scannerWatchConn then scannerWatchConn:Disconnect(); scannerWatchConn=nil; Config.ScannerWatch=false; scannerSet("Scanner watch stopped.","Watch stopped"); return end
Config.ScannerWatch=true; scannerWatchLast=collectGameMap(); local lastTick=0
scannerWatchConn=RunService.Heartbeat:Connect(function()
if not Config.ScannerWatch or ghostUnloaded then if scannerWatchConn then scannerWatchConn:Disconnect(); scannerWatchConn=nil end; return end
if now()-lastTick<(Config.ScannerWatchInterval or 2) then return end; lastTick=now()
local current=collectGameMap(); local added,removed=0,0
for path,_ in safePairs(current.all) do if not scannerWatchLast.all[path] then added=added+1 end end
for path,_ in safePairs(scannerWatchLast.all) do if not current.all[path] then removed=removed+1 end end
if added>0 or removed>0 then scannerSet("Watch update: +"..added.." / -"..removed.." objects.","Watch +"..added.." / -"..removed); scannerWatchLast=current end
end)
scannerSet("Scanner watch started.","Watch running")
end
function showScannerGuide()
scannerSet(table.concat({"-- Scanner Quick Guide","1) Environment Check","2) Scan Game","3) Aggressive Defense Scan","4) Script Indexer","5) Snapshot A -> action -> Snapshot B -> Compare A/B","6) Object Watch (passive live monitor)"},"\n"),"Scanner guide loaded")
showApplyPopup("Scanner guide","Guide loaded.","success")
end
function copyScannerOutput()
if setclipboard then setclipboard(scannerLastText or ""); showApplyPopup("Scanner copied","Output copied to clipboard.","success")
else showApplyPopup("Clipboard unavailable","setclipboard not supported.","error") end
end
-- =====================
-- PAGES SETUP
-- =====================
makeTab("Favorited","*"); makeTab("Combat","*"); makeTab("Visuals","*")
makeTab("Crosshair","+"); makeTab("Config","#"); makeTab("Settings","*")
makeTab("Theme Studio","*"); makeTab("Scanner","#"); makeTab("Notes","#")
fav=makePage("Favorited"); combat=makePage("Combat"); visuals=makePage("Visuals")
cross=makePage("Crosshair"); configP=makePage("Config"); settings=makePage("Settings")
themeStudio=makePage("Theme Studio"); scanner=makePage("Scanner"); notes=makePage("Notes")
-- =====================
-- FAVORITED PAGE
-- =====================
;(function()
local q,_ = card(fav,"Starred Settings","*")
favDynamicBody=q
rebuildFavorites=function()
if not favDynamicBody then return end
for _,child in safeIpairs(favDynamicBody:GetChildren()) do
if not child:IsA("UIListLayout") then child:Destroy() end
end
local grouped={}; local count=0
for key,item in safePairs(favoriteItems) do
if FavoriteKeys[key] then
local cat=item.category or favoriteCategories[key] or "Other"
grouped[cat]=grouped[cat] or {}; table.insert(grouped[cat],item); count=count+1
end
end
if count==0 then favRow(favDynamicBody,"No favorites yet","Click stars beside settings to add them here"); return end
for _,cat in safeIpairs(favoriteOrder) do
local list=grouped[cat]
if list and #list>0 then
local header=Instance.new("TextLabel",favDynamicBody)
header.BackgroundTransparency=1; header.Size=UDim2.new(1,0,0,24)
header.Text=" "..cat; header.Font=Enum.Font.GothamBlack; header.TextSize=13
header.TextColor3=GhostTextMain; header.TextXAlignment=Enum.TextXAlignment.Left; header.ZIndex=7
table.sort(list,function(a,b) return tostring(a.label)<tostring(b.label) end)
for _,item in safeIpairs(list) do buildFavoriteControl(favDynamicBody,item) end
end
end
end
local qp,_ = card(fav,"Quick Presets","#")
button(qp,"Load Default Preset","Restore defaults",function()
Config.Aimbot=false; Config.AimSmooth=1; Config.AimFOV=30; Config.AimAssist=true; Config.AimAssistStrength=0.25
Config.TriggerBot=true; Config.TriggerHold=true; Config.TriggerFOV=20; Config.ESP=true; Config.SkeletonESP=true
Config.SkeletonMode="Bone"; Config.OffscreenArrows=true; Config.Crosshair=true; Config.FOVVisible=true
Config.WeaponSilhouette=false; Config.NameplateDistanceScale=true; Config.LOSMapLines=true; Config.LOSPredictionCone=true
Config.PingNormalize=false; Config.TickRateCompensate=false; Config.FlickAssist=false
Config.MultiTargetSuppressor=false; Config.AimShakeDampener=false; Config.TargetWeightSystem=true
Config.AntiAimDetect=true; Config.AntiAimIndicator=true; Config.AntiLag=false
for _,fn in safePairs(controls) do pcall(fn) end; if rebuildFavorites then rebuildFavorites() end
end)
button(qp,"Hide Visuals","Quick panic visual hide",function()
Config.Hidden=true; Root.Visible=false; mouseDown=false; triggerHolding=false; pcall(mouse1release)
end)
button(qp,"Reset Drawings","Clear stuck drawings",function()
for _,obj in safePairs(ESPObjects) do hideAll(obj); obj.ArrowSmooth=nil end
if FOVCircle then FOVCircle.Visible=false end; if SACircle then SACircle.Visible=false end
if TriggerCircle then TriggerCircle.Visible=false end; if TargetLock then TargetLock.Visible=false end
if ReloadLbl then ReloadLbl.Visible=false end; if CHDot then CHDot.Visible=false end
for _,l in safePairs(CHLines) do if l then l.Visible=false end end
for _,l in ipairs(LOSLines) do l.Visible=false end; for _,c in ipairs(LOSCones) do c.Visible=false end
end)
end)()
local favModes,_ = card(fav,"Favorite Sets","*")
button(favModes,"Save Favorites","Save starred favorites now",function() local ok=ghostSaveConfigFile(false); showApplyPopup(ok and "Saved" or "Failed",ghostLastSaveStatus,ok and "success" or "error") end)
button(favModes,"Combat Favorites","Focus combat controls",function() FavoriteKeys.AimAssist=true; FavoriteKeys.AimFOV=true; FavoriteKeys.TriggerBot=true; FavoriteKeys.TriggerFOV=true; FavoriteKeys.ESP=false; FavoriteKeys.Crosshair=false; if rebuildFavorites then rebuildFavorites() end; ghostSaveConfigFile(true) end)
button(favModes,"Visual Favorites","Focus visual controls",function() FavoriteKeys.ESP=true; FavoriteKeys.OffscreenArrows=true; FavoriteKeys.ArrowSize=true; FavoriteKeys.TargetInfo=true; FavoriteKeys.AimAssist=false; if rebuildFavorites then rebuildFavorites() end; ghostSaveConfigFile(true) end)
-- =====================
-- COMBAT PAGE
-- =====================
;(function()
local a,_ = card(combat,"Aimbot","*")
toggle(a,"Enable Aimbot","Smooth camera aim toward target","Aimbot")
keybind(a,"Aim Key","Hold this key to aim","AimKey")
dropdown(a,"Aim Part","Target body part (Auto uses universal resolver)","AimPart",{"Auto","Head","Torso","Root"})
slider(a,"Aim FOV","Aimbot field of view","AimFOV",0,800,1)
slider(a,"Smoothness","Lower is snappier","AimSmooth",0.01,10,0.01)
toggle(a,"Prediction","Lead moving targets","AimPrediction")
slider(a,"Prediction Scale","Velocity prediction amount","AimPredictionScale",0,0.5,0.01)
toggle(a,"Humanize","Tiny natural randomness","AimHumanize")
slider(a,"Deadzone","Avoid micro jitter","AimDeadzone",0,20,1)
toggle(a,"Aim Assist","Magnetic camera assist","AimAssist")
slider(a,"Assist Strength","Camera assist power","AimAssistStrength",0.01,1.0,0.01)
toggle(a,"Target Lock Circle","Show lock circle on visible target","TargetLockCircle")
combatPreview(a)
local s,_ = card(combat,"Silent / Trigger","*")
toggle(s,"Silent Aim","Redirect supported ray calls","SilentAim")
slider(s,"Silent FOV","Silent aim field of view","SilentFOV",0,800,1)
slider(s,"Hit Chance","Percent chance to redirect","SilentHitChance",1,100,1)
toggle(s,"Triggerbot","Auto fire when on target","TriggerBot")
slider(s,"Trigger Delay","Hold cooldown / safety delay","TriggerDelay",0.05,0.5,0.01)
slider(s,"Trigger FOV","Triggerbot circle size","TriggerFOV",0,500,1)
toggle(s,"Trigger FOV Circle","Show triggerbot FOV circle","TriggerFOVVisible")
toggle(s,"Trigger Hold","Hold fire while target detected","TriggerHold")
toggle(s,"Auto Pistol","Rapid semi-auto clicking","AutoPistol")
toggle(s,"No Recoil","Dampen camera recoil","NoRecoil")
-- COMBAT ADVANCED CARD
local adv,_ = card(combat,"Advanced","*")
-- Aim shake dampener
toggle(adv,"Aim Shake Dampener","Smooth out game-induced camera shake before aim runs","AimShakeDampener")
slider(adv,"Dampener Strength","How aggressively shake is removed","AimShakeDampStrength",0.1,1.0,0.05)
-- Target weight system
toggle(adv,"Target Weight System","Score targets by shootable + distance + health","TargetWeightSystem")
toggle(adv,"Weight: Shootable","Prefer visible unobstructed targets","TargetWeightShootable")
toggle(adv,"Weight: Distance","Prefer closer targets","TargetWeightDistance")
toggle(adv,"Weight: Health","Prefer lower HP targets","TargetWeightHealth")
-- Ping normalizer
toggle(adv,"Ping Normalizer","Offset shot timing by your ping for consistent hit reg","PingNormalize")
-- Tick rate compensator
toggle(adv,"Tick Rate Compensator","Adjust prediction step to match detected server tick rate","TickRateCompensate")
-- Anti-aim detector
toggle(adv,"Anti-Aim Detector","Detect spinbot and flipbot movement patterns","AntiAimDetect")
toggle(adv,"Anti-Aim Indicator","Draw AA warning above player and at screen top","AntiAimIndicator")
-- Anti-lag
toggle(adv,"Anti-Lag","Compensate or match server lag for shot timing","AntiLag")
dropdown(adv,"Anti-Lag Mode","Compensate = lead by ping | Match = aim at past position","AntiLagMode",{"Compensate","Match"})
slider(adv,"Anti-Lag Offset","Manual fine-tune offset","AntiLagOffset",-50,50,1)
-- Flick assist
toggle(adv,"Flick Assist","Single fast flick toward targets outside FOV","FlickAssist")
slider(adv,"Flick Strength","How far the flick snaps","FlickAssistStrength",0.1,1.0,0.05)
-- Multi-target suppressor
toggle(adv,"Multi-Target Suppressor","When 3+ enemies in FOV area weight system prioritizes best","MultiTargetSuppressor")
slider(adv,"Multi-Target Radius","FOV multiplier to count nearby enemies","MultiTargetRadius",1,6,0.5)
end)()
-- =====================
-- VISUALS PAGE
-- =====================
;(function()
local e,_ = card(visuals,"ESP","*")
toggle(e,"Master ESP","Enable all enemy visuals","ESP")
toggle(e,"Box ESP","Draw boxes","BoxESP")
dropdown(e,"Box Style","Visual box type","BoxStyle",{"Full","Corner"})
toggle(e,"Name ESP","Show player names","NameESP")
toggle(e,"Health ESP","Show health bars","HealthESP")
toggle(e,"Distance ESP","Show distance text","DistanceESP")
dropdown(e,"ESP Stack","Name/health/distance layout","ESPStackMode",{"Clean","Compact","Minimal"})
toggle(e,"Optional Names","Allow name text in ESP stack","ESPNameOptional")
toggle(e,"Tracers","Lines to enemies","TracerESP")
toggle(e,"Skeleton ESP","Show bone/dot skeleton","SkeletonESP")
dropdown(e,"Skeleton Mode","Bone = joint lines | Dots = old circles | Both = all","SkeletonMode",{"Bone","Dots","Both"})
toggle(e,"Skeleton Distance Fade","Fade skeleton at long range","SkeletonDistanceFade")
toggle(e,"Chams","Highlight enemy models","Chams")
toggle(e,"Offscreen Arrows","Show arrows for offscreen enemies","OffscreenArrows")
slider(e,"Arrow Size","Threat pointer size","ArrowSize",10,24,1)
slider(e,"Arrow Padding","Distance from screen edge","ArrowPadding",24,90,2)
toggle(e,"Arrow Smart Stack","Separate overlapping arrows","ArrowSmartStack")
dropdown(e,"Arrow Labels","Label style","ArrowLabelMode",{"Distance","Threat","Off"})
toggle(e,"Vertical Hints","Show UP/DOWN on arrows","ArrowVerticalHints")
slider(e,"Vertical Threshold","Height needed for UP/DOWN","ArrowVerticalThreshold",5,80,1)
toggle(e,"Threat Pulse","Pulse arrows for visible threats","ArrowThreatPulse")
visualPreview(e)
-- ESP ADVANCED CARD
local ea,_ = card(visuals,"ESP Advanced","*")
toggle(ea,"Weapon Silhouette","Draw held tool icon on enemy ESP","WeaponSilhouette")
toggle(ea,"Nameplate Distance Scale","Shrink name text smoothly with distance","NameplateDistanceScale")
slider(ea,"Nameplate Max Size","Closest nameplate font size","NameplateMaxSize",10,24,1)
slider(ea,"Nameplate Min Size","Farthest nameplate font size","NameplateMinSize",6,16,1)
slider(ea,"Nameplate Scale Range","Distance at which text reaches minimum size","NameplateScaleRange",100,2000,50)
toggle(ea,"LoS Map Lines","Draw facing lines on minimap per enemy","LOSMapLines")
slider(ea,"LoS Line Length","How far the LoS line extends on map (studs)","LOSLineLength",5,60,1)
toggle(ea,"LoS Prediction Cone","Green velocity cone on minimap per enemy","LOSPredictionCone")
slider(ea,"Cone Length","How far the prediction cone extends (studs)","LOSConeLength",8,80,2)
slider(ea,"Cone Angle","Width of the prediction cone (degrees)","LOSConeAngle",5,60,1)
local w,_ = card(visuals,"World / Info","*")
w:SetAttribute("FavCategory","HUD")
toggle(w,"FOV Circles","Show aim/silent FOV","FOVVisible")
slider(w,"FOV Thickness","Circle line thickness","FOVThickness",1,5,1)
slider(w,"FOV Alpha","Circle transparency","FOVTransparency",0.1,1,0.05)
toggle(w,"Top Indicators","Small HUD in top right","TopIndicators")
toggle(w,"Target Info","Show health/studs on aimed target","TargetInfo")
toggle(w,"Opponent State Debug","Show replicated opponent weapon state","OpponentStateDebug")
toggle(w,"Opponent State Details","Show tool/ammo values","OpponentStateDetails")
toggle(w,"Opponent State Source","Show source path","OpponentStateSource")
toggle(w,"Opponent Movement Debug","Show movement relation state","OpponentPushDebug")
toggle(w,"Surround Map","Compass-style nearby player counts","SurroundMapHUD")
toggle(w,"Blind Spot Monitor","Warn when close players enter rear/sides","BlindSpotMonitor")
slider(w,"Surround Radius","Distance for surround counts","SurroundRadius",40,300,10)
slider(w,"Blind Spot Radius","Distance for blind spot warning","BlindSpotRadius",25,180,5)
toggle(w,"Movement Details","Show speed/closing values","OpponentPushDetails")
slider(w,"Push Speed Threshold","Speed needed for push/backoff labels","PushSpeedThreshold",2,30,1)
toggle(w,"Rainbow FOV","Animated FOV colors","FOVRainbow")
toggle(w,"Reload Predictor","Show reload guess near crosshair","ReloadPredictor")
toggle(w,"Reload State HUD","Show equipped weapon reload/ammo state","ReloadStateHUD")
toggle(w,"Reload Details","Show reserve ammo if available","ReloadStateDetails")
toggle(w,"Low Ammo Warning","Warn when local ammo is low","ReloadWarnLowAmmo")
slider(w,"Distance Limit","Max ESP target distance","DistanceLimit",100,5000,50)
toggle(w,"Team Check","Ignore teammates","TeamCheck")
toggle(w,"Wall Check","Visibility checks","WallCheck")
hudPreview(w)
local mm,_ = card(visuals,"Mini Map","*")
toggle(mm,"Mini Map","Enable minimap overlay","MiniMap")
slider(mm,"Map Size","Minimap pixel size","MiniMapSize",80,300,10)
slider(mm,"Map Opacity","Background transparency","MiniMapOpacity",0.1,0.9,0.05)
slider(mm,"Zoom","Studs per half-map","MiniMapZoom",0.5,8,0.5)
toggle(mm,"Team Dots","Show teammates","MiniMapTeam")
toggle(mm,"Labels","Show names on dots","MiniMapLabels")
toggle(mm,"Movement Trail","Show your recent path","MiniMapTrail")
toggle(mm,"Waypoints","Show placed waypoints","MiniMapWaypoints")
toggle(mm,"Grid Overlay","Distance rings on map background","MiniMapGrid")
slider(mm,"Grid Spacing","Stud interval between rings","MiniMapGridSpacing",5,100,5)
button(mm,"Add Waypoint","Place waypoint at current position",function()
table.insert(MiniMapWaypoints,getRoot(lp) and getRoot(lp).Position or Vector3.zero)
if #MiniMapWaypoints>8 then table.remove(MiniMapWaypoints,1) end
showApplyPopup("Waypoint added","WP"..#MiniMapWaypoints.." placed.","success")
end)
button(mm,"Clear Waypoints","Remove all waypoints",function()
MiniMapWaypoints={}
for k,d in safePairs(MiniMapDots) do if tostring(k):find("wp_",1,true) then d:Destroy(); MiniMapDots[k]=nil end end
showApplyPopup("Waypoints cleared","","success")
end)
minimapPreview(mm)
end)()
-- =====================
-- CROSSHAIR PAGE
-- =====================
;(function()
local c,_ = card(cross,"Crosshair Designer","+")
toggle(c,"Enable Crosshair","Custom drawing crosshair","Crosshair")
slider(c,"Gap","Center gap","CrosshairGap",0,60,1)
slider(c,"Length","Line length","CrosshairLength",2,80,1)
slider(c,"Thickness","Line thickness","CrosshairThickness",1,10,1)
toggle(c,"Dot","Center dot","CrosshairDot")
toggle(c,"Spin","Animated spin","CrosshairSpin")
toggle(c,"Shot Pulse","Visual kick when you click","CrosshairShootPulse")
toggle(c,"Auto Size","Scale with screen size","CrosshairAutoSize")
dropdown(c,"Profile","Crosshair shape preset","CrosshairProfile",{"Classic","Dot","T-Shape","Minimal","Circle","Box","Diamond","X","Sniper","Cyber"})
crosshairPreview(c)
button(c,"Save Crosshair","Save crosshair settings now",function() local ok=ghostSaveConfigFile(false); showApplyPopup(ok and "Saved" or "Failed",ghostLastSaveStatus,ok and "success" or "error") end)
button(c,"Ghost Accent","Set crosshair ghost blue",function() Config.CrosshairColor=Color3.fromRGB(210,240,255); ghostSaveConfigFile(true) end)
button(c,"Green Accent","Set crosshair green",function() Config.CrosshairColor=Color3.fromRGB(90,255,150); ghostSaveConfigFile(true) end)
button(c,"White Accent","Set crosshair white",function() Config.CrosshairColor=Color3.fromRGB(255,255,255); ghostSaveConfigFile(true) end)
end)()
-- =====================
-- CONFIG PAGE
-- =====================
;(function()
local cf,_ = card(configP,"Profiles","#")
button(cf,"Save Settings File","Write current Config to GhostMenu/settings.json",function()
local ok=ghostSaveConfigFile(false); showApplyPopup(ok and "Settings saved" or "Save failed",ghostLastSaveStatus,ok and "success" or "error")
end)
button(cf,"Load Settings File","Load GhostMenu/settings.json",function()
local ok=ghostLoadConfigFile(false)
if ok then for _,fn in safePairs(controls) do pcall(fn) end end
showApplyPopup(ok and "Settings loaded" or "Load failed",ghostLastSaveStatus,ok and "success" or "error")
end)
toggle(cf,"Auto Save","Auto-save changes","AutoSaveSettings")
toggle(cf,"Auto Load","Load settings on script start","AutoLoadSettings")
button(cf,"Save Status","Print current save status",function() showApplyPopup("Save status",ghostLastSaveStatus,"success") end)
button(cf,"Export Config","Copy JSON to clipboard",function()
local json=HttpService:JSONEncode(ghostConfigToSaveTable())
if setclipboard then setclipboard(json) end
showApplyPopup("Config exported","JSON copied to clipboard.","success")
end)
button(cf,"Import Config","Paste JSON from clipboard",function()
if not getclipboard then return end
local txt=getclipboard()
local ok,data=pcall(function() return HttpService:JSONDecode(txt) end)
if ok and type(data)=="table" then
ghostApplySaveTable(data); for _,fn in safePairs(controls) do pcall(fn) end
ghostScheduleAutoSave(); showApplyPopup("Config imported","Applied successfully.","success")
end
end)
button(cf,"Legit Preset","Low-key settings",function()
Config.Aimbot=true; Config.AimSmooth=0.35; Config.AimFOV=30; Config.SilentAim=false; Config.TriggerBot=false; Config.ESP=true; Config.BoxESP=true; Config.TracerESP=false
Config.SkeletonMode="Bone"; Config.WeaponSilhouette=false; Config.AntiAimDetect=true
for _,fn in safePairs(controls) do pcall(fn) end; ghostScheduleAutoSave()
end)
button(cf,"Rage Preset","Strong settings",function()
Config.Aimbot=true; Config.AimSmooth=0.05; Config.AimFOV=260; Config.SilentAim=true; Config.SilentFOV=240
Config.TriggerBot=true; Config.ESP=true; Config.TracerESP=true; Config.Chams=true
Config.TargetWeightSystem=true; Config.AntiAimDetect=true; Config.AntiLag=true; Config.AntiLagMode="Compensate"
for _,fn in safePairs(controls) do pcall(fn) end; ghostScheduleAutoSave()
end)
button(cf,"Panic Hide","Toggle hidden state",function()
Config.Hidden=not Config.Hidden; mouseDown=false; pcall(mouse1release); Root.Visible=not Config.Hidden
end)
end)()
-- =====================
-- SETTINGS PAGE
-- =====================
;(function()
local st,_ = card(settings,"General","*")
st:SetAttribute("FavCategory","Settings")
keybind(st,"Panic Key","Toggle hidden state","PanicKey")
toggle(st,"Glass Look","Transparent glass panels","Glass")
toggle(st,"Screen Auto Scale","Auto size menu for resolution","ScreenAutoScale")
slider(st,"Scale Min","Smallest auto UI scale","ScreenScaleMin",0.5,1,0.01)
slider(st,"Scale Max","Largest auto UI scale","ScreenScaleMax",0.8,1.5,0.01)
toggle(st,"Show Previews","Live editor preview panels","ShowPreviews")
toggle(st,"Apply Popups","Show preset change summaries","ApplyPopups")
toggle(st,"Dock Mode","Show mini dock when menu is hidden","DockMode")
toggle(st,"Search Spotlight","Dim non-matching settings while searching","SearchSpotlight")
toggle(st,"Hover Help","Explain settings when hovered","HoverHelp")
toggle(st,"Auto-Hide Dock","Fade dock when idle","DockAutoHide")
slider(st,"Dock Hide Delay","Seconds before fade","DockAutoHideDelay",1,10,0.5)
slider(st,"Dock Wake Range","Mouse distance to reveal dock","DockWakeDistance",30,220,10)
button(st,"Notifications","Open notification history",toggleNotificationDrawer)
dropdown(st,"Theme Preset","Ghost color theme","ThemePreset",{"Bright Phantom","Neon Wraith","Deep Violet","Void Glow","Glass Noir","High Contrast"})
toggle(st,"Ghost Background","Ghost watermark/image in menu","GhostBackground")
slider(st,"Ghost BG Alpha","Background ghost opacity","GhostBackgroundOpacity",0,0.75,0.01)
button(st,"Apply Theme","Refresh theme colors",function() applyGhostTheme(Config.ThemePreset); applyGlassLook(); updateGhostBackground(); ghostSaveConfigFile(true) end)
button(st,"Unload","Remove menu and drawings",function() if _G.GhostUnload then _G.GhostUnload() end end)
local clean,_ = card(settings,"Cleanup / Safety","*")
clean:SetAttribute("FavCategory","Settings")
button(clean,"Hide All Visuals","Temporarily hide menu and drawings",function()
Config.Hidden=true; menuVisible=false; mouseDown=false; pcall(mouse1release); Root.Visible=false
for _,obj in safePairs(ESPObjects) do hideAll(obj) end
if FOVCircle then FOVCircle.Visible=false end; if SACircle then SACircle.Visible=false end
if TriggerCircle then TriggerCircle.Visible=false end; if TargetLock then TargetLock.Visible=false end
if ReloadLbl then ReloadLbl.Visible=false end; if CHDot then CHDot.Visible=false end
for _,l in safePairs(CHLines) do l.Visible=false end
for _,l in ipairs(LOSLines) do l.Visible=false end; for _,c in ipairs(LOSCones) do c.Visible=false end
end)
button(clean,"Reset Drawings","Hide stuck ESP/arrows",function()
for _,obj in safePairs(ESPObjects) do hideAll(obj); obj.ArrowSmooth=nil end
if FOVCircle then FOVCircle.Visible=false end; if SACircle then SACircle.Visible=false end
if TriggerCircle then TriggerCircle.Visible=false end; if TargetLock then TargetLock.Visible=false end
if ReloadLbl then ReloadLbl.Visible=false end; if CHDot then CHDot.Visible=false end
for _,l in safePairs(CHLines) do if l then l.Visible=false end end
if topInfoText then topInfoText.Visible=false end; if targetInfoText then targetInfoText.Visible=false end
for _,l in ipairs(LOSLines) do l.Visible=false end; for _,c in ipairs(LOSCones) do c.Visible=false end
end)
button(clean,"Clear Chams","Remove GhostCham highlights",function()
for _,p in safeIpairs(Players:GetPlayers()) do
local ch=getChar(p); local h=ch and ch:FindFirstChild("GhostCham")
if h then pcall(function() h:Destroy() end) end
end
end)
button(clean,"Reset UI Position","Center the menu",function()
Root.Size=UDim2.new(0,880,0,520); Root.Position=UDim2.new(0.5,0,0.5,0)
menuVisible=true; Config.Hidden=false; Root.Visible=true
end)
button(clean,"Clear Runtime State","Clear target/resolver cache",function()
lastTarget=nil; resolverData={}; trackedHumanoids={}; arrowBuckets={}; rigCache={}; antiAimData={}
end)
button(clean,"Clear Rig Cache","Force re-resolve all characters",function()
rigCache={}; showApplyPopup("Rig cache cleared","Will re-resolve on next frame.","success")
end)
local teamDbg,_ = card(settings,"Team Debug","*")
teamDbg:SetAttribute("FavCategory","Settings")
local teamRow=row(teamDbg,"Team Detection","Friendly filter diagnostics")
local teamText=Instance.new("TextLabel",teamRow)
teamText.BackgroundTransparency=1; teamText.Position=UDim2.new(0,36,0,22); teamText.Size=UDim2.new(1,-48,0,18)
teamText.Font=Enum.Font.Gotham; teamText.TextSize=11; teamText.TextColor3=Color3.fromRGB(150,150,165)
teamText.TextXAlignment=Enum.TextXAlignment.Left; teamText.ZIndex=8
RunService.RenderStepped:Connect(function()
if ghostUnloaded then return end
if teamText and teamText.Parent then teamText.Text=teamDebugSummary() end
end)
-- Rig debug card
local rigDbg,_ = card(settings,"Resolver Debug","*")
rigDbg:SetAttribute("FavCategory","Settings")
local rigRow=row(rigDbg,"Rig Info","Universal rig resolver status")
local rigText=Instance.new("TextLabel",rigRow)
rigText.BackgroundTransparency=1; rigText.Position=UDim2.new(0,36,0,22); rigText.Size=UDim2.new(1,-48,0,18)
rigText.Font=Enum.Font.Gotham; rigText.TextSize=11; rigText.TextColor3=Color3.fromRGB(150,150,165)
rigText.TextXAlignment=Enum.TextXAlignment.Left; rigText.ZIndex=8
RunService.RenderStepped:Connect(function()
if ghostUnloaded then return end
if rigText and rigText.Parent then
local count=0; for _ in safePairs(rigCache) do count=count+1 end
rigText.Text="Cached rigs: "..count.." | Tick: "..math.floor(tickRateSmooth).."hz | AA: "..
(function() local n=0; for _ in safePairs(antiAimData) do n=n+1 end; return n end)().." tracked"
end
end)
button(rigDbg,"Print Rig Info","Print resolver data for all enemies",function()
for _,p in safeIpairs(Players:GetPlayers()) do
if validEnemy(p) then
local ch=getChar(p); local rig=ch and resolveRig(ch)
if rig then
print("[Ghost Resolver] "..p.Name.." | parts: "..#rig.parts.." | bones: "..#rig.bones.." | root: "..(rig.root and rig.root.Name or "nil").." | head: "..(rig.head and rig.head.Name or "nil").." | torso: "..(rig.torso and rig.torso.Name or "nil"))
end
end
end
end)
local info,_ = card(settings,"Status","*")
local status=row(info,"Runtime","Live stats")
local statText=Instance.new("TextLabel",status)
statText.BackgroundTransparency=1; statText.Position=UDim2.new(0,12,0,22); statText.Size=UDim2.new(1,-24,0,18)
statText.Font=Enum.Font.Gotham; statText.TextSize=11; statText.TextColor3=Color3.fromRGB(150,150,165)
statText.TextXAlignment=Enum.TextXAlignment.Left; statText.ZIndex=8
RunService.RenderStepped:Connect(function()
if ghostUnloaded then return end
if statText and statText.Parent then
statText.Text="Ping: "..getPing().."ms | Players: "..#Players:GetPlayers().." | Target: "..(lastTarget and lastTarget.Name or "none")
end
end)
end)()
-- =====================
-- THEME STUDIO PAGE
-- =====================
;(function()
local s,_ = card(themeStudio,"Theme Studio","*")
dropdown(s,"Theme Preset","Choose base palette","ThemePreset",{"Bright Phantom","Neon Wraith","Deep Violet","Void Glow","Glass Noir","High Contrast"})
dropdown(s,"Background Mode","Animated menu background","BackgroundMode",{"Ghost Drift","Ghost Fog","Spirit Pulse","Static Glass"})
toggle(s,"Idle Glow","Breathing border glow","IdleGlow")
toggle(s,"Ghost Parallax","Background follows mouse slightly","GhostParallax")
slider(s,"Parallax Strength","Mouse depth amount","GhostParallaxStrength",0,0.08,0.005)
dropdown(s,"Tab Transition","Page switch animation","TabTransition",{"Fade","Slide","Zoom","Instant","Glitch"})
toggle(s,"Profile Card","Show sidebar identity card","ProfileCard")
button(s,"Apply Theme Studio","Apply selected theme/background",function()
applyGhostTheme(Config.ThemePreset); applyGlassLook(); updateGhostBackground(); ghostSaveConfigFile(true)
showApplyPopup("Theme updated",Config.ThemePreset.." + "..Config.BackgroundMode,"success")
end)
end)()
-- =====================
-- SCANNER PAGE
-- =====================
;(function()
local guideCard,_ = card(scanner,"How To Use Scanner","i")
button(guideCard,"Scanner Guide","Show scanner workflow",showScannerGuide)
button(guideCard,"Copy Scanner Report","Copy report",function()
if setclipboard then setclipboard(scannerLastText or ""); showApplyPopup("Copied","Scanner report copied.","success") end
end)
local s,_ = card(scanner,"Passive Game Scanner","i")
toggle(s,"Passive Only","Scanner never fires remotes","ScannerPassiveOnly")
toggle(s,"Show Full Paths","Show object full paths","ScannerShowPaths")
slider(s,"Max Results","Limit rows per section","ScannerMaxResults",20,200,10)
toggle(s,"Aggressive Depth","Enable deeper passive audit","AggressiveScanDepth")
toggle(s,"Risk Scoring","Score exposed surfaces","AggressiveRiskScoring")
slider(s,"Watch Interval","Seconds between watch checks","ScannerWatchInterval",1,10,0.5)
button(s,"Scan Game","Map remotes/tools/modules/scripts",runPassiveScan)
button(s,"Aggressive Defense Scan","Deep passive audit/risk scoring",runAggressiveDefenseScan)
button(s,"Environment Check","Check executor/API capabilities",runEnvCheck)
button(s,"Script Indexer","Find interesting scripts/modules",runScriptIndexer)
button(s,"Copy Scanner Output","Copy current report",copyScannerOutput)
local d,_ = card(scanner,"Snapshot Diff","#")
button(d,"Take Snapshot A","Save current object map",function() takeScannerSnapshot("A") end)
button(d,"Take Snapshot B","Save later object map",function() takeScannerSnapshot("B") end)
button(d,"Compare A/B","Show added and removed objects",diffScannerSnapshots)
button(d,"Toggle Object Watch","Live passive object change monitor",toggleScannerWatch)
local o,_ = card(scanner,"Scanner Output","*")
scannerSummary=Instance.new("TextLabel",o)
scannerSummary.BackgroundTransparency=1; scannerSummary.Size=UDim2.new(1,0,0,22)
scannerSummary.Font=Enum.Font.GothamBold; scannerSummary.TextSize=12; scannerSummary.TextColor3=GhostTextMain
scannerSummary.TextXAlignment=Enum.TextXAlignment.Left; scannerSummary.Text="Ready"; scannerSummary.ZIndex=58
scannerOutput=Instance.new("TextLabel",o)
scannerOutput.BackgroundColor3=Color3.fromRGB(8,5,18); scannerOutput.BackgroundTransparency=0.14
scannerOutput.BorderSizePixel=0; scannerOutput.Position=UDim2.new(0,0,0,30); scannerOutput.Size=UDim2.new(1,0,0,360)
scannerOutput.Font=Enum.Font.Code; scannerOutput.TextSize=11; scannerOutput.TextColor3=Color3.fromRGB(220,215,240)
scannerOutput.TextXAlignment=Enum.TextXAlignment.Left; scannerOutput.TextYAlignment=Enum.TextYAlignment.Top
scannerOutput.TextWrapped=false; scannerOutput.Text=scannerLastText; scannerOutput.ZIndex=58
Instance.new("UICorner",scannerOutput).CornerRadius=UDim.new(0,12)
end)()
-- =====================
-- NOTES PAGE
-- =====================
;(function()
local n,_ = card(notes,"Ghost Notes v5.3","#")
function noteLine(parent,title,body)
local r=row(parent,title,body); r.Size=UDim2.new(1,0,0,58); return r
end
noteLine(n,"v5.3","Universal rig resolver, bone skeleton, weapon silhouette, LoS minimap, combat advanced card.")
noteLine(n,"Universal Resolver","Works on any game rig — R6, R15, custom blocky, Frontlines, Deadline, etc. No hardcoded part names.")
noteLine(n,"Skeleton Modes","Bone = joint-to-joint lines. Dots = old circle system. Both = render all. Toggle in Visuals > ESP.")
noteLine(n,"Weapon Silhouette","Draws a small gun icon near players holding a Tool. Toggleable in ESP Advanced.")
noteLine(n,"Nameplate Scaling","Name text shrinks with distance. Min/max size and range are sliders in ESP Advanced.")
noteLine(n,"LoS Map","Minimap shows each enemy's facing direction and a green velocity prediction cone.")
noteLine(n,"Minimap Grid","Distance rings every N studs drawn on the map background. Toggle + spacing in Visuals > Mini Map.")
noteLine(n,"Target Weight System","Scores targets: shootable first, then distance, then low health. Toggleable per criterion.")
noteLine(n,"Anti-Aim Detector","Detects spinbot and flipbot. Draws AA: SPIN/FLIP above enemy and global screen warning.")
noteLine(n,"Anti-Lag","Compensate = lead by ping. Match = aim at past position. Fine-tune with offset slider.")
noteLine(n,"Ping Normalizer","Offsets shot timing by your ping for consistent server-side hit registration.")
noteLine(n,"Tick Rate Compensator","Detects server tick rate over 60 frames and scales prediction step to match.")
noteLine(n,"Flick Assist","Off by default. Single fast flick toward targets just outside FOV, hands back to smooth assist.")
noteLine(n,"Aim Shake Dampener","Averages recent camera frames to filter out game-induced shake before aim runs.")
noteLine(n,"Multi-Target Suppressor","When 3+ enemies in FOV zone, weight system handles prioritization automatically.")
noteLine(n,"Resolver Debug","Settings > Resolver Debug shows cached rig count, tick rate, and AA tracking count.")
end)()
-- =====================
-- SHOW TAB
-- =====================
function showTab(name)
if not pages[name] then return end
currentTab=name; Title.Text=name; clearContent(); pages[name].Visible=true
pages[name].Position=UDim2.new(0,14,0,0)
pcall(function() tween(pages[name],0.18,{Position=UDim2.new(0,0,0,0)},Enum.EasingStyle.Quint) end)
for n,btn in safePairs(tabs) do
local active=n==name
tween(btn,0.18,{BackgroundColor3=active and Color3.fromRGB(42,16,70) or Color3.fromRGB(4,4,8),TextColor3=active and Color3.fromRGB(245,245,250) or Color3.fromRGB(165,165,178)},Enum.EasingStyle.Quint)
end
if not sidebarExpanded then setSidebarExpanded(false,true) end
end
if rebuildFavorites then rebuildFavorites() end
_G.GhostShowTab=function(name) showTab(name) end
createDock()
showTab("Favorited")
-- =====================
-- DRAGGING
-- =====================
Topbar.InputBegan:Connect(function(i)
if i.UserInputType==Enum.UserInputType.MouseButton1 then
dragging=true; local start=i.Position; local startPos=Root.Position
local conn; conn=UIS.InputChanged:Connect(function(ch)
if dragging and ch.UserInputType==Enum.UserInputType.MouseMovement then
local delta=ch.Position-start
Root.Position=UDim2.new(startPos.X.Scale,startPos.X.Offset+delta.X,startPos.Y.Scale,startPos.Y.Offset+delta.Y)
saveLayoutState()
end
end)
i.Changed:Connect(function() if i.UserInputState==Enum.UserInputState.End then dragging=false; if conn then conn:Disconnect() end end end)
end
end)
-- =====================
-- SEARCH FILTER
-- =====================
function applySearch()
local q=(SearchBox.Text or ""):lower(); local searching=q~=""
local cardHits={}
for _,rec in safeIpairs(rowRegistry) do
local rowHit=(not searching) or rec.text:find(q,1,true)~=nil
rec.row.Visible=rowHit
if rowHit then cardHits[rec.parent]=true end
end
if SearchDim then
SearchDim.Visible=searching and Config.SearchSpotlight
SearchDim.BackgroundTransparency=(searching and Config.SearchSpotlight) and 0.42 or 1
end
for _,rec in safeIpairs(cardRegistry) do
local titleHit=(rec.title or ""):lower():find(q,1,true)~=nil
local hit=(not searching) or titleHit or cardHits[rec.body]
rec.card.Visible=hit
if searching and hit then rec.body.Visible=true; rec.collapsed=false
elseif not searching then rec.collapsed=collapsedCards[rec.title] or false end
if rec.resize then rec.resize() end
end
end
SearchBox:GetPropertyChangedSignal("Text"):Connect(applySearch)
applySearch()
-- =====================
-- UI BUTTONS
-- =====================
Min.MouseButton1Click:Connect(function()
local small=Root.Size.Y.Offset>80
if small then tween(Root,0.25,{Size=UDim2.new(0,880,0,68)}) else tween(Root,0.25,{Size=UDim2.new(0,880,0,520)}) end
task.delay(0.3,saveLayoutState)
end)
Close.MouseButton1Click:Connect(function()
menuVisible=false; Root.Visible=false; setDockVisible(true)
end)
FullClose.MouseButton1Click:Connect(function()
if _G.GhostUnload then _G.GhostUnload() end
end)
-- =====================
-- AIM HELPERS
-- =====================
function aimKeyDown()
if Config.AimKey=="MouseButton2" then return UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton2) end
if Config.AimKey=="MouseButton1" then return UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) end
local ok,key=pcall(function() return Enum.KeyCode[Config.AimKey] end)
return ok and UIS:IsKeyDown(key)
end
function moveMouseTo(screenPos,smooth)
local mouse=UIS:GetMouseLocation()
local delta=screenPos-mouse
if delta.Magnitude<Config.AimDeadzone then return end
if Config.AimHumanize then delta=delta+Vector2.new(math.random(-2,2),math.random(-2,2)) end
if mousemoverel then mousemoverel(delta.X*(1-smooth),delta.Y*(1-smooth))
else
local cf=getDampenedCameraLook()
local ray=camera:ViewportPointToRay(screenPos.X,screenPos.Y)
camera.CFrame=cf:Lerp(CFrame.new(cf.Position,cf.Position+ray.Direction),1-smooth)
end
end
-- =====================
-- TRIGGER BOT
-- =====================
function triggerRayTarget()
local origin=camera.CFrame.Position
local dir=camera.CFrame.LookVector*Config.DistanceLimit
local params=RaycastParams.new()
params.FilterType=Enum.RaycastFilterType.Blacklist
params.FilterDescendantsInstances={lp.Character}
params.IgnoreWater=true
local hit=Workspace:Raycast(origin,dir,params)
if not hit then return nil,nil,nil end
local model=hit.Instance and hit.Instance:FindFirstAncestorOfClass("Model")
local plr=model and Players:GetPlayerFromCharacter(model)
if plr and validEnemy(plr) then
local hum=getHum(plr)
if hum and hum.Health>0 then return plr,hit.Instance,hit.Position end
end
return nil,nil,nil
end
function triggerCheck()
if not Config.TriggerBot or menuBlocksInput() then
if triggerHolding then triggerHolding=false; pcall(mouse1release) end; return
end
local target,part=triggerRayTarget()
if target and part then
lastTarget=target
if now()-lastShot>=Config.TriggerDelay then
if Config.TriggerHold then
if not triggerHolding then triggerHolding=true; pcall(mouse1press) end
else lastShot=now(); pcall(mouse1click) end
end
else
if triggerHolding then triggerHolding=false; lastShot=now(); pcall(mouse1release) end
end
end
-- =====================
-- AUTO PISTOL
-- =====================
mouseDown=false
UIS.InputBegan:Connect(function(i,gp) if not ghostUnloaded and not menuBlocksInput() and i.UserInputType==Enum.UserInputType.MouseButton1 then mouseDown=true end end)
UIS.InputEnded:Connect(function(i,gp) if i.UserInputType==Enum.UserInputType.MouseButton1 then mouseDown=false; if not triggerHolding then pcall(mouse1release) end end end)
local lastCamCF=camera.CFrame
-- =====================
-- RELOAD / WEAPON STATE HUD
-- =====================
function getEquippedTool()
local ch=getChar(lp); if not ch then return nil end
for _,obj in safeIpairs(ch:GetChildren()) do if obj:IsA("Tool") then return obj end end
return nil
end
function findToolValue(tool,names)
if not tool then return nil,nil end
for _,name in safeIpairs(names) do
local direct=tool:FindFirstChild(name)
if direct and direct:IsA("ValueBase") then return direct,direct.Value end
end
for _,obj in safeIpairs(tool:GetDescendants()) do
if obj:IsA("ValueBase") then
local n=obj.Name:lower()
for _,name in safeIpairs(names) do
if n==name:lower() or n:find(name:lower(),1,true) then return obj,obj.Value end
end
end
end
return nil,nil
end
function readLocalReloadState()
local tool=getEquippedTool()
if not tool then return {tool="None",state="NO TOOL",ammo=nil,reserve=nil,reloading=false,low=false} end
local _,ammo=findToolValue(tool,{"Ammo","Clip","Magazine","Mag","CurrentAmmo","Bullets","Rounds"})
local _,reserve=findToolValue(tool,{"Reserve","ReserveAmmo","StoredAmmo","TotalAmmo","AmmoReserve","ExtraAmmo"})
local _,reloading=findToolValue(tool,{"Reloading","IsReloading","Reload","ReloadState"})
local _,cooldown=findToolValue(tool,{"Cooldown","FireCooldown","Busy","Shooting","CanShoot","CanFire"})
local reloadBool=false
if typeof(reloading)=="boolean" then reloadBool=reloading elseif typeof(reloading)=="number" then reloadBool=reloading>0 end
local ammoNum=tonumber(ammo); local low=ammoNum~=nil and ammoNum<=3
local state="READY"
if reloadBool then state="RELOADING" elseif low and Config.ReloadWarnLowAmmo then state="LOW AMMO"
elseif typeof(cooldown)=="boolean" and cooldown==false then state="COOLDOWN" end
return {tool=tool.Name,state=state,ammo=ammo,reserve=reserve,reloading=reloadBool,low=low}
end
function getEquippedToolFor(p)
local ch=getChar(p); if not ch then return nil end
for _,obj in safeIpairs(ch:GetChildren()) do if obj:IsA("Tool") then return obj end end
return nil
end
function readPlayerReplicatedWeaponState(p)
local tool=getEquippedToolFor(p)
if not tool then return {tool="None",state="UNKNOWN",ammo=nil,reserve=nil,reloading=nil,source="no equipped Tool"} end
local ammoObj,ammo=findToolValue(tool,{"Ammo","Clip","Magazine","Mag","CurrentAmmo","Bullets","Rounds"})
local reserveObj,reserve=findToolValue(tool,{"Reserve","ReserveAmmo","StoredAmmo","TotalAmmo","AmmoReserve","ExtraAmmo"})
local reloadObj,reloading=findToolValue(tool,{"Reloading","IsReloading","Reload","ReloadState"})
local cooldownObj,cooldown=findToolValue(tool,{"Cooldown","FireCooldown","Busy","Shooting","CanShoot","CanFire"})
local reloadBool=nil
if typeof(reloading)=="boolean" then reloadBool=reloading elseif typeof(reloading)=="number" then reloadBool=reloading>0 end
local ammoNum=tonumber(ammo); local low=ammoNum~=nil and ammoNum<=3
local state="UNKNOWN"
if reloadBool==true then state="RELOADING" elseif reloadBool==false or ammo~=nil or cooldown~=nil then state="READY" end
if state~="RELOADING" and low then state="LOW AMMO" end
local src="replicated values"
if reloadObj then src=pathOf(reloadObj) elseif ammoObj then src=pathOf(ammoObj) end
return {tool=tool.Name,state=state,ammo=ammo,reserve=reserve,reloading=reloadBool,source=src,low=low}
end
function formatOpponentState(p)
if not Config.OpponentStateDebug or not p then return "" end
local s=readPlayerReplicatedWeaponState(p)
local text=" | "..s.state
if Config.OpponentStateDetails then
text=text.." | "..s.tool
if s.ammo~=nil then text=text.." "..tostring(s.ammo) end
if s.reserve~=nil then text=text.."/"..tostring(s.reserve) end
end
if Config.OpponentStateSource then text=text.."\nsrc: "..tostring(s.source) end
return text
end
function readOpponentMovementState(p)
local myRoot=getRoot(lp); local root=getRoot(p)
if not myRoot or not root then return {state="UNKNOWN",speed=0,closing=0} end
local vel=root.AssemblyLinearVelocity or Vector3.zero
local flatVel=Vector3.new(vel.X,0,vel.Z); local speed=flatVel.Magnitude
local toMe=Vector3.new(myRoot.Position.X-root.Position.X,0,myRoot.Position.Z-root.Position.Z)
local closing=0
if toMe.Magnitude>1 and speed>0.5 then closing=flatVel:Dot(toMe.Unit) end
local state="HOLDING"; local threshold=Config.PushSpeedThreshold or 8
if speed<2 then state="STILL"
elseif closing>threshold then state="PUSHING"
elseif closing<-threshold then state="BACKING OFF"
else
local right=camera and camera.CFrame.RightVector or Vector3.new(1,0,0)
local side=flatVel:Dot(Vector3.new(right.X,0,right.Z))
if math.abs(side)>threshold then state=(side>0) and "CROSSING RIGHT" or "CROSSING LEFT" else state="MOVING" end
end
local hum=getHum(p)
if hum then
local hs=hum:GetState()
if hs==Enum.HumanoidStateType.Jumping then state="JUMPING" elseif hs==Enum.HumanoidStateType.Freefall then state="FALLING" end
end
return {state=state,speed=speed,closing=closing}
end
function formatOpponentMovement(p)
if not Config.OpponentPushDebug or not p then return "" end
local m=readOpponentMovementState(p)
if Config.OpponentPushDetails then return " | move: "..m.state.." | spd "..tostring(math.floor(m.speed)).." | close "..tostring(math.floor(m.closing)) end
return " | move: "..m.state
end
function updateReloadStateHUD()
if not Config.ReloadStateHUD or not Config.ReloadPredictor or menuBlocksInput() or not ReloadLbl then return end
local s=readLocalReloadState()
if s.tool=="None" then ReloadLbl.Visible=false; return end
local ammoText=""
if s.ammo~=nil then ammoText=" | "..tostring(s.ammo) end
if Config.ReloadStateDetails and s.reserve~=nil then ammoText=ammoText.."/"..tostring(s.reserve) end
ReloadLbl.Text=s.state.." - "..s.tool..ammoText
if s.state=="RELOADING" then ReloadLbl.Color=Color3.fromRGB(255,190,70)
elseif s.state=="LOW AMMO" then ReloadLbl.Color=Color3.fromRGB(255,85,120)
elseif s.state=="COOLDOWN" then ReloadLbl.Color=Color3.fromRGB(120,190,255)
else ReloadLbl.Color=Color3.fromRGB(130,255,170) end
ReloadLbl.Visible=true
end
function setupTool(tool)
if not tool:IsA("Tool") then return end
if reloadConnections[tool] then return end
local con=tool.Activated:Connect(function()
if Config.ReloadPredictor and Drawing then
ReloadLbl.Text="Shot fired"; ReloadLbl.Visible=true
task.delay(0.45,function() if ReloadLbl then ReloadLbl.Text="Reload window?" end end)
task.delay(1.2,function() if ReloadLbl then ReloadLbl.Visible=false end end)
end
end)
reloadConnections[tool]=con
end
function watchTools(ch)
for _,t in safeIpairs(ch:GetChildren()) do setupTool(t) end
ch.ChildAdded:Connect(setupTool)
end
if lp.Character then watchTools(lp.Character) end
lp.CharacterAdded:Connect(watchTools)
-- =====================
-- SURROUND / BLIND SPOT
-- =====================
if Drawing then
surroundText = dnew("Text",{Text="",Size=13,Center=false,Outline=true, Color=Color3.fromRGB(220,210,255),Visible=false})
surroundShadow= dnew("Text",{Text="",Size=13,Center=false,Outline=false,Color=Color3.fromRGB(0,0,0),Transparency=0.75,Visible=false})
blindText = dnew("Text",{Text="",Size=14,Center=true, Outline=true, Color=Color3.fromRGB(255,180,110),Visible=false})
blindShadow = dnew("Text",{Text="",Size=14,Center=true, Outline=false,Color=Color3.fromRGB(0,0,0),Transparency=0.75,Visible=false})
end
function getRelativeZone(p)
local myRoot=getRoot(lp); local r=getRoot(p)
if not myRoot or not r then return nil,999 end
local rel=r.Position-myRoot.Position; local dist=rel.Magnitude
if dist>(Config.SurroundRadius or 120) then return nil,dist end
local flat=Vector3.new(rel.X,0,rel.Z)
if flat.Magnitude<1 then return "Front",dist end
local look=camera.CFrame.LookVector; local right=camera.CFrame.RightVector
local f=flat.Unit:Dot(Vector3.new(look.X,0,look.Z).Unit)
local s=flat.Unit:Dot(Vector3.new(right.X,0,right.Z).Unit)
if f>0.55 then return "Front",dist end
if f<-0.55 then return "Behind",dist end
if s>0 then return "Right",dist end
return "Left",dist
end
function updateSurroundAndBlindSpot()
if menuBlocksInput() or ghostUnloaded then
if surroundText then surroundText.Visible=false end; if surroundShadow then surroundShadow.Visible=false end
if blindText then blindText.Visible=false end; if blindShadow then blindShadow.Visible=false end
return
end
local counts={Front=0,Left=0,Right=0,Behind=0}
local nearestBlind=nil; local nearestBlindDist=99999; local closeTotal=0
for _,p in safeIpairs(Players:GetPlayers()) do
if validEnemy(p) then
local zone,dist=getRelativeZone(p)
if zone then
counts[zone]=counts[zone]+1; closeTotal=closeTotal+1
if (zone=="Behind" or zone=="Left" or zone=="Right") and dist<(Config.BlindSpotRadius or 80) and dist<nearestBlindDist then
nearestBlind=zone; nearestBlindDist=dist
end
end
end
end
if Config.SurroundMapHUD and surroundText and surroundShadow then
local pos=Vector2.new(22,180)
local txt="SURROUND\nF "..counts.Front.." | L "..counts.Left.." | R "..counts.Right.." | B "..counts.Behind.."\nclose: "..closeTotal
surroundShadow.Text=txt; surroundShadow.Position=pos+Vector2.new(2,2); surroundShadow.Visible=true
surroundText.Text=txt; surroundText.Position=pos; surroundText.Visible=true
surroundText.Color=(counts.Behind>0 or counts.Left+counts.Right>1) and Color3.fromRGB(255,180,110) or Color3.fromRGB(220,210,255)
elseif surroundText then surroundText.Visible=false; if surroundShadow then surroundShadow.Visible=false end end
if Config.BlindSpotMonitor and blindText and blindShadow and nearestBlind then
local vp=camera.ViewportSize
local label="BLIND SPOT: "..string.upper(nearestBlind).." "..math.floor(nearestBlindDist).."m"
local pos=Vector2.new(vp.X/2,vp.Y-135)
blindShadow.Text=label; blindShadow.Position=pos+Vector2.new(2,2); blindShadow.Visible=true
blindText.Text=label; blindText.Position=pos; blindText.Visible=true
elseif blindText then blindText.Visible=false; if blindShadow then blindShadow.Visible=false end end
end
-- =====================
-- CROSSHAIR UPDATE
-- =====================
local spin=0; local shotPulse=0; local fpsSmooth=60
UIS.InputBegan:Connect(function(input,gp)
if input.UserInputType==Enum.UserInputType.MouseButton1 then shotPulse=1 end
end)
function updateCrosshair(dt)
if not Drawing then return end
local allowMenuPreview=(menuVisible and currentTab=="Crosshair" and not Config.Hidden and not ghostUnloaded)
local m=UIS:GetMouseLocation()
local center=Vector2.new(m.X,m.Y)
local vp=camera and camera.ViewportSize or Vector2.new(1280,720)
local scale=1
if Config.CrosshairAutoSize then scale=clamp(math.min(vp.X/1280,vp.Y/720),0.75,1.35) end
spin=spin+dt*3; shotPulse=math.max(0,shotPulse-(dt*5.5))
local color=Config.CrosshairColor
if Config.FOVRainbow then color=Color3.fromHSV((tick()%5)/5,0.8,1) end
if Config.CrosshairShootPulse and shotPulse>0 then color=color:Lerp(Color3.fromRGB(255,255,255),shotPulse*0.75) end
if FOVCircle then FOVCircle.Position=center; FOVCircle.Radius=Config.SilentFOV; FOVCircle.Thickness=Config.FOVThickness; FOVCircle.Transparency=Config.FOVTransparency; FOVCircle.Visible=Config.FOVVisible and Config.SilentAim and not menuBlocksInput(); FOVCircle.Color=color end
if SACircle then SACircle.Position=center; SACircle.Radius=Config.AimFOV; SACircle.Thickness=Config.FOVThickness; SACircle.Transparency=Config.FOVTransparency; SACircle.Visible=Config.FOVVisible and (Config.Aimbot or Config.AimAssist) and not menuBlocksInput(); SACircle.Color=Color3.fromRGB(90,220,255) end
if TriggerCircle then TriggerCircle.Position=center; TriggerCircle.Radius=Config.TriggerFOV; TriggerCircle.Thickness=Config.FOVThickness; TriggerCircle.Transparency=Config.FOVTransparency; TriggerCircle.Visible=Config.TriggerFOVVisible and Config.TriggerBot and not menuBlocksInput(); TriggerCircle.Color=Color3.fromRGB(255,190,70) end
local visible=Config.Crosshair and (not menuBlocksInput() or allowMenuPreview)
local profile=Config.CrosshairProfile or "Classic"
local gap=(Config.CrosshairGap or 6)*scale; local len=(Config.CrosshairLength or 10)*scale; local th=(Config.CrosshairThickness or 2)
if Config.CrosshairDynamicGap then gap=gap+(shotPulse*7*scale) end
len=len+(shotPulse*5*scale); th=clamp(th+(shotPulse*1.5),1,10)
for _,line in safeIpairs(CHLines) do line.Visible=false end
if CHDot then CHDot.Visible=false end
local function setLine(i,a,b,t)
local line=CHLines[i]; if not line then return end
line.From=a; line.To=b; line.Thickness=t or th; line.Color=color; line.Visible=visible
end
local function rot(v,ang) local cs=math.cos(ang); local sn=math.sin(ang); return Vector2.new(v.X*cs-v.Y*sn,v.X*sn+v.Y*cs) end
local angle=Config.CrosshairSpin and spin or 0
local dirs={Vector2.new(1,0),Vector2.new(-1,0),Vector2.new(0,1),Vector2.new(0,-1)}
for i,d in safeIpairs(dirs) do dirs[i]=rot(d,angle) end
if profile=="Dot" then
if CHDot then CHDot.Position=center; CHDot.Color=color; CHDot.Radius=(3+shotPulse*2)*scale; CHDot.Filled=true; CHDot.Visible=visible end; return
elseif profile=="Circle" then
if CHDot then CHDot.Position=center; CHDot.Color=color; CHDot.Radius=(gap+len*0.65); CHDot.Filled=false; CHDot.Thickness=th; CHDot.Visible=visible end; return
elseif profile=="Box" then
local r=gap+len*0.55
local pts={Vector2.new(-r,-r),Vector2.new(r,-r),Vector2.new(r,r),Vector2.new(-r,r)}
for i=1,4 do pts[i]=center+rot(pts[i],angle) end
setLine(1,pts[1],pts[2]); setLine(2,pts[2],pts[3]); setLine(3,pts[3],pts[4]); setLine(4,pts[4],pts[1])
if CHDot and Config.CrosshairDot then CHDot.Position=center; CHDot.Color=color; CHDot.Radius=2*scale; CHDot.Filled=true; CHDot.Visible=visible end; return
elseif profile=="Diamond" then
local r=gap+len*0.75
local pts={Vector2.new(0,-r),Vector2.new(r,0),Vector2.new(0,r),Vector2.new(-r,0)}
for i=1,4 do pts[i]=center+rot(pts[i],angle) end
setLine(1,pts[1],pts[2]); setLine(2,pts[2],pts[3]); setLine(3,pts[3],pts[4]); setLine(4,pts[4],pts[1]); return
elseif profile=="X" then
dirs={Vector2.new(1,1).Unit,Vector2.new(-1,-1).Unit,Vector2.new(-1,1).Unit,Vector2.new(1,-1).Unit}
for i,d in safeIpairs(dirs) do d=rot(d,angle); setLine(i,center+d*gap,center+d*(gap+len),th) end; return
elseif profile=="Sniper" then
local long=len*1.8
setLine(1,center+dirs[1]*(gap+long*0.25),center+dirs[1]*(gap+long),th)
setLine(2,center+dirs[2]*(gap+long*0.25),center+dirs[2]*(gap+long),th)
setLine(3,center+dirs[3]*(gap+long*0.45),center+dirs[3]*(gap+long*1.15),math.max(1,th-0.5))
setLine(4,center+dirs[4]*(gap+long*0.45),center+dirs[4]*(gap+long*1.15),math.max(1,th-0.5))
if CHDot then CHDot.Position=center; CHDot.Color=color; CHDot.Radius=(gap*0.55); CHDot.Filled=false; CHDot.Thickness=math.max(1,th-0.5); CHDot.Visible=visible end; return
elseif profile=="Cyber" then
local a=rot(Vector2.new(1,0),angle); local b=rot(Vector2.new(0,1),angle)
setLine(1,center+a*gap,center+a*(gap+len*1.2),th+0.5)
setLine(2,center-a*gap,center-a*(gap+len*0.75),th)
setLine(3,center+b*gap,center+b*(gap+len*0.75),th)
setLine(4,center-b*gap,center-b*(gap+len*1.2),th+0.5)
if CHDot and Config.CrosshairDot then CHDot.Position=center; CHDot.Color=color; CHDot.Radius=(2+shotPulse*2)*scale; CHDot.Filled=true; CHDot.Visible=visible end; return
end
if profile=="Minimal" then len=math.max(4,math.floor(len*0.65)) end
for i,line in safeIpairs(CHLines) do
local d=dirs[i]; local hideLine=(profile=="T-Shape" and i==3)
line.From=center+d*gap; line.To=center+d*(gap+len); line.Thickness=th; line.Color=color; line.Visible=visible and not hideLine
end
if CHDot then CHDot.Position=center; CHDot.Color=color; CHDot.Radius=(Config.CrosshairDot and 2 or 0)+(shotPulse*1.5); CHDot.Filled=true; CHDot.Visible=visible and Config.CrosshairDot end
end
-- =====================
-- TARGET HUD
-- =====================
function updateTargetHud(target,part,scr,dt)
if not Drawing then return end
local vp=camera.ViewportSize
fpsSmooth=fpsSmooth*0.92+(1/math.max(dt or 1/60,1/240))*0.08
if topInfoText and topInfoShadow then
local targetName=target and target.Name or "none"
local txt="FPS "..math.floor(fpsSmooth).." | Ping "..getPing().." | Players "..#Players:GetPlayers().." | Target "..targetName
local pos=Vector2.new(vp.X-430,82)
topInfoShadow.Text=txt; topInfoShadow.Position=pos+Vector2.new(2,2); topInfoShadow.Visible=Config.TopIndicators and not menuBlocksInput()
topInfoText.Text=txt; topInfoText.Position=pos; topInfoText.Visible=Config.TopIndicators and not menuBlocksInput()
end
if target and part and scr and Config.TargetInfo and not menuBlocksInput() then
local hum=getHum(target); local root=getRoot(target)
local hp=hum and math.floor(hum.Health) or 0
local dist=root and math.floor((root.Position-camera.CFrame.Position).Magnitude) or 0
local txt=hp.." HP | "..dist.."m"..formatOpponentState(target)..formatOpponentMovement(target)
targetInfoShadow.Text=txt; targetInfoShadow.Position=scr+Vector2.new(2,20); targetInfoShadow.Visible=true
targetInfoText.Text=txt; targetInfoText.Position=scr+Vector2.new(0,18); targetInfoText.Visible=true
if TargetLock then TargetLock.Position=scr; TargetLock.Radius=clamp(16-(dist/120),7,16); TargetLock.Thickness=2; TargetLock.Color=Color3.fromRGB(90,255,150); TargetLock.Visible=Config.TargetLockCircle end
else
if targetInfoShadow then targetInfoShadow.Visible=false end
if targetInfoText then targetInfoText.Visible=false end
if TargetLock then TargetLock.Visible=false end
end
end
-- =====================
-- MAIN RENDER LOOP
-- =====================
local ghostStart = tick()
RunService.RenderStepped:Connect(function(dt)
if ghostUnloaded then return end
camera=Workspace.CurrentCamera
updateResolver() -- includes anti-aim detection
updateESP()
updateChams()
applyGlassLook()
updateGhostBackground()
updateAnimatedBackground(dt)
updateIdleGlow(dt)
updateDockAutoHide()
updateDockStyle()
updateMiniMap()
updateSurroundAndBlindSpot()
if ProfileCard then
ProfileCard.Visible=(sidebarExpanded and Config.ProfileCard==true)
pcStroke.Color=Config.UIAccent
local runtime=math.floor((tick()-ghostStart)/60)
pcBody.Text=(Config.ThemePreset or "Custom").." | "..runtime.."m"
end
getDampenedCameraLook() -- tick camera history every frame
updateCrosshair(dt)
triggerCheck()
updateReloadStateHUD()
local hudTarget,hudPart,hudScreen=nil,nil,nil
-- Multi-target suppressor: widen FOV if many enemies nearby
local activeFOV=Config.AimFOV
if Config.MultiTargetSuppressor and getMultiTargetCount()>=3 then
activeFOV=activeFOV*(Config.MultiTargetRadius or 3)
end
if Config.Aimbot and aimKeyDown() and not menuBlocksInput() then
local target,part=closestTarget(activeFOV,true)
lastTarget=target
if target and part then
local pos=predictedPos(target,part)
local scr,on=worldToScreen(pos)
if on then
hudTarget,hudPart,hudScreen=target,part,scr
moveMouseTo(scr,Config.AimSmooth)
if AimCircle then AimCircle.Position=scr; AimCircle.Visible=true end
if AimLine then AimLine.From=UIS:GetMouseLocation(); AimLine.To=scr; AimLine.Visible=true end
end
else
if AimCircle then AimCircle.Visible=false end; if AimLine then AimLine.Visible=false end
end
else
if not triggerHolding then lastTarget=nil end
if AimCircle then AimCircle.Visible=false end; if AimLine then AimLine.Visible=false end
end
if Config.AimAssist and not menuBlocksInput() then
local target,part=closestTarget(activeFOV,true)
if target and part then
local scr,on=worldToScreen(predictedPos(target,part))
if on then hudTarget,hudPart,hudScreen=target,part,scr; moveMouseTo(scr,1-Config.AimAssistStrength) end
end
end
-- Flick assist (runs when neither aimbot nor assist found a target in FOV)
if Config.FlickAssist and not menuBlocksInput() and not hudTarget then
tryFlickAssist()
end
if not hudTarget then
local t,p=closestTarget(activeFOV,true)
if t and p then local s,on=worldToScreen(p.Position); if on then hudTarget,hudPart,hudScreen=t,p,s end end
end
updateTargetHud(hudTarget,hudPart,hudScreen,dt)
if Config.AutoPistol and mouseDown and not menuBlocksInput() and now()-lastShot>0.08 then
lastShot=now(); pcall(mouse1click)
end
if Config.NoRecoil then
local cf=camera.CFrame
camera.CFrame=lastCamCF:Lerp(cf,0.35)
end
lastCamCF=camera.CFrame
if ReloadLbl then
ReloadLbl.Position=UIS:GetMouseLocation()+Vector2.new(0,35)
ReloadLbl.Visible=ReloadLbl.Visible and Config.ReloadPredictor and not menuBlocksInput()
end
end)
-- =====================
-- KEYBINDS
-- =====================
UIS.InputBegan:Connect(function(input,gp)
if ghostUnloaded then return end
if gp then return end
if input.KeyCode==Enum.KeyCode.F1 then
menuVisible=not menuVisible; Root.Visible=menuVisible; setDockVisible(not menuVisible)
if menuVisible then
setDockVisible(false); mouseDown=false; triggerHolding=false; pcall(mouse1release)
for _,obj in safePairs(ESPObjects) do hideAll(obj) end
if FOVCircle then FOVCircle.Visible=false end; if SACircle then SACircle.Visible=false end
if TriggerCircle then TriggerCircle.Visible=false end; if TargetLock then TargetLock.Visible=false end
if ReloadLbl then ReloadLbl.Visible=false end; if CHDot then CHDot.Visible=false end
for _,l in safePairs(CHLines) do l.Visible=false end
end
return
end
local ok,key=pcall(function() return Enum.KeyCode[Config.PanicKey] end)
if ok and input.KeyCode==key then
Config.Hidden=not Config.Hidden; mouseDown=false; triggerHolding=false; pcall(mouse1release)
if Config.Hidden then
for _,obj in safePairs(ESPObjects) do hideAll(obj) end
if FOVCircle then FOVCircle.Visible=false end; if SACircle then SACircle.Visible=false end
if TriggerCircle then TriggerCircle.Visible=false end; if TargetLock then TargetLock.Visible=false end
if ReloadLbl then ReloadLbl.Visible=false end
for _,l in safePairs(CHLines) do l.Visible=false end; if CHDot then CHDot.Visible=false end
Root.Visible=false
else Root.Visible=menuVisible end
end
end)
-- =====================
-- UNLOAD
-- =====================
_G.GhostUnload=function()
if ghostUnloaded then return end
ghostUnloaded=true
Config.Hidden=true; Config.ESP=false; Config.Aimbot=false; Config.AimAssist=false
Config.SilentAim=false; Config.TriggerBot=false; Config.AutoPistol=false; Config.NoRecoil=false
Config.Crosshair=false; Config.FOVVisible=false; Config.ReloadPredictor=false; Config.AntiAimDetect=false
mouseDown=false; triggerHolding=false; pcall(mouse1release)
if aimAssistConn then pcall(function() aimAssistConn:Disconnect() end) end
if autoPistolConn then pcall(function() autoPistolConn:Disconnect() end) end
if recoilConn then pcall(function() recoilConn:Disconnect() end) end
for _,c in safePairs(reloadConnections) do pcall(function() c:Disconnect() end) end
reloadConnections={}
for _,obj in safePairs(ESPObjects) do hideAll(obj) end
for player,_ in safePairs(ESPObjects) do removeESP(player) end
safeRemove(FOVCircle); safeRemove(SACircle); safeRemove(TriggerCircle)
safeRemove(AimCircle); safeRemove(AimLine); safeRemove(TargetLock)
safeRemove(topInfoShadow); safeRemove(topInfoText); safeRemove(targetInfoShadow); safeRemove(targetInfoText)
safeRemove(surroundText); safeRemove(surroundShadow); safeRemove(blindText); safeRemove(blindShadow)
safeRemove(antiAimIndicator); safeRemove(HoverTip); safeRemove(ReloadLbl)
for _,l in ipairs(LOSLines) do safeRemove(l) end; LOSLines={}
for _,c in ipairs(LOSCones) do safeRemove(c) end; LOSCones={}
if MiniMapFrame then pcall(function() MiniMapFrame:Destroy() end); MiniMapFrame=nil end
MiniMapDots={}; MiniMapWaypoints={}
for _,l in safePairs(CHLines) do safeRemove(l) end; CHLines={}
safeRemove(CHDot); CHDot=nil
for _,a in safePairs(OffArrows) do safeRemove(a) end; OffArrows={}
for _,p in safeIpairs(Players:GetPlayers()) do
local ch=getChar(p); local h=ch and ch:FindFirstChild("GhostCham")
if h then pcall(function() h:Destroy() end) end
end
pcall(function() menuBlur.Enabled=false; menuBlur:Destroy() end)
if scannerWatchConn then pcall(function() scannerWatchConn:Disconnect() end); scannerWatchConn=nil end
if Dock then pcall(function() Dock:Destroy() end); Dock=nil end
pcall(function() ScreenGui:Destroy() end)
trackedHumanoids={}; resolverData={}; arrowBuckets={}; ESPObjects={}; rigCache={}; antiAimData={}
print("Ghost Menu v5.3 fully unloaded.")
end
applyGhostTheme(Config.ThemePreset)
applyGlassLook()
updateGhostBackground()
print("Ghost Menu v5.3 loaded. F1 = toggle | "..Config.PanicKey.." = panic | Universal rig resolver active")
To embed this project on your website, copy the following code and paste it into your website's HTML: