KeysEsp CameraUnlock Fly Xray Teleport Ect
Key Required

KeysEsp CameraUnlock Fly Xray Teleport Ect

Piggy but It's 100 Players: Classic EditionEndermaterXEndermaterX 4.8K views 8.8K executesUpdated May 26, 2026
5.0/ 5(1 votes)
10100% Positive
Lua Script•2276 lines (55042 chars)
--[[
	piggy 100 players
	Created by: Endermaterx
	Credit: Endermaterx created and owns this menu script, UI style, object names, and branding.
]]

--// Services
local Players = game:GetService("Players")
local StarterGui = game:GetService("StarterGui")
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local CollectionService = game:GetService("CollectionService")

--// Player
local localPlayer = Players.LocalPlayer
local playerGui = localPlayer:WaitForChild("PlayerGui")

--// Config
local CREATOR_NAME = "Endermaterx"
local CREDIT_TEXT = "Created by: " .. CREATOR_NAME
local SCRIPT_TITLE = "piggy 100 players (Created by: " .. CREATOR_NAME .. ")"
local OBJECT_PREFIX = CREATOR_NAME .. "Piggy100Players"
local UI_TOGGLE_KEY = Enum.KeyCode.RightShift
local LOCAL_CAMERA_LOCK = OBJECT_PREFIX .. "LocalCameraLock"

local MENU_DEFAULT_WIDTH = 380
local MENU_DEFAULT_HEIGHT = 520
local MENU_MIN_WIDTH = 330
local MENU_MIN_HEIGHT = 310
local MENU_MAX_WIDTH = 760
local MENU_MAX_HEIGHT = 720

local LOW_GRAVITY = 45
local FORCE_JUMP_POWER = 34
local FORCE_JUMP_HEIGHT = 5.4
local TELEPORT_OFFSET = CFrame.new(0, 2.5, 4.5)

local COLORS = {
	Background = Color3.fromRGB(24, 13, 38),
	BackgroundDeep = Color3.fromRGB(13, 7, 23),
	Panel = Color3.fromRGB(42, 24, 65),
	PanelDeep = Color3.fromRGB(30, 17, 49),
	Track = Color3.fromRGB(73, 43, 105),
	Accent = Color3.fromRGB(178, 105, 255),
	AccentDark = Color3.fromRGB(125, 68, 196),
	AccentOn = Color3.fromRGB(211, 151, 255),
	AccentSoft = Color3.fromRGB(238, 220, 255),
	ItemRed = Color3.fromRGB(255, 45, 45),
	Text = Color3.fromRGB(250, 244, 255),
	TextMuted = Color3.fromRGB(224, 207, 245),
	Warning = Color3.fromRGB(198, 82, 224)
}

local TWEENS = {
	Fast = TweenInfo.new(0.1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out),
	Smooth = TweenInfo.new(0.18, Enum.EasingStyle.Quad, Enum.EasingDirection.Out),
	Pop = TweenInfo.new(0.22, Enum.EasingStyle.Back, Enum.EasingDirection.Out),
	Window = TweenInfo.new(0.26, Enum.EasingStyle.Quart, Enum.EasingDirection.Out)
}

local ITEM_NAME_KEYWORDS = {
	"key",
	"card",
	"coin",
	"token",
	"gem",
	"collect",
	"pickup",
	"item",
	"tool",
	"gear",
	"battery",
	"hammer",
	"wrench",
	"plank",
	"board",
	"ammo",
	"gun",
	"weapon",
	"crossbow",
	"carrot",
	"apple",
	"grass",
	"bone",
	"gas",
	"gasoline",
	"torch",
	"screwdriver",
	"scissors",
	"mop",
	"book",
	"code",
	"dynamite",
	"candle",
	"potion",
	"extinguisher",
	"crowbar",
	"whitekey",
	"redkey",
	"bluekey",
	"greenkey",
	"yellowkey",
	"purplekey",
	"orangekey"
}

local ITEM_BLOCKED_NAME_KEYWORDS = {
	"door",
	"gate",
	"wall",
	"floor",
	"ceiling",
	"roof",
	"window",
	"vent",
	"ladder",
	"stairs",
	"stair",
	"elevator",
	"portal",
	"barrier",
	"fence",
	"safe",
	"locker",
	"drawer",
	"cabinet",
	"button",
	"lever",
	"switch",
	"pad",
	"plate",
	"spawn",
	"checkpoint",
	"trigger",
	"zone",
	"hitbox",
	"collision",
	"invisible",
	"map",
	"building",
	"house",
	"wallpart",
	"escape"
}

local ITEM_ATTRIBUTE_NAMES = {
	"Collectible",
	"Grabbable",
	"Pickup",
	"PickUp",
	"Item",
	"IsItem",
	"CanPickup",
	"CanPickUp",
	"PiggyItem"
}

local ITEM_COLLECTION_TAGS = {
	"Collectible",
	"Grabbable",
	"Pickup",
	"Item",
	"PiggyItem",
	"KeyItem"
}

local ITEM_MAX_LONGEST_SIDE = 11
local ITEM_MAX_TOTAL_VOLUME = 450

--// Reset older copies
pcall(function()
	script.Name = SCRIPT_TITLE
	script:SetAttribute("CreatedBy", CREATOR_NAME)
	script:SetAttribute("Credit", CREDIT_TEXT)
	script:SetAttribute("Brand", "Endermaterx Piggy 100 Players")
end)

pcall(function()
	RunService:UnbindFromRenderStep(LOCAL_CAMERA_LOCK)
end)

for _, guiName in ipairs({ "OneScriptPlayerMenu", "EndermaterxPiggyPlayerMenu", SCRIPT_TITLE }) do
	local oldGui = playerGui:FindFirstChild(guiName)
	if oldGui then
		oldGui:Destroy()
	end
end

--// State
local State = {
	character = nil,
	humanoid = nil,
	root = nil,

	speed = 16,
	noclip = false,
	showPlayer = false,
	lowGravity = false,
	forceJump = false,
	fly = false,
	flySpeed = 60,
	xray = false,
	highlightItems = false,
	piggySpectateTarget = nil,

	hideUi = false,
	menuVisible = true,
	minimized = false
}

local Runtime = {
	normalGravity = Workspace.Gravity,
	originalCollision = {},
	originalJumpPower = nil,
	originalJumpHeight = nil,
	originalUseJumpPower = nil,
	descendantConnection = nil,

	flyVelocity = nil,
	flyGyro = nil,

	xrayObjects = {},
	xrayConnections = {},
	itemHighlights = {},
	itemConnections = {},

	hiddenScreenGuiStates = {},
	hiddenCoreGuiStates = {},
	coreGuiSnapshotTaken = false
}

local UI = {
	buttons = {},
	buttonBaseColors = {},
	actionLogs = {}
}

--// Small helpers
local function create(className, properties, parent)
	local object = Instance.new(className)

	for key, value in pairs(properties or {}) do
		object[key] = value
	end

	object.Parent = parent
	return object
end

local function tween(object, tweenInfo, properties)
	local animation = TweenService:Create(object, tweenInfo, properties)
	animation:Play()
	return animation
end

local function addCorner(object, radius)
	return create("UICorner", {
		CornerRadius = UDim.new(0, radius)
	}, object)
end

local function addStroke(object, color, thickness, transparency)
	return create("UIStroke", {
		Color = color,
		Thickness = thickness,
		Transparency = transparency or 0
	}, object)
end

local function disconnectAll(connections)
	for _, connection in ipairs(connections) do
		connection:Disconnect()
	end
end

local function getCharacterParts(targetCharacter)
	local parts = {}
	if not targetCharacter then
		return parts
	end

	for _, item in ipairs(targetCharacter:GetDescendants()) do
		if item:IsA("BasePart") then
			table.insert(parts, item)
		end
	end

	return parts
end

local function getPlayerRoot(targetPlayer)
	local targetCharacter = targetPlayer and targetPlayer.Character
	if not targetCharacter then
		return nil
	end

	return targetCharacter:FindFirstChild("HumanoidRootPart")
end

local function getPlayerLabel(targetPlayer)
	if not targetPlayer then
		return "None"
	end

	return targetPlayer.DisplayName .. "  @" .. targetPlayer.Name
end

