Run it
Copy the script and paste it into your executor.
Players = :()
CoreGui = :()
UserInputService = :()
TweenService = :()
RunService = :()
Workspace =
StarterGui = :()
LocalPlayer = Players.LocalPlayer
Camera = Workspace.CurrentCamera
Mouse = LocalPlayer:()
Camera LocalPlayer Mouse
TWEEN_INFO_FAST = TweenInfo.(, .EasingStyle.Quad, .EasingDirection.Out)
TWEEN_INFO_MED = TweenInfo.(, .EasingStyle.Back, .EasingDirection.Out)
TWEEN_INFO_SLOW = TweenInfo.(, .EasingStyle.Quart, .EasingDirection.Out)
THEME = {
bg = .(, , ),
panel = .(, , ),
miniPanel = .(, , ),
accent = .(, , ),
subtleAccent = .(, , ),
danger = .(, , ),
text = .(, , ),
muted = .(, , )
}
isMobile = UserInputService.TouchEnabled UserInputService.KeyboardEnabled
scale = isMobile
SIZES = {
MainW = * scale,
MainH = * scale,
MainX = * scale,
MainY = * scale,
TitleH = * scale,
BtnSize = * scale,
BtnPadding = * scale,
CornerS = * scale,
CornerM = * scale,
CornerL = * scale,
SearchH = * scale,
Padding = * scale,
ListTop = * scale,
ListBottom = * scale,
BottomBtnH = * scale,
BottomBtnY = * scale,
EntryH = * scale,
EntryPad = * scale,
AvatarSize = * scale,
AvatarPad = * scale,
AvatarY = * scale,
MiniH = * scale,
MiniIconSize = * scale,
MiniSideMargin = * scale,
MiniBetweenPadding = * scale,
MiniMinWidth = * scale,
MiniMaxWidth = * scale,
}
FONTS = {
Title = .( * scale),
Btn = .( * scale),
MiniIcon = .( * scale),
Search = .( * scale),
State = .( * scale),
Name = .( * scale),
Sub = .( * scale),
ViewBtn = .( * scale),
BottomBtn = .( * scale),
}
existing = CoreGui:()
existing
existing:()
isMinimized =
dragging, dragStart, startPos
searchDebounce =
spyConnection =
spyTargetPart =
spiedPlayer =
hiddenGuisBySpy = {}
isSpying =
cameraCanClip =
touchId =
orbit = {
enabled = ,
distance = ,
minDistance = ,
maxDistance = ,
smoothing = ,
}
DEFAULT_ORBIT_MAX_DISTANCE = orbit.maxDistance
isManualCameraActive =
manualJustActivated =
isTransitioning =
cameraAngle = .(, )
orbitRadius = orbit.distance
zoomDelta =
isMouseDown =
CAMERA_ROTATION_SENSITIVITY =
CAMERA_ZOOM_SPEED =
lastTouchScale =
PINCH_ZOOM_SENSITIVITY =
isPlaceholderActive =
ctrlLockActive =
prevCameraSaved =
prevCameraOffset =
prevCameraType =
prevCameraSubject =
initialCameraAngle = .(, )
hasInitialAngle =
npcCache = {}
lastNPCRefresh =
NPC_CACHE_TIMEOUT =
(character)
character
character:()
character:()
character:()
character:()
(player)
player
displayName = player.DisplayName player.DisplayName ~= player.DisplayName player.Name
displayName
(part)
part part:()
part.Anchored ==
part.CanCollide ==
(targetPos, desiredPos, ignoreInstances)
cameraCanClip desiredPos,
rayParams = RaycastParams.()
rayParams.FilterType = .RaycastFilterType.Blacklist
rayParams.FilterDescendantsInstances = ignoreInstances {}
direction = desiredPos - targetPos
ignored = {}
attempts =
attempts = attempts +
filterList = {}
ignoreInstances
_, v (ignoreInstances)
.(filterList, v)
_, v (ignored)
.(filterList, v)
rayParams.FilterDescendantsInstances = filterList
result = Workspace:(targetPos, direction, rayParams)
result
desiredPos,
part = result.Instance
(part)
.(ignored, part)
attempts >
offset = result.Normal *
result.Position + offset,
offset = result.Normal *
result.Position + offset,
(instance, props, info)
instance instance.Parent
(()
TweenService:(instance, info TWEEN_INFO_FAST, props):()
)
ScreenGui = .()
ScreenGui.Name =
ScreenGui.ZIndexBehavior = .ZIndexBehavior.Sibling
ScreenGui.Parent = CoreGui
ScreenGui.ResetOnSpawn =
ScreenGui.Enabled =
SpyFadeOverlay = .(, ScreenGui)
SpyFadeOverlay.Name =
SpyFadeOverlay.BackgroundColor3 = .(, , )
SpyFadeOverlay.BackgroundTransparency =
SpyFadeOverlay.BorderSizePixel =
SpyFadeOverlay.Size = .(, , , )
SpyFadeOverlay.ZIndex =
SpyFadeOverlay.Visible =
MainFrame = .(, ScreenGui)
MainFrame.Name =
MainFrame.Size = .(, SIZES.MainW, , SIZES.MainH)
MainFrame.Position = .(, SIZES.MainX, , SIZES.MainY)
MainFrame.BackgroundColor3 = THEME.bg
MainFrame.BorderSizePixel =
MainFrame.ClipsDescendants =
MainFrame.Active =
MainFrame.ZIndex =
.(, MainFrame).CornerRadius = .(, SIZES.CornerL)
mainStroke = .(, MainFrame)
mainStroke.Color = .(, , )
mainStroke.Transparency =
MiniCover = .(, MainFrame)
MiniCover.Name =
MiniCover.Size = .(, , , )
MiniCover.Position = .(, , , )
MiniCover.BackgroundColor3 = THEME.miniPanel
MiniCover.BorderSizePixel =
MiniCover.Visible =
.(, MiniCover).CornerRadius = .(, SIZES.CornerL)
MiniCover.ZIndex =
TitleBar = .(, MainFrame)
TitleBar.Name =
TitleBar.Size = .(, , , SIZES.TitleH)
TitleBar.Position = .(, , , )
TitleBar.BackgroundColor3 = THEME.panel
TitleBar.Active =
.(, TitleBar).CornerRadius = .(, SIZES.CornerL)
TitleContainer = .(, TitleBar)
TitleContainer.Size = .(, -(SIZES.Padding), , )
TitleContainer.Position = .(, SIZES.Padding / , , )
TitleContainer.BackgroundTransparency =
UIListLayout_Title = .(, TitleContainer)
UIListLayout_Title.FillDirection = .FillDirection.Horizontal
UIListLayout_Title.VerticalAlignment = .VerticalAlignment.Center
UIListLayout_Title.HorizontalAlignment = .HorizontalAlignment.Right
UIListLayout_Title.SortOrder = .SortOrder.LayoutOrder
UIListLayout_Title.Padding = .(, SIZES.BtnPadding)
TitleLabel = .(, TitleContainer)
TitleLabel.BackgroundTransparency =
TitleLabel.Size = .(, -(SIZES.BtnSize * + SIZES.BtnPadding * ), , )
TitleLabel.Text =
TitleLabel.TextColor3 = THEME.text
TitleLabel.Font = .Font.GothamBold
TitleLabel.TextSize = FONTS.Title
TitleLabel.TextXAlignment = .TextXAlignment.Left
TitleLabel.LayoutOrder =
ToggleCameraButton = .(, TitleContainer)
ToggleCameraButton.Name =
ToggleCameraButton.Size = .(, SIZES.BtnSize, , SIZES.BtnSize)
ToggleCameraButton.BackgroundColor3 = THEME.subtleAccent
ToggleCameraButton.Text =
ToggleCameraButton.Font = .Font.GothamBold
ToggleCameraButton.TextSize = FONTS.Btn *
ToggleCameraButton.BorderSizePixel =
ToggleCameraButton.Visible =
ToggleCameraButton.LayoutOrder =
.(, ToggleCameraButton).CornerRadius = .(, SIZES.CornerS)
MaximizeButton = .(, TitleContainer)
MaximizeButton.Size = .(, SIZES.BtnSize, , SIZES.BtnSize)
MaximizeButton.BackgroundColor3 = THEME.accent
MaximizeButton.Text =
MaximizeButton.Font = .Font.GothamBold
MaximizeButton.TextSize = FONTS.Btn
MaximizeButton.BorderSizePixel =
MaximizeButton.LayoutOrder =
.(, MaximizeButton).CornerRadius = .(, SIZES.CornerS)
MiniControls = .(, MainFrame)
MiniControls.Name =
MiniControls.BackgroundTransparency =
MiniControls.Visible =
MiniControls.ClipsDescendants =
MiniControls.ZIndex =
MiniLayout = .(, MiniControls)
MiniLayout.FillDirection = .FillDirection.Horizontal
MiniLayout.HorizontalAlignment = .HorizontalAlignment.Center
MiniLayout.VerticalAlignment = .VerticalAlignment.Center
MiniLayout.SortOrder = .SortOrder.LayoutOrder
MiniLayout.Padding = .(, SIZES.MiniBetweenPadding)
MaximizeMiniButton = .(, MiniControls)
MaximizeMiniButton.Size = .(, SIZES.MiniIconSize, , SIZES.MiniIconSize)
MaximizeMiniButton.BackgroundColor3 = THEME.accent
MaximizeMiniButton.Text =
MaximizeMiniButton.Font = .Font.GothamBold
MaximizeMiniButton.TextSize = FONTS.MiniIcon
MaximizeMiniButton.TextColor3 = .(, , )
MaximizeMiniButton.LayoutOrder =
.(, MaximizeMiniButton).CornerRadius = .(, SIZES.CornerM)
MaximizeMiniButton.ZIndex =
MiniManualButton = .(, MiniControls)
MiniManualButton.Size = .(, SIZES.MiniIconSize, , SIZES.MiniIconSize)
MiniManualButton.BackgroundColor3 = THEME.subtleAccent
MiniManualButton.Text =
MiniManualButton.Font = .Font.GothamBold
MiniManualButton.TextSize = FONTS.MiniIcon
MiniManualButton.TextColor3 = .(, , )
MiniManualButton.LayoutOrder =
MiniManualButton.BorderSizePixel =
.(, MiniManualButton).CornerRadius = .(, SIZES.CornerM)
MiniManualButton.ZIndex =
MiniBackButton = .(, MiniControls)
MiniBackButton.Size = .(, SIZES.MiniIconSize, , SIZES.MiniIconSize)
MiniBackButton.BackgroundColor3 = THEME.danger
MiniBackButton.Text =
MiniBackButton.Font = .Font.GothamBold
MiniBackButton.TextSize = FONTS.MiniIcon
MiniBackButton.TextColor3 = .(, , )
MiniBackButton.LayoutOrder =
MiniBackButton.BorderSizePixel =
.(, MiniBackButton).CornerRadius = .(, SIZES.CornerM)
MiniBackButton.ZIndex =
MiniBackSquare = .(, MiniBackButton)
sqSize = SIZES.MiniIconSize -
MiniBackSquare.Size = .(, sqSize, , sqSize)
MiniBackSquare.Position = .(, -sqSize/, , -sqSize/)
MiniBackSquare.BackgroundTransparency =
MiniBackSquare.BorderSizePixel =
MiniBackSquare.ZIndex =
MiniBackStroke = .(, MiniBackSquare)
MiniBackStroke.Color = .(, , )
MiniBackStroke.Thickness =
MiniBackStroke.ApplyStrokeMode = .ApplyStrokeMode.Border
SearchBox = .(, MainFrame)
SearchBox.Size = .(, -(SIZES.Padding * ), , SIZES.SearchH)
SearchBox.Position = .(, SIZES.Padding, , SIZES.TitleH + * scale)
SearchBox.PlaceholderText =
SearchBox.PlaceholderColor3 = THEME.muted
SearchBox.BackgroundColor3 = .(, , )
SearchBox.TextColor3 = THEME.text
SearchBox.TextSize = FONTS.Search
SearchBox.Text =
SearchBox.ClearTextOnFocus =
.(, SearchBox).CornerRadius = .(, SIZES.CornerS)
PlayerFrame = .(, MainFrame)
PlayerFrame.Size = .(, -(SIZES.Padding * ), , -SIZES.ListBottom)
PlayerFrame.Position = .(, SIZES.Padding, , SIZES.ListTop)
PlayerFrame.BackgroundColor3 = .(, , )
PlayerFrame.ScrollBarThickness = * scale
PlayerFrame.AutomaticCanvasSize = .AutomaticSize.Y
PlayerFrame.ScrollBarImageColor3 = THEME.accent
PlayerFrame.ClipsDescendants =
PlayerFrame.ScrollingDirection = .ScrollingDirection.Y
.(, PlayerFrame).CornerRadius = .(, * scale)
PlayerLayout = .(, PlayerFrame)
PlayerLayout.Padding = .(, SIZES.CornerS)
PlayerLayout.SortOrder = .SortOrder.LayoutOrder
PlayerLayout.HorizontalAlignment = .HorizontalAlignment.Center
BackToPlayerButton = .(, MainFrame)
BackToPlayerButton.Size = .(, -(SIZES.Padding * ), , SIZES.BottomBtnH)
BackToPlayerButton.Position = .(, SIZES.Padding, , -SIZES.BottomBtnY)
BackToPlayerButton.BackgroundColor3 = THEME.danger
BackToPlayerButton.Text =
BackToPlayerButton.Font = .Font.GothamBold
BackToPlayerButton.TextSize = FONTS.BottomBtn
BackToPlayerButton.BorderSizePixel =
.(, BackToPlayerButton).CornerRadius = .(, SIZES.CornerM)
StateLabel = .(, MainFrame)
StateLabel.Size = .(, -(SIZES.Padding * ), , * scale)
StateLabel.Position = .(, SIZES.Padding, , SIZES.TitleH + * scale + SIZES.SearchH + * scale)
StateLabel.BackgroundTransparency =
StateLabel.TextColor3 = THEME.muted
StateLabel.Font = .Font.Gotham
StateLabel.TextSize = FONTS.State
StateLabel.Visible =
()
gui, _ (hiddenGuisBySpy)
gui gui.Parent
(() gui.Enabled = )
hiddenGuisBySpy = {}
(enabled)
enabled == isSpying
isSpying = enabled
enabled
hiddenGuisBySpy = {}
cameraCanClip =
(()
StarterGui:(.CoreGuiType.All, )
StarterGui:(.CoreGuiType.PlayerList, )
)
_, gui (LocalPlayer.PlayerGui:())
gui:() gui.Name ~= ScreenGui.Name gui.Enabled ==
hiddenGuisBySpy[gui] =
gui.Enabled =
cameraCanClip =
(()
StarterGui:(.CoreGuiType.All, )
StarterGui:(.CoreGuiType.PlayerList, )
)
()
isMinimized
ToggleCameraButton.Visible = isSpying
()
spyConnection
spyConnection:()
spyConnection =
isTransitioning =
spyTargetPart =
spiedPlayer =
orbit.enabled =
isMouseDown =
lastTouchScale =
touchId =
ctrlLockActive =
(()
UserInputService.MouseBehavior = .MouseBehavior.Default
(() UserInputService.MouseIconEnabled = )
)
()
icon = isManualCameraActive
ToggleCameraButton ToggleCameraButton.Parent
ToggleCameraButton.Text = icon
MiniManualButton MiniManualButton.Parent
MiniManualButton.Text = icon
color = isManualCameraActive THEME.accent THEME.subtleAccent
ToggleCameraButton ToggleCameraButton.Parent
ToggleCameraButton.BackgroundColor3 = color
MiniManualButton MiniManualButton.Parent
MiniManualButton.BackgroundColor3 = color
(targetPos)
camPos = Camera.CFrame.Position
toTarget = (camPos - targetPos)
dir = toTarget.Unit
rotY = .(dir.X, -dir.Z)
rotX = .(.(dir.Y, -, ))
cameraAngle = .(rotY, rotX)
rotation = .(, rotY, ) * .(rotX, , )
correctPos = targetPos + (rotation.LookVector * orbitRadius * -)
Camera.CFrame = .(correctPos, targetPos)
(enabled)
isManualCameraActive = enabled
()
enabled
spyTargetPart spyTargetPart.Parent
tPos = spyTargetPart.Position + .(, , )
realDist = (Camera.CFrame.Position - tPos).Magnitude
orbitRadius = .(realDist, orbit.minDistance, orbit.maxDistance)
(tPos)
orbitRadius = orbit.distance
orbit.maxDistance = .(DEFAULT_ORBIT_MAX_DISTANCE, )
lastTouchScale =
manualJustActivated =
orbit.maxDistance = DEFAULT_ORBIT_MAX_DISTANCE
orbit.distance = orbitRadius
manualJustActivated =
(()
UserInputService.MouseBehavior = .MouseBehavior.Default
(() UserInputService.MouseIconEnabled = )
)
()
hasInitialAngle
camPos = Camera.CFrame.Position
forward = Camera.CFrame.LookVector
rotY = .(forward.X, -forward.Z)
rotX = .(.(forward.Y, -, ))
initialCameraAngle = .(rotY, rotX)
hasInitialAngle =
(charModel)
charModel charModel.Parent
isSpying
()
prevCameraSaved
localRoot = (LocalPlayer.Character)
localRoot
prevCameraType = Camera.CameraType
prevCameraSubject = Camera.CameraSubject
prevCameraOffset = localRoot.CFrame:(Camera.CFrame)
prevCameraSaved =
savedRadius
isManualCameraActive
savedRadius = orbitRadius
spyTargetPart spyTargetPart.Parent
tPos = spyTargetPart.Position + .(, , )
savedRadius = (Camera.CFrame.Position - tPos).Magnitude
localRoot = (LocalPlayer.Character)
savedRadius = localRoot (Camera.CFrame.Position - localRoot.Position).Magnitude orbit.distance
savedRadius = .(savedRadius, orbit.minDistance, DEFAULT_ORBIT_MAX_DISTANCE)
()
root = (charModel)
root
spyTargetPart = root
spiedPlayer = Players:(charModel)
orbit.distance = savedRadius
orbitRadius = savedRadius
orbit.maxDistance = isManualCameraActive
.(DEFAULT_ORBIT_MAX_DISTANCE, )
DEFAULT_ORBIT_MAX_DISTANCE
orbit.enabled =
Camera.CameraType = .CameraType.Scriptable
()
isManualCameraActive
tPos = root.Position + .(, , )
startCF = Camera.CFrame
duration =
elapsed =
isTransitioning =
animConn
animConn = RunService.RenderStepped:((dt)
(()
elapsed = elapsed + dt
t = .(elapsed / duration, , )
e = - ( - t)^
behindOffset = -root.CFrame.LookVector * orbitRadius + .(, , )
desiredPos = tPos + behindOffset
goalCF = .(desiredPos, tPos)
Camera.CFrame = startCF:(goalCF, e)
elapsed >= duration
animConn
animConn:()
animConn =
isTransitioning =
finalDir = (Camera.CFrame.Position - tPos).Unit
cameraAngle = .(
.(finalDir.X, -finalDir.Z),
.(.(finalDir.Y, -, ))
)
initialCameraAngle = cameraAngle
)
)
spyConnection = RunService.RenderStepped:((dt)
(()
isTransitioning
spyTargetPart spyTargetPart.Parent
spiedPlayer spiedPlayer.Character
newRoot = (spiedPlayer.Character)
newRoot
spyTargetPart = newRoot
()
()
tPos = spyTargetPart.Position + .(, , )
ignoreList = {}
spyTargetPart.Parent .(ignoreList, spyTargetPart.Parent)
LocalPlayer LocalPlayer.Character .(ignoreList, LocalPlayer.Character)
targetCFrame
isManualCameraActive
orbitRadius = .(orbit.minDistance, orbitRadius - zoomDelta)
zoomDelta =
rotation = .(, cameraAngle.X, ) * .(cameraAngle.Y, , )
desiredPos = tPos + (rotation.LookVector * orbitRadius * -)
camPosCollided, _ = (tPos, desiredPos, ignoreList)
targetCFrame = .(camPosCollided, tPos)
orbitRadius = orbit.distance
desiredPos = tPos - spyTargetPart.CFrame.LookVector * orbit.distance + .(, , )
minHeight = .(, tPos.Y + )
desiredPos.Y < minHeight desiredPos = .(desiredPos.X, minHeight, desiredPos.Z)
camPosCollided, _ = (tPos, desiredPos, ignoreList)
targetCFrame = .(camPosCollided, tPos)
manualJustActivated
Camera.CFrame = targetCFrame
manualJustActivated =
smooth = isManualCameraActive orbit.smoothing
alpha = .( - .(-dt * smooth), , )
Camera.CFrame = Camera.CFrame:(targetCFrame, alpha)
)
)
()
isSpying
hadSpy = isSpying
spyConnection
spyConnection:()
spyConnection =
root = (LocalPlayer.Character)
prevCameraSaved root prevCameraOffset
Camera.CameraType = .CameraType.Scriptable
startCFrame = Camera.CFrame
duration =
elapsed =
resetConn
resetConn = RunService.RenderStepped:((dt)
(()
elapsed = elapsed + dt
t = .(elapsed / duration, , )
eased
t <
eased = * t * t * t
f = ( * t) -
eased = * f * f * f +
currentRoot = (LocalPlayer.Character)
currentRoot
endCFrame = currentRoot.CFrame * prevCameraOffset
Camera.CFrame = startCFrame:(endCFrame, eased)
elapsed >= duration
resetConn
resetConn:()
resetConn =
prevCameraType
Camera.CameraType = prevCameraType
Camera.CameraType = .CameraType.Custom
prevCameraType == .CameraType.Custom prevCameraSubject
(() Camera.CameraSubject = prevCameraSubject )
prevCameraType == .CameraType.Custom
humanoid = LocalPlayer.Character LocalPlayer.Character:()
humanoid (() Camera.CameraSubject = humanoid )
prevCameraSaved =
prevCameraOffset =
prevCameraType =
prevCameraSubject =
)
)
root
Camera.CameraType = .CameraType.Scriptable
startCFrame = Camera.CFrame
duration =
elapsed =
resetConn
resetConn = RunService.RenderStepped:((dt)
(()
elapsed = elapsed + dt
t = .(elapsed / duration, , )
eased
t <
eased = * t * t * t
f = ( * t) -
eased = * f * f * f +
currentRoot = (LocalPlayer.Character)
currentRoot
desiredPos = currentRoot.Position + currentRoot.CFrame.LookVector * - + .(, , )
endCFrame = .(desiredPos, currentRoot.Position)
Camera.CFrame = startCFrame:(endCFrame, eased)
elapsed >= duration
resetConn
resetConn:()
resetConn =
Camera.CameraType = .CameraType.Custom
humanoid = LocalPlayer.Character:()
humanoid Camera.CameraSubject = humanoid
)
)
Camera.CameraType = .CameraType.Custom
hadSpy
()
()
hasInitialAngle =
initialCameraAngle = .(, )
orbit.maxDistance = DEFAULT_ORBIT_MAX_DISTANCE
()
BackToPlayerButton.MouseButton1Click:(()
isSpying
(BackToPlayerButton, {BackgroundColor3 = THEME.subtleAccent}, TWEEN_INFO_FAST)
.(, ()
(BackToPlayerButton, {BackgroundColor3 = THEME.danger}, TWEEN_INFO_FAST)
)
()
)
MiniBackButton.MouseButton1Click:(()
isSpying
(MiniBackButton, {BackgroundTransparency = }, TWEEN_INFO_FAST)
.(, ()
(MiniBackButton, {BackgroundTransparency = }, TWEEN_INFO_FAST)
)
()
)
MiniManualButton.MouseButton1Click:(()
isSpying
( isManualCameraActive)
)
ToggleCameraButton.MouseButton1Click:(()
isSpying
( isManualCameraActive)
)
(model)
entry = .()
entry.Name = .. model:()
entry.Parent = PlayerFrame
entry.Size = .(, -SIZES.EntryPad, , SIZES.EntryH)
entry.BackgroundColor3 = .(, , )
entry.BorderSizePixel =
entry.AutoButtonColor =
entry.Text =
entry.LayoutOrder = #PlayerFrame:()
.(, entry).CornerRadius = .(, SIZES.CornerM)
left = .(, entry)
left.BackgroundTransparency =
left.Position = .(, SIZES.AvatarPad, , SIZES.AvatarY)
left.Size = .(, SIZES.AvatarSize, , -(SIZES.AvatarY * ))
avatar = .(, left)
avatar.Size = .(, , , )
avatar.BackgroundColor3 = .(, , )
avatar.BorderSizePixel =
avatar.Image =
avatar.ScaleType = .ScaleType.Crop
.(, avatar).CornerRadius = .(, SIZES.CornerS)
nameX = SIZES.AvatarPad + SIZES.AvatarSize + * scale
btnW = * scale
btnPadding = SIZES.AvatarPad
btnTotalSpace = btnW + btnPadding
nameLabel = .(, entry)
nameLabel.BackgroundTransparency =
nameLabel.Position = .(, nameX, , * scale)
nameLabel.Size = .(, -(nameX + btnTotalSpace + * scale), , FONTS.Name + * scale)
nameLabel.TextXAlignment = .TextXAlignment.Left
nameLabel.Text = model.Name
nameLabel.TextColor3 = THEME.text
nameLabel.Font = .Font.GothamSemibold
nameLabel.TextSize = FONTS.Name
nameLabel.TextTruncate = .TextTruncate.AtEnd
subLabel = .(, entry)
subLabel.BackgroundTransparency =
subLabel.Position = .(, nameX, , ( * scale) + FONTS.Name + ( * scale))
subLabel.Size = .(, -(nameX + btnTotalSpace + * scale), , FONTS.Sub + * scale)
subLabel.TextXAlignment = .TextXAlignment.Left
subLabel.Text =
subLabel.TextColor3 = THEME.muted
subLabel.Font = .Font.Gotham
subLabel.TextSize = FONTS.Sub
subLabel.TextTruncate = .TextTruncate.AtEnd
viewBtn = .(, entry)
viewBtn.Size = .(, btnW, , SIZES.BtnSize)
viewBtn.Position = .(, -(btnW + btnPadding), , -(SIZES.BtnSize / ))
viewBtn.BackgroundColor3 = THEME.accent
viewBtn.Text =
viewBtn.TextColor3 = .(, , )
viewBtn.Font = .Font.GothamBold
viewBtn.TextSize = FONTS.ViewBtn
viewBtn.BorderSizePixel =
.(, viewBtn).CornerRadius = .(, SIZES.CornerS)
entry.MouseEnter:(()
(entry, {BackgroundColor3 = .(, , )}, TWEEN_INFO_FAST)
)
entry.MouseLeave:(()
(entry, {BackgroundColor3 = .(, , )}, TWEEN_INFO_FAST)
)
viewBtn.MouseButton1Click:(()
(viewBtn, {BackgroundTransparency = }, TWEEN_INFO_FAST)
.(, ()
(viewBtn, {BackgroundTransparency = }, TWEEN_INFO_FAST)
)
(model)
)
entry
(player)
entry = .()
entry.Name = .. player.UserId
entry.Parent = PlayerFrame
entry.Size = .(, -SIZES.EntryPad, , SIZES.EntryH)
entry.BackgroundColor3 = .(, , )
entry.BorderSizePixel =
entry.AutoButtonColor =
entry.Text =
entry.LayoutOrder = #PlayerFrame:()
.(, entry).CornerRadius = .(, SIZES.CornerM)
left = .(, entry)
left.BackgroundTransparency =
left.Position = .(, SIZES.AvatarPad, , SIZES.AvatarY)
left.Size = .(, SIZES.AvatarSize, , -(SIZES.AvatarY * ))
avatar = .(, left)
avatar.Size = .(, , , )
avatar.BackgroundColor3 = .(, , )
avatar.BorderSizePixel =
avatar.Image = .. (player.UserId) ..
avatar.ScaleType = .ScaleType.Crop
.(, avatar).CornerRadius = .(, SIZES.CornerS)
nameX = SIZES.AvatarPad + SIZES.AvatarSize + * scale
btnW = * scale
btnPadding = SIZES.AvatarPad
btnTotalSpace = btnW + btnPadding
nameLabel = .(, entry)
nameLabel.BackgroundTransparency =
nameLabel.Position = .(, nameX, , * scale)
nameLabel.Size = .(, -(nameX + btnTotalSpace + * scale), , FONTS.Name + * scale)
nameLabel.TextXAlignment = .TextXAlignment.Left
nameLabel.Text = (player)
nameLabel.TextColor3 = THEME.text
nameLabel.Font = .Font.GothamSemibold
nameLabel.TextSize = FONTS.Name
nameLabel.TextTruncate = .TextTruncate.AtEnd
subLabel = .(, entry)
subLabel.BackgroundTransparency =
subLabel.Position = .(, nameX, , ( * scale) + FONTS.Name + ( * scale))
subLabel.Size = .(, -(nameX + btnTotalSpace + * scale), , FONTS.Sub + * scale)
subLabel.TextXAlignment = .TextXAlignment.Left
subLabel.Text = .. player.Name
subLabel.TextColor3 = THEME.muted
subLabel.Font = .Font.Gotham
subLabel.TextSize = FONTS.Sub
subLabel.TextTruncate = .TextTruncate.AtEnd
viewBtn = .(, entry)
viewBtn.Size = .(, btnW, , SIZES.BtnSize)
viewBtn.Position = .(, -(btnW + btnPadding), , -(SIZES.BtnSize / ))
viewBtn.BackgroundColor3 = THEME.accent
viewBtn.Text =
viewBtn.TextColor3 = .(, , )
viewBtn.Font = .Font.GothamBold
viewBtn.TextSize = FONTS.ViewBtn
viewBtn.BorderSizePixel =
.(, viewBtn).CornerRadius = .(, SIZES.CornerS)
entry.MouseEnter:(()
(entry, {BackgroundColor3 = .(, , )}, TWEEN_INFO_FAST)
)
entry.MouseLeave:(()
(entry, {BackgroundColor3 = .(, , )}, TWEEN_INFO_FAST)
)
viewBtn.MouseButton1Click:(()
(viewBtn, {BackgroundTransparency = }, TWEEN_INFO_FAST)
.(, ()
(viewBtn, {BackgroundTransparency = }, TWEEN_INFO_FAST)
)
(player.Character)
)
entry
(filter)
filter = (filter ):()
_, child (PlayerFrame:())
child:() (child.Name:() child.Name:())
child:()
visibleCount =
_, player (Players:())
player == LocalPlayer
display = (player.DisplayName player.Name):()
username = (player.Name ):()
filter == display:(filter, , ) username:(filter, , )
visibleCount = visibleCount +
entry = (player)
entry.LayoutOrder = visibleCount
entry.BackgroundTransparency =
(entry, {BackgroundTransparency = }, TWEEN_INFO_MED)
npcCount =
processedNPCs = {}
currentTime = ()
currentTime - lastNPCRefresh > NPC_CACHE_TIMEOUT
npcCache = {}
lastNPCRefresh = currentTime
_, descendant (Workspace:())
descendant:()
model = descendant.Parent
processedNPCs[model]
rootPart = model:()
rootPart descendant.Health > Players:(model)
npcName = model.Name:()
filter == npcName:(filter, , )
processedNPCs[model] =
npcCount = npcCount +
entry = (model)
entry.LayoutOrder = visibleCount + npcCount +
entry.BackgroundTransparency =
(entry, {BackgroundTransparency = }, TWEEN_INFO_MED)
visibleCount == npcCount ==
StateLabel.Text =
StateLabel.Visible =
(StateLabel, {TextTransparency = }, TWEEN_INFO_FAST)
(StateLabel, {TextTransparency = }, TWEEN_INFO_FAST)
.(, () StateLabel.Visible = )
PlayerLayout:():(()
y = PlayerLayout.AbsoluteContentSize.Y
PlayerFrame.CanvasSize = .(, , , y + * scale)
)
Players.PlayerAdded:((player)
filterText = isPlaceholderActive SearchBox.Text
(filterText)
)
Players.PlayerRemoving:((player)
spiedPlayer player == spiedPlayer ()
filterText = isPlaceholderActive SearchBox.Text
(filterText)
)
SearchBox:():(()
SearchBox.Text ~= SearchBox.PlaceholderText SearchBox.Text ~=
isPlaceholderActive =
searchDebounce
searchDebounce =
.(, ()
filterText = (SearchBox.Text == SearchBox.PlaceholderText SearchBox.Text == ) SearchBox.Text
(filterText)
searchDebounce =
)
)
SearchBox.Focused:(()
isPlaceholderActive
SearchBox.Text =
)
SearchBox.FocusLost:(()
SearchBox.Text ==
isPlaceholderActive =
SearchBox.Text = SearchBox.PlaceholderText
()
)
()
()
children = MiniControls:()
btnCount =
_, c (children)
c:() c.Visible
btnCount = btnCount +
btnCount == SIZES.MiniMinWidth
totalIconsWidth = btnCount * SIZES.MiniIconSize
totalPadding = .(, btnCount - ) * SIZES.MiniBetweenPadding
width = SIZES.MiniSideMargin * + totalIconsWidth + totalPadding
width = .(width, SIZES.MiniMinWidth, SIZES.MiniMaxWidth)
width
()
isMinimized
MiniManualButton.Visible = isSpying
MiniManualButton.Visible =
MaximizeMiniButton.Visible =
MiniBackButton.Visible =
()
isMinimized
newW = ()
miniInnerW = newW - (SIZES.MiniSideMargin * )
(MiniControls, {Size = .(, miniInnerW, , SIZES.MiniH)}, TWEEN_INFO_MED)
(MiniControls, {Position = .(, -miniInnerW / , , -(SIZES.MiniH / ))}, TWEEN_INFO_MED)
(MainFrame, {Size = .(, newW, , SIZES.MiniH)}, TWEEN_INFO_MED)
(()
()
.()
)
()
SearchBox.Visible =
PlayerFrame.Visible =
BackToPlayerButton.Visible =
StateLabel.Visible =
TitleLabel.Visible =
()
SearchBox.Visible =
PlayerFrame.Visible =
BackToPlayerButton.Visible =
TitleLabel.Visible =
()
isMinimized
isMinimized =
()
MiniCover.Visible =
MiniCover.BackgroundTransparency =
MiniCover.ZIndex =
(TitleBar, {BackgroundColor3 = THEME.miniPanel}, TWEEN_INFO_FAST)
(TitleLabel, {TextTransparency = }, TWEEN_INFO_FAST)
(SearchBox, {BackgroundTransparency = , TextTransparency = }, TWEEN_INFO_FAST)
(PlayerFrame, {BackgroundTransparency = }, TWEEN_INFO_FAST)
(BackToPlayerButton, {BackgroundTransparency = , TextTransparency = }, TWEEN_INFO_FAST)
()
.(, ()
MaximizeButton.Visible =
ToggleCameraButton.Visible =
MiniControls.Visible =
MiniControls.ZIndex =
MiniCover.ZIndex =
)
()
isMinimized
isMinimized =
()
MiniCover.Visible =
TitleLabel.TextTransparency =
SearchBox.BackgroundTransparency =
SearchBox.TextTransparency =
PlayerFrame.BackgroundTransparency =
BackToPlayerButton.BackgroundTransparency =
BackToPlayerButton.TextTransparency =
(MainFrame, {Size = .(, SIZES.MainW, , SIZES.MainH)}, TWEEN_INFO_MED)
MaximizeButton.Visible =
ToggleCameraButton.Visible = isSpying
MiniControls.Visible =
(TitleBar, {BackgroundColor3 = THEME.panel}, TWEEN_INFO_FAST)
(TitleLabel, {TextTransparency = }, TWEEN_INFO_FAST)
(SearchBox, {BackgroundTransparency = , TextTransparency = }, TWEEN_INFO_FAST)
(PlayerFrame, {BackgroundTransparency = }, TWEEN_INFO_FAST)
(BackToPlayerButton, {BackgroundTransparency = , TextTransparency = }, TWEEN_INFO_FAST)
MaximizeButton.MouseButton1Click:(()
isMinimized
()
MaximizeButton.Text =
()
MaximizeButton.Text =
)
MaximizeMiniButton.MouseButton1Click:(()
()
MaximizeButton.Text =
)
(input)
input.UserInputType ~= .UserInputType.MouseButton1 input.UserInputType ~= .UserInputType.Touch
dragging =
dragStart = input.Position
startPos = MainFrame.Position
input.Changed:(()
input.UserInputState == .UserInputState.End
dragging =
)
(input)
dragging
delta = input.Position - dragStart
newX = startPos.X.Offset + delta.X
newY = startPos.Y.Offset + delta.Y
screenW, screenH = Workspace.CurrentCamera.ViewportSize.X, Workspace.CurrentCamera.ViewportSize.Y
fw, fh = MainFrame.AbsoluteSize.X, MainFrame.AbsoluteSize.Y
newX = .(newX, -fw + , screenW - )
newY = .(newY, -fh + , screenH - )
MainFrame.Position = .(, newX, , newY)
TitleBar.InputBegan:(beginDrag)
TitleBar.InputChanged:((input)
input.UserInputType == .UserInputType.MouseMovement input.UserInputType == .UserInputType.Touch
(input)
)
MiniControls.InputBegan:(beginDrag)
MiniControls.InputChanged:((input)
input.UserInputType == .UserInputType.MouseMovement input.UserInputType == .UserInputType.Touch
(input)
)
UserInputService.InputChanged:((input)
dragging (input.UserInputType == .UserInputType.MouseMovement input.UserInputType == .UserInputType.Touch)
(input)
)
UserInputService.InputBegan:((input, gameProcessed)
(()
gameProcessed
(input.KeyCode == .KeyCode.LeftControl input.KeyCode == .KeyCode.RightControl) isSpying isManualCameraActive
ctrlLockActive = ctrlLockActive
ctrlLockActive
isMouseDown =
(() UserInputService.MouseBehavior = .MouseBehavior.LockCenter )
(() UserInputService.MouseIconEnabled = )
isMouseDown =
(() UserInputService.MouseBehavior = .MouseBehavior.Default )
(() UserInputService.MouseIconEnabled = )
isSpying isManualCameraActive
isControlInput = input.UserInputType == .UserInputType.MouseButton2 input.UserInputType == .UserInputType.Touch input.UserInputType == .UserInputType.Gamepad1
isControlInput isMouseDown
input.UserInputType == .UserInputType.MouseButton2
isMouseDown =
UserInputService.MouseBehavior = .MouseBehavior.LockCenter
input.UserInputType == .UserInputType.Touch
isMouseDown =
touchId = input.UserInputType
input.UserInputType == .UserInputType.Gamepad1 input.KeyCode == .KeyCode.Thumbstick2
isMouseDown =
)
)
UserInputService.InputEnded:((input, gameProcessed)
(()
isSpying isManualCameraActive
isControlInput = input.UserInputType == .UserInputType.MouseButton2 input.UserInputType == .UserInputType.Touch input.UserInputType == .UserInputType.Gamepad1
isControlInput isMouseDown ctrlLockActive
input.UserInputType == .UserInputType.MouseButton2
isMouseDown =
UserInputService.MouseBehavior = .MouseBehavior.Default
input.UserInputType == .UserInputType.Touch
isMouseDown =
touchId =
input.UserInputType == .UserInputType.Gamepad1 input.KeyCode == .KeyCode.Thumbstick2
isMouseDown =
)
)
UserInputService.InputChanged:((input, gameProcessed)
(()
isSpying isManualCameraActive
isMouseDown
input.UserInputType == .UserInputType.MouseMovement
delta = input.Delta * CAMERA_ROTATION_SENSITIVITY
cameraAngle = cameraAngle + .(-delta.X, -delta.Y)
input.UserInputType == .UserInputType.Touch touchId
delta = input.Delta * CAMERA_ROTATION_SENSITIVITY * (isMobile )
cameraAngle = cameraAngle + .(-delta.X, -delta.Y)
input.UserInputType == .UserInputType.Gamepad1 input.KeyCode == .KeyCode.Thumbstick2
delta = .(-input.Position.X, input.Position.Y) * CAMERA_ROTATION_SENSITIVITY *
cameraAngle = cameraAngle + delta
cameraAngle = .(cameraAngle.X, .(cameraAngle.Y, -.pi/ + , .pi/ - ))
input.UserInputType == .UserInputType.MouseWheel
mousePos = UserInputService:()
absPos = MainFrame.AbsolutePosition
absSize = MainFrame.AbsoluteSize
overUI = mousePos.X >= absPos.X mousePos.X <= absPos.X + absSize.X
mousePos.Y >= absPos.Y mousePos.Y <= absPos.Y + absSize.Y
overUI
zoomDelta = zoomDelta + input.Position.Z * CAMERA_ZOOM_SPEED
input.UserInputType == .UserInputType.Gamepad1
input.KeyCode == .KeyCode.ButtonL1 input.KeyCode == .KeyCode.ButtonL2
input.UserInputState == .UserInputState.Begin zoomDelta = zoomDelta - CAMERA_ZOOM_SPEED *
input.KeyCode == .KeyCode.ButtonR1 input.KeyCode == .KeyCode.ButtonR2
input.UserInputState == .UserInputState.Begin zoomDelta = zoomDelta + CAMERA_ZOOM_SPEED *
)
)
UserInputService.TouchPinch:((touchPositions, scale, velocity, state)
(()
isSpying isManualCameraActive
state == .UserInputState.Begin lastTouchScale = scale
state == .UserInputState.Change
lastTouchScale
difference = scale - lastTouchScale
zoomDelta = zoomDelta + difference * PINCH_ZOOM_SENSITIVITY
lastTouchScale = scale
state == .UserInputState.End lastTouchScale =
)
)
UserInputService.InputBegan:((input, gameProcessed)
gameProcessed
input.KeyCode == .KeyCode.Escape
isMinimized () ()
)
MainFrame.Position = .(, SIZES.MainX, , -)
(MainFrame, {Position = .(, SIZES.MainX, , SIZES.MainY)}, TWEEN_INFO_SLOW)
(MainFrame, {Size = .(, SIZES.MainW, , SIZES.MainH)}, TWEEN_INFO_SLOW)ofrece una interfaz moderna que permite espiar jugadores o NPCs con controles de cámara avanzados. Incluye: UI adaptable con búsqueda, lista de jugadores/NPCs y botones de control. Modo espía que oculta la interfaz del jugador y sigue al objetivo. Cámara manual y automática con zoom, rotación orbital y colisión inteligente. Animaciones suaves para transiciones y restauración de la cámara original. Compatibilidad móvil/PC con escalado automático y controles táctiles o de teclado/ratón.

Universal