· 3 months ago · Jun 29, 2025, 11:30 PM
1-- SERVICES & MODULES
2local Players = game:GetService("Players")
3local ReplicatedStorage = game:GetService("ReplicatedStorage")
4local UserInputService = game:GetService("UserInputService")
5local player = Players.LocalPlayer
6
7local GetFarm = require(ReplicatedStorage.Modules.GetFarm)
8local MutationHandler = require(ReplicatedStorage.Modules:WaitForChild("MutationHandler"))
9local Remotes = require(ReplicatedStorage.Modules.Remotes)
10
11-- Helper to format numbers
12local function formatNumber(n)
13 if not n or type(n) ~= "number" then return "$0" end
14 local sign = (n < 0) and "-" or ""
15 local absn = math.abs(n)
16 local suffix = ""
17 if absn >= 1e12 then
18 n = n/1e12; suffix = "T"
19 elseif absn >= 1e9 then
20 n = n/1e9; suffix = "B"
21 elseif absn >= 1e6 then
22 n = n/1e6; suffix = "M"
23 elseif absn >= 1e3 then
24 n = n/1e3; suffix = "K"
25 end
26 local i = math.floor(math.abs(n))
27 local s = tostring(i)
28 while true do
29 local count
30 s, count = s:gsub("^(-?%d+)(%d%d%d)", "%1,%2")
31 if count == 0 then break end
32 end
33 return "$" .. sign .. s .. suffix
34end
35
36-- Helper function for mutation priority
37local function getMutationPriority(mutation)
38 local priorityMap = {
39 ["Moonlit"] = 6,
40 ["Choc"] = 5,
41 ["Shocked"] = 4,
42 ["Frozen"] = 3,
43 ["Chilled"] = 2,
44 ["Wet"] = 1,
45 ["None"] = 0
46 }
47
48 -- Count mutations and assign a priority
49 if mutation == "None" then
50 return 0
51 end
52
53 -- If it contains multiple mutations, count them
54 local count = 0
55 for w in mutation:gmatch("([^,]+)") do
56 count = count + 1
57 end
58
59 -- Multiple mutations always have highest priority
60 if count > 1 then
61 return 100 + count
62 end
63
64 -- Single mutation - look up its priority
65 for mutName, priority in pairs(priorityMap) do
66 if mutation:find(mutName) then
67 return priority
68 end
69 end
70
71 return 0
72end
73
74-- Helper function for variant priority
75local function getVariantPriority(variant)
76 local priorityMap = {
77 ["Rainbow"] = 3,
78 ["Gold"] = 2,
79 ["Normal"] = 1
80 }
81
82 return priorityMap[variant] or 0
83end
84
85-- ACCURATE price calculation based on wiki information
86local function calculatePrice(weight, variant, mutations)
87 -- Base price from weight
88 local basePrice = weight * 100
89
90 -- Parse mutations into a table for easier checking
91 local mutationsTable = {}
92 if mutations ~= "None" then
93 for mut in mutations:gmatch("([^,]+)") do
94 mut = mut:gsub("^%s*(.-)%s*$", "%1") -- Trim whitespace
95 mutationsTable[mut] = true
96 end
97 end
98
99 -- Mutation multipliers from wiki
100 local mutationMulti = 1
101
102 -- Check for each mutation type with their correct multipliers
103 if mutationsTable["Shocked"] then
104 mutationMulti = mutationMulti * 100 -- x100 for Shocked
105 end
106
107 if mutationsTable["Frozen"] then
108 mutationMulti = mutationMulti * 10 -- x10 for Frozen
109 end
110
111 if mutationsTable["Wet"] then
112 mutationMulti = mutationMulti * 2 -- x2 for Wet
113 end
114
115 if mutationsTable["Chilled"] then
116 mutationMulti = mutationMulti * 2 -- x2 for Chilled
117 end
118
119 if mutationsTable["Choc"] then
120 mutationMulti = mutationMulti * 2 -- x2 for Chocolate
121 end
122
123 if mutationsTable["Moonlit"] then
124 mutationMulti = mutationMulti * 2 -- x2 for Moonlit
125 end
126
127 -- Apply variant multiplier
128 local variantMulti = 1
129 if variant == "Gold" then
130 variantMulti = 20 -- x20 for Gold
131 elseif variant == "Rainbow" then
132 variantMulti = 50 -- x50 for Rainbow
133 end
134
135 -- Final calculation: basePrice * variantMulti * mutationMulti
136 local finalPrice = basePrice * variantMulti * mutationMulti
137 return finalPrice
138end
139
140-- GUI SETUP
141local playerGui = player:WaitForChild("PlayerGui")
142
143-- Check if GUI already exists and remove it
144local existingGui = playerGui:FindFirstChild("FruitListGui")
145if existingGui then
146 existingGui:Destroy()
147end
148
149-- State variables
150local currentSortColumn = "Fruit Name" -- Default sort by name
151local currentSortDir = "asc" -- Default ascending
152local allFruitsData = {} -- Will store all fruits data for sorting
153local isMinimized = false -- Track minimize state
154local originalSize -- Store original size when minimizing
155local areFruitsHidden = false -- Track visibility of fruits
156
157local fruitListGui = Instance.new("ScreenGui")
158fruitListGui.Name = "FruitListGui"
159fruitListGui.ResetOnSpawn = false
160fruitListGui.Parent = playerGui
161
162local mainFrame = Instance.new("Frame")
163mainFrame.Size = UDim2.new(0, 500, 0, 400)
164mainFrame.Position = UDim2.new(0.5, -250, 0.5, -200) -- change size and position
165mainFrame.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
166mainFrame.BackgroundTransparency = 0.1
167mainFrame.Parent = fruitListGui
168mainFrame.Active = true
169
170-- Store original size for minimizing
171originalSize = mainFrame.Size
172
173-- Add rounded corners to main frame
174local mainCorner = Instance.new("UICorner")
175mainCorner.CornerRadius = UDim.new(0, 8)
176mainCorner.Parent = mainFrame
177
178-- Title bar
179local titleBar = Instance.new("Frame")
180titleBar.Name = "TitleBar"
181titleBar.Size = UDim2.new(1, 0, 0, 30)
182titleBar.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
183titleBar.BorderSizePixel = 0
184titleBar.Parent = mainFrame
185
186-- Add rounded corners to title bar (top corners only)
187local titleCorner = Instance.new("UICorner")
188titleCorner.CornerRadius = UDim.new(0, 8)
189titleCorner.Parent = titleBar
190
191-- Make sure the title bar only rounds the top corners
192local bottomFrame = Instance.new("Frame")
193bottomFrame.Size = UDim2.new(1, 0, 0.5, 0)
194bottomFrame.Position = UDim2.new(0, 0, 0.5, 0)
195bottomFrame.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
196bottomFrame.BorderSizePixel = 0
197bottomFrame.Parent = titleBar
198
199local titleText = Instance.new("TextLabel")
200titleText.Name = "Title"
201titleText.Size = UDim2.new(1, -100, 1, 0)
202titleText.BackgroundTransparency = 1
203titleText.Text = "Farm Fruit List"
204titleText.Font = Enum.Font.SourceSansBold
205titleText.TextColor3 = Color3.fromRGB(255, 255, 255)
206titleText.TextSize = 18
207titleText.Parent = titleBar
208
209-- Close button
210local closeButton = Instance.new("TextButton")
211closeButton.Name = "CloseButton"
212closeButton.Size = UDim2.new(0, 30, 0, 30)
213closeButton.Position = UDim2.new(1, -30, 0, 0)
214closeButton.BackgroundColor3 = Color3.fromRGB(200, 60, 60)
215closeButton.Text = "X"
216closeButton.TextColor3 = Color3.fromRGB(255, 255, 255)
217closeButton.TextSize = 18
218closeButton.Font = Enum.Font.SourceSansBold
219closeButton.Parent = titleBar
220
221-- Add rounded corners to close button
222local closeCorner = Instance.new("UICorner")
223closeCorner.CornerRadius = UDim.new(0, 6)
224closeCorner.Parent = closeButton
225
226-- Minimize button
227local minimizeButton = Instance.new("TextButton")
228minimizeButton.Name = "MinimizeButton"
229minimizeButton.Size = UDim2.new(0, 30, 0, 30)
230minimizeButton.Position = UDim2.new(1, -65, 0, 0)
231minimizeButton.BackgroundColor3 = Color3.fromRGB(60, 60, 200)
232minimizeButton.Text = "-"
233minimizeButton.TextColor3 = Color3.fromRGB(255, 255, 255)
234minimizeButton.TextSize = 22
235minimizeButton.Font = Enum.Font.SourceSansBold
236minimizeButton.Parent = titleBar
237
238-- Add rounded corners to minimize button
239local minimizeCorner = Instance.new("UICorner")
240minimizeCorner.CornerRadius = UDim.new(0, 6)
241minimizeCorner.Parent = minimizeButton
242
243-- Function to toggle minimize state
244local function toggleMinimize()
245 isMinimized = not isMinimized
246
247 if isMinimized then
248 -- Store current size before minimizing
249 originalSize = mainFrame.Size
250
251 -- Minimize GUI - just show title bar
252 mainFrame.Size = UDim2.new(0, 300, 0, 30)
253 minimizeButton.Text = "+"
254
255 -- Hide content
256 if mainFrame:FindFirstChild("HeaderFrame") then
257 mainFrame.HeaderFrame.Visible = false
258 end
259 if mainFrame:FindFirstChild("ScrollingFrame") then
260 mainFrame.ScrollingFrame.Visible = false
261 end
262 if mainFrame:FindFirstChild("TotalFrame") then
263 mainFrame.TotalFrame.Visible = false
264 end
265 if mainFrame:FindFirstChild("ResizeHandle") then
266 mainFrame.ResizeHandle.Visible = false
267 end
268 else
269 -- Restore GUI to original size
270 mainFrame.Size = originalSize
271 minimizeButton.Text = "-"
272
273 -- Show content
274 if mainFrame:FindFirstChild("HeaderFrame") then
275 mainFrame.HeaderFrame.Visible = true
276 end
277 if mainFrame:FindFirstChild("ScrollingFrame") then
278 mainFrame.ScrollingFrame.Visible = true
279 end
280 if mainFrame:FindFirstChild("TotalFrame") then
281 mainFrame.TotalFrame.Visible = true
282 end
283 if mainFrame:FindFirstChild("ResizeHandle") then
284 mainFrame.ResizeHandle.Visible = true
285 end
286 end
287end
288
289-- Connect minimize button
290minimizeButton.MouseButton1Click:Connect(toggleMinimize)
291
292-- Add keyboard shortcut (Left Ctrl) to toggle minimize
293UserInputService.InputBegan:Connect(function(input)
294 if input.KeyCode == Enum.KeyCode.LeftControl then
295 toggleMinimize()
296 end
297end)
298
299-- Resize Handle
300local resizeHandle = Instance.new("Frame")
301resizeHandle.Size = UDim2.new(0, 24, 0, 24)
302resizeHandle.Position = UDim2.new(1, -24, 1, -24)
303resizeHandle.BackgroundColor3 = Color3.fromRGB(80, 80, 80)
304resizeHandle.BorderSizePixel = 0
305resizeHandle.Parent = mainFrame
306resizeHandle.Name = "ResizeHandle"
307resizeHandle.ZIndex = 10
308
309local resizeCorner = Instance.new("UICorner")
310resizeCorner.CornerRadius = UDim.new(0, 8)
311resizeCorner.Parent = resizeHandle
312
313-- IMPROVED DRAGGING IMPLEMENTATION
314local dragging = false
315local dragInput
316local dragStart
317local startPos
318local lastMousePos
319local lastGoalPos
320
321local function updateDrag(input)
322 if dragging then
323 local delta = input.Position - dragStart
324 local position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X,
325 startPos.Y.Scale, startPos.Y.Offset + delta.Y)
326
327 -- Use a smoother movement with lerping
328 game:GetService("RunService").RenderStepped:Wait()
329 mainFrame.Position = position
330 end
331end
332
333titleBar.InputBegan:Connect(function(input)
334 if input.UserInputType == Enum.UserInputType.MouseButton1 or
335 input.UserInputType == Enum.UserInputType.Touch then
336 dragging = true
337 dragStart = input.Position
338 startPos = mainFrame.Position
339 lastMousePos = Vector2.new(input.Position.X, input.Position.Y)
340
341 -- Continue tracking even if mouse leaves the titleBar
342 input.Changed:Connect(function()
343 if input.UserInputState == Enum.UserInputState.End then
344 dragging = false
345 end
346 end)
347 end
348end)
349
350titleBar.InputChanged:Connect(function(input)
351 if input.UserInputType == Enum.UserInputType.MouseMovement or
352 input.UserInputType == Enum.UserInputType.Touch then
353 dragInput = input
354 end
355end)
356
357UserInputService.InputChanged:Connect(function(input)
358 if input == dragInput and dragging then
359 updateDrag(input)
360 end
361end)
362
363-- Resize Script
364local draggingResize = false
365local resizeStart
366local startSize
367
368resizeHandle.InputBegan:Connect(function(input)
369 if input.UserInputType == Enum.UserInputType.MouseButton1 or
370 input.UserInputType == Enum.UserInputType.Touch then
371 draggingResize = true
372 resizeStart = input.Position
373 startSize = mainFrame.Size
374
375 -- Track input end even outside the resize handle
376 input.Changed:Connect(function()
377 if input.UserInputState == Enum.UserInputState.End then
378 draggingResize = false
379 end
380 end)
381 end
382end)
383
384UserInputService.InputChanged:Connect(function(input)
385 if draggingResize and (input.UserInputType == Enum.UserInputType.MouseMovement or
386 input.UserInputType == Enum.UserInputType.Touch) then
387 local delta = input.Position - resizeStart
388 local newWidth = math.max(400, startSize.X.Offset + delta.X)
389 local newHeight = math.max(300, startSize.Y.Offset + delta.Y)
390 mainFrame.Size = UDim2.new(0, newWidth, 0, newHeight)
391
392 -- Store new size for when un-minimizing
393 originalSize = mainFrame.Size
394
395 -- Recalculate scrolling frame size when resizing
396 local headerHeight = 30 -- title bar height
397 if mainFrame:FindFirstChild("HeaderFrame") and mainFrame:FindFirstChild("ScrollingFrame") then
398 mainFrame.ScrollingFrame.Size = UDim2.new(1, -20, 1, -(headerHeight + mainFrame.HeaderFrame.Size.Y.Offset + 20))
399 end
400 end
401end)
402
403-- Close button logic
404closeButton.MouseButton1Click:Connect(function()
405 fruitListGui:Destroy()
406end)
407
408-- Header Frame for column titles
409local headerFrame = Instance.new("Frame")
410headerFrame.Name = "HeaderFrame"
411headerFrame.Size = UDim2.new(1, -20, 0, 35)
412headerFrame.Position = UDim2.new(0, 10, 0, 40)
413headerFrame.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
414headerFrame.BackgroundTransparency = 0.5
415headerFrame.Parent = mainFrame
416
417-- Add rounded corners to header frame
418local headerCorner = Instance.new("UICorner")
419headerCorner.CornerRadius = UDim.new(0, 6)
420headerCorner.Parent = headerFrame
421
422-- Column Headers with sort buttons
423local columns = {"Fruit Name", "Variant", "Mutations", "Weight (kg)", "Price", "", ""} -- Two empty columns: hide and collect buttons
424local columnWidths = {0.22, 0.12, 0.21, 0.12, 0.16, 0.08, 0.09} -- Swapped widths (hide is smaller than collect)
425local sortButtons = {}
426
427-- Scrolling Frame for fruit list (create early so refreshFruitList can use it)
428local scrollingFrame = Instance.new("ScrollingFrame")
429scrollingFrame.Name = "ScrollingFrame"
430scrollingFrame.Size = UDim2.new(1, -20, 1, -105)
431scrollingFrame.Position = UDim2.new(0, 10, 0, 85)
432scrollingFrame.BackgroundTransparency = 0.9
433scrollingFrame.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
434scrollingFrame.BorderSizePixel = 0
435scrollingFrame.ScrollBarThickness = 8
436scrollingFrame.Parent = mainFrame
437
438-- Total price indicator
439local totalFrame = Instance.new("Frame")
440totalFrame.Name = "TotalFrame"
441totalFrame.Size = UDim2.new(1, -20, 0, 30)
442totalFrame.Position = UDim2.new(0, 10, 1, -40)
443totalFrame.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
444totalFrame.BackgroundTransparency = 0.5
445totalFrame.Parent = mainFrame
446
447-- Add rounded corners to total frame
448local totalCorner = Instance.new("UICorner")
449totalCorner.CornerRadius = UDim.new(0, 6)
450totalCorner.Parent = totalFrame
451
452local totalLabel = Instance.new("TextLabel")
453totalLabel.Name = "TotalLabel"
454totalLabel.Size = UDim2.new(0.5, 0, 1, 0)
455totalLabel.BackgroundTransparency = 1
456totalLabel.Font = Enum.Font.SourceSansBold
457totalLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
458totalLabel.TextSize = 18
459totalLabel.Text = "Total Value:"
460totalLabel.TextXAlignment = Enum.TextXAlignment.Left
461totalLabel.Position = UDim2.new(0, 10, 0, 0)
462totalLabel.Parent = totalFrame
463
464local totalValueLabel = Instance.new("TextLabel")
465totalValueLabel.Name = "TotalValueLabel"
466totalValueLabel.Size = UDim2.new(0.5, 0, 1, 0)
467totalValueLabel.Position = UDim2.new(0.5, 0, 0, 0)
468totalValueLabel.BackgroundTransparency = 1
469totalValueLabel.Font = Enum.Font.SourceSansBold
470totalValueLabel.TextColor3 = Color3.fromRGB(255, 255, 100)
471totalValueLabel.TextSize = 18
472totalValueLabel.Text = "$0"
473totalValueLabel.TextXAlignment = Enum.TextXAlignment.Right
474totalValueLabel.Position = UDim2.new(0.5, -10, 0, 0)
475totalValueLabel.Parent = totalFrame
476
477-- Add collect all button to the total frame
478local collectAllButton = Instance.new("TextButton")
479collectAllButton.Name = "CollectAllButton"
480collectAllButton.Size = UDim2.new(0, 100, 0, 24)
481collectAllButton.Position = UDim2.new(0, 100, 0.5, -12)
482collectAllButton.BackgroundColor3 = Color3.fromRGB(60, 150, 60)
483collectAllButton.Text = "Collect All"
484collectAllButton.TextColor3 = Color3.fromRGB(255, 255, 255)
485collectAllButton.TextSize = 15
486collectAllButton.Font = Enum.Font.SourceSansBold
487collectAllButton.Visible = true
488collectAllButton.Parent = totalFrame
489
490-- Add rounded corners to collect all button
491local collectAllCorner = Instance.new("UICorner")
492collectAllCorner.CornerRadius = UDim.new(0, 4)
493collectAllCorner.Parent = collectAllButton
494
495-- NEW: Add hide fruits button to toggle fruit visibility
496local hideFruitsButton = Instance.new("TextButton")
497hideFruitsButton.Name = "HideFruitsButton"
498hideFruitsButton.Size = UDim2.new(0, 100, 0, 24)
499hideFruitsButton.Position = UDim2.new(0, 210, 0.5, -12)
500hideFruitsButton.BackgroundColor3 = Color3.fromRGB(60, 60, 150)
501hideFruitsButton.Text = "Hide Fruits"
502hideFruitsButton.TextColor3 = Color3.fromRGB(255, 255, 255)
503hideFruitsButton.TextSize = 15
504hideFruitsButton.Font = Enum.Font.SourceSansBold
505hideFruitsButton.Visible = true
506hideFruitsButton.Parent = totalFrame
507
508-- Add rounded corners to hide fruits button
509local hideFruitsCorner = Instance.new("UICorner")
510hideFruitsCorner.CornerRadius = UDim.new(0, 4)
511hideFruitsCorner.Parent = hideFruitsButton
512
513-- Information display for keyboard shortcuts
514local infoLabel = Instance.new("TextLabel")
515infoLabel.Name = "InfoLabel"
516infoLabel.Size = UDim2.new(0, 260, 0, 20)
517infoLabel.Position = UDim2.new(1, -270, 0, 5)
518infoLabel.BackgroundTransparency = 1
519infoLabel.TextColor3 = Color3.fromRGB(180, 180, 180)
520infoLabel.Font = Enum.Font.SourceSans
521infoLabel.TextSize = 13
522infoLabel.Text = "Press LeftCtrl to Toggle Minimize"
523infoLabel.TextXAlignment = Enum.TextXAlignment.Right
524infoLabel.Parent = totalFrame
525
526-- Refresh Button
527local refreshButton = Instance.new("TextButton")
528refreshButton.Name = "RefreshButton"
529refreshButton.Size = UDim2.new(0, 100, 0, 25)
530refreshButton.Position = UDim2.new(0, 10, 0, 3)
531refreshButton.BackgroundColor3 = Color3.fromRGB(60, 120, 60)
532refreshButton.Text = "Refresh"
533refreshButton.TextColor3 = Color3.fromRGB(255, 255, 255)
534refreshButton.TextSize = 16
535refreshButton.Font = Enum.Font.SourceSansBold
536refreshButton.Parent = titleBar
537
538-- Create a UICorner for the refresh button
539local refreshCorner = Instance.new("UICorner")
540refreshCorner.CornerRadius = UDim.new(0, 4)
541refreshCorner.Parent = refreshButton
542
543-- Status label (for minimize tooltip)
544local statusLabel = Instance.new("TextLabel")
545statusLabel.Name = "StatusLabel"
546statusLabel.Size = UDim2.new(0, 200, 0, 20)
547statusLabel.Position = UDim2.new(0.5, -100, 0, -25)
548statusLabel.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
549statusLabel.BackgroundTransparency = 0.2
550statusLabel.Text = "Press Left Ctrl to minimize"
551statusLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
552statusLabel.TextSize = 14
553statusLabel.Font = Enum.Font.SourceSans
554statusLabel.Visible = false
555statusLabel.Parent = mainFrame
556
557-- Add rounded corners to status label
558local statusCorner = Instance.new("UICorner")
559statusCorner.CornerRadius = UDim.new(0, 4)
560statusCorner.Parent = statusLabel
561
562-- Show tooltip when hovering minimize button
563minimizeButton.MouseEnter:Connect(function()
564 statusLabel.Visible = true
565end)
566
567minimizeButton.MouseLeave:Connect(function()
568 statusLabel.Visible = false
569end)
570
571-- Function declaration for refreshFruitList (will be defined later)
572local refreshFruitList
573
574-- Function to create sorted fruit list
575local function createSortedFruitList()
576 -- Clear existing list
577 for _, child in pairs(scrollingFrame:GetChildren()) do
578 if child:IsA("Frame") then
579 child:Destroy()
580 end
581 end
582
583 -- Sort the fruits data based on current sort column and direction
584 -- Sort the fruits data based on current sort column and direction
585 table.sort(allFruitsData, function(a, b)
586 local aValue, bValue
587
588 if currentSortColumn == "Fruit Name" then
589 aValue = a.name:lower()
590 bValue = b.name:lower()
591
592 elseif currentSortColumn == "Variant" then
593 -- Sort by variant priority
594 aValue = getVariantPriority(a.variant)
595 bValue = getVariantPriority(b.variant)
596
597 elseif currentSortColumn == "Mutations" then
598 -- Sort by mutation priority
599 aValue = getMutationPriority(a.mutations)
600 bValue = getMutationPriority(b.mutations)
601
602 elseif currentSortColumn == "Weight (kg)" then
603 -- Use the raw numeric weight value instead of the string
604 aValue = a.weightNum or 0
605 bValue = b.weightNum or 0
606
607 elseif currentSortColumn == "Price" then
608 -- Use the raw price values (not formatted)
609 aValue = a.price or 0
610 bValue = b.price or 0
611 else
612 return false
613 end
614
615 if currentSortDir == "asc" then
616 return aValue < bValue
617 else
618 return aValue > bValue
619 end
620 end)
621
622 -- Update sort button appearance
623 for colName, button in pairs(sortButtons) do
624 if colName == currentSortColumn then
625 button.Text = currentSortDir == "asc" and "▲" or "▼"
626 button.TextColor3 = Color3.fromRGB(255, 255, 100) -- Highlight active sort
627 else
628 button.Text = "◆"
629 button.TextColor3 = Color3.fromRGB(150, 150, 150) -- Dim inactive sorts
630 end
631 end
632
633 local rowHeight = 30
634 for i, fruitData in ipairs(allFruitsData) do
635 -- Create row frame
636 local rowFrame = Instance.new("Frame")
637 rowFrame.Name = "Row_" .. i
638 rowFrame.Size = UDim2.new(1, 0, 0, rowHeight)
639 rowFrame.Position = UDim2.new(0, 0, 0, (i-1) * rowHeight)
640 rowFrame.BackgroundColor3 = i % 2 == 0 and Color3.fromRGB(40, 40, 40) or Color3.fromRGB(35, 35, 35)
641 rowFrame.BackgroundTransparency = 0.3
642 rowFrame.Parent = scrollingFrame
643
644 -- Store the fruit data in the row frame for later lookup
645 rowFrame:SetAttribute("FruitIndex", i)
646
647 -- Add hover effect
648 rowFrame.InputBegan:Connect(function(input)
649 if input.UserInputType == Enum.UserInputType.MouseMovement then
650 rowFrame.BackgroundTransparency = 0.1
651 end
652 end)
653
654 rowFrame.InputEnded:Connect(function(input)
655 if input.UserInputType == Enum.UserInputType.MouseMovement then
656 rowFrame.BackgroundTransparency = 0.3
657 end
658 end)
659
660 -- Create columns in the row
661 local currentX = 0
662 local columnValues = {fruitData.name, fruitData.variant, fruitData.mutations, fruitData.weight, fruitData.formattedPrice, "", ""}
663
664 for j, columnValue in ipairs(columnValues) do
665 if j < 6 then -- Regular data columns
666 local cell = Instance.new("TextLabel")
667 cell.Name = "Column" .. j
668 cell.Size = UDim2.new(columnWidths[j], 0, 1, 0)
669 cell.Position = UDim2.new(currentX, 0, 0, 0)
670 cell.BackgroundTransparency = 1
671 cell.Font = Enum.Font.SourceSans
672 cell.TextColor3 = Color3.fromRGB(255, 255, 255)
673 cell.TextSize = 16
674 cell.Text = tostring(columnValue)
675 cell.TextXAlignment = Enum.TextXAlignment.Left
676 cell.TextWrapped = true
677 cell.Parent = rowFrame
678
679 -- Add padding
680 cell.Position = UDim2.new(currentX, 5, 0, 0)
681 cell.Size = UDim2.new(columnWidths[j], -10, 1, 0)
682
683 elseif j == 6 then -- HIDE BUTTON (swapped with collect)
684 -- Create hide button for this fruit
685 local hideButton = Instance.new("TextButton")
686 hideButton.Name = "HideButton"
687 hideButton.Size = UDim2.new(columnWidths[j], -10, 0, 22)
688 hideButton.Position = UDim2.new(currentX, 5, 0.5, -11)
689 hideButton.BackgroundColor3 = Color3.fromRGB(60, 60, 150)
690 hideButton.Text = fruitData.isHidden and "Show" or "Hide"
691 hideButton.TextColor3 = Color3.fromRGB(255, 255, 255)
692 hideButton.TextSize = 14
693 hideButton.Font = Enum.Font.SourceSansBold
694 hideButton.Parent = rowFrame
695
696 -- Add rounded corners to button
697 local buttonCorner = Instance.new("UICorner")
698 buttonCorner.CornerRadius = UDim.new(0, 4)
699 buttonCorner.Parent = hideButton
700
701 -- Hide button functionality - using index lookup from allFruitsData
702 hideButton.MouseButton1Click:Connect(function()
703 local index = rowFrame:GetAttribute("FruitIndex")
704 local currentFruitData = allFruitsData[index]
705 local fruitModel = currentFruitData.model
706
707 if fruitModel and fruitModel:IsA("Model") and fruitModel.Parent then
708 -- Toggle this fruit's visibility
709 currentFruitData.isHidden = not currentFruitData.isHidden
710
711 -- Update all parts in the model
712 for _, part in pairs(fruitModel:GetDescendants()) do
713 if part:IsA("BasePart") or part:IsA("MeshPart") or
714 part:IsA("UnionOperation") or part:IsA("Decal") or
715 part:IsA("Texture") then
716 part.Transparency = currentFruitData.isHidden and 1 or 0
717 end
718 end
719
720 -- Update button text
721 hideButton.Text = currentFruitData.isHidden and "Show" or "Hide"
722 hideButton.BackgroundColor3 = currentFruitData.isHidden and Color3.fromRGB(80, 80, 160) or Color3.fromRGB(60, 60, 150)
723 end
724 end)
725
726 -- Add hover effect
727 hideButton.MouseEnter:Connect(function()
728 hideButton.BackgroundColor3 = fruitData.isHidden and Color3.fromRGB(100, 100, 200) or Color3.fromRGB(80, 80, 180)
729 end)
730
731 hideButton.MouseLeave:Connect(function()
732 hideButton.BackgroundColor3 = fruitData.isHidden and Color3.fromRGB(80, 80, 160) or Color3.fromRGB(60, 60, 150)
733 end)
734
735 else -- j == 7 - COLLECT BUTTON (swapped with hide)
736 -- Create collect button
737 local collectButton = Instance.new("TextButton")
738 collectButton.Name = "CollectButton"
739 collectButton.Size = UDim2.new(columnWidths[j], -10, 0, 22)
740 collectButton.Position = UDim2.new(currentX, 5, 0.5, -11)
741 collectButton.BackgroundColor3 = Color3.fromRGB(60, 150, 60)
742 collectButton.Text = "Collect"
743 collectButton.TextColor3 = Color3.fromRGB(255, 255, 255)
744 collectButton.TextSize = 14
745 collectButton.Font = Enum.Font.SourceSansBold
746 collectButton.Parent = rowFrame
747
748 -- Add rounded corners to button
749 local buttonCorner = Instance.new("UICorner")
750 buttonCorner.CornerRadius = UDim.new(0, 4)
751 buttonCorner.Parent = collectButton
752
753 -- Collect button functionality - using index lookup from allFruitsData
754 collectButton.MouseButton1Click:Connect(function()
755 local index = rowFrame:GetAttribute("FruitIndex")
756 local currentFruitData = allFruitsData[index]
757 local fruitModel = currentFruitData.model
758
759 if fruitModel and fruitModel:IsA("Model") and fruitModel.Parent then
760 -- Use Remotes module to collect just this fruit
761 Remotes.Crops.Collect.send({fruitModel})
762 collectButton.Text = "Collected!"
763 collectButton.BackgroundColor3 = Color3.fromRGB(100, 100, 100)
764 collectButton.Active = false
765
766 -- Refresh immediately after collecting
767 refreshFruitList()
768 end
769 end)
770
771 -- Add hover effect
772 collectButton.MouseEnter:Connect(function()
773 if collectButton.Active ~= false then
774 collectButton.BackgroundColor3 = Color3.fromRGB(80, 180, 80)
775 end
776 end)
777
778 collectButton.MouseLeave:Connect(function()
779 if collectButton.Active ~= false then
780 collectButton.BackgroundColor3 = Color3.fromRGB(60, 150, 60)
781 end
782 end)
783 end
784
785 currentX = currentX + columnWidths[j]
786 end
787 end
788
789 -- Update scrolling frame content size
790 scrollingFrame.CanvasSize = UDim2.new(0, 0, 0, #allFruitsData * rowHeight)
791
792 -- Update counter
793 titleText.Text = "Farm Fruit List - " .. #allFruitsData .. " Fruits"
794end
795
796
797-- Function to toggle fruit visibility in the world
798local function toggleFruitVisibility()
799 areFruitsHidden = not areFruitsHidden
800
801 -- Get player farm
802 local farm = GetFarm(player)
803 if not farm or not farm:FindFirstChild("Important") or not farm.Important:FindFirstChild("Plants_Physical") then
804 return
805 end
806
807 -- Loop through all tree types to find fruits
808 local plantsPhysical = farm.Important.Plants_Physical
809 for _, treeType in pairs(plantsPhysical:GetChildren()) do
810 local fruitsFolder = treeType:FindFirstChild("Fruits")
811 if fruitsFolder then
812 for _, fruitModel in pairs(fruitsFolder:GetChildren()) do
813 if fruitModel:IsA("Model") then
814 -- Check if this fruit has individual visibility override
815 local hasIndividualSetting = false
816
817 for _, fruitData in ipairs(allFruitsData) do
818 if fruitData.model == fruitModel and fruitData.isHidden then
819 hasIndividualSetting = true
820 break
821 end
822 end
823
824 -- Only apply global visibility if no individual setting
825 if not hasIndividualSetting then
826 -- Toggle visibility of all parts in the fruit model
827 for _, part in pairs(fruitModel:GetDescendants()) do
828 if part:IsA("BasePart") or part:IsA("MeshPart") or
829 part:IsA("UnionOperation") or part:IsA("Decal") or
830 part:IsA("Texture") then
831 part.Transparency = areFruitsHidden and 1 or 0
832 end
833 end
834 end
835 end
836 end
837 end
838 end
839
840 -- Update button text
841 hideFruitsButton.Text = areFruitsHidden and "Show Fruits" or "Hide Fruits"
842
843 -- Refresh the list to update the individual hide buttons
844 createSortedFruitList()
845end
846
847-- Connect hide fruits button
848hideFruitsButton.MouseButton1Click:Connect(toggleFruitVisibility)
849
850-- Add hover effect to hide fruits button
851hideFruitsButton.MouseEnter:Connect(function()
852 hideFruitsButton.BackgroundColor3 = Color3.fromRGB(80, 80, 180)
853end)
854
855hideFruitsButton.MouseLeave:Connect(function()
856 hideFruitsButton.BackgroundColor3 = Color3.fromRGB(60, 60, 150)
857end)
858
859-- Column Headers
860local currentX = 0
861for i, columnName in ipairs(columns) do
862 local headerContainer = Instance.new("Frame")
863 headerContainer.Name = columnName == "" and ("ActionHeaderContainer" .. i) or (columnName:gsub(" ", "") .. "HeaderContainer")
864 headerContainer.Size = UDim2.new(columnWidths[i], 0, 1, 0)
865 headerContainer.Position = UDim2.new(currentX, 0, 0, 0)
866 headerContainer.BackgroundTransparency = 1
867 headerContainer.Parent = headerFrame
868
869 if columnName ~= "" then -- Skip empty column (for action buttons)
870 local columnHeader = Instance.new("TextLabel")
871 columnHeader.Name = columnName:gsub(" ", "") .. "Header"
872 columnHeader.Size = UDim2.new(1, -25, 1, 0) -- Make room for sort button
873 columnHeader.Position = UDim2.new(0, 5, 0, 0)
874 columnHeader.BackgroundTransparency = 1
875 columnHeader.Font = Enum.Font.SourceSansBold
876 columnHeader.TextColor3 = Color3.fromRGB(255, 255, 255)
877 columnHeader.TextSize = 18
878 columnHeader.Text = columnName
879 columnHeader.TextXAlignment = Enum.TextXAlignment.Left
880 columnHeader.Parent = headerContainer
881
882 -- Add sort button
883 local sortButton = Instance.new("TextButton")
884 sortButton.Name = "SortButton"
885 sortButton.Size = UDim2.new(0, 20, 0, 20)
886 sortButton.Position = UDim2.new(1, -25, 0.5, -10)
887 sortButton.BackgroundTransparency = 0.8
888 sortButton.BackgroundColor3 = Color3.fromRGB(60, 60, 60)
889 sortButton.Text = columnName == currentSortColumn and "▲" or "◆" -- Triangle up for current sort, diamond for others
890 sortButton.TextColor3 = columnName == currentSortColumn
891 and Color3.fromRGB(255, 255, 100)
892 or Color3.fromRGB(150, 150, 150)
893 sortButton.TextSize = 14
894 sortButton.Font = Enum.Font.SourceSansBold
895 sortButton.Parent = headerContainer
896
897 -- Add rounded corners to sort button
898 local sortCorner = Instance.new("UICorner")
899 sortCorner.CornerRadius = UDim.new(0, 4)
900 sortCorner.Parent = sortButton
901
902 -- Store the sort button for later reference
903 sortButtons[columnName] = sortButton
904
905 -- Sort button click handler
906 sortButton.MouseButton1Click:Connect(function()
907 if currentSortColumn == columnName then
908 -- Toggle direction if same column
909 currentSortDir = currentSortDir == "asc" and "desc" or "asc"
910 else
911 -- New column, default directions
912 currentSortColumn = columnName
913
914 -- Special case: weight and price should default to descending (high to low)
915 if columnName == "Weight (kg)" or columnName == "Price" then
916 currentSortDir = "desc"
917 else
918 -- Variant and mutation have special logic so desc is actually "best first"
919 if columnName == "Variant" or columnName == "Mutations" then
920 currentSortDir = "desc" -- Rainbow/Multiple mutations first
921 else
922 currentSortDir = "asc" -- A-Z for regular text
923 end
924 end
925 end
926
927 createSortedFruitList()
928 end)
929
930 -- Add hover effect to sort button
931 sortButton.MouseEnter:Connect(function()
932 sortButton.BackgroundTransparency = 0.5
933 end)
934
935 sortButton.MouseLeave:Connect(function()
936 sortButton.BackgroundTransparency = 0.8
937 end)
938 else
939 -- Add headers for the action buttons
940 local actionText = i == 6 and "Hide" or "Collect" -- Swapped order
941
942 local actionHeader = Instance.new("TextLabel")
943 actionHeader.Name = actionText .. "Header"
944 actionHeader.Size = UDim2.new(1, -10, 1, 0)
945 actionHeader.Position = UDim2.new(0, 5, 0, 0)
946 actionHeader.BackgroundTransparency = 1
947 actionHeader.Font = Enum.Font.SourceSansBold
948 actionHeader.TextColor3 = Color3.fromRGB(255, 255, 255)
949 actionHeader.TextSize = 18
950 actionHeader.Text = actionText
951 actionHeader.TextXAlignment = Enum.TextXAlignment.Center
952 actionHeader.Parent = headerContainer
953 end
954
955 currentX = currentX + columnWidths[i]
956end
957
958-- Function to refresh the fruit list
959refreshFruitList = function()
960 -- Clear all fruit data
961 allFruitsData = {}
962
963 -- Get player farm
964 local farm = GetFarm(player)
965 if not farm or not farm:FindFirstChild("Important") or not farm.Important:FindFirstChild("Plants_Physical") then
966 local errorLabel = Instance.new("TextLabel")
967 errorLabel.Size = UDim2.new(1, 0, 0, 30)
968 errorLabel.Position = UDim2.new(0, 0, 0, 0)
969 errorLabel.BackgroundTransparency = 1
970 errorLabel.TextColor3 = Color3.fromRGB(255, 100, 100)
971 errorLabel.Text = "Farm not found!"
972 errorLabel.Font = Enum.Font.SourceSansSemibold
973 errorLabel.TextSize = 18
974 errorLabel.Parent = scrollingFrame
975 return
976 end
977
978 local plantsPhysical = farm.Important.Plants_Physical
979 local totalValue = 0
980
981 -- Loop through all tree types
982 for _, treeType in pairs(plantsPhysical:GetChildren()) do
983 local fruitsFolder = treeType:FindFirstChild("Fruits")
984 if fruitsFolder then
985 for _, fruitModel in pairs(fruitsFolder:GetChildren()) do
986 if fruitModel:IsA("Model") then
987 -- Get fruit attributes and properties
988 local fruitName = fruitModel.Name
989
990 -- Get variant (typically stored as a child)
991 local variant = fruitModel:FindFirstChild("Variant")
992 local variantText = variant and variant.Value or "Normal"
993
994 -- Get weight
995 local weight = fruitModel:FindFirstChild("Weight")
996 local weightNum = weight and weight.Value or 0
997 local weightValue = weight and string.format("%.2f", weightNum) or "?"
998
999 -- Get mutations from attributes (using MutationHandler if available)
1000 local mutations = ""
1001 local success, mutationString = pcall(function()
1002 return MutationHandler:GetMutationsAsString(fruitModel) or ""
1003 end)
1004
1005 if not success or mutationString == "" then
1006 -- Try checking attributes directly
1007 for attrName, value in pairs(fruitModel:GetAttributes()) do
1008 if value == true and typeof(value) == "boolean" then
1009 -- Check only known mutation attributes
1010 if attrName == "Shocked" or
1011 attrName == "Frozen" or
1012 attrName == "Wet" or
1013 attrName == "Chilled" or
1014 attrName == "Twisted" or
1015 attrName == "Choc" or
1016 attrName == "Burnt" or
1017 attrName == "Moonlit" then
1018
1019 mutations = mutations .. attrName .. ", "
1020 end
1021 end
1022 end
1023 if mutations ~= "" then
1024 mutations = mutations:sub(1, -3) -- Remove trailing comma and space
1025 else
1026 mutations = "None"
1027 end
1028 else
1029 mutations = mutationString ~= "" and mutationString or "None"
1030 end
1031
1032 -- Calculate price using the CORRECT formula from the wiki
1033 local price = calculatePrice(weightNum, variantText, mutations)
1034
1035 -- Add to total value
1036 totalValue = totalValue + price
1037
1038 -- Apply current visibility setting to fruit model parts
1039 if areFruitsHidden then
1040 for _, part in pairs(fruitModel:GetDescendants()) do
1041 if part:IsA("BasePart") or part:IsA("MeshPart") or
1042 part:IsA("UnionOperation") or part:IsA("Decal") or
1043 part:IsA("Texture") then
1044 part.Transparency = 1
1045 end
1046 end
1047 end
1048
1049 local isHidden = false
1050
1051 -- See if this fruit was already in our list
1052 for _, existingFruit in ipairs(allFruitsData) do
1053 if existingFruit.model == fruitModel then
1054 isHidden = existingFruit.isHidden
1055 break
1056 end
1057 end
1058
1059 -- Apply visibility setting for this individual fruit
1060 if isHidden then
1061 for _, part in pairs(fruitModel:GetDescendants()) do
1062 if part:IsA("BasePart") or part:IsA("MeshPart") or
1063 part:IsA("UnionOperation") or part:IsA("Decal") or
1064 part:IsA("Texture") then
1065 part.Transparency = 1
1066 end
1067 end
1068 elseif areFruitsHidden then
1069 -- Apply global hide setting if not individually overridden
1070 for _, part in pairs(fruitModel:GetDescendants()) do
1071 if part:IsA("BasePart") or part:IsA("MeshPart") or
1072 part:IsA("UnionOperation") or part:IsA("Decal") or
1073 part:IsA("Texture") then
1074 part.Transparency = 1
1075 end
1076 end
1077 end
1078
1079 -- Store fruit data for sorting
1080 table.insert(allFruitsData, {
1081 name = fruitName,
1082 variant = variantText,
1083 mutations = mutations,
1084 weight = weightValue,
1085 weightNum = weightNum, -- Store raw number for sorting
1086 price = price,
1087 formattedPrice = formatNumber(price),
1088 model = fruitModel,
1089 treeName = treeType.Name,
1090 isHidden = isHidden -- Track if this fruit is hidden
1091 })
1092 end
1093 end
1094 end
1095 end
1096
1097 -- Update total value display
1098 totalValueLabel.Text = formatNumber(totalValue)
1099
1100 -- Display sorted fruit list
1101 createSortedFruitList()
1102end
1103
1104-- Connect the refresh button
1105refreshButton.MouseButton1Click:Connect(refreshFruitList)
1106
1107-- Handle refresh on unhide
1108minimizeButton.MouseButton1Click:Connect(function()
1109 if isMinimized then
1110 -- Will refresh data when un-minimizing
1111 task.delay(0.1, function()
1112 refreshFruitList()
1113 end)
1114 end
1115end)
1116
1117-- Collect all button functionality
1118collectAllButton.MouseButton1Click:Connect(function()
1119 local models = {}
1120
1121 -- Gather all fruit models
1122 for _, fruitData in ipairs(allFruitsData) do
1123 if fruitData.model and fruitData.model:IsA("Model") then
1124 table.insert(models, fruitData.model)
1125 end
1126 end
1127
1128 -- Collect all fruits at once
1129 if #models > 0 then
1130 Remotes.Crops.Collect.send(models)
1131
1132 -- Update UI
1133 collectAllButton.Text = "Collected!"
1134 collectAllButton.BackgroundColor3 = Color3.fromRGB(100, 100, 100)
1135 collectAllButton.Active = false
1136
1137 -- Refresh immediately
1138 refreshFruitList()
1139
1140 -- Reset button after delay
1141 task.delay(1.5, function()
1142 collectAllButton.Text = "Collect All"
1143 collectAllButton.BackgroundColor3 = Color3.fromRGB(60, 150, 60)
1144 collectAllButton.Active = true
1145 end)
1146 end
1147end)
1148
1149-- Add hover effect
1150collectAllButton.MouseEnter:Connect(function()
1151 if collectAllButton.Active ~= false then
1152 collectAllButton.BackgroundColor3 = Color3.fromRGB(80, 180, 80)
1153 end
1154end)
1155
1156collectAllButton.MouseLeave:Connect(function()
1157 if collectAllButton.Active ~= false then
1158 collectAllButton.BackgroundColor3 = Color3.fromRGB(60, 150, 60)
1159 end
1160end)
1161
1162-- Initial refresh
1163refreshFruitList()