local function getPlayerDistanceText(targetPlayer)
	local targetRoot = getPlayerRoot(targetPlayer)
	if not State.root or not targetRoot then
		return ""
	end

	local distance = math.floor((State.root.Position - targetRoot.Position).Magnitude + 0.5)
	return "  [" .. distance .. " studs]"
end

local function getLocalLogName()
	return localPlayer.DisplayName ~= "" and localPlayer.DisplayName or localPlayer.Name
end

local function getPlayerFromCameraSubject(cameraSubject)
	if not cameraSubject then
		return nil
	end

	local subjectInstance = cameraSubject
	if cameraSubject:IsA("Humanoid") then
		subjectInstance = cameraSubject.Parent
	end

	for _, targetPlayer in ipairs(Players:GetPlayers()) do
		local targetCharacter = targetPlayer.Character
		if targetPlayer ~= localPlayer and targetCharacter then
			if subjectInstance == targetCharacter or subjectInstance:IsDescendantOf(targetCharacter) then
				return targetPlayer
			end
		end
	end

	return nil
end

local function getTeamColor(targetPlayer)
	if targetPlayer and targetPlayer.Team then
		return targetPlayer.Team.TeamColor.Color
	end

	if targetPlayer and targetPlayer.TeamColor then
		return targetPlayer.TeamColor.Color
	end

	return COLORS.Accent
end

local function setStatus(text)
	if UI.statusLabel then
		table.insert(UI.actionLogs, 1, getLocalLogName() .. ": " .. text)

		while #UI.actionLogs > 4 do
			table.remove(UI.actionLogs)
		end

		UI.statusLabel.Text = table.concat(UI.actionLogs, "\n")
	end
end

local function setButtonVisual(button, enabled, onText, offText)
	if not button then
		return
	end

	button.Text = enabled and onText or offText

	local color = enabled and COLORS.AccentOn or COLORS.AccentDark
	UI.buttonBaseColors[button] = color
	tween(button, TWEENS.Smooth, {
		BackgroundColor3 = color
	})
end

local function refreshHeader()
	if UI.statusLabel and #UI.actionLogs == 0 then
		UI.statusLabel.Text = "No actions yet."
	end
end

--// Camera and UI hiding
local function snapCameraToLocalPlayer()
	local camera = Workspace.CurrentCamera
	if not camera or not State.humanoid then
		return
	end

	localPlayer.CameraMode = Enum.CameraMode.Classic
	camera.CameraType = Enum.CameraType.Custom
	camera.CameraSubject = State.humanoid
end

local function hideCoreGui()
	if not Runtime.coreGuiSnapshotTaken then
		Runtime.hiddenCoreGuiStates = {}

		for _, coreType in ipairs(Enum.CoreGuiType:GetEnumItems()) do
			if coreType ~= Enum.CoreGuiType.All then
				local ok, enabled = pcall(function()
					return StarterGui:GetCoreGuiEnabled(coreType)
				end)

				if ok then
					Runtime.hiddenCoreGuiStates[coreType] = enabled
				end
			end
		end

		Runtime.coreGuiSnapshotTaken = true
	end

	pcall(function()
		StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false)
	end)

	for _, coreType in ipairs(Enum.CoreGuiType:GetEnumItems()) do
		if coreType ~= Enum.CoreGuiType.All then
			pcall(function()
				StarterGui:SetCoreGuiEnabled(coreType, false)
			end)
		end
	end
end

local function restoreCoreGui()
	if not Runtime.coreGuiSnapshotTaken then
		pcall(function()
			StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, true)
		end)
		return
	end

	for coreType, enabled in pairs(Runtime.hiddenCoreGuiStates) do
		pcall(function()
			StarterGui:SetCoreGuiEnabled(coreType, enabled)
		end)
	end

	Runtime.hiddenCoreGuiStates = {}
	Runtime.coreGuiSnapshotTaken = false
end

local function protectHiddenUi()
	if not State.hideUi or not UI.gui then
		return
	end

	hideCoreGui()

	for _, child in ipairs(playerGui:GetChildren()) do
		if child:IsA("ScreenGui") then
			if child == UI.gui then
				child.Enabled = true
			else
				if Runtime.hiddenScreenGuiStates[child] == nil then
					Runtime.hiddenScreenGuiStates[child] = child.Enabled
				end

				child.Enabled = false
			end
		end
	end
end

local function hideEverythingExceptMenu()
	State.hideUi = true
	State.menuVisible = true
	Runtime.hiddenScreenGuiStates = {}
	protectHiddenUi()
end

local function restoreHiddenUi()
	State.hideUi = false
	State.menuVisible = true

	for screenGui, wasEnabled in pairs(Runtime.hiddenScreenGuiStates) do
		if screenGui and screenGui.Parent then
			screenGui.Enabled = wasEnabled
		end
	end

	Runtime.hiddenScreenGuiStates = {}
	restoreCoreGui()

	if UI.gui then
		UI.gui.Enabled = true
	end
end

local function setOwnMenuVisible(visible)
	State.menuVisible = visible
	UI.gui.Enabled = true

	if visible then
		if UI.menu then
			UI.menu.Visible = true
		end
		if UI.shadow then
			UI.shadow.Visible = true
		end

		if UI.menuScale then
			UI.menuScale.Scale = 0.96
			tween(UI.menuScale, TWEENS.Pop, {
				Scale = 1
			})
		end
		if UI.shadow then
			UI.shadow.BackgroundTransparency = 1
			tween(UI.shadow, TWEENS.Window, {
				BackgroundTransparency = 0.74
			})
		end
	else
		if UI.menuScale then
			tween(UI.menuScale, TWEENS.Fast, {
				Scale = 0.96
			})
		end
		if UI.shadow then
			tween(UI.shadow, TWEENS.Fast, {
				BackgroundTransparency = 1
			})
		end

		task.delay(0.12, function()
			if not State.menuVisible then
				if UI.menu then
					UI.menu.Visible = false
				end
				if UI.shadow then
					UI.shadow.Visible = false
				end
			end
		end)
	end
end

local function setShowPlayer(enabled)
	State.showPlayer = enabled

	if enabled then
		hideEverythingExceptMenu()
		setOwnMenuVisible(true)
		snapCameraToLocalPlayer()
		setStatus("turned ShowPlayer on")
	else
		restoreHiddenUi()
		setStatus("turned ShowPlayer off")
	end

	setButtonVisual(UI.buttons.showPlayer, State.showPlayer, "ShowPlayer: ON", "ShowPlayer: OFF")
	refreshHeader()
end

--// Movement
local function rememberCollision(part)
	if Runtime.originalCollision[part] == nil then
		Runtime.originalCollision[part] = part.CanCollide
	end
end

local function restoreCollision()
	if not State.character then
		return
	end

	for _, part in ipairs(getCharacterParts(State.character)) do
		rememberCollision(part)
		part.CanCollide = Runtime.originalCollision[part]
	end
end

local function setNoclip(enabled)
	State.noclip = enabled

	if not enabled then
		restoreCollision()
	end

	setButtonVisual(UI.buttons.noclip, State.noclip, "Noclip: ON", "Noclip: OFF")
	setStatus("turned noclip " .. (State.noclip and "on" or "off"))
end

local function setLowGravity(enabled)
	State.lowGravity = enabled
	Workspace.Gravity = enabled and LOW_GRAVITY or Runtime.normalGravity
	setButtonVisual(UI.buttons.lowGravity, State.lowGravity, "Low Gravity: ON", "Low Gravity: OFF")
	setStatus("turned low gravity " .. (State.lowGravity and "on" or "off"))
end

local function applyForceJump()
	if not State.humanoid then
		return
	end

	pcall(function()
		State.humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
	end)

	pcall(function()
		State.humanoid:SetStateEnabled(Enum.HumanoidStateType.Freefall, true)
	end)

	if State.humanoid.UseJumpPower then
		State.humanoid.JumpPower = FORCE_JUMP_POWER
	else
		State.humanoid.JumpHeight = FORCE_JUMP_HEIGHT
	end
end

local function restoreJump()
	if not State.humanoid then
		return
	end

	if Runtime.originalUseJumpPower ~= nil then
		State.humanoid.UseJumpPower = Runtime.originalUseJumpPower
	end

	if Runtime.originalJumpPower ~= nil then
		State.humanoid.JumpPower = Runtime.originalJumpPower
	end

	if Runtime.originalJumpHeight ~= nil then
		State.humanoid.JumpHeight = Runtime.originalJumpHeight
	end
