Open source OBJECT INSPECTOR
Key RequiredUniversal

Open source OBJECT INSPECTOR

Universal ScriptTr0ngXTr0ngX 604 views 18 executesUpdated Dec 11, 2025
5.0/ 5(1 votes)
10100% Positive
Lua Script•2432 lines (94350 chars)
-- ═══════════════════════════════════════════════════════════
-- 📚 LOAD RAYFIELD LIBRARY
-- ═══════════════════════════════════════════════════════════
local Rayfield = loadstring(game:HttpGet('https://sirius.menu/rayfield'))()

-- ═══════════════════════════════════════════════════════════
-- 🔧 SERVICES
-- ═══════════════════════════════════════════════════════════
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local Workspace = game:GetService("Workspace")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Lighting = game:GetService("Lighting")
local SoundService = game:GetService("SoundService")
local CollectionService = game:GetService("CollectionService")
local HttpService = game:GetService("HttpService")

-- ═══════════════════════════════════════════════════════════
-- 👤 LOCAL PLAYER
-- ═══════════════════════════════════════════════════════════
local Player = Players.LocalPlayer
local Mouse = Player:GetMouse()
local Camera = Workspace.CurrentCamera

-- ═══════════════════════════════════════════════════════════
-- 📊 GLOBAL VARIABLES
-- ═══════════════════════════════════════════════════════════
local SelectedObject = nil
local IsInspecting = false
local AutoUpdate = true
local UpdateInterval = 0.1
local InspectorData = {}
local CopiedData = ""
local HighlightBox = nil
local SelectionEnabled = false
local LastUpdate = 0

-- ═══════════════════════════════════════════════════════════
-- ⚙️ SETTINGS
-- ═══════════════════════════════════════════════════════════
local Settings = {
    SelectHotkey = Enum.KeyCode.Q,
    InspectHotkey = Enum.KeyCode.E,
    ClearHotkey = Enum.KeyCode.X,
    AutoRefresh = true,
    RefreshRate = 0.3,
    ShowHighlight = true,
    HighlightColor = Color3.fromRGB(0, 255, 128),
    OutlineColor = Color3.fromRGB(255, 255, 255),
    DetailLevel = "Maximum",
    ShowDistanceRealtime = true,
    HighlightFillTransparency = 0.7
}

-- ═══════════════════════════════════════════════════════════
-- 🛠️ UTILITY FUNCTIONS - FORMAT
-- ═══════════════════════════════════════════════════════════

local function SafeCall(func, ...)
    local success, result = pcall(func, ...)
    if success then return result else return "Error" end
end

local function FormatNumber(num, decimals)
    decimals = decimals or 4
    if type(num) ~= "number" then return tostring(num) end
    if num == math.huge then return "Infinity" end
    if num ~= num then return "NaN" end
    return string.format("%." .. decimals .. "f", num)
end

local function FormatVector3(vec, decimals)
    decimals = decimals or 3
    if typeof(vec) ~= "Vector3" then return "N/A" end
    local fmt = "%." .. decimals .. "f"
    return string.format("X: " .. fmt .. " | Y: " .. fmt .. " | Z: " .. fmt, vec.X, vec.Y, vec.Z)
end

local function FormatVector3Short(vec)
    if typeof(vec) ~= "Vector3" then return "N/A" end
    return string.format("(%.2f, %.2f, %.2f)", vec.X, vec.Y, vec.Z)
end

local function FormatVector3Code(vec)
    if typeof(vec) ~= "Vector3" then return "N/A" end
    return string.format("Vector3.new(%.4f, %.4f, %.4f)", vec.X, vec.Y, vec.Z)
end

local function FormatVector2(vec)
    if typeof(vec) ~= "Vector2" then return "N/A" end
    return string.format("X: %.3f | Y: %.3f", vec.X, vec.Y)
end

local function FormatCFrame(cf)
    if typeof(cf) ~= "CFrame" then return "N/A" end
    local x, y, z = cf:ToEulerAnglesXYZ()
    return string.format("Pos: (%.2f, %.2f, %.2f) | Rot: (%.1f°, %.1f°, %.1f°)", 
        cf.Position.X, cf.Position.Y, cf.Position.Z,
        math.deg(x), math.deg(y), math.deg(z))
end

local function FormatCFrameDetailed(cf)
    if typeof(cf) ~= "CFrame" then return "N/A" end
    local rx, ry, rz = cf:ToEulerAnglesXYZ()
    local ox, oy, oz = cf:ToOrientation()
    return {
        Position = FormatVector3(cf.Position),
        LookVector = FormatVector3(cf.LookVector),
        RightVector = FormatVector3(cf.RightVector),
        UpVector = FormatVector3(cf.UpVector),
        EulerAngles = string.format("X: %.2f° | Y: %.2f° | Z: %.2f°", math.deg(rx), math.deg(ry), math.deg(rz)),
        Orientation = string.format("X: %.2f° | Y: %.2f° | Z: %.2f°", math.deg(ox), math.deg(oy), math.deg(oz))
    }
end

local function FormatColor3(color)
    if typeof(color) ~= "Color3" then return "N/A" end
    local r, g, b = math.floor(color.R * 255), math.floor(color.G * 255), math.floor(color.B * 255)
    local h, s, v = Color3.toHSV(color)
    return string.format("RGB(%d, %d, %d) | Hex: #%02X%02X%02X | HSV(%.0f°, %.0f%%, %.0f%%)", 
        r, g, b, r, g, b, h * 360, s * 100, v * 100)
end

local function FormatBrickColor(bc)
    if typeof(bc) ~= "BrickColor" then return "N/A" end
    return string.format("%s (Number: %d)", bc.Name, bc.Number)
end

local function FormatUDim2(udim)
    if typeof(udim) ~= "UDim2" then return "N/A" end
    return string.format("X: {%.3f, %d} | Y: {%.3f, %d}", 
        udim.X.Scale, udim.X.Offset, udim.Y.Scale, udim.Y.Offset)
end

local function FormatBoolean(bool)
    if type(bool) == "boolean" then
        return bool and "✅ TRUE" or "❌ FALSE"
    end
    return tostring(bool)
end

local function FormatTime(seconds)
    if type(seconds) ~= "number" then return "N/A" end
    local hours = math.floor(seconds / 3600)
    local mins = math.floor((seconds % 3600) / 60)
    local secs = math.floor(seconds % 60)
    if hours > 0 then
        return string.format("%02d:%02d:%02d", hours, mins, secs)
    else
        return string.format("%02d:%02d", mins, secs)
    end
end

local function FormatBytes(bytes)
    if type(bytes) ~= "number" then return "N/A" end
    if bytes < 1024 then return string.format("%d B", bytes)
    elseif bytes < 1024 * 1024 then return string.format("%.2f KB", bytes / 1024)
    elseif bytes < 1024 * 1024 * 1024 then return string.format("%.2f MB", bytes / (1024 * 1024))
    else return string.format("%.2f GB", bytes / (1024 * 1024 * 1024)) end
end

-- ═══════════════════════════════════════════════════════════
-- 🛠️ UTILITY FUNCTIONS - OBJECT ANALYSIS
-- ═══════════════════════════════════════════════════════════

local function GetObjectType(obj)
    if not obj then return "None" end
    
    -- Check for Player
    local player = Players:GetPlayerFromCharacter(obj)
    if player then return "👤 Player Character" end
    
    -- Detailed type detection
    if obj:IsA("Player") then return "👤 Player"
    elseif obj:IsA("Model") then
        if obj:FindFirstChildOfClass("Humanoid") then
            if obj:FindFirstChild("HumanoidRootPart") then
                return "🤖 Character/NPC"
            else
                return "🦴 Humanoid Model"
            end
        elseif obj.PrimaryPart then
            return "📦 Model (with PrimaryPart)"
        else
            return "📦 Model"
        end
    elseif obj:IsA("Tool") then return "🔧 Tool/Item"
    elseif obj:IsA("MeshPart") then return "🔷 MeshPart"
    elseif obj:IsA("UnionOperation") then return "🔶 Union"
    elseif obj:IsA("Part") then
        if obj.Shape == Enum.PartType.Ball then return "⚽ Sphere Part"
        elseif obj.Shape == Enum.PartType.Cylinder then return "🛢️ Cylinder Part"
        elseif obj.Shape == Enum.PartType.Block then return "🧱 Block Part"
        else return "📐 Part" end
    elseif obj:IsA("WedgePart") then return "📐 Wedge Part"
    elseif obj:IsA("CornerWedgePart") then return "📐 Corner Wedge"
    elseif obj:IsA("TrussPart") then return "🪜 Truss Part"
    elseif obj:IsA("SpawnLocation") then return "🏁 Spawn Location"
    elseif obj:IsA("Seat") then return "🪑 Seat"
    elseif obj:IsA("VehicleSeat") then return "🚗 Vehicle Seat"
    elseif obj:IsA("Accessory") then return "👒 Accessory"
    elseif obj:IsA("Decal") then return "🖼️ Decal"
    elseif obj:IsA("Texture") then return "🎨 Texture"
    elseif obj:IsA("SurfaceGui") then return "📺 Surface GUI"
    elseif obj:IsA("BillboardGui") then return "📋 Billboard GUI"
    elseif obj:IsA("ScreenGui") then return "🖥️ Screen GUI"
    elseif obj:IsA("ParticleEmitter") then return "✨ Particle Emitter"
    elseif obj:IsA("Trail") then return "🌈 Trail"
    elseif obj:IsA("Beam") then return "⚡ Beam"
    elseif obj:IsA("PointLight") then return "💡 Point Light"
    elseif obj:IsA("SpotLight") then return "🔦 Spot Light"
    elseif obj:IsA("SurfaceLight") then return "🌟 Surface Light"
    elseif obj:IsA("Sound") then return "🔊 Sound"
    elseif obj:IsA("Script") then return "📜 Script"
    elseif obj:IsA("LocalScript") then return "📜 LocalScript"
    elseif obj:IsA("ModuleScript") then return "📜 ModuleScript"
    elseif obj:IsA("Attachment") then return "📎 Attachment"
    elseif obj:IsA("Motor6D") then return "⚙️ Motor6D"
    elseif obj:IsA("Weld") then return "🔗 Weld"
    elseif obj:IsA("WeldConstraint") then return "🔗 WeldConstraint"
    elseif obj:IsA("Folder") then return "📁 Folder"
    elseif obj:IsA("Camera") then return "📷 Camera"
    elseif obj:IsA("Terrain") then return "🏔️ Terrain"
    elseif obj:IsA("Humanoid") then return "🏃 Humanoid"
    elseif obj:IsA("ClickDetector") then return "🖱️ ClickDetector"
    elseif obj:IsA("ProximityPrompt") then return "💬 ProximityPrompt"
    elseif obj:IsA("Fire") then return "🔥 Fire"
    elseif obj:IsA("Smoke") then return "💨 Smoke"
    elseif obj:IsA("Sparkles") then return "✨ Sparkles"
    elseif obj:IsA("Explosion") then return "💥 Explosion"
    elseif obj:IsA("ForceField") then return "🛡️ ForceField"
    elseif obj:IsA("ValueBase") then return "📊 Value (" .. obj.ClassName .. ")"
    elseif obj:IsA("RemoteEvent") then return "📡 RemoteEvent"
    elseif obj:IsA("RemoteFunction") then return "📡 RemoteFunction"
    elseif obj:IsA("BindableEvent") then return "🔔 BindableEvent"
    elseif obj:IsA("BindableFunction") then return "🔔 BindableFunction"
    else return "📄 " .. obj.ClassName
    end
end

local function GetDistance(obj)
    if not Player.Character or not Player.Character:FindFirstChild("HumanoidRootPart") then
        return "N/A", 0
    end
    local playerPos = Player.Character.HumanoidRootPart.Position
    local objPos
    
    if obj:IsA("BasePart") then
        objPos = obj.Position
    elseif obj:IsA("Model") and obj.PrimaryPart then
        objPos = obj.PrimaryPart.Position
    elseif obj:IsA("Model") then
        local success, cf, size = pcall(function() return obj:GetBoundingBox() end)
        if success then objPos = cf.Position else return "N/A", 0 end
    elseif obj:IsA("Attachment") then
        objPos = obj.WorldPosition
    else
        return "N/A", 0
    end
    
    local dist = (playerPos - objPos).Magnitude
    return string.format("%.2f studs (%.2f meters)", dist, dist * 0.28), dist
end

