-- Auto Proximity Prompt GUI with Enhanced Performance Monitoring -- Place this script in StarterPlayerScripts local Players = game:GetService("Players") local TweenService = game:GetService("TweenService") local RunService = game:GetService("RunService") local ProximityPromptService = game:GetService("ProximityPromptService") local UserInputService = game:GetService("UserInputService") local player = Players.LocalPlayer local playerGui = player:WaitForChild("PlayerGui") -- Close any existing instances of this GUI for _, gui in pairs(playerGui:GetChildren()) do if gui.Name == "AutoProximityGUI" then gui:Destroy() end end -- Performance tracking variables local performanceLog = {} local currentSession = { startTime = 0, promptsUsed = 0, totalSearchTime = 0, totalWaitTime = 0, failedAttempts = 0, averageDistance = 0, distanceSum = 0, loopIterations = 0, checks = { duplicatePromptCheck = 0, rangeValidationCheck = 0, promptEnabledCheck = 0, characterValidationCheck = 0, promptParentCheck = 0, distanceCalculationCheck = 0, holdDurationCheck = 0, promptCooldownCheck = 0, workspaceTraversalCheck = 0, memoryOptimizationCheck = 0 } } -- Create main GUI local screenGui = Instance.new("ScreenGui") screenGui.Name = "AutoProximityGUI" screenGui.ResetOnSpawn = false screenGui.Parent = playerGui -- Main frame (moveable) local mainFrame = Instance.new("Frame") mainFrame.Name = "MainFrame" mainFrame.Size = UDim2.new(0, 320, 0, 200) mainFrame.Position = UDim2.new(0.5, -160, 0.5, -100) mainFrame.BackgroundColor3 = Color3.fromRGB(45, 45, 45) mainFrame.BorderSizePixel = 0 mainFrame.Parent = screenGui -- Add corner radius local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 8) corner.Parent = mainFrame -- Title bar for dragging local titleBar = Instance.new("Frame") titleBar.Name = "TitleBar" titleBar.Size = UDim2.new(1, 0, 0, 30) titleBar.Position = UDim2.new(0, 0, 0, 0) titleBar.BackgroundColor3 = Color3.fromRGB(35, 35, 35) titleBar.BorderSizePixel = 0 titleBar.Parent = mainFrame local titleCorner = Instance.new("UICorner") titleCorner.CornerRadius = UDim.new(0, 8) titleCorner.Parent = titleBar -- Title text local titleLabel = Instance.new("TextLabel") titleLabel.Size = UDim2.new(1, -10, 1, 0) titleLabel.Position = UDim2.new(0, 5, 0, 0) titleLabel.BackgroundTransparency = 1 titleLabel.Text = "Auto Proximity v2.3" titleLabel.TextColor3 = Color3.fromRGB(255, 255, 255) titleLabel.TextScaled = true titleLabel.TextXAlignment = Enum.TextXAlignment.Left titleLabel.Font = Enum.Font.GothamBold titleLabel.Parent = titleBar -- Status label local statusLabel = Instance.new("TextLabel") statusLabel.Size = UDim2.new(1, -20, 0, 20) statusLabel.Position = UDim2.new(0, 10, 0, 35) statusLabel.BackgroundTransparency = 1 statusLabel.Text = "Status: Stopped" statusLabel.TextColor3 = Color3.fromRGB(255, 100, 100) statusLabel.TextScaled = true statusLabel.Font = Enum.Font.Gotham statusLabel.Parent = mainFrame -- Distance label local distanceLabel = Instance.new("TextLabel") distanceLabel.Size = UDim2.new(1, -20, 0, 15) distanceLabel.Position = UDim2.new(0, 10, 0, 55) distanceLabel.BackgroundTransparency = 1 distanceLabel.Text = "Distance: --" distanceLabel.TextColor3 = Color3.fromRGB(200, 200, 200) distanceLabel.TextScaled = true distanceLabel.Font = Enum.Font.Gotham distanceLabel.Parent = mainFrame -- Performance stats label local performanceLabel = Instance.new("TextLabel") performanceLabel.Size = UDim2.new(1, -20, 0, 15) performanceLabel.Position = UDim2.new(0, 10, 0, 70) performanceLabel.BackgroundTransparency = 1 performanceLabel.Text = "Prompts: 0 | Avg Time: 0ms" performanceLabel.TextColor3 = Color3.fromRGB(150, 200, 255) performanceLabel.TextScaled = true performanceLabel.Font = Enum.Font.Gotham performanceLabel.Parent = mainFrame -- Efficiency label local efficiencyLabel = Instance.new("TextLabel") efficiencyLabel.Size = UDim2.new(1, -20, 0, 15) efficiencyLabel.Position = UDim2.new(0, 10, 0, 85) efficiencyLabel.BackgroundTransparency = 1 efficiencyLabel.Text = "Efficiency: 100% | Checks: 0" efficiencyLabel.TextColor3 = Color3.fromRGB(100, 255, 150) efficiencyLabel.TextScaled = true efficiencyLabel.Font = Enum.Font.Gotham efficiencyLabel.Parent = mainFrame -- Button container local buttonContainer = Instance.new("Frame") buttonContainer.Size = UDim2.new(1, -20, 0, 60) buttonContainer.Position = UDim2.new(0, 10, 0, 105) buttonContainer.BackgroundTransparency = 1 buttonContainer.Parent = mainFrame -- Create a grid layout for buttons local buttonLayout = Instance.new("UIGridLayout") buttonLayout.CellSize = UDim2.new(0, 90, 0, 25) buttonLayout.CellPadding = UDim2.new(0, 5, 0, 5) buttonLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center buttonLayout.VerticalAlignment = Enum.VerticalAlignment.Top buttonLayout.Parent = buttonContainer -- Start button local startButton = Instance.new("TextButton") startButton.Size = UDim2.new(0, 90, 0, 25) startButton.BackgroundColor3 = Color3.fromRGB(100, 200, 100) startButton.BorderSizePixel = 0 startButton.Text = "Start" startButton.TextColor3 = Color3.fromRGB(255, 255, 255) startButton.TextScaled = true startButton.Font = Enum.Font.GothamBold startButton.Parent = buttonContainer local startCorner = Instance.new("UICorner") startCorner.CornerRadius = UDim.new(0, 4) startCorner.Parent = startButton -- Stop button local stopButton = Instance.new("TextButton") stopButton.Size = UDim2.new(0, 90, 0, 25) stopButton.BackgroundColor3 = Color3.fromRGB(200, 100, 100) stopButton.BorderSizePixel = 0 stopButton.Text = "Stop" stopButton.TextColor3 = Color3.fromRGB(255, 255, 255) stopButton.TextScaled = true stopButton.Font = Enum.Font.GothamBold stopButton.Parent = buttonContainer local stopCorner = Instance.new("UICorner") stopCorner.CornerRadius = UDim.new(0, 4) stopCorner.Parent = stopButton -- Exit button local exitButton = Instance.new("TextButton") exitButton.Size = UDim2.new(0, 90, 0, 25) exitButton.BackgroundColor3 = Color3.fromRGB(150, 150, 150) exitButton.BorderSizePixel = 0 exitButton.Text = "Exit" exitButton.TextColor3 = Color3.fromRGB(255, 255, 255) exitButton.TextScaled = true exitButton.Font = Enum.Font.GothamBold exitButton.Parent = buttonContainer local exitCorner = Instance.new("UICorner") exitCorner.CornerRadius = UDim.new(0, 4) exitCorner.Parent = exitButton -- Reset Stats button local resetButton = Instance.new("TextButton") resetButton.Size = UDim2.new(0, 90, 0, 25) resetButton.BackgroundColor3 = Color3.fromRGB(100, 150, 200) resetButton.BorderSizePixel = 0 resetButton.Text = "Reset" resetButton.TextColor3 = Color3.fromRGB(255, 255, 255) resetButton.TextScaled = true resetButton.Font = Enum.Font.GothamBold resetButton.Parent = buttonContainer local resetCorner = Instance.new("UICorner") resetCorner.CornerRadius = UDim.new(0, 4) resetCorner.Parent = resetButton -- Copy Log button local copyLogButton = Instance.new("TextButton") copyLogButton.Size = UDim2.new(0, 90, 0, 25) copyLogButton.BackgroundColor3 = Color3.fromRGB(200, 150, 100) copyLogButton.BorderSizePixel = 0 copyLogButton.Text = "Copy Log" copyLogButton.TextColor3 = Color3.fromRGB(255, 255, 255) copyLogButton.TextScaled = true copyLogButton.Font = Enum.Font.GothamBold copyLogButton.Parent = buttonContainer local copyLogCorner = Instance.new("UICorner") copyLogCorner.CornerRadius = UDim.new(0, 4) copyLogCorner.Parent = copyLogButton -- Debug Mode button local debugButton = Instance.new("TextButton") debugButton.Size = UDim2.new(0, 90, 0, 25) debugButton.BackgroundColor3 = Color3.fromRGB(150, 100, 200) debugButton.BorderSizePixel = 0 debugButton.Text = "Debug" debugButton.TextColor3 = Color3.fromRGB(255, 255, 255) debugButton.TextScaled = true debugButton.Font = Enum.Font.GothamBold debugButton.Parent = buttonContainer local debugCorner = Instance.new("UICorner") debugCorner.CornerRadius = UDim.new(0, 4) debugCorner.Parent = debugButton -- Variables for functionality local isRunning = false local debugMode = false local dragStart = nil local startPos = nil local lastUsedPrompt = nil local promptCooldowns = {} local currentPrompt = nil -- Enhanced performance tracking functions local function logEvent(eventType, data) table.insert(performanceLog, { timestamp = tick(), event = eventType, data = data or {}, promptName = data.prompt or "N/A", distance = data.distance or 0, errorMsg = data.error or "N/A", duration = data.duration or 0 }) -- Keep log size manageable if #performanceLog > 1000 then table.remove(performanceLog, 1) end end local function updatePerformanceDisplay() local runtime = tick() - currentSession.startTime local avgSearchTime = currentSession.totalSearchTime / math.max(currentSession.promptsUsed + currentSession.failedAttempts, 1) local totalChecks = 0 for _, count in pairs(currentSession.checks) do totalChecks = totalChecks + count end performanceLabel.Text = string.format("Prompts: %d | Avg Time: %.0fms", currentSession.promptsUsed, avgSearchTime * 1000) local efficiency = 100 if currentSession.promptsUsed > 0 or currentSession.failedAttempts > 0 then efficiency = math.floor((currentSession.promptsUsed / (currentSession.promptsUsed + currentSession.failedAttempts)) * 100) end efficiencyLabel.Text = string.format("Efficiency: %d%% | Checks: %d", efficiency, totalChecks) end -- Dragging functionality local function updateInput(input) local delta = input.Position - dragStart local position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y) mainFrame.Position = position end titleBar.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragStart = input.Position startPos = mainFrame.Position local connection connection = input.Changed:Connect(function() if input.UserInputState == Enum.UserInputState.End then connection:Disconnect() end end) end end) titleBar.InputChanged:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseMovement then if dragStart then updateInput(input) end end end) UserInputService.InputChanged:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseMovement and dragStart then updateInput(input) end end) UserInputService.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragStart = nil end end) -- Optimized prompt finding with caching local promptCache = {} local function findNearestProximityPrompt() local searchStartTime = tick() local character = player.Character -- Check 1: Character Validation Check currentSession.checks.characterValidationCheck = currentSession.checks.characterValidationCheck + 1 if not character or not character:FindFirstChild("HumanoidRootPart") then logEvent("CHARACTER_INVALID", {error = "No character or HumanoidRootPart"}) return nil, math.huge end local playerPosition = character.HumanoidRootPart.Position local nearestPrompt = nil local nearestDistance = math.huge local promptsChecked = 0 -- Check 2: Workspace Traversal Optimization Check currentSession.checks.workspaceTraversalCheck = currentSession.checks.workspaceTraversalCheck + 1 -- Update cache if needed if #promptCache == 0 then local function searchForPrompts(parent, depth) if depth > 10 then return end for _, child in pairs(parent:GetChildren()) do if child:IsA("ProximityPrompt") then table.insert(promptCache, child) end searchForPrompts(child, depth + 1) end end searchForPrompts(workspace, 0) logEvent("CACHE_REFRESHED", {count = #promptCache}) end for _, prompt in ipairs(promptCache) do promptsChecked = promptsChecked + 1 -- Check 3: Prompt Enabled Check currentSession.checks.promptEnabledCheck = currentSession.checks.promptEnabledCheck + 1 if not prompt.Enabled or not prompt.Parent then if debugMode then logEvent("PROMPT_INVALID", {prompt = prompt.Name, error = "Disabled or no parent"}) end continue end -- Check 4: Duplicate Prompt Check currentSession.checks.duplicatePromptCheck = currentSession.checks.duplicatePromptCheck + 1 if prompt == lastUsedPrompt and promptCooldowns[tostring(prompt)] then if debugMode then logEvent("DUPLICATE_PROMPT", {prompt = prompt.Name}) end continue end -- Check 5: Prompt Cooldown Check currentSession.checks.promptCooldownCheck = currentSession.checks.promptCooldownCheck + 1 local promptId = tostring(prompt) if promptCooldowns[promptId] and tick() - promptCooldowns[promptId] < 0.5 then if debugMode then logEvent("PROMPT_COOLDOWN", {prompt = prompt.Name}) end continue end -- Check 6: Prompt Parent Validation Check currentSession.checks.promptParentCheck = currentSession.checks.promptParentCheck + 1 local promptParent = prompt.Parent if not promptParent then if debugMode then logEvent("NO_PARENT", {prompt = prompt.Name}) end continue end local distance = math.huge -- Check 7: Distance Calculation Optimization Check currentSession.checks.distanceCalculationCheck = currentSession.checks.distanceCalculationCheck + 1 if promptParent:IsA("BasePart") then distance = (playerPosition - promptParent.Position).Magnitude elseif promptParent:FindFirstChild("HumanoidRootPart") then distance = (playerPosition - promptParent.HumanoidRootPart.Position).Magnitude else if debugMode then logEvent("NO_POSITION", {prompt = prompt.Name}) end continue end -- Check 8: Range Validation Check currentSession.checks.rangeValidationCheck = currentSession.checks.rangeValidationCheck + 1 if distance > prompt.MaxActivationDistance then if debugMode then logEvent("OUT_OF_RANGE", {distance = distance, maxDist = prompt.MaxActivationDistance}) end continue end -- Check 9: Hold Duration Validation Check currentSession.checks.holdDurationCheck = currentSession.checks.holdDurationCheck + 1 if prompt.HoldDuration > 10 then if debugMode then logEvent("LONG_HOLD_DURATION", {duration = prompt.HoldDuration}) end continue end if distance < nearestDistance then nearestDistance = distance nearestPrompt = prompt end end -- Check 10: Memory Optimization Check currentSession.checks.memoryOptimizationCheck = currentSession.checks.memoryOptimizationCheck + 1 if promptsChecked > 100 then logEvent("HIGH_PROMPT_COUNT", {count = promptsChecked}) end local searchTime = tick() - searchStartTime currentSession.totalSearchTime = currentSession.totalSearchTime + searchTime logEvent("SEARCH_COMPLETE", { promptsChecked = promptsChecked, searchTime = searchTime, nearestDistance = nearestDistance, found = nearestPrompt ~= nil, prompt = nearestPrompt and nearestPrompt.Name or "None" }) return nearestPrompt, nearestDistance end -- Optimized auto prompt loop local function autoProximityLoop() if not isRunning then return end local loopStartTime = tick() currentSession.loopIterations = currentSession.loopIterations + 1 -- If we have a current prompt, try to use it if currentPrompt and currentPrompt.Parent and currentPrompt.Enabled then local character = player.Character if character and character:FindFirstChild("HumanoidRootPart") then local playerPosition = character.HumanoidRootPart.Position local promptParent = currentPrompt.Parent local distance = math.huge if promptParent:IsA("BasePart") then distance = (playerPosition - promptParent.Position).Magnitude elseif promptParent:FindFirstChild("HumanoidRootPart") then distance = (playerPosition - promptParent.HumanoidRootPart.Position).Magnitude end distanceLabel.Text = "Distance: " .. math.floor(distance) .. " studs" currentSession.distanceSum = currentSession.distanceSum + distance if distance <= currentPrompt.MaxActivationDistance then statusLabel.Text = "Status: Using Prompt" statusLabel.TextColor3 = Color3.fromRGB(100, 255, 100) local useStartTime = tick() local success, errorMsg = pcall(function() fireproximityprompt(currentPrompt) end) if success then currentSession.promptsUsed = currentSession.promptsUsed + 1 lastUsedPrompt = currentPrompt promptCooldowns[tostring(currentPrompt)] = tick() logEvent("PROMPT_USED", { prompt = currentPrompt.Name, distance = distance, duration = currentPrompt.HoldDuration }) -- Wait only if prompt is still enabled and in range if currentPrompt.Parent and currentPrompt.Enabled and distance <= currentPrompt.MaxActivationDistance then local waitTime = math.min(currentPrompt.HoldDuration, 0.5) + 0.05 wait(waitTime) currentSession.totalWaitTime = currentSession.totalWaitTime + waitTime else currentPrompt = nil -- Clear if prompt is no longer valid logEvent("PROMPT_INVALIDATED", {prompt = currentPrompt and currentPrompt.Name or "N/A"}) end else currentSession.failedAttempts = currentSession.failedAttempts + 1 logEvent("PROMPT_FAILED", { prompt = currentPrompt.Name, error = errorMsg or "Unknown error", distance = distance }) currentPrompt = nil -- Clear current prompt on failure end else statusLabel.Text = "Status: Out of Range" statusLabel.TextColor3 = Color3.fromRGB(255, 200, 100) logEvent("OUT_OF_RANGE", {prompt = currentPrompt.Name, distance = distance, maxDist = currentPrompt.MaxActivationDistance}) currentPrompt = nil -- Clear if out of range end else currentPrompt = nil statusLabel.Text = "Status: No Character" statusLabel.TextColor3 = Color3.fromRGB(255, 100, 100) logEvent("CHARACTER_INVALID", {error = "No character available"}) end else -- Find new prompt if current one is invalid currentPrompt = nil local nearestPrompt, distance = findNearestProximityPrompt() if nearestPrompt then currentPrompt = nearestPrompt distanceLabel.Text = "Distance: " .. math.floor(distance) .. " studs" statusLabel.Text = "Status: Found Prompt" statusLabel.TextColor3 = Color3.fromRGB(100, 255, 100) logEvent("PROMPT_FOUND", {prompt = nearestPrompt.Name, distance = distance}) else distanceLabel.Text = "Distance: No prompts found" statusLabel.Text = "Status: Searching..." statusLabel.TextColor3 = Color3.fromRGB(255, 200, 100) currentSession.failedAttempts = currentSession.failedAttempts + 1 logEvent("NO_PROMPT_FOUND", {}) end end updatePerformanceDisplay() wait(0.01) -- Reduced for faster looping if isRunning then autoProximityLoop() end end -- Enhanced performance report local function generatePerformanceReport() local runtime = tick() - currentSession.startTime local report = {} table.insert(report, "=== AUTO PROXIMITY PERFORMANCE REPORT ===") table.insert(report, "Generated: " .. os.date("%X %x")) table.insert(report, "Runtime: " .. math.floor(runtime) .. " seconds") table.insert(report, "") table.insert(report, "=== BASIC STATS ===") table.insert(report, "Prompts Used: " .. currentSession.promptsUsed) table.insert(report, "Failed Attempts: " .. currentSession.failedAttempts) table.insert(report, "Success Rate: " .. math.floor((currentSession.promptsUsed / math.max(currentSession.promptsUsed + currentSession.failedAttempts, 1)) * 100) .. "%") table.insert(report, "Average Distance: " .. math.floor(currentSession.distanceSum / math.max(currentSession.promptsUsed, 1)) .. " studs") table.insert(report, "Loop Iterations: " .. currentSession.loopIterations) table.insert(report, "") table.insert(report, "=== PERFORMANCE METRICS ===") table.insert(report, "Average Search Time: " .. math.floor((currentSession.totalSearchTime / math.max(currentSession.promptsUsed + currentSession.failedAttempts, 1)) * 1000) .. "ms") table.insert(report, "Total Wait Time: " .. math.floor(currentSession.totalWaitTime) .. " seconds") table.insert(report, "Cache Hit Rate: " .. (#promptCache > 0 and math.floor((currentSession.promptsUsed / math.max(#promptCache, 1)) * 100) or 0) .. "%") table.insert(report, "") table.insert(report, "=== EFFICIENCY CHECKS PERFORMED ===") for checkName, count in pairs(currentSession.checks) do table.insert(report, checkName .. ": " .. count) end table.insert(report, "") table.insert(report, "=== DETAILED EVENT LOG (Last 20) ===") local recentEvents = {} for i = math.max(1, #performanceLog - 19), #performanceLog do if performanceLog[i] then local eventStr = string.format("%s | Prompt: %s | Distance: %.1f | Error: %s | Duration: %.2fs | Time: %s", performanceLog[i].event, performanceLog[i].promptName, performanceLog[i].distance, performanceLog[i].errorMsg, performanceLog[i].duration, os.date("%X", math.floor(performanceLog[i].timestamp)) ) table.insert(recentEvents, eventStr) end end for _, event in ipairs(recentEvents) do table.insert(report, event) end table.insert(report, "") table.insert(report, "=== OPTIMIZATION SUGGESTIONS ===") if currentSession.checks.workspaceTraversalCheck > 1000 then table.insert(report, "• Consider increasing cache refresh interval") end if currentSession.totalSearchTime / math.max(currentSession.promptsUsed + currentSession.failedAttempts, 1) > 0.1 then table.insert(report, "• Search time is high - optimize workspace traversal") end if currentSession.failedAttempts > currentSession.promptsUsed * 0.2 then table.insert(report, "• High failure rate - verify prompt accessibility and range") end if currentSession.checks.duplicatePromptCheck > currentSession.promptsUsed * 2 then table.insert(report, "• Excessive duplicate checks - optimize prompt tracking") end if #promptCache > 100 then table.insert(report, "• Large prompt cache - consider periodic cache cleanup") end if currentSession.totalWaitTime > currentSession.promptsUsed * 1 then table.insert(report, "• Excessive wait time - review prompt hold durations") end return table.concat(report, "\n") end -- Button functions startButton.MouseButton1Click:Connect(function() if not isRunning then isRunning = true currentSession.startTime = tick() statusLabel.Text = "Status: Starting..." statusLabel.TextColor3 = Color3.fromRGB(100, 255, 100) logEvent("SESSION_STARTED", {}) autoProximityLoop() end end) stopButton.MouseButton1Click:Connect(function() isRunning = false currentPrompt = nil statusLabel.Text = "Status: Stopped" statusLabel.TextColor3 = Color3.fromRGB(255, 100, 100) distanceLabel.Text = "Distance: --" logEvent("SESSION_STOPPED", {}) end) exitButton.MouseButton1Click:Connect(function() isRunning = false currentPrompt = nil logEvent("GUI_CLOSED", {}) screenGui:Destroy() end) resetButton.MouseButton1Click:Connect(function() currentSession = { startTime = tick(), promptsUsed = 0, totalSearchTime = 0, totalWaitTime = 0, failedAttempts = 0, averageDistance = 0, distanceSum = 0, loopIterations = 0, checks = { duplicatePromptCheck = 0, rangeValidationCheck = 0, promptEnabledCheck = 0, characterValidationCheck = 0, promptParentCheck = 0, distanceCalculationCheck = 0, holdDurationCheck = 0, promptCooldownCheck = 0, workspaceTraversalCheck = 0, memoryOptimizationCheck = 0 } } performanceLog = {} promptCooldowns = {} lastUsedPrompt = nil currentPrompt = nil promptCache = {} updatePerformanceDisplay() logEvent("STATS_RESET", {}) end) copyLogButton.MouseButton1Click:Connect(function() local report = generatePerformanceReport() setclipboard(report) -- Visual feedback copyLogButton.Text = "Copied!" copyLogButton.BackgroundColor3 = Color3.fromRGB(100, 200, 100) wait(1) copyLogButton.Text = "Copy Log" copyLogButton.BackgroundColor3 = Color3.fromRGB(200, 150, 100) end) debugButton.MouseButton1Click:Connect(function() debugMode = not debugMode if debugMode then debugButton.Text = "Debug ON" debugButton.BackgroundColor3 = Color3.fromRGB(100, 200, 100) else debugButton.Text = "Debug" debugButton.BackgroundColor3 = Color3.fromRGB(150, 100, 200) end end) -- Button hover effects local function addHoverEffect(button, normalColor, hoverColor) button.MouseEnter:Connect(function() button.BackgroundColor3 = hoverColor end) button.MouseLeave:Connect(function() button.BackgroundColor3 = normalColor end) end addHoverEffect(startButton, Color3.fromRGB(100, 200, 100), Color3.fromRGB(120, 220, 120)) addHoverEffect(stopButton, Color3.fromRGB(200, 100, 100), Color3.fromRGB(220, 120, 120)) addHoverEffect(exitButton, Color3.fromRGB(150, 150, 150), Color3.fromRGB(170, 170, 170)) addHoverEffect(resetButton, Color3.fromRGB(100, 150, 200), Color3.fromRGB(120, 170, 220)) addHoverEffect(copyLogButton, Color3.fromRGB(200, 150, 100), Color3.fromRGB(220, 170, 120)) addHoverEffect(debugButton, Color3.fromRGB(150, 100, 200), Color3.fromRGB(170, 120, 220)) -- Periodic cache cleanup RunService.Heartbeat:Connect(function() if isRunning and #promptCache > 0 then local newCache = {} for _, prompt in ipairs(promptCache) do if prompt.Parent and prompt.Enabled then table.insert(newCache, prompt) end end if #newCache < #promptCache then logEvent("CACHE_CLEANUP", {removed = #promptCache - #newCache}) end promptCache = newCache end end) print("Auto Proximity Prompt GUI v2.3 loaded with enhanced performance monitoring!")