end

local function setForceJump(enabled)
	State.forceJump = enabled

	if enabled then
		applyForceJump()
	else
		restoreJump()
	end

	setButtonVisual(UI.buttons.forceJump, State.forceJump, "Force Jump: ON", "Force Jump: OFF")
	setStatus("turned force jump " .. (State.forceJump and "on" or "off"))
end

local function destroyFlyForces()
	if Runtime.flyVelocity then
		Runtime.flyVelocity:Destroy()
		Runtime.flyVelocity = nil
	end

	if Runtime.flyGyro then
		Runtime.flyGyro:Destroy()
		Runtime.flyGyro = nil
	end
end

local function createFlyForces()
	if not State.root then
		return
	end

	if Runtime.flyVelocity and Runtime.flyVelocity.Parent == State.root and Runtime.flyGyro and Runtime.flyGyro.Parent == State.root then
		return
	end

	destroyFlyForces()

	Runtime.flyVelocity = create("BodyVelocity", {
		Name = OBJECT_PREFIX .. "FlyVelocity",
		MaxForce = Vector3.new(100000, 100000, 100000),
		P = 15000,
		Velocity = Vector3.zero
	}, State.root)

	Runtime.flyGyro = create("BodyGyro", {
		Name = OBJECT_PREFIX .. "FlyGyro",
		MaxTorque = Vector3.new(100000, 100000, 100000),
		P = 15000,
		D = 650,
		CFrame = State.root.CFrame
	}, State.root)
end

local function setFly(enabled)
	State.fly = enabled

	if enabled then
		createFlyForces()
		if State.humanoid then
			State.humanoid.PlatformStand = true
			State.humanoid:ChangeState(Enum.HumanoidStateType.Physics)
		end
	else
		destroyFlyForces()
		if State.humanoid then
			State.humanoid.PlatformStand = false
			State.humanoid:ChangeState(Enum.HumanoidStateType.Running)
		end
	end

	setButtonVisual(UI.buttons.fly, State.fly, "Fly: ON", "Fly: OFF")
	setStatus("turned fly " .. (State.fly and "on" or "off"))
end

local function updateFlyMovement()
	if not State.fly then
		return
	end

	if not State.root or not State.humanoid then
		setFly(false)
		return
	end

	createFlyForces()

	local camera = Workspace.CurrentCamera
	if not camera or not Runtime.flyVelocity or not Runtime.flyGyro then
		return
	end

	if UserInputService:GetFocusedTextBox() then
		Runtime.flyVelocity.Velocity = Vector3.zero
		return
	end

	local direction = Vector3.zero
	local cameraCFrame = camera.CFrame

	if UserInputService:IsKeyDown(Enum.KeyCode.W) then
		direction = direction + cameraCFrame.LookVector
	end
	if UserInputService:IsKeyDown(Enum.KeyCode.S) then
		direction = direction - cameraCFrame.LookVector
	end
	if UserInputService:IsKeyDown(Enum.KeyCode.D) then
		direction = direction + cameraCFrame.RightVector
	end
	if UserInputService:IsKeyDown(Enum.KeyCode.A) then
		direction = direction - cameraCFrame.RightVector
	end
	if UserInputService:IsKeyDown(Enum.KeyCode.Space) or UserInputService:IsKeyDown(Enum.KeyCode.E) then
		direction = direction + Vector3.new(0, 1, 0)
	end
	if UserInputService:IsKeyDown(Enum.KeyCode.LeftControl) or UserInputService:IsKeyDown(Enum.KeyCode.Q) then
		direction = direction - Vector3.new(0, 1, 0)
	end

	Runtime.flyVelocity.Velocity = direction.Magnitude > 0 and direction.Unit * State.flySpeed or Vector3.zero
	Runtime.flyGyro.CFrame = cameraCFrame
	State.humanoid.PlatformStand = true
end

--// Endermaterx click-to-teleport
local function teleportToPlayer(targetPlayer)
	if not targetPlayer then
		setStatus("teleport failed because the player was not found")
		return false
	end

	if not State.root then
		setStatus("teleport failed because your character is not ready")
		return false
	end

	local targetRoot = getPlayerRoot(targetPlayer)
	if not targetRoot then
		setStatus("teleport failed because " .. targetPlayer.DisplayName .. " has no character")
		return false
	end

	State.root.AssemblyLinearVelocity = Vector3.zero
	State.root.AssemblyAngularVelocity = Vector3.zero
	State.root.CFrame = targetRoot.CFrame * TELEPORT_OFFSET
	setStatus("teleported to " .. targetPlayer.DisplayName)
	return true
end

--// Player xray
local function clearXrayForPlayer(targetPlayer)
	local bundle = Runtime.xrayObjects[targetPlayer]
	if not bundle then
		return
	end

	for _, object in pairs(bundle) do
		if typeof(object) == "Instance" and object.Parent then
			object:Destroy()
		end
	end

	Runtime.xrayObjects[targetPlayer] = nil
end

local function updateXrayForPlayer(targetPlayer)
	if targetPlayer == localPlayer then
		return
	end

	clearXrayForPlayer(targetPlayer)

	if not State.xray then
		return
	end

	local targetCharacter = targetPlayer.Character
	if not targetCharacter then
		return
	end

	local targetHead = targetCharacter:FindFirstChild("Head")
	local teamColor = getTeamColor(targetPlayer)

	local highlight = create("Highlight", {
		Name = OBJECT_PREFIX .. "XrayHighlight",
		Adornee = targetCharacter,
		DepthMode = Enum.HighlightDepthMode.AlwaysOnTop,
		FillColor = teamColor,
		OutlineColor = teamColor:Lerp(Color3.new(1, 1, 1), 0.35),
		FillTransparency = 0.72,
		OutlineTransparency = 0.06
	}, targetCharacter)

	local billboard
	local label

	if targetHead then
		billboard = create("BillboardGui", {
			Name = OBJECT_PREFIX .. "XrayNameLabel",
			Adornee = targetHead,
			AlwaysOnTop = true,
			Size = UDim2.fromOffset(190, 42),
			StudsOffset = Vector3.new(0, 3.2, 0),
			MaxDistance = 900
		}, playerGui)

		label = create("TextLabel", {
			Size = UDim2.new(1, 0, 1, 0),
			BackgroundColor3 = COLORS.BackgroundDeep,
			BackgroundTransparency = 0.22,
			BorderSizePixel = 0,
			Text = targetPlayer.DisplayName,
			TextColor3 = teamColor:Lerp(Color3.new(1, 1, 1), 0.55),
			TextStrokeColor3 = COLORS.BackgroundDeep,
			TextStrokeTransparency = 0.25,
			TextSize = 13,
			Font = Enum.Font.GothamBold,
			TextTruncate = Enum.TextTruncate.AtEnd
		}, billboard)
		addCorner(label, 8)
		addStroke(label, teamColor, 1, 0.25)
	end

	Runtime.xrayObjects[targetPlayer] = {
		Highlight = highlight,
		Billboard = billboard,
		Label = label
	}
end

local function refreshXray()
	for targetPlayer in pairs(Runtime.xrayObjects) do
		clearXrayForPlayer(targetPlayer)
	end

	if not State.xray then
		return
	end

	for _, targetPlayer in ipairs(Players:GetPlayers()) do
		updateXrayForPlayer(targetPlayer)
	end
end

local function trackXrayPlayer(targetPlayer)
	if Runtime.xrayConnections[targetPlayer] then
		return
	end

	local connections = {}
	Runtime.xrayConnections[targetPlayer] = connections

	table.insert(connections, targetPlayer.CharacterAdded:Connect(function()
		task.wait(0.35)
		updateXrayForPlayer(targetPlayer)
	end))

	table.insert(connections, targetPlayer:GetPropertyChangedSignal("Team"):Connect(function()
		updateXrayForPlayer(targetPlayer)
	end))

	table.insert(connections, targetPlayer:GetPropertyChangedSignal("TeamColor"):Connect(function()
		updateXrayForPlayer(targetPlayer)
	end))
end

local function untrackXrayPlayer(targetPlayer)
	clearXrayForPlayer(targetPlayer)

	local connections = Runtime.xrayConnections[targetPlayer]
	if connections then
		disconnectAll(connections)
	end

	Runtime.xrayConnections[targetPlayer] = nil