local function GetDirectionTo(obj)
    if not Player.Character or not Player.Character:FindFirstChild("HumanoidRootPart") then
        return "N/A"
    end
    local playerPos = Player.Character.HumanoidRootPart.Position
    local objPos
    
    if obj:IsA("BasePart") then
        objPos = obj.Position
    elseif obj:IsA("Model") then
        local success, cf = pcall(function() return obj:GetBoundingBox() end)
        if success then objPos = cf.Position else return "N/A" end
    else
        return "N/A"
    end
    
    local direction = (objPos - playerPos).Unit
    local angle = math.deg(math.atan2(direction.X, direction.Z))
    
    local compass = ""
    if angle >= -22.5 and angle < 22.5 then compass = "North"
    elseif angle >= 22.5 and angle < 67.5 then compass = "North-East"
    elseif angle >= 67.5 and angle < 112.5 then compass = "East"
    elseif angle >= 112.5 and angle < 157.5 then compass = "South-East"
    elseif angle >= 157.5 or angle < -157.5 then compass = "South"
    elseif angle >= -157.5 and angle < -112.5 then compass = "South-West"
    elseif angle >= -112.5 and angle < -67.5 then compass = "West"
    else compass = "North-West" end
    
    local vertDir = ""
    if direction.Y > 0.3 then vertDir = " (Above)"
    elseif direction.Y < -0.3 then vertDir = " (Below)"
    end
    
    return string.format("%s%s (%.1f°)", compass, vertDir, angle)
end

local function CountChildren(obj, deep)
    if deep then
        return #obj:GetDescendants()
    else
        return #obj:GetChildren()
    end
end

local function GetHierarchyDepth(obj)
    local depth = 0
    local current = obj
    while current.Parent do
        depth = depth + 1
        current = current.Parent
    end
    return depth
end

local function EstimateMemory(obj)
    local baseSize = 100
    local descendants = obj:GetDescendants()
    local total = baseSize
    
    for _, child in pairs(descendants) do
        total = total + 50
        if child:IsA("BasePart") then total = total + 200 end
        if child:IsA("MeshPart") then total = total + 500 end
        if child:IsA("UnionOperation") then total = total + 800 end
        if child:IsA("Texture") or child:IsA("Decal") then total = total + 300 end
        if child:IsA("Sound") then total = total + 200 end
        if child:IsA("ParticleEmitter") then total = total + 150 end
        if child:IsA("Script") or child:IsA("LocalScript") then total = total + 100 end
    end
    
    return FormatBytes(total)
end

local function GetNetworkOwner(obj)
    if not obj:IsA("BasePart") then return "N/A" end
    local success, owner = pcall(function()
        return obj:GetNetworkOwner()
    end)
    if success then
        if owner then
            return owner.Name .. " (Player)"
        else
            return "Server"
        end
    else
        return "Cannot determine"
    end
end

local function GetAttributes(obj)
    local attrs = obj:GetAttributes()
    if next(attrs) == nil then return {} end
    
    local result = {}
    for name, value in pairs(attrs) do
        table.insert(result, {
            Name = name,
            Value = tostring(value),
            Type = typeof(value)
        })
    end
    return result
end

local function GetTags(obj)
    return CollectionService:GetTags(obj)
end

local function GetChildrenByClass(obj)
    local classes = {}
    for _, child in pairs(obj:GetChildren()) do
        local className = child.ClassName
        classes[className] = (classes[className] or 0) + 1
    end
    return classes
end

-- ═══════════════════════════════════════════════════════════
-- ✨ HIGHLIGHT SYSTEM
-- ═══════════════════════════════════════════════════════════

local function CreateHighlight(obj)
    if HighlightBox then
        HighlightBox:Destroy()
        HighlightBox = nil
    end
    
    if not Settings.ShowHighlight then return end
    if not obj then return end
    
    local highlight = Instance.new("Highlight")
    highlight.Name = "InspectorHighlight_" .. obj.Name
    highlight.FillColor = Settings.HighlightColor
    highlight.OutlineColor = Settings.OutlineColor
    highlight.FillTransparency = Settings.HighlightFillTransparency
    highlight.OutlineTransparency = 0
    highlight.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop
    
    if obj:IsA("BasePart") or obj:IsA("Model") then
        highlight.Adornee = obj
        highlight.Parent = Player.PlayerGui
        HighlightBox = highlight
    end
end

local function RemoveHighlight()
    if HighlightBox then
        HighlightBox:Destroy()
        HighlightBox = nil
    end
end

local function UpdateHighlight()
    if HighlightBox and Settings.ShowHighlight then
        HighlightBox.FillColor = Settings.HighlightColor
        HighlightBox.OutlineColor = Settings.OutlineColor
        HighlightBox.FillTransparency = Settings.HighlightFillTransparency
    end
end

-- ═══════════════════════════════════════════════════════════
-- 🖥️ CREATE RAYFIELD WINDOW
-- ═══════════════════════════════════════════════════════════

local Window = Rayfield:CreateWindow({
    Name = "🔍 ULTIMATE OBJECT INSPECTOR v2.0",
    LoadingTitle = "Loading Inspector...",
    LoadingSubtitle = "Cực Chi Tiết Edition",
    ConfigurationSaving = {
        Enabled = false,
        FolderName = nil,
        FileName = "InspectorConfig"
    },
    Discord = {
        Enabled = false
    },
    KeySystem = false
})

-- ═══════════════════════════════════════════════════════════
-- 📑 CREATE TABS
-- ═══════════════════════════════════════════════════════════

local MainTab = Window:CreateTab("🔍 Inspector", 4483362458)
local PlayerTab = Window:CreateTab("👤 Player Info", 4483362458)
local WorldTab = Window:CreateTab("🌍 World Info", 4483362458)
local SettingsTab = Window:CreateTab("⚙️ Settings", 4483362458)
local HelpTab = Window:CreateTab("❓ Help", 4483362458)

-- ═══════════════════════════════════════════════════════════
-- 🎯 MAIN TAB - SELECTION SECTION
-- ═══════════════════════════════════════════════════════════

local SelectionSection = MainTab:CreateSection("🎯 Object Selection")

local SelectionModeLabel = MainTab:CreateLabel("📌 Selection Mode: OFF")

MainTab:CreateButton({
    Name = "🔘 Toggle Selection Mode (or press Q)",
    Callback = function()
        SelectionEnabled = not SelectionEnabled
        SelectionModeLabel:Set("📌 Selection Mode: " .. (SelectionEnabled and "✅ ON" or "❌ OFF"))
        Rayfield:Notify({
            Title = SelectionEnabled and "Selection Enabled" or "Selection Disabled",
            Content = SelectionEnabled and "Press Q or click to select objects!" or "Selection mode turned off",
            Duration = 2
        })
    end,
})

local CurrentSelectionLabel = MainTab:CreateLabel("📦 Selected: None")
local ObjectTypeLabel = MainTab:CreateLabel("📁 Type: N/A")
local DistanceLabel = MainTab:CreateLabel("📏 Distance: N/A")
local DirectionLabel = MainTab:CreateLabel("🧭 Direction: N/A")

MainTab:CreateButton({
    Name = "🎯 Select Object Under Mouse (Q)",
    Callback = function()
        local target = Mouse.Target
        if target then
            SelectedObject = target
            CreateHighlight(target)
            CurrentSelectionLabel:Set("📦 Selected: " .. target.Name)
            ObjectTypeLabel:Set("📁 Type: " .. GetObjectType(target))
            local dist = GetDistance(target)
            DistanceLabel:Set("📏 Distance: " .. dist)
            DirectionLabel:Set("🧭 Direction: " .. GetDirectionTo(target))
            Rayfield:Notify({
                Title = "✅ Object Selected",
                Content = target.Name .. " (" .. target.ClassName .. ")",
                Duration = 2
            })
        else
            Rayfield:Notify({
                Title = "⚠️ No Object",
                Content = "Point your mouse at an object!",
                Duration = 2
            })
        end
    end,
})

MainTab:CreateButton({
    Name = "🔼 Select Parent of Current",
    Callback = function()
        if SelectedObject and SelectedObject.Parent then
            SelectedObject = SelectedObject.Parent
            CreateHighlight(SelectedObject)
            CurrentSelectionLabel:Set("📦 Selected: " .. SelectedObject.Name)
            Rayfield:Notify({
                Title = "Selected Parent",
                Content = SelectedObject.Name,
                Duration = 2
            })
        end
    end,
})

MainTab:CreateButton({
    Name = "👤 Select Nearest Player",
    Callback = function()
        local nearestPlayer = nil
        local nearestDist = math.huge
        local myPos = Player.Character and Player.Character:FindFirstChild("HumanoidRootPart") and Player.Character.HumanoidRootPart.Position
        
        if not myPos then
            Rayfield:Notify({Title = "❌ Error", Content = "Your character not found!", Duration = 2})
            return
        end
        
        for _, plr in pairs(Players:GetPlayers()) do
            if plr ~= Player and plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") then
                local dist = (plr.Character.HumanoidRootPart.Position - myPos).Magnitude
                if dist < nearestDist then
                    nearestDist = dist
                    nearestPlayer = plr
                end
            end
        end
        
        if nearestPlayer and nearestPlayer.Character then
            SelectedObject = nearestPlayer.Character
            CreateHighlight(nearestPlayer.Character)
            CurrentSelectionLabel:Set("📦 Selected: " .. nearestPlayer.Name .. "'s Character")
            ObjectTypeLabel:Set("📁 Type: 👤 Player Character")
            DistanceLabel:Set("📏 Distance: " .. string.format("%.2f studs", nearestDist))
            Rayfield:Notify({
                Title = "✅ Player Selected",
                Content = nearestPlayer.Name .. " - " .. string.format("%.1f", nearestDist) .. " studs away",
                Duration = 2
            })
        else
            Rayfield:Notify({Title = "⚠️ No Players", Content = "No other players found!", Duration = 2})
        end
    end,
})

MainTab:CreateButton({
    Name = "📦 Select Nearest Dropped Item",
    Callback = function()
        local nearestItem = nil
        local nearestDist = math.huge
        local myPos = Player.Character and Player.Character:FindFirstChild("HumanoidRootPart") and Player.Character.HumanoidRootPart.Position
        
        if not myPos then
            Rayfield:Notify({Title = "❌ Error", Content = "Your character not found!", Duration = 2})
            return
        end
        
        -- Search common item locations
        local searchLocations = {
            Workspace,
            Workspace:FindFirstChild("Drops"),
            Workspace:FindFirstChild("Items"),
            Workspace:FindFirstChild("DroppedItems"),
            Workspace:FindFirstChild("Loot"),
            Workspace:FindFirstChild("GroundItems"),
        }
        
        for _, location in pairs(searchLocations) do
            if location then
                for _, item in pairs(location:GetDescendants()) do
                    if item:IsA("Tool") or (item:IsA("Model") and item:FindFirstChild("Handle")) then
                        local pos
                        if item:IsA("Tool") and item:FindFirstChild("Handle") then
                            pos = item.Handle.Position
                        elseif item:IsA("Model") and item.PrimaryPart then
                            pos = item.PrimaryPart.Position
                        elseif item:IsA("Model") then
                            local success, cf = pcall(function() return item:GetBoundingBox() end)
                            if success then pos = cf.Position end
                        end
                        
                        if pos then
                            local dist = (pos - myPos).Magnitude
                            if dist < nearestDist then
                                nearestDist = dist
                                nearestItem = item
                            end
                        end
                    end
                end
            end
        end
        
        if nearestItem then
            SelectedObject = nearestItem
            CreateHighlight(nearestItem)
            CurrentSelectionLabel:Set("📦 Selected: " .. nearestItem.Name)
            Rayfield:Notify({
                Title = "✅ Item Selected",
                Content = nearestItem.Name .. " - " .. string.format("%.1f", nearestDist) .. " studs away",
                Duration = 2
            })
        else
            Rayfield:Notify({Title = "⚠️ No Items", Content = "No dropped items found!", Duration = 2})
        end
    end,
})

MainTab:CreateButton({
    Name = "❌ Clear Selection",
    Callback = function()
        SelectedObject = nil
        RemoveHighlight()
        CurrentSelectionLabel:Set("📦 Selected: None")
        ObjectTypeLabel:Set("📁 Type: N/A")
        DistanceLabel:Set("📏 Distance: N/A")
        DirectionLabel:Set("🧭 Direction: N/A")
        Rayfield:Notify({Title = "🗑️ Cleared", Content = "Selection cleared!", Duration = 1.5})
    end,
})

-- ═══════════════════════════════════════════════════════════
-- 📋 MAIN TAB - BASIC INFO SECTION
-- ═══════════════════════════════════════════════════════════

local BasicSection = MainTab:CreateSection("📋 Basic Information")

local NameLabel = MainTab:CreateLabel("Name: N/A")
local ClassLabel = MainTab:CreateLabel("ClassName: N/A")
local FullPathLabel = MainTab:CreateLabel("Path: N/A")
local ParentLabel = MainTab:CreateLabel("Parent: N/A")
local ChildrenLabel = MainTab:CreateLabel("Children: N/A")
local DescendantsLabel = MainTab:CreateLabel("Descendants: N/A")
local MemoryLabel = MainTab:CreateLabel("Est. Memory: N/A")
local DepthLabel = MainTab:CreateLabel("Hierarchy Depth: N/A")

-- ═══════════════════════════════════════════════════════════
-- 📐 MAIN TAB - TRANSFORM SECTION
-- ═══════════════════════════════════════════════════════════

local TransformSection = MainTab:CreateSection("📐 Transform & Position")

