suramraja1

dadwae

Jun 30th, 2025 (edited)
1,141
-1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 39.55 KB | None | 0 1
  1. -- SERVICES & MODULES
  2. local Players = game:GetService("Players")
  3. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  4. local UserInputService = game:GetService("UserInputService")
  5. local player = Players.LocalPlayer
  6.  
  7. local GetFarm = require(ReplicatedStorage.Modules.GetFarm)
  8. local MutationHandler = require(ReplicatedStorage.Modules:WaitForChild("MutationHandler"))
  9.  
  10. -- ✅ FRUIT LOG SYSTEM
  11. local fruitLog = {}
  12. local maxLogEntries = 200
  13. local lastKnownFruits = {} -- Track existing fruits to detect spawns/deletions
  14. local logGui = nil
  15.  
  16. -- Helper function for mutation priority
  17. local function getMutationPriority(mutation)
  18.     local priorityMap = {
  19.         ["Moonlit"] = 6,
  20.         ["Choc"] = 5,
  21.         ["Shocked"] = 4,
  22.         ["Frozen"] = 3,
  23.         ["Chilled"] = 2,
  24.         ["Wet"] = 1,
  25.         ["None"] = 0
  26.     }
  27.    
  28.     -- Count mutations and assign a priority
  29.     if mutation == "None" then
  30.         return 0
  31.     end
  32.    
  33.     -- If it contains multiple mutations, count them
  34.     local count = 0
  35.     for w in mutation:gmatch("([^•]+)") do -- Changed to match bullet separator
  36.         count = count + 1
  37.     end
  38.    
  39.     -- Multiple mutations always have highest priority
  40.     if count > 1 then
  41.         return 100 + count
  42.     end
  43.    
  44.     -- Single mutation - look up its priority
  45.     for mutName, priority in pairs(priorityMap) do
  46.         if mutation:find(mutName) then
  47.             return priority
  48.         end
  49.     end
  50.    
  51.     return 0
  52. end
  53.  
  54. -- Helper function for variant priority
  55. local function getVariantPriority(variant)
  56.     local priorityMap = {
  57.         ["Rainbow"] = 3,
  58.         ["Gold"] = 2,
  59.         ["Normal"] = 1
  60.     }
  61.    
  62.     return priorityMap[variant] or 0
  63. end
  64.  
  65. -- GUI SETUP
  66. local playerGui = player:WaitForChild("PlayerGui")
  67.  
  68. -- Check if GUI already exists and remove it
  69. local existingGui = playerGui:FindFirstChild("FruitListGui")
  70. if existingGui then
  71.     existingGui:Destroy()
  72. end
  73.  
  74. -- State variables
  75. local currentSortColumn = "Fruit Name" -- Default sort by name
  76. local currentSortDir = "asc" -- Default ascending
  77. local allFruitsData = {} -- Will store all fruits data for sorting
  78. local isMinimized = false -- Track minimize state
  79. local originalSize -- Store original size when minimizing
  80.  
  81. local fruitListGui = Instance.new("ScreenGui")
  82. fruitListGui.Name = "FruitListGui"
  83. fruitListGui.ResetOnSpawn = false
  84. fruitListGui.Parent = playerGui
  85.  
  86. local mainFrame = Instance.new("Frame")
  87. mainFrame.Size = UDim2.new(0, 500, 0, 400)
  88. mainFrame.Position = UDim2.new(0.5, -250, 0.5, -200)
  89. mainFrame.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
  90. mainFrame.BackgroundTransparency = 0.1
  91. mainFrame.Parent = fruitListGui
  92. mainFrame.Active = true
  93.  
  94. -- Store original size for minimizing
  95. originalSize = mainFrame.Size
  96.  
  97. -- Add rounded corners to main frame
  98. local mainCorner = Instance.new("UICorner")
  99. mainCorner.CornerRadius = UDim.new(0, 8)
  100. mainCorner.Parent = mainFrame
  101.  
  102. -- Title bar
  103. local titleBar = Instance.new("Frame")
  104. titleBar.Name = "TitleBar"
  105. titleBar.Size = UDim2.new(1, 0, 0, 30)
  106. titleBar.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
  107. titleBar.BorderSizePixel = 0
  108. titleBar.Parent = mainFrame
  109.  
  110. -- Add rounded corners to title bar (top corners only)
  111. local titleCorner = Instance.new("UICorner")
  112. titleCorner.CornerRadius = UDim.new(0, 8)
  113. titleCorner.Parent = titleBar
  114.  
  115. -- Make sure the title bar only rounds the top corners
  116. local bottomFrame = Instance.new("Frame")
  117. bottomFrame.Size = UDim2.new(1, 0, 0.5, 0)
  118. bottomFrame.Position = UDim2.new(0, 0, 0.5, 0)
  119. bottomFrame.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
  120. bottomFrame.BorderSizePixel = 0
  121. bottomFrame.Parent = titleBar
  122.  
  123. local titleText = Instance.new("TextLabel")
  124. titleText.Name = "Title"
  125. titleText.Size = UDim2.new(1, -60, 1, 0)
  126. titleText.BackgroundTransparency = 1
  127. titleText.Text = "Farm Fruit List"
  128. titleText.Font = Enum.Font.SourceSansBold
  129. titleText.TextColor3 = Color3.fromRGB(255, 255, 255)
  130. titleText.TextSize = 18
  131. titleText.Parent = titleBar
  132.  
  133. -- Close button
  134. local closeButton = Instance.new("TextButton")
  135. closeButton.Name = "CloseButton"
  136. closeButton.Size = UDim2.new(0, 30, 0, 30)
  137. closeButton.Position = UDim2.new(1, -30, 0, 0)
  138. closeButton.BackgroundColor3 = Color3.fromRGB(200, 60, 60)
  139. closeButton.Text = "X"
  140. closeButton.TextColor3 = Color3.fromRGB(255, 255, 255)
  141. closeButton.TextSize = 18
  142. closeButton.Font = Enum.Font.SourceSansBold
  143. closeButton.Parent = titleBar
  144.  
  145. -- Add rounded corners to close button
  146. local closeCorner = Instance.new("UICorner")
  147. closeCorner.CornerRadius = UDim.new(0, 6)
  148. closeCorner.Parent = closeButton
  149.  
  150. -- Minimize button
  151. local minimizeButton = Instance.new("TextButton")
  152. minimizeButton.Name = "MinimizeButton"
  153. minimizeButton.Size = UDim2.new(0, 30, 0, 30)
  154. minimizeButton.Position = UDim2.new(1, -65, 0, 0)
  155. minimizeButton.BackgroundColor3 = Color3.fromRGB(60, 60, 200)
  156. minimizeButton.Text = "-"
  157. minimizeButton.TextColor3 = Color3.fromRGB(255, 255, 255)
  158. minimizeButton.TextSize = 22
  159. minimizeButton.Font = Enum.Font.SourceSansBold
  160. minimizeButton.Parent = titleBar
  161.  
  162. -- Add rounded corners to minimize button
  163. local minimizeCorner = Instance.new("UICorner")
  164. minimizeCorner.CornerRadius = UDim.new(0, 6)
  165. minimizeCorner.Parent = minimizeButton
  166.  
  167. -- Function to toggle minimize state
  168. local function toggleMinimize()
  169.     isMinimized = not isMinimized
  170.    
  171.     if isMinimized then
  172.         -- Store current size before minimizing
  173.         originalSize = mainFrame.Size
  174.        
  175.         -- Minimize GUI - just show title bar
  176.         mainFrame.Size = UDim2.new(0, 300, 0, 30)
  177.         minimizeButton.Text = "+"
  178.        
  179.         -- Hide content
  180.         if mainFrame:FindFirstChild("HeaderFrame") then
  181.             mainFrame.HeaderFrame.Visible = false
  182.         end
  183.         if mainFrame:FindFirstChild("ScrollingFrame") then
  184.             mainFrame.ScrollingFrame.Visible = false
  185.         end
  186.         if mainFrame:FindFirstChild("ResizeHandle") then
  187.             mainFrame.ResizeHandle.Visible = false
  188.         end
  189.     else
  190.         -- Restore GUI to original size
  191.         mainFrame.Size = originalSize
  192.         minimizeButton.Text = "-"
  193.        
  194.         -- Show content
  195.         if mainFrame:FindFirstChild("HeaderFrame") then
  196.             mainFrame.HeaderFrame.Visible = true
  197.         end
  198.         if mainFrame:FindFirstChild("ScrollingFrame") then
  199.             mainFrame.ScrollingFrame.Visible = true
  200.         end
  201.         if mainFrame:FindFirstChild("ResizeHandle") then
  202.             mainFrame.ResizeHandle.Visible = true
  203.         end
  204.     end
  205. end
  206.  
  207. -- Connect minimize button
  208. minimizeButton.MouseButton1Click:Connect(toggleMinimize)
  209.  
  210. -- Add keyboard shortcut (Left Ctrl) to toggle minimize
  211. UserInputService.InputBegan:Connect(function(input)
  212.     if input.KeyCode == Enum.KeyCode.LeftControl then
  213.         toggleMinimize()
  214.     end
  215. end)
  216.  
  217. -- Resize Handle
  218. local resizeHandle = Instance.new("Frame")
  219. resizeHandle.Size = UDim2.new(0, 24, 0, 24)
  220. resizeHandle.Position = UDim2.new(1, -24, 1, -24)
  221. resizeHandle.BackgroundColor3 = Color3.fromRGB(80, 80, 80)
  222. resizeHandle.BorderSizePixel = 0
  223. resizeHandle.Parent = mainFrame
  224. resizeHandle.Name = "ResizeHandle"
  225. resizeHandle.ZIndex = 10
  226.  
  227. local resizeCorner = Instance.new("UICorner")
  228. resizeCorner.CornerRadius = UDim.new(0, 8)
  229. resizeCorner.Parent = resizeHandle
  230.  
  231. -- IMPROVED DRAGGING IMPLEMENTATION
  232. local dragging = false
  233. local dragInput
  234. local dragStart
  235. local startPos
  236. local lastMousePos
  237. local lastGoalPos
  238.  
  239. local function updateDrag(input)
  240.     if dragging then
  241.         local delta = input.Position - dragStart
  242.         local position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X,
  243.                                    startPos.Y.Scale, startPos.Y.Offset + delta.Y)
  244.        
  245.         -- Use a smoother movement with lerping
  246.         game:GetService("RunService").RenderStepped:Wait()
  247.         mainFrame.Position = position
  248.     end
  249. end
  250.  
  251. titleBar.InputBegan:Connect(function(input)
  252.     if input.UserInputType == Enum.UserInputType.MouseButton1 or
  253.        input.UserInputType == Enum.UserInputType.Touch then
  254.         dragging = true
  255.         dragStart = input.Position
  256.         startPos = mainFrame.Position
  257.         lastMousePos = Vector2.new(input.Position.X, input.Position.Y)
  258.        
  259.         -- Continue tracking even if mouse leaves the titleBar
  260.         input.Changed:Connect(function()
  261.             if input.UserInputState == Enum.UserInputState.End then
  262.                 dragging = false
  263.             end
  264.         end)
  265.     end
  266. end)
  267.  
  268. titleBar.InputChanged:Connect(function(input)
  269.     if input.UserInputType == Enum.UserInputType.MouseMovement or
  270.        input.UserInputType == Enum.UserInputType.Touch then
  271.         dragInput = input
  272.     end
  273. end)
  274.  
  275. UserInputService.InputChanged:Connect(function(input)
  276.     if input == dragInput and dragging then
  277.         updateDrag(input)
  278.     end
  279. end)
  280.  
  281. -- Resize Script
  282. local draggingResize = false
  283. local resizeStart
  284. local startSize
  285.  
  286. resizeHandle.InputBegan:Connect(function(input)
  287.     if input.UserInputType == Enum.UserInputType.MouseButton1 or
  288.        input.UserInputType == Enum.UserInputType.Touch then
  289.         draggingResize = true
  290.         resizeStart = input.Position
  291.         startSize = mainFrame.Size
  292.        
  293.         -- Track input end even outside the resize handle
  294.         input.Changed:Connect(function()
  295.             if input.UserInputState == Enum.UserInputState.End then
  296.                 draggingResize = false
  297.             end
  298.         end)
  299.     end
  300. end)
  301.  
  302. UserInputService.InputChanged:Connect(function(input)
  303.     if draggingResize and (input.UserInputType == Enum.UserInputType.MouseMovement or
  304.                           input.UserInputType == Enum.UserInputType.Touch) then
  305.         local delta = input.Position - resizeStart
  306.         local newWidth = math.max(400, startSize.X.Offset + delta.X)
  307.         local newHeight = math.max(300, startSize.Y.Offset + delta.Y)
  308.         mainFrame.Size = UDim2.new(0, newWidth, 0, newHeight)
  309.        
  310.         -- Store new size for when un-minimizing
  311.         originalSize = mainFrame.Size
  312.        
  313.         -- Recalculate scrolling frame size when resizing
  314.         local headerHeight = 30 -- title bar height
  315.         if mainFrame:FindFirstChild("HeaderFrame") and mainFrame:FindFirstChild("ScrollingFrame") then
  316.             mainFrame.ScrollingFrame.Size = UDim2.new(1, -20, 1, -(headerHeight + mainFrame.HeaderFrame.Size.Y.Offset + 20))
  317.         end
  318.     end
  319. end)
  320.  
  321. -- Close button logic
  322. closeButton.MouseButton1Click:Connect(function()
  323.     fruitListGui:Destroy()
  324. end)
  325.  
  326. -- Header Frame for column titles
  327. local headerFrame = Instance.new("Frame")
  328. headerFrame.Name = "HeaderFrame"
  329. headerFrame.Size = UDim2.new(1, -20, 0, 35)
  330. headerFrame.Position = UDim2.new(0, 10, 0, 40)
  331. headerFrame.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
  332. headerFrame.BackgroundTransparency = 0.5
  333. headerFrame.Parent = mainFrame
  334.  
  335. -- Add rounded corners to header frame
  336. local headerCorner = Instance.new("UICorner")
  337. headerCorner.CornerRadius = UDim.new(0, 6)
  338. headerCorner.Parent = headerFrame
  339.  
  340. -- Column Headers - SIMPLIFIED: only 4 columns now
  341. local columns = {"Fruit Name", "Variant", "Weight (kg)", "Mutations"}
  342. local columnWidths = {0.22, 0.18, 0.18, 0.42}  -- Give more space to mutations column
  343. local sortButtons = {}
  344.  
  345. -- Scrolling Frame for fruit list
  346. local scrollingFrame = Instance.new("ScrollingFrame")
  347. scrollingFrame.Name = "ScrollingFrame"
  348. scrollingFrame.Size = UDim2.new(1, -20, 1, -85)
  349. scrollingFrame.Position = UDim2.new(0, 10, 0, 85)
  350. scrollingFrame.BackgroundTransparency = 0.9
  351. scrollingFrame.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
  352. scrollingFrame.BorderSizePixel = 0
  353. scrollingFrame.ScrollBarThickness = 8
  354. scrollingFrame.Parent = mainFrame
  355.  
  356. -- Refresh Button
  357. local refreshButton = Instance.new("TextButton")
  358. refreshButton.Name = "RefreshButton"
  359. refreshButton.Size = UDim2.new(0, 100, 0, 25)
  360. refreshButton.Position = UDim2.new(0, 10, 0, 3)
  361. refreshButton.BackgroundColor3 = Color3.fromRGB(60, 120, 60)
  362. refreshButton.Text = "Refresh"
  363. refreshButton.TextColor3 = Color3.fromRGB(255, 255, 255)
  364. refreshButton.TextSize = 16
  365. refreshButton.Font = Enum.Font.SourceSansBold
  366. refreshButton.Parent = titleBar
  367.  
  368. -- Create a UICorner for the refresh button
  369. local refreshCorner = Instance.new("UICorner")
  370. refreshCorner.CornerRadius = UDim.new(0, 4)
  371. refreshCorner.Parent = refreshButton
  372.  
  373. -- Status label (for minimize tooltip)
  374. local statusLabel = Instance.new("TextLabel")
  375. statusLabel.Name = "StatusLabel"
  376. statusLabel.Size = UDim2.new(0, 200, 0, 20)
  377. statusLabel.Position = UDim2.new(0.5, -100, 0, -25)
  378. statusLabel.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
  379. statusLabel.BackgroundTransparency = 0.2
  380. statusLabel.Text = "Press Left Ctrl to minimize"
  381. statusLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
  382. statusLabel.TextSize = 14
  383. statusLabel.Font = Enum.Font.SourceSans
  384. statusLabel.Visible = false
  385. statusLabel.Parent = mainFrame
  386.  
  387. -- Add rounded corners to status label
  388. local statusCorner = Instance.new("UICorner")
  389. statusCorner.CornerRadius = UDim.new(0, 4)
  390. statusCorner.Parent = statusLabel
  391.  
  392. -- Show tooltip when hovering minimize button
  393. minimizeButton.MouseEnter:Connect(function()
  394.     statusLabel.Visible = true
  395. end)
  396.  
  397. minimizeButton.MouseLeave:Connect(function()
  398.     statusLabel.Visible = false
  399. end)
  400.  
  401. -- Function declaration for refreshFruitList (will be defined later)
  402. local refreshFruitList
  403.  
  404. -- Function to create sorted fruit list
  405. local function createSortedFruitList()
  406.     -- Clear existing list
  407.     for _, child in pairs(scrollingFrame:GetChildren()) do
  408.         if child:IsA("Frame") then
  409.             child:Destroy()
  410.         end
  411.     end
  412.    
  413.     -- Sort the fruits data based on current sort column and direction
  414.     table.sort(allFruitsData, function(a, b)
  415.         local aValue, bValue
  416.        
  417.         if currentSortColumn == "Fruit Name" then
  418.             aValue = a.name:lower()
  419.             bValue = b.name:lower()
  420.            
  421.         elseif currentSortColumn == "Variant" then
  422.             -- Sort by variant priority
  423.             aValue = getVariantPriority(a.variant)
  424.             bValue = getVariantPriority(b.variant)
  425.            
  426.         elseif currentSortColumn == "Mutations" then
  427.             -- Sort by mutation priority
  428.             aValue = getMutationPriority(a.mutations)
  429.             bValue = getMutationPriority(b.mutations)
  430.            
  431.         elseif currentSortColumn == "Weight (kg)" then
  432.             -- Use the raw numeric weight value instead of the string
  433.             aValue = a.weightNum or 0
  434.             bValue = b.weightNum or 0
  435.         else
  436.             return false
  437.         end
  438.        
  439.         if currentSortDir == "asc" then
  440.             return aValue < bValue
  441.         else
  442.             return aValue > bValue
  443.         end
  444.     end)
  445.    
  446.     -- Update sort button appearance
  447.     for colName, button in pairs(sortButtons) do
  448.         if colName == currentSortColumn then
  449.             button.Text = currentSortDir == "asc" and "▲" or "▼"
  450.             button.TextColor3 = Color3.fromRGB(255, 255, 100) -- Highlight active sort
  451.         else
  452.             button.Text = "◆"
  453.             button.TextColor3 = Color3.fromRGB(150, 150, 150) -- Dim inactive sorts
  454.         end
  455.     end
  456.    
  457.     local rowHeight = 50 -- Increased height for better mutation display
  458.     for i, fruitData in ipairs(allFruitsData) do
  459.         -- Create row frame
  460.         local rowFrame = Instance.new("Frame")
  461.         rowFrame.Name = "Row_" .. i
  462.         rowFrame.Size = UDim2.new(1, 0, 0, rowHeight)
  463.         rowFrame.Position = UDim2.new(0, 0, 0, (i-1) * rowHeight)
  464.         rowFrame.BackgroundColor3 = i % 2 == 0 and Color3.fromRGB(40, 40, 40) or Color3.fromRGB(35, 35, 35)
  465.         rowFrame.BackgroundTransparency = 0.3
  466.         rowFrame.Parent = scrollingFrame
  467.        
  468.         -- Add hover effect
  469.         rowFrame.InputBegan:Connect(function(input)
  470.             if input.UserInputType == Enum.UserInputType.MouseMovement then
  471.                 rowFrame.BackgroundTransparency = 0.1
  472.             end
  473.         end)
  474.        
  475.         rowFrame.InputEnded:Connect(function(input)
  476.             if input.UserInputType == Enum.UserInputType.MouseMovement then
  477.                 rowFrame.BackgroundTransparency = 0.3
  478.             end
  479.         end)
  480.        
  481.         -- Create columns in the row
  482.         local currentX = 0
  483.         local columnValues = {fruitData.name, fruitData.variant, fruitData.weight, fruitData.mutations}
  484.        
  485.         for j, columnValue in ipairs(columnValues) do
  486.             local cell = Instance.new("TextLabel")
  487.             cell.Name = "Column" .. j
  488.             cell.Size = UDim2.new(columnWidths[j], -10, 1, 0)
  489.             cell.Position = UDim2.new(currentX, 5, 0, 0)
  490.             cell.BackgroundTransparency = 1
  491.             cell.Font = Enum.Font.SourceSans
  492.             cell.TextColor3 = Color3.fromRGB(255, 255, 255)
  493.             cell.Text = tostring(columnValue)
  494.             cell.TextXAlignment = Enum.TextXAlignment.Left
  495.             cell.TextWrapped = true
  496.             cell.TextYAlignment = Enum.TextYAlignment.Top
  497.            
  498.             -- Special handling for mutations column (column 4)
  499.             if j == 4 then
  500.                 cell.TextSize = 14 -- Slightly smaller for more text
  501.                 cell.Font = Enum.Font.SourceSans
  502.                 -- Make sure mutations are fully visible
  503.                 if #tostring(columnValue) > 20 then
  504.                     cell.TextScaled = false -- Don't scale down, just wrap
  505.                 end
  506.             else
  507.                 cell.TextSize = 16
  508.                 cell.TextYAlignment = Enum.TextYAlignment.Center
  509.             end
  510.            
  511.             cell.Parent = rowFrame
  512.            
  513.             currentX = currentX + columnWidths[j]
  514.         end
  515.     end
  516.    
  517.     -- Update scrolling frame content size
  518.     scrollingFrame.CanvasSize = UDim2.new(0, 0, 0, #allFruitsData * rowHeight)
  519.    
  520.     -- Update counter
  521.     titleText.Text = "Farm Fruit List - " .. #allFruitsData .. " Fruits"
  522. end
  523.  
  524. -- Column Headers
  525. local currentX = 0
  526. for i, columnName in ipairs(columns) do
  527.     local headerContainer = Instance.new("Frame")
  528.     headerContainer.Name = columnName:gsub(" ", "") .. "HeaderContainer"
  529.     headerContainer.Size = UDim2.new(columnWidths[i], 0, 1, 0)
  530.     headerContainer.Position = UDim2.new(currentX, 0, 0, 0)
  531.     headerContainer.BackgroundTransparency = 1
  532.     headerContainer.Parent = headerFrame
  533.    
  534.     local columnHeader = Instance.new("TextLabel")
  535.     columnHeader.Name = columnName:gsub(" ", "") .. "Header"
  536.     columnHeader.Size = UDim2.new(1, -25, 1, 0) -- Make room for sort button
  537.     columnHeader.Position = UDim2.new(0, 5, 0, 0)
  538.     columnHeader.BackgroundTransparency = 1
  539.     columnHeader.Font = Enum.Font.SourceSansBold
  540.     columnHeader.TextColor3 = Color3.fromRGB(255, 255, 255)
  541.     columnHeader.TextSize = 18
  542.     columnHeader.Text = columnName
  543.     columnHeader.TextXAlignment = Enum.TextXAlignment.Left
  544.     columnHeader.Parent = headerContainer
  545.    
  546.     -- Add sort button
  547.     local sortButton = Instance.new("TextButton")
  548.     sortButton.Name = "SortButton"
  549.     sortButton.Size = UDim2.new(0, 20, 0, 20)
  550.     sortButton.Position = UDim2.new(1, -25, 0.5, -10)
  551.     sortButton.BackgroundTransparency = 0.8
  552.     sortButton.BackgroundColor3 = Color3.fromRGB(60, 60, 60)
  553.     sortButton.Text = columnName == currentSortColumn and "▲" or "◆" -- Triangle up for current sort, diamond for others
  554.     sortButton.TextColor3 = columnName == currentSortColumn
  555.                          and Color3.fromRGB(255, 255, 100)
  556.                          or Color3.fromRGB(150, 150, 150)
  557.     sortButton.TextSize = 14
  558.     sortButton.Font = Enum.Font.SourceSansBold
  559.     sortButton.Parent = headerContainer
  560.    
  561.     -- Add rounded corners to sort button
  562.     local sortCorner = Instance.new("UICorner")
  563.     sortCorner.CornerRadius = UDim.new(0, 4)
  564.     sortCorner.Parent = sortButton
  565.    
  566.     -- Store the sort button for later reference
  567.     sortButtons[columnName] = sortButton
  568.    
  569.     -- Sort button click handler
  570.     sortButton.MouseButton1Click:Connect(function()
  571.         if currentSortColumn == columnName then
  572.             -- Toggle direction if same column
  573.             currentSortDir = currentSortDir == "asc" and "desc" or "asc"
  574.         else
  575.             -- New column, default directions
  576.             currentSortColumn = columnName
  577.            
  578.             -- Special case: weight should default to descending (high to low)
  579.             if columnName == "Weight (kg)" then
  580.                 currentSortDir = "desc"
  581.             else
  582.                 -- Variant and mutation have special logic so desc is actually "best first"
  583.                 if columnName == "Variant" or columnName == "Mutations" then
  584.                     currentSortDir = "desc" -- Rainbow/Multiple mutations first
  585.                 else
  586.                     currentSortDir = "asc" -- A-Z for regular text
  587.                 end
  588.             end
  589.         end
  590.        
  591.         createSortedFruitList()
  592.     end)
  593.    
  594.     -- Add hover effect to sort button
  595.     sortButton.MouseEnter:Connect(function()
  596.         sortButton.BackgroundTransparency = 0.5
  597.     end)
  598.    
  599.     sortButton.MouseLeave:Connect(function()
  600.         sortButton.BackgroundTransparency = 0.8
  601.     end)
  602.    
  603.     currentX = currentX + columnWidths[i]
  604. end
  605.  
  606. -- Function to refresh the fruit list
  607. refreshFruitList = function()
  608.     -- Clear all fruit data
  609.     allFruitsData = {}
  610.    
  611.     -- Get player farm
  612.     local farm = GetFarm(player)
  613.     if not farm or not farm:FindFirstChild("Important") or not farm.Important:FindFirstChild("Plants_Physical") then
  614.         local errorLabel = Instance.new("TextLabel")
  615.         errorLabel.Size = UDim2.new(1, 0, 0, 30)
  616.         errorLabel.Position = UDim2.new(0, 0, 0, 0)
  617.         errorLabel.BackgroundTransparency = 1
  618.         errorLabel.TextColor3 = Color3.fromRGB(255, 100, 100)
  619.         errorLabel.Text = "Farm not found!"
  620.         errorLabel.Font = Enum.Font.SourceSansSemibold
  621.         errorLabel.TextSize = 18
  622.         errorLabel.Parent = scrollingFrame
  623.         return
  624.     end
  625.    
  626.     local plantsPhysical = farm.Important.Plants_Physical
  627.    
  628.     -- Loop through all tree types
  629.     for _, treeType in pairs(plantsPhysical:GetChildren()) do
  630.         local fruitsFolder = treeType:FindFirstChild("Fruits")
  631.         if fruitsFolder then
  632.             for _, fruitModel in pairs(fruitsFolder:GetChildren()) do
  633.                 if fruitModel:IsA("Model") then
  634.                     -- Get fruit attributes and properties
  635.                     local fruitName = fruitModel.Name
  636.                    
  637.                     -- Get variant (typically stored as a child)
  638.                     local variant = fruitModel:FindFirstChild("Variant")
  639.                     local variantText = variant and variant.Value or "Normal"
  640.                    
  641.                     -- Get weight
  642.                     local weight = fruitModel:FindFirstChild("Weight")
  643.                     local weightNum = weight and weight.Value or 0
  644.                     local weightValue = weight and string.format("%.2f kg", weightNum) or "? kg"
  645.                    
  646.                     -- Get mutations from attributes (using MutationHandler if available)
  647.                     local mutations = ""
  648.                     local success, mutationString = pcall(function()
  649.                         return MutationHandler:GetMutationsAsString(fruitModel) or ""
  650.                     end)
  651.                    
  652.                     if not success or mutationString == "" then
  653.                         -- Try checking attributes directly
  654.                         local mutationList = {}
  655.                         for attrName, value in pairs(fruitModel:GetAttributes()) do
  656.                             if value == true and typeof(value) == "boolean" then
  657.                                 -- Check only known mutation attributes
  658.                                 if attrName == "Shocked" or
  659.                                    attrName == "Frozen" or
  660.                                    attrName == "Wet" or
  661.                                    attrName == "Chilled" or
  662.                                    attrName == "Twisted" or
  663.                                    attrName == "Choc" or
  664.                                    attrName == "Burnt" or
  665.                                    attrName == "Moonlit" then
  666.                                    
  667.                                     table.insert(mutationList, attrName)
  668.                                 end
  669.                             end
  670.                         end
  671.                        
  672.                         if #mutationList > 0 then
  673.                             -- Sort mutations for consistent display
  674.                             table.sort(mutationList)
  675.                             mutations = table.concat(mutationList, " • ") -- Use bullet separator for better readability
  676.                         else
  677.                             mutations = "None"
  678.                         end
  679.                     else
  680.                         -- Format the mutation string for better readability
  681.                         if mutationString ~= "" then
  682.                             -- Replace commas with bullet points for better visual separation
  683.                             mutations = mutationString:gsub(", ", " • ")
  684.                         else
  685.                             mutations = "None"
  686.                         end
  687.                     end
  688.  
  689.                     -- Store fruit data for sorting
  690.                     table.insert(allFruitsData, {
  691.                         name = fruitName,
  692.                         variant = variantText,
  693.                         mutations = mutations,
  694.                         weight = weightValue,
  695.                         weightNum = weightNum, -- Store raw number for sorting
  696.                         model = fruitModel,
  697.                         treeName = treeType.Name
  698.                     })
  699.                 end
  700.             end
  701.         end
  702.     end
  703.    
  704.     -- Display sorted fruit list
  705.     createSortedFruitList()
  706. end
  707.  
  708. -- Connect the refresh button
  709. refreshButton.MouseButton1Click:Connect(refreshFruitList)
  710.  
  711. -- Handle refresh on unhide
  712. minimizeButton.MouseButton1Click:Connect(function()
  713.     if isMinimized then
  714.         -- Will refresh data when un-minimizing
  715.         task.delay(0.1, function()
  716.             refreshFruitList()
  717.         end)
  718.     end
  719. end)
  720.  
  721. -- ✅ FRUIT LOG FUNCTIONS
  722. local function addToFruitLog(action, fruitName, variant, weight, mutations, treeName)
  723.     local timestamp = os.date("%H:%M:%S")
  724.    
  725.     local logEntry = {
  726.         time = timestamp,
  727.         action = action, -- "SPAWNED" or "DELETED"
  728.         fruit = fruitName or "Unknown",
  729.         variant = variant or "Normal",
  730.         weight = weight or "Unknown",
  731.         mutations = mutations or "None",
  732.         tree = treeName or "Unknown"
  733.     }
  734.    
  735.     table.insert(fruitLog, 1, logEntry) -- Add to beginning
  736.    
  737.     -- Keep only last entries
  738.     if #fruitLog > maxLogEntries then
  739.         table.remove(fruitLog, maxLogEntries + 1)
  740.     end
  741.    
  742.     local actionEmoji = action == "SPAWNED" and "🌟" or "🗑️"
  743.     local mutText = mutations ~= "None" and " (" .. mutations .. ")" or ""
  744.     print(string.format("%s [%s] %s: %s - %s %s%s on %s", actionEmoji, timestamp, action, fruitName, weight, variant, mutText, treeName))
  745.    
  746.     -- Update log GUI if exists
  747.     if logGui then
  748.         updateFruitLogDisplay()
  749.     end
  750. end
  751.  
  752. -- ✅ MONITOR FRUIT CHANGES
  753. local function checkFruitChanges()
  754.     local currentFruits = {}
  755.    
  756.     -- Get current fruits on farm
  757.     local farm = GetFarm(player)
  758.     if farm and farm:FindFirstChild("Important") and farm.Important:FindFirstChild("Plants_Physical") then
  759.         local plantsPhysical = farm.Important.Plants_Physical
  760.        
  761.         -- Loop through all tree types
  762.         for _, treeType in pairs(plantsPhysical:GetChildren()) do
  763.             if treeType:IsA("Folder") or treeType:IsA("Model") then
  764.                 -- Check for Fruits folder in each tree type
  765.                 local fruitsFolder = treeType:FindFirstChild("Fruits")
  766.                 if fruitsFolder then
  767.                     for _, fruitModel in pairs(fruitsFolder:GetChildren()) do
  768.                         if fruitModel:IsA("Model") and fruitModel.Name ~= "Fruits" then
  769.                             -- Use a more reliable unique identifier
  770.                             local fruitId = treeType.Name .. "_" .. fruitModel.Name .. "_" .. tostring(fruitModel)
  771.                            
  772.                             -- Get fruit data
  773.                             local fruitName = fruitModel.Name
  774.                             local variant = fruitModel:FindFirstChild("Variant")
  775.                             local variantText = variant and variant.Value or "Normal"
  776.                             local weight = fruitModel:FindFirstChild("Weight")
  777.                             local weightValue = weight and string.format("%.2f kg", weight.Value) or "? kg"
  778.                            
  779.                             -- Get mutations using same method as main GUI
  780.                             local mutations = "None"
  781.                             local success, mutationString = pcall(function()
  782.                                 return MutationHandler:GetMutationsAsString(fruitModel) or ""
  783.                             end)
  784.                            
  785.                             if success and mutationString ~= "" then
  786.                                 mutations = mutationString:gsub(", ", " • ")
  787.                             else
  788.                                 -- Check attributes directly
  789.                                 local mutationList = {}
  790.                                 for attrName, value in pairs(fruitModel:GetAttributes()) do
  791.                                     if value == true and typeof(value) == "boolean" then
  792.                                         if attrName == "Shocked" or attrName == "Frozen" or
  793.                                            attrName == "Wet" or attrName == "Chilled" or
  794.                                            attrName == "Twisted" or attrName == "Choc" or
  795.                                            attrName == "Burnt" or attrName == "Moonlit" then
  796.                                             table.insert(mutationList, attrName)
  797.                                         end
  798.                                     end
  799.                                 end
  800.                                
  801.                                 if #mutationList > 0 then
  802.                                     table.sort(mutationList)
  803.                                     mutations = table.concat(mutationList, " • ")
  804.                                 end
  805.                             end
  806.                            
  807.                             currentFruits[fruitId] = {
  808.                                 name = fruitName,
  809.                                 variant = variantText,
  810.                                 weight = weightValue,
  811.                                 mutations = mutations,
  812.                                 tree = treeType.Name
  813.                             }
  814.                         end
  815.                     end
  816.                 end
  817.             end
  818.         end
  819.     end
  820.    
  821.     -- Compare with last known fruits to detect changes
  822.    
  823.     -- Check for new fruits (spawned)
  824.     for fruitId, fruitData in pairs(currentFruits) do
  825.         if not lastKnownFruits[fruitId] then
  826.             addToFruitLog("SPAWNED", fruitData.name, fruitData.variant, fruitData.weight, fruitData.mutations, fruitData.tree)
  827.         end
  828.     end
  829.    
  830.     -- Check for deleted fruits
  831.     for fruitId, fruitData in pairs(lastKnownFruits) do
  832.         if not currentFruits[fruitId] then
  833.             addToFruitLog("DELETED", fruitData.name, fruitData.variant, fruitData.weight, fruitData.mutations, fruitData.tree)
  834.         end
  835.     end
  836.    
  837.     -- Update known fruits
  838.     lastKnownFruits = currentFruits
  839. end
  840.  
  841. -- ✅ FRUIT LOG GUI
  842. local function createFruitLogGui()
  843.     local playerGui = player:WaitForChild("PlayerGui")
  844.    
  845.     -- Remove existing log GUI
  846.     if logGui then
  847.         logGui:Destroy()
  848.     end
  849.    
  850.     local screenGui = Instance.new("ScreenGui")
  851.     screenGui.Name = "FruitLogGui"
  852.     screenGui.ResetOnSpawn = false
  853.     screenGui.Parent = playerGui
  854.    
  855.     local frame = Instance.new("Frame")
  856.     frame.Size = UDim2.new(0, 600, 0, 400)
  857.     frame.Position = UDim2.new(0.5, -300, 0.5, -200)
  858.     frame.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
  859.     frame.BackgroundTransparency = 0.1
  860.     frame.Parent = screenGui
  861.     frame.Active = true
  862.    
  863.     -- Add rounded corners
  864.     local frameCorner = Instance.new("UICorner")
  865.     frameCorner.CornerRadius = UDim.new(0, 8)
  866.     frameCorner.Parent = frame
  867.    
  868.     -- Title bar
  869.     local titleBar = Instance.new("Frame")
  870.     titleBar.Size = UDim2.new(1, 0, 0, 30)
  871.     titleBar.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
  872.     titleBar.BorderSizePixel = 0
  873.     titleBar.Parent = frame
  874.    
  875.     local titleCorner = Instance.new("UICorner")
  876.     titleCorner.CornerRadius = UDim.new(0, 8)
  877.     titleCorner.Parent = titleBar
  878.    
  879.     -- Bottom frame for title bar
  880.     local bottomFrame = Instance.new("Frame")
  881.     bottomFrame.Size = UDim2.new(1, 0, 0.5, 0)
  882.     bottomFrame.Position = UDim2.new(0, 0, 0.5, 0)
  883.     bottomFrame.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
  884.     bottomFrame.BorderSizePixel = 0
  885.     bottomFrame.Parent = titleBar
  886.    
  887.     local titleText = Instance.new("TextLabel")
  888.     titleText.Size = UDim2.new(1, -60, 1, 0)
  889.     titleText.BackgroundTransparency = 1
  890.     titleText.Text = "🍎 Fruit Spawn/Delete Log"
  891.     titleText.Font = Enum.Font.SourceSansBold
  892.     titleText.TextColor3 = Color3.fromRGB(255, 255, 255)
  893.     titleText.TextSize = 18
  894.     titleText.Parent = titleBar
  895.    
  896.     -- Close button
  897.     local closeButton = Instance.new("TextButton")
  898.     closeButton.Size = UDim2.new(0, 30, 0, 30)
  899.     closeButton.Position = UDim2.new(1, -30, 0, 0)
  900.     closeButton.BackgroundColor3 = Color3.fromRGB(200, 60, 60)
  901.     closeButton.Text = "X"
  902.     closeButton.TextColor3 = Color3.fromRGB(255, 255, 255)
  903.     closeButton.TextSize = 18
  904.     closeButton.Font = Enum.Font.SourceSansBold
  905.     closeButton.Parent = titleBar
  906.    
  907.     local closeCorner = Instance.new("UICorner")
  908.     closeCorner.CornerRadius = UDim.new(0, 6)
  909.     closeCorner.Parent = closeButton
  910.    
  911.     closeButton.MouseButton1Click:Connect(function()
  912.         screenGui:Destroy()
  913.         logGui = nil
  914.     end)
  915.    
  916.     -- Clear button
  917.     local clearButton = Instance.new("TextButton")
  918.     clearButton.Size = UDim2.new(0, 80, 0, 25)
  919.     clearButton.Position = UDim2.new(0, 10, 0, 40)
  920.     clearButton.BackgroundColor3 = Color3.fromRGB(100, 100, 100)
  921.     clearButton.Text = "Clear Log"
  922.     clearButton.TextColor3 = Color3.fromRGB(255, 255, 255)
  923.     clearButton.TextSize = 12
  924.     clearButton.Font = Enum.Font.SourceSans
  925.     clearButton.Parent = frame
  926.    
  927.     local clearCorner = Instance.new("UICorner")
  928.     clearCorner.CornerRadius = UDim.new(0, 4)
  929.     clearCorner.Parent = clearButton
  930.    
  931.     clearButton.MouseButton1Click:Connect(function()
  932.         fruitLog = {}
  933.         updateFruitLogDisplay()
  934.     end)
  935.    
  936.     -- Scroll frame
  937.     local scrollFrame = Instance.new("ScrollingFrame")
  938.     scrollFrame.Name = "LogScrollFrame"
  939.     scrollFrame.Size = UDim2.new(1, -20, 1, -75)
  940.     scrollFrame.Position = UDim2.new(0, 10, 0, 70)
  941.     scrollFrame.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
  942.     scrollFrame.BackgroundTransparency = 0.2
  943.     scrollFrame.ScrollBarThickness = 8
  944.     scrollFrame.Parent = frame
  945.    
  946.     local scrollCorner = Instance.new("UICorner")
  947.     scrollCorner.CornerRadius = UDim.new(0, 6)
  948.     scrollCorner.Parent = scrollFrame
  949.    
  950.     logGui = screenGui
  951.     return screenGui
  952. end
  953.  
  954. -- ✅ UPDATE LOG DISPLAY
  955. function updateFruitLogDisplay()
  956.     if not logGui then return end
  957.    
  958.     local success, err = pcall(function()
  959.         local scrollFrame = logGui.FruitLogGui.LogScrollFrame
  960.        
  961.         -- Clear existing entries
  962.         for _, child in ipairs(scrollFrame:GetChildren()) do
  963.             if child:IsA("Frame") then
  964.                 child:Destroy()
  965.             end
  966.         end
  967.        
  968.         -- Update title with count
  969.         local titleLabel = logGui.FruitLogGui.Frame.Frame.TextLabel
  970.         if titleLabel then
  971.             titleLabel.Text = "🍎 Fruit Log (" .. #fruitLog .. " entries)"
  972.         end
  973.        
  974.         -- Add log entries
  975.         local yOffset = 0
  976.         for i, entry in ipairs(fruitLog) do
  977.             local entryFrame = Instance.new("Frame")
  978.             entryFrame.Size = UDim2.new(1, -10, 0, 30)
  979.             entryFrame.Position = UDim2.new(0, 5, 0, yOffset)
  980.             entryFrame.BackgroundColor3 = entry.action == "SPAWNED"
  981.                                          and Color3.fromRGB(40, 60, 40)
  982.                                          or Color3.fromRGB(60, 40, 40)
  983.             entryFrame.BackgroundTransparency = 0.3
  984.             entryFrame.Parent = scrollFrame
  985.            
  986.             local entryCorner = Instance.new("UICorner")
  987.             entryCorner.CornerRadius = UDim.new(0, 4)
  988.             entryCorner.Parent = entryFrame
  989.            
  990.             local entryLabel = Instance.new("TextLabel")
  991.             entryLabel.Size = UDim2.new(1, -10, 1, 0)
  992.             entryLabel.Position = UDim2.new(0, 5, 0, 0)
  993.             entryLabel.BackgroundTransparency = 1
  994.             entryLabel.Font = Enum.Font.SourceSans
  995.             entryLabel.TextSize = 11
  996.             entryLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
  997.             entryLabel.TextXAlignment = Enum.TextXAlignment.Left
  998.             entryLabel.TextYAlignment = Enum.TextYAlignment.Center
  999.             entryLabel.TextWrapped = true
  1000.            
  1001.             local actionEmoji = entry.action == "SPAWNED" and "🌟" or "🗑️"
  1002.             local mutText = entry.mutations ~= "None" and " (" .. entry.mutations .. ")" or ""
  1003.            
  1004.             entryLabel.Text = string.format("%s [%s] %s: %s - %s %s%s on %s",
  1005.                 actionEmoji, entry.time, entry.action, entry.fruit, entry.weight, entry.variant, mutText, entry.tree)
  1006.            
  1007.             entryLabel.Parent = entryFrame
  1008.             yOffset = yOffset + 35
  1009.         end
  1010.        
  1011.         scrollFrame.CanvasSize = UDim2.new(0, 0, 0, yOffset)
  1012.        
  1013.         -- Auto-scroll to bottom to see latest entries
  1014.         scrollFrame.CanvasPosition = Vector2.new(0, math.max(0, yOffset - scrollFrame.AbsoluteSize.Y))
  1015.     end)
  1016.    
  1017.     if not success then
  1018.         print("❌ Error updating fruit log display:", err)
  1019.     end
  1020. end
  1021.  
  1022. -- ✅ LOG BUTTON (Position next to refresh button)
  1023. local logButton = Instance.new("TextButton")
  1024. logButton.Name = "LogButton"
  1025. logButton.Size = UDim2.new(0, 80, 0, 25)
  1026. logButton.Position = UDim2.new(0, 115, 0, 3) -- Next to refresh button
  1027. logButton.BackgroundColor3 = Color3.fromRGB(60, 120, 60)
  1028. logButton.Text = "🍎 Log"
  1029. logButton.TextColor3 = Color3.fromRGB(255, 255, 255)
  1030. logButton.TextSize = 14
  1031. logButton.Font = Enum.Font.SourceSansBold
  1032. logButton.Parent = titleBar
  1033.  
  1034. local logCorner = Instance.new("UICorner")
  1035. logCorner.CornerRadius = UDim.new(0, 4)
  1036. logCorner.Parent = logButton
  1037.  
  1038. logButton.MouseButton1Click:Connect(function()
  1039.     if not logGui then
  1040.         createFruitLogGui()
  1041.         updateFruitLogDisplay()
  1042.     else
  1043.         logGui:Destroy()
  1044.         logGui = nil
  1045.     end
  1046. end)
  1047.  
  1048. -- ✅ START FRUIT MONITORING
  1049. spawn(function()
  1050.     -- Initial setup - populate known fruits to avoid spam on first run
  1051.     task.wait(3) -- Wait for GUI to load
  1052.     pcall(checkFruitChanges) -- First scan to populate baseline
  1053.    
  1054.     print("🍎 Fruit monitoring started!")
  1055.    
  1056.     while true do
  1057.         task.wait(3) -- Check every 3 seconds
  1058.         local success, error = pcall(checkFruitChanges)
  1059.         if not success then
  1060.             print("❌ Fruit monitoring error:", error)
  1061.         end
  1062.     end
  1063. end)
  1064.  
  1065. -- Initial refresh
  1066. refreshFruitList()
Advertisement
Add Comment
Please, Sign In to add comment