end

local function setXray(enabled)
	State.xray = enabled
	refreshXray()
	setButtonVisual(UI.buttons.xray, State.xray, "Xray: ON", "Xray: OFF")
	setStatus("turned xray " .. (State.xray and "on" or "off"))
end

--// Item highlighter
local function lowerContainsAny(text, keywords)
	local lowerText = string.lower(text)

	for _, keyword in ipairs(keywords) do
		if string.find(lowerText, keyword, 1, true) then
			return true
		end
	end

	return false
end

local function isPlayerCharacter(instance)
	if not instance then
		return false
	end

	for _, targetPlayer in ipairs(Players:GetPlayers()) do
		if targetPlayer.Character and instance:IsDescendantOf(targetPlayer.Character) then
			return true
		end
	end

	return false
end

local function hasItemAttribute(instance)
	for _, attributeName in ipairs(ITEM_ATTRIBUTE_NAMES) do
		if instance:GetAttribute(attributeName) then
			return true
		end
	end

	return false
end

local function hasItemTag(instance)
	for _, tagName in ipairs(ITEM_COLLECTION_TAGS) do
		if CollectionService:HasTag(instance, tagName) then
			return true
		end
	end

	return false
end

local function nameLooksLikeItem(instance)
	local current = instance

	while current and current ~= Workspace do
		if lowerContainsAny(current.Name, ITEM_NAME_KEYWORDS) then
			return true
		end

		if current:IsA("Folder") or current:IsA("WorldModel") then
			break
		end

		current = current.Parent
	end

	return false
end

local function hasBlockedItemName(instance)
	local current = instance

	while current and current ~= Workspace do
		if lowerContainsAny(current.Name, ITEM_BLOCKED_NAME_KEYWORDS) then
			return true
		end

		if current:IsA("Folder") or current:IsA("WorldModel") then
			break
		end

		current = current.Parent
	end

	return false
end

local function getItemSizeInfo(instance)
	if instance:IsA("BasePart") then
		return instance.Size, instance.Size.X * instance.Size.Y * instance.Size.Z
	end

	local minPoint
	local maxPoint
	local totalVolume = 0

	for _, descendant in ipairs(instance:GetDescendants()) do
		if descendant:IsA("BasePart") then
			local size = descendant.Size
			local halfSize = size * 0.5
			local position = descendant.Position
			local partMin = position - halfSize
			local partMax = position + halfSize

			totalVolume = totalVolume + (size.X * size.Y * size.Z)

			if not minPoint then
				minPoint = partMin
				maxPoint = partMax
			else
				minPoint = Vector3.new(
					math.min(minPoint.X, partMin.X),
					math.min(minPoint.Y, partMin.Y),
					math.min(minPoint.Z, partMin.Z)
				)
				maxPoint = Vector3.new(
					math.max(maxPoint.X, partMax.X),
					math.max(maxPoint.Y, partMax.Y),
					math.max(maxPoint.Z, partMax.Z)
				)
			end
		end
	end

	if not minPoint or not maxPoint then
		return nil, 0
	end

	return maxPoint - minPoint, totalVolume
end

local function isSmallPickupSized(instance)
	local size, totalVolume = getItemSizeInfo(instance)
	if not size then
		return false
	end

	local longestSide = math.max(size.X, size.Y, size.Z)
	return longestSide <= ITEM_MAX_LONGEST_SIDE and totalVolume <= ITEM_MAX_TOTAL_VOLUME
end

local function containsPickupInteraction(instance)
	if instance:IsA("ClickDetector") or instance:IsA("ProximityPrompt") then
		return true
	end

	return instance:FindFirstChildWhichIsA("ClickDetector", true) ~= nil or instance:FindFirstChildWhichIsA("ProximityPrompt", true) ~= nil
end

local function canHighlightItemAdornee(adornee)
	if not adornee or not adornee:IsDescendantOf(Workspace) or isPlayerCharacter(adornee) then
		return false
	end

	local looksImportant = hasItemAttribute(adornee) or hasItemTag(adornee) or nameLooksLikeItem(adornee) or containsPickupInteraction(adornee)
	if not looksImportant then
		return false
	end

	if not isSmallPickupSized(adornee) then
		return false
	end

	if hasBlockedItemName(adornee) and not nameLooksLikeItem(adornee) then
		return false
	end

	return true
end

local function findItemAdornee(instance)
	if not instance or not instance:IsDescendantOf(Workspace) or isPlayerCharacter(instance) then
		return nil
	end

	local tool = instance:FindFirstAncestorWhichIsA("Tool")
	if tool and canHighlightItemAdornee(tool) then
		return tool
	end

	if instance:IsA("Tool") and canHighlightItemAdornee(instance) then
		return instance
	end

	local model = instance:FindFirstAncestorWhichIsA("Model")
	if model and model ~= Workspace and not model:FindFirstChildWhichIsA("Humanoid") and canHighlightItemAdornee(model) then
		return model
	end

	if instance:IsA("BasePart") and canHighlightItemAdornee(instance) then
		return instance
	end

	if containsPickupInteraction(instance) then
		local part = instance:FindFirstAncestorWhichIsA("BasePart")
		if part and canHighlightItemAdornee(part) then
			return part
		end
	end

	return nil
end

local function clearItemHighlights()
	for adornee, highlight in pairs(Runtime.itemHighlights) do
		if highlight and highlight.Parent then
			highlight:Destroy()
		end

		Runtime.itemHighlights[adornee] = nil
	end
end

local function addItemHighlight(adornee)
	if not adornee or Runtime.itemHighlights[adornee] then
		return
	end

	Runtime.itemHighlights[adornee] = create("Highlight", {
		Name = OBJECT_PREFIX .. "ItemHighlight",
		Adornee = adornee,
		DepthMode = Enum.HighlightDepthMode.AlwaysOnTop,
		FillColor = COLORS.ItemRed,
		OutlineColor = Color3.fromRGB(255, 225, 225),
		FillTransparency = 0.58,
		OutlineTransparency = 0
	}, adornee)
end

local function scanForItemHighlight(instance)
	if not State.highlightItems then
		return
	end

	local adornee = findItemAdornee(instance)
	if adornee then
		addItemHighlight(adornee)
	end
end

local function refreshItemHighlights()
	clearItemHighlights()

	if not State.highlightItems then
		return
	end

	for _, instance in ipairs(Workspace:GetDescendants()) do
		scanForItemHighlight(instance)
	end
end

local function setHighlightItems(enabled)
	State.highlightItems = enabled

	if enabled then
		refreshItemHighlights()
	else
		clearItemHighlights()
	end

	setButtonVisual(UI.buttons.highlightItems, State.highlightItems, "Highlight Items: ON", "Highlight Items: OFF")
	setStatus("turned item highlights " .. (State.highlightItems and "on" or "off"))
end

--// Character binding
local function bindCharacter(newCharacter)
	destroyFlyForces()

	State.character = newCharacter
	State.humanoid = newCharacter:WaitForChild("Humanoid")
	State.root = newCharacter:WaitForChild("HumanoidRootPart")

	Runtime.originalCollision = {}
	Runtime.originalJumpPower = State.humanoid.JumpPower
	Runtime.originalJumpHeight = State.humanoid.JumpHeight
	Runtime.originalUseJumpPower = State.humanoid.UseJumpPower

	if Runtime.descendantConnection then
		Runtime.descendantConnection:Disconnect()
	end

	for _, part in ipairs(getCharacterParts(newCharacter)) do
		rememberCollision(part)
	end

	Runtime.descendantConnection = newCharacter.DescendantAdded:Connect(function(item)
		if item:IsA("BasePart") then
			rememberCollision(item)

			if State.noclip then
				item.CanCollide = false
			end
		end
	end)

	State.humanoid.WalkSpeed = State.speed

	if State.forceJump then
		applyForceJump()
	end

	if State.fly then
		setFly(true)
	end

	if State.showPlayer then
		snapCameraToLocalPlayer()
	end
end

if localPlayer.Character then
	bindCharacter(localPlayer.Character)
end

localPlayer.CharacterAdded:Connect(bindCharacter)

--// UI building
UI.gui = create("ScreenGui", {
	Name = SCRIPT_TITLE,
	ResetOnSpawn = false,
	IgnoreGuiInset = true,
	ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
	DisplayOrder = 100,
	Enabled = true
}, playerGui)