local PositionLabel = MainTab:CreateLabel("Position: N/A")
local RotationLabel = MainTab:CreateLabel("Rotation: N/A")
local OrientationLabel = MainTab:CreateLabel("Orientation: N/A")
local SizeLabel = MainTab:CreateLabel("Size: N/A")
local VolumeLabel = MainTab:CreateLabel("Volume: N/A")
local LookVectorLabel = MainTab:CreateLabel("LookVector: N/A")
local UpVectorLabel = MainTab:CreateLabel("UpVector: N/A")
local RightVectorLabel = MainTab:CreateLabel("RightVector: N/A")
local PivotLabel = MainTab:CreateLabel("Pivot Offset: N/A")

-- ═══════════════════════════════════════════════════════════
-- ⚡ MAIN TAB - PHYSICS SECTION
-- ═══════════════════════════════════════════════════════════

local PhysicsSection = MainTab:CreateSection("⚡ Physics Properties")

local AnchoredLabel = MainTab:CreateLabel("Anchored: N/A")
local CanCollideLabel = MainTab:CreateLabel("CanCollide: N/A")
local CanTouchLabel = MainTab:CreateLabel("CanTouch: N/A")
local CanQueryLabel = MainTab:CreateLabel("CanQuery: N/A")
local MassLabel = MainTab:CreateLabel("Mass: N/A")
local DensityLabel = MainTab:CreateLabel("Density: N/A")
local VelocityLabel = MainTab:CreateLabel("Velocity: N/A")
local AngularVelocityLabel = MainTab:CreateLabel("Angular Velocity: N/A")
local RootPartLabel = MainTab:CreateLabel("RootPart: N/A")
local CollisionGroupLabel = MainTab:CreateLabel("Collision Group: N/A")
local NetworkOwnerLabel = MainTab:CreateLabel("Network Owner: N/A")

-- ═══════════════════════════════════════════════════════════
-- 🎨 MAIN TAB - APPEARANCE SECTION
-- ═══════════════════════════════════════════════════════════

local AppearanceSection = MainTab:CreateSection("🎨 Appearance")

local ColorLabel = MainTab:CreateLabel("Color: N/A")
local BrickColorLabel = MainTab:CreateLabel("BrickColor: N/A")
local MaterialLabel = MainTab:CreateLabel("Material: N/A")
local MaterialVariantLabel = MainTab:CreateLabel("Material Variant: N/A")
local TransparencyLabel = MainTab:CreateLabel("Transparency: N/A")
local ReflectanceLabel = MainTab:CreateLabel("Reflectance: N/A")
local CastShadowLabel = MainTab:CreateLabel("CastShadow: N/A")
local SurfaceTypesLabel = MainTab:CreateLabel("Surface Types: N/A")

-- ═══════════════════════════════════════════════════════════
-- 🤖 MAIN TAB - HUMANOID SECTION
-- ═══════════════════════════════════════════════════════════

local HumanoidSection = MainTab:CreateSection("🤖 Humanoid Properties")

local HealthLabel = MainTab:CreateLabel("Health: N/A")
local MaxHealthLabel = MainTab:CreateLabel("MaxHealth: N/A")
local WalkSpeedLabel = MainTab:CreateLabel("WalkSpeed: N/A")
local JumpPowerLabel = MainTab:CreateLabel("JumpPower: N/A")
local JumpHeightLabel = MainTab:CreateLabel("JumpHeight: N/A")
local HipHeightLabel = MainTab:CreateLabel("HipHeight: N/A")
local StateLabel = MainTab:CreateLabel("State: N/A")
local SitLabel = MainTab:CreateLabel("Sit: N/A")
local DisplayNameLabel = MainTab:CreateLabel("DisplayName: N/A")
local RigTypeLabel = MainTab:CreateLabel("RigType: N/A")

-- ═══════════════════════════════════════════════════════════
-- 📊 MAIN TAB - ATTRIBUTES SECTION
-- ═══════════════════════════════════════════════════════════

local AttributesSection = MainTab:CreateSection("📊 Attributes & Tags")

local AttributesLabel = MainTab:CreateLabel("Attributes: N/A")
local TagsLabel = MainTab:CreateLabel("Tags: N/A")

-- ═══════════════════════════════════════════════════════════
-- 🌳 MAIN TAB - HIERARCHY SECTION
-- ═══════════════════════════════════════════════════════════

local HierarchySection = MainTab:CreateSection("🌳 Hierarchy & Classes")

local ChildClassesLabel = MainTab:CreateLabel("Child Classes: N/A")

-- ═══════════════════════════════════════════════════════════
-- 📋 MAIN TAB - COPY SECTION
-- ═══════════════════════════════════════════════════════════

local CopySection = MainTab:CreateSection("📋 Copy Data")

MainTab:CreateButton({
    Name = "📋 Copy ALL Data (Full Report)",
    Callback = function()
        if CopiedData ~= "" then
            setclipboard(CopiedData)
            Rayfield:Notify({
                Title = "✅ Copied!",
                Content = "Full inspector report copied to clipboard!",
                Duration = 2
            })
        else
            Rayfield:Notify({
                Title = "⚠️ No Data",
                Content = "Select an object first!",
                Duration = 2
            })
        end
    end,
})

MainTab:CreateButton({
    Name = "📍 Copy Position (Vector3)",
    Callback = function()
        if SelectedObject and SelectedObject:IsA("BasePart") then
            local pos = SelectedObject.Position
            setclipboard(FormatVector3Code(pos))
            Rayfield:Notify({Title = "✅ Copied!", Content = "Position: " .. FormatVector3Short(pos), Duration = 2})
        elseif SelectedObject and SelectedObject:IsA("Model") then
            local success, cf = pcall(function() return SelectedObject:GetBoundingBox() end)
            if success then
                setclipboard(FormatVector3Code(cf.Position))
                Rayfield:Notify({Title = "✅ Copied!", Content = "Model position copied!", Duration = 2})
            end
        else
            Rayfield:Notify({Title = "⚠️ Error", Content = "No valid object selected!", Duration = 2})
        end
    end,
})

MainTab:CreateButton({
    Name = "📐 Copy CFrame (Full)",
    Callback = function()
        if SelectedObject and SelectedObject:IsA("BasePart") then
            local cf = SelectedObject.CFrame
            local x, y, z = cf:ToEulerAnglesXYZ()
            local code = string.format("CFrame.new(%.4f, %.4f, %.4f) * CFrame.Angles(%.4f, %.4f, %.4f)", 
                cf.Position.X, cf.Position.Y, cf.Position.Z, x, y, z)
            setclipboard(code)
            Rayfield:Notify({Title = "✅ Copied!", Content = "Full CFrame copied!", Duration = 2})
        else
            Rayfield:Notify({Title = "⚠️ Error", Content = "Select a BasePart!", Duration = 2})
        end
    end,
})

MainTab:CreateButton({
    Name = "🔗 Copy Full Path",
    Callback = function()
        if SelectedObject then
            local path = SelectedObject:GetFullName()
            setclipboard('game.' .. path)
            Rayfield:Notify({Title = "✅ Copied!", Content = "Full path copied!", Duration = 2})
        else
            Rayfield:Notify({Title = "⚠️ Error", Content = "No object selected!", Duration = 2})
        end
    end,
})

MainTab:CreateButton({
    Name = "🎨 Copy Color (Color3)",
    Callback = function()
        if SelectedObject and SelectedObject:IsA("BasePart") then
            local c = SelectedObject.Color
            setclipboard(string.format("Color3.new(%.4f, %.4f, %.4f)", c.R, c.G, c.B))
            Rayfield:Notify({Title = "✅ Copied!", Content = "Color copied!", Duration = 2})
        else
            Rayfield:Notify({Title = "⚠️ Error", Content = "Select a BasePart!", Duration = 2})
        end
    end,
})

MainTab:CreateButton({
    Name = "📦 Copy Size (Vector3)",
    Callback = function()
        if SelectedObject and SelectedObject:IsA("BasePart") then
            setclipboard(FormatVector3Code(SelectedObject.Size))
            Rayfield:Notify({Title = "✅ Copied!", Content = "Size copied!", Duration = 2})
        else
            Rayfield:Notify({Title = "⚠️ Error", Content = "Select a BasePart!", Duration = 2})
        end
    end,
})

MainTab:CreateButton({
    Name = "📊 Copy All Attributes (JSON)",
    Callback = function()
        if SelectedObject then
            local attrs = SelectedObject:GetAttributes()
            if next(attrs) then
                local json = HttpService:JSONEncode(attrs)
                setclipboard(json)
                Rayfield:Notify({Title = "✅ Copied!", Content = "Attributes copied as JSON!", Duration = 2})
            else
                Rayfield:Notify({Title = "⚠️ No Attributes", Content = "This object has no attributes!", Duration = 2})
            end
        else
            Rayfield:Notify({Title = "⚠️ Error", Content = "No object selected!", Duration = 2})
        end
    end,
})

-- ═══════════════════════════════════════════════════════════
-- 👤 PLAYER TAB
-- ═══════════════════════════════════════════════════════════

local LocalPlayerSection = PlayerTab:CreateSection("👤 Local Player Info")

local PNameLabel = PlayerTab:CreateLabel("Name: " .. Player.Name)
local PDisplayLabel = PlayerTab:CreateLabel("DisplayName: " .. Player.DisplayName)
local PIdLabel = PlayerTab:CreateLabel("UserId: " .. Player.UserId)
local PAgeLabel = PlayerTab:CreateLabel("Account Age: " .. Player.AccountAge .. " days")
local PTeamLabel = PlayerTab:CreateLabel("Team: " .. (Player.Team and Player.Team.Name or "None"))
local PMembershipLabel = PlayerTab:CreateLabel("Membership: " .. tostring(Player.MembershipType))
local PFollowLabel = PlayerTab:CreateLabel("FollowUserId: " .. (Player.FollowUserId > 0 and tostring(Player.FollowUserId) or "None"))

local CharSection = PlayerTab:CreateSection("🏃 Character Info")

local CharPosLabel = PlayerTab:CreateLabel("Position: N/A")
local CharVelocityLabel = PlayerTab:CreateLabel("Velocity: N/A")
local CharSpeedLabel = PlayerTab:CreateLabel("Current Speed: N/A")
local CharHealthLabel = PlayerTab:CreateLabel("Health: N/A")
local CharWalkLabel = PlayerTab:CreateLabel("WalkSpeed: N/A")
local CharJumpLabel = PlayerTab:CreateLabel("JumpPower: N/A")
local CharLookLabel = PlayerTab:CreateLabel("Look Direction: N/A")
local CharMoveLabel = PlayerTab:CreateLabel("Move Direction: N/A")
local CharStateLabel = PlayerTab:CreateLabel("State: N/A")
local CharFloorLabel = PlayerTab:CreateLabel("Floor Material: N/A")

local CamSection = PlayerTab:CreateSection("📷 Camera Info")

local CamPosLabel = PlayerTab:CreateLabel("Position: N/A")
local CamLookLabel = PlayerTab:CreateLabel("Look Vector: N/A")
local CamFOVLabel = PlayerTab:CreateLabel("FOV: N/A")
local CamTypeLabel = PlayerTab:CreateLabel("Type: N/A")
local CamFocusLabel = PlayerTab:CreateLabel("Focus: N/A")
local CamSubjectLabel = PlayerTab:CreateLabel("Subject: N/A")
local CamDistLabel = PlayerTab:CreateLabel("View Distance: N/A")

local ToolsSection = PlayerTab:CreateSection("🔧 Equipped Tools")

local EquippedToolLabel = PlayerTab:CreateLabel("Equipped: None")
local BackpackLabel = PlayerTab:CreateLabel("Backpack: Loading...")

PlayerTab:CreateButton({
    Name = "📋 Copy Character Position",
    Callback = function()
        if Player.Character and Player.Character:FindFirstChild("HumanoidRootPart") then
            local pos = Player.Character.HumanoidRootPart.Position
            setclipboard(FormatVector3Code(pos))
            Rayfield:Notify({Title = "✅ Copied!", Content = "Your position copied!", Duration = 2})
        end
    end,
})

PlayerTab:CreateButton({
    Name = "📋 Copy Camera CFrame",
    Callback = function()
        local cf = Camera.CFrame
        local code = string.format("CFrame.new(%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f)", 
            cf.Position.X, cf.Position.Y, cf.Position.Z,
            cf:GetComponents())
        setclipboard(code)
        Rayfield:Notify({Title = "✅ Copied!", Content = "Camera CFrame copied!", Duration = 2})
    end,
})

-- ═══════════════════════════════════════════════════════════
-- 🌍 WORLD TAB
-- ═══════════════════════════════════════════════════════════

local GameSection = WorldTab:CreateSection("🎮 Game Info")

local GameIdLabel = WorldTab:CreateLabel("PlaceId: " .. game.PlaceId)
local GameVersionLabel = WorldTab:CreateLabel("PlaceVersion: " .. game.PlaceVersion)
local JobIdLabel = WorldTab:CreateLabel("JobId: " .. game.JobId)
local CreatorLabel = WorldTab:CreateLabel("Creator: " .. (game.CreatorType == Enum.CreatorType.User and "User" or "Group") .. " #" .. game.CreatorId)

local ServerSection = WorldTab:CreateSection("🖥️ Server Info")