UI.piggySpectateTeleportButton = create("TextButton", {
	Name = OBJECT_PREFIX .. "PiggySpectateTeleportButton",
	AnchorPoint = Vector2.new(1, 0.5),
	Size = UDim2.fromOffset(180, 74),
	Position = UDim2.new(1, -28, 0.5, 0),
	BackgroundColor3 = COLORS.AccentOn,
	Text = "Teleport",
	TextColor3 = COLORS.BackgroundDeep,
	TextSize = 24,
	Font = Enum.Font.GothamBlack,
	BorderSizePixel = 0,
	AutoButtonColor = false,
	Visible = false,
	ZIndex = 80
}, UI.gui)
addCorner(UI.piggySpectateTeleportButton, 14)
addStroke(UI.piggySpectateTeleportButton, COLORS.AccentSoft, 2, 0.1)

create("UIGradient", {
	Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, COLORS.AccentSoft),
		ColorSequenceKeypoint.new(1, COLORS.Accent)
	}),
	Rotation = 90
}, UI.piggySpectateTeleportButton)

local spectateTeleportScale = create("UIScale", {
	Scale = 1
}, UI.piggySpectateTeleportButton)

UI.piggySpectateTeleportButton.MouseEnter:Connect(function()
	tween(spectateTeleportScale, TWEENS.Fast, {
		Scale = 1.06
	})
end)

UI.piggySpectateTeleportButton.MouseLeave:Connect(function()
	tween(spectateTeleportScale, TWEENS.Smooth, {
		Scale = 1
	})
end)

UI.piggySpectateTeleportButton.Activated:Connect(function()
	teleportToPlayer(State.piggySpectateTarget)
end)

local function updatePiggySpectateTeleportButton()
	local camera = Workspace.CurrentCamera
	local targetPlayer

	if camera and not State.showPlayer then
		targetPlayer = getPlayerFromCameraSubject(camera.CameraSubject)
	end

	State.piggySpectateTarget = targetPlayer

	if not UI.piggySpectateTeleportButton then
		return
	end

	if targetPlayer then
		if not UI.piggySpectateTeleportButton.Visible then
			UI.piggySpectateTeleportButton.Visible = true
			spectateTeleportScale.Scale = 0.86
			tween(spectateTeleportScale, TWEENS.Pop, {
				Scale = 1
			})
		end
	else
		if UI.piggySpectateTeleportButton.Visible then
			tween(spectateTeleportScale, TWEENS.Fast, {
				Scale = 0.86
			})

			task.delay(0.11, function()
				if not State.piggySpectateTarget and UI.piggySpectateTeleportButton then
					UI.piggySpectateTeleportButton.Visible = false
					spectateTeleportScale.Scale = 1
				end
			end)
		end
	end
end

UI.shadow = create("Frame", {
	Name = OBJECT_PREFIX .. "Shadow",
	Size = UDim2.fromOffset(MENU_DEFAULT_WIDTH + 18, MENU_DEFAULT_HEIGHT + 18),
	Position = UDim2.fromOffset(43, 101),
	BackgroundColor3 = COLORS.Accent,
	BackgroundTransparency = 0.74,
	BorderSizePixel = 0,
	ZIndex = 0
}, UI.gui)
addCorner(UI.shadow, 18)

create("UIGradient", {
	Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, COLORS.AccentSoft),
		ColorSequenceKeypoint.new(1, COLORS.BackgroundDeep)
	}),
	Rotation = 90,
	Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 0.12),
		NumberSequenceKeypoint.new(1, 0.5)
	})
}, UI.shadow)

UI.menu = create("Frame", {
	Name = OBJECT_PREFIX .. "Window",
	Size = UDim2.fromOffset(MENU_DEFAULT_WIDTH, MENU_DEFAULT_HEIGHT),
	Position = UDim2.fromOffset(34, 92),
	BackgroundColor3 = COLORS.Background,
	BorderSizePixel = 0,
	ClipsDescendants = true,
	Active = true,
	ZIndex = 2
}, UI.gui)
addCorner(UI.menu, 14)
UI.menuStroke = addStroke(UI.menu, COLORS.Accent, 2, 0.12)

UI.menuScale = create("UIScale", {
	Scale = 0.96
}, UI.menu)

create("UIGradient", {
	Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, COLORS.Panel),
		ColorSequenceKeypoint.new(1, COLORS.BackgroundDeep)
	}),
	Rotation = 90
}, UI.menu)

local function syncShadow(animated)
	if not UI.menu or not UI.shadow then
		return
	end

	local targetSize = UDim2.fromOffset(UI.menu.AbsoluteSize.X + 18, UI.menu.AbsoluteSize.Y + 18)
	local targetPosition = UDim2.new(
		UI.menu.Position.X.Scale,
		UI.menu.Position.X.Offset + 9,
		UI.menu.Position.Y.Scale,
		UI.menu.Position.Y.Offset + 9
	)

	if animated then
		tween(UI.shadow, TWEENS.Window, {
			Size = targetSize,
			Position = targetPosition
		})
	else
		UI.shadow.Size = targetSize
		UI.shadow.Position = targetPosition
	end
end

UI.topBar = create("Frame", {
	Name = OBJECT_PREFIX .. "TopBar",
	Size = UDim2.new(1, 0, 0, 52),
	BackgroundColor3 = COLORS.Panel,
	BorderSizePixel = 0,
	Active = true,
	ZIndex = 4
}, UI.menu)
addCorner(UI.topBar, 14)

UI.titleLabel = create("TextLabel", {
	Name = OBJECT_PREFIX .. "Title",
	Size = UDim2.new(1, -74, 1, 0),
	Position = UDim2.fromOffset(16, 0),
	BackgroundTransparency = 1,
	Text = SCRIPT_TITLE,
	TextColor3 = COLORS.Text,
	TextSize = 14,
	Font = Enum.Font.GothamBold,
	TextXAlignment = Enum.TextXAlignment.Left,
	TextTruncate = Enum.TextTruncate.AtEnd,
	ZIndex = 5
}, UI.topBar)

UI.titleGlow = create("Frame", {
	Name = OBJECT_PREFIX .. "TitleGlow",
	Size = UDim2.new(1, -24, 0, 2),
	Position = UDim2.new(0, 12, 1, -3),
	BackgroundColor3 = COLORS.Accent,
	BackgroundTransparency = 0.15,
	BorderSizePixel = 0,
	ZIndex = 5
}, UI.topBar)
addCorner(UI.titleGlow, 999)

create("UIGradient", {
	Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, COLORS.AccentDark),
		ColorSequenceKeypoint.new(0.5, COLORS.AccentSoft),
		ColorSequenceKeypoint.new(1, COLORS.AccentDark)
	}),
	Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 0.65),
		NumberSequenceKeypoint.new(0.5, 0),
		NumberSequenceKeypoint.new(1, 0.65)
	})
}, UI.titleGlow)

UI.minimizeButton = create("TextButton", {
	Name = OBJECT_PREFIX .. "MinimizeButton",
	Size = UDim2.fromOffset(36, 30),
	Position = UDim2.new(1, -54, 0, 11),
	BackgroundColor3 = COLORS.Warning,
	Text = "-",
	TextColor3 = COLORS.Text,
	TextSize = 20,
	Font = Enum.Font.GothamBold,
	BorderSizePixel = 0,
	AutoButtonColor = false,
	ZIndex = 6
}, UI.topBar)
addCorner(UI.minimizeButton, 8)

local minimizeScale = create("UIScale", {
	Scale = 1
}, UI.minimizeButton)

UI.content = create("ScrollingFrame", {
	Name = OBJECT_PREFIX .. "Content",
	Size = UDim2.new(1, -28, 1, -68),
	Position = UDim2.fromOffset(14, 60),
	BackgroundTransparency = 1,
	BorderSizePixel = 0,
	CanvasSize = UDim2.fromOffset(0, 0),
	AutomaticCanvasSize = Enum.AutomaticSize.Y,
	ScrollBarThickness = 4,
	ScrollBarImageColor3 = COLORS.Accent,
	ScrollBarImageTransparency = 0.2,
	ScrollingDirection = Enum.ScrollingDirection.Y,
	ClipsDescendants = true,
	ZIndex = 3
}, UI.menu)

create("UIPadding", {
	PaddingTop = UDim.new(0, 2),
	PaddingBottom = UDim.new(0, 14),
	PaddingLeft = UDim.new(0, 1),
	PaddingRight = UDim.new(0, 6)
}, UI.content)

local contentLayout = create("UIListLayout", {
	Padding = UDim.new(0, 10),
	SortOrder = Enum.SortOrder.LayoutOrder
}, UI.content)

contentLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
	UI.content.CanvasSize = UDim2.fromOffset(0, contentLayout.AbsoluteContentSize.Y + 22)
end)

local function makeSection(title)
	local section = create("Frame", {
		Name = OBJECT_PREFIX .. title:gsub("%W", ""),
		Size = UDim2.new(1, 0, 0, 0),
		AutomaticSize = Enum.AutomaticSize.Y,
		BackgroundColor3 = COLORS.PanelDeep,
		BorderSizePixel = 0,
		ClipsDescendants = true,
		ZIndex = 4
	}, UI.content)
	addCorner(section, 10)
	addStroke(section, COLORS.AccentSoft, 1, 0.86)

	create("UIPadding", {
		PaddingTop = UDim.new(0, 10),
		PaddingBottom = UDim.new(0, 10),
		PaddingLeft = UDim.new(0, 10),
		PaddingRight = UDim.new(0, 10)
	}, section)

	create("UIListLayout", {
		Padding = UDim.new(0, 8),
		SortOrder = Enum.SortOrder.LayoutOrder
	}, section)

	create("TextLabel", {
		Size = UDim2.new(1, 0, 0, 22),
		BackgroundTransparency = 1,
		Text = title,
		TextColor3 = COLORS.TextMuted,
		TextSize = 14,
		Font = Enum.Font.GothamBold,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextTruncate = Enum.TextTruncate.AtEnd,
		ZIndex = 5
	}, section)

	return section
end

local function makeButton(parent, text, color, callback)
	local button = create("TextButton", {
		Name = OBJECT_PREFIX .. text:gsub("%W", "") .. "Button",
		Size = UDim2.new(1, 0, 0, 38),
		BackgroundColor3 = color,
		Text = text,
		TextColor3 = COLORS.Text,
		TextSize = 14,
		Font = Enum.Font.GothamBold,
		BorderSizePixel = 0,
		AutoButtonColor = false,
		TextTruncate = Enum.TextTruncate.AtEnd,
		ZIndex = 5
	}, parent)
	addCorner(button, 9)

	local buttonStroke = addStroke(button, COLORS.AccentSoft, 1, 0.82)
	local buttonScale = create("UIScale", {
		Scale = 1
	}, button)

	UI.buttonBaseColors[button] = color

	button.MouseEnter:Connect(function()
		local baseColor = UI.buttonBaseColors[button] or color
		tween(button, TWEENS.Fast, {
			BackgroundColor3 = baseColor:Lerp(COLORS.AccentSoft, 0.16)
		})
		tween(buttonStroke, TWEENS.Fast, {
			Transparency = 0.42
		})
		tween(buttonScale, TWEENS.Fast, {
			Scale = 1.012
		})
	end)

	button.MouseLeave:Connect(function()
		local baseColor = UI.buttonBaseColors[button] or color
		tween(button, TWEENS.Smooth, {
			BackgroundColor3 = baseColor
		})
		tween(buttonStroke, TWEENS.Smooth, {
			Transparency = 0.82
		})
		tween(buttonScale, TWEENS.Smooth, {
			Scale = 1
		})
	end)

	button.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			tween(buttonScale, TWEENS.Fast, {
				Scale = 0.982
			})
			tween(buttonStroke, TWEENS.Fast, {
				Transparency = 0.18
			})
		end
	end)

	button.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			tween(buttonScale, TWEENS.Pop, {
				Scale = 1
			})
		end
	end)

	button.Activated:Connect(callback)
	return button
end

local function makeSlider(parent, name, minValue, maxValue, defaultValue, displayFunction, callback)
	local holder = create("Frame", {
		Name = OBJECT_PREFIX .. name:gsub("%W", "") .. "Slider",
		Size = UDim2.new(1, 0, 0, 66),
		BackgroundColor3 = COLORS.BackgroundDeep,
		BorderSizePixel = 0,
		ClipsDescendants = false,
		ZIndex = 5
	}, parent)
	addCorner(holder, 10)
	local holderStroke = addStroke(holder, COLORS.AccentSoft, 1, 0.86)

	local label = create("TextLabel", {
		Size = UDim2.new(1, -20, 0, 24),
		Position = UDim2.fromOffset(10, 7),
		BackgroundTransparency = 1,
		TextColor3 = COLORS.TextMuted,
		TextSize = 14,
		Font = Enum.Font.GothamMedium,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextTruncate = Enum.TextTruncate.AtEnd,
		ZIndex = 6
	}, holder)

	local track = create("TextButton", {
		Size = UDim2.new(1, -22, 0, 12),
		Position = UDim2.fromOffset(11, 42),
		BackgroundColor3 = COLORS.Track,
		Text = "",
		BorderSizePixel = 0,
		AutoButtonColor = false,
		ZIndex = 6
	}, holder)
	addCorner(track, 999)

	local fill = create("Frame", {
		Size = UDim2.fromScale(0, 1),
		BackgroundColor3 = COLORS.Accent,
		BorderSizePixel = 0,
		ZIndex = 7
	}, track)
	addCorner(fill, 999)

	local knob = create("TextButton", {
		Size = UDim2.fromOffset(24, 24),
		Position = UDim2.fromOffset(-12, -6),
		BackgroundColor3 = COLORS.AccentSoft,
		Text = "",
		BorderSizePixel = 0,
		AutoButtonColor = false,
		ZIndex = 8
	}, track)
	addCorner(knob, 999)

	local knobStroke = addStroke(knob, COLORS.Accent, 2, 0)
	local knobScale = create("UIScale", {
		Scale = 1
	}, knob)

	local dragging = false

	local function setPercent(percent)
		percent = math.clamp(percent, 0, 1)
		local rawValue = minValue + ((maxValue - minValue) * percent)
		local value = math.floor(rawValue + 0.5)

		tween(fill, TWEENS.Fast, {
			Size = UDim2.fromScale(percent, 1)
		})
		tween(knob, TWEENS.Fast, {
			Position = UDim2.new(percent, -12, 0, -6)
		})

		label.Text = name .. ": " .. displayFunction(value, percent)
		callback(value, percent)
	end

	local function updateFromInput(input)
		local percent = (input.Position.X - track.AbsolutePosition.X) / track.AbsoluteSize.X
		setPercent(percent)
	end

	local function beginDrag(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			dragging = true
			tween(holderStroke, TWEENS.Fast, {
				Transparency = 0.42
			})
			tween(knobScale, TWEENS.Fast, {
				Scale = 1.16
			})
			tween(knobStroke, TWEENS.Fast, {
				Transparency = 0
			})
			updateFromInput(input)
		end
	end

	track.InputBegan:Connect(beginDrag)
	knob.InputBegan:Connect(beginDrag)

	holder.MouseEnter:Connect(function()
		tween(holder, TWEENS.Smooth, {
			BackgroundColor3 = COLORS.Panel
		})
	end)

	holder.MouseLeave:Connect(function()
		if not dragging then
			tween(holder, TWEENS.Smooth, {
				BackgroundColor3 = COLORS.BackgroundDeep
			})
			tween(holderStroke, TWEENS.Smooth, {
				Transparency = 0.86
			})
		end
	end)

	UserInputService.InputChanged:Connect(function(input)
		if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
			updateFromInput(input)
		end
	end)

	UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			dragging = false
			tween(holder, TWEENS.Smooth, {
				BackgroundColor3 = COLORS.BackgroundDeep
			})
			tween(holderStroke, TWEENS.Smooth, {
				Transparency = 0.86
			})
			tween(knobScale, TWEENS.Pop, {
				Scale = 1
			})
		end
	end)

	setPercent((defaultValue - minValue) / (maxValue - minValue))
	return holder
end

--// Header section
local headerSection = makeSection("Status")