local PlayerCountLabel = WorldTab:CreateLabel("Players: " .. #Players:GetPlayers() .. "/" .. Players.MaxPlayers)
local ServerTimeLabel = WorldTab:CreateLabel("Server Time: N/A")
local ServerAgeLabel = WorldTab:CreateLabel("Server Uptime: N/A")

local EnvironmentSection = WorldTab:CreateSection("🌅 Environment")

local LightingTimeLabel = WorldTab:CreateLabel("Time of Day: " .. Lighting.TimeOfDay)
local AmbientLabel = WorldTab:CreateLabel("Ambient: " .. FormatColor3(Lighting.Ambient))
local BrightnessLabel = WorldTab:CreateLabel("Brightness: " .. Lighting.Brightness)
local FogLabel = WorldTab:CreateLabel("Fog: " .. Lighting.FogStart .. " - " .. Lighting.FogEnd)
local GravityLabel = WorldTab:CreateLabel("Gravity: " .. Workspace.Gravity)

WorldTab:CreateButton({
    Name = "📋 Copy Game Info",
    Callback = function()
        local info = string.format([[
Game Info:
PlaceId: %d
PlaceVersion: %d
JobId: %s
CreatorId: %d
Players: %d/%d
]], game.PlaceId, game.PlaceVersion, game.JobId, game.CreatorId, #Players:GetPlayers(), Players.MaxPlayers)
        setclipboard(info)
        Rayfield:Notify({Title = "✅ Copied!", Content = "Game info copied!", Duration = 2})
    end,
})

-- ═══════════════════════════════════════════════════════════
-- ⚙️ SETTINGS TAB
-- ═══════════════════════════════════════════════════════════

local InspectorSettingsSection = SettingsTab:CreateSection("⚙️ Inspector Settings")

SettingsTab:CreateToggle({
    Name = "🔄 Auto Refresh Data",
    CurrentValue = Settings.AutoRefresh,
    Flag = "AutoRefresh",
    Callback = function(Value)
        Settings.AutoRefresh = Value
    end,
})

SettingsTab:CreateSlider({
    Name = "⏱️ Refresh Rate",
    Range = {0.1, 3},
    Increment = 0.1,
    Suffix = " seconds",
    CurrentValue = Settings.RefreshRate,
    Flag = "RefreshRate",
    Callback = function(Value)
        Settings.RefreshRate = Value
    end,
})

local HighlightSettingsSection = SettingsTab:CreateSection("✨ Highlight Settings")

SettingsTab:CreateToggle({
    Name = "✨ Show Selection Highlight",
    CurrentValue = Settings.ShowHighlight,
    Flag = "ShowHighlight",
    Callback = function(Value)
        Settings.ShowHighlight = Value
        if not Value then
            RemoveHighlight()
        elseif SelectedObject then
            CreateHighlight(SelectedObject)
        end
    end,
})

SettingsTab:CreateColorPicker({
    Name = "🎨 Highlight Fill Color",
    Color = Settings.HighlightColor,
    Flag = "HighlightColor",
    Callback = function(Value)
        Settings.HighlightColor = Value
        UpdateHighlight()
    end
})

SettingsTab:CreateColorPicker({
    Name = "⬜ Highlight Outline Color",
    Color = Settings.OutlineColor,
    Flag = "OutlineColor",
    Callback = function(Value)
        Settings.OutlineColor = Value
        UpdateHighlight()
    end
})

SettingsTab:CreateSlider({
    Name = "👁️ Highlight Transparency",
    Range = {0, 1},
    Increment = 0.05,
    Suffix = "",
    CurrentValue = Settings.HighlightFillTransparency,
    Flag = "HighlightTransparency",
    Callback = function(Value)
        Settings.HighlightFillTransparency = Value
        UpdateHighlight()
    end,
})

local HotkeySettingsSection = SettingsTab:CreateSection("⌨️ Hotkey Settings")

SettingsTab:CreateKeybind({
    Name = "🎯 Quick Select Hotkey",
    CurrentKeybind = "Q",
    HoldToInteract = false,
    Flag = "SelectKey",
    Callback = function(Keybind)
        if SelectionEnabled and Mouse.Target then
            SelectedObject = Mouse.Target
            CreateHighlight(Mouse.Target)
            CurrentSelectionLabel:Set("📦 Selected: " .. Mouse.Target.Name)
            ObjectTypeLabel:Set("📁 Type: " .. GetObjectType(Mouse.Target))
            Rayfield:Notify({
                Title = "⚡ Quick Select",
                Content = Mouse.Target.Name,
                Duration = 1.5
            })
        end
    end,
})

local DetailSettingsSection = SettingsTab:CreateSection("📊 Detail Level")

SettingsTab:CreateDropdown({
    Name = "📊 Information Detail Level",
    Options = {"Basic", "Detailed", "Maximum"},
    CurrentOption = {Settings.DetailLevel},
    MultipleOptions = false,
    Flag = "DetailLevel",
    Callback = function(Options)
        Settings.DetailLevel = Options[1]
    end,
})

-- ═══════════════════════════════════════════════════════════
-- ❓ HELP TAB
-- ═══════════════════════════════════════════════════════════

local UsageSection = HelpTab:CreateSection("📖 How to Use")

HelpTab:CreateLabel("1️⃣ Click 'Toggle Selection Mode' or press Q")
HelpTab:CreateLabel("2️⃣ Point mouse at any object")
HelpTab:CreateLabel("3️⃣ Press Q or click 'Select Object Under Mouse'")
HelpTab:CreateLabel("4️⃣ View all details in Inspector tab")
HelpTab:CreateLabel("5️⃣ Use Copy buttons to copy any data")

local HotkeyHelpSection = HelpTab:CreateSection("⌨️ Default Hotkeys")

HelpTab:CreateLabel("Q - Quick select object under cursor")
HelpTab:CreateLabel("RightShift - Toggle GUI visibility")

local InfoTypesSection = HelpTab:CreateSection("ℹ️ Available Information")

HelpTab:CreateLabel("📋 Basic: Name, Class, Path, Children")
HelpTab:CreateLabel("📐 Transform: Position, Rotation, Size, Vectors")
HelpTab:CreateLabel("⚡ Physics: Mass, Velocity, Anchored, Collision")
HelpTab:CreateLabel("🎨 Appearance: Color, Material, Transparency")
HelpTab:CreateLabel("🤖 Humanoid: Health, Speed, State, RigType")
HelpTab:CreateLabel("📊 Attributes: Custom attributes & tags")
HelpTab:CreateLabel("🌐 Network: Ownership, Replication status")

local TipsSection = HelpTab:CreateSection("💡 Tips")

HelpTab:CreateLabel("• Use 'Select Parent' to navigate up hierarchy")
HelpTab:CreateLabel("• Enable auto-refresh for real-time updates")
HelpTab:CreateLabel("• Copy data to use in your own scripts")
HelpTab:CreateLabel("• Adjust highlight settings for visibility")

-- ═══════════════════════════════════════════════════════════
-- 🔚 END OF PART 1 - PASTE PART 2 BELOW THIS LINE
-- ═══════════════════════════════════════════════════════════

print("✅ [INSPECTOR] Part 1 loaded successfully!")
print("📋 Waiting for Part 2...")
-- ═══════════════════════════════════════════════════════════
-- 🔍 ULTIMATE OBJECT INSPECTOR - PHẦN 2/2
-- ═══════════════════════════════════════════════════════════
-- Paste trực tiếp sau Phần 1
-- ═══════════════════════════════════════════════════════════

print("📋 [INSPECTOR] Loading Part 2...")

-- ═══════════════════════════════════════════════════════════
-- 🔍 DETAILED INSPECTION FUNCTIONS
-- ═══════════════════════════════════════════════════════════

local function InspectBasePart(obj)
    local data = {}
    
    -- Basic Info
    data.Name = obj.Name
    data.ClassName = obj.ClassName
    data.FullPath = obj:GetFullName()
    data.Parent = obj.Parent and obj.Parent.Name or "None"
    data.ObjectType = GetObjectType(obj)
    data.Children = CountChildren(obj, false)
    data.Descendants = CountChildren(obj, true)
    data.HierarchyDepth = GetHierarchyDepth(obj)
    data.EstimatedMemory = EstimateMemory(obj)
    
    -- Transform
    data.Position = FormatVector3(obj.Position)
    data.PositionCode = FormatVector3Code(obj.Position)
    data.CFrame = FormatCFrame(obj.CFrame)
    data.CFrameDetailed = FormatCFrameDetailed(obj.CFrame)
    data.Orientation = FormatVector3(obj.Orientation)
    data.Rotation = FormatVector3(obj.Rotation)
    data.Size = FormatVector3(obj.Size)
    data.SizeCode = FormatVector3Code(obj.Size)
    data.Volume = FormatNumber(obj.Size.X * obj.Size.Y * obj.Size.Z, 4) .. " studs³"
    data.LookVector = FormatVector3(obj.CFrame.LookVector)
    data.UpVector = FormatVector3(obj.CFrame.UpVector)
    data.RightVector = FormatVector3(obj.CFrame.RightVector)
    data.PivotOffset = FormatCFrame(obj.PivotOffset)
    
    -- Distance & Direction
    local distStr, distNum = GetDistance(obj)
    data.Distance = distStr
    data.DistanceRaw = distNum
    data.Direction = GetDirectionTo(obj)
    
    -- Physics
    data.Anchored = FormatBoolean(obj.Anchored)
    data.CanCollide = FormatBoolean(obj.CanCollide)
    data.CanTouch = FormatBoolean(obj.CanTouch)
    data.CanQuery = FormatBoolean(obj.CanQuery)
    data.Massless = FormatBoolean(obj.Massless)
    
    local success, mass = pcall(function() return obj:GetMass() end)
    data.Mass = success and FormatNumber(mass, 4) .. " kg" or "N/A"
    
    data.Density = FormatNumber(obj.CustomPhysicalProperties and obj.CustomPhysicalProperties.Density or "Default")
    data.Friction = obj.CustomPhysicalProperties and FormatNumber(obj.CustomPhysicalProperties.Friction) or "Default"
    data.Elasticity = obj.CustomPhysicalProperties and FormatNumber(obj.CustomPhysicalProperties.Elasticity) or "Default"
    
    local velocity = obj.AssemblyLinearVelocity
    data.Velocity = FormatVector3(velocity)
    data.Speed = FormatNumber(velocity.Magnitude, 2) .. " studs/s"
    data.AngularVelocity = FormatVector3(obj.AssemblyAngularVelocity)
    
    data.RootPart = obj.AssemblyRootPart and obj.AssemblyRootPart.Name or "Self"
    data.CollisionGroup = obj.CollisionGroup
    data.NetworkOwner = GetNetworkOwner(obj)
    
    -- Appearance
    data.Color = FormatColor3(obj.Color)
    data.ColorCode = string.format("Color3.new(%.4f, %.4f, %.4f)", obj.Color.R, obj.Color.G, obj.Color.B)
    data.BrickColor = FormatBrickColor(obj.BrickColor)
    data.Material = tostring(obj.Material):gsub("Enum.Material.", "")
    data.MaterialVariant = obj.MaterialVariant ~= "" and obj.MaterialVariant or "None"
    data.Transparency = FormatNumber(obj.Transparency, 4)
    data.Reflectance = FormatNumber(obj.Reflectance, 4)
    data.CastShadow = FormatBoolean(obj.CastShadow)
    
    -- Surface Types
    data.TopSurface = tostring(obj.TopSurface):gsub("Enum.SurfaceType.", "")
    data.BottomSurface = tostring(obj.BottomSurface):gsub("Enum.SurfaceType.", "")
    data.FrontSurface = tostring(obj.FrontSurface):gsub("Enum.SurfaceType.", "")
    data.BackSurface = tostring(obj.BackSurface):gsub("Enum.SurfaceType.", "")
    data.LeftSurface = tostring(obj.LeftSurface):gsub("Enum.SurfaceType.", "")
    data.RightSurface = tostring(obj.RightSurface):gsub("Enum.SurfaceType.", "")
    
    -- MeshPart specific
    if obj:IsA("MeshPart") then
        data.MeshId = obj.MeshId
        data.TextureID = obj.TextureID
        data.RenderFidelity = tostring(obj.RenderFidelity):gsub("Enum.RenderFidelity.", "")
        data.CollisionFidelity = tostring(obj.CollisionFidelity):gsub("Enum.CollisionFidelity.", "")
        data.DoubleSided = FormatBoolean(obj.DoubleSided)
    end
    
    -- UnionOperation specific
    if obj:IsA("UnionOperation") then
        data.UsePartColor = FormatBoolean(obj.UsePartColor)
        data.SmoothingAngle = FormatNumber(obj.SmoothingAngle, 2) .. "°"
    end
    
    -- Part specific
    if obj:IsA("Part") then
        data.Shape = tostring(obj.Shape):gsub("Enum.PartType.", "")
    end
    
    -- Attributes & Tags
    data.Attributes = GetAttributes(obj)
    data.Tags = GetTags(obj)
    
    -- Child Classes
    data.ChildClasses = GetChildrenByClass(obj)
    
    -- Special Components
    data.HasClickDetector = obj:FindFirstChildOfClass("ClickDetector") and "✅ Yes" or "❌ No"
    data.HasProximityPrompt = obj:FindFirstChildOfClass("ProximityPrompt") and "✅ Yes" or "❌ No"
    data.HasSound = obj:FindFirstChildOfClass("Sound") and "✅ Yes" or "❌ No"
    data.HasParticles = obj:FindFirstChildOfClass("ParticleEmitter") and "✅ Yes" or "❌ No"
    data.HasLight = (obj:FindFirstChildOfClass("PointLight") or obj:FindFirstChildOfClass("SpotLight") or obj:FindFirstChildOfClass("SurfaceLight")) and "✅ Yes" or "❌ No"
    data.HasDecal = obj:FindFirstChildOfClass("Decal") and "✅ Yes" or "❌ No"
    data.HasTexture = obj:FindFirstChildOfClass("Texture") and "✅ Yes" or "❌ No"
    data.HasScript = (obj:FindFirstChildOfClass("Script") or obj:FindFirstChildOfClass("LocalScript")) and "✅ Yes" or "❌ No"
    
    -- Constraints
    local constraints = {}
    for _, child in pairs(obj:GetChildren()) do
        if child:IsA("Constraint") then
            table.insert(constraints, child.ClassName .. ": " .. child.Name)
        end
    end
    data.Constraints = #constraints > 0 and constraints or {"None"}
    
    -- Welds & Joints
    local joints = {}
    for _, child in pairs(obj:GetChildren()) do
        if child:IsA("JointInstance") then
            table.insert(joints, child.ClassName .. ": " .. child.Name)
        end
    end
    data.Joints = #joints > 0 and joints or {"None"}
    
    return data
end

local function InspectModel(obj)
    local data = {}
    
    -- Basic Info
    data.Name = obj.Name
    data.ClassName = obj.ClassName
    data.FullPath = obj:GetFullName()
    data.Parent = obj.Parent and obj.Parent.Name or "None"
    data.ObjectType = GetObjectType(obj)
    data.Children = CountChildren(obj, false)
    data.Descendants = CountChildren(obj, true)
    data.HierarchyDepth = GetHierarchyDepth(obj)
    data.EstimatedMemory = EstimateMemory(obj)
    
    -- Model-specific
    data.PrimaryPart = obj.PrimaryPart and obj.PrimaryPart.Name or "None"
    data.ModelStreamingMode = tostring(obj.ModelStreamingMode):gsub("Enum.ModelStreamingMode.", "")
    data.LevelOfDetail = tostring(obj.LevelOfDetail):gsub("Enum.ModelLevelOfDetail.", "")
    
    -- Bounding Box
    local success, cf, size = pcall(function() return obj:GetBoundingBox() end)
    if success then
        data.BoundingBoxPosition = FormatVector3(cf.Position)
        data.BoundingBoxSize = FormatVector3(size)
        data.BoundingBoxVolume = FormatNumber(size.X * size.Y * size.Z, 4) .. " studs³"
        data.Position = FormatVector3(cf.Position)
        data.CFrame = FormatCFrame(cf)
        
        -- Distance & Direction
        local distStr, distNum = GetDistance(obj)
        data.Distance = distStr
        data.DistanceRaw = distNum
        data.Direction = GetDirectionTo(obj)
    else
        data.BoundingBoxPosition = "N/A"
        data.BoundingBoxSize = "N/A"
        data.BoundingBoxVolume = "N/A"
        data.Position = "N/A"
        data.Distance = "N/A"
        data.Direction = "N/A"
    end
    
    -- Pivot
    local pivotSuccess, pivot = pcall(function() return obj:GetPivot() end)
    if pivotSuccess then
        data.Pivot = FormatCFrame(pivot)
    else
        data.Pivot = "N/A"
    end
    
    -- Model Mass
    local massSuccess, mass = pcall(function()
        local totalMass = 0
        for _, part in pairs(obj:GetDescendants()) do
            if part:IsA("BasePart") then
                totalMass = totalMass + part:GetMass()
            end
        end
        return totalMass
    end)
    data.TotalMass = massSuccess and FormatNumber(mass, 4) .. " kg" or "N/A"
    
    -- Part Count
    local partCount = 0
    local meshCount = 0
    local unionCount = 0
    for _, descendant in pairs(obj:GetDescendants()) do
        if descendant:IsA("Part") then partCount = partCount + 1
        elseif descendant:IsA("MeshPart") then meshCount = meshCount + 1
        elseif descendant:IsA("UnionOperation") then unionCount = unionCount + 1
        end
    end
    data.PartCount = partCount
    data.MeshPartCount = meshCount
    data.UnionCount = unionCount
    data.TotalBaseParts = partCount + meshCount + unionCount
    
    -- Humanoid Check
    local humanoid = obj:FindFirstChildOfClass("Humanoid")
    if humanoid then
        data.HasHumanoid = "✅ Yes"
        data.Health = FormatNumber(humanoid.Health, 1) .. " / " .. FormatNumber(humanoid.MaxHealth, 1)
        data.HealthPercent = FormatNumber((humanoid.Health / humanoid.MaxHealth) * 100, 1) .. "%"
        data.WalkSpeed = FormatNumber(humanoid.WalkSpeed, 2)
        data.JumpPower = FormatNumber(humanoid.JumpPower, 2)
        data.JumpHeight = FormatNumber(humanoid.JumpHeight, 2)
        data.HipHeight = FormatNumber(humanoid.HipHeight, 2)
        data.MaxSlopeAngle = FormatNumber(humanoid.MaxSlopeAngle, 2) .. "°"
        data.HumanoidState = tostring(humanoid:GetState()):gsub("Enum.HumanoidStateType.", "")
        data.MoveDirection = FormatVector3(humanoid.MoveDirection)
        data.Sit = FormatBoolean(humanoid.Sit)
        data.SeatPart = humanoid.SeatPart and humanoid.SeatPart.Name or "None"
        data.PlatformStand = FormatBoolean(humanoid.PlatformStand)
        data.AutoRotate = FormatBoolean(humanoid.AutoRotate)
        data.AutoJumpEnabled = FormatBoolean(humanoid.AutoJumpEnabled)
        data.DisplayName = humanoid.DisplayName
        data.RigType = tostring(humanoid.RigType):gsub("Enum.HumanoidRigType.", "")
        data.NameOcclusion = tostring(humanoid.NameOcclusion):gsub("Enum.NameOcclusion.", "")
        data.HealthDisplayType = tostring(humanoid.HealthDisplayType):gsub("Enum.HumanoidHealthDisplayType.", "")
        data.FloorMaterial = tostring(humanoid.FloorMaterial):gsub("Enum.Material.", "")
        
        -- Body Parts
        local hrp = obj:FindFirstChild("HumanoidRootPart")
        if hrp then
            data.HumanoidRootPartPos = FormatVector3(hrp.Position)
            data.HumanoidRootPartVelocity = FormatVector3(hrp.AssemblyLinearVelocity)
            data.CurrentSpeed = FormatNumber(hrp.AssemblyLinearVelocity.Magnitude, 2) .. " studs/s"
        end
        
        local head = obj:FindFirstChild("Head")
        if head then
            data.HeadPosition = FormatVector3(head.Position)
        end
    else
        data.HasHumanoid = "❌ No"
    end
    
    -- Check for Player
    local player = Players:GetPlayerFromCharacter(obj)
    if player then
        data.IsPlayerCharacter = "✅ Yes"
        data.PlayerName = player.Name
        data.PlayerDisplayName = player.DisplayName
        data.PlayerUserId = tostring(player.UserId)
        data.PlayerAccountAge = player.AccountAge .. " days"
        data.PlayerTeam = player.Team and player.Team.Name or "None"
        data.PlayerMembership = tostring(player.MembershipType):gsub("Enum.MembershipType.", "")
    else
        data.IsPlayerCharacter = "❌ No"
    end
    
    -- Attributes & Tags
    data.Attributes = GetAttributes(obj)
    data.Tags = GetTags(obj)
    
    -- Child Classes
    data.ChildClasses = GetChildrenByClass(obj)
    
    return data
end

local function InspectTool(obj)
    local data = {}
    
    -- Basic Info
    data.Name = obj.Name
    data.ClassName = obj.ClassName
    data.FullPath = obj:GetFullName()
    data.Parent = obj.Parent and obj.Parent.Name or "None"
    data.ObjectType = GetObjectType(obj)
    data.Children = CountChildren(obj, false)
    data.Descendants = CountChildren(obj, true)
    
    -- Tool Properties
    data.ToolTip = obj.ToolTip ~= "" and obj.ToolTip or "None"
    data.RequiresHandle = FormatBoolean(obj.RequiresHandle)
    data.CanBeDropped = FormatBoolean(obj.CanBeDropped)
    data.ManualActivationOnly = FormatBoolean(obj.ManualActivationOnly)
    data.Enabled = FormatBoolean(obj.Enabled)
    
    -- Handle
    local handle = obj:FindFirstChild("Handle")
    if handle then
        data.HasHandle = "✅ Yes"
        data.HandlePosition = FormatVector3(handle.Position)
        data.HandleSize = FormatVector3(handle.Size)
        
        local distStr = GetDistance(handle)
        data.Distance = distStr
        data.Direction = GetDirectionTo(handle)
    else
        data.HasHandle = "❌ No"
        data.Distance = "N/A"
        data.Direction = "N/A"
    end
    
    -- Grip
    data.Grip = FormatCFrame(obj.Grip)
    data.GripPos = FormatVector3(obj.GripPos)
    data.GripForward = FormatVector3(obj.GripForward)
    data.GripRight = FormatVector3(obj.GripRight)
    data.GripUp = FormatVector3(obj.GripUp)
    
    -- TextureId
    data.TextureId = obj.TextureId ~= "" and obj.TextureId or "None"
    
    -- Owner
    if obj.Parent and obj.Parent:IsA("Backpack") then
        local owner = obj.Parent.Parent
        if owner:IsA("Player") then
            data.Owner = owner.Name .. " (In Backpack)"
        end
    elseif obj.Parent and obj.Parent:IsA("Model") then
        local player = Players:GetPlayerFromCharacter(obj.Parent)
        if player then
            data.Owner = player.Name .. " (Equipped)"
        else
            data.Owner = "NPC/Unknown"
        end
    else
        data.Owner = "Dropped/World"
    end
    
    -- Attributes & Tags
    data.Attributes = GetAttributes(obj)
    data.Tags = GetTags(obj)
    
    return data
end

local function InspectHumanoid(obj)
    local data = {}
    
    -- Basic
    data.Name = obj.Name
    data.ClassName = obj.ClassName
    data.FullPath = obj:GetFullName()
    data.Parent = obj.Parent and obj.Parent.Name or "None"
    data.ObjectType = GetObjectType(obj)
    
    -- Humanoid Stats
    data.Health = FormatNumber(obj.Health, 2)
    data.MaxHealth = FormatNumber(obj.MaxHealth, 2)
    data.HealthPercent = FormatNumber((obj.Health / obj.MaxHealth) * 100, 1) .. "%"
    data.WalkSpeed = FormatNumber(obj.WalkSpeed, 2)
    data.JumpPower = FormatNumber(obj.JumpPower, 2)
    data.JumpHeight = FormatNumber(obj.JumpHeight, 2)
    data.HipHeight = FormatNumber(obj.HipHeight, 2)
    data.MaxSlopeAngle = FormatNumber(obj.MaxSlopeAngle, 2) .. "°"
    
    -- State
    data.State = tostring(obj:GetState()):gsub("Enum.HumanoidStateType.", "")
    data.MoveDirection = FormatVector3(obj.MoveDirection)
    data.MoveSpeed = FormatNumber(obj.MoveDirection.Magnitude * obj.WalkSpeed, 2) .. " studs/s"
    
    -- Flags
    data.Sit = FormatBoolean(obj.Sit)
    data.SeatPart = obj.SeatPart and obj.SeatPart.Name or "None"
    data.PlatformStand = FormatBoolean(obj.PlatformStand)
    data.AutoRotate = FormatBoolean(obj.AutoRotate)
    data.AutoJumpEnabled = FormatBoolean(obj.AutoJumpEnabled)
    data.RequiresNeck = FormatBoolean(obj.RequiresNeck)
    data.BreakJointsOnDeath = FormatBoolean(obj.BreakJointsOnDeath)
    
    -- Display
    data.DisplayName = obj.DisplayName
    data.DisplayDistanceType = tostring(obj.DisplayDistanceType):gsub("Enum.HumanoidDisplayDistanceType.", "")
    data.HealthDisplayDistance = FormatNumber(obj.HealthDisplayDistance, 0)
    data.NameDisplayDistance = FormatNumber(obj.NameDisplayDistance, 0)
    data.HealthDisplayType = tostring(obj.HealthDisplayType):gsub("Enum.HumanoidHealthDisplayType.", "")
    data.NameOcclusion = tostring(obj.NameOcclusion):gsub("Enum.NameOcclusion.", "")
    
    -- Type
    data.RigType = tostring(obj.RigType):gsub("Enum.HumanoidRigType.", "")
    data.FloorMaterial = tostring(obj.FloorMaterial):gsub("Enum.Material.", "")
    
    -- Collision
    data.UseJumpPower = FormatBoolean(obj.UseJumpPower)
    data.EvaluateStateMachine = FormatBoolean(obj.EvaluateStateMachine)
    
    -- Accessories Count
    local accessories = {}
    if obj.Parent then
        for _, child in pairs(obj.Parent:GetChildren()) do
            if child:IsA("Accessory") then
                table.insert(accessories, child.Name)
            end
        end
    end
    data.Accessories = #accessories > 0 and accessories or {"None"}
    data.AccessoryCount = #accessories
    
    -- Body Colors
    local bodyColors = obj.Parent and obj.Parent:FindFirstChildOfClass("BodyColors")
    if bodyColors then
        data.HasBodyColors = "✅ Yes"
        data.HeadColor = FormatBrickColor(bodyColors.HeadColor)
        data.TorsoColor = FormatBrickColor(bodyColors.TorsoColor)
    else
        data.HasBodyColors = "❌ No"
    end
    
    return data
end

local function InspectSound(obj)
    local data = {}
    
    data.Name = obj.Name
    data.ClassName = obj.ClassName
    data.FullPath = obj:GetFullName()
    data.Parent = obj.Parent and obj.Parent.Name or "None"
    data.ObjectType = GetObjectType(obj)
    
    data.SoundId = obj.SoundId
    data.IsPlaying = FormatBoolean(obj.IsPlaying)
    data.IsPaused = FormatBoolean(obj.IsPaused)
    data.Playing = FormatBoolean(obj.Playing)
    data.Looped = FormatBoolean(obj.Looped)
    
    data.Volume = FormatNumber(obj.Volume, 4)
    data.Pitch = FormatNumber(obj.Pitch, 4)
    data.PlaybackSpeed = FormatNumber(obj.PlaybackSpeed, 4)
    data.TimePosition = FormatTime(obj.TimePosition)
    data.TimeLength = FormatTime(obj.TimeLength)
    data.Progress = obj.TimeLength > 0 and FormatNumber((obj.TimePosition / obj.TimeLength) * 100, 1) .. "%" or "N/A"
    
    data.RollOffMode = tostring(obj.RollOffMode):gsub("Enum.RollOffMode.", "")
    data.RollOffMinDistance = FormatNumber(obj.RollOffMinDistance, 2)
    data.RollOffMaxDistance = FormatNumber(obj.RollOffMaxDistance, 2)
    
    data.SoundGroup = obj.SoundGroup and obj.SoundGroup.Name or "None"
    
    return data
end

local function InspectLight(obj)
    local data = {}
    
    data.Name = obj.Name
    data.ClassName = obj.ClassName
    data.FullPath = obj:GetFullName()
    data.Parent = obj.Parent and obj.Parent.Name or "None"
    data.ObjectType = GetObjectType(obj)
    
    data.Enabled = FormatBoolean(obj.Enabled)
    data.Color = FormatColor3(obj.Color)
    data.Brightness = FormatNumber(obj.Brightness, 4)
    data.Shadows = FormatBoolean(obj.Shadows)
    
    if obj:IsA("PointLight") then
        data.Range = FormatNumber(obj.Range, 2) .. " studs"
    elseif obj:IsA("SpotLight") then
        data.Range = FormatNumber(obj.Range, 2) .. " studs"
        data.Angle = FormatNumber(obj.Angle, 2) .. "°"
        data.Face = tostring(obj.Face):gsub("Enum.NormalId.", "")
    elseif obj:IsA("SurfaceLight") then
        data.Range = FormatNumber(obj.Range, 2) .. " studs"
        data.Angle = FormatNumber(obj.Angle, 2) .. "°"
        data.Face = tostring(obj.Face):gsub("Enum.NormalId.", "")
    end
    
    return data
end

local function InspectParticleEmitter(obj)
    local data = {}
    
    data.Name = obj.Name
    data.ClassName = obj.ClassName
    data.FullPath = obj:GetFullName()
    data.Parent = obj.Parent and obj.Parent.Name or "None"
    data.ObjectType = GetObjectType(obj)
    
    data.Enabled = FormatBoolean(obj.Enabled)
    data.Texture = obj.Texture
    data.Rate = FormatNumber(obj.Rate, 2) .. " particles/sec"
    data.Lifetime = FormatNumber(obj.Lifetime.Min, 2) .. " - " .. FormatNumber(obj.Lifetime.Max, 2) .. " sec"
    data.Speed = FormatNumber(obj.Speed.Min, 2) .. " - " .. FormatNumber(obj.Speed.Max, 2) .. " studs/s"
    data.Rotation = FormatNumber(obj.Rotation.Min, 2) .. " - " .. FormatNumber(obj.Rotation.Max, 2) .. "°"
    data.RotSpeed = FormatNumber(obj.RotSpeed.Min, 2) .. " - " .. FormatNumber(obj.RotSpeed.Max, 2) .. "°/s"
    data.SpreadAngle = FormatVector2(obj.SpreadAngle)
    data.Acceleration = FormatVector3(obj.Acceleration)
    data.Drag = FormatNumber(obj.Drag, 4)
    data.VelocityInheritance = FormatNumber(obj.VelocityInheritance, 4)
    data.ZOffset = FormatNumber(obj.ZOffset, 2)
    data.EmissionDirection = tostring(obj.EmissionDirection):gsub("Enum.NormalId.", "")
    data.Shape = tostring(obj.Shape):gsub("Enum.ParticleEmitterShape.", "")
    data.LightEmission = FormatNumber(obj.LightEmission, 4)
    data.LightInfluence = FormatNumber(obj.LightInfluence, 4)
    
    return data
end

local function InspectProximityPrompt(obj)
    local data = {}
    
    data.Name = obj.Name
    data.ClassName = obj.ClassName
    data.FullPath = obj:GetFullName()
    data.Parent = obj.Parent and obj.Parent.Name or "None"
    data.ObjectType = GetObjectType(obj)
    
    data.Enabled = FormatBoolean(obj.Enabled)
    data.ActionText = obj.ActionText
    data.ObjectText = obj.ObjectText
    data.KeyboardKeyCode = tostring(obj.KeyboardKeyCode):gsub("Enum.KeyCode.", "")
    data.GamepadKeyCode = tostring(obj.GamepadKeyCode):gsub("Enum.KeyCode.", "")
    data.HoldDuration = FormatNumber(obj.HoldDuration, 2) .. " sec"
    data.MaxActivationDistance = FormatNumber(obj.MaxActivationDistance, 2) .. " studs"
    data.RequiresLineOfSight = FormatBoolean(obj.RequiresLineOfSight)
    data.Exclusivity = tostring(obj.Exclusivity):gsub("Enum.ProximityPromptExclusivity.", "")
    data.Style = tostring(obj.Style):gsub("Enum.ProximityPromptStyle.", "")
    data.ClickablePrompt = FormatBoolean(obj.ClickablePrompt)
    data.AutoLocalize = FormatBoolean(obj.AutoLocalize)
    
    return data
end

local function InspectClickDetector(obj)
    local data = {}
    
    data.Name = obj.Name
    data.ClassName = obj.ClassName
    data.FullPath = obj:GetFullName()
    data.Parent = obj.Parent and obj.Parent.Name or "None"
    data.ObjectType = GetObjectType(obj)
    
    data.MaxActivationDistance = FormatNumber(obj.MaxActivationDistance, 2) .. " studs"
    data.CursorIcon = obj.CursorIcon ~= "" and obj.CursorIcon or "Default"
    
    return data
end

local function InspectGeneric(obj)
    local data = {}
    
    data.Name = obj.Name
    data.ClassName = obj.ClassName
    data.FullPath = obj:GetFullName()
    data.Parent = obj.Parent and obj.Parent.Name or "None"
    data.ObjectType = GetObjectType(obj)
    data.Children = CountChildren(obj, false)
    data.Descendants = CountChildren(obj, true)
    data.HierarchyDepth = GetHierarchyDepth(obj)
    
    -- Try to get common properties
    pcall(function()
        if obj:IsA("ValueBase") then
            data.Value = tostring(obj.Value)
        end
    end)
    
    -- Attributes & Tags
    data.Attributes = GetAttributes(obj)
    data.Tags = GetTags(obj)
    
    -- Child Classes
    data.ChildClasses = GetChildrenByClass(obj)
    
    return data
end

-- ═══════════════════════════════════════════════════════════
-- 🔍 MASTER INSPECT FUNCTION
-- ═══════════════════════════════════════════════════════════

local function InspectObject(obj)
    if not obj then return nil end
    
    local data
    
    if obj:IsA("BasePart") then
        data = InspectBasePart(obj)
    elseif obj:IsA("Model") then
        data = InspectModel(obj)
    elseif obj:IsA("Tool") then
        data = InspectTool(obj)
    elseif obj:IsA("Humanoid") then
        data = InspectHumanoid(obj)
    elseif obj:IsA("Sound") then
        data = InspectSound(obj)
    elseif obj:IsA("Light") then
        data = InspectLight(obj)
    elseif obj:IsA("ParticleEmitter") then
        data = InspectParticleEmitter(obj)
    elseif obj:IsA("ProximityPrompt") then
        data = InspectProximityPrompt(obj)
    elseif obj:IsA("ClickDetector") then
        data = InspectClickDetector(obj)
    else
        data = InspectGeneric(obj)
    end
    
    return data
end

-- ═══════════════════════════════════════════════════════════
-- 📋 GENERATE FULL REPORT
-- ═══════════════════════════════════════════════════════════

local function GenerateFullReport(data)
    if not data then return "" end
    
    local report = [[
╔══════════════════════════════════════════════════════════════╗
║          🔍 ULTIMATE OBJECT INSPECTOR - FULL REPORT          ║
╚══════════════════════════════════════════════════════════════╝
Generated: ]] .. os.date("%Y-%m-%d %H:%M:%S") .. [[


═══════════════════════════════════════════════════════════════
📋 BASIC INFORMATION
═══════════════════════════════════════════════════════════════
]]
    
    local function addLine(label, value)
        if value ~= nil then
            report = report .. string.format("%-25s: %s\n", label, tostring(value))
        end
    end
    
    local function addSection(title)
        report = report .. "\n═══════════════════════════════════════════════════════════════\n"
        report = report .. title .. "\n"
        report = report .. "═══════════════════════════════════════════════════════════════\n"
    end
    
    -- Basic Info
    addLine("Name", data.Name)
    addLine("ClassName", data.ClassName)
    addLine("Type", data.ObjectType)
    addLine("Full Path", data.FullPath)
    addLine("Parent", data.Parent)
    addLine("Children", data.Children)
    addLine("Descendants", data.Descendants)
    addLine("Hierarchy Depth", data.HierarchyDepth)
    addLine("Est. Memory", data.EstimatedMemory)
    
    -- Distance
    if data.Distance then
        addSection("📏 DISTANCE & DIRECTION")
        addLine("Distance", data.Distance)
        addLine("Direction", data.Direction)
    end
    
    -- Transform
    if data.Position then
        addSection("📐 TRANSFORM & POSITION")
        addLine("Position", data.Position)
        addLine("Position (Code)", data.PositionCode)
        addLine("Rotation", data.Rotation)
        addLine("Orientation", data.Orientation)
        addLine("Size", data.Size)
        addLine("Size (Code)", data.SizeCode)
        addLine("Volume", data.Volume)
        addLine("CFrame", data.CFrame)
        addLine("LookVector", data.LookVector)
        addLine("UpVector", data.UpVector)
        addLine("RightVector", data.RightVector)
        addLine("Pivot", data.Pivot or data.PivotOffset)
    end
    
    -- Bounding Box (for Models)
    if data.BoundingBoxPosition then
        addSection("📦 BOUNDING BOX")
        addLine("BB Position", data.BoundingBoxPosition)
        addLine("BB Size", data.BoundingBoxSize)
        addLine("BB Volume", data.BoundingBoxVolume)
    end
    
    -- Physics
    if data.Anchored then
        addSection("⚡ PHYSICS PROPERTIES")
        addLine("Anchored", data.Anchored)
        addLine("CanCollide", data.CanCollide)
        addLine("CanTouch", data.CanTouch)
        addLine("CanQuery", data.CanQuery)
        addLine("Massless", data.Massless)
        addLine("Mass", data.Mass)
        addLine("Density", data.Density)
        addLine("Friction", data.Friction)
        addLine("Elasticity", data.Elasticity)
        addLine("Velocity", data.Velocity)
        addLine("Speed", data.Speed)
        addLine("Angular Velocity", data.AngularVelocity)
        addLine("Root Part", data.RootPart)
        addLine("Collision Group", data.CollisionGroup)
        addLine("Network Owner", data.NetworkOwner)
    end
    
    -- Model Stats
    if data.TotalMass then
        addSection("📊 MODEL STATISTICS")
        addLine("Total Mass", data.TotalMass)
        addLine("Part Count", data.PartCount)
        addLine("MeshPart Count", data.MeshPartCount)
        addLine("Union Count", data.UnionCount)
        addLine("Total BaseParts", data.TotalBaseParts)
        addLine("Primary Part", data.PrimaryPart)
        addLine("Streaming Mode", data.ModelStreamingMode)
        addLine("Level of Detail", data.LevelOfDetail)
    end
    
    -- Appearance
    if data.Color then
        addSection("🎨 APPEARANCE")
        addLine("Color", data.Color)
        addLine("Color (Code)", data.ColorCode)
        addLine("BrickColor", data.BrickColor)
        addLine("Material", data.Material)
        addLine("Material Variant", data.MaterialVariant)
        addLine("Transparency", data.Transparency)
        addLine("Reflectance", data.Reflectance)
        addLine("Cast Shadow", data.CastShadow)
    end
    
    -- Surface Types
    if data.TopSurface then
        addSection("🧱 SURFACE TYPES")
        addLine("Top", data.TopSurface)
        addLine("Bottom", data.BottomSurface)
        addLine("Front", data.FrontSurface)
        addLine("Back", data.BackSurface)
        addLine("Left", data.LeftSurface)
        addLine("Right", data.RightSurface)
    end
    
    -- MeshPart
    if data.MeshId then
        addSection("🔷 MESHPART PROPERTIES")
        addLine("MeshId", data.MeshId)
        addLine("TextureID", data.TextureID)
        addLine("Render Fidelity", data.RenderFidelity)
        addLine("Collision Fidelity", data.CollisionFidelity)
        addLine("Double Sided", data.DoubleSided)
    end
    
    -- Union
    if data.UsePartColor then
        addSection("🔶 UNION PROPERTIES")
        addLine("Use Part Color", data.UsePartColor)
        addLine("Smoothing Angle", data.SmoothingAngle)
    end
    
    -- Humanoid
    if data.Health or data.HasHumanoid == "✅ Yes" then
        addSection("🤖 HUMANOID PROPERTIES")
        addLine("Has Humanoid", data.HasHumanoid)
        addLine("Health", data.Health)
        addLine("Max Health", data.MaxHealth)
        addLine("Health %", data.HealthPercent)
        addLine("WalkSpeed", data.WalkSpeed)
        addLine("JumpPower", data.JumpPower)
        addLine("JumpHeight", data.JumpHeight)
        addLine("HipHeight", data.HipHeight)
        addLine("Max Slope Angle", data.MaxSlopeAngle)
        addLine("State", data.State or data.HumanoidState)
        addLine("Move Direction", data.MoveDirection)
        addLine("Move Speed", data.MoveSpeed)
        addLine("Sit", data.Sit)
        addLine("Seat Part", data.SeatPart)
        addLine("Platform Stand", data.PlatformStand)
        addLine("Auto Rotate", data.AutoRotate)
        addLine("Auto Jump", data.AutoJumpEnabled)
        addLine("Display Name", data.DisplayName)
        addLine("Rig Type", data.RigType)
        addLine("Floor Material", data.FloorMaterial)
        addLine("Name Occlusion", data.NameOcclusion)
        addLine("Health Display", data.HealthDisplayType)
    end
    
    -- Player Info
    if data.IsPlayerCharacter == "✅ Yes" then
        addSection("👤 PLAYER INFORMATION")
        addLine("Is Player", data.IsPlayerCharacter)
        addLine("Player Name", data.PlayerName)
        addLine("Display Name", data.PlayerDisplayName)
        addLine("UserId", data.PlayerUserId)
        addLine("Account Age", data.PlayerAccountAge)
        addLine("Team", data.PlayerTeam)
        addLine("Membership", data.PlayerMembership)
    end
    
    -- Tool Properties
    if data.ToolTip then
        addSection("🔧 TOOL PROPERTIES")
        addLine("ToolTip", data.ToolTip)
        addLine("Requires Handle", data.RequiresHandle)
        addLine("Can Be Dropped", data.CanBeDropped)
        addLine("Manual Activation", data.ManualActivationOnly)
        addLine("Enabled", data.Enabled)
        addLine("Has Handle", data.HasHandle)
        addLine("Handle Position", data.HandlePosition)
        addLine("Handle Size", data.HandleSize)
        addLine("Grip", data.Grip)
        addLine("TextureId", data.TextureId)
        addLine("Owner", data.Owner)
    end
    
    -- Sound Properties
    if data.SoundId then
        addSection("🔊 SOUND PROPERTIES")
        addLine("SoundId", data.SoundId)
        addLine("Is Playing", data.IsPlaying)
        addLine("Is Paused", data.IsPaused)
        addLine("Looped", data.Looped)
        addLine("Volume", data.Volume)
        addLine("Pitch", data.Pitch)
        addLine("Playback Speed", data.PlaybackSpeed)
        addLine("Time Position", data.TimePosition)
        addLine("Time Length", data.TimeLength)
        addLine("Progress", data.Progress)
        addLine("RollOff Mode", data.RollOffMode)
        addLine("RollOff Min", data.RollOffMinDistance)
        addLine("RollOff Max", data.RollOffMaxDistance)
        addLine("Sound Group", data.SoundGroup)
    end
    
    -- Light Properties
    if data.Brightness and data.Shadows then
        addSection("💡 LIGHT PROPERTIES")
        addLine("Enabled", data.Enabled)
        addLine("Color", data.Color)
        addLine("Brightness", data.Brightness)
        addLine("Shadows", data.Shadows)
        addLine("Range", data.Range)
        addLine("Angle", data.Angle)
        addLine("Face", data.Face)
    end
    
    -- Particle Properties
    if data.Rate then
        addSection("✨ PARTICLE PROPERTIES")
        addLine("Enabled", data.Enabled)
        addLine("Texture", data.Texture)
        addLine("Rate", data.Rate)
        addLine("Lifetime", data.Lifetime)
        addLine("Speed", data.Speed)
        addLine("Rotation", data.Rotation)
        addLine("Rot Speed", data.RotSpeed)
        addLine("Spread Angle", data.SpreadAngle)
        addLine("Acceleration", data.Acceleration)
        addLine("Drag", data.Drag)
        addLine("Emission Direction", data.EmissionDirection)
        addLine("Shape", data.Shape)
        addLine("Light Emission", data.LightEmission)
    end
    
    -- ProximityPrompt
    if data.ActionText then
        addSection("💬 PROXIMITY PROMPT")
        addLine("Enabled", data.Enabled)
        addLine("Action Text", data.ActionText)
        addLine("Object Text", data.ObjectText)
        addLine("Keyboard Key", data.KeyboardKeyCode)
        addLine("Gamepad Key", data.GamepadKeyCode)
        addLine("Hold Duration", data.HoldDuration)
        addLine("Max Distance", data.MaxActivationDistance)
        addLine("Line of Sight", data.RequiresLineOfSight)
        addLine("Exclusivity", data.Exclusivity)
        addLine("Style", data.Style)
    end
    
    -- Special Components
    if data.HasClickDetector then
        addSection("🔌 SPECIAL COMPONENTS")
        addLine("Click Detector", data.HasClickDetector)
        addLine("Proximity Prompt", data.HasProximityPrompt)
        addLine("Sound", data.HasSound)
        addLine("Particles", data.HasParticles)
        addLine("Light", data.HasLight)
        addLine("Decal", data.HasDecal)
        addLine("Texture", data.HasTexture)
        addLine("Script", data.HasScript)
    end
    
    -- Constraints
    if data.Constraints and #data.Constraints > 0 and data.Constraints[1] ~= "None" then
        addSection("⛓️ CONSTRAINTS")
        for i, constraint in ipairs(data.Constraints) do
            report = report .. string.format("  [%d] %s\n", i, constraint)
        end
    end
    
    -- Joints
    if data.Joints and #data.Joints > 0 and data.Joints[1] ~= "None" then
        addSection("🔗 JOINTS & WELDS")
        for i, joint in ipairs(data.Joints) do
            report = report .. string.format("  [%d] %s\n", i, joint)
        end
    end
    
    -- Accessories
    if data.Accessories and #data.Accessories > 0 and data.Accessories[1] ~= "None" then
        addSection("👒 ACCESSORIES")
        addLine("Count", data.AccessoryCount)
        for i, acc in ipairs(data.Accessories) do
            report = report .. string.format("  [%d] %s\n", i, acc)
        end
    end
    
    -- Attributes
    if data.Attributes and #data.Attributes > 0 then
        addSection("📊 ATTRIBUTES")
        for _, attr in ipairs(data.Attributes) do
            report = report .. string.format("  %s (%s): %s\n", attr.Name, attr.Type, attr.Value)
        end
    end
    
    -- Tags
    if data.Tags and #data.Tags > 0 then
        addSection("🏷️ TAGS")
        for i, tag in ipairs(data.Tags) do
            report = report .. string.format("  [%d] %s\n", i, tag)
        end
    end
    
    -- Child Classes
    if data.ChildClasses and next(data.ChildClasses) then
        addSection("🌳 CHILD CLASSES BREAKDOWN")
        for className, count in pairs(data.ChildClasses) do
            report = report .. string.format("  %-25s: %d\n", className, count)
        end
    end
    
    -- Value (for ValueBase)
    if data.Value then
        addSection("📈 VALUE")
        addLine("Value", data.Value)
    end
    
    report = report .. [[

═══════════════════════════════════════════════════════════════
                    END OF REPORT
═══════════════════════════════════════════════════════════════
]]
    
    return report
end

-- ═══════════════════════════════════════════════════════════
-- 🔄 UPDATE GUI FUNCTION
-- ═══════════════════════════════════════════════════════════

local function UpdateInspectorGUI()
    if not SelectedObject then
        CopiedData = ""
        return
    end
    
    -- Check if object still exists
    local success = pcall(function() local _ = SelectedObject.Parent end)
    if not success then
        SelectedObject = nil
        RemoveHighlight()
        CurrentSelectionLabel:Set("📦 Selected: [DELETED]")
        ObjectTypeLabel:Set("📁 Type: N/A")
        DistanceLabel:Set("📏 Distance: N/A")
        DirectionLabel:Set("🧭 Direction: N/A")
        CopiedData = ""
        return
    end
    
    -- Get inspection data
    local data = InspectObject(SelectedObject)
    if not data then return end
    
    -- Generate full report for copy
    CopiedData = GenerateFullReport(data)
    
    -- Update Selection Labels
    CurrentSelectionLabel:Set("📦 Selected: " .. (data.Name or "Unknown"))
    ObjectTypeLabel:Set("📁 Type: " .. (data.ObjectType or "Unknown"))
    
    -- Update Distance & Direction
    if data.Distance then
        DistanceLabel:Set("📏 Distance: " .. data.Distance)
        DirectionLabel:Set("🧭 Direction: " .. (data.Direction or "N/A"))
    end
    
    -- Update Basic Info
    NameLabel:Set("Name: " .. (data.Name or "N/A"))
    ClassLabel:Set("ClassName: " .. (data.ClassName or "N/A"))
    FullPathLabel:Set("Path: " .. (data.FullPath or "N/A"))
    ParentLabel:Set("Parent: " .. (data.Parent or "N/A"))
    ChildrenLabel:Set("Children: " .. (data.Children or "N/A"))
    DescendantsLabel:Set("Descendants: " .. (data.Descendants or "N/A"))
    MemoryLabel:Set("Est. Memory: " .. (data.EstimatedMemory or "N/A"))
    DepthLabel:Set("Hierarchy Depth: " .. (data.HierarchyDepth or "N/A"))
    
    -- Update Transform
    PositionLabel:Set("Position: " .. (data.Position or data.BoundingBoxPosition or "N/A"))
    RotationLabel:Set("Rotation: " .. (data.Rotation or "N/A"))
    OrientationLabel:Set("Orientation: " .. (data.Orientation or "N/A"))
    SizeLabel:Set("Size: " .. (data.Size or data.BoundingBoxSize or "N/A"))
    VolumeLabel:Set("Volume: " .. (data.Volume or data.BoundingBoxVolume or "N/A"))
    LookVectorLabel:Set("LookVector: " .. (data.LookVector or "N/A"))
    UpVectorLabel:Set("UpVector: " .. (data.UpVector or "N/A"))
    RightVectorLabel:Set("RightVector: " .. (data.RightVector or "N/A"))
    PivotLabel:Set("Pivot Offset: " .. (data.PivotOffset or data.Pivot or "N/A"))
    
    -- Update Physics
    AnchoredLabel:Set("Anchored: " .. (data.Anchored or "N/A"))
    CanCollideLabel:Set("CanCollide: " .. (data.CanCollide or "N/A"))
    CanTouchLabel:Set("CanTouch: " .. (data.CanTouch or "N/A"))
    CanQueryLabel:Set("CanQuery: " .. (data.CanQuery or "N/A"))
    MassLabel:Set("Mass: " .. (data.Mass or data.TotalMass or "N/A"))
    DensityLabel:Set("Density: " .. (data.Density or "N/A"))
    VelocityLabel:Set("Velocity: " .. (data.Velocity or data.HumanoidRootPartVelocity or "N/A"))
    AngularVelocityLabel:Set("Angular Velocity: " .. (data.AngularVelocity or "N/A"))
    RootPartLabel:Set("RootPart: " .. (data.RootPart or data.PrimaryPart or "N/A"))
    CollisionGroupLabel:Set("Collision Group: " .. (data.CollisionGroup or "N/A"))
    NetworkOwnerLabel:Set("Network Owner: " .. (data.NetworkOwner or "N/A"))
    
    -- Update Appearance
    ColorLabel:Set("Color: " .. (data.Color or "N/A"))
    BrickColorLabel:Set("BrickColor: " .. (data.BrickColor or "N/A"))
    MaterialLabel:Set("Material: " .. (data.Material or "N/A"))
    MaterialVariantLabel:Set("Material Variant: " .. (data.MaterialVariant or "N/A"))
    TransparencyLabel:Set("Transparency: " .. (data.Transparency or "N/A"))
    ReflectanceLabel:Set("Reflectance: " .. (data.Reflectance or "N/A"))
    CastShadowLabel:Set("CastShadow: " .. (data.CastShadow or "N/A"))
    
    if data.TopSurface then
        SurfaceTypesLabel:Set("Surfaces: T:" .. data.TopSurface .. " B:" .. data.BottomSurface .. " F:" .. data.FrontSurface)
    else
        SurfaceTypesLabel:Set("Surface Types: N/A")
    end
    
    -- Update Humanoid
    if data.Health or data.HasHumanoid == "✅ Yes" then
        HealthLabel:Set("Health: " .. (data.Health or "N/A"))
        MaxHealthLabel:Set("MaxHealth: " .. (data.MaxHealth or "N/A"))
        WalkSpeedLabel:Set("WalkSpeed: " .. (data.WalkSpeed or "N/A"))
        JumpPowerLabel:Set("JumpPower: " .. (data.JumpPower or "N/A"))
        JumpHeightLabel:Set("JumpHeight: " .. (data.JumpHeight or "N/A"))
        HipHeightLabel:Set("HipHeight: " .. (data.HipHeight or "N/A"))
        StateLabel:Set("State: " .. (data.State or data.HumanoidState or "N/A"))
        SitLabel:Set("Sit: " .. (data.Sit or "N/A") .. " | Seat: " .. (data.SeatPart or "N/A"))
        DisplayNameLabel:Set("DisplayName: " .. (data.DisplayName or "N/A"))
        RigTypeLabel:Set("RigType: " .. (data.RigType or "N/A"))
    else
        HealthLabel:Set("Health: N/A (No Humanoid)")
        MaxHealthLabel:Set("MaxHealth: N/A")
        WalkSpeedLabel:Set("WalkSpeed: N/A")
        JumpPowerLabel:Set("JumpPower: N/A")
        JumpHeightLabel:Set("JumpHeight: N/A")
        HipHeightLabel:Set("HipHeight: N/A")
        StateLabel:Set("State: N/A")
        SitLabel:Set("Sit: N/A")
        DisplayNameLabel:Set("DisplayName: N/A")
        RigTypeLabel:Set("RigType: N/A")
    end
    
    -- Update Attributes
    if data.Attributes and #data.Attributes > 0 then
        local attrStr = ""
        for i, attr in ipairs(data.Attributes) do
            if i <= 5 then
                attrStr = attrStr .. attr.Name .. "=" .. attr.Value .. "; "
            end
        end
        if #data.Attributes > 5 then
            attrStr = attrStr .. "(+" .. (#data.Attributes - 5) .. " more)"
        end
        AttributesLabel:Set("Attributes: " .. attrStr)
    else
        AttributesLabel:Set("Attributes: None")
    end
    
    -- Update Tags
    if data.Tags and #data.Tags > 0 then
        TagsLabel:Set("Tags: " .. table.concat(data.Tags, ", "))
    else
        TagsLabel:Set("Tags: None")
    end
    
    -- Update Child Classes
    if data.ChildClasses and next(data.ChildClasses) then
        local classStr = ""
        local count = 0
        for className, num in pairs(data.ChildClasses) do
            if count < 4 then
                classStr = classStr .. className .. "(" .. num .. ") "
                count = count + 1
            end
        end
        ChildClassesLabel:Set("Child Classes: " .. classStr)
    else
        ChildClassesLabel:Set("Child Classes: None")
    end
end

-- ═══════════════════════════════════════════════════════════
-- 👤 UPDATE PLAYER INFO FUNCTION
-- ═══════════════════════════════════════════════════════════

local function UpdatePlayerInfo()
    -- Team Update
    PTeamLabel:Set("Team: " .. (Player.Team and Player.Team.Name or "None"))
    
    -- Character Info
    if Player.Character and Player.Character:FindFirstChild("HumanoidRootPart") then
        local hrp = Player.Character.HumanoidRootPart
        local humanoid = Player.Character:FindFirstChildOfClass("Humanoid")
        
        CharPosLabel:Set("Position: " .. FormatVector3Short(hrp.Position))
        CharVelocityLabel:Set("Velocity: " .. FormatVector3Short(hrp.AssemblyLinearVelocity))
        CharSpeedLabel:Set("Current Speed: " .. FormatNumber(hrp.AssemblyLinearVelocity.Magnitude, 2) .. " studs/s")
        
        if humanoid then
            CharHealthLabel:Set("Health: " .. FormatNumber(humanoid.Health, 1) .. "/" .. FormatNumber(humanoid.MaxHealth, 1))
            CharWalkLabel:Set("WalkSpeed: " .. FormatNumber(humanoid.WalkSpeed, 2))
            CharJumpLabel:Set("JumpPower: " .. FormatNumber(humanoid.JumpPower, 2))
            CharLookLabel:Set("Look Direction: " .. FormatVector3Short(hrp.CFrame.LookVector))
            CharMoveLabel:Set("Move Direction: " .. FormatVector3Short(humanoid.MoveDirection))
            CharStateLabel:Set("State: " .. tostring(humanoid:GetState()):gsub("Enum.HumanoidStateType.", ""))
            CharFloorLabel:Set("Floor Material: " .. tostring(humanoid.FloorMaterial):gsub("Enum.Material.", ""))
        end
    else
        CharPosLabel:Set("Position: Character not found")
        CharVelocityLabel:Set("Velocity: N/A")
        CharSpeedLabel:Set("Current Speed: N/A")
        CharHealthLabel:Set("Health: N/A")
    end
    
    -- Camera Info
    CamPosLabel:Set("Position: " .. FormatVector3Short(Camera.CFrame.Position))
    CamLookLabel:Set("Look Vector: " .. FormatVector3Short(Camera.CFrame.LookVector))
    CamFOVLabel:Set("FOV: " .. FormatNumber(Camera.FieldOfView, 1) .. "°")
    CamTypeLabel:Set("Type: " .. tostring(Camera.CameraType):gsub("Enum.CameraType.", ""))
    CamFocusLabel:Set("Focus: " .. FormatVector3Short(Camera.Focus.Position))
    CamSubjectLabel:Set("Subject: " .. (Camera.CameraSubject and Camera.CameraSubject.Name or "None"))
    
    if Camera.CameraSubject and Camera.CameraSubject:IsA("Humanoid") then
        local subjectPos = Camera.CameraSubject.Parent:FindFirstChild("HumanoidRootPart")
        if subjectPos then
            local dist = (Camera.CFrame.Position - subjectPos.Position).Magnitude
            CamDistLabel:Set("View Distance: " .. FormatNumber(dist, 2) .. " studs")
        end
    else
        CamDistLabel:Set("View Distance: N/A")
    end
    
    -- Tools
    local equippedTool = Player.Character and Player.Character:FindFirstChildOfClass("Tool")
    EquippedToolLabel:Set("Equipped: " .. (equippedTool and equippedTool.Name or "None"))
    
    local backpackItems = {}
    for _, item in pairs(Player.Backpack:GetChildren()) do
        if item:IsA("Tool") then
            table.insert(backpackItems, item.Name)
        end
    end
    BackpackLabel:Set("Backpack: " .. (#backpackItems > 0 and table.concat(backpackItems, ", ") or "Empty"))
end

-- ═══════════════════════════════════════════════════════════
-- 🌍 UPDATE WORLD INFO FUNCTION
-- ═══════════════════════════════════════════════════════════

local function UpdateWorldInfo()
    -- Player Count
    PlayerCountLabel:Set("Players: " .. #Players:GetPlayers() .. "/" .. Players.MaxPlayers)
    
    -- Server Time
    ServerTimeLabel:Set("Server Time: " .. FormatTime(Workspace:GetServerTimeNow()))
    
    -- Lighting
    LightingTimeLabel:Set("Time of Day: " .. Lighting.TimeOfDay)
    AmbientLabel:Set("Ambient: " .. FormatColor3(Lighting.Ambient))
    BrightnessLabel:Set("Brightness: " .. Lighting.Brightness)
    FogLabel:Set("Fog: " .. Lighting.FogStart .. " - " .. Lighting.FogEnd)
    GravityLabel:Set("Gravity: " .. Workspace.Gravity .. " studs/s²")
end

-- ═══════════════════════════════════════════════════════════
-- ⌨️ INPUT HANDLING
-- ═══════════════════════════════════════════════════════════

UserInputService.InputBegan:Connect(function(input, gameProcessed)
    if gameProcessed then return end
    
    -- Quick Select (Q)
    if input.KeyCode == Settings.SelectHotkey then
        if Mouse.Target then
            SelectedObject = Mouse.Target
            CreateHighlight(Mouse.Target)
            CurrentSelectionLabel:Set("📦 Selected: " .. Mouse.Target.Name)
            ObjectTypeLabel:Set("📁 Type: " .. GetObjectType(Mouse.Target))
            
            local dist = GetDistance(Mouse.Target)
            DistanceLabel:Set("📏 Distance: " .. dist)
            DirectionLabel:Set("🧭 Direction: " .. GetDirectionTo(Mouse.Target))
            
            -- Force immediate update
            UpdateInspectorGUI()
            
            Rayfield:Notify({
                Title = "⚡ Quick Select",
                Content = Mouse.Target.Name .. " (" .. Mouse.Target.ClassName .. ")",
                Duration = 1.5
            })
        end
    end
    
    -- Clear (X)
    if input.KeyCode == Settings.ClearHotkey then
        SelectedObject = nil
        RemoveHighlight()
        CurrentSelectionLabel:Set("📦 Selected: None")
        ObjectTypeLabel:Set("📁 Type: N/A")
        DistanceLabel:Set("📏 Distance: N/A")
        DirectionLabel:Set("🧭 Direction: N/A")
        CopiedData = ""
        Rayfield:Notify({
            Title = "🗑️ Cleared",
            Content = "Selection cleared!",
            Duration = 1
        })
    end
end)

-- ═══════════════════════════════════════════════════════════
-- 🔁 MAIN UPDATE LOOP
-- ═══════════════════════════════════════════════════════════

local lastInspectorUpdate = 0
local lastPlayerUpdate = 0
local lastWorldUpdate = 0

RunService.Heartbeat:Connect(function()
    local currentTime = tick()
    
    -- Update Inspector (if auto refresh enabled)
    if Settings.AutoRefresh and SelectedObject then
        if currentTime - lastInspectorUpdate >= Settings.RefreshRate then
            lastInspectorUpdate = currentTime
            pcall(UpdateInspectorGUI)
        end
    end
    
    -- Update Player Info every 0.2 seconds
    if currentTime - lastPlayerUpdate >= 0.2 then
        lastPlayerUpdate = currentTime
        pcall(UpdatePlayerInfo)
    end
    
    -- Update World Info every 1 second
    if currentTime - lastWorldUpdate >= 1 then
        lastWorldUpdate = currentTime
        pcall(UpdateWorldInfo)
    end
end)

-- ═══════════════════════════════════════════════════════════
-- 🧹 CLEANUP ON PLAYER LEAVING
-- ═══════════════════════════════════════════════════════════

Player.AncestryChanged:Connect(function()
    RemoveHighlight()
end)

-- ═══════════════════════════════════════════════════════════
-- ✅ INITIALIZATION COMPLETE
-- ═══════════════════════════════════════════════════════════

Rayfield:Notify({
    Title = "🔍 Ultimate Inspector Loaded!",
    Content = "Press Q to quick select objects. View full details in Inspector tab!",
    Duration = 5
})

print("═══════════════════════════════════════════════════════════════")
print("✅ [INSPECTOR] Part 2 loaded successfully!")
print("✅ [INSPECTOR] Ultimate Object Inspector is now active!")
print("═══════════════════════════════════════════════════════════════")
print("")
print("📌 HOTKEYS:")
print("   Q - Quick select object under cursor")
print("   X - Clear current selection")
print("   RightShift - Toggle GUI visibility (Rayfield default)")
print("")
print("📋 FEATURES:")
print("   • Inspect any object in detail")
print("   • Real-time distance & direction tracking")
print("   • Copy any data to clipboard")
print("   • Player & World info tabs")
print("   • Custom highlight system")
print("   • Auto-refresh capability")
print("")
print("═══════════════════════════════════════════════════════════════")

Features & Information

Make with AI

Community Comments (1)

hygg520hygg520Aug 30, 2026

so good

More Scripts for Universal Scripts