UI.statusLabel = create("TextLabel", {
	Name = OBJECT_PREFIX .. "StatusLabel",
	Size = UDim2.new(1, 0, 0, 72),
	BackgroundTransparency = 1,
	Text = "No actions yet.",
	TextColor3 = COLORS.Text,
	TextSize = 12,
	Font = Enum.Font.GothamMedium,
	TextXAlignment = Enum.TextXAlignment.Left,
	TextYAlignment = Enum.TextYAlignment.Top,
	TextWrapped = true,
	ZIndex = 5
}, headerSection)

--// Movement section
local movementSection = makeSection("Movement")

makeSlider(movementSection, "Speed", 16, 150, State.speed, function(value)
	return tostring(value)
end, function(value)
	State.speed = value

	if State.humanoid then
		State.humanoid.WalkSpeed = State.speed
	end
end)

UI.buttons.noclip = makeButton(movementSection, "Noclip: OFF", COLORS.AccentDark, function()
	setNoclip(not State.noclip)
end)

UI.buttons.lowGravity = makeButton(movementSection, "Low Gravity: OFF", COLORS.AccentDark, function()
	setLowGravity(not State.lowGravity)
end)

UI.buttons.forceJump = makeButton(movementSection, "Force Jump: OFF", COLORS.AccentDark, function()
	setForceJump(not State.forceJump)
end)

UI.buttons.fly = makeButton(movementSection, "Fly: OFF", COLORS.AccentDark, function()
	setFly(not State.fly)
end)

makeSlider(movementSection, "Fly Speed", 20, 180, State.flySpeed, function(value)
	return tostring(value)
end, function(value)
	State.flySpeed = value
end)

--// Camera section
local cameraSection = makeSection("Camera")

UI.buttons.showPlayer = makeButton(cameraSection, "ShowPlayer: OFF", COLORS.AccentDark, function()
	setShowPlayer(not State.showPlayer)
end)

--// Vision section
local visionSection = makeSection("Vision And Items")

UI.buttons.xray = makeButton(visionSection, "Xray: OFF", COLORS.AccentDark, function()
	setXray(not State.xray)
end)

UI.buttons.highlightItems = makeButton(visionSection, "Highlight Items: OFF", COLORS.AccentDark, function()
	setHighlightItems(not State.highlightItems)
end)

--// Player list section
local playerSection = makeSection("Players")

local refreshPlayerButton = makeButton(playerSection, "Refresh Player List", COLORS.Track, function()
	if UI.refreshPlayerList then
		UI.refreshPlayerList()
	end
end)
UI.buttonBaseColors[refreshPlayerButton] = COLORS.Track

UI.playerList = create("ScrollingFrame", {
	Name = OBJECT_PREFIX .. "PlayerTeleportList",
	Size = UDim2.new(1, 0, 0, 178),
	BackgroundColor3 = COLORS.BackgroundDeep,
	BorderSizePixel = 0,
	CanvasSize = UDim2.fromOffset(0, 0),
	AutomaticCanvasSize = Enum.AutomaticSize.Y,
	ScrollBarThickness = 4,
	ScrollBarImageColor3 = COLORS.Accent,
	ScrollBarImageTransparency = 0.2,
	ScrollingDirection = Enum.ScrollingDirection.Y,
	ClipsDescendants = true,
	ZIndex = 5
}, playerSection)
addCorner(UI.playerList, 8)

create("UIPadding", {
	PaddingTop = UDim.new(0, 7),
	PaddingBottom = UDim.new(0, 7),
	PaddingLeft = UDim.new(0, 7),
	PaddingRight = UDim.new(0, 7)
}, UI.playerList)

local playerListLayout = create("UIListLayout", {
	Padding = UDim.new(0, 6),
	SortOrder = Enum.SortOrder.LayoutOrder
}, UI.playerList)

playerListLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
	UI.playerList.CanvasSize = UDim2.fromOffset(0, playerListLayout.AbsoluteContentSize.Y + 16)
end)

local function clearPlayerList()
	for _, child in ipairs(UI.playerList:GetChildren()) do
		if child:IsA("TextButton") or child:IsA("TextLabel") or child:IsA("Frame") then
			child:Destroy()
		end
	end
end

local function makeEmptyPlayerRow(text)
	local row = create("TextLabel", {
		Name = OBJECT_PREFIX .. "EmptyPlayerRow",
		Size = UDim2.new(1, -4, 0, 34),
		BackgroundColor3 = COLORS.Panel,
		Text = text,
		TextColor3 = COLORS.TextMuted,
		TextSize = 13,
		Font = Enum.Font.GothamMedium,
		BorderSizePixel = 0,
		TextTruncate = Enum.TextTruncate.AtEnd,
		ZIndex = 6
	}, UI.playerList)
	addCorner(row, 8)
end

local function makePlayerRow(targetPlayer)
	local row = create("TextButton", {
		Name = OBJECT_PREFIX .. "TeleportRow_" .. targetPlayer.Name,
		Size = UDim2.new(1, -4, 0, 38),
		BackgroundColor3 = COLORS.Panel,
		Text = getPlayerLabel(targetPlayer) .. getPlayerDistanceText(targetPlayer),
		TextColor3 = COLORS.Text,
		TextSize = 13,
		Font = Enum.Font.GothamMedium,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextTruncate = Enum.TextTruncate.AtEnd,
		BorderSizePixel = 0,
		AutoButtonColor = false,
		ZIndex = 6
	}, UI.playerList)
	addCorner(row, 8)
	local rowStroke = addStroke(row, COLORS.AccentSoft, 1, 0.88)

	create("UIPadding", {
		PaddingLeft = UDim.new(0, 8),
		PaddingRight = UDim.new(0, 6)
	}, row)

	row.MouseEnter:Connect(function()
		tween(row, TWEENS.Fast, {
			BackgroundColor3 = COLORS.AccentDark
		})
		tween(rowStroke, TWEENS.Fast, {
			Transparency = 0.42
		})
	end)

	row.MouseLeave:Connect(function()
		tween(row, TWEENS.Smooth, {
			BackgroundColor3 = COLORS.Panel
		})
		tween(rowStroke, TWEENS.Smooth, {
			Transparency = 0.88
		})
	end)

	row.Activated:Connect(function()
		teleportToPlayer(targetPlayer)
		if UI.refreshPlayerList then
			UI.refreshPlayerList()
		end
	end)
end

UI.refreshPlayerList = function()
	clearPlayerList()

	local playerList = {}
	for _, targetPlayer in ipairs(Players:GetPlayers()) do
		if targetPlayer ~= localPlayer then
			table.insert(playerList, targetPlayer)
		end
	end

	table.sort(playerList, function(firstPlayer, secondPlayer)
		return string.lower(firstPlayer.DisplayName) < string.lower(secondPlayer.DisplayName)
	end)

	if #playerList == 0 then
		makeEmptyPlayerRow("No other players found")
	else
		for _, targetPlayer in ipairs(playerList) do
			makePlayerRow(targetPlayer)
		end
	end

	refreshHeader()
end

--// Window movement and resize
local expandedMenuSize = UDim2.fromOffset(MENU_DEFAULT_WIDTH, MENU_DEFAULT_HEIGHT)
local draggingMenu = false
local dragStart
local menuStart
local resizingMenu = false
local resizeStart
local resizeStartSize
local resizeStartPosition
local resizeDirectionX = 0
local resizeDirectionY = 0

local function makeResizeHandle(name, anchorPoint, position, directionX, directionY)
	local handle = create("TextButton", {
		Name = name,
		AnchorPoint = anchorPoint,
		Position = position,
		Size = UDim2.fromOffset(28, 28),
		BackgroundTransparency = 1,
		Text = "",
		BorderSizePixel = 0,
		AutoButtonColor = false,
		ZIndex = 20
	}, UI.menu)

	handle.InputBegan:Connect(function(input)
		if State.minimized then
			return
		end

		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			resizingMenu = true
			resizeStart = input.Position
			resizeStartSize = UI.menu.AbsoluteSize
			resizeStartPosition = UI.menu.Position
			resizeDirectionX = directionX
			resizeDirectionY = directionY
		end
	end)
end

makeResizeHandle("TopLeftResize", Vector2.new(0, 0), UDim2.fromOffset(0, 0), -1, -1)
makeResizeHandle("TopRightResize", Vector2.new(1, 0), UDim2.new(1, 0, 0, 0), 1, -1)
makeResizeHandle("BottomLeftResize", Vector2.new(0, 1), UDim2.new(0, 0, 1, 0), -1, 1)
makeResizeHandle("BottomRightResize", Vector2.new(1, 1), UDim2.new(1, 0, 1, 0), 1, 1)

UI.topBar.InputBegan:Connect(function(input)
	if resizingMenu then
		return
	end

	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		draggingMenu = true
		dragStart = input.Position
		menuStart = UI.menu.Position
	end
end)

UserInputService.InputChanged:Connect(function(input)
	if resizingMenu and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
		local delta = input.Position - resizeStart
		local startWidth = resizeStartSize.X
		local startHeight = resizeStartSize.Y

		local newWidth = math.clamp(startWidth + (delta.X * resizeDirectionX), MENU_MIN_WIDTH, MENU_MAX_WIDTH)
		local newHeight = math.clamp(startHeight + (delta.Y * resizeDirectionY), MENU_MIN_HEIGHT, MENU_MAX_HEIGHT)

		local positionXOffset = resizeStartPosition.X.Offset
		local positionYOffset = resizeStartPosition.Y.Offset

		if resizeDirectionX < 0 then
			positionXOffset = resizeStartPosition.X.Offset + (startWidth - newWidth)
		end

		if resizeDirectionY < 0 then
			positionYOffset = resizeStartPosition.Y.Offset + (startHeight - newHeight)
		end

		UI.menu.Size = UDim2.fromOffset(newWidth, newHeight)
		expandedMenuSize = UI.menu.Size
		UI.menu.Position = UDim2.new(
			resizeStartPosition.X.Scale,
			positionXOffset,
			resizeStartPosition.Y.Scale,
			positionYOffset
		)
		syncShadow(false)
		return
	end

	if draggingMenu and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
		local delta = input.Position - dragStart
		UI.menu.Position = UDim2.new(
			menuStart.X.Scale,
			menuStart.X.Offset + delta.X,
			menuStart.Y.Scale,
			menuStart.Y.Offset + delta.Y
		)
		syncShadow(false)
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		draggingMenu = false
		resizingMenu = false
	end
end)

--// UI animations and controls
UI.topBar.MouseEnter:Connect(function()
	tween(UI.menuStroke, TWEENS.Smooth, {
		Transparency = 0
	})
end)

UI.topBar.MouseLeave:Connect(function()
	tween(UI.menuStroke, TWEENS.Smooth, {
		Transparency = 0.02
	})
end)

UI.minimizeButton.MouseEnter:Connect(function()
	tween(minimizeScale, TWEENS.Fast, {
		Scale = 1.08
	})
	tween(UI.minimizeButton, TWEENS.Fast, {
		BackgroundColor3 = COLORS.AccentOn
	})
end)

UI.minimizeButton.MouseLeave:Connect(function()
	tween(minimizeScale, TWEENS.Smooth, {
		Scale = 1
	})
	tween(UI.minimizeButton, TWEENS.Smooth, {
		BackgroundColor3 = State.minimized and COLORS.AccentDark or COLORS.Warning
	})
end)

UI.minimizeButton.Activated:Connect(function()
	State.minimized = not State.minimized

	if State.minimized then
		expandedMenuSize = UI.menu.Size
		UI.content.Visible = false
		tween(UI.menu, TWEENS.Window, {
			Size = UDim2.fromOffset(UI.menu.AbsoluteSize.X, 52)
		})
		tween(UI.shadow, TWEENS.Window, {
			Size = UDim2.fromOffset(UI.menu.AbsoluteSize.X + 18, 70)
		})
		UI.minimizeButton.Text = "+"
		tween(UI.minimizeButton, TWEENS.Smooth, {
			BackgroundColor3 = COLORS.AccentDark
		})
	else
		UI.content.Visible = true
		tween(UI.menu, TWEENS.Window, {
			Size = expandedMenuSize
		})
		tween(UI.shadow, TWEENS.Window, {
			Size = UDim2.fromOffset(expandedMenuSize.X.Offset + 18, expandedMenuSize.Y.Offset + 18)
		})
		UI.minimizeButton.Text = "-"
		tween(UI.minimizeButton, TWEENS.Smooth, {
			BackgroundColor3 = COLORS.Warning
		})
	end
end)

UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed or input.KeyCode ~= UI_TOGGLE_KEY then
		return
	end

	setOwnMenuVisible(not State.menuVisible)
end)

UserInputService.JumpRequest:Connect(function()
	if not State.forceJump or not State.humanoid then
		return
	end

	applyForceJump()
	State.humanoid.Jump = true
	State.humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end)

local titleHue = 0
RunService.RenderStepped:Connect(function(deltaTime)
	titleHue = (titleHue + (deltaTime * 2.8)) % 1
	UI.titleLabel.TextColor3 = Color3.fromHSV(titleHue, 0.8, 1)
	UI.titleGlow.BackgroundColor3 = Color3.fromHSV((titleHue + 0.12) % 1, 0.75, 1)
end)

TweenService:Create(UI.titleGlow, TweenInfo.new(1.6, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, -1, true), {
	BackgroundTransparency = 0.48
}):Play()

task.defer(function()
	tween(UI.menuScale, TWEENS.Pop, {
		Scale = 1
	})
	tween(UI.menuStroke, TWEENS.Window, {
		Transparency = 0.02
	})
end)

--// Live game hooks
UI.refreshPlayerList()

for _, targetPlayer in ipairs(Players:GetPlayers()) do
	trackXrayPlayer(targetPlayer)
end

Players.PlayerAdded:Connect(function(targetPlayer)
	trackXrayPlayer(targetPlayer)
	updateXrayForPlayer(targetPlayer)

	if UI.refreshPlayerList then
		UI.refreshPlayerList()
	end
end)

Players.PlayerRemoving:Connect(function(targetPlayer)
	untrackXrayPlayer(targetPlayer)

	if UI.refreshPlayerList then
		UI.refreshPlayerList()
	end
end)

table.insert(Runtime.itemConnections, Workspace.DescendantAdded:Connect(function(instance)
	if State.highlightItems then
		task.defer(function()
			scanForItemHighlight(instance)
		end)
	end
end))

table.insert(Runtime.itemConnections, Workspace.DescendantRemoving:Connect(function(instance)
	local adornee = findItemAdornee(instance) or instance
	local highlight = Runtime.itemHighlights[adornee]

	if highlight then
		highlight:Destroy()
		Runtime.itemHighlights[adornee] = nil
	end
end))

playerGui.ChildAdded:Connect(function(child)
	if State.hideUi and child:IsA("ScreenGui") then
		task.defer(protectHiddenUi)
	end
end)

RunService.Stepped:Connect(function()
	if State.noclip and State.character then
		for _, part in ipairs(getCharacterParts(State.character)) do
			rememberCollision(part)
			part.CanCollide = false
		end
	end
end)

RunService.Heartbeat:Connect(function()
	if State.humanoid and State.humanoid.Parent and State.humanoid.WalkSpeed ~= State.speed then
		State.humanoid.WalkSpeed = State.speed
	end

	if State.lowGravity and Workspace.Gravity ~= LOW_GRAVITY then
		Workspace.Gravity = LOW_GRAVITY
	end

	if State.forceJump then
		applyForceJump()
	end

	if State.fly then
		updateFlyMovement()
	end

	if State.hideUi then
		protectHiddenUi()
	end

	updatePiggySpectateTeleportButton()
end)

RunService:BindToRenderStep(LOCAL_CAMERA_LOCK, Enum.RenderPriority.Camera.Value - 1, function()
	local camera = Workspace.CurrentCamera
	if not camera then
		return
	end

	if State.showPlayer and State.humanoid then
		if localPlayer.CameraMode ~= Enum.CameraMode.Classic then
			localPlayer.CameraMode = Enum.CameraMode.Classic
		end

		if camera.CameraType ~= Enum.CameraType.Custom then
			camera.CameraType = Enum.CameraType.Custom
		end

		if camera.CameraSubject ~= State.humanoid then
			camera.CameraSubject = State.humanoid
		end
	end
end)

refreshHeader()

Features & Information

It has speed, noclip, low gravity, force jump, fly, teleport to player, player xray, and item highlights for things like keys. The menu can move, resize, minimize, and has animated buttons and sliders.

Community Comments (2)

alexhack9090alexhack9090Jun 18, 2026

this script does not even work when I try to load it doesn't work :(

NPC4456LOLNPC4456LOLAug 13, 2026

I haven't tried it so I'll try it now